mooore stuff
Some checks failed
Linux arm64 / Build (push) Failing after 5m5s

This commit is contained in:
2025-01-26 13:46:23 +01:00
parent caf7011f08
commit e51cc23459
20 changed files with 395 additions and 65 deletions

View File

@@ -0,0 +1,31 @@
package common;
import java.util.HashSet;
import java.util.Set;
public class Signal {
private final Set<Runnable> listeners;
public Signal() {
this.listeners = new HashSet<>();
}
public void connect(Runnable listener) {
this.listeners.add(listener);
}
public void clear() {
this.listeners.clear();
}
public void emit() {
for (Runnable listener : this.listeners) {
listener.run();
}
}
// public void disconnect(Runnable listener) {
// this.listeners.remove(listener);
// }
}

View File

@@ -0,0 +1,30 @@
package game;
import java.util.HashMap;
import java.util.Map;
public class Game {
private final Map<Integer, Player> players;
public Game() {
this.players = new HashMap<>();
}
public Player getPlayerById(int id) {
return players.get(id);
}
public void addPlayer(Player player) {
players.put(player.getId(), player);
}
public void removePlayer(int id) {
players.remove(id);
}
public Map<Integer, Player> getPlayers() {
return players;
}
}

View File

@@ -0,0 +1,25 @@
package game;
import java.io.Serializable;
public class Player implements Serializable {
static private final long serialVersionUID = 9999;
private final String pseudo;
private final int id;
public Player(int id, String pseudo) {
this.pseudo = pseudo;
this.id = id;
}
public String getPseudo() {
return this.pseudo;
}
public int getId() {
return this.id;
}
}

View File

