From 8db084036b7fc97286b9e067377d9bf34aa8af29 Mon Sep 17 00:00:00 2001 From: Gegy Date: Sun, 23 Jun 2024 10:31:59 +0200 Subject: [PATCH 1/6] Extract api versions to gradle.properties --- build.gradle | 38 +++++++++++++++++++------------------- gradle.properties | 17 ++++++++++++++++- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/build.gradle b/build.gradle index e33b3eb3..380f6119 100644 --- a/build.gradle +++ b/build.gradle @@ -87,25 +87,25 @@ dependencies { modApi "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - modApi include('xyz.nucleoid:server-translations-api:2.3.0+1.20.5-rc2') - modApi include('xyz.nucleoid:packet-tweaker:0.5.1+1.20.6') - modApi include('xyz.nucleoid:fantasy:0.6.2+1.20.6') - modApi include('xyz.nucleoid:more-codecs:0.3.3+1.20.2') - modApi include('xyz.nucleoid:stimuli:0.4.11+1.20.6') - modApi include('xyz.nucleoid:map-templates:0.1.9+1.20.4') - modApi include('xyz.nucleoid:substrate:0.2.2+1.20.1') - modApi 'eu.pb4:polymer-core:0.8.2+1.20.6' - modApi 'eu.pb4:polymer-resource-pack:0.8.2+1.20.6' - modApi 'eu.pb4:polymer-blocks:0.8.2+1.20.6' - modApi 'eu.pb4:polymer-virtual-entity:0.8.2+1.20.6' - modApi include('eu.pb4:sgui:1.5.1+1.20.5') - modApi include('eu.pb4:sidebar-api:0.4.0+1.20.5') - modApi include("eu.pb4:placeholder-api:2.4.0-pre.1+1.20.5") - modApi include("eu.pb4:map-canvas-api:0.3.0+1.20.6") - modApi include("eu.pb4:player-data-api:0.5.0+1.20.5") - modApi include("eu.pb4:predicate-api:0.4.0+1.20.5") - - modImplementation include("me.lucko:fabric-permissions-api:0.2-SNAPSHOT") + modApi include("xyz.nucleoid:server-translations-api:${project.server_translations_version}") + modApi include("xyz.nucleoid:packet-tweaker:${project.packet_tweaker_version}") + modApi include("xyz.nucleoid:fantasy:${project.fantasy_version}") + modApi include("xyz.nucleoid:more-codecs:${project.more_codecs_version}") + modApi include("xyz.nucleoid:stimuli:${project.stimuli_version}") + modApi include("xyz.nucleoid:map-templates:${project.map_templates_version}") + modApi include("xyz.nucleoid:substrate:${project.substrate_version}") + modApi "eu.pb4:polymer-core:${project.polymer_version}" + modApi "eu.pb4:polymer-resource-pack:${project.polymer_version}" + modApi "eu.pb4:polymer-blocks:${project.polymer_version}" + modApi "eu.pb4:polymer-virtual-entity:${project.polymer_version}" + modApi include("eu.pb4:sgui:${project.sgui_version}") + modApi include("eu.pb4:sidebar-api:${project.sidebar_api_version}") + modApi include("eu.pb4:placeholder-api:${project.placeholder_api_version}") + modApi include("eu.pb4:map-canvas-api:${project.map_canvas_api_version}") + modApi include("eu.pb4:player-data-api:${project.player_data_api_version}") + modApi include("eu.pb4:predicate-api:${project.predicate_api_version}") + + modImplementation include("me.lucko:fabric-permissions-api:${project.permission_api_version}") modCompileOnly('xyz.nucleoid:disguiselib-fabric:1.3.2') modCompileOnly('maven.modrinth:afkdisplay:1.1.0') diff --git a/gradle.properties b/gradle.properties index 59f55f52..fa5e867f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,8 +6,23 @@ minecraft_version=1.20.6 yarn_mappings=1.20.6+build.1 loader_version=0.15.10 -#Fabric api +# Dependencies fabric_version=0.99.0+1.20.6 +polymer_version=0.8.2+1.20.6 +server_translations_version=2.3.0+1.20.5-rc2 +packet_tweaker_version=0.5.1+1.20.6 +fantasy_version=0.6.2+1.20.6 +more_codecs_version=0.3.3+1.20.2 +stimuli_version=0.4.11+1.20.6 +map_templates_version=0.1.9+1.20.4 +substrate_version=0.2.2+1.20.1 +sgui_version=1.5.1+1.20.5 +sidebar_api_version=0.4.0+1.20.5 +placeholder_api_version=2.4.0-pre.1+1.20.5 +map_canvas_api_version=0.3.0+1.20.6 +player_data_api_version=0.5.0+1.20.5 +predicate_api_version=0.4.0+1.20.5 +permission_api_version=0.2-SNAPSHOT # Mod Properties mod_version=0.6 From dc8d18abac66e0c3ba8809a4312e20a392d05085 Mon Sep 17 00:00:00 2001 From: Gegy Date: Sun, 23 Jun 2024 10:42:24 +0200 Subject: [PATCH 2/6] Extract PlayerOffer implementation --- .../plasmid/game/event/GamePlayerEvents.java | 2 +- .../game/manager/ManagedGameSpacePlayers.java | 38 ++++----- .../plasmid/game/player/LocalPlayerOffer.java | 49 ++++++++++++ .../plasmid/game/player/PlayerOffer.java | 21 ++--- .../game/player/PlayerOfferResult.java | 77 ++----------------- 5 files changed, 82 insertions(+), 105 deletions(-) create mode 100644 src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.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 db12c502..3b9063cd 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java @@ -138,7 +138,7 @@ public final class GamePlayerEvents { try { for (var listener : ctx.getListeners()) { var result = listener.onOfferPlayer(offer); - if (result.isTerminal()) { + if (!(result instanceof PlayerOfferResult.Pass)) { return result; } } 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 bcd79d7f..7bc3ade9 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java @@ -6,8 +6,9 @@ import xyz.nucleoid.plasmid.game.GameResult; import xyz.nucleoid.plasmid.game.GameSpacePlayers; import xyz.nucleoid.plasmid.game.GameTexts; +import xyz.nucleoid.plasmid.game.player.LocalPlayerOffer; import xyz.nucleoid.plasmid.game.player.MutablePlayerSet; -import xyz.nucleoid.plasmid.game.player.PlayerOffer; +import xyz.nucleoid.plasmid.game.player.PlayerOfferResult; import xyz.nucleoid.plasmid.game.player.isolation.IsolatingPlayerTeleporter; import java.util.Collection; @@ -46,27 +47,26 @@ private GameResult attemptOffer(ServerPlayerEntity player) { return GameResult.error(GameTexts.Join.alreadyJoined()); } - var offer = new PlayerOffer(player); - var result = this.space.offerPlayer(offer); + var offer = new LocalPlayerOffer(player); - var reject = result.asReject(); - if (reject != null) { - return GameResult.error(reject.reason()); - } - - var accept = result.asAccept(); - if (accept != null) { - try { - this.teleporter.teleportIn(player, accept::applyJoin); - this.set.add(player); - this.space.onAddPlayer(player); + switch (this.space.offerPlayer(offer)) { + case LocalPlayerOffer.Accept accept -> { + try { + this.teleporter.teleportIn(player, accept::applyJoin); + this.set.add(player); + this.space.onAddPlayer(player); - return GameResult.ok(); - } catch (Throwable throwable) { - return GameResult.error(GameTexts.Join.unexpectedError()); + return GameResult.ok(); + } catch (Throwable throwable) { + return GameResult.error(GameTexts.Join.unexpectedError()); + } + } + case PlayerOfferResult.Reject reject -> { + return GameResult.error(reject.reason()); + } + default -> { + return GameResult.error(GameTexts.Join.genericError()); } - } else { - return GameResult.error(GameTexts.Join.genericError()); } } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java new file mode 100644 index 00000000..1d6dd7b2 --- /dev/null +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java @@ -0,0 +1,49 @@ +package xyz.nucleoid.plasmid.game.player; + +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; + +public record LocalPlayerOffer(ServerPlayerEntity player) implements PlayerOffer { + @Override + public PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position) { + return new Accept(world, position); + } + + @Override + public PlayerOfferResult.Reject reject(Text reason) { + return () -> reason; + } + + public static class Accept implements PlayerOfferResult.Accept { + private final ServerWorld world; + private final Vec3d position; + + private final List and = new ArrayList<>(); + + Accept(ServerWorld world, Vec3d position) { + this.world = world; + this.position = position; + } + + @Override + public Accept and(Runnable and) { + this.and.add(and); + return this; + } + + public ServerWorld applyJoin(ServerPlayerEntity player) { + player.changeGameMode(GameMode.SURVIVAL); + player.refreshPositionAndAngles(this.position.x, this.position.y, this.position.z, 0.0F, 0.0F); + + this.and.forEach(Runnable::run); + + 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 e0838bc0..465a10b9 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java @@ -17,14 +17,11 @@ * @see GameSpace * @see GamePlayerEvents#OFFER */ -public record PlayerOffer(ServerPlayerEntity player) { +public interface PlayerOffer { /** * @return the player that is requesting access to this {@link GameSpace}. */ - @Override - public ServerPlayerEntity player() { - return this.player; - } + ServerPlayerEntity player(); /** * Returns an offer result that accepts this player offer and allows the player into this {@link GameSpace}. @@ -37,9 +34,7 @@ public ServerPlayerEntity player() { * @return an "accept" offer result * @see PlayerOfferResult.Accept#and(Runnable) */ - public PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position) { - return new PlayerOfferResult.Accept(world, position); - } + PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position); /** * Returns an offer result that rejects this player offer and does not allow the player into this {@link GameSpace}. @@ -51,16 +46,14 @@ public PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position) { * @return a "reject" offer result * @see GameTexts.Join */ - public PlayerOfferResult.Reject reject(Text reason) { - return new PlayerOfferResult.Reject(reason); - } + PlayerOfferResult.Reject reject(Text reason); /** * Returns an offer result that does nothing with this player offer, passing on any handling to any other listener. * - * @return a "pass" offer result + * @return a "passing" offer result */ - public PlayerOfferResult pass() { - return PlayerOfferResult.Pass.INSTANCE; + default PlayerOfferResult pass() { + return PlayerOfferResult.PASS; } } 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 5679a843..5ce69108 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOfferResult.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOfferResult.java @@ -1,85 +1,20 @@ package xyz.nucleoid.plasmid.game.player; -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 org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; - -public interface PlayerOfferResult { - @Nullable - default Accept asAccept() { - return null; - } - - @Nullable - default Reject asReject() { - return null; - } - - boolean isTerminal(); +public sealed interface PlayerOfferResult permits PlayerOfferResult.Pass, PlayerOfferResult.Accept, PlayerOfferResult.Reject { + Pass PASS = new Pass(); final class Pass implements PlayerOfferResult { - static final Pass INSTANCE = new Pass(); - private Pass() { } - - @Override - public boolean isTerminal() { - return false; - } } - final class Accept implements PlayerOfferResult { - private final ServerWorld world; - private final Vec3d position; - - private final List and = new ArrayList<>(); - - Accept(ServerWorld world, Vec3d position) { - this.world = world; - this.position = position; - } - - public PlayerOfferResult.Accept and(Runnable and) { - this.and.add(and); - return this; - } - - public ServerWorld applyJoin(ServerPlayerEntity player) { - player.changeGameMode(GameMode.SURVIVAL); - player.refreshPositionAndAngles(this.position.x, this.position.y, this.position.z, 0.0F, 0.0F); - - this.and.forEach(Runnable::run); - - return this.world; - } - - @Override - public Accept asAccept() { - return this; - } - - @Override - public boolean isTerminal() { - return true; - } + non-sealed interface Accept extends PlayerOfferResult { + PlayerOfferResult.Accept and(Runnable and); } - record Reject(Text reason) implements PlayerOfferResult { - @Override - public Reject asReject() { - return this; - } - - @Override - public boolean isTerminal() { - return true; - } + non-sealed interface Reject extends PlayerOfferResult { + Text reason(); } } From d2172b60aea48eb21a93fd09f138034483cdf0b0 Mon Sep 17 00:00:00 2001 From: Gegy Date: Sun, 23 Jun 2024 10:46:03 +0200 Subject: [PATCH 3/6] Don't expose player entity in offer event until joined --- .../game/manager/ManagedGameSpace.java | 3 ++- .../plasmid/game/player/LocalPlayerOffer.java | 17 ++++++++++---- .../plasmid/game/player/PlayerOffer.java | 23 ++++++++++++++++--- .../game/player/PlayerOfferResult.java | 5 +++- .../xyz/nucleoid/plasmid/test/JankGame.java | 20 +++++++--------- .../xyz/nucleoid/plasmid/test/TestGame.java | 10 ++++---- .../test/TestGameWithResourcePack.java | 19 +++++++-------- 7 files changed, 59 insertions(+), 38 deletions(-) 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 894642a1..c340cf26 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java @@ -17,6 +17,7 @@ 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.LocalPlayerOffer; import xyz.nucleoid.plasmid.game.player.PlayerOffer; import xyz.nucleoid.plasmid.game.player.PlayerOfferResult; @@ -211,7 +212,7 @@ private GameResult attemptScreenJoins(Collection players) { return this.state.invoker(GamePlayerEvents.SCREEN_JOINS).screenJoins(players); } - PlayerOfferResult offerPlayer(PlayerOffer offer) { + PlayerOfferResult offerPlayer(LocalPlayerOffer offer) { if (this.closed) { return offer.reject(GameTexts.Join.gameClosed()); } else if (this.manager.inGame(offer.player())) { 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 1d6dd7b2..8ad58bcd 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java @@ -1,5 +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; @@ -8,8 +9,14 @@ import java.util.ArrayList; import java.util.List; +import java.util.function.Consumer; public record LocalPlayerOffer(ServerPlayerEntity player) implements PlayerOffer { + @Override + public GameProfile profile() { + return this.player.getGameProfile(); + } + @Override public PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position) { return new Accept(world, position); @@ -24,7 +31,7 @@ public static class Accept implements PlayerOfferResult.Accept { private final ServerWorld world; private final Vec3d position; - private final List and = new ArrayList<>(); + private final List> thenRun = new ArrayList<>(); Accept(ServerWorld world, Vec3d position) { this.world = world; @@ -32,8 +39,8 @@ public static class Accept implements PlayerOfferResult.Accept { } @Override - public Accept and(Runnable and) { - this.and.add(and); + public Accept thenRun(Consumer consumer) { + this.thenRun.add(consumer); return this; } @@ -41,7 +48,9 @@ public ServerWorld applyJoin(ServerPlayerEntity player) { player.changeGameMode(GameMode.SURVIVAL); player.refreshPositionAndAngles(this.position.x, this.position.y, this.position.z, 0.0F, 0.0F); - this.and.forEach(Runnable::run); + 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 465a10b9..685df714 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java @@ -1,5 +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; @@ -8,6 +9,8 @@ import xyz.nucleoid.plasmid.game.GameTexts; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; +import java.util.UUID; + /** * Represents a request for a {@link ServerPlayerEntity} to join a {@link GameSpace}. *

@@ -19,9 +22,23 @@ */ public interface PlayerOffer { /** - * @return the player that is requesting access to this {@link GameSpace}. + * @return the {@link GameProfile} of the player that is requesting access to this {@link GameSpace} */ - ServerPlayerEntity player(); + GameProfile profile(); + + /** + * @return the {@link UUID profile UUID} of the player that is requesting access to this {@link GameSpace} + */ + default UUID playerId() { + return this.profile().getId(); + } + + /** + * @return the username of the player that is requesting access to this {@link GameSpace} + */ + default String playerName() { + return this.profile().getName(); + } /** * Returns an offer result that accepts this player offer and allows the player into this {@link GameSpace}. @@ -32,7 +49,7 @@ public interface PlayerOffer { * @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 * @return an "accept" offer result - * @see PlayerOfferResult.Accept#and(Runnable) + * @see PlayerOfferResult.Accept#thenRun(java.util.function.Consumer) */ PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position); 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 5ce69108..ed123e85 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOfferResult.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOfferResult.java @@ -1,7 +1,10 @@ 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 PlayerOfferResult permits PlayerOfferResult.Pass, PlayerOfferResult.Accept, PlayerOfferResult.Reject { Pass PASS = new Pass(); @@ -11,7 +14,7 @@ private Pass() { } non-sealed interface Accept extends PlayerOfferResult { - PlayerOfferResult.Accept and(Runnable and); + PlayerOfferResult.Accept thenRun(Consumer 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 a0f260e4..8eaf7d57 100644 --- a/src/testmod/java/xyz/nucleoid/plasmid/test/JankGame.java +++ b/src/testmod/java/xyz/nucleoid/plasmid/test/JankGame.java @@ -2,7 +2,6 @@ import eu.pb4.polymer.common.api.PolymerCommonUtils; import eu.pb4.polymer.virtualentity.api.VirtualEntityUtils; -import eu.pb4.sidebars.api.SidebarUtils; import it.unimi.dsi.fastutil.ints.IntList; import net.minecraft.block.BlockState; import net.minecraft.entity.MovementType; @@ -13,9 +12,7 @@ import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket; import net.minecraft.network.packet.s2c.play.*; import net.minecraft.particle.ParticleTypes; -import net.minecraft.screen.ScreenTexts; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import net.minecraft.util.math.Vec3d; @@ -61,11 +58,10 @@ public static GameOpenProcedure open(GameOpenContext context) { .setGameRule(GameRules.KEEP_INVENTORY, true); return context.openWithWorld(worldConfig, (activity, world) -> { - activity.listen(GamePlayerEvents.OFFER, offer -> { - var player = offer.player(); - return offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) - .and(() -> player.changeGameMode(GameMode.ADVENTURE)); - }); + activity.listen(GamePlayerEvents.OFFER, offer -> + offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) + .thenRun(player -> player.changeGameMode(GameMode.ADVENTURE)) + ); GameWaitingLobby.addTo(activity, new PlayerConfig(1, 99)); @@ -174,10 +170,10 @@ private static GameResult startGame(GameSpace gameSpace) { player.networkHandler.sendPacket(new PlayerPositionLookS2CPacket(0, 0, 0, 0, 0f, Set.of(), 0)); }); - activity.listen(GamePlayerEvents.OFFER, offer -> { - return offer.accept(gameSpace.getWorlds().iterator().next(), new Vec3d(0.0, 65.0, 0.0)) - .and(() -> offer.player().changeGameMode(GameMode.ADVENTURE)); - }); + 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)) + ); }); return GameResult.ok(); diff --git a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java index a6acbc8b..eaf63ee5 100644 --- a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java +++ b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java @@ -34,7 +34,6 @@ import xyz.nucleoid.plasmid.util.WoodType; import xyz.nucleoid.stimuli.event.player.PlayerDeathEvent; -import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; @@ -59,11 +58,10 @@ public static GameOpenProcedure open(GameOpenContext context) { .setGameRule(GameRules.KEEP_INVENTORY, true); return context.openWithWorld(worldConfig, (activity, world) -> { - activity.listen(GamePlayerEvents.OFFER, offer -> { - var player = offer.player(); - return offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) - .and(() -> player.changeGameMode(GameMode.ADVENTURE)); - }); + activity.listen(GamePlayerEvents.OFFER, offer -> + offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) + .thenRun(player -> player.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 3f618751..5c170f52 100644 --- a/src/testmod/java/xyz/nucleoid/plasmid/test/TestGameWithResourcePack.java +++ b/src/testmod/java/xyz/nucleoid/plasmid/test/TestGameWithResourcePack.java @@ -9,7 +9,6 @@ import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import net.minecraft.util.Identifier; -import net.minecraft.util.Unit; import net.minecraft.util.math.Vec3d; import net.minecraft.world.GameMode; import net.minecraft.world.GameRules; @@ -52,11 +51,10 @@ public static GameOpenProcedure open(GameOpenContext context) { .setGameRule(GameRules.KEEP_INVENTORY, true); return context.openWithWorld(worldConfig, (activity, world) -> { - activity.listen(GamePlayerEvents.OFFER, offer -> { - var player = offer.player(); - return offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) - .and(() -> player.changeGameMode(GameMode.ADVENTURE)); - }); + activity.listen(GamePlayerEvents.OFFER, offer -> + offer.accept(world, new Vec3d(0.0, 65.0, 0.0)) + .thenRun(player -> player.changeGameMode(GameMode.ADVENTURE)) + ); GameWaitingLobby.addTo(activity, new PlayerConfig(1, 99)); @@ -129,11 +127,10 @@ private static GameResult startGame(GameSpace gameSpace, int iter) { return ActionResult.FAIL; }); - activity.listen(GamePlayerEvents.OFFER, offer -> { - var player = offer.player(); - return offer.accept(gameSpace.getWorlds().iterator().next(), new Vec3d(0.0, 65.0, 0.0)) - .and(() -> player.changeGameMode(GameMode.ADVENTURE)); - }); + 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)) + ); }); return GameResult.ok(); From 07f5845ca2e0478012616e61fa1888be425c5d97 Mon Sep 17 00:00:00 2001 From: Gegy Date: Sun, 23 Jun 2024 10:51:13 +0200 Subject: [PATCH 4/6] Add PlayerOffer.accept overload that sets a rotation --- .../plasmid/game/player/LocalPlayerOffer.java | 12 ++++++---- .../plasmid/game/player/PlayerOffer.java | 22 +++++++++++++++++-- 2 files changed, 28 insertions(+), 6 deletions(-) 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 8ad58bcd..059043e8 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java @@ -18,8 +18,8 @@ public GameProfile profile() { } @Override - public PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position) { - return new Accept(world, position); + public PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position, float yaw, float pitch) { + return new Accept(world, position, yaw, pitch); } @Override @@ -30,12 +30,16 @@ public PlayerOfferResult.Reject reject(Text reason) { public static class Accept implements PlayerOfferResult.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) { + Accept(ServerWorld world, Vec3d position, float yaw, float pitch) { this.world = world; this.position = position; + this.yaw = yaw; + this.pitch = pitch; } @Override @@ -46,7 +50,7 @@ public Accept thenRun(Consumer consumer) { public ServerWorld applyJoin(ServerPlayerEntity player) { player.changeGameMode(GameMode.SURVIVAL); - player.refreshPositionAndAngles(this.position.x, this.position.y, this.position.z, 0.0F, 0.0F); + player.refreshPositionAndAngles(this.position.x, this.position.y, this.position.z, this.yaw, this.pitch); for (Consumer consumer : this.thenRun) { consumer.accept(player); 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 685df714..bd697897 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java @@ -10,6 +10,7 @@ import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; import java.util.UUID; +import java.util.function.Consumer; /** * Represents a request for a {@link ServerPlayerEntity} to join a {@link GameSpace}. @@ -48,10 +49,27 @@ default String playerName() { * * @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 * @return an "accept" offer result - * @see PlayerOfferResult.Accept#thenRun(java.util.function.Consumer) + * @see PlayerOfferResult.Accept#thenRun(Consumer) */ - PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position); + 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}. + *

+ * 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 + * @return an "accept" offer result + * @see PlayerOfferResult.Accept#thenRun(Consumer) + */ + default PlayerOfferResult.Accept accept(ServerWorld world, Vec3d position) { + return this.accept(world, position, 0.0f, 0.0f); + } /** * Returns an offer result that rejects this player offer and does not allow the player into this {@link GameSpace}. From c13e2a4f04053d1640c28f66e661c17c82dc2b45 Mon Sep 17 00:00:00 2001 From: Gegy Date: Mon, 15 Jul 2024 21:47:27 +0200 Subject: [PATCH 5/6] Narrow SCREEN_JOINS event to receive only GameProfiles --- .../xyz/nucleoid/plasmid/game/common/GameWaitingLobby.java | 3 ++- .../xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java | 3 ++- .../xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) 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 e15a2f48..603a55b7 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/common/GameWaitingLobby.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/common/GameWaitingLobby.java @@ -1,5 +1,6 @@ package xyz.nucleoid.plasmid.game.common; +import com.mojang.authlib.GameProfile; import net.minecraft.entity.boss.BossBar; import net.minecraft.screen.ScreenTexts; import net.minecraft.server.network.ServerPlayerEntity; @@ -169,7 +170,7 @@ private GameResult requestStart() { } } - private GameResult screenJoins(Collection players) { + private GameResult screenJoins(Collection players) { int newPlayerCount = this.gameSpace.getPlayers().size() + players.size(); if (newPlayerCount > this.playerConfig.maxPlayers()) { return GameResult.error(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 3b9063cd..5698141b 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java @@ -1,5 +1,6 @@ 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; @@ -174,7 +175,7 @@ public interface Remove { } public interface ScreenJoins { - GameResult screenJoins(Collection players); + GameResult screenJoins(Collection players); } public interface 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 c340cf26..a5f2f105 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java @@ -1,8 +1,10 @@ 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; @@ -195,7 +197,7 @@ public GameBehavior getBehavior() { } GameResult screenJoins(Collection players) { - var result = this.attemptScreenJoins(players); + var result = this.attemptScreenJoins(players.stream().map(PlayerEntity::getGameProfile).toList()); if (result.isError()) { this.players.attemptGarbageCollection(); @@ -204,7 +206,7 @@ GameResult screenJoins(Collection players) { return result; } - private GameResult attemptScreenJoins(Collection players) { + private GameResult attemptScreenJoins(Collection players) { if (this.closed) { return GameResult.error(GameTexts.Join.gameClosed()); } From 8ee6f3b517ea56ffcb5567dbc5ae73de27afecaf Mon Sep 17 00:00:00 2001 From: Gegy Date: Mon, 15 Jul 2024 22:02:12 +0200 Subject: [PATCH 6/6] Add JoinIntent parameter to offer and screen joins events, currently unused --- .../nucleoid/plasmid/command/GameCommand.java | 9 ++-- .../plasmid/command/ui/GameJoinUi.java | 3 +- .../plasmid/game/GameSpacePlayers.java | 9 ++-- .../plasmid/game/common/GameWaitingLobby.java | 2 +- .../plasmid/game/event/GamePlayerEvents.java | 7 ++-- .../game/manager/ManagedGameSpace.java | 10 ++--- .../game/manager/ManagedGameSpacePlayers.java | 13 +++--- .../plasmid/game/player/GamePlayerJoiner.java | 10 ++--- .../plasmid/game/player/JoinIntent.java | 42 +++++++++++++++++++ .../plasmid/game/player/LocalPlayerOffer.java | 2 +- .../plasmid/game/player/PlayerOffer.java | 6 +++ .../game/ConcurrentGamePortalBackend.java | 5 ++- .../portal/game/NewGamePortalBackend.java | 3 +- .../portal/game/SingleGamePortalBackend.java | 3 +- 14 files changed, 91 insertions(+), 33 deletions(-) create mode 100644 src/main/java/xyz/nucleoid/plasmid/game/player/JoinIntent.java diff --git a/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java b/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java index 1f6d7328..7e71bdb3 100644 --- a/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java +++ b/src/main/java/xyz/nucleoid/plasmid/command/GameCommand.java @@ -9,7 +9,6 @@ import com.mojang.logging.LogUtils; import net.minecraft.command.argument.EntityArgumentType; import net.minecraft.command.argument.NbtCompoundArgumentType; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.NbtOps; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.server.command.ServerCommandSource; @@ -30,6 +29,7 @@ import xyz.nucleoid.plasmid.game.config.GameConfigs; import xyz.nucleoid.plasmid.game.manager.GameSpaceManager; import xyz.nucleoid.plasmid.game.player.GamePlayerJoiner; +import xyz.nucleoid.plasmid.game.player.JoinIntent; import xyz.nucleoid.plasmid.util.Scheduler; import java.util.Comparator; @@ -286,10 +286,11 @@ private static void joinAllPlayersToGame(ServerCommandSource source, GameSpace g .filter(player -> !GameSpaceManager.get().inGame(player)) .collect(Collectors.toList()); - var screen = gameSpace.getPlayers().screenJoins(players); + var intent = JoinIntent.ANY; + var screen = gameSpace.getPlayers().screenJoins(players, intent); if (screen.isOk()) { for (var player : players) { - gameSpace.getPlayers().offer(player); + gameSpace.getPlayers().offer(player, intent); } } else { source.sendError(screen.errorCopy().formatted(Formatting.RED)); @@ -297,7 +298,7 @@ private static void joinAllPlayersToGame(ServerCommandSource source, GameSpace g } private static void tryJoinGame(ServerPlayerEntity player, GameSpace gameSpace) { - var results = GamePlayerJoiner.tryJoin(player, gameSpace); + var results = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); results.sendErrorsTo(player); } 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 2efba57c..000bdb17 100644 --- a/src/main/java/xyz/nucleoid/plasmid/command/ui/GameJoinUi.java +++ b/src/main/java/xyz/nucleoid/plasmid/command/ui/GameJoinUi.java @@ -15,6 +15,7 @@ import xyz.nucleoid.plasmid.game.manager.GameSpaceManager; import xyz.nucleoid.plasmid.game.manager.ManagedGameSpace; import xyz.nucleoid.plasmid.game.player.GamePlayerJoiner; +import xyz.nucleoid.plasmid.game.player.JoinIntent; import xyz.nucleoid.plasmid.util.Guis; import java.util.ArrayList; @@ -38,7 +39,7 @@ public GameJoinUi(ServerPlayerEntity player) { private static void tryJoinGame(ServerPlayerEntity player, GameSpace gameSpace) { player.server.execute(() -> { - var results = GamePlayerJoiner.tryJoin(player, gameSpace); + var results = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); results.sendErrorsTo(player); }); } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/GameSpacePlayers.java b/src/main/java/xyz/nucleoid/plasmid/game/GameSpacePlayers.java index 6f6b0697..1dd79dbb 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/GameSpacePlayers.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/GameSpacePlayers.java @@ -2,6 +2,7 @@ import net.minecraft.server.network.ServerPlayerEntity; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; +import xyz.nucleoid.plasmid.game.player.JoinIntent; import xyz.nucleoid.plasmid.game.player.PlayerOps; import xyz.nucleoid.plasmid.game.player.PlayerSet; @@ -21,12 +22,13 @@ public interface GameSpacePlayers extends PlayerSet { * 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 * @see GamePlayerEvents#SCREEN_JOINS - * @see GameSpacePlayers#offer(ServerPlayerEntity) + * @see GameSpacePlayers#offer(ServerPlayerEntity, JoinIntent) * @see xyz.nucleoid.plasmid.game.player.GamePlayerJoiner */ - GameResult screenJoins(Collection players); + 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 @@ -35,11 +37,12 @@ public interface GameSpacePlayers extends PlayerSet { * This logic is controlled through the active {@link GameActivity} through {@link GamePlayerEvents#OFFER}. * * @param player the player 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 * @see GamePlayerEvents#OFFER * @see xyz.nucleoid.plasmid.game.player.GamePlayerJoiner */ - GameResult offer(ServerPlayerEntity player); + GameResult offer(ServerPlayerEntity player, JoinIntent intent); /** * Attempts to remove the given {@link ServerPlayerEntity} from this {@link GameSpace}. 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 603a55b7..838e75c7 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,7 @@ 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, lobby::screenJoins); + activity.listen(GamePlayerEvents.SCREEN_JOINS, (players, intent) -> lobby.screenJoins(players)); activity.listen(GamePlayerEvents.OFFER, lobby::offerPlayer); activity.listen(GamePlayerEvents.REMOVE, lobby::onRemovePlayer); 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 5698141b..a347fa98 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/event/GamePlayerEvents.java @@ -9,6 +9,7 @@ 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.PlayerOffer; import xyz.nucleoid.plasmid.game.player.PlayerOfferResult; import xyz.nucleoid.stimuli.event.StimulusEvent; @@ -108,10 +109,10 @@ public final class GamePlayerEvents { * * @see GamePlayerEvents#OFFER */ - public static final StimulusEvent SCREEN_JOINS = StimulusEvent.create(ScreenJoins.class, ctx -> players -> { + public static final StimulusEvent SCREEN_JOINS = StimulusEvent.create(ScreenJoins.class, ctx -> (players, intent) -> { try { for (var listener : ctx.getListeners()) { - var result = listener.screenJoins(players); + var result = listener.screenJoins(players, intent); if (result.isError()) { return result; } @@ -175,7 +176,7 @@ public interface Remove { } public interface ScreenJoins { - GameResult screenJoins(Collection players); + GameResult screenJoins(Collection players, JoinIntent intent); } public interface 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 a5f2f105..f6abc17f 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpace.java @@ -19,8 +19,8 @@ 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.LocalPlayerOffer; -import xyz.nucleoid.plasmid.game.player.PlayerOffer; import xyz.nucleoid.plasmid.game.player.PlayerOfferResult; import java.util.Collection; @@ -196,8 +196,8 @@ public GameBehavior getBehavior() { return this.state; } - GameResult screenJoins(Collection players) { - var result = this.attemptScreenJoins(players.stream().map(PlayerEntity::getGameProfile).toList()); + GameResult screenJoins(Collection players, JoinIntent intent) { + var result = this.attemptScreenJoins(players.stream().map(PlayerEntity::getGameProfile).toList(), intent); if (result.isError()) { this.players.attemptGarbageCollection(); @@ -206,12 +206,12 @@ GameResult screenJoins(Collection players) { return result; } - private GameResult attemptScreenJoins(Collection players) { + 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); + return this.state.invoker(GamePlayerEvents.SCREEN_JOINS).screenJoins(players, intent); } PlayerOfferResult offerPlayer(LocalPlayerOffer offer) { 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 7bc3ade9..593dcd36 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/manager/ManagedGameSpacePlayers.java @@ -6,6 +6,7 @@ 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; @@ -27,13 +28,13 @@ public final class ManagedGameSpacePlayers implements GameSpacePlayers { } @Override - public GameResult screenJoins(Collection players) { - return this.space.screenJoins(players); + public GameResult screenJoins(Collection players, JoinIntent intent) { + return this.space.screenJoins(players, intent); } @Override - public GameResult offer(ServerPlayerEntity player) { - var result = this.attemptOffer(player); + public GameResult offer(ServerPlayerEntity player, JoinIntent intent) { + var result = this.attemptOffer(player, intent); if (result.isError()) { this.attemptGarbageCollection(); @@ -42,12 +43,12 @@ public GameResult offer(ServerPlayerEntity player) { return result; } - private GameResult attemptOffer(ServerPlayerEntity player) { + private GameResult attemptOffer(ServerPlayerEntity player, JoinIntent intent) { if (this.set.contains(player)) { return GameResult.error(GameTexts.Join.alreadyJoined()); } - var offer = new LocalPlayerOffer(player); + var offer = new LocalPlayerOffer(player, intent); switch (this.space.offerPlayer(offer)) { case LocalPlayerOffer.Accept accept -> { 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 8085154a..cd76e5cf 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/GamePlayerJoiner.java @@ -19,10 +19,10 @@ * members, screening, and offering players to the {@link GameSpace}. */ public final class GamePlayerJoiner { - public static Results tryJoin(ServerPlayerEntity player, GameSpace gameSpace) { + public static Results tryJoin(ServerPlayerEntity player, GameSpace gameSpace, JoinIntent intent) { try { var players = collectPlayersForJoin(player, gameSpace); - return tryJoinAll(players, gameSpace); + return tryJoinAll(players, gameSpace, intent); } catch (Throwable throwable) { return handleJoinException(throwable); } @@ -37,17 +37,17 @@ private static Set collectPlayersForJoin(ServerPlayerEntity return players; } - private static Results tryJoinAll(Collection players, GameSpace gameSpace) { + private static Results tryJoinAll(Collection players, GameSpace gameSpace, JoinIntent intent) { var results = new Results(); - var screenResult = gameSpace.getPlayers().screenJoins(players); + var screenResult = gameSpace.getPlayers().screenJoins(players, intent); if (screenResult.isError()) { results.globalError = screenResult.error(); return results; } for (var player : players) { - var result = gameSpace.getPlayers().offer(player); + var result = gameSpace.getPlayers().offer(player, intent); if (result.isError()) { results.playerErrors.put(player, result.error()); } diff --git a/src/main/java/xyz/nucleoid/plasmid/game/player/JoinIntent.java b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinIntent.java new file mode 100644 index 00000000..adaade71 --- /dev/null +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/JoinIntent.java @@ -0,0 +1,42 @@ +package xyz.nucleoid.plasmid.game.player; + +import xyz.nucleoid.plasmid.game.GameSpace; +import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; + +/** + * 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. + */ +public enum JoinIntent { + /** + * The player has no particular intention. Generally, this should be considered as a preference to participate. + */ + ANY, + /** + * The player intends to join the game to participate. If they cannot be joined as a participant, they should not + * be allowed to join. + */ + PLAY, + /** + * The player intends to join the game to spectate. Unless the game does not support spectators, this player should + * generally always be accepted. + */ + SPECTATE, + ; + + /** + * @return {@code true} if the player may join as a participant under any circumstances + */ + public boolean canPlay() { + return this != SPECTATE; + } + + /** + * @return {@code true} if the player may join as a spectator under any circumstances + */ + public boolean canSpectate() { + return this != PLAY; + } +} 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 059043e8..81e2cdbb 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/LocalPlayerOffer.java @@ -11,7 +11,7 @@ import java.util.List; import java.util.function.Consumer; -public record LocalPlayerOffer(ServerPlayerEntity player) implements PlayerOffer { +public record LocalPlayerOffer(ServerPlayerEntity player, JoinIntent intent) implements PlayerOffer { @Override public GameProfile profile() { return this.player.getGameProfile(); 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 bd697897..1b82d964 100644 --- a/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java +++ b/src/main/java/xyz/nucleoid/plasmid/game/player/PlayerOffer.java @@ -41,6 +41,12 @@ default String playerName() { return this.profile().getName(); } + /** + * @return the {@link JoinIntent 'intent'} of the player, 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}. *

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 9ac7a93f..5afc7b7f 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 @@ -7,6 +7,7 @@ import xyz.nucleoid.plasmid.game.manager.GameSpaceManager; import xyz.nucleoid.plasmid.game.manager.ManagedGameSpace; import xyz.nucleoid.plasmid.game.player.GamePlayerJoiner; +import xyz.nucleoid.plasmid.game.player.JoinIntent; import java.util.concurrent.CompletableFuture; import java.util.function.Function; @@ -28,7 +29,7 @@ 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); + var results = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); if (results.globalError == null && results.playerErrors.get(player) == null) { return; @@ -42,7 +43,7 @@ public void applyTo(ServerPlayerEntity player) { this.gameFuture = null; GamePlayerJoiner.Results results; if (gameSpace != null) { - results = GamePlayerJoiner.tryJoin(player, gameSpace); + results = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); } else { results = GamePlayerJoiner.handleJoinException(throwable); } 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 2abcac09..2d633c86 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 @@ -7,6 +7,7 @@ import xyz.nucleoid.plasmid.game.manager.GameSpaceManager; import xyz.nucleoid.plasmid.game.manager.ManagedGameSpace; import xyz.nucleoid.plasmid.game.player.GamePlayerJoiner; +import xyz.nucleoid.plasmid.game.player.JoinIntent; import java.util.concurrent.CompletableFuture; import java.util.function.Function; @@ -19,7 +20,7 @@ public void applyTo(ServerPlayerEntity player) { .handleAsync((gameSpace, throwable) -> { GamePlayerJoiner.Results results; if (gameSpace != null) { - results = GamePlayerJoiner.tryJoin(player, gameSpace); + results = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); } else { results = GamePlayerJoiner.handleJoinException(throwable); } 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 bf7614b6..a16b1986 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 @@ -10,6 +10,7 @@ import xyz.nucleoid.plasmid.game.manager.GameSpaceManager; import xyz.nucleoid.plasmid.game.manager.ManagedGameSpace; import xyz.nucleoid.plasmid.game.player.GamePlayerJoiner; +import xyz.nucleoid.plasmid.game.player.JoinIntent; import java.util.concurrent.CompletableFuture; import java.util.function.Function; @@ -29,7 +30,7 @@ public void applyTo(ServerPlayerEntity player) { .handleAsync((gameSpace, throwable) -> { GamePlayerJoiner.Results results; if (gameSpace != null) { - results = GamePlayerJoiner.tryJoin(player, gameSpace); + results = GamePlayerJoiner.tryJoin(player, gameSpace, JoinIntent.ANY); } else { results = GamePlayerJoiner.handleJoinException(throwable); }