From 8dc33cadbc393e1efb8a9880176320cd9049eab2 Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Wed, 7 Jun 2023 22:34:03 -0400 Subject: [PATCH 001/181] remove gold platform --- .../java/org/phantazm/server/ProximaTest.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/server/src/main/java/org/phantazm/server/ProximaTest.java b/server/src/main/java/org/phantazm/server/ProximaTest.java index 570e6f915..acc855b1a 100644 --- a/server/src/main/java/org/phantazm/server/ProximaTest.java +++ b/server/src/main/java/org/phantazm/server/ProximaTest.java @@ -108,21 +108,21 @@ static void initialize(@NotNull EventNode global, @NotNull Spawner spawne } }).build()); - global.addListener(PlayerSpawnEvent.class, event -> { - if (!event.isFirstSpawn()) { - return; - } - - event.getPlayer().teleport(new Pos(0, 100, 0)).join(); - event.getPlayer().setGameMode(GameMode.CREATIVE); - event.getPlayer().setFlying(true); - Pos start = event.getPlayer().getPosition().sub(0, 1, 0); - - for (int i = 0; i < 100; i++) { - for (int j = 0; j < 100; j++) { - event.getSpawnInstance().setBlock(start.add(i, 0, j), Block.GOLD_BLOCK); - } - } - }); +// global.addListener(PlayerSpawnEvent.class, event -> { +// if (!event.isFirstSpawn()) { +// return; +// } +// +// event.getPlayer().teleport(new Pos(0, 100, 0)).join(); +// event.getPlayer().setGameMode(GameMode.CREATIVE); +// event.getPlayer().setFlying(true); +// Pos start = event.getPlayer().getPosition().sub(0, 1, 0); +// +// for (int i = 0; i < 100; i++) { +// for (int j = 0; j < 100; j++) { +// event.getSpawnInstance().setBlock(start.add(i, 0, j), Block.GOLD_BLOCK); +// } +// } +// }); } } From 20cc098674c6ae92bad9bd1e4803269a8f699186 Mon Sep 17 00:00:00 2001 From: steank Date: Wed, 14 Jun 2023 03:52:33 -0700 Subject: [PATCH 002/181] join() on futures in ZombiesScene#join, use whenComplete --- .../java/org/phantazm/zombies/scene/ZombiesScene.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java index 750fe2389..77eb1fd0f 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java @@ -137,14 +137,14 @@ public boolean isComplete() { }); } - CompletableFuture.allOf(futures.toArray(EMPTY_COMPLETABLE_FUTURE_ARRAY)).thenRun(() -> { - for (int i = 0; i < futures.size(); ++i) { + CompletableFuture.allOf(futures.toArray(EMPTY_COMPLETABLE_FUTURE_ARRAY)).whenComplete((ignored, error) -> { + for (int i = 0; i < futures.size(); i++) { PlayerView view = teleportedViews.get(i); Player teleportedPlayer = teleportedPlayers.get(i); CompletableFuture future = futures.get(i); if (future.isCompletedExceptionally()) { - future.whenComplete((ignored, throwable) -> { + future.whenComplete((ignored1, throwable) -> { LOGGER.warn("Failed to send {} to an instance", teleportedPlayer.getUuid(), throwable); }); continue; @@ -156,7 +156,8 @@ public boolean isComplete() { teleportedPlayer.sendPacket(otherPlayer.getRemovePlayerToList()); teleportedPlayer.removeViewer(otherPlayer); otherPlayer.sendPacket(teleportedPlayer.getRemovePlayerToList()); - } else { + } + else { teleportedPlayer.sendPacket(otherPlayer.getAddPlayerToList()); otherPlayer.addViewer(teleportedPlayer); otherPlayer.sendPacket(teleportedPlayer.getAddPlayerToList()); @@ -172,7 +173,7 @@ public boolean isComplete() { stage.onJoin(zombiesPlayer); } - }); + }).join(); return RouteResult.SUCCESSFUL; } From 580d9f62d8befe047beb7f40dbb8d79384fe5052 Mon Sep 17 00:00:00 2001 From: steank Date: Wed, 14 Jun 2023 04:30:21 -0700 Subject: [PATCH 003/181] fix potential NPE in inStage method --- .../java/org/phantazm/zombies/player/ZombiesPlayer.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java index 697237fb6..a0a877a8c 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java @@ -25,6 +25,7 @@ import org.phantazm.zombies.player.state.ZombiesPlayerStateKeys; import org.phantazm.zombies.powerup.Powerup; import org.phantazm.zombies.scene.ZombiesScene; +import org.phantazm.zombies.stage.Stage; import java.util.Map; import java.util.Optional; @@ -126,7 +127,12 @@ default boolean canBeTargeted() { } default boolean inStage(@NotNull Key stageKey) { - return getScene().getCurrentStage().key().equals(stageKey); + Stage currentStage = getScene().getCurrentStage(); + if (currentStage == null) { + return false; + } + + return currentStage.key().equals(stageKey); } default @NotNull String getUsername() { From fbdba548c1e403e08183926a38590d5befa7d571 Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Wed, 14 Jun 2023 07:47:33 -0400 Subject: [PATCH 004/181] add join to BasicLobbyJoinRequest, require invitation to parties in order to join, choose a new owner upon owner leave, add more quit checks, use whenComplete in certain places in PartyNotification --- .../scene/lobby/BasicLobbyJoinRequest.java | 2 +- .../core/guild/party/PartyNotification.java | 115 ++++++++++++++---- .../guild/party/command/PartyCommand.java | 5 +- .../guild/party/command/PartyJoinCommand.java | 5 + .../party/command/PartyLeaveCommand.java | 23 +++- .../PartyCreateCommandIntegrationTest.java | 4 +- .../PartyInviteCommandIntegrationTest.java | 10 +- .../PartyJoinCommandIntegrationTest.java | 31 ++++- .../PartyKickCommandIntegrationTest.java | 13 +- .../PartyLeaveCommandIntegrationTest.java | 33 ++++- .../org/phantazm/server/PartyFeature.java | 3 +- .../map/action/round/PlaySoundAction.java | 6 +- .../phantazm/zombies/stage/InGameStage.java | 4 + 13 files changed, 203 insertions(+), 51 deletions(-) diff --git a/core/src/main/java/org/phantazm/core/game/scene/lobby/BasicLobbyJoinRequest.java b/core/src/main/java/org/phantazm/core/game/scene/lobby/BasicLobbyJoinRequest.java index 524c17f48..594aeaf05 100644 --- a/core/src/main/java/org/phantazm/core/game/scene/lobby/BasicLobbyJoinRequest.java +++ b/core/src/main/java/org/phantazm/core/game/scene/lobby/BasicLobbyJoinRequest.java @@ -73,7 +73,7 @@ public void handleJoin(@NotNull Instance instance, @NotNull InstanceConfig insta } } } - }); + }).join(); } } diff --git a/core/src/main/java/org/phantazm/core/guild/party/PartyNotification.java b/core/src/main/java/org/phantazm/core/guild/party/PartyNotification.java index 5d3d70fff..8f8bde2de 100644 --- a/core/src/main/java/org/phantazm/core/guild/party/PartyNotification.java +++ b/core/src/main/java/org/phantazm/core/guild/party/PartyNotification.java @@ -7,9 +7,12 @@ import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; import org.jetbrains.annotations.NotNull; import org.phantazm.core.guild.invite.InvitationNotification; import org.phantazm.core.player.PlayerView; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Collection; @@ -18,6 +21,8 @@ public class PartyNotification implements InvitationNotification { + private static final Logger LOGGER = LoggerFactory.getLogger(PartyNotification.class); + private final Audience audience; private final Wrapper owner; @@ -57,24 +62,35 @@ public void notifyJoin(@NotNull PartyMember newMember) { @Override public void notifyInvitation(@NotNull PartyMember inviter, @NotNull PlayerView invitee) { - CompletableFuture inviterName = inviter.getPlayerView().getDisplayName(); - CompletableFuture inviteeName = invitee.getDisplayName(); + CompletableFuture inviterDisplayName = inviter.getPlayerView().getDisplayName(); + CompletableFuture inviteeDisplayName = invitee.getDisplayName(); + + CompletableFuture.allOf(inviterDisplayName, inviteeDisplayName).whenComplete((ignored, throwable) -> { + if (throwable != null) { + LOGGER.warn("Exception while sending invitation message", throwable); + return; + } - CompletableFuture.allOf(inviterName, inviteeName).thenRun(() -> { ComponentLike message = Component.text() - .append(inviterName.join(), Component.text(" has invited "), inviteeName.join(), + .append(inviterDisplayName.join(), Component.text(" has invited "), inviteeDisplayName.join(), Component.text(" to the party.")).color(NamedTextColor.GOLD); audience.sendMessage(message); }); if (inviter == owner.get()) { - inviterName.thenAccept(displayName -> { + CompletableFuture inviterName = inviter.getPlayerView().getUsername(); + CompletableFuture.allOf(inviterName, inviterDisplayName).whenComplete((ignored, throwable) -> { + if (throwable != null) { + LOGGER.warn("Exception while sending invitation message", throwable); + return; + } + invitee.getPlayer().ifPresent(player -> { - ComponentLike message = Component.text() - .append(displayName, Component.text(" has invited you to join their party. Click "), - Component.text("here", NamedTextColor.GOLD) - .clickEvent(ClickEvent.runCommand("/party join " + player.getUsername())), - Component.text(" to join!")).color(NamedTextColor.GOLD); + ComponentLike message = Component.text().append(inviterDisplayName.join(), + Component.text(" has invited you to join their party. Click "), + Component.text("here", NamedTextColor.GOLD, TextDecoration.BOLD) + .clickEvent(ClickEvent.runCommand("/party join " + inviterName.join())), + Component.text(" to join!")).color(NamedTextColor.GOLD); player.sendMessage(message); }); }); @@ -82,30 +98,46 @@ public void notifyInvitation(@NotNull PartyMember inviter, @NotNull PlayerView i else { CompletableFuture ownerName = owner.get().getPlayerView().getUsername(); CompletableFuture ownerDisplayName = owner.get().getPlayerView().getDisplayName(); - CompletableFuture.allOf(ownerName, ownerDisplayName, inviterName).thenRun(() -> { - invitee.getPlayer().ifPresent(player -> { - ComponentLike message = Component.text() - .append(inviterName.join(), Component.text(" has invited you to join "), - ownerDisplayName.join(), Component.text("'s party. Click "), - Component.text("here", NamedTextColor.GOLD) - .clickEvent(ClickEvent.runCommand("/party join " + ownerName.join())), - Component.text(" to join!")).color(NamedTextColor.GOLD); - player.sendMessage(message); - }); - }); + CompletableFuture.allOf(ownerName, ownerDisplayName, inviterDisplayName) + .whenComplete((ignored, throwable) -> { + if (throwable != null) { + LOGGER.warn("Exception while sending invitation message", throwable); + return; + } + + invitee.getPlayer().ifPresent(player -> { + ComponentLike message = Component.text() + .append(inviterDisplayName.join(), Component.text(" has invited you to join "), + ownerDisplayName.join(), Component.text("'s party. Click "), + Component.text("here", NamedTextColor.GOLD, TextDecoration.BOLD).clickEvent( + ClickEvent.runCommand("/party join " + ownerName.join())), + Component.text(" to join!")).color(NamedTextColor.GOLD); + player.sendMessage(message); + }); + }); } } @Override public void notifyExpiry(@NotNull PlayerView invitee) { - invitee.getDisplayName().thenAccept(displayName -> { + invitee.getDisplayName().whenComplete((displayName, throwable) -> { + if (throwable != null) { + LOGGER.warn("Exception while sending invitation message", throwable); + return; + } + ComponentLike message = Component.text() .append(Component.text("The invitation to "), displayName, Component.text(" has expired.")) .color(NamedTextColor.GOLD); audience.sendMessage(message); }); - owner.get().getPlayerView().getDisplayName().thenAccept(displayName -> { + owner.get().getPlayerView().getDisplayName().whenComplete((displayName, throwable) -> { + if (throwable != null) { + LOGGER.warn("Exception while sending invitation expiry message", throwable); + return; + } + invitee.getPlayer().ifPresent(player -> { ComponentLike message = Component.text().append(Component.text("The invitation to "), displayName, Component.text("'s party has expired.")).color(NamedTextColor.GOLD); @@ -115,7 +147,12 @@ public void notifyExpiry(@NotNull PlayerView invitee) { } public void notifyLeave(@NotNull PartyMember oldMember) { - oldMember.getPlayerView().getDisplayName().thenAccept(displayName -> { + oldMember.getPlayerView().getDisplayName().whenComplete((displayName, throwable) -> { + if (throwable != null) { + LOGGER.warn("Exception while sending party leave message", throwable); + return; + } + ComponentLike message = Component.text().append(displayName, Component.text(" has left the party.")) .color(NamedTextColor.GOLD); audience.sendMessage(message); @@ -130,14 +167,24 @@ public void notifyKick(@NotNull PartyMember kicker, @NotNull PartyMember toKick) CompletableFuture kickerName = kicker.getPlayerView().getDisplayName(); CompletableFuture toKickName = toKick.getPlayerView().getDisplayName(); - CompletableFuture.allOf(kickerName, toKickName).thenRun(() -> { + CompletableFuture.allOf(kickerName, toKickName).whenComplete((ignored, throwable) -> { + if (throwable != null) { + LOGGER.warn("Exception while sending kick message", throwable); + return; + } + ComponentLike message = Component.text() .append(toKickName.join(), Component.text(" was kicked by "), kickerName.join(), Component.text(".")).color(NamedTextColor.GOLD); audience.sendMessage(message); }); - kickerName.thenAccept(name -> { + kickerName.whenComplete((name, throwable) -> { + if (throwable != null) { + LOGGER.warn("Exception while sending kick message", throwable); + return; + } + toKick.getPlayerView().getPlayer().ifPresent(player -> { ComponentLike message = Component.text().append(Component.text("You were kicked by "), name, Component.text(".")) @@ -147,4 +194,20 @@ public void notifyKick(@NotNull PartyMember kicker, @NotNull PartyMember toKick) }); } + public void notifyTransfer(@NotNull PartyMember from, @NotNull PartyMember to) { + CompletableFuture fromDisplayName = from.getPlayerView().getDisplayName(); + CompletableFuture toDisplayName = to.getPlayerView().getDisplayName(); + + CompletableFuture.allOf(fromDisplayName, toDisplayName).whenComplete((ignored, throwable) -> { + if (throwable != null) { + LOGGER.warn("Exception while sending kick message", throwable); + return; + } + + ComponentLike message = Component.text().append(Component.text("The party has been transferred from "), + fromDisplayName.join(), Component.text(" to "), toDisplayName.join(), Component.text(".")).color(NamedTextColor.GOLD); + audience.sendMessage(message); + }); + } + } diff --git a/core/src/main/java/org/phantazm/core/guild/party/command/PartyCommand.java b/core/src/main/java/org/phantazm/core/guild/party/command/PartyCommand.java index 284d575ea..a4ee89b7a 100644 --- a/core/src/main/java/org/phantazm/core/guild/party/command/PartyCommand.java +++ b/core/src/main/java/org/phantazm/core/guild/party/command/PartyCommand.java @@ -7,16 +7,17 @@ import org.phantazm.core.player.PlayerViewProvider; import java.util.Map; +import java.util.Random; import java.util.UUID; public class PartyCommand { public static Command command(@NotNull Map parties, @NotNull PlayerViewProvider viewProvider, - @NotNull PartyCreator partyCreator) { + @NotNull PartyCreator partyCreator, @NotNull Random random) { Command command = new Command("party", "p"); command.addSubcommand(PartyCreateCommand.createCommand(parties, viewProvider, partyCreator)); command.addSubcommand(PartyJoinCommand.joinCommand(parties, viewProvider)); - command.addSubcommand(PartyLeaveCommand.leaveCommand(parties)); + command.addSubcommand(PartyLeaveCommand.leaveCommand(parties, random)); command.addSubcommand(PartyKickCommand.kickCommand(parties, viewProvider)); command.addSubcommand(PartyInviteCommand.inviteCommand(parties, viewProvider)); diff --git a/core/src/main/java/org/phantazm/core/guild/party/command/PartyJoinCommand.java b/core/src/main/java/org/phantazm/core/guild/party/command/PartyJoinCommand.java index 3b1f112fa..f2ff90f63 100644 --- a/core/src/main/java/org/phantazm/core/guild/party/command/PartyJoinCommand.java +++ b/core/src/main/java/org/phantazm/core/guild/party/command/PartyJoinCommand.java @@ -56,6 +56,11 @@ public static Command joinCommand(@NotNull Map parties, } Player player = (Player)sender; + if (!party.getInvitationManager().hasInvitation(player.getUuid())) { + sender.sendMessage(Component.text("You don't have an invite to the party.", NamedTextColor.RED)); + return; + } + Party previousParty = parties.get(player.getUuid()); if (previousParty != null) { previousParty.getMemberManager().removeMember(player.getUuid()); diff --git a/core/src/main/java/org/phantazm/core/guild/party/command/PartyLeaveCommand.java b/core/src/main/java/org/phantazm/core/guild/party/command/PartyLeaveCommand.java index c3eebddfe..db0ac0727 100644 --- a/core/src/main/java/org/phantazm/core/guild/party/command/PartyLeaveCommand.java +++ b/core/src/main/java/org/phantazm/core/guild/party/command/PartyLeaveCommand.java @@ -8,14 +8,13 @@ import org.phantazm.core.guild.party.Party; import org.phantazm.core.guild.party.PartyMember; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; +import java.util.*; public class PartyLeaveCommand { - public static Command leaveCommand(@NotNull Map parties) { + public static Command leaveCommand(@NotNull Map parties, @NotNull Random random) { Objects.requireNonNull(parties, "parties"); + Objects.requireNonNull(random, "random"); Command command = new Command("leave"); command.addConditionalSyntax((sender, commandString) -> { @@ -42,6 +41,22 @@ public static Command leaveCommand(@NotNull Map p party.getNotification().notifyLeave(oldMember); sender.sendMessage(Component.text("Left the party.", NamedTextColor.GREEN)); + + if (party.getOwner().get().getPlayerView().getUUID().equals(uuid)) { + if (party.getMemberManager().getMembers().isEmpty()) { + party.getOwner().set(null); + } else { + int memberIndex = random.nextInt(party.getMemberManager().getMembers().size()); + Iterator memberIterator = party.getMemberManager().getMembers().values().iterator(); + PartyMember newOwner = null; + for (int i = 0; i < memberIndex; ++i) { + newOwner = memberIterator.next(); + } + + party.getOwner().set(newOwner); + party.getNotification().notifyTransfer(oldMember, newOwner); + } + } }); return command; diff --git a/core/src/test/java/org/phantazm/core/guild/party/command/PartyCreateCommandIntegrationTest.java b/core/src/test/java/org/phantazm/core/guild/party/command/PartyCreateCommandIntegrationTest.java index a345d044b..32ef9b284 100644 --- a/core/src/test/java/org/phantazm/core/guild/party/command/PartyCreateCommandIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/guild/party/command/PartyCreateCommandIntegrationTest.java @@ -11,6 +11,8 @@ import org.phantazm.core.player.BasicPlayerViewProvider; import org.phantazm.core.player.PlayerViewProvider; +import java.util.Random; + import static org.junit.jupiter.api.Assertions.assertTrue; @EnvTest @@ -21,7 +23,7 @@ public class PartyCreateCommandIntegrationTest extends AbstractPartyCommandInteg public void testCreateCreatesParty(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player player = env.createPlayer(instance, Pos.ZERO); diff --git a/core/src/test/java/org/phantazm/core/guild/party/command/PartyInviteCommandIntegrationTest.java b/core/src/test/java/org/phantazm/core/guild/party/command/PartyInviteCommandIntegrationTest.java index bfd8241d4..b390236e8 100644 --- a/core/src/test/java/org/phantazm/core/guild/party/command/PartyInviteCommandIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/guild/party/command/PartyInviteCommandIntegrationTest.java @@ -12,6 +12,8 @@ import org.phantazm.core.player.BasicPlayerViewProvider; import org.phantazm.core.player.PlayerViewProvider; +import java.util.Random; + import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -23,7 +25,7 @@ public class PartyInviteCommandIntegrationTest extends AbstractPartyCommandInteg public void testCanInviteWithInvitePermission(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -43,7 +45,7 @@ public void testCanInviteWithInvitePermission(Env env) { public void testCanInviteOtherPlayerInPartyWithInvitePermission(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -64,7 +66,7 @@ public void testCanInviteOtherPlayerInPartyWithInvitePermission(Env env) { public void testCannotInviteWithoutInvitePermission(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 2); - Command command = PartyCommand.command(parties, viewProvider, partyCreator); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -84,7 +86,7 @@ public void testCannotInviteWithoutInvitePermission(Env env) { public void testCannotInviteSelf(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player player = env.createPlayer(instance, Pos.ZERO); diff --git a/core/src/test/java/org/phantazm/core/guild/party/command/PartyJoinCommandIntegrationTest.java b/core/src/test/java/org/phantazm/core/guild/party/command/PartyJoinCommandIntegrationTest.java index a12be179c..7afbe6c31 100644 --- a/core/src/test/java/org/phantazm/core/guild/party/command/PartyJoinCommandIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/guild/party/command/PartyJoinCommandIntegrationTest.java @@ -12,6 +12,8 @@ import org.phantazm.core.player.BasicPlayerViewProvider; import org.phantazm.core.player.PlayerViewProvider; +import java.util.Random; + import static org.junit.jupiter.api.Assertions.*; @EnvTest @@ -22,7 +24,7 @@ public class PartyJoinCommandIntegrationTest extends AbstractPartyCommandIntegra public void testNotInPartyAfterJoiningOtherPlayerNotInParty(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -38,10 +40,31 @@ public void testNotInPartyAfterJoiningOtherPlayerNotInParty(Env env) { @SuppressWarnings({"UnstableApiUsage", "JUnitMalformedDeclaration"}) @Test - public void testInPartyAfterJoiningOtherPlayerInParty(Env env) { + public void testNotInPartyWithoutInviteAndJoiningOtherPlayerInParty(Env env) { + PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); + PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + env.process().command().register(command); + Instance instance = env.createFlatInstance(); + Player firstPlayer = env.createPlayer(instance, Pos.ZERO); + firstPlayer.setUsernameField("first"); + env.process().command().execute(firstPlayer, "party create"); + Party party = parties.get(firstPlayer.getUuid()); + Player secondPlayer = env.createPlayer(instance, Pos.ZERO); + secondPlayer.setUsernameField("second"); + + env.process().command().execute(secondPlayer, "party join first"); + + assertFalse(parties.containsKey(secondPlayer.getUuid())); + assertFalse(party.getMemberManager().hasMember(secondPlayer.getUuid())); + } + + @SuppressWarnings({"UnstableApiUsage", "JUnitMalformedDeclaration"}) + @Test + public void testInPartyAfterInviteAndJoiningOtherPlayerInParty(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -50,6 +73,8 @@ public void testInPartyAfterJoiningOtherPlayerInParty(Env env) { Party party = parties.get(firstPlayer.getUuid()); Player secondPlayer = env.createPlayer(instance, Pos.ZERO); secondPlayer.setUsernameField("second"); + party.getInvitationManager().invite(party.getMemberManager().getMember(firstPlayer.getUuid()), + viewProvider.fromPlayer(secondPlayer)); env.process().command().execute(secondPlayer, "party join first"); diff --git a/core/src/test/java/org/phantazm/core/guild/party/command/PartyKickCommandIntegrationTest.java b/core/src/test/java/org/phantazm/core/guild/party/command/PartyKickCommandIntegrationTest.java index 16f930afb..73415934d 100644 --- a/core/src/test/java/org/phantazm/core/guild/party/command/PartyKickCommandIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/guild/party/command/PartyKickCommandIntegrationTest.java @@ -11,6 +11,8 @@ import org.phantazm.core.player.BasicPlayerViewProvider; import org.phantazm.core.player.PlayerViewProvider; +import java.util.Random; + import static org.junit.jupiter.api.Assertions.*; public class PartyKickCommandIntegrationTest extends AbstractPartyCommandIntegrationTest { @@ -20,7 +22,7 @@ public class PartyKickCommandIntegrationTest extends AbstractPartyCommandIntegra public void testCanKickWithSufficientRankAndGreaterRankThanTarget(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -29,6 +31,7 @@ public void testCanKickWithSufficientRankAndGreaterRankThanTarget(Env env) { Party party = parties.get(firstPlayer.getUuid()); Player secondPlayer = env.createPlayer(instance, Pos.ZERO); secondPlayer.setUsernameField("second"); + env.process().command().execute(firstPlayer, "party invite second"); env.process().command().execute(secondPlayer, "party join first"); env.process().command().execute(firstPlayer, "party kick second"); @@ -42,7 +45,7 @@ public void testCanKickWithSufficientRankAndGreaterRankThanTarget(Env env) { public void testCannotKickWithoutSufficientRankAndGreaterRankThanTarget(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 2, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -51,6 +54,7 @@ public void testCannotKickWithoutSufficientRankAndGreaterRankThanTarget(Env env) Party party = parties.get(firstPlayer.getUuid()); Player secondPlayer = env.createPlayer(instance, Pos.ZERO); secondPlayer.setUsernameField("second"); + env.process().command().execute(firstPlayer, "party invite second"); env.process().command().execute(secondPlayer, "party join first"); env.process().command().execute(firstPlayer, "party kick second"); @@ -64,7 +68,7 @@ public void testCannotKickWithoutSufficientRankAndGreaterRankThanTarget(Env env) public void testCannotKickWithSufficientRankAndEqualRankToTarget(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 2, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -73,6 +77,7 @@ public void testCannotKickWithSufficientRankAndEqualRankToTarget(Env env) { Party party = parties.get(firstPlayer.getUuid()); Player secondPlayer = env.createPlayer(instance, Pos.ZERO); secondPlayer.setUsernameField("second"); + env.process().command().execute(firstPlayer, "party invite second"); env.process().command().execute(secondPlayer, "party join first"); party.getMemberManager().getMember(secondPlayer.getUuid()).setRank(1); @@ -87,7 +92,7 @@ public void testCannotKickWithSufficientRankAndEqualRankToTarget(Env env) { public void testCannotKickSelf(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 2, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player player = env.createPlayer(instance, Pos.ZERO); diff --git a/core/src/test/java/org/phantazm/core/guild/party/command/PartyLeaveCommandIntegrationTest.java b/core/src/test/java/org/phantazm/core/guild/party/command/PartyLeaveCommandIntegrationTest.java index 6824e6b39..537d4bccd 100644 --- a/core/src/test/java/org/phantazm/core/guild/party/command/PartyLeaveCommandIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/guild/party/command/PartyLeaveCommandIntegrationTest.java @@ -12,17 +12,19 @@ import org.phantazm.core.player.BasicPlayerViewProvider; import org.phantazm.core.player.PlayerViewProvider; -import static org.junit.jupiter.api.Assertions.assertFalse; +import java.util.Random; + +import static org.junit.jupiter.api.Assertions.*; @EnvTest public class PartyLeaveCommandIntegrationTest extends AbstractPartyCommandIntegrationTest { @SuppressWarnings({"UnstableApiUsage", "JUnitMalformedDeclaration"}) @Test - public void testNotInPartyAfterLeaving(Env env) { + public void testNotInPartyAfterLeavingAndOwnerIsNullNoOtherMembers(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player player = env.createPlayer(instance, Pos.ZERO); @@ -33,6 +35,31 @@ public void testNotInPartyAfterLeaving(Env env) { assertFalse(parties.containsKey(player.getUuid())); assertFalse(party.getMemberManager().hasMember(player.getUuid())); + assertNull(party.getOwner().get()); + } + + @SuppressWarnings({"UnstableApiUsage", "JUnitMalformedDeclaration"}) + @Test + public void testOwnerIsNotNullAfterLeavingWithOtherMembers(Env env) { + PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); + PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); + Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + env.process().command().register(command); + Instance instance = env.createFlatInstance(); + Player firstPlayer = env.createPlayer(instance, Pos.ZERO); + firstPlayer.setUsernameField("first"); + env.process().command().execute(firstPlayer, "party create"); + Player secondPlayer = env.createPlayer(instance, Pos.ZERO); + Party party = parties.get(firstPlayer.getUuid()); + secondPlayer.setUsernameField("second"); + env.process().command().execute(firstPlayer, "party invite second"); + env.process().command().execute(secondPlayer, "party join first"); + + env.process().command().execute(firstPlayer, "party leave"); + + assertFalse(parties.containsKey(firstPlayer.getUuid())); + assertFalse(party.getMemberManager().hasMember(firstPlayer.getUuid())); + assertNotNull(party.getOwner().get()); } } diff --git a/server/src/main/java/org/phantazm/server/PartyFeature.java b/server/src/main/java/org/phantazm/server/PartyFeature.java index b86573e14..717ee04ef 100644 --- a/server/src/main/java/org/phantazm/server/PartyFeature.java +++ b/server/src/main/java/org/phantazm/server/PartyFeature.java @@ -12,6 +12,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Random; import java.util.UUID; public class PartyFeature { @@ -21,7 +22,7 @@ public class PartyFeature { public static void initialize(@NotNull CommandManager commandManager, @NotNull PlayerViewProvider viewProvider, @NotNull SchedulerManager schedulerManager) { PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command partyCommand = PartyCommand.command(parties, viewProvider, partyCreator); + Command partyCommand = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); commandManager.register(partyCommand); schedulerManager.scheduleTask(() -> { diff --git a/zombies/src/main/java/org/phantazm/zombies/map/action/round/PlaySoundAction.java b/zombies/src/main/java/org/phantazm/zombies/map/action/round/PlaySoundAction.java index 1a551df35..c928e2870 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/action/round/PlaySoundAction.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/action/round/PlaySoundAction.java @@ -30,8 +30,10 @@ public PlaySoundAction(@NotNull Data data, @NotNull Random random, @Override public void perform(@NotNull Round round) { for (ZombiesPlayer zombiesPlayer : playerMap.values()) { - zombiesPlayer.getPlayer() - .ifPresent(player -> player.playSound(Sound.sound(data.sound).seed(random.nextLong()).build())); + if (!zombiesPlayer.hasQuit()) { + zombiesPlayer.getPlayer() + .ifPresent(player -> player.playSound(Sound.sound(data.sound).seed(random.nextLong()).build())); + } } } diff --git a/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java b/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java index b5ec941f9..da6a158c8 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java +++ b/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java @@ -165,6 +165,10 @@ public void end() { } for (ZombiesPlayer zombiesPlayer : zombiesPlayers) { + if (zombiesPlayer.hasQuit()) { + continue; + } + zombiesPlayer.sendMessage(Component.text("==========================================", Style.style(NamedTextColor.GREEN, TextDecoration.STRIKETHROUGH))); From 03b6cc9db4645d8ad9e08c5b232245905419d72b Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Wed, 14 Jun 2023 07:49:35 -0400 Subject: [PATCH 005/181] fix rejoin command suggestions --- .../java/org/phantazm/zombies/command/ZombiesRejoinCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zombies/src/main/java/org/phantazm/zombies/command/ZombiesRejoinCommand.java b/zombies/src/main/java/org/phantazm/zombies/command/ZombiesRejoinCommand.java index d4c5ff529..1cbaae08f 100644 --- a/zombies/src/main/java/org/phantazm/zombies/command/ZombiesRejoinCommand.java +++ b/zombies/src/main/java/org/phantazm/zombies/command/ZombiesRejoinCommand.java @@ -36,7 +36,7 @@ public ZombiesRejoinCommand(@NotNull ZombiesSceneRouter router, @NotNull PlayerV UUID uuid = player.getUuid(); for (ZombiesScene scene : router.getScenes()) { - if (!scene.getPlayers().containsKey(uuid)) { + if (!scene.getZombiesPlayers().containsKey(uuid)) { continue; } From d8a475128a75f883ee1f2380df45b864864ad96f Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Wed, 14 Jun 2023 08:15:07 -0400 Subject: [PATCH 006/181] fix rejoinGame --- .../java/org/phantazm/zombies/scene/ZombiesSceneRouter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneRouter.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneRouter.java index 2b10df561..d6b1f18de 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneRouter.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneRouter.java @@ -119,7 +119,7 @@ private RouteResult joinGame(ZombiesRouteRequest routeRequest) { // TODO: optimize private RouteResult rejoinGame(ZombiesRouteRequest routeRequest) { for (ZombiesScene scene : getScenes()) { - if (!scene.getUuid().equals(routeRequest.targetGame())) { + if (scene.getUuid().equals(routeRequest.targetGame())) { return scene.join(routeRequest.joinRequest()); } } From 9255a890fb75c1aa2cdb823f705db1929038fbd8 Mon Sep 17 00:00:00 2001 From: steank Date: Wed, 14 Jun 2023 05:38:19 -0700 Subject: [PATCH 007/181] bump minestom version --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 517b4b9a3..d71c7f486 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ examination = "1.3.0" junit-jupiter = "5.9.0" -minestom = "3f0d31f441" +minestom = "a58959067c" toolkit = "0.3.0" From 8843ad94348eaa3ad282fcfb675bef4124a16265 Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Wed, 14 Jun 2023 09:21:06 -0400 Subject: [PATCH 008/181] prevent command instantiation, add PartyListCommand --- .../guild/party/command/PartyCommand.java | 7 +- .../party/command/PartyCreateCommand.java | 6 +- .../party/command/PartyInviteCommand.java | 6 +- .../guild/party/command/PartyJoinCommand.java | 6 +- .../guild/party/command/PartyKickCommand.java | 6 +- .../party/command/PartyLeaveCommand.java | 6 +- .../guild/party/command/PartyListCommand.java | 77 +++++++++++++++++++ .../PartyCreateCommandIntegrationTest.java | 2 +- .../PartyInviteCommandIntegrationTest.java | 8 +- .../PartyJoinCommandIntegrationTest.java | 6 +- .../PartyKickCommandIntegrationTest.java | 8 +- .../PartyLeaveCommandIntegrationTest.java | 4 +- .../org/phantazm/server/PartyFeature.java | 2 +- .../phantazm/zombies/stage/InGameStage.java | 6 +- 14 files changed, 126 insertions(+), 24 deletions(-) create mode 100644 core/src/main/java/org/phantazm/core/guild/party/command/PartyListCommand.java diff --git a/core/src/main/java/org/phantazm/core/guild/party/command/PartyCommand.java b/core/src/main/java/org/phantazm/core/guild/party/command/PartyCommand.java index a4ee89b7a..72403e41e 100644 --- a/core/src/main/java/org/phantazm/core/guild/party/command/PartyCommand.java +++ b/core/src/main/java/org/phantazm/core/guild/party/command/PartyCommand.java @@ -12,7 +12,11 @@ public class PartyCommand { - public static Command command(@NotNull Map parties, @NotNull PlayerViewProvider viewProvider, + private PartyCommand() { + throw new UnsupportedOperationException(); + } + + public static @NotNull Command partyCommand(@NotNull Map parties, @NotNull PlayerViewProvider viewProvider, @NotNull PartyCreator partyCreator, @NotNull Random random) { Command command = new Command("party", "p"); command.addSubcommand(PartyCreateCommand.createCommand(parties, viewProvider, partyCreator)); @@ -20,6 +24,7 @@ public static Command command(@NotNull Map parties, @NotNul command.addSubcommand(PartyLeaveCommand.leaveCommand(parties, random)); command.addSubcommand(PartyKickCommand.kickCommand(parties, viewProvider)); command.addSubcommand(PartyInviteCommand.inviteCommand(parties, viewProvider)); + command.addSubcommand(PartyListCommand.listCommand(parties)); return command; } diff --git a/core/src/main/java/org/phantazm/core/guild/party/command/PartyCreateCommand.java b/core/src/main/java/org/phantazm/core/guild/party/command/PartyCreateCommand.java index 5901a958e..143ec549e 100644 --- a/core/src/main/java/org/phantazm/core/guild/party/command/PartyCreateCommand.java +++ b/core/src/main/java/org/phantazm/core/guild/party/command/PartyCreateCommand.java @@ -15,7 +15,11 @@ public class PartyCreateCommand { - public static Command createCommand(@NotNull Map parties, + private PartyCreateCommand() { + throw new UnsupportedOperationException(); + } + + public static @NotNull Command createCommand(@NotNull Map parties, @NotNull PlayerViewProvider viewProvider, @NotNull PartyCreator partyCreator) { Objects.requireNonNull(parties, "parties"); Objects.requireNonNull(viewProvider, "viewProvider"); diff --git a/core/src/main/java/org/phantazm/core/guild/party/command/PartyInviteCommand.java b/core/src/main/java/org/phantazm/core/guild/party/command/PartyInviteCommand.java index a5ee4fb45..e2dfddc37 100644 --- a/core/src/main/java/org/phantazm/core/guild/party/command/PartyInviteCommand.java +++ b/core/src/main/java/org/phantazm/core/guild/party/command/PartyInviteCommand.java @@ -17,7 +17,11 @@ public class PartyInviteCommand { - public static Command inviteCommand(@NotNull Map parties, + private PartyInviteCommand() { + throw new UnsupportedOperationException(); + } + + public static @NotNull Command inviteCommand(@NotNull Map parties, @NotNull PlayerViewProvider viewProvider) { Objects.requireNonNull(parties, "parties"); Objects.requireNonNull(viewProvider, "viewProvider"); diff --git a/core/src/main/java/org/phantazm/core/guild/party/command/PartyJoinCommand.java b/core/src/main/java/org/phantazm/core/guild/party/command/PartyJoinCommand.java index f2ff90f63..66b321178 100644 --- a/core/src/main/java/org/phantazm/core/guild/party/command/PartyJoinCommand.java +++ b/core/src/main/java/org/phantazm/core/guild/party/command/PartyJoinCommand.java @@ -17,7 +17,11 @@ public class PartyJoinCommand { - public static Command joinCommand(@NotNull Map parties, + private PartyJoinCommand() { + throw new UnsupportedOperationException(); + } + + public static @NotNull Command joinCommand(@NotNull Map parties, @NotNull PlayerViewProvider viewProvider) { Objects.requireNonNull(parties, "parties"); Objects.requireNonNull(viewProvider, "viewProvider"); diff --git a/core/src/main/java/org/phantazm/core/guild/party/command/PartyKickCommand.java b/core/src/main/java/org/phantazm/core/guild/party/command/PartyKickCommand.java index b4546d54f..1a2655ce8 100644 --- a/core/src/main/java/org/phantazm/core/guild/party/command/PartyKickCommand.java +++ b/core/src/main/java/org/phantazm/core/guild/party/command/PartyKickCommand.java @@ -19,7 +19,11 @@ public class PartyKickCommand { - public static Command kickCommand(@NotNull Map parties, + private PartyKickCommand() { + throw new UnsupportedOperationException(); + } + + public static @NotNull Command kickCommand(@NotNull Map parties, @NotNull PlayerViewProvider viewProvider) { Objects.requireNonNull(parties, "parties"); Objects.requireNonNull(viewProvider, "viewProvider"); diff --git a/core/src/main/java/org/phantazm/core/guild/party/command/PartyLeaveCommand.java b/core/src/main/java/org/phantazm/core/guild/party/command/PartyLeaveCommand.java index db0ac0727..6f0083a64 100644 --- a/core/src/main/java/org/phantazm/core/guild/party/command/PartyLeaveCommand.java +++ b/core/src/main/java/org/phantazm/core/guild/party/command/PartyLeaveCommand.java @@ -12,7 +12,11 @@ public class PartyLeaveCommand { - public static Command leaveCommand(@NotNull Map parties, @NotNull Random random) { + private PartyLeaveCommand() { + throw new UnsupportedOperationException(); + } + + public static @NotNull Command leaveCommand(@NotNull Map parties, @NotNull Random random) { Objects.requireNonNull(parties, "parties"); Objects.requireNonNull(random, "random"); diff --git a/core/src/main/java/org/phantazm/core/guild/party/command/PartyListCommand.java b/core/src/main/java/org/phantazm/core/guild/party/command/PartyListCommand.java new file mode 100644 index 000000000..b1c7c56ed --- /dev/null +++ b/core/src/main/java/org/phantazm/core/guild/party/command/PartyListCommand.java @@ -0,0 +1,77 @@ +package org.phantazm.core.guild.party.command; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.JoinConfiguration; +import net.kyori.adventure.text.format.NamedTextColor; +import net.minestom.server.command.builder.Command; +import net.minestom.server.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.phantazm.core.guild.party.Party; +import org.phantazm.core.guild.party.PartyMember; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; +import java.util.concurrent.CompletableFuture; + +public class PartyListCommand { + + private static final Logger LOGGER = LoggerFactory.getLogger(PartyListCommand.class); + + private static final CompletableFuture[] EMPTY_COMPLETABLE_FUTURE_ARRAY = new CompletableFuture[0]; + + private PartyListCommand() { + throw new UnsupportedOperationException(); + } + + public static @NotNull Command listCommand(@NotNull Map parties) { + Objects.requireNonNull(parties, "parties"); + + Command command = new Command("list"); + command.addConditionalSyntax((sender, commandString) -> { + if (commandString == null) { + return sender instanceof Player; + } + + if (!(sender instanceof Player player)) { + sender.sendMessage(Component.text("You have to be a player to use that command!", NamedTextColor.RED)); + return false; + } + + Party party = parties.get(player.getUuid()); + if (party == null) { + sender.sendMessage(Component.text("You have to be in a party!", NamedTextColor.RED)); + return false; + } + + return true; + }, (sender, context) -> { + Party party = parties.get(((Player)sender).getUuid()); + List> displayNameFutures = + new ArrayList<>(party.getMemberManager().getMembers().size()); + for (PartyMember member : party.getMemberManager().getMembers().values()) { + displayNameFutures.add(member.getPlayerView().getDisplayName()); + } + + CompletableFuture.allOf(displayNameFutures.toArray(EMPTY_COMPLETABLE_FUTURE_ARRAY)) + .whenComplete((ignored, throwable) -> { + if (throwable != null) { + LOGGER.warn("Exception while sending list message", throwable); + return; + } + + List displayNames = new ArrayList<>(displayNameFutures.size()); + for (CompletableFuture future : displayNameFutures) { + displayNames.add(future.join()); + } + + sender.sendMessage( + Component.join(JoinConfiguration.separator(Component.text(", ")), displayNames)); + }); + }); + + return command; + } + +} diff --git a/core/src/test/java/org/phantazm/core/guild/party/command/PartyCreateCommandIntegrationTest.java b/core/src/test/java/org/phantazm/core/guild/party/command/PartyCreateCommandIntegrationTest.java index 32ef9b284..4f4133d2e 100644 --- a/core/src/test/java/org/phantazm/core/guild/party/command/PartyCreateCommandIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/guild/party/command/PartyCreateCommandIntegrationTest.java @@ -23,7 +23,7 @@ public class PartyCreateCommandIntegrationTest extends AbstractPartyCommandInteg public void testCreateCreatesParty(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player player = env.createPlayer(instance, Pos.ZERO); diff --git a/core/src/test/java/org/phantazm/core/guild/party/command/PartyInviteCommandIntegrationTest.java b/core/src/test/java/org/phantazm/core/guild/party/command/PartyInviteCommandIntegrationTest.java index b390236e8..bbf75952b 100644 --- a/core/src/test/java/org/phantazm/core/guild/party/command/PartyInviteCommandIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/guild/party/command/PartyInviteCommandIntegrationTest.java @@ -25,7 +25,7 @@ public class PartyInviteCommandIntegrationTest extends AbstractPartyCommandInteg public void testCanInviteWithInvitePermission(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -45,7 +45,7 @@ public void testCanInviteWithInvitePermission(Env env) { public void testCanInviteOtherPlayerInPartyWithInvitePermission(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -66,7 +66,7 @@ public void testCanInviteOtherPlayerInPartyWithInvitePermission(Env env) { public void testCannotInviteWithoutInvitePermission(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 2); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -86,7 +86,7 @@ public void testCannotInviteWithoutInvitePermission(Env env) { public void testCannotInviteSelf(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player player = env.createPlayer(instance, Pos.ZERO); diff --git a/core/src/test/java/org/phantazm/core/guild/party/command/PartyJoinCommandIntegrationTest.java b/core/src/test/java/org/phantazm/core/guild/party/command/PartyJoinCommandIntegrationTest.java index 7afbe6c31..6b90ab592 100644 --- a/core/src/test/java/org/phantazm/core/guild/party/command/PartyJoinCommandIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/guild/party/command/PartyJoinCommandIntegrationTest.java @@ -24,7 +24,7 @@ public class PartyJoinCommandIntegrationTest extends AbstractPartyCommandIntegra public void testNotInPartyAfterJoiningOtherPlayerNotInParty(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -43,7 +43,7 @@ public void testNotInPartyAfterJoiningOtherPlayerNotInParty(Env env) { public void testNotInPartyWithoutInviteAndJoiningOtherPlayerInParty(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -64,7 +64,7 @@ public void testNotInPartyWithoutInviteAndJoiningOtherPlayerInParty(Env env) { public void testInPartyAfterInviteAndJoiningOtherPlayerInParty(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); diff --git a/core/src/test/java/org/phantazm/core/guild/party/command/PartyKickCommandIntegrationTest.java b/core/src/test/java/org/phantazm/core/guild/party/command/PartyKickCommandIntegrationTest.java index 73415934d..98b28a252 100644 --- a/core/src/test/java/org/phantazm/core/guild/party/command/PartyKickCommandIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/guild/party/command/PartyKickCommandIntegrationTest.java @@ -22,7 +22,7 @@ public class PartyKickCommandIntegrationTest extends AbstractPartyCommandIntegra public void testCanKickWithSufficientRankAndGreaterRankThanTarget(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -45,7 +45,7 @@ public void testCanKickWithSufficientRankAndGreaterRankThanTarget(Env env) { public void testCannotKickWithoutSufficientRankAndGreaterRankThanTarget(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 2, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -68,7 +68,7 @@ public void testCannotKickWithoutSufficientRankAndGreaterRankThanTarget(Env env) public void testCannotKickWithSufficientRankAndEqualRankToTarget(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 2, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); @@ -92,7 +92,7 @@ public void testCannotKickWithSufficientRankAndEqualRankToTarget(Env env) { public void testCannotKickSelf(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 2, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player player = env.createPlayer(instance, Pos.ZERO); diff --git a/core/src/test/java/org/phantazm/core/guild/party/command/PartyLeaveCommandIntegrationTest.java b/core/src/test/java/org/phantazm/core/guild/party/command/PartyLeaveCommandIntegrationTest.java index 537d4bccd..597b12fee 100644 --- a/core/src/test/java/org/phantazm/core/guild/party/command/PartyLeaveCommandIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/guild/party/command/PartyLeaveCommandIntegrationTest.java @@ -24,7 +24,7 @@ public class PartyLeaveCommandIntegrationTest extends AbstractPartyCommandIntegr public void testNotInPartyAfterLeavingAndOwnerIsNullNoOtherMembers(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player player = env.createPlayer(instance, Pos.ZERO); @@ -43,7 +43,7 @@ public void testNotInPartyAfterLeavingAndOwnerIsNullNoOtherMembers(Env env) { public void testOwnerIsNotNullAfterLeavingWithOtherMembers(Env env) { PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command command = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); env.process().command().register(command); Instance instance = env.createFlatInstance(); Player firstPlayer = env.createPlayer(instance, Pos.ZERO); diff --git a/server/src/main/java/org/phantazm/server/PartyFeature.java b/server/src/main/java/org/phantazm/server/PartyFeature.java index 717ee04ef..3089066af 100644 --- a/server/src/main/java/org/phantazm/server/PartyFeature.java +++ b/server/src/main/java/org/phantazm/server/PartyFeature.java @@ -22,7 +22,7 @@ public class PartyFeature { public static void initialize(@NotNull CommandManager commandManager, @NotNull PlayerViewProvider viewProvider, @NotNull SchedulerManager schedulerManager) { PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); - Command partyCommand = PartyCommand.command(parties, viewProvider, partyCreator, new Random()); + Command partyCommand = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); commandManager.register(partyCommand); schedulerManager.scheduleTask(() -> { diff --git a/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java b/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java index da6a158c8..0fdb23523 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java +++ b/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java @@ -169,8 +169,8 @@ public void end() { continue; } - zombiesPlayer.sendMessage(Component.text("==========================================", - Style.style(NamedTextColor.GREEN, TextDecoration.STRIKETHROUGH))); + zombiesPlayer.sendMessage(Component.text("==========================================", NamedTextColor.GREEN, + TextDecoration.STRIKETHROUGH)); zombiesPlayer.sendMessage( Component.text("Zombies", NamedTextColor.YELLOW).append(Component.text(" - ", NamedTextColor.WHITE)) @@ -190,7 +190,7 @@ public void end() { zombiesPlayer.sendMessage(Component.empty()); zombiesPlayer.sendMessage(Component.text("==========================================", - Style.style(NamedTextColor.GREEN, TextDecoration.STRIKETHROUGH))); + NamedTextColor.GREEN, TextDecoration.STRIKETHROUGH)); } for (SidebarUpdater sidebarUpdater : sidebarUpdaters.values()) { From ea052821e68bd6a8344437cfe02dac27739d6844 Mon Sep 17 00:00:00 2001 From: steank Date: Wed, 14 Jun 2023 08:02:33 -0700 Subject: [PATCH 009/181] move TickTaskScheduler to ZombiesScene, include cleanup method to remove effects from players upon termination, also clear bombed area debuff when ending the effect --- .../commons/BasicTickTaskScheduler.java | 9 +++++++ .../phantazm/commons/TickTaskScheduler.java | 2 ++ .../org/phantazm/commons/TickableTask.java | 4 +++ .../org/phantazm/zombies/map/ZombiesMap.java | 1 - .../map/action/round/SelectBombedRoom.java | 25 +++++++++++++++++++ .../zombies/map/objects/BasicMapObjects.java | 10 ++------ .../map/objects/BasicMapObjectsSource.java | 6 +++-- .../zombies/map/objects/MapObjects.java | 6 ++--- .../phantazm/zombies/scene/ZombiesScene.java | 8 +++++- .../zombies/scene/ZombiesSceneProvider.java | 11 +++++--- 10 files changed, 63 insertions(+), 19 deletions(-) diff --git a/commons/src/main/java/org/phantazm/commons/BasicTickTaskScheduler.java b/commons/src/main/java/org/phantazm/commons/BasicTickTaskScheduler.java index a5391917a..482488453 100644 --- a/commons/src/main/java/org/phantazm/commons/BasicTickTaskScheduler.java +++ b/commons/src/main/java/org/phantazm/commons/BasicTickTaskScheduler.java @@ -41,6 +41,15 @@ public void tick(long time) { }); } + @Override + public void end() { + for (TickableTask tickableTask : tickableTasks) { + tickableTask.end(); + } + + tickableTasks.clear(); + } + @Override public void tick(long time) { Iterator taskIterator = tickableTasks.iterator(); diff --git a/commons/src/main/java/org/phantazm/commons/TickTaskScheduler.java b/commons/src/main/java/org/phantazm/commons/TickTaskScheduler.java index c95128394..a045332f5 100644 --- a/commons/src/main/java/org/phantazm/commons/TickTaskScheduler.java +++ b/commons/src/main/java/org/phantazm/commons/TickTaskScheduler.java @@ -6,4 +6,6 @@ public interface TickTaskScheduler extends Tickable { void scheduleTaskNow(@NotNull TickableTask tickableTask); void scheduleTaskAfter(@NotNull TickableTask tickableTask, long millis); + + void end(); } diff --git a/commons/src/main/java/org/phantazm/commons/TickableTask.java b/commons/src/main/java/org/phantazm/commons/TickableTask.java index 949b5f8bb..419265ab4 100644 --- a/commons/src/main/java/org/phantazm/commons/TickableTask.java +++ b/commons/src/main/java/org/phantazm/commons/TickableTask.java @@ -2,4 +2,8 @@ public interface TickableTask extends Tickable { boolean isFinished(); + + default void end() { + + } } diff --git a/zombies/src/main/java/org/phantazm/zombies/map/ZombiesMap.java b/zombies/src/main/java/org/phantazm/zombies/map/ZombiesMap.java index f69be2d19..db51fbbac 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/ZombiesMap.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/ZombiesMap.java @@ -67,7 +67,6 @@ public ZombiesMap(@NotNull MapObjects mapObjects, @NotNull SongPlayer songPlayer @Override public void tick(long time) { - mapObjects.tick(time); songPlayer.tick(time); powerupHandler.tick(time); roundHandler.tick(time); diff --git a/zombies/src/main/java/org/phantazm/zombies/map/action/round/SelectBombedRoom.java b/zombies/src/main/java/org/phantazm/zombies/map/action/round/SelectBombedRoom.java index 15e1f40be..88f7a17c1 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/action/round/SelectBombedRoom.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/action/round/SelectBombedRoom.java @@ -95,6 +95,15 @@ public boolean isFinished() { return finished; } + @Override + public void end() { + for (ZombiesPlayer zombiesPlayer : playerMap.values()) { + zombiesPlayer.getPlayer().ifPresent(player -> { + removeModifiers(player); + }); + } + } + @Override public void tick(long time) { if (!flagSet) { @@ -108,6 +117,22 @@ public void tick(long time) { room.flags().clearFlag(Flags.BOMBED_ROOM); flagSet = false; finished = true; + + for (ZombiesPlayer zombiesPlayer : playerMap.values()) { + zombiesPlayer.getPlayer().ifPresent(player -> { + Optional roomOptional = objects.roomTracker().atPoint(player.getPosition()); + if (roomOptional.isPresent()) { + Room currentRoom = roomOptional.get(); + if (!currentRoom.flags().hasFlag(Flags.BOMBED_ROOM)) { + removeModifiers(player); + } + } + else { + removeModifiers(player); + } + }); + } + return; } diff --git a/zombies/src/main/java/org/phantazm/zombies/map/objects/BasicMapObjects.java b/zombies/src/main/java/org/phantazm/zombies/map/objects/BasicMapObjects.java index ecb4bd136..eb6233145 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/objects/BasicMapObjects.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/objects/BasicMapObjects.java @@ -5,7 +5,6 @@ import net.minestom.server.coordinate.Point; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; -import org.phantazm.commons.BasicTickTaskScheduler; import org.phantazm.commons.TickTaskScheduler; import org.phantazm.core.tracker.BoundedTracker; import org.phantazm.mob.spawner.MobSpawner; @@ -36,7 +35,7 @@ public BasicMapObjects(@NotNull List spawnpoints, @NotNull BoundedTr @NotNull BoundedTracker shops, @NotNull BoundedTracker doors, @NotNull BoundedTracker rooms, @NotNull List rounds, @NotNull DependencyProvider mapDependencyProvider, @NotNull MobSpawner mobSpawner, @NotNull Point mapOrigin, - @NotNull Module module) { + @NotNull Module module, @NotNull TickTaskScheduler taskScheduler) { this.spawnpoints = List.copyOf(spawnpoints); this.rounds = List.copyOf(rounds); @@ -57,7 +56,7 @@ public BasicMapObjects(@NotNull List spawnpoints, @NotNull BoundedTr this.roomMap = Map.copyOf(map); this.mapOrigin = mapOrigin; - this.taskScheduler = new BasicTickTaskScheduler(); + this.taskScheduler = Objects.requireNonNull(taskScheduler, "taskScheduler"); } @Override @@ -119,9 +118,4 @@ public BasicMapObjects(@NotNull List spawnpoints, @NotNull BoundedTr public @NotNull TickTaskScheduler taskScheduler() { return taskScheduler; } - - @Override - public void tick(long time) { - taskScheduler.tick(time); - } } diff --git a/zombies/src/main/java/org/phantazm/zombies/map/objects/BasicMapObjectsSource.java b/zombies/src/main/java/org/phantazm/zombies/map/objects/BasicMapObjectsSource.java index b876609bd..6005c6d26 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/objects/BasicMapObjectsSource.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/objects/BasicMapObjectsSource.java @@ -19,6 +19,7 @@ import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; import org.jetbrains.annotations.NotNull; +import org.phantazm.commons.TickTaskScheduler; import org.phantazm.core.ClientBlockHandler; import org.phantazm.core.ClientBlockHandlerSource; import org.phantazm.core.ElementUtils; @@ -80,7 +81,8 @@ public BasicMapObjectsSource(@NotNull MapInfo mapInfo, @NotNull ContextManager c @NotNull Map playerMap, @NotNull Supplier roundHandlerSupplier, @NotNull MobStore mobStore, @NotNull Wrapper powerupHandler, @NotNull Wrapper windowHandler, - @NotNull Wrapper> eventNode, @NotNull SongPlayer songPlayer) { + @NotNull Wrapper> eventNode, @NotNull SongPlayer songPlayer, + @NotNull TickTaskScheduler tickTaskScheduler) { Random random = new Random(); ClientBlockHandler clientBlockHandler = clientBlockHandlerSource.forInstance(instance); SpawnDistributor spawnDistributor = new BasicSpawnDistributor(mobModels::get, random, playerMap.values()); @@ -129,7 +131,7 @@ public BasicMapObjectsSource(@NotNull MapInfo mapInfo, @NotNull ContextManager c MapObjects mapObjects = new BasicMapObjects(spawnpoints, windowTracker, shopTracker, doorTracker, roomTracker, rounds, provider, - mobSpawner, origin, module); + mobSpawner, origin, module, tickTaskScheduler); mapObjectsWrapper.set(mapObjects); return mapObjects; diff --git a/zombies/src/main/java/org/phantazm/zombies/map/objects/MapObjects.java b/zombies/src/main/java/org/phantazm/zombies/map/objects/MapObjects.java index b97f195be..fe6568c94 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/objects/MapObjects.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/objects/MapObjects.java @@ -12,7 +12,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; import org.phantazm.commons.TickTaskScheduler; -import org.phantazm.commons.Tickable; import org.phantazm.core.gui.SlotDistributor; import org.phantazm.core.sound.SongPlayer; import org.phantazm.core.tracker.BoundedTracker; @@ -29,7 +28,7 @@ import java.util.*; import java.util.function.Supplier; -public interface MapObjects extends Tickable { +public interface MapObjects { @Unmodifiable @NotNull List spawnpoints(); @Unmodifiable @NotNull List rounds(); @@ -59,7 +58,8 @@ public interface MapObjects extends Tickable { @NotNull Map playerMap, @NotNull Supplier roundHandlerSupplier, @NotNull MobStore mobStore, @NotNull Wrapper powerupHandler, @NotNull Wrapper windowHandler, - @NotNull Wrapper> eventNode, @NotNull SongPlayer songPlayer); + @NotNull Wrapper> eventNode, @NotNull SongPlayer songPlayer, + @NotNull TickTaskScheduler tickTaskScheduler); } interface Module { diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java index 77eb1fd0f..b5100bb88 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java @@ -12,6 +12,7 @@ import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.network.player.PlayerSocketConnection; import org.jetbrains.annotations.NotNull; +import org.phantazm.commons.TickTaskScheduler; import org.phantazm.core.game.scene.InstanceScene; import org.phantazm.core.game.scene.RouteResult; import org.phantazm.core.game.scene.fallback.SceneFallback; @@ -42,6 +43,7 @@ public class ZombiesScene extends InstanceScene { private final StageTransition stageTransition; private final LeaveHandler leaveHandler; private final Function playerCreator; + private final TickTaskScheduler taskScheduler; private boolean joinable = true; @@ -49,7 +51,8 @@ public ZombiesScene(@NotNull UUID uuid, @NotNull ConnectionManager connectionMan @NotNull Map players, @NotNull Map zombiesPlayers, @NotNull Instance instance, @NotNull SceneFallback fallback, @NotNull MapSettingsInfo mapSettingsInfo, @NotNull StageTransition stageTransition, @NotNull LeaveHandler leaveHandler, - @NotNull Function playerCreator) { + @NotNull Function playerCreator, + @NotNull TickTaskScheduler taskScheduler) { super(instance, players, fallback); this.uuid = Objects.requireNonNull(uuid, "uuid"); this.connectionManager = Objects.requireNonNull(connectionManager, "connectionManager"); @@ -59,6 +62,7 @@ public ZombiesScene(@NotNull UUID uuid, @NotNull ConnectionManager connectionMan this.stageTransition = Objects.requireNonNull(stageTransition, "stageTransition"); this.leaveHandler = Objects.requireNonNull(leaveHandler, "leaveHandler"); this.playerCreator = Objects.requireNonNull(playerCreator, "playerCreator"); + this.taskScheduler = Objects.requireNonNull(taskScheduler, "taskScheduler"); } public @NotNull Map getZombiesPlayers() { @@ -256,6 +260,7 @@ public int getJoinWeight(@NotNull ZombiesJoinRequest request) { @Override public void shutdown() { + taskScheduler.end(); for (ZombiesPlayer zombiesPlayer : zombiesPlayers.values()) { zombiesPlayer.end(); } @@ -272,6 +277,7 @@ public void tick(long time) { map.tick(time); stageTransition.tick(time); + taskScheduler.tick(time); for (ZombiesPlayer zombiesPlayer : zombiesPlayers.values()) { zombiesPlayer.tick(time); } diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java index 4d6911298..7365520b1 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java @@ -23,6 +23,8 @@ import net.minestom.server.instance.InstanceManager; import net.minestom.server.network.ConnectionManager; import org.jetbrains.annotations.NotNull; +import org.phantazm.commons.BasicTickTaskScheduler; +import org.phantazm.commons.TickTaskScheduler; import org.phantazm.core.ClientBlockHandlerSource; import org.phantazm.core.VecUtils; import org.phantazm.core.game.scene.SceneProviderAbstract; @@ -154,6 +156,7 @@ public ZombiesSceneProvider(int maximumScenes, Map zombiesPlayers = new LinkedHashMap<>(settings.maxPlayers()); MobStore mobStore = new MobStore(); + TickTaskScheduler tickTaskScheduler = new BasicTickTaskScheduler(); Wrapper roundHandlerWrapper = Wrapper.ofNull(); Wrapper powerupHandlerWrapper = Wrapper.ofNull(); @@ -163,7 +166,7 @@ public ZombiesSceneProvider(int maximumScenes, SongPlayer songPlayer = new BasicSongPlayer(); MapObjects mapObjects = createMapObjects(instance, zombiesPlayers, roundHandlerWrapper, mobStore, powerupHandlerWrapper, - windowHandlerWrapper, eventNodeWrapper, songPlayer); + windowHandlerWrapper, eventNodeWrapper, songPlayer, tickTaskScheduler); RoundHandler roundHandler = new BasicRoundHandler(mapObjects.rounds()); roundHandlerWrapper.set(roundHandler); @@ -214,7 +217,7 @@ public ZombiesSceneProvider(int maximumScenes, ZombiesScene scene = new ZombiesScene(UUID.randomUUID(), connectionManager, map, players, zombiesPlayers, instance, - sceneFallback, settings, stageTransition, leaveHandler, playerCreator); + sceneFallback, settings, stageTransition, leaveHandler, playerCreator, tickTaskScheduler); sceneWrapper.set(scene); eventNode.addChild(childNode); @@ -245,9 +248,9 @@ protected void cleanupScene(@NotNull ZombiesScene scene) { private MapObjects createMapObjects(Instance instance, Map zombiesPlayers, Supplier roundHandlerSupplier, MobStore mobStore, Wrapper powerupHandler, Wrapper windowHandler, - Wrapper> eventNode, SongPlayer songPlayer) { + Wrapper> eventNode, SongPlayer songPlayer, TickTaskScheduler tickTaskScheduler) { return mapObjectSource.make(instance, zombiesPlayers, roundHandlerSupplier, mobStore, powerupHandler, - windowHandler, eventNode, songPlayer); + windowHandler, eventNode, songPlayer, tickTaskScheduler); } private PowerupHandler createPowerupHandler(Instance instance, Map playerMap, From cfc6c486afa8c7109321e3d1dfc76442fd479d1c Mon Sep 17 00:00:00 2001 From: steank Date: Wed, 14 Jun 2023 08:10:27 -0700 Subject: [PATCH 010/181] remove instanceloader from ZombiesSceneProvider.java as it was unused --- .../java/org/phantazm/server/ZombiesFeature.java | 13 ++++++------- .../zombies/scene/ZombiesSceneProvider.java | 14 +++++--------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/server/src/main/java/org/phantazm/server/ZombiesFeature.java b/server/src/main/java/org/phantazm/server/ZombiesFeature.java index d6d22847b..6ed173d9c 100644 --- a/server/src/main/java/org/phantazm/server/ZombiesFeature.java +++ b/server/src/main/java/org/phantazm/server/ZombiesFeature.java @@ -140,13 +140,12 @@ static void initialize(@NotNull EventNode globalEventNode, @NotNull Conte for (Map.Entry entry : maps.entrySet()) { ZombiesSceneProvider provider = new ZombiesSceneProvider(2, instanceSpaceFunction, entry.getValue(), connectionManager, - MinecraftServer.getInstanceManager(), instanceLoader, sceneFallback, globalEventNode, - ZombiesFeature.mobSpawnerSource(), Mob.getModels(), - new BasicClientBlockHandlerSource(instance -> { - DimensionType dimensionType = instance.getDimensionType(); - return new InstanceClientBlockHandler(instance, globalEventNode, - dimensionType.getMinY(), dimensionType.getHeight()); - }), contextManager, keyParser, ZombiesFeature.powerups(), + instanceLoader, sceneFallback, globalEventNode, ZombiesFeature.mobSpawnerSource(), + Mob.getModels(), new BasicClientBlockHandlerSource(instance -> { + DimensionType dimensionType = instance.getDimensionType(); + return new InstanceClientBlockHandler(instance, globalEventNode, dimensionType.getMinY(), + dimensionType.getHeight()); + }), contextManager, keyParser, ZombiesFeature.powerups(), new BasicZombiesPlayerSource(EquipmentFeature::createEquipmentCreator, corpseTeam, Mob.getModels())); providers.put(entry.getKey(), provider); diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java index 7365520b1..3dce6a523 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java @@ -20,7 +20,6 @@ import net.minestom.server.event.item.ItemDropEvent; import net.minestom.server.event.player.*; import net.minestom.server.instance.Instance; -import net.minestom.server.instance.InstanceManager; import net.minestom.server.network.ConnectionManager; import org.jetbrains.annotations.NotNull; import org.phantazm.commons.BasicTickTaskScheduler; @@ -69,7 +68,6 @@ public class ZombiesSceneProvider extends SceneProviderAbstract contexts; private final MapInfo mapInfo; private final ConnectionManager connectionManager; - private final InstanceManager instanceManager; private final InstanceLoader instanceLoader; private final SceneFallback sceneFallback; private final EventNode eventNode; @@ -86,18 +84,16 @@ public class ZombiesSceneProvider extends SceneProviderAbstract instanceSpaceFunction, @NotNull MapInfo mapInfo, @NotNull ConnectionManager connectionManager, - @NotNull InstanceManager instanceManager, @NotNull InstanceLoader instanceLoader, - @NotNull SceneFallback sceneFallback, @NotNull EventNode eventNode, - @NotNull MobSpawnerSource mobSpawnerSource, @NotNull Map mobModels, - @NotNull ClientBlockHandlerSource clientBlockHandlerSource, @NotNull ContextManager contextManager, - @NotNull KeyParser keyParser, @NotNull Map powerups, - @NotNull ZombiesPlayer.Source zombiesPlayerSource) { + @NotNull InstanceLoader instanceLoader, @NotNull SceneFallback sceneFallback, + @NotNull EventNode eventNode, @NotNull MobSpawnerSource mobSpawnerSource, + @NotNull Map mobModels, @NotNull ClientBlockHandlerSource clientBlockHandlerSource, + @NotNull ContextManager contextManager, @NotNull KeyParser keyParser, + @NotNull Map powerups, @NotNull ZombiesPlayer.Source zombiesPlayerSource) { super(maximumScenes); this.instanceSpaceFunction = Objects.requireNonNull(instanceSpaceFunction, "instanceSpaceFunction"); this.contexts = new IdentityHashMap<>(maximumScenes); this.mapInfo = Objects.requireNonNull(mapInfo, "mapInfo"); this.connectionManager = Objects.requireNonNull(connectionManager, "connectionManager"); - this.instanceManager = Objects.requireNonNull(instanceManager, "instanceManager"); this.instanceLoader = Objects.requireNonNull(instanceLoader, "instanceLoader"); this.sceneFallback = Objects.requireNonNull(sceneFallback, "sceneFallback"); this.eventNode = Objects.requireNonNull(eventNode, "eventNode"); From f80b677f5512667543de374bb3abe960b9d246bd Mon Sep 17 00:00:00 2001 From: steank Date: Wed, 14 Jun 2023 20:43:58 -0700 Subject: [PATCH 011/181] make sure we properly lie to the client about instance chunks --- .../core/InstanceClientBlockHandler.java | 143 ++++++++++++------ .../map/action/round/SelectBombedRoom.java | 19 ++- 2 files changed, 106 insertions(+), 56 deletions(-) diff --git a/core/src/main/java/org/phantazm/core/InstanceClientBlockHandler.java b/core/src/main/java/org/phantazm/core/InstanceClientBlockHandler.java index 4f9f28551..fde8cc9d0 100644 --- a/core/src/main/java/org/phantazm/core/InstanceClientBlockHandler.java +++ b/core/src/main/java/org/phantazm/core/InstanceClientBlockHandler.java @@ -9,11 +9,13 @@ import net.minestom.server.event.Event; import net.minestom.server.event.EventFilter; import net.minestom.server.event.EventNode; +import net.minestom.server.event.instance.InstanceChunkUnloadEvent; import net.minestom.server.event.instance.InstanceUnregisterEvent; import net.minestom.server.event.instance.PreBlockChangeEvent; import net.minestom.server.event.player.PlayerBlockBreakEvent; import net.minestom.server.event.player.PlayerChunkLoadEvent; import net.minestom.server.event.player.PrePlayerStartDiggingEvent; +import net.minestom.server.event.player.PreSendChunkEvent; import net.minestom.server.event.trait.InstanceEvent; import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Instance; @@ -25,10 +27,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.lang.ref.Reference; -import java.lang.ref.WeakReference; import java.util.Iterator; import java.util.Objects; +import java.util.UUID; /** * Supports instance-wide client blocks. @@ -38,8 +39,9 @@ public class InstanceClientBlockHandler implements ClientBlockHandler { private static final Logger LOGGER = LoggerFactory.getLogger(InstanceClientBlockHandler.class); - private final Reference instance; - private final Long2ObjectMap> clientBlocks; + private Instance instance; + + private final Long2ObjectMap clientBlocks; private final int chunkFloor; private final int chunkHeight; @@ -49,86 +51,91 @@ public class InstanceClientBlockHandler implements ClientBlockHandler { *

