diff --git a/src/de/steamwar/towerrun/TowerRun.java b/src/de/steamwar/towerrun/TowerRun.java index 28545d2..4b1f47d 100644 --- a/src/de/steamwar/towerrun/TowerRun.java +++ b/src/de/steamwar/towerrun/TowerRun.java @@ -21,8 +21,10 @@ package de.steamwar.towerrun; import de.steamwar.message.Message; import de.steamwar.towerrun.commands.StartCommand; +import de.steamwar.towerrun.config.WorldConfig; import de.steamwar.towerrun.countdowns.EndCountdown; import de.steamwar.towerrun.countdowns.LobbyCountdown; +import de.steamwar.towerrun.generator.TowerGenerator; import de.steamwar.towerrun.listener.GlobalListener; import de.steamwar.towerrun.listener.IngameListener; import de.steamwar.towerrun.listener.LobbyListener; @@ -34,6 +36,8 @@ import org.bukkit.plugin.java.annotation.plugin.Description; import org.bukkit.plugin.java.annotation.plugin.Plugin; import org.bukkit.plugin.java.annotation.plugin.author.Author; +import java.util.Optional; + @Plugin(name = "TowerRun", version = "1.0.0") @Dependency(value = "SpigotCore") @Author(value = "YoyoNow") @@ -47,11 +51,18 @@ public class TowerRun extends JavaPlugin { @Getter private static Message message; + @Getter + private static TowerGenerator towerGenerator = null; + @Override public void onEnable() { instance = this; message = new Message("TowerRun", getClassLoader()); + if (WorldConfig.TOWER_GENERATOR_CONFIG != null) { + towerGenerator = new TowerGenerator(WorldConfig.TOWER_GENERATOR_CONFIG); + } + new LobbyListener(); new IngameListener(); new GlobalListener(); diff --git a/src/de/steamwar/towerrun/config/WorldConfig.java b/src/de/steamwar/towerrun/config/WorldConfig.java index 0a242af..c888197 100644 --- a/src/de/steamwar/towerrun/config/WorldConfig.java +++ b/src/de/steamwar/towerrun/config/WorldConfig.java @@ -19,6 +19,7 @@ package de.steamwar.towerrun.config; +import de.steamwar.sql.SchematicType; import de.steamwar.towerrun.TowerRun; import de.steamwar.towerrun.winconditions.FirstOutsideWincondition; import de.steamwar.towerrun.winconditions.LastOutsideWincondition; @@ -53,6 +54,7 @@ public class WorldConfig { public static final int MAP_MIN_Z; public static final int MAP_MAX_X; public static final int MAP_MAX_Z; + public static final TowerGeneratorConfig TOWER_GENERATOR_CONFIG; public static final List WINCONDITIONS = new ArrayList<>(); static { @@ -149,6 +151,13 @@ public class WorldConfig { ACTIVE_WINCONDITIONS = config.getStringList("winconditions"); WINCONDITIONS.stream().filter(winCondition -> ACTIVE_WINCONDITIONS.contains(winCondition.getName())).forEach(winCondition -> winCondition.setActive(true)); + + ConfigurationSection towerGeneratorSection = tower.getConfigurationSection("towerGenerator"); + if (towerGeneratorSection == null) { + TOWER_GENERATOR_CONFIG = null; + } else { + TOWER_GENERATOR_CONFIG = new TowerGeneratorConfig(towerGeneratorSection); + } } @Getter @@ -176,4 +185,19 @@ public class WorldConfig { && vector.getZ() >= min.getZ() && vector.getZ() <= max.getZ(); } } + + @Getter + public static final class TowerGeneratorConfig { + public final int x; + public final int y; + public final int z; + public final SchematicType schematicType; + + public TowerGeneratorConfig(ConfigurationSection section) { + x = section.getInt("x"); + y = section.getInt("y"); + z = section.getInt("z"); + schematicType = SchematicType.fromDB(section.getString("schematicType")); + } + } } diff --git a/src/de/steamwar/towerrun/countdowns/LobbyCountdown.java b/src/de/steamwar/towerrun/countdowns/LobbyCountdown.java index 43093b7..35a1794 100644 --- a/src/de/steamwar/towerrun/countdowns/LobbyCountdown.java +++ b/src/de/steamwar/towerrun/countdowns/LobbyCountdown.java @@ -47,7 +47,7 @@ public class LobbyCountdown extends Countdown { @Override void timerEnd() { - TowerRunGame.start(); + TowerRunGame.prepareTower(); } @Override diff --git a/src/de/steamwar/towerrun/game/TowerRunGame.java b/src/de/steamwar/towerrun/game/TowerRunGame.java index 0bc5db1..d0b14d6 100644 --- a/src/de/steamwar/towerrun/game/TowerRunGame.java +++ b/src/de/steamwar/towerrun/game/TowerRunGame.java @@ -48,8 +48,22 @@ public class TowerRunGame { return PLAYERS_ALIVE.contains(player); } - public static void start() { + public static void prepareTower() { if (GameState.getCurrentState() == GameStates.LOBBY) { + GameState.nextState(); + if (TowerRun.getTowerGenerator() == null) { + start(); + return; + } + + TowerRun.getTowerGenerator().generate(TowerRunGame::start); + } else { + throw new IllegalStateException("Game is already running!"); + } + } + + private static void start() { + if (GameState.getCurrentState() == GameStates.GENERATING_TOWER) { PLAYERS_ALIVE.addAll(TowerRunPlayer.getAll()); PLAYERS_ALIVE.forEach(TowerRunPlayer::reset); GameState.nextState(); diff --git a/src/de/steamwar/towerrun/game/TowerRunPlayer.java b/src/de/steamwar/towerrun/game/TowerRunPlayer.java index 9aa4629..015073b 100644 --- a/src/de/steamwar/towerrun/game/TowerRunPlayer.java +++ b/src/de/steamwar/towerrun/game/TowerRunPlayer.java @@ -19,6 +19,7 @@ package de.steamwar.towerrun.game; +import de.steamwar.towerrun.TowerRun; import de.steamwar.towerrun.config.WorldConfig; import org.bukkit.entity.Player; import org.bukkit.util.Vector; @@ -43,7 +44,11 @@ public record TowerRunPlayer(Player player) { } public void reset() { - player.teleport(WorldConfig.SPAWN); + if (TowerRun.getTowerGenerator() != null) { + player.teleport(WorldConfig.SPAWN.add(0, TowerRun.getTowerGenerator().getHeight(), 0)); + } else { + player.teleport(WorldConfig.SPAWN); + } player.setVelocity(new Vector(0, 0, 0)); } diff --git a/src/de/steamwar/towerrun/generator/TowerGenerator.java b/src/de/steamwar/towerrun/generator/TowerGenerator.java new file mode 100644 index 0000000..e1493df --- /dev/null +++ b/src/de/steamwar/towerrun/generator/TowerGenerator.java @@ -0,0 +1,104 @@ +package de.steamwar.towerrun.generator; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; +import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.session.ClipboardHolder; +import de.steamwar.sql.SchematicData; +import de.steamwar.sql.SchematicNode; +import de.steamwar.sql.SchematicType; +import de.steamwar.towerrun.TowerRun; +import de.steamwar.towerrun.config.WorldConfig; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitRunnable; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.List; +import java.util.Objects; +import java.util.Random; + +public class TowerGenerator { + + private Random random = new Random(); + private int x; + private int y; + private int z; + private List ALL_SCHEMATICS; + private Clipboard roof; + + @Getter + private int height; + + public TowerGenerator(WorldConfig.TowerGeneratorConfig config) { + this(config.x, config.y, config.z, config.schematicType); + } + + public TowerGenerator(int x, int y, int z, SchematicType schematicType) { + File file = new File(Bukkit.getWorlds().get(0).getWorldFolder(), "Roof.schematic"); + if (!file.exists()) { + Bukkit.shutdown(); + return; + } + roof = loadSchematic(file); + + this.x = x; + this.y = y; + this.z = z; + ALL_SCHEMATICS = SchematicNode.getAllSchematicsOfType(schematicType); + } + + private Clipboard loadSchematic(File file) { + Clipboard clipboard; + try (ClipboardReader reader = Objects.requireNonNull(ClipboardFormats.findByFile(file)).getReader(new FileInputStream(file))) { + clipboard = reader.read(); + } catch (NullPointerException | IOException e) { + Bukkit.shutdown(); + throw new SecurityException("TowerRun schematic not found", e); + } + return clipboard; + } + + public void generate(Runnable finishRunnable) { + new BukkitRunnable() { + int height = random.nextInt(50) + 200; + int y = TowerGenerator.this.y; + + { + TowerGenerator.this.height = height; + } + + @Override + public void run() { + if (height > 0) { + SchematicNode schematicNode = ALL_SCHEMATICS.get(random.nextInt(ALL_SCHEMATICS.size())); + SchematicData schematicData = new SchematicData(schematicNode); + try { + Clipboard clipboard = schematicData.load(); + try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(Bukkit.getWorlds().get(0)), -1)) { + ClipboardHolder ch = new ClipboardHolder(clipboard); + Operations.completeBlindly(ch.createPaste(e).to(BlockVector3.at(x, y, z)).build()); + } + y += clipboard.getDimensions().getY(); + height -= clipboard.getDimensions().getY(); + } catch (IOException e) { + ALL_SCHEMATICS.remove(schematicNode); + } + } else { + try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(Bukkit.getWorlds().get(0)), -1)) { + ClipboardHolder ch = new ClipboardHolder(roof); + Operations.completeBlindly(ch.createPaste(e).to(BlockVector3.at(x, y, z)).build()); + } + finishRunnable.run(); + } + } + }.runTaskTimer(TowerRun.getInstance(), 0, 1); + } +} diff --git a/src/de/steamwar/towerrun/listener/IngameListener.java b/src/de/steamwar/towerrun/listener/IngameListener.java index 62b1295..7ba25dd 100644 --- a/src/de/steamwar/towerrun/listener/IngameListener.java +++ b/src/de/steamwar/towerrun/listener/IngameListener.java @@ -112,6 +112,10 @@ public class IngameListener extends GameStateBukkitListener { @EventHandler public void onPlayerRespawn(PlayerRespawnEvent event) { - event.setRespawnLocation(WorldConfig.SPAWN); + if (TowerRun.getTowerGenerator() != null) { + event.setRespawnLocation(WorldConfig.SPAWN.add(0, TowerRun.getTowerGenerator().getHeight(), 0)); + } else { + event.setRespawnLocation(WorldConfig.SPAWN); + } } } diff --git a/src/de/steamwar/towerrun/listener/LobbyListener.java b/src/de/steamwar/towerrun/listener/LobbyListener.java index 470b198..b7542c1 100644 --- a/src/de/steamwar/towerrun/listener/LobbyListener.java +++ b/src/de/steamwar/towerrun/listener/LobbyListener.java @@ -19,6 +19,7 @@ package de.steamwar.towerrun.listener; +import de.steamwar.towerrun.TowerRun; import de.steamwar.towerrun.config.WorldConfig; import de.steamwar.towerrun.state.GameStateBukkitListener; import de.steamwar.towerrun.state.GameStates; @@ -42,8 +43,13 @@ public class LobbyListener extends GameStateBukkitListener { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); - player.teleport(WorldConfig.SPAWN); - player.setGameMode(GameMode.SURVIVAL); + if (TowerRun.getTowerGenerator() != null) { + player.teleport(WorldConfig.SPAWN.add(0, TowerRun.getTowerGenerator().getHeight(), 0)); + player.setGameMode(GameMode.SPECTATOR); + } else { + player.teleport(WorldConfig.SPAWN); + player.setGameMode(GameMode.SURVIVAL); + } } @EventHandler diff --git a/src/de/steamwar/towerrun/listener/NotLobbyListener.java b/src/de/steamwar/towerrun/listener/NotLobbyListener.java index 20078f9..1784e47 100644 --- a/src/de/steamwar/towerrun/listener/NotLobbyListener.java +++ b/src/de/steamwar/towerrun/listener/NotLobbyListener.java @@ -19,6 +19,7 @@ package de.steamwar.towerrun.listener; +import de.steamwar.towerrun.TowerRun; import de.steamwar.towerrun.config.WorldConfig; import de.steamwar.towerrun.state.GameStateBukkitListener; import de.steamwar.towerrun.state.GameStates; @@ -36,6 +37,10 @@ public class NotLobbyListener extends GameStateBukkitListener { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { event.getPlayer().setGameMode(GameMode.SPECTATOR); - event.getPlayer().teleport(WorldConfig.SPAWN); + if (TowerRun.getTowerGenerator() != null) { + event.getPlayer().teleport(WorldConfig.SPAWN.add(0, TowerRun.getTowerGenerator().getHeight(), 0)); + } else { + event.getPlayer().teleport(WorldConfig.SPAWN); + } } } diff --git a/src/de/steamwar/towerrun/state/GameStates.java b/src/de/steamwar/towerrun/state/GameStates.java index 3c838a3..347e981 100644 --- a/src/de/steamwar/towerrun/state/GameStates.java +++ b/src/de/steamwar/towerrun/state/GameStates.java @@ -27,7 +27,8 @@ import lombok.Getter; public enum GameStates { ENDING(null), INGAME(ENDING), - LOBBY(INGAME); + GENERATING_TOWER(INGAME), + LOBBY(GENERATING_TOWER); private final GameStates nextState; }