From 9468dbf4607af3ac4612d88654a451dfed8b9a25 Mon Sep 17 00:00:00 2001 From: Pufferfish Date: Mon, 15 Jul 2024 22:23:53 +0200 Subject: [PATCH 1/7] Don't require position and rotation when accepting --- README.md | 14 ++++++-------- .../nucleoid/plasmid/game/player/PlayerOffer.java | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index eb077072..fad7c79c 100644 --- a/README.md +++ b/README.md @@ -202,11 +202,10 @@ However! Before we give functionality to our brilliant example game, we need to An example offer listener may look like: ```java activity.listen(GamePlayerEvents.OFFER, offer -> { - ServerPlayerEntity player = offer.player(); - return offer.accept(world, new Vec3d(0.0, 64.0, 0.0)) - .and(() -> { - player.changeGameMode(GameMode.ADVENTURE); - }); + return offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) + .thenRun(player -> { + player.changeGameMode(GameMode.ADVENTURE); + }); }); ``` @@ -271,9 +270,8 @@ public final class ExampleGame { } private PlayerOfferResult onPlayerOffer(PlayerOffer offer) { - ServerPlayerEntity player = offer.player(); - return offer.accept(this.world, new Vec3d(0.0, 64.0, 0.0)) - .and(() -> { + return offer.accept(this.world, new Vec3d(0.0, 65.0, 0.0)) + .thenRun(player -> { player.changeGameMode(GameMode.ADVENTURE); }); } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java index 1b82d964..c8753f8d 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java @@ -77,6 +77,20 @@ default PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position) { return this.accept(world, position, 0.0f, 0.0f); } + /** + * Returns an offer result that accepts this player offer and allows the player into this {@link GameSpace}. + *

