1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2026-01-04 15:31:36 +00:00

More component hashers, also need tests

This commit is contained in:
Eclipse
2025-03-26 11:39:52 +00:00
parent 037f8c542d
commit 63326e468c
6 changed files with 93 additions and 7 deletions

View File

@@ -45,6 +45,7 @@ public final class TrimRecipe {
public static final ItemDescriptorWithCount ADDITION = tagDescriptor("minecraft:trim_materials");
public static final ItemDescriptorWithCount TEMPLATE = tagDescriptor("minecraft:trim_templates");
// TODO this is WRONG. this changed. FIXME in 1.21.5
public static TrimMaterial readTrimMaterial(RegistryEntryContext context) {
String key = context.id().asMinimalString();
@@ -65,6 +66,7 @@ public final class TrimRecipe {
return new TrimMaterial(key, legacy.substring(2).trim(), itemMapping.getBedrockIdentifier());
}
// TODO this is WRONG. this changed. FIXME in 1.21.5
public static TrimPattern readTrimPattern(RegistryEntryContext context) {
String key = context.id().asMinimalString();

View File

@@ -49,6 +49,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.FoodProperti
import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.IntComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.LodestoneTracker;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.MobEffectDetails;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.MobEffectInstance;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents;
@@ -57,6 +58,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.TooltipDispl
import org.geysermc.mcprotocollib.protocol.data.game.item.component.Unit;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.UseCooldown;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.Weapon;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.WritableBookContent;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.WrittenBookContent;
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.BuiltinSound;
import java.util.HashMap;
@@ -164,15 +167,35 @@ public class DataComponentHashers {
register(DataComponentTypes.POTION_DURATION_SCALE, MinecraftHasher.FLOAT);
register(DataComponentTypes.SUSPICIOUS_STEW_EFFECTS, RegistryHasher.SUSPICIOUS_STEW_EFFECT.list());
// TODO writable book content
// TODO written book content
// TODO trim
registerMap(DataComponentTypes.WRITABLE_BOOK_CONTENT, builder -> builder
.optionalList("pages", MinecraftHasher.STRING.filterable(), WritableBookContent::getPages));
registerMap(DataComponentTypes.WRITTEN_BOOK_CONTENT, builder -> builder
.accept("title", MinecraftHasher.STRING.filterable(), WrittenBookContent::getTitle)
.accept("author", MinecraftHasher.STRING, WrittenBookContent::getAuthor)
.accept("generation", MinecraftHasher.INT, WrittenBookContent::getGeneration)
.optionalList("pages", ComponentHasher.COMPONENT.filterable(), WrittenBookContent::getPages)
.optional("resolved", MinecraftHasher.BOOL, WrittenBookContent::isResolved, false));
register(DataComponentTypes.TRIM, RegistryHasher.ARMOR_TRIM);
register(DataComponentTypes.DEBUG_STICK_STATE, MinecraftHasher.NBT_MAP);
register(DataComponentTypes.ENTITY_DATA, MinecraftHasher.NBT_MAP);
register(DataComponentTypes.BUCKET_ENTITY_DATA, MinecraftHasher.NBT_MAP);
register(DataComponentTypes.BLOCK_ENTITY_DATA, MinecraftHasher.NBT_MAP);
register(DataComponentTypes.INSTRUMENT, RegistryHasher.INSTRUMENT_COMPONENT);
register(DataComponentTypes.PROVIDES_TRIM_MATERIAL, RegistryHasher.PROVIDES_TRIM_MATERIAL);
registerInt(DataComponentTypes.OMINOUS_BOTTLE_AMPLIFIER);
register(DataComponentTypes.JUKEBOX_PLAYABLE, RegistryHasher.JUKEBOX_PLAYABLE);
register(DataComponentTypes.PROVIDES_BANNER_PATTERNS, MinecraftHasher.TAG);
register(DataComponentTypes.RECIPES, MinecraftHasher.NBT_LIST);
registerMap(DataComponentTypes.LODESTONE_TRACKER, builder -> builder
.optionalNullable("target", MinecraftHasher.GLOBAL_POS, LodestoneTracker::getPos)
.optional("tracked", MinecraftHasher.BOOL, LodestoneTracker::isTracked, true));
// TODO firework explosion, fireworks
}
private static void registerUnit(DataComponentType<Unit> component) {

View File

@@ -28,11 +28,15 @@ package org.geysermc.geyser.item.hashing;
import com.google.common.base.Suppliers;
import com.google.common.hash.HashCode;
import net.kyori.adventure.key.Key;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.geysermc.geyser.item.components.Rarity;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.GlobalPos;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.Consumable;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.Filterable;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.Unit;
import java.util.List;
@@ -71,6 +75,10 @@ public interface MinecraftHasher<T> {
MinecraftHasher<NbtMap> NBT_MAP = (map, encoder) -> encoder.nbtMap(map);
MinecraftHasher<NbtList<?>> NBT_LIST = (list, encoder) -> encoder.nbtList(list);
MinecraftHasher<Vector3i> POS = INT_ARRAY.convert(pos -> IntStream.of(pos.getX(), pos.getY(), pos.getZ()));
MinecraftHasher<Key> KEY = STRING.convert(Key::asString);
MinecraftHasher<Key> TAG = STRING.convert(key -> "#" + key.asString());
@@ -87,12 +95,22 @@ public interface MinecraftHasher<T> {
MinecraftHasher<EquipmentSlot> EQUIPMENT_SLOT = fromEnum(); // FIXME MCPL enum constants aren't right
MinecraftHasher<GlobalPos> GLOBAL_POS = mapBuilder(builder -> builder
.accept("dimension", KEY, GlobalPos::getDimension)
.accept("pos", POS, GlobalPos::getPosition));
HashCode hash(T value, MinecraftHashEncoder encoder);
default MinecraftHasher<List<T>> list() {
return (list, encoder) -> encoder.list(list.stream().map(element -> hash(element, encoder)).toList());
}
default MinecraftHasher<Filterable<T>> filterable() {
return mapBuilder(builder -> builder
.accept("raw", this, Filterable::getRaw)
.optionalNullable("filtered", this, Filterable::getOptional));
}
default <D> MinecraftHasher<D> dispatch(String typeKey, Function<D, T> typeExtractor, Function<T, MapBuilder<D>> hashDispatch) {
return mapBuilder(builder -> builder
.accept(typeKey, this, typeExtractor)

View File

@@ -25,6 +25,7 @@
package org.geysermc.geyser.item.hashing;
import net.kyori.adventure.key.Key;
import org.geysermc.geyser.inventory.item.Potion;
import org.geysermc.geyser.session.cache.registry.JavaRegistries;
import org.geysermc.geyser.session.cache.registry.JavaRegistryKey;
@@ -33,12 +34,15 @@ import org.geysermc.mcprotocollib.protocol.data.game.Holder;
import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ArmorTrim;
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.HolderSet;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.InstrumentComponent;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.JukeboxPlayable;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.MobEffectInstance;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ProvidesTrimMaterial;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.SuspiciousStewEffect;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ToolData;
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.BuiltinSound;
@@ -46,6 +50,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.sound.CustomSound;
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.Sound;
import java.util.Arrays;
import java.util.Map;
public interface RegistryHasher extends MinecraftHasher<Integer> {
@@ -118,12 +123,44 @@ public interface RegistryHasher extends MinecraftHasher<Integer> {
.optionalNullable("speed", MinecraftHasher.FLOAT, ToolData.Rule::getSpeed)
.optionalNullable("correct_for_drops", MinecraftHasher.BOOL, ToolData.Rule::getCorrectForDrops));
MinecraftHasher<Map<Key, String>> TRIM_MATERIAL_ASSET_OVERRIDES = MinecraftHasher.map(KEY, STRING);
MinecraftHasher<ArmorTrim.TrimMaterial> DIRECT_TRIM_MATERIAL = MinecraftHasher.mapBuilder(builder -> builder
.accept("asset_name", MinecraftHasher.STRING, ArmorTrim.TrimMaterial::assetBase)
.optional("override_armor_assets", TRIM_MATERIAL_ASSET_OVERRIDES, ArmorTrim.TrimMaterial::assetOverrides, Map.of())
.accept("description", ComponentHasher.COMPONENT, ArmorTrim.TrimMaterial::description));
MinecraftHasher<Holder<ArmorTrim.TrimMaterial>> TRIM_MATERIAL = holder(JavaRegistries.TRIM_MATERIAL, DIRECT_TRIM_MATERIAL);
MinecraftHasher<ProvidesTrimMaterial> PROVIDES_TRIM_MATERIAL = MinecraftHasher.either(TRIM_MATERIAL, ProvidesTrimMaterial::materialHolder, KEY, ProvidesTrimMaterial::materialLocation);
MinecraftHasher<ArmorTrim.TrimPattern> DIRECT_TRIM_PATTERN = MinecraftHasher.mapBuilder(builder -> builder
.accept("asset_id", KEY, ArmorTrim.TrimPattern::assetId)
.accept("description", ComponentHasher.COMPONENT, ArmorTrim.TrimPattern::description)
.accept("decal", BOOL, ArmorTrim.TrimPattern::decal));
MinecraftHasher<Holder<ArmorTrim.TrimPattern>> TRIM_PATTERN = holder(JavaRegistries.TRIM_PATTERN, DIRECT_TRIM_PATTERN);
MinecraftHasher<ArmorTrim> ARMOR_TRIM = MinecraftHasher.mapBuilder(builder -> builder
.accept("material", TRIM_MATERIAL, ArmorTrim::material)
.accept("pattern", TRIM_PATTERN, ArmorTrim::pattern));
MinecraftHasher<JukeboxPlayable.JukeboxSong> DIRECT_JUKEBOX_SONG = MinecraftHasher.mapBuilder(builder -> builder
.accept("sound_event", SOUND_EVENT, JukeboxPlayable.JukeboxSong::soundEvent)
.accept("description", ComponentHasher.COMPONENT, JukeboxPlayable.JukeboxSong::description)
.accept("length_in_seconds", FLOAT, JukeboxPlayable.JukeboxSong::lengthInSeconds)
.accept("comparator_output", INT, JukeboxPlayable.JukeboxSong::comparatorOutput));
MinecraftHasher<Holder<JukeboxPlayable.JukeboxSong>> JUKEBOX_SONG = holder(JavaRegistries.JUKEBOX_SONG, DIRECT_JUKEBOX_SONG);
MinecraftHasher<JukeboxPlayable> JUKEBOX_PLAYABLE = MinecraftHasher.either(JUKEBOX_SONG, JukeboxPlayable::songHolder, KEY, JukeboxPlayable::songLocation);
static RegistryHasher registry(JavaRegistryKey<?> registry) {
MinecraftHasher<Integer> hasher = KEY.sessionConvert(registry::keyFromNetworkId);
return hasher::hash;
}
// We don't need the registry generic type, and this works easier for goat horn instruments
// We don't need the registry generic type, and this works easier for goat horn instruments and other registries
static <T> MinecraftHasher<Holder<T>> holder(JavaRegistryKey<?> registry, MinecraftHasher<T> direct) {
RegistryHasher registryHasher = registry(registry);
return (value, encoder) -> {

View File

@@ -91,10 +91,10 @@ public final class RegistryCache {
register("dimension_type", cache -> cache.dimensions, JavaDimension::read);
register(JavaRegistries.ENCHANTMENT, cache -> cache.enchantments, Enchantment::read);
register(JavaRegistries.INSTRUMENT, cache -> cache.instruments, GeyserInstrument::read);
register("jukebox_song", cache -> cache.jukeboxSongs, JukeboxSong::read);
register(JavaRegistries.JUKEBOX_SONG, cache -> cache.jukeboxSongs, JukeboxSong::read);
register("painting_variant", cache -> cache.paintings, context -> PaintingType.getByName(context.id()));
register("trim_material", cache -> cache.trimMaterials, TrimRecipe::readTrimMaterial);
register("trim_pattern", cache -> cache.trimPatterns, TrimRecipe::readTrimPattern);
register(JavaRegistries.TRIM_MATERIAL, cache -> cache.trimMaterials, TrimRecipe::readTrimMaterial);
register(JavaRegistries.TRIM_PATTERN, cache -> cache.trimPatterns, TrimRecipe::readTrimPattern);
register("worldgen/biome", (cache, array) -> cache.biomeTranslations = array, BiomeTranslator::loadServerBiome);
register("banner_pattern", cache -> cache.bannerPatterns, context -> BannerPattern.getByJavaIdentifier(context.id()));

View File

@@ -27,6 +27,8 @@ package org.geysermc.geyser.session.cache.registry;
import net.kyori.adventure.key.Key;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.data.TrimMaterial;
import org.cloudburstmc.protocol.bedrock.data.TrimPattern;
import org.geysermc.geyser.entity.type.living.animal.FrogEntity;
import org.geysermc.geyser.entity.type.living.animal.farm.TemperatureVariantAnimal;
import org.geysermc.geyser.entity.type.living.animal.tameable.CatEntity;
@@ -35,6 +37,7 @@ import org.geysermc.geyser.inventory.item.BannerPattern;
import org.geysermc.geyser.inventory.item.GeyserInstrument;
import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.level.JukeboxSong;
import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.ListRegistry;
@@ -57,6 +60,9 @@ public class JavaRegistries {
public static final JavaRegistryKey<Enchantment> ENCHANTMENT = create("enchantment", RegistryCache::enchantments);
public static final JavaRegistryKey<BannerPattern> BANNER_PATTERN = create("banner_pattern", RegistryCache::bannerPatterns);
public static final JavaRegistryKey<GeyserInstrument> INSTRUMENT = create("instrument", RegistryCache::instruments);
public static final JavaRegistryKey<JukeboxSong> JUKEBOX_SONG = create("jukebox_song", RegistryCache::jukeboxSongs);
public static final JavaRegistryKey<TrimMaterial> TRIM_MATERIAL = create("trim_material", RegistryCache::trimMaterials);
public static final JavaRegistryKey<TrimPattern> TRIM_PATTERN = create("trim_pattern", RegistryCache::trimPatterns);
public static final JavaRegistryKey<CatEntity.BuiltInVariant> CAT_VARIANT = create("cat_variant", RegistryCache::catVariants);
public static final JavaRegistryKey<FrogEntity.BuiltInVariant> FROG_VARIANT = create("frog_variant", RegistryCache::frogVariants);