diff options
| author | ilotterytea <iltsu@alright.party> | 2025-01-22 04:11:41 +0500 |
|---|---|---|
| committer | ilotterytea <iltsu@alright.party> | 2025-01-22 04:11:41 +0500 |
| commit | 449c70cbf900a80042f70dd8929f302f0f0016d7 (patch) | |
| tree | cd958299e1a421165c370cb31500315f0635560c /server/src | |
| parent | b96a6d7005fcb90a21aeb21ddebe8bb7b82a7ef5 (diff) | |
feat: MULTIPLAYER!!!!!!!!!!!!!!! LETS FUCKING GOOOOOOOO!!!!!
Diffstat (limited to 'server/src')
4 files changed, 169 insertions, 6 deletions
diff --git a/server/src/main/java/kz/ilotterytea/frogartha/server/FrogarthaServer.java b/server/src/main/java/kz/ilotterytea/frogartha/server/FrogarthaServer.java index 24a607d..dca0afd 100644 --- a/server/src/main/java/kz/ilotterytea/frogartha/server/FrogarthaServer.java +++ b/server/src/main/java/kz/ilotterytea/frogartha/server/FrogarthaServer.java @@ -3,6 +3,8 @@ package kz.ilotterytea.frogartha.server; import com.github.czyzby.websocket.serialization.impl.ManualSerializer; import kz.ilotterytea.frogartha.domain.Identity; import kz.ilotterytea.frogartha.domain.actions.ChangedDirectionAction; +import kz.ilotterytea.frogartha.domain.actions.JoinRoomAction; +import kz.ilotterytea.frogartha.domain.actions.LeaveRoomAction; import kz.ilotterytea.frogartha.domain.actions.PlayerJumpAction; import kz.ilotterytea.frogartha.exceptions.PlayerKickException; import kz.ilotterytea.frogartha.utils.Logger; @@ -21,14 +23,18 @@ public class FrogarthaServer extends WebSocketServer { private static FrogarthaServer instance; private final Logger log; + private final ArrayList<PlayerConnection> players; + private final ArrayList<Room> rooms; private final ManualSerializer serializer; private FrogarthaServer() { super(new InetSocketAddress(20015)); this.log = new Logger(FrogarthaServer.class); + this.players = new ArrayList<>(); + this.rooms = new ArrayList<>(); this.serializer = new ManualSerializer(); SerializerUtils.registerTypes(serializer); @@ -46,6 +52,7 @@ public class FrogarthaServer extends WebSocketServer { Optional<PlayerConnection> player = this.players.stream().filter((x) -> x.getConnection().equals(webSocket)).findFirst(); if (player.isPresent()) { + kickPlayerFromRoom(player.get()); log.log("{} has left! Reason: {} {}", player.get(), i, s); this.players.remove(player.get()); } else { @@ -55,7 +62,12 @@ public class FrogarthaServer extends WebSocketServer { @Override public void onMessage(WebSocket webSocket, String s) { - this.players.removeIf((x) -> x.getConnection().equals(webSocket)); + Optional<PlayerConnection> optionalPlayerConnection = this.players.stream() + .filter((x) -> x.getConnection().equals(webSocket)) + .findFirst(); + + optionalPlayerConnection.ifPresent((x) -> kickConnection(x, PlayerKickException.internalServerError())); + webSocket.send("Invalid input."); webSocket.close(CloseFrame.UNEXPECTED_CONDITION); } @@ -84,6 +96,10 @@ public class FrogarthaServer extends WebSocketServer { ServerHandlers.handlePlayerJumpAction(player, (PlayerJumpAction) obj); } else if (obj instanceof ChangedDirectionAction) { ServerHandlers.handleChangedDirectionAction(player, (ChangedDirectionAction) obj); + } else if (obj instanceof JoinRoomAction) { + ServerHandlers.handleJoinRoomAction(player, (JoinRoomAction) obj); + } else if (obj instanceof LeaveRoomAction) { + ServerHandlers.handleLeaveRoomAction(player, (LeaveRoomAction) obj); } else { throw PlayerKickException.internalServerError(); } @@ -108,12 +124,22 @@ public class FrogarthaServer extends WebSocketServer { } public void kickConnection(PlayerConnection player, PlayerKickException exception) { + kickPlayerFromRoom(player); player.send(exception); player.getConnection().close(); players.remove(player); log.log("Kicked out {}! Reason: {}", player, exception.getMessage()); } + public void kickPlayerFromRoom(PlayerConnection player) { + if (player.getRoom() == null) return; + Room room = player.getRoom(); + room.removePlayer(player); + if (room.getPlayers().isEmpty()) { + this.rooms.remove(room); + } + } + public static FrogarthaServer getInstance() { if (instance == null) instance = new FrogarthaServer(); return instance; @@ -123,6 +149,10 @@ public class FrogarthaServer extends WebSocketServer { return players; } + public ArrayList<Room> getRooms() { + return rooms; + } + public ManualSerializer getSerializer() { return serializer; } diff --git a/server/src/main/java/kz/ilotterytea/frogartha/server/PlayerConnection.java b/server/src/main/java/kz/ilotterytea/frogartha/server/PlayerConnection.java index f30dcfe..56dd695 100644 --- a/server/src/main/java/kz/ilotterytea/frogartha/server/PlayerConnection.java +++ b/server/src/main/java/kz/ilotterytea/frogartha/server/PlayerConnection.java @@ -10,6 +10,7 @@ public class PlayerConnection extends PlayerData { private final int id; private final WebSocket connection; + private Room room; private final Timestamp connectedTimestamp; @@ -18,6 +19,7 @@ public class PlayerConnection extends PlayerData { this.id = TOTAL_CONNECTION_IDS; TOTAL_CONNECTION_IDS++; + this.room = null; this.connectedTimestamp = new Timestamp(System.currentTimeMillis()); } @@ -38,6 +40,14 @@ public class PlayerConnection extends PlayerData { return connection; } + public Room getRoom() { + return room; + } + + public void setRoom(Room room) { + this.room = room; + } + public Timestamp getConnectedTimestamp() { return connectedTimestamp; } diff --git a/server/src/main/java/kz/ilotterytea/frogartha/server/Room.java b/server/src/main/java/kz/ilotterytea/frogartha/server/Room.java new file mode 100644 index 0000000..01f92d4 --- /dev/null +++ b/server/src/main/java/kz/ilotterytea/frogartha/server/Room.java @@ -0,0 +1,58 @@ +package kz.ilotterytea.frogartha.server; + +import kz.ilotterytea.frogartha.domain.PlayerData; +import kz.ilotterytea.frogartha.domain.RoomTopic; +import kz.ilotterytea.frogartha.domain.events.PlayerJoinedRoomEvent; +import kz.ilotterytea.frogartha.domain.events.PlayerLeftRoomEvent; +import kz.ilotterytea.frogartha.domain.events.SenderJoinedRoomEvent; +import kz.ilotterytea.frogartha.domain.events.SenderLeftRoomEvent; + +import java.util.ArrayList; +import java.util.stream.Collectors; + +public class Room { + private final RoomTopic topic; + private final ArrayList<PlayerConnection> players; + + public Room(RoomTopic topic) { + this.topic = topic; + this.players = new ArrayList<>(); + } + + public ArrayList<PlayerConnection> getPlayers() { + return players; + } + + public void addPlayer(PlayerConnection player) { + this.players.forEach((x) -> x.send(new PlayerJoinedRoomEvent(player.getId(), player))); + player.send(new SenderJoinedRoomEvent( + player.getId(), + this.players.stream().map(PlayerConnection::getId).collect(Collectors.toList()), + this.players.stream().map((x) -> (PlayerData) x).collect(Collectors.toList()) + )); + player.setRoom(this); + this.players.add(player); + } + + public void removePlayer(PlayerConnection player) { + player.setRoom(null); + this.players.remove(player); + + this.players.forEach((x) -> x.send(new PlayerLeftRoomEvent(player.getId()))); + if (player.getConnection().isOpen()) { + player.send(new SenderLeftRoomEvent(player.getId())); + } + } + + public RoomTopic getTopic() { + return topic; + } + + @Override + public String toString() { + return "Room{" + + "topic=" + topic + + ", playerSize=" + players.size() + + '}'; + } +} diff --git a/server/src/main/java/kz/ilotterytea/frogartha/server/ServerHandlers.java b/server/src/main/java/kz/ilotterytea/frogartha/server/ServerHandlers.java index 1cc0e57..c1bdbbe 100644 --- a/server/src/main/java/kz/ilotterytea/frogartha/server/ServerHandlers.java +++ b/server/src/main/java/kz/ilotterytea/frogartha/server/ServerHandlers.java @@ -5,13 +5,17 @@ import kz.ilotterytea.frogartha.FrogarthaConstants; import kz.ilotterytea.frogartha.domain.Identity; import kz.ilotterytea.frogartha.domain.PlayerState; import kz.ilotterytea.frogartha.domain.actions.ChangedDirectionAction; +import kz.ilotterytea.frogartha.domain.actions.JoinRoomAction; +import kz.ilotterytea.frogartha.domain.actions.LeaveRoomAction; import kz.ilotterytea.frogartha.domain.actions.PlayerJumpAction; import kz.ilotterytea.frogartha.domain.events.ChangedDirectionEvent; +import kz.ilotterytea.frogartha.domain.events.IdentifiedEvent; import kz.ilotterytea.frogartha.domain.events.PlayerJumpEvent; -import kz.ilotterytea.frogartha.domain.server.Acknowledge; import kz.ilotterytea.frogartha.exceptions.PlayerKickException; import kz.ilotterytea.frogartha.utils.Logger; +import java.util.Optional; + public class ServerHandlers { private static final Logger log = new Logger(ServerHandlers.class); private static final FrogarthaServer server = FrogarthaServer.getInstance(); @@ -26,11 +30,15 @@ public class ServerHandlers { } player.setIdentity(identity); - player.send(new Acknowledge(Acknowledge.AcknowledgeCode.IDENTIFIED)); + player.send(new IdentifiedEvent(player.getId())); log.log("Successfully identified {} for {}", identity, player); } public static void handlePlayerJumpAction(PlayerConnection player, PlayerJumpAction action) { + if (player.getRoom() == null) { + throw PlayerKickException.notInRoom(); + } + PlayerState state = player.getState(); float nowTimestamp = System.currentTimeMillis() / 1000f; @@ -56,18 +64,75 @@ public class ServerHandlers { state.setPosition(endPosition.x, endPosition.y, endPosition.z); - player.send(new PlayerJumpEvent( + PlayerJumpEvent event = new PlayerJumpEvent( player.getId(), startPosition, endPosition, action.getJumpStrength() - )); + ); + player.send(event); log.log("{} jumped from {} to {} with strength {}", player, startPosition, endPosition, action.getJumpStrength()); + + // broadcasting + Room room = player.getRoom(); + room.getPlayers().forEach((x) -> { + if (x.getId() == player.getId()) return; + x.send(event); + }); } public static void handleChangedDirectionAction(PlayerConnection player, ChangedDirectionAction action) { + if (player.getRoom() == null) { + throw PlayerKickException.notInRoom(); + } + PlayerState state = player.getState(); Vector3 direction = action.getDirection(); state.setDirection(direction.x, state.getPosition().y, direction.z); - player.send(new ChangedDirectionEvent(player.getId(), state.getDirection())); + ChangedDirectionEvent event = new ChangedDirectionEvent(player.getId(), state.getDirection()); + player.send(event); + + // broadcasting + Room room = player.getRoom(); + room.getPlayers().forEach((x) -> { + if (x.getId() == player.getId()) return; + x.send(event); + }); + } + + public static void handleJoinRoomAction(PlayerConnection player, JoinRoomAction action) { + Optional<Room> optionalRoom = server.getRooms().stream() + .filter((x) -> + x.getPlayers().size() < FrogarthaConstants.Room.MAX_PLAYERS && + x.getTopic().equals(action.getTopic()) + ) + .findFirst(); + + Room room = optionalRoom.orElse(new Room(action.getTopic())); + room.addPlayer(player); + + if (optionalRoom.isEmpty()) { + server.getRooms().add(room); + } + + log.log("{} joined {}", player, room); + } + + public static void handleLeaveRoomAction(PlayerConnection player, LeaveRoomAction action) { + Optional<Room> optionalRoom = server.getRooms().stream() + .filter((x) -> x.getPlayers().contains(player)) + .findFirst(); + + if (optionalRoom.isEmpty()) { + throw PlayerKickException.illegalOperation(); + } + + Room room = optionalRoom.get(); + room.removePlayer(player); + + if (room.getPlayers().isEmpty()) { + server.getRooms().remove(room); + } + + log.log("{} left {}", player, room); } } |
