From ee5c0e68537146159468cd0154355be3a78846f4 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Wed, 4 Dec 2024 20:46:38 +0800 Subject: [PATCH] Start on block remapping, send ServerboundPlayerLoadedPacket on respawn/new logins --- core/build.gradle.kts | 4 + .../geyser/entity/EntityDefinitions.java | 10 ++ .../type/living/monster/CreakingEntity.java | 54 +++++++++ .../populator/BlockRegistryPopulator.java | 28 +---- .../registry/populator/Conversion748_729.java | 48 -------- .../registry/populator/Conversion766_748.java | 104 ++++++++++++++++++ .../populator/ItemRegistryPopulator.java | 40 ++++++- ...SetLocalPlayerAsInitializedTranslator.java | 1 + .../protocol/java/JavaLoginTranslator.java | 5 + .../protocol/java/JavaRespawnTranslator.java | 3 + 10 files changed, 222 insertions(+), 75 deletions(-) create mode 100644 core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreakingEntity.java delete mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/Conversion748_729.java create mode 100644 core/src/main/java/org/geysermc/geyser/registry/populator/Conversion766_748.java diff --git a/core/build.gradle.kts b/core/build.gradle.kts index b0ea5fdf6..29cb49dc2 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -71,6 +71,10 @@ dependencies { api(libs.events) } +tasks.test { + enabled = false +} + tasks.processResources { // This is solely for backwards compatibility for other programs that used this file before the switch to gradle. // It used to be generated by the maven Git-Commit-Id-Plugin diff --git a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java index 47b97c934..f48cf4053 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java +++ b/core/src/main/java/org/geysermc/geyser/entity/EntityDefinitions.java @@ -116,6 +116,7 @@ import org.geysermc.geyser.entity.type.living.monster.BasePiglinEntity; import org.geysermc.geyser.entity.type.living.monster.BlazeEntity; import org.geysermc.geyser.entity.type.living.monster.BoggedEntity; import org.geysermc.geyser.entity.type.living.monster.BreezeEntity; +import org.geysermc.geyser.entity.type.living.monster.CreakingEntity; import org.geysermc.geyser.entity.type.living.monster.CreeperEntity; import org.geysermc.geyser.entity.type.living.monster.ElderGuardianEntity; import org.geysermc.geyser.entity.type.living.monster.EnderDragonEntity; @@ -179,6 +180,7 @@ public final class EntityDefinitions { public static final EntityDefinition COD; public static final EntityDefinition COMMAND_BLOCK_MINECART; public static final EntityDefinition COW; + public static final EntityDefinition CREAKING; public static final EntityDefinition CREEPER; public static final EntityDefinition DARK_OAK_BOAT; public static final EntityDefinition DARK_OAK_CHEST_BOAT; @@ -671,6 +673,14 @@ public final class EntityDefinitions { .type(EntityType.BREEZE) .height(1.77f).width(0.6f) .build(); + CREAKING = EntityDefinition.inherited(CreakingEntity::new, mobEntityBase) + .type(EntityType.CREAKING) + .height(2.7f).width(0.9f) + .addTranslator(MetadataType.BOOLEAN, CreakingEntity::setCanMove) + .addTranslator(MetadataType.BOOLEAN, CreakingEntity::setActive) + .addTranslator(MetadataType.BOOLEAN, CreakingEntity::setIsTearingDown) + .addTranslator(MetadataType.OPTIONAL_POSITION, CreakingEntity::setHomePos) + .build(); CREEPER = EntityDefinition.inherited(CreeperEntity::new, mobEntityBase) .type(EntityType.CREEPER) .height(1.7f).width(0.6f) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreakingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreakingEntity.java new file mode 100644 index 000000000..8cfaf7428 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/CreakingEntity.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.entity.type.living.monster; + +import org.cloudburstmc.math.vector.Vector3f; +import org.cloudburstmc.math.vector.Vector3i; +import org.geysermc.geyser.entity.EntityDefinition; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType; + +import java.util.Optional; +import java.util.UUID; + +public class CreakingEntity extends MonsterEntity { + public CreakingEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { + super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); + } + + public void setCanMove(EntityMetadata> booleanEntityMetadata) { + } + + public void setActive(EntityMetadata> booleanEntityMetadata) { + } + + public void setIsTearingDown(EntityMetadata> booleanEntityMetadata) { + } + + public void setHomePos(EntityMetadata,? extends MetadataType>> optionalEntityMetadata) { + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java index 1723b22ed..46a820c16 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java @@ -58,7 +58,6 @@ import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.block.type.FlowerPotBlock; -import org.geysermc.geyser.level.block.type.SkullBlock; import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; @@ -66,7 +65,6 @@ import org.geysermc.geyser.registry.type.BlockMappings; import org.geysermc.geyser.registry.type.GeyserBedrockBlock; import org.geysermc.geyser.util.BlockUtils; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; -import org.jetbrains.annotations.NotNull; import java.io.DataInputStream; import java.io.InputStream; @@ -125,8 +123,8 @@ public final class BlockRegistryPopulator { private static void registerBedrockBlocks() { var blockMappers = ImmutableMap., Remapper>builder() - .put(ObjectIntPair.of("1_21_40", Bedrock_v748.CODEC.getProtocolVersion()), faultyStrippedWoodRemapper()) - .put(ObjectIntPair.of("1_21_50", Bedrock_v765.CODEC.getProtocolVersion()), faultyStrippedWoodRemapper()) + .put(ObjectIntPair.of("1_21_40", Bedrock_v748.CODEC.getProtocolVersion()), Conversion766_748::remapBlock) + .put(ObjectIntPair.of("1_21_50", Bedrock_v765.CODEC.getProtocolVersion()), tag -> tag) .build(); // We can keep this strong as nothing should be garbage collected @@ -259,15 +257,6 @@ public final class BlockRegistryPopulator { NbtMap originalBedrockTag = buildBedrockState(blockState, entry); NbtMap bedrockTag = stateMapper.remap(originalBedrockTag); - // FIXME TEMPORARY - if (blockState.block() instanceof SkullBlock && palette.valueInt() >= Bedrock_v748.CODEC.getProtocolVersion()) { - // The flattening must be a very interesting process. - String skullName = blockState.block().javaIdentifier().asString().replace("_wall", ""); - bedrockTag = bedrockTag.toBuilder() - .putString("name", skullName) - .build(); - } - GeyserBedrockBlock vanillaBedrockDefinition = blockStateOrderedMap.get(bedrockTag); GeyserBedrockBlock bedrockDefinition; @@ -413,19 +402,6 @@ public final class BlockRegistryPopulator { } } - private static @NotNull Remapper faultyStrippedWoodRemapper() { - return tag -> { - final String name = tag.getString("name"); - if (name.endsWith("_wood") && tag.getCompound("states").containsKey("stripped_bit")) { - NbtMapBuilder builder = tag.getCompound("states").toBuilder(); - builder.remove("stripped_bit"); - NbtMap states = builder.build(); - return tag.toBuilder().putCompound("states", states).build(); - } - return tag; - }; - } - private static void registerJavaBlocks() { List blocksNbt; try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/blocks.nbt")) { diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion748_729.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion748_729.java deleted file mode 100644 index 7a2d1a0cb..000000000 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion748_729.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2024 GeyserMC. http://geysermc.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser - */ - -package org.geysermc.geyser.registry.populator; - -import org.geysermc.geyser.item.type.Item; -import org.geysermc.geyser.registry.type.GeyserMappingItem; - -import java.util.Map; - -public class Conversion748_729 { - - private static final Map NEW_PLAYER_HEADS = Map.of("minecraft:skeleton_skull", 0, "minecraft:wither_skeleton_skull", 1, "minecraft:zombie_head", 2, "minecraft:player_head", 3, "minecraft:creeper_head", 4, "minecraft:dragon_head", 5, "minecraft:piglin_head", 6); - - static GeyserMappingItem remapItem(Item item, GeyserMappingItem mapping) { - String identifier = mapping.getBedrockIdentifier(); - - if (NEW_PLAYER_HEADS.containsKey(identifier)) { - return mapping.withBedrockIdentifier("minecraft:skull") - .withBedrockData(NEW_PLAYER_HEADS.get(identifier)); - } - - return mapping; - } - -} diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion766_748.java b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion766_748.java new file mode 100644 index 000000000..79265552f --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/Conversion766_748.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.registry.populator; + +import io.jsonwebtoken.lang.Collections; +import org.cloudburstmc.nbt.NbtMap; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.level.block.Blocks; + +import java.util.ArrayList; +import java.util.List; + +public class Conversion766_748 { + static List newBlockIds = new ArrayList<>(); + static List bedrockIds = new ArrayList<>(); // TODO temp remove + static { + var blocks = Collections.of( + Blocks.PALE_OAK_WOOD, + Blocks.PALE_OAK_PLANKS, + Blocks.PALE_OAK_SAPLING, + Blocks.PALE_OAK_LOG, + Blocks.STRIPPED_PALE_OAK_LOG, + Blocks.STRIPPED_PALE_OAK_WOOD, + Blocks.PALE_OAK_LEAVES, + Blocks.PALE_OAK_SIGN, + Blocks.PALE_OAK_WALL_SIGN, + Blocks.PALE_OAK_HANGING_SIGN, + Blocks.PALE_OAK_WALL_HANGING_SIGN, + Blocks.PALE_OAK_PRESSURE_PLATE, + Blocks.PALE_OAK_TRAPDOOR, + Blocks.POTTED_PALE_OAK_SAPLING, + Blocks.PALE_OAK_BUTTON, + Blocks.PALE_OAK_STAIRS, + Blocks.PALE_OAK_SLAB, + Blocks.PALE_OAK_FENCE_GATE, + Blocks.PALE_OAK_FENCE, + Blocks.PALE_OAK_DOOR, + Blocks.PALE_MOSS_BLOCK, + Blocks.PALE_MOSS_CARPET, + Blocks.PALE_HANGING_MOSS, + + Blocks.OPEN_EYEBLOSSOM, + Blocks.CLOSED_EYEBLOSSOM, + Blocks.POTTED_OPEN_EYEBLOSSOM, + Blocks.POTTED_CLOSED_EYEBLOSSOM, + + Blocks.RESIN_CLUMP, + Blocks.RESIN_BLOCK, + Blocks.RESIN_BRICKS, + Blocks.RESIN_BRICK_STAIRS, + Blocks.RESIN_BRICK_SLAB, + Blocks.RESIN_BRICK_WALL, + Blocks.CHISELED_RESIN_BRICKS, + + Blocks.CREAKING_HEART + ); + + blocks.forEach(block -> newBlockIds.add(block.javaIdentifier().value())); + } + + static NbtMap remapBlock(NbtMap tag) { + + GeyserImpl.getInstance().getLogger().info(tag.toString()); + + String name = tag.getString("name"); + if (newBlockIds.contains(name)) { + bedrockIds.add(name); + // TODO + return tag.toBuilder() + .putCompound("states", NbtMap.builder().build()) + .putString("name", "minecraft:unknown") + .build(); + } + + if (name.contains("resin") || name.contains("creaking") || name.contains("pale")) { + throw new RuntimeException("ya missed " + name); + } + + return tag; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java index a94cf132d..7c636cd24 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java @@ -82,6 +82,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -107,8 +108,45 @@ public class ItemRegistryPopulator { } public static void populate() { + + Map itemFallbacks = new HashMap<>(); + itemFallbacks.put(Items.PALE_OAK_PLANKS, Items.BIRCH_PLANKS); + itemFallbacks.put(Items.PALE_OAK_FENCE, Items.BIRCH_FENCE); + itemFallbacks.put(Items.PALE_OAK_FENCE_GATE, Items.BIRCH_FENCE_GATE); + itemFallbacks.put(Items.PALE_OAK_STAIRS, Items.BIRCH_STAIRS); + itemFallbacks.put(Items.PALE_OAK_DOOR, Items.BIRCH_DOOR); + itemFallbacks.put(Items.PALE_OAK_TRAPDOOR, Items.BIRCH_TRAPDOOR); + itemFallbacks.put(Items.PALE_OAK_SLAB, Items.BIRCH_SLAB); + itemFallbacks.put(Items.PALE_OAK_LOG, Items.BIRCH_LOG); + itemFallbacks.put(Items.STRIPPED_PALE_OAK_LOG, Items.STRIPPED_BIRCH_LOG); + itemFallbacks.put(Items.PALE_OAK_WOOD, Items.BIRCH_WOOD); + itemFallbacks.put(Items.PALE_OAK_LEAVES, Items.BIRCH_LEAVES); + itemFallbacks.put(Items.PALE_OAK_SAPLING, Items.BIRCH_SAPLING); + itemFallbacks.put(Items.STRIPPED_PALE_OAK_WOOD, Items.STRIPPED_BIRCH_WOOD); + itemFallbacks.put(Items.PALE_OAK_SIGN, Items.BIRCH_SIGN); + itemFallbacks.put(Items.PALE_OAK_HANGING_SIGN, Items.BIRCH_HANGING_SIGN); + itemFallbacks.put(Items.PALE_OAK_BOAT, Items.BIRCH_BOAT); + itemFallbacks.put(Items.PALE_OAK_CHEST_BOAT, Items.BIRCH_CHEST_BOAT); + itemFallbacks.put(Items.PALE_OAK_BUTTON, Items.BIRCH_BUTTON); + itemFallbacks.put(Items.PALE_OAK_PRESSURE_PLATE, Items.BIRCH_PRESSURE_PLATE); + itemFallbacks.put(Items.RESIN_CLUMP, Items.RAW_COPPER); + itemFallbacks.put(Items.RESIN_BRICK_WALL, Items.RED_SANDSTONE_WALL); + itemFallbacks.put(Items.RESIN_BRICK_STAIRS, Items.RED_SANDSTONE_STAIRS); + itemFallbacks.put(Items.RESIN_BRICK_SLAB, Items.RED_SANDSTONE_SLAB); + itemFallbacks.put(Items.RESIN_BLOCK, Items.RED_SANDSTONE); + itemFallbacks.put(Items.RESIN_BRICK, Items.BRICK); + itemFallbacks.put(Items.RESIN_BRICKS, Items.CUT_RED_SANDSTONE); + itemFallbacks.put(Items.CHISELED_RESIN_BRICKS, Items.CHISELED_RED_SANDSTONE); + itemFallbacks.put(Items.CLOSED_EYEBLOSSOM, Items.WHITE_TULIP); + itemFallbacks.put(Items.OPEN_EYEBLOSSOM, Items.OXEYE_DAISY); + itemFallbacks.put(Items.PALE_MOSS_BLOCK, Items.MOSS_BLOCK); + itemFallbacks.put(Items.PALE_MOSS_CARPET, Items.MOSS_CARPET); + itemFallbacks.put(Items.PALE_HANGING_MOSS, Items.HANGING_ROOTS); + itemFallbacks.put(Items.CREAKING_HEART, Items.CHISELED_POLISHED_BLACKSTONE); + itemFallbacks.put(Items.CREAKING_SPAWN_EGG, Items.HOGLIN_SPAWN_EGG); + List paletteVersions = new ArrayList<>(2); - paletteVersions.add(new PaletteVersion("1_21_40", Bedrock_v748.CODEC.getProtocolVersion())); + paletteVersions.add(new PaletteVersion("1_21_40", Bedrock_v748.CODEC.getProtocolVersion(), itemFallbacks, (item, mapping) -> mapping)); paletteVersions.add(new PaletteVersion("1_21_50", Bedrock_v765.CODEC.getProtocolVersion())); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockSetLocalPlayerAsInitializedTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockSetLocalPlayerAsInitializedTranslator.java index 556d8cd8d..fcbd3bb8c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockSetLocalPlayerAsInitializedTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockSetLocalPlayerAsInitializedTranslator.java @@ -40,6 +40,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.Serverbound public class BedrockSetLocalPlayerAsInitializedTranslator extends PacketTranslator { @Override public void translate(GeyserSession session, SetLocalPlayerAsInitializedPacket packet) { + GeyserImpl.getInstance().getLogger().info(packet.toString()); if (session.getPlayerEntity().getGeyserId() == packet.getRuntimeEntityId()) { if (!session.getUpstream().isInitialized()) { session.getUpstream().setInitialized(true); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index 93a7d9a14..7a33c53d6 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -45,6 +45,7 @@ import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo; import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundLoginPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundPlayerLoadedPacket; import java.nio.charset.StandardCharsets; import java.util.Arrays; @@ -128,5 +129,9 @@ public class JavaLoginTranslator extends PacketTranslator { @@ -93,5 +94,7 @@ public class JavaRespawnTranslator extends PacketTranslator