Init server code

This commit is contained in:
Bas de Jong
2025-12-12 15:15:55 +01:00
parent 0132981d94
commit 66cb000fad
49 changed files with 475 additions and 92 deletions

View File

@@ -14,14 +14,14 @@ import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.gameFramework.controller.GameController; import org.toop.framework.gameFramework.controller.GameController;
import org.toop.framework.eventbus.GlobalEventBus; import org.toop.framework.eventbus.GlobalEventBus;
import org.toop.framework.gameFramework.model.player.Player; import org.toop.framework.gameFramework.model.player.Player;
import org.toop.framework.networking.clients.TournamentNetworkingClient; import org.toop.framework.networking.connection.clients.TournamentNetworkingClient;
import org.toop.framework.networking.events.NetworkEvents; import org.toop.framework.networking.connection.events.NetworkEvents;
import org.toop.framework.networking.types.NetworkingConnector; import org.toop.framework.networking.connection.types.NetworkingConnector;
import org.toop.game.games.reversi.BitboardReversi; import org.toop.framework.game.games.reversi.BitboardReversi;
import org.toop.game.games.tictactoe.BitboardTicTacToe; import org.toop.framework.game.games.tictactoe.BitboardTicTacToe;
import org.toop.game.players.ArtificialPlayer; import org.toop.framework.game.players.ArtificialPlayer;
import org.toop.game.players.OnlinePlayer; import org.toop.framework.game.players.OnlinePlayer;
import org.toop.game.players.RandomAI; import org.toop.framework.game.players.RandomAI;
import org.toop.local.AppContext; import org.toop.local.AppContext;
import java.util.List; import java.util.List;

View File

