Add some documentation

This commit is contained in:
Eclipse 2024-07-10 19:29:36 +00:00
parent dbd062d56d
commit 9a40e5de09
No known key found for this signature in database
GPG key ID: 95E6998F82EC938A
9 changed files with 60 additions and 16 deletions

View file

@ -27,7 +27,6 @@ package org.geysermc.geyser.inventory.updater;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.util.stream.IntStream;
import net.kyori.adventure.text.Component;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
@ -42,7 +41,6 @@ import org.geysermc.geyser.inventory.item.BedrockEnchantment;
import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.TagRegistry;
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.ItemUtils;
@ -312,9 +310,9 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
for (Object2IntMap.Entry<Enchantment> entry : getEnchantments(session, material).object2IntEntrySet()) {
Enchantment enchantment = entry.getKey();
boolean canApply = isEnchantedBook(input) || session.getTagCache().is(enchantment.supportedItems(), input.getJavaId(), TagRegistry.ITEM);
boolean canApply = isEnchantedBook(input) || session.getTagCache().is(enchantment.supportedItems(), input.getJavaId());
int[] incompatibleEnchantments = enchantment.exclusiveSet().resolve(session.getTagCache(), TagRegistry.ENCHANTMENT);
int[] incompatibleEnchantments = enchantment.exclusiveSet().resolve(session.getTagCache());
for (int i : incompatibleEnchantments) {
Enchantment incompatible = session.getRegistryCache().enchantments().byId(i);
if (combinedEnchantments.containsKey(incompatible)) {

View file

@ -48,10 +48,11 @@ import java.util.Map;
/**
* Manages information sent from the {@link ClientboundUpdateTagsPacket}. If that packet is not sent, all lists here
* will remain empty, matching Java Edition behavior.
* will remain empty, matching Java Edition behavior. Only tags from registries in {@link TagRegistry} are stored.
*/
@ParametersAreNonnullByDefault
public final class TagCache {
// Stores the indexes of non-vanilla tag keys in the tags array.
private List<Object2IntMap<Key>> tagIndexMaps = new ArrayList<>();
private int[][][] tags = new int[TagRegistry.values().length][][];
@ -147,10 +148,13 @@ public final class TagCache {
/**
* @return true if the specified network ID is in the given holder set.
*/
public boolean is(HolderSet holderSet, int id, TagRegistry registry) {
return contains(holderSet.resolve(this, registry), id);
public boolean is(HolderSet holderSet, int id) {
return contains(holderSet.resolve(this), id);
}
/**
* @return the network IDs in the given tag. This can be an empty list. Vanilla tags will be resolved faster than non-vanilla ones.
*/
public int[] get(Tag tag) {
if (tag instanceof VanillaTag vanillaTag) {
return this.tags[tag.registry().ordinal()][vanillaTag.ordinal()];

View file

@ -31,6 +31,9 @@ import org.geysermc.geyser.util.MinecraftKey;
import java.util.HashMap;
import java.util.Map;
/**
* Lists vanilla block tags.
*/
@SuppressWarnings("unused")
public final class BlockTag {
public static final Map<Key, Tag> ALL_BLOCK_TAGS = new HashMap<>();

View file

@ -31,6 +31,9 @@ import org.geysermc.geyser.util.MinecraftKey;
import java.util.HashMap;
import java.util.Map;
/**
* Lists vanilla enchantment tags.
*/
@SuppressWarnings("unused")
public final class EnchantmentTag {
public static final Map<Key, Tag> ALL_ENCHANTMENT_TAGS = new HashMap<>();

View file

@ -33,39 +33,57 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.session.cache.TagCache;
/**
* Similar to vanilla Minecraft's HolderSets, stores either a tag or a list of IDs (this list can also be represented as a single ID in vanilla HolderSets).
*
* Use the {@link HolderSet#readHolderSet} method to easily read a HolderSet from NBT sent by a server. To turn the HolderSet into a list of network IDs, use the {@link HolderSet#resolve} method.
*/
@Data
public final class HolderSet {
private final @Nullable Key tagId;
private final @Nullable Tag tag;
private final int @Nullable [] holders;
public HolderSet(int @NonNull [] holders) {
this.tagId = null;
this.tag = null;
this.holders = holders;
}
public HolderSet(@NonNull Key tagId) {
this.tagId = tagId;
public HolderSet(@NonNull Tag tagId) {
this.tag = tagId;
this.holders = null;
}
public int[] resolve(TagCache tagCache, TagRegistry registry) {
/**
* Resolves the HolderSet. If the HolderSet is a list of IDs, this will be returned. If it is a tag, the tag will be resolved from the tag cache.
*
* @return the HolderSet turned into a list of network IDs.
*/
public int[] resolve(TagCache tagCache) {
if (holders != null) {
return holders;
}
return tagCache.get(Tag.createTag(registry, tagId));
assert tag != null;
return tagCache.get(tag);
}
public static HolderSet readHolderSet(@Nullable Object holderSet, Function<Key, Integer> keyIdMapping) {
/**
* Reads a HolderSet from an object from NBT.
*
* @param registry the registry the HolderSet contains IDs from.
* @param holderSet the HolderSet as an object from NBT.
* @param keyIdMapping a function that maps resource location IDs in the HolderSet's registry to their network IDs.
*/
public static HolderSet readHolderSet(TagRegistry registry, @Nullable Object holderSet, Function<Key, Integer> keyIdMapping) {
if (holderSet == null) {
return new HolderSet(new int[]{});
}
if (holderSet instanceof String stringTag) {
// Tag
if (stringTag.startsWith("#")) {
return new HolderSet(Key.key(stringTag.substring(1))); // Remove '#' at beginning that indicates tag
// Tag
return new HolderSet(Tag.createTag(registry, Key.key(stringTag.substring(1)))); // Remove '#' at beginning that indicates tag
} else if (stringTag.isEmpty()) {
return new HolderSet(new int[]{});
}

View file

@ -31,6 +31,9 @@ import org.geysermc.geyser.util.MinecraftKey;
import java.util.HashMap;
import java.util.Map;
/**
* Lists vanilla item tags.
*/
@SuppressWarnings("unused")
public final class ItemTag {
public static final Map<Key, Tag> ALL_ITEM_TAGS = new HashMap<>();

View file

@ -27,6 +27,9 @@ package org.geysermc.geyser.session.cache.tags;
import net.kyori.adventure.key.Key;
/**
* A non-vanilla tag. This can be any key in any of the registries that are stored by Geyser.
*/
public record NonVanillaTag(TagRegistry registry, Key tag) implements Tag {
}

View file

@ -27,6 +27,12 @@ package org.geysermc.geyser.session.cache.tags;
import net.kyori.adventure.key.Key;
/**
* A tag in any of the registries that are stored by Geyser.
*
* The recommended way to turn a tag key into a Tag is to use {@link Tag#createTag}.
* This ensures a {@link VanillaTag} is used when the tag key is a vanilla one, which allows for faster lookup of the tag.
*/
public interface Tag {
TagRegistry registry();

View file

@ -31,6 +31,12 @@ import net.kyori.adventure.key.Key;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.util.MinecraftKey;
/**
* Lists registries that Geyser stores tags for.
*
* When wanting to store tags from a new registry, add the registry here, and add a map for all the vanilla tags in the registry. These vanilla tags
* can be stored in a vanilla tag class, like {@link BlockTag} and {@link ItemTag}.
*/
@Getter
public enum TagRegistry {
BLOCK("block", BlockTag.ALL_BLOCK_TAGS),