From 73a374e5296210e6aef437b6841ecc9a923b79c8 Mon Sep 17 00:00:00 2001
From: lars <larslukasneuhaus@gmx.de>
Date: Wed, 23 Oct 2024 17:26:31 +0200
Subject: [PATCH] added timeout for tetris and display points at end of
 PointsWinScore

---
 .../game/stateless/StatelessGame.java         |  6 ++--
 .../game/stateless/types/tetris/Tetris.java   | 18 ++++++++--
 .../types/tetris/game/TetrisGame.java         | 21 +++++++-----
 .../minigames/score/PointsWinScore.java       | 34 +++++++++++++++++++
 .../mhsl/minenet/minigames/score/Score.java   |  2 ++
 5 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/StatelessGame.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/StatelessGame.java
index c9efbb0..d0bd25d 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/StatelessGame.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/StatelessGame.java
@@ -51,7 +51,9 @@ public class StatelessGame extends Game {
                 int timeLeft = timeLimit - timePlayed;
                 switch (timeLeft) {
                     case 60, 30, 10, 5, 4, 3, 2, 1 ->
-                            new ChatMessage(Icon.SCIENCE).appendStatic("Noch " + timeLeft + " Sekunden!").send(getPlayers());
+                        new ChatMessage(Icon.SCIENCE).appendStatic("Noch " + timeLeft + " Sekunden!").send(getPlayers());
+                    case 120 ->
+                        new ChatMessage(Icon.SCIENCE).appendStatic("Noch 2 Minuten!").send(getPlayers());
                 }
 
                 timePlayed++;
@@ -100,7 +102,7 @@ public class StatelessGame extends Game {
         countdownUnload();
     }
 
-    private void countdownUnload() {
+    protected void countdownUnload() {
         new TitleMessage(Duration.ofSeconds(1)).appendTranslated("score#done").send(getPlayers());
         scheduler().scheduleTask(this::unload, TaskSchedule.seconds(5), TaskSchedule.stop());
     }
diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/Tetris.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/Tetris.java
index da6f2ec..75bedec 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/Tetris.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/Tetris.java
@@ -18,16 +18,18 @@ import org.jetbrains.annotations.NotNull;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Random;
 
 class Tetris extends StatelessGame {
     private final Map<Player, TetrisGame> tetrisGames = new HashMap<>();
     private final int nextTetrominoesCount;
     private final boolean isFast;
     private final boolean hasCombat;
+    private boolean setTimeLimit = false;
+    private final long randomSeed;
 
     public Tetris(int nextTetrominoesCount, boolean isFast, boolean hasCombat) {
         super(Dimension.THE_END.key, "Tetris", new PointsWinScore());
-//        this.setGenerator(new CircularPlateTerrainGenerator(20));
 
         eventNode()
             .addListener(PlayerUseItemEvent.class, this::onPlayerInteract)
@@ -37,6 +39,9 @@ class Tetris extends StatelessGame {
         this.nextTetrominoesCount = nextTetrominoesCount;
         this.isFast = isFast;
         this.hasCombat = hasCombat;
+
+        Random random = new Random();
+        this.randomSeed = random.nextLong();
     }
 
     @Override
@@ -54,6 +59,8 @@ class Tetris extends StatelessGame {
 
     @Override
     protected void onStop() {
+        this.tetrisGames.forEach((player, tetrisGame) -> tetrisGame.loose());
+        this.tetrisGames.forEach((player, tetrisGame) -> getScore().insertResult(player, tetrisGame.getScore()));
         this.tetrisGames.forEach((player, tetrisGame) -> tetrisGame.sidebar.removeViewer(player));
     }
 
@@ -120,7 +127,11 @@ class Tetris extends StatelessGame {
         if(tetrisGame.lost && event.getPlayer().getGameMode() != GameMode.SPECTATOR) {
             event.getPlayer().setGameMode(GameMode.SPECTATOR);
             getScore().insertResult(event.getPlayer(), tetrisGame.getScore());
-            tetrisGame.sidebar.removeViewer(event.getPlayer());
+
+            if(!setTimeLimit) {
+                this.setTimeLimit(120);
+                setTimeLimit = true;
+            }
         }
     }
 
@@ -136,7 +147,8 @@ class Tetris extends StatelessGame {
                 Tetromino.Shape.J,
                 this.nextTetrominoesCount,
                 this.isFast,
-                this.hasCombat
+                this.hasCombat,
+                this.randomSeed
             ));
             this.tetrisGames.get(p).generate();
             this.tetrisGames.forEach((player, tetrisGame) -> tetrisGame.updateOtherTetrisGames(this.tetrisGames.values().stream().toList()));
diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/TetrisGame.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/TetrisGame.java
index 7e3366f..e829501 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/TetrisGame.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/TetrisGame.java
@@ -32,6 +32,7 @@ public class TetrisGame {
     public Sidebar sidebar = new Sidebar(Component.text("Info:"));
     private final Map<Button, Long> lastPresses = new HashMap<>();
     private final List<TetrisGame> otherTetrisGames = new ArrayList<>();
+    private final Random random;
 
     public enum Button {
         W,
@@ -43,15 +44,16 @@ public class TetrisGame {
         space
     }
 
-    public TetrisGame(StatelessGame instance, Pos lowerLeftCorner) {
-        this(instance, lowerLeftCorner, Tetromino.Shape.J, 3, false, false);
+    public TetrisGame(StatelessGame instance, Pos lowerLeftCorner, long randomSeed) {
+        this(instance, lowerLeftCorner, Tetromino.Shape.J, 3, false, false, randomSeed);
     }
 
-    public TetrisGame(StatelessGame instance, Pos lowerLeftCorner, Tetromino.Shape startTetrominoShape, int nextTetrominoesCount, boolean isfast, boolean hasCombat) {
+    public TetrisGame(StatelessGame instance, Pos lowerLeftCorner, Tetromino.Shape startTetrominoShape, int nextTetrominoesCount, boolean isfast, boolean hasCombat, long randomSeed) {
         this.isFast = isfast;
         this.hasCombat = hasCombat;
         this.instance = instance;
         this.playfield = new Playfield(lowerLeftCorner, this.instance, nextTetrominoesCount);
+        this.random = new Random(randomSeed);
 
         this.holdPosition = this.playfield.getHoldPosition();
         this.nextPosition = this.playfield.getNextPosition();
@@ -130,17 +132,22 @@ public class TetrisGame {
     public void updateOtherTetrisGames(List<TetrisGame> tetrisGames) {
         List<TetrisGame> games = new ArrayList<>(tetrisGames);
         games.remove(this);
+        games.removeIf(tetrisGame -> tetrisGame.lost);
         this.otherTetrisGames.clear();
         this.otherTetrisGames.addAll(games);
     }
 
     public void getAttacked(int lines) {
-        if(this.hasCombat) {
+        if(this.hasCombat && !this.lost) {
             this.attackingLines += lines;
             this.playfield.updateAttackingLines(this.attackingLines);
         }
     }
 
+    public void loose() {
+        this.lost = true;
+    }
+
 
     private boolean rotate(boolean clockwise) {
         if(this.lost || this.paused) return false;
@@ -223,7 +230,7 @@ public class TetrisGame {
             for(Tetromino.Shape shape : Tetromino.Shape.values()) {
                 this.tetrominoBag.add(new Tetromino(this.instance, shape));
             }
-            Collections.shuffle(this.tetrominoBag);
+            Collections.shuffle(this.tetrominoBag, this.random);
         }
 
         if(!this.nextTetrominoes.isEmpty()) this.nextTetrominoes.forEach(Tetromino::remove);
@@ -240,10 +247,6 @@ public class TetrisGame {
         });
     }
 
-    private void loose() {
-        this.lost = true;
-    }
-
     private void buildSidebar() {
         this.sidebar.createLine(new Sidebar.ScoreboardLine(
             "0",
diff --git a/src/main/java/eu/mhsl/minenet/minigames/score/PointsWinScore.java b/src/main/java/eu/mhsl/minenet/minigames/score/PointsWinScore.java
index 95ba294..209cfe1 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/score/PointsWinScore.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/score/PointsWinScore.java
@@ -1,12 +1,15 @@
 package eu.mhsl.minenet.minigames.score;
 
+import eu.mhsl.minenet.minigames.message.Icon;
 import eu.mhsl.minenet.minigames.message.TranslatableMessage;
+import eu.mhsl.minenet.minigames.message.type.ChatMessage;
 import eu.mhsl.minenet.minigames.message.type.TitleMessage;
 import eu.mhsl.minenet.minigames.util.MapUtil;
 import net.minestom.server.entity.Player;
 
 import java.time.Duration;
 import java.util.*;
+import java.util.stream.Collectors;
 
 public class PointsWinScore extends Score {
     private Map<Set<Player>, Integer> scoreOrder = new HashMap<>();
@@ -32,6 +35,37 @@ public class PointsWinScore extends Score {
         this.checkGameEnd();
     }
 
+    @Override
+    public void setDone() {
+        if(isClosed()) return;
+        close();
+        new ChatMessage(Icon.STAR, true)
+            .appendTranslated("score#result")
+            .newLine()
+            .indent()
+            .numberedList(
+                getScores()
+                    .stream()
+                    .filter(players -> !players.stream()
+                        .filter(player -> !player.getUsername().isBlank())
+                        .toList()
+                        .isEmpty())
+                    .map(players -> players
+                        .stream()
+                        .filter(player -> scoreOrder.get(Set.of(player)) != null)
+                        .map(player -> player.getUsername()+" :  "+scoreOrder.get(Set.of(player)).toString())
+                        .collect(Collectors.joining(", "))
+                    )
+                    .toList()
+            )
+            .undent()
+            .newLine()
+            .appendTranslated("score#thanks")
+            .send(instance.getPlayers());
+
+        instance.stop();
+    }
+
     @Override
     protected TranslatableMessage scoreMessage() {
         return new TitleMessage(Duration.ofMillis(1000), Duration.ofSeconds(1)).appendTranslated("score#death");
diff --git a/src/main/java/eu/mhsl/minenet/minigames/score/Score.java b/src/main/java/eu/mhsl/minenet/minigames/score/Score.java
index 38b54ae..383a9e5 100644
--- a/src/main/java/eu/mhsl/minenet/minigames/score/Score.java
+++ b/src/main/java/eu/mhsl/minenet/minigames/score/Score.java
@@ -103,6 +103,8 @@ public abstract class Score {
         return isClosed;
     }
 
+    public void close() { isClosed = true; }
+
     protected void onGameEnd() {
         this.instance.stop();
     }