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 b61d0e389..4781110f7 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 @@ -100,10 +100,11 @@ public class BlockRegistryPopulator { GeyserImpl.getInstance().getLogger().debug("Registered " + customBlocks.size() + " custom blocks."); } - private static void generateCustomBlockStates(List blockStates, List customExtBlockStates, CustomBlockData customBlock, int stateVersion) { + private static void generateCustomBlockStates(CustomBlockData customBlock, List blockStates, List customExtBlockStates, int stateVersion) { + String name = CUSTOM_PREFIX + customBlock.name(); if (customBlock.properties().isEmpty()) { blockStates.add(NbtMap.builder() - .putString("name", CUSTOM_PREFIX + customBlock.name()) + .putString("name", name) .putInt("version", stateVersion) .putCompound("states", NbtMap.EMPTY) .build()); @@ -121,7 +122,6 @@ public class BlockRegistryPopulator { statesBuilder.put(property.name(), property.values().get(permIndex % property.values().size())); permIndex /= property.values().size(); } - String name = CUSTOM_PREFIX + customBlock.name(); NbtMap states = statesBuilder.build(); blockStates.add(NbtMap.builder() @@ -171,17 +171,6 @@ public class BlockRegistryPopulator { return new BlockPropertyData(CUSTOM_PREFIX + customBlock.name(), propertyTag); } - private static final long FNV1_64_OFFSET_BASIS = 0xcbf29ce484222325L; - private static final long FNV1_64_PRIME = 1099511628211L; - - private static long fnv164(String str) { - long hash = FNV1_64_OFFSET_BASIS; - for (byte b : str.getBytes(StandardCharsets.UTF_8)) { - hash *= FNV1_64_PRIME; - hash ^= b; - } - return hash; - } private static void registerBedrockBlocks() { for (Map.Entry, BiFunction> palette : BLOCK_MAPPERS.entrySet()) { NbtList blocksTag; @@ -203,19 +192,13 @@ public class BlockRegistryPopulator { if (BlockRegistries.CUSTOM_BLOCKS.get().length != 0) { for (CustomBlockData customBlock : BlockRegistries.CUSTOM_BLOCKS.get()) { customBlockProperties.add(generateBlockPropertyData(customBlock)); - generateCustomBlockStates(customBlockStates, customExtBlockStates, customBlock, stateVersion); + generateCustomBlockStates(customBlock, customBlockStates, customExtBlockStates, stateVersion); } blockStates.addAll(customBlockStates); GeyserImpl.getInstance().getLogger().debug("Added " + customBlockStates.size() + " custom block states to v" + palette.getKey().valueInt() + " palette."); - if (palette.getKey().valueInt() > 486) { - // Version 1.18.30 and above sort the palette by the FNV1 64 bit hash of the name - blockStates.sort((a, b) -> Long.compareUnsigned(fnv164(a.getString("name")), fnv164(b.getString("name")))); - } else { - // Version below 1.18.30 sort the palette alphabetically by name - blockStates.sort(Comparator.comparing(state -> state.getString("name"))); - } - + // The palette is sorted by the FNV1 64-bit hash of the name + blockStates.sort((a, b) -> Long.compareUnsigned(fnv164(a.getString("name")), fnv164(b.getString("name")))); } // New since 1.16.100 - find the block runtime ID by the order given to us in the block palette, @@ -602,4 +585,16 @@ public class BlockRegistryPopulator { tagBuilder.put("states", statesBuilder.build()); return tagBuilder.build(); } + + private static final long FNV1_64_OFFSET_BASIS = 0xcbf29ce484222325L; + private static final long FNV1_64_PRIME = 1099511628211L; + + private static long fnv164(String str) { + long hash = FNV1_64_OFFSET_BASIS; + for (byte b : str.getBytes(StandardCharsets.UTF_8)) { + hash *= FNV1_64_PRIME; + hash ^= b; + } + return hash; + } } 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 bcfe9b8ee..150f1b6bd 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 @@ -646,6 +646,7 @@ public class ItemRegistryPopulator { entries.put(identifier, new StartGamePacket.ItemEntry(identifier, (short) customProtocolId)); customBlockItemIds.put(customBlock, customProtocolId); + customIdMappings.put(customProtocolId, identifier); } } 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 af5e9658f..995408318 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 @@ -53,7 +53,6 @@ import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.util.FileUtils; import javax.annotation.Nonnull; -import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.stream.Collectors; @@ -180,7 +179,7 @@ public abstract class ItemTranslator { translateCustomItem(nbt, builder, bedrockItem); if (bedrockItem == session.getItemMappings().getStoredItems().playerHead()) { - translatePlayerHead(session, nbt, builder, bedrockItem); + translatePlayerHead(session, nbt, builder); } if (nbt != null) { @@ -551,39 +550,19 @@ public abstract class ItemTranslator { } } - private static void translatePlayerHead(GeyserSession session, CompoundTag nbt, ItemData.Builder builder, ItemMapping mapping) { + private static void translatePlayerHead(GeyserSession session, CompoundTag nbt, ItemData.Builder builder) { if (nbt != null && nbt.contains("SkullOwner")) { - String skinHash = null; - Tag skullOwner = nbt.get("SkullOwner"); - if (skullOwner instanceof StringTag) { + if (!(nbt.get("SkullOwner") instanceof CompoundTag skullOwner)) { // It's a username give up d: return; - } else if (skullOwner instanceof CompoundTag) { - Tag properties = ((CompoundTag) skullOwner).get("Properties"); - if (properties instanceof CompoundTag) { - Tag textures = ((CompoundTag) properties).get("textures"); - if (textures instanceof ListTag) { - List textureTags = ((ListTag) textures).getValue(); - if (!textureTags.isEmpty()) { - Tag skinTag = textureTags.get(0); - if (skinTag instanceof CompoundTag) { - Tag valueTag = ((CompoundTag) skinTag).get("Value"); - String encodedJson = (String) valueTag.getValue(); - try { - SkinManager.GameProfileData data = SkinManager.GameProfileData.loadFromJson(encodedJson); - skinHash = data.skinUrl().substring(data.skinUrl().lastIndexOf('/') + 1); - } catch (IOException e) { - session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + nbt + " " + e.getMessage()); - return; - } - } - } - } - } } - if (skinHash == null) { + SkinManager.GameProfileData data = SkinManager.GameProfileData.from(skullOwner); + if (data == null) { session.getGeyser().getLogger().debug("Not sure how to handle skull head item display. " + nbt); + return; } + + String skinHash = data.skinUrl().substring(data.skinUrl().lastIndexOf('/') + 1); GeyserConvertSkullInventoryEvent skullInventoryEvent = new GeyserConvertSkullInventoryEvent(skinHash); GeyserImpl.getInstance().getEventBus().fire(skullInventoryEvent); diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java index 07c1552a2..6c03a737c 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/SkullBlockEntityTranslator.java @@ -74,10 +74,9 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements return CompletableFuture.completedFuture(null); } - public static int translateSkull(GeyserSession session, CompoundTag tag, int posX, int posY, int posZ, int blockState) { + public static int translateSkull(GeyserSession session, CompoundTag tag, Vector3i blockPosition, int blockState) { try { String texturesProperty = getTextures(tag).get(); - Vector3i blockPosition = Vector3i.from(posX, posY, posZ); if (texturesProperty == null) { session.getGeyser().getLogger().debug("Custom skull with invalid SkullOwner tag: " + blockPosition + " " + tag); return -1; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java index 5feefa681..0f3912066 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java @@ -53,6 +53,7 @@ import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.geyser.session.cache.SkullCache; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.util.BlockUtils; @@ -507,9 +508,10 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator> 4) - (bedrockDimension.minY() >> 4); GeyserChunkSection bedrockSection = sections[bedrockSectionY];