From a5c8d48e17515edefcd87b4c436aa2af9a4a707a Mon Sep 17 00:00:00 2001 From: Tim Brust Date: Sat, 1 Jun 2024 13:34:08 +0300 Subject: [PATCH 1/4] feat: adds support for Minecraft 1.20.6 --- .github/workflows/maven-pr.yml | 1 + README.md | 3 +- modules/API/pom.xml | 2 +- modules/SilkSpawners/pom.xml | 7 +- .../dustplanet/silkspawners/SilkSpawners.java | 2 +- modules/v1_20_R4/pom.xml | 72 +++++++++++++++++++ pom.xml | 1 + 7 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 modules/v1_20_R4/pom.xml diff --git a/.github/workflows/maven-pr.yml b/.github/workflows/maven-pr.yml index cbec9093..a58aa042 100644 --- a/.github/workflows/maven-pr.yml +++ b/.github/workflows/maven-pr.yml @@ -75,6 +75,7 @@ jobs: [ -f ~/.m2/repository/org/spigotmc/spigot/1.20.1-R0.1-SNAPSHOT/spigot-1.20.1-R0.1-SNAPSHOT-remapped-mojang.jar ] || java -jar BuildTools.jar --rev 1.20.1 --remapped [ -f ~/.m2/repository/org/spigotmc/spigot/1.20.2-R0.1-SNAPSHOT/spigot-1.20.2-R0.1-SNAPSHOT-remapped-mojang.jar ] || java -jar BuildTools.jar --rev 1.20.2 --remapped [ -f ~/.m2/repository/org/spigotmc/spigot/1.20.4-R0.1-SNAPSHOT/spigot-1.20.4-R0.1-SNAPSHOT-remapped-mojang.jar ] || java -jar BuildTools.jar --rev 1.20.4 --remapped + [ -f ~/.m2/repository/org/spigotmc/spigot/1.20.6-R0.1-SNAPSHOT/spigot-1.20.6-R0.1-SNAPSHOT-remapped-mojang.jar ] || java -jar BuildTools.jar --rev 1.20.6 --remapped - name: Build with Maven run: mvn -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" "-Dhttps.protocols=TLSv1.2" -DskipTests=true "-Dmaven.javadoc.skip=true" -B clean package diff --git a/README.md b/README.md index f183f6e4..33a631aa 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ This Bukkit (compatible with CraftBukkit, Spigot, Paper) plugin adds a way to ob - Economy addon [SilkSpawnersEcoAddon](https://dev.bukkit.org/projects/silkspawnersecoaddon) - Shop addon [SilkSpawnersShopAddon](https://spigotmc.org/resources/12028/) (login required, Premium Plugin) - BossBarAPI support for >= 1.9, otherwise BarAPI can be used -- Support for multiple Minecraft versions, from 1.8.8 to 1.20.4 (with exlusion of 1.9 and 1.10) +- Support for multiple Minecraft versions, from 1.8.8 to 1.20.6 (with exlusion of 1.9 and 1.10) _Third party features, all of them can be disabled_ @@ -315,6 +315,7 @@ Unfortunately, I can't give access to https://repo.dustplanet.de/artifactory/pri mkdir -p BuildTools cd BuildTools wget -q https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar +java -jar BuildTools.jar --rev 1.20.6 --remapped java -jar BuildTools.jar --rev 1.20.4 --remapped java -jar BuildTools.jar --rev 1.20.2 --remapped java -jar BuildTools.jar --rev 1.20.1 --remapped diff --git a/modules/API/pom.xml b/modules/API/pom.xml index 4fd5ea9b..490ec7e8 100644 --- a/modules/API/pom.xml +++ b/modules/API/pom.xml @@ -23,7 +23,7 @@ org.spigotmc spigot-api - 1.20.4-R0.1-SNAPSHOT + 1.20.6-R0.1-SNAPSHOT diff --git a/modules/SilkSpawners/pom.xml b/modules/SilkSpawners/pom.xml index f2ce6736..064dffd1 100644 --- a/modules/SilkSpawners/pom.xml +++ b/modules/SilkSpawners/pom.xml @@ -42,7 +42,7 @@ org.spigotmc spigot-api - 1.20.4-R0.1-SNAPSHOT + 1.20.6-R0.1-SNAPSHOT com.sk89q @@ -198,6 +198,11 @@ silkspawners-v1_20_R3 8.0.1-SNAPSHOT + + de.dustplanet + silkspawners-v1_20_R4 + 8.0.1-SNAPSHOT + de.dustplanet silkspawners-API 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 d5ea0fe0..2794c514 100644 --- a/modules/SilkSpawners/src/main/java/de/dustplanet/silkspawners/SilkSpawners.java +++ b/modules/SilkSpawners/src/main/java/de/dustplanet/silkspawners/SilkSpawners.java @@ -55,7 +55,7 @@ public class SilkSpawners extends JavaPlugin { private static final int BSTATS_PLUGIN_ID = 273; 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_R2", "v1_20_R3", "v1_20_R4" }; public CommentedConfiguration config; public CommentedConfiguration localization; @Getter diff --git a/modules/v1_20_R4/pom.xml b/modules/v1_20_R4/pom.xml new file mode 100644 index 00000000..86816ba1 --- /dev/null +++ b/modules/v1_20_R4/pom.xml @@ -0,0 +1,72 @@ + + 4.0.0 + silkspawners-v1_20_R4 + jar + SilkSpawners for v1_20_R4 + + + de.dustplanet + silkspawners-parent + 8.0.1-SNAPSHOT + ../../ + + + + + org.spigotmc + spigot + 1.20.6-R0.1-SNAPSHOT + provided + remapped-mojang + + + org.spigotmc + minecraft-server + + + + + de.dustplanet + silkspawners-API + 8.0.1-SNAPSHOT + + + + + + + net.md-5 + specialsource-maven-plugin + 2.0.3 + + + package + + remap + + remap-mojang + + org.spigotmc:minecraft-server:1.20.6-R0.1-SNAPSHOT:txt:maps-mojang + true + org.spigotmc:spigot:1.20.6-R0.1-SNAPSHOT:jar:remapped-mojang + true + remapped-mojang + + + + package + + remap + + remap-spigot + + ${project.build.directory}/${project.artifactId}-${project.version}-remapped-mojang.jar + org.spigotmc:minecraft-server:1.20.6-R0.1-SNAPSHOT:csrg:maps-spigot + org.spigotmc:spigot:1.20.6-R0.1-SNAPSHOT:jar:remapped-mojang + + + + + + + diff --git a/pom.xml b/pom.xml index bc392147..f3065690 100644 --- a/pom.xml +++ b/pom.xml @@ -40,6 +40,7 @@ modules/v1_20_R1 modules/v1_20_R2 modules/v1_20_R3 + modules/v1_20_R4 modules/SilkSpawners From 200296d24f4f14910c9184e716d6e379754ac0f2 Mon Sep 17 00:00:00 2001 From: Tim Brust Date: Sat, 1 Jun 2024 13:34:24 +0300 Subject: [PATCH 2/4] fix: updates import and package --- .../compat/v1_20_R3/NMSHandler.java | 524 ++++++++++++++++++ 1 file changed, 524 insertions(+) create mode 100644 modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R3/NMSHandler.java diff --git a/modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R3/NMSHandler.java b/modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R3/NMSHandler.java new file mode 100644 index 00000000..d7555057 --- /dev/null +++ b/modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R3/NMSHandler.java @@ -0,0 +1,524 @@ +package de.dustplanet.silkspawners.compat.v1_20_R4; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +import javax.annotation.Nullable; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; +import org.bukkit.craftbukkit.v1_20_R4.CraftServer; +import org.bukkit.craftbukkit.v1_20_R4.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R4.block.CraftBlockEntityState; +import org.bukkit.craftbukkit.v1_20_R4.block.CraftCreatureSpawner; +import org.bukkit.craftbukkit.v1_20_R4.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftItemStack; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; +import org.spigotmc.SpigotWorldConfig; + +import com.google.common.base.CaseFormat; +import com.mojang.authlib.GameProfile; + +import de.dustplanet.silkspawners.compat.api.NMSProvider; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ClientInformation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerPlayerConnection; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.entity.SpawnerBlockEntity; + +public class NMSHandler implements NMSProvider { + private Field tileField; + private final Collection spawnEggs = Arrays.stream(Material.values()) + .filter(material -> material.name().endsWith("_SPAWN_EGG")).collect(Collectors.toList()); + + public NMSHandler() { + this(true); + } + + public NMSHandler(final boolean checkForNerfFlags) { + try { + tileField = CraftCreatureSpawner.class.getDeclaredField("snapshot"); + tileField.setAccessible(true); + } catch (SecurityException | NoSuchFieldException e) { + try { + tileField = CraftBlockEntityState.class.getDeclaredField("snapshot"); + tileField.setAccessible(true); + } catch (NoSuchFieldException | SecurityException e1) { + Bukkit.getLogger().warning("[SilkSpawners] Reflection failed: " + e.getMessage() + " " + e1.getMessage()); + e.printStackTrace(); + e1.printStackTrace(); + } + } + + if (checkForNerfFlags) { + @SuppressWarnings("resource") + final ServerLevel handle = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(); + + try { + final SpigotWorldConfig spigotConfig = handle.spigotConfig; + if (spigotConfig.nerfSpawnerMobs) { + Bukkit.getLogger().warning( + "[SilkSpawners] Warning! \"nerf-spawner-mobs\" is set to true in the spigot.yml! Spawned mobs WON'T HAVE ANY AI!"); + } + } catch (@SuppressWarnings("unused") final NoSuchFieldError e) { + // Silence + } + + try { + final Field paperConfigField = Level.class.getDeclaredField("paperConfig"); + paperConfigField.setAccessible(true); + + final Field ironGolemsCanSpawnInAirField = paperConfigField.getType().getDeclaredField("ironGolemsCanSpawnInAir"); + ironGolemsCanSpawnInAirField.setAccessible(true); + if (!ironGolemsCanSpawnInAirField.getBoolean(paperConfigField.get(handle))) { + Bukkit.getLogger().warning( + "[SilkSpawners] Warning! \"iron-golems-can-spawn-in-air\" is set to false in the paper.yml! Iron Golem farms might not work!"); + } + } catch (@SuppressWarnings("unused") final NoSuchFieldError | IllegalArgumentException | IllegalAccessException + | NoSuchFieldException | SecurityException e) { + // Silence + } + } + } + + @SuppressWarnings("resource") + @Override + public void spawnEntity(final org.bukkit.World w, final String entityID, final double x, final double y, final double z, + final Player player) { + final CompoundTag tag = new CompoundTag(); + tag.putString("id", entityID); + + final ServerLevel world = ((CraftWorld) w).getHandle(); + final Optional entity = EntityType.create(tag, world); + + if (!entity.isPresent()) { + Bukkit.getLogger().warning("[SilkSpawners] Failed to spawn, falling through. You should report this (entity == null)!"); + return; + } + + final float yaw = world.random.nextFloat() * (-180 - 180) + 180; + entity.get().moveTo(x, y, z, yaw, 0); + ((CraftWorld) w).addEntity(entity.get(), SpawnReason.SPAWNER_EGG); + final Packet rotationPacket = new ClientboundRotateHeadPacket(entity.get(), (byte) yaw); + final ServerPlayerConnection connection = ((CraftPlayer) player).getHandle().connection; + connection.send(rotationPacket); + } + + @Override + public List rawEntityMap() { + final List entities = new ArrayList<>(); + try { + final Registry> entityTypeRegistry = BuiltInRegistries.ENTITY_TYPE; + for (final EntityType next : entityTypeRegistry) { + entities.add(EntityType.getKey(next).getPath()); + } + } catch (SecurityException | IllegalArgumentException e) { + Bukkit.getLogger().severe("[SilkSpawners] Failed to dump entity map: " + e.getMessage()); + e.printStackTrace(); + } + return entities; + } + + @Override + public String getMobNameOfSpawner(final BlockState blockState) { + final CraftCreatureSpawner spawner = (CraftCreatureSpawner) blockState; + try { + final SpawnerBlockEntity tile = (SpawnerBlockEntity) tileField.get(spawner); + final CompoundTag resourceLocation = tile.getSpawner().nextSpawnData.entityToSpawn(); + return resourceLocation != null ? resourceLocation.getString("id").replace("minecraft:", "") : ""; + } catch (IllegalArgumentException | IllegalAccessException e) { + Bukkit.getLogger().warning("[SilkSpawners] Reflection failed: " + e.getMessage()); + e.printStackTrace(); + } + return ""; + } + + @Override + public void setSpawnersUnstackable() { + final ResourceLocation resourceLocation = new ResourceLocation(NAMESPACED_SPAWNER_ID); + final Registry itemRegistry = BuiltInRegistries.ITEM; + final Item spawner = itemRegistry.get(resourceLocation); + try { + final Field maxStackSize = Item.class.getDeclaredField("maxStackSize"); + maxStackSize.setAccessible(true); + maxStackSize.set(spawner, 1); + } catch (@SuppressWarnings("unused") NoSuchFieldException | SecurityException | IllegalArgumentException + | IllegalAccessException e) { + try { + // int maxStackSize -> d + final Field maxStackSize = Item.class.getDeclaredField("d"); + maxStackSize.setAccessible(true); + maxStackSize.set(spawner, 1); + } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e1) { + e1.printStackTrace(); + } + } + } + + @SuppressWarnings("resource") + @Override + public boolean setMobNameOfSpawner(final BlockState blockState, final String mobID) { + // Prevent ResourceKeyInvalidException: Non [a-z0-9/._-] character in path of location + final String safeMobID = caseFormatOf(mobID.replace(" ", "_")).to(CaseFormat.LOWER_UNDERSCORE, mobID.replace(" ", "_")) + .toLowerCase(Locale.ENGLISH); + final CraftCreatureSpawner spawner = (CraftCreatureSpawner) blockState; + + try { + final SpawnerBlockEntity tile = (SpawnerBlockEntity) tileField.get(spawner); + final Registry> entityTypeRegistry = BuiltInRegistries.ENTITY_TYPE; + final ResourceLocation resourceLocation = new ResourceLocation(safeMobID); + tile.getSpawner().setEntityId(entityTypeRegistry.get(resourceLocation), spawner.getWorldHandle().getMinecraftWorld(), + spawner.getWorldHandle().getRandom(), spawner.getPosition()); + return true; + } catch (IllegalArgumentException | IllegalAccessException e) { + Bukkit.getLogger().warning("[SilkSpawners] Reflection failed: " + e.getMessage()); + e.printStackTrace(); + } + return false; + } + + @Override + public ItemStack setNBTEntityID(final ItemStack item, final String entity) { + if (item == null || StringUtils.isBlank(entity)) { + Bukkit.getLogger().warning("[SilkSpawners] Skipping invalid spawner to set NBT data on."); + return null; + } + + String prefixedEntity; + if (!entity.startsWith("minecraft:")) { + prefixedEntity = "minecraft:" + entity; + } else { + prefixedEntity = entity; + } + + net.minecraft.world.item.ItemStack itemStack = null; + final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); + itemStack = CraftItemStack.asNMSCopy(craftStack); + CompoundTag tag = itemStack.getOrCreateTag(); + + // 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()); + } + + tag = tag.getCompound("BlockEntityTag"); + + // EntityId - Deprecated in 1.9 + tag.putString("EntityId", entity); + tag.putString("id", BlockEntityType.getKey(BlockEntityType.MOB_SPAWNER).getPath()); + + // SpawnData + if (!tag.contains("SpawnData")) { + tag.put("SpawnData", new CompoundTag()); + } + + final CompoundTag spawnDataTag = tag.getCompound("SpawnData"); + if (!spawnDataTag.contains("entity")) { + spawnDataTag.put("entity", new CompoundTag()); + } + spawnDataTag.getCompound("entity").putString("id", prefixedEntity); + + if (!tag.contains("SpawnPotentials")) { + tag.put("SpawnPotentials", new CompoundTag()); + } + + // SpawnEgg data + if (!tag.contains("EntityTag")) { + tag.put("EntityTag", new CompoundTag()); + } + tag.getCompound("EntityTag").putString("id", prefixedEntity); + + return CraftItemStack.asCraftMirror(itemStack); + } + + @Override + @Nullable + public String getSilkSpawnersNBTEntityID(final ItemStack item) { + net.minecraft.world.item.ItemStack itemStack = null; + final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); + itemStack = CraftItemStack.asNMSCopy(craftStack); + final CompoundTag tag = itemStack.getTag(); + + if (tag == null || !tag.contains("SilkSpawners")) { + return null; + } + return tag.getCompound("SilkSpawners").getString("entity"); + } + + @Override + @Nullable + public String getVanillaNBTEntityID(final ItemStack item) { + net.minecraft.world.item.ItemStack itemStack = null; + final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); + itemStack = CraftItemStack.asNMSCopy(craftStack); + CompoundTag tag = itemStack.getTag(); + + 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")) { + return tag.getCompound("SpawnData").getString("id"); + } else if (tag.contains("SpawnData") && tag.getCompound("SpawnData").contains("entity") + && tag.getCompound("SpawnData").getCompound("entity").contains("id")) { + return tag.getCompound("SpawnData").getCompound("entity").getString("id"); + } else if (tag.contains("SpawnPotentials") && !tag.getList("SpawnPotentials", 8).isEmpty()) { + return tag.getList("SpawnPotentials", 8).getCompound(0).getCompound("Entity").getString("id"); + } else { + return null; + } + } + + /** + * Return the spawner block the player is looking at, or null if isn't. + * + * @param player the player + * @param distance the reach distance + * @return the found block or null + */ + @Override + public Block getSpawnerFacing(final Player player, final int distance) { + final Block block = player.getTargetBlock((Set) null, distance); + if (block == null || block.getType() != Material.SPAWNER) { + return null; + } + return block; + } + + @SuppressWarnings("deprecation") + @Override + public ItemStack newEggItem(final String entityID, final int amount, final String displayName) { + Material spawnEgg = Material.matchMaterial(entityID.toUpperCase() + "_SPAWN_EGG"); + if (spawnEgg == null) { + spawnEgg = Material.LEGACY_MONSTER_EGG; + } + + final ItemStack item = new ItemStack(spawnEgg, amount); + if (displayName != null) { + final ItemMeta itemMeta = item.getItemMeta(); + itemMeta.setDisplayName(displayName); + item.setItemMeta(itemMeta); + } + net.minecraft.world.item.ItemStack itemStack = null; + final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); + itemStack = CraftItemStack.asNMSCopy(craftStack); + final CompoundTag tag = itemStack.getOrCreateTag(); + + if (!tag.contains("SilkSpawners")) { + tag.put("SilkSpawners", new CompoundTag()); + } + + tag.getCompound("SilkSpawners").putString("entity", entityID); + + if (!tag.contains("EntityTag")) { + tag.put("EntityTag", new CompoundTag()); + } + + String prefixedEntity; + if (!entityID.startsWith("minecraft:")) { + prefixedEntity = "minecraft:" + entityID; + } else { + prefixedEntity = entityID; + } + tag.getCompound("EntityTag").putString("id", prefixedEntity); + + return CraftItemStack.asCraftMirror(itemStack); + } + + @Override + public String getVanillaEggNBTEntityID(final ItemStack item) { + net.minecraft.world.item.ItemStack itemStack = null; + final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); + itemStack = CraftItemStack.asNMSCopy(craftStack); + CompoundTag tag = itemStack.getTag(); + + 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:", ""); + } + } + return null; + } + + @Override + public void displayBossBar(final String title, final String colorName, final String styleName, final Player player, final Plugin plugin, + final int period) { + final BarColor color = BarColor.valueOf(colorName.toUpperCase()); + final BarStyle style = BarStyle.valueOf(styleName.toUpperCase()); + final BossBar bar = Bukkit.createBossBar(title, color, style); + bar.addPlayer(player); + bar.setVisible(true); + final double interval = 1.0 / (period * 20L); + new BukkitRunnable() { + @Override + public void run() { + final double progress = bar.getProgress(); + final double newProgress = progress - interval; + if (progress <= 0.0 || newProgress <= 0.0) { + bar.setVisible(false); + bar.removeAll(); + this.cancel(); + } else { + bar.setProgress(newProgress); + } + } + }.runTaskTimerAsynchronously(plugin, 0, 1L); + } + + @Override + public Player getPlayer(final String playerUUIDOrName) { + try { + final UUID playerUUID = UUID.fromString(playerUUIDOrName); + return Bukkit.getPlayer(playerUUID); + } catch (@SuppressWarnings("unused") final IllegalArgumentException e) { + for (final Player onlinePlayer : Bukkit.getOnlinePlayers()) { + if (onlinePlayer.getName().equalsIgnoreCase(playerUUIDOrName)) { + return onlinePlayer; + } + } + } + return null; + } + + @Override + public ItemStack getItemInHand(final Player player) { + return player.getInventory().getItemInMainHand(); + } + + @Override + public void reduceEggs(final Player player) { + final ItemStack itemInMainHand = player.getInventory().getItemInMainHand(); + final ItemStack itemInOffHand = player.getInventory().getItemInOffHand(); + ItemStack eggs; + if (getSpawnEggMaterials().contains(itemInMainHand.getType())) { + eggs = itemInMainHand; + if (eggs.getAmount() == 1) { + player.getInventory().setItemInMainHand(null); + } else { + eggs.setAmount(eggs.getAmount() - 1); + player.getInventory().setItemInMainHand(eggs); + } + } else { + eggs = itemInOffHand; + if (eggs.getAmount() == 1) { + player.getInventory().setItemInOffHand(null); + } else { + eggs.setAmount(eggs.getAmount() - 1); + player.getInventory().setItemInOffHand(eggs); + } + } + } + + @Override + public ItemStack getSpawnerItemInHand(final Player player) { + final PlayerInventory inv = player.getInventory(); + final ItemStack mainHand = inv.getItemInMainHand(); + final ItemStack offHand = inv.getItemInOffHand(); + if ((getSpawnEggMaterials().contains(mainHand.getType()) || mainHand.getType() == Material.SPAWNER) + && (getSpawnEggMaterials().contains(offHand.getType()) || offHand.getType() == Material.SPAWNER)) { + return null; // not determinable + } else if (getSpawnEggMaterials().contains(mainHand.getType()) || mainHand.getType() == Material.SPAWNER) { + return mainHand; + } else if (getSpawnEggMaterials().contains(offHand.getType()) || offHand.getType() == Material.SPAWNER) { + return offHand; + } + return null; + } + + @Override + public void setSpawnerItemInHand(final Player player, final ItemStack newItem) { + final PlayerInventory inv = player.getInventory(); + final ItemStack mainHand = inv.getItemInMainHand(); + final ItemStack offHand = inv.getItemInOffHand(); + if ((getSpawnEggMaterials().contains(mainHand.getType()) || mainHand.getType() == Material.SPAWNER) + && (getSpawnEggMaterials().contains(offHand.getType()) || offHand.getType() == Material.SPAWNER)) { + return; // not determinable + } else if (getSpawnEggMaterials().contains(mainHand.getType()) || mainHand.getType() == Material.SPAWNER) { + inv.setItemInMainHand(newItem); + } else if (getSpawnEggMaterials().contains(offHand.getType()) || offHand.getType() == Material.SPAWNER) { + inv.setItemInOffHand(newItem); + } + } + + @SuppressWarnings("deprecation") + @Override + public Material getSpawnEggMaterial() { + return Material.LEGACY_MONSTER_EGG; + } + + @Override + public Collection getSpawnEggMaterials() { + return spawnEggs; + } + + @SuppressWarnings("resource") + @Override + public Player loadPlayer(final OfflinePlayer offline) { + if (!offline.hasPlayedBefore()) { + return null; + } + + final GameProfile profile = new GameProfile(offline.getUniqueId(), + offline.getName() != null ? offline.getName() : offline.getUniqueId().toString()); + final MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + final ServerPlayer entity = new ServerPlayer(server, server.getLevel(Level.OVERWORLD), profile, ClientInformation.createDefault()); + + final Player target = entity.getBukkitEntity(); + if (target != null) { + target.loadData(); + } + return target; + } + +} From a011e037b123a4d81fe4e5250d57b424976c6370 Mon Sep 17 00:00:00 2001 From: Tim Brust Date: Sat, 1 Jun 2024 13:52:37 +0200 Subject: [PATCH 3/4] fix: update codebase to 1.20.6 changes --- .../{v1_20_R3 => v1_20_R4}/NMSHandler.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) rename modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/{v1_20_R3 => v1_20_R4}/NMSHandler.java (94%) diff --git a/modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R3/NMSHandler.java b/modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R4/NMSHandler.java similarity index 94% rename from modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R3/NMSHandler.java rename to modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R4/NMSHandler.java index d7555057..7cfd1bb2 100644 --- a/modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R3/NMSHandler.java +++ b/modules/v1_20_R4/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R4/NMSHandler.java @@ -42,6 +42,7 @@ import de.dustplanet.silkspawners.compat.api.NMSProvider; import net.minecraft.core.Registry; +import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.protocol.Packet; @@ -56,6 +57,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.Item; +import net.minecraft.world.item.component.CustomData; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.SpawnerBlockEntity; @@ -228,7 +230,8 @@ public ItemStack setNBTEntityID(final ItemStack item, final String entity) { net.minecraft.world.item.ItemStack itemStack = null; final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); itemStack = CraftItemStack.asNMSCopy(craftStack); - CompoundTag tag = itemStack.getOrCreateTag(); + final CustomData blockData = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); + CompoundTag tag = blockData.copyTag(); // Check for SilkSpawners key if (!tag.contains("SilkSpawners")) { @@ -269,6 +272,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)); return CraftItemStack.asCraftMirror(itemStack); } @@ -278,7 +282,8 @@ public String getSilkSpawnersNBTEntityID(final ItemStack item) { net.minecraft.world.item.ItemStack itemStack = null; final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); itemStack = CraftItemStack.asNMSCopy(craftStack); - final CompoundTag tag = itemStack.getTag(); + final CustomData blockEntityData = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); + final CompoundTag tag = blockEntityData.copyTag(); if (tag == null || !tag.contains("SilkSpawners")) { return null; @@ -292,7 +297,8 @@ public String getVanillaNBTEntityID(final ItemStack item) { net.minecraft.world.item.ItemStack itemStack = null; final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); itemStack = CraftItemStack.asNMSCopy(craftStack); - CompoundTag tag = itemStack.getTag(); + final CustomData blockEntityData = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); + CompoundTag tag = blockEntityData.copyTag(); if (tag == null || !tag.contains("BlockEntityTag")) { return null; @@ -316,7 +322,7 @@ public String getVanillaNBTEntityID(final ItemStack item) { /** * Return the spawner block the player is looking at, or null if isn't. * - * @param player the player + * @param player the player * @param distance the reach distance * @return the found block or null */ @@ -346,7 +352,8 @@ 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 CompoundTag tag = itemStack.getOrCreateTag(); + final CustomData blockEntityData = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); + final CompoundTag tag = blockEntityData.copyTag(); if (!tag.contains("SilkSpawners")) { tag.put("SilkSpawners", new CompoundTag()); @@ -366,6 +373,7 @@ public ItemStack newEggItem(final String entityID, final int amount, final Strin } tag.getCompound("EntityTag").putString("id", prefixedEntity); + itemStack.set(DataComponents.BLOCK_ENTITY_DATA, CustomData.of(tag)); return CraftItemStack.asCraftMirror(itemStack); } @@ -374,7 +382,8 @@ public String getVanillaEggNBTEntityID(final ItemStack item) { net.minecraft.world.item.ItemStack itemStack = null; final CraftItemStack craftStack = CraftItemStack.asCraftCopy(item); itemStack = CraftItemStack.asNMSCopy(craftStack); - CompoundTag tag = itemStack.getTag(); + final CustomData blockEntityData = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); + CompoundTag tag = blockEntityData.copyTag(); if (tag == null || !tag.contains("EntityTag")) { final Registry itemRegistry = BuiltInRegistries.ITEM; From 3223dfee965c22de4a7879f5ee681b2f67a5c439 Mon Sep 17 00:00:00 2001 From: Tim Brust Date: Sat, 1 Jun 2024 14:38:21 +0200 Subject: [PATCH 4/4] build: fix Java building for PR --- .github/workflows/maven-pr.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/maven-pr.yml b/.github/workflows/maven-pr.yml index a58aa042..ae3e65d1 100644 --- a/.github/workflows/maven-pr.yml +++ b/.github/workflows/maven-pr.yml @@ -75,6 +75,17 @@ jobs: [ -f ~/.m2/repository/org/spigotmc/spigot/1.20.1-R0.1-SNAPSHOT/spigot-1.20.1-R0.1-SNAPSHOT-remapped-mojang.jar ] || java -jar BuildTools.jar --rev 1.20.1 --remapped [ -f ~/.m2/repository/org/spigotmc/spigot/1.20.2-R0.1-SNAPSHOT/spigot-1.20.2-R0.1-SNAPSHOT-remapped-mojang.jar ] || java -jar BuildTools.jar --rev 1.20.2 --remapped [ -f ~/.m2/repository/org/spigotmc/spigot/1.20.4-R0.1-SNAPSHOT/spigot-1.20.4-R0.1-SNAPSHOT-remapped-mojang.jar ] || java -jar BuildTools.jar --rev 1.20.4 --remapped + + - name: Set up Java 21 + uses: actions/setup-java@v4.2.1 + with: + distribution: "temurin" + java-version: 21 + cache: "maven" + + - name: Build Spigot versions with JDK 21 + run: | + cd BuildTools [ -f ~/.m2/repository/org/spigotmc/spigot/1.20.6-R0.1-SNAPSHOT/spigot-1.20.6-R0.1-SNAPSHOT-remapped-mojang.jar ] || java -jar BuildTools.jar --rev 1.20.6 --remapped - name: Build with Maven