Files
SteamWar/TowerRun/src/de/steamwar/towerrun/game/TowerRunGame.java
T
2026-05-16 22:41:17 +02:00

200 lines
7.5 KiB
Java

/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.towerrun.game;
import de.steamwar.core.CraftbukkitWrapper;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.towerrun.TowerRun;
import de.steamwar.towerrun.config.Config;
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.LevelChunk;
import org.bukkit.*;
import org.bukkit.craftbukkit.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<TowerRunPlayer> PLAYERS_ALIVE = new ArrayList<>();
public static final List<TowerRunPlayer> PLAYERS_ESCAPED = new ArrayList<>();
private static final World world = Bukkit.getWorlds().get(0);
public static boolean isEscaped(TowerRunPlayer player) {
return PLAYERS_ESCAPED.contains(player);
}
public static boolean isAlive(TowerRunPlayer player) {
return PLAYERS_ALIVE.contains(player);
}
public static void prepareTowerOrStart() {
if (GameState.getCurrentState() == GameStates.WAITING) {
GameState.nextState();
if (TowerRun.getTowerGenerator() == null) {
start();
return;
}
TowerRun.getTowerGenerator().generate();
} else {
throw new IllegalStateException("Game is already running!");
}
}
public static void start() {
if (GameState.getCurrentState() == GameStates.GENERATING_TOWER) {
PLAYERS_ALIVE.forEach(p -> {
p.reset();
p.player().setGameMode(GameMode.SURVIVAL);
});
GameState.nextState();
generateLava();
TowerRun.getMessage().broadcast("GAME_START");
for (Location door : WorldConfig.DOORS) {
door.getBlock().setType(Material.AIR);
door.clone().add(0, 1, 0).getBlock().setType(Material.AIR);
}
} else {
throw new IllegalStateException("Game is already running!");
}
}
private static void generateLava() {
for (int x = WorldConfig.MIN_TOWER.getBlockX(); x < WorldConfig.MAX_TOWER.getBlockX(); x += WorldConfig.LAVE_SPACE) {
for (int z = WorldConfig.MIN_TOWER.getBlockZ(); z < WorldConfig.MAX_TOWER.getBlockZ(); z += WorldConfig.LAVE_SPACE) {
Vector pos = new Vector(x, 0, z);
if (Arrays.stream(WorldConfig.REGIONS).anyMatch(region -> region.contains(pos))) {
int offset = WorldConfig.LAVA_Y;
if (TowerRun.getTowerGenerator() != null) {
offset += TowerRun.getTowerGenerator().getHeight();
}
WorldConfig.MIN_TOWER.getWorld().getBlockAt(x, offset, z).setType(Material.LAVA, true);
WorldConfig.MIN_TOWER.getWorld().getBlockAt(x, offset - 1, z).setType(Material.BEDROCK, true);
}
}
}
}
public static void remove(TowerRunPlayer towerRunPlayer) {
PLAYERS_ALIVE.remove(towerRunPlayer);
PLAYERS_ESCAPED.remove(towerRunPlayer);
}
public static void tie() {
Bukkit.getOnlinePlayers().forEach(player -> player.setGameMode(GameMode.SPECTATOR));
PLAYERS_ALIVE.clear();
Bukkit.getOnlinePlayers().forEach(player -> player.sendTitle(TowerRun.getMessage().parse("GAME_TIE", player), "", 10, 70, 20));
GameState.nextState();
if (Config.event()) {
Config.EVENT_FIGHT.setErgebnis(3);
}
}
public static void win(TowerRunPlayer tPlayer) {
Bukkit.getOnlinePlayers().forEach(player -> player.setGameMode(GameMode.SPECTATOR));
PLAYERS_ALIVE.clear();
tPlayer.player().setGameMode(GameMode.SPECTATOR);
TowerRun.getMessage().broadcast("GAME_WIN", tPlayer.player().getName());
Bukkit.getOnlinePlayers().forEach(player -> {
player.sendTitle(TowerRun.getMessage().parse("GAME_WIN", player, tPlayer.player().getName()), "", 10, 70, 20);
player.playSound(player.getLocation(), Sound.ENTITY_ENDER_DRAGON_DEATH, 1, 1);
});
GameState.nextState();
if (Config.event()) {
Config.EVENT_FIGHT.setErgebnis(SteamwarUser.get(tPlayer.player().getUniqueId()).getTeam() == Config.EVENT_TEAM_BLUE_ID ? 1 : 2);
}
}
public static void reset() {
PLAYERS_ALIVE.clear();
PLAYERS_ESCAPED.clear();
resetWorld();
GameState.reset();
Bukkit.getOnlinePlayers().forEach(player -> {
if (TowerRun.getTowerGenerator() != null) {
player.setGameMode(GameMode.SPECTATOR);
} else {
player.setGameMode(GameMode.SURVIVAL);
}
player.teleport(WorldConfig.SPAWN);
PLAYERS_ALIVE.add(TowerRunPlayer.get(player));
});
}
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<Integer> 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) {
LevelChunk chunk = ((CraftWorld) world).getHandle().getChunk(x, z);
LevelChunk backupChunk = ((CraftWorld) backup).getHandle().getChunk(x, z);
System.arraycopy(backupChunk.getSections(), 0, chunk.getSections(), 0, chunk.getSections().length);
for (Player p : Bukkit.getOnlinePlayers()) {
CraftbukkitWrapper.sendChunk(p, x, z);
}
}
}