diff --git a/NMS/NMS-API/src/com/songoda/core/nms/ReflectionUtils.java b/NMS/NMS-API/src/com/songoda/core/nms/ReflectionUtils.java
new file mode 100644
index 00000000..311c60bd
--- /dev/null
+++ b/NMS/NMS-API/src/com/songoda/core/nms/ReflectionUtils.java
@@ -0,0 +1,52 @@
+package com.songoda.core.nms;
+
+import java.lang.reflect.Field;
+
+public class ReflectionUtils {
+ private ReflectionUtils() {
+ throw new IllegalStateException("Utility class");
+ }
+
+ public static Object getFieldValue(Object instance, String fieldName) throws NoSuchFieldException, IllegalAccessException {
+ Field f = getField(instance, fieldName);
+ boolean accessible = f.isAccessible();
+
+ f.setAccessible(true);
+
+ Object result = f.get(instance);
+
+ f.setAccessible(accessible);
+
+ return result;
+ }
+
+ public static void setFieldValue(Object instance, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
+ Field f = getField(instance, fieldName);
+ boolean accessible = f.isAccessible();
+
+ f.setAccessible(true);
+
+ f.set(instance, value);
+
+ f.setAccessible(accessible);
+ }
+
+ private static Field getField(Object instance, String fieldName) throws NoSuchFieldException {
+ Field f = null;
+
+ Class> currClass = instance.getClass();
+ do {
+ try {
+ f = currClass.getDeclaredField(fieldName);
+ } catch (NoSuchFieldException ex) {
+ currClass = currClass.getSuperclass();
+
+ if (currClass == null) {
+ throw ex;
+ }
+ }
+ } while (f == null);
+
+ return f;
+ }
+}
diff --git a/NMS/NMS-API/src/com/songoda/core/nms/world/BBaseSpawner.java b/NMS/NMS-API/src/com/songoda/core/nms/world/BBaseSpawner.java
new file mode 100644
index 00000000..d510705d
--- /dev/null
+++ b/NMS/NMS-API/src/com/songoda/core/nms/world/BBaseSpawner.java
@@ -0,0 +1,12 @@
+package com.songoda.core.nms.world;
+
+import java.lang.reflect.InvocationTargetException;
+
+public interface BBaseSpawner {
+ boolean isNearPlayer() throws InvocationTargetException, IllegalAccessException;
+
+ /**
+ * Ignores {@link #isNearPlayer()} - Make sure the server isn't already ticking the spawner!
+ */
+ void tick() throws NoSuchFieldException, IllegalAccessException, InvocationTargetException;
+}
diff --git a/NMS/NMS-API/src/com/songoda/core/nms/world/WorldCore.java b/NMS/NMS-API/src/com/songoda/core/nms/world/WorldCore.java
index d1143b5f..75da36f8 100644
--- a/NMS/NMS-API/src/com/songoda/core/nms/world/WorldCore.java
+++ b/NMS/NMS-API/src/com/songoda/core/nms/world/WorldCore.java
@@ -1,12 +1,15 @@
package com.songoda.core.nms.world;
+import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
+import org.bukkit.block.BlockState;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
-public interface WorldCore {
+import java.lang.reflect.InvocationTargetException;
+public interface WorldCore {
SSpawner getSpawner(CreatureSpawner spawner);
SSpawner getSpawner(Location location);
@@ -14,4 +17,39 @@ public interface WorldCore {
SItemStack getItemStack(ItemStack item);
SWorld getWorld(World world);
+
+ BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException;
+
+ /**
+ * Performs random ticks on a specific chunks.
+ *
+ * More information: https://minecraft.fandom.com/wiki/Tick#Random_tick
+ *
+ * @param bukkitChunk The chunk to tick
+ * @param tickAmount The number of blocks to tick per ChunkSection, normally referred to as randomTickSpeed
+ */
+ void randomTickChunk(Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException;
+
+ /**
+ * Ticks all inactive spawners in a specific chunk ignoring the minimum required players within a specific range.
+ * A spawner is deemed inactive if no player is within its activation range.
+ *
+ * @param chunk The chunk to tick the spawners in
+ * @param amount The amount of ticks to execute for each spawner
+ */
+ default void tickInactiveSpawners(Chunk chunk, int amount) throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
+ if (amount <= 0) return;
+
+ for (BlockState tileEntity : chunk.getTileEntities()) {
+ if (tileEntity instanceof CreatureSpawner) {
+ BBaseSpawner spawner = getBaseSpawner((CreatureSpawner) tileEntity);
+
+ if (!spawner.isNearPlayer()) {
+ for (int i = 0; i < amount; ++i) {
+ spawner.tick();
+ }
+ }
+ }
+ }
+ }
}
diff --git a/NMS/NMS-v1_10_R1/src/com/songoda/core/nms/v1_10_R1/world/WorldCoreImpl.java b/NMS/NMS-v1_10_R1/src/com/songoda/core/nms/v1_10_R1/world/WorldCoreImpl.java
index 9fa44825..2630a68a 100644
--- a/NMS/NMS-v1_10_R1/src/com/songoda/core/nms/v1_10_R1/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_10_R1/src/com/songoda/core/nms/v1_10_R1/world/WorldCoreImpl.java
@@ -1,16 +1,26 @@
package com.songoda.core.nms.v1_10_R1.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_10_R1.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_10_R1.Block;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.Chunk;
+import net.minecraft.server.v1_10_R1.ChunkSection;
+import net.minecraft.server.v1_10_R1.IBlockData;
+import net.minecraft.server.v1_10_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_10_R1.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_10_R1.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +40,47 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#j()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ int j = chunk.locX * 16;
+ int k = chunk.locZ * 16;
+
+ for (ChunkSection chunksection : chunk.getSections()) {
+ if (chunksection != net.minecraft.server.v1_10_R1.Chunk.a && chunksection.shouldTick()) {
+ for (int i = 0; i < tickAmount; ++i) {
+ int worldL = (int) ReflectionUtils.getFieldValue(chunk.world, "l");
+ worldL = worldL * 3 + 1013904223;
+ ReflectionUtils.setFieldValue(chunk.world, "l", worldL);
+
+ int l1 = worldL >> 2;
+ int i2 = l1 & 15;
+ int j2 = l1 >> 8 & 15;
+ int k2 = l1 >> 16 & 15;
+
+ IBlockData iblockdata = chunksection.getType(i2, k2, j2);
+ Block block = iblockdata.getBlock();
+
+ if (block.isTicking()) {
+ block.a(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), iblockdata, chunk.world.random);
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/NMS/NMS-v1_10_R1/src/com/songoda/core/nms/v1_10_R1/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_10_R1/src/com/songoda/core/nms/v1_10_R1/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..18e7a641
--- /dev/null
+++ b/NMS/NMS-v1_10_R1/src/com/songoda/core/nms/v1_10_R1/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,165 @@
+package com.songoda.core.nms.v1_10_R1.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_10_R1.AxisAlignedBB;
+import net.minecraft.server.v1_10_R1.BlockPosition;
+import net.minecraft.server.v1_10_R1.ChunkRegionLoader;
+import net.minecraft.server.v1_10_R1.Entity;
+import net.minecraft.server.v1_10_R1.EntityInsentient;
+import net.minecraft.server.v1_10_R1.EnumParticle;
+import net.minecraft.server.v1_10_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_10_R1.MobSpawnerData;
+import net.minecraft.server.v1_10_R1.NBTTagCompound;
+import net.minecraft.server.v1_10_R1.NBTTagList;
+import org.bukkit.craftbukkit.v1_10_R1.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private static Method iMethod, hMethod;
+
+ private final MobSpawnerAbstract spawner;
+
+ static {
+ try {
+ iMethod = MobSpawnerAbstract.class.getDeclaredMethod("i");
+ iMethod.setAccessible(true);
+
+ hMethod = MobSpawnerAbstract.class.getDeclaredMethod("h");
+ hMethod.setAccessible(true);
+ } catch (NoSuchMethodException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#h()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() throws InvocationTargetException, IllegalAccessException {
+ return (boolean) hMethod.invoke(spawner);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
+ BlockPosition blockposition = spawner.b();
+
+ if (spawner.a().isClientSide) {
+ double d0 = (float) blockposition.getX() + spawner.a().random.nextFloat();
+ double d1 = (float) blockposition.getY() + spawner.a().random.nextFloat();
+ double d2 = (float) blockposition.getZ() + spawner.a().random.nextFloat();
+
+ spawner.a().addParticle(EnumParticle.SMOKE_NORMAL, d0, d1, d2, 0D, 0D, 0D);
+ spawner.a().addParticle(EnumParticle.FLAME, d0, d1, d2, 0D, 0D, 0D);
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerD = (double) ReflectionUtils.getFieldValue(spawner, "d");
+
+ ReflectionUtils.setFieldValue(spawner, "e", spawnerD);
+ ReflectionUtils.setFieldValue(spawner, "d", (spawnerD + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ int spawnCount = (int) ReflectionUtils.getFieldValue(spawner, "spawnCount");
+ int spawnRange = (int) ReflectionUtils.getFieldValue(spawner, "spawnRange");
+ int maxNearbyEntities = (int) ReflectionUtils.getFieldValue(spawner, "maxNearbyEntities");
+ MobSpawnerData spawnData = (MobSpawnerData) ReflectionUtils.getFieldValue(spawner, "spawnData");
+
+ while (true) {
+ if (i >= spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = spawnData.b();
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+
+ net.minecraft.server.v1_10_R1.World world = spawner.a();
+
+ int j = nbttaglist.size();
+ double d3 = j >= 1 ? nbttaglist.e(0) : (double) blockposition.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawnRange + .5D;
+ double d4 = j >= 2 ? nbttaglist.e(1) : (double) (blockposition.getY() + world.random.nextInt(3) - 1);
+ double d5 = j >= 3 ? nbttaglist.e(2) : (double) blockposition.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawnRange + .5D;
+
+ Entity entity = ChunkRegionLoader.a(nbttagcompound, world, d3, d4, d5, false);
+
+ if (entity == null) {
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .g(spawnRange)).size();
+
+ if (k >= maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ EntityInsentient entityinsentient = entity instanceof EntityInsentient ? (EntityInsentient) entity : null;
+ entity.setPositionRotation(entity.locX, entity.locY, entity.locZ, world.random.nextFloat() * 360.0F, 0.0F);
+
+ if (entityinsentient == null || entityinsentient.cK() && entityinsentient.canSpawn()) {
+ if (spawnData.b().d() == 1 && spawnData.b().hasKeyOfType("id", 8) && entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).prepare(world.D(new BlockPosition(entity)), null);
+ }
+
+ if (entity.world.spigotConfig.nerfSpawnerMobs) {
+ entity.fromMobSpawner = true;
+ }
+
+ if (!CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ ChunkRegionLoader.a(entity, world, CreatureSpawnEvent.SpawnReason.SPAWNER);
+ world.triggerEffect(2004, blockposition, 0);
+ if (entityinsentient != null) {
+ entityinsentient.doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#i()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) throws InvocationTargetException, IllegalAccessException {
+ iMethod.invoke(spawner);
+ }
+}
\ No newline at end of file
diff --git a/NMS/NMS-v1_11_R1/src/com/songoda/core/nms/v1_11_R1/world/WorldCoreImpl.java b/NMS/NMS-v1_11_R1/src/com/songoda/core/nms/v1_11_R1/world/WorldCoreImpl.java
index 191ba2fa..7d45f652 100644
--- a/NMS/NMS-v1_11_R1/src/com/songoda/core/nms/v1_11_R1/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_11_R1/src/com/songoda/core/nms/v1_11_R1/world/WorldCoreImpl.java
@@ -1,16 +1,26 @@
package com.songoda.core.nms.v1_11_R1.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_11_R1.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_11_R1.Block;
+import net.minecraft.server.v1_11_R1.BlockPosition;
+import net.minecraft.server.v1_11_R1.Chunk;
+import net.minecraft.server.v1_11_R1.ChunkSection;
+import net.minecraft.server.v1_11_R1.IBlockData;
+import net.minecraft.server.v1_11_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_11_R1.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_11_R1.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +40,47 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#j()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ int j = chunk.locX * 16;
+ int k = chunk.locZ * 16;
+
+ for (ChunkSection chunksection : chunk.getSections()) {
+ if (chunksection != net.minecraft.server.v1_11_R1.Chunk.a && chunksection.shouldTick()) {
+ for (int i = 0; i < tickAmount; ++i) {
+ int worldL = (int) ReflectionUtils.getFieldValue(chunk.world, "l");
+ worldL = worldL * 3 + 1013904223;
+ ReflectionUtils.setFieldValue(chunk.world, "l", worldL);
+
+ int l1 = worldL >> 2;
+ int i2 = l1 & 15;
+ int j2 = l1 >> 8 & 15;
+ int k2 = l1 >> 16 & 15;
+
+ IBlockData iblockdata = chunksection.getType(i2, k2, j2);
+ Block block = iblockdata.getBlock();
+
+ if (block.isTicking()) {
+ block.a(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), iblockdata, chunk.world.random);
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/NMS/NMS-v1_11_R1/src/com/songoda/core/nms/v1_11_R1/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_11_R1/src/com/songoda/core/nms/v1_11_R1/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..bbb52105
--- /dev/null
+++ b/NMS/NMS-v1_11_R1/src/com/songoda/core/nms/v1_11_R1/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,160 @@
+package com.songoda.core.nms.v1_11_R1.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_11_R1.AxisAlignedBB;
+import net.minecraft.server.v1_11_R1.BlockPosition;
+import net.minecraft.server.v1_11_R1.ChunkRegionLoader;
+import net.minecraft.server.v1_11_R1.Entity;
+import net.minecraft.server.v1_11_R1.EntityInsentient;
+import net.minecraft.server.v1_11_R1.EnumParticle;
+import net.minecraft.server.v1_11_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_11_R1.MobSpawnerData;
+import net.minecraft.server.v1_11_R1.NBTTagCompound;
+import net.minecraft.server.v1_11_R1.NBTTagList;
+import org.bukkit.craftbukkit.v1_11_R1.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private static Method iMethod, hMethod;
+
+ private final MobSpawnerAbstract spawner;
+
+ static {
+ try {
+ hMethod = MobSpawnerAbstract.class.getDeclaredMethod("h");
+ hMethod.setAccessible(true);
+
+ iMethod = MobSpawnerAbstract.class.getDeclaredMethod("i");
+ iMethod.setAccessible(true);
+ } catch (NoSuchMethodException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#h()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() throws InvocationTargetException, IllegalAccessException {
+ return (boolean) hMethod.invoke(spawner);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
+ BlockPosition blockposition = spawner.b();
+
+ if (spawner.a().isClientSide) {
+ double d0 = (float) blockposition.getX() + spawner.a().random.nextFloat();
+ double d1 = (float) blockposition.getY() + spawner.a().random.nextFloat();
+ double d2 = (float) blockposition.getZ() + spawner.a().random.nextFloat();
+
+ spawner.a().addParticle(EnumParticle.SMOKE_NORMAL, d0, d1, d2, 0D, 0D, 0D);
+ spawner.a().addParticle(EnumParticle.FLAME, d0, d1, d2, 0D, 0D, 0D);
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerD = (double) ReflectionUtils.getFieldValue(spawner, "d");
+
+ ReflectionUtils.setFieldValue(spawner, "e", spawnerD);
+ ReflectionUtils.setFieldValue(spawner, "d", (spawnerD + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ int spawnCount = (int) ReflectionUtils.getFieldValue(spawner, "spawnCount");
+ int spawnRange = (int) ReflectionUtils.getFieldValue(spawner, "spawnRange");
+ int maxNearbyEntities = (int) ReflectionUtils.getFieldValue(spawner, "maxNearbyEntities");
+ MobSpawnerData spawnData = (MobSpawnerData) ReflectionUtils.getFieldValue(spawner, "spawnData");
+
+ while (true) {
+ if (i >= spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = spawnData.b();
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+ net.minecraft.server.v1_11_R1.World world = spawner.a();
+ int j = nbttaglist.size();
+ double d3 = j >= 1 ? nbttaglist.e(0) : (double) blockposition.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawnRange + .5D;
+ double d4 = j >= 2 ? nbttaglist.e(1) : (double) (blockposition.getY() + world.random.nextInt(3) - 1);
+ double d5 = j >= 3 ? nbttaglist.e(2) : (double) blockposition.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawnRange + .5D;
+ Entity entity = ChunkRegionLoader.a(nbttagcompound, world, d3, d4, d5, false);
+ if (entity == null) {
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(
+ blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .g(spawnRange)).size();
+ if (k >= maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ EntityInsentient entityinsentient = entity instanceof EntityInsentient ? (EntityInsentient) entity : null;
+ entity.setPositionRotation(entity.locX, entity.locY, entity.locZ, world.random.nextFloat() * 360.0F, 0.0F);
+ if (entityinsentient == null || entityinsentient.cM() && entityinsentient.canSpawn()) {
+ if (spawnData.b().d() == 1 && spawnData.b().hasKeyOfType("id", 8) && entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).prepare(world.D(new BlockPosition(entity)), null);
+ }
+
+ if (entity.world.spigotConfig.nerfSpawnerMobs) {
+ entity.fromMobSpawner = true;
+ }
+
+ if (!CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ ChunkRegionLoader.a(entity, world, CreatureSpawnEvent.SpawnReason.SPAWNER);
+ world.triggerEffect(2004, blockposition, 0);
+
+ if (entityinsentient != null) {
+ entityinsentient.doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#i()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) throws InvocationTargetException, IllegalAccessException {
+ iMethod.invoke(spawner);
+ }
+}
\ No newline at end of file
diff --git a/NMS/NMS-v1_12_R1/src/com/songoda/core/nms/v1_12_R1/world/WorldCoreImpl.java b/NMS/NMS-v1_12_R1/src/com/songoda/core/nms/v1_12_R1/world/WorldCoreImpl.java
index aeb21a05..df653a91 100644
--- a/NMS/NMS-v1_12_R1/src/com/songoda/core/nms/v1_12_R1/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_12_R1/src/com/songoda/core/nms/v1_12_R1/world/WorldCoreImpl.java
@@ -1,16 +1,26 @@
package com.songoda.core.nms.v1_12_R1.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_12_R1.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_12_R1.Block;
+import net.minecraft.server.v1_12_R1.BlockPosition;
+import net.minecraft.server.v1_12_R1.Chunk;
+import net.minecraft.server.v1_12_R1.ChunkSection;
+import net.minecraft.server.v1_12_R1.IBlockData;
+import net.minecraft.server.v1_12_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_12_R1.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_12_R1.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +40,47 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#j()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ int j = chunk.locX * 16;
+ int k = chunk.locZ * 16;
+
+ for (ChunkSection chunksection : chunk.getSections()) {
+ if (chunksection != net.minecraft.server.v1_12_R1.Chunk.a && chunksection.shouldTick()) {
+ for (int k1 = 0; k1 < tickAmount; ++k1) {
+ int worldL = (int) ReflectionUtils.getFieldValue(chunk.world, "l");
+ worldL = worldL * 3 + 1013904223;
+ ReflectionUtils.setFieldValue(chunk.world, "l", worldL);
+
+ int l1 = worldL >> 2;
+ int i2 = l1 & 15;
+ int j2 = l1 >> 8 & 15;
+ int k2 = l1 >> 16 & 15;
+
+ IBlockData iblockdata = chunksection.getType(i2, k2, j2);
+ Block block = iblockdata.getBlock();
+
+ if (block.isTicking()) {
+ block.a(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), iblockdata, chunk.world.random);
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/NMS/NMS-v1_12_R1/src/com/songoda/core/nms/v1_12_R1/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_12_R1/src/com/songoda/core/nms/v1_12_R1/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..47501034
--- /dev/null
+++ b/NMS/NMS-v1_12_R1/src/com/songoda/core/nms/v1_12_R1/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,164 @@
+package com.songoda.core.nms.v1_12_R1.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_12_R1.AxisAlignedBB;
+import net.minecraft.server.v1_12_R1.BlockPosition;
+import net.minecraft.server.v1_12_R1.ChunkRegionLoader;
+import net.minecraft.server.v1_12_R1.Entity;
+import net.minecraft.server.v1_12_R1.EntityInsentient;
+import net.minecraft.server.v1_12_R1.EnumParticle;
+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.NBTTagList;
+import org.bukkit.craftbukkit.v1_12_R1.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private static Method iMethod;
+
+ private final MobSpawnerAbstract spawner;
+
+ static {
+ try {
+ iMethod = MobSpawnerAbstract.class.getDeclaredMethod("i");
+ iMethod.setAccessible(true);
+ } catch (NoSuchMethodException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#h()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() {
+ BlockPosition blockposition = spawner.b();
+
+ return spawner.a().isPlayerNearby(
+ (double) blockposition.getX() + 0.5D,
+ (double) blockposition.getY() + 0.5D,
+ (double) blockposition.getZ() + 0.5D,
+ spawner.requiredPlayerRange);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
+ BlockPosition blockposition = spawner.b();
+
+ if (spawner.a().isClientSide) {
+ double d0 = (float) blockposition.getX() + spawner.a().random.nextFloat();
+ double d1 = (float) blockposition.getY() + spawner.a().random.nextFloat();
+ double d2 = (float) blockposition.getZ() + spawner.a().random.nextFloat();
+ spawner.a().addParticle(EnumParticle.SMOKE_NORMAL, d0, d1, d2, 0.0D, 0.0D, 0.0D);
+ spawner.a().addParticle(EnumParticle.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D);
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerD = (double) ReflectionUtils.getFieldValue(spawner, "d");
+
+ ReflectionUtils.setFieldValue(spawner, "e", spawnerD);
+ ReflectionUtils.setFieldValue(spawner, "d", (spawnerD + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ MobSpawnerData spawnData = (MobSpawnerData) ReflectionUtils.getFieldValue(spawner, "spawnData");
+
+ while (true) {
+ if (i >= spawner.spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = spawnData.b();
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+
+ net.minecraft.server.v1_12_R1.World world = spawner.a();
+
+ int j = nbttaglist.size();
+ double d3 = j >= 1 ? nbttaglist.f(0) : (double) blockposition.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ double d4 = j >= 2 ? nbttaglist.f(1) : (double) (blockposition.getY() + world.random.nextInt(3) - 1);
+ double d5 = j >= 3 ? nbttaglist.f(2) : (double) blockposition.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+
+ Entity entity = ChunkRegionLoader.a(nbttagcompound, world, d3, d4, d5, false);
+
+ if (entity == null) {
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(
+ blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .g(spawner.spawnRange)).size();
+
+ if (k >= spawner.maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ EntityInsentient entityinsentient = entity instanceof EntityInsentient ? (EntityInsentient) entity : null;
+ entity.setPositionRotation(entity.locX, entity.locY, entity.locZ, world.random.nextFloat() * 360.0F, 0.0F);
+
+ if (entityinsentient == null || entityinsentient.P() && entityinsentient.canSpawn()) {
+ if (spawnData.b().d() == 1 && spawnData.b().hasKeyOfType("id", 8) && entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).prepare(world.D(new BlockPosition(entity)), null);
+ }
+
+ if (entity.world.spigotConfig.nerfSpawnerMobs) {
+ entity.fromMobSpawner = true;
+ }
+
+ if (!CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ ChunkRegionLoader.a(entity, world, CreatureSpawnEvent.SpawnReason.SPAWNER);
+ world.triggerEffect(2004, blockposition, 0);
+
+ if (entityinsentient != null) {
+ entityinsentient.doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#i()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) throws InvocationTargetException, IllegalAccessException {
+ iMethod.invoke(spawner);
+ }
+}
\ No newline at end of file
diff --git a/NMS/NMS-v1_13_R1/src/com/songoda/core/nms/v1_13_R1/world/WorldCoreImpl.java b/NMS/NMS-v1_13_R1/src/com/songoda/core/nms/v1_13_R1/world/WorldCoreImpl.java
index 7e152faa..027c9521 100644
--- a/NMS/NMS-v1_13_R1/src/com/songoda/core/nms/v1_13_R1/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_13_R1/src/com/songoda/core/nms/v1_13_R1/world/WorldCoreImpl.java
@@ -1,16 +1,26 @@
package com.songoda.core.nms.v1_13_R1.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_13_R1.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_13_R1.BlockPosition;
+import net.minecraft.server.v1_13_R1.Chunk;
+import net.minecraft.server.v1_13_R1.ChunkSection;
+import net.minecraft.server.v1_13_R1.Fluid;
+import net.minecraft.server.v1_13_R1.IBlockData;
+import net.minecraft.server.v1_13_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_13_R1.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_13_R1.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +40,51 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#l()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ int j = chunk.locX * 16;
+ int k = chunk.locZ * 16;
+
+ for (ChunkSection chunksection : chunk.getSections()) {
+ if (chunksection != net.minecraft.server.v1_13_R1.Chunk.a && chunksection.b()) {
+ for (int i = 0; i < tickAmount; ++i) {
+ int worldM = (int) ReflectionUtils.getFieldValue(chunk.world, "m");
+ worldM = worldM * 3 + 1013904223;
+ ReflectionUtils.setFieldValue(chunk.world, "m", worldM);
+
+ int l1 = worldM >> 2;
+ int i2 = l1 & 15;
+ int j2 = l1 >> 8 & 15;
+ int k2 = l1 >> 16 & 15;
+
+ IBlockData iblockdata = chunksection.getType(i2, k2, j2);
+ Fluid fluid = chunksection.b(i2, k2, j2);
+
+ if (iblockdata.t()) {
+ iblockdata.b(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), chunk.world.random);
+ }
+
+ if (fluid.h()) {
+ fluid.b(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), chunk.world.random);
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/NMS/NMS-v1_13_R1/src/com/songoda/core/nms/v1_13_R1/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_13_R1/src/com/songoda/core/nms/v1_13_R1/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..f19c4c64
--- /dev/null
+++ b/NMS/NMS-v1_13_R1/src/com/songoda/core/nms/v1_13_R1/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,167 @@
+package com.songoda.core.nms.v1_13_R1.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_13_R1.AxisAlignedBB;
+import net.minecraft.server.v1_13_R1.BlockPosition;
+import net.minecraft.server.v1_13_R1.ChunkRegionLoader;
+import net.minecraft.server.v1_13_R1.Entity;
+import net.minecraft.server.v1_13_R1.EntityInsentient;
+import net.minecraft.server.v1_13_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_13_R1.MobSpawnerData;
+import net.minecraft.server.v1_13_R1.NBTTagCompound;
+import net.minecraft.server.v1_13_R1.NBTTagList;
+import net.minecraft.server.v1_13_R1.Particles;
+import org.bukkit.craftbukkit.v1_13_R1.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private static Method iMethod;
+
+ private final MobSpawnerAbstract spawner;
+
+ static {
+ try {
+ iMethod = MobSpawnerAbstract.class.getDeclaredMethod("i");
+ iMethod.setAccessible(true);
+ } catch (NoSuchMethodException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#h()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() {
+ BlockPosition blockposition = spawner.b();
+
+ return spawner.a().isPlayerNearby(
+ (double) blockposition.getX() + .5D,
+ (double) blockposition.getY() + .5D,
+ (double) blockposition.getZ() + .5D,
+ spawner.requiredPlayerRange);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
+ BlockPosition blockposition = spawner.b();
+
+ if (spawner.a().isClientSide) {
+ double d0 = (float) blockposition.getX() + spawner.a().random.nextFloat();
+ double d1 = (float) blockposition.getY() + spawner.a().random.nextFloat();
+ double d2 = (float) blockposition.getZ() + spawner.a().random.nextFloat();
+
+ spawner.a().addParticle(Particles.M, d0, d1, d2, 0D, 0D, 0D);
+ spawner.a().addParticle(Particles.y, d0, d1, d2, 0D, 0D, 0D);
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerE = (double) ReflectionUtils.getFieldValue(spawner, "e");
+
+ ReflectionUtils.setFieldValue(spawner, "f", spawnerE);
+ ReflectionUtils.setFieldValue(spawner, "e", (spawnerE + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ MobSpawnerData spawnData = (MobSpawnerData) ReflectionUtils.getFieldValue(spawner, "spawnData");
+
+ while (true) {
+ if (i >= spawner.spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = spawnData.b();
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+
+ net.minecraft.server.v1_13_R1.World world = spawner.a();
+
+ int j = nbttaglist.size();
+ double d3 = j >= 1 ? nbttaglist.k(0) : (double) blockposition.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ double d4 = j >= 2 ? nbttaglist.k(1) : (double) (blockposition.getY() + world.random.nextInt(3) - 1);
+ double d5 = j >= 3 ? nbttaglist.k(2) : (double) blockposition.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+
+ Entity entity = ChunkRegionLoader.a(nbttagcompound, world, d3, d4, d5, false);
+
+ if (entity == null) {
+ delay(spawner);
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .g(spawner.spawnRange)).size();
+
+ if (k >= spawner.maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ EntityInsentient entityinsentient = entity instanceof EntityInsentient ? (EntityInsentient) entity : null;
+ entity.setPositionRotation(entity.locX, entity.locY, entity.locZ, world.random.nextFloat() * 360F, 0F);
+
+ if (entityinsentient == null || entityinsentient.M() && entityinsentient.canSpawn()) {
+ if (spawnData.b().d() == 1 && spawnData.b().hasKeyOfType("id", 8) && entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).prepare(world.getDamageScaler(new BlockPosition(entity)), null, null);
+ }
+
+ if (entity.world.spigotConfig.nerfSpawnerMobs) {
+ entity.fromMobSpawner = true;
+ }
+
+ if (!CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ ChunkRegionLoader.a(entity, world, CreatureSpawnEvent.SpawnReason.SPAWNER);
+ world.triggerEffect(2004, blockposition, 0);
+
+ if (entityinsentient != null) {
+ entityinsentient.doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#i()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) throws InvocationTargetException, IllegalAccessException {
+ iMethod.invoke(spawner);
+ }
+}
diff --git a/NMS/NMS-v1_13_R2/src/com/songoda/core/nms/v1_13_R2/world/WorldCoreImpl.java b/NMS/NMS-v1_13_R2/src/com/songoda/core/nms/v1_13_R2/world/WorldCoreImpl.java
index de90a615..6f4e89e9 100644
--- a/NMS/NMS-v1_13_R2/src/com/songoda/core/nms/v1_13_R2/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_13_R2/src/com/songoda/core/nms/v1_13_R2/world/WorldCoreImpl.java
@@ -1,16 +1,26 @@
package com.songoda.core.nms.v1_13_R2.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_13_R2.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_13_R2.BlockPosition;
+import net.minecraft.server.v1_13_R2.Chunk;
+import net.minecraft.server.v1_13_R2.ChunkSection;
+import net.minecraft.server.v1_13_R2.Fluid;
+import net.minecraft.server.v1_13_R2.IBlockData;
+import net.minecraft.server.v1_13_R2.MobSpawnerAbstract;
+import net.minecraft.server.v1_13_R2.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_13_R2.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +40,58 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#n_()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ int j = chunk.locX * 16;
+ int k = chunk.locZ * 16;
+
+ chunk.world.methodProfiler.enter("tickBlocks");
+ for (ChunkSection chunksection : chunk.getSections()) {
+ if (chunksection != net.minecraft.server.v1_13_R2.Chunk.a && chunksection.b()) {
+ for (int k1 = 0; k1 < tickAmount; ++k1) {
+ int worldM = (int) ReflectionUtils.getFieldValue(chunk.world, "m");
+ worldM = worldM * 3 + 1013904223;
+ ReflectionUtils.setFieldValue(chunk.world, "m", worldM);
+
+ int l1 = worldM >> 2;
+ int i2 = l1 & 15;
+ int j2 = l1 >> 8 & 15;
+ int k2 = l1 >> 16 & 15;
+
+ IBlockData iblockdata = chunksection.getType(i2, k2, j2);
+ Fluid fluid = chunksection.b(i2, k2, j2);
+
+ chunk.world.methodProfiler.enter("randomTick");
+
+ if (iblockdata.t()) {
+ iblockdata.b(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), chunk.world.random);
+ }
+
+ if (fluid.h()) {
+ fluid.b(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), chunk.world.random);
+ }
+
+ chunk.world.methodProfiler.exit();
+ }
+ }
+ }
+
+ chunk.world.methodProfiler.exit();
+ }
+ }
}
diff --git a/NMS/NMS-v1_13_R2/src/com/songoda/core/nms/v1_13_R2/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_13_R2/src/com/songoda/core/nms/v1_13_R2/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..af7a68cd
--- /dev/null
+++ b/NMS/NMS-v1_13_R2/src/com/songoda/core/nms/v1_13_R2/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,172 @@
+package com.songoda.core.nms.v1_13_R2.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_13_R2.AxisAlignedBB;
+import net.minecraft.server.v1_13_R2.BlockPosition;
+import net.minecraft.server.v1_13_R2.ChunkRegionLoader;
+import net.minecraft.server.v1_13_R2.Entity;
+import net.minecraft.server.v1_13_R2.EntityInsentient;
+import net.minecraft.server.v1_13_R2.MobSpawnerAbstract;
+import net.minecraft.server.v1_13_R2.MobSpawnerData;
+import net.minecraft.server.v1_13_R2.NBTTagCompound;
+import net.minecraft.server.v1_13_R2.NBTTagList;
+import net.minecraft.server.v1_13_R2.Particles;
+import org.bukkit.craftbukkit.v1_13_R2.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private static Method iMethod;
+
+ private final MobSpawnerAbstract spawner;
+
+ static {
+ try {
+ iMethod = MobSpawnerAbstract.class.getDeclaredMethod("i");
+ iMethod.setAccessible(true);
+ } catch (NoSuchMethodException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#h()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() {
+ BlockPosition blockposition = spawner.b();
+
+ return spawner.a().b(
+ (double) blockposition.getX() + .5D,
+ (double) blockposition.getY() + .5D,
+ (double) blockposition.getZ() + .5D,
+ spawner.requiredPlayerRange);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
+ BlockPosition blockposition = spawner.b();
+
+ if (spawner.a().isClientSide) {
+ double d0 = (float) blockposition.getX() + spawner.a().random.nextFloat();
+ double d1 = (float) blockposition.getY() + spawner.a().random.nextFloat();
+ double d2 = (float) blockposition.getZ() + spawner.a().random.nextFloat();
+ spawner.a().addParticle(Particles.M, d0, d1, d2, 0.0D, 0.0D, 0.0D);
+ spawner.a().addParticle(Particles.y, d0, d1, d2, 0.0D, 0.0D, 0.0D);
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerE = (double) ReflectionUtils.getFieldValue(spawner, "e");
+
+ ReflectionUtils.setFieldValue(spawner, "f", spawnerE);
+ ReflectionUtils.setFieldValue(spawner, "e", (spawnerE + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ MobSpawnerData spawnData = (MobSpawnerData) ReflectionUtils.getFieldValue(spawner, "spawnData");
+
+ while (true) {
+ if (i >= spawner.spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = spawnData.b();
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+ net.minecraft.server.v1_13_R2.World world = spawner.a();
+ int j = nbttaglist.size();
+ double d3 = j >= 1 ? nbttaglist.k(0) : (double) blockposition.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ double d4 = j >= 2 ? nbttaglist.k(1) : (double) (blockposition.getY() + world.random.nextInt(3) - 1);
+ double d5 = j >= 3 ? nbttaglist.k(2) : (double) blockposition.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ Entity entity = ChunkRegionLoader.a(nbttagcompound, world, d3, d4, d5, false);
+ if (entity == null) {
+ delay(spawner);
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(
+ blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .g(spawner.spawnRange)).size();
+
+ if (k >= spawner.maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ EntityInsentient entityinsentient = entity instanceof EntityInsentient ? (EntityInsentient) entity : null;
+ entity.setPositionRotation(entity.locX, entity.locY, entity.locZ, world.random.nextFloat() * 360.0F, 0.0F);
+ if (entityinsentient == null || entityinsentient.a(world, true) && entityinsentient.canSpawn()) {
+ if (spawnData.b().d() == 1 && spawnData.b().hasKeyOfType("id", 8) && entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).prepare(world.getDamageScaler(new BlockPosition(entity)), null, null);
+ }
+
+ if (entity.world.spigotConfig.nerfSpawnerMobs) {
+ entity.fromMobSpawner = true;
+ }
+
+ if (CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ Entity vehicle = entity.getVehicle();
+ if (vehicle != null) {
+ vehicle.dead = true;
+ }
+
+ Entity passenger;
+ for (Iterator var19 = entity.getAllPassengers().iterator(); var19.hasNext(); passenger.dead = true) {
+ passenger = var19.next();
+ }
+ } else {
+ ChunkRegionLoader.a(entity, world, CreatureSpawnEvent.SpawnReason.SPAWNER);
+ world.triggerEffect(2004, blockposition, 0);
+
+ if (entityinsentient != null) {
+ entityinsentient.doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#i()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) throws InvocationTargetException, IllegalAccessException {
+ iMethod.invoke(spawner);
+ }
+}
diff --git a/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/world/WorldCoreImpl.java b/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/world/WorldCoreImpl.java
index 5650cce8..b2ffa2a8 100644
--- a/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/world/WorldCoreImpl.java
@@ -1,16 +1,28 @@
package com.songoda.core.nms.v1_14_R1.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_14_R1.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_14_R1.BlockPosition;
+import net.minecraft.server.v1_14_R1.Chunk;
+import net.minecraft.server.v1_14_R1.ChunkCoordIntPair;
+import net.minecraft.server.v1_14_R1.ChunkSection;
+import net.minecraft.server.v1_14_R1.Fluid;
+import net.minecraft.server.v1_14_R1.GameProfilerFiller;
+import net.minecraft.server.v1_14_R1.IBlockData;
+import net.minecraft.server.v1_14_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_14_R1.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_14_R1.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +42,53 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#a(Chunk, int)}.
+ */
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
+ int j = chunkcoordintpair.d();
+ int k = chunkcoordintpair.e();
+
+ GameProfilerFiller profiler = chunk.world.getMethodProfiler();
+
+ profiler.enter("tickBlocks");
+ for (ChunkSection chunksection : chunk.getSections()) {
+ if (chunksection != net.minecraft.server.v1_14_R1.Chunk.a && chunksection.d()) {
+ int j1 = chunksection.getYPosition();
+
+ for (int i = 0; i < tickAmount; ++i) {
+ BlockPosition blockposition2 = chunk.world.a(j, j1, k, 15);
+ profiler.enter("randomTick");
+ IBlockData iblockdata = chunksection.getType(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k);
+
+ if (iblockdata.q()) {
+ iblockdata.b(chunk.world, blockposition2, chunk.world.random);
+ }
+
+ Fluid fluid = iblockdata.p();
+ if (fluid.h()) {
+ fluid.b(chunk.world, blockposition2, chunk.world.random);
+ }
+
+ profiler.exit();
+ }
+ }
+ }
+
+ profiler.exit();
+ }
+ }
}
diff --git a/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..a09bf563
--- /dev/null
+++ b/NMS/NMS-v1_14_R1/src/com/songoda/core/nms/v1_14_R1/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,202 @@
+package com.songoda.core.nms.v1_14_R1.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_14_R1.AxisAlignedBB;
+import net.minecraft.server.v1_14_R1.BlockPosition;
+import net.minecraft.server.v1_14_R1.Entity;
+import net.minecraft.server.v1_14_R1.EntityInsentient;
+import net.minecraft.server.v1_14_R1.EntityPositionTypes;
+import net.minecraft.server.v1_14_R1.EntityTypes;
+import net.minecraft.server.v1_14_R1.EnumMobSpawn;
+import net.minecraft.server.v1_14_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_14_R1.NBTTagCompound;
+import net.minecraft.server.v1_14_R1.NBTTagList;
+import net.minecraft.server.v1_14_R1.Particles;
+import net.minecraft.server.v1_14_R1.WeightedRandom;
+import org.bukkit.craftbukkit.v1_14_R1.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.util.Iterator;
+import java.util.Optional;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private final MobSpawnerAbstract spawner;
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#h()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() {
+ BlockPosition blockposition = spawner.b();
+
+ return spawner.a().isPlayerNearby(
+ (double) blockposition.getX() + .5D,
+ (double) blockposition.getY() + .5D,
+ (double) blockposition.getZ() + .5D,
+ spawner.requiredPlayerRange);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException {
+ net.minecraft.server.v1_14_R1.World world = spawner.a();
+ BlockPosition blockposition = spawner.b();
+
+ if (world.isClientSide) {
+ double d0 = (float) blockposition.getX() + world.random.nextFloat();
+ double d1 = (float) blockposition.getY() + world.random.nextFloat();
+ double d2 = (float) blockposition.getZ() + world.random.nextFloat();
+
+ world.addParticle(Particles.SMOKE, d0, d1, d2, 0D, 0D, 0D);
+ world.addParticle(Particles.FLAME, d0, d1, d2, 0D, 0D, 0D);
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerE = (double) ReflectionUtils.getFieldValue(spawner, "e");
+ ReflectionUtils.setFieldValue(spawner, "f", spawnerE);
+ ReflectionUtils.setFieldValue(spawner, "e", (spawnerE + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ while (true) {
+ if (i >= spawner.spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = spawner.spawnData.getEntity();
+ Optional> optional = EntityTypes.a(nbttagcompound);
+ if (!optional.isPresent()) {
+ delay(spawner);
+ return;
+ }
+
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+ int j = nbttaglist.size();
+ double d3 = j >= 1 ? nbttaglist.h(0) : (double) blockposition.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ double d4 = j >= 2 ? nbttaglist.h(1) : (double) (blockposition.getY() + world.random.nextInt(3) - 1);
+ double d5 = j >= 3 ? nbttaglist.h(2) : (double) blockposition.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ if (world.c(optional.get().a(d3, d4, d5)) && EntityPositionTypes.a(optional.get(), world.getMinecraftWorld(), EnumMobSpawn.SPAWNER, new BlockPosition(d3, d4, d5), world.getRandom())) {
+ label112:
+ {
+ Entity entity = EntityTypes.a(nbttagcompound, world, (entity1) -> {
+ entity1.setPositionRotation(d3, d4, d5, entity1.yaw, entity1.pitch);
+ return entity1;
+ });
+ if (entity == null) {
+ delay(spawner);
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(
+ blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .g(spawner.spawnRange)).size();
+
+ if (k >= spawner.maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ entity.setPositionRotation(entity.locX, entity.locY, entity.locZ, world.random.nextFloat() * 360F, 0F);
+ if (entity instanceof EntityInsentient) {
+ EntityInsentient entityinsentient = (EntityInsentient) entity;
+ if (!entityinsentient.a(world, EnumMobSpawn.SPAWNER) || !entityinsentient.a(world)) {
+ break label112;
+ }
+
+ if (spawner.spawnData.getEntity().d() == 1 && spawner.spawnData.getEntity().hasKeyOfType("id", 8)) {
+ ((EntityInsentient) entity).prepare(world, world.getDamageScaler(new BlockPosition(entity)), EnumMobSpawn.SPAWNER, null, null);
+ }
+ }
+
+ if (entity.world.spigotConfig.nerfSpawnerMobs) {
+ entity.fromMobSpawner = true;
+ }
+
+ if (CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ Entity vehicle = entity.getVehicle();
+ if (vehicle != null) {
+ vehicle.dead = true;
+ }
+
+ Entity passenger;
+ for (Iterator var19 = entity.getAllPassengers().iterator(); var19.hasNext(); passenger.dead = true) {
+ passenger = var19.next();
+ }
+ } else {
+ addWithPassengers(spawner, entity);
+ world.triggerEffect(2004, blockposition, 0);
+
+ if (entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#i()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) {
+ if (spawner.maxSpawnDelay <= spawner.minSpawnDelay) {
+ spawner.spawnDelay = spawner.minSpawnDelay;
+ } else {
+ int i = spawner.maxSpawnDelay - spawner.minSpawnDelay;
+ spawner.spawnDelay = spawner.minSpawnDelay + spawner.a().random.nextInt(i);
+ }
+
+ if (!spawner.mobs.isEmpty()) {
+ spawner.setSpawnData(WeightedRandom.a(spawner.a().random, spawner.mobs));
+ }
+
+ spawner.a(1);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#a(Entity)}.
+ */
+ @SuppressWarnings("JavadocReference")
+ static void addWithPassengers(MobSpawnerAbstract spawner, Entity entity) {
+ if (spawner.a().addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER)) {
+ for (Entity value : entity.getPassengers()) {
+ addWithPassengers(spawner, value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/world/WorldCoreImpl.java b/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/world/WorldCoreImpl.java
index 22fd035b..fa37a0ae 100644
--- a/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/world/WorldCoreImpl.java
@@ -1,16 +1,28 @@
package com.songoda.core.nms.v1_15_R1.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_15_R1.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_15_R1.BlockPosition;
+import net.minecraft.server.v1_15_R1.Chunk;
+import net.minecraft.server.v1_15_R1.ChunkCoordIntPair;
+import net.minecraft.server.v1_15_R1.ChunkSection;
+import net.minecraft.server.v1_15_R1.Fluid;
+import net.minecraft.server.v1_15_R1.GameProfilerFiller;
+import net.minecraft.server.v1_15_R1.IBlockData;
+import net.minecraft.server.v1_15_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_15_R1.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_15_R1.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +42,56 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#a(net.minecraft.server.v1_15_R1.Chunk, int)}.
+ */
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
+ int j = chunkcoordintpair.d();
+ int k = chunkcoordintpair.e();
+ GameProfilerFiller profiler = chunk.world.getMethodProfiler();
+
+ profiler.enter("tickBlocks");
+
+ for (ChunkSection chunksection : chunk.getSections()) {
+ if (chunksection != Chunk.a && chunksection.d()) {
+ int j1 = chunksection.getYPosition();
+
+ for (int k1 = 0; k1 < tickAmount; ++k1) {
+ BlockPosition blockposition2 = chunk.world.a(j, j1, k, 15);
+ profiler.enter("randomTick");
+ IBlockData iblockdata = chunksection.getType(
+ blockposition2.getX() - j,
+ blockposition2.getY() - j1,
+ blockposition2.getZ() - k);
+
+ if (iblockdata.q()) {
+ iblockdata.b((WorldServer) chunk.world, blockposition2, chunk.world.random);
+ }
+
+ Fluid fluid = iblockdata.getFluid();
+ if (fluid.h()) {
+ fluid.b(chunk.world, blockposition2, chunk.world.random);
+ }
+
+ profiler.exit();
+ }
+ }
+ }
+
+ profiler.exit();
+ }
+ }
}
diff --git a/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..a353d577
--- /dev/null
+++ b/NMS/NMS-v1_15_R1/src/com/songoda/core/nms/v1_15_R1/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,203 @@
+package com.songoda.core.nms.v1_15_R1.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_15_R1.AxisAlignedBB;
+import net.minecraft.server.v1_15_R1.BlockPosition;
+import net.minecraft.server.v1_15_R1.Entity;
+import net.minecraft.server.v1_15_R1.EntityInsentient;
+import net.minecraft.server.v1_15_R1.EntityPositionTypes;
+import net.minecraft.server.v1_15_R1.EntityTypes;
+import net.minecraft.server.v1_15_R1.EnumMobSpawn;
+import net.minecraft.server.v1_15_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_15_R1.NBTTagCompound;
+import net.minecraft.server.v1_15_R1.NBTTagList;
+import net.minecraft.server.v1_15_R1.Particles;
+import net.minecraft.server.v1_15_R1.WeightedRandom;
+import org.bukkit.craftbukkit.v1_15_R1.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.util.Iterator;
+import java.util.Optional;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private final MobSpawnerAbstract spawner;
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#h()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() {
+ BlockPosition blockposition = spawner.b();
+
+ return spawner.a().isPlayerNearby(
+ (double) blockposition.getX() + .5D,
+ (double) blockposition.getY() + .5D,
+ (double) blockposition.getZ() + .5D,
+ spawner.requiredPlayerRange);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException {
+ net.minecraft.server.v1_15_R1.World world = spawner.a();
+ BlockPosition blockposition = spawner.b();
+
+ if (world.isClientSide) {
+ double d0 = (double) blockposition.getX() + (double) world.random.nextFloat();
+ double d1 = (double) blockposition.getY() + (double) world.random.nextFloat();
+ double d2 = (double) blockposition.getZ() + (double) world.random.nextFloat();
+ world.addParticle(Particles.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D);
+ world.addParticle(Particles.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D);
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerE = (double) ReflectionUtils.getFieldValue(spawner, "e");
+ ReflectionUtils.setFieldValue(spawner, "f", spawnerE);
+ ReflectionUtils.setFieldValue(spawner, "e", (spawnerE + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ while (true) {
+ if (i >= spawner.spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = spawner.spawnData.getEntity();
+ Optional> optional = EntityTypes.a(nbttagcompound);
+ if (!optional.isPresent()) {
+ delay(spawner);
+ return;
+ }
+
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+ int j = nbttaglist.size();
+ double d3 = j >= 1 ? nbttaglist.h(0) : (double) blockposition.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ double d4 = j >= 2 ? nbttaglist.h(1) : (double) (blockposition.getY() + world.random.nextInt(3) - 1);
+ double d5 = j >= 3 ? nbttaglist.h(2) : (double) blockposition.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ if (world.a(optional.get().a(d3, d4, d5)) && EntityPositionTypes.a(optional.get(), world.getMinecraftWorld(), EnumMobSpawn.SPAWNER, new BlockPosition(d3, d4, d5), world.getRandom())) {
+ label112:
+ {
+ Entity entity = EntityTypes.a(nbttagcompound, world, (entity1) -> {
+ entity1.setPositionRotation(d3, d4, d5, entity1.yaw, entity1.pitch);
+ return entity1;
+ });
+ if (entity == null) {
+ delay(spawner);
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(
+ blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .g(spawner.spawnRange)).size();
+
+ if (k >= spawner.maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ entity.setPositionRotation(entity.locX(), entity.locY(), entity.locZ(), world.random.nextFloat() * 360F, 0F);
+ if (entity instanceof EntityInsentient) {
+ EntityInsentient entityinsentient = (EntityInsentient) entity;
+ if (!entityinsentient.a(world, EnumMobSpawn.SPAWNER) || !entityinsentient.a(world)) {
+ break label112;
+ }
+
+ if (spawner.spawnData.getEntity().e() == 1 && spawner.spawnData.getEntity().hasKeyOfType("id", 8)) {
+ ((EntityInsentient) entity).prepare(world, world.getDamageScaler(new BlockPosition(entity)), EnumMobSpawn.SPAWNER, null, null);
+ }
+
+ if (entityinsentient.world.spigotConfig.nerfSpawnerMobs) {
+ try {
+ entityinsentient.getClass().getField("aware").setBoolean(entityinsentient, false);
+ } catch (NoSuchFieldException ignore) { // Spigot 1.15.0 uses another flag for it
+ entityinsentient.fromMobSpawner = true;
+ }
+ }
+ }
+
+ if (CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ Entity vehicle = entity.getVehicle();
+ if (vehicle != null) {
+ vehicle.dead = true;
+ }
+
+ Entity passenger;
+ for (Iterator var19 = entity.getAllPassengers().iterator(); var19.hasNext(); passenger.dead = true) {
+ passenger = var19.next();
+ }
+ } else {
+ addWithPassengers(spawner, entity);
+ world.triggerEffect(2004, blockposition, 0);
+ if (entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#i()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) {
+ if (spawner.maxSpawnDelay <= spawner.minSpawnDelay) {
+ spawner.spawnDelay = spawner.minSpawnDelay;
+ } else {
+ int i = spawner.maxSpawnDelay - spawner.minSpawnDelay;
+ spawner.spawnDelay = spawner.minSpawnDelay + spawner.a().random.nextInt(i);
+ }
+
+ if (!spawner.mobs.isEmpty()) {
+ spawner.setSpawnData(WeightedRandom.a(spawner.a().random, spawner.mobs));
+ }
+
+ spawner.a(1);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#a(Entity)}.
+ */
+ @SuppressWarnings("JavadocReference")
+ static void addWithPassengers(MobSpawnerAbstract spawner, Entity entity) {
+ if (spawner.a().addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER)) {
+ for (Entity entity1 : entity.getPassengers()) {
+ addWithPassengers(spawner, entity1);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/NMS/NMS-v1_16_R1/src/com/songoda/core/nms/v1_16_R1/world/WorldCoreImpl.java b/NMS/NMS-v1_16_R1/src/com/songoda/core/nms/v1_16_R1/world/WorldCoreImpl.java
index 7167300d..573f20b1 100644
--- a/NMS/NMS-v1_16_R1/src/com/songoda/core/nms/v1_16_R1/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_16_R1/src/com/songoda/core/nms/v1_16_R1/world/WorldCoreImpl.java
@@ -1,16 +1,28 @@
package com.songoda.core.nms.v1_16_R1.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_16_R1.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_16_R1.BlockPosition;
+import net.minecraft.server.v1_16_R1.Chunk;
+import net.minecraft.server.v1_16_R1.ChunkCoordIntPair;
+import net.minecraft.server.v1_16_R1.ChunkSection;
+import net.minecraft.server.v1_16_R1.Fluid;
+import net.minecraft.server.v1_16_R1.GameProfilerFiller;
+import net.minecraft.server.v1_16_R1.IBlockData;
+import net.minecraft.server.v1_16_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_16_R1.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_16_R1.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +42,57 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#a(Chunk, int)}.
+ */
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
+ int j = chunkcoordintpair.d();
+ int k = chunkcoordintpair.e();
+
+ GameProfilerFiller profiler = chunk.world.getMethodProfiler();
+
+ profiler.enter("tickBlocks");
+ for (ChunkSection chunksection : chunk.getSections()) {
+ if (chunksection != Chunk.a && chunksection.d()) {
+ int j1 = chunksection.getYPosition();
+
+ for (int k1 = 0; k1 < tickAmount; ++k1) {
+ BlockPosition blockposition2 = chunk.world.a(j, j1, k, 15);
+ profiler.enter("randomTick");
+
+ IBlockData iblockdata = chunksection.getType(
+ blockposition2.getX() - j,
+ blockposition2.getY() - j1,
+ blockposition2.getZ() - k);
+
+ if (iblockdata.isTicking()) {
+ iblockdata.b(chunk.world, blockposition2, chunk.world.random);
+ }
+
+ Fluid fluid = iblockdata.getFluid();
+ if (fluid.f()) {
+ fluid.b(chunk.world, blockposition2, chunk.world.random);
+ }
+
+ profiler.exit();
+ }
+ }
+ }
+
+ profiler.exit();
+ }
+ }
}
diff --git a/NMS/NMS-v1_16_R1/src/com/songoda/core/nms/v1_16_R1/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_16_R1/src/com/songoda/core/nms/v1_16_R1/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..1ba12b09
--- /dev/null
+++ b/NMS/NMS-v1_16_R1/src/com/songoda/core/nms/v1_16_R1/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,197 @@
+package com.songoda.core.nms.v1_16_R1.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_16_R1.AxisAlignedBB;
+import net.minecraft.server.v1_16_R1.BlockPosition;
+import net.minecraft.server.v1_16_R1.Entity;
+import net.minecraft.server.v1_16_R1.EntityInsentient;
+import net.minecraft.server.v1_16_R1.EntityPositionTypes;
+import net.minecraft.server.v1_16_R1.EntityTypes;
+import net.minecraft.server.v1_16_R1.EnumMobSpawn;
+import net.minecraft.server.v1_16_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_16_R1.NBTTagCompound;
+import net.minecraft.server.v1_16_R1.NBTTagList;
+import net.minecraft.server.v1_16_R1.Particles;
+import net.minecraft.server.v1_16_R1.WeightedRandom;
+import org.bukkit.craftbukkit.v1_16_R1.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.util.Iterator;
+import java.util.Optional;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private final MobSpawnerAbstract spawner;
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#h()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() {
+ BlockPosition blockposition = spawner.b();
+
+ return spawner.a().isPlayerNearby((double) blockposition.getX() + .5D,
+ (double) blockposition.getY() + .5D,
+ (double) blockposition.getZ() + .5D,
+ spawner.requiredPlayerRange);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException {
+ net.minecraft.server.v1_16_R1.World world = spawner.a();
+ BlockPosition blockposition = spawner.b();
+
+ if (world.isClientSide) {
+ double d0 = (double) blockposition.getX() + world.random.nextDouble();
+ double d1 = (double) blockposition.getY() + world.random.nextDouble();
+ double d2 = (double) blockposition.getZ() + world.random.nextDouble();
+ world.addParticle(Particles.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D);
+ world.addParticle(Particles.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D);
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerE = (double) ReflectionUtils.getFieldValue(spawner, "e");
+ ReflectionUtils.setFieldValue(spawner, "f", spawnerE);
+ ReflectionUtils.setFieldValue(spawner, "e", (spawnerE + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ while (true) {
+ if (i >= spawner.spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = spawner.spawnData.getEntity();
+ Optional> optional = EntityTypes.a(nbttagcompound);
+ if (!optional.isPresent()) {
+ delay(spawner);
+ return;
+ }
+
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+ int j = nbttaglist.size();
+ double d3 = j >= 1 ? nbttaglist.h(0) : (double) blockposition.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ double d4 = j >= 2 ? nbttaglist.h(1) : (double) (blockposition.getY() + world.random.nextInt(3) - 1);
+ double d5 = j >= 3 ? nbttaglist.h(2) : (double) blockposition.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ if (world.b(optional.get().a(d3, d4, d5)) && EntityPositionTypes.a(optional.get(), world.getMinecraftWorld(), EnumMobSpawn.SPAWNER, new BlockPosition(d3, d4, d5), world.getRandom())) {
+ label112:
+ {
+ Entity entity = EntityTypes.a(nbttagcompound, world, (entity1) -> {
+ entity1.setPositionRotation(d3, d4, d5, entity1.yaw, entity1.pitch);
+ return entity1;
+ });
+ if (entity == null) {
+ delay(spawner);
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(
+ blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .g(spawner.spawnRange)).size();
+ if (k >= spawner.maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ entity.setPositionRotation(entity.locX(), entity.locY(), entity.locZ(), world.random.nextFloat() * 360.0F, 0.0F);
+ if (entity instanceof EntityInsentient) {
+ EntityInsentient entityinsentient = (EntityInsentient) entity;
+ if (!entityinsentient.a(world, EnumMobSpawn.SPAWNER) || !entityinsentient.a(world)) {
+ break label112;
+ }
+
+ if (spawner.spawnData.getEntity().e() == 1 && spawner.spawnData.getEntity().hasKeyOfType("id", 8)) {
+ ((EntityInsentient) entity).prepare(world, world.getDamageScaler(entity.getChunkCoordinates()), EnumMobSpawn.SPAWNER, null, null);
+ }
+
+ if (entityinsentient.world.spigotConfig.nerfSpawnerMobs) {
+ entityinsentient.aware = false;
+ }
+ }
+
+ if (CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ Entity vehicle = entity.getVehicle();
+ if (vehicle != null) {
+ vehicle.dead = true;
+ }
+
+ Entity passenger;
+ for (Iterator var19 = entity.getAllPassengers().iterator(); var19.hasNext(); passenger.dead = true) {
+ passenger = var19.next();
+ }
+ } else {
+ addWithPassengers(spawner, entity);
+ world.triggerEffect(2004, blockposition, 0);
+ if (entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#i()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) {
+ if (spawner.maxSpawnDelay <= spawner.minSpawnDelay) {
+ spawner.spawnDelay = spawner.minSpawnDelay;
+ } else {
+ int i = spawner.maxSpawnDelay - spawner.minSpawnDelay;
+ spawner.spawnDelay = spawner.minSpawnDelay + spawner.a().random.nextInt(i);
+ }
+
+ if (!spawner.mobs.isEmpty()) {
+ spawner.setSpawnData(WeightedRandom.a(spawner.a().random, spawner.mobs));
+ }
+
+ spawner.a(1);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#a(Entity)}.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void addWithPassengers(MobSpawnerAbstract spawner, Entity entity) {
+ if (spawner.a().addEntity(entity, CreatureSpawnEvent.SpawnReason.SPAWNER)) {
+
+ for (Entity entity1 : entity.getPassengers()) {
+ addWithPassengers(spawner, entity1);
+ }
+ }
+ }
+}
diff --git a/NMS/NMS-v1_16_R2/src/com/songoda/core/nms/v1_16_R2/world/WorldCoreImpl.java b/NMS/NMS-v1_16_R2/src/com/songoda/core/nms/v1_16_R2/world/WorldCoreImpl.java
index 17e0a0ad..e35abdbb 100644
--- a/NMS/NMS-v1_16_R2/src/com/songoda/core/nms/v1_16_R2/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_16_R2/src/com/songoda/core/nms/v1_16_R2/world/WorldCoreImpl.java
@@ -1,16 +1,28 @@
package com.songoda.core.nms.v1_16_R2.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_16_R2.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_16_R2.BlockPosition;
+import net.minecraft.server.v1_16_R2.Chunk;
+import net.minecraft.server.v1_16_R2.ChunkCoordIntPair;
+import net.minecraft.server.v1_16_R2.ChunkSection;
+import net.minecraft.server.v1_16_R2.Fluid;
+import net.minecraft.server.v1_16_R2.GameProfilerFiller;
+import net.minecraft.server.v1_16_R2.IBlockData;
+import net.minecraft.server.v1_16_R2.MobSpawnerAbstract;
+import net.minecraft.server.v1_16_R2.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_16_R2.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +42,57 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#a(Chunk, int)}.
+ */
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
+ int j = chunkcoordintpair.d();
+ int k = chunkcoordintpair.e();
+
+ GameProfilerFiller profiler = chunk.world.getMethodProfiler();
+
+ profiler.enter("tickBlocks");
+ for (ChunkSection chunksection : chunk.getSections()) {
+ if (chunksection != Chunk.a && chunksection.d()) {
+ int j1 = chunksection.getYPosition();
+
+ for (int i = 0; i < tickAmount; ++i) {
+ BlockPosition blockposition2 = chunk.world.a(j, j1, k, 15);
+ profiler.enter("randomTick");
+
+ IBlockData iblockdata = chunksection.getType(
+ blockposition2.getX() - j,
+ blockposition2.getY() - j1,
+ blockposition2.getZ() - k);
+
+ if (iblockdata.isTicking()) {
+ iblockdata.b(chunk.world, blockposition2, chunk.world.random);
+ }
+
+ Fluid fluid = iblockdata.getFluid();
+ if (fluid.f()) {
+ fluid.b(chunk.world, blockposition2, chunk.world.random);
+ }
+
+ profiler.exit();
+ }
+ }
+ }
+
+ profiler.exit();
+ }
+ }
}
diff --git a/NMS/NMS-v1_16_R2/src/com/songoda/core/nms/v1_16_R2/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_16_R2/src/com/songoda/core/nms/v1_16_R2/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..75e1b9ea
--- /dev/null
+++ b/NMS/NMS-v1_16_R2/src/com/songoda/core/nms/v1_16_R2/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,195 @@
+package com.songoda.core.nms.v1_16_R2.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_16_R2.AxisAlignedBB;
+import net.minecraft.server.v1_16_R2.BlockPosition;
+import net.minecraft.server.v1_16_R2.Entity;
+import net.minecraft.server.v1_16_R2.EntityInsentient;
+import net.minecraft.server.v1_16_R2.EntityPositionTypes;
+import net.minecraft.server.v1_16_R2.EntityTypes;
+import net.minecraft.server.v1_16_R2.EnumMobSpawn;
+import net.minecraft.server.v1_16_R2.MobSpawnerAbstract;
+import net.minecraft.server.v1_16_R2.NBTTagCompound;
+import net.minecraft.server.v1_16_R2.NBTTagList;
+import net.minecraft.server.v1_16_R2.Particles;
+import net.minecraft.server.v1_16_R2.WeightedRandom;
+import net.minecraft.server.v1_16_R2.WorldServer;
+import org.bukkit.craftbukkit.v1_16_R2.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.util.Iterator;
+import java.util.Optional;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private final MobSpawnerAbstract spawner;
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#h()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() {
+ BlockPosition blockposition = spawner.b();
+
+ return spawner.a().isPlayerNearby(
+ (double) blockposition.getX() + .5D,
+ (double) blockposition.getY() + .5D,
+ (double) blockposition.getZ() + .5D,
+ spawner.requiredPlayerRange);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException {
+ net.minecraft.server.v1_16_R2.World world = spawner.a();
+ BlockPosition blockposition = spawner.b();
+
+ if (!(world instanceof WorldServer)) {
+ double d0 = (double) blockposition.getX() + world.random.nextDouble();
+ double d1 = (double) blockposition.getY() + world.random.nextDouble();
+ double d2 = (double) blockposition.getZ() + world.random.nextDouble();
+ world.addParticle(Particles.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D);
+ world.addParticle(Particles.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D);
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerE = (double) ReflectionUtils.getFieldValue(spawner, "e");
+ ReflectionUtils.setFieldValue(spawner, "f", spawnerE);
+ ReflectionUtils.setFieldValue(spawner, "e", (spawnerE + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ while (true) {
+ if (i >= spawner.spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = spawner.spawnData.getEntity();
+ Optional> optional = EntityTypes.a(nbttagcompound);
+ if (!optional.isPresent()) {
+ delay(spawner);
+ return;
+ }
+
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+ int j = nbttaglist.size();
+ double d3 = j >= 1 ? nbttaglist.h(0) : (double) blockposition.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ double d4 = j >= 2 ? nbttaglist.h(1) : (double) (blockposition.getY() + world.random.nextInt(3) - 1);
+ double d5 = j >= 3 ? nbttaglist.h(2) : (double) blockposition.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ if (world.b(optional.get().a(d3, d4, d5))) {
+ WorldServer worldserver = (WorldServer) world;
+ if (EntityPositionTypes.a(optional.get(), worldserver, EnumMobSpawn.SPAWNER, new BlockPosition(d3, d4, d5), world.getRandom())) {
+ label116:
+ {
+ Entity entity = EntityTypes.a(nbttagcompound, world, (entity1) -> {
+ entity1.setPositionRotation(d3, d4, d5, entity1.yaw, entity1.pitch);
+ return entity1;
+ });
+ if (entity == null) {
+ delay(spawner);
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(
+ blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .g(spawner.spawnRange)).size();
+
+ if (k >= spawner.maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ entity.setPositionRotation(entity.locX(), entity.locY(), entity.locZ(), world.random.nextFloat() * 360.0F, 0.0F);
+ if (entity instanceof EntityInsentient) {
+ EntityInsentient entityinsentient = (EntityInsentient) entity;
+ if (!entityinsentient.a(world, EnumMobSpawn.SPAWNER) || !entityinsentient.a(world)) {
+ break label116;
+ }
+
+ if (spawner.spawnData.getEntity().e() == 1 && spawner.spawnData.getEntity().hasKeyOfType("id", 8)) {
+ ((EntityInsentient) entity).prepare(worldserver, world.getDamageScaler(entity.getChunkCoordinates()), EnumMobSpawn.SPAWNER, null, null);
+ }
+
+ if (entityinsentient.world.spigotConfig.nerfSpawnerMobs) {
+ entityinsentient.aware = false;
+ }
+ }
+
+ if (CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ Entity vehicle = entity.getVehicle();
+ if (vehicle != null) {
+ vehicle.dead = true;
+ }
+
+ Entity passenger;
+ for (Iterator var20 = entity.getAllPassengers().iterator(); var20.hasNext(); passenger.dead = true) {
+ passenger = var20.next();
+ }
+ } else {
+ if (!worldserver.addAllEntitiesSafely(entity, CreatureSpawnEvent.SpawnReason.SPAWNER)) {
+ delay(spawner);
+ return;
+ }
+
+ world.triggerEffect(2004, blockposition, 0);
+ if (entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#i()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) {
+ if (spawner.maxSpawnDelay <= spawner.minSpawnDelay) {
+ spawner.spawnDelay = spawner.minSpawnDelay;
+ } else {
+ int i = spawner.maxSpawnDelay - spawner.minSpawnDelay;
+ spawner.spawnDelay = spawner.minSpawnDelay + spawner.a().random.nextInt(i);
+ }
+
+ if (!spawner.mobs.isEmpty()) {
+ spawner.setSpawnData(WeightedRandom.a(spawner.a().random, spawner.mobs));
+ }
+
+ spawner.a(1);
+ }
+}
diff --git a/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/world/WorldCoreImpl.java b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/world/WorldCoreImpl.java
index 80fec184..5b254bb7 100644
--- a/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/world/WorldCoreImpl.java
@@ -1,16 +1,28 @@
package com.songoda.core.nms.v1_16_R3.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_16_R3.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_16_R3.BlockPosition;
+import net.minecraft.server.v1_16_R3.Chunk;
+import net.minecraft.server.v1_16_R3.ChunkCoordIntPair;
+import net.minecraft.server.v1_16_R3.ChunkSection;
+import net.minecraft.server.v1_16_R3.Fluid;
+import net.minecraft.server.v1_16_R3.GameProfilerFiller;
+import net.minecraft.server.v1_16_R3.IBlockData;
+import net.minecraft.server.v1_16_R3.MobSpawnerAbstract;
+import net.minecraft.server.v1_16_R3.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_16_R3.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +42,58 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#a(Chunk, int)}.
+ */
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ GameProfilerFiller profiler = chunk.world.getMethodProfiler();
+
+ ChunkCoordIntPair chunkPos = chunk.getPos();
+ int minBlockX = chunkPos.d();
+ int minBlockZ = chunkPos.e();
+
+ profiler.enter("tickBlocks");
+ for (ChunkSection cSection : chunk.getSections()) {
+ if (cSection != Chunk.a && // cSection != Chunk.EMPTY_SECTION
+ cSection.d()) { // #isRandomlyTicking()
+ int bottomBlockY = cSection.getYPosition();
+
+ for (int i = 0; i < tickAmount; ++i) {
+ BlockPosition randomBlockPos = chunk.world.a(minBlockX, bottomBlockY, minBlockZ, 15); // getBlockRandomPos
+ profiler.enter("randomTick");
+
+ IBlockData blockState = cSection.getType(
+ randomBlockPos.getX() - minBlockX,
+ randomBlockPos.getY() - bottomBlockY,
+ randomBlockPos.getZ() - minBlockZ); // #getBlockState
+
+ if (blockState.isTicking()) { // #isRandomlyTicking()
+ blockState.b(chunk.world, randomBlockPos, chunk.world.random); // #randomTick
+ }
+
+ Fluid fluidState = blockState.getFluid(); // #getFluidState()
+ if (fluidState.f()) { // #isRandomlyTicking()
+ fluidState.b(chunk.world, randomBlockPos, chunk.world.random); // #randomTick
+ }
+
+ profiler.exit();
+ }
+ }
+ }
+
+ profiler.exit();
+ }
+ }
}
diff --git a/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..e493bee6
--- /dev/null
+++ b/NMS/NMS-v1_16_R3/src/com/songoda/core/nms/v1_16_R3/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,198 @@
+package com.songoda.core.nms.v1_16_R3.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_16_R3.AxisAlignedBB;
+import net.minecraft.server.v1_16_R3.BlockPosition;
+import net.minecraft.server.v1_16_R3.Entity;
+import net.minecraft.server.v1_16_R3.EntityInsentient;
+import net.minecraft.server.v1_16_R3.EntityPositionTypes;
+import net.minecraft.server.v1_16_R3.EntityTypes;
+import net.minecraft.server.v1_16_R3.EnumMobSpawn;
+import net.minecraft.server.v1_16_R3.MobSpawnerAbstract;
+import net.minecraft.server.v1_16_R3.NBTTagCompound;
+import net.minecraft.server.v1_16_R3.NBTTagList;
+import net.minecraft.server.v1_16_R3.Particles;
+import net.minecraft.server.v1_16_R3.WeightedRandom;
+import net.minecraft.server.v1_16_R3.WorldServer;
+import org.bukkit.craftbukkit.v1_16_R3.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.util.Iterator;
+import java.util.Optional;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private final MobSpawnerAbstract spawner;
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#h()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() {
+ BlockPosition blockposition = spawner.b();
+
+ return spawner.a()
+ .isPlayerNearby((double) blockposition.getX() + 0.5D,
+ (double) blockposition.getY() + 0.5D,
+ (double) blockposition.getZ() + 0.5D,
+ spawner.requiredPlayerRange);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException {
+ net.minecraft.server.v1_16_R3.World world = spawner.a();
+ BlockPosition blockposition = spawner.b();
+
+ if (!(world instanceof WorldServer)) {
+ double d0 = (double) blockposition.getX() + world.random.nextDouble();
+ double d1 = (double) blockposition.getY() + world.random.nextDouble();
+ double d2 = (double) blockposition.getZ() + world.random.nextDouble();
+
+ world.addParticle(Particles.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D);
+ world.addParticle(Particles.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D);
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerE = (double) ReflectionUtils.getFieldValue(spawner, "e");
+ ReflectionUtils.setFieldValue(spawner, "f", spawnerE);
+ ReflectionUtils.setFieldValue(spawner, "e", (spawnerE + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ while (true) {
+ if (i >= spawner.spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = spawner.spawnData.getEntity();
+ Optional> optional = EntityTypes.a(nbttagcompound);
+ if (!optional.isPresent()) {
+ delay(spawner);
+ return;
+ }
+
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+ int j = nbttaglist.size();
+ double d3 = j >= 1 ? nbttaglist.h(0) : (double) blockposition.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+ double d4 = j >= 2 ? nbttaglist.h(1) : (double) (blockposition.getY() + world.random.nextInt(3) - 1);
+ double d5 = j >= 3 ? nbttaglist.h(2) : (double) blockposition.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawner.spawnRange + .5D;
+
+ if (world.b(optional.get().a(d3, d4, d5))) {
+ WorldServer worldserver = (WorldServer) world;
+ if (EntityPositionTypes.a(optional.get(), worldserver, EnumMobSpawn.SPAWNER, new BlockPosition(d3, d4, d5), world.getRandom())) {
+ label116:
+ {
+ Entity entity = EntityTypes.a(nbttagcompound, world, (entity1) -> {
+ entity1.setPositionRotation(d3, d4, d5, entity1.yaw, entity1.pitch);
+ return entity1;
+ });
+ if (entity == null) {
+ delay(spawner);
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(
+ blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .g(spawner.spawnRange)).size();
+
+ if (k >= spawner.maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ entity.setPositionRotation(entity.locX(), entity.locY(), entity.locZ(), world.random.nextFloat() * 360F, 0F);
+ if (entity instanceof EntityInsentient) {
+ EntityInsentient entityinsentient = (EntityInsentient) entity;
+ if (!entityinsentient.a(world, EnumMobSpawn.SPAWNER) || !entityinsentient.a(world)) {
+ break label116;
+ }
+
+ if (spawner.spawnData.getEntity().e() == 1 && spawner.spawnData.getEntity().hasKeyOfType("id", 8)) {
+ ((EntityInsentient) entity).prepare(worldserver, world.getDamageScaler(entity.getChunkCoordinates()), EnumMobSpawn.SPAWNER, null, null);
+ }
+
+ if (entityinsentient.world.spigotConfig.nerfSpawnerMobs) {
+ entityinsentient.aware = false;
+ }
+ }
+
+ if (CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ Entity vehicle = entity.getVehicle();
+ if (vehicle != null) {
+ vehicle.dead = true;
+ }
+
+ Entity passenger;
+ for (Iterator var20 = entity.getAllPassengers().iterator(); var20.hasNext(); passenger.dead = true) {
+ passenger = var20.next();
+ }
+ } else {
+ if (!worldserver.addAllEntitiesSafely(entity, CreatureSpawnEvent.SpawnReason.SPAWNER)) {
+ delay(spawner);
+ return;
+ }
+
+ world.triggerEffect(2004, blockposition, 0);
+ if (entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#i()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) {
+ if (spawner.maxSpawnDelay <= spawner.minSpawnDelay) {
+ spawner.spawnDelay = spawner.minSpawnDelay;
+ } else {
+ int i = spawner.maxSpawnDelay - spawner.minSpawnDelay;
+ spawner.spawnDelay = spawner.minSpawnDelay + spawner.a().random.nextInt(i);
+ }
+
+ if (!spawner.mobs.isEmpty()) {
+ spawner.setSpawnData(WeightedRandom.a(spawner.a().random, spawner.mobs));
+ }
+
+ spawner.a(1);
+ }
+}
diff --git a/NMS/NMS-v1_17_R1/src/com/songoda/core/nms/v1_17_R1/world/WorldCoreImpl.java b/NMS/NMS-v1_17_R1/src/com/songoda/core/nms/v1_17_R1/world/WorldCoreImpl.java
index 7152abfe..3b4ba2f3 100644
--- a/NMS/NMS-v1_17_R1/src/com/songoda/core/nms/v1_17_R1/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_17_R1/src/com/songoda/core/nms/v1_17_R1/world/WorldCoreImpl.java
@@ -1,12 +1,25 @@
package com.songoda.core.nms.v1_17_R1.world;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_17_R1.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SItemStack;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.core.BlockPosition;
+import net.minecraft.server.level.WorldServer;
+import net.minecraft.util.profiling.GameProfilerFiller;
+import net.minecraft.world.level.ChunkCoordIntPair;
+import net.minecraft.world.level.MobSpawnerAbstract;
+import net.minecraft.world.level.block.state.IBlockData;
+import net.minecraft.world.level.chunk.Chunk;
+import net.minecraft.world.level.chunk.ChunkSection;
+import net.minecraft.world.level.material.Fluid;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
+import org.bukkit.craftbukkit.v1_17_R1.CraftChunk;
import org.bukkit.inventory.ItemStack;
public class WorldCoreImpl implements WorldCore {
@@ -30,4 +43,56 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl(world);
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
+
+ return new BBaseSpawnerImpl(spawner, (MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#a(Chunk, int)}.
+ */
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+ WorldServer world = (WorldServer) chunk.getWorld();
+
+ if (tickAmount > 0) {
+ GameProfilerFiller profiler = world.getMethodProfiler();
+
+ ChunkCoordIntPair chunkPos = chunk.getPos();
+ int minBlockX = chunkPos.d();
+ int minBlockZ = chunkPos.e();
+
+ profiler.enter("tickBlocks");
+ for (ChunkSection cSection : chunk.getSections()) {
+ if (cSection != Chunk.a && // cSection != Chunk.EMPTY_SECTION
+ cSection.d()) { // #isRandomlyTicking
+ int bottomBlockY = cSection.getYPosition();
+
+ for (int k1 = 0; k1 < tickAmount; ++k1) {
+ BlockPosition bPos = world.a(minBlockX, bottomBlockY, minBlockZ, 15);
+ profiler.enter("randomTick");
+
+ IBlockData blockState = cSection.getType(bPos.getX() - minBlockX, bPos.getY() - bottomBlockY, bPos.getZ() - minBlockZ);
+
+ if (blockState.isTicking()) {
+ blockState.b(world, bPos, chunk.getWorld().w); // #randomTick
+ }
+
+ Fluid fluid = blockState.getFluid();
+ if (fluid.f()) { // #isRandomlyTicking
+ fluid.b(world, bPos, chunk.getWorld().w); // #randomTick
+ }
+
+ profiler.exit();
+ }
+ }
+ }
+
+ profiler.exit();
+ }
+ }
}
diff --git a/NMS/NMS-v1_17_R1/src/com/songoda/core/nms/v1_17_R1/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_17_R1/src/com/songoda/core/nms/v1_17_R1/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..4a06dc0a
--- /dev/null
+++ b/NMS/NMS-v1_17_R1/src/com/songoda/core/nms/v1_17_R1/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,171 @@
+package com.songoda.core.nms.v1_17_R1.world.spawner;
+
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.core.BlockPosition;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.server.level.WorldServer;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.EntityInsentient;
+import net.minecraft.world.entity.EntityPositionTypes;
+import net.minecraft.world.entity.EntityTypes;
+import net.minecraft.world.entity.EnumMobSpawn;
+import net.minecraft.world.level.MobSpawnerAbstract;
+import net.minecraft.world.level.World;
+import net.minecraft.world.phys.AxisAlignedBB;
+import org.bukkit.block.CreatureSpawner;
+import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
+import org.bukkit.craftbukkit.v1_17_R1.block.CraftCreatureSpawner;
+import org.bukkit.craftbukkit.v1_17_R1.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.util.Optional;
+import java.util.Random;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private final CreatureSpawner bukkitSpawner;
+ private final MobSpawnerAbstract spawner;
+
+ private static final Random spawnerFieldP = new Random(); // Field p in MobSpawnerAbstract is private - We use one random for *all* our spawners (should be fine, right?)
+
+ public BBaseSpawnerImpl(CreatureSpawner bukkitSpawner, MobSpawnerAbstract spawner) {
+ this.bukkitSpawner = bukkitSpawner;
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c(World, BlockPosition)}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() {
+ BlockPosition bPos = getBlockPosition();
+
+ return getWorld().isPlayerNearby((double) bPos.getX() + 0.5D, (double) bPos.getY() + 0.5D, (double) bPos.getZ() + 0.5D, this.spawner.n);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#a(WorldServer, BlockPosition)}.
+ */
+ @Override
+ public void tick() {
+ WorldServer world = getWorld();
+ BlockPosition bPos = getBlockPosition();
+
+ if (this.spawner.d == -1) {
+ this.delay(world, bPos);
+ }
+
+ if (this.spawner.d > 0) {
+ --this.spawner.d;
+ } else {
+ boolean flag = false;
+ int i = 0;
+
+ while (true) {
+ if (i >= this.spawner.k) {
+ if (flag) {
+ this.delay(world, bPos);
+ }
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = this.spawner.f.getEntity();
+ Optional> optional = EntityTypes.a(nbttagcompound);
+ if (optional.isEmpty()) {
+ this.delay(world, bPos);
+ return;
+ }
+
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+ int j = nbttaglist.size();
+ double d0 = j >= 1 ? nbttaglist.h(0) : (double) bPos.getX() + (world.w.nextDouble() - world.w.nextDouble()) * (double) this.spawner.o + 0.5D;
+ double d1 = j >= 2 ? nbttaglist.h(1) : (double) (bPos.getY() + world.w.nextInt(3) - 1);
+ double d2 = j >= 3 ? nbttaglist.h(2) : (double) bPos.getZ() + (world.w.nextDouble() - world.w.nextDouble()) * (double) this.spawner.o + 0.5D;
+ if (world.b(optional.get().a(d0, d1, d2)) && EntityPositionTypes.a((EntityTypes>) optional.get(), world, EnumMobSpawn.c, new BlockPosition(d0, d1, d2), world.getRandom())) {
+ label107:
+ {
+ Entity entity = EntityTypes.a(nbttagcompound, world, (entity1) -> {
+ entity1.setPositionRotation(d0, d1, d2, entity1.getYRot(), entity1.getXRot());
+ return entity1;
+ });
+ if (entity == null) {
+ this.delay(world, bPos);
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(bPos.getX(), bPos.getY(), bPos.getZ(), bPos.getX() + 1, bPos.getY() + 1, bPos.getZ() + 1)).g(this.spawner.o)).size();
+ if (k >= this.spawner.m) {
+ this.delay(world, bPos);
+ return;
+ }
+
+ entity.setPositionRotation(entity.locX(), entity.locY(), entity.locZ(), world.w.nextFloat() * 360.0F, 0.0F);
+ if (entity instanceof EntityInsentient entityinsentient) {
+ if (!entityinsentient.a(world, EnumMobSpawn.c) || !entityinsentient.a(world)) {
+ break label107;
+ }
+
+ if (this.spawner.f.getEntity().e() == 1 && this.spawner.f.getEntity().hasKeyOfType("id", 8)) {
+ ((EntityInsentient) entity).prepare(world, world.getDamageScaler(entity.getChunkCoordinates()), EnumMobSpawn.c, null, null);
+ }
+
+ if (entityinsentient.t.spigotConfig.nerfSpawnerMobs) {
+ entityinsentient.aware = false;
+ }
+ }
+
+ if (CraftEventFactory.callSpawnerSpawnEvent(entity, bPos).isCancelled()) {
+ Entity vehicle = entity.getVehicle();
+ if (vehicle != null) {
+ vehicle.die();
+ }
+
+ for (Entity passenger : entity.getAllPassengers()) {
+ passenger.die();
+ }
+ } else {
+ if (!world.addAllEntitiesSafely(entity, CreatureSpawnEvent.SpawnReason.SPAWNER)) {
+ this.delay(world, bPos);
+ return;
+ }
+
+ world.triggerEffect(2004, bPos, 0);
+ if (entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#d(World, BlockPosition)}.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(WorldServer world, BlockPosition bPos) {
+ if (this.spawner.j <= this.spawner.i) {
+ this.spawner.d = this.spawner.i;
+ } else {
+ this.spawner.d = this.spawner.i + spawnerFieldP.nextInt(this.spawner.j - this.spawner.i);
+ }
+
+ this.spawner.e.b(spawnerFieldP)
+ .ifPresent((mobspawnerdata) -> this.spawner.setSpawnData(world, bPos, mobspawnerdata));
+ this.spawner.a(world, getBlockPosition(), 1);
+ }
+
+ private WorldServer getWorld() {
+ return ((CraftWorld) this.bukkitSpawner.getWorld()).getHandle();
+ }
+
+ private BlockPosition getBlockPosition() {
+ return ((CraftCreatureSpawner) this.bukkitSpawner).getPosition();
+ }
+}
diff --git a/NMS/NMS-v1_8_R1/src/com/songoda/core/nms/v1_8_R1/world/WorldCoreImpl.java b/NMS/NMS-v1_8_R1/src/com/songoda/core/nms/v1_8_R1/world/WorldCoreImpl.java
index ef77f758..33364b37 100644
--- a/NMS/NMS-v1_8_R1/src/com/songoda/core/nms/v1_8_R1/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_8_R1/src/com/songoda/core/nms/v1_8_R1/world/WorldCoreImpl.java
@@ -1,16 +1,26 @@
package com.songoda.core.nms.v1_8_R1.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_8_R1.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_8_R1.Block;
+import net.minecraft.server.v1_8_R1.BlockPosition;
+import net.minecraft.server.v1_8_R1.Chunk;
+import net.minecraft.server.v1_8_R1.ChunkSection;
+import net.minecraft.server.v1_8_R1.IBlockData;
+import net.minecraft.server.v1_8_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_8_R1.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_8_R1.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +40,50 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#h()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ int k = chunk.locX * 16;
+ int l = chunk.locZ * 16;
+
+ for (ChunkSection cSection : chunk.getSections()) {
+ if (cSection != null && cSection.shouldTick()) {
+
+ for (int i = 0; i < tickAmount; ++i) {
+ int m = (int) ReflectionUtils.getFieldValue(chunk.world, "m");
+
+ m = m * 3 + 1013904223;
+ ReflectionUtils.setFieldValue(chunk.world, "m", m);
+
+ int i2 = m >> 2;
+ int j2 = i2 & 15;
+ int k2 = i2 >> 8 & 15;
+ int l2 = i2 >> 16 & 15;
+
+ BlockPosition blockposition2 = new BlockPosition(j2 + k, l2 + cSection.getYPosition(), k2 + l);
+ IBlockData iblockdata = cSection.getType(j2, l2, k2);
+ Block block = iblockdata.getBlock();
+
+ if (block.isTicking()) {
+ block.a(chunk.world, blockposition2, iblockdata, chunk.world.random);
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/NMS/NMS-v1_8_R1/src/com/songoda/core/nms/v1_8_R1/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_8_R1/src/com/songoda/core/nms/v1_8_R1/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..69237cf4
--- /dev/null
+++ b/NMS/NMS-v1_8_R1/src/com/songoda/core/nms/v1_8_R1/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,146 @@
+package com.songoda.core.nms.v1_8_R1.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_8_R1.AxisAlignedBB;
+import net.minecraft.server.v1_8_R1.BlockPosition;
+import net.minecraft.server.v1_8_R1.Entity;
+import net.minecraft.server.v1_8_R1.EntityInsentient;
+import net.minecraft.server.v1_8_R1.EntityTypes;
+import net.minecraft.server.v1_8_R1.EnumParticle;
+import net.minecraft.server.v1_8_R1.MobSpawnerAbstract;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private static Method aEntityBooleanMethod, gMethod, hMethod;
+
+ private final MobSpawnerAbstract spawner;
+
+ static {
+ try {
+ aEntityBooleanMethod = MobSpawnerAbstract.class.getDeclaredMethod("a", Entity.class, boolean.class);
+ aEntityBooleanMethod.setAccessible(true);
+
+ gMethod = MobSpawnerAbstract.class.getDeclaredMethod("g");
+ gMethod.setAccessible(true);
+
+ hMethod = MobSpawnerAbstract.class.getDeclaredMethod("h");
+ hMethod.setAccessible(true);
+ } catch (NoSuchMethodException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#g()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() throws InvocationTargetException, IllegalAccessException {
+ return (boolean) gMethod.invoke(spawner);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
+ BlockPosition blockposition = spawner.b();
+
+ if (spawner.a().isStatic) {
+ double d1 = (float) blockposition.getX() + spawner.a().random.nextFloat();
+ double d2 = (float) blockposition.getY() + spawner.a().random.nextFloat();
+ double d0 = (float) blockposition.getZ() + spawner.a().random.nextFloat();
+
+ spawner.a().addParticle(EnumParticle.SMOKE_NORMAL, d1, d2, d0, 0D, 0D, 0D);
+ spawner.a().addParticle(EnumParticle.FLAME, d1, d2, d0, 0D, 0D, 0D);
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerE = (double) ReflectionUtils.getFieldValue(spawner, "e");
+
+ ReflectionUtils.setFieldValue(spawner, "f", spawnerE);
+ ReflectionUtils.setFieldValue(spawner, "e", (spawnerE + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ int spawnCount = (int) ReflectionUtils.getFieldValue(spawner, "spawnCount");
+ int spawnRange = (int) ReflectionUtils.getFieldValue(spawner, "spawnRange");
+ int maxNearbyEntities = (int) ReflectionUtils.getFieldValue(spawner, "maxNearbyEntities");
+ while (true) {
+ if (i >= spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+
+ break;
+ }
+
+ Entity entity = EntityTypes.createEntityByName(spawner.getMobName(), spawner.a());
+ if (entity == null) {
+ return;
+ }
+
+ int j = spawner.a()
+ .a(entity.getClass(), (new AxisAlignedBB(blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .grow(spawnRange, spawnRange, spawnRange)).size();
+
+ if (j >= maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ double d0 = (double) blockposition.getX() + (spawner.a().random.nextDouble() - spawner.a().random.nextDouble()) * (double) spawnRange + 0.5D;
+ double d3 = blockposition.getY() + spawner.a().random.nextInt(3) - 1;
+ double d4 = (double) blockposition.getZ() + (spawner.a().random.nextDouble() - spawner.a().random.nextDouble()) * (double) spawnRange + 0.5D;
+
+ EntityInsentient entityinsentient = entity instanceof EntityInsentient ? (EntityInsentient) entity : null;
+ entity.setPositionRotation(d0, d3, d4, spawner.a().random.nextFloat() * 360.0F, 0.0F);
+
+ if (entityinsentient == null || entityinsentient.bQ() && entityinsentient.canSpawn()) {
+ aEntityBooleanMethod.invoke(spawner, entity, true);
+ spawner.a().triggerEffect(2004, blockposition, 0);
+
+ if (entityinsentient != null) {
+ entityinsentient.y();
+ }
+
+ flag = true;
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#h()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) throws InvocationTargetException, IllegalAccessException {
+ hMethod.invoke(spawner);
+ }
+}
diff --git a/NMS/NMS-v1_8_R2/src/com/songoda/core/nms/v1_8_R2/world/WorldCoreImpl.java b/NMS/NMS-v1_8_R2/src/com/songoda/core/nms/v1_8_R2/world/WorldCoreImpl.java
index c7b8ffe2..aabaa81f 100644
--- a/NMS/NMS-v1_8_R2/src/com/songoda/core/nms/v1_8_R2/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_8_R2/src/com/songoda/core/nms/v1_8_R2/world/WorldCoreImpl.java
@@ -1,16 +1,28 @@
package com.songoda.core.nms.v1_8_R2.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_8_R2.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_8_R2.Block;
+import net.minecraft.server.v1_8_R2.BlockPosition;
+import net.minecraft.server.v1_8_R2.Chunk;
+import net.minecraft.server.v1_8_R2.ChunkSection;
+import net.minecraft.server.v1_8_R2.IBlockData;
+import net.minecraft.server.v1_8_R2.MobSpawnerAbstract;
+import net.minecraft.server.v1_8_R2.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_8_R2.CraftChunk;
+
+import java.lang.reflect.Method;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +42,49 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#h()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ int k = chunk.locX * 16;
+ int l = chunk.locZ * 16;
+
+ for (ChunkSection cSection : chunk.getSections()) {
+ if (cSection != null && cSection.shouldTick()) {
+ for (int i = 0; i < tickAmount; ++i) {
+ int m = (int) ReflectionUtils.getFieldValue(chunk.world, "m");
+
+ m = m * 3 + 1013904223;
+ ReflectionUtils.setFieldValue(chunk.world, "m", m);
+
+ int i2 = m >> 2;
+ int j2 = i2 & 15;
+ int k2 = i2 >> 8 & 15;
+ int l2 = i2 >> 16 & 15;
+
+ BlockPosition blockposition2 = new BlockPosition(j2 + k, l2 + cSection.getYPosition(), k2 + l);
+ IBlockData iblockdata = cSection.getType(j2, l2, k2);
+ Block block = iblockdata.getBlock();
+
+ if (block.isTicking()) {
+ block.a(chunk.world, blockposition2, iblockdata, chunk.world.random);
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/NMS/NMS-v1_8_R2/src/com/songoda/core/nms/v1_8_R2/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_8_R2/src/com/songoda/core/nms/v1_8_R2/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..d9b6cabd
--- /dev/null
+++ b/NMS/NMS-v1_8_R2/src/com/songoda/core/nms/v1_8_R2/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,139 @@
+package com.songoda.core.nms.v1_8_R2.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_8_R2.AxisAlignedBB;
+import net.minecraft.server.v1_8_R2.BlockPosition;
+import net.minecraft.server.v1_8_R2.Entity;
+import net.minecraft.server.v1_8_R2.EntityInsentient;
+import net.minecraft.server.v1_8_R2.EntityTypes;
+import net.minecraft.server.v1_8_R2.EnumParticle;
+import net.minecraft.server.v1_8_R2.MobSpawnerAbstract;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private static Method aEntityBooleanMethod, gMethod, hMethod;
+ private final MobSpawnerAbstract spawner;
+
+ static {
+ try {
+ aEntityBooleanMethod = MobSpawnerAbstract.class.getDeclaredMethod("a", Entity.class, boolean.class);
+ aEntityBooleanMethod.setAccessible(true);
+
+ gMethod = MobSpawnerAbstract.class.getDeclaredMethod("g");
+ gMethod.setAccessible(true);
+
+ hMethod = MobSpawnerAbstract.class.getDeclaredMethod("h");
+ hMethod.setAccessible(true);
+ } catch (NoSuchMethodException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#g()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() throws InvocationTargetException, IllegalAccessException {
+ return (boolean) gMethod.invoke(spawner);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
+ BlockPosition blockposition = spawner.b();
+
+ if (spawner.a().isClientSide) {
+ double d1 = (float) blockposition.getX() + spawner.a().random.nextFloat();
+ double d2 = (float) blockposition.getY() + spawner.a().random.nextFloat();
+ double d0 = (float) blockposition.getZ() + spawner.a().random.nextFloat();
+ spawner.a().addParticle(EnumParticle.SMOKE_NORMAL, d1, d2, d0, 0.0D, 0.0D, 0.0D);
+ spawner.a().addParticle(EnumParticle.FLAME, d1, d2, d0, 0.0D, 0.0D, 0.0D);
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerE = (double) ReflectionUtils.getFieldValue(spawner, "e");
+
+ ReflectionUtils.setFieldValue(spawner, "f", spawnerE);
+ ReflectionUtils.setFieldValue(spawner, "e", (spawnerE + (double) (1000F / ((float) spawner.spawnDelay + 200.0F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ int spawnCount = (int) ReflectionUtils.getFieldValue(spawner, "spawnCount");
+ int spawnRange = (int) ReflectionUtils.getFieldValue(spawner, "spawnRange");
+ int maxNearbyEntities = (int) ReflectionUtils.getFieldValue(spawner, "maxNearbyEntities");
+
+ while (true) {
+ if (i >= spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+ break;
+ }
+
+ Entity entity = EntityTypes.createEntityByName(spawner.getMobName(), spawner.a());
+ if (entity == null) {
+ return;
+ }
+
+ int j = spawner.a().a(entity.getClass(), (new AxisAlignedBB(
+ blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .grow(spawnRange, spawnRange, spawnRange)).size();
+ if (j >= maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ double d0 = (double) blockposition.getX() + (spawner.a().random.nextDouble() - spawner.a().random.nextDouble()) * (double) spawnRange + .5D;
+ double d3 = blockposition.getY() + spawner.a().random.nextInt(3) - 1;
+ double d4 = (double) blockposition.getZ() + (spawner.a().random.nextDouble() - spawner.a().random.nextDouble()) * (double) spawnRange + .5D;
+ EntityInsentient entityinsentient = entity instanceof EntityInsentient ? (EntityInsentient) entity : null;
+ entity.setPositionRotation(d0, d3, d4, spawner.a().random.nextFloat() * 360F, 0F);
+ if (entityinsentient == null || entityinsentient.bR() && entityinsentient.canSpawn()) {
+ aEntityBooleanMethod.invoke(spawner, entity, true);
+ spawner.a().triggerEffect(2004, blockposition, 0);
+ if (entityinsentient != null) {
+ entityinsentient.y();
+ }
+
+ flag = true;
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#h()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) throws InvocationTargetException, IllegalAccessException {
+ hMethod.invoke(spawner);
+ }
+}
\ No newline at end of file
diff --git a/NMS/NMS-v1_8_R3/src/com/songoda/core/nms/v1_8_R3/world/WorldCoreImpl.java b/NMS/NMS-v1_8_R3/src/com/songoda/core/nms/v1_8_R3/world/WorldCoreImpl.java
index d0c61449..fd5a3919 100644
--- a/NMS/NMS-v1_8_R3/src/com/songoda/core/nms/v1_8_R3/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_8_R3/src/com/songoda/core/nms/v1_8_R3/world/WorldCoreImpl.java
@@ -1,16 +1,26 @@
package com.songoda.core.nms.v1_8_R3.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_8_R3.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_8_R3.Block;
+import net.minecraft.server.v1_8_R3.BlockPosition;
+import net.minecraft.server.v1_8_R3.Chunk;
+import net.minecraft.server.v1_8_R3.ChunkSection;
+import net.minecraft.server.v1_8_R3.IBlockData;
+import net.minecraft.server.v1_8_R3.MobSpawnerAbstract;
+import net.minecraft.server.v1_8_R3.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +40,48 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#h()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ int k = chunk.locX * 16;
+ int l = chunk.locZ * 16;
+
+ for (ChunkSection chunksection : chunk.getSections()) {
+ if (chunksection != null && chunksection.shouldTick()) {
+ for (int l1 = 0; l1 < tickAmount; ++l1) {
+ int m = (int) ReflectionUtils.getFieldValue(chunk.world, "m");
+
+ m = m * 3 + 1013904223;
+ ReflectionUtils.setFieldValue(chunk.world, "m", m);
+
+ int i2 = m >> 2;
+ int j2 = i2 & 15;
+ int k2 = i2 >> 8 & 15;
+ int l2 = i2 >> 16 & 15;
+
+ IBlockData iblockdata = chunksection.getType(j2, l2, k2);
+ Block block = iblockdata.getBlock();
+
+ if (block.isTicking()) {
+ block.a(chunk.world, new BlockPosition(j2 + k, l2 + chunksection.getYPosition(), k2 + l), iblockdata, chunk.world.random);
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/NMS/NMS-v1_8_R3/src/com/songoda/core/nms/v1_8_R3/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_8_R3/src/com/songoda/core/nms/v1_8_R3/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..f65e5502
--- /dev/null
+++ b/NMS/NMS-v1_8_R3/src/com/songoda/core/nms/v1_8_R3/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,143 @@
+package com.songoda.core.nms.v1_8_R3.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_8_R3.AxisAlignedBB;
+import net.minecraft.server.v1_8_R3.BlockPosition;
+import net.minecraft.server.v1_8_R3.Entity;
+import net.minecraft.server.v1_8_R3.EntityInsentient;
+import net.minecraft.server.v1_8_R3.EntityTypes;
+import net.minecraft.server.v1_8_R3.EnumParticle;
+import net.minecraft.server.v1_8_R3.MobSpawnerAbstract;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private static Method aEntityBooleanMethod, gMethod, hMethod;
+
+ private final MobSpawnerAbstract spawner;
+
+ static {
+ try {
+ aEntityBooleanMethod = MobSpawnerAbstract.class.getDeclaredMethod("a", Entity.class, boolean.class);
+ aEntityBooleanMethod.setAccessible(true);
+
+ gMethod = MobSpawnerAbstract.class.getDeclaredMethod("g");
+ gMethod.setAccessible(true);
+
+ hMethod = MobSpawnerAbstract.class.getDeclaredMethod("h");
+ hMethod.setAccessible(true);
+ } catch (NoSuchMethodException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#g()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() throws InvocationTargetException, IllegalAccessException {
+ return (boolean) gMethod.invoke(spawner);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
+
+ BlockPosition blockposition = spawner.b();
+
+ if (spawner.a().isClientSide) {
+ double d1 = (float) blockposition.getX() + spawner.a().random.nextFloat();
+ double d2 = (float) blockposition.getY() + spawner.a().random.nextFloat();
+ double d0 = (float) blockposition.getZ() + spawner.a().random.nextFloat();
+ spawner.a().addParticle(EnumParticle.SMOKE_NORMAL, d1, d2, d0, 0D, 0D, 0D);
+ spawner.a().addParticle(EnumParticle.FLAME, d1, d2, d0, 0D, 0D, 0D);
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerE = (double) ReflectionUtils.getFieldValue(spawner, "e");
+
+ ReflectionUtils.setFieldValue(spawner, "f", spawnerE);
+ ReflectionUtils.setFieldValue(spawner, "e", (spawnerE + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ int spawnCount = (int) ReflectionUtils.getFieldValue(spawner, "spawnCount");
+ int spawnRange = (int) ReflectionUtils.getFieldValue(spawner, "spawnRange");
+ int maxNearbyEntities = (int) ReflectionUtils.getFieldValue(spawner, "maxNearbyEntities");
+
+ while (true) {
+ if (i >= spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+ break;
+ }
+
+ Entity entity = EntityTypes.createEntityByName(spawner.getMobName(), spawner.a());
+ if (entity == null) {
+ return;
+ }
+
+ int j = spawner.a().a(entity.getClass(), (new AxisAlignedBB(
+ blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .grow(spawnRange, spawnRange, spawnRange)).size();
+ if (j >= maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ double d0 = (double) blockposition.getX() + (spawner.a().random.nextDouble() - spawner.a().random.nextDouble()) * (double) spawnRange + .5D;
+ double d3 = blockposition.getY() + spawner.a().random.nextInt(3) - 1;
+ double d4 = (double) blockposition.getZ() + (spawner.a().random.nextDouble() - spawner.a().random.nextDouble()) * (double) spawnRange + .5D;
+
+ EntityInsentient entityinsentient = entity instanceof EntityInsentient ? (EntityInsentient) entity : null;
+ entity.setPositionRotation(d0, d3, d4, spawner.a().random.nextFloat() * 360F, 0F);
+
+ if (entityinsentient == null || entityinsentient.bR() && entityinsentient.canSpawn()) {
+ aEntityBooleanMethod.invoke(spawner, entity, true);
+ spawner.a().triggerEffect(2004, blockposition, 0);
+ if (entityinsentient != null) {
+ entityinsentient.y();
+ }
+
+ flag = true;
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#h()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) throws InvocationTargetException, IllegalAccessException {
+ hMethod.invoke(spawner);
+ }
+}
\ No newline at end of file
diff --git a/NMS/NMS-v1_9_R1/src/com/songoda/core/nms/v1_9_R1/world/WorldCoreImpl.java b/NMS/NMS-v1_9_R1/src/com/songoda/core/nms/v1_9_R1/world/WorldCoreImpl.java
index c98c70c0..74d6c9b2 100644
--- a/NMS/NMS-v1_9_R1/src/com/songoda/core/nms/v1_9_R1/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_9_R1/src/com/songoda/core/nms/v1_9_R1/world/WorldCoreImpl.java
@@ -1,16 +1,26 @@
package com.songoda.core.nms.v1_9_R1.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_9_R1.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_9_R1.Block;
+import net.minecraft.server.v1_9_R1.BlockPosition;
+import net.minecraft.server.v1_9_R1.Chunk;
+import net.minecraft.server.v1_9_R1.ChunkSection;
+import net.minecraft.server.v1_9_R1.IBlockData;
+import net.minecraft.server.v1_9_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_9_R1.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_9_R1.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +40,48 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#j()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ int j = chunk.locX * 16;
+ int k = chunk.locZ * 16;
+
+ for (ChunkSection chunksection : chunk.getSections()) {
+ if (chunksection != net.minecraft.server.v1_9_R1.Chunk.a && chunksection.shouldTick()) {
+ for (int i = 0; i < tickAmount; ++i) {
+ int worldL = (int) ReflectionUtils.getFieldValue(chunk.world, "l");
+
+ worldL = worldL * 3 + 1013904223;
+ ReflectionUtils.setFieldValue(chunk.world, "l", worldL);
+
+ int l1 = worldL >> 2;
+ int i2 = l1 & 15;
+ int j2 = l1 >> 8 & 15;
+ int k2 = l1 >> 16 & 15;
+
+ IBlockData iblockdata = chunksection.getType(i2, k2, j2);
+ Block block = iblockdata.getBlock();
+
+ if (block.isTicking()) {
+ block.a(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), iblockdata, chunk.world.random);
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/NMS/NMS-v1_9_R1/src/com/songoda/core/nms/v1_9_R1/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_9_R1/src/com/songoda/core/nms/v1_9_R1/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..da587db1
--- /dev/null
+++ b/NMS/NMS-v1_9_R1/src/com/songoda/core/nms/v1_9_R1/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,156 @@
+package com.songoda.core.nms.v1_9_R1.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_9_R1.AxisAlignedBB;
+import net.minecraft.server.v1_9_R1.BlockPosition;
+import net.minecraft.server.v1_9_R1.ChunkRegionLoader;
+import net.minecraft.server.v1_9_R1.Entity;
+import net.minecraft.server.v1_9_R1.EntityInsentient;
+import net.minecraft.server.v1_9_R1.EnumParticle;
+import net.minecraft.server.v1_9_R1.MobSpawnerAbstract;
+import net.minecraft.server.v1_9_R1.MobSpawnerData;
+import net.minecraft.server.v1_9_R1.NBTTagCompound;
+import net.minecraft.server.v1_9_R1.NBTTagList;
+import org.bukkit.craftbukkit.v1_9_R1.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private static Method iMethod, hMethod;
+
+ private final MobSpawnerAbstract spawner;
+
+ static {
+ try {
+ iMethod = MobSpawnerAbstract.class.getDeclaredMethod("i");
+ iMethod.setAccessible(true);
+
+ hMethod = MobSpawnerAbstract.class.getDeclaredMethod("h");
+ hMethod.setAccessible(true);
+ } catch (NoSuchMethodException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#h()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() throws InvocationTargetException, IllegalAccessException {
+ return (boolean) hMethod.invoke(spawner);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
+ BlockPosition blockposition = spawner.b();
+ if (spawner.a().isClientSide) {
+ double d0 = (float) blockposition.getX() + spawner.a().random.nextFloat();
+ double d1 = (float) blockposition.getY() + spawner.a().random.nextFloat();
+ double d2 = (float) blockposition.getZ() + spawner.a().random.nextFloat();
+ spawner.a().addParticle(EnumParticle.SMOKE_NORMAL, d0, d1, d2, 0D, 0D, 0D);
+ spawner.a().addParticle(EnumParticle.FLAME, d0, d1, d2, 0D, 0D, 0D);
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerD = (double) ReflectionUtils.getFieldValue(spawner, "d");
+
+ ReflectionUtils.setFieldValue(spawner, "e", spawnerD);
+ ReflectionUtils.setFieldValue(spawner, "d", (spawnerD + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ int spawnCount = (int) ReflectionUtils.getFieldValue(spawner, "spawnCount");
+ int spawnRange = (int) ReflectionUtils.getFieldValue(spawner, "spawnRange");
+ int maxNearbyEntities = (int) ReflectionUtils.getFieldValue(spawner, "maxNearbyEntities");
+ MobSpawnerData spawnData = (MobSpawnerData) ReflectionUtils.getFieldValue(spawner, "spawnData");
+
+ while (true) {
+ if (i >= spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = spawnData.b();
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+ net.minecraft.server.v1_9_R1.World world = spawner.a();
+ int j = nbttaglist.size();
+ double d3 = j >= 1 ? nbttaglist.e(0) : (double) blockposition.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawnRange + .5D;
+ double d4 = j >= 2 ? nbttaglist.e(1) : (double) (blockposition.getY() + world.random.nextInt(3) - 1);
+ double d5 = j >= 3 ? nbttaglist.e(2) : (double) blockposition.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawnRange + .5D;
+ Entity entity = ChunkRegionLoader.a(nbttagcompound, world, d3, d4, d5, false);
+ if (entity == null) {
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(
+ blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .g(spawnRange)).size();
+ if (k >= maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ EntityInsentient entityinsentient = entity instanceof EntityInsentient ? (EntityInsentient) entity : null;
+ entity.setPositionRotation(entity.locX, entity.locY, entity.locZ, world.random.nextFloat() * 360F, 0F);
+ if (entityinsentient == null || entityinsentient.cF() && entityinsentient.canSpawn()) {
+ if (spawnData.b().d() == 1 && spawnData.b().hasKeyOfType("id", 8) && entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).prepare(world.D(new BlockPosition(entity)), null);
+ }
+
+ if (entity.world.spigotConfig.nerfSpawnerMobs) {
+ entity.fromMobSpawner = true;
+ }
+
+ if (!CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ ChunkRegionLoader.a(entity, world, CreatureSpawnEvent.SpawnReason.SPAWNER);
+ world.triggerEffect(2004, blockposition, 0);
+ if (entityinsentient != null) {
+ entityinsentient.doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#i()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) throws InvocationTargetException, IllegalAccessException {
+ iMethod.invoke(spawner);
+ }
+}
\ No newline at end of file
diff --git a/NMS/NMS-v1_9_R2/src/com/songoda/core/nms/v1_9_R2/world/WorldCoreImpl.java b/NMS/NMS-v1_9_R2/src/com/songoda/core/nms/v1_9_R2/world/WorldCoreImpl.java
index 4ab75b8b..00908f5d 100644
--- a/NMS/NMS-v1_9_R2/src/com/songoda/core/nms/v1_9_R2/world/WorldCoreImpl.java
+++ b/NMS/NMS-v1_9_R2/src/com/songoda/core/nms/v1_9_R2/world/WorldCoreImpl.java
@@ -1,16 +1,26 @@
package com.songoda.core.nms.v1_9_R2.world;
import com.songoda.core.nms.world.SItemStack;
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.v1_9_R2.world.spawner.BBaseSpawnerImpl;
+import com.songoda.core.nms.world.BBaseSpawner;
import com.songoda.core.nms.world.SSpawner;
import com.songoda.core.nms.world.SWorld;
import com.songoda.core.nms.world.WorldCore;
+import net.minecraft.server.v1_9_R2.Block;
+import net.minecraft.server.v1_9_R2.BlockPosition;
+import net.minecraft.server.v1_9_R2.Chunk;
+import net.minecraft.server.v1_9_R2.ChunkSection;
+import net.minecraft.server.v1_9_R2.IBlockData;
+import net.minecraft.server.v1_9_R2.MobSpawnerAbstract;
+import net.minecraft.server.v1_9_R2.WorldServer;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.craftbukkit.v1_9_R2.CraftChunk;
public class WorldCoreImpl implements WorldCore {
-
@Override
public SSpawner getSpawner(CreatureSpawner spawner) {
return new SSpawnerImpl(spawner.getLocation());
@@ -30,4 +40,47 @@ public class WorldCoreImpl implements WorldCore {
public SWorld getWorld(World world) {
return new SWorldImpl();
}
+
+ @Override
+ public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
+ Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
+
+ return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
+ }
+
+ /**
+ * Method is based on {@link WorldServer#j()}.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
+ Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
+
+ if (tickAmount > 0) {
+ int j = chunk.locX * 16;
+ int k = chunk.locZ * 16;
+
+ for (ChunkSection chunksection : chunk.getSections()) {
+ if (chunksection != net.minecraft.server.v1_9_R2.Chunk.a && chunksection.shouldTick()) {
+ for (int k1 = 0; k1 < tickAmount; ++k1) {
+ int worldL = (int) ReflectionUtils.getFieldValue(chunk.world, "l");
+ worldL = worldL * 3 + 1013904223;
+ ReflectionUtils.setFieldValue(chunk.world, "l", worldL);
+
+ int l1 = worldL >> 2;
+ int i2 = l1 & 15;
+ int j2 = l1 >> 8 & 15;
+ int k2 = l1 >> 16 & 15;
+
+ IBlockData iblockdata = chunksection.getType(i2, k2, j2);
+ Block block = iblockdata.getBlock();
+
+ if (block.isTicking()) {
+ block.a(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), iblockdata, chunk.world.random);
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/NMS/NMS-v1_9_R2/src/com/songoda/core/nms/v1_9_R2/world/spawner/BBaseSpawnerImpl.java b/NMS/NMS-v1_9_R2/src/com/songoda/core/nms/v1_9_R2/world/spawner/BBaseSpawnerImpl.java
new file mode 100644
index 00000000..d6a95f09
--- /dev/null
+++ b/NMS/NMS-v1_9_R2/src/com/songoda/core/nms/v1_9_R2/world/spawner/BBaseSpawnerImpl.java
@@ -0,0 +1,159 @@
+package com.songoda.core.nms.v1_9_R2.world.spawner;
+
+import com.songoda.core.nms.ReflectionUtils;
+import com.songoda.core.nms.world.BBaseSpawner;
+import net.minecraft.server.v1_9_R2.AxisAlignedBB;
+import net.minecraft.server.v1_9_R2.BlockPosition;
+import net.minecraft.server.v1_9_R2.ChunkRegionLoader;
+import net.minecraft.server.v1_9_R2.Entity;
+import net.minecraft.server.v1_9_R2.EntityInsentient;
+import net.minecraft.server.v1_9_R2.EnumParticle;
+import net.minecraft.server.v1_9_R2.MobSpawnerAbstract;
+import net.minecraft.server.v1_9_R2.MobSpawnerData;
+import net.minecraft.server.v1_9_R2.NBTTagCompound;
+import net.minecraft.server.v1_9_R2.NBTTagList;
+import org.bukkit.craftbukkit.v1_9_R2.event.CraftEventFactory;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class BBaseSpawnerImpl implements BBaseSpawner {
+ private static Method iMethod, hMethod;
+
+ private final MobSpawnerAbstract spawner;
+
+ static {
+ try {
+ iMethod = MobSpawnerAbstract.class.getDeclaredMethod("i");
+ iMethod.setAccessible(true);
+
+ hMethod = MobSpawnerAbstract.class.getDeclaredMethod("h");
+ hMethod.setAccessible(true);
+ } catch (NoSuchMethodException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public BBaseSpawnerImpl(MobSpawnerAbstract spawner) {
+ this.spawner = spawner;
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#h()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ @Override
+ public boolean isNearPlayer() throws InvocationTargetException, IllegalAccessException {
+ return (boolean) hMethod.invoke(spawner);
+ }
+
+ /**
+ * This method is based on {@link MobSpawnerAbstract#c()}.
+ */
+ @Override
+ public void tick() throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
+ BlockPosition blockposition = spawner.b();
+
+ if (spawner.a().isClientSide) {
+ double d0 = (float) blockposition.getX() + spawner.a().random.nextFloat();
+ double d1 = (float) blockposition.getY() + spawner.a().random.nextFloat();
+ double d2 = (float) blockposition.getZ() + spawner.a().random.nextFloat();
+
+ spawner.a().addParticle(EnumParticle.SMOKE_NORMAL, d0, d1, d2, 0D, 0D, 0D);
+ spawner.a().addParticle(EnumParticle.FLAME, d0, d1, d2, 0D, 0D, 0D);
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ }
+
+ double spawnerD = (double) ReflectionUtils.getFieldValue(spawner, "d");
+
+ ReflectionUtils.setFieldValue(spawner, "e", spawnerD);
+ ReflectionUtils.setFieldValue(spawner, "d", (spawnerD + (double) (1000F / ((float) spawner.spawnDelay + 200F))) % 360D);
+ } else {
+ if (spawner.spawnDelay == -1) {
+ delay(spawner);
+ }
+
+ if (spawner.spawnDelay > 0) {
+ --spawner.spawnDelay;
+ return;
+ }
+
+ boolean flag = false;
+ int i = 0;
+
+ int spawnCount = (int) ReflectionUtils.getFieldValue(spawner, "spawnCount");
+ int spawnRange = (int) ReflectionUtils.getFieldValue(spawner, "spawnRange");
+ int maxNearbyEntities = (int) ReflectionUtils.getFieldValue(spawner, "maxNearbyEntities");
+ MobSpawnerData spawnData = (MobSpawnerData) ReflectionUtils.getFieldValue(spawner, "spawnData");
+
+ while (true) {
+ if (i >= spawnCount) {
+ if (flag) {
+ delay(spawner);
+ }
+ break;
+ }
+
+ NBTTagCompound nbttagcompound = spawnData.b();
+ NBTTagList nbttaglist = nbttagcompound.getList("Pos", 6);
+ net.minecraft.server.v1_9_R2.World world = spawner.a();
+ int j = nbttaglist.size();
+ double d3 = j >= 1 ? nbttaglist.e(0) : (double) blockposition.getX() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawnRange + .5D;
+ double d4 = j >= 2 ? nbttaglist.e(1) : (double) (blockposition.getY() + world.random.nextInt(3) - 1);
+ double d5 = j >= 3 ? nbttaglist.e(2) : (double) blockposition.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) spawnRange + .5D;
+ Entity entity = ChunkRegionLoader.a(nbttagcompound, world, d3, d4, d5, false);
+ if (entity == null) {
+ return;
+ }
+
+ int k = world.a(entity.getClass(), (new AxisAlignedBB(
+ blockposition.getX(),
+ blockposition.getY(),
+ blockposition.getZ(),
+ blockposition.getX() + 1,
+ blockposition.getY() + 1,
+ blockposition.getZ() + 1))
+ .g(spawnRange)).size();
+ if (k >= maxNearbyEntities) {
+ delay(spawner);
+ return;
+ }
+
+ EntityInsentient entityinsentient = entity instanceof EntityInsentient ? (EntityInsentient) entity : null;
+ entity.setPositionRotation(entity.locX, entity.locY, entity.locZ, world.random.nextFloat() * 360.0F, 0.0F);
+ if (entityinsentient == null || entityinsentient.cG() && entityinsentient.canSpawn()) {
+ if (spawnData.b().d() == 1 && spawnData.b().hasKeyOfType("id", 8) && entity instanceof EntityInsentient) {
+ ((EntityInsentient) entity).prepare(world.D(new BlockPosition(entity)), null);
+ }
+
+ if (entity.world.spigotConfig.nerfSpawnerMobs) {
+ entity.fromMobSpawner = true;
+ }
+
+ if (!CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) {
+ ChunkRegionLoader.a(entity, world, CreatureSpawnEvent.SpawnReason.SPAWNER);
+ world.triggerEffect(2004, blockposition, 0);
+ if (entityinsentient != null) {
+ entityinsentient.doSpawnEffect();
+ }
+
+ flag = true;
+ }
+ }
+
+ ++i;
+ }
+ }
+ }
+
+ /**
+ * This method calls {@link MobSpawnerAbstract#i()} using Reflections.
+ */
+ @SuppressWarnings("JavadocReference")
+ private void delay(MobSpawnerAbstract spawner) throws InvocationTargetException, IllegalAccessException {
+ iMethod.invoke(spawner);
+ }
+}
\ No newline at end of file