From 3e1b8a629e510d3097659318675e7c03a1b3d48d Mon Sep 17 00:00:00 2001 From: Wim Wenigerkind Date: Tue, 4 Mar 2025 14:14:09 +0100 Subject: [PATCH] zuul extra wip --- Dockerfile-game | 34 ++++++++ Dockerfile-nginx | 13 +++ docker-compose.yaml | 27 ++++++ html/index.html | 77 +++++++++++++++++ nginx/nginx.conf | 36 ++++++++ src/de/szut/zuul/Game.java | 128 ++++++++++++++-------------- src/de/szut/zuul/Parser.java | 41 ++++----- src/de/szut/zuul/ZuulUI.java | 2 +- src/de/szut/zuul/ZuulWebsocket.java | 67 +++++++++++++++ 9 files changed, 335 insertions(+), 90 deletions(-) create mode 100755 Dockerfile-game create mode 100644 Dockerfile-nginx create mode 100644 docker-compose.yaml create mode 100755 html/index.html create mode 100644 nginx/nginx.conf create mode 100644 src/de/szut/zuul/ZuulWebsocket.java diff --git a/Dockerfile-game b/Dockerfile-game new file mode 100755 index 0000000..a92988b --- /dev/null +++ b/Dockerfile-game @@ -0,0 +1,34 @@ +# 1. Java-Stage: Kompilieren +FROM openjdk:17-jdk-slim AS java-build +WORKDIR /app + +# Java-WebSocket und SLF4J-Bibliothek herunterladen +RUN apt-get update && apt-get install -y wget \ + && wget https://repo1.maven.org/maven2/org/java-websocket/Java-WebSocket/1.5.3/Java-WebSocket-1.5.3.jar -O /app/Java-WebSocket.jar \ + && wget https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.32/slf4j-api-1.7.32.jar -O /app/slf4j-api-1.7.32.jar \ + && wget https://repo1.maven.org/maven2/org/slf4j/slf4j-simple/1.7.32/slf4j-simple-1.7.32.jar -O /app/slf4j-simple-1.7.32.jar + +# Quellcode kopieren +COPY src /app/src + +# Erstelle bin-Ordner für kompilierten Code +RUN mkdir -p /app/bin + +# Kompilieren mit der WebSocket-Bibliothek +RUN javac -cp /app/Java-WebSocket.jar:/app/slf4j-api-1.7.32.jar:/app/slf4j-simple-1.7.32.jar -d /app/bin /app/src/de/szut/zuul/*.java + +# 2. Finale Java-Stage +FROM openjdk:17-jdk-slim +WORKDIR /app + +# Kopiere das kompilierte Java-Programm +COPY --from=java-build /app/bin /app +COPY --from=java-build /app/Java-WebSocket.jar /app/Java-WebSocket.jar +COPY --from=java-build /app/slf4j-api-1.7.32.jar /app/slf4j-api-1.7.32.jar +COPY --from=java-build /app/slf4j-simple-1.7.32.jar /app/slf4j-simple-1.7.32.jar + +# Port für WebSocket öffnen +EXPOSE 8867 + +# WebSocket-Server starten +CMD ["java", "-cp", "/app:/app/Java-WebSocket.jar:/app/slf4j-api-1.7.32.jar:/app/slf4j-simple-1.7.32.jar", "de.szut.zuul.ZuulWebsocket"] diff --git a/Dockerfile-nginx b/Dockerfile-nginx new file mode 100644 index 0000000..c251237 --- /dev/null +++ b/Dockerfile-nginx @@ -0,0 +1,13 @@ +FROM nginx:alpine + +# Kopiere die Nginx-Konfiguration +COPY nginx/nginx.conf /etc/nginx/nginx.conf + +# Kopiere die HTML-Datei, die xterm.js verwendet +COPY html/index.html /usr/share/nginx/html/index.html + +# Setze die richtigen Berechtigungen für das HTML-Verzeichnis und die Datei +RUN chmod -R 755 /usr/share/nginx/html && chmod 644 /usr/share/nginx/html/index.html + +# Exponiere Port 80 für den Nginx-Server +EXPOSE 80 diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..53ce759 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,27 @@ +version: '3' +services: + game: + build: + context: . + dockerfile: Dockerfile-game + container_name: game-1 + ports: + - "8867:8867" + networks: + - app-network + + nginx: + build: + context: . + dockerfile: Dockerfile-nginx + container_name: nginx-1 + ports: + - "8067:80" + depends_on: + - game + networks: + - app-network + +networks: + app-network: + driver: bridge diff --git a/html/index.html b/html/index.html new file mode 100755 index 0000000..fe1841d --- /dev/null +++ b/html/index.html @@ -0,0 +1,77 @@ + + + + WebSocket Terminal + + + +
+> + + + + + + \ No newline at end of file diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..415c3a5 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,36 @@ +events { + worker_connections 1024; +} + +http { + server { + listen 80; + + location / { + root /usr/share/nginx/html; + index index.html; + } + + location /ws { + proxy_pass http://game-1:8867; # WebSocket-Server + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + + # CORS: Erlaubt alle Ursprünge + add_header Access-Control-Allow-Origin *; + add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; + add_header Access-Control-Allow-Headers 'Origin, X-Requested-With, Content-Type, Accept, Authorization'; + + # CORS für OPTIONS-Anfragen + if ($request_method = 'OPTIONS') { + add_header Access-Control-Allow-Origin *; + add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; + add_header Access-Control-Allow-Headers 'Origin, X-Requested-With, Content-Type, Accept, Authorization'; + return 204; + } + } + } +} diff --git a/src/de/szut/zuul/Game.java b/src/de/szut/zuul/Game.java index bbbe6fd..c85bd8a 100644 --- a/src/de/szut/zuul/Game.java +++ b/src/de/szut/zuul/Game.java @@ -1,5 +1,6 @@ package de.szut.zuul; +import org.java_websocket.WebSocket; import java.util.Random; /** @@ -23,6 +24,7 @@ public class Game { private Parser parser; private Player player; + private WebSocket conn; /** * Create the game and initialise its internal map. @@ -116,32 +118,26 @@ public class Game * * @return */ - public void play() + public void play(WebSocket conn) { - printWelcome(); + this.conn = conn; + + conn.send("Spiel wurde gestartet..."); + printWelcome(conn); // Enter the main command loop. Here we repeatedly read commands and // execute them until the game is over. - - boolean finished = false; - while (! finished) { - Command command = parser.getCommand(); - finished = processCommand(command); - } - System.out.println("Thank you for playing. Good bye."); } /** * Print out the opening message for the player. */ - private void printWelcome() + public void printWelcome(WebSocket conn) { - System.out.println(); - System.out.println("Welcome to the World of Zuul!"); - System.out.println("World of Zuul is a new, incredibly boring adventure game."); - System.out.println("Type 'help' if you need help."); - System.out.println(); - printRoomInformation(); + conn.send("Welcome to the World of Zuul!"); + conn.send("World of Zuul is a new, incredibly boring adventure game."); + conn.send("Type 'help' if you need help."); + printRoomInformation(conn); } /** @@ -149,24 +145,25 @@ public class Game * @param command The command to be processed. * @return true If the command ends the game, false otherwise. */ - private boolean processCommand(Command command) + + public boolean processCommand(Command command, WebSocket conn) { boolean wantToQuit = false; if(command.isUnknown()) { - System.out.println("I don't know what you mean..."); + conn.send("I don't know what you mean..."); return false; } String commandWord = command.getCommandWord(); switch (commandWord) { - case "help" -> printHelp(); - case "go" -> goRoom(command); - case "quit" -> wantToQuit = quit(command); - case "look" -> look(player.getCurrentRoom()); - case "status" -> showStatus(); - case "take" -> takeItem(command); - case "drop" -> dropItem(command); + case "help" -> printHelp(conn); + case "go" -> goRoom(command, conn); + case "quit" -> wantToQuit = quit(command, conn); + case "look" -> look(player.getCurrentRoom(), conn); + case "status" -> showStatus(conn); + case "take" -> takeItem(command, conn); + case "drop" -> dropItem(command, conn); case "say" -> { if (command.hasSecondWord()) { if (command.getSecondWord().equals("health")) { @@ -175,10 +172,10 @@ public class Game Ollama.chat(command.getSecondWord(), player); } } else { - System.out.println("Chat what?"); + conn.send("Chat what?"); } } - case "eat" -> eatMuffin(command); + case "eat" -> eatMuffin(command, conn); } return wantToQuit; @@ -191,24 +188,24 @@ public class Game * Here we print some stupid, cryptic message and a list of the * command words. */ - private void printHelp() + public void printHelp(WebSocket conn) { - System.out.println("You are lost. You are alone. You wander"); - System.out.println("through the jungle. At once there is a glade. On it there a buildings..."); - System.out.println(); - System.out.println("Your command words are:"); - System.out.println(parser.showCommands()); + conn.send("You are lost. You are alone. You wander"); + conn.send("through the jungle. At once there is a glade. On it there a buildings..."); + conn.send(" "); + conn.send("Your command words are:"); + conn.send(parser.showCommands()); } /** * Try to go in one direction. If there is an exit, enter * the new room, otherwise print an error message. */ - private void goRoom(Command command) + public void goRoom(Command command, WebSocket conn) { if(!command.hasSecondWord()) { // if there is no second word, we don't know where to go... - System.out.println("Go where?"); + conn.send("Go where?"); return; } @@ -220,11 +217,11 @@ public class Game nextRoom = player.getCurrentRoom().getExits(direction); if (nextRoom == null) { - System.out.println("There is no door!"); + conn.send("There is no door!"); } else { player.goTo(nextRoom); - printRoomInformation(); + printRoomInformation(conn); } } @@ -233,34 +230,33 @@ public class Game * whether we really quit the game. * @return true, if this command quits the game, false otherwise. */ - private boolean quit(Command command) + public boolean quit(Command command, WebSocket conn) { if(command.hasSecondWord()) { - System.out.println("Quit what?"); + conn.send("Quit what?"); return false; } else { return true; // signal that we want to quit } } - private void printRoomInformation() + private void printRoomInformation(WebSocket conn) { - System.out.print(player.getCurrentRoom().getLongDescription()); - System.out.println(); + conn.send(player.getCurrentRoom().getLongDescription()); } - private void look(Room currentRoom) + private void look(Room currentRoom, WebSocket conn) { - System.out.println(currentRoom.getLongDescription()); + conn.send(currentRoom.getLongDescription()); } - private void showStatus() + private void showStatus(WebSocket conn) { - System.out.println(player.showStatus()); - printRoomInformation(); + conn.send(player.showStatus()); + printRoomInformation(conn); } - private void takeItem(Command command) + private void takeItem(Command command, WebSocket conn) { if (!command.hasSecondWord()) { - System.out.println("Take what?"); + conn.send("Take what?"); return; } @@ -268,20 +264,20 @@ public class Game Item item = player.getCurrentRoom().removeItem(itemName); if (item != null) { if (player.takeItem(item)) { - System.out.println("You took the item: " + item.getName()); + conn.send("You took the item: " + item.getName()); } else { - System.out.println("You can't take this item. It's too heavy."); + conn.send("You can't take this item. It's too heavy."); player.getCurrentRoom().putItem(item); } } else { - System.out.println("There is no such item in this room."); + conn.send("There is no such item in this room."); } - showStatus(); + showStatus(conn); } - private void dropItem(Command command) + private void dropItem(Command command, WebSocket conn) { if (!command.hasSecondWord()) { - System.out.println("Drop what?"); + conn.send("Drop what?"); return; } @@ -289,29 +285,33 @@ public class Game Item item = player.dropItem(itemName); if (item != null) { player.getCurrentRoom().putItem(item); - System.out.println("You dropped the item: " + item.getName()); + conn.send("You dropped the item: " + item.getName()); } else { - System.out.println("You don't have this item."); + conn.send("You don't have this item."); } - showStatus(); + showStatus(conn); } - private void eatMuffin(Command command) + private void eatMuffin(Command command, WebSocket conn) { if (command.hasSecondWord()) { if (command.getSecondWord().equals("Muffin")) { Item item = player.getCurrentRoom().removeItem("Muffin"); if (item != null) { player.eatMuffin(); - System.out.println("You ate a muffin. Your load capacity is now " + player.getLoadCapacity()); - showStatus(); + conn.send("You ate a muffin. Your load capacity is now " + player.getLoadCapacity()); + showStatus(conn); } else { - System.out.println("There is no muffin in this room."); + conn.send("There is no muffin in this room."); } } else { - System.out.println("Eat what?"); + conn.send("Eat what?"); } } else { - System.out.println("Eat what?"); + conn.send("Eat what?"); } } + public Player getPlayer() + { + return player; + } } diff --git a/src/de/szut/zuul/Parser.java b/src/de/szut/zuul/Parser.java index c02530f..a050bbd 100644 --- a/src/de/szut/zuul/Parser.java +++ b/src/de/szut/zuul/Parser.java @@ -1,5 +1,6 @@ package de.szut.zuul; +import org.java_websocket.WebSocket; import java.util.Scanner; /** @@ -21,7 +22,6 @@ import java.util.Scanner; public class Parser { private CommandWords commands; // holds all valid command words - private Scanner reader; // source of command input /** * Create a parser to read from the terminal window. @@ -29,39 +29,30 @@ public class Parser public Parser() { commands = new CommandWords(); - reader = new Scanner(System.in); } /** * @return The next command from the user. */ - public Command getCommand() + public Command getCommand(String inputLine, WebSocket conn) { - String inputLine; // will hold the full input line - String word1 = null; - String word2 = null; - - System.out.print("> "); // print prompt - - inputLine = reader.nextLine(); - - // Find up to two words on the line. - Scanner tokenizer = new Scanner(inputLine); - if(tokenizer.hasNext()) { - word1 = tokenizer.next(); // get first word - if(tokenizer.hasNext()) { - word2 = tokenizer.next(); // get second word - // note: we just ignore the rest of the input line. - } + if (inputLine == null || inputLine.trim().isEmpty()) { + // Falls die Eingabe leer oder null ist, eine ungültige Eingabe zurückgeben + return new Command(null, null); } - // Now check whether this word is known. If so, create a command - // with it. If not, create a "null" command (for unknown command). - if(commands.isCommand(word1)) { + // Entferne führende und nachfolgende Leerzeichen und teile die Eingabe in Wörter + String[] words = inputLine.trim().split("\\s+"); + + String word1 = words[0]; // Das erste Wort + String word2 = words.length > 1 ? words[1] : null; // Das zweite Wort, falls vorhanden + + // Jetzt prüfen, ob das erste Wort ein gültiger Befehl ist. + if (commands.isCommand(word1)) { return new Command(word1, word2); - } - else { - return new Command(null, word2); + } else { + // Wenn der Befehl ungültig ist, ein null-Command zurückgeben + return new Command(null, word2); } } public String showCommands() diff --git a/src/de/szut/zuul/ZuulUI.java b/src/de/szut/zuul/ZuulUI.java index d0955d7..e48677c 100644 --- a/src/de/szut/zuul/ZuulUI.java +++ b/src/de/szut/zuul/ZuulUI.java @@ -7,7 +7,7 @@ public class ZuulUI { */ public static void main(String[] args) { Game game = new Game(); - game.play(); + //game.play(); } } diff --git a/src/de/szut/zuul/ZuulWebsocket.java b/src/de/szut/zuul/ZuulWebsocket.java new file mode 100644 index 0000000..06c3bfb --- /dev/null +++ b/src/de/szut/zuul/ZuulWebsocket.java @@ -0,0 +1,67 @@ +package de.szut.zuul; + +import java.io.IOException; +import java.net.InetSocketAddress; +import org.java_websocket.server.WebSocketServer; +import org.java_websocket.WebSocket; +import org.java_websocket.handshake.ClientHandshake; + +public class ZuulWebsocket extends WebSocketServer { + private Game game; + private Parser parser; + + public ZuulWebsocket(int port) { + super(new InetSocketAddress(port)); + this.game = new Game(); + this.parser = new Parser(); + } + + @Override + public void onOpen(WebSocket conn, ClientHandshake handshake) { + // Begrüßung des Spielers und Aufforderung, das Spiel zu starten + conn.send("Start Game."); + game.play(conn); + } + + @Override + public void onMessage(WebSocket conn, String message) { + boolean finished = false; + + conn.send(" "); + + // Verarbeite den Befehl, nur einmal pro Nachricht + Command command = parser.getCommand(message, conn); + + // Beende die Schleife, wenn der Befehl erfolgreich verarbeitet wurde + finished = game.processCommand(command, conn); + + // Eine Nachricht zum Beenden des Spiels senden + if (finished) { + conn.send("Thank you for playing. Good bye."); + } + } + + @Override + public void onClose(WebSocket conn, int code, String reason, boolean remote) { + // Hier kannst du ggf. noch Aufräumarbeiten machen + } + + @Override + public void onError(WebSocket conn, Exception ex) { + System.err.println("Fehler aufgetreten: " + ex.getMessage()); + ex.printStackTrace(); + } + + // Leere Implementierung der onStart-Methode + @Override + public void onStart() { + System.out.println("WebSocket-Server gestartet"); + } + + public static void main(String[] args) { + int port = 8867; // Port für den WebSocket-Server + ZuulWebsocket server = new ZuulWebsocket(port); // Instanziierung der Klasse + server.start(); + System.out.println("WebSocket-Server läuft auf Port " + port); + } +}