Skip to content

Commit

Permalink
feat: Start on making networking thread-safe.
Browse files Browse the repository at this point in the history
Closes #38.
  • Loading branch information
crykn committed Dec 27, 2023
1 parent 65d401a commit 67a7ecf
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ public ReadyableGameServer(ServerSettings serverSettings,
}

@Override
protected void onPlayerChange(Connection con, C2SChangePlayerPacket msg) {
protected synchronized void onPlayerChange(Connection con,
C2SChangePlayerPacket msg) {
super.onPlayerChange(con, msg);

for (P p : lobbyData.getPlayers().values()) {
Expand Down
29 changes: 17 additions & 12 deletions engine/src/main/java/de/eskalon/commons/net/SimpleGameClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import de.damios.guacamole.gdx.log.Logger;
import de.damios.guacamole.gdx.log.LoggerService;
import de.eskalon.commons.net.data.ChatMessage;
import de.eskalon.commons.net.packets.chat.C2SSendChatMessagePacke;
import de.eskalon.commons.net.packets.chat.C2SSendChatMessagePacket;
import de.eskalon.commons.net.packets.chat.S2CChatMessageReceivedPacket;
import de.eskalon.commons.net.packets.data.LobbyData;
import de.eskalon.commons.net.packets.handshake.C2SRequestJoiningLobbyPacket;
Expand Down Expand Up @@ -125,19 +125,24 @@ public void disconnected(Connection connection) {
});
// Lobby data syncing
listener.addTypeHandler(S2CLobbyDataChangedPacket.class, (con, msg) -> {
LobbyData<G, S, P> tmp = this.lobbyData;
this.lobbyData = msg.getLobbyData();
synchronized (SimpleGameClient.this) {
LobbyData<G, S, P> tmp = this.lobbyData;
this.lobbyData = msg.getLobbyData();

onLobbyDataChanged(tmp, msg.getLobbyData(), msg.getChangeType());
onLobbyDataChanged(tmp, msg.getLobbyData(),
msg.getChangeType());
}
});
// Chat messages
listener.addTypeHandler(S2CChatMessageReceivedPacket.class,
(con, msg) -> {
ChatMessage chatMessage = new ChatMessage<>(
lobbyData.getPlayers().get(msg.getSender()),
msg.getMessage());
chatMessages.add(chatMessage);
onChatMessageReceived(chatMessage);
synchronized (SimpleGameClient.this) {
ChatMessage chatMessage = new ChatMessage<>(
lobbyData.getPlayers().get(msg.getSender()),
msg.getMessage());
chatMessages.add(chatMessage);
onChatMessageReceived(chatMessage);
}
});
// Ping
listener.addTypeHandler(Ping.class, (con, msg) -> {
Expand Down Expand Up @@ -186,7 +191,7 @@ public void stop() {
* The time delta in seconds.
* @see #PING_UPDATE_INTERVAL
*/
public synchronized void updatePing(float delta) {
public void updatePing(float delta) {
timeSinceLastPingUpdate += delta;

if (timeSinceLastPingUpdate >= PING_UPDATE_INTERVAL) {
Expand All @@ -213,8 +218,8 @@ public ArrayList<ChatMessage<P>> getChatMessages() {
return chatMessages;
}

public void sendChatMessage(String message) {
client.sendTCP(new C2SSendChatMessagePacke(message));
public synchronized void sendChatMessage(String message) {
client.sendTCP(new C2SSendChatMessagePacket(message));
chatMessages.add(new ChatMessage(
lobbyData.getPlayers().get(localClientId), message));
}
Expand Down
42 changes: 24 additions & 18 deletions engine/src/main/java/de/eskalon/commons/net/SimpleGameServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import de.eskalon.commons.lang.Lang;
import de.eskalon.commons.net.data.ServerSettings;
import de.eskalon.commons.net.packets.S2CDiscoveryResponsePacket;
import de.eskalon.commons.net.packets.chat.C2SSendChatMessagePacke;
import de.eskalon.commons.net.packets.chat.C2SSendChatMessagePacket;
import de.eskalon.commons.net.packets.chat.S2CChatMessageReceivedPacket;
import de.eskalon.commons.net.packets.data.LobbyData;
import de.eskalon.commons.net.packets.handshake.C2SRequestJoiningLobbyPacket;
Expand Down Expand Up @@ -97,25 +97,29 @@ public void disconnected(Connection con) {
(con, msg) -> onPlayerChange(con, msg));
typeListener.addTypeHandler(C2SChangeGameSetupPacket.class,
(con, msg) -> {
if ((short) con
.getArbitraryData() == HOST_PLAYER_NETWORK_ID) {
lobbyData.setGameState(msg.getGameState());
lobbyData.setSessionSetup(msg.getSessionSetup());
server.sendToAllTCP(new S2CLobbyDataChangedPacket(
ChangeType.DATA_CHANGE, lobbyData));
} else {
LOG.warn(
"[SERVER] Non-host player %d tried to change the lobby data!",
(short) con.getArbitraryData());
synchronized (SimpleGameServer.this) {
if ((short) con
.getArbitraryData() == HOST_PLAYER_NETWORK_ID) {
lobbyData.setGameState(msg.getGameState());
lobbyData.setSessionSetup(msg.getSessionSetup());
server.sendToAllTCP(new S2CLobbyDataChangedPacket(
ChangeType.DATA_CHANGE, lobbyData));
} else {
LOG.warn(
"[SERVER] Non-host player %d tried to change the lobby data!",
(short) con.getArbitraryData());
}
}
});
// Chat messages
typeListener.addTypeHandler(C2SSendChatMessagePacke.class,
typeListener.addTypeHandler(C2SSendChatMessagePacket.class,
(con, msg) -> {
server.sendToAllExceptTCP(con.getID(),
new S2CChatMessageReceivedPacket(
(short) con.getArbitraryData(),
msg.getMessage()));
synchronized (SimpleGameServer.this) {
server.sendToAllExceptTCP(con.getID(),
new S2CChatMessageReceivedPacket(
(short) con.getArbitraryData(),
msg.getMessage()));
}
});
server.addListener(typeListener);
}
Expand Down Expand Up @@ -155,7 +159,8 @@ private void startBroadcastServer() {
broadcastServer.getKryo().register(S2CDiscoveryResponsePacket.class);
broadcastServer.setDiscoveryHandler(new ServerDiscoveryHandler() {
@Override
public boolean onDiscoverHost(DatagramChannel datagramChannel,
public synchronized boolean onDiscoverHost(
DatagramChannel datagramChannel,
InetSocketAddress fromAddress) throws IOException {
S2CDiscoveryResponsePacket packet = new S2CDiscoveryResponsePacket(
serverSettings.getPort(), serverSettings.getGameName(),
Expand Down Expand Up @@ -235,7 +240,8 @@ private synchronized void onLobbyJoinRequest(Connection con,
ChangeType.PLAYER_JOINED, lobbyData));
}

protected void onPlayerChange(Connection con, C2SChangePlayerPacket msg) {
protected synchronized void onPlayerChange(Connection con,
C2SChangePlayerPacket msg) {
lobbyData.getPlayers().put((short) con.getArbitraryData(),
(P) msg.getPlayerData());
server.sendToAllTCP(new S2CLobbyDataChangedPacket(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

@AllArgsConstructor
@NoArgsConstructor
public final class C2SSendChatMessagePacke {
public final class C2SSendChatMessagePacket {

private @Getter String message;

Expand Down
16 changes: 9 additions & 7 deletions game/src/main/java/de/eskalon/gg/net/GameClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
import de.eskalon.gg.events.LobbyDataChangedEvent;
import de.eskalon.gg.events.VoteFinishedEvent;
import de.eskalon.gg.net.packets.ArrangeVotePacket;
import de.eskalon.gg.net.packets.CastVotePacket;
import de.eskalon.gg.net.packets.VoteFinishedPacket;
import de.eskalon.gg.net.packets.C2SCastVotePacket;
import de.eskalon.gg.net.packets.S2CVoteFinishedPacket;
import de.eskalon.gg.net.packets.data.VoteType;
import de.eskalon.gg.simulation.GameSetup;
import de.eskalon.gg.simulation.GameState;
Expand All @@ -49,10 +49,12 @@ public GameClient() {

TypeListener typeListener = new TypeListener();
typeListener.addTypeHandler(ArrangeVotePacket.class, (con, msg) -> {
LOG.debug("[CLIENT] A new vote was arranged");
mattersToVoteOn.add(msg);
synchronized (GameClient.this) {
LOG.debug("[CLIENT] A new vote was arranged");
mattersToVoteOn.add(msg);
}
});
typeListener.addTypeHandler(VoteFinishedPacket.class, (con, msg) -> {
typeListener.addTypeHandler(S2CVoteFinishedPacket.class, (con, msg) -> {
eventBus.post(new VoteFinishedEvent(msg.getIndividualVotes()));
});
client.addListener(typeListener);
Expand Down Expand Up @@ -83,7 +85,7 @@ protected void onChatMessageReceived(ChatMessage msg) {
}

@Override
protected void onLobbyDataChanged(
protected synchronized void onLobbyDataChanged(
LobbyData<GameSetup, GameState, PlayerData> oldData,
LobbyData<GameSetup, GameState, PlayerData> newData,
ChangeType changeType) {
Expand Down Expand Up @@ -121,7 +123,7 @@ public void arrangeVote(VoteType impeachment, short callerId,
}

public void castVote(int option) {
client.sendTCP(new CastVotePacket(option));
client.sendTCP(new C2SCastVotePacket(option));
}

/**
Expand Down
36 changes: 20 additions & 16 deletions game/src/main/java/de/eskalon/gg/net/GameServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
import de.eskalon.gg.misc.PlayerUtils;
import de.eskalon.gg.misc.PlayerUtils.PlayerTemplate;
import de.eskalon.gg.net.packets.ArrangeVotePacket;
import de.eskalon.gg.net.packets.CastVotePacket;
import de.eskalon.gg.net.packets.VoteFinishedPacket;
import de.eskalon.gg.net.packets.C2SCastVotePacket;
import de.eskalon.gg.net.packets.S2CVoteFinishedPacket;
import de.eskalon.gg.simulation.GameSetup;
import de.eskalon.gg.simulation.GameSimulation;
import de.eskalon.gg.simulation.GameState;
Expand Down Expand Up @@ -55,19 +55,23 @@ public GameServer(ServerSettings serverSettings, GameSetup sessionSetup,

TypeListener typeListener = new TypeListener();
typeListener.addTypeHandler(ArrangeVotePacket.class, (con, msg) -> {
// TODO check whether the player is allowed to arrange the vote; if
// not send an OutOfSyncMessage(crash = false) to the client!
server.sendToAllTCP(msg);
mattersToVoteOn.add(msg);

LOG.debug("[SERVER] Player %d has arranged a vote",
(short) con.getArbitraryData());

// TODO: for applications, also send an IPlayerAction, which does
// the following:
// pos.getApplicants().add(world.getPlayer(clientId).getCurrentlyPlayedCharacterId());
synchronized (GameServer.this) {
// TODO check whether the player is allowed to arrange the vote;
// if
// not send an OutOfSyncMessage(crash = false) to the client!
server.sendToAllTCP(msg);
mattersToVoteOn.add(msg);

LOG.debug("[SERVER] Player %d has arranged a vote",
(short) con.getArbitraryData());

// TODO: for applications, also send an IPlayerAction, which
// does
// the following:
// pos.getApplicants().add(world.getPlayer(clientId).getCurrentlyPlayedCharacterId());
}
});
typeListener.addTypeHandler(CastVotePacket.class, (con, msg) -> {
typeListener.addTypeHandler(C2SCastVotePacket.class, (con, msg) -> {
// TODO check whether player is allowed to vote; if not send an
// OutOfSyncMessage(crash = false) to the client!
LOG.debug("[SERVER] Player %d has cast a vote",
Expand All @@ -80,7 +84,7 @@ public GameServer(ServerSettings serverSettings, GameSetup sessionSetup,
}

@Override
public void onAllActionsReceived(int tick,
public synchronized void onAllActionsReceived(int tick,
List<PlayerActionsWrapper> list) {
LOG.trace("[SERVER] Processing tick %d", tick);
simulation.onSimulationTick(tick, list);
Expand Down Expand Up @@ -117,7 +121,7 @@ private void processMatterToVoteOn() {
"[SERVER] Voting on the current matter was closed. %d votes were received.",
receivedVotes.size());

server.sendToAllTCP(new VoteFinishedPacket(receivedVotes));
server.sendToAllTCP(new S2CVoteFinishedPacket(receivedVotes));
simulation.processVotes(matterToVoteOn, receivedVotes);
receivedVotes.clear();
matterToVoteOn = null;
Expand Down
12 changes: 6 additions & 6 deletions game/src/main/java/de/eskalon/gg/net/NetworkRegisterer.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.badlogic.gdx.utils.IntMap;
import com.esotericsoftware.kryo.Kryo;

import de.eskalon.commons.net.packets.chat.C2SSendChatMessagePacke;
import de.eskalon.commons.net.packets.chat.C2SSendChatMessagePacket;
import de.eskalon.commons.net.packets.chat.S2CChatMessageReceivedPacket;
import de.eskalon.commons.net.packets.data.IPlayerAction;
import de.eskalon.commons.net.packets.data.IReadyable;
Expand All @@ -24,8 +24,8 @@
import de.eskalon.commons.net.packets.sync.S2CLobbyDataChangedPacket;
import de.eskalon.commons.net.packets.sync.S2CLobbyDataChangedPacket.ChangeType;
import de.eskalon.gg.net.packets.ArrangeVotePacket;
import de.eskalon.gg.net.packets.CastVotePacket;
import de.eskalon.gg.net.packets.VoteFinishedPacket;
import de.eskalon.gg.net.packets.C2SCastVotePacket;
import de.eskalon.gg.net.packets.S2CVoteFinishedPacket;
import de.eskalon.gg.net.packets.data.VoteType;
import de.eskalon.gg.simulation.GameSetup;
import de.eskalon.gg.simulation.actions.GameSpeedChangeAction;
Expand Down Expand Up @@ -71,7 +71,7 @@ public static void registerClasses(Kryo kryo) {

// Engine packets
kryo.register(S2CChatMessageReceivedPacket.class);
kryo.register(C2SSendChatMessagePacke.class);
kryo.register(C2SSendChatMessagePacket.class);

kryo.register(S2CConnectionEstablishedPacket.class);
kryo.register(S2CConnectionRejectedPacket.class);
Expand All @@ -93,8 +93,8 @@ public static void registerClasses(Kryo kryo) {

// GG packets
kryo.register(ArrangeVotePacket.class);
kryo.register(VoteFinishedPacket.class);
kryo.register(CastVotePacket.class);
kryo.register(S2CVoteFinishedPacket.class);
kryo.register(C2SCastVotePacket.class);

// Lobby (Player) Stuff
kryo.register(PlayerData.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

@AllArgsConstructor
@NoArgsConstructor
public final class CastVotePacket {
public final class C2SCastVotePacket {

private @Getter int option;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

@AllArgsConstructor
@NoArgsConstructor
public final class VoteFinishedPacket {
public final class S2CVoteFinishedPacket {

private @Getter HashMap<Short, Integer> individualVotes;

Expand Down

0 comments on commit 67a7ecf

Please sign in to comment.