Added better client input handling.
This commit is contained in:
parent
7df8120c16
commit
e321979c3c
|
@ -7,7 +7,6 @@ import nl.andrewl.aos2_client.model.ClientPlayer;
|
||||||
import nl.andrewl.aos2_client.model.OtherPlayer;
|
import nl.andrewl.aos2_client.model.OtherPlayer;
|
||||||
import nl.andrewl.aos2_client.render.GameRenderer;
|
import nl.andrewl.aos2_client.render.GameRenderer;
|
||||||
import nl.andrewl.aos2_client.sound.SoundManager;
|
import nl.andrewl.aos2_client.sound.SoundManager;
|
||||||
import nl.andrewl.aos_core.FileUtils;
|
|
||||||
import nl.andrewl.aos_core.config.Config;
|
import nl.andrewl.aos_core.config.Config;
|
||||||
import nl.andrewl.aos_core.model.Player;
|
import nl.andrewl.aos_core.model.Player;
|
||||||
import nl.andrewl.aos_core.model.Projectile;
|
import nl.andrewl.aos_core.model.Projectile;
|
||||||
|
@ -137,7 +136,7 @@ public class Client implements Runnable {
|
||||||
gameRenderer.getCamera().setToPlayer(myPlayer);
|
gameRenderer.getCamera().setToPlayer(myPlayer);
|
||||||
}
|
}
|
||||||
if (soundManager != null) {
|
if (soundManager != null) {
|
||||||
soundManager.updateListener(myPlayer.getPosition(), myPlayer.getVelocity());
|
soundManager.updateListener(myPlayer.getEyePosition(), myPlayer.getVelocity());
|
||||||
}
|
}
|
||||||
lastPlayerUpdate = playerUpdate.timestamp();
|
lastPlayerUpdate = playerUpdate.timestamp();
|
||||||
} else {
|
} else {
|
||||||
|
@ -206,7 +205,7 @@ public class Client implements Runnable {
|
||||||
} else if (msg instanceof ChatMessage chatMessage) {
|
} else if (msg instanceof ChatMessage chatMessage) {
|
||||||
chat.chatReceived(chatMessage);
|
chat.chatReceived(chatMessage);
|
||||||
if (soundManager != null) {
|
if (soundManager != null) {
|
||||||
soundManager.play("chat", 1, myPlayer.getPosition(), myPlayer.getVelocity());
|
soundManager.play("chat", 1, myPlayer.getEyePosition(), myPlayer.getVelocity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,10 +267,11 @@ public class Client implements Runnable {
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
List<Path> configPaths = Config.getCommonConfigPaths();
|
List<Path> configPaths = Config.getCommonConfigPaths();
|
||||||
|
configPaths.add(0, Path.of("client.yaml")); // Add this first so we create client.yaml if needed.
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
configPaths.add(Path.of(args[0].trim()));
|
configPaths.add(Path.of(args[0].trim()));
|
||||||
}
|
}
|
||||||
ClientConfig clientConfig = Config.loadConfig(ClientConfig.class, configPaths, new ClientConfig(), FileUtils.readClasspathFile("default-config.yaml"));
|
ClientConfig clientConfig = Config.loadConfig(ClientConfig.class, configPaths, new ClientConfig(), "default-config.yaml");
|
||||||
Client client = new Client(clientConfig);
|
Client client = new Client(clientConfig);
|
||||||
client.run();
|
client.run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package nl.andrewl.aos_core.config;
|
package nl.andrewl.aos_core.config;
|
||||||
|
|
||||||
|
import nl.andrewl.aos_core.FileUtils;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -19,7 +20,7 @@ public final class Config {
|
||||||
* @param paths The paths to load from.
|
* @param paths The paths to load from.
|
||||||
* @param fallback A default configuration object to use if no config could
|
* @param fallback A default configuration object to use if no config could
|
||||||
* be loaded from any of the paths.
|
* be loaded from any of the paths.
|
||||||
* @param defaultConfigFile The default config file to save.
|
* @param defaultConfigFile The default config file resource to save.
|
||||||
* @return The configuration object.
|
* @return The configuration object.
|
||||||
* @param <T> The type of the configuration object.
|
* @param <T> The type of the configuration object.
|
||||||
*/
|
*/
|
||||||
|
@ -35,25 +36,13 @@ public final class Config {
|
||||||
}
|
}
|
||||||
Path outputPath = paths.size() > 0 ? paths.get(0) : Path.of("config.yaml");
|
Path outputPath = paths.size() > 0 ? paths.get(0) : Path.of("config.yaml");
|
||||||
try (var writer = Files.newBufferedWriter(outputPath)) {
|
try (var writer = Files.newBufferedWriter(outputPath)) {
|
||||||
writer.write(defaultConfigFile);
|
writer.write(FileUtils.readClasspathFile(defaultConfigFile));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T loadConfig(Class<T> configType, List<Path> paths, String defaultConfigFile) {
|
|
||||||
var cfg = loadConfig(configType, paths, null, defaultConfigFile);
|
|
||||||
if (cfg == null) {
|
|
||||||
throw new RuntimeException("Could not load config from any of the supplied paths.");
|
|
||||||
}
|
|
||||||
return cfg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T loadConfig(Class<T> configType, T fallback, String defaultConfigFile, Path... paths) {
|
|
||||||
return loadConfig(configType, List.of(paths), fallback, defaultConfigFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Path> getCommonConfigPaths() {
|
public static List<Path> getCommonConfigPaths() {
|
||||||
List<Path> paths = new ArrayList<>();
|
List<Path> paths = new ArrayList<>();
|
||||||
paths.add(Path.of("config.yaml"));
|
paths.add(Path.of("config.yaml"));
|
||||||
|
|
|
@ -17,7 +17,7 @@ import java.util.Map;
|
||||||
* that players can interact in.
|
* that players can interact in.
|
||||||
*/
|
*/
|
||||||
public class World {
|
public class World {
|
||||||
private static final float DELTA = 0.01f;
|
private static final float DELTA = 0.001f;
|
||||||
|
|
||||||
protected final Map<Vector3ic, Chunk> chunkMap = new HashMap<>();
|
protected final Map<Vector3ic, Chunk> chunkMap = new HashMap<>();
|
||||||
protected ColorPalette palette;
|
protected ColorPalette palette;
|
||||||
|
@ -164,8 +164,12 @@ public class World {
|
||||||
public Hit getLookingAtPos(Vector3f eyePos, Vector3f eyeDir, float limit) {
|
public Hit getLookingAtPos(Vector3f eyePos, Vector3f eyeDir, float limit) {
|
||||||
if (eyeDir.lengthSquared() == 0 || limit <= 0) return null;
|
if (eyeDir.lengthSquared() == 0 || limit <= 0) return null;
|
||||||
Vector3f pos = new Vector3f(eyePos);
|
Vector3f pos = new Vector3f(eyePos);
|
||||||
|
Vector3f previousPos = new Vector3f();
|
||||||
while (pos.distance(eyePos) < limit) {
|
while (pos.distance(eyePos) < limit) {
|
||||||
|
previousPos.set(pos);
|
||||||
stepToNextBlock(pos, eyeDir);
|
stepToNextBlock(pos, eyeDir);
|
||||||
|
// If for some reason we couldn't advance to the next block, exit null, so we don't infinitely loop.
|
||||||
|
if (pos.equals(previousPos)) return null;
|
||||||
if (getBlockAt(pos) > 0) {
|
if (getBlockAt(pos) > 0) {
|
||||||
Vector3i hitPos = new Vector3i(
|
Vector3i hitPos = new Vector3i(
|
||||||
(int) Math.floor(pos.x),
|
(int) Math.floor(pos.x),
|
||||||
|
@ -234,7 +238,7 @@ public class World {
|
||||||
// Testing code!
|
// Testing code!
|
||||||
if (diff == 0) {
|
if (diff == 0) {
|
||||||
System.out.printf("n = %.8f, nextValue = %.8f, floor(n) - DELTA = %.8f%n", n, nextValue, Math.floor(n) - DELTA);
|
System.out.printf("n = %.8f, nextValue = %.8f, floor(n) - DELTA = %.8f%n", n, nextValue, Math.floor(n) - DELTA);
|
||||||
throw new RuntimeException("EEK");
|
return Float.MAX_VALUE;
|
||||||
}
|
}
|
||||||
return Math.abs(diff / dir);
|
return Math.abs(diff / dir);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package nl.andrewl.aos_core.net.client;
|
||||||
|
|
||||||
|
import nl.andrewl.record_net.Message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message that the server sends to clients, to tell them to update their
|
||||||
|
* player's orientation to the specified values.
|
||||||
|
*/
|
||||||
|
public record ClientOrientationUpdateMessage(
|
||||||
|
float x, float y
|
||||||
|
) implements Message {}
|
|
@ -177,10 +177,11 @@ public class Server implements Runnable {
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
List<Path> configPaths = Config.getCommonConfigPaths();
|
List<Path> configPaths = Config.getCommonConfigPaths();
|
||||||
|
configPaths.add(0, Path.of("server.yaml"));
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
configPaths.add(Path.of(args[0].trim()));
|
configPaths.add(Path.of(args[0].trim()));
|
||||||
}
|
}
|
||||||
ServerConfig cfg = Config.loadConfig(ServerConfig.class, configPaths, new ServerConfig(), null);
|
ServerConfig cfg = Config.loadConfig(ServerConfig.class, configPaths, new ServerConfig(), "default-config.yaml");
|
||||||
Server server = new Server(cfg);
|
Server server = new Server(cfg);
|
||||||
new Thread(server).start();
|
new Thread(server).start();
|
||||||
ServerCli.start(server);
|
ServerCli.start(server);
|
||||||
|
|
|
@ -29,8 +29,8 @@ import static nl.andrewl.aos2_server.model.ServerPlayer.RADIUS;
|
||||||
*/
|
*/
|
||||||
public class PlayerActionManager {
|
public class PlayerActionManager {
|
||||||
private final ServerPlayer player;
|
private final ServerPlayer player;
|
||||||
|
private final PlayerInputTracker input;
|
||||||
|
|
||||||
private ClientInputState lastInputState;
|
|
||||||
private long lastBlockRemovedAt = 0;
|
private long lastBlockRemovedAt = 0;
|
||||||
private long lastBlockPlacedAt = 0;
|
private long lastBlockPlacedAt = 0;
|
||||||
|
|
||||||
|
@ -45,23 +45,15 @@ public class PlayerActionManager {
|
||||||
|
|
||||||
public PlayerActionManager(ServerPlayer player) {
|
public PlayerActionManager(ServerPlayer player) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
lastInputState = new ClientInputState(
|
this.input = new PlayerInputTracker(player);
|
||||||
player.getId(),
|
|
||||||
false, false, false, false,
|
|
||||||
false, false, false,
|
|
||||||
false, false, false,
|
|
||||||
player.getInventory().getSelectedIndex()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClientInputState getLastInputState() {
|
public PlayerInputTracker getInput() {
|
||||||
return lastInputState;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setLastInputState(ClientInputState lastInputState) {
|
public boolean setLastInputState(ClientInputState lastInputState) {
|
||||||
boolean change = !lastInputState.equals(this.lastInputState);
|
return input.setLastInputState(lastInputState);
|
||||||
if (change) this.lastInputState = lastInputState;
|
|
||||||
return change;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUpdated() {
|
public boolean isUpdated() {
|
||||||
|
@ -70,8 +62,8 @@ public class PlayerActionManager {
|
||||||
|
|
||||||
public void tick(long now, float dt, World world, Server server) {
|
public void tick(long now, float dt, World world, Server server) {
|
||||||
updated = false; // Reset the updated flag. This will be set to true if the player was updated in this tick.
|
updated = false; // Reset the updated flag. This will be set to true if the player was updated in this tick.
|
||||||
if (player.getInventory().getSelectedIndex() != lastInputState.selectedInventoryIndex()) {
|
if (player.getInventory().getSelectedIndex() != input.selectedInventoryIndex()) {
|
||||||
player.getInventory().setSelectedIndex(lastInputState.selectedInventoryIndex());
|
player.getInventory().setSelectedIndex(input.selectedInventoryIndex());
|
||||||
// Tell the client that their inventory slot has been updated properly.
|
// Tell the client that their inventory slot has been updated properly.
|
||||||
server.getPlayerManager().getHandler(player.getId()).sendDatagramPacket(new InventorySelectedStackMessage(player.getInventory().getSelectedIndex()));
|
server.getPlayerManager().getHandler(player.getId()).sendDatagramPacket(new InventorySelectedStackMessage(player.getInventory().getSelectedIndex()));
|
||||||
updated = true; // Tell everyone else that this player's selected item has changed.
|
updated = true; // Tell everyone else that this player's selected item has changed.
|
||||||
|
@ -81,7 +73,7 @@ public class PlayerActionManager {
|
||||||
if (selectedStack instanceof BlockItemStack b) {
|
if (selectedStack instanceof BlockItemStack b) {
|
||||||
tickBlockAction(now, server, world, b);
|
tickBlockAction(now, server, world, b);
|
||||||
} else if (selectedStack instanceof GunItemStack g) {
|
} else if (selectedStack instanceof GunItemStack g) {
|
||||||
tickGunAction(now, server, world, g);
|
tickGunAction(now, server, g);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -93,18 +85,19 @@ public class PlayerActionManager {
|
||||||
lastResupplyAt = now;
|
lastResupplyAt = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.isCrouching() != lastInputState.crouching()) {
|
if (player.isCrouching() != input.crouching()) {
|
||||||
player.setCrouching(lastInputState.crouching());
|
player.setCrouching(input.crouching());
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
tickMovement(dt, server, world, server.getConfig().physics);
|
tickMovement(dt, server, world, server.getConfig().physics);
|
||||||
|
input.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickGunAction(long now, Server server, World world, GunItemStack g) {
|
private void tickGunAction(long now, Server server, GunItemStack g) {
|
||||||
Gun gun = (Gun) g.getType();
|
Gun gun = (Gun) g.getType();
|
||||||
if (// Check to see if the player is shooting.
|
if (// Check to see if the player is shooting.
|
||||||
lastInputState.hitting() &&
|
input.hitting() &&
|
||||||
g.getBulletCount() > 0 &&
|
g.getBulletCount() > 0 &&
|
||||||
!gunReloading &&
|
!gunReloading &&
|
||||||
now - gunLastShotAt > gun.getShotCooldownTime() * 1000 &&
|
now - gunLastShotAt > gun.getShotCooldownTime() * 1000 &&
|
||||||
|
@ -126,11 +119,14 @@ public class PlayerActionManager {
|
||||||
} else if (gun instanceof Winchester) {
|
} else if (gun instanceof Winchester) {
|
||||||
shotSound = "shot_winchester_1";
|
shotSound = "shot_winchester_1";
|
||||||
}
|
}
|
||||||
server.getPlayerManager().broadcastUdpMessage(new SoundMessage(shotSound, 1, player.getPosition(), player.getVelocity()));
|
Vector3f soundLocation = new Vector3f(player.getPosition());
|
||||||
|
soundLocation.y += 1.4f;
|
||||||
|
soundLocation.add(player.getViewVector());
|
||||||
|
server.getPlayerManager().broadcastUdpMessage(new SoundMessage(shotSound, 1, soundLocation, player.getVelocity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (// Check to see if the player is reloading.
|
if (// Check to see if the player is reloading.
|
||||||
lastInputState.reloading() &&
|
input.reloading() &&
|
||||||
!gunReloading &&
|
!gunReloading &&
|
||||||
g.getClipCount() > 0
|
g.getClipCount() > 0
|
||||||
) {
|
) {
|
||||||
|
@ -151,7 +147,7 @@ public class PlayerActionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if the player released the trigger, for non-automatic weapons.
|
// Check to see if the player released the trigger, for non-automatic weapons.
|
||||||
if (!gun.isAutomatic() && gunNeedsReCock && !lastInputState.hitting()) {
|
if (!gun.isAutomatic() && gunNeedsReCock && !input.hitting()) {
|
||||||
gunNeedsReCock = false;
|
gunNeedsReCock = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,7 +155,7 @@ public class PlayerActionManager {
|
||||||
private void tickBlockAction(long now, Server server, World world, BlockItemStack stack) {
|
private void tickBlockAction(long now, Server server, World world, BlockItemStack stack) {
|
||||||
// Check for breaking blocks.
|
// Check for breaking blocks.
|
||||||
if (
|
if (
|
||||||
lastInputState.hitting() &&
|
input.hitting() &&
|
||||||
stack.getAmount() < stack.getType().getMaxAmount() &&
|
stack.getAmount() < stack.getType().getMaxAmount() &&
|
||||||
now - lastBlockRemovedAt > server.getConfig().actions.blockBreakCooldown * 1000
|
now - lastBlockRemovedAt > server.getConfig().actions.blockBreakCooldown * 1000
|
||||||
) {
|
) {
|
||||||
|
@ -175,7 +171,7 @@ public class PlayerActionManager {
|
||||||
}
|
}
|
||||||
// Check for placing blocks.
|
// Check for placing blocks.
|
||||||
if (
|
if (
|
||||||
lastInputState.interacting() &&
|
input.interacting() &&
|
||||||
stack.getAmount() > 0 &&
|
stack.getAmount() > 0 &&
|
||||||
now - lastBlockPlacedAt > server.getConfig().actions.blockPlaceCooldown * 1000
|
now - lastBlockPlacedAt > server.getConfig().actions.blockPlaceCooldown * 1000
|
||||||
) {
|
) {
|
||||||
|
@ -202,8 +198,8 @@ public class PlayerActionManager {
|
||||||
tickHorizontalVelocity(config, grounded);
|
tickHorizontalVelocity(config, grounded);
|
||||||
|
|
||||||
if (isGrounded(world)) {
|
if (isGrounded(world)) {
|
||||||
if (lastInputState.jumping()) {
|
if (input.jumping()) {
|
||||||
velocity.y = config.jumpVerticalSpeed * (lastInputState.sprinting() ? 1.25f : 1f);
|
velocity.y = config.jumpVerticalSpeed * (input.sprinting() ? 1.25f : 1f);
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -239,19 +235,19 @@ public class PlayerActionManager {
|
||||||
velocity.z == velocity.z ? velocity.z : 0f
|
velocity.z == velocity.z ? velocity.z : 0f
|
||||||
);
|
);
|
||||||
Vector3f acceleration = new Vector3f(0);
|
Vector3f acceleration = new Vector3f(0);
|
||||||
if (lastInputState.forward()) acceleration.z -= 1;
|
if (input.forward()) acceleration.z -= 1;
|
||||||
if (lastInputState.backward()) acceleration.z += 1;
|
if (input.backward()) acceleration.z += 1;
|
||||||
if (lastInputState.left()) acceleration.x -= 1;
|
if (input.left()) acceleration.x -= 1;
|
||||||
if (lastInputState.right()) acceleration.x += 1;
|
if (input.right()) acceleration.x += 1;
|
||||||
if (acceleration.lengthSquared() > 0) {
|
if (acceleration.lengthSquared() > 0) {
|
||||||
acceleration.normalize();
|
acceleration.normalize();
|
||||||
acceleration.rotateAxis(orientation.x, 0, 1, 0);
|
acceleration.rotateAxis(orientation.x, 0, 1, 0);
|
||||||
acceleration.mul(config.movementAcceleration);
|
acceleration.mul(config.movementAcceleration);
|
||||||
horizontalVelocity.add(acceleration);
|
horizontalVelocity.add(acceleration);
|
||||||
final float maxSpeed;
|
final float maxSpeed;
|
||||||
if (lastInputState.crouching()) {
|
if (input.crouching()) {
|
||||||
maxSpeed = config.crouchingSpeed;
|
maxSpeed = config.crouchingSpeed;
|
||||||
} else if (lastInputState.sprinting()) {
|
} else if (input.sprinting()) {
|
||||||
maxSpeed = config.sprintingSpeed;
|
maxSpeed = config.sprintingSpeed;
|
||||||
} else {
|
} else {
|
||||||
maxSpeed = config.walkingSpeed;
|
maxSpeed = config.walkingSpeed;
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package nl.andrewl.aos2_server.logic;
|
||||||
|
|
||||||
|
import nl.andrewl.aos_core.net.client.ClientInputState;
|
||||||
|
|
||||||
|
public class PlayerImpulses {
|
||||||
|
public boolean forward;
|
||||||
|
public boolean backward;
|
||||||
|
public boolean left;
|
||||||
|
public boolean right;
|
||||||
|
public boolean jumping;
|
||||||
|
public boolean crouching;
|
||||||
|
public boolean sprinting;
|
||||||
|
public boolean hitting;
|
||||||
|
public boolean interacting;
|
||||||
|
public boolean reloading;
|
||||||
|
|
||||||
|
public void update(ClientInputState s) {
|
||||||
|
forward = forward || s.forward();
|
||||||
|
backward = backward || s.backward();
|
||||||
|
left = left || s.left();
|
||||||
|
right = right || s.right();
|
||||||
|
jumping = jumping || s.jumping();
|
||||||
|
crouching = crouching || s.crouching();
|
||||||
|
sprinting = sprinting || s.sprinting();
|
||||||
|
hitting = hitting || s.hitting();
|
||||||
|
interacting = interacting || s.interacting();
|
||||||
|
reloading = reloading || s.reloading();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
forward = false;
|
||||||
|
backward = false;
|
||||||
|
left = false;
|
||||||
|
right = false;
|
||||||
|
jumping = false;
|
||||||
|
crouching = false;
|
||||||
|
sprinting = false;
|
||||||
|
hitting = false;
|
||||||
|
interacting = false;
|
||||||
|
reloading = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package nl.andrewl.aos2_server.logic;
|
||||||
|
|
||||||
|
import nl.andrewl.aos2_server.model.ServerPlayer;
|
||||||
|
import nl.andrewl.aos_core.net.client.ClientInputState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around the various information we have about a player's input state,
|
||||||
|
* including their last known state, and any impulses they've made since the
|
||||||
|
* last tick.
|
||||||
|
*/
|
||||||
|
public class PlayerInputTracker {
|
||||||
|
private ClientInputState lastInputState;
|
||||||
|
private final PlayerImpulses impulsesSinceLastTick;
|
||||||
|
|
||||||
|
public PlayerInputTracker(ServerPlayer player) {
|
||||||
|
lastInputState = new ClientInputState(
|
||||||
|
player.getId(),
|
||||||
|
false, false, false, false,
|
||||||
|
false, false, false,
|
||||||
|
false, false, false,
|
||||||
|
player.getInventory().getSelectedIndex()
|
||||||
|
);
|
||||||
|
this.impulsesSinceLastTick = new PlayerImpulses();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setLastInputState(ClientInputState lastInputState) {
|
||||||
|
boolean updated = !lastInputState.equals(this.lastInputState);
|
||||||
|
if (updated) {
|
||||||
|
this.lastInputState = lastInputState;
|
||||||
|
impulsesSinceLastTick.update(lastInputState);
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
impulsesSinceLastTick.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean forward() {
|
||||||
|
return lastInputState.forward() || impulsesSinceLastTick.forward;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean backward() {
|
||||||
|
return lastInputState.backward() || impulsesSinceLastTick.backward;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean left() {
|
||||||
|
return lastInputState.left() || impulsesSinceLastTick.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean right() {
|
||||||
|
return lastInputState.right() || impulsesSinceLastTick.right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean jumping() {
|
||||||
|
return lastInputState.jumping() || impulsesSinceLastTick.jumping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean crouching() {
|
||||||
|
return lastInputState.crouching() || impulsesSinceLastTick.crouching;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sprinting() {
|
||||||
|
return lastInputState.sprinting() || impulsesSinceLastTick.sprinting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hitting() {
|
||||||
|
return lastInputState.hitting() || impulsesSinceLastTick.hitting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interacting() {
|
||||||
|
return lastInputState.interacting() || impulsesSinceLastTick.interacting;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean reloading() {
|
||||||
|
return lastInputState.reloading() || impulsesSinceLastTick.reloading;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int selectedInventoryIndex() {
|
||||||
|
return lastInputState.selectedInventoryIndex();
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,6 @@ import nl.andrewl.aos_core.model.item.BlockItemStack;
|
||||||
import nl.andrewl.aos_core.model.item.GunItemStack;
|
import nl.andrewl.aos_core.model.item.GunItemStack;
|
||||||
import nl.andrewl.aos_core.model.item.Inventory;
|
import nl.andrewl.aos_core.model.item.Inventory;
|
||||||
import nl.andrewl.aos_core.model.item.ItemTypes;
|
import nl.andrewl.aos_core.model.item.ItemTypes;
|
||||||
import nl.andrewl.aos_core.model.item.gun.Winchester;
|
|
||||||
import nl.andrewl.aos_core.net.client.PlayerUpdateMessage;
|
import nl.andrewl.aos_core.net.client.PlayerUpdateMessage;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -69,7 +68,7 @@ public class ServerPlayer extends Player {
|
||||||
position.x, position.y, position.z,
|
position.x, position.y, position.z,
|
||||||
velocity.x, velocity.y, velocity.z,
|
velocity.x, velocity.y, velocity.z,
|
||||||
orientation.x, orientation.y,
|
orientation.x, orientation.y,
|
||||||
actionManager.getLastInputState().crouching(),
|
actionManager.getInput().crouching(),
|
||||||
inventory.getSelectedItemStack().getType().getId()
|
inventory.getSelectedItemStack().getType().getId()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Ace of Shades 2 Server Configuration
|
||||||
|
port: 25565
|
||||||
|
connectionBacklog: 5
|
||||||
|
ticksPerSecond: 20.0
|
||||||
|
world: worlds.redfort
|
||||||
|
teams:
|
||||||
|
- name: Red
|
||||||
|
color: [0.8, 0, 0]
|
||||||
|
spawnPoint: A
|
||||||
|
- name: Blue
|
||||||
|
color: [0, 0, 0.8]
|
||||||
|
spawnPoint: B
|
||||||
|
physics:
|
||||||
|
gravity: 29.43
|
||||||
|
walkingSpeed: 4
|
||||||
|
crouchingSpeed: 1.5
|
||||||
|
sprintingSpeed: 9
|
||||||
|
movementAcceleration: 2
|
||||||
|
movementDeceleration: 1
|
||||||
|
jumpVerticalSpeed: 8
|
||||||
|
actions:
|
||||||
|
blockBreakCooldown: 0.25
|
||||||
|
blockPlaceCooldown: 0.1
|
||||||
|
blockBreakReach: 5
|
||||||
|
blockPlaceReach: 5
|
||||||
|
blockBulletDamageResistance: 3
|
||||||
|
blockBulletDamageCooldown: 10
|
||||||
|
resupplyCooldown: 30
|
||||||
|
resupplyRadius: 3
|
||||||
|
teamSpawnProtection: 10
|
||||||
|
movementAccuracyDecreaseFactor: 0.01
|
||||||
|
friendlyFire: false
|
Loading…
Reference in New Issue