@@ -12,7 +12,7 @@ public abstract class BaseView {
public abstract void render(); public abstract void render();
public void onKill() {} public void cleanResources() {}
public void closeMenu() { public void closeMenu() {
this.stateMachine.popState(); this.stateMachine.popState();

View File

@@ -0,0 +1,60 @@
package gui.menu;
import java.io.IOException;
import java.net.UnknownHostException;
import imgui.ImGui;
import network.client.Client;
import network.server.Server;
public class ConnexionStatusView extends BaseView {
private Client client;
private Server server;
public ConnexionStatusView(StateMachine stateMachine, String address, short port) throws UnknownHostException, IOException {
this(stateMachine, null, new Client(address, port));
}
public ConnexionStatusView(StateMachine stateMachine, short port) throws UnknownHostException, IOException {
this(stateMachine, new Server(port), new Client("localhost", port));
}
private ConnexionStatusView(StateMachine stateMachine, Server server, Client client) {
super(stateMachine);
this.client = client;
this.client.onConnect.connect(this::onConnect);
this.client.onClosed.connect(this::onLeave);
this.server = server;
}
public void onConnect() {
// System.out.println("Connecté");
this.stateMachine.pushState(new MultiPlayerView(stateMachine, client));
}
public void onLeave() {
// System.out.println("Quitté !");
this.client.onDisconnect.clear();
this.client = null;
// on passe le menu de la connexion
this.closeMenu();
}
@Override
public void render() {
ImGui.text("Connecting ...");
}
@Override
public void cleanResources() {
// System.out.println("Bye bye !");
if (this.server != null) {
this.server.stop();
}
if (this.client != null) {
this.client.stop();
}
}
}

View File

@@ -22,7 +22,7 @@ public class MultiMenu extends BaseView {
ImGui.inputInt("Port", port); ImGui.inputInt("Port", port);
if (ImGui.button("Créer")) { if (ImGui.button("Créer")) {
try { try {
this.stateMachine.pushState(new MultiPlayerView(stateMachine, (short) port.get())); this.stateMachine.pushState(new ConnexionStatusView(stateMachine, (short) port.get()));
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
@@ -37,7 +37,7 @@ public class MultiMenu extends BaseView {
ImGui.inputInt("Port", port); ImGui.inputInt("Port", port);
if (ImGui.button("Rejoindre")) { if (ImGui.button("Rejoindre")) {
try { try {
this.stateMachine.pushState(new MultiPlayerView(stateMachine, address.get(), (short) port.get())); this.stateMachine.pushState(new ConnexionStatusView(stateMachine, address.get(), (short) port.get()));
} catch (IOException e) { } catch (IOException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();

View File

@@ -1,53 +1,28 @@
package gui.menu; package gui.menu;
import java.io.IOException;
import java.net.UnknownHostException;
import imgui.ImGui; import imgui.ImGui;
import network.client.Client; import network.client.Client;
import network.server.Server;
public class MultiPlayerView extends BaseView { public class MultiPlayerView extends BaseView {
private Client client; private final Client client;
private Server server;
/** public MultiPlayerView(StateMachine stateMachine, Client client) {
* Client
*
* @param stateMachine
* @param address
* @param port
* @throws IOException
* @throws UnknownHostException
*/
public MultiPlayerView(StateMachine stateMachine, String address, short port)
throws UnknownHostException, IOException {
super(stateMachine); super(stateMachine);
this.client = new Client(address, port); this.client = client;
} this.client.onDisconnect.connect(this::onDisconnect);
/**
* Server
*
* @param stateMachine
* @param port
* @throws IOException
*/
public MultiPlayerView(StateMachine stateMachine, short port) throws IOException {
super(stateMachine);
this.server = new Server(port);
this.client = new Client("localhost", port);
} }
@Override @Override
public void onKill() { public void closeMenu() {
if (this.server != null) { this.client.forceDisconnect();
this.server.stop(); super.closeMenu();
}
if (this.client != null) {
this.client.stop();
} }
public void onDisconnect() {
// System.out.println("ohohohohohohoho");
this.stateMachine.popState();
this.client.onDisconnect.clear();
} }
@Override @Override

View File

@@ -17,7 +17,7 @@ public class StateMachine {
public void clear() { public void clear() {
for (BaseView view : menus) { for (BaseView view : menus) {
view.onKill(); view.cleanResources();
} }
menus.clear(); menus.clear();
} }
@@ -27,13 +27,13 @@ public class StateMachine {
} }
public void popState() { public void popState() {
menus.get(menus.size() - 1).onKill(); menus.getLast().cleanResources();
menus.pop(); menus.pop();
} }
private void checkEscape() { private void checkEscape() {
if (ImGui.isKeyPressed(ImGuiKey.Escape) && menus.size() > 1) { if (ImGui.isKeyPressed(ImGuiKey.Escape) && menus.size() > 1) {
popState(); menus.getLast().closeMenu();
} }
} }

View File

@@ -20,9 +20,14 @@ public abstract class Connexion implements PacketVisitor {
this.connexionThread.start(); this.connexionThread.start();
} }
public void sendPacket(Packet packet) { public boolean isClosed() {
return this.socket.isClosed();
}
public synchronized void sendPacket(Packet packet) {
try { try {
objectOutputStream.writeObject(packet); objectOutputStream.writeObject(packet);
objectOutputStream.flush();
} catch (IOException e) { } catch (IOException e) {
System.err.println("Error while sending packet ! " + e.getLocalizedMessage()); System.err.println("Error while sending packet ! " + e.getLocalizedMessage());
close(); close();

View File

@@ -19,11 +19,14 @@ public class ConnexionThread extends Thread{
public void run() { public void run() {
while (!interrupted()) { while (!interrupted()) {
try { try {
// System.out.println(objectInputStream.available());
Object o = objectInputStream.readObject(); Object o = objectInputStream.readObject();
if (o instanceof Packet packet) { if (o instanceof Packet packet) {
connexion.visitPacket(packet); connexion.visitPacket(packet);
} }
} catch (ClassNotFoundException | IOException e) { } catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
this.connexion.close();
break; break;
} }
} }

View File

@@ -3,20 +3,45 @@ package network.client;
import java.io.IOException; import java.io.IOException;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import common.Signal;
import game.Game;
import game.Player;
import network.protocol.packets.LoginPacket;
public class Client { public class Client {
private final ClientConnexion clientConnection; private final ClientConnexion clientConnection;
private final Game game;
public final Signal onConnect = new Signal();
public final Signal onDisconnect = new Signal();
public final Signal onClosed = new Signal();
public Client(String address, short port) throws UnknownHostException, IOException { public Client(String address, short port) throws UnknownHostException, IOException {
this.clientConnection = new ClientConnexion(address, port, this); this.clientConnection = new ClientConnexion(address, port, this);
this.game = new Game();
login("Player2" + Math.random());
}
public void login(String pseudo) {
System.out.println("Logging in with pseudo " + pseudo + " ...");
this.clientConnection.sendPacket(new LoginPacket(pseudo));
} }
public void stop() { public void stop() {
this.clientConnection.close(); this.clientConnection.close();
} }
public void onDisconnect() { public void addPlayer(Player player) {
// do some stuff this.game.addPlayer(player);
System.out.println("OSEKOUR"); }
public Game getGame() {
return game;
}
public void forceDisconnect() {
this.onClosed.emit();
stop();
} }
} }

View File

@@ -4,14 +4,19 @@ import java.io.IOException;
import java.net.Socket; import java.net.Socket;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import game.Player;
import network.Connexion; import network.Connexion;
import network.protocol.packets.ConnexionInfoPacket; import network.protocol.packets.ConnexionInfoPacket;
import network.protocol.packets.DisconnectPacket; import network.protocol.packets.DisconnectPacket;
import network.protocol.packets.KeepAlivePacket; import network.protocol.packets.KeepAlivePacket;
import network.protocol.packets.LoginPacket;
import network.protocol.packets.PlayerJoinPacket;
import network.protocol.packets.PlayerLeavePacket;
public class ClientConnexion extends Connexion { public class ClientConnexion extends Connexion {
private final Client client; private final Client client;
private Player player = null;
public ClientConnexion(String address, short port, Client client) throws UnknownHostException, IOException { public ClientConnexion(String address, short port, Client client) throws UnknownHostException, IOException {
super(new Socket(address, port)); super(new Socket(address, port));
@@ -20,13 +25,16 @@ public class ClientConnexion extends Connexion {
@Override @Override
public void close() { public void close() {
if (!this.isClosed()) {
super.close(); super.close();
client.onDisconnect(); client.onDisconnect.emit();
}
} }
@Override @Override
public void visitPacket(ConnexionInfoPacket packet) { public void visitPacket(ConnexionInfoPacket packet) {
this.player = this.client.getGame().getPlayerById(packet.getConnectionId());
client.onConnect.emit();
} }
@Override @Override
@@ -40,4 +48,20 @@ public class ClientConnexion extends Connexion {
close(); close();
} }
@Override
public void visitPacket(LoginPacket packet) {
throw new UnsupportedOperationException("Unimplemented method 'visitPacketLogin'");
}
@Override
public void visitPacket(PlayerJoinPacket packet) {
this.client.addPlayer(packet.getPlayer());
System.out.println("[Client] " + packet.getPlayer().getPseudo() + " joined the game !");
}
@Override
public void visitPacket(PlayerLeavePacket packet) {
this.client.getGame().removePlayer(packet.getPlayer());
}
} }

View File

@@ -3,6 +3,9 @@ package network.protocol;
import network.protocol.packets.ConnexionInfoPacket; import network.protocol.packets.ConnexionInfoPacket;
import network.protocol.packets.DisconnectPacket; import network.protocol.packets.DisconnectPacket;
import network.protocol.packets.KeepAlivePacket; import network.protocol.packets.KeepAlivePacket;
import network.protocol.packets.LoginPacket;
import network.protocol.packets.PlayerJoinPacket;
import network.protocol.packets.PlayerLeavePacket;
public interface PacketVisitor { public interface PacketVisitor {
@@ -13,5 +16,8 @@ public interface PacketVisitor {
void visitPacket(ConnexionInfoPacket packet); void visitPacket(ConnexionInfoPacket packet);
void visitPacket(DisconnectPacket packet); void visitPacket(DisconnectPacket packet);
void visitPacket(KeepAlivePacket packet); void visitPacket(KeepAlivePacket packet);
void visitPacket(LoginPacket packet);
void visitPacket(PlayerJoinPacket packet);
void visitPacket(PlayerLeavePacket packet);
} }

View File

@@ -2,6 +2,6 @@ package network.protocol;
public enum Packets { public enum Packets {
ConnectionInfo, KeepAlive, Disconnect ConnectionInfo, KeepAlive, Disconnect, Login, PlayerJoin, PlayerLeave
} }

View File

@@ -2,9 +2,12 @@ package network.protocol.packets;
import network.protocol.Packet; import network.protocol.Packet;
import network.protocol.PacketVisitor; import network.protocol.PacketVisitor;
import network.protocol.Packets;
public class DisconnectPacket extends Packet { public class DisconnectPacket extends Packet {
static private final long serialVersionUID = Packets.Disconnect.ordinal();
private final String reason; private final String reason;
public DisconnectPacket(String reason) { public DisconnectPacket(String reason) {

View File

@@ -0,0 +1,26 @@
package network.protocol.packets;
import network.protocol.Packet;
import network.protocol.PacketVisitor;
import network.protocol.Packets;
public class LoginPacket extends Packet {
static private final long serialVersionUID = Packets.Login.ordinal();
private final String pseudo;
public LoginPacket(String pseudo) {
this.pseudo = pseudo;
}
public String getPseudo() {
return pseudo;
}
@Override
public void accept(PacketVisitor packetVisitor) {
packetVisitor.visitPacket(this);
}
}

View File

@@ -0,0 +1,29 @@
package network.protocol.packets;
import game.Player;
import network.protocol.Packet;
import network.protocol.PacketVisitor;
import network.protocol.Packets;
public class PlayerJoinPacket extends Packet{
static private final long serialVersionUID = Packets.PlayerJoin.ordinal();
private final Player player;
public PlayerJoinPacket(Player player) {
this.player = player;
}
public Player getPlayer() {
return player;
}
@Override
public void accept(PacketVisitor packetVisitor) {
packetVisitor.visitPacket(this);
}
}

View File

@@ -0,0 +1,28 @@
package network.protocol.packets;
import network.protocol.Packet;
import network.protocol.PacketVisitor;
import network.protocol.Packets;
public class PlayerLeavePacket extends Packet{
static private final long serialVersionUID = Packets.PlayerLeave.ordinal();
private final int playerId;
public PlayerLeavePacket(int playerId) {
this.playerId = playerId;
}
public int getPlayer() {
return playerId;
}
@Override
public void accept(PacketVisitor packetVisitor) {
packetVisitor.visitPacket(this);
}
}

View File

@@ -5,6 +5,8 @@ import java.net.ServerSocket;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import game.Game;
import game.Player;
import network.protocol.Packet; import network.protocol.Packet;
public class Server { public class Server {
@@ -13,6 +15,8 @@ public class Server {
final List<ServerConnexion> connexions; final List<ServerConnexion> connexions;
private final ServerAcceptThread acceptThread; private final ServerAcceptThread acceptThread;
private final ServerLogicThread logicThread; private final ServerLogicThread logicThread;
private final Game game;
private int nextPlayerId = 0;
public Server(short port) throws IOException { public Server(short port) throws IOException {
this.serverSocket = new ServerSocket(port); this.serverSocket = new ServerSocket(port);
@@ -21,6 +25,7 @@ public class Server {
this.acceptThread.start(); this.acceptThread.start();
this.logicThread = new ServerLogicThread(this); this.logicThread = new ServerLogicThread(this);
this.logicThread.start(); this.logicThread.start();
this.game = new Game();
} }
public void broadcastPacket(Packet packet) { public void broadcastPacket(Packet packet) {
@@ -34,6 +39,7 @@ public class Server {
ServerConnexion connexion = it.next(); ServerConnexion connexion = it.next();
if (!connexion.update()) { if (!connexion.update()) {
connexion.close(); connexion.close();
connexion.nukeConnection();
it.remove(); it.remove();
} }
} }
@@ -47,4 +53,15 @@ public class Server {
} }
} }
public Player addPlayer(String pseudo) {
Player p = new Player(nextPlayerId, pseudo);
this.game.addPlayer(p);
nextPlayerId++;
return p;
}
public Game getGame() {
return game;
}
} }

View File

@@ -3,16 +3,21 @@ package network.server;
import java.io.IOException; import java.io.IOException;
import java.net.Socket; import java.net.Socket;
import game.Player;
import network.Connexion; import network.Connexion;
import network.protocol.packets.ConnexionInfoPacket; import network.protocol.packets.ConnexionInfoPacket;
import network.protocol.packets.DisconnectPacket; import network.protocol.packets.DisconnectPacket;
import network.protocol.packets.KeepAlivePacket; import network.protocol.packets.KeepAlivePacket;
import network.protocol.packets.LoginPacket;
import network.protocol.packets.PlayerJoinPacket;
import network.protocol.packets.PlayerLeavePacket;
public class ServerConnexion extends Connexion { public class ServerConnexion extends Connexion {
private final Server server; private final Server server;
private final KeepAliveHandler keepAliveHandler; private final KeepAliveHandler keepAliveHandler;
private boolean shouldClose = false; private boolean shouldClose = false;
private Player player = null;
public ServerConnexion(Socket socket, Server server) throws IOException { public ServerConnexion(Socket socket, Server server) throws IOException {
super(socket); super(socket);
@@ -21,21 +26,36 @@ public class ServerConnexion extends Connexion {
} }
public boolean update() { public boolean update() {
if (shouldClose) if (shouldClose | isClosed())
return false; return false;
return this.keepAliveHandler.update(); return this.keepAliveHandler.update();
} }
@Override public void nukeConnection() {
public void close() { if (player != null) {
sendPacket(new DisconnectPacket("Server stopped")); sendPacket(new DisconnectPacket("Server stopped"));
super.close(); this.server.broadcastPacket(new PlayerLeavePacket(player.getId()));
shouldClose = true; this.server.getGame().removePlayer(player.getId());
}
} }
@Override @Override
public void visitPacket(ConnexionInfoPacket packet) { public synchronized void close() {
throw new UnsupportedOperationException("Unimplemented method 'visitPacket'"); if(shouldClose)
return;
super.close();
shouldClose = true;
System.out.println("[Server] Closing connexion !");
}
private void finishLogin() {
// send players that have already joined (excluding this one)
for (Player p : this.server.getGame().getPlayers().values()) {
if (p.getId() != player.getId())
sendPacket(new PlayerJoinPacket(p));
}
this.server.broadcastPacket(new PlayerJoinPacket(player));
sendPacket(new ConnexionInfoPacket(player.getId()));
} }
@Override @Override
@@ -48,4 +68,27 @@ public class ServerConnexion extends Connexion {
close(); close();
} }
@Override
public void visitPacket(LoginPacket packet) {
if (this.player != null)
return;
this.player = this.server.addPlayer(packet.getPseudo());
finishLogin();
}
@Override
public void visitPacket(ConnexionInfoPacket packet) {
throw new UnsupportedOperationException("Unimplemented method 'visitPacketConnexionInfo'");
}
@Override
public void visitPacket(PlayerJoinPacket packet) {
throw new UnsupportedOperationException("Unimplemented method 'visitPacketPlayerJoin'");
}
@Override
public void visitPacket(PlayerLeavePacket packet) {
throw new UnsupportedOperationException("Unimplemented method 'visitPacketPlayerLeave'");
}
} }