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 a9f06f9..6e03ed0 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 @@ -7,6 +7,7 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.types.deathcube.Deathcu import eu.mhsl.minenet.minigames.instance.game.stateless.types.minerun.MinerunFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.types.spleef.SpleefFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.types.stickfight.StickFightFactory; +import eu.mhsl.minenet.minigames.instance.game.stateless.types.tntrun.TntRunFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.types.towerdefense.TowerdefenseFactory; import eu.mhsl.minenet.minigames.instance.game.stateless.types.trafficlightrace.TrafficLightRaceFactory; @@ -18,6 +19,7 @@ public enum GameList { TOWERDEFENSE(new TowerdefenseFactory(), GameType.PROTOTYPE), BEDWARS(new BedwarsFactory(), GameType.PROTOTYPE), BACKROOMS(new BackroomsFactory(), GameType.PROTOTYPE), + TNTRUN(new TntRunFactory(), GameType.OTHER), SPLEEF(new SpleefFactory(), GameType.PVP); private final GameFactory factory; diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tntrun/TntRun.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tntrun/TntRun.java new file mode 100644 index 0000000..c4f6a02 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tntrun/TntRun.java @@ -0,0 +1,85 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.tntrun; + +import eu.mhsl.minenet.minigames.instance.Dimension; +import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; +import eu.mhsl.minenet.minigames.score.LastWinsScore; +import eu.mhsl.minenet.minigames.util.BatchUtil; +import eu.mhsl.minenet.minigames.world.generator.terrain.CircularTerrainGenerator; +import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.GameMode; +import net.minestom.server.entity.metadata.other.PrimedTntMeta; +import net.minestom.server.event.player.PlayerMoveEvent; +import net.minestom.server.instance.batch.AbsoluteBlockBatch; +import net.minestom.server.instance.block.Block; +import net.minestom.server.timer.ExecutionType; +import net.minestom.server.timer.TaskSchedule; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.CompletableFuture; + +public class TntRun extends StatelessGame { + final int totalElevation = 50; + final int heightPerLevel = 20; + + final int radius; + final int stackCount; + public TntRun(int radius, int stackCount) { + super(Dimension.OVERWORLD.DIMENSION, "tntRun", new LastWinsScore()); + this.radius = radius; + this.stackCount = stackCount; + setGenerator(new CircularTerrainGenerator(radius, false)); + } + + @Override + protected void onLoad(@NotNull CompletableFuture callback) { + AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); + for (int level = 0; level < stackCount; level++) { + for(int x = -radius; x <= radius; x++) { + for(int z = -radius; z <= radius; z++) { + if(new Pos(x, 0, z).distance(new Pos(0, 0, 0)) > radius) continue; + + batch.setBlock(x, totalElevation + (level * heightPerLevel), z, Block.TNT); + } + } + } + + BatchUtil.loadAndApplyBatch(batch, this, () -> callback.complete(null)); + } + + @Override + protected void onPlayerMove(@NotNull PlayerMoveEvent playerMoveEvent) { + if(playerMoveEvent.getNewPosition().y() < totalElevation) { + playerMoveEvent.getPlayer().setGameMode(GameMode.SPECTATOR); + getScore().insertResult(playerMoveEvent.getPlayer()); + } + + if(isRunning && !getScore().hasResult(playerMoveEvent.getPlayer())) { + MinecraftServer.getSchedulerManager().scheduleTask(() -> { + float radius = 0.5F; + for (float x = -radius; x <= radius; x++) { + for (float z = -radius; z <= radius; z++) { + Pos firstLocation = playerMoveEvent.getNewPosition().add(x, -1, z); + Pos secondLocation = firstLocation.withY(y -> y-1); + if(!getBlock(firstLocation).isAir() || !getBlock(secondLocation).isAir()) { + setBlock(firstLocation, Block.AIR); + setBlock(secondLocation, Block.AIR); + + Entity fallingTnt = new Entity(EntityType.TNT); + PrimedTntMeta fallingTntMeta = (PrimedTntMeta) fallingTnt.getEntityMeta(); + fallingTntMeta.setFuseTime(20); + fallingTnt.setInstance(this, secondLocation); + } + } + } + }, TaskSchedule.millis(500), TaskSchedule.stop(), ExecutionType.ASYNC); + } + } + + @Override + public Pos getSpawn() { + return new Pos(0, totalElevation + heightPerLevel * (stackCount-1) + 1, 0); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tntrun/TntRunFactory.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tntrun/TntRunFactory.java new file mode 100644 index 0000000..59c6d9c --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tntrun/TntRunFactory.java @@ -0,0 +1,35 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.tntrun; + +import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; +import eu.mhsl.minenet.minigames.instance.game.stateless.config.ConfigManager; +import eu.mhsl.minenet.minigames.instance.game.stateless.config.GameFactory; +import eu.mhsl.minenet.minigames.instance.game.stateless.config.Option; +import eu.mhsl.minenet.minigames.instance.game.stateless.config.common.NumericOption; +import eu.mhsl.minenet.minigames.message.component.TranslatedComponent; +import net.minestom.server.item.Material; + +import java.util.Map; + +public class TntRunFactory implements GameFactory { + @Override + public TranslatedComponent name() { + return TranslatedComponent.byId("game_tntRun#name"); + } + + @Override + public Material symbol() { + return Material.TNT; + } + + @Override + public ConfigManager configuration() { + return new ConfigManager() + .addOption(new NumericOption("radius", Material.STICK, TranslatedComponent.byId("game_tntRun#radius"), 20, 30, 50, 60)) + .addOption(new NumericOption("levels", Material.SCAFFOLDING, TranslatedComponent.byId("game_tntRun#levels"), 1, 2, 3, 4, 5)); + } + + @Override + public StatelessGame manufacture(Map> configuration) throws Exception { + return new TntRun(configuration.get("radius").getAsInt(), configuration.get("levels").getAsInt()); + } +}