diff --git a/src/TowerRun.properties b/src/TowerRun.properties index 1598692..16cd5de 100644 --- a/src/TowerRun.properties +++ b/src/TowerRun.properties @@ -25,6 +25,7 @@ GAME_WIN= GAME_STARTING=§7Starting: §e{0}s§8! GAME_WAITING=§7Waiting for players§8... SERVER_STOPPING=§cThe server stops in §e{0}s§8! +SERVER_RESET=§cThe server will be reset in §e{0}s§8! KEY_NAME=§eKey KEY_FOUND=§a{0} §7found a key§8! GAME_TIE=§aThe game ended in a tie§8! diff --git a/src/TowerRun_de.properties b/src/TowerRun_de.properties index 613a86d..42c4d1d 100644 --- a/src/TowerRun_de.properties +++ b/src/TowerRun_de.properties @@ -23,6 +23,7 @@ GAME_WIN= GAME_STARTING=§7Das Spiel startet in §e{0}s§8! GAME_WAITING=§7Warte auf weitere Spieler§8... SERVER_STOPPING=§cDer Server stoppt in §e{0}s§8! +SERVER_RESET=§cDer Server wird in §e{0}s §czurückgesetzt§8! GAME_TIE=§7Keiner hat gewonnen§8! KEY_NAME=§eSchlüssel diff --git a/src/de/steamwar/towerrun/config/WorldConfig.java b/src/de/steamwar/towerrun/config/WorldConfig.java index 73453e1..0a242af 100644 --- a/src/de/steamwar/towerrun/config/WorldConfig.java +++ b/src/de/steamwar/towerrun/config/WorldConfig.java @@ -49,6 +49,10 @@ public class WorldConfig { public static final Location MIN_TOWER; public static final Location MAX_TOWER; public static final List ACTIVE_WINCONDITIONS; + public static final int MAP_MIN_X; + public static final int MAP_MIN_Z; + public static final int MAP_MAX_X; + public static final int MAP_MAX_Z; public static final List WINCONDITIONS = new ArrayList<>(); static { @@ -137,6 +141,12 @@ public class WorldConfig { LAVA_Y = tower.getInt("lavaY"); LAVE_SPACE = tower.getInt("laveSpace"); + + MAP_MIN_X = config.getInt("minX"); + MAP_MIN_Z = config.getInt("minZ"); + MAP_MAX_X = config.getInt("maxX"); + MAP_MAX_Z = config.getInt("maxZ"); + ACTIVE_WINCONDITIONS = config.getStringList("winconditions"); WINCONDITIONS.stream().filter(winCondition -> ACTIVE_WINCONDITIONS.contains(winCondition.getName())).forEach(winCondition -> winCondition.setActive(true)); } diff --git a/src/de/steamwar/towerrun/countdowns/EndCountdown.java b/src/de/steamwar/towerrun/countdowns/EndCountdown.java index 334f6b3..0578da2 100644 --- a/src/de/steamwar/towerrun/countdowns/EndCountdown.java +++ b/src/de/steamwar/towerrun/countdowns/EndCountdown.java @@ -20,17 +20,20 @@ package de.steamwar.towerrun.countdowns; import de.steamwar.towerrun.TowerRun; -import de.steamwar.towerrun.state.GameStateToggleListener; +import de.steamwar.towerrun.game.TowerRunGame; import de.steamwar.towerrun.state.GameStates; -import net.md_5.bungee.api.ChatMessageType; -import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; import org.bukkit.Sound; -import org.bukkit.scheduler.BukkitTask; +import java.io.File; +import java.io.FilenameFilter; import java.util.EnumSet; +import java.util.Objects; public class EndCountdown extends Countdown { + + private static boolean RESETS = Objects.requireNonNull(Bukkit.getWorlds().get(0).getWorldFolder().list((dir, name) -> name.equals("backup"))).length > 0; + public EndCountdown() { super(EnumSet.of(GameStates.ENDING)); } @@ -43,7 +46,11 @@ public class EndCountdown extends Countdown { @Override void timerEnd() { Bukkit.getOnlinePlayers().forEach(player -> player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1, 1)); - Bukkit.shutdown(); + if (RESETS) { + TowerRunGame.reset(); + } else { + Bukkit.shutdown(); + } } @Override @@ -53,6 +60,6 @@ public class EndCountdown extends Countdown { @Override void run() { - TowerRun.getMessage().broadcastActionbar("SERVER_STOPPING", time); + TowerRun.getMessage().broadcastActionbar(RESETS ? "SERVER_RESET" : "SERVER_STOPPING", time); } } diff --git a/src/de/steamwar/towerrun/game/TowerRunGame.java b/src/de/steamwar/towerrun/game/TowerRunGame.java index de56c26..0bc5db1 100644 --- a/src/de/steamwar/towerrun/game/TowerRunGame.java +++ b/src/de/steamwar/towerrun/game/TowerRunGame.java @@ -19,22 +19,30 @@ package de.steamwar.towerrun.game; +import de.steamwar.core.CraftbukkitWrapper; import de.steamwar.towerrun.TowerRun; import de.steamwar.towerrun.config.WorldConfig; import de.steamwar.towerrun.state.GameState; import de.steamwar.towerrun.state.GameStates; import lombok.experimental.UtilityClass; +import net.minecraft.world.level.chunk.Chunk; import org.bukkit.*; +import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; import org.bukkit.util.Vector; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.function.ObjIntConsumer; @UtilityClass public class TowerRunGame { public static final List PLAYERS_ALIVE = new ArrayList<>(); public static final List PLAYERS_ESCAPED = new ArrayList<>(); + private static final World world = Bukkit.getWorlds().get(0); public static boolean isAlive(TowerRunPlayer player) { return PLAYERS_ALIVE.contains(player); @@ -92,4 +100,60 @@ public class TowerRunGame { }); GameState.nextState(); } + + public static void reset() { + PLAYERS_ALIVE.clear(); + PLAYERS_ESCAPED.clear(); + resetWorld(); + GameState.reset(); + Bukkit.getOnlinePlayers().forEach(player -> { + player.setGameMode(GameMode.SURVIVAL); + player.teleport(WorldConfig.SPAWN); + }); + } + + private static double posToChunk(int pos){ + return pos / 16.0; + } + + private static int getMinChunkX(){ + return (int) Math.floor(posToChunk(WorldConfig.MAP_MIN_X)); + } + + private static int getMaxChunkX(){ + return (int) Math.ceil(posToChunk(WorldConfig.MAP_MAX_X)); + } + + private static int getMinChunkZ(){ + return (int) Math.floor(posToChunk(WorldConfig.MAP_MIN_Z)); + } + + private static int getMaxChunkZ(){ + return (int) Math.ceil(posToChunk(WorldConfig.MAP_MAX_Z)); + } + + private static void forEachChunk(ObjIntConsumer executor) { + for(int x = getMinChunkX(); x <= getMaxChunkX(); x++) + for(int z = getMinChunkZ(); z <= getMaxChunkZ(); z++) + executor.accept(x, z); + } + + private static void resetWorld(){ + world.getEntities().stream().filter(entity -> entity.getType() != EntityType.PLAYER).forEach(Entity::remove); + + World backup = new WorldCreator(world.getName() + "/backup").createWorld(); + assert backup != null; + forEachChunk((x, z) -> resetChunk(backup, x, z)); + Bukkit.unloadWorld(backup, false); + } + + private static void resetChunk(World backup, int x, int z) { + Chunk chunk = ((CraftWorld) world).getHandle().d(x, z); + Chunk backupChunk = ((CraftWorld) backup).getHandle().d(x, z); + + System.arraycopy(backupChunk.d(), 0, chunk.d(), 0, chunk.d().length); + + for(Player p : Bukkit.getOnlinePlayers()) + CraftbukkitWrapper.impl.sendChunk(p, x, z); + } } diff --git a/src/de/steamwar/towerrun/state/GameState.java b/src/de/steamwar/towerrun/state/GameState.java index 120b6a8..bb95101 100644 --- a/src/de/steamwar/towerrun/state/GameState.java +++ b/src/de/steamwar/towerrun/state/GameState.java @@ -47,6 +47,10 @@ public class GameState { gameStateChanges(oldState, currentState); } + public static void reset() { + currentState = GameStates.LOBBY; + } + private static void gameStateChanges(GameStates oldState, GameStates newState) { gameStateListeners.forEach(gameStateListener -> gameStateListener.onGameStateChange(oldState, newState)); } diff --git a/src/world.yml b/src/world.yml index 62f09d9..0a26512 100644 --- a/src/world.yml +++ b/src/world.yml @@ -42,6 +42,11 @@ tower: lavaY: 220 laveSpace: 7 +minX: 29 +maxX: 164 +minZ: 243 +maxZ: 376 + winconditions: - LAST_REMAINING - LAST_OUTSIDE \ No newline at end of file