From 16cf29a5903ace916c2865930dc953af55cf5c7d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Elias=20M=C3=BCller?= <elias@elias-mueller.com>
Date: Tue, 3 Oct 2023 10:40:32 +0200
Subject: [PATCH] Refactored User room to be optional

---
 .../privileged/SetRoomOwnerCommand.java       |  6 ++---
 .../handler/global/PlayerLoginHandler.java    |  6 ++++-
 .../minenet/minigames/instance/game/Game.java |  2 +-
 .../minigames/instance/game/GameList.java     | 10 ++++----
 .../minigames/instance/game/GameType.java     |  4 ++-
 .../trafficlightrace/TrafficLightRace.java    |  7 +++++-
 .../instance/hub/inventory/JoinInventory.java | 15 +++++------
 .../minenet/minigames/instance/room/Room.java | 25 +++++++++++++------
 8 files changed, 46 insertions(+), 29 deletions(-)

diff --git a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetRoomOwnerCommand.java b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetRoomOwnerCommand.java
index 45f1e87..ac6e53b 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetRoomOwnerCommand.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/command/privileged/SetRoomOwnerCommand.java
@@ -19,7 +19,7 @@ public class SetRoomOwnerCommand extends PrivilegedCommand {
 
         setDefaultExecutor((sender, context) -> {
             if(sender instanceof Player p) {
-                Room.getRoom(p).setOwner(p);
+                Room.getRoom(p).orElseThrow().setOwner(p);
                 new ChatMessage(Icon.SUCCESS).appendStatic("You are now the owner of this room!").send(sender);
             }
         });
@@ -28,7 +28,7 @@ public class SetRoomOwnerCommand extends PrivilegedCommand {
             System.out.println("Test");
             if(sender instanceof Player p) {
                 Player newOwner = MinecraftServer.getConnectionManager().getPlayer(context.getRaw("player"));
-                Room.getRoom(p).setOwner(Objects.requireNonNull(newOwner));
+                Room.getRoom(p).orElseThrow().setOwner(Objects.requireNonNull(newOwner));
                 new ChatMessage(Icon.SUCCESS).appendStatic("The new owner has been set!").send(sender);
             }
         }, ArgumentType.Entity("player").onlyPlayers(true));
@@ -36,6 +36,6 @@ public class SetRoomOwnerCommand extends PrivilegedCommand {
 
     @Override
     protected CommandCondition isPrivileged() {
-        return (sender, commandString) -> super.isPrivileged().canUse(sender, commandString) || Room.getRoom(((Player) sender)).getOwner() == sender;
+        return (sender, commandString) -> super.isPrivileged().canUse(sender, commandString) || Room.getRoom(((Player) sender)).orElseThrow().getOwner() == sender;
     }
 }
diff --git a/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLoginHandler.java b/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLoginHandler.java
index 19043c0..e64ea10 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLoginHandler.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/handler/global/PlayerLoginHandler.java
@@ -1,6 +1,8 @@
 package eu.mhsl.minenet.minigames.handler.global;
 
+import eu.mhsl.minenet.minigames.instance.room.Room;
 import eu.mhsl.minenet.minigames.skin.SkinCache;
+import net.minestom.server.MinecraftServer;
 import net.minestom.server.entity.Player;
 import net.minestom.server.event.EventListener;
 import net.minestom.server.event.player.PlayerLoginEvent;
