From 243b1f2e8bd10619bc7b2dd795fcdd0735b7daae Mon Sep 17 00:00:00 2001 From: Tim Brust Date: Thu, 25 Jan 2024 12:05:49 +0100 Subject: [PATCH] feat: re-add 1.20.2 support --- .github/workflows/maven-pr.yml | 1 + README.md | 1 + modules/SilkSpawners/pom.xml | 8 +- .../dustplanet/silkspawners/SilkSpawners.java | 2 +- modules/v1_20_R2/pom.xml | 73 +++ .../compat/v1_20_R2/NMSHandler.java | 524 ++++++++++++++++++ pom.xml | 4 +- 7 files changed, 610 insertions(+), 3 deletions(-) create mode 100644 modules/v1_20_R2/pom.xml create mode 100644 modules/v1_20_R2/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R2/NMSHandler.java diff --git a/.github/workflows/maven-pr.yml b/.github/workflows/maven-pr.yml index 080da65e..ee42d9c2 100644 --- a/.github/workflows/maven-pr.yml +++ b/.github/workflows/maven-pr.yml @@ -73,6 +73,7 @@ jobs: [ -f ~/.m2/repository/org/spigotmc/spigot/1.19.3-R0.1-SNAPSHOT/spigot-1.19.3-R0.1-SNAPSHOT-remapped-mojang.jar ] || java -jar BuildTools.jar --rev 1.19.3 --remapped [ -f ~/.m2/repository/org/spigotmc/spigot/1.19.4-R0.1-SNAPSHOT/spigot-1.19.4-R0.1-SNAPSHOT-remapped-mojang.jar ] || java -jar BuildTools.jar --rev 1.19.4 --remapped [ -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: Build with Maven diff --git a/README.md b/README.md index 63dc903e..f183f6e4 100644 --- a/README.md +++ b/README.md @@ -316,6 +316,7 @@ 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.4 --remapped +java -jar BuildTools.jar --rev 1.20.2 --remapped java -jar BuildTools.jar --rev 1.20.1 --remapped java -jar BuildTools.jar --rev 1.19.4 --remapped java -jar BuildTools.jar --rev 1.19.3 --remapped diff --git a/modules/SilkSpawners/pom.xml b/modules/SilkSpawners/pom.xml index 9b686ca2..dbf5c87d 100644 --- a/modules/SilkSpawners/pom.xml +++ b/modules/SilkSpawners/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 de.dustplanet silkspawners @@ -187,6 +188,11 @@ silkspawners-v1_20_R1 8.0.1-SNAPSHOT + + de.dustplanet + silkspawners-v1_20_R2 + 8.0.1-SNAPSHOT + de.dustplanet silkspawners-v1_20_R3 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 ff0d4c90..d5ea0fe0 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_R3" }; + "v1_20_R2", "v1_20_R3" }; public CommentedConfiguration config; public CommentedConfiguration localization; @Getter diff --git a/modules/v1_20_R2/pom.xml b/modules/v1_20_R2/pom.xml new file mode 100644 index 00000000..7ba7540c --- /dev/null +++ b/modules/v1_20_R2/pom.xml @@ -0,0 +1,73 @@ + + 4.0.0 + silkspawners-v1_20_R2 + jar + SilkSpawners for v1_20_R2 + + + de.dustplanet + silkspawners-parent + 8.0.1-SNAPSHOT + ../../ + + + + + org.spigotmc + spigot + 1.20.2-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.2 + + + package + + remap + + remap-mojang + + org.spigotmc:minecraft-server:1.20.2-R0.1-SNAPSHOT:txt:maps-mojang + true + org.spigotmc:spigot:1.20.2-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.2-R0.1-SNAPSHOT:csrg:maps-spigot + org.spigotmc:spigot:1.20.2-R0.1-SNAPSHOT:jar:remapped-mojang + + + + + + + diff --git a/modules/v1_20_R2/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R2/NMSHandler.java b/modules/v1_20_R2/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R2/NMSHandler.java new file mode 100644 index 00000000..e8891a95 --- /dev/null +++ b/modules/v1_20_R2/src/main/java/de/dustplanet/silkspawners/compat/v1_20_R2/NMSHandler.java @@ -0,0 +1,524 @@ +package de.dustplanet.silkspawners.compat.v1_20_R2; + +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_R2.CraftServer; +import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlockEntityState; +import org.bukkit.craftbukkit.v1_20_R2.block.CraftCreatureSpawner; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R2.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; + } + +} diff --git a/pom.xml b/pom.xml index 7ab972d7..ebe614c9 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 de.dustplanet silkspawners-parent @@ -37,6 +38,7 @@ modules/v1_19_R2 modules/v1_19_R3 modules/v1_20_R1 + modules/v1_20_R2 modules/v1_20_R3 modules/SilkSpawners