diff --git a/build.gradle.kts b/build.gradle.kts index bd65a26..1c2b4b3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,7 +17,7 @@ repositories { } dependencies { - implementation("dev.emortal.minestom:game-sdk:37fbbc3") + implementation("dev.emortal.minestom:game-sdk:a4f51db") implementation("dev.hollowcube:polar:1.3.1") implementation("dev.emortal:rayfast:a4a8041") diff --git a/src/main/java/dev/emortal/minestom/marathon/Main.java b/src/main/java/dev/emortal/minestom/marathon/Main.java index 8039c06..77ce7ca 100644 --- a/src/main/java/dev/emortal/minestom/marathon/Main.java +++ b/src/main/java/dev/emortal/minestom/marathon/Main.java @@ -13,7 +13,7 @@ public static void main(String[] args) { return GameSdkConfig.builder() .minPlayers(1) .maxGames(50) - .gameCreator(MarathonGame::new) + .gameCreator(MarathonGameRunner::new) .build(); }); } diff --git a/src/main/java/dev/emortal/minestom/marathon/MarathonGame.java b/src/main/java/dev/emortal/minestom/marathon/MarathonGame.java old mode 100755 new mode 100644 index 48b5f42..57caffe --- a/src/main/java/dev/emortal/minestom/marathon/MarathonGame.java +++ b/src/main/java/dev/emortal/minestom/marathon/MarathonGame.java @@ -1,7 +1,5 @@ package dev.emortal.minestom.marathon; -import dev.emortal.minestom.gamesdk.config.GameCreationInfo; -import dev.emortal.minestom.gamesdk.game.Game; import dev.emortal.minestom.marathon.animator.BlockAnimator; import dev.emortal.minestom.marathon.animator.SuvatAnimator; import dev.emortal.minestom.marathon.generator.DefaultGenerator; @@ -20,6 +18,8 @@ import net.minestom.server.entity.Entity; import net.minestom.server.entity.GameMode; import net.minestom.server.entity.Player; +import net.minestom.server.event.Event; +import net.minestom.server.event.EventNode; import net.minestom.server.event.player.PlayerMoveEvent; import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; @@ -41,11 +41,10 @@ import java.util.Date; import java.util.List; import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; -public final class MarathonGame extends Game { - private static final Logger LOGGER = LoggerFactory.getLogger(MarathonGame.class); +public final class MarathonGame { + private static final Logger LOGGER = LoggerFactory.getLogger(MarathonGameRunner.class); static final @NotNull DimensionType FULLBRIGHT_DIMENSION = DimensionType.builder(NamespaceID.from("fullbright")).ambientLight(1F).build(); @@ -55,12 +54,12 @@ public final class MarathonGame extends Game { public static final @NotNull Tag MARATHON_ENTITY_TAG = Tag.Boolean("marathonEntity"); private final @NotNull Instance instance; + private final @NotNull Player player; private final @NotNull Generator generator; private final @NotNull BlockAnimator animator; private final @NotNull BlockPalette palette; private final ArrayDeque blocks = new ArrayDeque<>(NEXT_BLOCKS_COUNT + 1); - private final AtomicBoolean playerJoined = new AtomicBoolean(false); private int score; private int combo; @@ -72,8 +71,8 @@ public final class MarathonGame extends Game { private @Nullable Task breakingTask; - public MarathonGame(@NotNull GameCreationInfo creationInfo) { - super(creationInfo); + MarathonGame(@NotNull Player player, @NotNull EventNode eventNode) { + this.player = player; this.generator = DefaultGenerator.INSTANCE; this.animator = new SuvatAnimator(); @@ -86,34 +85,17 @@ public MarathonGame(@NotNull GameCreationInfo creationInfo) { this.startRefreshDisplaysTask(); MovementListener movementListener = new MovementListener(this); - this.getEventNode().addListener(PlayerMoveEvent.class, movementListener::onMove); + eventNode.addListener(PlayerMoveEvent.class, movementListener::onMove); this.reset(); } - @Override - public void start() { - } - - @Override - public void onJoin(@NotNull Player player) { - if (!this.playerJoined.compareAndSet(false, true)) { - LOGGER.error("There should be no more than one player joining Marathon!"); - player.kick(Component.text("An error occurred and you were placed in the wrong game. Please reconnect.")); - return; - } - + void onJoin(@NotNull Player player) { player.setGameMode(GameMode.ADVENTURE); player.setRespawnPoint(RESET_POINT.add(0, 1, 0)); } - @Override - public void onLeave(@NotNull Player player) { - // Do nothing - game SDK will check if player count is 0 and end the game - } - - @Override - public void cleanUp() { + void cleanUp() { this.instance.scheduleNextTick(MinecraftServer.getInstanceManager()::unregisterInstance); } @@ -141,14 +123,15 @@ public void reset() { this.blocks.clear(); this.blocks.addLast(RESET_POINT); - for (Player player : this.getPlayers()) { - player.teleport(player.getRespawnPoint()); - } this.instance.setBlock(RESET_POINT, Block.DIAMOND_BLOCK); this.generateNextBlocks(NEXT_BLOCKS_COUNT, false); - refreshDisplays(); + this.refreshDisplays(); + } + + public void teleportPlayerToStart() { + this.player.teleport(this.player.getRespawnPoint()); } private void startRefreshDisplaysTask() { @@ -169,7 +152,7 @@ private void refreshDisplays() { .append(Component.text(scorePerSecond + "bps", NamedTextColor.GRAY)) .build(); - this.sendActionBar(message); + this.player.sendActionBar(message); // this.player.showTitle(Title.title( // Component.empty(), @@ -210,8 +193,8 @@ private void generateNextBlock(boolean shouldAnimate) { } public void generateNextBlocks(int blockCount, boolean shouldAnimate) { - if (startTimestamp == -1 && shouldAnimate) { - beginTimer(); + if (this.startTimestamp == -1 && shouldAnimate) { + this.beginTimer(); } for (int i = 0; i < blockCount; i++) { @@ -243,7 +226,8 @@ public void generateNextBlocks(int blockCount, boolean shouldAnimate) { private void playSound(int combo) { float pitch = 0.9f + (combo - 1) * 0.05f; - this.playSound(Sound.sound(SoundEvent.BLOCK_NOTE_BLOCK_BASS, Sound.Source.MASTER, 1f, pitch), Sound.Emitter.self()); + Sound comboSound = Sound.sound(SoundEvent.BLOCK_NOTE_BLOCK_BASS, Sound.Source.MASTER, 1f, pitch); + this.player.playSound(comboSound, Sound.Emitter.self()); } private void createBreakingTask() { @@ -268,7 +252,8 @@ public TaskSchedule get() { MarathonGame.this.createBreakingTask(); } - MarathonGame.this.playSound(Sound.sound(SoundEvent.BLOCK_WOOD_HIT, Sound.Source.MASTER, 0.5f, 1f), Sound.Emitter.self()); + Sound breakingSound = Sound.sound(SoundEvent.BLOCK_WOOD_HIT, Sound.Source.MASTER, 0.5f, 1f); + MarathonGame.this.player.playSound(breakingSound, Sound.Emitter.self()); BlockPacketUtils.sendBlockDamage(MarathonGame.this.instance, block, this.destroyStage); return TaskSchedule.tick(10); @@ -277,15 +262,15 @@ public TaskSchedule get() { } public void beginTimer() { - startTimestamp = System.currentTimeMillis(); + this.startTimestamp = System.currentTimeMillis(); } - public @NotNull Collection getBlocks() { - return this.blocks; + public @NotNull Instance getInstance() { + return this.instance; } - public @NotNull Instance getSpawningInstance() { - return this.instance; + public @NotNull Collection getBlocks() { + return this.blocks; } public boolean isRunInvalidated() { diff --git a/src/main/java/dev/emortal/minestom/marathon/MarathonGameRunner.java b/src/main/java/dev/emortal/minestom/marathon/MarathonGameRunner.java new file mode 100755 index 0000000..bd06128 --- /dev/null +++ b/src/main/java/dev/emortal/minestom/marathon/MarathonGameRunner.java @@ -0,0 +1,51 @@ +package dev.emortal.minestom.marathon; + +import dev.emortal.minestom.gamesdk.config.GameCreationInfo; +import dev.emortal.minestom.gamesdk.game.Game; +import net.minestom.server.entity.Player; +import net.minestom.server.instance.Instance; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public final class MarathonGameRunner extends Game { + + private final Map games = new HashMap<>(); + + public MarathonGameRunner(@NotNull GameCreationInfo creationInfo) { + super(creationInfo); + } + + @Override + public void start() { + } + + @Override + public void onJoin(@NotNull Player player) { + MarathonGame game = this.games.computeIfAbsent(player.getUuid(), uuid -> new MarathonGame(player, this.getEventNode())); + game.onJoin(player); + } + + @Override + public void onLeave(@NotNull Player player) { + // Do nothing - game SDK will check if player count is 0 and end the game + } + + @Override + public void cleanUp() { + for (MarathonGame game : this.games.values()) { + game.cleanUp(); + } + } + + @Override + public @NotNull Instance getSpawningInstance(@NotNull Player player) { + MarathonGame game = this.games.get(player.getUuid()); + if (game == null) { + throw new IllegalStateException("No game found for player " + player.getUsername() + " when instance requested!"); + } + return game.getInstance(); + } +} diff --git a/src/main/java/dev/emortal/minestom/marathon/listener/MovementListener.java b/src/main/java/dev/emortal/minestom/marathon/listener/MovementListener.java index 656f7bb..582d28c 100644 --- a/src/main/java/dev/emortal/minestom/marathon/listener/MovementListener.java +++ b/src/main/java/dev/emortal/minestom/marathon/listener/MovementListener.java @@ -54,6 +54,7 @@ private void checkPosition(@NotNull Point newPosition) { if (newPosition.blockY() < (minY - 3)) { // too far below this.game.reset(); + this.game.teleportPlayerToStart(); } if (this.game.isRunInvalidated()) return;