mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-12-19 14:59:27 +00:00
Update data component hashers for 1.21.6's changes
This commit is contained in:
@@ -35,6 +35,7 @@ import net.kyori.adventure.text.TranslatableComponent;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.ShadowColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
@@ -96,9 +97,9 @@ public interface ComponentHasher {
|
||||
.optionalNullable("name", COMPONENT, event -> ((HoverEvent.ShowEntity) event.value()).name());
|
||||
});
|
||||
|
||||
// TODO shadow colours - needs kyori bump
|
||||
MapBuilder<Style> STYLE = builder -> builder
|
||||
.optionalNullable("color", COLOR, Style::color)
|
||||
.optionalNullable("shadow_color", MinecraftHasher.INT.cast(ShadowColor::value), Style::shadowColor)
|
||||
.optional("bold", DECORATION_STATE, style -> style.decoration(TextDecoration.BOLD), TextDecoration.State.NOT_SET)
|
||||
.optional("italic", DECORATION_STATE, style -> style.decoration(TextDecoration.ITALIC), TextDecoration.State.NOT_SET)
|
||||
.optional("underlined", DECORATION_STATE, style -> style.decoration(TextDecoration.UNDERLINED), TextDecoration.State.NOT_SET)
|
||||
|
||||
@@ -43,8 +43,13 @@ import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.registry.JavaRegistries;
|
||||
import org.geysermc.geyser.util.MinecraftKey;
|
||||
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.EquipmentSlot;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.GlobalPos;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.HashedStack;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.BlockStateProperties;
|
||||
@@ -75,6 +80,7 @@ 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 org.geysermc.mcprotocollib.protocol.data.game.level.sound.CustomSound;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -158,7 +164,9 @@ public class DataComponentHashers {
|
||||
.optional("dispensable", MinecraftHasher.BOOL, Equippable::dispensable, true)
|
||||
.optional("swappable", MinecraftHasher.BOOL, Equippable::swappable, true)
|
||||
.optional("damage_on_hurt", MinecraftHasher.BOOL, Equippable::damageOnHurt, true)
|
||||
.optional("equip_on_interact", MinecraftHasher.BOOL, Equippable::equipOnInteract, false));
|
||||
.optional("equip_on_interact", MinecraftHasher.BOOL, Equippable::equipOnInteract, false)
|
||||
.optional("can_be_sheared", MinecraftHasher.BOOL, Equippable::canBeSheared, false)
|
||||
.optional("shearing_sound", RegistryHasher.SOUND_EVENT, Equippable::shearingSound, BuiltinSound.ITEM_SHEARS_SNIP));
|
||||
registerMap(DataComponentTypes.REPAIRABLE, builder -> builder
|
||||
.accept("items", RegistryHasher.ITEM.holderSet(), Function.identity()));
|
||||
|
||||
@@ -258,7 +266,7 @@ public class DataComponentHashers {
|
||||
.sessionCast((session, holder) -> holder.getOrCompute(id -> JavaRegistries.CHICKEN_VARIANT.key(session, id)))); // Why, Mojang?
|
||||
register(DataComponentTypes.FROG_VARIANT, RegistryHasher.FROG_VARIANT);
|
||||
register(DataComponentTypes.HORSE_VARIANT, RegistryHasher.HORSE_VARIANT);
|
||||
register(DataComponentTypes.PAINTING_VARIANT, RegistryHasher.PAINTING_VARIANT.holder());
|
||||
register(DataComponentTypes.PAINTING_VARIANT, RegistryHasher.PAINTING_VARIANT.cast(Holder::id)); // This can and will throw when a direct holder was received, which is still possible due to a bug in 1.21.6.
|
||||
register(DataComponentTypes.LLAMA_VARIANT, RegistryHasher.LLAMA_VARIANT);
|
||||
register(DataComponentTypes.AXOLOTL_VARIANT, RegistryHasher.AXOLOTL_VARIANT);
|
||||
register(DataComponentTypes.CAT_VARIANT, RegistryHasher.CAT_VARIANT);
|
||||
@@ -367,6 +375,56 @@ public class DataComponentHashers {
|
||||
0, 1
|
||||
)), 0); // TODO identifier lookup
|
||||
|
||||
testHash(session, DataComponentTypes.ATTRIBUTE_MODIFIERS, new ItemAttributeModifiers(
|
||||
List.of(
|
||||
ItemAttributeModifiers.Entry.builder()
|
||||
.attribute(AttributeType.Builtin.ATTACK_DAMAGE.getId())
|
||||
.modifier(ItemAttributeModifiers.AttributeModifier.builder()
|
||||
.id(MinecraftKey.key("test_modifier_1"))
|
||||
.amount(2.0)
|
||||
.operation(ModifierOperation.ADD)
|
||||
.build())
|
||||
.slot(ItemAttributeModifiers.EquipmentSlotGroup.ANY)
|
||||
.display(new ItemAttributeModifiers.Display(ItemAttributeModifiers.DisplayType.DEFAULT, null))
|
||||
.build(),
|
||||
ItemAttributeModifiers.Entry.builder()
|
||||
.attribute(AttributeType.Builtin.JUMP_STRENGTH.getId())
|
||||
.modifier(ItemAttributeModifiers.AttributeModifier.builder()
|
||||
.id(MinecraftKey.key("test_modifier_2"))
|
||||
.amount(4.2)
|
||||
.operation(ModifierOperation.ADD_MULTIPLIED_TOTAL)
|
||||
.build())
|
||||
.slot(ItemAttributeModifiers.EquipmentSlotGroup.HEAD)
|
||||
.display(new ItemAttributeModifiers.Display(ItemAttributeModifiers.DisplayType.HIDDEN, null))
|
||||
.build(),
|
||||
ItemAttributeModifiers.Entry.builder()
|
||||
.attribute(AttributeType.Builtin.WAYPOINT_RECEIVE_RANGE.getId())
|
||||
.modifier(ItemAttributeModifiers.AttributeModifier.builder()
|
||||
.id(MinecraftKey.key("geyser_mc:test_modifier_3"))
|
||||
.amount(5.4)
|
||||
.operation(ModifierOperation.ADD_MULTIPLIED_BASE)
|
||||
.build())
|
||||
.slot(ItemAttributeModifiers.EquipmentSlotGroup.FEET)
|
||||
.display(new ItemAttributeModifiers.Display(ItemAttributeModifiers.DisplayType.DEFAULT, null))
|
||||
.build()
|
||||
)
|
||||
), 1889444548);
|
||||
|
||||
testHash(session, DataComponentTypes.ATTRIBUTE_MODIFIERS, new ItemAttributeModifiers(
|
||||
List.of(
|
||||
ItemAttributeModifiers.Entry.builder()
|
||||
.attribute(AttributeType.Builtin.WAYPOINT_TRANSMIT_RANGE.getId())
|
||||
.modifier(ItemAttributeModifiers.AttributeModifier.builder()
|
||||
.id(MinecraftKey.key("geyser_mc:test_modifier_4"))
|
||||
.amount(2.0)
|
||||
.operation(ModifierOperation.ADD)
|
||||
.build())
|
||||
.slot(ItemAttributeModifiers.EquipmentSlotGroup.ANY)
|
||||
.display(new ItemAttributeModifiers.Display(ItemAttributeModifiers.DisplayType.OVERRIDE, Component.text("give me a test")))
|
||||
.build()
|
||||
)
|
||||
), 1375953017);
|
||||
|
||||
testHash(session, DataComponentTypes.CUSTOM_MODEL_DATA,
|
||||
new CustomModelData(List.of(5.0F, 3.0F, -1.0F), List.of(false, true, false), List.of("1", "3", "2"), List.of(3424, -123, 345)), 1947635619);
|
||||
|
||||
@@ -411,18 +469,25 @@ public class DataComponentHashers {
|
||||
|
||||
testHash(session, DataComponentTypes.ENCHANTABLE, 3, -1834983819);
|
||||
|
||||
// TODO
|
||||
// testHash(session, DataComponentTypes.EQUIPPABLE, new Equippable(EquipmentSlot.BODY, BuiltinSound.ITEM_ARMOR_EQUIP_GENERIC, null, null, null,
|
||||
// true, true, true, false), 1294431019);
|
||||
// testHash(session, DataComponentTypes.EQUIPPABLE, new Equippable(EquipmentSlot.BODY, BuiltinSound.ITEM_ARMOR_EQUIP_CHAIN, MinecraftKey.key("testing"), null, null,
|
||||
// true, true, true, false), 1226203061);
|
||||
// testHash(session, DataComponentTypes.EQUIPPABLE, new Equippable(EquipmentSlot.BODY, BuiltinSound.AMBIENT_CAVE, null, null, null,
|
||||
// false, true, false, false), 1416408052);
|
||||
// testHash(session, DataComponentTypes.EQUIPPABLE, new Equippable(EquipmentSlot.BODY, BuiltinSound.ENTITY_BREEZE_WIND_BURST, null, MinecraftKey.key("testing"),
|
||||
// new HolderSet(new int[]{EntityType.ACACIA_BOAT.ordinal()}), false, true, false, false), 1711275245);
|
||||
//
|
||||
// testHash(session, DataComponentTypes.EQUIPPABLE, new Equippable(EquipmentSlot.HELMET, BuiltinSound.ITEM_ARMOR_EQUIP_GENERIC, null, null, null,
|
||||
// true, true, true, false), 497790992); // TODO broken because equipment slot names don't match
|
||||
testHash(session, DataComponentTypes.EQUIPPABLE, new Equippable(EquipmentSlot.BODY, BuiltinSound.ITEM_ARMOR_EQUIP_GENERIC, null, null, null,
|
||||
true, true, true, false,
|
||||
false, BuiltinSound.ITEM_SHEARS_SNIP), 1294431019);
|
||||
testHash(session, DataComponentTypes.EQUIPPABLE, new Equippable(EquipmentSlot.BODY, BuiltinSound.ITEM_ARMOR_EQUIP_CHAIN, MinecraftKey.key("testing"), null, null,
|
||||
true, true, true, false,
|
||||
true, BuiltinSound.ITEM_BONE_MEAL_USE), -801616214);
|
||||
testHash(session, DataComponentTypes.EQUIPPABLE, new Equippable(EquipmentSlot.BODY, BuiltinSound.AMBIENT_CAVE, null, null, null,
|
||||
false, true, false, false,
|
||||
false, new CustomSound("testing_equippable", false, 10.0F)), -1145684769);
|
||||
testHash(session, DataComponentTypes.EQUIPPABLE, new Equippable(EquipmentSlot.BODY, BuiltinSound.ENTITY_BREEZE_WIND_BURST, null, MinecraftKey.key("testing"),
|
||||
new HolderSet(new int[]{EntityType.ACACIA_BOAT.ordinal()}), false, true, false, false,
|
||||
true, BuiltinSound.BLOCK_NETHERITE_BLOCK_PLACE), -115079770);
|
||||
testHash(session, DataComponentTypes.EQUIPPABLE, new Equippable(EquipmentSlot.HELMET, BuiltinSound.ITEM_ARMOR_EQUIP_GENERIC, null, null, null,
|
||||
true, true, true, false,
|
||||
false, BuiltinSound.ITEM_SHEARS_SNIP), 497790992);
|
||||
testHash(session, DataComponentTypes.EQUIPPABLE, new Equippable(EquipmentSlot.HELMET, BuiltinSound.ITEM_ARMOR_EQUIP_GENERIC, null, null,
|
||||
new HolderSet(MinecraftKey.key("aquatic")),
|
||||
true, true, true, false,
|
||||
false, BuiltinSound.ITEM_SHEARS_SNIP), 264760955);
|
||||
|
||||
testHash(session, DataComponentTypes.REPAIRABLE, new HolderSet(new int[]{Items.AMETHYST_BLOCK.javaId(), Items.PUMPKIN.javaId()}), -36715567);
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public interface MapBuilder<Type> extends UnaryOperator<MapHasher<Type>> {
|
||||
*
|
||||
* @param <Type> the type to encode.
|
||||
*/
|
||||
static <Type> MapBuilder<Type> empty() {
|
||||
static <Type> MapBuilder<Type> unit() {
|
||||
return builder -> builder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,10 @@ import com.google.common.hash.HashCode;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* {@link MapHasher}s are used to encode a {@link Type} to a map-like structure, which is then hashed using a {@link MinecraftHashEncoder}.
|
||||
@@ -135,11 +137,7 @@ public class MapHasher<Type> {
|
||||
* @param <Value> the type of the value.
|
||||
*/
|
||||
public <Value> MapHasher<Type> optionalNullable(String key, MinecraftHasher<Value> hasher, Function<Type, Value> extractor) {
|
||||
Value value = extractor.apply(object);
|
||||
if (value != null) {
|
||||
acceptConstant(key, hasher, value);
|
||||
}
|
||||
return this;
|
||||
return optionalPredicate(key, hasher, extractor, Objects::nonNull);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,8 +164,21 @@ public class MapHasher<Type> {
|
||||
* @param <Value> the type of the value.
|
||||
*/
|
||||
public <Value> MapHasher<Type> optional(String key, MinecraftHasher<Value> hasher, Function<Type, Value> extractor, Value defaultValue) {
|
||||
return optionalPredicate(key, hasher, extractor, value -> !value.equals(defaultValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a {@link Value} from a {@link Type} using the {@code extractor}, and adds it to the map only if {@code predicate} returns {@code true} for it.
|
||||
*
|
||||
* @param key the key to put the {@link Value} in.
|
||||
* @param hasher the hasher used to hash a {@link Value}.
|
||||
* @param extractor the function that extracts a {@link Value} from a {@link Type}.
|
||||
* @param predicate the predicate that checks if a {@link Value} should be added to the map. The {@link Value} won't be added to the map if the predicate returns {@code false} for it.
|
||||
* @param <Value> the type of the value.
|
||||
*/
|
||||
public <Value> MapHasher<Type> optionalPredicate(String key, MinecraftHasher<Value> hasher, Function<Type, Value> extractor, Predicate<Value> predicate) {
|
||||
Value value = extractor.apply(object);
|
||||
if (!value.equals(defaultValue)) {
|
||||
if (predicate.test(value)) {
|
||||
acceptConstant(key, hasher, value);
|
||||
}
|
||||
return this;
|
||||
|
||||
@@ -88,7 +88,7 @@ import java.util.stream.IntStream;
|
||||
@FunctionalInterface
|
||||
public interface MinecraftHasher<Type> {
|
||||
|
||||
MinecraftHasher<Unit> UNIT = (unit, encoder) -> encoder.emptyMap();
|
||||
MinecraftHasher<Unit> UNIT = unit();
|
||||
|
||||
MinecraftHasher<Byte> BYTE = (b, encoder) -> encoder.number(b);
|
||||
|
||||
@@ -237,6 +237,13 @@ public interface MinecraftHasher<Type> {
|
||||
.optionalNullable("filtered", this, Filterable::getOptional));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a hasher that always encodes into an empty map.
|
||||
*/
|
||||
static <Type> MinecraftHasher<Type> unit() {
|
||||
return (value, encoder) -> encoder.emptyMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily-initialises the given hasher using {@link Suppliers#memoize(com.google.common.base.Supplier)}.
|
||||
*/
|
||||
|
||||
@@ -50,7 +50,6 @@ 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.attribute.AttributeType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.PaintingVariant;
|
||||
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.AdventureModePredicate;
|
||||
@@ -189,14 +188,7 @@ public interface RegistryHasher<DirectType> extends MinecraftHasher<Integer> {
|
||||
|
||||
RegistryHasher<?> FROG_VARIANT = registry(JavaRegistries.FROG_VARIANT);
|
||||
|
||||
MinecraftHasher<PaintingVariant> DIRECT_PAINTING_VARIANT = MinecraftHasher.mapBuilder(builder -> builder
|
||||
.accept("width", INT, PaintingVariant::width)
|
||||
.accept("height", INT, PaintingVariant::height)
|
||||
.accept("asset_id", KEY, PaintingVariant::assetId)
|
||||
.optionalNullable("title", ComponentHasher.COMPONENT, PaintingVariant::title)
|
||||
.optionalNullable("author", ComponentHasher.COMPONENT, PaintingVariant::author));
|
||||
|
||||
RegistryHasher<PaintingVariant> PAINTING_VARIANT = registry(JavaRegistries.PAINTING_VARIANT, DIRECT_PAINTING_VARIANT);
|
||||
RegistryHasher<?> PAINTING_VARIANT = registry(JavaRegistries.PAINTING_VARIANT);
|
||||
|
||||
RegistryHasher<?> CAT_VARIANT = registry(JavaRegistries.CAT_VARIANT);
|
||||
|
||||
@@ -287,12 +279,22 @@ public interface RegistryHasher<DirectType> extends MinecraftHasher<Integer> {
|
||||
MinecraftHasher<AdventureModePredicate> ADVENTURE_MODE_PREDICATE = MinecraftHasher.either(BLOCK_PREDICATE,
|
||||
predicate -> predicate.getPredicates().size() == 1 ? predicate.getPredicates().get(0) : null, BLOCK_PREDICATE.list(), AdventureModePredicate::getPredicates);
|
||||
|
||||
MinecraftHasher<ItemAttributeModifiers.DisplayType> ATTRIBUTE_MODIFIER_DISPLAY_TYPE = MinecraftHasher.fromEnum();
|
||||
|
||||
MinecraftHasher<ItemAttributeModifiers.Display> ATTRIBUTE_MODIFIER_DISPLAY = ATTRIBUTE_MODIFIER_DISPLAY_TYPE.dispatch(ItemAttributeModifiers.Display::getType,
|
||||
displayType -> switch (displayType) {
|
||||
case DEFAULT, HIDDEN -> MapBuilder.unit();
|
||||
case OVERRIDE -> builder -> builder
|
||||
.accept("value", ComponentHasher.COMPONENT, ItemAttributeModifiers.Display::getComponent);
|
||||
});
|
||||
|
||||
MinecraftHasher<ItemAttributeModifiers.Entry> ATTRIBUTE_MODIFIER_ENTRY = MinecraftHasher.mapBuilder(builder -> builder
|
||||
.accept("type", RegistryHasher.ATTRIBUTE, ItemAttributeModifiers.Entry::getAttribute)
|
||||
.accept("id", KEY, entry -> entry.getModifier().getId())
|
||||
.accept("amount", DOUBLE, entry -> entry.getModifier().getAmount())
|
||||
.accept("operation", ATTRIBUTE_MODIFIER_OPERATION, entry -> entry.getModifier().getOperation())
|
||||
.optional("slot", EQUIPMENT_SLOT_GROUP, ItemAttributeModifiers.Entry::getSlot, ItemAttributeModifiers.EquipmentSlotGroup.ANY));
|
||||
.optional("slot", EQUIPMENT_SLOT_GROUP, ItemAttributeModifiers.Entry::getSlot, ItemAttributeModifiers.EquipmentSlotGroup.ANY)
|
||||
.optionalPredicate("display", ATTRIBUTE_MODIFIER_DISPLAY, ItemAttributeModifiers.Entry::getDisplay, display -> display.getType() != ItemAttributeModifiers.DisplayType.DEFAULT));
|
||||
|
||||
MinecraftHasher<Consumable.ItemUseAnimation> ITEM_USE_ANIMATION = MinecraftHasher.fromEnum();
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public enum ConsumeEffectType {
|
||||
|
||||
<T extends ConsumeEffect> ConsumeEffectType(Class<T> clazz) {
|
||||
this.clazz = clazz;
|
||||
this.builder = MapBuilder.empty();
|
||||
this.builder = MapBuilder.unit();
|
||||
}
|
||||
|
||||
<T extends ConsumeEffect> ConsumeEffectType(Class<T> clazz, MapBuilder<T> builder) {
|
||||
|
||||
@@ -15,7 +15,7 @@ protocol-codec = "3.0.0.Beta6-20250506.012145-17"
|
||||
raknet = "1.0.0.CR3-20250218.160705-18"
|
||||
minecraftauth = "4.1.1"
|
||||
mcprotocollib = "1.21.6-SNAPSHOT"
|
||||
adventure = "4.14.0"
|
||||
adventure = "4.21.0"
|
||||
adventure-platform = "4.3.0"
|
||||
junit = "5.9.2"
|
||||
checkerframework = "3.19.0"
|
||||
|
||||
Reference in New Issue
Block a user