diff --git a/src/main/java/xyz/nucleoid/extras/NucleoidExtrasConfig.java b/src/main/java/xyz/nucleoid/extras/NucleoidExtrasConfig.java index 2566090..87d8ab5 100644 --- a/src/main/java/xyz/nucleoid/extras/NucleoidExtrasConfig.java +++ b/src/main/java/xyz/nucleoid/extras/NucleoidExtrasConfig.java @@ -16,6 +16,7 @@ import xyz.nucleoid.extras.command.CommandAliasConfig; import xyz.nucleoid.extras.error.ErrorReportingConfig; import xyz.nucleoid.extras.integrations.IntegrationsConfig; +import xyz.nucleoid.extras.lobby.LobbySpawnConfig; import xyz.nucleoid.extras.util.ExtraCodecs; import java.io.IOException; @@ -31,6 +32,7 @@ public record NucleoidExtrasConfig( boolean sidebar, Optional gamePortalOpener, + @Nullable LobbySpawnConfig lobbySpawn, @Nullable IntegrationsConfig integrations, @Nullable CommandAliasConfig aliases, @Nullable ChatFilterConfig chatFilter, @@ -47,6 +49,7 @@ public record NucleoidExtrasConfig( instance.group( Codec.BOOL.optionalFieldOf("sidebar", false).forGetter(NucleoidExtrasConfig::sidebar), Identifier.CODEC.optionalFieldOf("game_portal_opener").forGetter(NucleoidExtrasConfig::gamePortalOpener), + LobbySpawnConfig.CODEC.optionalFieldOf("lobby_spawn").forGetter(config -> Optional.ofNullable(config.lobbySpawn())), IntegrationsConfig.CODEC.optionalFieldOf("integrations").forGetter(config -> Optional.ofNullable(config.integrations())), CommandAliasConfig.CODEC.optionalFieldOf("aliases").forGetter(config -> Optional.ofNullable(config.aliases())), ChatFilterConfig.CODEC.optionalFieldOf("chat_filter").forGetter(config -> Optional.ofNullable(config.chatFilter())), @@ -54,15 +57,15 @@ public record NucleoidExtrasConfig( ErrorReportingConfig.CODEC.optionalFieldOf("error_reporting", ErrorReportingConfig.NONE).forGetter(NucleoidExtrasConfig::errorReporting), Codec.BOOL.optionalFieldOf("dev_server", false).forGetter(NucleoidExtrasConfig::devServer), ExtraCodecs.URI.optionalFieldOf("http_api").forGetter(config -> Optional.ofNullable(config.httpApi())) - ).apply(instance, (sidebar, gamePortalOpener, integrations, aliases, filter, contributorDataUrl, errorReporting, devServer, httpApiUrl) -> - new NucleoidExtrasConfig(sidebar, gamePortalOpener, integrations.orElse(null), aliases.orElse(null), filter.orElse(null), contributorDataUrl.orElse(null), errorReporting, devServer, httpApiUrl.orElse(null)) + ).apply(instance, (sidebar, gamePortalOpener, lobbySpawn, integrations, aliases, filter, contributorDataUrl, errorReporting, devServer, httpApiUrl) -> + new NucleoidExtrasConfig(sidebar, gamePortalOpener, lobbySpawn.orElse(null), integrations.orElse(null), aliases.orElse(null), filter.orElse(null), contributorDataUrl.orElse(null), errorReporting, devServer, httpApiUrl.orElse(null)) ) ); private static NucleoidExtrasConfig instance; private NucleoidExtrasConfig() { - this(false, Optional.empty(), null, null, null, null, ErrorReportingConfig.NONE, false, null); + this(false, Optional.empty(), null, null, null, null, null, ErrorReportingConfig.NONE, false, null); } @NotNull diff --git a/src/main/java/xyz/nucleoid/extras/command/ExtraCommands.java b/src/main/java/xyz/nucleoid/extras/command/ExtraCommands.java index 6a8f2e9..185385f 100644 --- a/src/main/java/xyz/nucleoid/extras/command/ExtraCommands.java +++ b/src/main/java/xyz/nucleoid/extras/command/ExtraCommands.java @@ -13,6 +13,7 @@ public static void register() { } private static void register(CommandDispatcher dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) { + SpawnCommand.register(dispatcher); StatsCommand.register(dispatcher); } } diff --git a/src/main/java/xyz/nucleoid/extras/command/SpawnCommand.java b/src/main/java/xyz/nucleoid/extras/command/SpawnCommand.java new file mode 100644 index 0000000..128facd --- /dev/null +++ b/src/main/java/xyz/nucleoid/extras/command/SpawnCommand.java @@ -0,0 +1,41 @@ +package xyz.nucleoid.extras.command; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.server.command.ServerCommandSource; +import xyz.nucleoid.extras.NucleoidExtrasConfig; +import xyz.nucleoid.extras.lobby.NEItems; + +import static net.minecraft.server.command.CommandManager.literal; + +public class SpawnCommand { + public static void register(CommandDispatcher dispatcher) { + var config = NucleoidExtrasConfig.get(); + + if (config.lobbySpawn() != null) { + dispatcher.register(literal("spawn").executes(SpawnCommand::execute)); + + // https://github.com/Mojang/brigadier/issues/46 + dispatcher.register(literal("lobby").executes(SpawnCommand::execute)); + dispatcher.register(literal("hub").executes(SpawnCommand::execute)); + } + } + + private static int execute(CommandContext context) throws CommandSyntaxException { + var source = context.getSource(); + + var player = source.getPlayerOrThrow(); + var server = source.getServer(); + + var config = NucleoidExtrasConfig.get().lobbySpawn(); + + config.teleport(player, server.getOverworld()); + config.changeGameMode(player, server.getDefaultGameMode()); + + NEItems.giveLobbyItems(player); + + return Command.SINGLE_SUCCESS; + } +} diff --git a/src/main/java/xyz/nucleoid/extras/lobby/LobbySpawnConfig.java b/src/main/java/xyz/nucleoid/extras/lobby/LobbySpawnConfig.java new file mode 100644 index 0000000..8aa41c7 --- /dev/null +++ b/src/main/java/xyz/nucleoid/extras/lobby/LobbySpawnConfig.java @@ -0,0 +1,36 @@ +package xyz.nucleoid.extras.lobby; + +import java.util.Collections; +import java.util.Optional; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.GameMode; + +public record LobbySpawnConfig( + Vec3d pos, + float yaw, + float pitch, + Optional gameMode +) { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group( + Vec3d.CODEC.fieldOf("pos").forGetter(LobbySpawnConfig::pos), + Codec.FLOAT.optionalFieldOf("yaw", 0f).forGetter(LobbySpawnConfig::yaw), + Codec.FLOAT.optionalFieldOf("pitch", 0f).forGetter(LobbySpawnConfig::pitch), + GameMode.CODEC.optionalFieldOf("game_mode").forGetter(LobbySpawnConfig::gameMode) + ).apply(instance, LobbySpawnConfig::new) + ); + + public void teleport(ServerPlayerEntity player, ServerWorld world) { + player.teleport(world, this.pos.getX(), this.pos.getY(), this.pos.getZ(), Collections.emptySet(), this.yaw, this.pitch); + } + + public void changeGameMode(ServerPlayerEntity player, GameMode fallback) { + player.changeGameMode(this.gameMode.orElse(fallback)); + } +} diff --git a/src/main/java/xyz/nucleoid/extras/lobby/NEItems.java b/src/main/java/xyz/nucleoid/extras/lobby/NEItems.java index 601f6f4..7b54680 100644 --- a/src/main/java/xyz/nucleoid/extras/lobby/NEItems.java +++ b/src/main/java/xyz/nucleoid/extras/lobby/NEItems.java @@ -18,6 +18,7 @@ import net.minecraft.registry.Registry; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayNetworkHandler; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; @@ -813,8 +814,8 @@ public static void register() { UseEntityCallback.EVENT.register(NEItems::onUseEntity); } - private static boolean tryOfferStack(ServerPlayNetworkHandler handler, Item item, Consumer consumer) { - var inventory = handler.getPlayer().getInventory(); + private static boolean tryOfferStack(ServerPlayerEntity player, Item item, Consumer consumer) { + var inventory = player.getInventory(); if (inventory.containsAny(Collections.singleton(item))) { return false; @@ -823,21 +824,25 @@ private static boolean tryOfferStack(ServerPlayNetworkHandler handler, Item item var stack = new ItemStack(item); consumer.accept(stack); - handler.getPlayer().getInventory().offer(stack, true); + player.getInventory().offer(stack, true); return true; } - private static boolean tryOfferStack(ServerPlayNetworkHandler handler, Item item) { - return tryOfferStack(handler, item, stack -> {}); + private static boolean tryOfferStack(ServerPlayerEntity player, Item item) { + return tryOfferStack(player, item, stack -> {}); } private static void onPlayerJoin(ServerPlayNetworkHandler handler, PacketSender packetSender, MinecraftServer server) { + giveLobbyItems(handler.getPlayer()); + } + + public static void giveLobbyItems(ServerPlayerEntity player) { var config = NucleoidExtrasConfig.get(); - tryOfferStack(handler, TATER_BOX); + tryOfferStack(player, TATER_BOX); config.gamePortalOpener().ifPresent(gamePortal -> { - tryOfferStack(handler, GAME_PORTAL_OPENER, stack -> { + tryOfferStack(player, GAME_PORTAL_OPENER, stack -> { GamePortalOpenerItem.setGamePortalId(stack, gamePortal); }); });