@@ -2,10 +2,7 @@ package org.toop.app.canvas;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import org.toop.app.App; import org.toop.app.App;
import org.toop.game.games.reversi.BitboardReversi; import org.toop.framework.game.games.reversi.BitboardReversi;
import java.util.Arrays;
import java.util.function.Consumer;
public class ReversiBitCanvas extends BitGameCanvas<BitboardReversi> { public class ReversiBitCanvas extends BitGameCanvas<BitboardReversi> {
public ReversiBitCanvas() { public ReversiBitCanvas() {

View File

@@ -2,10 +2,7 @@ package org.toop.app.canvas;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import org.toop.app.App; import org.toop.app.App;
import org.toop.game.games.tictactoe.BitboardTicTacToe; import org.toop.framework.game.games.tictactoe.BitboardTicTacToe;
import java.util.Arrays;
import java.util.function.Consumer;
public class TicTacToeBitCanvas extends BitGameCanvas<BitboardTicTacToe>{ public class TicTacToeBitCanvas extends BitGameCanvas<BitboardTicTacToe>{
public TicTacToeBitCanvas() { public TicTacToeBitCanvas() {

View File

@@ -15,8 +15,8 @@ import org.toop.framework.gameFramework.model.game.TurnBasedGame;
import org.toop.framework.gameFramework.model.game.threadBehaviour.ThreadBehaviour; import org.toop.framework.gameFramework.model.game.threadBehaviour.ThreadBehaviour;
import org.toop.framework.gameFramework.model.player.Player; import org.toop.framework.gameFramework.model.player.Player;
import org.toop.framework.gameFramework.view.GUIEvents; import org.toop.framework.gameFramework.view.GUIEvents;
import org.toop.framework.networking.events.NetworkEvents; import org.toop.framework.networking.connection.events.NetworkEvents;
import org.toop.game.players.LocalPlayer; import org.toop.framework.game.players.LocalPlayer;
public class GenericGameController<T extends TurnBasedGame<T>> implements GameController { public class GenericGameController<T extends TurnBasedGame<T>> implements GameController {
protected final EventFlow eventFlow = new EventFlow(); protected final EventFlow eventFlow = new EventFlow();

View File

@@ -3,10 +3,10 @@ package org.toop.app.gameControllers;
import org.toop.app.canvas.ReversiBitCanvas; import org.toop.app.canvas.ReversiBitCanvas;
import org.toop.framework.gameFramework.model.game.threadBehaviour.ThreadBehaviour; import org.toop.framework.gameFramework.model.game.threadBehaviour.ThreadBehaviour;
import org.toop.framework.gameFramework.model.player.Player; import org.toop.framework.gameFramework.model.player.Player;
import org.toop.game.gameThreads.LocalThreadBehaviour; import org.toop.framework.game.gameThreads.LocalThreadBehaviour;
import org.toop.game.gameThreads.OnlineThreadBehaviour; import org.toop.framework.game.gameThreads.OnlineThreadBehaviour;
import org.toop.game.games.reversi.BitboardReversi; import org.toop.framework.game.games.reversi.BitboardReversi;
import org.toop.game.players.OnlinePlayer; import org.toop.framework.game.players.OnlinePlayer;
public class ReversiBitController extends GenericGameController<BitboardReversi> { public class ReversiBitController extends GenericGameController<BitboardReversi> {
public ReversiBitController(Player<BitboardReversi>[] players) { public ReversiBitController(Player<BitboardReversi>[] players) {

View File

@@ -3,11 +3,10 @@ package org.toop.app.gameControllers;
import org.toop.app.canvas.TicTacToeBitCanvas; import org.toop.app.canvas.TicTacToeBitCanvas;
import org.toop.framework.gameFramework.model.game.threadBehaviour.ThreadBehaviour; import org.toop.framework.gameFramework.model.game.threadBehaviour.ThreadBehaviour;
import org.toop.framework.gameFramework.model.player.Player; import org.toop.framework.gameFramework.model.player.Player;
import org.toop.game.gameThreads.LocalFixedRateThreadBehaviour; import org.toop.framework.game.gameThreads.LocalThreadBehaviour;
import org.toop.game.gameThreads.LocalThreadBehaviour; import org.toop.framework.game.gameThreads.OnlineThreadBehaviour;
import org.toop.game.gameThreads.OnlineThreadBehaviour; import org.toop.framework.game.games.tictactoe.BitboardTicTacToe;
import org.toop.game.games.tictactoe.BitboardTicTacToe; import org.toop.framework.game.players.OnlinePlayer;
import org.toop.game.players.OnlinePlayer;
public class TicTacToeBitController extends GenericGameController<BitboardTicTacToe> { public class TicTacToeBitController extends GenericGameController<BitboardTicTacToe> {
public TicTacToeBitController(Player<BitboardTicTacToe>[] players) { public TicTacToeBitController(Player<BitboardTicTacToe>[] players) {

View File

@@ -2,24 +2,21 @@ package org.toop.app.widget.view;
import javafx.application.Platform; import javafx.application.Platform;
import org.toop.app.GameInformation; import org.toop.app.GameInformation;
import org.toop.app.canvas.ReversiBitCanvas;
import org.toop.app.canvas.TicTacToeBitCanvas;
import org.toop.app.gameControllers.GenericGameController;
import org.toop.app.gameControllers.ReversiBitController; import org.toop.app.gameControllers.ReversiBitController;
import org.toop.app.gameControllers.TicTacToeBitController; import org.toop.app.gameControllers.TicTacToeBitController;
import org.toop.framework.gameFramework.controller.GameController; import org.toop.framework.gameFramework.controller.GameController;
import org.toop.framework.gameFramework.model.player.Player; import org.toop.framework.gameFramework.model.player.Player;
import org.toop.game.games.reversi.BitboardReversi; import org.toop.framework.game.games.reversi.BitboardReversi;
import org.toop.game.games.tictactoe.BitboardTicTacToe; import org.toop.framework.game.games.tictactoe.BitboardTicTacToe;
import org.toop.game.players.ArtificialPlayer; import org.toop.framework.game.players.ArtificialPlayer;
import org.toop.game.players.LocalPlayer; import org.toop.framework.game.players.LocalPlayer;
import org.toop.app.widget.Primitive; import org.toop.app.widget.Primitive;
import org.toop.app.widget.complex.PlayerInfoWidget; import org.toop.app.widget.complex.PlayerInfoWidget;
import org.toop.app.widget.complex.ViewWidget; import org.toop.app.widget.complex.ViewWidget;
import org.toop.app.widget.popup.ErrorPopup; import org.toop.app.widget.popup.ErrorPopup;
import org.toop.app.widget.tutorial.*; import org.toop.app.widget.tutorial.*;
import org.toop.game.players.MiniMaxAI; import org.toop.framework.game.players.MiniMaxAI;
import org.toop.game.players.RandomAI; import org.toop.framework.game.players.RandomAI;
import org.toop.local.AppContext; import org.toop.local.AppContext;
import javafx.geometry.Pos; import javafx.geometry.Pos;
@@ -27,9 +24,6 @@ import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import org.toop.local.AppSettings; import org.toop.local.AppSettings;
import java.util.Arrays;
import java.util.Random;
public class LocalMultiplayerView extends ViewWidget { public class LocalMultiplayerView extends ViewWidget {
private final GameInformation information; private final GameInformation information;

View File

@@ -147,7 +147,6 @@
<version>2.42.0</version> <version>2.42.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>

View File

@@ -1,3 +1,3 @@
package org.toop.game; package org.toop.framework.game;
// TODO: Remove this, only used in ReversiCanvas. Needs to not // TODO: Remove this, only used in ReversiCanvas. Needs to not
public record Move(int position, char value) {} public record Move(int position, char value) {}

View File

@@ -1,4 +1,4 @@
package org.toop.game.gameThreads; package org.toop.framework.game.gameThreads;
import org.toop.framework.eventbus.EventFlow; import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.gameFramework.GameState; import org.toop.framework.gameFramework.GameState;

View File

@@ -1,4 +1,4 @@
package org.toop.game.gameThreads; package org.toop.framework.game.gameThreads;
import org.toop.framework.eventbus.EventFlow; import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.gameFramework.model.game.threadBehaviour.AbstractThreadBehaviour; import org.toop.framework.gameFramework.model.game.threadBehaviour.AbstractThreadBehaviour;

View File

@@ -1,4 +1,4 @@
package org.toop.game.gameThreads; package org.toop.framework.game.gameThreads;
import org.toop.framework.eventbus.EventFlow; import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.gameFramework.model.game.threadBehaviour.AbstractThreadBehaviour; import org.toop.framework.gameFramework.model.game.threadBehaviour.AbstractThreadBehaviour;
@@ -6,7 +6,7 @@ import org.toop.framework.gameFramework.view.GUIEvents;
import org.toop.framework.gameFramework.model.game.TurnBasedGame; import org.toop.framework.gameFramework.model.game.TurnBasedGame;
import org.toop.framework.gameFramework.model.game.SupportsOnlinePlay; import org.toop.framework.gameFramework.model.game.SupportsOnlinePlay;
import org.toop.framework.gameFramework.model.player.Player; import org.toop.framework.gameFramework.model.player.Player;
import org.toop.game.players.OnlinePlayer; import org.toop.framework.game.players.OnlinePlayer;
/** /**
* Handles online multiplayer game logic. * Handles online multiplayer game logic.

View File

@@ -1,7 +1,6 @@
package org.toop.game.gameThreads; package org.toop.framework.game.gameThreads;
import org.toop.framework.gameFramework.model.game.TurnBasedGame; import org.toop.framework.gameFramework.model.game.TurnBasedGame;
import org.toop.framework.networking.events.NetworkEvents;
/** /**
* Online thread behaviour that adds a fixed delay before processing * Online thread behaviour that adds a fixed delay before processing

View File

@@ -1,8 +1,7 @@
package org.toop.game.players; package org.toop.framework.game.players;
import org.toop.framework.gameFramework.model.game.TurnBasedGame; import org.toop.framework.gameFramework.model.game.TurnBasedGame;
import org.toop.framework.gameFramework.model.player.AbstractPlayer; import org.toop.framework.gameFramework.model.player.AbstractPlayer;
import org.toop.framework.gameFramework.model.player.Player;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;

View File

@@ -1,4 +1,4 @@
package org.toop.game.players; package org.toop.framework.game.players;
import org.toop.framework.gameFramework.GameState; import org.toop.framework.gameFramework.GameState;
import org.toop.framework.gameFramework.model.game.PlayResult; import org.toop.framework.gameFramework.model.game.PlayResult;

View File

@@ -1,4 +1,4 @@
package org.toop.game.players; package org.toop.framework.game.players;
import org.toop.framework.gameFramework.model.game.TurnBasedGame; import org.toop.framework.gameFramework.model.game.TurnBasedGame;
import org.toop.framework.gameFramework.model.player.AbstractPlayer; import org.toop.framework.gameFramework.model.player.AbstractPlayer;

View File

@@ -1,4 +1,4 @@
package org.toop.game.players; package org.toop.framework.game.players;
import org.toop.framework.gameFramework.model.game.TurnBasedGame; import org.toop.framework.gameFramework.model.game.TurnBasedGame;
import org.toop.framework.gameFramework.model.player.AbstractAI; import org.toop.framework.gameFramework.model.player.AbstractAI;

View File

@@ -1,8 +1,7 @@
package org.toop.framework.gameFramework.controller; package org.toop.framework.gameFramework.controller;
import org.toop.framework.gameFramework.model.game.SupportsOnlinePlay;
import org.toop.framework.gameFramework.model.game.threadBehaviour.Controllable; import org.toop.framework.gameFramework.model.game.threadBehaviour.Controllable;
import org.toop.framework.networking.events.NetworkEvents; import org.toop.framework.networking.connection.events.NetworkEvents;
public interface GameController extends Controllable, UpdatesGameUI { public interface GameController extends Controllable, UpdatesGameUI {
/** Called when it is this player's turn to make a move. */ /** Called when it is this player's turn to make a move. */

View File

@@ -1,7 +1,5 @@
package org.toop.framework.gameFramework.model.game; package org.toop.framework.gameFramework.model.game;
import org.toop.framework.networking.events.NetworkEvents;
/** /**
* Interface for games that support online multiplayer play. * Interface for games that support online multiplayer play.
* <p> * <p>

View File

@@ -1,13 +1,13 @@
package org.toop.framework.networking; package org.toop.framework.networking.connection;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.framework.SnowflakeGenerator; import org.toop.framework.SnowflakeGenerator;
import org.toop.framework.eventbus.EventFlow; import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.eventbus.bus.EventBus; import org.toop.framework.eventbus.bus.EventBus;
import org.toop.framework.networking.events.NetworkEvents; import org.toop.framework.networking.connection.events.NetworkEvents;
import org.toop.framework.networking.exceptions.ClientNotFoundException; import org.toop.framework.networking.connection.exceptions.ClientNotFoundException;
import org.toop.framework.networking.interfaces.NetworkingClientManager; import org.toop.framework.networking.connection.interfaces.NetworkingClientManager;
public class NetworkingClientEventListener { public class NetworkingClientEventListener {
private static final Logger logger = LogManager.getLogger(NetworkingClientEventListener.class); private static final Logger logger = LogManager.getLogger(NetworkingClientEventListener.class);

View File

@@ -1,4 +1,4 @@
package org.toop.framework.networking; package org.toop.framework.networking.connection;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@@ -10,13 +10,13 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.framework.eventbus.EventFlow; import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.eventbus.bus.EventBus; import org.toop.framework.eventbus.bus.EventBus;
import org.toop.framework.networking.events.NetworkEvents; import org.toop.framework.networking.connection.events.NetworkEvents;
import org.toop.framework.networking.exceptions.ClientNotFoundException; import org.toop.framework.networking.connection.exceptions.ClientNotFoundException;
import org.toop.framework.networking.exceptions.CouldNotConnectException; import org.toop.framework.networking.connection.exceptions.CouldNotConnectException;
import org.toop.framework.networking.interfaces.NetworkingClient; import org.toop.framework.networking.connection.interfaces.NetworkingClient;
import org.toop.framework.networking.types.NetworkingConnector; import org.toop.framework.networking.connection.types.NetworkingConnector;
public class NetworkingClientManager implements org.toop.framework.networking.interfaces.NetworkingClientManager { public class NetworkingClientManager implements org.toop.framework.networking.connection.interfaces.NetworkingClientManager {
private static final Logger logger = LogManager.getLogger(NetworkingClientManager.class); private static final Logger logger = LogManager.getLogger(NetworkingClientManager.class);
private final EventBus eventBus; private final EventBus eventBus;

View File

@@ -1,4 +1,4 @@
package org.toop.framework.networking.clients; package org.toop.framework.networking.connection.clients;
import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*; import io.netty.channel.*;
@@ -12,9 +12,9 @@ import io.netty.util.CharsetUtil;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.framework.eventbus.bus.EventBus; import org.toop.framework.eventbus.bus.EventBus;
import org.toop.framework.networking.exceptions.CouldNotConnectException; import org.toop.framework.networking.connection.exceptions.CouldNotConnectException;
import org.toop.framework.networking.handlers.NetworkingGameClientHandler; import org.toop.framework.networking.connection.handlers.NetworkingGameClientHandler;
import org.toop.framework.networking.interfaces.NetworkingClient; import org.toop.framework.networking.connection.interfaces.NetworkingClient;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;

View File

@@ -1,4 +1,4 @@
package org.toop.framework.networking.events; package org.toop.framework.networking.connection.events;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@@ -6,8 +6,8 @@ import java.util.concurrent.CompletableFuture;
import org.toop.annotations.AutoResponseResult; import org.toop.annotations.AutoResponseResult;
import org.toop.framework.eventbus.GlobalEventBus; import org.toop.framework.eventbus.GlobalEventBus;
import org.toop.framework.eventbus.events.*; import org.toop.framework.eventbus.events.*;
import org.toop.framework.networking.interfaces.NetworkingClient; import org.toop.framework.networking.connection.interfaces.NetworkingClient;
import org.toop.framework.networking.types.NetworkingConnector; import org.toop.framework.networking.connection.types.NetworkingConnector;
/** /**
* Defines all event types related to the networking subsystem. * Defines all event types related to the networking subsystem.

View File

@@ -1,4 +1,4 @@
package org.toop.framework.networking.exceptions; package org.toop.framework.networking.connection.exceptions;
/** /**
* Thrown when an operation is attempted on a networking client * Thrown when an operation is attempted on a networking client

View File

@@ -1,4 +1,4 @@
package org.toop.framework.networking.exceptions; package org.toop.framework.networking.connection.exceptions;
public class CouldNotConnectException extends RuntimeException { public class CouldNotConnectException extends RuntimeException {

View File

@@ -1,4 +1,4 @@
package org.toop.framework.networking.exceptions; package org.toop.framework.networking.connection.exceptions;
public class NetworkingInitializationException extends RuntimeException { public class NetworkingInitializationException extends RuntimeException {
public NetworkingInitializationException(String message, Throwable cause) { public NetworkingInitializationException(String message, Throwable cause) {

View File

@@ -1,4 +1,4 @@
package org.toop.framework.networking.handlers; package org.toop.framework.networking.connection.handlers;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
@@ -9,7 +9,7 @@ import java.util.regex.Pattern;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.toop.framework.eventbus.bus.EventBus; import org.toop.framework.eventbus.bus.EventBus;
import org.toop.framework.networking.events.NetworkEvents; import org.toop.framework.networking.connection.events.NetworkEvents;
public class NetworkingGameClientHandler extends ChannelInboundHandlerAdapter { public class NetworkingGameClientHandler extends ChannelInboundHandlerAdapter {
private static final Logger logger = LogManager.getLogger(NetworkingGameClientHandler.class); private static final Logger logger = LogManager.getLogger(NetworkingGameClientHandler.class);

View File

@@ -1,6 +1,6 @@
package org.toop.framework.networking.interfaces; package org.toop.framework.networking.connection.interfaces;
import org.toop.framework.networking.exceptions.CouldNotConnectException; import org.toop.framework.networking.connection.exceptions.CouldNotConnectException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;

View File

@@ -1,8 +1,8 @@
package org.toop.framework.networking.interfaces; package org.toop.framework.networking.connection.interfaces;
import org.toop.framework.networking.exceptions.ClientNotFoundException; import org.toop.framework.networking.connection.exceptions.ClientNotFoundException;
import org.toop.framework.networking.exceptions.CouldNotConnectException; import org.toop.framework.networking.connection.exceptions.CouldNotConnectException;
import org.toop.framework.networking.types.NetworkingConnector; import org.toop.framework.networking.connection.types.NetworkingConnector;
public interface NetworkingClientManager { public interface NetworkingClientManager {
void startClient( void startClient(

View File

@@ -1,4 +1,4 @@
package org.toop.framework.networking.types; package org.toop.framework.networking.connection.types;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;

View File

@@ -1,3 +1,3 @@
package org.toop.framework.networking.types; package org.toop.framework.networking.connection.types;
public record ServerCommand(long clientId, String command) {} public record ServerCommand(long clientId, String command) {}

View File

@@ -0,0 +1,3 @@
package org.toop.framework.networking.connection.types;
public record ServerMessage(String message) {}

View File

@@ -0,0 +1,30 @@
package org.toop.framework.networking.server;
import org.toop.framework.game.BitboardGame;
public class Game implements OnlineGame {
private long id;
private User[] users;
private GameDefinition<BitboardGame<?>> game;
public Game(GameDefinition game, User... users) {
this.game = game;
this.users = users;
}
@Override
public long id() {
return id;
}
@Override
public GameDefinition game() {
return game;
}
@Override
public User[] users() {
return users;
}
}

View File

@@ -0,0 +1,26 @@
package org.toop.framework.networking.server;
import java.lang.reflect.InvocationTargetException;
public class GameDefinition<T> {
private final String name;
private final Class<T> game;
public GameDefinition(String name, Class<T> game) {
this.name = name;
this.game = game;
}
public String name() {
return name;
}
public T create(String... users) {
try {
return game.getDeclaredConstructor().newInstance(users);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,8 @@
package org.toop.framework.networking.server;
public interface GameServer {
// List<?> gameTypes();
// List<?> ongoingGames();
// void startGame(String gameType, User... users);
// String[] onlineUsers();
}

View File

@@ -0,0 +1,68 @@
package org.toop.framework.networking.server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.nio.NioIoHandler;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.toop.framework.SnowflakeGenerator;
import org.toop.framework.game.BitboardGame;
import java.util.Map;
public class MasterServer {
private final int port;
public final Server gs;
public MasterServer(int port, Map<String, GameDefinition<BitboardGame<?>>> gameTypes) {
this.port = port;
this.gs = new Server(gameTypes);
}
public void start() throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory());
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(workerGroup);
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.option(ChannelOption.SO_BACKLOG, 128);
bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
bootstrap.handler(new LoggingHandler(LogLevel.INFO));
bootstrap.childHandler(
new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new LineBasedFrameDecoder(8192));
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
long userid = SnowflakeGenerator.nextId();
User user = new User(userid, ""+userid);
pipeline.addLast(new ServerHandler(user, gs));
}
}
);
ChannelFuture future = bootstrap.bind(port).sync();
System.out.println("MasterServer listening on port " + port);
future.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}

View File

@@ -0,0 +1,7 @@
package org.toop.framework.networking.server;
public interface MessageStore {
void add(String message);
String get();
void reset();
}

View File

@@ -0,0 +1,7 @@
package org.toop.framework.networking.server;
public interface OnlineGame {
long id();
GameDefinition game();
User[] users();
}

View File

@@ -0,0 +1,4 @@
package org.toop.framework.networking.server;
public record ParsedMessage(String command, String... args) {}

View File

@@ -0,0 +1,4 @@
package org.toop.framework.networking.server;
public class Parser {
}

View File

@@ -0,0 +1,4 @@
package org.toop.framework.networking.server;
public interface ServableGame {
}

View File

@@ -0,0 +1,51 @@
package org.toop.framework.networking.server;
import org.toop.framework.game.BitboardGame;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Server implements GameServer {
final private Map<String, GameDefinition<BitboardGame<?>>> gameTypes;
public List<OnlineGame> games = new ArrayList<>();
final private Map<Long, ServerUser> users = new ConcurrentHashMap<>();
public Server(Map<String, GameDefinition<BitboardGame<?>>> gameTypes) {
this.gameTypes = gameTypes;
}
public void addUser(ServerUser user) {
users.putIfAbsent(user.id(), user);
}
public void removeUser(ServerUser user) {
users.remove(user.id());
}
public String[] gameTypes() {
return gameTypes.keySet().toArray(new String[0]);
}
// public List<OnlineGame<BitboardGame<?>>> ongoingGames() {
// return List.of();
// }
public void startGame(String gameType, User... users) {
if (!gameTypes.containsKey(gameType)) return;
try {
var game = new Game(gameTypes.get(gameType).create(), users);
games.addLast(new Game(game, users));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String[] onlineUsers() {
return users.values().stream().map(ServerUser::name).toArray(String[]::new);
}
}

View File

@@ -0,0 +1,117 @@
package org.toop.framework.networking.server;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class ServerHandler extends SimpleChannelInboundHandler<String> {
private final User user;
private final Server server;
public ServerHandler(User user, Server server) {
this.user = user;
this.server = server;
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush("WELCOME " + user.id() + "\n");
user.setCtx(ctx);
server.addUser(user); // TODO set correct name on login
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
ParsedMessage p = parse(msg);
if (p == null) return;
IO.println(p.command() + " " + Arrays.toString(p.args()));
switch (p.command()) {
case "ping" -> ctx.writeAndFlush("PONG\n");
case "login" -> handleLogin(p);
case "get" -> handleGet(p);
case "subscribe" -> handleSubscribe(p);
case "move" -> handleMove(p);
case "challenge" -> handleChallenge(p);
case "message" -> handleMessage(p);
case "help" -> handleHelp(p);
default -> ctx.writeAndFlush("ERROR Unknown command\n");
}
}
private boolean allowedArgs(String... args) {
if (args.length < 1) return false;
return true;
}
private void handleLogin(ParsedMessage p) {
if (!allowedArgs(p.args())) return;
user.setName(p.args()[0]);
}
private void handleGet(ParsedMessage p) {
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()));
}
}
private void handleSubscribe(ParsedMessage p) {
// TODO
}
private void handleHelp(ParsedMessage p) {
// TODO
}
private void handleMessage(ParsedMessage p) {
// TODO
}
private void handleChallenge(ParsedMessage p) {
// TODO
}
private void handleMove(ParsedMessage p) {
// TODO
}
private ParsedMessage parse(String msg) {
// TODO, what if empty string.
if (msg.isEmpty()) return null;
msg = msg.trim().toLowerCase();
List<String> parts = new LinkedList<>(List.of(msg.split(" ")));
if (parts.size() > 1) {
String command = parts.removeFirst();
return new ParsedMessage(command, parts.toArray(String[]::new));
}
else {
return new ParsedMessage(msg);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
server.removeUser(user);
}
}

View File

@@ -0,0 +1,27 @@
package org.toop.framework.networking.server;
import java.util.Queue;
public class ServerMessageStore implements MessageStore {
Queue<String> messageQueue;
public ServerMessageStore(Queue<String> messageQueue) {
this.messageQueue = messageQueue;
}
@Override
public void add(String message) {
messageQueue.offer(message);
}
@Override
public String get() {
return messageQueue.poll();
}
@Override
public void reset() {
messageQueue.clear();
}
}

View File

@@ -0,0 +1,9 @@
package org.toop.framework.networking.server;
import java.net.InetSocketAddress;
public interface ServerUser {
long id();
String name();
void setName(String name);
}

View File

@@ -0,0 +1,40 @@
package org.toop.framework.networking.server;
import io.netty.channel.ChannelHandlerContext;
import java.net.InetSocketAddress;
public class User implements ServerUser {
final private long id;
private String name;
private ChannelHandlerContext connectionContext;
public User(long userId, String name) {
this.id = userId;
this.name = name;
}
@Override
public long id() {
return id;
}
@Override
public String name() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
public ChannelHandlerContext ctx() {
return connectionContext;
}
public void setCtx(ChannelHandlerContext ctx) {
this.connectionContext = ctx;
}
}

View File

@@ -1,3 +0,0 @@
package org.toop.framework.networking.types;
public record ServerMessage(String message) {}

View File

@@ -9,7 +9,7 @@
//import org.mockito.*; //import org.mockito.*;
//import org.toop.framework.SnowflakeGenerator; //import org.toop.framework.SnowflakeGenerator;
//import org.toop.framework.eventbus.EventFlow; //import org.toop.framework.eventbus.EventFlow;
//import org.toop.framework.networking.events.NetworkEvents; //import org.toop.framework.networking.connection.events.NetworkEvents;
// //
//class NetworkingClientManagerTest { //class NetworkingClientManagerTest {
// //

View File

@@ -1,4 +1,4 @@
//package org.toop.framework.networking.events; //package org.toop.framework.networking.connection.events;
// //
//import static org.junit.jupiter.api.Assertions.*; //import static org.junit.jupiter.api.Assertions.*;
// //