diff --git a/client/src/main/java/nl/andrewl/aos2_client/Client.java b/client/src/main/java/nl/andrewl/aos2_client/Client.java index e193b37..6cde20a 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/Client.java +++ b/client/src/main/java/nl/andrewl/aos2_client/Client.java @@ -8,7 +8,6 @@ import nl.andrewl.aos2_client.model.OtherPlayer; import nl.andrewl.aos2_client.render.GameRenderer; import nl.andrewl.aos2_client.sound.SoundManager; import nl.andrewl.aos_core.config.Config; -import nl.andrewl.aos_core.model.Player; import nl.andrewl.aos_core.model.Projectile; import nl.andrewl.aos_core.model.Team; import nl.andrewl.aos_core.net.client.*; @@ -149,22 +148,11 @@ public class Client implements Runnable { } } else if (msg instanceof PlayerJoinMessage joinMessage) { runLater(() -> { - Player p = joinMessage.toPlayer(); - OtherPlayer op = new OtherPlayer(p.getId(), p.getUsername()); - if (joinMessage.teamId() != -1) { - op.setTeam(teams.get(joinMessage.teamId())); - } - op.getPosition().set(p.getPosition()); - op.getVelocity().set(p.getVelocity()); - op.getOrientation().set(p.getOrientation()); - op.setHeldItemId(joinMessage.selectedItemId()); - op.setSelectedBlockValue(joinMessage.selectedBlockValue()); + OtherPlayer op = OtherPlayer.fromJoinMessage(joinMessage, this); players.put(op.getId(), op); }); } else if (msg instanceof PlayerLeaveMessage leaveMessage) { - runLater(() -> { - players.remove(leaveMessage.id()); - }); + runLater(() -> players.remove(leaveMessage.id())); } else if (msg instanceof SoundMessage soundMessage) { if (soundManager != null) { soundManager.play( diff --git a/client/src/main/java/nl/andrewl/aos2_client/CommunicationHandler.java b/client/src/main/java/nl/andrewl/aos2_client/CommunicationHandler.java index 55e0128..c092704 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/CommunicationHandler.java +++ b/client/src/main/java/nl/andrewl/aos2_client/CommunicationHandler.java @@ -3,6 +3,7 @@ package nl.andrewl.aos2_client; import nl.andrewl.aos2_client.model.ClientPlayer; import nl.andrewl.aos2_client.model.OtherPlayer; import nl.andrewl.aos_core.Net; +import nl.andrewl.aos_core.model.PlayerMode; import nl.andrewl.aos_core.model.Team; import nl.andrewl.aos_core.model.item.ItemStack; import nl.andrewl.aos_core.model.world.World; @@ -174,6 +175,7 @@ public class CommunicationHandler { player.setCrouching(in.readBoolean()); player.setHeldItemId(in.readInt()); player.setSelectedBlockValue(in.readByte()); + player.setMode(PlayerMode.values()[in.readInt()]); client.getPlayers().put(player.getId(), player); } @@ -189,5 +191,6 @@ public class CommunicationHandler { int teamId = in.readInt(); if (teamId != -1) client.getMyPlayer().setTeam(client.getTeams().get(teamId)); client.getMyPlayer().getPosition().set(in.readFloat(), in.readFloat(), in.readFloat()); + client.getMyPlayer().setMode(PlayerMode.values()[in.readInt()]); } } diff --git a/client/src/main/java/nl/andrewl/aos2_client/model/OtherPlayer.java b/client/src/main/java/nl/andrewl/aos2_client/model/OtherPlayer.java index c975772..aefac88 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/model/OtherPlayer.java +++ b/client/src/main/java/nl/andrewl/aos2_client/model/OtherPlayer.java @@ -1,8 +1,10 @@ package nl.andrewl.aos2_client.model; import nl.andrewl.aos2_client.Camera; +import nl.andrewl.aos2_client.Client; import nl.andrewl.aos_core.model.Player; import nl.andrewl.aos_core.model.item.ItemTypes; +import nl.andrewl.aos_core.net.client.PlayerJoinMessage; import org.joml.Matrix3f; import org.joml.Matrix4f; import org.joml.Vector3f; @@ -99,4 +101,18 @@ public class OtherPlayer extends Player { public float[] getHeldItemNormalTransformData() { return heldItemNormalTransformData; } + + public static OtherPlayer fromJoinMessage(PlayerJoinMessage msg, Client client) { + OtherPlayer op = new OtherPlayer(msg.id(), msg.username()); + if (msg.teamId() != -1 && client.getTeams().containsKey(msg.teamId())) { + op.setTeam(client.getTeams().get(msg.teamId())); + } + op.getPosition().set(msg.px(), msg.py(), msg.pz()); + op.getVelocity().set(msg.vx(), msg.vy(), msg.vz()); + op.getOrientation().set(msg.ox(), msg.oy()); + op.setHeldItemId(msg.selectedItemId()); + op.setSelectedBlockValue(msg.selectedBlockValue()); + op.setMode(msg.mode()); + return op; + } } diff --git a/client/src/main/java/nl/andrewl/aos2_client/render/GameRenderer.java b/client/src/main/java/nl/andrewl/aos2_client/render/GameRenderer.java index d1cc73a..4991a42 100644 --- a/client/src/main/java/nl/andrewl/aos2_client/render/GameRenderer.java +++ b/client/src/main/java/nl/andrewl/aos2_client/render/GameRenderer.java @@ -8,6 +8,7 @@ import nl.andrewl.aos2_client.model.ClientPlayer; import nl.andrewl.aos2_client.render.chunk.ChunkRenderer; import nl.andrewl.aos2_client.render.gui.GuiRenderer; import nl.andrewl.aos2_client.render.model.Model; +import nl.andrewl.aos_core.model.PlayerMode; import nl.andrewl.aos_core.model.Team; import nl.andrewl.aos_core.model.item.BlockItemStack; import nl.andrewl.aos_core.model.item.ItemTypes; @@ -181,6 +182,7 @@ public class GameRenderer { playerModel.bind(); for (var player : client.getPlayers().values()) { + if (player.getMode() == PlayerMode.SPECTATOR) continue; if (player.getTeam() != null) { modelRenderer.setAspectColor(player.getTeam().getColor()); } else { @@ -196,6 +198,7 @@ public class GameRenderer { modelRenderer.render(rifleModel, myPlayer.getHeldItemTransformData(), myPlayer.getHeldItemNormalTransformData()); } for (var player : client.getPlayers().values()) { + if (player.getMode() == PlayerMode.SPECTATOR) continue; if (player.getHeldItemId() == ItemTypes.RIFLE.getId()) { modelRenderer.render(rifleModel, player.getHeldItemTransformData(), player.getHeldItemNormalTransformData()); } @@ -206,6 +209,7 @@ public class GameRenderer { modelRenderer.render(smgModel, myPlayer.getHeldItemTransformData(), myPlayer.getHeldItemNormalTransformData()); } for (var player : client.getPlayers().values()) { + if (player.getMode() == PlayerMode.SPECTATOR) continue; if (player.getHeldItemId() == ItemTypes.AK_47.getId()) { modelRenderer.render(smgModel, player.getHeldItemTransformData(), player.getHeldItemNormalTransformData()); } @@ -216,6 +220,7 @@ public class GameRenderer { modelRenderer.render(shotgunModel, myPlayer.getHeldItemTransformData(), myPlayer.getHeldItemNormalTransformData()); } for (var player : client.getPlayers().values()) { + if (player.getMode() == PlayerMode.SPECTATOR) continue; if (player.getHeldItemId() == ItemTypes.WINCHESTER.getId()) { modelRenderer.render(shotgunModel, player.getHeldItemTransformData(), player.getHeldItemNormalTransformData()); } @@ -230,6 +235,7 @@ public class GameRenderer { } modelRenderer.setAspectColor(new Vector3f(0.5f, 0.5f, 0.5f)); for (var player : client.getPlayers().values()) { + if (player.getMode() == PlayerMode.SPECTATOR) continue; if (player.getHeldItemId() == ItemTypes.BLOCK.getId()) { modelRenderer.setAspectColor(client.getWorld().getPalette().getColor(player.getSelectedBlockValue())); modelRenderer.render(blockModel, player.getHeldItemTransformData(), player.getHeldItemNormalTransformData()); diff --git a/core/src/main/java/nl/andrewl/aos_core/model/Player.java b/core/src/main/java/nl/andrewl/aos_core/model/Player.java index 79f6c7c..23bbe99 100644 --- a/core/src/main/java/nl/andrewl/aos_core/model/Player.java +++ b/core/src/main/java/nl/andrewl/aos_core/model/Player.java @@ -74,7 +74,13 @@ public class Player { */ protected Team team; - public Player(int id, String username, Team team) { + /** + * The mode that the player is in, which dictates how they can move and/or + * interact with the world. + */ + protected PlayerMode mode; + + public Player(int id, String username, Team team, PlayerMode mode) { this.position = new Vector3f(); this.velocity = new Vector3f(); this.orientation = new Vector2f(); @@ -82,10 +88,11 @@ public class Player { this.id = id; this.username = username; this.team = team; + this.mode = mode; } public Player(int id, String username) { - this(id, username, null); + this(id, username, null, PlayerMode.NORMAL); } public Vector3f getPosition() { @@ -138,6 +145,14 @@ public class Player { this.team = team; } + public PlayerMode getMode() { + return mode; + } + + public void setMode(PlayerMode mode) { + this.mode = mode; + } + public Vector3f getViewVector() { return viewVector; } diff --git a/core/src/main/java/nl/andrewl/aos_core/net/client/PlayerJoinMessage.java b/core/src/main/java/nl/andrewl/aos_core/net/client/PlayerJoinMessage.java index d3e9480..8b24311 100644 --- a/core/src/main/java/nl/andrewl/aos_core/net/client/PlayerJoinMessage.java +++ b/core/src/main/java/nl/andrewl/aos_core/net/client/PlayerJoinMessage.java @@ -1,6 +1,7 @@ package nl.andrewl.aos_core.net.client; import nl.andrewl.aos_core.model.Player; +import nl.andrewl.aos_core.model.PlayerMode; import nl.andrewl.aos_core.model.item.ItemTypes; import nl.andrewl.record_net.Message; @@ -15,13 +16,15 @@ public record PlayerJoinMessage( float ox, float oy, boolean crouching, int selectedItemId, - byte selectedBlockValue + byte selectedBlockValue, + PlayerMode mode ) implements Message { public Player toPlayer() { Player p = new Player(id, username); p.getPosition().set(px, py, pz); p.getVelocity().set(vx, vy, vz); p.getOrientation().set(ox, oy); + p.setMode(mode); return p; } } diff --git a/core/src/main/java/nl/andrewl/aos_core/net/client/PlayerUpdateMessage.java b/core/src/main/java/nl/andrewl/aos_core/net/client/PlayerUpdateMessage.java index 48189b5..4bca576 100644 --- a/core/src/main/java/nl/andrewl/aos_core/net/client/PlayerUpdateMessage.java +++ b/core/src/main/java/nl/andrewl/aos_core/net/client/PlayerUpdateMessage.java @@ -1,6 +1,7 @@ package nl.andrewl.aos_core.net.client; import nl.andrewl.aos_core.model.Player; +import nl.andrewl.aos_core.model.PlayerMode; import nl.andrewl.record_net.Message; /** @@ -16,7 +17,8 @@ public record PlayerUpdateMessage( float vx, float vy, float vz, float ox, float oy, boolean crouching, - int selectedItemId + int selectedItemId, + PlayerMode mode ) implements Message { public void apply(Player p) { @@ -24,5 +26,6 @@ public record PlayerUpdateMessage( p.getVelocity().set(vx, vy, vz); p.getOrientation().set(ox, oy); p.setCrouching(crouching); + p.setMode(mode); } } diff --git a/server/src/main/java/nl/andrewl/aos2_server/ClientCommunicationHandler.java b/server/src/main/java/nl/andrewl/aos2_server/ClientCommunicationHandler.java index f68b59d..e524f56 100644 --- a/server/src/main/java/nl/andrewl/aos2_server/ClientCommunicationHandler.java +++ b/server/src/main/java/nl/andrewl/aos2_server/ClientCommunicationHandler.java @@ -233,6 +233,7 @@ public class ClientCommunicationHandler { out.writeBoolean(player.isCrouching()); out.writeInt(player.getInventory().getSelectedItemStack().getType().getId()); out.writeByte(player.getInventory().getSelectedBlockValue()); + out.writeInt(player.getMode().ordinal()); } // Send the player's own inventory data. @@ -251,5 +252,7 @@ public class ClientCommunicationHandler { out.writeFloat(player.getPosition().x()); out.writeFloat(player.getPosition().y()); out.writeFloat(player.getPosition().z()); + + out.writeInt(player.getMode().ordinal()); } } diff --git a/server/src/main/java/nl/andrewl/aos2_server/PlayerManager.java b/server/src/main/java/nl/andrewl/aos2_server/PlayerManager.java index daac8d7..662df22 100644 --- a/server/src/main/java/nl/andrewl/aos2_server/PlayerManager.java +++ b/server/src/main/java/nl/andrewl/aos2_server/PlayerManager.java @@ -2,6 +2,7 @@ package nl.andrewl.aos2_server; import nl.andrewl.aos2_server.model.ServerPlayer; import nl.andrewl.aos_core.Net; +import nl.andrewl.aos_core.model.PlayerMode; import nl.andrewl.aos_core.model.Team; import nl.andrewl.aos_core.model.item.BlockItemStack; import nl.andrewl.aos_core.model.item.Gun; @@ -46,6 +47,7 @@ public class PlayerManager { joinMessage = username + " joined the game."; } player.setPosition(getBestSpawnPoint(player)); + player.setMode(PlayerMode.NORMAL); // Tell all other players that this one has joined. broadcastTcpMessageToAllBut(new PlayerJoinMessage( player.getId(), player.getUsername(), player.getTeam() == null ? -1 : player.getTeam().getId(), @@ -54,7 +56,8 @@ public class PlayerManager { player.getOrientation().x(), player.getOrientation().y(), player.isCrouching(), player.getInventory().getSelectedItemStack().getType().getId(), - player.getInventory().getSelectedBlockValue() + player.getInventory().getSelectedBlockValue(), + player.getMode() ), player); broadcastTcpMessageToAllBut(ChatMessage.announce(joinMessage), player); return player; diff --git a/server/src/main/java/nl/andrewl/aos2_server/logic/WorldUpdater.java b/server/src/main/java/nl/andrewl/aos2_server/logic/WorldUpdater.java index 5f4089a..bd9eaf1 100644 --- a/server/src/main/java/nl/andrewl/aos2_server/logic/WorldUpdater.java +++ b/server/src/main/java/nl/andrewl/aos2_server/logic/WorldUpdater.java @@ -31,9 +31,11 @@ public class WorldUpdater implements Runnable { final long nsPerTick = (long) Math.floor(secondsPerTick * 1_000_000_000); System.out.printf("Running world updater at %d ms/tick, or %d ns/tick.%n", msPerTick, nsPerTick); running = true; + while (running) { long start = System.nanoTime(); - tick(System.currentTimeMillis()); + long now = System.currentTimeMillis(); + tick(now); long elapsedNs = System.nanoTime() - start; if (elapsedNs > nsPerTick) { System.err.printf("Took %d ns to do one tick, which is more than the desired %d ns per tick.%n", elapsedNs, nsPerTick); diff --git a/server/src/main/java/nl/andrewl/aos2_server/model/ServerPlayer.java b/server/src/main/java/nl/andrewl/aos2_server/model/ServerPlayer.java index c96d10d..88cc82a 100644 --- a/server/src/main/java/nl/andrewl/aos2_server/model/ServerPlayer.java +++ b/server/src/main/java/nl/andrewl/aos2_server/model/ServerPlayer.java @@ -2,6 +2,7 @@ package nl.andrewl.aos2_server.model; import nl.andrewl.aos2_server.logic.PlayerActionManager; import nl.andrewl.aos_core.model.Player; +import nl.andrewl.aos_core.model.PlayerMode; import nl.andrewl.aos_core.model.item.BlockItemStack; import nl.andrewl.aos_core.model.item.GunItemStack; import nl.andrewl.aos_core.model.item.Inventory; @@ -84,7 +85,8 @@ public class ServerPlayer extends Player { velocity.x, velocity.y, velocity.z, orientation.x, orientation.y, actionManager.getInput().crouching(), - inventory.getSelectedItemStack().getType().getId() + inventory.getSelectedItemStack().getType().getId(), + mode ); } }