From a0edc4de2a6c5d6c4bf91f8ca399c314d4a5fb41 Mon Sep 17 00:00:00 2001 From: Tim Brust Date: Sun, 2 Jun 2024 00:01:54 +0200 Subject: [PATCH] fix: 1.20.6 support and Paper support --- .../dustplanet/silkspawners/SilkSpawners.java | 35 ++++++++-- .../java/de/dustplanet/util/SilkUtil.java | 55 ++++++++++----- .../compat/v1_20_R4/NMSHandler.java | 68 ++++++++----------- 3 files changed, 97 insertions(+), 61 deletions(-) diff --git a/modules/SilkSpawners/src/main/java/de/dustplanet/silkspawners/SilkSpawners.java b/modules/SilkSpawners/src/main/java/de/dustplanet/silkspawners/SilkSpawners.java index 2794c514..6e325ac6 100644 --- a/modules/SilkSpawners/src/main/java/de/dustplanet/silkspawners/SilkSpawners.java +++ b/modules/SilkSpawners/src/main/java/de/dustplanet/silkspawners/SilkSpawners.java @@ -5,16 +5,21 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.logging.Level; import org.apache.commons.lang.StringUtils; import org.bstats.bukkit.Metrics; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.NamespacedKey; +import org.bukkit.Server; +import org.bukkit.UnsafeValues; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -24,6 +29,8 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; +import com.vdurmont.semver4j.Semver; + import de.dustplanet.silkspawners.commands.SilkSpawnersTabCompleter; import de.dustplanet.silkspawners.commands.SpawnerCommand; import de.dustplanet.silkspawners.configs.Config; @@ -56,6 +63,12 @@ public class SilkSpawners extends JavaPlugin { private static final String[] COMPATIBLE_MINECRAFT_VERSIONS = { "v1_8_R3", "v1_11_R1", "v1_12_R1", "v1_13_R2", "v1_14_R1", "v1_15_R1", "v1_16_R1", "v1_16_R2", "v1_16_R3", "v1_17_R1", "v1_18_R1", "v1_18_R2", "v1_19_R1", "v1_19_R2", "v1_19_R3", "v1_20_R1", "v1_20_R2", "v1_20_R3", "v1_20_R4" }; + public static final Map PROTOCOL_VERSION_PACKAGE_MAP = new HashMap() { + private static final long serialVersionUID = -5188779509588704507L; + { + put(766, "v1_20_R4"); + } + }; public CommentedConfiguration config; public CommentedConfiguration localization; @Getter @@ -78,7 +91,21 @@ public void onEnable() { final String packageName = getServer().getClass().getPackage().getName(); // org.bukkit.craftbukkit.version // Get the last element of the package - setNmsVersion(packageName.substring(packageName.lastIndexOf('.') + 1)); + String _nmsVersion = packageName.substring(packageName.lastIndexOf('.') + 1); + if (_nmsVersion.equals("craftbukkit")) { + try { + String minecraftVersion = (String) Server.class.getDeclaredMethod("getMinecraftVersion").invoke(Bukkit.getServer()); + Semver semver = new Semver(minecraftVersion); + if (semver.isGreaterThanOrEqualTo("1.20.5")) { + @SuppressWarnings("deprecation") + int protocolVersion = (Integer) UnsafeValues.class.getDeclaredMethod("getProtocolVersion").invoke(Bukkit.getUnsafe()); + _nmsVersion = PROTOCOL_VERSION_PACKAGE_MAP.get(protocolVersion); + } + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | SecurityException e) { + e.printStackTrace(); + } + } + setNmsVersion(_nmsVersion); // Test for right Minecraft version if (config.getBoolean("testMCVersion", true)) { @@ -403,7 +430,7 @@ private void loadRecipes() { // If the custom recipe fails, we have a fallback getLogger().log(Level.WARNING, "Could not add the recipe of {0}!", entityID); getLogger().log(Level.WARNING, "Error:", e); - recipe.shape(new String[] { "AAA", "ABA", "AAA" }); + recipe.shape("AAA", "ABA", "AAA"); recipe.setIngredient('A', su.nmsProvider.getIronFenceMaterial()); if (legacySpawnEggs) { recipe.setIngredient('X', su.nmsProvider.getSpawnEggMaterial(), 0); @@ -496,7 +523,7 @@ private void loadBaseEggRecipe() { } catch (final IllegalArgumentException e) { // If the custom recipe fails, we have a fallback getLogger().log(Level.WARNING, "Could not add the default recipe!", e); - baseSpawnerRecipe.shape(new String[] { "AAA", "ABA", "AAA" }); + baseSpawnerRecipe.shape("AAA", "ABA", "AAA"); baseSpawnerRecipe.setIngredient('A', su.nmsProvider.getIronFenceMaterial()); // Use the right egg! baseSpawnerRecipe.setIngredient('B', su.nmsProvider.getSpawnEggMaterial()); @@ -529,7 +556,7 @@ private boolean shapeContainsIngredient(final List shape, final char c) /** * Sends a message to the player if the 'silkspawners.info' permission is granted. Empty messages are ignored and not are not sent. * - * @param player the player to message + * @param player the player to message * @param message the message to send */ public void informPlayer(final Player player, final String message) { diff --git a/modules/SilkSpawners/src/main/java/de/dustplanet/util/SilkUtil.java b/modules/SilkSpawners/src/main/java/de/dustplanet/util/SilkUtil.java index 09cb5a89..84c1f156 100644 --- a/modules/SilkSpawners/src/main/java/de/dustplanet/util/SilkUtil.java +++ b/modules/SilkSpawners/src/main/java/de/dustplanet/util/SilkUtil.java @@ -20,6 +20,8 @@ import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Server; +import org.bukkit.UnsafeValues; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.block.CreatureSpawner; @@ -41,6 +43,7 @@ import com.sk89q.worldguard.protection.flags.Flags; import com.sk89q.worldguard.protection.regions.RegionContainer; import com.sk89q.worldguard.protection.regions.RegionQuery; +import com.vdurmont.semver4j.Semver; import de.dustplanet.silkspawners.SilkSpawners; import de.dustplanet.silkspawners.compat.api.NMSProvider; @@ -160,7 +163,21 @@ private boolean setupNMSProvider() { // Rare cases might trigger API usage before SilkSpawners if (version == null) { final String packageName = Bukkit.getServer().getClass().getPackage().getName(); - version = (packageName.substring(packageName.lastIndexOf('.') + 1)); + String nmsVersion = packageName.substring(packageName.lastIndexOf('.') + 1); + if (nmsVersion.equals("craftbukkit")) { + try { + String minecraftVersion = (String) Server.class.getDeclaredMethod("getMinecraftVersion").invoke(Bukkit.getServer()); + Semver semver = new Semver(minecraftVersion); + if (semver.isGreaterThanOrEqualTo("1.20.5")) { + @SuppressWarnings("deprecation") + int protocolVersion = (Integer) UnsafeValues.class.getDeclaredMethod("getProtocolVersion") + .invoke(Bukkit.getUnsafe()); + version = SilkSpawners.PROTOCOL_VERSION_PACKAGE_MAP.get(protocolVersion); + } + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | SecurityException e) { + e.printStackTrace(); + } + } } final FileConfiguration config = plugin.getConfig(); @@ -320,7 +337,7 @@ public boolean isVanillaBossBar() { * * @deprecated Use {@link SilkUtil#newEggItem(String, int, String)} instead. * @param entityID which mob should be spawned - * @param amount the amount of spawn eggs + * @param amount the amount of spawn eggs * @return the ItemStack */ @Deprecated @@ -331,8 +348,8 @@ public ItemStack newEggItem(final String entityID, final int amount) { /** * Returns a new ItemStack of a spawn egg with the specified amount and mob. * - * @param entityID which mob should be spawned - * @param amount the amount of spawn eggs + * @param entityID which mob should be spawned + * @param amount the amount of spawn eggs * @param displayName the display name of the egg in case of unknown entities * @return the ItemStack */ @@ -344,10 +361,10 @@ public ItemStack newEggItem(final String entityID, final int amount, final Strin /** * This method will make a new MobSpawner with a custom entityID, name and amount. * - * @param entityID the mob + * @param entityID the mob * @param customName if the MobSpawner should be named different - * @param amount the wanted amount - * @param forceLore whether the lore tag should be forces + * @param amount the wanted amount + * @param forceLore whether the lore tag should be forces * @return the ItemStack with the configured options */ public ItemStack newSpawnerItem(final String entityID, final String customName, final int amount, final boolean forceLore) { @@ -395,10 +412,12 @@ public String getStoredEggEntityID(final ItemStack item) { if (isUsingReflection()) { // Now try reflection for NBT tag entityID = nmsProvider.getSilkSpawnersNBTEntityID(item); + plugin.getLogger().log(Level.FINE, "EntityID from egg item stack (custom tag) is {0}", entityID); if (entityID != null) { return entityID; } entityID = nmsProvider.getVanillaEggNBTEntityID(item); + plugin.getLogger().log(Level.FINE, "EntityID from egg item stack (vanilla tag) is {0}", entityID); if (entityID != null) { return entityID; } @@ -423,10 +442,12 @@ public String getStoredEggEntityID(final ItemStack item) { public String getStoredSpawnerItemEntityID(final ItemStack item) { if (isUsingReflection()) { String entityID = nmsProvider.getSilkSpawnersNBTEntityID(item); + plugin.getLogger().log(Level.FINE, "EntityID from item stack (custom tag) is {0}", entityID); if (StringUtils.isNotBlank(entityID)) { return entityID; } entityID = nmsProvider.getVanillaNBTEntityID(item); + plugin.getLogger().log(Level.FINE, "EntityID from item stack (vanilla tag) is {0}", entityID); if (StringUtils.isNotBlank(entityID)) { return entityID.replace("minecraft:", ""); } @@ -505,7 +526,7 @@ public String getSpawnerEntityID(final Block block) { /** * Set the specified MonterSpawner to another entity ID. * - * @param block MonsterSpawner + * @param block MonsterSpawner * @param entity the wanted entity */ public void setSpawnerEntityID(final Block block, final String entity) { @@ -539,9 +560,9 @@ public void setSpawnerEntityID(final Block block, final String entity) { /** * Set a spawner (if allowed) to a new mob. * - * @param block the MonsterSpawner - * @param entityID the new entity ID - * @param player the player + * @param block the MonsterSpawner + * @param entityID the new entity ID + * @param player the player * @param messageDenied the message which is shown, when the player can't build here see {@link #canBuildHere(Player, Location)} * @return whether the operation was successful or not */ @@ -559,8 +580,8 @@ public boolean setSpawnerType(final Block block, final String entityID, final Pl /** * Sets a spawner item or egg to a new ID. * - * @param item ItemStack (Egg or Spawner) - * @param entityID wanted entity ID + * @param item ItemStack (Egg or Spawner) + * @param entityID wanted entity ID * @param customName if a custom name should be used (null for none) * @return the updated ItemStack */ @@ -706,7 +727,7 @@ public List scanEntityMap() { /** * Notify a player about the spawner. * - * @param player the player + * @param player the player * @param spawnerName the creature name */ @SuppressWarnings("deprecation") @@ -892,7 +913,7 @@ private void getWorldGuard() { /** * Checks if a player can build here (WorldGuard). * - * @param player the player + * @param player the player * @param location the location to check * @return the result, true or false */ @@ -934,9 +955,9 @@ public boolean isLegacySpawnEggs() { /** * Helper methods to check if a player has any of the aliases permissions for a given mobID. * - * @param permissible - the permissible to check the permission for + * @param permissible - the permissible to check the permission for * @param basePermission - the basis permission without the specific mob - * @param entityID - the internal mob ID (not display name) + * @param entityID - the internal mob ID (not display name) * @return the permission check result, true if the player has got the permission, false otherwise */ public boolean hasPermission(final Permissible permissible, final String basePermission, final String entityID) { diff --git a/modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R4/NMSHandler.java b/modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R4/NMSHandler.java index 7cfd1bb2..e8c19dcd 100644 --- a/modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R4/NMSHandler.java +++ b/modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R4/NMSHandler.java @@ -231,21 +231,16 @@ public ItemStack setNBTEntityID(final ItemStack item, final String entity) { final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); itemStack = CraftItemStack.asNMSCopy(craftStack); final CustomData blockData = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); + final CustomData customData = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY); CompoundTag tag = blockData.copyTag(); + CompoundTag customTag = customData.copyTag(); // Check for SilkSpawners key - if (!tag.contains("SilkSpawners")) { - tag.put("SilkSpawners", new CompoundTag()); - } - - tag.getCompound("SilkSpawners").putString("entity", entity); - - // Check for Vanilla keys - if (!tag.contains("BlockEntityTag")) { - tag.put("BlockEntityTag", new CompoundTag()); + if (!customTag.contains("SilkSpawners")) { + customTag.put("SilkSpawners", new CompoundTag()); } - tag = tag.getCompound("BlockEntityTag"); + customTag.getCompound("SilkSpawners").putString("entity", entity); // EntityId - Deprecated in 1.9 tag.putString("EntityId", entity); @@ -273,6 +268,7 @@ public ItemStack setNBTEntityID(final ItemStack item, final String entity) { tag.getCompound("EntityTag").putString("id", prefixedEntity); itemStack.set(DataComponents.BLOCK_ENTITY_DATA, CustomData.of(tag)); + itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(customTag)); return CraftItemStack.asCraftMirror(itemStack); } @@ -282,10 +278,10 @@ public String getSilkSpawnersNBTEntityID(final ItemStack item) { net.minecraft.world.item.ItemStack itemStack = null; final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); itemStack = CraftItemStack.asNMSCopy(craftStack); - final CustomData blockEntityData = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); + final CustomData blockEntityData = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY); final CompoundTag tag = blockEntityData.copyTag(); - if (tag == null || !tag.contains("SilkSpawners")) { + if (!tag.contains("SilkSpawners")) { return null; } return tag.getCompound("SilkSpawners").getString("entity"); @@ -300,11 +296,6 @@ public String getVanillaNBTEntityID(final ItemStack item) { final CustomData blockEntityData = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); CompoundTag tag = blockEntityData.copyTag(); - if (tag == null || !tag.contains("BlockEntityTag")) { - return null; - } - - tag = tag.getCompound("BlockEntityTag"); if (tag.contains("EntityId")) { return tag.getString("EntityId"); } else if (tag.contains("SpawnData") && tag.getCompound("SpawnData").contains("id")) { @@ -352,18 +343,16 @@ public ItemStack newEggItem(final String entityID, final int amount, final Strin net.minecraft.world.item.ItemStack itemStack = null; final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); itemStack = CraftItemStack.asNMSCopy(craftStack); - final CustomData blockEntityData = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); - final CompoundTag tag = blockEntityData.copyTag(); + final CustomData blockData = itemStack.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY); + final CustomData customData = itemStack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY); + CompoundTag tag = blockData.copyTag(); + CompoundTag customTag = customData.copyTag(); - if (!tag.contains("SilkSpawners")) { - tag.put("SilkSpawners", new CompoundTag()); + if (!customTag.contains("SilkSpawners")) { + customTag.put("SilkSpawners", new CompoundTag()); } - tag.getCompound("SilkSpawners").putString("entity", entityID); - - if (!tag.contains("EntityTag")) { - tag.put("EntityTag", new CompoundTag()); - } + customTag.getCompound("SilkSpawners").putString("entity", entityID); String prefixedEntity; if (!entityID.startsWith("minecraft:")) { @@ -371,9 +360,10 @@ public ItemStack newEggItem(final String entityID, final int amount, final Strin } else { prefixedEntity = entityID; } - tag.getCompound("EntityTag").putString("id", prefixedEntity); + tag.putString("id", prefixedEntity); - itemStack.set(DataComponents.BLOCK_ENTITY_DATA, CustomData.of(tag)); + itemStack.set(DataComponents.ENTITY_DATA, CustomData.of(tag)); + itemStack.set(DataComponents.CUSTOM_DATA, CustomData.of(customTag)); return CraftItemStack.asCraftMirror(itemStack); } @@ -382,21 +372,19 @@ public String getVanillaEggNBTEntityID(final ItemStack item) { net.minecraft.world.item.ItemStack itemStack = null; final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); itemStack = CraftItemStack.asNMSCopy(craftStack); - final CustomData blockEntityData = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); + final CustomData blockEntityData = itemStack.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY); CompoundTag tag = blockEntityData.copyTag(); - if (tag == null || !tag.contains("EntityTag")) { - final Registry itemRegistry = BuiltInRegistries.ITEM; - final ResourceLocation vanillaKey = itemRegistry.getKey(itemStack.getItem()); - if (vanillaKey != null) { - return vanillaKey.getPath().replace("minecraft:", "").replace("_spawn_egg", ""); - } - } else { - tag = tag.getCompound("EntityTag"); - if (tag.contains("id")) { - return tag.getString("id").replace("minecraft:", ""); - } + if (tag.contains("id")) { + return tag.getString("id").replace("minecraft:", ""); + } + + final Registry itemRegistry = BuiltInRegistries.ITEM; + final ResourceLocation vanillaKey = itemRegistry.getKey(itemStack.getItem()); + if (vanillaKey != null) { + return vanillaKey.getPath().replace("minecraft:", "").replace("_spawn_egg", ""); } + return null; }