From e694ab56483edbe1696410ca239003baa7f220a6 Mon Sep 17 00:00:00 2001 From: OmerBenGera Date: Sat, 23 Jul 2022 11:10:00 +0300 Subject: [PATCH] Changed the way spawner rates is handled for better performance & detection of new spawners, potentially fixes #1287 --- .../listeners/WildStackerListener.java | 5 +- .../type/UpgradeTypeSpawnerRates.java | 69 ++++++++---- .../superiorskyblock/nms/NMSWorld.java | 7 +- .../nms/v1_12_R1/NMSWorldImpl.java | 36 ++++-- .../spawners/MobSpawnerAbstractNotifier.java | 85 +++++++++++++++ .../nms/v1_16_R3/NMSWorldImpl.java | 35 ++++-- .../spawners/MobSpawnerAbstractNotifier.java | 94 ++++++++++++++++ .../nms/v1_17_R1/NMSWorldImpl.java | 35 ++++-- .../spawners/MobSpawnerAbstractNotifier.java | 103 ++++++++++++++++++ .../nms/v1_18_R1/NMSWorldImpl.java | 32 +++--- .../spawners/MobSpawnerAbstractNotifier.java | 102 +++++++++++++++++ .../nms/v1_18_R2/NMSWorldImpl.java | 32 +++--- .../spawners/MobSpawnerAbstractNotifier.java | 102 +++++++++++++++++ .../nms/v1_19_R1/NMSChunksImpl.java | 3 +- .../nms/v1_19_R1/NMSWorldImpl.java | 32 +++--- .../spawners/MobSpawnerAbstractNotifier.java | 102 +++++++++++++++++ .../nms/v1_8_R3/NMSWorldImpl.java | 36 ++++-- .../spawners/MobSpawnerAbstractNotifier.java | 83 ++++++++++++++ 18 files changed, 872 insertions(+), 121 deletions(-) create mode 100644 v1_12_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_12_R1/spawners/MobSpawnerAbstractNotifier.java create mode 100644 v1_16_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_16_R3/spawners/MobSpawnerAbstractNotifier.java create mode 100644 v1_17_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_17_R1/spawners/MobSpawnerAbstractNotifier.java create mode 100644 v1_18_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R1/spawners/MobSpawnerAbstractNotifier.java create mode 100644 v1_18_R2/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R2/spawners/MobSpawnerAbstractNotifier.java create mode 100644 v1_19_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_19_R1/spawners/MobSpawnerAbstractNotifier.java create mode 100644 v1_8_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_8_R3/spawners/MobSpawnerAbstractNotifier.java diff --git a/Hook_WildStacker/src/main/java/com/bgsoftware/superiorskyblock/module/upgrades/listeners/WildStackerListener.java b/Hook_WildStacker/src/main/java/com/bgsoftware/superiorskyblock/module/upgrades/listeners/WildStackerListener.java index 0cbb22650..35866aca5 100644 --- a/Hook_WildStacker/src/main/java/com/bgsoftware/superiorskyblock/module/upgrades/listeners/WildStackerListener.java +++ b/Hook_WildStacker/src/main/java/com/bgsoftware/superiorskyblock/module/upgrades/listeners/WildStackerListener.java @@ -2,6 +2,7 @@ import com.bgsoftware.superiorskyblock.module.BuiltinModules; import com.bgsoftware.superiorskyblock.module.upgrades.type.UpgradeTypeSpawnerRates; +import com.bgsoftware.wildstacker.api.events.SpawnerPlaceEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -14,9 +15,9 @@ public class WildStackerListener implements Listener { .getEnabledUpgradeType(UpgradeTypeSpawnerRates.class); @EventHandler - public void onWildStackerStackSpawn(com.bgsoftware.wildstacker.api.events.SpawnerStackedEntitySpawnEvent e) { + public void onWildStackerStackSpawn(SpawnerPlaceEvent e) { if (spawnerRates != null) - spawnerRates.handleSpawnerSpawn(e.getSpawner()); + spawnerRates.handleSpawnerPlace(e.getSpawner().getSpawner()); } } diff --git a/src/main/java/com/bgsoftware/superiorskyblock/module/upgrades/type/UpgradeTypeSpawnerRates.java b/src/main/java/com/bgsoftware/superiorskyblock/module/upgrades/type/UpgradeTypeSpawnerRates.java index 1fb1a040c..c204e9f2a 100644 --- a/src/main/java/com/bgsoftware/superiorskyblock/module/upgrades/type/UpgradeTypeSpawnerRates.java +++ b/src/main/java/com/bgsoftware/superiorskyblock/module/upgrades/type/UpgradeTypeSpawnerRates.java @@ -3,30 +3,27 @@ import com.bgsoftware.superiorskyblock.SuperiorSkyblockPlugin; import com.bgsoftware.superiorskyblock.api.island.Island; import com.bgsoftware.superiorskyblock.commands.ISuperiorCommand; +import com.bgsoftware.superiorskyblock.core.Materials; import com.bgsoftware.superiorskyblock.core.threads.BukkitExecutor; import com.bgsoftware.superiorskyblock.module.upgrades.commands.CmdAdminAddSpawnerRates; import com.bgsoftware.superiorskyblock.module.upgrades.commands.CmdAdminSetSpawnerRates; -import com.bgsoftware.superiorskyblock.core.collections.AutoRemovalCollection; +import org.bukkit.block.BlockState; import org.bukkit.block.CreatureSpawner; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.entity.SpawnerSpawnEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.world.ChunkLoadEvent; -import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeUnit; public class UpgradeTypeSpawnerRates implements IUpgradeType { private static final List commands = Arrays.asList(new CmdAdminAddSpawnerRates(), new CmdAdminSetSpawnerRates()); - private final Collection alreadyTrackedSpawning = AutoRemovalCollection.newHashSet(10L * 50, TimeUnit.MILLISECONDS); - private final SuperiorSkyblockPlugin plugin; public UpgradeTypeSpawnerRates(SuperiorSkyblockPlugin plugin) { @@ -43,34 +40,58 @@ public List getCommands() { return commands; } - public void handleSpawnerSpawn(@Nullable CreatureSpawner creatureSpawner) { - if (creatureSpawner == null || creatureSpawner.getLocation() == null) - return; - + public void handleSpawnerPlace(CreatureSpawner creatureSpawner) { Island island = plugin.getGrid().getIslandAt(creatureSpawner.getLocation()); if (island == null) return; - double spawnerRatesMultiplier = island.getSpawnerRatesMultiplier(); + // We want to replace the spawner in a delay so other plugins that might change the spawner will be taken in action as well. + BukkitExecutor.sync(() -> plugin.getNMSWorld().listenSpawner(creatureSpawner, + spawnDelay -> calculateNewSpawnerDelay(island, spawnDelay)), 20L); + } - if (spawnerRatesMultiplier > 1 && alreadyTrackedSpawning.add(island.getOwner().getUniqueId())) { - BukkitExecutor.sync(() -> { - int spawnDelay = plugin.getNMSWorld().getSpawnerDelay(creatureSpawner); - if (spawnDelay > 0) { - plugin.getNMSWorld().setSpawnerDelay(creatureSpawner, - (int) Math.round(spawnDelay / spawnerRatesMultiplier)); - } - }, 5L); + private int calculateNewSpawnerDelay(Island island, int spawnDelay) { + double spawnerRatesMultiplier = island.getSpawnerRatesMultiplier(); + if (spawnerRatesMultiplier > 1) { + return (int) Math.round(spawnDelay / spawnerRatesMultiplier); + } else { + return spawnDelay; } } private class SpawnerRatesListener implements Listener { + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onSpawnerPlace(BlockPlaceEvent e) { + if (e.getBlock().getType() == Materials.SPAWNER.toBukkitType()) + handleSpawnerPlace((CreatureSpawner) e.getBlock().getState()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onChunkLoad(ChunkLoadEvent e) { + Island island = plugin.getGrid().getIslandAt(e.getChunk()); + + if (island == null) + return; + + List creatureSpawners = new ArrayList<>(); + + for (BlockState tileEntity : e.getChunk().getTileEntities()) { + if (tileEntity instanceof CreatureSpawner) { + creatureSpawners.add((CreatureSpawner) tileEntity); + } + } + + if (!creatureSpawners.isEmpty()) { + // We want to replace the spawner in a delay so other plugins that might change the spawner will be taken in action as well. + BukkitExecutor.sync(() -> { + creatureSpawners.forEach(creatureSpawner -> { + plugin.getNMSWorld().listenSpawner(creatureSpawner, spawnDelay -> calculateNewSpawnerDelay(island, spawnDelay)); + }); + }, 20L); + } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onSpawn(SpawnerSpawnEvent e) { - handleSpawnerSpawn(e.getSpawner()); } } diff --git a/src/main/java/com/bgsoftware/superiorskyblock/nms/NMSWorld.java b/src/main/java/com/bgsoftware/superiorskyblock/nms/NMSWorld.java index 20b37dac0..609373e37 100644 --- a/src/main/java/com/bgsoftware/superiorskyblock/nms/NMSWorld.java +++ b/src/main/java/com/bgsoftware/superiorskyblock/nms/NMSWorld.java @@ -4,8 +4,8 @@ import com.bgsoftware.superiorskyblock.api.island.Island; import com.bgsoftware.superiorskyblock.api.key.Key; import com.bgsoftware.superiorskyblock.api.wrappers.SuperiorPlayer; -import com.bgsoftware.superiorskyblock.tag.CompoundTag; import com.bgsoftware.superiorskyblock.core.SchematicBlock; +import com.bgsoftware.superiorskyblock.tag.CompoundTag; import org.bukkit.Chunk; import org.bukkit.ChunkSnapshot; import org.bukkit.Location; @@ -17,14 +17,13 @@ import org.bukkit.generator.ChunkGenerator; import java.util.List; +import java.util.function.IntFunction; public interface NMSWorld { Key getBlockKey(ChunkSnapshot chunkSnapshot, int x, int y, int z); - int getSpawnerDelay(CreatureSpawner creatureSpawner); - - void setSpawnerDelay(CreatureSpawner creatureSpawner, int spawnDelay); + void listenSpawner(CreatureSpawner creatureSpawner, IntFunction delayChangeCallback); void setWorldBorder(SuperiorPlayer superiorPlayer, Island island); diff --git a/v1_12_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_12_R1/NMSWorldImpl.java b/v1_12_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_12_R1/NMSWorldImpl.java index 00edef8ce..77fd76fc3 100644 --- a/v1_12_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_12_R1/NMSWorldImpl.java +++ b/v1_12_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_12_R1/NMSWorldImpl.java @@ -13,6 +13,7 @@ import com.bgsoftware.superiorskyblock.nms.ICachedBlock; import com.bgsoftware.superiorskyblock.nms.NMSWorld; import com.bgsoftware.superiorskyblock.nms.v1_12_R1.generator.IslandsGeneratorImpl; +import com.bgsoftware.superiorskyblock.nms.v1_12_R1.spawners.MobSpawnerAbstractNotifier; import com.bgsoftware.superiorskyblock.tag.CompoundTag; import net.minecraft.server.v1_12_R1.BiomeBase; import net.minecraft.server.v1_12_R1.BlockDoubleStep; @@ -22,6 +23,7 @@ import net.minecraft.server.v1_12_R1.EnumSkyBlock; import net.minecraft.server.v1_12_R1.IBlockData; import net.minecraft.server.v1_12_R1.IChatBaseComponent; +import net.minecraft.server.v1_12_R1.MobSpawnerAbstract; import net.minecraft.server.v1_12_R1.NBTTagCompound; import net.minecraft.server.v1_12_R1.PacketPlayOutBlockChange; import net.minecraft.server.v1_12_R1.PacketPlayOutWorldBorder; @@ -50,13 +52,17 @@ import org.bukkit.event.block.SignChangeEvent; import org.bukkit.generator.ChunkGenerator; +import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; +import java.util.function.IntFunction; public class NMSWorldImpl implements NMSWorld { private static final ReflectField BIOME_BASE_ARRAY = new ReflectField<>( "org.bukkit.craftbukkit.VERSION.generator.CustomChunkGenerator$CustomBiomeGrid", BiomeBase[].class, "biome"); + private static final ReflectField MOB_SPAWNER_ABSTRACT = new ReflectField( + TileEntityMobSpawner.class, MobSpawnerAbstract.class, Modifier.PRIVATE | Modifier.FINAL, 1).removeFinal(); private final SuperiorSkyblockPlugin plugin; private final Singleton signsListener; @@ -83,19 +89,27 @@ public Key getBlockKey(ChunkSnapshot chunkSnapshot, int x, int y, int z) { } @Override - public int getSpawnerDelay(CreatureSpawner creatureSpawner) { + public void listenSpawner(CreatureSpawner creatureSpawner, IntFunction delayChangeCallback) { Location location = creatureSpawner.getLocation(); - TileEntityMobSpawner mobSpawner = (TileEntityMobSpawner) ((CraftWorld) location.getWorld()) - .getTileEntityAt(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - return mobSpawner.getSpawner().spawnDelay; - } + org.bukkit.World world = location.getWorld(); - @Override - public void setSpawnerDelay(CreatureSpawner creatureSpawner, int spawnDelay) { - Location location = creatureSpawner.getLocation(); - TileEntityMobSpawner mobSpawner = (TileEntityMobSpawner) ((CraftWorld) location.getWorld()) - .getTileEntityAt(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - mobSpawner.getSpawner().spawnDelay = spawnDelay; + if (world == null) + return; + + WorldServer worldServer = ((CraftWorld) world).getHandle(); + BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + TileEntity mobSpawner = worldServer.getTileEntity(blockPosition); + + if (!(mobSpawner instanceof TileEntityMobSpawner)) + return; + + MobSpawnerAbstract mobSpawnerAbstract = ((TileEntityMobSpawner) mobSpawner).getSpawner(); + + if (!(mobSpawnerAbstract instanceof MobSpawnerAbstractNotifier)) { + MobSpawnerAbstractNotifier mobSpawnerAbstractNotifier = new MobSpawnerAbstractNotifier(mobSpawnerAbstract, delayChangeCallback); + MOB_SPAWNER_ABSTRACT.set(mobSpawner, mobSpawnerAbstractNotifier); + mobSpawnerAbstractNotifier.updateDelay(); + } } @Override diff --git a/v1_12_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_12_R1/spawners/MobSpawnerAbstractNotifier.java b/v1_12_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_12_R1/spawners/MobSpawnerAbstractNotifier.java new file mode 100644 index 000000000..5ff4a6fdc --- /dev/null +++ b/v1_12_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_12_R1/spawners/MobSpawnerAbstractNotifier.java @@ -0,0 +1,85 @@ +package com.bgsoftware.superiorskyblock.nms.v1_12_R1.spawners; + +import net.minecraft.server.v1_12_R1.BlockPosition; +import net.minecraft.server.v1_12_R1.MinecraftKey; +import net.minecraft.server.v1_12_R1.MobSpawnerAbstract; +import net.minecraft.server.v1_12_R1.MobSpawnerData; +import net.minecraft.server.v1_12_R1.NBTTagCompound; +import net.minecraft.server.v1_12_R1.World; + +import javax.annotation.Nullable; +import java.util.function.IntFunction; + +public class MobSpawnerAbstractNotifier extends MobSpawnerAbstract { + + private final MobSpawnerAbstract mobSpawnerAbstract; + private final IntFunction delayChangeCallback; + + public MobSpawnerAbstractNotifier(MobSpawnerAbstract mobSpawnerAbstract, IntFunction delayChangeCallback) { + this.mobSpawnerAbstract = mobSpawnerAbstract; + this.delayChangeCallback = delayChangeCallback; + } + + @Nullable + @Override + public MinecraftKey getMobName() { + return mobSpawnerAbstract.getMobName(); + } + + @Override + public void setMobName(@Nullable MinecraftKey minecraftkey) { + mobSpawnerAbstract.setMobName(minecraftkey); + } + + @Override + public void c() { + int startDelay = mobSpawnerAbstract.spawnDelay; + try { + mobSpawnerAbstract.c(); + } finally { + int newDelay = mobSpawnerAbstract.spawnDelay; + if (newDelay > startDelay) + updateDelay(); + } + } + + @Override + public void a(NBTTagCompound nbttagcompound) { + mobSpawnerAbstract.a(nbttagcompound); + } + + @Override + public NBTTagCompound b(NBTTagCompound nbttagcompound) { + return mobSpawnerAbstract.b(nbttagcompound); + } + + @Override + public boolean b(int i) { + return mobSpawnerAbstract.b(i); + } + + @Override + public void a(MobSpawnerData mobspawnerdata) { + mobSpawnerAbstract.a(mobspawnerdata); + } + + @Override + public void a(int i) { + mobSpawnerAbstract.a(i); + } + + @Override + public World a() { + return mobSpawnerAbstract.a(); + } + + @Override + public BlockPosition b() { + return mobSpawnerAbstract.b(); + } + + public void updateDelay() { + mobSpawnerAbstract.spawnDelay = delayChangeCallback.apply(mobSpawnerAbstract.spawnDelay); + } + +} diff --git a/v1_16_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_16_R3/NMSWorldImpl.java b/v1_16_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_16_R3/NMSWorldImpl.java index 913ebf4b0..135f974dc 100644 --- a/v1_16_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_16_R3/NMSWorldImpl.java +++ b/v1_16_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_16_R3/NMSWorldImpl.java @@ -15,6 +15,7 @@ import com.bgsoftware.superiorskyblock.nms.ICachedBlock; import com.bgsoftware.superiorskyblock.nms.NMSWorld; import com.bgsoftware.superiorskyblock.nms.v1_16_R3.generator.IslandsGeneratorImpl; +import com.bgsoftware.superiorskyblock.nms.v1_16_R3.spawners.MobSpawnerAbstractNotifier; import com.bgsoftware.superiorskyblock.nms.v1_16_R3.world.BlockStatesMapper; import com.bgsoftware.superiorskyblock.tag.ByteTag; import com.bgsoftware.superiorskyblock.tag.CompoundTag; @@ -38,6 +39,7 @@ import net.minecraft.server.v1_16_R3.IChatBaseComponent; import net.minecraft.server.v1_16_R3.IRegistry; import net.minecraft.server.v1_16_R3.LightEngine; +import net.minecraft.server.v1_16_R3.MobSpawnerAbstract; import net.minecraft.server.v1_16_R3.NBTTagCompound; import net.minecraft.server.v1_16_R3.PacketPlayOutBlockChange; import net.minecraft.server.v1_16_R3.PacketPlayOutWorldBorder; @@ -68,9 +70,11 @@ import org.bukkit.event.block.SignChangeEvent; import org.bukkit.generator.ChunkGenerator; +import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.function.IntFunction; public class NMSWorldImpl implements NMSWorld { @@ -85,6 +89,8 @@ public class NMSWorldImpl implements NMSWorld { private static final ReflectMethod SOUND_PITCH = new ReflectMethod<>(SoundEffectType.class, "b"); private static final ReflectField CHUNK_PACKET_BLOCK_CONTROLLER = new ReflectField<>(World.class, Object.class, "chunkPacketBlockController").removeFinal(); + private static final ReflectField MOB_SPAWNER_ABSTRACT = new ReflectField( + TileEntityMobSpawner.class, MobSpawnerAbstract.class, Modifier.PRIVATE | Modifier.FINAL, 1).removeFinal(); private final SuperiorSkyblockPlugin plugin; private final Singleton signsListener; @@ -111,20 +117,27 @@ public Key getBlockKey(ChunkSnapshot chunkSnapshot, int x, int y, int z) { } @Override - public int getSpawnerDelay(CreatureSpawner creatureSpawner) { + public void listenSpawner(CreatureSpawner creatureSpawner, IntFunction delayChangeCallback) { Location location = creatureSpawner.getLocation(); - BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - TileEntityMobSpawner mobSpawner = (TileEntityMobSpawner) ((CraftWorld) location.getWorld()).getHandle().getTileEntity(blockPosition); - return mobSpawner == null ? 0 : mobSpawner.getSpawner().spawnDelay; - } + org.bukkit.World world = location.getWorld(); - @Override - public void setSpawnerDelay(CreatureSpawner creatureSpawner, int spawnDelay) { - Location location = creatureSpawner.getLocation(); + if (world == null) + return; + + WorldServer worldServer = ((CraftWorld) world).getHandle(); BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - TileEntityMobSpawner mobSpawner = (TileEntityMobSpawner) ((CraftWorld) location.getWorld()).getHandle().getTileEntity(blockPosition); - if (mobSpawner != null) - mobSpawner.getSpawner().spawnDelay = spawnDelay; + TileEntity mobSpawner = worldServer.getTileEntity(blockPosition); + + if (!(mobSpawner instanceof TileEntityMobSpawner)) + return; + + MobSpawnerAbstract mobSpawnerAbstract = ((TileEntityMobSpawner) mobSpawner).getSpawner(); + + if (!(mobSpawnerAbstract instanceof MobSpawnerAbstractNotifier)) { + MobSpawnerAbstractNotifier mobSpawnerAbstractNotifier = new MobSpawnerAbstractNotifier(mobSpawnerAbstract, delayChangeCallback); + MOB_SPAWNER_ABSTRACT.set(mobSpawner, mobSpawnerAbstractNotifier); + mobSpawnerAbstractNotifier.updateDelay(); + } } @Override diff --git a/v1_16_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_16_R3/spawners/MobSpawnerAbstractNotifier.java b/v1_16_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_16_R3/spawners/MobSpawnerAbstractNotifier.java new file mode 100644 index 000000000..d88197421 --- /dev/null +++ b/v1_16_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_16_R3/spawners/MobSpawnerAbstractNotifier.java @@ -0,0 +1,94 @@ +package com.bgsoftware.superiorskyblock.nms.v1_16_R3.spawners; + +import net.minecraft.server.v1_16_R3.BlockPosition; +import net.minecraft.server.v1_16_R3.EntityTypes; +import net.minecraft.server.v1_16_R3.MinecraftKey; +import net.minecraft.server.v1_16_R3.MobSpawnerAbstract; +import net.minecraft.server.v1_16_R3.MobSpawnerData; +import net.minecraft.server.v1_16_R3.NBTTagCompound; +import net.minecraft.server.v1_16_R3.World; + +import javax.annotation.Nullable; +import java.util.function.IntFunction; + +public class MobSpawnerAbstractNotifier extends MobSpawnerAbstract { + + private final MobSpawnerAbstract mobSpawnerAbstract; + private final IntFunction delayChangeCallback; + + public MobSpawnerAbstractNotifier(MobSpawnerAbstract mobSpawnerAbstract, IntFunction delayChangeCallback) { + this.mobSpawnerAbstract = mobSpawnerAbstract; + this.delayChangeCallback = delayChangeCallback; + } + + @Nullable + @Override + public MinecraftKey getMobName() { + return mobSpawnerAbstract.getMobName(); + } + + @Override + public void setMobName(EntityTypes type) { + mobSpawnerAbstract.setMobName(type); + } + + public boolean isActivated() { + return mobSpawnerAbstract.isActivated(); + } + + @Override + public void c() { + int startDelay = mobSpawnerAbstract.spawnDelay; + try { + mobSpawnerAbstract.c(); + } finally { + int newDelay = mobSpawnerAbstract.spawnDelay; + if (newDelay > startDelay) + updateDelay(); + } + } + + public void resetTimer() { + mobSpawnerAbstract.resetTimer(); + } + + @Override + public void a(NBTTagCompound nbttagcompound) { + mobSpawnerAbstract.a(nbttagcompound); + } + + @Override + public NBTTagCompound b(NBTTagCompound nbttagcompound) { + return mobSpawnerAbstract.b(nbttagcompound); + } + + @Override + public boolean b(int i) { + return mobSpawnerAbstract.b(i); + } + + @Override + public void setSpawnData(MobSpawnerData mobspawnerdata) { + mobSpawnerAbstract.setSpawnData(mobspawnerdata); + } + + @Override + public void a(int i) { + mobSpawnerAbstract.a(i); + } + + @Override + public World a() { + return mobSpawnerAbstract.a(); + } + + @Override + public BlockPosition b() { + return mobSpawnerAbstract.b(); + } + + public void updateDelay() { + mobSpawnerAbstract.spawnDelay = delayChangeCallback.apply(mobSpawnerAbstract.spawnDelay); + } + +} diff --git a/v1_17_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_17_R1/NMSWorldImpl.java b/v1_17_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_17_R1/NMSWorldImpl.java index 3bdee8988..081b2466d 100644 --- a/v1_17_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_17_R1/NMSWorldImpl.java +++ b/v1_17_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_17_R1/NMSWorldImpl.java @@ -15,6 +15,7 @@ import com.bgsoftware.superiorskyblock.nms.ICachedBlock; import com.bgsoftware.superiorskyblock.nms.NMSWorld; import com.bgsoftware.superiorskyblock.nms.v1_17_R1.generator.IslandsGeneratorImpl; +import com.bgsoftware.superiorskyblock.nms.v1_17_R1.spawners.MobSpawnerAbstractNotifier; import com.bgsoftware.superiorskyblock.nms.v1_17_R1.world.BlockStatesMapper; import com.bgsoftware.superiorskyblock.tag.ByteTag; import com.bgsoftware.superiorskyblock.tag.CompoundTag; @@ -32,6 +33,7 @@ import net.minecraft.sounds.SoundCategory; import net.minecraft.tags.TagsBlock; import net.minecraft.world.level.EnumSkyBlock; +import net.minecraft.world.level.MobSpawnerAbstract; import net.minecraft.world.level.World; import net.minecraft.world.level.biome.BiomeBase; import net.minecraft.world.level.block.Block; @@ -67,9 +69,11 @@ import org.bukkit.event.block.SignChangeEvent; import org.bukkit.generator.ChunkGenerator; +import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.function.IntFunction; public class NMSWorldImpl implements NMSWorld { @@ -80,6 +84,8 @@ public class NMSWorldImpl implements NMSWorld { private static final ReflectMethod LINES_SIGN_CHANGE_EVENT = new ReflectMethod<>(SignChangeEvent.class, "lines"); private static final ReflectField CHUNK_PACKET_BLOCK_CONTROLLER = new ReflectField<>(World.class, Object.class, "chunkPacketBlockController").removeFinal(); + private static final ReflectField MOB_SPAWNER_ABSTRACT = new ReflectField( + TileEntityMobSpawner.class, MobSpawnerAbstract.class, Modifier.PRIVATE | Modifier.FINAL, 1).removeFinal(); private final SuperiorSkyblockPlugin plugin; private final Singleton signsListener; @@ -106,20 +112,27 @@ public Key getBlockKey(ChunkSnapshot chunkSnapshot, int x, int y, int z) { } @Override - public int getSpawnerDelay(CreatureSpawner creatureSpawner) { + public void listenSpawner(CreatureSpawner creatureSpawner, IntFunction delayChangeCallback) { Location location = creatureSpawner.getLocation(); - BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - TileEntityMobSpawner mobSpawner = (TileEntityMobSpawner) ((CraftWorld) location.getWorld()).getHandle().getTileEntity(blockPosition); - return mobSpawner == null ? 0 : mobSpawner.getSpawner().d; - } + org.bukkit.World world = location.getWorld(); - @Override - public void setSpawnerDelay(CreatureSpawner creatureSpawner, int spawnDelay) { - Location location = creatureSpawner.getLocation(); + if (world == null) + return; + + WorldServer worldServer = ((CraftWorld) world).getHandle(); BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - TileEntityMobSpawner mobSpawner = (TileEntityMobSpawner) ((CraftWorld) location.getWorld()).getHandle().getTileEntity(blockPosition); - if (mobSpawner != null) - mobSpawner.getSpawner().d = spawnDelay; + TileEntity mobSpawner = worldServer.getTileEntity(blockPosition); + + if (!(mobSpawner instanceof TileEntityMobSpawner tileEntityMobSpawner)) + return; + + MobSpawnerAbstract mobSpawnerAbstract = tileEntityMobSpawner.getSpawner(); + + if (!(mobSpawnerAbstract instanceof MobSpawnerAbstractNotifier)) { + MobSpawnerAbstractNotifier mobSpawnerAbstractNotifier = new MobSpawnerAbstractNotifier(mobSpawnerAbstract, delayChangeCallback); + MOB_SPAWNER_ABSTRACT.set(tileEntityMobSpawner, mobSpawnerAbstractNotifier); + mobSpawnerAbstractNotifier.updateDelay(); + } } @Override diff --git a/v1_17_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_17_R1/spawners/MobSpawnerAbstractNotifier.java b/v1_17_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_17_R1/spawners/MobSpawnerAbstractNotifier.java new file mode 100644 index 000000000..96cfd6bd6 --- /dev/null +++ b/v1_17_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_17_R1/spawners/MobSpawnerAbstractNotifier.java @@ -0,0 +1,103 @@ +package com.bgsoftware.superiorskyblock.nms.v1_17_R1.spawners; + +import net.minecraft.core.BlockPosition; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.resources.MinecraftKey; +import net.minecraft.server.level.WorldServer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityTypes; +import net.minecraft.world.level.MobSpawnerAbstract; +import net.minecraft.world.level.World; + +import javax.annotation.Nullable; +import java.util.function.IntFunction; + +public class MobSpawnerAbstractNotifier extends MobSpawnerAbstract { + + private final MobSpawnerAbstract mobSpawnerAbstract; + private final IntFunction delayChangeCallback; + + public MobSpawnerAbstractNotifier(MobSpawnerAbstract mobSpawnerAbstract, IntFunction delayChangeCallback) { + this.mobSpawnerAbstract = mobSpawnerAbstract; + this.delayChangeCallback = delayChangeCallback; + } + + @Nullable + @Override + public MinecraftKey getMobName(@Nullable World world, BlockPosition pos) { + return mobSpawnerAbstract.getMobName(world, pos); + } + + @Override + public void setMobName(EntityTypes type) { + mobSpawnerAbstract.setMobName(type); + } + + @Override + public boolean c(World world, BlockPosition pos) { + return mobSpawnerAbstract.c(world, pos); + } + + @Override + public void a(World world, BlockPosition pos) { + mobSpawnerAbstract.a(world, pos); + } + + @Override + public void a(WorldServer world, BlockPosition pos) { + int startDelay = mobSpawnerAbstract.d; + try { + mobSpawnerAbstract.a(world, pos); + } finally { + int newDelay = mobSpawnerAbstract.d; + if (newDelay > startDelay) + updateDelay(); + } + } + + @Override + public void d(World world, BlockPosition pos) { + mobSpawnerAbstract.d(world, pos); + } + + @Override + public void a(@Nullable World world, BlockPosition pos, NBTTagCompound nbt) { + mobSpawnerAbstract.a(world, pos, nbt); + } + + @Override + public NBTTagCompound b(@Nullable World world, BlockPosition pos, NBTTagCompound nbt) { + return mobSpawnerAbstract.b(world, pos, nbt); + } + + @Nullable + @Override + public Entity a(World world) { + return mobSpawnerAbstract.a(world); + } + + @Override + public boolean a(World world, int status) { + return mobSpawnerAbstract.a(world, status); + } + + @Override + public void a(World world, BlockPosition blockPosition, int i) { + mobSpawnerAbstract.a(world, blockPosition, i); + } + + @Override + public double a() { + return mobSpawnerAbstract.a(); + } + + @Override + public double b() { + return mobSpawnerAbstract.b(); + } + + public void updateDelay() { + mobSpawnerAbstract.d = delayChangeCallback.apply(mobSpawnerAbstract.d); + } + +} diff --git a/v1_18_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R1/NMSWorldImpl.java b/v1_18_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R1/NMSWorldImpl.java index 6254e97e2..470648b12 100644 --- a/v1_18_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R1/NMSWorldImpl.java +++ b/v1_18_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R1/NMSWorldImpl.java @@ -29,6 +29,7 @@ import com.bgsoftware.superiorskyblock.nms.v1_18_R1.mapping.net.minecraft.world.level.chunk.ChunkAccess; import com.bgsoftware.superiorskyblock.nms.v1_18_R1.mapping.net.minecraft.world.level.chunk.ChunkSection; import com.bgsoftware.superiorskyblock.nms.v1_18_R1.mapping.net.minecraft.world.level.lighting.LightEngine; +import com.bgsoftware.superiorskyblock.nms.v1_18_R1.spawners.MobSpawnerAbstractNotifier; import com.bgsoftware.superiorskyblock.nms.v1_18_R1.world.BlockStatesMapper; import com.bgsoftware.superiorskyblock.tag.ByteTag; import com.bgsoftware.superiorskyblock.tag.CompoundTag; @@ -41,9 +42,11 @@ import net.minecraft.network.protocol.game.PacketPlayOutBlockChange; import net.minecraft.sounds.SoundCategory; import net.minecraft.world.level.EnumSkyBlock; +import net.minecraft.world.level.MobSpawnerAbstract; import net.minecraft.world.level.World; import net.minecraft.world.level.biome.BiomeBase; import net.minecraft.world.level.block.BlockStepAbstract; +import net.minecraft.world.level.block.entity.TileEntityMobSpawner; import net.minecraft.world.level.block.entity.TileEntitySign; import net.minecraft.world.level.block.state.IBlockData; import net.minecraft.world.level.block.state.properties.BlockPropertySlabType; @@ -70,8 +73,10 @@ import org.bukkit.event.block.SignChangeEvent; import org.bukkit.generator.ChunkGenerator; +import java.lang.reflect.Modifier; import java.util.List; import java.util.Map; +import java.util.function.IntFunction; public class NMSWorldImpl implements NMSWorld { @@ -80,6 +85,8 @@ public class NMSWorldImpl implements NMSWorld { private static final ReflectMethod LINES_SIGN_CHANGE_EVENT = new ReflectMethod<>(SignChangeEvent.class, "lines"); private static final ReflectField CHUNK_PACKET_BLOCK_CONTROLLER = new ReflectField<>(World.class, Object.class, "chunkPacketBlockController").removeFinal(); + private static final ReflectField MOB_SPAWNER_ABSTRACT = new ReflectField( + TileEntityMobSpawner.class, MobSpawnerAbstract.class, Modifier.PRIVATE | Modifier.FINAL, 1).removeFinal(); private final SuperiorSkyblockPlugin plugin; private final Singleton signsListener; @@ -106,32 +113,27 @@ public Key getBlockKey(ChunkSnapshot chunkSnapshot, int x, int y, int z) { } @Override - public int getSpawnerDelay(CreatureSpawner creatureSpawner) { + public void listenSpawner(CreatureSpawner creatureSpawner, IntFunction delayChangeCallback) { Location location = creatureSpawner.getLocation(); org.bukkit.World world = location.getWorld(); if (world == null) - return 0; + return; WorldServer worldServer = new WorldServer(((CraftWorld) world).getHandle()); BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); TileEntity mobSpawner = worldServer.getTileEntity(blockPosition); - return mobSpawner == null ? 0 : mobSpawner.getSpawner().c; - } - - @Override - public void setSpawnerDelay(CreatureSpawner creatureSpawner, int spawnDelay) { - Location location = creatureSpawner.getLocation(); - org.bukkit.World world = location.getWorld(); - if (world == null) + if (!(mobSpawner.getHandle() instanceof TileEntityMobSpawner)) return; - WorldServer worldServer = new WorldServer(((CraftWorld) world).getHandle()); - BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - TileEntity mobSpawner = worldServer.getTileEntity(blockPosition); - if (mobSpawner != null) - mobSpawner.getSpawner().c = spawnDelay; + MobSpawnerAbstract mobSpawnerAbstract = mobSpawner.getSpawner(); + + if (!(mobSpawnerAbstract instanceof MobSpawnerAbstractNotifier)) { + MobSpawnerAbstractNotifier mobSpawnerAbstractNotifier = new MobSpawnerAbstractNotifier(mobSpawnerAbstract, delayChangeCallback); + MOB_SPAWNER_ABSTRACT.set(mobSpawner.getHandle(), mobSpawnerAbstractNotifier); + mobSpawnerAbstractNotifier.updateDelay(); + } } @Override diff --git a/v1_18_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R1/spawners/MobSpawnerAbstractNotifier.java b/v1_18_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R1/spawners/MobSpawnerAbstractNotifier.java new file mode 100644 index 000000000..2cc6dc928 --- /dev/null +++ b/v1_18_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R1/spawners/MobSpawnerAbstractNotifier.java @@ -0,0 +1,102 @@ +package com.bgsoftware.superiorskyblock.nms.v1_18_R1.spawners; + +import net.minecraft.core.BlockPosition; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.server.level.WorldServer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityTypes; +import net.minecraft.world.level.MobSpawnerAbstract; +import net.minecraft.world.level.MobSpawnerData; +import net.minecraft.world.level.World; + +import javax.annotation.Nullable; +import java.util.function.IntFunction; + +public class MobSpawnerAbstractNotifier extends MobSpawnerAbstract { + + private final MobSpawnerAbstract mobSpawnerAbstract; + private final IntFunction delayChangeCallback; + + public MobSpawnerAbstractNotifier(MobSpawnerAbstract mobSpawnerAbstract, IntFunction delayChangeCallback) { + this.mobSpawnerAbstract = mobSpawnerAbstract; + this.delayChangeCallback = delayChangeCallback; + } + + @Override + public void a(EntityTypes type) { + mobSpawnerAbstract.a(type); + } + + @Override + public boolean b(World world, BlockPosition pos) { + return mobSpawnerAbstract.b(world, pos); + } + + @Override + public void a(World world, BlockPosition pos) { + mobSpawnerAbstract.a(world, pos); + } + + @Override + public void a(WorldServer world, BlockPosition pos) { + int startDelay = mobSpawnerAbstract.c; + try { + mobSpawnerAbstract.a(world, pos); + } finally { + int newDelay = mobSpawnerAbstract.c; + if (newDelay > startDelay) + updateDelay(); + } + } + + @Override + public void c(World world, BlockPosition pos) { + mobSpawnerAbstract.c(world, pos); + } + + @Override + public void a(@Nullable World world, BlockPosition pos, NBTTagCompound nbt) { + mobSpawnerAbstract.a(world, pos, nbt); + } + + @Override + public NBTTagCompound a(NBTTagCompound nbt) { + return mobSpawnerAbstract.a(nbt); + } + + @Nullable + @Override + public Entity a(World world) { + return mobSpawnerAbstract.a(world); + } + + @Override + public boolean a(World world, int status) { + return mobSpawnerAbstract.a(world, status); + } + + @Override + public void a(@Nullable World world, BlockPosition pos, MobSpawnerData spawnEntry) { + mobSpawnerAbstract.a(world, pos, spawnEntry); + } + + @Override + public void a(World world, BlockPosition blockPosition, int i) { + mobSpawnerAbstract.a(world, blockPosition, i); + } + + @Override + public double a() { + return mobSpawnerAbstract.a(); + } + + @Override + public double b() { + return mobSpawnerAbstract.b(); + } + + public void updateDelay() { + mobSpawnerAbstract.c = delayChangeCallback.apply(mobSpawnerAbstract.c); + } + +} diff --git a/v1_18_R2/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R2/NMSWorldImpl.java b/v1_18_R2/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R2/NMSWorldImpl.java index 1fe7de518..019888689 100644 --- a/v1_18_R2/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R2/NMSWorldImpl.java +++ b/v1_18_R2/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R2/NMSWorldImpl.java @@ -29,6 +29,7 @@ import com.bgsoftware.superiorskyblock.nms.v1_18_R2.mapping.net.minecraft.world.level.chunk.ChunkAccess; import com.bgsoftware.superiorskyblock.nms.v1_18_R2.mapping.net.minecraft.world.level.chunk.ChunkSection; import com.bgsoftware.superiorskyblock.nms.v1_18_R2.mapping.net.minecraft.world.level.lighting.LightEngine; +import com.bgsoftware.superiorskyblock.nms.v1_18_R2.spawners.MobSpawnerAbstractNotifier; import com.bgsoftware.superiorskyblock.nms.v1_18_R2.world.BlockStatesMapper; import com.bgsoftware.superiorskyblock.tag.ByteTag; import com.bgsoftware.superiorskyblock.tag.CompoundTag; @@ -43,9 +44,11 @@ import net.minecraft.network.protocol.game.PacketPlayOutBlockChange; import net.minecraft.sounds.SoundCategory; import net.minecraft.world.level.EnumSkyBlock; +import net.minecraft.world.level.MobSpawnerAbstract; import net.minecraft.world.level.World; import net.minecraft.world.level.biome.BiomeBase; import net.minecraft.world.level.block.BlockStepAbstract; +import net.minecraft.world.level.block.entity.TileEntityMobSpawner; import net.minecraft.world.level.block.entity.TileEntitySign; import net.minecraft.world.level.block.state.IBlockData; import net.minecraft.world.level.block.state.properties.BlockPropertySlabType; @@ -72,8 +75,10 @@ import org.bukkit.event.block.SignChangeEvent; import org.bukkit.generator.ChunkGenerator; +import java.lang.reflect.Modifier; import java.util.List; import java.util.Map; +import java.util.function.IntFunction; public class NMSWorldImpl implements NMSWorld { @@ -82,6 +87,8 @@ public class NMSWorldImpl implements NMSWorld { private static final ReflectMethod LINES_SIGN_CHANGE_EVENT = new ReflectMethod<>(SignChangeEvent.class, "lines"); private static final ReflectField CHUNK_PACKET_BLOCK_CONTROLLER = new ReflectField<>(World.class, Object.class, "chunkPacketBlockController").removeFinal(); + private static final ReflectField MOB_SPAWNER_ABSTRACT = new ReflectField( + TileEntityMobSpawner.class, MobSpawnerAbstract.class, Modifier.PRIVATE | Modifier.FINAL, 1).removeFinal(); private final SuperiorSkyblockPlugin plugin; private final Singleton signsListener; @@ -108,32 +115,27 @@ public Key getBlockKey(ChunkSnapshot chunkSnapshot, int x, int y, int z) { } @Override - public int getSpawnerDelay(CreatureSpawner creatureSpawner) { + public void listenSpawner(CreatureSpawner creatureSpawner, IntFunction delayChangeCallback) { Location location = creatureSpawner.getLocation(); org.bukkit.World world = location.getWorld(); if (world == null) - return 0; + return; WorldServer worldServer = new WorldServer(((CraftWorld) world).getHandle()); BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); TileEntity mobSpawner = worldServer.getTileEntity(blockPosition); - return mobSpawner == null ? 0 : mobSpawner.getSpawner().c; - } - - @Override - public void setSpawnerDelay(CreatureSpawner creatureSpawner, int spawnDelay) { - Location location = creatureSpawner.getLocation(); - org.bukkit.World world = location.getWorld(); - if (world == null) + if (!(mobSpawner.getHandle() instanceof TileEntityMobSpawner)) return; - WorldServer worldServer = new WorldServer(((CraftWorld) world).getHandle()); - BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - TileEntity mobSpawner = worldServer.getTileEntity(blockPosition); - if (mobSpawner != null) - mobSpawner.getSpawner().c = spawnDelay; + MobSpawnerAbstract mobSpawnerAbstract = mobSpawner.getSpawner(); + + if (!(mobSpawnerAbstract instanceof MobSpawnerAbstractNotifier)) { + MobSpawnerAbstractNotifier mobSpawnerAbstractNotifier = new MobSpawnerAbstractNotifier(mobSpawnerAbstract, delayChangeCallback); + MOB_SPAWNER_ABSTRACT.set(mobSpawner.getHandle(), mobSpawnerAbstractNotifier); + mobSpawnerAbstractNotifier.updateDelay(); + } } @Override diff --git a/v1_18_R2/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R2/spawners/MobSpawnerAbstractNotifier.java b/v1_18_R2/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R2/spawners/MobSpawnerAbstractNotifier.java new file mode 100644 index 000000000..b3c5a4ec0 --- /dev/null +++ b/v1_18_R2/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_18_R2/spawners/MobSpawnerAbstractNotifier.java @@ -0,0 +1,102 @@ +package com.bgsoftware.superiorskyblock.nms.v1_18_R2.spawners; + +import net.minecraft.core.BlockPosition; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.server.level.WorldServer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityTypes; +import net.minecraft.world.level.MobSpawnerAbstract; +import net.minecraft.world.level.MobSpawnerData; +import net.minecraft.world.level.World; + +import javax.annotation.Nullable; +import java.util.function.IntFunction; + +public class MobSpawnerAbstractNotifier extends MobSpawnerAbstract { + + private final MobSpawnerAbstract mobSpawnerAbstract; + private final IntFunction delayChangeCallback; + + public MobSpawnerAbstractNotifier(MobSpawnerAbstract mobSpawnerAbstract, IntFunction delayChangeCallback) { + this.mobSpawnerAbstract = mobSpawnerAbstract; + this.delayChangeCallback = delayChangeCallback; + } + + @Override + public void a(EntityTypes type) { + mobSpawnerAbstract.a(type); + } + + @Override + public boolean b(World world, BlockPosition pos) { + return mobSpawnerAbstract.b(world, pos); + } + + @Override + public void a(World world, BlockPosition pos) { + mobSpawnerAbstract.a(world, pos); + } + + @Override + public void a(WorldServer world, BlockPosition pos) { + int startDelay = mobSpawnerAbstract.c; + try { + mobSpawnerAbstract.a(world, pos); + } finally { + int newDelay = mobSpawnerAbstract.c; + if (newDelay > startDelay) + updateDelay(); + } + } + + @Override + public void c(World world, BlockPosition pos) { + mobSpawnerAbstract.c(world, pos); + } + + @Override + public void a(@Nullable World world, BlockPosition pos, NBTTagCompound nbt) { + mobSpawnerAbstract.a(world, pos, nbt); + } + + @Override + public NBTTagCompound a(NBTTagCompound nbt) { + return mobSpawnerAbstract.a(nbt); + } + + @Nullable + @Override + public Entity a(World world) { + return mobSpawnerAbstract.a(world); + } + + @Override + public boolean a(World world, int status) { + return mobSpawnerAbstract.a(world, status); + } + + @Override + public void a(@Nullable World world, BlockPosition pos, MobSpawnerData spawnEntry) { + mobSpawnerAbstract.a(world, pos, spawnEntry); + } + + @Override + public void a(World world, BlockPosition blockPosition, int i) { + mobSpawnerAbstract.a(world, blockPosition, i); + } + + @Override + public double a() { + return mobSpawnerAbstract.a(); + } + + @Override + public double b() { + return mobSpawnerAbstract.b(); + } + + public void updateDelay() { + mobSpawnerAbstract.c = delayChangeCallback.apply(mobSpawnerAbstract.c); + } + +} diff --git a/v1_19_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_19_R1/NMSChunksImpl.java b/v1_19_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_19_R1/NMSChunksImpl.java index 754b42f22..b847399e6 100644 --- a/v1_19_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_19_R1/NMSChunksImpl.java +++ b/v1_19_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_19_R1/NMSChunksImpl.java @@ -493,10 +493,9 @@ private static void removeBlocks(ChunkAccess chunk) { worldServer.getChunkProvider().getRandomState(), chunk.getHandle()); - worldServer.getHandle().k().h(); - chunkGenerator.a(region, worldServer.getStructureManager().getStructureManager(region).getHandle(), + worldServer.getChunkProvider().getRandomState(), chunk.getHandle()); } } diff --git a/v1_19_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_19_R1/NMSWorldImpl.java b/v1_19_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_19_R1/NMSWorldImpl.java index 3f3f23cf5..c8df642c8 100644 --- a/v1_19_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_19_R1/NMSWorldImpl.java +++ b/v1_19_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_19_R1/NMSWorldImpl.java @@ -27,6 +27,7 @@ import com.bgsoftware.superiorskyblock.nms.v1_19_R1.mapping.net.minecraft.world.level.chunk.ChunkAccess; import com.bgsoftware.superiorskyblock.nms.v1_19_R1.mapping.net.minecraft.world.level.chunk.ChunkSection; import com.bgsoftware.superiorskyblock.nms.v1_19_R1.mapping.net.minecraft.world.level.lighting.LightEngine; +import com.bgsoftware.superiorskyblock.nms.v1_19_R1.spawners.MobSpawnerAbstractNotifier; import com.bgsoftware.superiorskyblock.nms.v1_19_R1.world.BlockStatesMapper; import com.bgsoftware.superiorskyblock.tag.ByteTag; import com.bgsoftware.superiorskyblock.tag.CompoundTag; @@ -40,9 +41,11 @@ import net.minecraft.network.protocol.game.PacketPlayOutBlockChange; import net.minecraft.sounds.SoundCategory; import net.minecraft.world.level.EnumSkyBlock; +import net.minecraft.world.level.MobSpawnerAbstract; import net.minecraft.world.level.World; import net.minecraft.world.level.biome.BiomeBase; import net.minecraft.world.level.block.BlockStepAbstract; +import net.minecraft.world.level.block.entity.TileEntityMobSpawner; import net.minecraft.world.level.block.entity.TileEntitySign; import net.minecraft.world.level.block.state.IBlockData; import net.minecraft.world.level.block.state.properties.BlockPropertySlabType; @@ -70,8 +73,10 @@ import org.bukkit.event.block.SignChangeEvent; import org.bukkit.generator.ChunkGenerator; +import java.lang.reflect.Modifier; import java.util.List; import java.util.Map; +import java.util.function.IntFunction; public final class NMSWorldImpl implements NMSWorld { @@ -80,6 +85,8 @@ public final class NMSWorldImpl implements NMSWorld { private static final ReflectMethod LINES_SIGN_CHANGE_EVENT = new ReflectMethod<>(SignChangeEvent.class, "lines"); private static final ReflectField CHUNK_PACKET_BLOCK_CONTROLLER = new ReflectField<>(World.class, Object.class, "chunkPacketBlockController").removeFinal(); + private static final ReflectField MOB_SPAWNER_ABSTRACT = new ReflectField( + TileEntityMobSpawner.class, MobSpawnerAbstract.class, Modifier.PRIVATE | Modifier.FINAL, 1).removeFinal(); private final SuperiorSkyblockPlugin plugin; private final Singleton signsListener; @@ -106,32 +113,27 @@ public Key getBlockKey(ChunkSnapshot chunkSnapshot, int x, int y, int z) { } @Override - public int getSpawnerDelay(CreatureSpawner creatureSpawner) { + public void listenSpawner(CreatureSpawner creatureSpawner, IntFunction delayChangeCallback) { Location location = creatureSpawner.getLocation(); org.bukkit.World world = location.getWorld(); if (world == null) - return 0; + return; WorldServer worldServer = new WorldServer(((CraftWorld) world).getHandle()); BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); TileEntity mobSpawner = worldServer.getTileEntity(blockPosition); - return mobSpawner == null ? 0 : mobSpawner.getSpawner().c; - } - - @Override - public void setSpawnerDelay(CreatureSpawner creatureSpawner, int spawnDelay) { - Location location = creatureSpawner.getLocation(); - org.bukkit.World world = location.getWorld(); - if (world == null) + if (!(mobSpawner.getHandle() instanceof TileEntityMobSpawner)) return; - WorldServer worldServer = new WorldServer(((CraftWorld) world).getHandle()); - BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - TileEntity mobSpawner = worldServer.getTileEntity(blockPosition); - if (mobSpawner != null) - mobSpawner.getSpawner().c = spawnDelay; + MobSpawnerAbstract mobSpawnerAbstract = mobSpawner.getSpawner(); + + if (!(mobSpawnerAbstract instanceof MobSpawnerAbstractNotifier)) { + MobSpawnerAbstractNotifier mobSpawnerAbstractNotifier = new MobSpawnerAbstractNotifier(mobSpawnerAbstract, delayChangeCallback); + MOB_SPAWNER_ABSTRACT.set(mobSpawner.getHandle(), mobSpawnerAbstractNotifier); + mobSpawnerAbstractNotifier.updateDelay(); + } } @Override diff --git a/v1_19_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_19_R1/spawners/MobSpawnerAbstractNotifier.java b/v1_19_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_19_R1/spawners/MobSpawnerAbstractNotifier.java new file mode 100644 index 000000000..5f56dc95c --- /dev/null +++ b/v1_19_R1/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_19_R1/spawners/MobSpawnerAbstractNotifier.java @@ -0,0 +1,102 @@ +package com.bgsoftware.superiorskyblock.nms.v1_19_R1.spawners; + +import net.minecraft.core.BlockPosition; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.server.level.WorldServer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityTypes; +import net.minecraft.world.level.MobSpawnerAbstract; +import net.minecraft.world.level.MobSpawnerData; +import net.minecraft.world.level.World; + +import javax.annotation.Nullable; +import java.util.function.IntFunction; + +public class MobSpawnerAbstractNotifier extends MobSpawnerAbstract { + + private final MobSpawnerAbstract mobSpawnerAbstract; + private final IntFunction delayChangeCallback; + + public MobSpawnerAbstractNotifier(MobSpawnerAbstract mobSpawnerAbstract, IntFunction delayChangeCallback) { + this.mobSpawnerAbstract = mobSpawnerAbstract; + this.delayChangeCallback = delayChangeCallback; + } + + @Override + public void a(EntityTypes type) { + mobSpawnerAbstract.a(type); + } + + @Override + public boolean b(World world, BlockPosition pos) { + return mobSpawnerAbstract.b(world, pos); + } + + @Override + public void a(World world, BlockPosition pos) { + mobSpawnerAbstract.a(world, pos); + } + + @Override + public void a(WorldServer world, BlockPosition pos) { + int startDelay = mobSpawnerAbstract.c; + try { + mobSpawnerAbstract.a(world, pos); + } finally { + int newDelay = mobSpawnerAbstract.c; + if (newDelay > startDelay) + updateDelay(); + } + } + + @Override + public void c(World world, BlockPosition pos) { + mobSpawnerAbstract.c(world, pos); + } + + @Override + public void a(@Nullable World world, BlockPosition pos, NBTTagCompound nbt) { + mobSpawnerAbstract.a(world, pos, nbt); + } + + @Override + public NBTTagCompound a(NBTTagCompound nbt) { + return mobSpawnerAbstract.a(nbt); + } + + @Nullable + @Override + public Entity a(World world) { + return mobSpawnerAbstract.a(world); + } + + @Override + public boolean a(World world, int status) { + return mobSpawnerAbstract.a(world, status); + } + + @Override + public void a(@Nullable World world, BlockPosition pos, MobSpawnerData spawnEntry) { + mobSpawnerAbstract.a(world, pos, spawnEntry); + } + + @Override + public void a(World world, BlockPosition blockPosition, int i) { + mobSpawnerAbstract.a(world, blockPosition, i); + } + + @Override + public double a() { + return mobSpawnerAbstract.a(); + } + + @Override + public double b() { + return mobSpawnerAbstract.b(); + } + + public void updateDelay() { + mobSpawnerAbstract.c = delayChangeCallback.apply(mobSpawnerAbstract.c); + } + +} diff --git a/v1_8_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_8_R3/NMSWorldImpl.java b/v1_8_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_8_R3/NMSWorldImpl.java index d39ebf777..5f34a0e03 100644 --- a/v1_8_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_8_R3/NMSWorldImpl.java +++ b/v1_8_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_8_R3/NMSWorldImpl.java @@ -13,6 +13,7 @@ import com.bgsoftware.superiorskyblock.nms.ICachedBlock; import com.bgsoftware.superiorskyblock.nms.NMSWorld; import com.bgsoftware.superiorskyblock.nms.v1_8_R3.generator.IslandsGeneratorImpl; +import com.bgsoftware.superiorskyblock.nms.v1_8_R3.spawners.MobSpawnerAbstractNotifier; import com.bgsoftware.superiorskyblock.tag.CompoundTag; import net.minecraft.server.v1_8_R3.BiomeBase; import net.minecraft.server.v1_8_R3.BlockDoubleStep; @@ -22,6 +23,7 @@ import net.minecraft.server.v1_8_R3.EnumSkyBlock; import net.minecraft.server.v1_8_R3.IBlockData; import net.minecraft.server.v1_8_R3.IChatBaseComponent; +import net.minecraft.server.v1_8_R3.MobSpawnerAbstract; import net.minecraft.server.v1_8_R3.NBTTagCompound; import net.minecraft.server.v1_8_R3.PacketPlayOutBlockChange; import net.minecraft.server.v1_8_R3.PacketPlayOutWorldBorder; @@ -47,13 +49,17 @@ import org.bukkit.event.block.SignChangeEvent; import org.bukkit.generator.ChunkGenerator; +import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; +import java.util.function.IntFunction; public class NMSWorldImpl implements NMSWorld { private static final ReflectField BIOME_BASE_ARRAY = new ReflectField<>( "org.bukkit.craftbukkit.VERSION.generator.CustomChunkGenerator$CustomBiomeGrid", BiomeBase[].class, "biome"); + private static final ReflectField MOB_SPAWNER_ABSTRACT = new ReflectField( + TileEntityMobSpawner.class, MobSpawnerAbstract.class, Modifier.PRIVATE | Modifier.FINAL, 1).removeFinal(); private final SuperiorSkyblockPlugin plugin; private final Singleton signsListener; @@ -80,19 +86,27 @@ public Key getBlockKey(ChunkSnapshot chunkSnapshot, int x, int y, int z) { } @Override - public int getSpawnerDelay(CreatureSpawner creatureSpawner) { + public void listenSpawner(CreatureSpawner creatureSpawner, IntFunction delayChangeCallback) { Location location = creatureSpawner.getLocation(); - TileEntityMobSpawner mobSpawner = (TileEntityMobSpawner) ((CraftWorld) location.getWorld()) - .getTileEntityAt(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - return mobSpawner.getSpawner().spawnDelay; - } + org.bukkit.World world = location.getWorld(); - @Override - public void setSpawnerDelay(CreatureSpawner creatureSpawner, int spawnDelay) { - Location location = creatureSpawner.getLocation(); - TileEntityMobSpawner mobSpawner = (TileEntityMobSpawner) ((CraftWorld) location.getWorld()) - .getTileEntityAt(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - mobSpawner.getSpawner().spawnDelay = spawnDelay; + if (world == null) + return; + + WorldServer worldServer = ((CraftWorld) world).getHandle(); + BlockPosition blockPosition = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + TileEntity mobSpawner = worldServer.getTileEntity(blockPosition); + + if (!(mobSpawner instanceof TileEntityMobSpawner)) + return; + + MobSpawnerAbstract mobSpawnerAbstract = ((TileEntityMobSpawner) mobSpawner).getSpawner(); + + if (!(mobSpawnerAbstract instanceof MobSpawnerAbstractNotifier)) { + MobSpawnerAbstractNotifier mobSpawnerAbstractNotifier = new MobSpawnerAbstractNotifier(mobSpawnerAbstract, delayChangeCallback); + MOB_SPAWNER_ABSTRACT.set(mobSpawner, mobSpawnerAbstractNotifier); + mobSpawnerAbstractNotifier.updateDelay(); + } } @Override diff --git a/v1_8_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_8_R3/spawners/MobSpawnerAbstractNotifier.java b/v1_8_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_8_R3/spawners/MobSpawnerAbstractNotifier.java new file mode 100644 index 000000000..3a9afde34 --- /dev/null +++ b/v1_8_R3/src/main/java/com/bgsoftware/superiorskyblock/nms/v1_8_R3/spawners/MobSpawnerAbstractNotifier.java @@ -0,0 +1,83 @@ +package com.bgsoftware.superiorskyblock.nms.v1_8_R3.spawners; + +import net.minecraft.server.v1_8_R3.BlockPosition; +import net.minecraft.server.v1_8_R3.MobSpawnerAbstract; +import net.minecraft.server.v1_8_R3.NBTTagCompound; +import net.minecraft.server.v1_8_R3.World; + +import javax.annotation.Nullable; +import java.util.function.IntFunction; + +public class MobSpawnerAbstractNotifier extends MobSpawnerAbstract { + + private final MobSpawnerAbstract mobSpawnerAbstract; + private final IntFunction delayChangeCallback; + + public MobSpawnerAbstractNotifier(MobSpawnerAbstract mobSpawnerAbstract, IntFunction delayChangeCallback) { + this.mobSpawnerAbstract = mobSpawnerAbstract; + this.delayChangeCallback = delayChangeCallback; + } + + @Nullable + @Override + public String getMobName() { + return mobSpawnerAbstract.getMobName(); + } + + @Override + public void setMobName(String name) { + mobSpawnerAbstract.setMobName(name); + } + + @Override + public void c() { + int startDelay = mobSpawnerAbstract.spawnDelay; + try { + mobSpawnerAbstract.c(); + } finally { + int newDelay = mobSpawnerAbstract.spawnDelay; + if (newDelay > startDelay) + updateDelay(); + } + } + + @Override + public void a(NBTTagCompound nbttagcompound) { + mobSpawnerAbstract.a(nbttagcompound); + } + + @Override + public void b(NBTTagCompound nbttagcompound) { + mobSpawnerAbstract.b(nbttagcompound); + } + + @Override + public boolean b(int i) { + return mobSpawnerAbstract.b(i); + } + + @Override + public void a(a mobspawnerabstract_a) { + mobSpawnerAbstract.a(mobspawnerabstract_a); + } + + @Override + public void a(int i) { + mobSpawnerAbstract.a(i); + } + + @Override + public World a() { + return mobSpawnerAbstract.a(); + } + + @Override + public BlockPosition b() { + return mobSpawnerAbstract.b(); + } + + public void updateDelay() { + mobSpawnerAbstract.spawnDelay = delayChangeCallback.apply(mobSpawnerAbstract.spawnDelay); + } + +}