package net.rustnotmc.client; /** * The numbers that make our player move the way our player moves. * * The player is the vanilla one with two things changed: the crouch is a * little faster and the jump is a little higher. Both numbers live here so * that the rest of the code has one place to point at, and so that a change * is one line. * * They can be set from the command line: * * -Drsx.sneakSpeed=1.6 -Drsx.jumpHeight=1.4 * * A value that is set below the floor is not taken: the crouch stays at 1.5 * blocks per second and the jump at 1.5 blocks. The defaults are the ones we * want, and they are not put through the floor. */ public final class RsxPlayerTuning { /** How fast the player walks, in blocks per second. The vanilla. */ public static final float WALK_SPEED = 4.317F; /** How fast the player crouches, in blocks per second. */ public static final float SNEAK_SPEED = 1.5F; /** How much the vanilla crouch slows the movement down. */ public static final float VANILLA_SNEAK_FACTOR = 0.3F; /** How high the player jumps, in blocks. The vanilla jumps 1.25. */ public static final float JUMP_HEIGHT = 1.35F; /** * How high the player jumps when it is standing still, in blocks. * * Jumping on the spot is the Rust-like hop: it clears a block that the * walking jump does not. Jumping while moving keeps the vanilla height. */ public static final float JUMP_HEIGHT_STANDING = 1.5F; /** How high the player jumps while moving, in blocks. The vanilla. */ public static final float JUMP_HEIGHT_MOVING = 1.25F; /** * How tall the player is while crouching, in blocks. * * The vanilla crouches to 1.65, which does not fit through a hole of one * and a half blocks. Ours is low enough to squeeze through it. */ public static final float CROUCH_HEIGHT = 1.45F; /** How far below the top of the head the eyes sit while crouching. */ public static final float CROUCH_EYE_OFFSET = 0.08F; /** The crouch never goes below this, in blocks per second. */ public static final float SNEAK_SPEED_FLOOR = 1.5F; /** The jump never goes below this, in blocks. */ public static final float JUMP_HEIGHT_FLOOR = 1.5F; /** The jump the vanilla has, in blocks. Used to scale the jump speed. */ private static final float VANILLA_JUMP_HEIGHT = 1.25F; /** The speed the vanilla jumps with. */ private static final float VANILLA_JUMP_MOTION = 0.42F; /** How fast the motion falls on every tick. */ private static final float GRAVITY = 0.08F; /** How much of the motion the air takes on every tick. */ private static final float AIR_DRAG = 0.98F; private RsxPlayerTuning() { } /** The crouch speed: the setting, or the default. */ public static float sneakSpeed() { return setting("rsx.sneakSpeed", SNEAK_SPEED, SNEAK_SPEED_FLOOR); } /** The jump height: the setting, or the default. */ public static float jumpHeight() { return setting("rsx.jumpHeight", JUMP_HEIGHT, JUMP_HEIGHT_FLOOR); } /** The height of the hop from a standstill, in blocks. */ public static float jumpHeightStanding() { return setting("rsx.jumpHeightStanding", JUMP_HEIGHT_STANDING, JUMP_HEIGHT_FLOOR); } /** The height of the jump while moving, in blocks. */ public static float jumpHeightMoving() { return setting("rsx.jumpHeightMoving", JUMP_HEIGHT_MOVING, JUMP_HEIGHT_FLOOR); } /** How tall the player is while crouching, in blocks. */ public static float crouchHeight() { return setting("rsx.crouchHeight", CROUCH_HEIGHT, CROUCH_HEIGHT); } /** The factor the crouch slows the movement down by. */ public static float sneakFactor() { return sneakSpeed() / WALK_SPEED; } /** * How much faster our crouch is than the vanilla one. * * The vanilla already multiplied the movement by a third. We undo that * and put ours in its place. */ public static float sneakCorrection() { return sneakFactor() / VANILLA_SNEAK_FACTOR; } /** The upward speed a jump of our height needs. */ public static float jumpMotion() { return jumpMotion(jumpHeight()); } /** * The upward speed a jump of that height needs. * * The height of a jump is not the square of the speed, because the * motion loses a little to the air on every tick. So the speed is found * the honest way: the height is computed for a guess and the guess is * corrected until it is the height that was asked for. */ public static float jumpMotion(float height) { if (height <= 0.0F) { return VANILLA_JUMP_MOTION; } float low = 0.0F; float high = 1.0F; for (int i = 0; i < 60; i++) { float middle = (low + high) * 0.5F; if (heightOf(middle) < height) { low = middle; } else { high = middle; } } return (low + high) * 0.5F; } /** * How high a jump with that speed carries the player. * * The motion of the vanilla on every tick: the speed falls by the * gravity and then by the air. The player is as high as the sum of the * upward steps. */ private static float heightOf(float motion) { float height = 0.0F; float speed = motion; while (speed > 0.0F) { height += speed; speed = (speed - GRAVITY) * AIR_DRAG; } return height; } private static float setting(String name, float fallback, float floor) { String value = System.getProperty(name); if (value == null || value.trim().isEmpty()) { return fallback; } float parsed; try { parsed = Float.parseFloat(value.trim()); } catch (NumberFormatException ignored) { return fallback; } if (parsed != parsed) { return fallback; } return parsed < floor ? floor : parsed; } }