diff --git a/core/src/main/java/org/geysermc/geyser/entity/GeyserDirtyMetadata.java b/core/src/main/java/org/geysermc/geyser/entity/GeyserDirtyMetadata.java index c81514eae..bc567ab91 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/GeyserDirtyMetadata.java +++ b/core/src/main/java/org/geysermc/geyser/entity/GeyserDirtyMetadata.java @@ -37,7 +37,7 @@ import java.util.Map; public final class GeyserDirtyMetadata { private final Map, Object> metadata = new Object2ObjectLinkedOpenHashMap<>(); - public void put(EntityDataType entityData, Object value) { + public void put(EntityDataType entityData, T value) { metadata.put(entityData, value); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java index f9e6879da..f9da5c69f 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/BoatEntity.java @@ -73,7 +73,7 @@ public class BoatEntity extends Entity { super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw + 90, 0, yaw + 90); // Required to be able to move on land 1.16.200+ or apply gravity not in the water 1.16.100+ - dirtyMetadata.put(EntityDataTypes.IS_BUOYANT, (byte) 1); + dirtyMetadata.put(EntityDataTypes.IS_BUOYANT, true); dirtyMetadata.put(EntityDataTypes.BUOYANCY_DATA, BUOYANCY_DATA); } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/CommandBlockMinecartEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/CommandBlockMinecartEntity.java index 6b0630546..6e40d288a 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/CommandBlockMinecartEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/CommandBlockMinecartEntity.java @@ -50,7 +50,7 @@ public class CommandBlockMinecartEntity extends DefaultBlockMinecartEntity { dirtyMetadata.put(EntityDataTypes.CONTAINER_TYPE, (byte) 16); dirtyMetadata.put(EntityDataTypes.CONTAINER_SIZE, 1); // Required, or else the client does not bother to send a packet back with the new information - dirtyMetadata.put(EntityDataTypes.COMMAND_BLOCK_ENABLED, (byte) 1); + dirtyMetadata.put(EntityDataTypes.COMMAND_BLOCK_ENABLED, true); } /** diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java index 243cfd23d..75bd34d68 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/ThrownPotionEntity.java @@ -62,7 +62,7 @@ public class ThrownPotionEntity extends ThrowableItemEntity { if (potionTag instanceof StringTag) { Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); if (potion != null) { - dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, potion.getBedrockId()); + dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, (int) potion.getBedrockId()); setFlag(EntityFlag.ENCHANTED, !NON_ENCHANTED_POTIONS.contains(potion)); } else { dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, 0); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java index 27188c79e..856c4cc66 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/TippedArrowEntity.java @@ -47,13 +47,13 @@ public class TippedArrowEntity extends AbstractArrowEntity { int potionColor = entityMetadata.getPrimitiveValue(); // -1 means no color if (potionColor == -1) { - dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, 0); + dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, (byte) 0); } else { TippedArrowPotion potion = TippedArrowPotion.getByJavaColor(potionColor); if (potion != null && potion.getJavaColor() != -1) { dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, (byte) potion.getBedrockId()); } else { - dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, 0); + dirtyMetadata.put(EntityDataTypes.CUSTOM_DISPLAY, (byte) 0); } } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java index 5ad7d8740..ee622dc42 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/monster/ShulkerEntity.java @@ -47,7 +47,7 @@ public class ShulkerEntity extends GolemEntity { public void setAttachedFace(EntityMetadata entityMetadata) { Direction direction = entityMetadata.getValue(); - dirtyMetadata.put(EntityDataTypes.SHULKER_ATTACH_FACE, (byte) direction.ordinal()); + dirtyMetadata.put(EntityDataTypes.SHULKER_ATTACH_FACE, direction.ordinal()); } public void setShulkerHeight(ByteEntityMetadata entityMetadata) { @@ -56,7 +56,7 @@ public class ShulkerEntity extends GolemEntity { } public void setShulkerColor(ByteEntityMetadata entityMetadata) { - byte color = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue(); + byte color = entityMetadata.getPrimitiveValue(); if (color == 16) { // 16 is default on both editions dirtyMetadata.put(EntityDataTypes.VARIANT, 16); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index ddd9a41e0..fe188ddb2 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -288,7 +288,7 @@ public class PlayerEntity extends LivingEntity { ParrotEntity parrot = new ParrotEntity(session, 0, session.getEntityCache().getNextEntityId().incrementAndGet(), null, EntityDefinitions.PARROT, position, motion, getYaw(), getPitch(), getHeadYaw()); parrot.spawnEntity(); - parrot.getDirtyMetadata().put(EntityDataTypes.VARIANT, tag.get("Variant").getValue()); + parrot.getDirtyMetadata().put(EntityDataTypes.VARIANT, (Integer) tag.get("Variant").getValue()); // Different position whether the parrot is left or right float offset = isLeft ? 0.4f : -0.4f; parrot.getDirtyMetadata().put(EntityDataTypes.SEAT_OFFSET, Vector3f.from(offset, -0.22, -0.1)); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java index 7ca006231..35cad7d6e 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java @@ -244,9 +244,9 @@ public class SessionPlayerEntity extends PlayerEntity { if (pos != null) { dirtyMetadata.put(EntityDataTypes.PLAYER_LAST_DEATH_POS, pos.getPosition()); dirtyMetadata.put(EntityDataTypes.PLAYER_LAST_DEATH_DIMENSION, DimensionUtils.javaToBedrock(pos.getDimension())); - dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, (byte) 1); + dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, true); } else { - dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, (byte) 0); + dirtyMetadata.put(EntityDataTypes.PLAYER_HAS_DIED, false); } } } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java index 73528a6a5..732769287 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/GeyserItemStack.java @@ -92,9 +92,10 @@ public class GeyserItemStack { } public ItemData getItemData(GeyserSession session) { - ItemData itemData = ItemTranslator.translateToBedrock(session, getItemStack()); - itemData.setNetId(getNetId()); - return itemData; + ItemData.Builder itemData = ItemTranslator.translateToBedrock(session, javaId, amount, nbt); + itemData.netId(getNetId()); + itemData.usingNetId(true); + return itemData.build(); } public ItemMapping getMapping(GeyserSession session) { diff --git a/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java b/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java index dd29527af..9bcf30789 100644 --- a/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java +++ b/core/src/main/java/org/geysermc/geyser/network/GeyserServerInitializer.java @@ -28,8 +28,6 @@ package org.geysermc.geyser.network; import io.netty.channel.DefaultEventLoopGroup; import io.netty.util.concurrent.DefaultThreadFactory; import org.cloudburstmc.protocol.bedrock.BedrockServerSession; -import org.cloudburstmc.protocol.bedrock.codec.v554.Bedrock_v554; -import org.cloudburstmc.protocol.bedrock.data.PacketCompressionAlgorithm; import org.cloudburstmc.protocol.bedrock.netty.initializer.BedrockServerInitializer; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.session.GeyserSession; @@ -72,14 +70,9 @@ public class GeyserServerInitializer extends BedrockServerInitializer { @Override public void initSession(@Nonnull BedrockServerSession bedrockServerSession) { - System.out.println("init session"); try { - bedrockServerSession.setCodec(Bedrock_v554.CODEC); // Has the RequestNetworkSettingsPacket bedrockServerSession.setLogging(true); bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(this.geyser, new GeyserSession(this.geyser, bedrockServerSession, this.eventLoopGroup.next()))); - bedrockServerSession.setCompression(PacketCompressionAlgorithm.ZLIB); - bedrockServerSession.setCompressionLevel(this.geyser.getConfig().getBedrock().getCompressionLevel()); - // Set the packet codec to default just in case we need to send disconnect packets. } catch (Throwable e) { // Error must be caught or it will be swallowed this.geyser.getLogger().error("Error occurred while initializing player!", e); diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index d5bb17aa8..0a81f430d 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -73,7 +73,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { } private PacketSignal translateAndDefault(BedrockPacket packet) { - return Registries.BEDROCK_PACKET_TRANSLATORS.translate(packet.getClass(), packet, session) ? PacketSignal.HANDLED : PacketSignal.UNHANDLED; + Registries.BEDROCK_PACKET_TRANSLATORS.translate(packet.getClass(), packet, session); + return PacketSignal.HANDLED; // PacketSignal.UNHANDLED will log a WARN publicly } @Override @@ -109,6 +110,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { } else if (BedrockDisconnectReasons.TIMEOUT.equals(reason)) { this.session.getUpstream().getSession().setDisconnectReason(GeyserLocale.getLocaleStringLog("geyser.network.disconnect.timed_out")); } + this.session.disconnect(this.session.getUpstream().getSession().getDisconnectReason()); } @Override @@ -128,6 +130,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { session.sendUpstreamPacketImmediately(responsePacket); session.getUpstream().getSession().setCompression(algorithm); + session.getUpstream().getSession().setCompressionLevel(this.geyser.getConfig().getBedrock().getCompressionLevel()); return PacketSignal.HANDLED; } @@ -139,6 +142,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { return PacketSignal.HANDLED; } +// session.getUpstream().getSession().getCodec() == null + if (!newProtocol) { if (!setCorrectCodec(loginPacket.getProtocolVersion())) { // REMOVE WHEN ONLY 1.19.30 IS SUPPORTED OR 1.20 return PacketSignal.HANDLED; diff --git a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java index f3a49400d..0acfeee93 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java @@ -27,9 +27,7 @@ package org.geysermc.geyser.registry; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundTabListPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLightUpdatePacket; -import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; import io.netty.channel.EventLoop; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.registry.loader.RegistryLoaders; import org.geysermc.geyser.session.GeyserSession; @@ -68,9 +66,10 @@ public class PacketTranslatorRegistry extends AbstractMappedRegistry 25 ? packet.getClass().getSimpleName() : packet)); + if (GeyserImpl.getInstance().getConfig().isDebugMode()) { + if (!IGNORED_PACKETS.contains(clazz)) { + GeyserImpl.getInstance().getLogger().debug("Could not find packet for " + (packet.toString().length() > 25 ? packet.getClass().getSimpleName() : packet)); + } } return false; 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 dce59352a..aec39cdd3 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 @@ -28,22 +28,13 @@ package org.geysermc.geyser.registry.populator; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.google.common.collect.ImmutableMap; -import org.cloudburstmc.nbt.NBTInputStream; -import org.cloudburstmc.nbt.NbtList; -import org.cloudburstmc.nbt.NbtMap; -import org.cloudburstmc.nbt.NbtMapBuilder; -import org.cloudburstmc.nbt.NbtType; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; -import it.unimi.dsi.fastutil.objects.Object2ObjectMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectIntPair; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.*; +import org.cloudburstmc.nbt.*; import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544; import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560; import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; -import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleBlockDefinition; import org.cloudburstmc.protocol.common.SimpleDefinitionRegistry; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.level.block.BlockStateValues; @@ -51,6 +42,7 @@ import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.registry.type.BlockMappings; +import org.geysermc.geyser.registry.type.GeyserBedrockBlock; import org.geysermc.geyser.util.BlockUtils; import java.io.DataInputStream; @@ -93,7 +85,7 @@ public final class BlockRegistryPopulator { } // New since 1.16.100 - find the block runtime ID by the order given to us in the block palette, // as we no longer send a block palette - Object2ObjectMap blockStateOrderedMap = new Object2ObjectOpenHashMap<>(blocksTag.size()); + Object2ObjectMap blockStateOrderedMap = new Object2ObjectOpenHashMap<>(blocksTag.size()); int stateVersion = -1; for (int i = 0; i < blocksTag.size(); i++) { @@ -103,14 +95,15 @@ public final class BlockRegistryPopulator { if (blockStateOrderedMap.containsKey(tag)) { throw new AssertionError("Duplicate block states in Bedrock palette: " + tag); } - blockStateOrderedMap.put(tag, new SimpleBlockDefinition(tag.getString("name"), i, tag)); + GeyserBedrockBlock block = new GeyserBedrockBlock(i, tag); + blockStateOrderedMap.put(tag, block); if (stateVersion == -1) { stateVersion = tag.getInt("version"); } } int javaRuntimeId = -1; - BlockDefinition airDefinition = null; + GeyserBedrockBlock airDefinition = null; BlockDefinition commandBlockDefinition = null; BlockDefinition waterDefinition = null; BlockDefinition movingBlockDefinition = null; @@ -118,7 +111,7 @@ public final class BlockRegistryPopulator { BiFunction stateMapper = blockMappers.getOrDefault(palette.getKey(), emptyMapper); - BlockDefinition[] javaToBedrockBlocks = new BlockDefinition[BLOCKS_JSON.size()]; + GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[BLOCKS_JSON.size()]; SimpleDefinitionRegistry.Builder registry = SimpleDefinitionRegistry.builder(); Map flowerPotBlocks = new Object2ObjectOpenHashMap<>(); @@ -132,7 +125,7 @@ public final class BlockRegistryPopulator { Map.Entry entry = blocksIterator.next(); String javaId = entry.getKey(); - BlockDefinition bedrockDefinition = blockStateOrderedMap.get(buildBedrockState(entry.getValue(), stateVersion, stateMapper)); + GeyserBedrockBlock bedrockDefinition = blockStateOrderedMap.get(buildBedrockState(entry.getValue(), stateVersion, stateMapper)); if (bedrockDefinition == null) { throw new RuntimeException("Unable to find " + javaId + " Bedrock BlockDefinition! Built NBT tag: \n" + buildBedrockState(entry.getValue(), stateVersion, stateMapper)); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java index f40e66c47..57ea15030 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/CreativeItemRegistryPopulator.java @@ -34,7 +34,6 @@ import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.BlockMappings; -import org.geysermc.geyser.registry.type.ItemMappings; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -80,7 +79,7 @@ public class CreativeItemRegistryPopulator { private static ItemData.Builder createItemData(JsonNode itemNode, BlockMappings blockMappings, Map definitions) { int count = 1; int damage = 0; - int blockRuntimeId = 0; + int bedrockBlockRuntimeId = 0; NbtMap tag = null; JsonNode damageNode = itemNode.get("damage"); if (damageNode != null) { @@ -94,7 +93,7 @@ public class CreativeItemRegistryPopulator { JsonNode blockRuntimeIdNode = itemNode.get("blockRuntimeId"); if (blockRuntimeIdNode != null) { - blockRuntimeId = blockRuntimeIdNode.asInt(); + bedrockBlockRuntimeId = blockRuntimeIdNode.asInt(); } JsonNode nbtNode = itemNode.get("nbt_b64"); @@ -126,6 +125,6 @@ public class CreativeItemRegistryPopulator { .damage(damage) .count(count) .tag(tag) - .blockDefinition(blockMappings.getBedrockBlock(blockRuntimeId)); + .blockDefinition(blockMappings.getDefinitionRegistry().getDefinition(bedrockBlockRuntimeId)); } } 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 33e6eea38..8fe8723f3 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 @@ -29,6 +29,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.google.common.collect.Multimap; import com.google.common.collect.MultimapBuilder; import it.unimi.dsi.fastutil.Pair; +import it.unimi.dsi.fastutil.objects.*; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; @@ -37,15 +38,10 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544; import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; +import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; @@ -141,7 +137,7 @@ public class ItemRegistryPopulator { registry.add(definition); } - Object2IntMap bedrockBlockIdOverrides = new Object2IntOpenHashMap<>(); + Object2ObjectMap bedrockBlockIdOverrides = new Object2ObjectOpenHashMap<>(); Object2IntMap blacklistedIdentifiers = new Object2IntOpenHashMap<>(); List boats = new ObjectArrayList<>(); @@ -157,7 +153,7 @@ public class ItemRegistryPopulator { AtomicInteger creativeNetId = new AtomicInteger(); CreativeItemRegistryPopulator.populate(palette, definitions, itemBuilder -> { - ItemData item = itemBuilder.netId(creativeNetId.getAndIncrement()).build(); + ItemData item = itemBuilder.netId(creativeNetId.incrementAndGet()).build(); creativeItems.add(item); if (item.getBlockDefinition() != null) { @@ -166,12 +162,12 @@ public class ItemRegistryPopulator { // Add override for item mapping, unless it already exists... then we know multiple states can exist if (!blacklistedIdentifiers.containsKey(identifier)) { if (bedrockBlockIdOverrides.containsKey(identifier)) { - bedrockBlockIdOverrides.removeInt(identifier); + bedrockBlockIdOverrides.remove(identifier); // Save this as a blacklist, but also as knowledge of what the block state name should be blacklistedIdentifiers.put(identifier, item.getBlockDefinition().getRuntimeId()); } else { // Unless there's multiple possibilities for this one state, let this be - bedrockBlockIdOverrides.put(identifier, item.getBlockDefinition().getRuntimeId()); + bedrockBlockIdOverrides.put(identifier, item.getBlockDefinition()); } } } @@ -221,19 +217,19 @@ public class ItemRegistryPopulator { int stackSize = mappingItem.getStackSize(); - int bedrockBlockId = -1; + BlockDefinition bedrockBlock = null; Integer firstBlockRuntimeId = entry.getValue().getFirstBlockRuntimeId(); if (firstBlockRuntimeId != null) { - int blockIdOverride = bedrockBlockIdOverrides.getOrDefault(bedrockIdentifier, -1); - if (blockIdOverride != -1) { + BlockDefinition blockOverride = bedrockBlockIdOverrides.get(bedrockIdentifier); + if (blockOverride != null) { // Straight from BDS is our best chance of getting an item that doesn't run into issues - bedrockBlockId = blockIdOverride; + bedrockBlock = blockOverride; } else { // Try to get an example block runtime ID from the creative contents packet, for Bedrock identifier obtaining int aValidBedrockBlockId = blacklistedIdentifiers.getOrDefault(bedrockIdentifier, -1); if (aValidBedrockBlockId == -1) { // Fallback - bedrockBlockId = blockMappings.getBedrockBlockId(firstBlockRuntimeId); + bedrockBlock = blockMappings.getBedrockBlock(firstBlockRuntimeId); } else { // As of 1.16.220, every item requires a block runtime ID attached to it. // This is mostly for identifying different blocks with the same item ID - wool, slabs, some walls. @@ -247,8 +243,8 @@ public class ItemRegistryPopulator { // and the last, if relevant. We then iterate over all those values and get their Bedrock equivalents Integer lastBlockRuntimeId = entry.getValue().getLastBlockRuntimeId() == null ? firstBlockRuntimeId : entry.getValue().getLastBlockRuntimeId(); for (int i = firstBlockRuntimeId; i <= lastBlockRuntimeId; i++) { - int bedrockBlockRuntimeId = blockMappings.getBedrockBlockId(i); - NbtMap blockTag = blockMappings.getBedrockBlockPalette().get(bedrockBlockRuntimeId); + GeyserBedrockBlock bedrockBlockRuntimeId = blockMappings.getBedrockBlock(i); + NbtMap blockTag = bedrockBlockRuntimeId.getState(); String bedrockName = blockTag.getString("name"); if (!bedrockName.equals(correctBedrockIdentifier)) { continue; @@ -259,7 +255,7 @@ public class ItemRegistryPopulator { firstPass = false; if (states.size() == 0) { // No need to iterate and find all block states - this is the one, as there can't be any others - bedrockBlockId = bedrockBlockRuntimeId; + bedrockBlock = bedrockBlockRuntimeId; break; } requiredBlockStatesBuilder.putAll(states); @@ -282,7 +278,7 @@ public class ItemRegistryPopulator { } NbtMap requiredBlockStates = requiredBlockStatesBuilder.build(); - if (bedrockBlockId == -1) { + if (bedrockBlock == null) { int i = -1; // We need to loop around again (we can't cache the block tags above) because Bedrock can include states that we don't have a pairing for // in it's "preferred" block state - I.E. the first matching block state in the list @@ -299,12 +295,12 @@ public class ItemRegistryPopulator { } } if (valid) { - bedrockBlockId = i; + bedrockBlock = blockMappings.getDefinitionRegistry().getDefinition(i); break; } } } - if (bedrockBlockId == -1) { + if (bedrockBlock == null) { throw new RuntimeException("Could not find a block match for " + entry.getKey()); } } @@ -328,7 +324,7 @@ public class ItemRegistryPopulator { } } if (valid) { - creativeItems.set(j, itemData.toBuilder().blockDefinition(blockMappings.getBedrockBlock(bedrockBlockId)).build()); + creativeItems.set(j, itemData.toBuilder().blockDefinition(bedrockBlock).build()); break; } } @@ -343,7 +339,7 @@ public class ItemRegistryPopulator { .bedrockIdentifier(bedrockIdentifier.intern()) .bedrockDefinition(definition) .bedrockData(mappingItem.getBedrockData()) - .bedrockBlockDefinition(blockMappings.getBedrockBlock(bedrockBlockId)) + .bedrockBlockDefinition(bedrockBlock) .stackSize(stackSize) .maxDamage(mappingItem.getMaxDamage()) .hasSuspiciousStewEffect(mappingItem.isHasSuspiciousStewEffect()); @@ -364,7 +360,7 @@ public class ItemRegistryPopulator { if (javaOnlyItems.contains(javaIdentifier)) { // These items don't exist on Bedrock, so set up a variable that indicates they should have custom names - mappingBuilder = mappingBuilder.translationString((bedrockBlockId != -1 ? "block." : "item.") + entry.getKey().replace(":", ".")); + mappingBuilder = mappingBuilder.translationString((bedrockBlock != null ? "block." : "item.") + entry.getKey().replace(":", ".")); GeyserImpl.getInstance().getLogger().debug("Adding " + entry.getKey() + " as an item that needs to be translated."); } diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java index ed9463a4e..a565e7309 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/BlockMappings.java @@ -30,7 +30,6 @@ import lombok.Value; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; -import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleBlockDefinition; import org.cloudburstmc.protocol.common.DefinitionRegistry; import java.util.Map; @@ -39,13 +38,13 @@ import java.util.Set; @Builder @Value public class BlockMappings { - BlockDefinition bedrockAir; + GeyserBedrockBlock bedrockAir; BlockDefinition bedrockWater; BlockDefinition bedrockMovingBlock; int blockStateVersion; - BlockDefinition[] javaToBedrockBlocks; + GeyserBedrockBlock[] javaToBedrockBlocks; DefinitionRegistry definitionRegistry; NbtList bedrockBlockPalette; @@ -57,18 +56,15 @@ public class BlockMappings { Set jigsawStates; - public int getBedrockBlockId(int state) { - if (state < 0 || state >= this.javaToBedrockBlocks.length) { - return bedrockAir.getRuntimeId(); - } - return this.javaToBedrockBlocks[state].getRuntimeId(); + public int getBedrockBlockId(int javaState) { + return getBedrockBlock(javaState).getRuntimeId(); } - public BlockDefinition getBedrockBlock(int state) { - if (state < 0 || state >= this.javaToBedrockBlocks.length) { + public GeyserBedrockBlock getBedrockBlock(int javaState) { + if (javaState < 0 || javaState >= this.javaToBedrockBlocks.length) { return bedrockAir; } - return this.javaToBedrockBlocks[state]; + return this.javaToBedrockBlocks[javaState]; } public BlockDefinition getItemFrame(NbtMap tag) { @@ -76,7 +72,7 @@ public class BlockMappings { } public boolean isItemFrame(BlockDefinition definition) { - if (definition instanceof SimpleBlockDefinition def) { + if (definition instanceof GeyserBedrockBlock def) { return this.itemFrames.containsKey(def.getState()); } diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/GeyserBedrockBlock.java b/core/src/main/java/org/geysermc/geyser/registry/type/GeyserBedrockBlock.java new file mode 100644 index 000000000..2fefc539b --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/registry/type/GeyserBedrockBlock.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019-2022 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.type; + +import org.cloudburstmc.nbt.NbtMap; +import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; + +public class GeyserBedrockBlock implements BlockDefinition { + private final int runtimeId; + private final NbtMap state; + + public GeyserBedrockBlock(int runtimeId, NbtMap state) { + this.runtimeId = runtimeId; + this.state = state; + } + + @Override + public int getRuntimeId() { + return runtimeId; + } + + public NbtMap getState() { + return state; + } + + @Override + public String toString() { + return "GeyserBedrockBlock{" + state.getString("name") + "}"; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 41068b76d..229649ded 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -89,19 +89,11 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.protocol.bedrock.BedrockServerSession; -import org.cloudburstmc.protocol.bedrock.data.Ability; -import org.cloudburstmc.protocol.bedrock.data.AbilityLayer; -import org.cloudburstmc.protocol.bedrock.data.AttributeData; -import org.cloudburstmc.protocol.bedrock.data.AuthoritativeMovementMode; -import org.cloudburstmc.protocol.bedrock.data.ChatRestrictionLevel; -import org.cloudburstmc.protocol.bedrock.data.GamePublishSetting; -import org.cloudburstmc.protocol.bedrock.data.GameRuleData; -import org.cloudburstmc.protocol.bedrock.data.GameType; -import org.cloudburstmc.protocol.bedrock.data.PlayerPermission; -import org.cloudburstmc.protocol.bedrock.data.SoundEvent; +import org.cloudburstmc.protocol.bedrock.data.*; import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.*; +import org.cloudburstmc.protocol.common.util.OptionalBoolean; import org.geysermc.api.util.BedrockPlatform; import org.geysermc.api.util.InputMode; import org.geysermc.api.util.UiProfile; @@ -879,14 +871,13 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { downstream = new LocalSession(this.remoteServer.address(), this.remoteServer.port(), geyser.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress(), this.protocol, this.protocol.createHelper()); + this.downstream = new DownstreamSession(downstream); } else { downstream = new TcpClientSession(this.remoteServer.address(), this.remoteServer.port(), this.protocol); + this.downstream = new DownstreamSession(downstream); disableSrvResolving(); } - // Wrap in DownstreamSession - this.downstream = new DownstreamSession(downstream); - if (geyser.getConfig().getRemote().isUseProxyProtocol()) { downstream.setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true); downstream.setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress()); @@ -1473,6 +1464,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { startGamePacket.setUsingMsaGamertagsOnly(false); startGamePacket.setFromWorldTemplate(false); startGamePacket.setWorldTemplateOptionLocked(false); + startGamePacket.setSpawnBiomeType(SpawnBiomeType.DEFAULT); + startGamePacket.setCustomBiomeName(""); + startGamePacket.setEducationProductionId(""); + startGamePacket.setForceExperimentalGameplay(OptionalBoolean.empty()); String serverName = geyser.getConfig().getBedrock().serverName(); startGamePacket.setLevelId(serverName); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java index 0b079fffd..b69e00ad7 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/item/ItemTranslator.java @@ -147,6 +147,16 @@ public abstract class ItemTranslator { return itemStack; } + @Nonnull + public static ItemData.Builder translateToBedrock(GeyserSession session, int javaId, int count, CompoundTag tag) { + ItemMapping bedrockItem = session.getItemMappings().getMapping(javaId); + if (bedrockItem == ItemMapping.AIR) { + session.getGeyser().getLogger().debug("ItemMapping returned air: " + javaId); + return ItemData.builder(); + } + return translateToBedrock(session, bedrockItem, count, tag); + } + @Nonnull public static ItemData translateToBedrock(GeyserSession session, ItemStack stack) { if (stack == null) { @@ -154,38 +164,43 @@ public abstract class ItemTranslator { } ItemMapping bedrockItem = session.getItemMappings().getMapping(stack); - if (bedrockItem == null) { - session.getGeyser().getLogger().debug("No matching ItemMapping for " + stack); + if (bedrockItem == ItemMapping.AIR) { + session.getGeyser().getLogger().debug("ItemMapping returned air: " + stack); return ItemData.AIR; } + return translateToBedrock(session, bedrockItem, stack.getAmount(), stack.getNbt()) + .build(); + } - CompoundTag nbt = stack.getNbt() != null ? stack.getNbt().clone() : null; + @Nonnull + private static ItemData.Builder translateToBedrock(GeyserSession session, ItemMapping mapping, int count, CompoundTag tag) { + CompoundTag nbt = tag != null ? tag.clone() : null; // This is a fallback for maps with no nbt - if (nbt == null && bedrockItem.getJavaIdentifier().equals("minecraft:filled_map")) { + if (nbt == null && mapping.getJavaIdentifier().equals("minecraft:filled_map")) { nbt = new CompoundTag(""); nbt.put(new IntTag("map", 0)); } if (nbt != null) { for (NbtItemStackTranslator translator : NBT_TRANSLATORS) { - if (translator.acceptItem(bedrockItem)) { - translator.translateToBedrock(session, nbt, bedrockItem); + if (translator.acceptItem(mapping)) { + translator.translateToBedrock(session, nbt, mapping); } } } - nbt = translateDisplayProperties(session, nbt, bedrockItem); + nbt = translateDisplayProperties(session, nbt, mapping); if (session.isAdvancedTooltips()) { - nbt = addAdvancedTooltips(nbt, bedrockItem, session.locale()); + nbt = addAdvancedTooltips(nbt, mapping, session.locale()); } - ItemStack itemStack = new ItemStack(stack.getId(), stack.getAmount(), nbt); + ItemStack itemStack = new ItemStack(mapping.getJavaId(), count, nbt); - ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.getOrDefault(bedrockItem.getJavaId(), DEFAULT_TRANSLATOR); - ItemData.Builder builder = itemStackTranslator.translateToBedrock(itemStack, bedrockItem, session.getItemMappings()); - if (bedrockItem.isBlock()) { - builder.blockDefinition(bedrockItem.getBedrockBlockDefinition()); + ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.getOrDefault(mapping.getJavaId(), DEFAULT_TRANSLATOR); + ItemData.Builder builder = itemStackTranslator.translateToBedrock(itemStack, mapping, session.getItemMappings()); + if (mapping.isBlock()) { + builder.blockDefinition(mapping.getBedrockBlockDefinition()); } if (nbt != null) { @@ -202,7 +217,7 @@ public abstract class ItemTranslator { } } - return builder.build(); + return builder; } private static CompoundTag addAdvancedTooltips(CompoundTag nbt, ItemMapping mapping, String language) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java index 08f40429b..e284bbbea 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCommandsTranslator.java @@ -109,7 +109,7 @@ public class JavaCommandsTranslator extends PacketTranslator entry : session.getItemFrameCache().entrySet()) { diff --git a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java index 8141675ff..894a19539 100644 --- a/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/ChunkUtils.java @@ -25,17 +25,17 @@ package org.geysermc.geyser.util; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; +import it.unimi.dsi.fastutil.ints.IntLists; +import lombok.experimental.UtilityClass; import org.cloudburstmc.math.vector.Vector2i; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.packet.LevelChunkPacket; import org.cloudburstmc.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; -import it.unimi.dsi.fastutil.ints.IntLists; -import lombok.experimental.UtilityClass; import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.level.JavaDimension; @@ -181,18 +181,18 @@ public class ChunkUtils { } byteBuf.writeByte(0); // Border blocks - Edu edition only + + LevelChunkPacket data = new LevelChunkPacket(); + data.setChunkX(chunkX); + data.setChunkZ(chunkZ); + data.setSubChunksLength(0); + data.setData(byteBuf.retain()); + data.setCachingEnabled(false); + session.sendUpstreamPacket(data); } finally { byteBuf.release(); } - LevelChunkPacket data = new LevelChunkPacket(); - data.setChunkX(chunkX); - data.setChunkZ(chunkZ); - data.setSubChunksLength(0); - data.setData(byteBuf); - data.setCachingEnabled(false); - session.sendUpstreamPacket(data); - if (forceUpdate) { Vector3i pos = Vector3i.from(chunkX << 4, 80, chunkZ << 4); UpdateBlockPacket blockPacket = new UpdateBlockPacket(); diff --git a/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java b/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java index ec37ca6bd..0504b6321 100644 --- a/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/LoginEncryptionUtils.java @@ -54,7 +54,6 @@ import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; import javax.crypto.SecretKey; -import java.io.IOException; import java.net.URI; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -192,12 +191,13 @@ public class LoginEncryptionUtils { KeyPair serverKeyPair = generator.generateKeyPair(); byte[] token = EncryptionUtils.generateRandomToken(); - SecretKey encryptionKey = EncryptionUtils.getSecretKey(serverKeyPair.getPrivate(), key, token); - session.getUpstream().getSession().enableEncryption(encryptionKey); ServerToClientHandshakePacket packet = new ServerToClientHandshakePacket(); packet.setJwt(EncryptionUtils.createHandshakeJwt(serverKeyPair, token).serialize()); session.sendUpstreamPacketImmediately(packet); + + SecretKey encryptionKey = EncryptionUtils.getSecretKey(serverKeyPair.getPrivate(), key, token); + session.getUpstream().getSession().enableEncryption(encryptionKey); } private static void sendEncryptionFailedMessage(GeyserImpl geyser) {