diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts index ebe727253..5b66e0f37 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -8,8 +8,6 @@ architectury { fabric() } -val includeTransitive: Configuration = configurations.getByName("includeTransitive") - dependencies { modImplementation(libs.fabric.loader) modApi(libs.fabric.api) diff --git a/bootstrap/mod/neoforge/build.gradle.kts b/bootstrap/mod/neoforge/build.gradle.kts index 2c58192fb..310e8c3f6 100644 --- a/bootstrap/mod/neoforge/build.gradle.kts +++ b/bootstrap/mod/neoforge/build.gradle.kts @@ -16,8 +16,6 @@ provided("com.google.errorprone", "error_prone_annotations") // Jackson shipped by Minecraft is too old, so we shade & relocate our newer version relocate("com.fasterxml.jackson") -val includeTransitive: Configuration = configurations.getByName("includeTransitive") - dependencies { // See https://github.com/google/guava/issues/6618 modules { diff --git a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts index b157c0e53..903d82258 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -96,8 +96,8 @@ tasks { afterEvaluate { val providedDependencies = providedDependencies[project.name]!! - val shadedDependencies = configurations.getByName("shadowBundle") - .dependencies.stream().map { dependency -> "${dependency.group}:${dependency.name}" }.toList() + val shadedDependencies = configurations.getByName("shadowBundle").resolvedConfiguration.resolvedArtifacts.stream() + .map { dependency -> "${dependency.moduleVersion.id.module}" }.toList() // Now: Include all transitive dependencies that aren't excluded configurations["includeTransitive"].resolvedConfiguration.resolvedArtifacts.forEach { dep -> diff --git a/core/src/main/java/org/geysermc/geyser/item/hashing/DataComponentHashers.java b/core/src/main/java/org/geysermc/geyser/item/hashing/DataComponentHashers.java index 40d8628c5..ca9840994 100644 --- a/core/src/main/java/org/geysermc/geyser/item/hashing/DataComponentHashers.java +++ b/core/src/main/java/org/geysermc/geyser/item/hashing/DataComponentHashers.java @@ -74,6 +74,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.MobEffectIns import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ToolData; import org.geysermc.mcprotocollib.protocol.data.game.item.component.TooltipDisplay; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.TypedEntityData; 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; @@ -213,9 +214,15 @@ public class DataComponentHashers { register(DataComponentTypes.TRIM, RegistryHasher.ARMOR_TRIM); register(DataComponentTypes.DEBUG_STICK_STATE, MinecraftHasher.NBT_MAP); - // register(DataComponentTypes.ENTITY_DATA, MinecraftHasher.NBT_MAP); TODO 1.21.9 + registerMap(DataComponentTypes.ENTITY_DATA, builder -> builder + .accept("id", RegistryHasher.ENTITY_TYPE_KEY, TypedEntityData::type) + .inlineNbt(TypedEntityData::tag) + ); register(DataComponentTypes.BUCKET_ENTITY_DATA, MinecraftHasher.NBT_MAP); - // register(DataComponentTypes.BLOCK_ENTITY_DATA, MinecraftHasher.NBT_MAP); TODO 1.21.9 + registerMap(DataComponentTypes.BLOCK_ENTITY_DATA, builder -> builder + .accept("id", RegistryHasher.BLOCK_ENTITY_TYPE_KEY, TypedEntityData::type) + .inlineNbt(TypedEntityData::tag) + ); register(DataComponentTypes.INSTRUMENT, RegistryHasher.INSTRUMENT_COMPONENT); register(DataComponentTypes.PROVIDES_TRIM_MATERIAL, RegistryHasher.PROVIDES_TRIM_MATERIAL); @@ -235,7 +242,7 @@ public class DataComponentHashers { .optional("flight_duration", MinecraftHasher.BYTE, fireworks -> (byte) fireworks.getFlightDuration(), (byte) 0) .optionalList("explosions", RegistryHasher.FIREWORK_EXPLOSION, Fireworks::getExplosions)); - // register(DataComponentTypes.PROFILE, MinecraftHasher.GAME_PROFILE); TODO 1.21.9 + register(DataComponentTypes.PROFILE, MinecraftHasher.RESOLVABLE_PROFILE); register(DataComponentTypes.NOTE_BLOCK_SOUND, MinecraftHasher.KEY); register(DataComponentTypes.BANNER_PATTERNS, RegistryHasher.BANNER_PATTERN_LAYER.list()); register(DataComponentTypes.BASE_COLOR, MinecraftHasher.DYE_COLOR); diff --git a/core/src/main/java/org/geysermc/geyser/item/hashing/MapHasher.java b/core/src/main/java/org/geysermc/geyser/item/hashing/MapHasher.java index 2072ace29..187360308 100644 --- a/core/src/main/java/org/geysermc/geyser/item/hashing/MapHasher.java +++ b/core/src/main/java/org/geysermc/geyser/item/hashing/MapHasher.java @@ -26,6 +26,8 @@ package org.geysermc.geyser.item.hashing; import com.google.common.hash.HashCode; +import org.cloudburstmc.nbt.NbtList; +import org.cloudburstmc.nbt.NbtMap; import java.util.HashMap; import java.util.List; @@ -67,6 +69,14 @@ public class MapHasher { return this; } + private MapHasher accept(String key, Object value, HashCode valueHash) { + if (unhashed != null) { + unhashed.put(key, value); + } + map.put(encoder.string(key), valueHash); + return this; + } + /** * Adds a constant {@link Value} to the map. * @@ -82,6 +92,25 @@ public class MapHasher { return accept(key, hasher.hash(value, encoder)); } + public MapHasher inlineNbt(Function extractor) { + NbtMap nbtMap = extractor.apply(object); + for (String key : nbtMap.keySet()) { + Object value = nbtMap.get(key); + if (value instanceof NbtList list) { + accept(key, value, encoder.nbtList(list)); + } else { + nbtMap.listenForNumber(key, n -> accept(key, value, encoder.number(n))); + nbtMap.listenForString(key, s -> accept(key, value, encoder.string(s))); + nbtMap.listenForCompound(key, compound -> accept(key, value, encoder.nbtMap(compound))); + + nbtMap.listenForByteArray(key, bytes -> accept(key, value, encoder.byteArray(bytes))); + nbtMap.listenForIntArray(key, ints -> accept(key, value, encoder.intArray(ints))); + nbtMap.listenForLongArray(key, longs -> accept(key, value, encoder.longArray(longs))); + } + } + return this; + } + /** * Extracts a {@link Value} from a {@link Type} using the {@code extractor}, and adds it to the map. * diff --git a/core/src/main/java/org/geysermc/geyser/item/hashing/MinecraftHasher.java b/core/src/main/java/org/geysermc/geyser/item/hashing/MinecraftHasher.java index 08c79c049..7f135e2d6 100644 --- a/core/src/main/java/org/geysermc/geyser/item/hashing/MinecraftHasher.java +++ b/core/src/main/java/org/geysermc/geyser/item/hashing/MinecraftHasher.java @@ -37,6 +37,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.mcprotocollib.auth.GameProfile; 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.entity.player.ResolvableProfile; import org.geysermc.mcprotocollib.protocol.data.game.item.component.Filterable; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemAttributeModifiers; import org.geysermc.mcprotocollib.protocol.data.game.item.component.Unit; @@ -45,6 +46,7 @@ import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.UUID; import java.util.function.BiFunction; import java.util.function.Function; @@ -131,10 +133,15 @@ public interface MinecraftHasher { .accept("value", STRING, GameProfile.Property::getValue) .optionalNullable("signature", STRING, GameProfile.Property::getSignature)); - MinecraftHasher GAME_PROFILE = mapBuilder(builder -> builder - .optionalNullable("name", STRING, GameProfile::getName) - .optionalNullable("id", UUID, GameProfile::getId) - .optionalList("properties", GAME_PROFILE_PROPERTY, GameProfile::getProperties)); + MinecraftHasher RESOLVABLE_PROFILE = mapBuilder(builder -> builder + .optionalNullable("name", STRING, resolvableProfile -> resolvableProfile.getProfile().getName()) + .optionalNullable("id", UUID, resolvableProfile -> resolvableProfile.getProfile().getId()) + .optionalList("properties", GAME_PROFILE_PROPERTY, resolvableProfile -> resolvableProfile.getProfile().getProperties()) + .optionalNullable("texture", KEY, ResolvableProfile::getBody) + .optionalNullable("cape", KEY, ResolvableProfile::getCape) + .optionalNullable("elytra", KEY, ResolvableProfile::getElytra) + .optional("model", STRING, resolvableProfile -> Optional.ofNullable(resolvableProfile.getModel()).map(GameProfile.TextureModel::name)) + ); MinecraftHasher RARITY = fromIdEnum(Rarity.values(), Rarity::getName); diff --git a/core/src/main/java/org/geysermc/geyser/item/hashing/RegistryHasher.java b/core/src/main/java/org/geysermc/geyser/item/hashing/RegistryHasher.java index cd72874e5..85916592c 100644 --- a/core/src/main/java/org/geysermc/geyser/item/hashing/RegistryHasher.java +++ b/core/src/main/java/org/geysermc/geyser/item/hashing/RegistryHasher.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.item.hashing; import com.google.common.hash.HashCode; import net.kyori.adventure.key.Key; -import org.cloudburstmc.nbt.NbtMap; import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.item.hashing.data.ConsumeEffectType; import org.geysermc.geyser.item.hashing.data.FireworkExplosionShape; @@ -74,6 +73,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.ProvidesTrim 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.item.component.Unit; +import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import org.geysermc.mcprotocollib.protocol.data.game.level.sound.BuiltinSound; import org.geysermc.mcprotocollib.protocol.data.game.level.sound.CustomSound; import org.geysermc.mcprotocollib.protocol.data.game.level.sound.Sound; @@ -110,6 +110,10 @@ public interface RegistryHasher extends MinecraftHasher { RegistryHasher ENTITY_TYPE = enumIdRegistry(EntityType.values()); + MinecraftHasher ENTITY_TYPE_KEY = enumRegistry(); + + MinecraftHasher BLOCK_ENTITY_TYPE_KEY = enumRegistry(); + RegistryHasher ENCHANTMENT = registry(JavaRegistries.ENCHANTMENT); RegistryHasher ATTRIBUTE = enumIdRegistry(AttributeType.Builtin.values(), AttributeType::getIdentifier); @@ -346,7 +350,8 @@ public interface RegistryHasher extends MinecraftHasher { .optional("has_twinkle", BOOL, Fireworks.FireworkExplosion::isHasTwinkle, false)); MinecraftHasher BEEHIVE_OCCUPANT = MinecraftHasher.mapBuilder(builder -> builder - .optional("entity_data", NBT_MAP, BeehiveOccupant::getEntityData, NbtMap.EMPTY) + .accept("id", RegistryHasher.ENTITY_TYPE_KEY, beehiveOccupant -> beehiveOccupant.getEntityData().type()) + .inlineNbt(beehiveOccupant -> beehiveOccupant.getEntityData().tag()) .accept("ticks_in_hive", INT, BeehiveOccupant::getTicksInHive) .accept("min_ticks_in_hive", INT, BeehiveOccupant::getMinTicksInHive)); diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b85ca10a7..71eb9e633 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ protocol-common = "3.0.0.Beta8-20250929.213851-8" protocol-codec = "3.0.0.Beta8-20250929.213851-8" raknet = "1.0.0.CR3-20250811.214335-20" minecraftauth = "4.1.1" -mcprotocollib = "1.21.9-20251005.132211-10" +mcprotocollib = "1.21.9-20251008.155050-11" adventure = "4.24.0" adventure-platform = "4.3.0" junit = "5.9.2"