diff --git a/core/src/main/java/org/geysermc/geyser/item/Items.java b/core/src/main/java/org/geysermc/geyser/item/Items.java index 302fdf99c..f123583f3 100644 --- a/core/src/main/java/org/geysermc/geyser/item/Items.java +++ b/core/src/main/java/org/geysermc/geyser/item/Items.java @@ -45,6 +45,7 @@ import org.geysermc.geyser.item.type.FireworkStarItem; import org.geysermc.geyser.item.type.FishingRodItem; import org.geysermc.geyser.item.type.GoatHornItem; import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.item.type.LightItem; import org.geysermc.geyser.item.type.MaceItem; import org.geysermc.geyser.item.type.MapItem; import org.geysermc.geyser.item.type.PlayerHeadItem; @@ -526,7 +527,7 @@ public final class Items { public static final Item RED_TERRACOTTA = register(new BlockItem(builder(), Blocks.RED_TERRACOTTA)); public static final Item BLACK_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLACK_TERRACOTTA)); public static final Item BARRIER = register(new BlockItem(builder(), Blocks.BARRIER)); - public static final Item LIGHT = register(new BlockItem(builder(), Blocks.LIGHT)); + public static final Item LIGHT = register(new LightItem(builder(), Blocks.LIGHT)); public static final Item HAY_BLOCK = register(new BlockItem(builder(), Blocks.HAY_BLOCK)); public static final Item WHITE_CARPET = register(new BlockItem(builder(), Blocks.WHITE_CARPET)); public static final Item ORANGE_CARPET = register(new BlockItem(builder(), Blocks.ORANGE_CARPET)); diff --git a/core/src/main/java/org/geysermc/geyser/item/type/LightItem.java b/core/src/main/java/org/geysermc/geyser/item/type/LightItem.java new file mode 100644 index 000000000..fa10b08b1 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/item/type/LightItem.java @@ -0,0 +1,79 @@ +/* + * 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.item.type; + +import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; +import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; +import org.geysermc.geyser.level.block.property.Properties; +import org.geysermc.geyser.level.block.type.Block; +import org.geysermc.geyser.registry.type.ItemMapping; +import org.geysermc.geyser.registry.type.ItemMappings; +import org.geysermc.geyser.session.GeyserSession; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.BlockStateProperties; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; + +public class LightItem extends BlockItem { + + public LightItem(Builder builder, Block block, Block... otherBlocks) { + super(builder, block, otherBlocks); + } + + @Override + public ItemData.Builder translateToBedrock(GeyserSession session, int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { + ItemMapping lightLevelMapping = getLightLevelMapping(components, mappings); + if (lightLevelMapping != null) { + return super.translateToBedrock(session, count, components, lightLevelMapping, mappings); + } + return super.translateToBedrock(session, count, components, mapping, mappings); + } + + @Override + public ItemMapping toBedrockDefinition(DataComponents components, ItemMappings mappings) { + ItemMapping lightLevelMapping = getLightLevelMapping(components, mappings); + if (lightLevelMapping != null) { + return lightLevelMapping; + } + return super.toBedrockDefinition(components, mappings); + } + + + private static ItemMapping getLightLevelMapping(DataComponents components, ItemMappings mappings) { + String lightLevel = "15"; + if (components != null) { + BlockStateProperties blockStateProperties = components.get(DataComponentType.BLOCK_STATE); + + if (blockStateProperties != null) { + lightLevel = blockStateProperties.getProperties().get(Properties.LEVEL.name()); + } + } + ItemDefinition definition = mappings.getDefinition("minecraft:light_block_" + lightLevel); + if (definition != null) { + return mappings.getLightBlocks().get(definition.getRuntimeId()); + } + return null; + } +} 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 18a34f088..1da3b0e66 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 @@ -70,6 +70,7 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.components.Rarity; import org.geysermc.geyser.item.type.BlockItem; import org.geysermc.geyser.item.type.Item; +import org.geysermc.geyser.level.block.property.Properties; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.BlockMappings; @@ -508,6 +509,26 @@ public class ItemRegistryPopulator { javaItemToMapping.put(javaItem, mapping); } + // Add the light block level since it doesn't exist on java but we need it for item conversion + Int2ObjectMap lightBlocks = new Int2ObjectOpenHashMap<>(); + + for (int i = 0; i <= Properties.LEVEL.high(); i++) { + ItemDefinition lightBlock = definitions.get("minecraft:light_block_" + i); + if (lightBlock == null) { + break; + } + + ItemMapping lightBlockEntry = ItemMapping.builder() + .javaItem(Items.LIGHT) + .bedrockIdentifier("minecraft:light_block_" + i) + .bedrockDefinition(lightBlock) + .bedrockData(0) + .bedrockBlockDefinition(null) + .customItemOptions(Collections.emptyList()) + .build(); + lightBlocks.put(lightBlock.getRuntimeId(), lightBlockEntry); + } + ItemDefinition lodestoneCompass = definitions.get("minecraft:lodestone_compass"); if (lodestoneCompass == null) { throw new RuntimeException("Lodestone compass not found in item palette!"); @@ -641,6 +662,7 @@ public class ItemRegistryPopulator { .javaOnlyItems(javaOnlyItems) .buckets(buckets) .componentItemData(componentItemData) + .lightBlocks(lightBlocks) .lodestoneCompass(lodestoneEntry) .customIdMappings(customIdMappings) .customBlockItemDefinitions(customBlockItemDefinitions) diff --git a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java index 189474238..8aae05fdc 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java +++ b/core/src/main/java/org/geysermc/geyser/registry/type/ItemMappings.java @@ -59,6 +59,7 @@ public class ItemMappings implements DefinitionRegistry { * A unique exception as this is an item in Bedrock, but not in Java. */ ItemMapping lodestoneCompass; + Int2ObjectMap lightBlocks; ItemData[] creativeItems; Int2ObjectMap itemDefinitions; @@ -136,6 +137,11 @@ public class ItemMappings implements DefinitionRegistry { return lodestoneCompass; } + ItemMapping lightBlock = lightBlocks.get(definition.getRuntimeId()); + if (lightBlock != null) { + return lightBlock; + } + boolean isBlock = data.getBlockDefinition() != null; boolean hasDamage = data.getDamage() != 0;