1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2025-12-31 04:36:33 +00:00

Implement data component hashing in inventory transactions, disable printing tests

This commit is contained in:
Eclipse
2025-03-28 21:22:21 +00:00
parent dbd3187349
commit 6e790b89c6
3 changed files with 34 additions and 14 deletions

View File

@@ -26,12 +26,14 @@
package org.geysermc.geyser.inventory.click;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.SlotType;
import org.geysermc.geyser.item.hashing.DataComponentHashers;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.BundleInventoryTranslator;
import org.geysermc.geyser.translator.inventory.CraftingInventoryTranslator;
@@ -41,7 +43,6 @@ import org.geysermc.geyser.util.thirdparty.Fraction;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerActionType;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.MoveToHotbarAction;
import org.geysermc.mcprotocollib.protocol.data.game.item.HashedStack;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSelectBundleItemPacket;
@@ -51,8 +52,6 @@ import org.jetbrains.annotations.Contract;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
public final class ClickPlan {
private final List<ClickAction> plan = new ArrayList<>();
@@ -160,8 +159,8 @@ public final class ClickPlan {
action.slot,
action.click.actionType,
action.click.action,
hashStack(clickedItemStack),
new Int2ObjectOpenHashMap<>() // TODO fixme
DataComponentHashers.hashStack(session, clickedItemStack),
Int2ObjectMaps.emptyMap()
);
session.sendDownstreamGamePacket(clickPacket);
@@ -517,9 +516,4 @@ public final class ClickPlan {
private record ClickAction(Click click, int slot, boolean force) {
}
// TODO probably move this
public static HashedStack hashStack(ItemStack stack) {
return stack == null ? null : new HashedStack(stack.getId(), stack.getAmount(), Map.of(), Set.of()); // TODO this is WRONG. figure out stack hashing
}
}

View File

@@ -45,12 +45,14 @@ 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.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;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.BlocksAttacks;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.Consumable;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ConsumeEffect;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.CustomModelData;
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.DataComponentTypes;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
@@ -75,8 +77,10 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.WrittenBookC
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.BuiltinSound;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
@SuppressWarnings("UnstableApiUsage")
@@ -292,11 +296,33 @@ public class DataComponentHashers {
public static <T> HashCode hash(GeyserSession session, DataComponentType<T> component, T value) {
MinecraftHasher<T> hasher = (MinecraftHasher<T>) hashers.get(component);
if (hasher == null) {
throw new IllegalStateException("Unregistered hasher for component " + component + "!"); // TODO we might not have hashers for every component, in which case, fix this
throw new IllegalStateException("Unregistered hasher for component " + component + "!");
}
return hasher.hash(value, new MinecraftHashEncoder(session));
}
public static HashedStack hashStack(GeyserSession session, ItemStack stack) {
if (stack == null) {
return null;
}
DataComponents patch = stack.getDataComponentsPatch();
if (patch == null) {
return new HashedStack(stack.getId(), stack.getAmount(), Map.of(), Set.of());
}
Map<DataComponentType<?>, DataComponent<?, ?>> components = patch.getDataComponents();
Map<DataComponentType<?>, Integer> hashedAdditions = new HashMap<>();
Set<DataComponentType<?>> removals = new HashSet<>();
for (Map.Entry<DataComponentType<?>, DataComponent<?, ?>> component : components.entrySet()) {
if (component.getValue().getValue() == null) {
removals.add(component.getKey());
} else {
hashedAdditions.put(component.getKey(), hash(session, (DataComponentType) component.getKey(), component.getValue().getValue()).asInt());
}
}
return new HashedStack(stack.getId(), stack.getAmount(), hashedAdditions, removals);
}
// TODO better testing, at the moment this is just called when the player is spawned
public static void testHashing(GeyserSession session) {
// Hashed values generated by vanilla Java

View File

@@ -52,9 +52,9 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.click.Click;
import org.geysermc.geyser.inventory.click.ClickPlan;
import org.geysermc.geyser.inventory.item.GeyserInstrument;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.hashing.DataComponentHashers;
import org.geysermc.geyser.item.type.BlockItem;
import org.geysermc.geyser.item.type.BoatItem;
import org.geysermc.geyser.item.type.Item;
@@ -143,11 +143,11 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
return;
}
itemStack.sub(1);
changedItem = Int2ObjectMaps.singleton(hotbarSlot, ClickPlan.hashStack(itemStack.getItemStack()));
changedItem = Int2ObjectMaps.singleton(hotbarSlot, DataComponentHashers.hashStack(session, itemStack.getItemStack()));
}
ServerboundContainerClickPacket dropPacket = new ServerboundContainerClickPacket(
inventory.getJavaId(), inventory.getStateId(), hotbarSlot, clickType.actionType, clickType.action,
ClickPlan.hashStack(inventory.getCursor().getItemStack()), changedItem);
DataComponentHashers.hashStack(session, inventory.getCursor().getItemStack()), changedItem);
session.sendDownstreamGamePacket(dropPacket);
return;
}