hanze/game-client

added cool network client (b150d3e46e015cd9edb3baa914966a91551465d5)
Repositories

commit b150d3e46e015cd9edb3baa914966a91551465d5
parent db2d2efd9c560594cc576fd4b772671fd1a92d77
Author: Friedel Schoen <[email protected]>
Date:   Thu,  6 Oct 2022 02:10:48 +0200

added cool network client

Diffstat:
AISYGameClient.iml33+++++++++++++++++++++++++++++++++
Aprotocol.txt204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/main/java/nl/isygameclient/Application.java28----------------------------
Asrc/main/java/nl/isygameclient/network/EventParser.java82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/nl/isygameclient/network/GameClient.java111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/nl/isygameclient/network/GameClientBase.java166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atarget/classes/module-info.class0
Atarget/classes/nl/isygameclient/controllers/HelloController.class0
Atarget/classes/nl/isygameclient/css/hello.css4++++
Atarget/classes/nl/isygameclient/images/reversie_logo.png0
Atarget/classes/nl/isygameclient/images/tictactoe_logo.png0
Atarget/classes/nl/isygameclient/models/SimpleCalculator.class0
Atarget/classes/nl/isygameclient/network/EventParser.class0
Atarget/classes/nl/isygameclient/network/GameClient.class0
Atarget/classes/nl/isygameclient/network/GameClientBase$ClientException.class0
Atarget/classes/nl/isygameclient/network/GameClientBase$Event.class0
Atarget/classes/nl/isygameclient/network/GameClientBase$EventType.class0
Atarget/classes/nl/isygameclient/network/GameClientBase.class0
Atarget/classes/nl/isygameclient/util/Settings.class0
Atarget/classes/nl/isygameclient/util/SettingsHandler.class0
Atarget/classes/nl/isygameclient/views/hello-view.fxml14++++++++++++++
Atarget/test-classes/nl/isygameclient/models/SimpleCalculatorTest.class0
Atarget/test-classes/nl/isygameclient/util/SettingsTest.class0
23 files changed, 614 insertions(+), 28 deletions(-)

