From d98cebd86f77273112a03ab18af7fb487a43bcd8 Mon Sep 17 00:00:00 2001 From: lars Date: Tue, 2 Sep 2025 22:29:47 +0200 Subject: [PATCH] added turtleGame playfield and movement --- .../minigames/instance/game/GameList.java | 2 + .../types/turtleGame/TurtleGame.java | 61 ++++++++++++++++++- .../types/turtleGame/TurtleGameFactory.java | 21 ++++++- .../turtleGame/game/TurtleGameInstance.java | 53 ++++++++++++++++ 4 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/game/TurtleGameInstance.java 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 6fc6d6d..f6236c1 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 @@ -18,6 +18,7 @@ import eu.mhsl.minenet.minigames.instance.game.stateless.types.sumo.SumoFactory; 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; +import eu.mhsl.minenet.minigames.instance.game.stateless.types.turtleGame.TurtleGameFactory; public enum GameList { DEATHCUBE(new DeathcubeFactory(), GameType.JUMPNRUN), @@ -28,6 +29,7 @@ public enum GameList { BEDWARS(new BedwarsFactory(), GameType.PROTOTYPE), BACKROOMS(new BackroomsFactory(), GameType.PROTOTYPE), BOWSPLEEF(new BowSpleefFactory(), GameType.PROTOTYPE), + TURTLEGAME(new TurtleGameFactory(), GameType.PROTOTYPE), TETRIS(new TetrisFactory(), GameType.OTHER), TNTRUN(new TntRunFactory(), GameType.OTHER), ANVILRUN(new AnvilRunFactory(), GameType.PVE), diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/TurtleGame.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/TurtleGame.java index 69435c7..3e93cd5 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/TurtleGame.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/TurtleGame.java @@ -2,10 +2,69 @@ package eu.mhsl.minenet.minigames.instance.game.stateless.types.turtleGame; import eu.mhsl.minenet.minigames.instance.Dimension; import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; +import eu.mhsl.minenet.minigames.instance.game.stateless.types.turtleGame.game.TurtleGameInstance; import eu.mhsl.minenet.minigames.score.PointsWinScore; +import net.kyori.adventure.text.Component; +import net.minestom.server.MinecraftServer; +import net.minestom.server.entity.EntityCreature; +import net.minestom.server.entity.Player; +import net.minestom.server.entity.attribute.Attribute; +import net.minestom.server.event.player.PlayerMoveEvent; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.WeakHashMap; class TurtleGame extends StatelessGame { - public TurtleGame() { + private final boolean firstPerson; + private final Map gameInstances = new WeakHashMap<>(); + + public TurtleGame(boolean firstPerson) { super(Dimension.OVERWORLD.key, "Tetris", new PointsWinScore()); + this.firstPerson = firstPerson; + + this.eventNode() + .addListener(PlayerMoveEvent.class, this::onPlayerMove); + } + + protected void onPlayerMove(@NotNull PlayerMoveEvent event) { + TurtleGameInstance gameInstance = this.gameInstances.get(event.getPlayer()); + gameInstance.getTurtle().setView(event.getPlayer().getPosition().yaw(), gameInstance.getTurtle().getPosition().pitch()); + if(this.isRunning()) gameInstance.moveTurtle(event.getPlayer().getPosition().direction()); + } + + @Override + protected boolean onPlayerJoin(Player p) { + p.getInventory().setItemStack(0, ItemStack.builder(Material.BARRIER).customName(Component.text("Reset")).build()); + + if(this.gameInstances.get(p) == null) { + this.gameInstances.put(p, new TurtleGameInstance( + this, + this.getSpawn().sub(6, 8, 15).add(this.gameInstances.size()*50, 0, 0) + )); + this.gameInstances.get(p).generate(); + } + + TurtleGameInstance gameInstance = this.gameInstances.get(p); + + p.teleport(gameInstance.getPlayerSpawnPosition()); + + EntityCreature turtle = gameInstance.getTurtle(); + MinecraftServer.getSchedulerManager().scheduleNextTick(() -> { + turtle.setInstance(this); + turtle.teleport(gameInstance.getPlayerSpawnPosition()); + turtle.addPassenger(p); + turtle.getAttribute(Attribute.MOVEMENT_SPEED).setBaseValue(0.15); + }); + + return super.onPlayerJoin(p); + } + + @Override + protected void onStart() { + this.gameInstances.forEach(((player, gameInstance) -> gameInstance.moveTurtle(player.getPosition().direction()))); +// this.gameInstances.forEach(((player, turtleGameInstance) -> turtleGameInstance.start())); } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/TurtleGameFactory.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/TurtleGameFactory.java index 0ea7728..d2b9a20 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/TurtleGameFactory.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/TurtleGameFactory.java @@ -1,10 +1,13 @@ package eu.mhsl.minenet.minigames.instance.game.stateless.types.turtleGame; import eu.mhsl.minenet.minigames.instance.game.Game; +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.BoolOption; import eu.mhsl.minenet.minigames.instance.room.Room; import eu.mhsl.minenet.minigames.message.component.TranslatedComponent; +import net.minestom.server.item.Material; import java.util.Map; @@ -15,8 +18,24 @@ public class TurtleGameFactory implements GameFactory { return TranslatedComponent.byId("game_TurtleGame#name"); } + @Override + public TranslatedComponent description() { + return TranslatedComponent.byId("game_TurtleGame#description"); + } + + @Override + public ConfigManager configuration() { + return new ConfigManager() + .addOption(new BoolOption("firstPerson", Material.SPYGLASS, TranslatedComponent.byId("game_TurtleGame#firstPerson"))); + } + @Override public Game manufacture(Room parent, Map> configuration) throws Exception { - return new TurtleGame(); + return new TurtleGame(configuration.get("firstPerson").getAsBoolean()); + } + + @Override + public Material symbol() { + return Material.TURTLE_EGG; } } diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/game/TurtleGameInstance.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/game/TurtleGameInstance.java new file mode 100644 index 0000000..38216e9 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/turtleGame/game/TurtleGameInstance.java @@ -0,0 +1,53 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.turtleGame.game; + +import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; +import eu.mhsl.minenet.minigames.util.BatchUtil; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.coordinate.Vec; +import net.minestom.server.entity.EntityCreature; +import net.minestom.server.entity.EntityType; +import net.minestom.server.instance.batch.AbsoluteBlockBatch; +import net.minestom.server.instance.block.Block; + +import java.awt.*; + +public class TurtleGameInstance { + private final StatelessGame instance; + private final Pos startPosition; + private final EntityCreature turtle = new EntityCreature(EntityType.TURTLE); + + public TurtleGameInstance(StatelessGame instance, Pos startPosition) { + this.instance = instance; + this.startPosition = startPosition; + } + + public void moveTurtle(Vec direction) { + Vec targetDirection = direction.withY(0).normalize().mul(100); + Pos targetPosition = this.turtle.getPosition().add(targetDirection); + this.turtle.getNavigator().setPathTo(targetPosition); + } + + public void generate() { + AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); + + for (int z = -1; z < 66; z++) { + for (int x = -1; x < 44; x++) { + if(z < 0 || z >= 65 || x < 0 || x >= 43) { + batch.setBlock(this.startPosition.add(x, 1, z), Block.STONE); + batch.setBlock(this.startPosition.add(x, 2, z), Block.STONE_SLAB); + } + batch.setBlock(this.startPosition.add(x, 0, z), Block.SAND); + } + } + + BatchUtil.loadAndApplyBatch(batch, this.instance, () -> {}); + } + + public Pos getPlayerSpawnPosition() { + return this.startPosition.add(20, 1, 30); + } + + public EntityCreature getTurtle() { + return this.turtle; + } +}