Adapt for new enchantment changes

This commit is contained in:
Camotoy 2024-06-03 23:43:35 -04:00
parent 8ad10f8a9e
commit 6c245a66e2
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
23 changed files with 775 additions and 338 deletions

View file

@ -33,8 +33,8 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.item.Enchantment;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.enchantment.EnchantmentComponent;
import org.geysermc.geyser.item.type.DyeItem;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag;
@ -123,7 +123,7 @@ public class WolfEntity extends TameableEntity {
@Override
public void setChestplate(ItemStack stack) {
super.setChestplate(stack);
isCurseOfBinding = ItemUtils.getEnchantmentLevel(stack.getDataComponents(), Enchantment.JavaEnchantment.BINDING_CURSE) > 0;
isCurseOfBinding = ItemUtils.hasEffect(session, stack.getDataComponents(), EnchantmentComponent.PREVENT_ARMOR_CHANGE); // TODO test
}
@Override

View file

@ -25,12 +25,11 @@
package org.geysermc.geyser.inventory;
import lombok.Getter;
import org.cloudburstmc.protocol.bedrock.data.inventory.EnchantData;
import org.cloudburstmc.protocol.bedrock.data.inventory.EnchantOptionData;
import lombok.Getter;
import org.geysermc.geyser.session.GeyserSession;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@ -44,13 +43,13 @@ public class GeyserEnchantOption {
* is controlled by the server.
* So, of course, we have to throw in some easter eggs. ;)
*/
private static final List<String> ENCHANT_NAMES = Arrays.asList("tougher armor", "lukeeey", "fall better",
"explode less", "camo toy", "breathe better", "rtm five one six", "armor stab", "water walk", "you are elsa",
"tim two zero three", "fast walk nether", "davchoo", "oof ouch owie", "enemy on fire", "spider sad", "aj ferguson", "redned",
"more items thx", "long sword reach", "fast tool", "give me block", "less breaky break", "cube craft",
"strong arrow", "fist arrow", "spicy arrow", "many many arrows", "geyser", "come here fish", "i like this",
"stabby stab", "supreme mortal", "avatar i guess", "more arrows", "fly finder seventeen", "in and out",
"xp heals tools", "dragon proxy waz here");
private static final List<String> ENCHANT_NAMES = List.of("tougher armor", "lukeeey", "fall better",
"explode less", "camo toy", "armor stab", "breathe better", "water walk", "rtm five one six", "oof ouch owie",
"enemy on fire", "spider sad", "aj ferguson", "redned", "more items thx", "fast tool", "give me block",
"less breaky break", "cube craft", "strong arrow", "fist arrow", "spicy arrow", "many many arrows", "geyser",
"come here fish", "you are elsa", "xp heals tools", "tim two zero three", "dragon proxy waz here",
"stabby stab", "supreme mortal", "i like this", "avatar i guess", "more arrows", "in and out",
"fly finder seventeen", "fast walk nether", "davchoo", "onechris", "death bringer thirteen", "kastle");
@Getter
private final int javaIndex;
@ -62,7 +61,6 @@ public class GeyserEnchantOption {
private boolean hasChanged;
private int xpCost = 0;
private int javaEnchantIndex = -1;
private int bedrockEnchantIndex = -1;
private int enchantLevel = -1;
@ -74,7 +72,7 @@ public class GeyserEnchantOption {
this.hasChanged = false;
return new EnchantOptionData(xpCost, javaIndex + 16, EMPTY,
enchantLevel == -1 ? EMPTY : Collections.singletonList(new EnchantData(bedrockEnchantIndex, enchantLevel)), EMPTY,
javaEnchantIndex == -1 ? "unknown" : ENCHANT_NAMES.get(javaEnchantIndex), enchantLevel == -1 ? 0 : session.getNextItemNetId());
bedrockEnchantIndex == -1 ? "unknown" : ENCHANT_NAMES.get(bedrockEnchantIndex), enchantLevel == -1 ? 0 : session.getNextItemNetId());
}
public boolean hasChanged() {
@ -88,10 +86,9 @@ public class GeyserEnchantOption {
}
}
public void setEnchantIndex(int javaEnchantIndex, int bedrockEnchantIndex) {
if (this.javaEnchantIndex != javaEnchantIndex) {
public void setEnchantIndex(int bedrockEnchantIndex) {
if (this.bedrockEnchantIndex != bedrockEnchantIndex) {
hasChanged = true;
this.javaEnchantIndex = javaEnchantIndex;
this.bedrockEnchantIndex = bedrockEnchantIndex;
}
}

View file

@ -25,13 +25,11 @@
package org.geysermc.geyser.inventory.item;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Locale;
@Getter
public enum Enchantment {
public enum BedrockEnchantment {
PROTECTION,
FIRE_PROTECTION,
FEATHER_FALLING,
@ -69,18 +67,21 @@ public enum Enchantment {
PIERCING,
QUICK_CHARGE,
SOUL_SPEED,
SWIFT_SNEAK;
SWIFT_SNEAK,
WIND_BURST,
DENSITY,
BREACH;
private static final Enchantment[] VALUES = values();
private static final BedrockEnchantment[] VALUES = values();
private final String javaIdentifier;
Enchantment() {
BedrockEnchantment() {
this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ENGLISH);
}
public static @Nullable Enchantment getByJavaIdentifier(String javaIdentifier) {
for (Enchantment enchantment : VALUES) {
public static @Nullable BedrockEnchantment getByJavaIdentifier(String javaIdentifier) {
for (BedrockEnchantment enchantment : VALUES) {
if (enchantment.javaIdentifier.equals(javaIdentifier) || enchantment.name().toLowerCase(Locale.ENGLISH).equalsIgnoreCase(javaIdentifier)) {
return enchantment;
}
@ -88,7 +89,7 @@ public enum Enchantment {
return null;
}
public static @Nullable Enchantment getByBedrockId(int bedrockId) {
public static @Nullable BedrockEnchantment getByBedrockId(int bedrockId) {
if (bedrockId >= 0 && bedrockId < VALUES.length) {
return VALUES[bedrockId];
}
@ -141,35 +142,5 @@ public enum Enchantment {
WIND_BURST,
MENDING,
VANISHING_CURSE;
private static final JavaEnchantment[] VALUES = JavaEnchantment.values();
public static JavaEnchantment of(int index) {
return VALUES[index];
}
/**
* A list of all enchantment Java identifiers for use with command suggestions.
*/
public static final String[] ALL_JAVA_IDENTIFIERS;
public static @Nullable JavaEnchantment getByJavaIdentifier(String javaIdentifier) {
if (!javaIdentifier.startsWith("minecraft:")) {
javaIdentifier = "minecraft:" + javaIdentifier;
}
for (int i = 0; i < ALL_JAVA_IDENTIFIERS.length; i++) {
if (ALL_JAVA_IDENTIFIERS[i].equalsIgnoreCase(javaIdentifier)) {
return VALUES[i];
}
}
return null;
}
static {
ALL_JAVA_IDENTIFIERS = new String[VALUES.length];
for (int i = 0; i < ALL_JAVA_IDENTIFIERS.length; i++) {
ALL_JAVA_IDENTIFIERS[i] = "minecraft:" + VALUES[i].name().toLowerCase(Locale.ENGLISH);
}
}
}
}

View file

@ -26,7 +26,6 @@
package org.geysermc.geyser.inventory.updater;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntMaps;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import net.kyori.adventure.text.Component;
import org.cloudburstmc.nbt.NbtMap;
@ -38,10 +37,9 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.AnvilContainer;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
import org.geysermc.geyser.inventory.item.BedrockEnchantment;
import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.EnchantmentData;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.translator.text.MessageTranslator;
@ -307,18 +305,17 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
*/
private int calcMergeEnchantmentCost(GeyserSession session, GeyserItemStack input, GeyserItemStack material, boolean bedrock) {
boolean hasCompatible = false;
Object2IntMap<JavaEnchantment> combinedEnchantments = getEnchantments(input);
Object2IntMap<Enchantment> combinedEnchantments = getEnchantments(session, input);
int cost = 0;
for (Object2IntMap.Entry<JavaEnchantment> entry : getEnchantments(material).object2IntEntrySet()) {
JavaEnchantment enchantment = entry.getKey();
EnchantmentData data = Registries.ENCHANTMENTS.get(enchantment);
if (data == null) {
GeyserImpl.getInstance().getLogger().debug("Java enchantment not in registry: " + enchantment);
continue;
}
for (Object2IntMap.Entry<Enchantment> entry : getEnchantments(session, material).object2IntEntrySet()) {
Enchantment enchantment = entry.getKey();
boolean canApply = isEnchantedBook(input) || data.validItems().contains(input.getJavaId());
for (JavaEnchantment incompatible : data.incompatibleEnchantments()) {
boolean canApply = isEnchantedBook(input) || session.getTagCache().is(enchantment.supportedItems(), input);
var exclusiveSet = enchantment.exclusiveSet();
if (exclusiveSet != null) {
int[] incompatibleEnchantments = session.getTagCache().get(exclusiveSet);
for (int i : incompatibleEnchantments) {
Enchantment incompatible = session.getRegistryCache().enchantments().byId(i);
if (combinedEnchantments.containsKey(incompatible)) {
canApply = false;
if (!bedrock) {
@ -326,6 +323,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
}
}
}
}
if (canApply || (!bedrock && session.getGameMode() == GameMode.CREATIVE)) {
int currentLevel = combinedEnchantments.getOrDefault(enchantment, 0);
@ -334,12 +332,12 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
newLevel++;
}
newLevel = Math.max(currentLevel, newLevel);
if (newLevel > data.maxLevel()) {
newLevel = data.maxLevel();
if (newLevel > enchantment.maxLevel()) {
newLevel = enchantment.maxLevel();
}
combinedEnchantments.put(enchantment, newLevel);
int rarityMultiplier = data.rarityMultiplier();
int rarityMultiplier = enchantment.anvilCost();
if (isEnchantedBook(material) && rarityMultiplier > 1) {
rarityMultiplier /= 2;
}
@ -347,11 +345,11 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
if (newLevel > currentLevel) {
hasCompatible = true;
}
if (enchantment == JavaEnchantment.IMPALING) {
if (enchantment.bedrockEnchantment() == BedrockEnchantment.IMPALING) {
// Multiplier is halved on Bedrock for some reason
rarityMultiplier /= 2;
} else if (enchantment == JavaEnchantment.SWEEPING_EDGE) {
// Doesn't exist on Bedrock
} else if (enchantment.bedrockEnchantment() == null) {
// Whatever this is, doesn't exist on Bedrock
rarityMultiplier = 0;
}
cost += rarityMultiplier * (newLevel - currentLevel);
@ -368,7 +366,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
return cost;
}
private Object2IntMap<JavaEnchantment> getEnchantments(GeyserItemStack itemStack) {
private Object2IntMap<Enchantment> getEnchantments(GeyserSession session, GeyserItemStack itemStack) {
ItemEnchantments enchantmentComponent;
if (isEnchantedBook(itemStack)) {
enchantmentComponent = itemStack.getComponent(DataComponentType.STORED_ENCHANTMENTS);
@ -376,9 +374,9 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
enchantmentComponent = itemStack.getComponent(DataComponentType.ENCHANTMENTS);
}
if (enchantmentComponent != null) {
Object2IntMap<JavaEnchantment> enchantments = new Object2IntOpenHashMap<>();
Object2IntMap<Enchantment> enchantments = new Object2IntOpenHashMap<>();
for (Map.Entry<Integer, Integer> entry : enchantmentComponent.getEnchantments().entrySet()) {
JavaEnchantment enchantment = JavaEnchantment.of(entry.getKey());
Enchantment enchantment = session.getRegistryCache().enchantments().byId(entry.getKey());
if (enchantment == null) {
GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment in anvil: " + entry.getKey());
continue;

View file

@ -0,0 +1,90 @@
/*
* Copyright (c) 2024 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.item.enchantment;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtMap;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.item.BedrockEnchantment;
import org.geysermc.geyser.session.cache.tags.EnchantmentTag;
import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry;
import java.util.*;
/**
* @param description only populated if {@link #bedrockEnchantment()} is not null.
* @param anvilCost also as a rarity multiplier
*/
public record Enchantment(String identifier,
Set<EnchantmentComponent> effects,
ItemTag supportedItems,
int maxLevel,
String description,
int anvilCost,
@Nullable EnchantmentTag exclusiveSet,
@Nullable BedrockEnchantment bedrockEnchantment) {
// Implementation note: I have a feeling the tags can be a list of items, because in vanilla they're HolderSet classes.
// I'm not sure how that's wired over the network, so we'll put it off.
public static Enchantment read(RegistryEntry entry) {
NbtMap data = entry.getData();
Set<EnchantmentComponent> effects = readEnchantmentComponents(data.getCompound("effects"));
String supportedItems = data.getString("supported_items").substring(1); // Remove '#' at beginning that indicates tag
int maxLevel = data.getInt("max_level");
int anvilCost = data.getInt("anvil_cost");
String exclusiveSet = data.getString("exclusive_set", null);
EnchantmentTag exclusiveSetTag = exclusiveSet == null ? null : EnchantmentTag.ALL_ENCHANTMENT_TAGS.get(exclusiveSet.substring(1));
BedrockEnchantment bedrockEnchantment = BedrockEnchantment.getByJavaIdentifier(entry.getId());
String description = bedrockEnchantment == null ? readDescription(data) : null;
return new Enchantment(entry.getId(), effects, ItemTag.ALL_ITEM_TAGS.get(supportedItems), maxLevel,
description, anvilCost, exclusiveSetTag, bedrockEnchantment);
}
private static Set<EnchantmentComponent> readEnchantmentComponents(NbtMap effects) {
if (effects.isEmpty()) {
return Collections.emptySet();
}
Set<EnchantmentComponent> components = new HashSet<>();
for (Map.Entry<String, Object> entry : effects.entrySet()) {
switch (entry.getKey()) {
case "minecraft:prevent_armor_change" -> components.add(EnchantmentComponent.PREVENT_ARMOR_CHANGE);
}
}
return components;
}
private static String readDescription(NbtMap tag) {
NbtMap description = tag.getCompound("description");
String translate = description.getString("translate", null);
if (translate == null) {
GeyserImpl.getInstance().getLogger().debug("Don't know how to read description! " + tag);
return "";
}
return translate;
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2024 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.item.enchantment;
public class EnchantmentComponent {
/**
* Singleton with no additional data
*/
public static final EnchantmentComponent PREVENT_ARMOR_CHANGE = new EnchantmentComponent();
}

View file

@ -31,7 +31,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.item.Enchantment;
import org.geysermc.geyser.inventory.item.BedrockEnchantment;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
@ -78,11 +78,11 @@ public class EnchantedBookItem extends Item {
for (NbtMap bedrockEnchantment : enchantmentTag) {
short bedrockId = bedrockEnchantment.getShort("id");
Enchantment enchantment = Enchantment.getByBedrockId(bedrockId);
BedrockEnchantment enchantment = BedrockEnchantment.getByBedrockId(bedrockId);
if (enchantment != null) {
int level = bedrockEnchantment.getShort("lvl", (short) 1);
// TODO
javaEnchantments.put(Enchantment.JavaEnchantment.valueOf(enchantment.name()).ordinal(), level);
//javaEnchantments.put(BedrockEnchantment.JavaEnchantment.valueOf(enchantment.name()).ordinal(), level);
} else {
GeyserImpl.getInstance().getLogger().debug("Unknown bedrock enchantment: " + bedrockId);
}

View file

@ -33,8 +33,9 @@ import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.item.Enchantment;
import org.geysermc.geyser.inventory.item.BedrockEnchantment;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
@ -201,7 +202,7 @@ public class Item {
// ShortTag bedrockId = tagValue.get("id");
// if (bedrockId == null) continue;
//
// Enchantment enchantment = Enchantment.getByBedrockId(bedrockId.getValue());
// BedrockEnchantment enchantment = BedrockEnchantment.getByBedrockId(bedrockId.getValue());
// if (enchantment != null) {
// CompoundTag javaTag = new CompoundTag("");
// Map<String, Tag> javaValue = javaTag.getValue();
@ -226,33 +227,22 @@ public class Item {
// }
}
/**
* This is a map from Java-only enchantments to their translation keys so that we can
* map these enchantments to Bedrock clients, since they don't actually exist there.
*/
private static final Map<Enchantment.JavaEnchantment, String> ENCHANTMENT_TRANSLATION_KEYS = Map.of(
Enchantment.JavaEnchantment.SWEEPING_EDGE, "enchantment.minecraft.sweeping",
Enchantment.JavaEnchantment.DENSITY, "enchantment.minecraft.density",
Enchantment.JavaEnchantment.BREACH, "enchantment.minecraft.breach",
Enchantment.JavaEnchantment.WIND_BURST, "enchantment.minecraft.wind_burst");
protected final @Nullable NbtMap remapEnchantment(GeyserSession session, int enchantId, int level, BedrockItemBuilder builder) {
// TODO verify
// TODO streamline Enchantment process
Enchantment.JavaEnchantment enchantment = Enchantment.JavaEnchantment.of(enchantId);
String translationKey = ENCHANTMENT_TRANSLATION_KEYS.get(enchantment);
if (translationKey != null) {
String enchantmentTranslation = MinecraftLocale.getLocaleString(translationKey, session.locale());
addJavaOnlyEnchantment(session, builder, enchantmentTranslation, level);
return null;
}
Enchantment enchantment = session.getRegistryCache().enchantments().byId(enchantId);
if (enchantment == null) {
GeyserImpl.getInstance().getLogger().debug("Unknown Java enchantment while NBT item translating: " + enchantId);
return null;
}
BedrockEnchantment bedrockEnchantment = enchantment.bedrockEnchantment();
if (bedrockEnchantment == null) {
String enchantmentTranslation = MinecraftLocale.getLocaleString(enchantment.description(), session.locale());
addJavaOnlyEnchantment(session, builder, enchantmentTranslation, level);
return null;
}
return NbtMap.builder()
.putShort("id", (short) Enchantment.valueOf(enchantment.name()).ordinal())
.putShort("id", (short) bedrockEnchantment.ordinal())
.putShort("lvl", (short) level)
.build();
}
@ -260,7 +250,7 @@ public class Item {
private void addJavaOnlyEnchantment(GeyserSession session, BedrockItemBuilder builder, String enchantmentName, int level) {
String lvlTranslation = MinecraftLocale.getLocaleString("enchantment.level." + level, session.locale());
builder.getOrCreateLore().add(ChatColor.RESET + ChatColor.GRAY + enchantmentName + " " + lvlTranslation);
builder.getOrCreateLore().add(0, ChatColor.RESET + ChatColor.GRAY + enchantmentName + " " + lvlTranslation);
}
/* Translation methods end */

View file

@ -25,12 +25,6 @@
package org.geysermc.geyser.registry;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent;
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.RecipeType;
import org.geysermc.mcprotocollib.network.packet.Packet;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
@ -43,7 +37,6 @@ import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.pack.ResourcePack;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.loader.*;
@ -51,7 +44,6 @@ import org.geysermc.geyser.registry.populator.ItemRegistryPopulator;
import org.geysermc.geyser.registry.populator.PacketRegistryPopulator;
import org.geysermc.geyser.registry.populator.RecipeRegistryPopulator;
import org.geysermc.geyser.registry.provider.ProviderSupplier;
import org.geysermc.geyser.registry.type.EnchantmentData;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.registry.type.ParticleMapping;
import org.geysermc.geyser.registry.type.SoundMapping;
@ -59,6 +51,12 @@ import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
import org.geysermc.geyser.translator.level.event.LevelEventTranslator;
import org.geysermc.geyser.translator.sound.SoundInteractionTranslator;
import org.geysermc.geyser.translator.sound.SoundTranslator;
import org.geysermc.mcprotocollib.network.packet.Packet;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent;
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.RecipeType;
import java.util.*;
@ -102,11 +100,6 @@ public final class Registries {
*/
public static final VersionedRegistry<Map<RecipeType, List<RecipeData>>> CRAFTING_DATA = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new));
/**
* A registry holding data of all the known enchantments.
*/
public static final SimpleMappedRegistry<JavaEnchantment, EnchantmentData> ENCHANTMENTS;
/**
* A map containing all entity types and their respective Geyser definitions
*/
@ -127,7 +120,10 @@ public final class Registries {
*/
public static final PacketTranslatorRegistry<Packet> JAVA_PACKET_TRANSLATORS = PacketTranslatorRegistry.create();
public static final SimpleRegistry<List<Item>> JAVA_ITEMS = SimpleRegistry.create(RegistryLoaders.empty(ArrayList::new));
/**
* A registry containing all Java items ordered by their network ID.
*/
public static final ListRegistry<Item> JAVA_ITEMS = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
public static final SimpleMappedRegistry<String, Item> JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
@ -190,7 +186,6 @@ public final class Registries {
// Create registries that require other registries to load first
POTION_MIXES = VersionedRegistry.create(PotionMixRegistryLoader::new);
ENCHANTMENTS = SimpleMappedRegistry.create("mappings/enchantments.json", EnchantmentRegistryLoader::new);
// Remove unneeded client generation data from NbtMapBuilder
NbtMapBuilder biomesNbt = NbtMap.builder();

View file

@ -1,86 +0,0 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.registry.loader;
import com.fasterxml.jackson.databind.JsonNode;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.EnchantmentData;
import java.io.InputStream;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Map;
public class EnchantmentRegistryLoader implements RegistryLoader<String, Map<JavaEnchantment, EnchantmentData>> {
@Override
public Map<JavaEnchantment, EnchantmentData> load(String input) {
JsonNode enchantmentsNode;
try (InputStream enchantmentsStream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input)) {
enchantmentsNode = GeyserImpl.JSON_MAPPER.readTree(enchantmentsStream);
} catch (Exception e) {
throw new AssertionError("Unable to load enchantment data", e);
}
Map<JavaEnchantment, EnchantmentData> enchantments = new EnumMap<>(JavaEnchantment.class);
Iterator<Map.Entry<String, JsonNode>> it = enchantmentsNode.fields();
while (it.hasNext()) {
Map.Entry<String, JsonNode> entry = it.next();
JavaEnchantment key = JavaEnchantment.getByJavaIdentifier(entry.getKey());
JsonNode node = entry.getValue();
int rarityMultiplier = node.get("anvil_cost").asInt();
int maxLevel = node.get("max_level").asInt();
EnumSet<JavaEnchantment> incompatibleEnchantments = EnumSet.noneOf(JavaEnchantment.class);
JsonNode incompatibleEnchantmentsNode = node.get("incompatible_enchantments");
if (incompatibleEnchantmentsNode != null) {
for (JsonNode incompatibleNode : incompatibleEnchantmentsNode) {
incompatibleEnchantments.add(JavaEnchantment.getByJavaIdentifier(incompatibleNode.textValue()));
}
}
IntSet validItems = new IntOpenHashSet();
for (JsonNode itemNode : node.get("valid_items")) {
String javaIdentifier = itemNode.textValue();
Item item = Registries.JAVA_ITEM_IDENTIFIERS.get(javaIdentifier);
if (item != null) {
validItems.add(item.javaId());
} else {
throw new NullPointerException("No item entry exists for java identifier: " + javaIdentifier);
}
}
EnchantmentData enchantmentData = new EnchantmentData(rarityMultiplier, maxLevel, incompatibleEnchantments, validItems);
enchantments.put(key, enchantmentData);
}
return enchantments;
}
}

View file

@ -26,7 +26,7 @@
package org.geysermc.geyser.registry.type;
import it.unimi.dsi.fastutil.ints.IntSet;
import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
import org.geysermc.geyser.inventory.item.BedrockEnchantment.JavaEnchantment;
import java.util.Set;

View file

@ -1307,7 +1307,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
*/
public void useItem(Hand hand) {
sendDownstreamGamePacket(new ServerboundUseItemPacket(
hand, worldCache.nextPredictionSequence(), playerEntity.getPitch(), playerEntity.getYaw()));
hand, worldCache.nextPredictionSequence(), playerEntity.getYaw(), playerEntity.getPitch()));
}
/**

View file

@ -38,7 +38,7 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.entity.type.living.animal.tameable.WolfEntity;
import org.geysermc.geyser.inventory.item.BannerPattern;
import org.geysermc.geyser.inventory.recipe.TrimRecipe;
import org.geysermc.geyser.item.Enchantment;
import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.level.JavaDimension;
import org.geysermc.geyser.level.PaintingType;
import org.geysermc.geyser.session.GeyserSession;

View file

@ -25,47 +25,40 @@
package org.geysermc.geyser.session.cache;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntArrays;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.BlockTag;
import org.geysermc.geyser.session.cache.tags.EnchantmentTag;
import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.util.Ordered;
import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Arrays;
import java.util.Map;
import static org.geysermc.geyser.session.cache.tags.BlockTag.ALL_BLOCK_TAGS;
import static org.geysermc.geyser.session.cache.tags.EnchantmentTag.ALL_ENCHANTMENT_TAGS;
import static org.geysermc.geyser.session.cache.tags.ItemTag.ALL_ITEM_TAGS;
/**
* Manages information sent from the {@link ClientboundUpdateTagsPacket}. If that packet is not sent, all lists here
* will remain empty, matching Java Edition behavior.
*
* This system is designed for easy extensibility - just add an enum to {@link BlockTag} or {@link ItemTag}.
*/
@ParametersAreNonnullByDefault
public final class TagCache {
// Put these here so the enums can load without a static map
public static final Map<String, BlockTag> ALL_BLOCK_TAGS = new HashMap<>();
public static final Map<String, ItemTag> ALL_ITEM_TAGS = new HashMap<>();
private final Map<BlockTag, IntList> blocks = new EnumMap<>(BlockTag.class);
private final Map<ItemTag, IntList> items = new EnumMap<>(ItemTag.class);
private final int[][] blocks = new int[ALL_BLOCK_TAGS.size()][];
private final int[][] items = new int[ALL_ITEM_TAGS.size()][];
private final int[][] enchantments = new int[ALL_ENCHANTMENT_TAGS.size()][];
public void loadPacket(GeyserSession session, ClientboundUpdateTagsPacket packet) {
Map<String, int[]> blockTags = packet.getTags().get("minecraft:block");
this.blocks.clear();
ALL_BLOCK_TAGS.forEach((location, tag) -> {
int[] values = blockTags.get(location);
if (values != null) {
this.blocks.put(tag, IntList.of(values));
} else {
session.getGeyser().getLogger().debug("Block tag not found from server: " + location);
}
});
loadTags("Block", blockTags, ALL_BLOCK_TAGS, this.blocks);
// Hack btw
GeyserLogger logger = session.getGeyser().getLogger();
@ -77,15 +70,7 @@ public final class TagCache {
}
Map<String, int[]> itemTags = packet.getTags().get("minecraft:item");
this.items.clear();
ALL_ITEM_TAGS.forEach((location, tag) -> {
int[] values = itemTags.get(location);
if (values != null) {
this.items.put(tag, IntList.of(values));
} else {
session.getGeyser().getLogger().debug("Item tag not found from server: " + location);
}
});
loadTags("Item", itemTags, ALL_ITEM_TAGS, this.items);
// Hack btw
boolean emulatePost1_13Logic = itemTags.get("minecraft:signs").length > 1;
@ -93,17 +78,31 @@ public final class TagCache {
if (logger.isDebug()) {
logger.debug("Emulating post 1.13 villager logic for " + session.bedrockUsername() + "? " + emulatePost1_13Logic);
}
Map<String, int[]> enchantmentTags = packet.getTags().get("minecraft:enchantment");
loadTags("Enchantment", enchantmentTags, ALL_ENCHANTMENT_TAGS, this.enchantments);
}
private <T extends Ordered> void loadTags(String type, Map<String, int[]> packetTags, Map<String, T> allTags, int[][] localValues) {
Arrays.fill(localValues, IntArrays.EMPTY_ARRAY);
allTags.forEach((location, tag) -> {
int[] values = packetTags.get(location);
if (values != null) {
if (values.length != 0) {
localValues[tag.ordinal()] = values;
}
} else {
GeyserImpl.getInstance().getLogger().debug(type + " tag not found from server: " + location);
}
});
}
/**
* @return true if the block tag is present and contains this block mapping's Java ID.
*/
public boolean is(BlockTag tag, Block block) {
IntList values = this.blocks.get(tag);
if (values != null) {
return values.contains(block.javaId());
}
return false;
int[] values = this.blocks[tag.ordinal()];
return contains(values, block.javaId());
}
/**
@ -117,9 +116,19 @@ public final class TagCache {
* @return true if the item tag is present and contains this item's Java ID.
*/
public boolean is(ItemTag tag, Item item) {
IntList values = this.items.get(tag);
if (values != null) {
return values.contains(item.javaId());
int[] values = this.items[tag.ordinal()];
return contains(values, item.javaId());
}
public int[] get(EnchantmentTag tag) {
return this.enchantments[tag.ordinal()];
}
private static boolean contains(int[] array, int i) {
for (int item : array) {
if (item == i) {
return true;
}
}
return false;
}

View file

@ -25,24 +25,212 @@
package org.geysermc.geyser.session.cache.tags;
import org.geysermc.geyser.session.cache.TagCache;
import org.geysermc.geyser.util.Ordered;
public enum BlockTag {
LEAVES("leaves"),
WOOL("wool"),
AXE_EFFECTIVE("mineable/axe"),
HOE_EFFECTIVE("mineable/hoe"),
PICKAXE_EFFECTIVE("mineable/pickaxe"),
SHOVEL_EFFECTIVE("mineable/shovel"),
NEEDS_STONE_TOOL("needs_stone_tool"),
NEEDS_IRON_TOOL("needs_iron_tool"),
NEEDS_DIAMOND_TOOL("needs_diamond_tool");
import java.util.HashMap;
import java.util.Map;
BlockTag(String identifier) {
@SuppressWarnings("unused")
public final class BlockTag implements Ordered {
public static final Map<String, BlockTag> ALL_BLOCK_TAGS = new HashMap<>();
public static final BlockTag WOOL = new BlockTag("wool");
public static final BlockTag PLANKS = new BlockTag("planks");
public static final BlockTag STONE_BRICKS = new BlockTag("stone_bricks");
public static final BlockTag WOODEN_BUTTONS = new BlockTag("wooden_buttons");
public static final BlockTag STONE_BUTTONS = new BlockTag("stone_buttons");
public static final BlockTag BUTTONS = new BlockTag("buttons");
public static final BlockTag WOOL_CARPETS = new BlockTag("wool_carpets");
public static final BlockTag WOODEN_DOORS = new BlockTag("wooden_doors");
public static final BlockTag WOODEN_STAIRS = new BlockTag("wooden_stairs");
public static final BlockTag WOODEN_SLABS = new BlockTag("wooden_slabs");
public static final BlockTag WOODEN_FENCES = new BlockTag("wooden_fences");
public static final BlockTag PRESSURE_PLATES = new BlockTag("pressure_plates");
public static final BlockTag WOODEN_PRESSURE_PLATES = new BlockTag("wooden_pressure_plates");
public static final BlockTag STONE_PRESSURE_PLATES = new BlockTag("stone_pressure_plates");
public static final BlockTag WOODEN_TRAPDOORS = new BlockTag("wooden_trapdoors");
public static final BlockTag DOORS = new BlockTag("doors");
public static final BlockTag SAPLINGS = new BlockTag("saplings");
public static final BlockTag LOGS_THAT_BURN = new BlockTag("logs_that_burn");
public static final BlockTag OVERWORLD_NATURAL_LOGS = new BlockTag("overworld_natural_logs");
public static final BlockTag LOGS = new BlockTag("logs");
public static final BlockTag DARK_OAK_LOGS = new BlockTag("dark_oak_logs");
public static final BlockTag OAK_LOGS = new BlockTag("oak_logs");
public static final BlockTag BIRCH_LOGS = new BlockTag("birch_logs");
public static final BlockTag ACACIA_LOGS = new BlockTag("acacia_logs");
public static final BlockTag CHERRY_LOGS = new BlockTag("cherry_logs");
public static final BlockTag JUNGLE_LOGS = new BlockTag("jungle_logs");
public static final BlockTag SPRUCE_LOGS = new BlockTag("spruce_logs");
public static final BlockTag MANGROVE_LOGS = new BlockTag("mangrove_logs");
public static final BlockTag CRIMSON_STEMS = new BlockTag("crimson_stems");
public static final BlockTag WARPED_STEMS = new BlockTag("warped_stems");
public static final BlockTag BAMBOO_BLOCKS = new BlockTag("bamboo_blocks");
public static final BlockTag WART_BLOCKS = new BlockTag("wart_blocks");
public static final BlockTag BANNERS = new BlockTag("banners");
public static final BlockTag SAND = new BlockTag("sand");
public static final BlockTag SMELTS_TO_GLASS = new BlockTag("smelts_to_glass");
public static final BlockTag STAIRS = new BlockTag("stairs");
public static final BlockTag SLABS = new BlockTag("slabs");
public static final BlockTag WALLS = new BlockTag("walls");
public static final BlockTag ANVIL = new BlockTag("anvil");
public static final BlockTag RAILS = new BlockTag("rails");
public static final BlockTag LEAVES = new BlockTag("leaves");
public static final BlockTag TRAPDOORS = new BlockTag("trapdoors");
public static final BlockTag SMALL_FLOWERS = new BlockTag("small_flowers");
public static final BlockTag BEDS = new BlockTag("beds");
public static final BlockTag FENCES = new BlockTag("fences");
public static final BlockTag TALL_FLOWERS = new BlockTag("tall_flowers");
public static final BlockTag FLOWERS = new BlockTag("flowers");
public static final BlockTag PIGLIN_REPELLENTS = new BlockTag("piglin_repellents");
public static final BlockTag GOLD_ORES = new BlockTag("gold_ores");
public static final BlockTag IRON_ORES = new BlockTag("iron_ores");
public static final BlockTag DIAMOND_ORES = new BlockTag("diamond_ores");
public static final BlockTag REDSTONE_ORES = new BlockTag("redstone_ores");
public static final BlockTag LAPIS_ORES = new BlockTag("lapis_ores");
public static final BlockTag COAL_ORES = new BlockTag("coal_ores");
public static final BlockTag EMERALD_ORES = new BlockTag("emerald_ores");
public static final BlockTag COPPER_ORES = new BlockTag("copper_ores");
public static final BlockTag CANDLES = new BlockTag("candles");
public static final BlockTag DIRT = new BlockTag("dirt");
public static final BlockTag TERRACOTTA = new BlockTag("terracotta");
public static final BlockTag BADLANDS_TERRACOTTA = new BlockTag("badlands_terracotta");
public static final BlockTag CONCRETE_POWDER = new BlockTag("concrete_powder");
public static final BlockTag COMPLETES_FIND_TREE_TUTORIAL = new BlockTag("completes_find_tree_tutorial");
public static final BlockTag FLOWER_POTS = new BlockTag("flower_pots");
public static final BlockTag ENDERMAN_HOLDABLE = new BlockTag("enderman_holdable");
public static final BlockTag ICE = new BlockTag("ice");
public static final BlockTag VALID_SPAWN = new BlockTag("valid_spawn");
public static final BlockTag IMPERMEABLE = new BlockTag("impermeable");
public static final BlockTag UNDERWATER_BONEMEALS = new BlockTag("underwater_bonemeals");
public static final BlockTag CORAL_BLOCKS = new BlockTag("coral_blocks");
public static final BlockTag WALL_CORALS = new BlockTag("wall_corals");
public static final BlockTag CORAL_PLANTS = new BlockTag("coral_plants");
public static final BlockTag CORALS = new BlockTag("corals");
public static final BlockTag BAMBOO_PLANTABLE_ON = new BlockTag("bamboo_plantable_on");
public static final BlockTag STANDING_SIGNS = new BlockTag("standing_signs");
public static final BlockTag WALL_SIGNS = new BlockTag("wall_signs");
public static final BlockTag SIGNS = new BlockTag("signs");
public static final BlockTag CEILING_HANGING_SIGNS = new BlockTag("ceiling_hanging_signs");
public static final BlockTag WALL_HANGING_SIGNS = new BlockTag("wall_hanging_signs");
public static final BlockTag ALL_HANGING_SIGNS = new BlockTag("all_hanging_signs");
public static final BlockTag ALL_SIGNS = new BlockTag("all_signs");
public static final BlockTag DRAGON_IMMUNE = new BlockTag("dragon_immune");
public static final BlockTag DRAGON_TRANSPARENT = new BlockTag("dragon_transparent");
public static final BlockTag WITHER_IMMUNE = new BlockTag("wither_immune");
public static final BlockTag WITHER_SUMMON_BASE_BLOCKS = new BlockTag("wither_summon_base_blocks");
public static final BlockTag BEEHIVES = new BlockTag("beehives");
public static final BlockTag CROPS = new BlockTag("crops");
public static final BlockTag BEE_GROWABLES = new BlockTag("bee_growables");
public static final BlockTag PORTALS = new BlockTag("portals");
public static final BlockTag FIRE = new BlockTag("fire");
public static final BlockTag NYLIUM = new BlockTag("nylium");
public static final BlockTag BEACON_BASE_BLOCKS = new BlockTag("beacon_base_blocks");
public static final BlockTag SOUL_SPEED_BLOCKS = new BlockTag("soul_speed_blocks");
public static final BlockTag WALL_POST_OVERRIDE = new BlockTag("wall_post_override");
public static final BlockTag CLIMBABLE = new BlockTag("climbable");
public static final BlockTag FALL_DAMAGE_RESETTING = new BlockTag("fall_damage_resetting");
public static final BlockTag SHULKER_BOXES = new BlockTag("shulker_boxes");
public static final BlockTag HOGLIN_REPELLENTS = new BlockTag("hoglin_repellents");
public static final BlockTag SOUL_FIRE_BASE_BLOCKS = new BlockTag("soul_fire_base_blocks");
public static final BlockTag STRIDER_WARM_BLOCKS = new BlockTag("strider_warm_blocks");
public static final BlockTag CAMPFIRES = new BlockTag("campfires");
public static final BlockTag GUARDED_BY_PIGLINS = new BlockTag("guarded_by_piglins");
public static final BlockTag PREVENT_MOB_SPAWNING_INSIDE = new BlockTag("prevent_mob_spawning_inside");
public static final BlockTag FENCE_GATES = new BlockTag("fence_gates");
public static final BlockTag UNSTABLE_BOTTOM_CENTER = new BlockTag("unstable_bottom_center");
public static final BlockTag MUSHROOM_GROW_BLOCK = new BlockTag("mushroom_grow_block");
public static final BlockTag INFINIBURN_OVERWORLD = new BlockTag("infiniburn_overworld");
public static final BlockTag INFINIBURN_NETHER = new BlockTag("infiniburn_nether");
public static final BlockTag INFINIBURN_END = new BlockTag("infiniburn_end");
public static final BlockTag BASE_STONE_OVERWORLD = new BlockTag("base_stone_overworld");
public static final BlockTag STONE_ORE_REPLACEABLES = new BlockTag("stone_ore_replaceables");
public static final BlockTag DEEPSLATE_ORE_REPLACEABLES = new BlockTag("deepslate_ore_replaceables");
public static final BlockTag BASE_STONE_NETHER = new BlockTag("base_stone_nether");
public static final BlockTag OVERWORLD_CARVER_REPLACEABLES = new BlockTag("overworld_carver_replaceables");
public static final BlockTag NETHER_CARVER_REPLACEABLES = new BlockTag("nether_carver_replaceables");
public static final BlockTag CANDLE_CAKES = new BlockTag("candle_cakes");
public static final BlockTag CAULDRONS = new BlockTag("cauldrons");
public static final BlockTag CRYSTAL_SOUND_BLOCKS = new BlockTag("crystal_sound_blocks");
public static final BlockTag INSIDE_STEP_SOUND_BLOCKS = new BlockTag("inside_step_sound_blocks");
public static final BlockTag COMBINATION_STEP_SOUND_BLOCKS = new BlockTag("combination_step_sound_blocks");
public static final BlockTag CAMEL_SAND_STEP_SOUND_BLOCKS = new BlockTag("camel_sand_step_sound_blocks");
public static final BlockTag OCCLUDES_VIBRATION_SIGNALS = new BlockTag("occludes_vibration_signals");
public static final BlockTag DAMPENS_VIBRATIONS = new BlockTag("dampens_vibrations");
public static final BlockTag DRIPSTONE_REPLACEABLE_BLOCKS = new BlockTag("dripstone_replaceable_blocks");
public static final BlockTag CAVE_VINES = new BlockTag("cave_vines");
public static final BlockTag MOSS_REPLACEABLE = new BlockTag("moss_replaceable");
public static final BlockTag LUSH_GROUND_REPLACEABLE = new BlockTag("lush_ground_replaceable");
public static final BlockTag AZALEA_ROOT_REPLACEABLE = new BlockTag("azalea_root_replaceable");
public static final BlockTag SMALL_DRIPLEAF_PLACEABLE = new BlockTag("small_dripleaf_placeable");
public static final BlockTag BIG_DRIPLEAF_PLACEABLE = new BlockTag("big_dripleaf_placeable");
public static final BlockTag SNOW = new BlockTag("snow");
public static final BlockTag MINEABLE_AXE = new BlockTag("mineable/axe");
public static final BlockTag MINEABLE_HOE = new BlockTag("mineable/hoe");
public static final BlockTag MINEABLE_PICKAXE = new BlockTag("mineable/pickaxe");
public static final BlockTag MINEABLE_SHOVEL = new BlockTag("mineable/shovel");
public static final BlockTag SWORD_EFFICIENT = new BlockTag("sword_efficient");
public static final BlockTag NEEDS_DIAMOND_TOOL = new BlockTag("needs_diamond_tool");
public static final BlockTag NEEDS_IRON_TOOL = new BlockTag("needs_iron_tool");
public static final BlockTag NEEDS_STONE_TOOL = new BlockTag("needs_stone_tool");
public static final BlockTag INCORRECT_FOR_NETHERITE_TOOL = new BlockTag("incorrect_for_netherite_tool");
public static final BlockTag INCORRECT_FOR_DIAMOND_TOOL = new BlockTag("incorrect_for_diamond_tool");
public static final BlockTag INCORRECT_FOR_IRON_TOOL = new BlockTag("incorrect_for_iron_tool");
public static final BlockTag INCORRECT_FOR_STONE_TOOL = new BlockTag("incorrect_for_stone_tool");
public static final BlockTag INCORRECT_FOR_GOLD_TOOL = new BlockTag("incorrect_for_gold_tool");
public static final BlockTag INCORRECT_FOR_WOODEN_TOOL = new BlockTag("incorrect_for_wooden_tool");
public static final BlockTag FEATURES_CANNOT_REPLACE = new BlockTag("features_cannot_replace");
public static final BlockTag LAVA_POOL_STONE_CANNOT_REPLACE = new BlockTag("lava_pool_stone_cannot_replace");
public static final BlockTag GEODE_INVALID_BLOCKS = new BlockTag("geode_invalid_blocks");
public static final BlockTag FROG_PREFER_JUMP_TO = new BlockTag("frog_prefer_jump_to");
public static final BlockTag SCULK_REPLACEABLE = new BlockTag("sculk_replaceable");
public static final BlockTag SCULK_REPLACEABLE_WORLD_GEN = new BlockTag("sculk_replaceable_world_gen");
public static final BlockTag ANCIENT_CITY_REPLACEABLE = new BlockTag("ancient_city_replaceable");
public static final BlockTag VIBRATION_RESONATORS = new BlockTag("vibration_resonators");
public static final BlockTag ANIMALS_SPAWNABLE_ON = new BlockTag("animals_spawnable_on");
public static final BlockTag ARMADILLO_SPAWNABLE_ON = new BlockTag("armadillo_spawnable_on");
public static final BlockTag AXOLOTLS_SPAWNABLE_ON = new BlockTag("axolotls_spawnable_on");
public static final BlockTag GOATS_SPAWNABLE_ON = new BlockTag("goats_spawnable_on");
public static final BlockTag MOOSHROOMS_SPAWNABLE_ON = new BlockTag("mooshrooms_spawnable_on");
public static final BlockTag PARROTS_SPAWNABLE_ON = new BlockTag("parrots_spawnable_on");
public static final BlockTag POLAR_BEARS_SPAWNABLE_ON_ALTERNATE = new BlockTag("polar_bears_spawnable_on_alternate");
public static final BlockTag RABBITS_SPAWNABLE_ON = new BlockTag("rabbits_spawnable_on");
public static final BlockTag FOXES_SPAWNABLE_ON = new BlockTag("foxes_spawnable_on");
public static final BlockTag WOLVES_SPAWNABLE_ON = new BlockTag("wolves_spawnable_on");
public static final BlockTag FROGS_SPAWNABLE_ON = new BlockTag("frogs_spawnable_on");
public static final BlockTag AZALEA_GROWS_ON = new BlockTag("azalea_grows_on");
public static final BlockTag CONVERTABLE_TO_MUD = new BlockTag("convertable_to_mud");
public static final BlockTag MANGROVE_LOGS_CAN_GROW_THROUGH = new BlockTag("mangrove_logs_can_grow_through");
public static final BlockTag MANGROVE_ROOTS_CAN_GROW_THROUGH = new BlockTag("mangrove_roots_can_grow_through");
public static final BlockTag DEAD_BUSH_MAY_PLACE_ON = new BlockTag("dead_bush_may_place_on");
public static final BlockTag SNAPS_GOAT_HORN = new BlockTag("snaps_goat_horn");
public static final BlockTag REPLACEABLE_BY_TREES = new BlockTag("replaceable_by_trees");
public static final BlockTag SNOW_LAYER_CANNOT_SURVIVE_ON = new BlockTag("snow_layer_cannot_survive_on");
public static final BlockTag SNOW_LAYER_CAN_SURVIVE_ON = new BlockTag("snow_layer_can_survive_on");
public static final BlockTag INVALID_SPAWN_INSIDE = new BlockTag("invalid_spawn_inside");
public static final BlockTag SNIFFER_DIGGABLE_BLOCK = new BlockTag("sniffer_diggable_block");
public static final BlockTag SNIFFER_EGG_HATCH_BOOST = new BlockTag("sniffer_egg_hatch_boost");
public static final BlockTag TRAIL_RUINS_REPLACEABLE = new BlockTag("trail_ruins_replaceable");
public static final BlockTag REPLACEABLE = new BlockTag("replaceable");
public static final BlockTag ENCHANTMENT_POWER_PROVIDER = new BlockTag("enchantment_power_provider");
public static final BlockTag ENCHANTMENT_POWER_TRANSMITTER = new BlockTag("enchantment_power_transmitter");
public static final BlockTag MAINTAINS_FARMLAND = new BlockTag("maintains_farmland");
public static final BlockTag BLOCKS_WIND_CHARGE_EXPLOSIONS = new BlockTag("blocks_wind_charge_explosions");
public static final BlockTag DOES_NOT_BLOCK_HOPPERS = new BlockTag("does_not_block_hoppers");
public static final BlockTag AIR = new BlockTag("air");
private final int id;
private BlockTag(String identifier) {
this.id = ALL_BLOCK_TAGS.size();
register(identifier, this);
}
@Override
public int ordinal() {
return id;
}
private static void register(String name, BlockTag tag) {
TagCache.ALL_BLOCK_TAGS.put("minecraft:" + name, tag);
ALL_BLOCK_TAGS.put(("minecraft:" + name).intern(), tag);
}
}

View file

@ -0,0 +1,89 @@
/*
* Copyright (c) 2024 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.session.cache.tags;
import org.geysermc.geyser.util.Ordered;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings("unused")
public final class EnchantmentTag implements Ordered {
public static final Map<String, EnchantmentTag> ALL_ENCHANTMENT_TAGS = new HashMap<>();
public static final EnchantmentTag TOOLTIP_ORDER = new EnchantmentTag("tooltip_order");
public static final EnchantmentTag EXCLUSIVE_SET_ARMOR = new EnchantmentTag("exclusive_set/armor");
public static final EnchantmentTag EXCLUSIVE_SET_BOOTS = new EnchantmentTag("exclusive_set/boots");
public static final EnchantmentTag EXCLUSIVE_SET_BOW = new EnchantmentTag("exclusive_set/bow");
public static final EnchantmentTag EXCLUSIVE_SET_CROSSBOW = new EnchantmentTag("exclusive_set/crossbow");
public static final EnchantmentTag EXCLUSIVE_SET_DAMAGE = new EnchantmentTag("exclusive_set/damage");
public static final EnchantmentTag EXCLUSIVE_SET_MINING = new EnchantmentTag("exclusive_set/mining");
public static final EnchantmentTag EXCLUSIVE_SET_RIPTIDE = new EnchantmentTag("exclusive_set/riptide");
public static final EnchantmentTag TRADEABLE = new EnchantmentTag("tradeable");
public static final EnchantmentTag DOUBLE_TRADE_PRICE = new EnchantmentTag("double_trade_price");
public static final EnchantmentTag IN_ENCHANTING_TABLE = new EnchantmentTag("in_enchanting_table");
public static final EnchantmentTag ON_MOB_SPAWN_EQUIPMENT = new EnchantmentTag("on_mob_spawn_equipment");
public static final EnchantmentTag ON_TRADED_EQUIPMENT = new EnchantmentTag("on_traded_equipment");
public static final EnchantmentTag ON_RANDOM_LOOT = new EnchantmentTag("on_random_loot");
public static final EnchantmentTag CURSE = new EnchantmentTag("curse");
public static final EnchantmentTag SMELTS_LOOT = new EnchantmentTag("smelts_loot");
public static final EnchantmentTag PREVENTS_BEE_SPAWNS_WHEN_MINING = new EnchantmentTag("prevents_bee_spawns_when_mining");
public static final EnchantmentTag PREVENTS_DECORATED_POT_SHATTERING = new EnchantmentTag("prevents_decorated_pot_shattering");
public static final EnchantmentTag PREVENTS_ICE_MELTING = new EnchantmentTag("prevents_ice_melting");
public static final EnchantmentTag PREVENTS_INFESTED_SPAWNS = new EnchantmentTag("prevents_infested_spawns");
public static final EnchantmentTag TREASURE = new EnchantmentTag("treasure");
public static final EnchantmentTag NON_TREASURE = new EnchantmentTag("non_treasure");
public static final EnchantmentTag TRADES_DESERT_COMMON = new EnchantmentTag("trades/desert_common");
public static final EnchantmentTag TRADES_JUNGLE_COMMON = new EnchantmentTag("trades/jungle_common");
public static final EnchantmentTag TRADES_PLAINS_COMMON = new EnchantmentTag("trades/plains_common");
public static final EnchantmentTag TRADES_SAVANNA_COMMON = new EnchantmentTag("trades/savanna_common");
public static final EnchantmentTag TRADES_SNOW_COMMON = new EnchantmentTag("trades/snow_common");
public static final EnchantmentTag TRADES_SWAMP_COMMON = new EnchantmentTag("trades/swamp_common");
public static final EnchantmentTag TRADES_TAIGA_COMMON = new EnchantmentTag("trades/taiga_common");
public static final EnchantmentTag TRADES_DESERT_SPECIAL = new EnchantmentTag("trades/desert_special");
public static final EnchantmentTag TRADES_JUNGLE_SPECIAL = new EnchantmentTag("trades/jungle_special");
public static final EnchantmentTag TRADES_PLAINS_SPECIAL = new EnchantmentTag("trades/plains_special");
public static final EnchantmentTag TRADES_SAVANNA_SPECIAL = new EnchantmentTag("trades/savanna_special");
public static final EnchantmentTag TRADES_SNOW_SPECIAL = new EnchantmentTag("trades/snow_special");
public static final EnchantmentTag TRADES_SWAMP_SPECIAL = new EnchantmentTag("trades/swamp_special");
public static final EnchantmentTag TRADES_TAIGA_SPECIAL = new EnchantmentTag("trades/taiga_special");
private final int id;
private EnchantmentTag(String identifier) {
this.id = ALL_ENCHANTMENT_TAGS.size();
register(identifier, this);
}
@Override
public int ordinal() {
return id;
}
private static void register(String name, EnchantmentTag tag) {
ALL_ENCHANTMENT_TAGS.put(("minecraft:" + name).intern(), tag);
}
}

View file

@ -25,44 +25,176 @@
package org.geysermc.geyser.session.cache.tags;
import org.geysermc.geyser.session.cache.TagCache;
import org.geysermc.geyser.util.Ordered;
public enum ItemTag {
AXOLOTL_FOOD("axolotl_food"),
CREEPER_IGNITERS("creeper_igniters"),
FISHES("fishes"),
FOX_FOOD("fox_food"),
PIGLIN_LOVED("piglin_loved"),
SMALL_FLOWERS("small_flowers"),
SNIFFER_FOOD("sniffer_food"),
PIGLIN_FOOD("piglin_food"),
COW_FOOD("cow_food"),
GOAT_FOOD("goat_food"),
SHEEP_FOOD("sheep_food"),
WOLF_FOOD("wolf_food"),
CAT_FOOD("cat_food"),
HORSE_FOOD("horse_food"),
CAMEL_FOOD("camel_food"),
ARMADILLO_FOOD("armadillo_food"),
BEE_FOOD("bee_food"),
CHICKEN_FOOD("chicken_food"),
FROG_FOOD("frog_food"),
HOGLIN_FOOD("hoglin_food"),
LLAMA_FOOD("llama_food"),
OCELOT_FOOD("ocelot_food"),
PANDA_FOOD("panda_food"),
PIG_FOOD("pig_food"),
RABBIT_FOOD("rabbit_food"),
STRIDER_FOOD("strider_food"),
TURTLE_FOOD("turtle_food"),
PARROT_FOOD("parrot_food"),
PARROT_POISONOUS_FOOD("parrot_poisonous_food");
import java.util.HashMap;
import java.util.Map;
ItemTag(String identifier) {
@SuppressWarnings("unused")
public final class ItemTag implements Ordered {
public static final Map<String, ItemTag> ALL_ITEM_TAGS = new HashMap<>();
public static final ItemTag WOOL = new ItemTag("wool");
public static final ItemTag PLANKS = new ItemTag("planks");
public static final ItemTag STONE_BRICKS = new ItemTag("stone_bricks");
public static final ItemTag WOODEN_BUTTONS = new ItemTag("wooden_buttons");
public static final ItemTag STONE_BUTTONS = new ItemTag("stone_buttons");
public static final ItemTag BUTTONS = new ItemTag("buttons");
public static final ItemTag WOOL_CARPETS = new ItemTag("wool_carpets");
public static final ItemTag WOODEN_DOORS = new ItemTag("wooden_doors");
public static final ItemTag WOODEN_STAIRS = new ItemTag("wooden_stairs");
public static final ItemTag WOODEN_SLABS = new ItemTag("wooden_slabs");
public static final ItemTag WOODEN_FENCES = new ItemTag("wooden_fences");
public static final ItemTag FENCE_GATES = new ItemTag("fence_gates");
public static final ItemTag WOODEN_PRESSURE_PLATES = new ItemTag("wooden_pressure_plates");
public static final ItemTag WOODEN_TRAPDOORS = new ItemTag("wooden_trapdoors");
public static final ItemTag DOORS = new ItemTag("doors");
public static final ItemTag SAPLINGS = new ItemTag("saplings");
public static final ItemTag LOGS_THAT_BURN = new ItemTag("logs_that_burn");
public static final ItemTag LOGS = new ItemTag("logs");
public static final ItemTag DARK_OAK_LOGS = new ItemTag("dark_oak_logs");
public static final ItemTag OAK_LOGS = new ItemTag("oak_logs");
public static final ItemTag BIRCH_LOGS = new ItemTag("birch_logs");
public static final ItemTag ACACIA_LOGS = new ItemTag("acacia_logs");
public static final ItemTag CHERRY_LOGS = new ItemTag("cherry_logs");
public static final ItemTag JUNGLE_LOGS = new ItemTag("jungle_logs");
public static final ItemTag SPRUCE_LOGS = new ItemTag("spruce_logs");
public static final ItemTag MANGROVE_LOGS = new ItemTag("mangrove_logs");
public static final ItemTag CRIMSON_STEMS = new ItemTag("crimson_stems");
public static final ItemTag WARPED_STEMS = new ItemTag("warped_stems");
public static final ItemTag BAMBOO_BLOCKS = new ItemTag("bamboo_blocks");
public static final ItemTag WART_BLOCKS = new ItemTag("wart_blocks");
public static final ItemTag BANNERS = new ItemTag("banners");
public static final ItemTag SAND = new ItemTag("sand");
public static final ItemTag SMELTS_TO_GLASS = new ItemTag("smelts_to_glass");
public static final ItemTag STAIRS = new ItemTag("stairs");
public static final ItemTag SLABS = new ItemTag("slabs");
public static final ItemTag WALLS = new ItemTag("walls");
public static final ItemTag ANVIL = new ItemTag("anvil");
public static final ItemTag RAILS = new ItemTag("rails");
public static final ItemTag LEAVES = new ItemTag("leaves");
public static final ItemTag TRAPDOORS = new ItemTag("trapdoors");
public static final ItemTag SMALL_FLOWERS = new ItemTag("small_flowers");
public static final ItemTag BEDS = new ItemTag("beds");
public static final ItemTag FENCES = new ItemTag("fences");
public static final ItemTag TALL_FLOWERS = new ItemTag("tall_flowers");
public static final ItemTag FLOWERS = new ItemTag("flowers");
public static final ItemTag PIGLIN_REPELLENTS = new ItemTag("piglin_repellents");
public static final ItemTag PIGLIN_LOVED = new ItemTag("piglin_loved");
public static final ItemTag IGNORED_BY_PIGLIN_BABIES = new ItemTag("ignored_by_piglin_babies");
public static final ItemTag MEAT = new ItemTag("meat");
public static final ItemTag SNIFFER_FOOD = new ItemTag("sniffer_food");
public static final ItemTag PIGLIN_FOOD = new ItemTag("piglin_food");
public static final ItemTag FOX_FOOD = new ItemTag("fox_food");
public static final ItemTag COW_FOOD = new ItemTag("cow_food");
public static final ItemTag GOAT_FOOD = new ItemTag("goat_food");
public static final ItemTag SHEEP_FOOD = new ItemTag("sheep_food");
public static final ItemTag WOLF_FOOD = new ItemTag("wolf_food");
public static final ItemTag CAT_FOOD = new ItemTag("cat_food");
public static final ItemTag HORSE_FOOD = new ItemTag("horse_food");
public static final ItemTag HORSE_TEMPT_ITEMS = new ItemTag("horse_tempt_items");
public static final ItemTag CAMEL_FOOD = new ItemTag("camel_food");
public static final ItemTag ARMADILLO_FOOD = new ItemTag("armadillo_food");
public static final ItemTag BEE_FOOD = new ItemTag("bee_food");
public static final ItemTag CHICKEN_FOOD = new ItemTag("chicken_food");
public static final ItemTag FROG_FOOD = new ItemTag("frog_food");
public static final ItemTag HOGLIN_FOOD = new ItemTag("hoglin_food");
public static final ItemTag LLAMA_FOOD = new ItemTag("llama_food");
public static final ItemTag LLAMA_TEMPT_ITEMS = new ItemTag("llama_tempt_items");
public static final ItemTag OCELOT_FOOD = new ItemTag("ocelot_food");
public static final ItemTag PANDA_FOOD = new ItemTag("panda_food");
public static final ItemTag PIG_FOOD = new ItemTag("pig_food");
public static final ItemTag RABBIT_FOOD = new ItemTag("rabbit_food");
public static final ItemTag STRIDER_FOOD = new ItemTag("strider_food");
public static final ItemTag STRIDER_TEMPT_ITEMS = new ItemTag("strider_tempt_items");
public static final ItemTag TURTLE_FOOD = new ItemTag("turtle_food");
public static final ItemTag PARROT_FOOD = new ItemTag("parrot_food");
public static final ItemTag PARROT_POISONOUS_FOOD = new ItemTag("parrot_poisonous_food");
public static final ItemTag AXOLOTL_FOOD = new ItemTag("axolotl_food");
public static final ItemTag GOLD_ORES = new ItemTag("gold_ores");
public static final ItemTag IRON_ORES = new ItemTag("iron_ores");
public static final ItemTag DIAMOND_ORES = new ItemTag("diamond_ores");
public static final ItemTag REDSTONE_ORES = new ItemTag("redstone_ores");
public static final ItemTag LAPIS_ORES = new ItemTag("lapis_ores");
public static final ItemTag COAL_ORES = new ItemTag("coal_ores");
public static final ItemTag EMERALD_ORES = new ItemTag("emerald_ores");
public static final ItemTag COPPER_ORES = new ItemTag("copper_ores");
public static final ItemTag NON_FLAMMABLE_WOOD = new ItemTag("non_flammable_wood");
public static final ItemTag SOUL_FIRE_BASE_BLOCKS = new ItemTag("soul_fire_base_blocks");
public static final ItemTag CANDLES = new ItemTag("candles");
public static final ItemTag DIRT = new ItemTag("dirt");
public static final ItemTag TERRACOTTA = new ItemTag("terracotta");
public static final ItemTag COMPLETES_FIND_TREE_TUTORIAL = new ItemTag("completes_find_tree_tutorial");
public static final ItemTag BOATS = new ItemTag("boats");
public static final ItemTag CHEST_BOATS = new ItemTag("chest_boats");
public static final ItemTag FISHES = new ItemTag("fishes");
public static final ItemTag SIGNS = new ItemTag("signs");
public static final ItemTag CREEPER_DROP_MUSIC_DISCS = new ItemTag("creeper_drop_music_discs");
public static final ItemTag COALS = new ItemTag("coals");
public static final ItemTag ARROWS = new ItemTag("arrows");
public static final ItemTag LECTERN_BOOKS = new ItemTag("lectern_books");
public static final ItemTag BOOKSHELF_BOOKS = new ItemTag("bookshelf_books");
public static final ItemTag BEACON_PAYMENT_ITEMS = new ItemTag("beacon_payment_items");
public static final ItemTag STONE_TOOL_MATERIALS = new ItemTag("stone_tool_materials");
public static final ItemTag STONE_CRAFTING_MATERIALS = new ItemTag("stone_crafting_materials");
public static final ItemTag FREEZE_IMMUNE_WEARABLES = new ItemTag("freeze_immune_wearables");
public static final ItemTag DAMPENS_VIBRATIONS = new ItemTag("dampens_vibrations");
public static final ItemTag CLUSTER_MAX_HARVESTABLES = new ItemTag("cluster_max_harvestables");
public static final ItemTag COMPASSES = new ItemTag("compasses");
public static final ItemTag HANGING_SIGNS = new ItemTag("hanging_signs");
public static final ItemTag CREEPER_IGNITERS = new ItemTag("creeper_igniters");
public static final ItemTag NOTEBLOCK_TOP_INSTRUMENTS = new ItemTag("noteblock_top_instruments");
public static final ItemTag FOOT_ARMOR = new ItemTag("foot_armor");
public static final ItemTag LEG_ARMOR = new ItemTag("leg_armor");
public static final ItemTag CHEST_ARMOR = new ItemTag("chest_armor");
public static final ItemTag HEAD_ARMOR = new ItemTag("head_armor");
public static final ItemTag SKULLS = new ItemTag("skulls");
public static final ItemTag TRIMMABLE_ARMOR = new ItemTag("trimmable_armor");
public static final ItemTag TRIM_MATERIALS = new ItemTag("trim_materials");
public static final ItemTag TRIM_TEMPLATES = new ItemTag("trim_templates");
public static final ItemTag DECORATED_POT_SHERDS = new ItemTag("decorated_pot_sherds");
public static final ItemTag DECORATED_POT_INGREDIENTS = new ItemTag("decorated_pot_ingredients");
public static final ItemTag SWORDS = new ItemTag("swords");
public static final ItemTag AXES = new ItemTag("axes");
public static final ItemTag HOES = new ItemTag("hoes");
public static final ItemTag PICKAXES = new ItemTag("pickaxes");
public static final ItemTag SHOVELS = new ItemTag("shovels");
public static final ItemTag BREAKS_DECORATED_POTS = new ItemTag("breaks_decorated_pots");
public static final ItemTag VILLAGER_PLANTABLE_SEEDS = new ItemTag("villager_plantable_seeds");
public static final ItemTag DYEABLE = new ItemTag("dyeable");
public static final ItemTag ENCHANTABLE_FOOT_ARMOR = new ItemTag("enchantable/foot_armor");
public static final ItemTag ENCHANTABLE_LEG_ARMOR = new ItemTag("enchantable/leg_armor");
public static final ItemTag ENCHANTABLE_CHEST_ARMOR = new ItemTag("enchantable/chest_armor");
public static final ItemTag ENCHANTABLE_HEAD_ARMOR = new ItemTag("enchantable/head_armor");
public static final ItemTag ENCHANTABLE_ARMOR = new ItemTag("enchantable/armor");
public static final ItemTag ENCHANTABLE_SWORD = new ItemTag("enchantable/sword");
public static final ItemTag ENCHANTABLE_FIRE_ASPECT = new ItemTag("enchantable/fire_aspect");
public static final ItemTag ENCHANTABLE_SHARP_WEAPON = new ItemTag("enchantable/sharp_weapon");
public static final ItemTag ENCHANTABLE_WEAPON = new ItemTag("enchantable/weapon");
public static final ItemTag ENCHANTABLE_MINING = new ItemTag("enchantable/mining");
public static final ItemTag ENCHANTABLE_MINING_LOOT = new ItemTag("enchantable/mining_loot");
public static final ItemTag ENCHANTABLE_FISHING = new ItemTag("enchantable/fishing");
public static final ItemTag ENCHANTABLE_TRIDENT = new ItemTag("enchantable/trident");
public static final ItemTag ENCHANTABLE_DURABILITY = new ItemTag("enchantable/durability");
public static final ItemTag ENCHANTABLE_BOW = new ItemTag("enchantable/bow");
public static final ItemTag ENCHANTABLE_EQUIPPABLE = new ItemTag("enchantable/equippable");
public static final ItemTag ENCHANTABLE_CROSSBOW = new ItemTag("enchantable/crossbow");
public static final ItemTag ENCHANTABLE_VANISHING = new ItemTag("enchantable/vanishing");
public static final ItemTag ENCHANTABLE_MACE = new ItemTag("enchantable/mace");
private final int id;
private ItemTag(String identifier) {
this.id = ALL_ITEM_TAGS.size();
register(identifier, this);
}
@Override
public int ordinal() {
return id;
}
private static void register(String name, ItemTag tag) {
TagCache.ALL_ITEM_TAGS.put("minecraft:" + name, tag);
ALL_ITEM_TAGS.put(("minecraft:" + name).intern(), tag);
}
}

View file

@ -36,15 +36,14 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse;
import org.cloudburstmc.protocol.bedrock.packet.PlayerEnchantOptionsPacket;
import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.item.Enchantment;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
import java.util.Arrays;
import java.util.Locale;
public class EnchantingInventoryTranslator extends AbstractBlockInventoryTranslator {
public EnchantingInventoryTranslator() {
@ -73,16 +72,16 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla
// The Bedrock index might need changed, so let's look it up and see.
int bedrockIndex = value;
if (bedrockIndex != -1) {
Enchantment enchantment = Enchantment.getByJavaIdentifier("minecraft:" + Enchantment.JavaEnchantment.of(bedrockIndex).name().toLowerCase(Locale.ROOT));
if (enchantment != null) {
Enchantment enchantment = session.getRegistryCache().enchantments().byId(value);
if (enchantment != null && enchantment.bedrockEnchantment() != null) {
// Convert the Java enchantment index to Bedrock's
bedrockIndex = enchantment.ordinal();
bedrockIndex = enchantment.bedrockEnchantment().ordinal();
} else {
// There is no Bedrock enchantment equivalent
bedrockIndex = -1;
}
}
enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setEnchantIndex(value, bedrockIndex);
enchantingInventory.getGeyserEnchantOptions()[slotToUpdate].setEnchantIndex(bedrockIndex);
break;
case 7:
case 8:

View file

@ -26,11 +26,6 @@
package org.geysermc.geyser.translator.protocol.java;
import com.google.common.base.Suppliers;
import org.geysermc.mcprotocollib.protocol.data.game.command.CommandNode;
import org.geysermc.mcprotocollib.protocol.data.game.command.CommandParser;
import org.geysermc.mcprotocollib.protocol.data.game.command.properties.ResourceProperties;
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundCommandsPacket;
import it.unimi.dsi.fastutil.Hash;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@ -46,13 +41,18 @@ import org.cloudburstmc.protocol.bedrock.packet.AvailableCommandsPacket;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.event.java.ServerDefineCommandsEvent;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.inventory.item.Enchantment;
import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.mcprotocollib.protocol.data.game.command.CommandNode;
import org.geysermc.mcprotocollib.protocol.data.game.command.CommandParser;
import org.geysermc.mcprotocollib.protocol.data.game.command.properties.ResourceProperties;
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundCommandsPacket;
import java.util.*;
import java.util.function.Supplier;
@ -267,7 +267,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
private static Object handleResource(CommandBuilderContext context, String resource, boolean tags) {
return switch (resource) {
case "minecraft:attribute" -> ATTRIBUTES;
case "minecraft:enchantment" -> Enchantment.JavaEnchantment.ALL_JAVA_IDENTIFIERS;
case "minecraft:enchantment" -> context.getEnchantments();
case "minecraft:entity_type" -> context.getEntityTypes();
case "minecraft:mob_effect" -> ALL_EFFECT_IDENTIFIERS;
case "minecraft:worldgen/biome" -> tags ? context.getBiomesWithTags() : context.getBiomes();
@ -292,6 +292,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
private final GeyserSession session;
private Object biomesWithTags;
private Object biomesNoTags;
private String[] enchantments;
private String[] entityTypes;
private String[] itemNames;
private CommandEnumData teams;
@ -318,6 +319,14 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
return (biomesWithTags = identifiers != null ? identifiers : CommandParam.STRING);
}
private String[] getEnchantments() {
if (enchantments != null) {
return enchantments;
}
return (enchantments = session.getRegistryCache().enchantments().values().stream()
.map(Enchantment::identifier).toArray(String[]::new));
}
private String[] getEntityTypes() {
if (entityTypes != null) {
return entityTypes;

View file

@ -29,7 +29,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.item.Enchantment;
import org.geysermc.geyser.inventory.item.BedrockEnchantment;
import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.BlockRegistries;
@ -43,11 +43,11 @@ public final class BlockUtils {
private static boolean correctTool(GeyserSession session, Block block, String itemToolType) {
return switch (itemToolType) {
case "axe" -> session.getTagCache().is(BlockTag.AXE_EFFECTIVE, block);
case "hoe" -> session.getTagCache().is(BlockTag.HOE_EFFECTIVE, block);
case "pickaxe" -> session.getTagCache().is(BlockTag.PICKAXE_EFFECTIVE, block);
case "axe" -> session.getTagCache().is(BlockTag.MINEABLE_AXE, block);
case "hoe" -> session.getTagCache().is(BlockTag.MINEABLE_HOE, block);
case "pickaxe" -> session.getTagCache().is(BlockTag.MINEABLE_PICKAXE, block);
case "shears" -> session.getTagCache().is(BlockTag.LEAVES, block) || session.getTagCache().is(BlockTag.WOOL, block);
case "shovel" -> session.getTagCache().is(BlockTag.SHOVEL_EFFECTIVE, block);
case "shovel" -> session.getTagCache().is(BlockTag.MINEABLE_SHOVEL, block);
case "sword" -> block == Blocks.COBWEB;
default -> {
session.getGeyser().getLogger().warning("Unknown tool type: " + itemToolType);
@ -145,7 +145,7 @@ public final class BlockUtils {
toolCanBreak = canToolTierBreakBlock(session, block, toolTier);
}
int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(components, Enchantment.JavaEnchantment.EFFICIENCY);
int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(session, components, BedrockEnchantment.EFFICIENCY);
int hasteLevel = 0;
int miningFatigueLevel = 0;
@ -160,7 +160,7 @@ public final class BlockUtils {
boolean waterInEyes = session.getCollisionManager().isWaterInEyes();
boolean insideOfWaterWithoutAquaAffinity = waterInEyes &&
ItemUtils.getEnchantmentLevel(session.getPlayerInventory().getItem(5).getComponents(), Enchantment.JavaEnchantment.AQUA_AFFINITY) < 1;
ItemUtils.getEnchantmentLevel(session, session.getPlayerInventory().getItem(5).getComponents(), BedrockEnchantment.AQUA_AFFINITY) < 1;
return calculateBreakTime(block.destroyTime(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective,
toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity, session.getPlayerEntity().isOnGround());

View file

@ -27,17 +27,26 @@ package org.geysermc.geyser.util;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.inventory.item.Enchantment;
import org.geysermc.geyser.inventory.item.BedrockEnchantment;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.item.enchantment.EnchantmentComponent;
import org.geysermc.geyser.item.type.FishingRodItem;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
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.ItemEnchantments;
public class ItemUtils {
import java.util.Map;
public static int getEnchantmentLevel(@Nullable DataComponents components, Enchantment.JavaEnchantment enchantment) {
public final class ItemUtils {
/**
* Cheap hack. Proper solution is to read the enchantment effects.
*/
@Deprecated
public static int getEnchantmentLevel(GeyserSession session, @Nullable DataComponents components, BedrockEnchantment bedrockEnchantment) {
if (components == null) {
return 0;
}
@ -47,7 +56,32 @@ public class ItemUtils {
return 0;
}
return enchantmentData.getEnchantments().getOrDefault(enchantment.ordinal(), 0);
for (Map.Entry<Integer, Integer> entry : enchantmentData.getEnchantments().entrySet()) {
Enchantment enchantment = session.getRegistryCache().enchantments().byId(entry.getKey());
if (enchantment.bedrockEnchantment() == bedrockEnchantment) {
return entry.getValue();
}
}
return 0;
}
public static boolean hasEffect(GeyserSession session, @Nullable DataComponents components, EnchantmentComponent component) {
if (components == null) {
return false;
}
ItemEnchantments enchantmentData = components.get(DataComponentType.ENCHANTMENTS);
if (enchantmentData == null) {
return false;
}
for (Integer id : enchantmentData.getEnchantments().keySet()) {
Enchantment enchantment = session.getRegistryCache().enchantments().byId(id);
if (enchantment.effects().contains(component)) {
return true;
}
}
return false;
}
/**
@ -73,4 +107,7 @@ public class ItemUtils {
}
return components.get(DataComponentType.CUSTOM_NAME);
}
private ItemUtils() {
}
}

View file

@ -23,25 +23,11 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.item;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtMap;
import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry;
package org.geysermc.geyser.util;
/**
* @param anvilCost also as a rarity multiplier
* Represents anything that could be tracked like a enum, without also creating a name and enum-wide array.
*/
public record Enchantment(String supportedItemsTag, int maxLevel, int anvilCost, @Nullable String exclusiveSetTag) {
// Implementation note: I have a feeling the tags can be a list of items, because in vanilla they're HolderSet classes.
// I'm not sure how that's wired over the network, so we'll put it off.
public static Enchantment read(RegistryEntry entry) {
NbtMap data = entry.getData();
String supportedItems = data.getString("supported_items");
int maxLevel = data.getInt("max_level");
int anvilCost = data.getInt("anvil_cost");
String exclusiveSet = data.getString("exclusive_set", null);
return new Enchantment(supportedItems, maxLevel, anvilCost, exclusiveSet);
}
public interface Ordered {
int ordinal();
}

@ -1 +1 @@
Subproject commit 88e50df1008916c266428ac11f76f07dc24638c5
Subproject commit 1f1d5ce8c482dac142f13e95e19368e3f36de144