From 9c20fcbc39b990a4638cbbf0e1a5a522887256b6 Mon Sep 17 00:00:00 2001 From: lieght <49651652+BAFGdeJong@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:01:28 +0100 Subject: [PATCH] Fixed bugs, easy to use host button --- app/src/main/java/org/toop/app/App.java | 20 ---------- app/src/main/java/org/toop/app/Server.java | 2 +- .../org/toop/app/widget/view/OnlineView.java | 33 ++++++++++++++- .../connection/events/NetworkEvents.java | 2 +- .../networking/server/GameChallenge.java | 14 ++++--- .../framework/networking/server/Server.java | 40 ++++++++++--------- .../networking/server/ServerHandler.java | 23 +++++++++-- 7 files changed, 83 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/org/toop/app/App.java b/app/src/main/java/org/toop/app/App.java index 9245318..9645cd5 100644 --- a/app/src/main/java/org/toop/app/App.java +++ b/app/src/main/java/org/toop/app/App.java @@ -20,15 +20,8 @@ import org.toop.framework.audio.*; import org.toop.framework.audio.events.AudioEvents; import org.toop.framework.eventbus.EventFlow; import org.toop.framework.eventbus.GlobalEventBus; -import org.toop.framework.game.BitboardGame; -import org.toop.framework.game.games.reversi.BitboardReversi; -import org.toop.framework.game.games.tictactoe.BitboardTicTacToe; -import org.toop.framework.gameFramework.model.game.TurnBasedGame; import org.toop.framework.networking.connection.NetworkingClientEventListener; import org.toop.framework.networking.connection.NetworkingClientManager; -import org.toop.framework.networking.server.GameDefinition; -import org.toop.framework.networking.server.MasterServer; -import org.toop.framework.networking.server.Server; import org.toop.framework.resource.ResourceLoader; import org.toop.framework.resource.ResourceManager; import org.toop.framework.resource.events.AssetLoaderEvents; @@ -38,9 +31,7 @@ import org.toop.framework.resource.resources.SoundEffectAsset; import org.toop.local.AppContext; import org.toop.local.AppSettings; -import java.time.Duration; import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -101,17 +92,6 @@ public final class App extends Application { WidgetContainer.setCurrentView(loading); - var games = new ConcurrentHashMap>(); - games.put("tictactoe", BitboardTicTacToe.class); - games.put("reversi", BitboardReversi.class); - - var a = new MasterServer(6666, games, Duration.ofSeconds(5)); - try { - a.start(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - setOnLoadingSuccess(loading); EventFlow loadingFlow = new EventFlow(); diff --git a/app/src/main/java/org/toop/app/Server.java b/app/src/main/java/org/toop/app/Server.java index 6c73aa1..d1eb6bb 100644 --- a/app/src/main/java/org/toop/app/Server.java +++ b/app/src/main/java/org/toop/app/Server.java @@ -263,7 +263,7 @@ public final class Server { String gameType = extractQuotedValue(response.gameType()); final String finalGameType = gameType; var a = new ChallengePopup(challengerName, gameType, (playerInformation) -> { - final int challengeId = Integer.parseInt(response.challengeId().replaceAll("\\D", "")); + final long challengeId = Long.parseLong(response.challengeId().replaceAll("\\D", "")); new EventFlow().addPostEvent(new NetworkEvents.SendAcceptChallenge(clientId, challengeId)).postEvent(); isSingleGame.set(true); }); diff --git a/app/src/main/java/org/toop/app/widget/view/OnlineView.java b/app/src/main/java/org/toop/app/widget/view/OnlineView.java index 16ed1df..2dc51a8 100644 --- a/app/src/main/java/org/toop/app/widget/view/OnlineView.java +++ b/app/src/main/java/org/toop/app/widget/view/OnlineView.java @@ -6,6 +6,13 @@ import org.toop.app.widget.complex.LabeledInputWidget; import org.toop.app.widget.complex.ViewWidget; import javafx.geometry.Pos; +import org.toop.framework.game.games.reversi.BitboardReversi; +import org.toop.framework.game.games.tictactoe.BitboardTicTacToe; +import org.toop.framework.gameFramework.model.game.TurnBasedGame; +import org.toop.framework.networking.server.MasterServer; + +import java.time.Duration; +import java.util.concurrent.ConcurrentHashMap; public class OnlineView extends ViewWidget { public OnlineView() { @@ -23,6 +30,28 @@ public class OnlineView extends ViewWidget { ); }); + var localHostButton = Primitive.button("host!", () -> { + var games = new ConcurrentHashMap>(); + games.put("tictactoe", BitboardTicTacToe.class); + games.put("reversi", BitboardReversi.class); + + var a = new MasterServer(6666, games, Duration.ofSeconds(10)); + + new Thread(() -> { + try { + a.start(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }).start(); + + new Server( + "127.0.0.1", + "6666", + "host" + ); + }, false); + add(Pos.CENTER, Primitive.vbox( serverInformationHeader, Primitive.separator(), @@ -32,7 +61,9 @@ public class OnlineView extends ViewWidget { playerNameInput.getNode(), Primitive.separator(), - connectButton + connectButton, + Primitive.separator(), + localHostButton )); } } \ No newline at end of file diff --git a/framework/src/main/java/org/toop/framework/networking/connection/events/NetworkEvents.java b/framework/src/main/java/org/toop/framework/networking/connection/events/NetworkEvents.java index d6c0140..22f9588 100644 --- a/framework/src/main/java/org/toop/framework/networking/connection/events/NetworkEvents.java +++ b/framework/src/main/java/org/toop/framework/networking/connection/events/NetworkEvents.java @@ -102,7 +102,7 @@ public class NetworkEvents extends EventsBase { implements GenericEvent {} /** Requests to accept an existing challenge. */ - public record SendAcceptChallenge(long clientId, int challengeId) + public record SendAcceptChallenge(long clientId, long challengeId) implements GenericEvent {} /** Requests to forfeit the current game. */ diff --git a/framework/src/main/java/org/toop/framework/networking/server/GameChallenge.java b/framework/src/main/java/org/toop/framework/networking/server/GameChallenge.java index 0c936a5..50a5c2b 100644 --- a/framework/src/main/java/org/toop/framework/networking/server/GameChallenge.java +++ b/framework/src/main/java/org/toop/framework/networking/server/GameChallenge.java @@ -5,14 +5,14 @@ import org.toop.framework.SnowflakeGenerator; public class GameChallenge { private final long id = SnowflakeGenerator.nextId(); // I don't need this, but the tournament server uses it... - private final ServerUser from; - private final ServerUser to; + private final User from; + private final User to; private final String gameType; private final SimpleTimer timer; private boolean isChallengeAccepted = false; - public GameChallenge(ServerUser from, ServerUser to, String gameType, SimpleTimer timer) { + public GameChallenge(User from, User to, String gameType, SimpleTimer timer) { this.from = from; this.to = to; this.gameType = gameType; @@ -23,8 +23,8 @@ public class GameChallenge { return id; } - public ServerUser[] getUsers() { - return new ServerUser[]{from, to}; + public User[] getUsers() { + return new User[]{from, to}; } public void forceExpire() { @@ -37,6 +37,10 @@ public class GameChallenge { return gameType; } + public boolean isChallengeAccepted() { + return isChallengeAccepted; + } + public boolean isExpired() { return timer.isExpired(); } diff --git a/framework/src/main/java/org/toop/framework/networking/server/Server.java b/framework/src/main/java/org/toop/framework/networking/server/Server.java index 80e7792..dc35906 100644 --- a/framework/src/main/java/org/toop/framework/networking/server/Server.java +++ b/framework/src/main/java/org/toop/framework/networking/server/Server.java @@ -13,7 +13,7 @@ import java.time.Duration; public class Server implements GameServer { final private Map> gameTypes; - final private Map users = new ConcurrentHashMap<>(); + final private Map users = new ConcurrentHashMap<>(); final private List gameChallenges = new CopyOnWriteArrayList<>(); final private List> games = new CopyOnWriteArrayList<>(); @@ -32,53 +32,53 @@ public class Server implements GameServer { scheduler.schedule(this::serverTask, 500, TimeUnit.MILLISECONDS); } - public void addUser(ServerUser user) { + public void addUser(User user) { users.putIfAbsent(user.id(), user); } - public void removeUser(ServerUser user) { + public void removeUser(User user) { users.remove(user.id()); } - public String[] gameTypes() { - return gameTypes.keySet().toArray(new String[0]); + public List gameTypes() { + return gameTypes.keySet().stream().toList(); } public List> ongoingGames() { return games; } - public ServerUser getUser(String username) { + public User getUser(String username) { return users.values().stream().filter(e -> e.name().equalsIgnoreCase(username)).findFirst().orElse(null); } - public ServerUser getUser(long id) { + public User getUser(long id) { return users.get(id); } public void challengeUser(String fromUser, String toUser, String gameType) { - ServerUser from = getUser(fromUser); + User from = getUser(fromUser); if (from == null) { return; } if (!gameTypes.containsKey(gameType)) { - from.sendMessage("ERR gametype not found"); + from.sendMessage("ERR gametype not found \n"); return; } - ServerUser to = getUser(toUser); + User to = getUser(toUser); if (to == null) { - from.sendMessage("ERR user not found"); + from.sendMessage("ERR user not found \n"); return; } var ch = new GameChallenge(from, to, gameType, new GameChallengeTimer(challengeDuration)); to.sendMessage( - "\"SVR GAME CHALLENGE {CHALLENGER: \"%s\", GAMETYPE: \"%s\", CHALLENGENUMBER: \"%s\"}" - .formatted(from.name(), gameType, ch.id()) + "SVR GAME CHALLENGE {CHALLENGER: \"%s\", CHALLENGENUMBER: \"%s\", GAMETYPE: \"%s\"} \n" + .formatted(from.name(), ch.id(), gameType) ); if (!isValidChallenge(ch)) { @@ -90,8 +90,8 @@ public class Server implements GameServer { gameChallenges.addLast(ch); } - private void warnUserExpiredChallenge(ServerUser user, long challengeId) { - user.sendMessage("SVR GAME CHALLENGE CANCELLED {CHALLENGENUMBER: \"" + challengeId + "\"}"); + private void warnUserExpiredChallenge(User user, long challengeId) { + user.sendMessage("SVR GAME CHALLENGE CANCELLED {CHALLENGENUMBER: \"" + challengeId + "\"}" + "\n"); } private boolean isValidChallenge(GameChallenge gameChallenge) { @@ -119,7 +119,9 @@ public class Server implements GameServer { if (isValidChallenge(challenge)) continue; if (challenge.isExpired()) { - Arrays.stream(challenge.getUsers()).forEach(user -> warnUserExpiredChallenge(user, challenge.id())); + if (!challenge.isChallengeAccepted()) Arrays.stream(challenge.getUsers()) + .forEach(user -> warnUserExpiredChallenge(user, challenge.id())); + gameChallenges.remove(i); } } @@ -128,7 +130,7 @@ public class Server implements GameServer { public void acceptChallenge(long challengeId) { for (var challenge : gameChallenges) { if (challenge.id() == challengeId) { - startGame(challenge.acceptChallenge(), (User[]) challenge.getUsers()); + startGame(challenge.acceptChallenge(), challenge.getUsers()); break; } } @@ -162,8 +164,8 @@ public class Server implements GameServer { // } // } - public String[] onlineUsers() { - return users.values().stream().map(ServerUser::name).toArray(String[]::new); + public List onlineUsers() { + return users.values().stream().toList(); } public void closeServer() { diff --git a/framework/src/main/java/org/toop/framework/networking/server/ServerHandler.java b/framework/src/main/java/org/toop/framework/networking/server/ServerHandler.java index 8357abb..f31912f 100644 --- a/framework/src/main/java/org/toop/framework/networking/server/ServerHandler.java +++ b/framework/src/main/java/org/toop/framework/networking/server/ServerHandler.java @@ -2,8 +2,10 @@ package org.toop.framework.networking.server; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; +import org.apache.maven.surefire.shared.utils.StringUtils; import java.util.Arrays; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -17,6 +19,10 @@ public class ServerHandler extends SimpleChannelInboundHandler { this.server = server; } + private String returnQuotedString(Iterator strings) { // TODO more places this could be useful + return "\"" + StringUtils.join(strings, "\",\"") + "\""; + } + @Override public void channelActive(ChannelHandlerContext ctx) { ctx.writeAndFlush("WELCOME " + user.id() + "\n"); @@ -27,6 +33,9 @@ public class ServerHandler extends SimpleChannelInboundHandler { @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) { + + IO.println(msg); + ParsedMessage p = parse(msg); if (p == null) return; @@ -61,8 +70,14 @@ public class ServerHandler extends SimpleChannelInboundHandler { if (!allowedArgs(p.args())) return; switch (p.args()[0]) { - case "playerlist" -> user.ctx().writeAndFlush(Arrays.toString(server.onlineUsers())); - case "gamelist" -> user.ctx().writeAndFlush(Arrays.toString(server.gameTypes())); + case "playerlist" -> { + var names = server.onlineUsers().stream().map(ServerUser::name).iterator(); + user.ctx().writeAndFlush("SVR PLAYERLIST " + returnQuotedString(names) + "\n"); + } + case "gamelist" -> { + var names = server.gameTypes().stream().iterator(); + user.ctx().writeAndFlush("SVR GAMELIST " + returnQuotedString(names) + "\n"); + } } } @@ -87,14 +102,14 @@ public class ServerHandler extends SimpleChannelInboundHandler { long id = Long.parseLong(p.args()[1]); if (id <= 0) { - user.sendMessage("ERR id must be a positive number"); + user.sendMessage("ERR id must be a positive number \n"); return; } server.acceptChallenge(id); } catch (NumberFormatException e) { - user.sendMessage("ERR id is not a valid number or too big"); + user.sendMessage("ERR id is not a valid number or too big \n"); return; } return;