Add methods to force randomTicks and spawner ticks

This commit is contained in:
Christian Koop 2021-06-26 17:11:52 +02:00
parent 64fa850955
commit d4a299f35f
35 changed files with 3795 additions and 16 deletions

View File

@ -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;
}
}

View File

@ -0,0 +1,12 @@
package com.songoda.core.nms.world;
import java.lang.reflect.InvocationTargetException;
public interface BBaseSpawner {
boolean isNearPlayer() throws InvocationTargetException, IllegalAccessException;
/**
* <b>Ignores {@link #isNearPlayer()} - Make sure the server isn't already ticking the spawner!</b>
*/
void tick() throws NoSuchFieldException, IllegalAccessException, InvocationTargetException;
}

View File

@ -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.
* <br><br>
* More information: <a href="https://minecraft.fandom.com/wiki/Tick#Random_tick">https://minecraft.fandom.com/wiki/Tick#Random_tick</a>
*
* @param bukkitChunk The chunk to tick
* @param tickAmount The number of blocks to tick per ChunkSection, normally referred to as <code>randomTickSpeed</code>
*/
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.<br>
* 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();
}
}
}
}
}
}

View File

@ -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);
}
}
}
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}
}
}
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}
}

View File

@ -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<Entity> 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);
}
}

View File

@ -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();
}
}
}

View File

@ -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<EntityTypes<?>> 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<Entity> 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);
}
}
}
}

View File

@ -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();
}
}
}

View File

@ -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<EntityTypes<?>> 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<Entity> 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);
}
}
}
}

View File

@ -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();
}
}
}

View File

@ -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<EntityTypes<?>> 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<Entity> 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);
}
}
}
}

View File

@ -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();
}
}
}

View File

@ -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<EntityTypes<?>> 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<Entity> 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);
}
}

View File

@ -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();
}
}
}

View File

@ -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<EntityTypes<?>> 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<Entity> 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);
}
}

View File

@ -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();
}
}
}

View File

@ -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<EntityTypes<?>> 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();
}
}

View File

@ -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);
}
}
}
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}
}
}
}
}

View File

@ -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);
}
}