diff --git a/ISYGameClient.iml b/ISYGameClient.iml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_16"> + <output url="file://$MODULE_DIR$/target/classes" /> + <output-test url="file://$MODULE_DIR$/target/test-classes" /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> + <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> + <excludeFolder url="file://$MODULE_DIR$/target" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="library" name="Maven: org.openjfx:javafx-controls:18.0.2" level="project" /> + <orderEntry type="library" name="Maven: org.openjfx:javafx-controls:win:18.0.2" level="project" /> + <orderEntry type="library" name="Maven: org.openjfx:javafx-graphics:18.0.2" level="project" /> + <orderEntry type="library" name="Maven: org.openjfx:javafx-graphics:win:18.0.2" level="project" /> + <orderEntry type="library" name="Maven: org.openjfx:javafx-base:18.0.2" level="project" /> + <orderEntry type="library" name="Maven: org.openjfx:javafx-base:win:18.0.2" level="project" /> + <orderEntry type="library" name="Maven: org.openjfx:javafx-fxml:18.0.2" level="project" /> + <orderEntry type="library" name="Maven: org.openjfx:javafx-fxml:win:18.0.2" level="project" /> + <orderEntry type="library" name="Maven: org.controlsfx:controlsfx:11.1.1" level="project" /> + <orderEntry type="library" name="Maven: org.kordamp.bootstrapfx:bootstrapfx-core:0.4.0" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.9.0" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.9.0" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.2" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.9.0" level="project" /> + <orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.9.0" level="project" /> + <orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.24" level="project" /> + </component> +</module> +\ No newline at end of file diff --git a/protocol.txt b/protocol.txt @@ -0,0 +1,204 @@ +New Game server - Protocol Documentatie 2021 + +Auteurs: Hilko Janssen, Remi Reuvekamp, Gertjan Haan, Timo Strating +Onder begeleiding van: Bas Heijne +Gemaakt in opdracht voor: Lech Bialek +--------------------------------------------- + + +!!! Dit project wat je nu aan het bekijken bent is een 2de iteratie van een oude server. De oude server was heel erg + strict in het hanteren van het protocol. Daarnaast verstuurde het ook dingen in een volgorde die soms anders + gedocumenteerd was. De nieuwe server staat een meer vrije implementatie toe van het protocol. Zo zijn kan de nieuwe + server ook commando's begrijpen als er geen ""-quotes om een argument heen staan. + + De nieuwe server is dus volledig backwards compatible met de stricte versie van dit protocol. + + +--------------------------------------------- +Commando's in detail + +C = Client +S = Server + +Notes bij server antwoorden: +Items tussen vierkante haken ('[' en ']') geven een lijst weer. +Items tussen accolades ('{' en '}') geven een map weer. Zoals bij alle maps, is de volgorde niet bepaald. + +Notes bij client commando's: +Alle commando's zijn niet hoofdlettergevoelig. +Alle argumenten zijn niet hoofdlettergevoelig. + +De server kan naast een server-berichten sturen ook de connectie verbreken. + + +Niet ondersteunde commando: +C: <niet ondersteunde commando> | <commando> <verkeerd(e) argument(en)> +S: ERR <reden> +->Geen gevolg. + +Inloggen: +C: login <speler> +S: OK | ERR <reden> +->Nu ingelogd met spelersnaam lowercase(<speler>). Een naam moet lowercase uniek zijn. + Als deze spelersnaam al bekend was, maar bijvoorbeeld vroegtijdig weg is gegaan bij een toernooi, dan wordt je weer opnieuw in het toernooi gezet. + +Uitloggen/Verbinding verbreken: +C: logout | exit | quit | disconnect | bye +S: - +->Verbinding is verbroken. De speler blijft in het toernooi en kan weer meespelen als hij met de oude spelersnaam opnieuw inlogt. + +Lijst opvragen met ondersteunde spellen: +C: get gamelist +S: OK +S: SVR GAMELIST ["<speltype>", ...] +->Lijst met spellen ontvangen. + +Lijst opvragen met verbonden spelers: +C: get playerlist +S: OK +S: SVR PLAYERLIST ["<speler>", ...] +->Lijst met spelers ontvangen. + +Inschrijven voor de spelzoeker om (voor de lol) een potje met iemand te spelen. +C: subscribe <speltype> +S: OK +->Ingeschreven voor speltype <speltype>. Zodra nog een speler zich heeft ingeschreven start een match hiermee. + +Match aangeboden krijgen, bericht naar beide spelers: +S: SVR GAME MATCH {PLAYERTOMOVE: "<naam speler1>", GAMTYPE: "<speltype>", OPPONENT: "<naam tegenstander>"} +->Nu bezig met een match, de inschrijving voor een speltype is vervallen. + +De beurt toegewezen krijgen tijdens match: +S: SVR GAME YOURTURN {TURNMESSAGE: "<bericht voor deze beurt>"} +->Nu mogelijkheid een zet te doen. + +Een zet doen na het toegewezen krijgen van een beurt: +C: move <zet> +S: OK +->De zet is geaccepteerd door de server, gevolg voor spel zal volgen. +NB: <zet> is een integer van 0 t/m 8 (Tic Tac Toe) resp. 0 t/m 63 (Othello). +De nummering van de vakjes op het bord is rij-gewijs, van linksboven naar rechtsonder. + +Resultaat van een zet ontvangen, bericht naar beide spelers: +S: SVR GAME MOVE {PLAYER: "<speler>", DETAILS: "<reactie spel op zet>", MOVE: "<zet>"} +->Er is een zet gedaan, dit bericht geeft aan wie deze gezet heeft, wat de reactie van het spel erop is + +Resultaat van een match ontvangen, bericht naar beide spelers: +S: SVR GAME <speler resultaat> {PLAYERONESCORE: "<score speler1>", PLAYERTWOSCORE: "<score speler2>", COMMENT: "<commentaar op resultaat>"} +->De match is afgelopen, <speler resultaat> kan de waarde 'WIN', 'LOSS' of 'DRAW' bevatten. + <score speler1> kan arbitrair zijn als + +Een match opgeven: +C: forfeit +S: OK +->De speler heeft het spel opgegeven, de server zal het resultaat van de match doorgeven. + +Resultaat van een match die opgegeven is door een speler, bericht naar beide spelers: +S: SVR GAME <speler resultaat> {PLAYERONESCORE: "<score speler1>", PLAYERTWOSCORE: "<score speler2>", COMMENT: "Player forfeited match"} +->De match is afgelopen, <speler> heeft de match opgegeven. + +Resultaat van een match, speler heeft de verbinding verbroken: +S: SVR GAME <speler resultaat> {PLAYERONESCORE: "<score speler1>", PLAYERTWOSCORE: "<score speler2>", COMMENT: "Client disconnected"} +->De match is afgelopen, <speler> heeft de verbinding verbroken. + +Een speler uitdagen voor een spel: +C: challenge "<speler>" "<speltype>" | challenge <speler> <speltype> +S: OK +->De speler is nu uitgedaagd voor een spel. Eerder gemaakte uitdagingen zijn komen te vervallen. Gebruik quotes als er een spatie in een naam zit + +Een uitdaging ontvangen: +S: SVR GAME CHALLENGE {CHALLENGER: "Sjors", GAMETYPE: "Guess Game", CHALLENGENUMBER: "1"} +->Nu mogelijkheid de uitdaging te accepteren. + +Resultaat van een uitdaging die is komen te vervallen: +S: SVR GAME CHALLENGE CANCELLED {CHALLENGENUMBER: "<uitdaging nummer>"} +->De uitdaging is vervallen. Mogelijke oorzaken: speler heeft een andere uitdaging gestart, speler is een match begonnen, speler heeft de verbinding verbroken. + +Een uitdaging accepteren: +C: challenge accept <uitdaging nummer> +S: OK +->De uitdaging is geaccepteerd. De match wordt gestart, bericht volgt. + +Chatten, alleen toegestaan als chat ingeschakeld is door de admin: +C: message <bericht zonder spaties> | message "<bericht met spaties>" +S: OK | ERR <reden> + +Help opvragen: +C: help +S: OK +->De client heeft nu help informatie opgevraagd, de server zal antwoorden met help informatie. + +Help opvragen van een commando: +C: help <commando> +S: OK +->De client heeft nu help informatie opgevraagd voor een commando, de server zal antwoorden met help informatie. + +Help informatie ontvangen: +S: SVR HELP <help informatie> +->Help informatie is ontvangen, kan meerdere achtereenvolgende responses bevatten. + + +--------------------------------------------- +Overzicht van server-berichten: + +OK Commando geaccepteerd +ERR Commando afgewezen +SVR [ HELP | GAME [MATCH | YOURTURN | MOVE | CHALLENGE | [WIN | LOSS | DRAW]]] + Bericht van server + HELP Bericht met help informatie + GAME Bericht met betrekking op een spel/match + MATCH Toewijzing van een match + YOURTURN Toewijzing van de beurt tijdens de match + MOVE Een zet gedaan tijdens de match + CHALLENGE Bericht met betrekking op een uitdaging + WIN Ontvanger heeft spel gewonnen + LOSS Ontvanger heeft spel verloren + DRAW Match is geeindigd in gelijk spel + +--------------------------------------------- +Overzicht van client-commando's: + +login Aanmelden als speler +logout | exit | quit | disconnect | bye + Uitloggen en verbinding verbreken +get <gamelist | playerlist> + Opvragen van gegevens + gamelist Opvragen van de lijst met ondersteunde speltypes + playerlist Opvragen van de lijst met aangemelde spelers +subscribe Inschrijven voor een speltype +move Een zet doen tijdens een match +challenge [accept] Uitdagingen behandelen + accept Uitdaging accepteren +forfeit De huidige match opgeven +message Stuur een berichtje +help [commando] Help weergeven + + + + + + + + +Enkele tips/tricks van de schrijvers van deze server en voormalig winnaars van het toernooi in 2019 +--------------------------------------------- + +1: Neem eens een kijkje op de wiki pagina van othello en reversi. Er zijn 4 manieren waardoor de server zal concluderen dat je hebt gewonnen. + +2: Hardcode het copyright bericht niet in je client. + +3: Veel server instellingen kunnen worden veranderd. Verwacht deze aanpasingen dan ook. Sommige oude clients gaan de mist in als de server de client bijvoorbeeld maar 5 seconde zou geven om te reageren. + +4: Daag eens een klasgenoot uit voor een potje voordat het toernooit begint. + +5: Sommige spellen hebben bordposities waarbij je beurt gepasseerd moet worden, maar de server heeft geen pass commando. + +6: Wees een beetje lief tegen de server, niet spammen enzo. + +7: Oude clients hadden soms popups die nare gevolgen met zich mee brachten. + +8: Iedereen die met de server is verbonden wordt "waarschijnlijk" tijdens het starten van een toernooi in het toernooi gezet. Er is dus niet een commando om deel te nemen aan het toernooi. + +9: Test Test Test + +10: De persoon die dit heeft getyped heeft dit project ook moeten doen maar dan zonder deze tips en heeft gewonnen dus doe er je voordeel mee (alvast sorry voor de spelfouten in het geval je die hebt gevonden). diff --git a/src/main/java/nl/isygameclient/Application.java b/src/main/java/nl/isygameclient/Application.java @@ -1,27 +0,0 @@ -package nl.isygameclient; - -import java.io.IOException; -import javafx.fxml.FXMLLoader; -import javafx.scene.Scene; -import javafx.stage.Stage; -import nl.isygameclient.util.SettingsHandler; - -public class Application extends javafx.application.Application { - @Override - public void start(Stage primaryStage) throws IOException { - FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("views/hello-view.fxml")); - Scene scene = new Scene(fxmlLoader.load(), SettingsHandler.getSettings().getScreenWidth(), SettingsHandler.getSettings().getScreenHeight()); - primaryStage.setTitle(SettingsHandler.getSettings().getTitle()); - primaryStage.setScene(scene); - primaryStage.setFullScreen(SettingsHandler.getSettings().isFullscreen()); - primaryStage.show(); - primaryStage.setOnCloseRequest((windowEvent) -> { - SettingsHandler.saveProperties(); - }); - } - - - public static void main(String[] args) { - launch(); - } -} -\ No newline at end of file diff --git a/src/main/java/nl/isygameclient/network/EventParser.java b/src/main/java/nl/isygameclient/network/EventParser.java @@ -0,0 +1,82 @@ +package nl.isygameclient.network; + +import java.util.ArrayList; +import java.util.HashMap; +import nl.isygameclient.network.GameClientBase.ClientException; + +public class EventParser { + private final String str; + + private int index = 0; + + private void stripLeft() { + while (Character.isSpaceChar(str.charAt(index))) + index++; + } + + public EventParser(String str) { + this.str = str; + } + + public Object parseData() throws ClientException { + try { + stripLeft(); + + if (index >= str.length()) + return null; + + switch (str.charAt(index)) { + case '"': + index++; + var string = str.substring(index, str.indexOf("\"", index)); + index = str.indexOf("\"", index) + 1; + return string; + case '[': + index++; + var array = new ArrayList<Object>(); + for (;;) { + array.add(parseData()); + stripLeft(); + if (str.charAt(index) == ']') { + index++; + return array; + } else if (str.charAt(index) == ',') { + index++; + } else { + throw new ClientException(String.format("invalid server response: unexpected '%c' at %d in '%s'", str.charAt(index), index, str)); + } + } + case '{': + index++; + var map = new HashMap<String, Object>(); + for (;;) { + stripLeft(); + var key = str.substring(index, str.indexOf(":", index)); + + index = str.indexOf(":", index) + 1; + map.put(key, parseData()); + stripLeft(); + if (str.charAt(index) == '}') { + index++; + return map; + } else if (str.charAt(index) == ',') { + index++; + } else { + throw new ClientException(String.format("invalid server response: unexpected '%c' at %d in '%s'", str.charAt(index), index, str)); + } + } + default: + if (index != 0) + throw new ClientException(String.format("invalid server response: unexpected '%c' at %d in '%s'", str.charAt(index), index, str)); + index = str.length(); + return str; + } + } catch (Exception ext) { + throw new ClientException(String.format("invalid server response: unexpected '%c' at %d in '%s'", str.charAt(index), index, str)); + } + } + + public void reset() { + index = 0; + } +} diff --git a/src/main/java/nl/isygameclient/network/GameClient.java b/src/main/java/nl/isygameclient/network/GameClient.java @@ -0,0 +1,111 @@ +package nl.isygameclient.network; + +import java.io.IOException; +import java.net.UnknownHostException; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.function.Function; + +public class GameClient extends GameClientBase { + private final String name; + + public GameClient(String host, int port, String name) throws UnknownHostException, IOException, InterruptedException { + super(host, port); + + this.name = name; + } + + + public String getName() { + return name; + } + + @SuppressWarnings("unchecked") + public List<String> games() throws IOException, ClientException, InterruptedException { + send("get gamelist"); + + return (List<String>) getEvent(EventType.GAMELIST).data; + } + + @SuppressWarnings("unchecked") + public List<String> players() throws IOException, ClientException, InterruptedException { + send("get playerlist"); + + return (List<String>) getEvent(EventType.GAMELIST).data; + } + + public void login() throws ClientException, IOException { + send("login", name); + } + + @SuppressWarnings("unchecked") + public Map<String, Object> startMatch(String game) throws IOException, ClientException, InterruptedException { + send("subscribe", game); + + return (Map<String, Object>) getEvent(-1, EventType.MATCH).data; + } + + public void move(int move) throws IOException, ClientException { + send("move", Integer.toString(move)); + } + + public static void printMap(int[] moves) { + Function<Integer, Character> toChar = (c) -> c == -1 ? 'x' : c == 0 ? ' ' + : 'o'; + + System.out.println("---------"); + System.out.printf("| %c %c %c |\n", toChar.apply(moves[0]), toChar.apply(moves[1]), toChar.apply(moves[2])); + System.out.printf("| %c %c %c |\n", toChar.apply(moves[3]), toChar.apply(moves[4]), toChar.apply(moves[5])); + System.out.printf("| %c %c %c |\n", toChar.apply(moves[6]), toChar.apply(moves[7]), toChar.apply(moves[8])); + System.out.println("---------"); + System.out.println(); + } + + public static void main(String[] args) throws Exception { + var name = "testclient" + new Random().nextInt(100); + var gc = new GameClient("localhost", 7789, name); // public: 145.33.225.170 + + gc.login(); + System.out.println("connected as " + name); + + Event evt; + int points = 0; + int other = 0; + do { + gc.startMatch("tic-tac-toe"); + + var moves = new int[9]; + int move; + + do { + evt = gc.getEvent(-1, EventType.MOVE, EventType.YOURTURN, EventType.WIN, EventType.DRAW, EventType.LOSS); + + switch (evt.type) { + case YOURTURN: + do { + move = new Random().nextInt(9); + } while (moves[move] != 0); + gc.move(move); + break; + case MOVE: + var moveMap = (Map<String, String>) evt.data; + + moves[Integer.parseInt(moveMap.get("MOVE"))] = moveMap.get("PLAYER").equals(name) ? 1 : -1; + printMap(moves); + break; + case WIN: + points++; + System.out.printf("You won! %d:%d\n", points, other); + break; + case LOSS: + other++; + System.out.printf("You lose! %d:%d\n", points, other); + break; + default: + } + } while (evt.type == EventType.YOURTURN || evt.type == EventType.MOVE); + } while (points < 25 && other < 25); + gc.close(); + } +} diff --git a/src/main/java/nl/isygameclient/network/GameClientBase.java b/src/main/java/nl/isygameclient/network/GameClientBase.java @@ -0,0 +1,166 @@ +package nl.isygameclient.network; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.LinkedList; + +public class GameClientBase { + public static enum EventType { + PLAYERLIST, + GAMELIST, + MATCH, + YOURTURN, + MOVE, + CHALLENGE, + WIN, + LOSS, + DRAW, + } + + public static class Event { + public final EventType type; + public final Object data; + + public Event(EventType type, Object data) { + this.type = type; + this.data = data; + } + + public String toString() { + return String.format("Event.%s(%s)", type, data); + } + } + + public static class ClientException extends Exception { + public ClientException(String reason) { + super(reason); + } + } + + + private final Socket socket; + private final OutputStream outputStream; + private final BufferedReader inputBuffer; + + protected LinkedList<Event> eventQueue = new LinkedList<>(); + protected LinkedList<String> eventLineQueue = new LinkedList<>(); + + public GameClientBase(String host, int port) throws UnknownHostException, IOException, InterruptedException { + socket = new Socket(host, port); + outputStream = socket.getOutputStream(); + inputBuffer = new BufferedReader(new InputStreamReader(socket.getInputStream())); + + Thread.sleep(100); + while (inputBuffer.ready()) { + inputBuffer.readLine(); + Thread.sleep(100); + } + } + + protected void sendQuoted(String command, String... arguments) throws IOException, ClientException { + for (int i = 0; i < arguments.length; i++) + arguments[i] = '"' + arguments[i] + '"'; + + send(command, arguments); + } + + + protected void send(String command, String... arguments) throws IOException, ClientException { + var requestBuilder = new StringBuilder(command); + for (var argument : arguments) { + requestBuilder.append(' '); + requestBuilder.append(argument); + } + + requestBuilder.append('\n'); + outputStream.write(requestBuilder.toString().getBytes()); + + String response; + for (;;) { + response = inputBuffer.readLine(); + if (response.startsWith("ERR ")) + throw new ClientException(response.substring(4)); + else if (response.startsWith("SVR ")) { + eventLineQueue.add(response); + continue; + } else if (response.equals("OK")) + break; + throw new ClientException("invalid server response: '" + response + "'"); + } + } + + public Event getEvent(EventType... target) throws ClientException, IOException, InterruptedException { + return getEvent(1, target); + } + + public Event getEvent(double timeout, EventType... target) throws ClientException, IOException, InterruptedException { + if (!eventQueue.isEmpty()) { + if (target == null) + return eventQueue.poll(); + + for (int i = 0; i < eventQueue.size(); i++) { + if (Arrays.asList(target).contains(eventQueue.get(i).type)) { + return eventQueue.remove(i); + } + } + } + + long start = System.currentTimeMillis(); + Event result = null; + + do { + String line; + if (eventLineQueue.isEmpty()) { + Thread.sleep(100); + if (!inputBuffer.ready()) + continue; + line = inputBuffer.readLine(); + } else { + line = eventLineQueue.poll(); + } + + if (!line.startsWith("SVR ")) + throw new ClientException("invalid server response: '" + line + "'"); + + var format = line.split(" ", 3); + switch (format[1].toLowerCase()) { + case "playerlist": + result = new Event(EventType.PLAYERLIST, new EventParser(format[2]).parseData()); + break; + case "gamelist": + result = new Event(EventType.GAMELIST, new EventParser(format[2]).parseData()); + break; + case "game": + format = line.split(" ", 4); + for (var evt : EventType.values()) { + if (evt.name().equals(format[2])) { + result = new Event(evt, new EventParser(format[3]).parseData()); + break; + } + } + if (result == null) + throw new ClientException("invalid server response: '" + line + "'"); + } + + if (result != null) { + if (target.length == 0 || target.length > 0 && Arrays.asList(target).contains(result.type)) + return result; + + eventQueue.push(result); + result = null; + } + } while (result == null && (timeout == -1 || System.currentTimeMillis() - start < timeout * 1000)); + + return null; + } + + public void close() throws IOException { + outputStream.write("logout\n".getBytes()); + socket.close(); + } +} diff --git a/target/classes/module-info.class b/target/classes/module-info.class Binary files differ. diff --git a/target/classes/nl/isygameclient/controllers/HelloController.class b/target/classes/nl/isygameclient/controllers/HelloController.class Binary files differ. diff --git a/target/classes/nl/isygameclient/css/hello.css b/target/classes/nl/isygameclient/css/hello.css @@ -0,0 +1,3 @@ +.button { + -fx-background-color: #2196F3; +} +\ No newline at end of file diff --git a/target/classes/nl/isygameclient/images/reversie_logo.png b/target/classes/nl/isygameclient/images/reversie_logo.png Binary files differ. diff --git a/target/classes/nl/isygameclient/images/tictactoe_logo.png b/target/classes/nl/isygameclient/images/tictactoe_logo.png Binary files differ. diff --git a/target/classes/nl/isygameclient/models/SimpleCalculator.class b/target/classes/nl/isygameclient/models/SimpleCalculator.class Binary files differ. diff --git a/target/classes/nl/isygameclient/network/EventParser.class b/target/classes/nl/isygameclient/network/EventParser.class Binary files differ. diff --git a/target/classes/nl/isygameclient/network/GameClient.class b/target/classes/nl/isygameclient/network/GameClient.class Binary files differ. diff --git a/target/classes/nl/isygameclient/network/GameClientBase$ClientException.class b/target/classes/nl/isygameclient/network/GameClientBase$ClientException.class Binary files differ. diff --git a/target/classes/nl/isygameclient/network/GameClientBase$Event.class b/target/classes/nl/isygameclient/network/GameClientBase$Event.class Binary files differ. diff --git a/target/classes/nl/isygameclient/network/GameClientBase$EventType.class b/target/classes/nl/isygameclient/network/GameClientBase$EventType.class Binary files differ. diff --git a/target/classes/nl/isygameclient/network/GameClientBase.class b/target/classes/nl/isygameclient/network/GameClientBase.class Binary files differ. diff --git a/target/classes/nl/isygameclient/util/Settings.class b/target/classes/nl/isygameclient/util/Settings.class Binary files differ. diff --git a/target/classes/nl/isygameclient/util/SettingsHandler.class b/target/classes/nl/isygameclient/util/SettingsHandler.class Binary files differ. diff --git a/target/classes/nl/isygameclient/views/hello-view.fxml b/target/classes/nl/isygameclient/views/hello-view.fxml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.*?> +<?import javafx.scene.control.*?> +<?import javafx.scene.layout.*?> + +<VBox alignment="CENTER" spacing="20.0" stylesheets="@../css/hello.css" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/16" fx:controller="nl.isygameclient.controllers.HelloController"> + <padding> + <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" /> + </padding> + + <Label fx:id="welcomeText" /> + <Button fx:id="welcomeButton" onAction="#onHelloButtonClick" text="Hello!" /> +</VBox> diff --git a/target/test-classes/nl/isygameclient/models/SimpleCalculatorTest.class b/target/test-classes/nl/isygameclient/models/SimpleCalculatorTest.class Binary files differ. diff --git a/target/test-classes/nl/isygameclient/util/SettingsTest.class b/target/test-classes/nl/isygameclient/util/SettingsTest.class Binary files differ.