diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registries.java b/core/src/main/java/org/geysermc/geyser/registry/Registries.java index ecfc2cd09..a522c9621 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -147,7 +147,7 @@ public final class Registries { /** * A registry holding all the potion mixes. */ - public static final SimpleRegistry> POTION_MIXES; + public static final VersionedRegistry> POTION_MIXES; /** * A versioned registry holding all the recipes, with the net ID being the key, and {@link GeyserRecipe} as the value. @@ -185,7 +185,7 @@ public final class Registries { RecipeRegistryPopulator.populate(); // Create registries that require other registries to load first - POTION_MIXES = SimpleRegistry.create(PotionMixRegistryLoader::new); + POTION_MIXES = VersionedRegistry.create(PotionMixRegistryLoader::new); ENCHANTMENTS = SimpleMappedRegistry.create("mappings/enchantments.json", EnchantmentRegistryLoader::new); // Remove unneeded client generation data from NbtMapBuilder diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java index 8d40edac3..694aeba9c 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/PotionMixRegistryLoader.java @@ -26,17 +26,18 @@ package org.geysermc.geyser.registry.loader; import com.nukkitx.protocol.bedrock.data.inventory.PotionMixData; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.geysermc.geyser.inventory.item.Potion; -import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.type.ItemMapping; +import org.geysermc.geyser.registry.type.ItemMappings; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; -//TODO this needs to be versioned, but the runtime item states between 1.17 and 1.17.10 are identical except for new blocks so this works for both /** * Generates a collection of {@link PotionMixData} that enables the * Bedrock client to place brewing items into the brewing stand. @@ -46,64 +47,72 @@ import java.util.Set; * (Ex: Bedrock cannot normally place glass bottles or fully upgraded * potions into the brewing stand, but Java can.) */ -public class PotionMixRegistryLoader implements RegistryLoader> { +public class PotionMixRegistryLoader implements RegistryLoader>> { @Override - public Set load(Object input) { - List ingredients = new ArrayList<>(); - ingredients.add(getNonNull("minecraft:nether_wart")); - ingredients.add(getNonNull("minecraft:redstone")); - ingredients.add(getNonNull("minecraft:glowstone_dust")); - ingredients.add(getNonNull("minecraft:fermented_spider_eye")); - ingredients.add(getNonNull("minecraft:gunpowder")); - ingredients.add(getNonNull("minecraft:dragon_breath")); - ingredients.add(getNonNull("minecraft:sugar")); - ingredients.add(getNonNull("minecraft:rabbit_foot")); - ingredients.add(getNonNull("minecraft:glistering_melon_slice")); - ingredients.add(getNonNull("minecraft:spider_eye")); - ingredients.add(getNonNull("minecraft:pufferfish")); - ingredients.add(getNonNull("minecraft:magma_cream")); - ingredients.add(getNonNull("minecraft:golden_carrot")); - ingredients.add(getNonNull("minecraft:blaze_powder")); - ingredients.add(getNonNull("minecraft:ghast_tear")); - ingredients.add(getNonNull("minecraft:turtle_helmet")); - ingredients.add(getNonNull("minecraft:phantom_membrane")); + public Int2ObjectMap> load(Object input) { + var allPotionMixes = new Int2ObjectOpenHashMap>(Registries.ITEMS.get().size()); + for (var entry : Registries.ITEMS.get().int2ObjectEntrySet()) { + ItemMappings mappings = entry.getValue(); + List ingredients = new ArrayList<>(); + ingredients.add(getNonNull(mappings, "minecraft:nether_wart")); + ingredients.add(getNonNull(mappings, "minecraft:redstone")); + ingredients.add(getNonNull(mappings, "minecraft:glowstone_dust")); + ingredients.add(getNonNull(mappings, "minecraft:fermented_spider_eye")); + ingredients.add(getNonNull(mappings, "minecraft:gunpowder")); + ingredients.add(getNonNull(mappings, "minecraft:dragon_breath")); + ingredients.add(getNonNull(mappings, "minecraft:sugar")); + ingredients.add(getNonNull(mappings, "minecraft:rabbit_foot")); + ingredients.add(getNonNull(mappings, "minecraft:glistering_melon_slice")); + ingredients.add(getNonNull(mappings, "minecraft:spider_eye")); + ingredients.add(getNonNull(mappings, "minecraft:pufferfish")); + ingredients.add(getNonNull(mappings, "minecraft:magma_cream")); + ingredients.add(getNonNull(mappings, "minecraft:golden_carrot")); + ingredients.add(getNonNull(mappings, "minecraft:blaze_powder")); + ingredients.add(getNonNull(mappings, "minecraft:ghast_tear")); + ingredients.add(getNonNull(mappings, "minecraft:turtle_helmet")); + ingredients.add(getNonNull(mappings, "minecraft:phantom_membrane")); - List inputs = new ArrayList<>(); - inputs.add(getNonNull("minecraft:potion")); - inputs.add(getNonNull("minecraft:splash_potion")); - inputs.add(getNonNull("minecraft:lingering_potion")); + List inputs = List.of( + getNonNull(mappings, "minecraft:potion"), + getNonNull(mappings, "minecraft:splash_potion"), + getNonNull(mappings, "minecraft:lingering_potion") + ); - ItemMapping glassBottle = getNonNull("minecraft:glass_bottle"); + ItemMapping glassBottle = getNonNull(mappings, "minecraft:glass_bottle"); - Set potionMixes = new HashSet<>(); + Set potionMixes = new HashSet<>(); - // Add all types of potions as inputs - ItemMapping fillerIngredient = ingredients.get(0); - for (ItemMapping entryInput : inputs) { - for (Potion potion : Potion.values()) { + // Add all types of potions as inputs + ItemMapping fillerIngredient = ingredients.get(0); + for (ItemMapping entryInput : inputs) { + for (Potion potion : Potion.VALUES) { + potionMixes.add(new PotionMixData( + entryInput.getBedrockId(), potion.getBedrockId(), + fillerIngredient.getBedrockId(), fillerIngredient.getBedrockData(), + glassBottle.getBedrockId(), glassBottle.getBedrockData()) + ); + } + } + + // Add all brewing ingredients + // Also adds glass bottle as input + for (ItemMapping ingredient : ingredients) { potionMixes.add(new PotionMixData( - entryInput.getBedrockId(), potion.getBedrockId(), - fillerIngredient.getBedrockId(), fillerIngredient.getBedrockData(), + glassBottle.getBedrockId(), glassBottle.getBedrockData(), + ingredient.getBedrockId(), ingredient.getBedrockData(), glassBottle.getBedrockId(), glassBottle.getBedrockData()) ); } - } - // Add all brewing ingredients - // Also adds glass bottle as input - for (ItemMapping ingredient : ingredients) { - potionMixes.add(new PotionMixData( - glassBottle.getBedrockId(), glassBottle.getBedrockData(), - ingredient.getBedrockId(), ingredient.getBedrockData(), - glassBottle.getBedrockId(), glassBottle.getBedrockData()) - ); + allPotionMixes.put(entry.getIntKey(), potionMixes); } - return potionMixes; + allPotionMixes.trim(); + return allPotionMixes; } - private static ItemMapping getNonNull(String javaIdentifier) { - ItemMapping itemMapping = Registries.ITEMS.forVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()).getMapping(javaIdentifier); + private static ItemMapping getNonNull(ItemMappings mappings, String javaIdentifier) { + ItemMapping itemMapping = mappings.getMapping(javaIdentifier); if (itemMapping == null) throw new NullPointerException("No item entry exists for java identifier: " + javaIdentifier); diff --git a/core/src/main/java/org/geysermc/geyser/scoreboard/Team.java b/core/src/main/java/org/geysermc/geyser/scoreboard/Team.java index b2e9043b5..e985ca803 100644 --- a/core/src/main/java/org/geysermc/geyser/scoreboard/Team.java +++ b/core/src/main/java/org/geysermc/geyser/scoreboard/Team.java @@ -33,9 +33,9 @@ import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.HashSet; -import java.util.Objects; import java.util.Set; @Getter @@ -46,7 +46,7 @@ public final class Team { @Getter(AccessLevel.PACKAGE) private final Set entities; - @Setter @Nullable private NameTagVisibility nameTagVisibility; + @Nonnull private NameTagVisibility nameTagVisibility = NameTagVisibility.ALWAYS; @Setter private TeamColor color; private final TeamData currentData; @@ -189,11 +189,6 @@ public final class Team { } public boolean isVisibleFor(String entity) { - if (nameTagVisibility == null) { - // Null - normal behavior - return true; - } - return switch (nameTagVisibility) { case HIDE_FOR_OTHER_TEAMS -> { // Player must be in a team in order for HIDE_FOR_OTHER_TEAMS to be triggered @@ -206,8 +201,12 @@ public final class Team { }; } - public NameTagVisibility getNameTagVisibility() { - return Objects.requireNonNullElse(this.nameTagVisibility, NameTagVisibility.ALWAYS); + public Team setNameTagVisibility(@Nullable NameTagVisibility nameTagVisibility) { + if (nameTagVisibility != null) { + // Null check like this (and this.nameTagVisibility defaults to ALWAYS) as of Java 1.19.4 + this.nameTagVisibility = nameTagVisibility; + } + return this; } @Override diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index 7cddda6dc..9a233fad3 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -646,7 +646,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { // Potion mixes are registered by default, as they are needed to be able to put ingredients into the brewing stand. CraftingDataPacket craftingDataPacket = new CraftingDataPacket(); craftingDataPacket.setCleanRecipes(true); - craftingDataPacket.getPotionMixData().addAll(Registries.POTION_MIXES.get()); + craftingDataPacket.getPotionMixData().addAll(Registries.POTION_MIXES.forVersion(this.upstream.getProtocolVersion())); upstream.sendPacket(craftingDataPacket); PlayStatusPacket playStatusPacket = new PlayStatusPacket(); @@ -1704,6 +1704,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { abilities.add(Ability.MINE); // Needed so you can drop items abilities.add(Ability.DOORS_AND_SWITCHES); + // Required for lecterns to work (likely started around 1.19.10; confirmed on 1.19.70) + abilities.add(Ability.OPEN_CONTAINERS); if (gameMode == GameMode.CREATIVE) { // Needed so the client doesn't attempt to take away items abilities.add(Ability.INSTABUILD); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java index e6cc010f5..8fe6597c6 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/InventoryTranslator.java @@ -88,7 +88,7 @@ public abstract class InventoryTranslator { put(ContainerType.LOOM, new LoomInventoryTranslator()); put(ContainerType.MERCHANT, new MerchantInventoryTranslator()); put(ContainerType.SHULKER_BOX, new ShulkerInventoryTranslator()); - put(ContainerType.SMITHING, new SmithingInventoryTranslator()); + put(ContainerType.LEGACY_SMITHING, new SmithingInventoryTranslator()); put(ContainerType.STONECUTTER, new StonecutterInventoryTranslator()); /* Lectern */ diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestAbilityTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestAbilityTranslator.java index 1ac75079c..bf268fd0e 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestAbilityTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockRequestAbilityTranslator.java @@ -43,25 +43,21 @@ public class BedrockRequestAbilityTranslator extends PacketTranslator stonecutterRecipeMap = new Int2ObjectOpenHashMap<>(); for (Int2ObjectMap.Entry> data : unsortedStonecutterData.int2ObjectEntrySet()) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3fef94519..7e8ddb2ad 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ websocket = "1.5.1" protocol = "2.9.17-20230217.002312-1" raknet = "1.6.28-20220125.214016-6" mcauthlib = "d9d773e" -mcprotocollib = "1.19.4-20230314.173921-2" +mcprotocollib = "1.19.4-20230317.173631-4" adventure = "4.12.0-20220629.025215-9" adventure-platform = "4.1.2" junit = "5.9.2"