Load default item components

This commit is contained in:
onebeastchris 2024-12-04 00:01:54 +08:00
parent 84faeba4b2
commit be77e6b2bf
5 changed files with 101 additions and 15 deletions

View file

@ -66,11 +66,6 @@ import static org.geysermc.geyser.item.type.Item.builder;
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Items { public final class Items {
static {
// Load data components here
}
public static final Item AIR = register(new Item("air", builder())); public static final Item AIR = register(new Item("air", builder()));
public static final Item STONE = register(new BlockItem(builder(), Blocks.STONE)); public static final Item STONE = register(new BlockItem(builder(), Blocks.STONE));
public static final Item GRANITE = register(new BlockItem(builder(), Blocks.GRANITE)); public static final Item GRANITE = register(new BlockItem(builder(), Blocks.GRANITE));

View file

@ -40,6 +40,7 @@ import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.components.Rarity; import org.geysermc.geyser.item.components.Rarity;
import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -65,12 +66,9 @@ public class Item {
private final int attackDamage; private final int attackDamage;
private final DataComponents baseComponents; // unmodifiable private final DataComponents baseComponents; // unmodifiable
private final List<Item> enchantmentGlintPresent = List.of(Items.ENCHANTED_GOLDEN_APPLE, Items.EXPERIENCE_BOTTLE, Items.WRITTEN_BOOK,
Items.NETHER_STAR, Items.ENCHANTED_BOOK, Items.END_CRYSTAL);
public Item(String javaIdentifier, Builder builder) { public Item(String javaIdentifier, Builder builder) {
this.javaIdentifier = MinecraftKey.key(javaIdentifier); this.javaIdentifier = MinecraftKey.key(javaIdentifier);
this.baseComponents = builder.components; this.baseComponents = builder.components == null ? Registries.DEFAULT_DATA_COMPONENTS.get(javaId) : builder.components;
this.attackDamage = builder.attackDamage; this.attackDamage = builder.attackDamage;
} }
@ -297,7 +295,7 @@ public class Item {
} }
public static Builder builder() { public static Builder builder() {
return new Builder().components(new DataComponents(ImmutableMap.of())); // TODO actually set components here return new Builder();
} }
public static final class Builder { public static final class Builder {
@ -315,10 +313,6 @@ public class Item {
return this; return this;
} }
public DataComponents components() {
return new DataComponents(ImmutableMap.copyOf(components.getDataComponents()));
}
private Builder() { private Builder() {
} }
} }

View file

@ -47,6 +47,7 @@ import org.geysermc.geyser.registry.loader.RegistryLoaders;
import org.geysermc.geyser.registry.loader.SoundEventsRegistryLoader; import org.geysermc.geyser.registry.loader.SoundEventsRegistryLoader;
import org.geysermc.geyser.registry.loader.SoundRegistryLoader; import org.geysermc.geyser.registry.loader.SoundRegistryLoader;
import org.geysermc.geyser.registry.loader.SoundTranslatorRegistryLoader; import org.geysermc.geyser.registry.loader.SoundTranslatorRegistryLoader;
import org.geysermc.geyser.registry.populator.DataComponentRegistryPopulator;
import org.geysermc.geyser.registry.populator.ItemRegistryPopulator; import org.geysermc.geyser.registry.populator.ItemRegistryPopulator;
import org.geysermc.geyser.registry.populator.PacketRegistryPopulator; import org.geysermc.geyser.registry.populator.PacketRegistryPopulator;
import org.geysermc.geyser.registry.populator.TagRegistryPopulator; import org.geysermc.geyser.registry.populator.TagRegistryPopulator;
@ -60,6 +61,7 @@ import org.geysermc.geyser.translator.sound.SoundInteractionTranslator;
import org.geysermc.geyser.translator.sound.SoundTranslator; import org.geysermc.geyser.translator.sound.SoundTranslator;
import org.geysermc.mcprotocollib.network.packet.Packet; import org.geysermc.mcprotocollib.network.packet.Packet;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent; import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent;
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType;
@ -139,6 +141,8 @@ public final class Registries {
*/ */
public static final SimpleMappedRegistry<String, Item> JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); public static final SimpleMappedRegistry<String, Item> JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
public static final ListRegistry<DataComponents> DEFAULT_DATA_COMPONENTS = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
/** /**
* A versioned registry which holds {@link ItemMappings} for each version. These item mappings contain * A versioned registry which holds {@link ItemMappings} for each version. These item mappings contain
* primarily Bedrock version-specific data. * primarily Bedrock version-specific data.
@ -209,6 +213,7 @@ public final class Registries {
public static void populate() { public static void populate() {
PacketRegistryPopulator.populate(); PacketRegistryPopulator.populate();
DataComponentRegistryPopulator.populate();
ItemRegistryPopulator.populate(); ItemRegistryPopulator.populate();
TagRegistryPopulator.populate(); TagRegistryPopulator.populate();

View file

@ -0,0 +1,89 @@
/*
* 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 com.google.common.collect.ImmutableMap;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponent;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemCodecHelper;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class DataComponentRegistryPopulator {
public static void populate() {
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
List<DataComponents> defaultComponents;
try (InputStream stream = bootstrap.getResourceOrThrow("mappings/item_data_components.json")) {
JsonElement rootElement = JsonParser.parseReader(new InputStreamReader(stream));
JsonArray jsonArray = rootElement.getAsJsonArray();
defaultComponents = new ObjectArrayList<>(jsonArray.size());
for (JsonElement element : jsonArray) {
JsonObject entryObject = element.getAsJsonObject();
JsonObject components = entryObject.getAsJsonObject("components");
Map<DataComponentType<?>, DataComponent<?, ?>> map = new HashMap<>();
for (Map.Entry<String, JsonElement> componentEntry : components.entrySet()) {
String encodedValue = componentEntry.getValue().getAsString();
byte[] bytes = Base64.getDecoder().decode(encodedValue);
ByteBuf buf = Unpooled.wrappedBuffer(bytes);
MinecraftCodecHelper helper = new MinecraftCodecHelper();
int varInt = helper.readVarInt(buf);
DataComponentType<?> dataComponentType = DataComponentType.from(varInt);
DataComponent<?, ?> dataComponent = dataComponentType.readDataComponent(ItemCodecHelper.INSTANCE, buf);
map.put(dataComponentType, dataComponent);
}
defaultComponents.add(new DataComponents(ImmutableMap.copyOf(map)));
}
} catch (Exception e) {
throw new AssertionError("Unable to load or parse components", e);
}
Registries.DEFAULT_DATA_COMPONENTS.set(defaultComponents);
}
}

View file

@ -102,6 +102,9 @@ public final class ItemTranslator {
SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.BODY, "body"); SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.BODY, "body");
} }
private final static List<Item> GLINT_PRESENT = List.of(Items.ENCHANTED_GOLDEN_APPLE, Items.EXPERIENCE_BOTTLE, Items.WRITTEN_BOOK,
Items.NETHER_STAR, Items.ENCHANTED_BOOK, Items.END_CRYSTAL);
private ItemTranslator() { private ItemTranslator() {
} }
@ -180,7 +183,7 @@ public final class ItemTranslator {
} }
// Add enchantment override. We can't remove it - enchantments would stop showing - but we can add it. // Add enchantment override. We can't remove it - enchantments would stop showing - but we can add it.
if (components.getOrDefault(DataComponentType.ENCHANTMENT_GLINT_OVERRIDE, false)) { if (components.getOrDefault(DataComponentType.ENCHANTMENT_GLINT_OVERRIDE, false) && !GLINT_PRESENT.contains(javaItem)) {
NbtMapBuilder nbtMapBuilder = nbtBuilder.getOrCreateNbt(); NbtMapBuilder nbtMapBuilder = nbtBuilder.getOrCreateNbt();
nbtMapBuilder.putIfAbsent("ench", NbtList.EMPTY); nbtMapBuilder.putIfAbsent("ench", NbtList.EMPTY);
} }