@@ -25,8 +27,10 @@ public class PlayerLoginHandler implements EventListener<PlayerLoginEvent> {
         SkinCache.applySkin(p);
 
 
-        if(p.getUsername().equalsIgnoreCase("minetec"))
+        if(p.getUsername().equalsIgnoreCase("minetec")) {
             p.addPermission(new Permission("admin"));
+            MinecraftServer.getSchedulerManager().scheduleNextTick(() -> Room.createRoom(p));
+        }
 
         Logger.getLogger("user").info(p.getUsername() + " joined");
 
diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java
index 4364ac9..07bcba2 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/Game.java
@@ -52,7 +52,7 @@ public abstract class Game extends MineNetInstance implements Spawnable {
         try {
 
             Game game = factory.manufacture(options);
-            Room.getRoom(owner).moveMembersToGame(game);
+            Room.getRoom(owner).orElseThrow().moveMembersToGame(game);
             game.load();
 
         } catch (Exception e) {
diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/GameList.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/GameList.java
index 8fe8871..a9f06f9 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/GameList.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/GameList.java
@@ -11,13 +11,13 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.types.towerdefense.Towe
 import eu.mhsl.minenet.minigames.instance.game.stateless.types.trafficlightrace.TrafficLightRaceFactory;
 
 public enum GameList {
-    DEATHCUBE(new DeathcubeFactory(), GameType.OTHER),
+    DEATHCUBE(new DeathcubeFactory(), GameType.JUMPNRUN),
     STICKFIGHT(new StickFightFactory(), GameType.PVP),
-    MINERUN(new MinerunFactory(), GameType.PVE),
+    MINERUN(new MinerunFactory(), GameType.JUMPNRUN),
     TRAFFICLIGHTRACE(new TrafficLightRaceFactory(), GameType.OTHER),
-    TOWERDEFENSE(new TowerdefenseFactory(), GameType.PVE),
-    BEDWARS(new BedwarsFactory(), GameType.PVP),
-    BACKROOMS(new BackroomsFactory(), GameType.PVE),
+    TOWERDEFENSE(new TowerdefenseFactory(), GameType.PROTOTYPE),
+    BEDWARS(new BedwarsFactory(), GameType.PROTOTYPE),
+    BACKROOMS(new BackroomsFactory(), GameType.PROTOTYPE),
     SPLEEF(new SpleefFactory(), GameType.PVP);
 
     private final GameFactory factory;
diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/GameType.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/GameType.java
index 94ae8f4..ea2d329 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/GameType.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/GameType.java
@@ -6,7 +6,9 @@ import net.minestom.server.item.Material;
 public enum GameType {
     OTHER(Material.GRASS_BLOCK, TranslatedComponent.byId("GameType#other"), TranslatedComponent.byId("GameType#other_description")),
     PVP(Material.DIAMOND_SWORD, TranslatedComponent.byId("GameType#pvp"), TranslatedComponent.byId("GameType#pvp_description")),
-    PVE(Material.DIAMOND_PICKAXE, TranslatedComponent.byId("GameType#pve"), TranslatedComponent.byId("GameType#pve_description"));
+    PVE(Material.DIAMOND_PICKAXE, TranslatedComponent.byId("GameType#pve"), TranslatedComponent.byId("GameType#pve_description")),
+    JUMPNRUN(Material.DIAMOND_BOOTS, TranslatedComponent.byId("GameType#jumpnrun"), TranslatedComponent.byId("GameType#jumpnrun_description")),
+    PROTOTYPE(Material.COMMAND_BLOCK, TranslatedComponent.byId("GameType#prototype"), TranslatedComponent.byId("GameType#prototype_description"));
 
 
     final Material icon;
diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/TrafficLightRace.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/TrafficLightRace.java
index 6bdd271..3f29679 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/TrafficLightRace.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/trafficlightrace/TrafficLightRace.java
@@ -4,6 +4,7 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
 import eu.mhsl.minenet.minigames.score.FirstWinsScore;
 import eu.mhsl.minenet.minigames.util.BatchUtil;
 import eu.mhsl.minenet.minigames.instance.Dimension;
+import net.minestom.server.coordinate.Pos;
 import net.minestom.server.coordinate.Vec;
 import net.minestom.server.event.player.PlayerMoveEvent;
 import net.minestom.server.instance.batch.AbsoluteBlockBatch;
@@ -26,7 +27,7 @@ class TrafficLightRace extends StatelessGame {
     protected void onLoad(@NotNull CompletableFuture<Void> callback) {
         AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
         for (int x = -10; x <= 10; x++) {
-            for (int z = 5; z <= 100; z++) {
+            for (int z = 0; z <= 100; z++) {
                 batch.setBlock(x, 5, z, super.rnd.nextInt(0, 100) > 90 ? Block.SOUL_SAND : Block.BLACK_CONCRETE_POWDER);
             }
         }
@@ -67,4 +68,8 @@ class TrafficLightRace extends StatelessGame {
         }
     }
 
+    @Override
+    public Pos getSpawn() {
+        return new Pos(0, 6, 10);
+    }
 }
diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/hub/inventory/JoinInventory.java b/src/main/java/eu/mhsl/minenet/minigames/instance/hub/inventory/JoinInventory.java
index 0f1ea29..dfe6025 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/instance/hub/inventory/JoinInventory.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/instance/hub/inventory/JoinInventory.java
@@ -15,24 +15,21 @@ import net.minestom.server.inventory.click.ClickType;
 import net.minestom.server.inventory.condition.InventoryConditionResult;
 import net.minestom.server.item.ItemStack;
 import net.minestom.server.item.Material;
-import net.minestom.server.item.metadata.PlayerHeadMeta;
 import net.minestom.server.network.packet.client.play.ClientNameItemPacket;
 
 import java.util.Locale;
+import java.util.Optional;
 
 public class JoinInventory extends InteractableInventory {
     private String typedText = "";
-    private final String prefix = "Name:";
+    private final String prefix = "Suche: ";
 
     public JoinInventory(Player p) {
         super(InventoryType.ANVIL, TranslatedComponent.assemble("hub#join_title", p));
 
         setClickableItem(
-                ItemStack.builder(Material.PLAYER_HEAD)
+                ItemStack.builder(Material.GREEN_STAINED_GLASS_PANE)
                         .displayName(Component.text(prefix))
-                        .meta(PlayerHeadMeta.class, builder -> {
-
-                        })
                         .build(),
                 0,
                 itemClick -> {}
@@ -54,9 +51,9 @@ public class JoinInventory extends InteractableInventory {
 
         typedText = formatInput(typedText);
 
-        Room target = Room.getRoom(MinecraftServer.getConnectionManager().findPlayer(typedText));
-        if(target != null)
-            Room.setRoom(player, target);
+        Optional<Room> target = Room.getRoom(MinecraftServer.getConnectionManager().findPlayer(typedText));
+        if(target.isPresent())
+            Room.setRoom(player, target.get());
         else
             new ChatMessage(Icon.ERROR).appendTranslated("hub#join_notFound").appendStatic(" " + typedText).send(player);
     }
diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java b/src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java
index 8b1c069..6640a2a 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/instance/room/Room.java
@@ -17,6 +17,7 @@ import net.minestom.server.entity.GameMode;
 import net.minestom.server.entity.Player;
 import net.minestom.server.event.player.PlayerBlockBreakEvent;
 import net.minestom.server.event.player.PlayerDisconnectEvent;
+import net.minestom.server.event.player.PlayerEntityInteractEvent;
 import net.minestom.server.instance.AnvilLoader;
 
 import java.util.*;
@@ -30,22 +31,22 @@ public class Room extends MineNetInstance implements Spawnable {
     public static Room createRoom(Player owner) {
         logger.info("Creating room with owner " + owner.getUsername());
         setRoom(owner, new Room(owner));
-        return getRoom(owner);
+        return getRoom(owner).orElseThrow();
     }
 
     public static void deleteRoom(Room room) {
-        logger.info("Deleting room with owner " + room.owner.getUsername());
+        logger.info("Deleting room " + room.uniqueId);
         rooms.values().removeAll(Collections.singleton(room)); // remove(room) would only remove the first one
         room.getAllMembers().forEach(player -> MoveInstance.move(player, Hub.INSTANCE));
         MoveInstance.forceCloseInstance(room);
     }
 
-    public static Room getRoom(Player p) {
-        return rooms.get(p);
+    public static Optional<Room> getRoom(Player p) {
+        return Optional.ofNullable(rooms.get(p));
     }
 
     public static void setOwnRoom(Player p) {
-        setRoom(p, getRoom(p));
+        setRoom(p, getRoom(p).orElseThrow());
     }
 
     public static void setRoom(Player p, Room room) {
@@ -68,11 +69,13 @@ public class Room extends MineNetInstance implements Spawnable {
     }
 
     private Player owner;
+    private GameSelector gameSelector;
     private Room(Player owner) {
         super(Dimension.THE_END.DIMENSION);
         construct();
         setOwner(owner);
-        new GameSelector().setInstance(this, new Pos(0.5, 16, 9.5));
+        this.gameSelector = new GameSelector();
+        this.gameSelector.setInstance(this, new Pos(0.5, 16, 9.5));
     }
 
     protected Room() {
@@ -104,7 +107,7 @@ public class Room extends MineNetInstance implements Spawnable {
                     .findFirst() // find the first user meeting the requirement
                     .ifPresentOrElse(
                             this::setOwner, // set the new owner
-                            () -> Room.deleteRoom(Room.getRoom(p)) // or else delete the room (no players in the room)
+                            () -> Room.getRoom(p).ifPresent(Room::deleteRoom) // or else delete the room (no players in the room)
                     );
 
             Room.unsetRoom(p); // remove the player itself from the room
@@ -122,10 +125,16 @@ public class Room extends MineNetInstance implements Spawnable {
 
     public Set<Player> getAllMembers() {
         return rooms.keySet().stream()
-                .filter(player -> getRoom(player) == this)
+                .filter(player -> getRoom(player).orElse(null) == this)
                 .collect(Collectors.toSet());
     }
 
+    @Override
+    protected boolean onPlayerJoin(Player p) {
+        this.gameSelector.onInteract(new PlayerEntityInteractEvent(p, gameSelector, Player.Hand.MAIN, p.getPosition()));
+        return super.onPlayerJoin(p);
+    }
+
     @Override
     public Pos getSpawn() {
         return new Pos(0.5, 16, 0.5);