+ * This function does not do anything on its own, but its result must be returned within a + * {@link GamePlayerEvents#OFFER} listener. + * + * @param world the world that the player should be teleported to when accepted + * @return an "accept" offer result + * @see PlayerOfferResult.Accept#thenRun(Consumer) + */ + default PlayerOfferResult.Accept accept(ServerWorld world) { + return this.accept(world, Vec3d.ofBottomCenter(world.getSpawnPos())); + } + /** * Returns an offer result that rejects this player offer and does not allow the player into this {@link GameSpace}. *

From 25f6dc2a896545414186b4893ea29e3313917b67 Mon Sep 17 00:00:00 2001 From: Pufferfish Date: Tue, 16 Jul 2024 11:50:51 +0200 Subject: [PATCH 2/7] Implement offers with multiple players --- README.md | 4 +- .../nucleoid/plasmid/command/GameCommand.java | 4 +- .../plasmid/game/GameSpacePlayers.java | 14 ++--- .../game/manager/ManagedGameSpace.java | 4 +- .../game/manager/ManagedGameSpacePlayers.java | 27 +++++----- .../plasmid/game/player/GamePlayerJoiner.java | 6 +-- .../plasmid/game/player/LocalPlayerOffer.java | 43 +++++++++++---- .../plasmid/game/player/PlayerOffer.java | 54 ++++++++++--------- .../game/player/PlayerOfferResult.java | 9 +++- .../xyz/nucleoid/plasmid/test/JankGame.java | 8 ++- .../xyz/nucleoid/plasmid/test/TestGame.java | 4 +- .../test/TestGameWithResourcePack.java | 8 ++- 12 files changed, 115 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index fad7c79c..c6c27767 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ An example offer listener may look like: ```java activity.listen(GamePlayerEvents.OFFER, offer -> { return offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) - .thenRun(player -> { + .thenRunForEach(player -> { player.changeGameMode(GameMode.ADVENTURE); }); }); @@ -271,7 +271,7 @@ public final class ExampleGame { private PlayerOfferResult onPlayerOffer(PlayerOffer offer) { return offer.accept(this.world, new Vec3d(0.0, 65.0, 0.0)) - .thenRun(player -> { + .thenRunForEach(player -> { player.changeGameMode(GameMode.ADVENTURE); }); } diff --git a/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java b/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java index 7e71bdb3..792b4843 100644 --- a/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java +++ b/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java @@ -289,9 +289,7 @@ private static void joinAllPlayersToGame(ServerCommandSource source, GameSpace g var intent = JoinIntent.ANY; var screen = gameSpace.getPlayers().screenJoins(players, intent); if (screen.isOk()) { - for (var player : players) { - gameSpace.getPlayers().offer(player, intent); - } + gameSpace.getPlayers().offer(players, intent); } else { source.sendError(screen.errorCopy().formatted(Formatting.RED)); } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/GameSpacePlayers.java b/src/main/java/xyz/nucleoid/plasmid/game/GameSpacePlayers.java index 1dd79dbb..81def39d 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/GameSpacePlayers.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/GameSpacePlayers.java @@ -17,32 +17,32 @@ */ public interface GameSpacePlayers extends PlayerSet { /** - * Screens a group of players and returns whether the collective group should be allowed into the game. + * Screens a player or group of players and returns whether the collective group should be allowed into the game. *

* This logic is controlled through the active {@link GameActivity} through {@link GamePlayerEvents#SCREEN_JOINS}. * * @param players the group of players trying to join * @param intent the intent of the players trying to join, such as whether they want to participate or spectate - * @return a {@link GameResult} describing whether this group can join this game, or an error if not + * @return a {@link GameResult} describing whether these players can join this game, or an error if not * @see GamePlayerEvents#SCREEN_JOINS - * @see GameSpacePlayers#offer(ServerPlayerEntity, JoinIntent) + * @see GameSpacePlayers#offer(Collection, JoinIntent) * @see xyz.nucleoid.plasmid.game.player.GamePlayerJoiner */ GameResult screenJoins(Collection players, JoinIntent intent); /** - * Offers an individual player to join this game. If accepted, they will be teleported into the game, and if not + * Offers a player or group of players to join this game. If accepted, they will be teleported into the game, and if not * an error {@link GameResult} will be returned. *

* This logic is controlled through the active {@link GameActivity} through {@link GamePlayerEvents#OFFER}. * - * @param player the player trying to join + * @param players the players trying to join * @param intent the intent of the players trying to join, such as whether they want to participate or spectate - * @return a {@link GameResult} describing whether this player joined the game, or an error if not + * @return a {@link GameResult} describing whether these players joined the game, or an error if not * @see GamePlayerEvents#OFFER * @see xyz.nucleoid.plasmid.game.player.GamePlayerJoiner */ - GameResult offer(ServerPlayerEntity player, JoinIntent intent); + GameResult offer(Collection players, JoinIntent intent); /** * Attempts to remove the given {@link ServerPlayerEntity} from this {@link GameSpace}. diff --git a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java index f6abc17f..fc38864c 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java @@ -217,9 +217,9 @@ private GameResult attemptScreenJoins(Collection players, JoinInten PlayerOfferResult offerPlayer(LocalPlayerOffer offer) { if (this.closed) { return offer.reject(GameTexts.Join.gameClosed()); - } else if (this.manager.inGame(offer.player())) { + } else if (offer.serverPlayers().stream().anyMatch(this.manager::inGame)) { return offer.reject(GameTexts.Join.inOtherGame()); - } else if (!Permissions.check(offer.player(), "plasmid.join_game", true)) { + } else if (offer.serverPlayers().stream().anyMatch(p -> !Permissions.check(p, "plasmid.join_game", true))) { return offer.reject(GameTexts.Join.notAllowed()); } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java index 593dcd36..50abf51c 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java @@ -6,14 +6,12 @@ import xyz.nucleoid.plasmid.game.GameResult; import xyz.nucleoid.plasmid.game.GameSpacePlayers; import xyz.nucleoid.plasmid.game.GameTexts; -import xyz.nucleoid.plasmid.game.player.JoinIntent; -import xyz.nucleoid.plasmid.game.player.LocalPlayerOffer; -import xyz.nucleoid.plasmid.game.player.MutablePlayerSet; -import xyz.nucleoid.plasmid.game.player.PlayerOfferResult; +import xyz.nucleoid.plasmid.game.player.*; import xyz.nucleoid.plasmid.game.player.isolation.IsolatingPlayerTeleporter; import java.util.Collection; import java.util.Iterator; +import java.util.List; import java.util.UUID; public final class ManagedGameSpacePlayers implements GameSpacePlayers { @@ -33,8 +31,8 @@ public GameResult screenJoins(Collection players, JoinIntent } @Override - public GameResult offer(ServerPlayerEntity player, JoinIntent intent) { - var result = this.attemptOffer(player, intent); + public GameResult offer(Collection players, JoinIntent intent) { + var result = this.attemptOffer(players, intent); if (result.isError()) { this.attemptGarbageCollection(); @@ -43,19 +41,24 @@ public GameResult offer(ServerPlayerEntity player, JoinIntent intent) { return result; } - private GameResult attemptOffer(ServerPlayerEntity player, JoinIntent intent) { - if (this.set.contains(player)) { + private GameResult attemptOffer(Collection players, JoinIntent intent) { + if (players.stream().anyMatch(this.set::contains)) { return GameResult.error(GameTexts.Join.alreadyJoined()); } - var offer = new LocalPlayerOffer(player, intent); + var offer = new LocalPlayerOffer(players, intent); switch (this.space.offerPlayer(offer)) { case LocalPlayerOffer.Accept accept -> { try { - this.teleporter.teleportIn(player, accept::applyJoin); - this.set.add(player); - this.space.onAddPlayer(player); + var joiningSet = new MutablePlayerSet(this.space.getServer()); + for (var player : players) { + this.teleporter.teleportIn(player, accept::applyJoin); + this.set.add(player); + this.space.onAddPlayer(player); + joiningSet.add(player); + } + accept.joinAll(joiningSet); return GameResult.ok(); } catch (Throwable throwable) { diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java b/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java index cd76e5cf..fbf89e5c 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java @@ -46,9 +46,9 @@ private static Results tryJoinAll(Collection players, GameSp return results; } - for (var player : players) { - var result = gameSpace.getPlayers().offer(player, intent); - if (result.isError()) { + var result = gameSpace.getPlayers().offer(players, intent); + if (result.isError()) { + for (var player : players) { results.playerErrors.put(player, result.error()); } } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java index 81e2cdbb..e4efe1da 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java @@ -1,20 +1,39 @@ package xyz.nucleoid.plasmid.game.player; import com.mojang.authlib.GameProfile; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; import net.minecraft.util.math.Vec3d; import net.minecraft.world.GameMode; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import java.util.function.Consumer; -public record LocalPlayerOffer(ServerPlayerEntity player, JoinIntent intent) implements PlayerOffer { +public record LocalPlayerOffer(Collection serverPlayers, JoinIntent intent) implements PlayerOffer { @Override - public GameProfile profile() { - return this.player.getGameProfile(); + public Collection players() { + return this.serverPlayers + .stream() + .map(PlayerEntity::getGameProfile) + .toList(); + } + + @Override + public Collection playerIds() { + return this.serverPlayers + .stream() + .map(player -> player.getGameProfile().getId()) + .toList(); + } + + @Override + public Collection playerNames() { + return this.serverPlayers + .stream() + .map(player -> player.getGameProfile().getName()) + .toList(); } @Override @@ -33,7 +52,7 @@ public static class Accept implements PlayerOfferResult.Accept { private final float yaw; private final float pitch; - private final List> thenRun = new ArrayList<>(); + private final List> thenRun = new ArrayList<>(); Accept(ServerWorld world, Vec3d position, float yaw, float pitch) { this.world = world; @@ -43,19 +62,21 @@ public static class Accept implements PlayerOfferResult.Accept { } @Override - public Accept thenRun(Consumer consumer) { + public Accept thenRun(Consumer consumer) { this.thenRun.add(consumer); return this; } + public void joinAll(PlayerSet players) { + for (var consumer : this.thenRun) { + consumer.accept(players); + } + } + public ServerWorld applyJoin(ServerPlayerEntity player) { player.changeGameMode(GameMode.SURVIVAL); player.refreshPositionAndAngles(this.position.x, this.position.y, this.position.z, this.yaw, this.pitch); - for (Consumer consumer : this.thenRun) { - consumer.accept(player); - } - return this.world; } } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java index c8753f8d..e24f7362 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java @@ -1,7 +1,6 @@ package xyz.nucleoid.plasmid.game.player; import com.mojang.authlib.GameProfile; -import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; import net.minecraft.util.math.Vec3d; @@ -9,11 +8,12 @@ import xyz.nucleoid.plasmid.game.GameTexts; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; +import java.util.Collection; import java.util.UUID; import java.util.function.Consumer; /** - * Represents a request for a {@link ServerPlayerEntity} to join a {@link GameSpace}. + * Represents a request for of a player or group of players to join a {@link GameSpace}. *

* This object should be used in order to construct a {@link PlayerOfferResult} object to return from a listener to the * {@link GamePlayerEvents#OFFER} event. @@ -23,53 +23,59 @@ */ public interface PlayerOffer { /** - * @return the {@link GameProfile} of the player that is requesting access to this {@link GameSpace} + * @return the set of {@link GameProfile} of the players that are requesting access to this {@link GameSpace} */ - GameProfile profile(); + Collection players(); /** - * @return the {@link UUID profile UUID} of the player that is requesting access to this {@link GameSpace} + * @return the {@link UUID profile UUID} of the players that are requesting access to this {@link GameSpace} */ - default UUID playerId() { - return this.profile().getId(); + default Collection playerIds() { + return this.players() + .stream() + .map(GameProfile::getId) + .toList(); } /** - * @return the username of the player that is requesting access to this {@link GameSpace} + * @return the usernames of the players that are requesting access to this {@link GameSpace} */ - default String playerName() { - return this.profile().getName(); + default Collection playerNames() { + return this.players() + .stream() + .map(GameProfile::getName) + .toList(); } /** - * @return the {@link JoinIntent 'intent'} of the player, such as whether they want to participate or spectate + * @return the {@link JoinIntent 'intent'} of the players, such as whether they want to participate or spectate * @see JoinIntent */ JoinIntent intent(); /** - * Returns an offer result that accepts this player offer and allows the player into this {@link GameSpace}. + * Returns an offer result that accepts this offer and allows the players into this {@link GameSpace}. *

* This function does not do anything on its own, but its result must be returned within a * {@link GamePlayerEvents#OFFER} listener. * - * @param world the world that the player should be teleported to when accepted - * @param position the position that the player should be teleported to when accepted - * @param yaw the 'yaw' angle that the player should be teleported to when accepted - * @param pitch the 'pitch' angle that the player should be teleported to when accepted + * @param world the world that the players should be teleported to when accepted + * @param position the position that the players should be teleported to when accepted + * @param yaw the 'yaw' angle that the players should be teleported to when accepted + * @param pitch the 'pitch' angle that the players should be teleported to when accepted * @return an "accept" offer result * @see PlayerOfferResult.Accept#thenRun(Consumer) */ PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position, float yaw, float pitch); /** - * Returns an offer result that accepts this player offer and allows the player into this {@link GameSpace}. + * Returns an offer result that accepts this offer and allows the player into this {@link GameSpace}. *

* This function does not do anything on its own, but its result must be returned within a * {@link GamePlayerEvents#OFFER} listener. * - * @param world the world that the player should be teleported to when accepted - * @param position the position that the player should be teleported to when accepted + * @param world the world that the players should be teleported to when accepted + * @param position the position that the players should be teleported to when accepted * @return an "accept" offer result * @see PlayerOfferResult.Accept#thenRun(Consumer) */ @@ -78,12 +84,12 @@ default PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position) { } /** - * Returns an offer result that accepts this player offer and allows the player into this {@link GameSpace}. + * Returns an offer result that accepts this offer and allows the players into this {@link GameSpace}. *

* This function does not do anything on its own, but its result must be returned within a * {@link GamePlayerEvents#OFFER} listener. * - * @param world the world that the player should be teleported to when accepted + * @param world the world that the players should be teleported to when accepted * @return an "accept" offer result * @see PlayerOfferResult.Accept#thenRun(Consumer) */ @@ -92,19 +98,19 @@ default PlayerOfferResult.Accept accept(ServerWorld world) { } /** - * Returns an offer result that rejects this player offer and does not allow the player into this {@link GameSpace}. + * Returns an offer result that rejects this offer and does not allow the players into this {@link GameSpace}. *

* This function does not do anything on its own, but its result must be returned within a * {@link GamePlayerEvents#OFFER} listener. * - * @param reason a text message that explains why this player was rejected + * @param reason a text message that explains why these players were rejected * @return a "reject" offer result * @see GameTexts.Join */ PlayerOfferResult.Reject reject(Text reason); /** - * Returns an offer result that does nothing with this player offer, passing on any handling to any other listener. + * Returns an offer result that does nothing with this offer, passing on any handling to any other listener. * * @return a "passing" offer result */ diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOfferResult.java b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOfferResult.java index ed123e85..3ecc59c9 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOfferResult.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOfferResult.java @@ -3,6 +3,9 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; +import java.util.Collection; +import java.util.List; +import java.util.Set; import java.util.function.Consumer; public sealed interface PlayerOfferResult permits PlayerOfferResult.Pass, PlayerOfferResult.Accept, PlayerOfferResult.Reject { @@ -14,7 +17,11 @@ private Pass() { } non-sealed interface Accept extends PlayerOfferResult { - PlayerOfferResult.Accept thenRun(Consumer consumer); + PlayerOfferResult.Accept thenRun(Consumer consumer); + + default PlayerOfferResult.Accept thenRunForEach(Consumer consumer) { + return this.thenRun(players -> players.forEach(consumer)); + } } non-sealed interface Reject extends PlayerOfferResult { diff --git a/src/testmod/java/xyz/nucleoid/plasmid/test/JankGame.java b/src/testmod/java/xyz/nucleoid/plasmid/test/JankGame.java index 8eaf7d57..db989009 100644 --- a/src/testmod/java/xyz/nucleoid/plasmid/test/JankGame.java +++ b/src/testmod/java/xyz/nucleoid/plasmid/test/JankGame.java @@ -60,7 +60,9 @@ public static GameOpenProcedure open(GameOpenContext context) { return context.openWithWorld(worldConfig, (activity, world) -> { activity.listen(GamePlayerEvents.OFFER, offer -> offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) - .thenRun(player -> player.changeGameMode(GameMode.ADVENTURE)) + .thenRunForEach(joiningPlayer -> { + joiningPlayer.changeGameMode(GameMode.ADVENTURE); + }) ); GameWaitingLobby.addTo(activity, new PlayerConfig(1, 99)); @@ -172,7 +174,9 @@ private static GameResult startGame(GameSpace gameSpace) { activity.listen(GamePlayerEvents.OFFER, offer -> offer.accept(gameSpace.getWorlds().iterator().next(), new Vec3d(0.0, 65.0, 0.0)) - .thenRun(joiningPlayer -> joiningPlayer.changeGameMode(GameMode.ADVENTURE)) + .thenRunForEach(joiningPlayer -> { + joiningPlayer.changeGameMode(GameMode.ADVENTURE); + }) ); }); diff --git a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java index eaf63ee5..4463a4f8 100644 --- a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java +++ b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java @@ -60,7 +60,9 @@ public static GameOpenProcedure open(GameOpenContext context) { return context.openWithWorld(worldConfig, (activity, world) -> { activity.listen(GamePlayerEvents.OFFER, offer -> offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) - .thenRun(player -> player.changeGameMode(GameMode.ADVENTURE)) + .thenRunForEach(joiningPlayer -> { + joiningPlayer.changeGameMode(GameMode.ADVENTURE); + }) ); GameWaitingLobby.addTo(activity, new PlayerConfig(1, 99)); diff --git a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGameWithResourcePack.java b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGameWithResourcePack.java index 5c170f52..59726fae 100644 --- a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGameWithResourcePack.java +++ b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGameWithResourcePack.java @@ -53,7 +53,9 @@ public static GameOpenProcedure open(GameOpenContext context) { return context.openWithWorld(worldConfig, (activity, world) -> { activity.listen(GamePlayerEvents.OFFER, offer -> offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) - .thenRun(player -> player.changeGameMode(GameMode.ADVENTURE)) + .thenRunForEach(joiningPlayer -> { + joiningPlayer.changeGameMode(GameMode.ADVENTURE); + }) ); GameWaitingLobby.addTo(activity, new PlayerConfig(1, 99)); @@ -129,7 +131,9 @@ private static GameResult startGame(GameSpace gameSpace, int iter) { activity.listen(GamePlayerEvents.OFFER, offer -> offer.accept(gameSpace.getWorlds().iterator().next(), new Vec3d(0.0, 65.0, 0.0)) - .thenRun(player -> player.changeGameMode(GameMode.ADVENTURE)) + .thenRunForEach(joiningPlayer -> { + joiningPlayer.changeGameMode(GameMode.ADVENTURE); + }) ); }); From a4309eb963c8c646b727f89c9afa510dfefbf80e Mon Sep 17 00:00:00 2001 From: Pufferfish Date: Tue, 16 Jul 2024 11:54:31 +0200 Subject: [PATCH 3/7] Rename PlayerOffer to JoinOffer --- .../plasmid/game/common/GameWaitingLobby.java | 6 ++-- .../plasmid/game/event/GamePlayerEvents.java | 14 ++++----- .../game/manager/ManagedGameSpace.java | 6 ++-- .../game/manager/ManagedGameSpacePlayers.java | 7 ++--- .../plasmid/game/player/JoinIntent.java | 2 +- .../{PlayerOffer.java => JoinOffer.java} | 22 +++++++------- .../plasmid/game/player/JoinOfferResult.java | 27 +++++++++++++++++ ...alPlayerOffer.java => LocalJoinOffer.java} | 8 ++--- .../game/player/PlayerOfferResult.java | 30 ------------------- 9 files changed, 59 insertions(+), 63 deletions(-) rename src/main/java/xyz/nucleoid/plasmid/game/player/{PlayerOffer.java => JoinOffer.java} (85%) create mode 100644 src/main/java/xyz/nucleoid/plasmid/game/player/JoinOfferResult.java rename src/main/java/xyz/nucleoid/plasmid/game/player/{LocalPlayerOffer.java => LocalJoinOffer.java} (86%) delete mode 100644 src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOfferResult.java diff --git a/src/main/java/xyz/nucleoid/plasmid/game/common/GameWaitingLobby.java b/src/main/java/xyz/nucleoid/plasmid/game/common/GameWaitingLobby.java index 838e75c7..ecd4acdf 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/common/GameWaitingLobby.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/common/GameWaitingLobby.java @@ -22,8 +22,8 @@ import xyz.nucleoid.plasmid.game.event.GameActivityEvents; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; import xyz.nucleoid.plasmid.game.manager.GameSpaceManager; -import xyz.nucleoid.plasmid.game.player.PlayerOffer; -import xyz.nucleoid.plasmid.game.player.PlayerOfferResult; +import xyz.nucleoid.plasmid.game.player.JoinOffer; +import xyz.nucleoid.plasmid.game.player.JoinOfferResult; import xyz.nucleoid.plasmid.game.rule.GameRuleType; import xyz.nucleoid.plasmid.util.compatibility.AfkDisplayCompatibility; @@ -179,7 +179,7 @@ private GameResult screenJoins(Collection players) { return GameResult.ok(); } - private PlayerOfferResult offerPlayer(PlayerOffer offer) { + private JoinOfferResult offerPlayer(JoinOffer offer) { if (this.isFull()) { return offer.reject(GameTexts.Join.gameFull()); } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java b/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java index a347fa98..66856b98 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java @@ -10,8 +10,8 @@ import xyz.nucleoid.plasmid.game.GameSpace; import xyz.nucleoid.plasmid.game.GameTexts; import xyz.nucleoid.plasmid.game.player.JoinIntent; -import xyz.nucleoid.plasmid.game.player.PlayerOffer; -import xyz.nucleoid.plasmid.game.player.PlayerOfferResult; +import xyz.nucleoid.plasmid.game.player.JoinOffer; +import xyz.nucleoid.plasmid.game.player.JoinOfferResult; import xyz.nucleoid.stimuli.event.StimulusEvent; import java.util.Collection; @@ -129,10 +129,10 @@ public final class GamePlayerEvents { * the player into the {@link GameSpace} world in the correct location. *

* Games must respond to this event in order for a player to be able to join by returning either - * {@link PlayerOffer#accept(ServerWorld, Vec3d)} or {@link PlayerOffer#reject(Text)}. + * {@link JoinOffer#accept(ServerWorld, Vec3d)} or {@link JoinOffer#reject(Text)}. * - * @see PlayerOffer - * @see PlayerOfferResult + * @see JoinOffer + * @see JoinOfferResult * @see GamePlayerEvents#SCREEN_JOINS * @see GamePlayerEvents#JOIN */ @@ -140,7 +140,7 @@ public final class GamePlayerEvents { try { for (var listener : ctx.getListeners()) { var result = listener.onOfferPlayer(offer); - if (!(result instanceof PlayerOfferResult.Pass)) { + if (!(result instanceof JoinOfferResult.Pass)) { return result; } } @@ -180,7 +180,7 @@ public interface ScreenJoins { } public interface Offer { - PlayerOfferResult onOfferPlayer(PlayerOffer offer); + JoinOfferResult onOfferPlayer(JoinOffer offer); } public interface Name { diff --git a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java index fc38864c..08e4f519 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java @@ -20,8 +20,8 @@ import xyz.nucleoid.plasmid.game.event.GameActivityEvents; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; import xyz.nucleoid.plasmid.game.player.JoinIntent; -import xyz.nucleoid.plasmid.game.player.LocalPlayerOffer; -import xyz.nucleoid.plasmid.game.player.PlayerOfferResult; +import xyz.nucleoid.plasmid.game.player.LocalJoinOffer; +import xyz.nucleoid.plasmid.game.player.JoinOfferResult; import java.util.Collection; import java.util.Map; @@ -214,7 +214,7 @@ private GameResult attemptScreenJoins(Collection players, JoinInten return this.state.invoker(GamePlayerEvents.SCREEN_JOINS).screenJoins(players, intent); } - PlayerOfferResult offerPlayer(LocalPlayerOffer offer) { + JoinOfferResult offerPlayer(LocalJoinOffer offer) { if (this.closed) { return offer.reject(GameTexts.Join.gameClosed()); } else if (offer.serverPlayers().stream().anyMatch(this.manager::inGame)) { diff --git a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java index 50abf51c..fd7540ad 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java @@ -11,7 +11,6 @@ import java.util.Collection; import java.util.Iterator; -import java.util.List; import java.util.UUID; public final class ManagedGameSpacePlayers implements GameSpacePlayers { @@ -46,10 +45,10 @@ private GameResult attemptOffer(Collection players, JoinInte return GameResult.error(GameTexts.Join.alreadyJoined()); } - var offer = new LocalPlayerOffer(players, intent); + var offer = new LocalJoinOffer(players, intent); switch (this.space.offerPlayer(offer)) { - case LocalPlayerOffer.Accept accept -> { + case LocalJoinOffer.Accept accept -> { try { var joiningSet = new MutablePlayerSet(this.space.getServer()); for (var player : players) { @@ -65,7 +64,7 @@ private GameResult attemptOffer(Collection players, JoinInte return GameResult.error(GameTexts.Join.unexpectedError()); } } - case PlayerOfferResult.Reject reject -> { + case JoinOfferResult.Reject reject -> { return GameResult.error(reject.reason()); } default -> { diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinIntent.java b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinIntent.java index adaade71..f2bfe3f5 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinIntent.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinIntent.java @@ -7,7 +7,7 @@ * Represents the "intention" of a player or group of players joining a {@link GameSpace}. * It is up to the game implementation to respect this intent in the way that is appropriate for their game. This may be * accomplished by handling the {@link GamePlayerEvents#SCREEN_JOINS 'Screen Joins'} and - * {@link GamePlayerEvents#OFFER 'Player Offer'} events. + * {@link GamePlayerEvents#OFFER 'Join Offer'} events. */ public enum JoinIntent { /** diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOffer.java similarity index 85% rename from src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java rename to src/main/java/xyz/nucleoid/plasmid/game/player/JoinOffer.java index e24f7362..67960574 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOffer.java @@ -15,13 +15,13 @@ /** * Represents a request for of a player or group of players to join a {@link GameSpace}. *

- * This object should be used in order to construct a {@link PlayerOfferResult} object to return from a listener to the + * This object should be used in order to construct a {@link JoinOfferResult} object to return from a listener to the * {@link GamePlayerEvents#OFFER} event. * * @see GameSpace * @see GamePlayerEvents#OFFER */ -public interface PlayerOffer { +public interface JoinOffer { /** * @return the set of {@link GameProfile} of the players that are requesting access to this {@link GameSpace} */ @@ -64,9 +64,9 @@ default Collection playerNames() { * @param yaw the 'yaw' angle that the players should be teleported to when accepted * @param pitch the 'pitch' angle that the players should be teleported to when accepted * @return an "accept" offer result - * @see PlayerOfferResult.Accept#thenRun(Consumer) + * @see JoinOfferResult.Accept#thenRun(Consumer) */ - PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position, float yaw, float pitch); + JoinOfferResult.Accept accept(ServerWorld world, Vec3d position, float yaw, float pitch); /** * Returns an offer result that accepts this offer and allows the player into this {@link GameSpace}. @@ -77,9 +77,9 @@ default Collection playerNames() { * @param world the world that the players should be teleported to when accepted * @param position the position that the players should be teleported to when accepted * @return an "accept" offer result - * @see PlayerOfferResult.Accept#thenRun(Consumer) + * @see JoinOfferResult.Accept#thenRun(Consumer) */ - default PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position) { + default JoinOfferResult.Accept accept(ServerWorld world, Vec3d position) { return this.accept(world, position, 0.0f, 0.0f); } @@ -91,9 +91,9 @@ default PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position) { * * @param world the world that the players should be teleported to when accepted * @return an "accept" offer result - * @see PlayerOfferResult.Accept#thenRun(Consumer) + * @see JoinOfferResult.Accept#thenRun(Consumer) */ - default PlayerOfferResult.Accept accept(ServerWorld world) { + default JoinOfferResult.Accept accept(ServerWorld world) { return this.accept(world, Vec3d.ofBottomCenter(world.getSpawnPos())); } @@ -107,14 +107,14 @@ default PlayerOfferResult.Accept accept(ServerWorld world) { * @return a "reject" offer result * @see GameTexts.Join */ - PlayerOfferResult.Reject reject(Text reason); + JoinOfferResult.Reject reject(Text reason); /** * Returns an offer result that does nothing with this offer, passing on any handling to any other listener. * * @return a "passing" offer result */ - default PlayerOfferResult pass() { - return PlayerOfferResult.PASS; + default JoinOfferResult pass() { + return JoinOfferResult.PASS; } } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOfferResult.java b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOfferResult.java new file mode 100644 index 00000000..ed9920b9 --- /dev/null +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOfferResult.java @@ -0,0 +1,27 @@ +package xyz.nucleoid.plasmid.game.player; + +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; + +import java.util.function.Consumer; + +public sealed interface JoinOfferResult permits JoinOfferResult.Pass, JoinOfferResult.Accept, JoinOfferResult.Reject { + Pass PASS = new Pass(); + + final class Pass implements JoinOfferResult { + private Pass() { + } + } + + non-sealed interface Accept extends JoinOfferResult { + JoinOfferResult.Accept thenRun(Consumer consumer); + + default JoinOfferResult.Accept thenRunForEach(Consumer consumer) { + return this.thenRun(players -> players.forEach(consumer)); + } + } + + non-sealed interface Reject extends JoinOfferResult { + Text reason(); + } +} diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinOffer.java similarity index 86% rename from src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java rename to src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinOffer.java index e4efe1da..710863b9 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinOffer.java @@ -11,7 +11,7 @@ import java.util.*; import java.util.function.Consumer; -public record LocalPlayerOffer(Collection serverPlayers, JoinIntent intent) implements PlayerOffer { +public record LocalJoinOffer(Collection serverPlayers, JoinIntent intent) implements JoinOffer { @Override public Collection players() { return this.serverPlayers @@ -37,16 +37,16 @@ public Collection playerNames() { } @Override - public PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position, float yaw, float pitch) { + public JoinOfferResult.Accept accept(ServerWorld world, Vec3d position, float yaw, float pitch) { return new Accept(world, position, yaw, pitch); } @Override - public PlayerOfferResult.Reject reject(Text reason) { + public JoinOfferResult.Reject reject(Text reason) { return () -> reason; } - public static class Accept implements PlayerOfferResult.Accept { + public static class Accept implements JoinOfferResult.Accept { private final ServerWorld world; private final Vec3d position; private final float yaw; diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOfferResult.java b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOfferResult.java deleted file mode 100644 index 3ecc59c9..00000000 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOfferResult.java +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.nucleoid.plasmid.game.player; - -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; - -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.function.Consumer; - -public sealed interface PlayerOfferResult permits PlayerOfferResult.Pass, PlayerOfferResult.Accept, PlayerOfferResult.Reject { - Pass PASS = new Pass(); - - final class Pass implements PlayerOfferResult { - private Pass() { - } - } - - non-sealed interface Accept extends PlayerOfferResult { - PlayerOfferResult.Accept thenRun(Consumer consumer); - - default PlayerOfferResult.Accept thenRunForEach(Consumer consumer) { - return this.thenRun(players -> players.forEach(consumer)); - } - } - - non-sealed interface Reject extends PlayerOfferResult { - Text reason(); - } -} From 8c02c3f0eb2e265c03eff361578869dfe399c01e Mon Sep 17 00:00:00 2001 From: Pufferfish Date: Tue, 16 Jul 2024 14:03:33 +0200 Subject: [PATCH 4/7] Remove screen joins event and reimplement with offer --- .../nucleoid/plasmid/command/GameCommand.java | 8 ++--- .../plasmid/game/GameSpacePlayers.java | 9 +++--- .../plasmid/game/common/GameWaitingLobby.java | 13 ++------ .../plasmid/game/event/GamePlayerEvents.java | 30 +------------------ .../game/manager/ManagedGameSpace.java | 18 ----------- .../game/manager/ManagedGameSpacePlayers.java | 14 +++++++-- .../plasmid/game/player/GamePlayerJoiner.java | 8 +---- .../plasmid/game/player/JoinIntent.java | 3 +- 8 files changed, 24 insertions(+), 79 deletions(-) diff --git a/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java b/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java index 792b4843..da551289 100644 --- a/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java +++ b/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java @@ -287,11 +287,9 @@ private static void joinAllPlayersToGame(ServerCommandSource source, GameSpace g .collect(Collectors.toList()); var intent = JoinIntent.ANY; - var screen = gameSpace.getPlayers().screenJoins(players, intent); - if (screen.isOk()) { - gameSpace.getPlayers().offer(players, intent); - } else { - source.sendError(screen.errorCopy().formatted(Formatting.RED)); + var result = gameSpace.getPlayers().offer(players, intent); + if (result.isError()) { + source.sendError(result.errorCopy().formatted(Formatting.RED)); } } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/GameSpacePlayers.java b/src/main/java/xyz/nucleoid/plasmid/game/GameSpacePlayers.java index 81def39d..080312c0 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/GameSpacePlayers.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/GameSpacePlayers.java @@ -17,18 +17,17 @@ */ public interface GameSpacePlayers extends PlayerSet { /** - * Screens a player or group of players and returns whether the collective group should be allowed into the game. + * Simulates offer to join a player or group of players and returns whether they should be allowed into the game. *

- * This logic is controlled through the active {@link GameActivity} through {@link GamePlayerEvents#SCREEN_JOINS}. + * This logic is controlled through the active {@link GameActivity} through {@link GamePlayerEvents#OFFER}. * * @param players the group of players trying to join * @param intent the intent of the players trying to join, such as whether they want to participate or spectate * @return a {@link GameResult} describing whether these players can join this game, or an error if not - * @see GamePlayerEvents#SCREEN_JOINS - * @see GameSpacePlayers#offer(Collection, JoinIntent) + * @see GameSpacePlayers#offer(Collection, JoinIntent) * @see xyz.nucleoid.plasmid.game.player.GamePlayerJoiner */ - GameResult screenJoins(Collection players, JoinIntent intent); + GameResult simulateOffer(Collection players, JoinIntent intent); /** * Offers a player or group of players to join this game. If accepted, they will be teleported into the game, and if not diff --git a/src/main/java/xyz/nucleoid/plasmid/game/common/GameWaitingLobby.java b/src/main/java/xyz/nucleoid/plasmid/game/common/GameWaitingLobby.java index ecd4acdf..bef63af3 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/common/GameWaitingLobby.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/common/GameWaitingLobby.java @@ -89,7 +89,6 @@ public static GameWaitingLobby addTo(GameActivity activity, PlayerConfig playerC activity.listen(GameActivityEvents.TICK, lobby::onTick); activity.listen(GameActivityEvents.REQUEST_START, lobby::requestStart); - activity.listen(GamePlayerEvents.SCREEN_JOINS, (players, intent) -> lobby.screenJoins(players)); activity.listen(GamePlayerEvents.OFFER, lobby::offerPlayer); activity.listen(GamePlayerEvents.REMOVE, lobby::onRemovePlayer); @@ -170,17 +169,9 @@ private GameResult requestStart() { } } - private GameResult screenJoins(Collection players) { - int newPlayerCount = this.gameSpace.getPlayers().size() + players.size(); - if (newPlayerCount > this.playerConfig.maxPlayers()) { - return GameResult.error(GameTexts.Join.gameFull()); - } - - return GameResult.ok(); - } - private JoinOfferResult offerPlayer(JoinOffer offer) { - if (this.isFull()) { + int newPlayerCount = this.gameSpace.getPlayers().size() + offer.players().size(); + if (newPlayerCount > this.playerConfig.maxPlayers()) { return offer.reject(GameTexts.Join.gameFull()); } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java b/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java index 66856b98..e1ca59c4 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java @@ -101,39 +101,15 @@ public final class GamePlayerEvents { } }); - /** - * Called when a group of players try to join this game. This should be used to reject multiple players as a group, - * such as when a party tries to join but has too many players to fit into the game. - *

- * This is called before {@link GamePlayerEvents#OFFER} which handles specifically bringing a player into the game. - * - * @see GamePlayerEvents#OFFER - */ - public static final StimulusEvent SCREEN_JOINS = StimulusEvent.create(ScreenJoins.class, ctx -> (players, intent) -> { - try { - for (var listener : ctx.getListeners()) { - var result = listener.screenJoins(players, intent); - if (result.isError()) { - return result; - } - } - return GameResult.ok(); - } catch (Throwable throwable) { - ctx.handleException(throwable); - return GameResult.error(GameTexts.Join.unexpectedError()); - } - }); - /** * Called when a single {@link ServerPlayerEntity} tries to join this game. This event is responsible for bringing * the player into the {@link GameSpace} world in the correct location. *

* Games must respond to this event in order for a player to be able to join by returning either - * {@link JoinOffer#accept(ServerWorld, Vec3d)} or {@link JoinOffer#reject(Text)}. + * {@link JoinOffer#accept(ServerWorld)} or {@link JoinOffer#reject(Text)}. * * @see JoinOffer * @see JoinOfferResult - * @see GamePlayerEvents#SCREEN_JOINS * @see GamePlayerEvents#JOIN */ public static final StimulusEvent OFFER = StimulusEvent.create(Offer.class, ctx -> offer -> { @@ -175,10 +151,6 @@ public interface Remove { void onRemovePlayer(ServerPlayerEntity player); } - public interface ScreenJoins { - GameResult screenJoins(Collection players, JoinIntent intent); - } - public interface Offer { JoinOfferResult onOfferPlayer(JoinOffer offer); } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java index 08e4f519..e0c5b5b6 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java @@ -196,24 +196,6 @@ public GameBehavior getBehavior() { return this.state; } - GameResult screenJoins(Collection players, JoinIntent intent) { - var result = this.attemptScreenJoins(players.stream().map(PlayerEntity::getGameProfile).toList(), intent); - - if (result.isError()) { - this.players.attemptGarbageCollection(); - } - - return result; - } - - private GameResult attemptScreenJoins(Collection players, JoinIntent intent) { - if (this.closed) { - return GameResult.error(GameTexts.Join.gameClosed()); - } - - return this.state.invoker(GamePlayerEvents.SCREEN_JOINS).screenJoins(players, intent); - } - JoinOfferResult offerPlayer(LocalJoinOffer offer) { if (this.closed) { return offer.reject(GameTexts.Join.gameClosed()); diff --git a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java index fd7540ad..65ebb64d 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java @@ -25,8 +25,18 @@ public final class ManagedGameSpacePlayers implements GameSpacePlayers { } @Override - public GameResult screenJoins(Collection players, JoinIntent intent) { - return this.space.screenJoins(players, intent); + public GameResult simulateOffer(Collection players, JoinIntent intent) { + if (players.stream().anyMatch(this.set::contains)) { + return GameResult.error(GameTexts.Join.alreadyJoined()); + } + + var offer = new LocalJoinOffer(players, intent); + + return switch (this.space.offerPlayer(offer)) { + case JoinOfferResult.Accept accept -> GameResult.ok(); + case JoinOfferResult.Reject reject -> GameResult.error(reject.reason()); + default -> GameResult.error(GameTexts.Join.genericError()); + }; } @Override diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java b/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java index fbf89e5c..d2c3f939 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java @@ -16,7 +16,7 @@ /** * Utility class for joining players to a {@link GameSpace}. This handles all logic such as collecting all party - * members, screening, and offering players to the {@link GameSpace}. + * members, and offering players to the {@link GameSpace}. */ public final class GamePlayerJoiner { public static Results tryJoin(ServerPlayerEntity player, GameSpace gameSpace, JoinIntent intent) { @@ -40,12 +40,6 @@ private static Set collectPlayersForJoin(ServerPlayerEntity private static Results tryJoinAll(Collection players, GameSpace gameSpace, JoinIntent intent) { var results = new Results(); - var screenResult = gameSpace.getPlayers().screenJoins(players, intent); - if (screenResult.isError()) { - results.globalError = screenResult.error(); - return results; - } - var result = gameSpace.getPlayers().offer(players, intent); if (result.isError()) { for (var player : players) { diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinIntent.java b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinIntent.java index f2bfe3f5..7cdc94ab 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinIntent.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinIntent.java @@ -6,8 +6,7 @@ /** * Represents the "intention" of a player or group of players joining a {@link GameSpace}. * It is up to the game implementation to respect this intent in the way that is appropriate for their game. This may be - * accomplished by handling the {@link GamePlayerEvents#SCREEN_JOINS 'Screen Joins'} and - * {@link GamePlayerEvents#OFFER 'Join Offer'} events. + * accomplished by handling the {@link GamePlayerEvents#OFFER 'Join Offer'} events. */ public enum JoinIntent { /** From fad28db7757cde3915bd5549cb9c587a5ec5269a Mon Sep 17 00:00:00 2001 From: Pufferfish Date: Sat, 20 Jul 2024 13:15:50 +0200 Subject: [PATCH 5/7] Replace GamePlayerJoiner.Results with GameResult --- .../nucleoid/plasmid/command/GameCommand.java | 6 ++- .../plasmid/command/ui/GameJoinUi.java | 6 ++- .../plasmid/game/player/GamePlayerJoiner.java | 47 +++---------------- .../game/ConcurrentGamePortalBackend.java | 16 ++++--- .../portal/game/NewGamePortalBackend.java | 12 +++-- .../portal/game/SingleGamePortalBackend.java | 12 +++-- 6 files changed, 40 insertions(+), 59 deletions(-) diff --git a/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java b/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java index da551289..db15c11f 100644 --- a/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java +++ b/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java @@ -294,8 +294,10 @@ private static void joinAllPlayersToGame(ServerCommandSource source, GameSpace g } private static void tryJoinGame(ServerPlayerEntity player, GameSpace gameSpace) { - var results = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); - results.sendErrorsTo(player); + var result = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); + if (result.isError()) { + player.sendMessage(result.errorCopy().formatted(Formatting.RED)); + } } private static GameSpace getJoinableGameSpace() throws CommandSyntaxException { diff --git a/src/main/java/xyz/nucleoid/plasmid/command/ui/GameJoinUi.java b/src/main/java/xyz/nucleoid/plasmid/command/ui/GameJoinUi.java index 000bdb17..65939d37 100644 --- a/src/main/java/xyz/nucleoid/plasmid/command/ui/GameJoinUi.java +++ b/src/main/java/xyz/nucleoid/plasmid/command/ui/GameJoinUi.java @@ -39,8 +39,10 @@ public GameJoinUi(ServerPlayerEntity player) { private static void tryJoinGame(ServerPlayerEntity player, GameSpace gameSpace) { player.server.execute(() -> { - var results = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); - results.sendErrorsTo(player); + var result = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); + if (result.isError()) { + player.sendMessage(result.errorCopy().formatted(Formatting.RED)); + } }); } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java b/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java index d2c3f939..627d25a2 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java @@ -1,17 +1,15 @@ package xyz.nucleoid.plasmid.game.player; -import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import xyz.nucleoid.plasmid.event.GameEvents; import xyz.nucleoid.plasmid.game.GameOpenException; +import xyz.nucleoid.plasmid.game.GameResult; import xyz.nucleoid.plasmid.game.GameSpace; import xyz.nucleoid.plasmid.game.GameTexts; import java.util.Collection; -import java.util.Map; import java.util.Set; /** @@ -19,7 +17,7 @@ * members, and offering players to the {@link GameSpace}. */ public final class GamePlayerJoiner { - public static Results tryJoin(ServerPlayerEntity player, GameSpace gameSpace, JoinIntent intent) { + public static GameResult tryJoin(ServerPlayerEntity player, GameSpace gameSpace, JoinIntent intent) { try { var players = collectPlayersForJoin(player, gameSpace); return tryJoinAll(players, gameSpace, intent); @@ -37,23 +35,12 @@ private static Set collectPlayersForJoin(ServerPlayerEntity return players; } - private static Results tryJoinAll(Collection players, GameSpace gameSpace, JoinIntent intent) { - var results = new Results(); - - var result = gameSpace.getPlayers().offer(players, intent); - if (result.isError()) { - for (var player : players) { - results.playerErrors.put(player, result.error()); - } - } - - return results; + private static GameResult tryJoinAll(Collection players, GameSpace gameSpace, JoinIntent intent) { + return gameSpace.getPlayers().offer(players, intent); } - public static Results handleJoinException(Throwable throwable) { - var results = new Results(); - results.globalError = getFeedbackForException(throwable); - return results; + public static GameResult handleJoinException(Throwable throwable) { + return GameResult.error(getFeedbackForException(throwable)); } private static Text getFeedbackForException(Throwable throwable) { @@ -64,26 +51,4 @@ private static Text getFeedbackForException(Throwable throwable) { return GameTexts.Join.unexpectedError(); } } - - public static final class Results { - public Text globalError; - public final Map playerErrors = new Reference2ObjectOpenHashMap<>(); - public boolean isSuccessful; - - public void sendErrorsTo(ServerPlayerEntity player) { - if (this.globalError != null) { - player.sendMessage(this.globalError.copy().formatted(Formatting.RED), false); - } else if (!this.playerErrors.isEmpty()) { - player.sendMessage( - GameTexts.Join.partyJoinError(this.playerErrors.size()).formatted(Formatting.RED), - false - ); - - for (var entry : this.playerErrors.entrySet()) { - Text error = entry.getValue().copy().formatted(Formatting.RED); - entry.getKey().sendMessage(error, false); - } - } - } - } } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/portal/game/ConcurrentGamePortalBackend.java b/src/main/java/xyz/nucleoid/plasmid/game/portal/game/ConcurrentGamePortalBackend.java index 5afc7b7f..f0d84194 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/portal/game/ConcurrentGamePortalBackend.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/portal/game/ConcurrentGamePortalBackend.java @@ -3,6 +3,8 @@ import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Formatting; +import xyz.nucleoid.plasmid.game.GameResult; import xyz.nucleoid.plasmid.game.config.GameConfig; import xyz.nucleoid.plasmid.game.manager.GameSpaceManager; import xyz.nucleoid.plasmid.game.manager.ManagedGameSpace; @@ -29,9 +31,9 @@ public RegistryEntry> game() { public void applyTo(ServerPlayerEntity player) { for (var gameSpace : GameSpaceManager.get().getOpenGameSpaces()) { if (gameSpace.getMetadata().sourceConfig().equals(this.game)) { - var results = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); + var result = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); - if (results.globalError == null && results.playerErrors.get(player) == null) { + if (result.isOk()) { return; } } @@ -41,14 +43,16 @@ public void applyTo(ServerPlayerEntity player) { .thenCompose(Function.identity()) .handleAsync((gameSpace, throwable) -> { this.gameFuture = null; - GamePlayerJoiner.Results results; + GameResult result; if (gameSpace != null) { - results = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); + result = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); } else { - results = GamePlayerJoiner.handleJoinException(throwable); + result = GamePlayerJoiner.handleJoinException(throwable); } - results.sendErrorsTo(player); + if (result.isError()) { + player.sendMessage(result.errorCopy().formatted(Formatting.RED), false); + } return null; }, player.server); diff --git a/src/main/java/xyz/nucleoid/plasmid/game/portal/game/NewGamePortalBackend.java b/src/main/java/xyz/nucleoid/plasmid/game/portal/game/NewGamePortalBackend.java index 2d633c86..2f4cc81f 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/portal/game/NewGamePortalBackend.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/portal/game/NewGamePortalBackend.java @@ -3,6 +3,8 @@ import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Formatting; +import xyz.nucleoid.plasmid.game.GameResult; import xyz.nucleoid.plasmid.game.config.GameConfig; import xyz.nucleoid.plasmid.game.manager.GameSpaceManager; import xyz.nucleoid.plasmid.game.manager.ManagedGameSpace; @@ -18,14 +20,16 @@ public void applyTo(ServerPlayerEntity player) { CompletableFuture.supplyAsync(() -> this.openGame(player.server)) .thenCompose(Function.identity()) .handleAsync((gameSpace, throwable) -> { - GamePlayerJoiner.Results results; + GameResult result; if (gameSpace != null) { - results = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); + result = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); } else { - results = GamePlayerJoiner.handleJoinException(throwable); + result = GamePlayerJoiner.handleJoinException(throwable); } - results.sendErrorsTo(player); + if (result.isError()) { + player.sendMessage(result.errorCopy().formatted(Formatting.RED), false); + } return null; }, player.server); diff --git a/src/main/java/xyz/nucleoid/plasmid/game/portal/game/SingleGamePortalBackend.java b/src/main/java/xyz/nucleoid/plasmid/game/portal/game/SingleGamePortalBackend.java index a16b1986..ce2cb575 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/portal/game/SingleGamePortalBackend.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/portal/game/SingleGamePortalBackend.java @@ -3,8 +3,10 @@ import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.Formatting; import xyz.nucleoid.plasmid.game.GameCloseReason; import xyz.nucleoid.plasmid.game.GameLifecycle; +import xyz.nucleoid.plasmid.game.GameResult; import xyz.nucleoid.plasmid.game.GameSpace; import xyz.nucleoid.plasmid.game.config.GameConfig; import xyz.nucleoid.plasmid.game.manager.GameSpaceManager; @@ -28,14 +30,16 @@ public void applyTo(ServerPlayerEntity player) { CompletableFuture.supplyAsync(() -> this.getOrOpen(player.server)) .thenCompose(Function.identity()) .handleAsync((gameSpace, throwable) -> { - GamePlayerJoiner.Results results; + GameResult result; if (gameSpace != null) { - results = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); + result = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); } else { - results = GamePlayerJoiner.handleJoinException(throwable); + result = GamePlayerJoiner.handleJoinException(throwable); } - results.sendErrorsTo(player); + if (result.isError()) { + player.sendMessage(result.errorCopy().formatted(Formatting.RED), false); + } return null; }, player.server); From fac06448595e3894c87080b58f0e05ee86b58867 Mon Sep 17 00:00:00 2001 From: Pufferfish Date: Sat, 20 Jul 2024 14:02:27 +0200 Subject: [PATCH 6/7] Return Set instead of Collection in JoinOffer --- .../xyz/nucleoid/plasmid/game/player/JoinOffer.java | 12 +++++++----- .../plasmid/game/player/LocalJoinOffer.java | 13 +++++++------ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOffer.java b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOffer.java index 67960574..6d4e0406 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOffer.java @@ -9,8 +9,10 @@ import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; import java.util.Collection; +import java.util.Set; import java.util.UUID; import java.util.function.Consumer; +import java.util.stream.Collectors; /** * Represents a request for of a player or group of players to join a {@link GameSpace}. @@ -25,26 +27,26 @@ public interface JoinOffer { /** * @return the set of {@link GameProfile} of the players that are requesting access to this {@link GameSpace} */ - Collection players(); + Set players(); /** * @return the {@link UUID profile UUID} of the players that are requesting access to this {@link GameSpace} */ - default Collection playerIds() { + default Set playerIds() { return this.players() .stream() .map(GameProfile::getId) - .toList(); + .collect(Collectors.toSet()); } /** * @return the usernames of the players that are requesting access to this {@link GameSpace} */ - default Collection playerNames() { + default Set playerNames() { return this.players() .stream() .map(GameProfile::getName) - .toList(); + .collect(Collectors.toSet()); } /** diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinOffer.java b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinOffer.java index 710863b9..5dbba46e 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinOffer.java @@ -10,30 +10,31 @@ import java.util.*; import java.util.function.Consumer; +import java.util.stream.Collectors; public record LocalJoinOffer(Collection serverPlayers, JoinIntent intent) implements JoinOffer { @Override - public Collection players() { + public Set players() { return this.serverPlayers .stream() .map(PlayerEntity::getGameProfile) - .toList(); + .collect(Collectors.toSet()); } @Override - public Collection playerIds() { + public Set playerIds() { return this.serverPlayers .stream() .map(player -> player.getGameProfile().getId()) - .toList(); + .collect(Collectors.toSet()); } @Override - public Collection playerNames() { + public Set playerNames() { return this.serverPlayers .stream() .map(player -> player.getGameProfile().getName()) - .toList(); + .collect(Collectors.toSet()); } @Override From 3946bd99dc6bb0cb26086c44a2336419f08fbbb4 Mon Sep 17 00:00:00 2001 From: Pufferfish Date: Mon, 22 Jul 2024 11:43:35 +0200 Subject: [PATCH 7/7] Add join accept event and modify offer event --- .../plasmid/game/event/GamePlayerEvents.java | 50 +++++-- .../game/manager/ManagedGameSpace.java | 15 ++- .../game/manager/ManagedGameSpacePlayers.java | 27 ++-- .../plasmid/game/player/JoinAcceptor.java | 127 ++++++++++++++++++ .../game/player/JoinAcceptorResult.java | 22 +++ .../plasmid/game/player/JoinOffer.java | 40 +----- .../plasmid/game/player/JoinOfferResult.java | 11 +- .../game/player/LocalJoinAcceptor.java | 106 +++++++++++++++ .../plasmid/game/player/LocalJoinOffer.java | 44 ------ .../xyz/nucleoid/plasmid/util/PlayerPos.java | 11 ++ .../xyz/nucleoid/plasmid/test/JankGame.java | 11 +- .../xyz/nucleoid/plasmid/test/TestGame.java | 6 +- .../test/TestGameWithResourcePack.java | 11 +- 13 files changed, 350 insertions(+), 131 deletions(-) create mode 100644 src/main/java/xyz/nucleoid/plasmid/game/player/JoinAcceptor.java create mode 100644 src/main/java/xyz/nucleoid/plasmid/game/player/JoinAcceptorResult.java create mode 100644 src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinAcceptor.java create mode 100644 src/main/java/xyz/nucleoid/plasmid/util/PlayerPos.java diff --git a/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java b/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java index e1ca59c4..43f71623 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java @@ -1,21 +1,16 @@ package xyz.nucleoid.plasmid.game.event; -import com.mojang.authlib.GameProfile; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; -import net.minecraft.util.math.Vec3d; import xyz.nucleoid.plasmid.game.GameActivity; -import xyz.nucleoid.plasmid.game.GameResult; import xyz.nucleoid.plasmid.game.GameSpace; import xyz.nucleoid.plasmid.game.GameTexts; -import xyz.nucleoid.plasmid.game.player.JoinIntent; +import xyz.nucleoid.plasmid.game.player.JoinAcceptor; +import xyz.nucleoid.plasmid.game.player.JoinAcceptorResult; import xyz.nucleoid.plasmid.game.player.JoinOffer; import xyz.nucleoid.plasmid.game.player.JoinOfferResult; import xyz.nucleoid.stimuli.event.StimulusEvent; -import java.util.Collection; - /** * Events relating to players being added and removed from a {@link GameSpace} or {@link GameActivity}. */ @@ -102,20 +97,19 @@ public final class GamePlayerEvents { }); /** - * Called when a single {@link ServerPlayerEntity} tries to join this game. This event is responsible for bringing - * the player into the {@link GameSpace} world in the correct location. + * Called when a group of {@link ServerPlayerEntity} tries to join this game. *

- * Games must respond to this event in order for a player to be able to join by returning either - * {@link JoinOffer#accept(ServerWorld)} or {@link JoinOffer#reject(Text)}. + * Games must respond to this event in order for players to be able to join by returning either + * {@link JoinOffer#accept()} or {@link JoinOffer#reject(Text)}. * * @see JoinOffer * @see JoinOfferResult - * @see GamePlayerEvents#JOIN + * @see GamePlayerEvents#ACCEPT */ public static final StimulusEvent OFFER = StimulusEvent.create(Offer.class, ctx -> offer -> { try { for (var listener : ctx.getListeners()) { - var result = listener.onOfferPlayer(offer); + var result = listener.onOfferPlayers(offer); if (!(result instanceof JoinOfferResult.Pass)) { return result; } @@ -127,6 +121,30 @@ public final class GamePlayerEvents { } }); + /** + * Called when a group of {@link ServerPlayerEntity} is accepted to join this game. This event is responsible for bringing + * the players into the {@link GameSpace} world in the correct location. + *

+ * Games must respond to this event in order for players to be able to join. + * + * @see JoinAcceptor + * @see JoinAcceptorResult + * @see GamePlayerEvents#JOIN + */ + public static final StimulusEvent ACCEPT = StimulusEvent.create(Accept.class, ctx -> accept -> { + try { + for (var listener : ctx.getListeners()) { + var result = listener.onAcceptPlayers(accept); + if (!(result instanceof JoinAcceptorResult.Pass)) { + return result; + } + } + } catch (Throwable throwable) { + ctx.handleException(throwable); + } + return accept.pass(); + }); + /** * Called when display name of {@link ServerPlayerEntity} is created. * Can be used to manipulate it in game. @@ -152,7 +170,11 @@ public interface Remove { } public interface Offer { - JoinOfferResult onOfferPlayer(JoinOffer offer); + JoinOfferResult onOfferPlayers(JoinOffer offer); + } + + public interface Accept { + JoinAcceptorResult onAcceptPlayers(JoinAcceptor acceptor); } public interface Name { diff --git a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java index e0c5b5b6..4ea9ad9b 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java @@ -1,10 +1,8 @@ package xyz.nucleoid.plasmid.game.manager; import com.google.common.collect.Lists; -import com.mojang.authlib.GameProfile; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.registry.RegistryKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; @@ -19,11 +17,11 @@ import xyz.nucleoid.plasmid.game.config.GameConfig; import xyz.nucleoid.plasmid.game.event.GameActivityEvents; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; -import xyz.nucleoid.plasmid.game.player.JoinIntent; +import xyz.nucleoid.plasmid.game.player.JoinAcceptorResult; +import xyz.nucleoid.plasmid.game.player.LocalJoinAcceptor; import xyz.nucleoid.plasmid.game.player.LocalJoinOffer; import xyz.nucleoid.plasmid.game.player.JoinOfferResult; -import java.util.Collection; import java.util.Map; import java.util.function.Consumer; @@ -196,7 +194,7 @@ public GameBehavior getBehavior() { return this.state; } - JoinOfferResult offerPlayer(LocalJoinOffer offer) { + JoinOfferResult offerPlayers(LocalJoinOffer offer) { if (this.closed) { return offer.reject(GameTexts.Join.gameClosed()); } else if (offer.serverPlayers().stream().anyMatch(this.manager::inGame)) { @@ -205,9 +203,14 @@ JoinOfferResult offerPlayer(LocalJoinOffer offer) { return offer.reject(GameTexts.Join.notAllowed()); } - return this.state.invoker(GamePlayerEvents.OFFER).onOfferPlayer(offer); + return this.state.invoker(GamePlayerEvents.OFFER).onOfferPlayers(offer); } + JoinAcceptorResult acceptPlayers(LocalJoinAcceptor acceptor) { + return this.state.invoker(GamePlayerEvents.ACCEPT).onAcceptPlayers(acceptor); + } + + void onAddPlayer(ServerPlayerEntity player) { this.state.propagatingInvoker(GamePlayerEvents.JOIN).onAddPlayer(player); this.state.propagatingInvoker(GamePlayerEvents.ADD).onAddPlayer(player); diff --git a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java index 65ebb64d..bf7ab28c 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java @@ -32,7 +32,7 @@ public GameResult simulateOffer(Collection players, JoinInte var offer = new LocalJoinOffer(players, intent); - return switch (this.space.offerPlayer(offer)) { + return switch (this.space.offerPlayers(offer)) { case JoinOfferResult.Accept accept -> GameResult.ok(); case JoinOfferResult.Reject reject -> GameResult.error(reject.reason()); default -> GameResult.error(GameTexts.Join.genericError()); @@ -57,29 +57,34 @@ private GameResult attemptOffer(Collection players, JoinInte var offer = new LocalJoinOffer(players, intent); - switch (this.space.offerPlayer(offer)) { - case LocalJoinOffer.Accept accept -> { + return switch (this.space.offerPlayers(offer)) { + case JoinOfferResult.Accept accept -> this.accept(players, intent); + case JoinOfferResult.Reject reject -> GameResult.error(reject.reason()); + default -> GameResult.error(GameTexts.Join.genericError()); + }; + } + + private GameResult accept(Collection players, JoinIntent intent) { + var acceptor = new LocalJoinAcceptor(players, intent); + + switch (this.space.acceptPlayers(acceptor)) { + case LocalJoinAcceptor.Teleport teleport -> { try { var joiningSet = new MutablePlayerSet(this.space.getServer()); for (var player : players) { - this.teleporter.teleportIn(player, accept::applyJoin); + this.teleporter.teleportIn(player, teleport::applyTeleport); this.set.add(player); this.space.onAddPlayer(player); joiningSet.add(player); } - accept.joinAll(joiningSet); + teleport.runCallbacks(joiningSet); return GameResult.ok(); } catch (Throwable throwable) { return GameResult.error(GameTexts.Join.unexpectedError()); } } - case JoinOfferResult.Reject reject -> { - return GameResult.error(reject.reason()); - } - default -> { - return GameResult.error(GameTexts.Join.genericError()); - } + default -> throw new IllegalStateException("Accept event must be handled"); } } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinAcceptor.java b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinAcceptor.java new file mode 100644 index 00000000..1c5045db --- /dev/null +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinAcceptor.java @@ -0,0 +1,127 @@ +package xyz.nucleoid.plasmid.game.player; + +import com.mojang.authlib.GameProfile; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.Vec3d; +import xyz.nucleoid.plasmid.game.GameSpace; +import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; +import xyz.nucleoid.plasmid.util.PlayerPos; + +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Represents an agent which is responsible for bringing a player or group of players + * into the {@link GameSpace} world in the correct location. + *

+ * This object should be used in order to construct a {@link JoinAcceptorResult} object to return from a listener to the + * {@link GamePlayerEvents#ACCEPT} event. + * + * @see GameSpace + * @see GamePlayerEvents#ACCEPT + */ +public interface JoinAcceptor { + /** + * @return the set of {@link GameProfile} of the players that are joining to this {@link GameSpace} + */ + Set players(); + + /** + * @return the {@link UUID profile UUID} of the players that are joining to this {@link GameSpace} + */ + default Set playerIds() { + return this.players() + .stream() + .map(GameProfile::getId) + .collect(Collectors.toSet()); + } + + /** + * @return the usernames of the players that are joining to this {@link GameSpace} + */ + default Set playerNames() { + return this.players() + .stream() + .map(GameProfile::getName) + .collect(Collectors.toSet()); + } + + /** + * @return the {@link JoinIntent 'intent'} of the players, such as whether they want to participate or spectate + * @see JoinIntent + */ + JoinIntent intent(); + + /** + * Returns a result that completes this join by teleporting the players. + *

+ * The result of this function must be returned within a + * {@link GamePlayerEvents#ACCEPT} listener. + * + * @param positions the map of positions where the players should be teleported to + * @return a "teleport" result + * @throws IllegalArgumentException when positions are not specified for all joining players + * @see JoinAcceptorResult.Teleport#thenRun(Consumer) + * @see JoinAcceptorResult.Teleport#thenRunForEach(Consumer) + */ + JoinAcceptorResult.Teleport teleport(Map positions); + + /** + * Returns a result that completes this join by teleporting the players. + *

+ * The result of this function must be returned within a + * {@link GamePlayerEvents#ACCEPT} listener. + * + * @param positions a function that for given player returns position where the player should be teleported to + * @return a "teleport" result + * @throws IllegalArgumentException when positions are not specified for all joining players + * @see JoinAcceptorResult.Teleport#thenRun(Consumer) + * @see JoinAcceptorResult.Teleport#thenRunForEach(Consumer) + */ + JoinAcceptorResult.Teleport teleport(Function positions); + + /** + * Returns a result that completes this join by teleporting the players. + *

+ * The result of this function must be returned within a + * {@link GamePlayerEvents#ACCEPT} listener. + * + * @param world the world that all the players should be teleported to + * @param position the position that all the players should be teleported to + * @param yaw the 'yaw' angle that all the players should be teleported to + * @param pitch the 'pitch' angle that all the players should be teleported to + * @return a "teleport" result + * @see JoinAcceptorResult.Teleport#thenRun(Consumer) + * @see JoinAcceptorResult.Teleport#thenRunForEach(Consumer) + */ + JoinAcceptorResult.Teleport teleport(ServerWorld world, Vec3d position, float yaw, float pitch); + + /** + * Returns a result that completes this join by teleporting the players. + *

+ * The result of this function must be returned within a + * {@link GamePlayerEvents#ACCEPT} listener. + * + * @param world the world that all the players should be teleported to + * @param position the position that all the players should be teleported to + * @return a "teleport" result + * @see JoinAcceptorResult.Teleport#thenRun(Consumer) + * @see JoinAcceptorResult.Teleport#thenRunForEach(Consumer) + */ + default JoinAcceptorResult.Teleport teleport(ServerWorld world, Vec3d position) { + return this.teleport(world, position, 0, 0); + } + + /** + * Returns a result that does nothing, passing on any handling to any other listener. + * + * @return a "passing" result + */ + default JoinAcceptorResult pass() { + return JoinAcceptorResult.PASS; + } +} diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinAcceptorResult.java b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinAcceptorResult.java new file mode 100644 index 00000000..6ad082d0 --- /dev/null +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinAcceptorResult.java @@ -0,0 +1,22 @@ +package xyz.nucleoid.plasmid.game.player; + +import net.minecraft.server.network.ServerPlayerEntity; + +import java.util.function.Consumer; + +public sealed interface JoinAcceptorResult permits JoinAcceptorResult.Pass, JoinAcceptorResult.Teleport { + Pass PASS = new Pass(); + + final class Pass implements JoinAcceptorResult { + private Pass() { + } + } + + non-sealed interface Teleport extends JoinAcceptorResult { + Teleport thenRun(Consumer consumer); + + default Teleport thenRunForEach(Consumer consumer) { + return this.thenRun(players -> players.forEach(consumer)); + } + } +} diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOffer.java b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOffer.java index 6d4e0406..b49f6b83 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOffer.java @@ -1,17 +1,13 @@ package xyz.nucleoid.plasmid.game.player; import com.mojang.authlib.GameProfile; -import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; -import net.minecraft.util.math.Vec3d; import xyz.nucleoid.plasmid.game.GameSpace; import xyz.nucleoid.plasmid.game.GameTexts; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; -import java.util.Collection; import java.util.Set; import java.util.UUID; -import java.util.function.Consumer; import java.util.stream.Collectors; /** @@ -61,42 +57,10 @@ default Set playerNames() { * This function does not do anything on its own, but its result must be returned within a * {@link GamePlayerEvents#OFFER} listener. * - * @param world the world that the players should be teleported to when accepted - * @param position the position that the players should be teleported to when accepted - * @param yaw the 'yaw' angle that the players should be teleported to when accepted - * @param pitch the 'pitch' angle that the players should be teleported to when accepted * @return an "accept" offer result - * @see JoinOfferResult.Accept#thenRun(Consumer) */ - JoinOfferResult.Accept accept(ServerWorld world, Vec3d position, float yaw, float pitch); - - /** - * Returns an offer result that accepts this offer and allows the player into this {@link GameSpace}. - *

- * This function does not do anything on its own, but its result must be returned within a - * {@link GamePlayerEvents#OFFER} listener. - * - * @param world the world that the players should be teleported to when accepted - * @param position the position that the players should be teleported to when accepted - * @return an "accept" offer result - * @see JoinOfferResult.Accept#thenRun(Consumer) - */ - default JoinOfferResult.Accept accept(ServerWorld world, Vec3d position) { - return this.accept(world, position, 0.0f, 0.0f); - } - - /** - * Returns an offer result that accepts this offer and allows the players into this {@link GameSpace}. - *

- * This function does not do anything on its own, but its result must be returned within a - * {@link GamePlayerEvents#OFFER} listener. - * - * @param world the world that the players should be teleported to when accepted - * @return an "accept" offer result - * @see JoinOfferResult.Accept#thenRun(Consumer) - */ - default JoinOfferResult.Accept accept(ServerWorld world) { - return this.accept(world, Vec3d.ofBottomCenter(world.getSpawnPos())); + default JoinOfferResult.Accept accept() { + return JoinOfferResult.ACCEPT; } /** diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOfferResult.java b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOfferResult.java index ed9920b9..e3c75f18 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOfferResult.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinOfferResult.java @@ -1,23 +1,18 @@ package xyz.nucleoid.plasmid.game.player; -import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; -import java.util.function.Consumer; - public sealed interface JoinOfferResult permits JoinOfferResult.Pass, JoinOfferResult.Accept, JoinOfferResult.Reject { Pass PASS = new Pass(); + Accept ACCEPT = new Accept(); final class Pass implements JoinOfferResult { private Pass() { } } - non-sealed interface Accept extends JoinOfferResult { - JoinOfferResult.Accept thenRun(Consumer consumer); - - default JoinOfferResult.Accept thenRunForEach(Consumer consumer) { - return this.thenRun(players -> players.forEach(consumer)); + final class Accept implements JoinOfferResult { + private Accept() { } } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinAcceptor.java b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinAcceptor.java new file mode 100644 index 00000000..ca56aa1e --- /dev/null +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinAcceptor.java @@ -0,0 +1,106 @@ +package xyz.nucleoid.plasmid.game.player; + +import com.mojang.authlib.GameProfile; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.GameMode; +import xyz.nucleoid.plasmid.util.PlayerPos; + +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; + +public record LocalJoinAcceptor(Collection serverPlayers, JoinIntent intent) implements JoinAcceptor { + @Override + public Set players() { + return this.serverPlayers + .stream() + .map(PlayerEntity::getGameProfile) + .collect(Collectors.toSet()); + } + + @Override + public Set playerIds() { + return this.serverPlayers + .stream() + .map(player -> player.getGameProfile().getId()) + .collect(Collectors.toSet()); + } + + @Override + public Set playerNames() { + return this.serverPlayers + .stream() + .map(player -> player.getGameProfile().getName()) + .collect(Collectors.toSet()); + } + + @Override + public JoinAcceptorResult.Teleport teleport(Map positions) { + if (this.serverPlayers.stream().anyMatch(player -> !positions.containsKey(player.getUuid()))) { + throw new IllegalArgumentException("Positions for all players must be specified"); + } + return new LocalJoinAcceptor.Teleport(positions); + } + + @Override + public JoinAcceptorResult.Teleport teleport(Function positions) { + return new LocalJoinAcceptor.Teleport( + this.serverPlayers.stream().collect(Collectors.toMap( + ServerPlayerEntity::getUuid, + player -> positions.apply(player.getGameProfile()) + )) + ); + } + + @Override + public JoinAcceptorResult.Teleport teleport(ServerWorld world, Vec3d position, float yaw, float pitch) { + var playerPos = new PlayerPos(world, position, yaw, pitch); + return new LocalJoinAcceptor.Teleport( + this.serverPlayers.stream().collect(Collectors.toMap( + ServerPlayerEntity::getUuid, + player -> playerPos + )) + ); + } + + public static class Teleport implements JoinAcceptorResult.Teleport { + private final Map positions; + + private final List> thenRun = new ArrayList<>(); + + Teleport(Map positions) { + this.positions = positions; + } + + @Override + public JoinAcceptorResult.Teleport thenRun(Consumer consumer) { + this.thenRun.add(consumer); + return this; + } + + public void runCallbacks(PlayerSet players) { + for (var consumer : this.thenRun) { + consumer.accept(players); + } + } + + public ServerWorld applyTeleport(ServerPlayerEntity player) { + var pos = this.positions.get(player.getUuid()); + + player.changeGameMode(GameMode.SURVIVAL); + player.refreshPositionAndAngles( + pos.x(), + pos.y(), + pos.z(), + pos.yaw(), + pos.pitch() + ); + + return pos.world(); + } + } +} diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinOffer.java b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinOffer.java index 5dbba46e..f23ac5a7 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalJoinOffer.java @@ -3,13 +3,9 @@ import com.mojang.authlib.GameProfile; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; import net.minecraft.text.Text; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.GameMode; import java.util.*; -import java.util.function.Consumer; import java.util.stream.Collectors; public record LocalJoinOffer(Collection serverPlayers, JoinIntent intent) implements JoinOffer { @@ -37,48 +33,8 @@ public Set playerNames() { .collect(Collectors.toSet()); } - @Override - public JoinOfferResult.Accept accept(ServerWorld world, Vec3d position, float yaw, float pitch) { - return new Accept(world, position, yaw, pitch); - } - @Override public JoinOfferResult.Reject reject(Text reason) { return () -> reason; } - - public static class Accept implements JoinOfferResult.Accept { - private final ServerWorld world; - private final Vec3d position; - private final float yaw; - private final float pitch; - - private final List> thenRun = new ArrayList<>(); - - Accept(ServerWorld world, Vec3d position, float yaw, float pitch) { - this.world = world; - this.position = position; - this.yaw = yaw; - this.pitch = pitch; - } - - @Override - public Accept thenRun(Consumer consumer) { - this.thenRun.add(consumer); - return this; - } - - public void joinAll(PlayerSet players) { - for (var consumer : this.thenRun) { - consumer.accept(players); - } - } - - public ServerWorld applyJoin(ServerPlayerEntity player) { - player.changeGameMode(GameMode.SURVIVAL); - player.refreshPositionAndAngles(this.position.x, this.position.y, this.position.z, this.yaw, this.pitch); - - return this.world; - } - } } diff --git a/src/main/java/xyz/nucleoid/plasmid/util/PlayerPos.java b/src/main/java/xyz/nucleoid/plasmid/util/PlayerPos.java new file mode 100644 index 00000000..c7f2ad92 --- /dev/null +++ b/src/main/java/xyz/nucleoid/plasmid/util/PlayerPos.java @@ -0,0 +1,11 @@ +package xyz.nucleoid.plasmid.util; + +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.Vec3d; + +public record PlayerPos(ServerWorld world, double x, double y, double z, float yaw, float pitch) { + + public PlayerPos(ServerWorld world, Vec3d position, float yaw, float pitch) { + this(world, position.x, position.y, position.z, yaw, pitch); + } +} diff --git a/src/testmod/java/xyz/nucleoid/plasmid/test/JankGame.java b/src/testmod/java/xyz/nucleoid/plasmid/test/JankGame.java index db989009..54b12d38 100644 --- a/src/testmod/java/xyz/nucleoid/plasmid/test/JankGame.java +++ b/src/testmod/java/xyz/nucleoid/plasmid/test/JankGame.java @@ -27,6 +27,7 @@ import xyz.nucleoid.plasmid.game.common.config.PlayerConfig; import xyz.nucleoid.plasmid.game.event.GameActivityEvents; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; +import xyz.nucleoid.plasmid.game.player.JoinOffer; import xyz.nucleoid.plasmid.game.rule.GameRuleType; import xyz.nucleoid.plasmid.game.world.generator.TemplateChunkGenerator; import xyz.nucleoid.stimuli.event.player.PlayerC2SPacketEvent; @@ -58,8 +59,9 @@ public static GameOpenProcedure open(GameOpenContext context) { .setGameRule(GameRules.KEEP_INVENTORY, true); return context.openWithWorld(worldConfig, (activity, world) -> { - activity.listen(GamePlayerEvents.OFFER, offer -> - offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) + activity.listen(GamePlayerEvents.OFFER, JoinOffer::accept); + activity.listen(GamePlayerEvents.ACCEPT, acceptor -> + acceptor.teleport(world, new Vec3d(0.0, 65.0, 0.0)) .thenRunForEach(joiningPlayer -> { joiningPlayer.changeGameMode(GameMode.ADVENTURE); }) @@ -172,8 +174,9 @@ private static GameResult startGame(GameSpace gameSpace) { player.networkHandler.sendPacket(new PlayerPositionLookS2CPacket(0, 0, 0, 0, 0f, Set.of(), 0)); }); - activity.listen(GamePlayerEvents.OFFER, offer -> - offer.accept(gameSpace.getWorlds().iterator().next(), new Vec3d(0.0, 65.0, 0.0)) + activity.listen(GamePlayerEvents.OFFER, JoinOffer::accept); + activity.listen(GamePlayerEvents.ACCEPT, acceptor -> + acceptor.teleport(gameSpace.getWorlds().iterator().next(), new Vec3d(0.0, 65.0, 0.0)) .thenRunForEach(joiningPlayer -> { joiningPlayer.changeGameMode(GameMode.ADVENTURE); }) diff --git a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java index 4463a4f8..8bfa6143 100644 --- a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java +++ b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java @@ -27,6 +27,7 @@ import xyz.nucleoid.plasmid.game.common.team.*; import xyz.nucleoid.plasmid.game.event.GameActivityEvents; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; +import xyz.nucleoid.plasmid.game.player.JoinOffer; import xyz.nucleoid.plasmid.game.rule.GameRuleType; import xyz.nucleoid.plasmid.game.stats.GameStatisticBundle; import xyz.nucleoid.plasmid.game.stats.StatisticKey; @@ -58,8 +59,9 @@ public static GameOpenProcedure open(GameOpenContext context) { .setGameRule(GameRules.KEEP_INVENTORY, true); return context.openWithWorld(worldConfig, (activity, world) -> { - activity.listen(GamePlayerEvents.OFFER, offer -> - offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) + activity.listen(GamePlayerEvents.OFFER, JoinOffer::accept); + activity.listen(GamePlayerEvents.ACCEPT, acceptor -> + acceptor.teleport(world, new Vec3d(0.0, 65.0, 0.0)) .thenRunForEach(joiningPlayer -> { joiningPlayer.changeGameMode(GameMode.ADVENTURE); }) diff --git a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGameWithResourcePack.java b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGameWithResourcePack.java index 59726fae..b4f6fb0d 100644 --- a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGameWithResourcePack.java +++ b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGameWithResourcePack.java @@ -26,6 +26,7 @@ import xyz.nucleoid.plasmid.game.common.team.TeamManager; import xyz.nucleoid.plasmid.game.event.GameActivityEvents; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; +import xyz.nucleoid.plasmid.game.player.JoinOffer; import xyz.nucleoid.plasmid.game.rule.GameRuleType; import xyz.nucleoid.plasmid.game.stats.GameStatisticBundle; import xyz.nucleoid.plasmid.game.stats.StatisticKey; @@ -51,8 +52,9 @@ public static GameOpenProcedure open(GameOpenContext context) { .setGameRule(GameRules.KEEP_INVENTORY, true); return context.openWithWorld(worldConfig, (activity, world) -> { - activity.listen(GamePlayerEvents.OFFER, offer -> - offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) + activity.listen(GamePlayerEvents.OFFER, JoinOffer::accept); + activity.listen(GamePlayerEvents.ACCEPT, acceptor -> + acceptor.teleport(world, new Vec3d(0.0, 65.0, 0.0)) .thenRunForEach(joiningPlayer -> { joiningPlayer.changeGameMode(GameMode.ADVENTURE); }) @@ -129,8 +131,9 @@ private static GameResult startGame(GameSpace gameSpace, int iter) { return ActionResult.FAIL; }); - activity.listen(GamePlayerEvents.OFFER, offer -> - offer.accept(gameSpace.getWorlds().iterator().next(), new Vec3d(0.0, 65.0, 0.0)) + activity.listen(GamePlayerEvents.OFFER, JoinOffer::accept); + activity.listen(GamePlayerEvents.ACCEPT, acceptor -> + acceptor.teleport(gameSpace.getWorlds().iterator().next(), new Vec3d(0.0, 65.0, 0.0)) .thenRunForEach(joiningPlayer -> { joiningPlayer.changeGameMode(GameMode.ADVENTURE); })