Constructs a new instance of this class bound to the provided {@link Instance}. This will add a few necessary * listeners to the given {@link EventNode}.

* - *

The lifetime of this object is free to exceed that of the Instance; no strong reference to it is retained.

- * * @param instance the instance this handler is bound to * @param globalNode the node to add block event listeners to + * @param chunkFloor the minimum y-coordinate of chunks in this instance */ public InstanceClientBlockHandler(@NotNull Instance instance, @NotNull EventNode globalNode, int chunkFloor, int chunkHeight) { //weakref necessary as instance field will be captured by the expiration predicate - this.instance = new WeakReference<>(Objects.requireNonNull(instance, "instance")); + this.instance = Objects.requireNonNull(instance, "instance"); this.clientBlocks = new Long2ObjectOpenHashMap<>(); this.chunkFloor = chunkFloor; this.chunkHeight = chunkHeight; + UUID uuid = instance.getUniqueId(); this.childNode = EventNode.event("instance_client_block_handler{" + instance.getUniqueId() + "}", - EventFilter.from(InstanceEvent.class, Instance.class, InstanceEvent::getInstance), instanceEvent -> { - Instance thisInstance = this.instance.get(); - return thisInstance != null && thisInstance == instanceEvent.getInstance(); - }); + EventFilter.from(InstanceEvent.class, Instance.class, InstanceEvent::getInstance), + instanceEvent -> instanceEvent.getInstance().getUniqueId().equals(uuid)); childNode.addListener(InstanceUnregisterEvent.class, this::onInstanceUnregister); childNode.addListener(PlayerChunkLoadEvent.class, this::onPlayerChunkLoad); childNode.addListener(PreBlockChangeEvent.class, this::onPreBlockChange); childNode.addListener(PlayerBlockBreakEvent.class, this::onPlayerBlockBreak); childNode.addListener(PrePlayerStartDiggingEvent.class, this::onPrePlayerStartDigging); + childNode.addListener(PreSendChunkEvent.class, this::onPreSendChunk); + childNode.addListener(InstanceChunkUnloadEvent.class, this::onChunkUnload); globalNode.addChild(childNode); } @Override public void setClientBlock(@NotNull Block type, int x, int y, int z) { - Instance instance = this.instance.get(); + Instance instance = this.instance; if (instance == null) { return; } - int cx = ChunkUtils.getChunkCoordinate(x); - int cz = ChunkUtils.getChunkCoordinate(z); - long index = ChunkUtils.getChunkIndex(cx, cz); + Chunk serverChunk = instance.getChunkAt(x, z); + if (serverChunk == null) { + return; + } + int cx = serverChunk.getChunkX(); + int cz = serverChunk.getChunkZ(); + + long index = ChunkUtils.getChunkIndex(cx, cz); synchronized (clientBlocks) { - Vec3I2ObjectMap positionedBlocks = clientBlocks.get(index); - if (positionedBlocks == null) { - clientBlocks.put(index, - positionedBlocks = new HashVec3I2ObjectMap<>(0, chunkFloor, 0, 16, chunkHeight, 16)); + Data data = clientBlocks.get(index); + if (data == null) { + data = new Data(new HashVec3I2ObjectMap<>(0, chunkFloor, 0, Chunk.CHUNK_SIZE_X, chunkHeight, + Chunk.CHUNK_SIZE_Z), serverChunk.copy(instance, cx, cz)); + clientBlocks.put(index, data); } - PositionedBlock block = positionedBlocks.get(x, y, z); + PositionedBlock block = data.blocks.get(x, y, z); if (block == null) { - positionedBlocks.put(x, y, z, new PositionedBlock(type, x, y, z)); + data.blocks.put(x, y, z, new PositionedBlock(type, x, y, z)); } else { block.block = type; } - Chunk chunk = instance.getChunk(cx, cz); - if (chunk != null) { - chunk.sendPacketToViewers(new BlockChangePacket(new Vec(x, y, z), type)); - } + data.chunk.setBlock(x, y, z, type); + serverChunk.sendPacketToViewers(new BlockChangePacket(new Vec(x, y, z), type)); } } @Override public void clearClientBlocks() { - Instance instance = this.instance.get(); + Instance instance = this.instance; if (instance == null) { return; } synchronized (clientBlocks) { - for (Long2ObjectMap.Entry> entry : clientBlocks.long2ObjectEntrySet()) { + for (Long2ObjectMap.Entry entry : clientBlocks.long2ObjectEntrySet()) { long index = entry.getLongKey(); int x = ChunkUtils.getChunkCoordX(index); int z = ChunkUtils.getChunkCoordZ(index); - Chunk chunk = instance.getChunkAt(x, z); - Vec3I2ObjectMap blocks = entry.getValue(); - if (chunk != null) { + Chunk serverChunk = instance.getChunkAt(x, z); + Vec3I2ObjectMap blocks = entry.getValue().blocks; + + if (serverChunk != null) { for (PositionedBlock block : blocks.values()) { - Block serverBlock = chunk.getBlock(block.x, block.y, block.z); - chunk.sendPacketToViewers( + Block serverBlock = serverChunk.getBlock(block.x, block.y, block.z); + serverChunk.sendPacketToViewers( new BlockChangePacket(new Vec(block.x, block.y, block.z), serverBlock)); } } @@ -142,7 +149,7 @@ public void clearClientBlocks() { @Override public void removeClientBlock(int x, int y, int z) { - Instance instance = this.instance.get(); + Instance instance = this.instance; if (instance == null) { return; } @@ -151,9 +158,11 @@ public void removeClientBlock(int x, int y, int z) { int cz = ChunkUtils.getChunkCoordinate(z); long index = ChunkUtils.getChunkIndex(cx, cz); synchronized (clientBlocks) { - Vec3I2ObjectMap blocks = clientBlocks.get(index); + Data data = clientBlocks.get(index); + + if (data != null) { + Vec3I2ObjectMap blocks = data.blocks; - if (blocks != null) { if (blocks.remove(x, y, z) != null) { Chunk chunk = instance.getChunk(cx, cz); @@ -162,6 +171,7 @@ public void removeClientBlock(int x, int y, int z) { //make sure player gets the actual block chunk.sendPacketToViewers(new BlockChangePacket(new Vec(x, y, z), serverBlock)); + data.chunk.setBlock(x, y, z, serverBlock); } if (blocks.isEmpty()) { @@ -172,12 +182,38 @@ public void removeClientBlock(int x, int y, int z) { } } - private void onInstanceUnregister(InstanceUnregisterEvent event) { - this.instance.clear(); + private record Data(Vec3I2ObjectMap blocks, Chunk chunk) { + } + + private void onPreSendChunk(PreSendChunkEvent event) { + Chunk chunk = event.chunk(); + + int cx = chunk.getChunkX(); + int cz = chunk.getChunkZ(); + long index = ChunkUtils.getChunkIndex(cx, cz); + synchronized (clientBlocks) { - this.clientBlocks.clear(); + Data data = clientBlocks.get(index); + + if (data != null) { + event.setChunk(data.chunk); + } + } + } + + private void onChunkUnload(InstanceChunkUnloadEvent event) { + Chunk chunk = event.getChunk(); + + int cx = chunk.getChunkX(); + int cz = chunk.getChunkZ(); + long index = ChunkUtils.getChunkIndex(cx, cz); + + synchronized (clientBlocks) { + clientBlocks.remove(index); } + } + private void onInstanceUnregister(InstanceUnregisterEvent event) { EventNode parent = childNode.getParent(); if (parent != null) { parent.removeChild(childNode); @@ -185,17 +221,23 @@ private void onInstanceUnregister(InstanceUnregisterEvent event) { else { LOGGER.warn("Orphaned event node " + childNode.getName()); } + + this.instance = null; + + synchronized (clientBlocks) { + this.clientBlocks.clear(); + } } private void onPrePlayerStartDigging(PrePlayerStartDiggingEvent event) { Point blockPosition = event.getBlockPosition(); long index = ChunkUtils.getChunkIndex(blockPosition); synchronized (clientBlocks) { - Vec3I2ObjectMap blocks = clientBlocks.get(index); + Data data = clientBlocks.get(index); - if (blocks != null) { + if (data != null) { PositionedBlock block = - blocks.get(blockPosition.blockX(), blockPosition.blockY(), blockPosition.blockZ()); + data.blocks.get(blockPosition.blockX(), blockPosition.blockY(), blockPosition.blockZ()); if (block != null) { if (event.getResult().success()) { @@ -212,12 +254,12 @@ private void onPlayerBlockBreak(PlayerBlockBreakEvent event) { Point blockPosition = event.getBlockPosition(); long index = ChunkUtils.getChunkIndex(blockPosition); synchronized (clientBlocks) { - Vec3I2ObjectMap blocks = clientBlocks.get(index); + Data data = clientBlocks.get(index); - if (blocks != null) { + if (data != null) { //remove the client block; no need to send something else as it will be updated soon - if (blocks.remove(blockPosition.blockX(), blockPosition.blockY(), blockPosition.blockZ()) != null && - blocks.isEmpty()) { + if (data.blocks.remove(blockPosition.blockX(), blockPosition.blockY(), blockPosition.blockZ()) != + null && data.blocks.isEmpty()) { clientBlocks.remove(index); } } @@ -228,9 +270,11 @@ private void onPreBlockChange(PreBlockChangeEvent event) { Point blockPosition = event.blockPosition(); long index = ChunkUtils.getChunkIndex(blockPosition); synchronized (clientBlocks) { - Vec3I2ObjectMap blocks = clientBlocks.get(index); + Data data = clientBlocks.get(index); + + if (data != null) { + Vec3I2ObjectMap blocks = data.blocks; - if (blocks != null) { if (blocks.containsKey(blockPosition.blockX(), blockPosition.blockY(), blockPosition.blockZ())) { //allow the server to update the block, but don't tell the client event.setSyncClient(false); @@ -246,9 +290,10 @@ private void onPlayerChunkLoad(PlayerChunkLoadEvent event) { BlockChangePacket[] packets = null; long index = ChunkUtils.getChunkIndex(cx, cz); synchronized (clientBlocks) { - Vec3I2ObjectMap blocks = clientBlocks.get(index); + Data data = clientBlocks.get(index); - if (blocks != null) { + if (data != null) { + Vec3I2ObjectMap blocks = data.blocks; Iterator blockIterator = blocks.values().iterator(); packets = new BlockChangePacket[blocks.size()]; for (int i = 0; i < packets.length; i++) { diff --git a/zombies/src/main/java/org/phantazm/zombies/map/action/round/SelectBombedRoom.java b/zombies/src/main/java/org/phantazm/zombies/map/action/round/SelectBombedRoom.java index 88f7a17c1..4d1d0837c 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/action/round/SelectBombedRoom.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/action/round/SelectBombedRoom.java @@ -120,15 +120,20 @@ public void tick(long time) { for (ZombiesPlayer zombiesPlayer : playerMap.values()) { zombiesPlayer.getPlayer().ifPresent(player -> { - Optional roomOptional = objects.roomTracker().atPoint(player.getPosition()); - if (roomOptional.isPresent()) { - Room currentRoom = roomOptional.get(); - if (!currentRoom.flags().hasFlag(Flags.BOMBED_ROOM)) { - removeModifiers(player); - } + if (!zombiesPlayer.isAlive()) { + removeModifiers(player); } else { - removeModifiers(player); + Optional roomOptional = objects.roomTracker().atPoint(player.getPosition()); + if (roomOptional.isPresent()) { + Room currentRoom = roomOptional.get(); + if (!currentRoom.flags().hasFlag(Flags.BOMBED_ROOM)) { + removeModifiers(player); + } + } + else { + removeModifiers(player); + } } }); } From c1fe89f3d044f567cc14a069a8a93d3c3a5898b1 Mon Sep 17 00:00:00 2001 From: steank Date: Wed, 14 Jun 2023 20:48:15 -0700 Subject: [PATCH 012/181] small fixes --- .../java/org/phantazm/core/InstanceClientBlockHandler.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/phantazm/core/InstanceClientBlockHandler.java b/core/src/main/java/org/phantazm/core/InstanceClientBlockHandler.java index fde8cc9d0..b8debb673 100644 --- a/core/src/main/java/org/phantazm/core/InstanceClientBlockHandler.java +++ b/core/src/main/java/org/phantazm/core/InstanceClientBlockHandler.java @@ -18,6 +18,7 @@ import net.minestom.server.event.player.PreSendChunkEvent; import net.minestom.server.event.trait.InstanceEvent; import net.minestom.server.instance.Chunk; +import net.minestom.server.instance.DynamicChunk; import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; import net.minestom.server.listener.PlayerDiggingListener; @@ -195,8 +196,8 @@ private void onPreSendChunk(PreSendChunkEvent event) { synchronized (clientBlocks) { Data data = clientBlocks.get(index); - if (data != null) { - event.setChunk(data.chunk); + if (data != null && data.chunk instanceof DynamicChunk dynamicChunk) { + event.setChunk(dynamicChunk); } } } From 7cac25c292baa3c890918c395944f9e907b5a817 Mon Sep 17 00:00:00 2001 From: steank Date: Wed, 14 Jun 2023 20:49:53 -0700 Subject: [PATCH 013/181] bump minestom version --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d71c7f486..2ae356e14 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ examination = "1.3.0" junit-jupiter = "5.9.0" -minestom = "a58959067c" +minestom = "4759fb68ad" toolkit = "0.3.0" From e399016644b8af18eb70c194fb2cd2dd30dab8bf Mon Sep 17 00:00:00 2001 From: steank Date: Wed, 14 Jun 2023 22:02:32 -0700 Subject: [PATCH 014/181] bugfix + optimization by caching fake client chunks when possible --- .../core/InstanceClientBlockHandler.java | 167 ++++++++++-------- 1 file changed, 89 insertions(+), 78 deletions(-) diff --git a/core/src/main/java/org/phantazm/core/InstanceClientBlockHandler.java b/core/src/main/java/org/phantazm/core/InstanceClientBlockHandler.java index b8debb673..578961e6d 100644 --- a/core/src/main/java/org/phantazm/core/InstanceClientBlockHandler.java +++ b/core/src/main/java/org/phantazm/core/InstanceClientBlockHandler.java @@ -13,7 +13,6 @@ import net.minestom.server.event.instance.InstanceUnregisterEvent; import net.minestom.server.event.instance.PreBlockChangeEvent; import net.minestom.server.event.player.PlayerBlockBreakEvent; -import net.minestom.server.event.player.PlayerChunkLoadEvent; import net.minestom.server.event.player.PrePlayerStartDiggingEvent; import net.minestom.server.event.player.PreSendChunkEvent; import net.minestom.server.event.trait.InstanceEvent; @@ -28,7 +27,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Iterator; import java.util.Objects; import java.util.UUID; @@ -42,7 +40,8 @@ public class InstanceClientBlockHandler implements ClientBlockHandler { private Instance instance; - private final Long2ObjectMap clientBlocks; + private final Long2ObjectMap clientData; + private final int chunkFloor; private final int chunkHeight; @@ -60,7 +59,7 @@ public InstanceClientBlockHandler(@NotNull Instance instance, @NotNull EventNode int chunkHeight) { //weakref necessary as instance field will be captured by the expiration predicate this.instance = Objects.requireNonNull(instance, "instance"); - this.clientBlocks = new Long2ObjectOpenHashMap<>(); + this.clientData = new Long2ObjectOpenHashMap<>(); this.chunkFloor = chunkFloor; this.chunkHeight = chunkHeight; @@ -70,7 +69,6 @@ public InstanceClientBlockHandler(@NotNull Instance instance, @NotNull EventNode instanceEvent -> instanceEvent.getInstance().getUniqueId().equals(uuid)); childNode.addListener(InstanceUnregisterEvent.class, this::onInstanceUnregister); - childNode.addListener(PlayerChunkLoadEvent.class, this::onPlayerChunkLoad); childNode.addListener(PreBlockChangeEvent.class, this::onPreBlockChange); childNode.addListener(PlayerBlockBreakEvent.class, this::onPlayerBlockBreak); childNode.addListener(PrePlayerStartDiggingEvent.class, this::onPrePlayerStartDigging); @@ -96,12 +94,13 @@ public void setClientBlock(@NotNull Block type, int x, int y, int z) { int cz = serverChunk.getChunkZ(); long index = ChunkUtils.getChunkIndex(cx, cz); - synchronized (clientBlocks) { - Data data = clientBlocks.get(index); + synchronized (clientData) { + Data data = clientData.get(index); + if (data == null) { data = new Data(new HashVec3I2ObjectMap<>(0, chunkFloor, 0, Chunk.CHUNK_SIZE_X, chunkHeight, - Chunk.CHUNK_SIZE_Z), serverChunk.copy(instance, cx, cz)); - clientBlocks.put(index, data); + Chunk.CHUNK_SIZE_Z)); + clientData.put(index, data); } PositionedBlock block = data.blocks.get(x, y, z); @@ -112,11 +111,12 @@ public void setClientBlock(@NotNull Block type, int x, int y, int z) { block.block = type; } - data.chunk.setBlock(x, y, z, type); + data.dirty = true; serverChunk.sendPacketToViewers(new BlockChangePacket(new Vec(x, y, z), type)); } } + @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") @Override public void clearClientBlocks() { Instance instance = this.instance; @@ -124,16 +124,19 @@ public void clearClientBlocks() { return; } - synchronized (clientBlocks) { - for (Long2ObjectMap.Entry entry : clientBlocks.long2ObjectEntrySet()) { + synchronized (clientData) { + for (Long2ObjectMap.Entry entry : clientData.long2ObjectEntrySet()) { long index = entry.getLongKey(); int x = ChunkUtils.getChunkCoordX(index); int z = ChunkUtils.getChunkCoordZ(index); - Chunk serverChunk = instance.getChunkAt(x, z); - Vec3I2ObjectMap blocks = entry.getValue().blocks; + Chunk serverChunk = instance.getChunk(x, z); + if (serverChunk == null) { + continue; + } - if (serverChunk != null) { + Vec3I2ObjectMap blocks = entry.getValue().blocks; + synchronized (serverChunk) { for (PositionedBlock block : blocks.values()) { Block serverBlock = serverChunk.getBlock(block.x, block.y, block.z); serverChunk.sendPacketToViewers( @@ -144,7 +147,7 @@ public void clearClientBlocks() { blocks.clear(); } - clientBlocks.clear(); + clientData.clear(); } } @@ -158,46 +161,81 @@ public void removeClientBlock(int x, int y, int z) { int cx = ChunkUtils.getChunkCoordinate(x); int cz = ChunkUtils.getChunkCoordinate(z); long index = ChunkUtils.getChunkIndex(cx, cz); - synchronized (clientBlocks) { - Data data = clientBlocks.get(index); + synchronized (clientData) { + Data data = clientData.get(index); + if (data == null) { + return; + } - if (data != null) { - Vec3I2ObjectMap blocks = data.blocks; + if (data.blocks.remove(x, y, z) != null) { + Chunk serverChunk = instance.getChunk(cx, cz); - if (blocks.remove(x, y, z) != null) { - Chunk chunk = instance.getChunk(cx, cz); + if (serverChunk == null) { + clientData.remove(index); + return; + } - if (chunk != null) { - Block serverBlock = chunk.getBlock(x, y, z); + Block serverBlock = serverChunk.getBlock(x, y, z); - //make sure player gets the actual block - chunk.sendPacketToViewers(new BlockChangePacket(new Vec(x, y, z), serverBlock)); - data.chunk.setBlock(x, y, z, serverBlock); - } + //make sure player gets the actual block + serverChunk.sendPacketToViewers(new BlockChangePacket(new Vec(x, y, z), serverBlock)); - if (blocks.isEmpty()) { - clientBlocks.remove(index); - } + if (data.blocks.isEmpty()) { + clientData.remove(index); } + + data.dirty = true; } } } - private record Data(Vec3I2ObjectMap blocks, Chunk chunk) { + private static class Data { + private final Vec3I2ObjectMap blocks; + private DynamicChunk chunk; + private boolean dirty; + + public Data(Vec3I2ObjectMap blocks) { + this.blocks = blocks; + } } + @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") private void onPreSendChunk(PreSendChunkEvent event) { - Chunk chunk = event.chunk(); + Instance instance = this.instance; + if (instance == null) { + return; + } - int cx = chunk.getChunkX(); - int cz = chunk.getChunkZ(); + DynamicChunk serverChunk = event.chunk(); + + int cx = serverChunk.getChunkX(); + int cz = serverChunk.getChunkZ(); long index = ChunkUtils.getChunkIndex(cx, cz); - synchronized (clientBlocks) { - Data data = clientBlocks.get(index); + synchronized (clientData) { + Data data = clientData.get(index); + + if (data != null) { + DynamicChunk copy = data.chunk; + + boolean updateCopyBlocks = false; + synchronized (serverChunk) { + if (copy == null || copy.getLastChangeTime() != serverChunk.getLastChangeTime() || data.dirty) { + copy = serverChunk.copy(instance, cx, cz); + data.chunk = copy; + updateCopyBlocks = true; + } + } - if (data != null && data.chunk instanceof DynamicChunk dynamicChunk) { - event.setChunk(dynamicChunk); + if (updateCopyBlocks) { + for (PositionedBlock positionedBlock : data.blocks.values()) { + copy.setBlock(positionedBlock.x, positionedBlock.y, positionedBlock.z, positionedBlock.block); + } + + data.dirty = false; + } + + event.setChunk(copy); } } } @@ -209,8 +247,8 @@ private void onChunkUnload(InstanceChunkUnloadEvent event) { int cz = chunk.getChunkZ(); long index = ChunkUtils.getChunkIndex(cx, cz); - synchronized (clientBlocks) { - clientBlocks.remove(index); + synchronized (clientData) { + clientData.remove(index); } } @@ -225,16 +263,16 @@ private void onInstanceUnregister(InstanceUnregisterEvent event) { this.instance = null; - synchronized (clientBlocks) { - this.clientBlocks.clear(); + synchronized (clientData) { + this.clientData.clear(); } } private void onPrePlayerStartDigging(PrePlayerStartDiggingEvent event) { Point blockPosition = event.getBlockPosition(); long index = ChunkUtils.getChunkIndex(blockPosition); - synchronized (clientBlocks) { - Data data = clientBlocks.get(index); + synchronized (clientData) { + Data data = clientData.get(index); if (data != null) { PositionedBlock block = @@ -254,14 +292,14 @@ private void onPrePlayerStartDigging(PrePlayerStartDiggingEvent event) { private void onPlayerBlockBreak(PlayerBlockBreakEvent event) { Point blockPosition = event.getBlockPosition(); long index = ChunkUtils.getChunkIndex(blockPosition); - synchronized (clientBlocks) { - Data data = clientBlocks.get(index); + synchronized (clientData) { + Data data = clientData.get(index); if (data != null) { //remove the client block; no need to send something else as it will be updated soon if (data.blocks.remove(blockPosition.blockX(), blockPosition.blockY(), blockPosition.blockZ()) != null && data.blocks.isEmpty()) { - clientBlocks.remove(index); + clientData.remove(index); } } } @@ -270,13 +308,11 @@ private void onPlayerBlockBreak(PlayerBlockBreakEvent event) { private void onPreBlockChange(PreBlockChangeEvent event) { Point blockPosition = event.blockPosition(); long index = ChunkUtils.getChunkIndex(blockPosition); - synchronized (clientBlocks) { - Data data = clientBlocks.get(index); + synchronized (clientData) { + Data data = clientData.get(index); if (data != null) { - Vec3I2ObjectMap blocks = data.blocks; - - if (blocks.containsKey(blockPosition.blockX(), blockPosition.blockY(), blockPosition.blockZ())) { + if (data.blocks.containsKey(blockPosition.blockX(), blockPosition.blockY(), blockPosition.blockZ())) { //allow the server to update the block, but don't tell the client event.setSyncClient(false); } @@ -284,31 +320,6 @@ private void onPreBlockChange(PreBlockChangeEvent event) { } } - private void onPlayerChunkLoad(PlayerChunkLoadEvent event) { - int cx = event.getChunkX(); - int cz = event.getChunkZ(); - - BlockChangePacket[] packets = null; - long index = ChunkUtils.getChunkIndex(cx, cz); - synchronized (clientBlocks) { - Data data = clientBlocks.get(index); - - if (data != null) { - Vec3I2ObjectMap blocks = data.blocks; - Iterator blockIterator = blocks.values().iterator(); - packets = new BlockChangePacket[blocks.size()]; - for (int i = 0; i < packets.length; i++) { - PositionedBlock block = blockIterator.next(); - packets[i] = new BlockChangePacket(new Vec(block.x, block.y, block.z), block.block); - } - } - } - - if (packets != null) { - event.getPlayer().sendPackets(packets); - } - } - private static class PositionedBlock { private final int x; private final int y; From 996bdaf516319cb831c0a9cae878b9719be0ff65 Mon Sep 17 00:00:00 2001 From: steank Date: Wed, 14 Jun 2023 22:12:52 -0700 Subject: [PATCH 015/181] instead of hiding boss bars, destroy them --- .../zombies/powerup/action/BossBarTimerAction.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/zombies/src/main/java/org/phantazm/zombies/powerup/action/BossBarTimerAction.java b/zombies/src/main/java/org/phantazm/zombies/powerup/action/BossBarTimerAction.java index 92d75a7fe..c42ce9ef5 100644 --- a/zombies/src/main/java/org/phantazm/zombies/powerup/action/BossBarTimerAction.java +++ b/zombies/src/main/java/org/phantazm/zombies/powerup/action/BossBarTimerAction.java @@ -56,7 +56,8 @@ public boolean shouldDeactivate(long time) { @Override public void tick(long time) { - if (startTime < 0) { + BossBar bossBar = this.bossBar; + if (startTime < 0 || bossBar == null) { return; } @@ -68,14 +69,18 @@ public void tick(long time) { public void activate(@NotNull Powerup powerup, @NotNull ZombiesPlayer player, long time) { this.startTime = System.currentTimeMillis(); - this.bossBar = BossBar.bossBar(data.name, 1.0F, data.color, data.overlay); - instance.showBossBar(this.bossBar); + BossBar bossBar = BossBar.bossBar(data.name, 1.0F, data.color, data.overlay); + instance.showBossBar(bossBar); + + this.bossBar = bossBar; } @Override public void deactivate(@NotNull ZombiesPlayer player) { + BossBar bossBar = this.bossBar; if (bossBar != null) { - instance.hideBossBar(bossBar); + MinecraftServer.getBossBarManager().destroyBossBar(bossBar); + this.bossBar = null; } } From 40ca45bf972bf6fc19412d7bc952c167bd9ad5af Mon Sep 17 00:00:00 2001 From: steank Date: Thu, 15 Jun 2023 13:04:08 -0700 Subject: [PATCH 016/181] improve mob movement a bit by increasing a constant --- .../phantazm/proxima/bindings/minestom/ProximaEntity.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/proxima-minestom/src/main/java/org/phantazm/proxima/bindings/minestom/ProximaEntity.java b/proxima-minestom/src/main/java/org/phantazm/proxima/bindings/minestom/ProximaEntity.java index 046d4099b..d0f0220e0 100644 --- a/proxima-minestom/src/main/java/org/phantazm/proxima/bindings/minestom/ProximaEntity.java +++ b/proxima-minestom/src/main/java/org/phantazm/proxima/bindings/minestom/ProximaEntity.java @@ -29,6 +29,8 @@ * An entity with navigation capabilities based on the Proxima library. */ public class ProximaEntity extends LivingEntity { + private static final double NODE_REACH_DISTANCE = 0.4; + protected final Pathfinding pathfinding; protected final List goalGroups; @@ -258,7 +260,8 @@ protected boolean initPath(@NotNull PathResult pathResult) { protected boolean withinDistance(@NotNull Node node) { Pos position = getPosition(); - return position.distanceSquared(new Vec(node.x + 0.5, node.y + node.blockOffset, node.z + 0.5)) < 0.0625; + return position.distanceSquared(new Vec(node.x + 0.5, node.y + node.blockOffset, node.z + 0.5)) < + NODE_REACH_DISTANCE; } protected boolean moveAlongPath(long time) { From 167fda826fbd4a125ff7a1bf24f7c638319cf7e9 Mon Sep 17 00:00:00 2001 From: steank Date: Thu, 15 Jun 2023 13:08:43 -0700 Subject: [PATCH 017/181] more tweaking of constant values --- .../minestom/controller/GroundController.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/proxima-minestom/src/main/java/org/phantazm/proxima/bindings/minestom/controller/GroundController.java b/proxima-minestom/src/main/java/org/phantazm/proxima/bindings/minestom/controller/GroundController.java index 121d6381f..d95631f77 100644 --- a/proxima-minestom/src/main/java/org/phantazm/proxima/bindings/minestom/controller/GroundController.java +++ b/proxima-minestom/src/main/java/org/phantazm/proxima/bindings/minestom/controller/GroundController.java @@ -24,6 +24,8 @@ import java.util.function.Predicate; public class GroundController implements Controller { + private static final double ENTITY_COLLISION_FACTOR = 10; + private final LivingEntity entity; private final double step; private final TrackerPredicate trackerPredicate; @@ -101,14 +103,12 @@ public boolean test(LivingEntity candidate) { else { double pZ = -vX; if (iterations % 2 == 0) { - candidate.setVelocity( - new Vec(vZ * scaleFactor * MinecraftServer.TICK_PER_SECOND, oldVelocity.y(), - pZ * scaleFactor * MinecraftServer.TICK_PER_SECOND)); + candidate.setVelocity(new Vec(vZ * scaleFactor * ENTITY_COLLISION_FACTOR, oldVelocity.y(), + pZ * scaleFactor * ENTITY_COLLISION_FACTOR)); } else { - candidate.setVelocity( - new Vec(-vZ * scaleFactor * MinecraftServer.TICK_PER_SECOND, oldVelocity.y(), - -pZ * scaleFactor * MinecraftServer.TICK_PER_SECOND)); + candidate.setVelocity(new Vec(-vZ * scaleFactor * ENTITY_COLLISION_FACTOR, oldVelocity.y(), + -pZ * scaleFactor * ENTITY_COLLISION_FACTOR)); } } } From 57b15877db925cfa74ff01064cd707330c6f5cd0 Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Thu, 15 Jun 2023 20:57:59 -0400 Subject: [PATCH 018/181] remove extra leave message fix owner transfer --- .../phantazm/core/guild/party/command/PartyLeaveCommand.java | 3 +-- .../guild/party/command/PartyLeaveCommandIntegrationTest.java | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/phantazm/core/guild/party/command/PartyLeaveCommand.java b/core/src/main/java/org/phantazm/core/guild/party/command/PartyLeaveCommand.java index 6f0083a64..21729c4e4 100644 --- a/core/src/main/java/org/phantazm/core/guild/party/command/PartyLeaveCommand.java +++ b/core/src/main/java/org/phantazm/core/guild/party/command/PartyLeaveCommand.java @@ -44,7 +44,6 @@ private PartyLeaveCommand() { PartyMember oldMember = party.getMemberManager().removeMember(uuid); party.getNotification().notifyLeave(oldMember); - sender.sendMessage(Component.text("Left the party.", NamedTextColor.GREEN)); if (party.getOwner().get().getPlayerView().getUUID().equals(uuid)) { if (party.getMemberManager().getMembers().isEmpty()) { @@ -52,7 +51,7 @@ private PartyLeaveCommand() { } else { int memberIndex = random.nextInt(party.getMemberManager().getMembers().size()); Iterator memberIterator = party.getMemberManager().getMembers().values().iterator(); - PartyMember newOwner = null; + PartyMember newOwner = memberIterator.next(); for (int i = 0; i < memberIndex; ++i) { newOwner = memberIterator.next(); } diff --git a/core/src/test/java/org/phantazm/core/guild/party/command/PartyLeaveCommandIntegrationTest.java b/core/src/test/java/org/phantazm/core/guild/party/command/PartyLeaveCommandIntegrationTest.java index 597b12fee..10abe17f7 100644 --- a/core/src/test/java/org/phantazm/core/guild/party/command/PartyLeaveCommandIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/guild/party/command/PartyLeaveCommandIntegrationTest.java @@ -60,6 +60,7 @@ public void testOwnerIsNotNullAfterLeavingWithOtherMembers(Env env) { assertFalse(parties.containsKey(firstPlayer.getUuid())); assertFalse(party.getMemberManager().hasMember(firstPlayer.getUuid())); assertNotNull(party.getOwner().get()); + assertNotEquals(firstPlayer.getUuid(), party.getOwner().get().getPlayerView().getUUID()); } } From 75b830018f6fcb4de2ebea1eca95064e517c4008 Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Fri, 16 Jun 2023 13:40:28 -0400 Subject: [PATCH 019/181] another attempt at fixing rejoin --- .../PartyCreateCommandIntegrationTest.java | 19 +++++++++ .../phantazm/zombies/scene/ZombiesScene.java | 41 ++++++++++++------- .../zombies/scene/ZombiesSceneRouter.java | 37 +++++++++-------- 3 files changed, 67 insertions(+), 30 deletions(-) diff --git a/core/src/test/java/org/phantazm/core/guild/party/command/PartyCreateCommandIntegrationTest.java b/core/src/test/java/org/phantazm/core/guild/party/command/PartyCreateCommandIntegrationTest.java index 4f4133d2e..335ae5928 100644 --- a/core/src/test/java/org/phantazm/core/guild/party/command/PartyCreateCommandIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/guild/party/command/PartyCreateCommandIntegrationTest.java @@ -7,12 +7,14 @@ import net.minestom.testing.Env; import net.minestom.testing.EnvTest; import org.junit.jupiter.api.Test; +import org.phantazm.core.guild.party.Party; import org.phantazm.core.guild.party.PartyCreator; import org.phantazm.core.player.BasicPlayerViewProvider; import org.phantazm.core.player.PlayerViewProvider; import java.util.Random; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @EnvTest @@ -33,4 +35,21 @@ public void testCreateCreatesParty(Env env) { assertTrue(parties.containsKey(player.getUuid())); } + @SuppressWarnings({"UnstableApiUsage", "JUnitMalformedDeclaration"}) + @Test + public void testCreateDoesNotCreatePartyIfAlreadyInParty(Env env) { + PlayerViewProvider viewProvider = new BasicPlayerViewProvider(identitySource, env.process().connection()); + PartyCreator partyCreator = new PartyCreator(1, 0, 20, 1, 1); + Command command = PartyCommand.partyCommand(parties, viewProvider, partyCreator, new Random()); + env.process().command().register(command); + Instance instance = env.createFlatInstance(); + Player player = env.createPlayer(instance, Pos.ZERO); + env.process().command().execute(player, "party create"); + Party party = parties.get(player.getUuid()); + + env.process().command().execute(player, "party create"); + + assertEquals(party, parties.get(player.getUuid())); + } + } diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java index b5100bb88..effa0d447 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java @@ -100,7 +100,9 @@ public boolean isComplete() { for (PlayerView player : joinRequest.getPlayers()) { ZombiesPlayer zombiesPlayer = zombiesPlayers.get(player.getUUID()); if (zombiesPlayer != null) { - oldPlayers.add(zombiesPlayer); + if (zombiesPlayer.hasQuit()) { + oldPlayers.add(zombiesPlayer); + } } else { newPlayers.add(player); @@ -124,20 +126,33 @@ public boolean isComplete() { return protocolResult; } - for (ZombiesPlayer zombiesPlayer : oldPlayers) { - zombiesPlayer.setState(ZombiesPlayerStateKeys.DEAD, DeadPlayerStateContext.rejoin()); - } - Vec3I spawn = mapSettingsInfo.origin().add(mapSettingsInfo.spawn()); Pos pos = new Pos(spawn.x(), spawn.y(), spawn.z(), mapSettingsInfo.yaw(), mapSettingsInfo.pitch()); - List teleportedViews = new ArrayList<>(newPlayers.size()); - List teleportedPlayers = new ArrayList<>(newPlayers.size()); - List> futures = new ArrayList<>(newPlayers.size()); + List teleportedViews = new ArrayList<>(oldPlayers.size() + newPlayers.size()); + List teleportedPlayers = new ArrayList<>(oldPlayers.size() + newPlayers.size()); + List> futures = new ArrayList<>(oldPlayers.size() + newPlayers.size()); + List runnables = new ArrayList<>(oldPlayers.size() + newPlayers.size()); + for (ZombiesPlayer zombiesPlayer : oldPlayers) { + zombiesPlayer.getPlayer().ifPresent(player -> { + teleportedViews.add(zombiesPlayer.module().getPlayerView()); + teleportedPlayers.add(player); + futures.add(player.setInstance(instance, pos)); + runnables.add(() -> { + zombiesPlayer.setState(ZombiesPlayerStateKeys.DEAD, DeadPlayerStateContext.rejoin()); + }); + }); + } for (PlayerView view : newPlayers) { view.getPlayer().ifPresent(player -> { teleportedViews.add(view); teleportedPlayers.add(player); futures.add(player.setInstance(instance, pos)); + runnables.add(() -> { + ZombiesPlayer zombiesPlayer = playerCreator.apply(view); + zombiesPlayer.start(); + zombiesPlayer.setState(ZombiesPlayerStateKeys.ALIVE, NoContext.INSTANCE); + zombiesPlayers.put(view.getUUID(), zombiesPlayer); + }); }); } @@ -146,6 +161,7 @@ public boolean isComplete() { PlayerView view = teleportedViews.get(i); Player teleportedPlayer = teleportedPlayers.get(i); CompletableFuture future = futures.get(i); + Runnable runnable = runnables.get(i); if (future.isCompletedExceptionally()) { future.whenComplete((ignored1, throwable) -> { @@ -169,13 +185,10 @@ public boolean isComplete() { } } - ZombiesPlayer zombiesPlayer = playerCreator.apply(view); - zombiesPlayer.start(); - zombiesPlayer.setState(ZombiesPlayerStateKeys.ALIVE, NoContext.INSTANCE); - zombiesPlayers.put(view.getUUID(), zombiesPlayer); - players.put(view.getUUID(), view); + runnable.run(); - stage.onJoin(zombiesPlayer); + players.put(view.getUUID(), view); + stage.onJoin(zombiesPlayers.get(teleportedPlayer.getUuid())); } }).join(); diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneRouter.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneRouter.java index d6b1f18de..e8b8c6299 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneRouter.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneRouter.java @@ -96,32 +96,37 @@ private RouteResult joinGame(ZombiesRouteRequest routeRequest) { ZombiesJoinRequest joinRequest = routeRequest.joinRequest(); Optional sceneOptional = sceneProvider.provideScene(joinRequest); - if (sceneOptional.isPresent()) { - ZombiesScene scene = sceneOptional.get(); - RouteResult result = scene.join(joinRequest); - if (result.success()) { - for (PlayerView playerView : routeRequest.joinRequest().getPlayers()) { - ZombiesScene oldScene = playerSceneMap.get(playerView.getUUID()); - if (oldScene != null && oldScene != scene) { - oldScene.leave(Collections.singleton(playerView.getUUID())); - } + if (sceneOptional.isEmpty()) { + return new RouteResult(false, Component.text("No games are joinable.")); + } - playerSceneMap.put(playerView.getUUID(), scene); - } + ZombiesScene scene = sceneOptional.get(); + RouteResult result = scene.join(joinRequest); + if (result.success()) { + for (PlayerView playerView : routeRequest.joinRequest().getPlayers()) { + playerSceneMap.put(playerView.getUUID(), scene); } - - return result; } - return new RouteResult(false, Component.text("No games are joinable.")); + return result; + } // TODO: optimize private RouteResult rejoinGame(ZombiesRouteRequest routeRequest) { for (ZombiesScene scene : getScenes()) { - if (scene.getUuid().equals(routeRequest.targetGame())) { - return scene.join(routeRequest.joinRequest()); + if (!scene.getUuid().equals(routeRequest.targetGame())) { + continue; } + + RouteResult result = scene.join(routeRequest.joinRequest()); + if (result.success()) { + for (PlayerView playerView : routeRequest.joinRequest().getPlayers()) { + playerSceneMap.put(playerView.getUUID(), scene); + } + } + + return result; } return new RouteResult(false, Component.text("Not a valid game.")); From 4d39615785b874bf3de4f716f7c8663b50f3eabf Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Fri, 16 Jun 2023 15:05:27 -0400 Subject: [PATCH 020/181] lots of fixes associated with joining --- .../core/game/scene/InstanceScene.java | 9 +- .../org/phantazm/core/game/scene/Scene.java | 2 + .../phantazm/core/game/scene/SceneRouter.java | 15 +++ .../scene/lobby/BasicLobbyJoinRequest.java | 6 +- .../game/scene/lobby/BasicLobbyProvider.java | 3 +- .../phantazm/core/game/scene/lobby/Lobby.java | 5 +- .../scene/lobby/LobbyProviderAbstract.java | 8 ++ .../core/game/scene/lobby/LobbyRouter.java | 42 ++++++- .../scene/lobby/LobbyIntegrationTest.java | 4 +- .../lobby/LobbyRouterIntegrationTest.java | 7 +- .../java/org/phantazm/server/Lobbies.java | 2 +- .../org/phantazm/server/ZombiesFeature.java | 16 ++- .../zombies/command/ZombiesCommand.java | 17 +-- .../zombies/command/ZombiesJoinCommand.java | 31 ++++- .../zombies/command/ZombiesRejoinCommand.java | 34 +++++- .../phantazm/zombies/scene/LeaveHandler.java | 20 ++-- .../zombies/scene/SceneContainer.java | 11 -- .../zombies/scene/ZombiesJoinRequest.java | 4 + .../phantazm/zombies/scene/ZombiesScene.java | 20 ++-- .../zombies/scene/ZombiesSceneProvider.java | 15 ++- .../zombies/scene/ZombiesSceneRouter.java | 30 ++++- .../zombies/stage/CountdownStage.java | 16 +++ .../org/phantazm/zombies/stage/EndStage.java | 5 + .../org/phantazm/zombies/stage/IdleStage.java | 8 ++ .../phantazm/zombies/stage/InGameStage.java | 5 + .../org/phantazm/zombies/stage/Stage.java | 106 +----------------- 26 files changed, 266 insertions(+), 175 deletions(-) create mode 100644 core/src/main/java/org/phantazm/core/game/scene/SceneRouter.java delete mode 100644 zombies/src/main/java/org/phantazm/zombies/scene/SceneContainer.java diff --git a/core/src/main/java/org/phantazm/core/game/scene/InstanceScene.java b/core/src/main/java/org/phantazm/core/game/scene/InstanceScene.java index 27fe7b898..3514d868d 100644 --- a/core/src/main/java/org/phantazm/core/game/scene/InstanceScene.java +++ b/core/src/main/java/org/phantazm/core/game/scene/InstanceScene.java @@ -15,6 +15,7 @@ * @param */ public abstract class InstanceScene implements Scene { + private final UUID uuid; protected final Instance instance; protected final SceneFallback fallback; protected final Map players; @@ -22,8 +23,9 @@ public abstract class InstanceScene implement private boolean shutdown = false; - public InstanceScene(@NotNull Instance instance, @NotNull Map players, + public InstanceScene(@NotNull UUID uuid, @NotNull Instance instance, @NotNull Map players, @NotNull SceneFallback fallback) { + this.uuid = Objects.requireNonNull(uuid, "uuid"); this.instance = Objects.requireNonNull(instance, "instance"); this.players = Objects.requireNonNull(players, "players"); this.unmodifiablePlayers = Collections.unmodifiableMap(players); @@ -35,6 +37,11 @@ public InstanceScene(@NotNull Instance instance, @NotNull Map return unmodifiablePlayers; } + @Override + public @NotNull UUID getUUID() { + return uuid; + } + @Override public int getIngamePlayerCount() { Wrapper count = Wrapper.of(0); diff --git a/core/src/main/java/org/phantazm/core/game/scene/Scene.java b/core/src/main/java/org/phantazm/core/game/scene/Scene.java index f9c73fe0b..d4df0223b 100644 --- a/core/src/main/java/org/phantazm/core/game/scene/Scene.java +++ b/core/src/main/java/org/phantazm/core/game/scene/Scene.java @@ -39,6 +39,8 @@ public interface Scene extends Tickable { */ @UnmodifiableView @NotNull Map getPlayers(); + @NotNull UUID getUUID(); + /** * Gets the number of players that are considered "ingame" in the scene. * This count may differ from the number of entries in diff --git a/core/src/main/java/org/phantazm/core/game/scene/SceneRouter.java b/core/src/main/java/org/phantazm/core/game/scene/SceneRouter.java new file mode 100644 index 000000000..6e8a9eaa1 --- /dev/null +++ b/core/src/main/java/org/phantazm/core/game/scene/SceneRouter.java @@ -0,0 +1,15 @@ +package org.phantazm.core.game.scene; + +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Optional; +import java.util.UUID; + +public interface SceneRouter extends Scene { + + @NotNull Collection getScenes(); + + @NotNull Optional getScene(@NotNull UUID playerUUID); + +} diff --git a/core/src/main/java/org/phantazm/core/game/scene/lobby/BasicLobbyJoinRequest.java b/core/src/main/java/org/phantazm/core/game/scene/lobby/BasicLobbyJoinRequest.java index 594aeaf05..7a22c43a8 100644 --- a/core/src/main/java/org/phantazm/core/game/scene/lobby/BasicLobbyJoinRequest.java +++ b/core/src/main/java/org/phantazm/core/game/scene/lobby/BasicLobbyJoinRequest.java @@ -51,7 +51,11 @@ public void handleJoin(@NotNull Instance instance, @NotNull InstanceConfig insta player.setGameMode(GameMode.ADVENTURE); teleportedPlayers.add(player); - futures.add(player.setInstance(instance, instanceConfig.spawnPoint())); + if (player.getInstance() == instance) { + futures.add(player.teleport(instanceConfig.spawnPoint())); + } else { + futures.add(player.setInstance(instance, instanceConfig.spawnPoint())); + } }); } diff --git a/core/src/main/java/org/phantazm/core/game/scene/lobby/BasicLobbyProvider.java b/core/src/main/java/org/phantazm/core/game/scene/lobby/BasicLobbyProvider.java index 9e91f1a5b..7cce5200a 100644 --- a/core/src/main/java/org/phantazm/core/game/scene/lobby/BasicLobbyProvider.java +++ b/core/src/main/java/org/phantazm/core/game/scene/lobby/BasicLobbyProvider.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Objects; +import java.util.UUID; /** * Basic implementation of a {@link LobbyProviderAbstract}. @@ -72,7 +73,7 @@ public BasicLobbyProvider(int maximumLobbies, int newLobbyThreshold, @NotNull In }); eventNode.addListener(PlayerBlockBreakEvent.class, event -> event.setCancelled(true)); - return new Lobby(instance, instanceConfig, fallback); + return new Lobby(UUID.randomUUID(), instance, instanceConfig, fallback); } @Override diff --git a/core/src/main/java/org/phantazm/core/game/scene/lobby/Lobby.java b/core/src/main/java/org/phantazm/core/game/scene/lobby/Lobby.java index 34df8ce1c..153dd17ac 100644 --- a/core/src/main/java/org/phantazm/core/game/scene/lobby/Lobby.java +++ b/core/src/main/java/org/phantazm/core/game/scene/lobby/Lobby.java @@ -28,8 +28,9 @@ public class Lobby extends InstanceScene { * @param instanceConfig The {@link InstanceConfig} used for the lobby's {@link Instance} * @param fallback A fallback for the lobby */ - public Lobby(@NotNull Instance instance, @NotNull InstanceConfig instanceConfig, @NotNull SceneFallback fallback) { - super(instance, new HashMap<>(), fallback); + public Lobby(@NotNull UUID uuid, @NotNull Instance instance, @NotNull InstanceConfig instanceConfig, + @NotNull SceneFallback fallback) { + super(uuid, instance, new HashMap<>(), fallback); this.instanceConfig = Objects.requireNonNull(instanceConfig, "instanceConfig"); } diff --git a/core/src/main/java/org/phantazm/core/game/scene/lobby/LobbyProviderAbstract.java b/core/src/main/java/org/phantazm/core/game/scene/lobby/LobbyProviderAbstract.java index ba280eead..127309a43 100644 --- a/core/src/main/java/org/phantazm/core/game/scene/lobby/LobbyProviderAbstract.java +++ b/core/src/main/java/org/phantazm/core/game/scene/lobby/LobbyProviderAbstract.java @@ -3,6 +3,7 @@ import org.jetbrains.annotations.NotNull; import org.phantazm.core.game.scene.SceneProvider; import org.phantazm.core.game.scene.SceneProviderAbstract; +import org.phantazm.core.player.PlayerView; import java.util.Optional; @@ -31,7 +32,14 @@ public LobbyProviderAbstract(int maximumLobbies, int newLobbyThreshold) { Lobby maximumLobby = null; int maximumWeighting = Integer.MIN_VALUE; + sceneLoop: for (Lobby lobby : getScenes()) { + for (PlayerView playerView : request.getPlayers()) { + if (lobby.getPlayers().containsKey(playerView.getUUID())) { + continue sceneLoop; + } + } + int joinWeight = lobby.getJoinWeight(request); if (joinWeight > maximumWeighting) { diff --git a/core/src/main/java/org/phantazm/core/game/scene/lobby/LobbyRouter.java b/core/src/main/java/org/phantazm/core/game/scene/lobby/LobbyRouter.java index 3c32d5463..7fab12915 100644 --- a/core/src/main/java/org/phantazm/core/game/scene/lobby/LobbyRouter.java +++ b/core/src/main/java/org/phantazm/core/game/scene/lobby/LobbyRouter.java @@ -6,6 +6,7 @@ import org.phantazm.core.game.scene.RouteResult; import org.phantazm.core.game.scene.Scene; import org.phantazm.core.game.scene.SceneProvider; +import org.phantazm.core.game.scene.SceneRouter; import org.phantazm.core.player.PlayerView; import java.util.*; @@ -13,7 +14,8 @@ /** * {@link Scene} router for {@link Lobby}s. */ -public class LobbyRouter implements Scene { +public class LobbyRouter implements SceneRouter { + private final UUID uuid; private final Map> lobbyProviders; @@ -66,10 +68,27 @@ public Set> entrySet() { * * @param lobbyProviders The {@link SceneProvider}s for lobbies mapped based on lobby name. */ - public LobbyRouter(@NotNull Map> lobbyProviders) { + public LobbyRouter(@NotNull UUID uuid, + @NotNull Map> lobbyProviders) { + this.uuid = Objects.requireNonNull(uuid, "uuid"); this.lobbyProviders = Objects.requireNonNull(lobbyProviders, "lobbyProviders"); } + @Override + public @NotNull Collection getScenes() { + Collection scenes = new ArrayList<>(); + for (SceneProvider sceneProvider : lobbyProviders.values()) { + scenes.addAll(sceneProvider.getScenes()); + } + + return scenes; + } + + @Override + public @NotNull Optional getScene(@NotNull UUID uuid) { + return Optional.ofNullable(playerLobbyMap.get(uuid)); + } + @Override public @NotNull RouteResult join(@NotNull LobbyRouteRequest routeRequest) { if (isShutdown()) { @@ -115,11 +134,21 @@ public LobbyRouter(@NotNull Map> } } + boolean success = true; for (UUID uuid : leavers) { - playerLobbyMap.get(uuid).leave(List.of(uuid)); + RouteResult subResult = playerLobbyMap.get(uuid).leave(List.of(uuid)); + if (subResult.success()) { + playerLobbyMap.remove(uuid); + } else { + success = false; + } + } + + if (success) { + return RouteResult.SUCCESSFUL; } - return RouteResult.SUCCESSFUL; + return new RouteResult(false, Optional.of(Component.text("Failed to remove a player from a lobby."))); } @Override @@ -127,6 +156,11 @@ public LobbyRouter(@NotNull Map> return unmodifiablePlayers; } + @Override + public @NotNull UUID getUUID() { + return uuid; + } + @Override public int getIngamePlayerCount() { int playerCount = 0; diff --git a/core/src/test/java/org/phantazm/core/game/scene/lobby/LobbyIntegrationTest.java b/core/src/test/java/org/phantazm/core/game/scene/lobby/LobbyIntegrationTest.java index 85431f909..98e00398b 100644 --- a/core/src/test/java/org/phantazm/core/game/scene/lobby/LobbyIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/game/scene/lobby/LobbyIntegrationTest.java @@ -34,7 +34,7 @@ public void testShutdown(Env env) { InstanceConfig instanceConfig = new InstanceConfig(InstanceConfig.DEFAULT_POS, InstanceConfig.DEFAULT_TIME, InstanceConfig.DEFAULT_TIME_RATE); SceneFallback sceneFallback = (ignored) -> true; - Lobby lobby = new Lobby(instance, instanceConfig, sceneFallback); + Lobby lobby = new Lobby(UUID.randomUUID(), instance, instanceConfig, sceneFallback); PlayerView playerView = mock(PlayerView.class); lobby.shutdown(); @@ -51,7 +51,7 @@ public void testJoin(Env env) { InstanceConfig instanceConfig = new InstanceConfig(InstanceConfig.DEFAULT_POS, InstanceConfig.DEFAULT_TIME, InstanceConfig.DEFAULT_TIME_RATE); SceneFallback sceneFallback = (ignored) -> true; - Lobby lobby = new Lobby(instance, instanceConfig, sceneFallback); + Lobby lobby = new Lobby(UUID.randomUUID(), instance, instanceConfig, sceneFallback); Player player = mock(Player.class); when(player.setInstance(any(), any())).thenReturn(CompletableFuture.completedFuture(null)); PlayerView playerView = new PlayerView() { diff --git a/core/src/test/java/org/phantazm/core/game/scene/lobby/LobbyRouterIntegrationTest.java b/core/src/test/java/org/phantazm/core/game/scene/lobby/LobbyRouterIntegrationTest.java index e588eea4d..c255aaa6e 100644 --- a/core/src/test/java/org/phantazm/core/game/scene/lobby/LobbyRouterIntegrationTest.java +++ b/core/src/test/java/org/phantazm/core/game/scene/lobby/LobbyRouterIntegrationTest.java @@ -9,6 +9,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.mockito.Mockito.mock; @@ -22,7 +23,7 @@ public void testJoinRejectionWhenNotJoinable(Env env) { String lobbyName = "main"; Map> sceneProviders = Collections.singletonMap(lobbyName, (SceneProvider)mock(SceneProvider.class)); - Scene router = new LobbyRouter(sceneProviders); + Scene router = new LobbyRouter(UUID.randomUUID(), sceneProviders); router.setJoinable(false); LobbyRouteRequest request = @@ -37,7 +38,7 @@ public void testJoinRejectionWhenShutdown(Env env) { String lobbyName = "main"; Map> sceneProviders = Collections.singletonMap(lobbyName, (SceneProvider)mock(SceneProvider.class)); - Scene router = new LobbyRouter(sceneProviders); + Scene router = new LobbyRouter(UUID.randomUUID(), sceneProviders); router.shutdown(); LobbyRouteRequest request = @@ -52,7 +53,7 @@ public void testJoinRequestWithNoMatchingSceneProvider(Env env) { String lobbyName = "main"; Map> sceneProviders = Collections.singletonMap(lobbyName, (SceneProvider)mock(SceneProvider.class)); - Scene router = new LobbyRouter(sceneProviders); + Scene router = new LobbyRouter(UUID.randomUUID(), sceneProviders); LobbyRouteRequest request = new LobbyRouteRequest("notMain", new BasicLobbyJoinRequest(env.process().connection(), List.of())); diff --git a/server/src/main/java/org/phantazm/server/Lobbies.java b/server/src/main/java/org/phantazm/server/Lobbies.java index 770315365..a61ae285e 100644 --- a/server/src/main/java/org/phantazm/server/Lobbies.java +++ b/server/src/main/java/org/phantazm/server/Lobbies.java @@ -66,7 +66,7 @@ static void initialize(@NotNull EventNode node, @NotNull PlayerViewProvid Map> lobbyProviders = new HashMap<>(lobbiesConfig.lobbies().size()); - lobbyRouter = new LobbyRouter(lobbyProviders); + lobbyRouter = new LobbyRouter(UUID.randomUUID(), lobbyProviders); sceneStore.addScene(SceneKeys.LOBBY_ROUTER, lobbyRouter); LobbyConfig mainLobbyConfig = lobbiesConfig.lobbies().get(lobbiesConfig.mainLobbyName()); diff --git a/server/src/main/java/org/phantazm/server/ZombiesFeature.java b/server/src/main/java/org/phantazm/server/ZombiesFeature.java index 6ed173d9c..2f5e703c9 100644 --- a/server/src/main/java/org/phantazm/server/ZombiesFeature.java +++ b/server/src/main/java/org/phantazm/server/ZombiesFeature.java @@ -27,7 +27,9 @@ import org.phantazm.core.VecUtils; import org.phantazm.core.equipment.LinearUpgradePath; import org.phantazm.core.equipment.NoUpgradePath; +import org.phantazm.core.game.scene.Scene; import org.phantazm.core.game.scene.fallback.SceneFallback; +import org.phantazm.core.game.scene.lobby.Lobby; import org.phantazm.core.guild.party.Party; import org.phantazm.core.instance.AnvilFileSystemInstanceLoader; import org.phantazm.core.instance.InstanceLoader; @@ -151,7 +153,7 @@ static void initialize(@NotNull EventNode globalEventNode, @NotNull Conte providers.put(entry.getKey(), provider); } - ZombiesFeature.sceneRouter = new ZombiesSceneRouter(providers); + ZombiesFeature.sceneRouter = new ZombiesSceneRouter(UUID.randomUUID(), providers); MinecraftServer.getSchedulerManager() .scheduleTask(() -> sceneRouter.tick(System.currentTimeMillis()), TaskSchedule.immediate(), @@ -159,7 +161,17 @@ static void initialize(@NotNull EventNode globalEventNode, @NotNull Conte commandManager.register( new ZombiesCommand(parties, sceneRouter, keyParser, maps, viewProvider, ZombiesFeature::getPlayerScene, - sceneFallback)); + uuid -> { + if (Lobbies.getLobbyRouter().getScene(uuid).isPresent()) { + return Optional.of(Lobbies.getLobbyRouter()); + } + + if (ZombiesFeature.getPlayerScene(uuid).isPresent()) { + return Optional.of(sceneRouter); + } + + return Optional.empty(); + }, sceneFallback)); } private static void registerElementClasses(ContextManager contextManager) { diff --git a/zombies/src/main/java/org/phantazm/zombies/command/ZombiesCommand.java b/zombies/src/main/java/org/phantazm/zombies/command/ZombiesCommand.java index 3a7c89844..f088e0987 100644 --- a/zombies/src/main/java/org/phantazm/zombies/command/ZombiesCommand.java +++ b/zombies/src/main/java/org/phantazm/zombies/command/ZombiesCommand.java @@ -5,11 +5,11 @@ import net.minestom.server.command.builder.Command; import org.jetbrains.annotations.NotNull; import org.phantazm.core.game.scene.Scene; +import org.phantazm.core.game.scene.SceneRouter; import org.phantazm.core.game.scene.fallback.SceneFallback; import org.phantazm.core.guild.party.Party; import org.phantazm.core.player.PlayerViewProvider; import org.phantazm.zombies.map.MapInfo; -import org.phantazm.zombies.scene.ZombiesRouteRequest; import org.phantazm.zombies.scene.ZombiesScene; import org.phantazm.zombies.scene.ZombiesSceneRouter; @@ -20,20 +20,21 @@ import java.util.function.Function; public class ZombiesCommand extends Command { - public ZombiesCommand(@NotNull Map parties, - @NotNull ZombiesSceneRouter router, - @NotNull KeyParser keyParser, - @NotNull Map maps, @NotNull PlayerViewProvider viewProvider, - @NotNull Function> sceneMapper, @NotNull SceneFallback fallback) { + public ZombiesCommand(@NotNull Map parties, @NotNull ZombiesSceneRouter router, + @NotNull KeyParser keyParser, @NotNull Map maps, @NotNull PlayerViewProvider viewProvider, + @NotNull Function> sceneMapper, + @NotNull Function, ?>>> globalRouterMapper, + @NotNull SceneFallback fallback) { super("zombies"); Objects.requireNonNull(router, "router"); + Objects.requireNonNull(globalRouterMapper, "globalRouterMapper"); Objects.requireNonNull(keyParser, "keyParser"); Objects.requireNonNull(maps, "maps"); Objects.requireNonNull(viewProvider, "viewProvider"); Objects.requireNonNull(fallback, "fallback"); - addSubcommand(new ZombiesJoinCommand(parties, router, keyParser, maps, viewProvider)); + addSubcommand(new ZombiesJoinCommand(router, globalRouterMapper, keyParser, maps, viewProvider, parties)); addSubcommand(new GiveCoinsCommand(sceneMapper)); addSubcommand(new RoundCommand(sceneMapper)); addSubcommand(new KillAllCommand(sceneMapper)); @@ -41,6 +42,6 @@ public ZombiesCommand(@NotNull Map parties, addSubcommand(new AmmoRefillCommand(sceneMapper)); addSubcommand(new FlagToggleCommand(sceneMapper, keyParser)); addSubcommand(new QuitCommand(router, fallback, viewProvider)); - addSubcommand(new ZombiesRejoinCommand(router, viewProvider, parties)); + addSubcommand(new ZombiesRejoinCommand(router, globalRouterMapper, viewProvider, parties)); } } diff --git a/zombies/src/main/java/org/phantazm/zombies/command/ZombiesJoinCommand.java b/zombies/src/main/java/org/phantazm/zombies/command/ZombiesJoinCommand.java index a13923c93..a3e24f337 100644 --- a/zombies/src/main/java/org/phantazm/zombies/command/ZombiesJoinCommand.java +++ b/zombies/src/main/java/org/phantazm/zombies/command/ZombiesJoinCommand.java @@ -13,27 +13,33 @@ import org.jetbrains.annotations.NotNull; import org.phantazm.core.game.scene.RouteResult; import org.phantazm.core.game.scene.Scene; +import org.phantazm.core.game.scene.SceneRouter; import org.phantazm.core.guild.GuildMember; import org.phantazm.core.guild.party.Party; import org.phantazm.core.player.PlayerView; import org.phantazm.core.player.PlayerViewProvider; import org.phantazm.zombies.map.MapInfo; +import org.phantazm.zombies.scene.ZombiesJoinRequest; import org.phantazm.zombies.scene.ZombiesRouteRequest; import java.util.*; +import java.util.function.Function; public class ZombiesJoinCommand extends Command { - public ZombiesJoinCommand(@NotNull Map parties, - @NotNull Scene router, @NotNull KeyParser keyParser, @NotNull Map maps, - @NotNull PlayerViewProvider viewProvider) { + public ZombiesJoinCommand(@NotNull Scene router, + @NotNull Function, ?>>> globalRouterMapper, + @NotNull KeyParser keyParser, @NotNull Map maps, @NotNull PlayerViewProvider viewProvider, + @NotNull Map parties) { super("join"); Argument mapKeyArgument = ArgumentType.String("map-key"); Objects.requireNonNull(router, "router"); + Objects.requireNonNull(globalRouterMapper, "globalRouterMapper"); Objects.requireNonNull(keyParser, "keyParser"); Objects.requireNonNull(maps, "maps"); Objects.requireNonNull(viewProvider, "viewProvider"); + Objects.requireNonNull(parties, "parties"); mapKeyArgument.setSuggestionCallback((sender, context, suggestion) -> { for (Map.Entry entry : maps.entrySet()) { @@ -75,7 +81,24 @@ public ZombiesJoinCommand(@NotNull Map parties, } } - RouteResult result = router.join(ZombiesRouteRequest.joinGame(mapKey, () -> playerViews)); + Set excluded = new HashSet<>(); + for (PlayerView playerView : playerViews) { + globalRouterMapper.apply(playerView.getUUID()).ifPresent(oldRouter -> { + oldRouter.getScene(playerView.getUUID()).map(Scene::getUUID).ifPresent(excluded::add); + oldRouter.leave(Collections.singleton(playerView.getUUID())); + }); + } + RouteResult result = router.join(ZombiesRouteRequest.joinGame(mapKey, new ZombiesJoinRequest() { + @Override + public @NotNull Collection getPlayers() { + return playerViews; + } + + @Override + public @NotNull Set excludedScenes() { + return excluded; + } + })); result.message().ifPresent(sender::sendMessage); }, mapKeyArgument); } diff --git a/zombies/src/main/java/org/phantazm/zombies/command/ZombiesRejoinCommand.java b/zombies/src/main/java/org/phantazm/zombies/command/ZombiesRejoinCommand.java index 1cbaae08f..41e2023e2 100644 --- a/zombies/src/main/java/org/phantazm/zombies/command/ZombiesRejoinCommand.java +++ b/zombies/src/main/java/org/phantazm/zombies/command/ZombiesRejoinCommand.java @@ -9,22 +9,28 @@ import net.minestom.server.entity.Player; import org.jetbrains.annotations.NotNull; import org.phantazm.core.game.scene.RouteResult; +import org.phantazm.core.game.scene.Scene; +import org.phantazm.core.game.scene.SceneRouter; import org.phantazm.core.guild.GuildMember; import org.phantazm.core.guild.party.Party; import org.phantazm.core.player.PlayerView; import org.phantazm.core.player.PlayerViewProvider; +import org.phantazm.zombies.scene.ZombiesJoinRequest; import org.phantazm.zombies.scene.ZombiesRouteRequest; import org.phantazm.zombies.scene.ZombiesScene; import org.phantazm.zombies.scene.ZombiesSceneRouter; import java.util.*; +import java.util.function.Function; public class ZombiesRejoinCommand extends Command { - public ZombiesRejoinCommand(@NotNull ZombiesSceneRouter router, @NotNull PlayerViewProvider viewProvider, - @NotNull Map parties) { + public ZombiesRejoinCommand(@NotNull ZombiesSceneRouter router, + @NotNull Function, ?>>> globalRouterMapper, + @NotNull PlayerViewProvider viewProvider, @NotNull Map parties) { super("rejoin"); Objects.requireNonNull(router, "router"); + Objects.requireNonNull(globalRouterMapper, "globalSceneMapper"); Objects.requireNonNull(viewProvider, "viewProvider"); Objects.requireNonNull(parties, "parties"); @@ -40,7 +46,8 @@ public ZombiesRejoinCommand(@NotNull ZombiesSceneRouter router, @NotNull PlayerV continue; } - SuggestionEntry entry = new SuggestionEntry(scene.getUuid().toString(), scene.getMapSettingsInfo().displayName()); + SuggestionEntry entry = + new SuggestionEntry(scene.getUUID().toString(), scene.getMapSettingsInfo().displayName()); suggestion.addEntry(entry); } })); @@ -57,7 +64,7 @@ public ZombiesRejoinCommand(@NotNull ZombiesSceneRouter router, @NotNull PlayerV boolean anyMatch = false; for (ZombiesScene scene : router.getScenes()) { - if (scene.getUuid().equals(targetGame)) { + if (scene.getUUID().equals(targetGame)) { anyMatch = true; break; } @@ -81,7 +88,24 @@ public ZombiesRejoinCommand(@NotNull ZombiesSceneRouter router, @NotNull PlayerV } } - RouteResult result = router.join(ZombiesRouteRequest.rejoinGame(targetGame, () -> playerViews)); + Set excluded = new HashSet<>(); + for (PlayerView playerView : playerViews) { + globalRouterMapper.apply(playerView.getUUID()).ifPresent(oldRouter -> { + oldRouter.getScene(playerView.getUUID()).map(Scene::getUUID).ifPresent(excluded::add); + oldRouter.leave(Collections.singleton(playerView.getUUID())); + }); + } + RouteResult result = router.join(ZombiesRouteRequest.rejoinGame(targetGame, new ZombiesJoinRequest() { + @Override + public @NotNull Collection getPlayers() { + return playerViews; + } + + @Override + public @NotNull Set excludedScenes() { + return excluded; + } + })); result.message().ifPresent(sender::sendMessage); }, targetGameArgument); } diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/LeaveHandler.java b/zombies/src/main/java/org/phantazm/zombies/scene/LeaveHandler.java index f47313ae6..21631dc3c 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/LeaveHandler.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/LeaveHandler.java @@ -23,7 +23,8 @@ public class LeaveHandler { private final Map zombiesPlayers; - public LeaveHandler(@NotNull StageTransition stageTransition, @NotNull Map players, + public LeaveHandler(@NotNull StageTransition stageTransition, + @NotNull Map players, @NotNull Map zombiesPlayers) { this.stageTransition = Objects.requireNonNull(stageTransition, "stageTransition"); this.players = Objects.requireNonNull(players, "players"); @@ -42,17 +43,18 @@ public RouteResult leave(@NotNull Iterable leavers) { players.remove(leaver); Stage stage = stageTransition.getCurrentStage(); - ZombiesPlayer zombiesPlayer; + + ZombiesPlayer zombiesPlayer = zombiesPlayers.get(leaver); + if (stage != null) { + stage.onLeave(zombiesPlayer); + } + if (stage == null || !stage.hasPermanentPlayers()) { - zombiesPlayer = zombiesPlayers.remove(leaver); + zombiesPlayers.remove(leaver); zombiesPlayer.end(); } - else { - zombiesPlayer = zombiesPlayers.get(leaver); - - if (zombiesPlayer != null) { - zombiesPlayer.setState(ZombiesPlayerStateKeys.QUIT, new QuitPlayerStateContext(true)); - } + else if (zombiesPlayer != null) { + zombiesPlayer.setState(ZombiesPlayerStateKeys.QUIT, new QuitPlayerStateContext(true)); } } diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/SceneContainer.java b/zombies/src/main/java/org/phantazm/zombies/scene/SceneContainer.java deleted file mode 100644 index bd587311a..000000000 --- a/zombies/src/main/java/org/phantazm/zombies/scene/SceneContainer.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.phantazm.zombies.scene; - -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; - -public interface SceneContainer { - - @NotNull Collection getScenes(); - -} diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesJoinRequest.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesJoinRequest.java index 25fb20b90..dc0e08837 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesJoinRequest.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesJoinRequest.java @@ -5,11 +5,15 @@ import org.phantazm.core.player.PlayerView; import java.util.Collection; +import java.util.Set; +import java.util.UUID; public interface ZombiesJoinRequest extends SceneJoinRequest { @NotNull Collection getPlayers(); + @NotNull Set excludedScenes(); + @Override default int getRequestWeight() { return getPlayers().size(); diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java index effa0d447..3c77e1cef 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java @@ -35,7 +35,6 @@ public class ZombiesScene extends InstanceScene { private static final Logger LOGGER = LoggerFactory.getLogger(ZombiesScene.class); private static final CompletableFuture[] EMPTY_COMPLETABLE_FUTURE_ARRAY = new CompletableFuture[0]; - private final UUID uuid; private final ConnectionManager connectionManager; private final ZombiesMap map; private final Map zombiesPlayers; @@ -53,8 +52,7 @@ public ZombiesScene(@NotNull UUID uuid, @NotNull ConnectionManager connectionMan @NotNull StageTransition stageTransition, @NotNull LeaveHandler leaveHandler, @NotNull Function playerCreator, @NotNull TickTaskScheduler taskScheduler) { - super(instance, players, fallback); - this.uuid = Objects.requireNonNull(uuid, "uuid"); + super(uuid, instance, players, fallback); this.connectionManager = Objects.requireNonNull(connectionManager, "connectionManager"); this.map = Objects.requireNonNull(map, "map"); this.zombiesPlayers = Objects.requireNonNull(zombiesPlayers, "zombiesPlayers"); @@ -81,10 +79,6 @@ public boolean isComplete() { return stageTransition.isComplete(); } - public @NotNull UUID getUuid() { - return uuid; - } - public @NotNull ZombiesMap getMap() { return map; } @@ -136,7 +130,11 @@ public boolean isComplete() { zombiesPlayer.getPlayer().ifPresent(player -> { teleportedViews.add(zombiesPlayer.module().getPlayerView()); teleportedPlayers.add(player); - futures.add(player.setInstance(instance, pos)); + if (player.getInstance() == instance) { + futures.add(player.teleport(pos)); + } else { + futures.add(player.setInstance(instance, pos)); + } runnables.add(() -> { zombiesPlayer.setState(ZombiesPlayerStateKeys.DEAD, DeadPlayerStateContext.rejoin()); }); @@ -146,7 +144,11 @@ public boolean isComplete() { view.getPlayer().ifPresent(player -> { teleportedViews.add(view); teleportedPlayers.add(player); - futures.add(player.setInstance(instance, pos)); + if (player.getInstance() == instance) { + futures.add(player.teleport(pos)); + } else { + futures.add(player.setInstance(instance, pos)); + } runnables.add(() -> { ZombiesPlayer zombiesPlayer = playerCreator.apply(view); zombiesPlayer.start(); diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java index 3dce6a523..f75c553a7 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java @@ -117,8 +117,9 @@ public ZombiesSceneProvider(int maximumScenes, @Override protected @NotNull Optional chooseScene(@NotNull ZombiesJoinRequest request) { + sceneLoop: for (ZombiesScene scene : getScenes()) { - if (scene.isComplete() || !scene.isJoinable() || scene.isShutdown()) { + if (request.excludedScenes().contains(scene.getUUID()) || scene.isComplete() || !scene.isJoinable() || scene.isShutdown()) { continue; } @@ -130,9 +131,17 @@ public ZombiesSceneProvider(int maximumScenes, int maxPlayers = scene.getMapSettingsInfo().maxPlayers(); int currentPlayerCount = scene.getZombiesPlayers().size(); - if (currentPlayerCount + request.getPlayers().size() <= maxPlayers) { - return Optional.of(scene); + if (currentPlayerCount + request.getPlayers().size() > maxPlayers) { + continue; + } + + for (PlayerView view : request.getPlayers()) { + if (scene.getPlayers().containsKey(view.getUUID())) { + continue sceneLoop; + } } + + return Optional.of(scene); } return Optional.empty(); diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneRouter.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneRouter.java index e8b8c6299..03c9373bc 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneRouter.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneRouter.java @@ -7,11 +7,13 @@ import org.phantazm.core.game.scene.RouteResult; import org.phantazm.core.game.scene.Scene; import org.phantazm.core.game.scene.SceneProvider; +import org.phantazm.core.game.scene.SceneRouter; import org.phantazm.core.player.PlayerView; import java.util.*; -public class ZombiesSceneRouter implements Scene, SceneContainer { +public class ZombiesSceneRouter implements SceneRouter { + private final UUID uuid; private final Map> sceneProviders; private final Map playerSceneMap = new HashMap<>(); @@ -56,11 +58,13 @@ public Set> entrySet() { private boolean shutdown = false; private boolean joinable = true; - public ZombiesSceneRouter( + public ZombiesSceneRouter(@NotNull UUID uuid, @NotNull Map> sceneProviders) { + this.uuid = Objects.requireNonNull(uuid, "uuid"); this.sceneProviders = Objects.requireNonNull(sceneProviders, "sceneProviders"); } + @Override public @NotNull Optional getScene(@NotNull UUID uuid) { return Optional.ofNullable(playerSceneMap.get(uuid)); } @@ -115,7 +119,7 @@ private RouteResult joinGame(ZombiesRouteRequest routeRequest) { // TODO: optimize private RouteResult rejoinGame(ZombiesRouteRequest routeRequest) { for (ZombiesScene scene : getScenes()) { - if (!scene.getUuid().equals(routeRequest.targetGame())) { + if (!scene.getUUID().equals(routeRequest.targetGame())) { continue; } @@ -140,11 +144,22 @@ private RouteResult rejoinGame(ZombiesRouteRequest routeRequest) { } } + boolean success = true; for (UUID uuid : leavers) { - playerSceneMap.get(uuid).leave(Collections.singleton(uuid)); + RouteResult subResult = playerSceneMap.get(uuid).leave(Collections.singleton(uuid)); + if (subResult.success()) { + playerSceneMap.remove(uuid); + } + else { + success = false; + } + } + + if (success) { + return RouteResult.SUCCESSFUL; } - return RouteResult.SUCCESSFUL; + return new RouteResult(false, Optional.of(Component.text("Failed to remove a player from a game."))); } @Override @@ -152,6 +167,11 @@ private RouteResult rejoinGame(ZombiesRouteRequest routeRequest) { return unmodifiablePlayers; } + @Override + public @NotNull UUID getUUID() { + return uuid; + } + @Override public int getIngamePlayerCount() { int playerCount = 0; diff --git a/zombies/src/main/java/org/phantazm/zombies/stage/CountdownStage.java b/zombies/src/main/java/org/phantazm/zombies/stage/CountdownStage.java index aed2f27c1..d443fcae4 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stage/CountdownStage.java +++ b/zombies/src/main/java/org/phantazm/zombies/stage/CountdownStage.java @@ -28,6 +28,8 @@ public class CountdownStage implements Stage { private final Wrapper ticksRemaining; + private final long initialTicks; + private final LongList alertTicks; private final TickFormatter tickFormatter; @@ -43,6 +45,7 @@ protected CountdownStage(@NotNull Instance instance, @NotNull Collection activables = new ArrayList<>(); - - private BooleanSupplier continueCondition; - - private BooleanSupplier revertCondition = () -> false; - - private Consumer playerJoinHandler = unused -> { - }; - - private boolean hasPermanentPlayers; - - public Builder(@NotNull Key key) { - this.key = Objects.requireNonNull(key, "key"); - } - - public @NotNull Builder setContinueCondition(@NotNull BooleanSupplier continueCondition) { - this.continueCondition = Objects.requireNonNull(continueCondition, "continueCondition"); - return this; - } - - public @NotNull Builder setRevertCondition(@NotNull BooleanSupplier revertCondition) { - this.revertCondition = Objects.requireNonNull(revertCondition, "revertCondition"); - return this; - } - - public @NotNull Builder setPlayerJoinHandler(@NotNull Consumer playerJoinHandler) { - this.playerJoinHandler = Objects.requireNonNull(playerJoinHandler, "playerJoinHandler"); - return this; - } - - public @NotNull Builder setPermanentPlayers(boolean hasPermanentPlayers) { - this.hasPermanentPlayers = hasPermanentPlayers; - return this; - } + void onLeave(@NotNull ZombiesPlayer zombiesPlayer); - public @NotNull Builder addActivable(@NotNull Activable activable) { - activables.add(Objects.requireNonNull(activable, "activable")); - return this; - } - - public @NotNull Builder addActivables(@NotNull Collection activables) { - this.activables.addAll(List.copyOf(activables)); - return this; - } - - public @NotNull Stage build() { - Objects.requireNonNull(continueCondition, "continueCondition"); - - return new Stage() { - - @Override - public @NotNull Key key() { - return key; - } - - @Override - public void start() { - for (Activable activable : activables) { - activable.start(); - } - } - - @Override - public void tick(long time) { - for (Activable activable : activables) { - activable.tick(time); - } - } - - @Override - public void end() { - for (Activable activable : activables) { - activable.end(); - } - } - - @Override - public boolean shouldContinue() { - return continueCondition.getAsBoolean(); - } - - @Override - public boolean shouldRevert() { - return revertCondition.getAsBoolean(); - } - - @Override - public void onJoin(@NotNull ZombiesPlayer zombiesPlayer) { - playerJoinHandler.accept(Objects.requireNonNull(zombiesPlayer, "zombiesPlayer")); - } - - @Override - public boolean hasPermanentPlayers() { - return hasPermanentPlayers; - } - }; - } - - } + boolean hasPermanentPlayers(); } From a866949e8b6e1950daec8b11c8616fb4452ec09b Mon Sep 17 00:00:00 2001 From: steank Date: Fri, 16 Jun 2023 16:41:58 -0700 Subject: [PATCH 021/181] fix resistInstakill not working, add RadialDamageEntitySkill --- .../mob/skill/RadialDamageEntitySkill.java | 59 +++++++++++++++++++ .../main/java/org/phantazm/server/Mob.java | 1 + .../org/phantazm/zombies/ExtraNodeKeys.java | 2 +- 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 mob/src/main/java/org/phantazm/mob/skill/RadialDamageEntitySkill.java diff --git a/mob/src/main/java/org/phantazm/mob/skill/RadialDamageEntitySkill.java b/mob/src/main/java/org/phantazm/mob/skill/RadialDamageEntitySkill.java new file mode 100644 index 000000000..441cda19e --- /dev/null +++ b/mob/src/main/java/org/phantazm/mob/skill/RadialDamageEntitySkill.java @@ -0,0 +1,59 @@ +package org.phantazm.mob.skill; + +import com.github.steanky.element.core.annotation.*; +import net.minestom.server.entity.LivingEntity; +import net.minestom.server.entity.damage.DamageType; +import org.jetbrains.annotations.NotNull; +import org.phantazm.mob.PhantazmMob; +import org.phantazm.mob.target.TargetSelector; + +import java.util.Objects; + +@Model("mob.skill.radial_damage") +@Cache(false) +public class RadialDamageEntitySkill implements Skill { + + private final Data data; + private final TargetSelector selector; + + @FactoryMethod + public RadialDamageEntitySkill(@NotNull Data data, @NotNull @Child("selector") TargetSelector selector) { + this.data = Objects.requireNonNull(data, "data"); + this.selector = Objects.requireNonNull(selector, "selector"); + } + + @Override + public void use(@NotNull PhantazmMob self) { + selector.selectTarget(self).ifPresent(object -> { + LivingEntity selfEntity = self.entity(); + if (object instanceof Iterable iterable) { + Iterable entityIterable = (Iterable)iterable; + for (LivingEntity entity : entityIterable) { + double damage = calculateDamage(entity.getDistanceSquared(selfEntity)); + entity.damage(DamageType.fromEntity(selfEntity), (float)damage, data.bypassArmor); + } + } + else if (object instanceof LivingEntity living) { + double damage = calculateDamage(living.getDistanceSquared(selfEntity)); + living.damage(DamageType.fromEntity(selfEntity), (float)damage, data.bypassArmor); + } + }); + } + + private double calculateDamage(double distanceToEntitySquared) { + return Math.sqrt(Math.max(-distanceToEntitySquared + (data.range * data.range), 0)); + } + + @DataObject + public record Data(@NotNull @ChildPath("selector") String selector, + float damage, + boolean bypassArmor, + double range) { + + public Data { + Objects.requireNonNull(selector, "selector"); + } + + } + +} diff --git a/server/src/main/java/org/phantazm/server/Mob.java b/server/src/main/java/org/phantazm/server/Mob.java index 1aaf842a9..3f4fc9a68 100644 --- a/server/src/main/java/org/phantazm/server/Mob.java +++ b/server/src/main/java/org/phantazm/server/Mob.java @@ -139,6 +139,7 @@ private static void registerElementClasses(@NotNull ContextManager contextManage contextManager.registerElementClass(SendMessageSkill.class); contextManager.registerElementClass(JumpTowardsTargetSkill.class); contextManager.registerElementClass(SpawnParticleSkill.class); + contextManager.registerElementClass(RadialDamageEntitySkill.class); //mob meta skills contextManager.registerElementClass(TimerSkill.class); diff --git a/zombies/src/main/java/org/phantazm/zombies/ExtraNodeKeys.java b/zombies/src/main/java/org/phantazm/zombies/ExtraNodeKeys.java index b3cfaaec2..ba8b2495a 100644 --- a/zombies/src/main/java/org/phantazm/zombies/ExtraNodeKeys.java +++ b/zombies/src/main/java/org/phantazm/zombies/ExtraNodeKeys.java @@ -4,5 +4,5 @@ public final class ExtraNodeKeys { private ExtraNodeKeys() { } - public static final String RESIST_INSTAKILL = "resistInstaKill"; + public static final String RESIST_INSTAKILL = "resistInstakill"; } From a6fb88f17e2a00c9439357142816f7e6e7fbc1af Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Fri, 16 Jun 2023 21:57:51 -0400 Subject: [PATCH 022/181] add better checks for player actions --- .../org/phantazm/server/ZombiesFeature.java | 1 + .../org/phantazm/zombies/map/Spawnpoint.java | 5 ++- .../map/action/round/SelectBombedRoom.java | 4 +-- .../map/handler/BasicWindowHandler.java | 2 +- .../shop/predicate/PlayerInGamePredicate.java | 24 +++++++++++++ .../zombies/player/ZombiesPlayer.java | 36 ++++++++++++++++--- .../zombies/player/ZombiesPlayerMeta.java | 20 ----------- .../state/BasicAliveStateActivable.java | 4 --- .../player/state/BasicDeadStateActivable.java | 4 --- .../state/BasicKnockedStateActivable.java | 3 -- .../player/state/BasicQuitStateActivable.java | 3 -- .../state/revive/NearbyReviverFinder.java | 19 +--------- .../player/state/revive/ReviveHandler.java | 3 +- .../org/phantazm/zombies/stage/EndStage.java | 4 ++- .../phantazm/zombies/stage/InGameStage.java | 3 +- .../state/revive/ReviveHandlerTest.java | 1 - 16 files changed, 68 insertions(+), 68 deletions(-) create mode 100644 zombies/src/main/java/org/phantazm/zombies/map/shop/predicate/PlayerInGamePredicate.java diff --git a/server/src/main/java/org/phantazm/server/ZombiesFeature.java b/server/src/main/java/org/phantazm/server/ZombiesFeature.java index 2f5e703c9..0c39298ef 100644 --- a/server/src/main/java/org/phantazm/server/ZombiesFeature.java +++ b/server/src/main/java/org/phantazm/server/ZombiesFeature.java @@ -192,6 +192,7 @@ private static void registerElementClasses(ContextManager contextManager) { contextManager.registerElementClass(MapFlagPredicate.class); contextManager.registerElementClass(InteractingPredicate.class); contextManager.registerElementClass(PlayerFlagPredicate.class); + contextManager.registerElementClass(PlayerInGamePredicate.class); contextManager.registerElementClass(PlayerStatePredicate.class); contextManager.registerElementClass(UuidPredicate.class); contextManager.registerElementClass(TypePredicate.class); diff --git a/zombies/src/main/java/org/phantazm/zombies/map/Spawnpoint.java b/zombies/src/main/java/org/phantazm/zombies/map/Spawnpoint.java index 19c0feda3..6437cbc15 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/Spawnpoint.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/Spawnpoint.java @@ -130,12 +130,11 @@ else if (linkedRoom != null && !linkedRoom.isOpen()) { double slaSquared = spawnrule.slaSquared(); boolean inRange = false; for (ZombiesPlayer player : zombiesPlayers) { - ZombiesPlayerModule module = player.module(); - if (!(module.getMeta().canTriggerSLA())) { + if (!player.canTriggerSLA()) { continue; } - Optional playerOptional = module.getPlayerView().getPlayer(); + Optional playerOptional = player.getPlayer(); if (playerOptional.isPresent()) { if (playerOptional.get().getPosition().distanceSquared(spawnPoint) < slaSquared) { inRange = true; diff --git a/zombies/src/main/java/org/phantazm/zombies/map/action/round/SelectBombedRoom.java b/zombies/src/main/java/org/phantazm/zombies/map/action/round/SelectBombedRoom.java index 4d1d0837c..ac4699e71 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/action/round/SelectBombedRoom.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/action/round/SelectBombedRoom.java @@ -120,7 +120,7 @@ public void tick(long time) { for (ZombiesPlayer zombiesPlayer : playerMap.values()) { zombiesPlayer.getPlayer().ifPresent(player -> { - if (!zombiesPlayer.isAlive()) { + if (!zombiesPlayer.canDoGenericActions()) { removeModifiers(player); } else { @@ -146,7 +146,7 @@ public void tick(long time) { if (++ticks % 4 == 0) { for (ZombiesPlayer zombiesPlayer : playerMap.values()) { - if (!zombiesPlayer.isAlive()) { + if (!zombiesPlayer.canDoGenericActions()) { continue; } diff --git a/zombies/src/main/java/org/phantazm/zombies/map/handler/BasicWindowHandler.java b/zombies/src/main/java/org/phantazm/zombies/map/handler/BasicWindowHandler.java index deecf114e..1b2cb78c0 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/handler/BasicWindowHandler.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/handler/BasicWindowHandler.java @@ -110,7 +110,7 @@ public void tick(long time) { while (repairOperationIterator.hasNext()) { RepairOperation repairOperation = repairOperationIterator.next(); ZombiesPlayer zombiesPlayer = repairOperation.zombiesPlayer; - if (!zombiesPlayer.isAlive()) { + if (!zombiesPlayer.canRepairWindow()) { repairOperationIterator.remove(); continue; } diff --git a/zombies/src/main/java/org/phantazm/zombies/map/shop/predicate/PlayerInGamePredicate.java b/zombies/src/main/java/org/phantazm/zombies/map/shop/predicate/PlayerInGamePredicate.java new file mode 100644 index 000000000..1024c7fe4 --- /dev/null +++ b/zombies/src/main/java/org/phantazm/zombies/map/shop/predicate/PlayerInGamePredicate.java @@ -0,0 +1,24 @@ +package org.phantazm.zombies.map.shop.predicate; + +import com.github.steanky.element.core.annotation.DataObject; +import com.github.steanky.element.core.annotation.FactoryMethod; +import com.github.steanky.element.core.annotation.Model; +import org.jetbrains.annotations.NotNull; +import org.phantazm.zombies.map.shop.PlayerInteraction; + +@Model("zombies.map.shop.predicate.in_game") +public class PlayerInGamePredicate extends PredicateBase { + @FactoryMethod + public PlayerInGamePredicate(@NotNull Data data) { + super(data); + } + + @Override + public boolean canInteract(@NotNull PlayerInteraction interaction) { + return interaction.player().module().getMeta().isInGame(); + } + + @DataObject + public record Data() { + } +} diff --git a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java index a0a877a8c..7d205c2ca 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java @@ -2,6 +2,7 @@ import net.kyori.adventure.audience.Audience; import net.kyori.adventure.key.Key; +import net.minestom.server.entity.Entity; import net.minestom.server.entity.GameMode; import net.minestom.server.entity.Player; import net.minestom.server.event.Event; @@ -104,28 +105,53 @@ default boolean hasQuit() { } default boolean canPickupPowerup(@NotNull Powerup powerup) { - return isAlive(); + return canDoGenericActions(); } default boolean canOpenDoor(@NotNull Door door) { - return isAlive(); + return canDoGenericActions(); } default boolean canRepairWindow() { - return isAlive(); + return canDoGenericActions(); } default boolean canTakeDamage() { - return isAlive(); + return canDoGenericActions(); } default boolean canBeTargeted() { - return isAlive() && getPlayer().map(player -> { + return canDoGenericActions() && getPlayer().map(player -> { GameMode mode = player.getGameMode(); return mode == GameMode.SURVIVAL || mode == GameMode.ADVENTURE; }).orElse(false); } + default boolean canDoGenericActions() { + return isAlive() && isInGame(); + } + + default boolean canRevive() { + if (!canDoGenericActions()) { + return false; + } + + ZombiesPlayerMeta meta = module().getMeta(); + if (meta.isReviving()) { + return false; + } + + return getPlayer().filter(value -> value.getPose() == Entity.Pose.SNEAKING).isPresent(); + } + + default boolean canTriggerSLA() { + return canDoGenericActions(); + } + + default boolean isInGame() { + return module().getMeta().isInGame(); + } + default boolean inStage(@NotNull Key stageKey) { Stage currentStage = getScene().getCurrentStage(); if (currentStage == null) { diff --git a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayerMeta.java b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayerMeta.java index 3f1fef05a..3398596b6 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayerMeta.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayerMeta.java @@ -12,12 +12,8 @@ public class ZombiesPlayerMeta { private boolean inGame = false; - private boolean canRevive = false; - private boolean isReviving = false; - private boolean canTriggerSLA = true; - private int windowRepairAmount = 1; public Optional getCorpse() { @@ -36,14 +32,6 @@ public void setInGame(boolean inGame) { this.inGame = inGame; } - public boolean isCanRevive() { - return canRevive; - } - - public void setCanRevive(boolean canRevive) { - this.canRevive = canRevive; - } - public boolean isReviving() { return isReviving; } @@ -52,14 +40,6 @@ public void setReviving(boolean reviving) { isReviving = reviving; } - public boolean canTriggerSLA() { - return canTriggerSLA; - } - - public void setCanTriggerSLA(boolean canTriggerSLA) { - this.canTriggerSLA = canTriggerSLA; - } - public int getWindowRepairAmount() { return windowRepairAmount; } diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicAliveStateActivable.java b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicAliveStateActivable.java index dc17d69a9..141a4bfd8 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicAliveStateActivable.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicAliveStateActivable.java @@ -43,10 +43,6 @@ public void start() { }); accessRegistry.switchAccess(InventoryKeys.ALIVE_ACCESS); - - meta.setInGame(true); - meta.setCanRevive(true); - meta.setCanTriggerSLA(true); } @Override diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicDeadStateActivable.java b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicDeadStateActivable.java index 567c54089..d78dd4a48 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicDeadStateActivable.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicDeadStateActivable.java @@ -49,10 +49,6 @@ public void start() { }); accessRegistry.switchAccess(InventoryKeys.DEAD_ACCESS); - - meta.setInGame(true); - meta.setCanRevive(false); - meta.setCanTriggerSLA(false); } @Override diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicKnockedStateActivable.java b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicKnockedStateActivable.java index 573afe4fe..6761aa542 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicKnockedStateActivable.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicKnockedStateActivable.java @@ -68,9 +68,6 @@ public void start() { playerView.getDisplayName().thenAccept(displayName -> { instance.sendMessage(buildDeathMessage(displayName)); }); - meta.setInGame(true); - meta.setCanRevive(false); - meta.setCanTriggerSLA(false); } @Override diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java index 211272815..fd0091263 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java @@ -46,9 +46,6 @@ public void start() { }); playerView.getDisplayName() .thenAccept(displayName -> instance.sendMessage(displayName.append(Component.text(" quit.")))); - meta.setInGame(false); - meta.setCanRevive(false); - meta.setCanTriggerSLA(false); } } diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/revive/NearbyReviverFinder.java b/zombies/src/main/java/org/phantazm/zombies/player/state/revive/NearbyReviverFinder.java index 1dad135af..f125a075e 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/revive/NearbyReviverFinder.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/revive/NearbyReviverFinder.java @@ -51,20 +51,7 @@ public ZombiesPlayer get() { .nearbyEntitiesUntil(knockedPosition, reviveRadius, EntityTracker.Target.PLAYERS, candidate -> { UUID candidateUUID = candidate.getUuid(); ZombiesPlayer revivingPlayer = zombiesPlayers.get(candidateUUID); - if (revivingPlayer == null) { - return false; - } - - if (candidateUUID.equals(playerView.getUUID())) { - return false; - } - - if (!revivingPlayer.isAlive()) { - return false; - } - - ZombiesPlayerMeta meta = revivingPlayer.module().getMeta(); - if (!(meta.isCanRevive() && !meta.isReviving())) { + if (revivingPlayer == null || candidateUUID.equals(playerView.getUUID()) || !revivingPlayer.canRevive()) { return false; } @@ -72,11 +59,7 @@ public ZombiesPlayer get() { if (reviverPlayerOptional.isEmpty()) { return false; } - Player player = reviverPlayerOptional.get(); - if (player.getPose() != Entity.Pose.SNEAKING) { - return false; - } if (player.getPosition().distance(knockedPosition) <= reviveRadius) { playerWrapper.set(revivingPlayer); diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/revive/ReviveHandler.java b/zombies/src/main/java/org/phantazm/zombies/player/state/revive/ReviveHandler.java index bb7497b04..f5a5ccbf8 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/revive/ReviveHandler.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/revive/ReviveHandler.java @@ -84,8 +84,7 @@ public void tick(long time) { --ticksUntilDeath; } } - else if (!reviver.module().getMeta().isCanRevive() || - !reviver.getPlayer().map(player -> player.getPose() == Entity.Pose.SNEAKING).orElse(true)) { + else if (!reviver.canRevive()) { reviver.module().getMeta().setReviving(false); reviver = null; ticksUntilRevive = -1; diff --git a/zombies/src/main/java/org/phantazm/zombies/stage/EndStage.java b/zombies/src/main/java/org/phantazm/zombies/stage/EndStage.java index 8a98af2e9..63a11eebb 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stage/EndStage.java +++ b/zombies/src/main/java/org/phantazm/zombies/stage/EndStage.java @@ -52,7 +52,7 @@ public boolean shouldRevert() { @Override public void onJoin(@NotNull ZombiesPlayer zombiesPlayer) { - + zombiesPlayer.module().getMeta().setInGame(false); } @Override @@ -70,6 +70,8 @@ public void start() { instance.playSound(Sound.sound(SoundEvent.ENTITY_ENDER_DRAGON_DEATH, Sound.Source.MASTER, 1.0F, 1.0F)); for (ZombiesPlayer zombiesPlayer : zombiesPlayers) { + zombiesPlayer.module().getMeta().setInGame(false); + if (zombiesPlayer.isState(ZombiesPlayerStateKeys.KNOCKED)) { zombiesPlayer.setState(ZombiesPlayerStateKeys.DEAD, DeadPlayerStateContext.killed(null, null)); } diff --git a/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java b/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java index d2847d7da..c9a1210f5 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java +++ b/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java @@ -77,7 +77,7 @@ public boolean shouldRevert() { @Override public void onJoin(@NotNull ZombiesPlayer zombiesPlayer) { - + zombiesPlayer.module().getMeta().setInGame(true); } @Override @@ -95,6 +95,7 @@ public void start() { this.startTime = System.currentTimeMillis(); for (ZombiesPlayer zombiesPlayer : zombiesPlayers) { + zombiesPlayer.module().getMeta().setInGame(true); zombiesPlayer.getPlayer().ifPresent(player -> { player.teleport(spawnPos); }); diff --git a/zombies/src/test/java/org/phantazm/zombies/game/player/state/revive/ReviveHandlerTest.java b/zombies/src/test/java/org/phantazm/zombies/game/player/state/revive/ReviveHandlerTest.java index c0f0f8349..36aab6fa8 100644 --- a/zombies/src/test/java/org/phantazm/zombies/game/player/state/revive/ReviveHandlerTest.java +++ b/zombies/src/test/java/org/phantazm/zombies/game/player/state/revive/ReviveHandlerTest.java @@ -95,7 +95,6 @@ public void testDisabledReviverResetsRevive() { new ReviveHandler(() -> aliveState, () -> deathState, () -> reviver, initialDeathTime); reviveHandler.tick(0L); - when(meta.isCanRevive()).thenReturn(false); reviveHandler.tick(0L); assertFalse(reviveHandler.isReviving()); From 911ce1c0426458b6583f7adb361a0a08b2b69b0d Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Sat, 17 Jun 2023 00:17:48 -0400 Subject: [PATCH 023/181] configurable mob/player pushing --- .../org/phantazm/server/ZombiesFeature.java | 5 ++++- .../phantazm/zombies/map/MapProcessors.java | 5 ++++- .../phantazm/zombies/map/MapSettingsInfo.java | 3 ++- .../map/objects/BasicMapObjectsSource.java | 11 +++++++---- .../zombies/map/objects/MapObjects.java | 8 +++++--- .../zombies/scene/ZombiesSceneProvider.java | 19 +++++++++++-------- .../zombies/spawn/BasicSpawnDistributor.java | 15 +++++++++++++-- 7 files changed, 46 insertions(+), 20 deletions(-) diff --git a/server/src/main/java/org/phantazm/server/ZombiesFeature.java b/server/src/main/java/org/phantazm/server/ZombiesFeature.java index 0c39298ef..c3482851d 100644 --- a/server/src/main/java/org/phantazm/server/ZombiesFeature.java +++ b/server/src/main/java/org/phantazm/server/ZombiesFeature.java @@ -139,6 +139,9 @@ static void initialize(@NotNull EventNode globalEventNode, @NotNull Conte TeamManager teamManager = MinecraftServer.getTeamManager(); Team corpseTeam = teamManager.createBuilder("corpses").collisionRule(TeamsPacket.CollisionRule.NEVER) .nameTagVisibility(TeamsPacket.NameTagVisibility.NEVER).build(); + // https://bugs.mojang.com/browse/MC-87984 + Team mobNoPushTeam = + teamManager.createBuilder("mobNoPush").collisionRule(TeamsPacket.CollisionRule.PUSH_OTHER_TEAMS).build(); for (Map.Entry entry : maps.entrySet()) { ZombiesSceneProvider provider = new ZombiesSceneProvider(2, instanceSpaceFunction, entry.getValue(), connectionManager, @@ -147,7 +150,7 @@ static void initialize(@NotNull EventNode globalEventNode, @NotNull Conte DimensionType dimensionType = instance.getDimensionType(); return new InstanceClientBlockHandler(instance, globalEventNode, dimensionType.getMinY(), dimensionType.getHeight()); - }), contextManager, keyParser, ZombiesFeature.powerups(), + }), contextManager, keyParser, mobNoPushTeam, ZombiesFeature.powerups(), new BasicZombiesPlayerSource(EquipmentFeature::createEquipmentCreator, corpseTeam, Mob.getModels())); providers.put(entry.getKey(), provider); diff --git a/zombies-mapdata/src/main/java/org/phantazm/zombies/map/MapProcessors.java b/zombies-mapdata/src/main/java/org/phantazm/zombies/map/MapProcessors.java index 9a528632c..61797ea1a 100644 --- a/zombies-mapdata/src/main/java/org/phantazm/zombies/map/MapProcessors.java +++ b/zombies-mapdata/src/main/java/org/phantazm/zombies/map/MapProcessors.java @@ -294,6 +294,7 @@ public MapSettingsInfo dataFromElement(@NotNull ConfigElement element) throws Co int rollsPerChest = element.getNumberOrThrow("rollsPerChest").intValue(); float punchDamage = element.getNumberOrThrow("punchDamage").floatValue(); float punchRange = element.getNumberOrThrow("punchRange").floatValue(); + boolean mobPlayerCollisions = element.getBooleanOrThrow("mobPlayerCollisions"); List milestoneRounds = integerList.dataFromElement(element.getElementOrThrow("milestoneRounds")); Map> defaultEquipment = @@ -305,7 +306,8 @@ public MapSettingsInfo dataFromElement(@NotNull ConfigElement element) throws Co scoreboardHeader, leaderboardPosition, leaderboardLength, worldTime, maxPlayers, minPlayers, startingCoins, repairCoins, windowRepairRadius, powerupPickupRadius, windowRepairTicks, corpseDeathTicks, healTicks, reviveRadius, canWallshoot, perksLostOnDeath, baseReviveTicks, - rollsPerChest, punchDamage, punchRange, milestoneRounds, defaultEquipment, equipmentGroups); + rollsPerChest, punchDamage, punchRange, mobPlayerCollisions, milestoneRounds, defaultEquipment, + equipmentGroups); } @Override @@ -344,6 +346,7 @@ public MapSettingsInfo dataFromElement(@NotNull ConfigElement element) throws Co node.putNumber("rollsPerChest", mapConfig.rollsPerChest()); node.putNumber("punchDamage", mapConfig.punchDamage()); node.putNumber("punchRange", mapConfig.punchRange()); + node.putBoolean("mobPlayerCollisions", mapConfig.mobPlayerCollisions()); node.put("milestoneRounds", integerList.elementFromData(mapConfig.milestoneRounds())); node.put("defaultEquipment", keyToListKeyMap.elementFromData(mapConfig.defaultEquipment())); node.put("equipmentGroups", keyToEquipmentGroup.elementFromData(mapConfig.equipmentGroups())); diff --git a/zombies-mapdata/src/main/java/org/phantazm/zombies/map/MapSettingsInfo.java b/zombies-mapdata/src/main/java/org/phantazm/zombies/map/MapSettingsInfo.java index 264782e32..294e76ff9 100644 --- a/zombies-mapdata/src/main/java/org/phantazm/zombies/map/MapSettingsInfo.java +++ b/zombies-mapdata/src/main/java/org/phantazm/zombies/map/MapSettingsInfo.java @@ -42,6 +42,7 @@ public record MapSettingsInfo(int mapDataVersion, int rollsPerChest, float punchDamage, float punchRange, + boolean mobPlayerCollisions, @NotNull List milestoneRounds, @NotNull Map> defaultEquipment, @NotNull Map equipmentGroups) { @@ -106,6 +107,6 @@ public MapSettingsInfo(@NotNull Key id, @NotNull Vec3I origin) { this(MAP_DATA_VERSION, id, List.of(), origin, 47, -1, Vec3I.ORIGIN, 0, 0, Component.text(id.value()), "{id:\"stone\",Count:1,tag:{Name:\"" + id.value() + "\"}}", new ArrayList<>(0), Component.text(id.value()), Vec3I.ORIGIN, 15, 0, 4, 1, 0, 20, 3, 1, 20, 500, 20, 2, false, false, 30, 5, - 0, 4.5F, new ArrayList<>(0), new HashMap<>(0), new HashMap<>()); + 0, 4.5F, false, new ArrayList<>(0), new HashMap<>(0), new HashMap<>()); } } diff --git a/zombies/src/main/java/org/phantazm/zombies/map/objects/BasicMapObjectsSource.java b/zombies/src/main/java/org/phantazm/zombies/map/objects/BasicMapObjectsSource.java index 6005c6d26..500475a1b 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/objects/BasicMapObjectsSource.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/objects/BasicMapObjectsSource.java @@ -18,7 +18,9 @@ import net.minestom.server.event.EventNode; import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; +import net.minestom.server.scoreboard.Team; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.phantazm.commons.TickTaskScheduler; import org.phantazm.core.ClientBlockHandler; import org.phantazm.core.ClientBlockHandlerSource; @@ -80,12 +82,13 @@ public BasicMapObjectsSource(@NotNull MapInfo mapInfo, @NotNull ContextManager c public @NotNull MapObjects make(@NotNull Instance instance, @NotNull Map playerMap, @NotNull Supplier roundHandlerSupplier, @NotNull MobStore mobStore, - @NotNull Wrapper powerupHandler, @NotNull Wrapper windowHandler, - @NotNull Wrapper> eventNode, @NotNull SongPlayer songPlayer, - @NotNull TickTaskScheduler tickTaskScheduler) { + @Nullable Team mobNoPushTeam, @NotNull Wrapper powerupHandler, + @NotNull Wrapper windowHandler, @NotNull Wrapper> eventNode, + @NotNull SongPlayer songPlayer, @NotNull TickTaskScheduler tickTaskScheduler) { Random random = new Random(); ClientBlockHandler clientBlockHandler = clientBlockHandlerSource.forInstance(instance); - SpawnDistributor spawnDistributor = new BasicSpawnDistributor(mobModels::get, random, playerMap.values()); + SpawnDistributor spawnDistributor = + new BasicSpawnDistributor(mobModels::get, random, playerMap.values(), mobNoPushTeam); Flaggable flaggable = new BasicFlaggable(); TransactionModifierSource transactionModifierSource = new BasicTransactionModifierSource(); diff --git a/zombies/src/main/java/org/phantazm/zombies/map/objects/MapObjects.java b/zombies/src/main/java/org/phantazm/zombies/map/objects/MapObjects.java index fe6568c94..9880087a1 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/objects/MapObjects.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/objects/MapObjects.java @@ -9,7 +9,9 @@ import net.minestom.server.event.Event; import net.minestom.server.event.EventNode; import net.minestom.server.instance.Instance; +import net.minestom.server.scoreboard.Team; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Unmodifiable; import org.phantazm.commons.TickTaskScheduler; import org.phantazm.core.gui.SlotDistributor; @@ -57,9 +59,9 @@ public interface MapObjects { @NotNull MapObjects make(@NotNull Instance instance, @NotNull Map playerMap, @NotNull Supplier roundHandlerSupplier, @NotNull MobStore mobStore, - @NotNull Wrapper powerupHandler, @NotNull Wrapper windowHandler, - @NotNull Wrapper> eventNode, @NotNull SongPlayer songPlayer, - @NotNull TickTaskScheduler tickTaskScheduler); + @Nullable Team mobNoPushTeam, @NotNull Wrapper powerupHandler, + @NotNull Wrapper windowHandler, @NotNull Wrapper> eventNode, + @NotNull SongPlayer songPlayer, @NotNull TickTaskScheduler tickTaskScheduler); } interface Module { diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java index f75c553a7..c58687244 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java @@ -21,6 +21,7 @@ import net.minestom.server.event.player.*; import net.minestom.server.instance.Instance; import net.minestom.server.network.ConnectionManager; +import net.minestom.server.scoreboard.Team; import org.jetbrains.annotations.NotNull; import org.phantazm.commons.BasicTickTaskScheduler; import org.phantazm.commons.TickTaskScheduler; @@ -73,6 +74,7 @@ public class ZombiesSceneProvider extends SceneProviderAbstract eventNode; private final ContextManager contextManager; private final KeyParser keyParser; + private final Team mobNoPushTeam; private final MapObjects.Source mapObjectSource; private final ZombiesPlayer.Source zombiesPlayerSource; @@ -87,7 +89,7 @@ public ZombiesSceneProvider(int maximumScenes, @NotNull InstanceLoader instanceLoader, @NotNull SceneFallback sceneFallback, @NotNull EventNode eventNode, @NotNull MobSpawnerSource mobSpawnerSource, @NotNull Map mobModels, @NotNull ClientBlockHandlerSource clientBlockHandlerSource, - @NotNull ContextManager contextManager, @NotNull KeyParser keyParser, + @NotNull ContextManager contextManager, @NotNull KeyParser keyParser, @NotNull Team mobNoPushTeam, @NotNull Map powerups, @NotNull ZombiesPlayer.Source zombiesPlayerSource) { super(maximumScenes); this.instanceSpaceFunction = Objects.requireNonNull(instanceSpaceFunction, "instanceSpaceFunction"); @@ -102,6 +104,7 @@ public ZombiesSceneProvider(int maximumScenes, Objects.requireNonNull(powerups, "powerups"); MapSettingsInfo settingsInfo = mapInfo.settings(); + this.mobNoPushTeam = settingsInfo.mobPlayerCollisions() ? null : mobNoPushTeam; this.mapObjectSource = new BasicMapObjectsSource(mapInfo, contextManager, mobSpawnerSource, mobModels, clientBlockHandlerSource, keyParser); @@ -119,7 +122,8 @@ public ZombiesSceneProvider(int maximumScenes, protected @NotNull Optional chooseScene(@NotNull ZombiesJoinRequest request) { sceneLoop: for (ZombiesScene scene : getScenes()) { - if (request.excludedScenes().contains(scene.getUUID()) || scene.isComplete() || !scene.isJoinable() || scene.isShutdown()) { + if (request.excludedScenes().contains(scene.getUUID()) || scene.isComplete() || !scene.isJoinable() || + scene.isShutdown()) { continue; } @@ -169,9 +173,8 @@ public ZombiesSceneProvider(int maximumScenes, Wrapper> eventNodeWrapper = Wrapper.ofNull(); SongPlayer songPlayer = new BasicSongPlayer(); - MapObjects mapObjects = - createMapObjects(instance, zombiesPlayers, roundHandlerWrapper, mobStore, powerupHandlerWrapper, - windowHandlerWrapper, eventNodeWrapper, songPlayer, tickTaskScheduler); + MapObjects mapObjects = createMapObjects(instance, zombiesPlayers, roundHandlerWrapper, mobStore, mobNoPushTeam, + powerupHandlerWrapper, windowHandlerWrapper, eventNodeWrapper, songPlayer, tickTaskScheduler); RoundHandler roundHandler = new BasicRoundHandler(mapObjects.rounds()); roundHandlerWrapper.set(roundHandler); @@ -251,11 +254,11 @@ protected void cleanupScene(@NotNull ZombiesScene scene) { } private MapObjects createMapObjects(Instance instance, Map zombiesPlayers, - Supplier roundHandlerSupplier, MobStore mobStore, + Supplier roundHandlerSupplier, MobStore mobStore, Team mobNoPushTeam, Wrapper powerupHandler, Wrapper windowHandler, Wrapper> eventNode, SongPlayer songPlayer, TickTaskScheduler tickTaskScheduler) { - return mapObjectSource.make(instance, zombiesPlayers, roundHandlerSupplier, mobStore, powerupHandler, - windowHandler, eventNode, songPlayer, tickTaskScheduler); + return mapObjectSource.make(instance, zombiesPlayers, roundHandlerSupplier, mobStore, mobNoPushTeam, + powerupHandler, windowHandler, eventNode, songPlayer, tickTaskScheduler); } private PowerupHandler createPowerupHandler(Instance instance, Map playerMap, diff --git a/zombies/src/main/java/org/phantazm/zombies/spawn/BasicSpawnDistributor.java b/zombies/src/main/java/org/phantazm/zombies/spawn/BasicSpawnDistributor.java index 28ed0f501..a22703e03 100644 --- a/zombies/src/main/java/org/phantazm/zombies/spawn/BasicSpawnDistributor.java +++ b/zombies/src/main/java/org/phantazm/zombies/spawn/BasicSpawnDistributor.java @@ -3,7 +3,9 @@ import it.unimi.dsi.fastutil.Pair; import net.kyori.adventure.key.Key; import net.minestom.server.entity.Player; +import net.minestom.server.scoreboard.Team; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.phantazm.mob.MobModel; import org.phantazm.mob.PhantazmMob; import org.phantazm.zombies.map.SpawnInfo; @@ -23,11 +25,15 @@ public class BasicSpawnDistributor implements SpawnDistributor { private final Collection zombiesPlayers; + private final Team mobNoPushTeam; + public BasicSpawnDistributor(@NotNull Function modelFunction, - @NotNull Random random, @NotNull Collection zombiesPlayers) { + @NotNull Random random, @NotNull Collection zombiesPlayers, + @Nullable Team mobNoPushTeam) { this.modelFunction = Objects.requireNonNull(modelFunction, "modelFunction"); this.random = Objects.requireNonNull(random, "random"); this.zombiesPlayers = Objects.requireNonNull(zombiesPlayers, "zombiesPlayers"); + this.mobNoPushTeam = mobNoPushTeam; } @Override @@ -102,7 +108,12 @@ public BasicSpawnDistributor(@NotNull Function candidateIndex %= sortedSpawnpoints.size(); if (candidate.canSpawn(model, spawnType, zombiesPlayers)) { - spawnedMobs.add(candidate.spawn(model)); + PhantazmMob mob = candidate.spawn(model); + if (mobNoPushTeam != null) { + mob.entity().setTeam(mobNoPushTeam); + } + + spawnedMobs.add(mob); spawned = true; break; } From 523c348b3d7d9c518c1681d311a9846de2921d10 Mon Sep 17 00:00:00 2001 From: steank Date: Sat, 17 Jun 2023 03:18:16 -0700 Subject: [PATCH 024/181] add block scalar signature --- server/src/main/java/org/phantazm/server/Ethylene.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/phantazm/server/Ethylene.java b/server/src/main/java/org/phantazm/server/Ethylene.java index 289369f9d..9be95e12c 100644 --- a/server/src/main/java/org/phantazm/server/Ethylene.java +++ b/server/src/main/java/org/phantazm/server/Ethylene.java @@ -24,6 +24,7 @@ import net.kyori.adventure.title.TitlePart; import net.kyori.adventure.util.RGBLike; import net.minestom.server.color.Color; +import net.minestom.server.instance.block.Block; import net.minestom.server.item.ItemStack; import net.minestom.server.particle.Particle; import org.jetbrains.annotations.NotNull; @@ -54,7 +55,7 @@ static void initialize(@NotNull KeyParser keyParser) { .withCustomSignature(bounds3D()).withCustomSignature(rgbLike()).withScalarSignature(key()) .withScalarSignature(uuid()).withScalarSignature(component()).withScalarSignature(itemStack()) .withScalarSignature(titlePartComponent()).withScalarSignature(namedTextColor()) - .withScalarSignature(particle()) + .withScalarSignature(particle()).withScalarSignature(block()) .withTypeImplementation(Object2IntOpenHashMap.class, Object2IntMap.class) .withTypeImplementation(IntOpenHashSet.class, IntSet.class).withStandardSignatures() .withStandardTypeImplementations().ignoringLengths().build(); @@ -149,6 +150,12 @@ private static ScalarSignature itemStack() { }, itemStack -> itemStack == null ? ConfigPrimitive.NULL : ConfigPrimitive.of(itemStack.toItemNBT().toSNBT())); } + private static ScalarSignature block() { + return ScalarSignature.of(Token.ofClass(Block.class), element -> { + return Objects.requireNonNullElse(Block.fromNamespaceId(element.asString()), Block.AIR); + }, block -> block == null ? ConfigPrimitive.NULL : ConfigPrimitive.of(block.name())); + } + private static ScalarSignature> titlePartComponent() { ConfigPrimitive title = ConfigPrimitive.of("TITLE"); ConfigPrimitive subtitle = ConfigPrimitive.of("SUBTITLE"); From 77902e45605692824eb96d0297925634b10c2ef4 Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Sat, 17 Jun 2023 08:10:47 -0400 Subject: [PATCH 025/181] possible revive fix --- .../main/java/org/phantazm/zombies/player/ZombiesPlayer.java | 5 ----- .../zombies/player/state/revive/NearbyReviverFinder.java | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java index 7d205c2ca..84e53f45a 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java @@ -136,11 +136,6 @@ default boolean canRevive() { return false; } - ZombiesPlayerMeta meta = module().getMeta(); - if (meta.isReviving()) { - return false; - } - return getPlayer().filter(value -> value.getPose() == Entity.Pose.SNEAKING).isPresent(); } diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/revive/NearbyReviverFinder.java b/zombies/src/main/java/org/phantazm/zombies/player/state/revive/NearbyReviverFinder.java index f125a075e..ea7e9b8ca 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/revive/NearbyReviverFinder.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/revive/NearbyReviverFinder.java @@ -55,6 +55,11 @@ public ZombiesPlayer get() { return false; } + ZombiesPlayerMeta meta = revivingPlayer.module().getMeta(); + if (meta.isReviving()) { + return false; + } + Optional reviverPlayerOptional = revivingPlayer.getPlayer(); if (reviverPlayerOptional.isEmpty()) { return false; From d5e736a8c34f72e3d1f6f71a64e3894809c24859 Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Sat, 17 Jun 2023 09:15:32 -0400 Subject: [PATCH 026/181] clear reviving actionbars, cleanup activables --- .../player/BasicZombiesPlayerSource.java | 8 ++-- .../state/BasicAliveStateActivable.java | 5 +-- .../player/state/BasicDeadStateActivable.java | 4 +- .../state/BasicKnockedStateActivable.java | 38 ++++++++++--------- .../player/state/BasicQuitStateActivable.java | 8 +--- .../player/state/revive/ReviveHandler.java | 24 ++++++------ 6 files changed, 42 insertions(+), 45 deletions(-) diff --git a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java index 97a8a4869..b9740a579 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java @@ -150,13 +150,13 @@ public BasicZombiesPlayerSource( Function aliveStateCreator = unused -> { return new BasicZombiesPlayerState(Component.text("ALIVE"), ZombiesPlayerStateKeys.ALIVE.key(), - List.of(new BasicAliveStateActivable(accessRegistry, playerView, meta, sidebar, tabList))); + List.of(new BasicAliveStateActivable(accessRegistry, playerView, sidebar, tabList))); }; BiFunction, ZombiesPlayerState> deadStateCreator = (context, activables) -> { List combinedActivables = new ArrayList<>(activables); combinedActivables.add( - new BasicDeadStateActivable(accessRegistry, context, instance, playerView, meta, sidebar, + new BasicDeadStateActivable(accessRegistry, context, instance, playerView, sidebar, tabList)); return new BasicZombiesPlayerState(Component.text("DEAD").color(NamedTextColor.RED), ZombiesPlayerStateKeys.DEAD.key(), combinedActivables); @@ -194,7 +194,7 @@ public void end() { return new KnockedPlayerState(reviveHandler, List.of(new BasicKnockedStateActivable(context, instance, playerView, reviveHandler, tickFormatter, - meta, sidebar, tabList), corpse.asKnockActivable(reviveHandler), new Activable() { + sidebar, tabList), corpse.asKnockActivable(reviveHandler), new Activable() { @Override public void start() { meta.setCorpse(corpse); @@ -204,7 +204,7 @@ public void start() { Function quitStateCreator = unused -> { return new BasicZombiesPlayerState(Component.text("QUIT").color(NamedTextColor.RED), ZombiesPlayerStateKeys.QUIT.key(), - List.of(new BasicQuitStateActivable(instance, zombiesPlayers.values(), playerView, meta, sidebar, + List.of(new BasicQuitStateActivable(instance, playerView, sidebar, tabList))); }; PlayerStateSwitcher stateSwitcher = new PlayerStateSwitcher(); diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicAliveStateActivable.java b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicAliveStateActivable.java index 141a4bfd8..944c3a33b 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicAliveStateActivable.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicAliveStateActivable.java @@ -16,17 +16,14 @@ public class BasicAliveStateActivable implements Activable { private final InventoryAccessRegistry accessRegistry; private final PlayerView playerView; - private final ZombiesPlayerMeta meta; private final Sidebar sidebar; private final TabList tabList; private long lastHeal; - public BasicAliveStateActivable(@NotNull InventoryAccessRegistry accessRegistry, @NotNull PlayerView playerView, - @NotNull ZombiesPlayerMeta meta, @NotNull Sidebar sidebar, @NotNull TabList tabList) { + public BasicAliveStateActivable(@NotNull InventoryAccessRegistry accessRegistry, @NotNull PlayerView playerView, @NotNull Sidebar sidebar, @NotNull TabList tabList) { this.accessRegistry = Objects.requireNonNull(accessRegistry, "accessRegistry"); this.playerView = Objects.requireNonNull(playerView, "playerView"); - this.meta = Objects.requireNonNull(meta, "meta"); this.sidebar = Objects.requireNonNull(sidebar, "sidebar"); this.tabList = Objects.requireNonNull(tabList, "tabList"); } diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicDeadStateActivable.java b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicDeadStateActivable.java index d78dd4a48..34398d165 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicDeadStateActivable.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicDeadStateActivable.java @@ -20,18 +20,16 @@ public class BasicDeadStateActivable implements Activable { private final DeadPlayerStateContext context; private final Instance instance; private final PlayerView playerView; - private final ZombiesPlayerMeta meta; private final Sidebar sidebar; private final TabList tabList; public BasicDeadStateActivable(@NotNull InventoryAccessRegistry accessRegistry, @NotNull DeadPlayerStateContext context, @NotNull Instance instance, @NotNull PlayerView playerView, - @NotNull ZombiesPlayerMeta meta, @NotNull Sidebar sidebar, @NotNull TabList tabList) { + @NotNull Sidebar sidebar, @NotNull TabList tabList) { this.accessRegistry = Objects.requireNonNull(accessRegistry, "accessRegistry"); this.context = Objects.requireNonNull(context, "context"); this.instance = Objects.requireNonNull(instance, "instance"); this.playerView = Objects.requireNonNull(playerView, "playerView"); - this.meta = Objects.requireNonNull(meta, "meta"); this.sidebar = Objects.requireNonNull(sidebar, "sidebar"); this.tabList = Objects.requireNonNull(tabList, "tabList"); } diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicKnockedStateActivable.java b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicKnockedStateActivable.java index 6761aa542..4ce874be8 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicKnockedStateActivable.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicKnockedStateActivable.java @@ -14,7 +14,6 @@ import org.phantazm.core.player.PlayerView; import org.phantazm.core.time.TickFormatter; import org.phantazm.zombies.player.ZombiesPlayer; -import org.phantazm.zombies.player.ZombiesPlayerMeta; import org.phantazm.zombies.player.state.context.KnockedPlayerStateContext; import org.phantazm.zombies.player.state.revive.ReviveHandler; @@ -37,17 +36,14 @@ public class BasicKnockedStateActivable implements Activable { private final TabList tabList; - private final ZombiesPlayerMeta meta; - public BasicKnockedStateActivable(@NotNull KnockedPlayerStateContext context, @NotNull Instance instance, @NotNull PlayerView playerView, @NotNull ReviveHandler reviveHandler, @NotNull TickFormatter tickFormatter, - @NotNull ZombiesPlayerMeta meta, @NotNull Sidebar sidebar, @NotNull TabList tabList) { + @NotNull Sidebar sidebar, @NotNull TabList tabList) { this.context = Objects.requireNonNull(context, "context"); this.instance = Objects.requireNonNull(instance, "instance"); this.playerView = Objects.requireNonNull(playerView, "playerView"); this.reviveHandler = Objects.requireNonNull(reviveHandler, "reviveHandler"); this.tickFormatter = Objects.requireNonNull(tickFormatter, "tickFormatter"); - this.meta = Objects.requireNonNull(meta, "meta"); this.sidebar = Objects.requireNonNull(sidebar, "sidebar"); this.tabList = tabList; } @@ -72,15 +68,20 @@ public void start() { @Override public void tick(long time) { - reviveHandler.getReviver().ifPresentOrElse(reviver -> { - Wrapper knockedDisplayName = Wrapper.ofNull(), reviverDisplayName = Wrapper.ofNull(); - CompletableFuture knockedFuture = playerView.getDisplayName().thenAccept(knockedDisplayName::set); - CompletableFuture reviverFuture = - reviver.module().getPlayerView().getDisplayName().thenAccept(reviverDisplayName::set); - CompletableFuture.allOf(knockedFuture, reviverFuture).thenAccept(v -> { - sendReviveStatus(reviver, knockedDisplayName.get(), reviverDisplayName.get()); + if (reviveHandler.isReviving()) { + reviveHandler.getReviver().ifPresent(reviver -> { + Wrapper knockedDisplayName = Wrapper.ofNull(), reviverDisplayName = Wrapper.ofNull(); + CompletableFuture knockedFuture = playerView.getDisplayName().thenAccept(knockedDisplayName::set); + CompletableFuture reviverFuture = + reviver.module().getPlayerView().getDisplayName().thenAccept(reviverDisplayName::set); + CompletableFuture.allOf(knockedFuture, reviverFuture).thenAccept(v -> { + sendReviveStatus(reviver, knockedDisplayName.get(), reviverDisplayName.get()); + }); }); - }, this::sendDyingStatus); + } + else { + sendDyingStatus(); + } } @Override @@ -92,6 +93,7 @@ public void end() { player.setFlyingSpeed(Attribute.FLYING_SPEED.defaultValue()); player.getAttribute(Attribute.MOVEMENT_SPEED).setBaseValue(0.1F); player.setGameMode(GameMode.ADVENTURE); + player.sendActionBar(Component.empty()); sidebar.addViewer(player); tabList.addViewer(player); context.getVehicle().remove(); @@ -102,13 +104,15 @@ public void end() { private void sendReviveStatus(@NotNull ZombiesPlayer reviver, @NotNull Component knockedDisplayName, @NotNull Component reviverDisplayName) { reviver.module().getPlayerView().getPlayer().ifPresent(reviverPlayer -> { - reviverPlayer.sendActionBar( + Component message = Component.textOfChildren(Component.text("Reviving "), knockedDisplayName, Component.text(" - "), - tickFormatter.format(reviveHandler.getTicksUntilRevive()))); + tickFormatter.format(reviveHandler.getTicksUntilRevive())); + reviverPlayer.sendActionBar(message); }); playerView.getPlayer().ifPresent(player -> { - player.sendActionBar(Component.textOfChildren(reviverDisplayName, Component.text(" is reviving you - "), - tickFormatter.format(reviveHandler.getTicksUntilRevive()))); + Component message = Component.textOfChildren(reviverDisplayName, Component.text(" is reviving you - "), + tickFormatter.format(reviveHandler.getTicksUntilRevive())); + player.sendActionBar(message); }); } diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java index fd0091263..af1d3cb68 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java @@ -19,18 +19,14 @@ public class BasicQuitStateActivable implements Activable { private final PlayerView playerView; - private final ZombiesPlayerMeta meta; - private final Sidebar sidebar; private final TabList tabList; - public BasicQuitStateActivable(@NotNull Instance instance, - @NotNull Collection zombiesPlayers, @NotNull PlayerView playerView, - @NotNull ZombiesPlayerMeta meta, @NotNull Sidebar sidebar, @NotNull TabList tabList) { + public BasicQuitStateActivable(@NotNull Instance instance, @NotNull PlayerView playerView, @NotNull Sidebar sidebar, + @NotNull TabList tabList) { this.instance = Objects.requireNonNull(instance, "instance"); this.playerView = Objects.requireNonNull(playerView, "playerView"); - this.meta = Objects.requireNonNull(meta, "meta"); this.sidebar = Objects.requireNonNull(sidebar, "sidebar"); this.tabList = Objects.requireNonNull(tabList, "tabList"); } diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/revive/ReviveHandler.java b/zombies/src/main/java/org/phantazm/zombies/player/state/revive/ReviveHandler.java index f5a5ccbf8..0e719320c 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/revive/ReviveHandler.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/revive/ReviveHandler.java @@ -1,6 +1,6 @@ package org.phantazm.zombies.player.state.revive; -import net.minestom.server.entity.Entity; +import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.phantazm.commons.Activable; @@ -54,7 +54,7 @@ public void tick(long time) { } if (reviver != null) { - reviver.module().getMeta().setReviving(false); + clearReviverState(); } reviver = null; @@ -66,7 +66,7 @@ public void tick(long time) { } if (reviver != null) { - reviver.module().getMeta().setReviving(false); + clearReviverState(); } reviver = null; @@ -85,7 +85,7 @@ public void tick(long time) { } } else if (!reviver.canRevive()) { - reviver.module().getMeta().setReviving(false); + clearReviverState(); reviver = null; ticksUntilRevive = -1; } @@ -96,10 +96,7 @@ else if (!reviver.canRevive()) { @Override public void end() { - if (reviver != null) { - reviver.module().getMeta().setReviving(false); - } - + clearReviverState(); reviver = null; } @@ -112,9 +109,7 @@ public void setReviver(@Nullable ZombiesPlayer reviver) { return; } - if (this.reviver != null) { - this.reviver.module().getMeta().setReviving(false); - } + clearReviverState(); this.reviver = reviver; if (reviver != null) { ticksUntilDeath = deathTime; @@ -126,6 +121,13 @@ public void setReviver(@Nullable ZombiesPlayer reviver) { } } + private void clearReviverState() { + if (reviver != null) { + reviver.module().getMeta().setReviving(false); + reviver.getPlayer().ifPresent(player -> player.sendActionBar(Component.empty())); + } + } + public boolean isReviving() { return reviver != null; } From e8b3083fe7ffd002552d086b8d641cd20eed6edf Mon Sep 17 00:00:00 2001 From: steank Date: Sat, 17 Jun 2023 08:30:42 -0700 Subject: [PATCH 027/181] cancellable API and possible fix for bossbar timers --- .../phantazm/commons/CancellableState.java | 36 +++++++++++++++ .../zombies/player/BasicZombiesPlayer.java | 45 ++++++++++++++++--- .../zombies/player/ZombiesPlayer.java | 8 ++++ .../action/AttributeModifierAction.java | 19 +++++--- .../powerup/action/BossBarTimerAction.java | 25 +++++++++-- 5 files changed, 118 insertions(+), 15 deletions(-) create mode 100644 commons/src/main/java/org/phantazm/commons/CancellableState.java diff --git a/commons/src/main/java/org/phantazm/commons/CancellableState.java b/commons/src/main/java/org/phantazm/commons/CancellableState.java new file mode 100644 index 000000000..fde9c4cee --- /dev/null +++ b/commons/src/main/java/org/phantazm/commons/CancellableState.java @@ -0,0 +1,36 @@ +package org.phantazm.commons; + +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public interface CancellableState { + void start(); + + void end(); + + @NotNull String id(); + + static @NotNull CancellableState named(@NotNull String id, @NotNull Runnable start, @NotNull Runnable end) { + Objects.requireNonNull(id, "id"); + Objects.requireNonNull(start, "start"); + Objects.requireNonNull(end, "end"); + + return new CancellableState() { + @Override + public void start() { + start.run(); + } + + @Override + public void end() { + end.run(); + } + + @Override + public @NotNull String id() { + return id; + } + }; + } +} diff --git a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java index c5e5bafb6..83e86dac5 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java @@ -4,6 +4,9 @@ import net.kyori.adventure.audience.ForwardingAudience; import net.minestom.server.entity.Player; import org.jetbrains.annotations.NotNull; +import org.phantazm.commons.BasicTickTaskScheduler; +import org.phantazm.commons.CancellableState; +import org.phantazm.commons.TickTaskScheduler; import org.phantazm.core.inventory.InventoryObject; import org.phantazm.core.inventory.InventoryProfile; import org.phantazm.zombies.Attributes; @@ -12,19 +15,20 @@ import org.phantazm.zombies.player.state.context.QuitPlayerStateContext; import org.phantazm.zombies.scene.ZombiesScene; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; public class BasicZombiesPlayer implements ZombiesPlayer, ForwardingAudience { - private final ZombiesScene scene; - private final ZombiesPlayerModule module; + private final TickTaskScheduler scheduler; + private final Map cancellables; public BasicZombiesPlayer(@NotNull ZombiesScene scene, @NotNull ZombiesPlayerModule module) { this.scene = Objects.requireNonNull(scene, "scene"); this.module = Objects.requireNonNull(module, "module"); + this.scheduler = new BasicTickTaskScheduler(); + this.cancellables = new ConcurrentHashMap<>(); } @Override @@ -43,9 +47,34 @@ public long getReviveTime() { return scene; } + @Override + public @NotNull TickTaskScheduler scheduler() { + return scheduler; + } + + @Override + public void registerCancellable(@NotNull CancellableState cancellable) { + CancellableState oldCancellable = cancellables.put(cancellable.id(), cancellable); + + if (oldCancellable != null) { + oldCancellable.end(); + } + + cancellable.start(); + } + + @Override + public void removeCancellable(@NotNull String id) { + cancellables.remove(id); + } + @Override public void start() { module.getStateSwitcher().start(); + + for (CancellableState cancellableState : cancellables.values()) { + cancellableState.start(); + } } @Override @@ -57,6 +86,11 @@ public void tick(long time) { } module.getStateSwitcher().tick(time); + scheduler.tick(time); + + for (CancellableState cancellableState : cancellables.values()) { + cancellableState.end(); + } } @Override @@ -65,6 +99,7 @@ public void end() { setState(ZombiesPlayerStateKeys.QUIT, new QuitPlayerStateContext(false)); } module.getStateSwitcher().end(); + scheduler.end(); } private void inventoryTick(Player player, long time) { diff --git a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java index 84e53f45a..4f193219f 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java @@ -10,6 +10,8 @@ import net.minestom.server.instance.Instance; import org.jetbrains.annotations.NotNull; import org.phantazm.commons.Activable; +import org.phantazm.commons.CancellableState; +import org.phantazm.commons.TickTaskScheduler; import org.phantazm.core.equipment.Equipment; import org.phantazm.core.inventory.InventoryObject; import org.phantazm.core.inventory.InventoryProfile; @@ -43,6 +45,12 @@ public interface ZombiesPlayer extends Activable, Flaggable.Source, Audience { @NotNull ZombiesScene getScene(); + @NotNull TickTaskScheduler scheduler(); + + void registerCancellable(@NotNull CancellableState cancellable); + + void removeCancellable(@NotNull String id); + default @NotNull Optional getHeldEquipment() { Optional playerOptional = module().getPlayerView().getPlayer(); if (playerOptional.isEmpty()) { diff --git a/zombies/src/main/java/org/phantazm/zombies/powerup/action/AttributeModifierAction.java b/zombies/src/main/java/org/phantazm/zombies/powerup/action/AttributeModifierAction.java index 4789ae199..f59a11830 100644 --- a/zombies/src/main/java/org/phantazm/zombies/powerup/action/AttributeModifierAction.java +++ b/zombies/src/main/java/org/phantazm/zombies/powerup/action/AttributeModifierAction.java @@ -5,6 +5,7 @@ import net.minestom.server.attribute.AttributeModifier; import net.minestom.server.attribute.AttributeOperation; import org.jetbrains.annotations.NotNull; +import org.phantazm.commons.CancellableState; import org.phantazm.zombies.Attributes; import org.phantazm.zombies.player.ZombiesPlayer; import org.phantazm.zombies.powerup.Powerup; @@ -62,16 +63,20 @@ private Action(Data data, DeactivationPredicate deactivationPredicate, } private void applyAttribute(ZombiesPlayer player) { - player.getPlayer().ifPresent(p -> { - p.getAttribute(attribute).addModifier( - new AttributeModifier(attributeUID, attributeName, data.amount, data.attributeOperation)); - }); + player.registerCancellable(CancellableState.named(attributeName, () -> { + player.getPlayer().ifPresent(p -> { + p.getAttribute(attribute).addModifier( + new AttributeModifier(attributeUID, attributeName, data.amount, data.attributeOperation)); + }); + }, () -> { + player.getPlayer().ifPresent(p -> { + p.getAttribute(attribute).removeModifier(attributeUID); + }); + })); } private void removeAttribute(ZombiesPlayer player) { - player.getPlayer().ifPresent(p -> { - p.getAttribute(attribute).removeModifier(attributeUID); - }); + player.removeCancellable(attributeName); } @Override diff --git a/zombies/src/main/java/org/phantazm/zombies/powerup/action/BossBarTimerAction.java b/zombies/src/main/java/org/phantazm/zombies/powerup/action/BossBarTimerAction.java index c42ce9ef5..539be8752 100644 --- a/zombies/src/main/java/org/phantazm/zombies/powerup/action/BossBarTimerAction.java +++ b/zombies/src/main/java/org/phantazm/zombies/powerup/action/BossBarTimerAction.java @@ -6,11 +6,14 @@ import net.minestom.server.MinecraftServer; import net.minestom.server.instance.Instance; import org.jetbrains.annotations.NotNull; +import org.phantazm.commons.CancellableState; import org.phantazm.commons.MathUtils; import org.phantazm.zombies.player.ZombiesPlayer; import org.phantazm.zombies.powerup.Powerup; import org.phantazm.zombies.powerup.predicate.DeactivationPredicate; +import java.util.Map; +import java.util.UUID; import java.util.function.Supplier; @Model("zombies.powerup.action.boss_bar_timer") @@ -18,27 +21,32 @@ public class BossBarTimerAction implements Supplier { private final Data data; private final Instance instance; + private final Map playerMap; @FactoryMethod - public BossBarTimerAction(@NotNull Data data, @NotNull Instance instance) { + public BossBarTimerAction(@NotNull Data data, @NotNull Instance instance, + @NotNull Map playerMap) { this.data = data; this.instance = instance; + this.playerMap = playerMap; } @Override public PowerupAction get() { - return new Action(data, instance); + return new Action(data, instance, playerMap); } private static class Action implements PowerupAction { private final Data data; private final Instance instance; private final DeactivationPredicate predicate; + private final Map playerMap; + private final String name; private long startTime = -1; private BossBar bossBar; - private Action(Data data, Instance instance) { + private Action(Data data, Instance instance, Map playerMap) { this.data = data; this.instance = instance; this.predicate = new DeactivationPredicate() { @@ -52,6 +60,8 @@ public boolean shouldDeactivate(long time) { return (time - startTime) / MinecraftServer.TICK_MS >= data.duration; } }; + this.playerMap = playerMap; + this.name = UUID.randomUUID().toString(); } @Override @@ -73,6 +83,15 @@ public void activate(@NotNull Powerup powerup, @NotNull ZombiesPlayer player, lo instance.showBossBar(bossBar); this.bossBar = bossBar; + + for (ZombiesPlayer zombiesPlayer : playerMap.values()) { + zombiesPlayer.registerCancellable(CancellableState.named(name, () -> { + }, () -> { + zombiesPlayer.getPlayer().ifPresent(actualPlayer -> { + actualPlayer.hideBossBar(bossBar); + }); + })); + } } @Override From 810a1e518e68df23d54c5eb98f2d74ba71a176fa Mon Sep 17 00:00:00 2001 From: steank Date: Sat, 17 Jun 2023 08:34:22 -0700 Subject: [PATCH 028/181] cancellable API and possible fix for bossbar timers --- .../org/phantazm/commons/CancellableState.java | 7 ++++--- .../zombies/player/BasicZombiesPlayer.java | 4 ++-- .../phantazm/zombies/player/ZombiesPlayer.java | 2 +- .../powerup/action/AttributeModifierAction.java | 4 ++-- .../powerup/action/BossBarTimerAction.java | 17 ++++++++--------- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/commons/src/main/java/org/phantazm/commons/CancellableState.java b/commons/src/main/java/org/phantazm/commons/CancellableState.java index fde9c4cee..71be0f6f1 100644 --- a/commons/src/main/java/org/phantazm/commons/CancellableState.java +++ b/commons/src/main/java/org/phantazm/commons/CancellableState.java @@ -3,15 +3,16 @@ import org.jetbrains.annotations.NotNull; import java.util.Objects; +import java.util.UUID; public interface CancellableState { void start(); void end(); - @NotNull String id(); + @NotNull UUID id(); - static @NotNull CancellableState named(@NotNull String id, @NotNull Runnable start, @NotNull Runnable end) { + static @NotNull CancellableState named(@NotNull UUID id, @NotNull Runnable start, @NotNull Runnable end) { Objects.requireNonNull(id, "id"); Objects.requireNonNull(start, "start"); Objects.requireNonNull(end, "end"); @@ -28,7 +29,7 @@ public void end() { } @Override - public @NotNull String id() { + public @NotNull UUID id() { return id; } }; diff --git a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java index 83e86dac5..86d5821b5 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java @@ -22,7 +22,7 @@ public class BasicZombiesPlayer implements ZombiesPlayer, ForwardingAudience { private final ZombiesScene scene; private final ZombiesPlayerModule module; private final TickTaskScheduler scheduler; - private final Map cancellables; + private final Map cancellables; public BasicZombiesPlayer(@NotNull ZombiesScene scene, @NotNull ZombiesPlayerModule module) { this.scene = Objects.requireNonNull(scene, "scene"); @@ -64,7 +64,7 @@ public void registerCancellable(@NotNull CancellableState cancellable) { } @Override - public void removeCancellable(@NotNull String id) { + public void removeCancellable(@NotNull UUID id) { cancellables.remove(id); } diff --git a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java index 4f193219f..18e2b5111 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayer.java @@ -49,7 +49,7 @@ public interface ZombiesPlayer extends Activable, Flaggable.Source, Audience { void registerCancellable(@NotNull CancellableState cancellable); - void removeCancellable(@NotNull String id); + void removeCancellable(@NotNull UUID id); default @NotNull Optional getHeldEquipment() { Optional playerOptional = module().getPlayerView().getPlayer(); diff --git a/zombies/src/main/java/org/phantazm/zombies/powerup/action/AttributeModifierAction.java b/zombies/src/main/java/org/phantazm/zombies/powerup/action/AttributeModifierAction.java index f59a11830..99b205dbd 100644 --- a/zombies/src/main/java/org/phantazm/zombies/powerup/action/AttributeModifierAction.java +++ b/zombies/src/main/java/org/phantazm/zombies/powerup/action/AttributeModifierAction.java @@ -63,7 +63,7 @@ private Action(Data data, DeactivationPredicate deactivationPredicate, } private void applyAttribute(ZombiesPlayer player) { - player.registerCancellable(CancellableState.named(attributeName, () -> { + player.registerCancellable(CancellableState.named(attributeUID, () -> { player.getPlayer().ifPresent(p -> { p.getAttribute(attribute).addModifier( new AttributeModifier(attributeUID, attributeName, data.amount, data.attributeOperation)); @@ -76,7 +76,7 @@ private void applyAttribute(ZombiesPlayer player) { } private void removeAttribute(ZombiesPlayer player) { - player.removeCancellable(attributeName); + player.removeCancellable(attributeUID); } @Override diff --git a/zombies/src/main/java/org/phantazm/zombies/powerup/action/BossBarTimerAction.java b/zombies/src/main/java/org/phantazm/zombies/powerup/action/BossBarTimerAction.java index 539be8752..c4a9bf1b7 100644 --- a/zombies/src/main/java/org/phantazm/zombies/powerup/action/BossBarTimerAction.java +++ b/zombies/src/main/java/org/phantazm/zombies/powerup/action/BossBarTimerAction.java @@ -41,7 +41,7 @@ private static class Action implements PowerupAction { private final Instance instance; private final DeactivationPredicate predicate; private final Map playerMap; - private final String name; + private final UUID id; private long startTime = -1; private BossBar bossBar; @@ -61,7 +61,7 @@ public boolean shouldDeactivate(long time) { } }; this.playerMap = playerMap; - this.name = UUID.randomUUID().toString(); + this.id = UUID.randomUUID(); } @Override @@ -85,12 +85,8 @@ public void activate(@NotNull Powerup powerup, @NotNull ZombiesPlayer player, lo this.bossBar = bossBar; for (ZombiesPlayer zombiesPlayer : playerMap.values()) { - zombiesPlayer.registerCancellable(CancellableState.named(name, () -> { - }, () -> { - zombiesPlayer.getPlayer().ifPresent(actualPlayer -> { - actualPlayer.hideBossBar(bossBar); - }); - })); + zombiesPlayer.registerCancellable(CancellableState.named(id, () -> { + }, () -> zombiesPlayer.getPlayer().ifPresent(actualPlayer -> actualPlayer.hideBossBar(bossBar)))); } } @@ -98,7 +94,10 @@ public void activate(@NotNull Powerup powerup, @NotNull ZombiesPlayer player, lo public void deactivate(@NotNull ZombiesPlayer player) { BossBar bossBar = this.bossBar; if (bossBar != null) { - MinecraftServer.getBossBarManager().destroyBossBar(bossBar); + for (ZombiesPlayer zombiesPlayer : playerMap.values()) { + zombiesPlayer.removeCancellable(id); + } + this.bossBar = null; } } From 12c3c14169ce62da8bf5ed499f78f91cf52a52d7 Mon Sep 17 00:00:00 2001 From: steank Date: Sat, 17 Jun 2023 08:54:28 -0700 Subject: [PATCH 029/181] put cancellable state map reference in BasicQuitStateActivable & call when necessary --- .../zombies/player/BasicZombiesPlayer.java | 21 ++++++------------- .../player/BasicZombiesPlayerSource.java | 8 ++++--- .../player/state/BasicQuitStateActivable.java | 17 +++++++++++---- .../phantazm/zombies/scene/ZombiesScene.java | 15 ++++++++++--- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java index 86d5821b5..d6d9f0bd1 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java @@ -16,19 +16,19 @@ import org.phantazm.zombies.scene.ZombiesScene; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; public class BasicZombiesPlayer implements ZombiesPlayer, ForwardingAudience { private final ZombiesScene scene; private final ZombiesPlayerModule module; private final TickTaskScheduler scheduler; - private final Map cancellables; + private final Map stateMap; - public BasicZombiesPlayer(@NotNull ZombiesScene scene, @NotNull ZombiesPlayerModule module) { + public BasicZombiesPlayer(@NotNull ZombiesScene scene, @NotNull ZombiesPlayerModule module, + @NotNull Map stateMap) { this.scene = Objects.requireNonNull(scene, "scene"); this.module = Objects.requireNonNull(module, "module"); this.scheduler = new BasicTickTaskScheduler(); - this.cancellables = new ConcurrentHashMap<>(); + this.stateMap = Objects.requireNonNull(stateMap, "stateMap"); } @Override @@ -54,7 +54,7 @@ public long getReviveTime() { @Override public void registerCancellable(@NotNull CancellableState cancellable) { - CancellableState oldCancellable = cancellables.put(cancellable.id(), cancellable); + CancellableState oldCancellable = stateMap.put(cancellable.id(), cancellable); if (oldCancellable != null) { oldCancellable.end(); @@ -65,16 +65,12 @@ public void registerCancellable(@NotNull CancellableState cancellable) { @Override public void removeCancellable(@NotNull UUID id) { - cancellables.remove(id); + stateMap.remove(id); } @Override public void start() { module.getStateSwitcher().start(); - - for (CancellableState cancellableState : cancellables.values()) { - cancellableState.start(); - } } @Override @@ -87,10 +83,6 @@ public void tick(long time) { module.getStateSwitcher().tick(time); scheduler.tick(time); - - for (CancellableState cancellableState : cancellables.values()) { - cancellableState.end(); - } } @Override @@ -123,7 +115,6 @@ private void inventoryTick(Player player, long time) { return module.flags(); } - @Override public @NotNull Iterable audiences() { Optional playerOptional = getPlayer(); diff --git a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java index b9740a579..517b078e9 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java @@ -22,6 +22,7 @@ import org.jglrxavpok.hephaistos.nbt.NBTException; import org.jglrxavpok.hephaistos.parser.SNBTParser; import org.phantazm.commons.Activable; +import org.phantazm.commons.CancellableState; import org.phantazm.core.entity.fakeplayer.MinimalFakePlayer; import org.phantazm.core.equipment.EquipmentCreator; import org.phantazm.core.equipment.EquipmentHandler; @@ -61,6 +62,7 @@ import java.io.StringReader; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; @@ -201,11 +203,11 @@ public void start() { } })); }; + Map stateMap = new ConcurrentHashMap<>(); Function quitStateCreator = unused -> { return new BasicZombiesPlayerState(Component.text("QUIT").color(NamedTextColor.RED), ZombiesPlayerStateKeys.QUIT.key(), - List.of(new BasicQuitStateActivable(instance, playerView, sidebar, - tabList))); + List.of(new BasicQuitStateActivable(instance, playerView, sidebar, tabList, stateMap))); }; PlayerStateSwitcher stateSwitcher = new PlayerStateSwitcher(); Map, Function> stateFunctions = @@ -219,7 +221,7 @@ public void start() { accessRegistry, stateSwitcher, stateFunctions, sidebar, tabList, mapTransactionModifierSource, playerTransactionModifierSource, flaggable); - ZombiesPlayer zombiesPlayer = new BasicZombiesPlayer(scene, module); + ZombiesPlayer zombiesPlayer = new BasicZombiesPlayer(scene, module, stateMap); zombiesPlayerWrapper.set(zombiesPlayer); return zombiesPlayer; } diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java index af1d3cb68..bfb19bac2 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java @@ -6,12 +6,12 @@ import net.minestom.server.scoreboard.TabList; import org.jetbrains.annotations.NotNull; import org.phantazm.commons.Activable; +import org.phantazm.commons.CancellableState; import org.phantazm.core.player.PlayerView; -import org.phantazm.zombies.player.ZombiesPlayer; -import org.phantazm.zombies.player.ZombiesPlayerMeta; -import java.util.Collection; +import java.util.Map; import java.util.Objects; +import java.util.UUID; public class BasicQuitStateActivable implements Activable { @@ -23,12 +23,15 @@ public class BasicQuitStateActivable implements Activable { private final TabList tabList; + private final Map stateMap; + public BasicQuitStateActivable(@NotNull Instance instance, @NotNull PlayerView playerView, @NotNull Sidebar sidebar, - @NotNull TabList tabList) { + @NotNull TabList tabList, @NotNull Map stateMap) { this.instance = Objects.requireNonNull(instance, "instance"); this.playerView = Objects.requireNonNull(playerView, "playerView"); this.sidebar = Objects.requireNonNull(sidebar, "sidebar"); this.tabList = Objects.requireNonNull(tabList, "tabList"); + this.stateMap = Objects.requireNonNull(stateMap, "stateMap"); } @Override @@ -42,6 +45,12 @@ public void start() { }); playerView.getDisplayName() .thenAccept(displayName -> instance.sendMessage(displayName.append(Component.text(" quit.")))); + + for (CancellableState state : stateMap.values()) { + state.end(); + } + + stateMap.clear(); } } diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java index 3c77e1cef..0f70221cf 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java @@ -132,11 +132,12 @@ public boolean isComplete() { teleportedPlayers.add(player); if (player.getInstance() == instance) { futures.add(player.teleport(pos)); - } else { + } + else { futures.add(player.setInstance(instance, pos)); } runnables.add(() -> { - zombiesPlayer.setState(ZombiesPlayerStateKeys.DEAD, DeadPlayerStateContext.rejoin()); + zombiesPlayer.setState(ZombiesPlayerStateKeys.DEAD, DeadPlayerStateContext.rejoin()); }); }); } @@ -146,7 +147,8 @@ public boolean isComplete() { teleportedPlayers.add(player); if (player.getInstance() == instance) { futures.add(player.teleport(pos)); - } else { + } + else { futures.add(player.setInstance(instance, pos)); } runnables.add(() -> { @@ -199,6 +201,13 @@ public boolean isComplete() { @Override public @NotNull RouteResult leave(@NotNull Iterable leavers) { + for (UUID uuid : leavers) { + ZombiesPlayer zombiesPlayer = zombiesPlayers.get(uuid); + if (zombiesPlayer != null) { + zombiesPlayer.end(); + } + } + return leaveHandler.leave(leavers); } From c7e918d99f6837b79f37db177bbf36bfd14b4b2a Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Sat, 17 Jun 2023 15:50:56 -0400 Subject: [PATCH 030/181] add basic zombies stats, add sqlite database functionality --- defaultRunData/server-1/zombies.db | Bin 0 -> 16384 bytes .../server-1/zombies.hikari.properties | 2 + gradle/libs.versions.toml | 4 + mob/build.gradle.kts | 5 +- proxima-minestom/build.gradle.kts | 2 +- server/build.gradle.kts | 2 + .../org/phantazm/server/EquipmentFeature.java | 1 + .../org/phantazm/server/PhantazmServer.java | 10 +- .../org/phantazm/server/ZombiesFeature.java | 26 ++- zombies/build.gradle.kts | 7 +- .../equipment/gun/ZombiesEquipmentModule.java | 13 +- .../ZombiesPlayerMapStatsShotHandler.java | 37 +++++ .../zombies/kill/BasicPlayerKills.java | 11 ++ .../map/handler/BasicRoundHandler.java | 14 +- .../player/BasicZombiesPlayerSource.java | 12 +- .../zombies/player/ZombiesPlayerModule.java | 10 +- .../player/state/PlayerStateSwitcher.java | 15 +- .../player/state/revive/ReviveHandler.java | 1 + .../phantazm/zombies/scene/ZombiesScene.java | 6 +- .../zombies/scene/ZombiesSceneProvider.java | 10 +- .../phantazm/zombies/stage/InGameStage.java | 5 + .../stats/BasicZombiesPlayerMapStats.java | 151 ++++++++++++++++++ .../zombies/stats/HikariZombiesDatabase.java | 51 ++++++ .../zombies/stats/SqliteZombiesDatabase.java | 55 +++++++ .../zombies/stats/ZombiesDatabase.java | 9 ++ .../zombies/stats/ZombiesPlayerMapStats.java | 50 ++++++ .../zombies/kill/BasicPlayerKillsTest.java | 10 +- 27 files changed, 487 insertions(+), 32 deletions(-) create mode 100644 defaultRunData/server-1/zombies.db create mode 100644 defaultRunData/server-1/zombies.hikari.properties create mode 100644 zombies/src/main/java/org/phantazm/zombies/equipment/gun/shoot/handler/ZombiesPlayerMapStatsShotHandler.java create mode 100644 zombies/src/main/java/org/phantazm/zombies/stats/BasicZombiesPlayerMapStats.java create mode 100644 zombies/src/main/java/org/phantazm/zombies/stats/HikariZombiesDatabase.java create mode 100644 zombies/src/main/java/org/phantazm/zombies/stats/SqliteZombiesDatabase.java create mode 100644 zombies/src/main/java/org/phantazm/zombies/stats/ZombiesDatabase.java create mode 100644 zombies/src/main/java/org/phantazm/zombies/stats/ZombiesPlayerMapStats.java diff --git a/defaultRunData/server-1/zombies.db b/defaultRunData/server-1/zombies.db new file mode 100644 index 0000000000000000000000000000000000000000..a5da2e00c121b962d7d45445837bb2d80f3b66ff GIT binary patch literal 16384 zcmeI2Pm9w)7{-%y(YDKW7i8&m*wZew(o$BpN?}*&sRhyP!CRa(lQuN}noO$Qs|tP! z*$*Ii@dNn5JUEjk+O-K~@m8J}CX<q)2vBJ*^TEY1%lpO*tf^{@ao4J)aXVcAQ3{l24tnrCdlNUp1j__M%BL+v9A) z!hdqTx4kIKBl~<+=*ONJ=}{am>;*FmR5ROg)|2JuntA?swkFG0nT+!3R#nL4`}~#V z=L*>*c4(+aQ=dz1zG}*-nJJ1%jD0WSAr&b|Q8D#kmXt{*2}0YY;gZO5ovu~4LDC|g zRnNrf?%RBzDz;~`57FEa=Ruvu+)u`O;Zw|s&fP$7ZxM(Sr218w`{N@uaq{P`^!2@+ ztle>P(L-~5oVYVHaP`l|SKiL%8|02%H!4IDpKeZXH6~e^a`Ts|4L283=WQ-Xv%M-k zsE>R1u2o@?WCV|V!e|!S?4b3yN?*IS* literal 0 HcmV?d00001 diff --git a/defaultRunData/server-1/zombies.hikari.properties b/defaultRunData/server-1/zombies.hikari.properties new file mode 100644 index 000000000..6e2cae748 --- /dev/null +++ b/defaultRunData/server-1/zombies.hikari.properties @@ -0,0 +1,2 @@ +dataSourceClassName=org.sqlite.SQLiteDataSource +dataSource.url=jdbc:sqlite:zombies.db diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2ae356e14..899d86dc2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -41,6 +41,8 @@ fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version = "0.83.0+ fastutil = { module = "it.unimi.dsi:fastutil", version = "8.5.8" } +hikariCP = { module = "com.zaxxer:HikariCP", version = "5.0.1" } + jetbrains-annotations = { module = "org.jetbrains:annotations", version = "23.0.0" } junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit-jupiter" } @@ -60,6 +62,8 @@ proxima-core = { module = "com.github.steanky:proxima-core", version = "0.4.3" } renderer = { module = "com.github.0x3C50:Renderer", version = "e1bb03f45e" } +sqlite = { module = "org.xerial:sqlite-jdbc", version = "3.42.0.0" } + snakeyaml = { module = "org.snakeyaml:snakeyaml-engine", version = "2.3" } toolkit-collection = { module = "com.github.steanky:toolkit-collection", version.ref = "toolkit" } diff --git a/mob/build.gradle.kts b/mob/build.gradle.kts index 2ea367de2..b62641911 100644 --- a/mob/build.gradle.kts +++ b/mob/build.gradle.kts @@ -4,7 +4,6 @@ plugins { dependencies { api(projects.phantazmProximaMinestom) - implementation(projects.phantazmCore) - implementation(projects.phantazmCommons) - implementation(libs.adventure.text.minimessage) + api(projects.phantazmCore) + api(projects.phantazmCommons) } diff --git a/proxima-minestom/build.gradle.kts b/proxima-minestom/build.gradle.kts index b373b97aa..b45299f6c 100644 --- a/proxima-minestom/build.gradle.kts +++ b/proxima-minestom/build.gradle.kts @@ -4,5 +4,5 @@ plugins { dependencies { api(libs.proxima.core) - implementation(projects.phantazmCore) + api(projects.phantazmCore) } diff --git a/server/build.gradle.kts b/server/build.gradle.kts index 0c168a1fb..c2bebc9d1 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -22,6 +22,8 @@ dependencies { implementation(libs.ethylene.json) implementation(libs.element.core) implementation(libs.ethylene.mapper) + + runtimeOnly(libs.sqlite) } tasks.getByName("copyLibs") { diff --git a/server/src/main/java/org/phantazm/server/EquipmentFeature.java b/server/src/main/java/org/phantazm/server/EquipmentFeature.java index a254a8439..e9291c5d9 100644 --- a/server/src/main/java/org/phantazm/server/EquipmentFeature.java +++ b/server/src/main/java/org/phantazm/server/EquipmentFeature.java @@ -215,6 +215,7 @@ private static void registerElementClasses(@NotNull ContextManager contextManage contextManager.registerElementClass(PotionShotHandler.class); contextManager.registerElementClass(SlowDownShotHandler.class); contextManager.registerElementClass(SoundShotHandler.class); + contextManager.registerElementClass(ZombiesPlayerMapStatsShotHandler.class); contextManager.registerElementClass(StateShootTester.class); contextManager.registerElementClass(AroundEndFinder.class); contextManager.registerElementClass(BetweenPointsFinder.class); diff --git a/server/src/main/java/org/phantazm/server/PhantazmServer.java b/server/src/main/java/org/phantazm/server/PhantazmServer.java index d1eff3265..af69bf20d 100644 --- a/server/src/main/java/org/phantazm/server/PhantazmServer.java +++ b/server/src/main/java/org/phantazm/server/PhantazmServer.java @@ -59,6 +59,8 @@ public final class PhantazmServer { public static final Path BANS_FILE = Path.of("./bans.txt"); public static final Path WHITELIST_FILE = Path.of("./whitelist.txt"); + private static LoginValidator loginValidator; + /** * Starting point for the server. * @@ -126,7 +128,7 @@ else if (serverInfoConfig.isUnsafeConfiguration()) { return; } - LoginValidator loginValidator = + loginValidator = new BasicLoginValidator(serverConfig.serverInfoConfig().whitelist(), WHITELIST_FILE, BANS_FILE); EventNode node = MinecraftServer.getGlobalEventHandler(); @@ -145,8 +147,6 @@ else if (serverInfoConfig.isUnsafeConfiguration()) { if (!MinecraftServer.isStopping()) { shutdown("interrupt"); } - - loginValidator.flush(); })); MinecraftServer.setBrandName(BRAND_NAME); @@ -162,6 +162,10 @@ else if (serverInfoConfig.isUnsafeConfiguration()) { public static void shutdown(@Nullable String reason) { LOGGER.info("Shutting down server. Reason: " + reason); + + ZombiesFeature.getDatabase().close(); + loginValidator.flush(); + MinecraftServer.stopCleanly(); } diff --git a/server/src/main/java/org/phantazm/server/ZombiesFeature.java b/server/src/main/java/org/phantazm/server/ZombiesFeature.java index c3482851d..64f1e3bd1 100644 --- a/server/src/main/java/org/phantazm/server/ZombiesFeature.java +++ b/server/src/main/java/org/phantazm/server/ZombiesFeature.java @@ -5,6 +5,8 @@ import com.github.steanky.ethylene.codec.yaml.YamlCodec; import com.github.steanky.ethylene.core.ConfigCodec; import com.github.steanky.ethylene.core.processor.ConfigProcessor; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; import it.unimi.dsi.fastutil.booleans.BooleanObjectPair; import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Keyed; @@ -27,9 +29,7 @@ import org.phantazm.core.VecUtils; import org.phantazm.core.equipment.LinearUpgradePath; import org.phantazm.core.equipment.NoUpgradePath; -import org.phantazm.core.game.scene.Scene; import org.phantazm.core.game.scene.fallback.SceneFallback; -import org.phantazm.core.game.scene.lobby.Lobby; import org.phantazm.core.guild.party.Party; import org.phantazm.core.instance.AnvilFileSystemInstanceLoader; import org.phantazm.core.instance.InstanceLoader; @@ -89,12 +89,20 @@ import org.phantazm.zombies.sidebar.section.CollectionSidebarSection; import org.phantazm.zombies.sidebar.section.ZombiesPlayerSection; import org.phantazm.zombies.sidebar.section.ZombiesPlayersSection; +import org.phantazm.zombies.stats.HikariZombiesDatabase; +import org.phantazm.zombies.stats.OracleZombiesDatabase; +import org.phantazm.zombies.stats.SqliteZombiesDatabase; +import org.phantazm.zombies.stats.ZombiesDatabase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.file.Path; +import java.sql.Connection; +import java.sql.SQLException; import java.util.*; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import java.util.function.Function; public final class ZombiesFeature { @@ -108,6 +116,7 @@ public final class ZombiesFeature { private static Map powerups; private static MobSpawnerSource mobSpawnerSource; private static ZombiesSceneRouter sceneRouter; + private static HikariZombiesDatabase database; static void initialize(@NotNull EventNode globalEventNode, @NotNull ContextManager contextManager, @NotNull Map, ConfigProcessor> processorMap, @NotNull Spawner spawner, @@ -142,6 +151,13 @@ static void initialize(@NotNull EventNode globalEventNode, @NotNull Conte // https://bugs.mojang.com/browse/MC-87984 Team mobNoPushTeam = teamManager.createBuilder("mobNoPush").collisionRule(TeamsPacket.CollisionRule.PUSH_OTHER_TEAMS).build(); + Executor databaseExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); + HikariConfig config = new HikariConfig("./zombies.hikari.properties"); + HikariDataSource dataSource = new HikariDataSource(config); + database = switch (dataSource.getDataSourceClassName()) { + case "org.sqlite.SQLiteDataSource" -> new SqliteZombiesDatabase(databaseExecutor, dataSource); + default -> throw new RuntimeException("Unknown data source " + dataSource.getDataSourceClassName()); + }; for (Map.Entry entry : maps.entrySet()) { ZombiesSceneProvider provider = new ZombiesSceneProvider(2, instanceSpaceFunction, entry.getValue(), connectionManager, @@ -150,7 +166,7 @@ static void initialize(@NotNull EventNode globalEventNode, @NotNull Conte DimensionType dimensionType = instance.getDimensionType(); return new InstanceClientBlockHandler(instance, globalEventNode, dimensionType.getMinY(), dimensionType.getHeight()); - }), contextManager, keyParser, mobNoPushTeam, ZombiesFeature.powerups(), + }), contextManager, keyParser, mobNoPushTeam, database, ZombiesFeature.powerups(), new BasicZombiesPlayerSource(EquipmentFeature::createEquipmentCreator, corpseTeam, Mob.getModels())); providers.put(entry.getKey(), provider); @@ -364,4 +380,8 @@ private static Map loadFeature(String featureName, Loa public static @NotNull ZombiesSceneRouter zombiesSceneRouter() { return FeatureUtils.check(sceneRouter); } + + public static @NotNull HikariZombiesDatabase getDatabase() { + return database; + } } diff --git a/zombies/build.gradle.kts b/zombies/build.gradle.kts index 599163540..e4aeed5be 100644 --- a/zombies/build.gradle.kts +++ b/zombies/build.gradle.kts @@ -4,9 +4,10 @@ plugins { } dependencies { - implementation(projects.phantazmCore) - implementation(projects.phantazmMob) - implementation(projects.phantazmZombiesMapdata) + api(projects.phantazmCore) + api(projects.phantazmMob) + api(projects.phantazmZombiesMapdata) + api(libs.hikariCP) } elementAutodoc { diff --git a/zombies/src/main/java/org/phantazm/zombies/equipment/gun/ZombiesEquipmentModule.java b/zombies/src/main/java/org/phantazm/zombies/equipment/gun/ZombiesEquipmentModule.java index 9f3716096..39fe8b99d 100644 --- a/zombies/src/main/java/org/phantazm/zombies/equipment/gun/ZombiesEquipmentModule.java +++ b/zombies/src/main/java/org/phantazm/zombies/equipment/gun/ZombiesEquipmentModule.java @@ -14,6 +14,7 @@ import org.phantazm.mob.spawner.MobSpawner; import org.phantazm.zombies.map.objects.MapObjects; import org.phantazm.zombies.player.ZombiesPlayer; +import org.phantazm.zombies.stats.ZombiesPlayerMapStats; import java.util.*; import java.util.function.Function; @@ -25,6 +26,7 @@ public class ZombiesEquipmentModule implements DependencyModule { private final Map playerMap; private final PlayerView playerView; + private final ZombiesPlayerMapStats mapStats; private final MobSpawner mobSpawner; private final MobStore mobStore; private final EventNode eventNode; @@ -34,12 +36,13 @@ public class ZombiesEquipmentModule implements DependencyModule { private final Function mobModelFunction; public ZombiesEquipmentModule(@NotNull Map playerMap, - @NotNull PlayerView playerView, @NotNull MobSpawner mobSpawner, @NotNull MobStore mobStore, - @NotNull EventNode eventNode, @NotNull Random random, @NotNull MapObjects mapObjects, - @NotNull Supplier zombiesPlayerSupplier, + @NotNull PlayerView playerView, @NotNull ZombiesPlayerMapStats mapStats, @NotNull MobSpawner mobSpawner, + @NotNull MobStore mobStore, @NotNull EventNode eventNode, @NotNull Random random, + @NotNull MapObjects mapObjects, @NotNull Supplier zombiesPlayerSupplier, @NotNull Function mobModelFunction) { this.playerMap = Objects.requireNonNull(playerMap, "playerMap"); this.playerView = Objects.requireNonNull(playerView, "playerView"); + this.mapStats = Objects.requireNonNull(mapStats, "mapStats"); this.mobSpawner = Objects.requireNonNull(mobSpawner, "mobSpawner"); this.mobStore = Objects.requireNonNull(mobStore, "mobStore"); this.eventNode = Objects.requireNonNull(eventNode, "eventNode"); @@ -57,6 +60,10 @@ public ZombiesEquipmentModule(@NotNull Map> getPlayerSupplier() { return playerView::getPlayer; } diff --git a/zombies/src/main/java/org/phantazm/zombies/equipment/gun/shoot/handler/ZombiesPlayerMapStatsShotHandler.java b/zombies/src/main/java/org/phantazm/zombies/equipment/gun/shoot/handler/ZombiesPlayerMapStatsShotHandler.java new file mode 100644 index 000000000..0fdd182db --- /dev/null +++ b/zombies/src/main/java/org/phantazm/zombies/equipment/gun/shoot/handler/ZombiesPlayerMapStatsShotHandler.java @@ -0,0 +1,37 @@ +package org.phantazm.zombies.equipment.gun.shoot.handler; + +import com.github.steanky.element.core.annotation.FactoryMethod; +import com.github.steanky.element.core.annotation.Model; +import net.minestom.server.entity.Entity; +import org.jetbrains.annotations.NotNull; +import org.phantazm.zombies.equipment.gun.Gun; +import org.phantazm.zombies.equipment.gun.GunState; +import org.phantazm.zombies.equipment.gun.shoot.GunShot; +import org.phantazm.zombies.stats.ZombiesPlayerMapStats; + +import java.util.Collection; +import java.util.Objects; +import java.util.UUID; + +@Model("zombies.gun.shot_handler.zombies_player_map_stats") +public class ZombiesPlayerMapStatsShotHandler implements ShotHandler { + + private final ZombiesPlayerMapStats stats; + + @FactoryMethod + public ZombiesPlayerMapStatsShotHandler(@NotNull ZombiesPlayerMapStats stats) { + this.stats = Objects.requireNonNull(stats, "stats"); + } + + @Override + public void tick(@NotNull GunState state, long time) { + + } + + @Override + public void handle(@NotNull Gun gun, @NotNull GunState state, @NotNull Entity attacker, + @NotNull Collection previousHits, @NotNull GunShot shot) { + stats.setRegularShots(stats.getRegularShots() + shot.regularTargets().size()); + stats.setHeadshots(stats.getHeadshots() + shot.headshotTargets().size()); + } +} diff --git a/zombies/src/main/java/org/phantazm/zombies/kill/BasicPlayerKills.java b/zombies/src/main/java/org/phantazm/zombies/kill/BasicPlayerKills.java index 61f17076b..0782154e4 100644 --- a/zombies/src/main/java/org/phantazm/zombies/kill/BasicPlayerKills.java +++ b/zombies/src/main/java/org/phantazm/zombies/kill/BasicPlayerKills.java @@ -2,13 +2,24 @@ import org.jetbrains.annotations.NotNull; import org.phantazm.mob.PhantazmMob; +import org.phantazm.zombies.stats.ZombiesPlayerMapStats; + +import java.util.Objects; public class BasicPlayerKills implements PlayerKills { + + private final ZombiesPlayerMapStats stats; + private int kills = 0; + public BasicPlayerKills(@NotNull ZombiesPlayerMapStats stats) { + this.stats = Objects.requireNonNull(stats, "stats"); + } + @Override public void onKill(@NotNull PhantazmMob mob) { ++kills; + stats.setKills(stats.getKills() + 1); } @Override diff --git a/zombies/src/main/java/org/phantazm/zombies/map/handler/BasicRoundHandler.java b/zombies/src/main/java/org/phantazm/zombies/map/handler/BasicRoundHandler.java index 94f15ec9f..21744fb43 100644 --- a/zombies/src/main/java/org/phantazm/zombies/map/handler/BasicRoundHandler.java +++ b/zombies/src/main/java/org/phantazm/zombies/map/handler/BasicRoundHandler.java @@ -2,12 +2,12 @@ import org.jetbrains.annotations.NotNull; import org.phantazm.zombies.map.Round; +import org.phantazm.zombies.player.ZombiesPlayer; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.util.*; public class BasicRoundHandler implements RoundHandler { + private final Collection zombiesPlayers; private final List rounds; private Round currentRound; @@ -15,7 +15,8 @@ public class BasicRoundHandler implements RoundHandler { private boolean hasEnded; - public BasicRoundHandler(@NotNull List rounds) { + public BasicRoundHandler(@NotNull Collection zombiesPlayers, @NotNull List rounds) { + this.zombiesPlayers = Objects.requireNonNull(zombiesPlayers, "zombiesPlayers"); this.rounds = Objects.requireNonNull(rounds, "rounds"); if (rounds.isEmpty()) { @@ -29,6 +30,11 @@ public void tick(long time) { currentRound.tick(time); if (!currentRound.isActive()) { + for (ZombiesPlayer zombiesPlayer : zombiesPlayers) { + zombiesPlayer.module().getStats() + .setRoundsSurvived(zombiesPlayer.module().getStats().getRoundsSurvived() + 1); + } + if (++roundIndex < rounds.size()) { currentRound = rounds.get(roundIndex); currentRound.startRound(time); diff --git a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java index 517b078e9..df9fb501b 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java @@ -57,6 +57,8 @@ import org.phantazm.zombies.player.state.revive.NearbyReviverFinder; import org.phantazm.zombies.player.state.revive.ReviveHandler; import org.phantazm.zombies.scene.ZombiesScene; +import org.phantazm.zombies.stats.BasicZombiesPlayerMapStats; +import org.phantazm.zombies.stats.ZombiesPlayerMapStats; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -95,9 +97,11 @@ public BasicZombiesPlayerSource( TransactionModifierSource playerTransactionModifierSource = new BasicTransactionModifierSource(); ZombiesPlayerMeta meta = new ZombiesPlayerMeta(); + ZombiesPlayerMapStats stats = + BasicZombiesPlayerMapStats.createBasicStats(playerView.getUUID(), mapSettingsInfo.id()); PlayerCoins coins = new BasicPlayerCoins(playerView, new BasicTransactionComponentCreator(), 0); - PlayerKills kills = new BasicPlayerKills(); + PlayerKills kills = new BasicPlayerKills(stats); InventoryProfile livingProfile = new BasicInventoryProfile(45); @@ -142,7 +146,7 @@ public BasicZombiesPlayerSource( Wrapper zombiesPlayerWrapper = Wrapper.ofNull(); ZombiesEquipmentModule equipmentModule = - new ZombiesEquipmentModule(zombiesPlayers, playerView, mobSpawner, mobStore, eventNode, random, + new ZombiesEquipmentModule(zombiesPlayers, playerView, stats, mobSpawner, mobStore, eventNode, random, mapObjects, zombiesPlayerWrapper, mobModelMap::get); EquipmentCreator equipmentCreator = equipmentCreatorFunction.apply(equipmentModule); @@ -209,7 +213,7 @@ public void start() { ZombiesPlayerStateKeys.QUIT.key(), List.of(new BasicQuitStateActivable(instance, playerView, sidebar, tabList, stateMap))); }; - PlayerStateSwitcher stateSwitcher = new PlayerStateSwitcher(); + PlayerStateSwitcher stateSwitcher = new PlayerStateSwitcher(stats); Map, Function> stateFunctions = Map.of(ZombiesPlayerStateKeys.ALIVE, aliveStateCreator, ZombiesPlayerStateKeys.DEAD, (Function)context -> deadStateCreator.apply(context, @@ -219,7 +223,7 @@ public void start() { ZombiesPlayerModule module = new ZombiesPlayerModule(playerView, meta, coins, kills, equipmentHandler, equipmentCreator, accessRegistry, stateSwitcher, stateFunctions, sidebar, tabList, mapTransactionModifierSource, - playerTransactionModifierSource, flaggable); + playerTransactionModifierSource, flaggable, stats); ZombiesPlayer zombiesPlayer = new BasicZombiesPlayer(scene, module, stateMap); zombiesPlayerWrapper.set(zombiesPlayer); diff --git a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayerModule.java b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayerModule.java index e9f5e5db1..33d437c85 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayerModule.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/ZombiesPlayerModule.java @@ -17,6 +17,7 @@ import org.phantazm.zombies.player.state.PlayerStateKey; import org.phantazm.zombies.player.state.PlayerStateSwitcher; import org.phantazm.zombies.player.state.ZombiesPlayerState; +import org.phantazm.zombies.stats.ZombiesPlayerMapStats; import java.util.Map; import java.util.Objects; @@ -39,6 +40,7 @@ public class ZombiesPlayerModule implements DependencyModule { private final TransactionModifierSource playerTransactionModifierSource; private final TransactionModifierSource compositeTransactionModifierSource; private final Flaggable flaggable; + private final ZombiesPlayerMapStats stats; public ZombiesPlayerModule(@NotNull PlayerView playerView, @NotNull ZombiesPlayerMeta meta, @NotNull PlayerCoins coins, @NotNull PlayerKills kills, @NotNull EquipmentHandler equipmentHandler, @@ -47,7 +49,8 @@ public ZombiesPlayerModule(@NotNull PlayerView playerView, @NotNull ZombiesPlaye @NotNull Map, Function> stateFunctions, @NotNull Sidebar sidebar, @NotNull TabList tabList, @NotNull TransactionModifierSource mapTransactionModifierSource, - @NotNull TransactionModifierSource playerTransactionModifierSource, @NotNull Flaggable flaggable) { + @NotNull TransactionModifierSource playerTransactionModifierSource, @NotNull Flaggable flaggable, + @NotNull ZombiesPlayerMapStats stats) { this.playerView = Objects.requireNonNull(playerView, "playerView"); this.meta = Objects.requireNonNull(meta, "meta"); this.coins = Objects.requireNonNull(coins, "coins"); @@ -64,6 +67,7 @@ public ZombiesPlayerModule(@NotNull PlayerView playerView, @NotNull ZombiesPlaye this.compositeTransactionModifierSource = TransactionModifierSource.compositeView(mapTransactionModifierSource, playerTransactionModifierSource); this.flaggable = Objects.requireNonNull(flaggable, "flags"); + this.stats = Objects.requireNonNull(stats, "stats"); } public @NotNull ZombiesPlayerMeta getMeta() { @@ -123,4 +127,8 @@ public ZombiesPlayerModule(@NotNull PlayerView playerView, @NotNull ZombiesPlaye public @NotNull Flaggable flags() { return flaggable; } + + public @NotNull ZombiesPlayerMapStats getStats() { + return stats; + } } diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/PlayerStateSwitcher.java b/zombies/src/main/java/org/phantazm/zombies/player/state/PlayerStateSwitcher.java index febb6333d..56b793850 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/PlayerStateSwitcher.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/PlayerStateSwitcher.java @@ -2,13 +2,18 @@ import org.jetbrains.annotations.NotNull; import org.phantazm.commons.Activable; +import org.phantazm.zombies.stats.ZombiesPlayerMapStats; + +import java.util.Objects; public class PlayerStateSwitcher implements Activable { - private ZombiesPlayerState state; + private final ZombiesPlayerMapStats stats; - public PlayerStateSwitcher() { + private ZombiesPlayerState state; + public PlayerStateSwitcher(@NotNull ZombiesPlayerMapStats stats) { + this.stats = Objects.requireNonNull(stats, "stats"); } @Override @@ -47,6 +52,12 @@ public void setState(@NotNull ZombiesPlayerState state) { this.state.end(); } + if (state.key().equals(ZombiesPlayerStateKeys.KNOCKED.key())) { + stats.setKnocks(stats.getKnocks() + 1); + } else if (state.key().equals(ZombiesPlayerStateKeys.DEAD.key())) { + stats.setDeaths(stats.getDeaths() + 1); + } + this.state = state; this.state.start(); } diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/revive/ReviveHandler.java b/zombies/src/main/java/org/phantazm/zombies/player/state/revive/ReviveHandler.java index 0e719320c..188e2b91f 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/revive/ReviveHandler.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/revive/ReviveHandler.java @@ -66,6 +66,7 @@ public void tick(long time) { } if (reviver != null) { + reviver.module().getStats().setRevives(reviver.module().getStats().getRevives() + 1); clearReviverState(); } diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java index 0f70221cf..c404e39ef 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java @@ -25,6 +25,7 @@ import org.phantazm.zombies.player.state.context.NoContext; import org.phantazm.zombies.stage.Stage; import org.phantazm.zombies.stage.StageTransition; +import org.phantazm.zombies.stats.ZombiesDatabase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,6 +44,7 @@ public class ZombiesScene extends InstanceScene { private final LeaveHandler leaveHandler; private final Function playerCreator; private final TickTaskScheduler taskScheduler; + private final ZombiesDatabase database; private boolean joinable = true; @@ -51,7 +53,7 @@ public ZombiesScene(@NotNull UUID uuid, @NotNull ConnectionManager connectionMan @NotNull Instance instance, @NotNull SceneFallback fallback, @NotNull MapSettingsInfo mapSettingsInfo, @NotNull StageTransition stageTransition, @NotNull LeaveHandler leaveHandler, @NotNull Function playerCreator, - @NotNull TickTaskScheduler taskScheduler) { + @NotNull TickTaskScheduler taskScheduler, @NotNull ZombiesDatabase database) { super(uuid, instance, players, fallback); this.connectionManager = Objects.requireNonNull(connectionManager, "connectionManager"); this.map = Objects.requireNonNull(map, "map"); @@ -61,6 +63,7 @@ public ZombiesScene(@NotNull UUID uuid, @NotNull ConnectionManager connectionMan this.leaveHandler = Objects.requireNonNull(leaveHandler, "leaveHandler"); this.playerCreator = Objects.requireNonNull(playerCreator, "playerCreator"); this.taskScheduler = Objects.requireNonNull(taskScheduler, "taskScheduler"); + this.database = Objects.requireNonNull(database, "database"); } public @NotNull Map getZombiesPlayers() { @@ -286,6 +289,7 @@ public int getJoinWeight(@NotNull ZombiesJoinRequest request) { public void shutdown() { taskScheduler.end(); for (ZombiesPlayer zombiesPlayer : zombiesPlayers.values()) { + database.synchronize(zombiesPlayer.module().getStats()); zombiesPlayer.end(); } super.shutdown(); diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java index c58687244..2111f926d 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesSceneProvider.java @@ -59,6 +59,7 @@ import org.phantazm.zombies.sidebar.SidebarModule; import org.phantazm.zombies.sidebar.SidebarUpdater; import org.phantazm.zombies.stage.*; +import org.phantazm.zombies.stats.ZombiesDatabase; import java.util.*; import java.util.function.Function; @@ -75,6 +76,7 @@ public class ZombiesSceneProvider extends SceneProviderAbstract eventNode, @NotNull MobSpawnerSource mobSpawnerSource, @NotNull Map mobModels, @NotNull ClientBlockHandlerSource clientBlockHandlerSource, @NotNull ContextManager contextManager, @NotNull KeyParser keyParser, @NotNull Team mobNoPushTeam, - @NotNull Map powerups, @NotNull ZombiesPlayer.Source zombiesPlayerSource) { + @NotNull ZombiesDatabase database, @NotNull Map powerups, + @NotNull ZombiesPlayer.Source zombiesPlayerSource) { super(maximumScenes); this.instanceSpaceFunction = Objects.requireNonNull(instanceSpaceFunction, "instanceSpaceFunction"); this.contexts = new IdentityHashMap<>(maximumScenes); @@ -101,6 +104,7 @@ public ZombiesSceneProvider(int maximumScenes, this.eventNode = Objects.requireNonNull(eventNode, "eventNode"); this.contextManager = Objects.requireNonNull(contextManager, "contextManager"); this.keyParser = Objects.requireNonNull(keyParser, "keyParser"); + this.database = Objects.requireNonNull(database, "database"); Objects.requireNonNull(powerups, "powerups"); MapSettingsInfo settingsInfo = mapInfo.settings(); @@ -176,7 +180,7 @@ public ZombiesSceneProvider(int maximumScenes, MapObjects mapObjects = createMapObjects(instance, zombiesPlayers, roundHandlerWrapper, mobStore, mobNoPushTeam, powerupHandlerWrapper, windowHandlerWrapper, eventNodeWrapper, songPlayer, tickTaskScheduler); - RoundHandler roundHandler = new BasicRoundHandler(mapObjects.rounds()); + RoundHandler roundHandler = new BasicRoundHandler(zombiesPlayers.values(), mapObjects.rounds()); roundHandlerWrapper.set(roundHandler); PowerupHandler powerupHandler = @@ -225,7 +229,7 @@ public ZombiesSceneProvider(int maximumScenes, ZombiesScene scene = new ZombiesScene(UUID.randomUUID(), connectionManager, map, players, zombiesPlayers, instance, - sceneFallback, settings, stageTransition, leaveHandler, playerCreator, tickTaskScheduler); + sceneFallback, settings, stageTransition, leaveHandler, playerCreator, tickTaskScheduler, database); sceneWrapper.set(scene); eventNode.addChild(childNode); diff --git a/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java b/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java index c9a1210f5..3bcbe683b 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java +++ b/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java @@ -96,6 +96,7 @@ public void start() { for (ZombiesPlayer zombiesPlayer : zombiesPlayers) { zombiesPlayer.module().getMeta().setInGame(true); + zombiesPlayer.module().getStats().setGamesPlayed(zombiesPlayer.module().getStats().getGamesPlayed() + 1); zombiesPlayer.getPlayer().ifPresent(player -> { player.teleport(spawnPos); }); @@ -165,6 +166,10 @@ public void end() { instance.sendTitlePart(TitlePart.TITLE, Component.text("You Win!", NamedTextColor.GREEN)); instance.sendTitlePart(TitlePart.SUBTITLE, Component.text("You made it to Round ", NamedTextColor.GRAY) .append(Component.text(bestRound, NamedTextColor.WHITE)).append(Component.text("!"))); + + for (ZombiesPlayer zombiesPlayer : zombiesPlayers) { + zombiesPlayer.module().getStats().setWins(zombiesPlayer.module().getStats().getWins() + 1); + } } else { instance.sendTitlePart(TitlePart.TITLE, Component.text("You lost...", NamedTextColor.RED)); diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/BasicZombiesPlayerMapStats.java b/zombies/src/main/java/org/phantazm/zombies/stats/BasicZombiesPlayerMapStats.java new file mode 100644 index 000000000..c60c68f72 --- /dev/null +++ b/zombies/src/main/java/org/phantazm/zombies/stats/BasicZombiesPlayerMapStats.java @@ -0,0 +1,151 @@ +package org.phantazm.zombies.stats; + +import net.kyori.adventure.key.Key; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.UUID; + +public class BasicZombiesPlayerMapStats implements ZombiesPlayerMapStats { + + private final UUID playerUUID; + + private final Key mapKey; + + private int gamesPlayed; + + private int wins; + + private int roundsSurvived; + + private int kills; + + private int knocks; + + private int deaths; + + private int revives; + + private int regularShots; + + private int headshots; + + public BasicZombiesPlayerMapStats(@NotNull UUID playerUUID, @NotNull Key mapKey, int gamesPlayed, int wins, + int roundsSurvived, int kills, int knocks, int deaths, int revives, int regularShots, int headshots) { + this.playerUUID = Objects.requireNonNull(playerUUID, "playerUUID"); + this.mapKey = Objects.requireNonNull(mapKey, "mapKey"); + this.gamesPlayed = gamesPlayed; + this.wins = wins; + this.roundsSurvived = roundsSurvived; + this.kills = kills; + this.knocks = knocks; + this.deaths = deaths; + this.revives = revives; + this.regularShots = regularShots; + this.headshots = headshots; + } + + public static ZombiesPlayerMapStats createBasicStats(@NotNull UUID playerUUID, @NotNull Key mapKey) { + return new BasicZombiesPlayerMapStats(playerUUID, mapKey, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } + + @Override + public @NotNull UUID getPlayerUUID() { + return playerUUID; + } + + @Override + public @NotNull Key getMapKey() { + return mapKey; + } + + @Override + public int getGamesPlayed() { + return gamesPlayed; + } + + @Override + public void setGamesPlayed(int gamesPlayed) { + this.gamesPlayed = gamesPlayed; + } + + @Override + public int getWins() { + return wins; + } + + @Override + public void setWins(int wins) { + this.wins = wins; + } + + @Override + public int getRoundsSurvived() { + return roundsSurvived; + } + + @Override + public void setRoundsSurvived(int roundsSurvived) { + this.roundsSurvived = roundsSurvived; + } + + @Override + public int getKills() { + return kills; + } + + @Override + public void setKills(int kills) { + this.kills = kills; + } + + @Override + public int getKnocks() { + return knocks; + } + + @Override + public void setKnocks(int knocks) { + this.knocks = knocks; + } + + @Override + public int getDeaths() { + return deaths; + } + + @Override + public void setDeaths(int deaths) { + this.deaths = deaths; + } + + @Override + public int getRevives() { + return revives; + } + + @Override + public void setRevives(int revives) { + this.revives = revives; + } + + @Override + public int getRegularShots() { + return regularShots; + } + + @Override + public void setRegularShots(int regularShots) { + this.regularShots = regularShots; + } + + @Override + public int getHeadshots() { + return headshots; + } + + @Override + public void setHeadshots(int headshots) { + this.headshots = headshots; + } +} diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/HikariZombiesDatabase.java b/zombies/src/main/java/org/phantazm/zombies/stats/HikariZombiesDatabase.java new file mode 100644 index 000000000..43fd5998e --- /dev/null +++ b/zombies/src/main/java/org/phantazm/zombies/stats/HikariZombiesDatabase.java @@ -0,0 +1,51 @@ +package org.phantazm.zombies.stats; + +import com.zaxxer.hikari.HikariDataSource; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Closeable; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +public abstract class HikariZombiesDatabase implements Closeable, ZombiesDatabase { + + private static final Logger LOGGER = LoggerFactory.getLogger(HikariZombiesDatabase.class); + + private final Executor executor; + + private final HikariDataSource dataSource; + + public HikariZombiesDatabase(@NotNull Executor executor, @NotNull HikariDataSource dataSource) { + this.executor = Objects.requireNonNull(executor, "executor"); + this.dataSource = Objects.requireNonNull(dataSource, "dataSource"); + } + + @Override + public void synchronize(@NotNull ZombiesPlayerMapStats stats) { + CompletableFuture.runAsync(() -> { + try (Connection connection = dataSource.getConnection()) { + synchronizeInternal(connection, stats); + } + catch (SQLException e) { + throw new RuntimeException(e); + } + }, executor).whenComplete((ignored, throwable) -> { + if (throwable != null) { + LOGGER.warn("Exception while synchronizing Zombies database", throwable); + } + }); + } + + protected abstract void synchronizeInternal(@NotNull Connection connection, + @NotNull ZombiesPlayerMapStats stats) throws SQLException; + + @Override + public void close() { + dataSource.close(); + } +} diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/SqliteZombiesDatabase.java b/zombies/src/main/java/org/phantazm/zombies/stats/SqliteZombiesDatabase.java new file mode 100644 index 000000000..a0eaa177e --- /dev/null +++ b/zombies/src/main/java/org/phantazm/zombies/stats/SqliteZombiesDatabase.java @@ -0,0 +1,55 @@ +package org.phantazm.zombies.stats; + +import com.zaxxer.hikari.HikariDataSource; +import org.jetbrains.annotations.NotNull; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.concurrent.Executor; + +public class SqliteZombiesDatabase extends HikariZombiesDatabase { + public SqliteZombiesDatabase(@NotNull Executor executor, @NotNull HikariDataSource dataSource) { + super(executor, dataSource); + } + + @Override + protected void synchronizeInternal(@NotNull Connection connection, @NotNull ZombiesPlayerMapStats stats) + throws SQLException { + PreparedStatement statement = connection.prepareStatement(""" + INSERT INTO zombies_player_map_stats (player_uuid, map_key, games_played, wins, rounds_survived, kills, knocks, deaths, revives, regular_shots, headshots) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT (player_uuid, map_key) DO UPDATE + SET games_played = games_played + ?, + wins = wins + ?, + rounds_survived = rounds_survived + ?, + kills = kills + ?, + knocks = knocks + ?, + deaths = deaths + ?, + revives = revives + ?, + regular_shots = regular_shots + ?, + headshots = headshots = ? + """); + statement.setString(1, stats.getPlayerUUID().toString()); + statement.setString(2, stats.getMapKey().asString()); + statement.setInt(3, stats.getGamesPlayed()); + statement.setInt(4, stats.getWins()); + statement.setInt(5, stats.getRoundsSurvived()); + statement.setInt(6, stats.getKills()); + statement.setInt(7, stats.getKnocks()); + statement.setInt(8, stats.getKnocks()); + statement.setInt(9, stats.getRevives()); + statement.setInt(10, stats.getRegularShots()); + statement.setInt(11, stats.getHeadshots()); + statement.setInt(12, stats.getGamesPlayed()); + statement.setInt(13, stats.getWins()); + statement.setInt(14, stats.getRoundsSurvived()); + statement.setInt(15, stats.getKills()); + statement.setInt(16, stats.getKnocks()); + statement.setInt(17, stats.getKnocks()); + statement.setInt(18, stats.getRevives()); + statement.setInt(19, stats.getRegularShots()); + statement.setInt(20, stats.getHeadshots()); + statement.execute(); + } +} diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesDatabase.java b/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesDatabase.java new file mode 100644 index 000000000..ae587fd35 --- /dev/null +++ b/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesDatabase.java @@ -0,0 +1,9 @@ +package org.phantazm.zombies.stats; + +import org.jetbrains.annotations.NotNull; + +public interface ZombiesDatabase { + + void synchronize(@NotNull ZombiesPlayerMapStats stats); + +} diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesPlayerMapStats.java b/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesPlayerMapStats.java new file mode 100644 index 000000000..43268ece7 --- /dev/null +++ b/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesPlayerMapStats.java @@ -0,0 +1,50 @@ +package org.phantazm.zombies.stats; + +import net.kyori.adventure.key.Key; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public interface ZombiesPlayerMapStats { + + @NotNull UUID getPlayerUUID(); + + @NotNull Key getMapKey(); + + int getGamesPlayed(); + + void setGamesPlayed(int gamesPlayed); + + int getWins(); + + void setWins(int wins); + + int getRoundsSurvived(); + + void setRoundsSurvived(int roundsSurvived); + + int getKills(); + + void setKills(int kills); + + int getKnocks(); + + void setKnocks(int knocks); + + int getDeaths(); + + void setDeaths(int deaths); + + int getRevives(); + + void setRevives(int revives); + + int getRegularShots(); + + void setRegularShots(int regularShots); + + int getHeadshots(); + + void setHeadshots(int headshots); + +} diff --git a/zombies/src/test/java/org/phantazm/zombies/kill/BasicPlayerKillsTest.java b/zombies/src/test/java/org/phantazm/zombies/kill/BasicPlayerKillsTest.java index 81bddcee2..e208658ce 100644 --- a/zombies/src/test/java/org/phantazm/zombies/kill/BasicPlayerKillsTest.java +++ b/zombies/src/test/java/org/phantazm/zombies/kill/BasicPlayerKillsTest.java @@ -1,8 +1,14 @@ package org.phantazm.zombies.kill; +import net.kyori.adventure.key.Key; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.phantazm.commons.Namespaces; import org.phantazm.mob.PhantazmMob; +import org.phantazm.zombies.stats.BasicZombiesPlayerMapStats; +import org.phantazm.zombies.stats.ZombiesPlayerMapStats; + +import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; @@ -13,7 +19,9 @@ public class BasicPlayerKillsTest { @BeforeEach public void setup() { - kills = new BasicPlayerKills(); + ZombiesPlayerMapStats mapStats = BasicZombiesPlayerMapStats.createBasicStats(UUID.randomUUID(), + Key.key(Namespaces.PHANTAZM, "test_map")); + kills = new BasicPlayerKills(mapStats); } @Test From 2c07218ba22a1abfb6a6d5d933702dcab474920e Mon Sep 17 00:00:00 2001 From: steank Date: Sat, 17 Jun 2023 18:12:52 -0700 Subject: [PATCH 031/181] end player TickTaskScheduler when they quit --- .../phantazm/zombies/player/BasicZombiesPlayer.java | 12 +++++------- .../zombies/player/BasicZombiesPlayerSource.java | 8 ++++++-- .../player/state/BasicQuitStateActivable.java | 13 ++++++------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java index d6d9f0bd1..13c9b8ae1 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java @@ -4,7 +4,6 @@ import net.kyori.adventure.audience.ForwardingAudience; import net.minestom.server.entity.Player; import org.jetbrains.annotations.NotNull; -import org.phantazm.commons.BasicTickTaskScheduler; import org.phantazm.commons.CancellableState; import org.phantazm.commons.TickTaskScheduler; import org.phantazm.core.inventory.InventoryObject; @@ -20,14 +19,14 @@ public class BasicZombiesPlayer implements ZombiesPlayer, ForwardingAudience { private final ZombiesScene scene; private final ZombiesPlayerModule module; - private final TickTaskScheduler scheduler; + private final TickTaskScheduler taskScheduler; private final Map stateMap; public BasicZombiesPlayer(@NotNull ZombiesScene scene, @NotNull ZombiesPlayerModule module, - @NotNull Map stateMap) { + @NotNull Map stateMap, @NotNull TickTaskScheduler taskScheduler) { this.scene = Objects.requireNonNull(scene, "scene"); this.module = Objects.requireNonNull(module, "module"); - this.scheduler = new BasicTickTaskScheduler(); + this.taskScheduler = Objects.requireNonNull(taskScheduler, "taskScheduler"); this.stateMap = Objects.requireNonNull(stateMap, "stateMap"); } @@ -49,7 +48,7 @@ public long getReviveTime() { @Override public @NotNull TickTaskScheduler scheduler() { - return scheduler; + return taskScheduler; } @Override @@ -82,7 +81,7 @@ public void tick(long time) { } module.getStateSwitcher().tick(time); - scheduler.tick(time); + taskScheduler.tick(time); } @Override @@ -91,7 +90,6 @@ public void end() { setState(ZombiesPlayerStateKeys.QUIT, new QuitPlayerStateContext(false)); } module.getStateSwitcher().end(); - scheduler.end(); } private void inventoryTick(Player player, long time) { diff --git a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java index 517b078e9..795ae87cb 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayerSource.java @@ -22,7 +22,9 @@ import org.jglrxavpok.hephaistos.nbt.NBTException; import org.jglrxavpok.hephaistos.parser.SNBTParser; import org.phantazm.commons.Activable; +import org.phantazm.commons.BasicTickTaskScheduler; import org.phantazm.commons.CancellableState; +import org.phantazm.commons.TickTaskScheduler; import org.phantazm.core.entity.fakeplayer.MinimalFakePlayer; import org.phantazm.core.equipment.EquipmentCreator; import org.phantazm.core.equipment.EquipmentHandler; @@ -204,10 +206,12 @@ public void start() { })); }; Map stateMap = new ConcurrentHashMap<>(); + TickTaskScheduler taskScheduler = new BasicTickTaskScheduler(); Function quitStateCreator = unused -> { return new BasicZombiesPlayerState(Component.text("QUIT").color(NamedTextColor.RED), ZombiesPlayerStateKeys.QUIT.key(), - List.of(new BasicQuitStateActivable(instance, playerView, sidebar, tabList, stateMap))); + List.of(new BasicQuitStateActivable(instance, playerView, sidebar, tabList, stateMap, + taskScheduler))); }; PlayerStateSwitcher stateSwitcher = new PlayerStateSwitcher(); Map, Function> stateFunctions = @@ -221,7 +225,7 @@ public void start() { accessRegistry, stateSwitcher, stateFunctions, sidebar, tabList, mapTransactionModifierSource, playerTransactionModifierSource, flaggable); - ZombiesPlayer zombiesPlayer = new BasicZombiesPlayer(scene, module, stateMap); + ZombiesPlayer zombiesPlayer = new BasicZombiesPlayer(scene, module, stateMap, taskScheduler); zombiesPlayerWrapper.set(zombiesPlayer); return zombiesPlayer; } diff --git a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java index bfb19bac2..b9bac17b6 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/state/BasicQuitStateActivable.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.phantazm.commons.Activable; import org.phantazm.commons.CancellableState; +import org.phantazm.commons.TickTaskScheduler; import org.phantazm.core.player.PlayerView; import java.util.Map; @@ -14,24 +15,22 @@ import java.util.UUID; public class BasicQuitStateActivable implements Activable { - private final Instance instance; - private final PlayerView playerView; - private final Sidebar sidebar; - private final TabList tabList; - private final Map stateMap; + private final TickTaskScheduler scheduler; public BasicQuitStateActivable(@NotNull Instance instance, @NotNull PlayerView playerView, @NotNull Sidebar sidebar, - @NotNull TabList tabList, @NotNull Map stateMap) { + @NotNull TabList tabList, @NotNull Map stateMap, + @NotNull TickTaskScheduler scheduler) { this.instance = Objects.requireNonNull(instance, "instance"); this.playerView = Objects.requireNonNull(playerView, "playerView"); this.sidebar = Objects.requireNonNull(sidebar, "sidebar"); this.tabList = Objects.requireNonNull(tabList, "tabList"); this.stateMap = Objects.requireNonNull(stateMap, "stateMap"); + this.scheduler = Objects.requireNonNull(scheduler, "scheduler"); } @Override @@ -50,7 +49,7 @@ public void start() { state.end(); } + scheduler.end(); stateMap.clear(); } - } From 1395066841e7f1c044f9be88a01bd62a3fab337e Mon Sep 17 00:00:00 2001 From: steank Date: Sat, 17 Jun 2023 18:30:09 -0700 Subject: [PATCH 032/181] additional nullcheck --- .../main/java/org/phantazm/commons/BasicTickTaskScheduler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/commons/src/main/java/org/phantazm/commons/BasicTickTaskScheduler.java b/commons/src/main/java/org/phantazm/commons/BasicTickTaskScheduler.java index 482488453..9a5bfd555 100644 --- a/commons/src/main/java/org/phantazm/commons/BasicTickTaskScheduler.java +++ b/commons/src/main/java/org/phantazm/commons/BasicTickTaskScheduler.java @@ -22,6 +22,7 @@ public void scheduleTaskNow(@NotNull TickableTask tickableTask) { @Override public void scheduleTaskAfter(@NotNull TickableTask tickableTask, long millis) { + Objects.requireNonNull(tickableTask, "tickableTask"); long startTime = System.currentTimeMillis(); tickableTasks.add(new TickableTask() { private boolean finished; From 37d6d75e35aebfb25b7ecf13fa2a4c282a8d4b49 Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Sat, 17 Jun 2023 22:47:19 -0400 Subject: [PATCH 033/181] add best times, mariadb zombies db --- defaultRunData/server-1/zombies.db | Bin 16384 -> 12288 bytes gradle/libs.versions.toml | 2 + server/build.gradle.kts | 1 + .../org/phantazm/server/ZombiesFeature.java | 6 +- .../phantazm/zombies/scene/ZombiesScene.java | 2 +- .../phantazm/zombies/stage/InGameStage.java | 17 ++-- .../stats/BasicZombiesPlayerMapStats.java | 22 +++- .../org/phantazm/zombies/stats/BestTime.java | 8 ++ .../zombies/stats/HikariZombiesDatabase.java | 30 +++++- .../zombies/stats/MariaDBZombiesDatabase.java | 93 +++++++++++++++++ .../zombies/stats/SqliteZombiesDatabase.java | 94 ++++++++++++------ .../zombies/stats/ZombiesDatabase.java | 8 +- .../zombies/stats/ZombiesPlayerMapStats.java | 6 ++ 13 files changed, 240 insertions(+), 49 deletions(-) create mode 100644 zombies/src/main/java/org/phantazm/zombies/stats/BestTime.java create mode 100644 zombies/src/main/java/org/phantazm/zombies/stats/MariaDBZombiesDatabase.java diff --git a/defaultRunData/server-1/zombies.db b/defaultRunData/server-1/zombies.db index a5da2e00c121b962d7d45445837bb2d80f3b66ff..c95cdd2671bc45534f5ffff46db94ed8a299c214 100644 GIT binary patch delta 164 zcmZo@U~EX3AT7wuz`y{)Fu*ub#~3K6m(0k^|AT>vSCfHPlYjYUL4ln-{4Ldt?Bcez zjGde%iAg!BlNI?SCLiaPn7oqDa1eYWx<+LO)v5VW$kj2#RUyRD$;VYe2_(j- zG`Wv={$?+}SVlIWWort(C$Hr<kB9JpE@GSqbPYqZFeBLbR!fj& zFyjMbLR=$46!P**6!J=Qa=3I9auW;Uvr{V-P{ef<(i3x2i{lG&5-U?v6f*NlQqxn5 z;M#N)$}{tdF@-04@+k!>WM}5&V3AbF&dX2E#wL-Hnpl#7O`<5ZEYqKP@=AU`Zcs>r z0so)Pf(o1XCpOp#a3%poSa?Cg0t^iNTYwU4`8j;7896vO85t+9 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 899d86dc2..2b7717bea 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -50,6 +50,8 @@ junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", vers libgui = { module = "io.github.cottonmc:LibGui", version = "7.1.0+1.19.4" } +mariadb = { module = "org.mariadb.jdbc:mariadb-java-client", version = "3.0.10" } + minecraft = { module = "com.mojang:minecraft", version = "1.19.4" } minestom = { module = "org.phantazm.Minestom:Minestom", version.ref = "minestom" } diff --git a/server/build.gradle.kts b/server/build.gradle.kts index c2bebc9d1..9dc7998f7 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -23,6 +23,7 @@ dependencies { implementation(libs.element.core) implementation(libs.ethylene.mapper) + runtimeOnly(libs.mariadb) runtimeOnly(libs.sqlite) } diff --git a/server/src/main/java/org/phantazm/server/ZombiesFeature.java b/server/src/main/java/org/phantazm/server/ZombiesFeature.java index 64f1e3bd1..2144ad8f2 100644 --- a/server/src/main/java/org/phantazm/server/ZombiesFeature.java +++ b/server/src/main/java/org/phantazm/server/ZombiesFeature.java @@ -90,16 +90,13 @@ import org.phantazm.zombies.sidebar.section.ZombiesPlayerSection; import org.phantazm.zombies.sidebar.section.ZombiesPlayersSection; import org.phantazm.zombies.stats.HikariZombiesDatabase; -import org.phantazm.zombies.stats.OracleZombiesDatabase; +import org.phantazm.zombies.stats.MariaDBZombiesDatabase; import org.phantazm.zombies.stats.SqliteZombiesDatabase; -import org.phantazm.zombies.stats.ZombiesDatabase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.file.Path; -import java.sql.Connection; -import java.sql.SQLException; import java.util.*; import java.util.concurrent.Executor; import java.util.concurrent.Executors; @@ -156,6 +153,7 @@ static void initialize(@NotNull EventNode globalEventNode, @NotNull Conte HikariDataSource dataSource = new HikariDataSource(config); database = switch (dataSource.getDataSourceClassName()) { case "org.sqlite.SQLiteDataSource" -> new SqliteZombiesDatabase(databaseExecutor, dataSource); + case "org.mariadb.jdbc.MariaDbDataSource" -> new MariaDBZombiesDatabase(databaseExecutor, dataSource); default -> throw new RuntimeException("Unknown data source " + dataSource.getDataSourceClassName()); }; for (Map.Entry entry : maps.entrySet()) { diff --git a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java index c404e39ef..cbb7b9be1 100644 --- a/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java +++ b/zombies/src/main/java/org/phantazm/zombies/scene/ZombiesScene.java @@ -289,7 +289,7 @@ public int getJoinWeight(@NotNull ZombiesJoinRequest request) { public void shutdown() { taskScheduler.end(); for (ZombiesPlayer zombiesPlayer : zombiesPlayers.values()) { - database.synchronize(zombiesPlayer.module().getStats()); + database.synchronizeZombiesPlayerMapStats(zombiesPlayer.module().getStats()); zombiesPlayer.end(); } super.shutdown(); diff --git a/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java b/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java index 3bcbe683b..b399abc96 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java +++ b/zombies/src/main/java/org/phantazm/zombies/stage/InGameStage.java @@ -18,6 +18,7 @@ import org.phantazm.zombies.player.ZombiesPlayer; import org.phantazm.zombies.player.ZombiesPlayerModule; import org.phantazm.zombies.sidebar.SidebarUpdater; +import org.phantazm.zombies.stats.ZombiesPlayerMapStats; import java.util.*; import java.util.function.Function; @@ -35,8 +36,6 @@ public class InGameStage implements Stage { private final ShopHandler shopHandler; private final TickFormatter tickFormatter; - private long startTime; - public InGameStage(@NotNull Instance instance, @NotNull Collection zombiesPlayers, @NotNull Pos spawnPos, @NotNull RoundHandler roundHandler, @NotNull Wrapper ticksSinceStart, @NotNull Map> defaultEquipment, @NotNull Set equipmentGroups, @@ -92,8 +91,6 @@ public boolean hasPermanentPlayers() { @Override public void start() { - this.startTime = System.currentTimeMillis(); - for (ZombiesPlayer zombiesPlayer : zombiesPlayers) { zombiesPlayer.module().getMeta().setInGame(true); zombiesPlayer.module().getStats().setGamesPlayed(zombiesPlayer.module().getStats().getGamesPlayed() + 1); @@ -149,8 +146,6 @@ public void tick(long time) { @Override public void end() { - long endTime = System.currentTimeMillis(); - boolean anyAlive = false; for (ZombiesPlayer zombiesPlayer : zombiesPlayers) { if (zombiesPlayer.isAlive()) { @@ -159,7 +154,7 @@ public void end() { } } - Component finalTime = tickFormatter.format((endTime - startTime) / MinecraftServer.TICK_MS); + Component finalTime = tickFormatter.format(ticksSinceStart.get()); int bestRound = Math.min(roundHandler.currentRoundIndex() + 1, roundHandler.roundCount()); if (anyAlive) { @@ -168,7 +163,13 @@ public void end() { .append(Component.text(bestRound, NamedTextColor.WHITE)).append(Component.text("!"))); for (ZombiesPlayer zombiesPlayer : zombiesPlayers) { - zombiesPlayer.module().getStats().setWins(zombiesPlayer.module().getStats().getWins() + 1); + ZombiesPlayerMapStats stats = zombiesPlayer.module().getStats(); + stats.setWins(stats.getWins() + 1); + stats.getBestTime().ifPresentOrElse(prevBest -> { + if (ticksSinceStart.get() < prevBest) { + stats.setBestTime(ticksSinceStart.get()); + } + }, () -> stats.setBestTime(ticksSinceStart.get())); } } else { diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/BasicZombiesPlayerMapStats.java b/zombies/src/main/java/org/phantazm/zombies/stats/BasicZombiesPlayerMapStats.java index c60c68f72..4d828305e 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stats/BasicZombiesPlayerMapStats.java +++ b/zombies/src/main/java/org/phantazm/zombies/stats/BasicZombiesPlayerMapStats.java @@ -2,8 +2,10 @@ import net.kyori.adventure.key.Key; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Objects; +import java.util.Optional; import java.util.UUID; public class BasicZombiesPlayerMapStats implements ZombiesPlayerMapStats { @@ -16,6 +18,8 @@ public class BasicZombiesPlayerMapStats implements ZombiesPlayerMapStats { private int wins; + private Long bestTime; + private int roundsSurvived; private int kills; @@ -30,12 +34,14 @@ public class BasicZombiesPlayerMapStats implements ZombiesPlayerMapStats { private int headshots; - public BasicZombiesPlayerMapStats(@NotNull UUID playerUUID, @NotNull Key mapKey, int gamesPlayed, int wins, - int roundsSurvived, int kills, int knocks, int deaths, int revives, int regularShots, int headshots) { + public BasicZombiesPlayerMapStats(@NotNull UUID playerUUID, @NotNull Key mapKey, + int gamesPlayed, int wins, @Nullable Long bestTime, int roundsSurvived, int kills, int knocks, int deaths, int revives, + int regularShots, int headshots) { this.playerUUID = Objects.requireNonNull(playerUUID, "playerUUID"); this.mapKey = Objects.requireNonNull(mapKey, "mapKey"); this.gamesPlayed = gamesPlayed; this.wins = wins; + this.bestTime = bestTime; this.roundsSurvived = roundsSurvived; this.kills = kills; this.knocks = knocks; @@ -46,7 +52,7 @@ public BasicZombiesPlayerMapStats(@NotNull UUID playerUUID, @NotNull Key mapKey, } public static ZombiesPlayerMapStats createBasicStats(@NotNull UUID playerUUID, @NotNull Key mapKey) { - return new BasicZombiesPlayerMapStats(playerUUID, mapKey, 0, 0, 0, 0, 0, 0, 0, 0, 0); + return new BasicZombiesPlayerMapStats(playerUUID, mapKey, 0, 0, null,0, 0, 0, 0, 0, 0, 0); } @Override @@ -79,6 +85,16 @@ public void setWins(int wins) { this.wins = wins; } + @Override + public @NotNull Optional getBestTime() { + return Optional.ofNullable(bestTime); + } + + @Override + public void setBestTime(@Nullable Long bestTime) { + this.bestTime = bestTime; + } + @Override public int getRoundsSurvived() { return roundsSurvived; diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/BestTime.java b/zombies/src/main/java/org/phantazm/zombies/stats/BestTime.java new file mode 100644 index 000000000..a8624bdb7 --- /dev/null +++ b/zombies/src/main/java/org/phantazm/zombies/stats/BestTime.java @@ -0,0 +1,8 @@ +package org.phantazm.zombies.stats; + +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public record BestTime(@NotNull UUID uuid, long time) { +} diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/HikariZombiesDatabase.java b/zombies/src/main/java/org/phantazm/zombies/stats/HikariZombiesDatabase.java index 43fd5998e..c0c5c2342 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stats/HikariZombiesDatabase.java +++ b/zombies/src/main/java/org/phantazm/zombies/stats/HikariZombiesDatabase.java @@ -1,6 +1,7 @@ package org.phantazm.zombies.stats; import com.zaxxer.hikari.HikariDataSource; +import net.kyori.adventure.key.Key; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -8,7 +9,9 @@ import java.io.Closeable; import java.sql.Connection; import java.sql.SQLException; +import java.util.List; import java.util.Objects; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; @@ -26,24 +29,43 @@ public HikariZombiesDatabase(@NotNull Executor executor, @NotNull HikariDataSour } @Override - public void synchronize(@NotNull ZombiesPlayerMapStats stats) { + public void synchronizeZombiesPlayerMapStats(@NotNull ZombiesPlayerMapStats stats) { CompletableFuture.runAsync(() -> { try (Connection connection = dataSource.getConnection()) { - synchronizeInternal(connection, stats); + synchronizeZombiesPlayerMapStatsInternal(connection, stats); } catch (SQLException e) { throw new RuntimeException(e); } }, executor).whenComplete((ignored, throwable) -> { if (throwable != null) { - LOGGER.warn("Exception while synchronizing Zombies database", throwable); + LOGGER.warn("Exception while querying database", throwable); } }); } - protected abstract void synchronizeInternal(@NotNull Connection connection, + @Override + public CompletableFuture> getBestTimes(@NotNull Key mapKey) { + return CompletableFuture.supplyAsync(() -> { + try (Connection connection = dataSource.getConnection()) { + return getBestTimesInternal(connection, mapKey); + } + catch (SQLException e) { + throw new RuntimeException(e); + } + }, executor).whenComplete((ignored, throwable) -> { + if (throwable != null) { + LOGGER.warn("Exception while querying database", throwable); + } + }); + } + + protected abstract void synchronizeZombiesPlayerMapStatsInternal(@NotNull Connection connection, @NotNull ZombiesPlayerMapStats stats) throws SQLException; + protected abstract @NotNull List getBestTimesInternal(@NotNull Connection connection, @NotNull Key mapKey) + throws SQLException; + @Override public void close() { dataSource.close(); diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/MariaDBZombiesDatabase.java b/zombies/src/main/java/org/phantazm/zombies/stats/MariaDBZombiesDatabase.java new file mode 100644 index 000000000..fafe5d315 --- /dev/null +++ b/zombies/src/main/java/org/phantazm/zombies/stats/MariaDBZombiesDatabase.java @@ -0,0 +1,93 @@ +package org.phantazm.zombies.stats; + +import com.zaxxer.hikari.HikariDataSource; +import net.kyori.adventure.key.Key; +import org.jetbrains.annotations.NotNull; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.Executor; + +public class MariaDBZombiesDatabase extends HikariZombiesDatabase { + public MariaDBZombiesDatabase(@NotNull Executor executor, @NotNull HikariDataSource dataSource) { + super(executor, dataSource); + } + + @Override + protected void synchronizeZombiesPlayerMapStatsInternal(@NotNull Connection connection, @NotNull ZombiesPlayerMapStats stats) throws + SQLException { + PreparedStatement statement = connection.prepareStatement(""" + INSERT INTO zombies_player_map_stats (player_uuid, map_key, games_played, wins, best_time, rounds_survived, kills, knocks, deaths, revives, regular_shots, headshots) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + games_played = games_played + ?, + wins = wins + ?, + best_time = CASE WHEN ? IS NULL THEN best_time ELSE ? END, + rounds_survived = rounds_survived + ?, + kills = kills + ?, + knocks = knocks + ?, + deaths = deaths + ?, + revives = revives + ?, + regular_shots = regular_shots + ?, + headshots = headshots + ? + """); + int parameterIndex = 0; + statement.setString(++parameterIndex, stats.getPlayerUUID().toString()); + statement.setString(++parameterIndex, stats.getMapKey().asString()); + statement.setInt(++parameterIndex, stats.getGamesPlayed()); + statement.setInt(++parameterIndex, stats.getWins()); + if (stats.getBestTime().isPresent()) { + statement.setLong(++parameterIndex, stats.getBestTime().get()); + } else { + statement.setNull(++parameterIndex, Types.INTEGER); + } + statement.setInt(++parameterIndex, stats.getRoundsSurvived()); + statement.setInt(++parameterIndex, stats.getKills()); + statement.setInt(++parameterIndex, stats.getKnocks()); + statement.setInt(++parameterIndex, stats.getKnocks()); + statement.setInt(++parameterIndex, stats.getRevives()); + statement.setInt(++parameterIndex, stats.getRegularShots()); + statement.setInt(++parameterIndex, stats.getHeadshots()); + statement.setInt(++parameterIndex, stats.getGamesPlayed()); + statement.setInt(++parameterIndex, stats.getWins()); + if (stats.getBestTime().isPresent()) { + statement.setLong(++parameterIndex, stats.getBestTime().get()); + statement.setLong(++parameterIndex, stats.getBestTime().get()); + } else { + statement.setNull(++parameterIndex, Types.INTEGER); + statement.setNull(++parameterIndex, Types.INTEGER); + } + statement.setInt(++parameterIndex, stats.getRoundsSurvived()); + statement.setInt(++parameterIndex, stats.getKills()); + statement.setInt(++parameterIndex, stats.getKnocks()); + statement.setInt(++parameterIndex, stats.getKnocks()); + statement.setInt(++parameterIndex, stats.getRevives()); + statement.setInt(++parameterIndex, stats.getRegularShots()); + statement.setInt(++parameterIndex, stats.getHeadshots()); + statement.execute(); + } + + @Override + protected @NotNull List getBestTimesInternal(@NotNull Connection connection, @NotNull Key mapKey) + throws SQLException { + PreparedStatement statement = connection.prepareStatement(""" + SELECT player_uuid, best_time + FROM zombies_player_map_stats + WHERE map_key = ? + AND best_time IS NOT NULL + ORDER BY best_time + """); + statement.setString(1, mapKey.asString()); + ResultSet resultSet = statement.executeQuery(); + List bestTimes = new ArrayList<>(); + while (resultSet.next()) { + UUID uuid = UUID.fromString(resultSet.getString("player_uuid")); + long bestTime = resultSet.getLong("best_time"); + bestTimes.add(new BestTime(uuid, bestTime)); + } + + return bestTimes; + } +} diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/SqliteZombiesDatabase.java b/zombies/src/main/java/org/phantazm/zombies/stats/SqliteZombiesDatabase.java index a0eaa177e..b9d2e46e5 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stats/SqliteZombiesDatabase.java +++ b/zombies/src/main/java/org/phantazm/zombies/stats/SqliteZombiesDatabase.java @@ -1,11 +1,13 @@ package org.phantazm.zombies.stats; import com.zaxxer.hikari.HikariDataSource; +import net.kyori.adventure.key.Key; import org.jetbrains.annotations.NotNull; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; import java.util.concurrent.Executor; public class SqliteZombiesDatabase extends HikariZombiesDatabase { @@ -14,42 +16,78 @@ public SqliteZombiesDatabase(@NotNull Executor executor, @NotNull HikariDataSour } @Override - protected void synchronizeInternal(@NotNull Connection connection, @NotNull ZombiesPlayerMapStats stats) - throws SQLException { + protected void synchronizeZombiesPlayerMapStatsInternal(@NotNull Connection connection, + @NotNull ZombiesPlayerMapStats stats) throws SQLException { PreparedStatement statement = connection.prepareStatement(""" - INSERT INTO zombies_player_map_stats (player_uuid, map_key, games_played, wins, rounds_survived, kills, knocks, deaths, revives, regular_shots, headshots) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + INSERT INTO zombies_player_map_stats (player_uuid, map_key, games_played, wins, best_time, rounds_survived, kills, knocks, deaths, revives, regular_shots, headshots) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT (player_uuid, map_key) DO UPDATE SET games_played = games_played + ?, wins = wins + ?, + best_time = CASE WHEN ? IS NULL THEN best_time ELSE ? END, rounds_survived = rounds_survived + ?, kills = kills + ?, knocks = knocks + ?, deaths = deaths + ?, revives = revives + ?, regular_shots = regular_shots + ?, - headshots = headshots = ? + headshots = headshots + ? """); - statement.setString(1, stats.getPlayerUUID().toString()); - statement.setString(2, stats.getMapKey().asString()); - statement.setInt(3, stats.getGamesPlayed()); - statement.setInt(4, stats.getWins()); - statement.setInt(5, stats.getRoundsSurvived()); - statement.setInt(6, stats.getKills()); - statement.setInt(7, stats.getKnocks()); - statement.setInt(8, stats.getKnocks()); - statement.setInt(9, stats.getRevives()); - statement.setInt(10, stats.getRegularShots()); - statement.setInt(11, stats.getHeadshots()); - statement.setInt(12, stats.getGamesPlayed()); - statement.setInt(13, stats.getWins()); - statement.setInt(14, stats.getRoundsSurvived()); - statement.setInt(15, stats.getKills()); - statement.setInt(16, stats.getKnocks()); - statement.setInt(17, stats.getKnocks()); - statement.setInt(18, stats.getRevives()); - statement.setInt(19, stats.getRegularShots()); - statement.setInt(20, stats.getHeadshots()); + int parameterIndex = 0; + statement.setString(++parameterIndex, stats.getPlayerUUID().toString()); + statement.setString(++parameterIndex, stats.getMapKey().asString()); + statement.setInt(++parameterIndex, stats.getGamesPlayed()); + statement.setInt(++parameterIndex, stats.getWins()); + if (stats.getBestTime().isPresent()) { + statement.setLong(++parameterIndex, stats.getBestTime().get()); + } else { + statement.setNull(++parameterIndex, Types.INTEGER); + } + statement.setInt(++parameterIndex, stats.getRoundsSurvived()); + statement.setInt(++parameterIndex, stats.getKills()); + statement.setInt(++parameterIndex, stats.getKnocks()); + statement.setInt(++parameterIndex, stats.getKnocks()); + statement.setInt(++parameterIndex, stats.getRevives()); + statement.setInt(++parameterIndex, stats.getRegularShots()); + statement.setInt(++parameterIndex, stats.getHeadshots()); + statement.setInt(++parameterIndex, stats.getGamesPlayed()); + statement.setInt(++parameterIndex, stats.getWins()); + if (stats.getBestTime().isPresent()) { + statement.setLong(++parameterIndex, stats.getBestTime().get()); + statement.setLong(++parameterIndex, stats.getBestTime().get()); + } else { + statement.setNull(++parameterIndex, Types.INTEGER); + statement.setNull(++parameterIndex, Types.INTEGER); + } + statement.setInt(++parameterIndex, stats.getRoundsSurvived()); + statement.setInt(++parameterIndex, stats.getKills()); + statement.setInt(++parameterIndex, stats.getKnocks()); + statement.setInt(++parameterIndex, stats.getKnocks()); + statement.setInt(++parameterIndex, stats.getRevives()); + statement.setInt(++parameterIndex, stats.getRegularShots()); + statement.setInt(++parameterIndex, stats.getHeadshots()); statement.execute(); } + + @Override + protected @NotNull List getBestTimesInternal(@NotNull Connection connection, @NotNull Key mapKey) + throws SQLException { + PreparedStatement statement = connection.prepareStatement(""" + SELECT player_uuid + FROM zombies_player_map_stats + WHERE map_key = ? + AND best_time IS NOT NULL + ORDER BY best_time + """); + statement.setString(1, mapKey.asString()); + ResultSet resultSet = statement.executeQuery(); + List bestTimes = new ArrayList<>(); + while (resultSet.next()) { + UUID uuid = UUID.fromString(resultSet.getString("player_uuid")); + long bestTime = resultSet.getLong("best_time"); + bestTimes.add(new BestTime(uuid, bestTime)); + } + + return bestTimes; + } } diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesDatabase.java b/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesDatabase.java index ae587fd35..803e56243 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesDatabase.java +++ b/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesDatabase.java @@ -1,9 +1,15 @@ package org.phantazm.zombies.stats; +import net.kyori.adventure.key.Key; import org.jetbrains.annotations.NotNull; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + public interface ZombiesDatabase { - void synchronize(@NotNull ZombiesPlayerMapStats stats); + void synchronizeZombiesPlayerMapStats(@NotNull ZombiesPlayerMapStats stats); + CompletableFuture> getBestTimes(@NotNull Key mapKey); } diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesPlayerMapStats.java b/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesPlayerMapStats.java index 43268ece7..af2284b1c 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesPlayerMapStats.java +++ b/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesPlayerMapStats.java @@ -2,7 +2,9 @@ import net.kyori.adventure.key.Key; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.Optional; import java.util.UUID; public interface ZombiesPlayerMapStats { @@ -19,6 +21,10 @@ public interface ZombiesPlayerMapStats { void setWins(int wins); + @NotNull Optional getBestTime(); + + void setBestTime(@Nullable Long bestTime); + int getRoundsSurvived(); void setRoundsSurvived(int roundsSurvived); From 4a0f12b0c523bcf36705a957e6e9b675920b05bf Mon Sep 17 00:00:00 2001 From: tahmid-23 <60953955+tahmid-23@users.noreply.github.com> Date: Sat, 17 Jun 2023 23:48:49 -0400 Subject: [PATCH 034/181] shutdown executor --- .../org/phantazm/server/PhantazmServer.java | 2 +- .../org/phantazm/server/ZombiesFeature.java | 33 +++++++++++++++++-- .../zombies/stats/HikariZombiesDatabase.java | 23 ++++++------- .../zombies/stats/ZombiesDatabase.java | 3 +- 4 files changed, 42 insertions(+), 19 deletions(-) diff --git a/server/src/main/java/org/phantazm/server/PhantazmServer.java b/server/src/main/java/org/phantazm/server/PhantazmServer.java index af69bf20d..c7833513e 100644 --- a/server/src/main/java/org/phantazm/server/PhantazmServer.java +++ b/server/src/main/java/org/phantazm/server/PhantazmServer.java @@ -163,7 +163,7 @@ else if (serverInfoConfig.isUnsafeConfiguration()) { public static void shutdown(@Nullable String reason) { LOGGER.info("Shutting down server. Reason: " + reason); - ZombiesFeature.getDatabase().close(); + ZombiesFeature.end(); loginValidator.flush(); MinecraftServer.stopCleanly(); diff --git a/server/src/main/java/org/phantazm/server/ZombiesFeature.java b/server/src/main/java/org/phantazm/server/ZombiesFeature.java index 2144ad8f2..508548a76 100644 --- a/server/src/main/java/org/phantazm/server/ZombiesFeature.java +++ b/server/src/main/java/org/phantazm/server/ZombiesFeature.java @@ -99,7 +99,9 @@ import java.nio.file.Path; import java.util.*; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.function.Function; public final class ZombiesFeature { @@ -113,6 +115,7 @@ public final class ZombiesFeature { private static Map powerups; private static MobSpawnerSource mobSpawnerSource; private static ZombiesSceneRouter sceneRouter; + private static ExecutorService databaseExecutor; private static HikariZombiesDatabase database; static void initialize(@NotNull EventNode globalEventNode, @NotNull ContextManager contextManager, @@ -148,7 +151,7 @@ static void initialize(@NotNull EventNode globalEventNode, @NotNull Conte // https://bugs.mojang.com/browse/MC-87984 Team mobNoPushTeam = teamManager.createBuilder("mobNoPush").collisionRule(TeamsPacket.CollisionRule.PUSH_OTHER_TEAMS).build(); - Executor databaseExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); + databaseExecutor = Executors.newSingleThreadExecutor(); HikariConfig config = new HikariConfig("./zombies.hikari.properties"); HikariDataSource dataSource = new HikariDataSource(config); database = switch (dataSource.getDataSourceClassName()) { @@ -379,7 +382,31 @@ private static Map loadFeature(String featureName, Loa return FeatureUtils.check(sceneRouter); } - public static @NotNull HikariZombiesDatabase getDatabase() { - return database; + public static void end() { + if (database != null) { + FeatureUtils.check(database).close(); + } + + if (databaseExecutor != null) { + FeatureUtils.check(databaseExecutor).shutdown(); + + try { + LOGGER.info( + "Shutting down database executor. Please allow for one minute before shutdown " + "completes."); + if (!databaseExecutor.awaitTermination(1L, TimeUnit.MINUTES)) { + databaseExecutor.shutdownNow(); + + LOGGER.warn( + "Not all database tasks completed. Please allow for one minute for tasks to be canceled."); + if (!databaseExecutor.awaitTermination(1L, TimeUnit.MINUTES)) { + LOGGER.warn("Database tasks failed to cancel."); + } + } + } + catch (InterruptedException e) { + databaseExecutor.shutdownNow(); + Thread.currentThread().interrupt(); + } + } } } diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/HikariZombiesDatabase.java b/zombies/src/main/java/org/phantazm/zombies/stats/HikariZombiesDatabase.java index c0c5c2342..7614a8e22 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stats/HikariZombiesDatabase.java +++ b/zombies/src/main/java/org/phantazm/zombies/stats/HikariZombiesDatabase.java @@ -11,7 +11,6 @@ import java.sql.SQLException; import java.util.List; import java.util.Objects; -import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; @@ -29,19 +28,15 @@ public HikariZombiesDatabase(@NotNull Executor executor, @NotNull HikariDataSour } @Override - public void synchronizeZombiesPlayerMapStats(@NotNull ZombiesPlayerMapStats stats) { - CompletableFuture.runAsync(() -> { + public @NotNull CompletableFuture synchronizeZombiesPlayerMapStats(@NotNull ZombiesPlayerMapStats stats) { + return CompletableFuture.runAsync(() -> { try (Connection connection = dataSource.getConnection()) { synchronizeZombiesPlayerMapStatsInternal(connection, stats); } catch (SQLException e) { throw new RuntimeException(e); } - }, executor).whenComplete((ignored, throwable) -> { - if (throwable != null) { - LOGGER.warn("Exception while querying database", throwable); - } - }); + }, executor).whenComplete(this::logException); } @Override @@ -53,11 +48,13 @@ public CompletableFuture> getBestTimes(@NotNull Key mapKey) { catch (SQLException e) { throw new RuntimeException(e); } - }, executor).whenComplete((ignored, throwable) -> { - if (throwable != null) { - LOGGER.warn("Exception while querying database", throwable); - } - }); + }, executor).whenComplete(this::logException); + } + + private void logException(T ignored, Throwable throwable) { + if (throwable != null) { + LOGGER.warn("Exception while querying database", throwable); + } } protected abstract void synchronizeZombiesPlayerMapStatsInternal(@NotNull Connection connection, diff --git a/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesDatabase.java b/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesDatabase.java index 803e56243..f6ae52961 100644 --- a/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesDatabase.java +++ b/zombies/src/main/java/org/phantazm/zombies/stats/ZombiesDatabase.java @@ -4,12 +4,11 @@ import org.jetbrains.annotations.NotNull; import java.util.List; -import java.util.UUID; import java.util.concurrent.CompletableFuture; public interface ZombiesDatabase { - void synchronizeZombiesPlayerMapStats(@NotNull ZombiesPlayerMapStats stats); + @NotNull CompletableFuture synchronizeZombiesPlayerMapStats(@NotNull ZombiesPlayerMapStats stats); CompletableFuture> getBestTimes(@NotNull Key mapKey); } From 1e7f61825d92c367a45eea423c7c8ae85fb91074 Mon Sep 17 00:00:00 2001 From: steank Date: Sat, 17 Jun 2023 23:08:43 -0700 Subject: [PATCH 035/181] change order --- .../java/org/phantazm/zombies/player/BasicZombiesPlayer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java index 13c9b8ae1..032a2ff47 100644 --- a/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java +++ b/zombies/src/main/java/org/phantazm/zombies/player/BasicZombiesPlayer.java @@ -19,15 +19,15 @@ public class BasicZombiesPlayer implements ZombiesPlayer, ForwardingAudience { private final ZombiesScene scene; private final ZombiesPlayerModule module; - private final TickTaskScheduler taskScheduler; private final Map stateMap; + private final TickTaskScheduler taskScheduler; public BasicZombiesPlayer(@NotNull ZombiesScene scene, @NotNull ZombiesPlayerModule module, @NotNull Map stateMap, @NotNull TickTaskScheduler taskScheduler) { this.scene = Objects.requireNonNull(scene, "scene"); this.module = Objects.requireNonNull(module, "module"); - this.taskScheduler = Objects.requireNonNull(taskScheduler, "taskScheduler"); this.stateMap = Objects.requireNonNull(stateMap, "stateMap"); + this.taskScheduler = Objects.requireNonNull(taskScheduler, "taskScheduler"); } @Override From 71d5ebb38ee0f2d98eba7c28ba94fb9fed82e259 Mon Sep 17 00:00:00 2001 From: steank Date: Sat, 17 Jun 2023 23:40:46 -0700 Subject: [PATCH 036/181] massively jack up connection-timeout and read-timeout to 24 hours, to prevent disconnects when timing out (recommend TimeOut Out Fabric mod on the client as well) --- defaultRunData/velocity/velocity.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/defaultRunData/velocity/velocity.toml b/defaultRunData/velocity/velocity.toml index 429addec3..f62f352f9 100644 --- a/defaultRunData/velocity/velocity.toml +++ b/defaultRunData/velocity/velocity.toml @@ -94,10 +94,10 @@ compression-level = -1 login-ratelimit = 3000 # Specify a custom timeout for connection timeouts here. The default is five seconds. -connection-timeout = 5000 +connection-timeout = 86400000 # Specify a read timeout for connections here. The default is 30 seconds. -read-timeout = 30000 +read-timeout = 86400000 # Enables compatibility with HAProxy's PROXY protocol. If you don't know what this is for, then # don't enable it. From 3e3d90576d5a3edcc30d583be3f87f34a02ba32c Mon Sep 17 00:00:00 2001 From: steank Date: Sat, 17 Jun 2023 23:51:33 -0700 Subject: [PATCH 037/181] configure "Run server" run configuration to operate on an unbounded packet queue + make Minestom interpret negative packet queue limits as unbounded --- .run/Run server.run.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.run/Run server.run.xml b/.run/Run server.run.xml index 060941559..e6b3ba9c2 100644 --- a/.run/Run server.run.xml +++ b/.run/Run server.run.xml @@ -1,7 +1,7 @@