mirror of
https://github.com/songoda/SongodaCore.git
synced 2024-11-23 18:45:34 +01:00
Add methods to force randomTicks and spawner ticks
This commit is contained in:
parent
64fa850955
commit
d4a299f35f
52
NMS/NMS-API/src/com/songoda/core/nms/ReflectionUtils.java
Normal file
52
NMS/NMS-API/src/com/songoda/core/nms/ReflectionUtils.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
12
NMS/NMS-API/src/com/songoda/core/nms/world/BBaseSpawner.java
Normal file
12
NMS/NMS-API/src/com/songoda/core/nms/world/BBaseSpawner.java
Normal 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;
|
||||||
|
}
|
@ -1,12 +1,15 @@
|
|||||||
package com.songoda.core.nms.world;
|
package com.songoda.core.nms.world;
|
||||||
|
|
||||||
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
public interface WorldCore {
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
public interface WorldCore {
|
||||||
SSpawner getSpawner(CreatureSpawner spawner);
|
SSpawner getSpawner(CreatureSpawner spawner);
|
||||||
|
|
||||||
SSpawner getSpawner(Location location);
|
SSpawner getSpawner(Location location);
|
||||||
@ -14,4 +17,39 @@ public interface WorldCore {
|
|||||||
SItemStack getItemStack(ItemStack item);
|
SItemStack getItemStack(ItemStack item);
|
||||||
|
|
||||||
SWorld getWorld(World world);
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,26 @@
|
|||||||
package com.songoda.core.nms.v1_10_R1.world;
|
package com.songoda.core.nms.v1_10_R1.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_10_R1.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +40,47 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,26 @@
|
|||||||
package com.songoda.core.nms.v1_11_R1.world;
|
package com.songoda.core.nms.v1_11_R1.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_11_R1.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +40,47 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,26 @@
|
|||||||
package com.songoda.core.nms.v1_12_R1.world;
|
package com.songoda.core.nms.v1_12_R1.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_12_R1.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +40,47 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,26 @@
|
|||||||
package com.songoda.core.nms.v1_13_R1.world;
|
package com.songoda.core.nms.v1_13_R1.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_13_R1.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +40,51 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,26 @@
|
|||||||
package com.songoda.core.nms.v1_13_R2.world;
|
package com.songoda.core.nms.v1_13_R2.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_13_R2.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +40,58 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,28 @@
|
|||||||
package com.songoda.core.nms.v1_14_R1.world;
|
package com.songoda.core.nms.v1_14_R1.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_14_R1.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +42,53 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,28 @@
|
|||||||
package com.songoda.core.nms.v1_15_R1.world;
|
package com.songoda.core.nms.v1_15_R1.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_15_R1.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +42,56 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,28 @@
|
|||||||
package com.songoda.core.nms.v1_16_R1.world;
|
package com.songoda.core.nms.v1_16_R1.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_16_R1.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +42,57 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,28 @@
|
|||||||
package com.songoda.core.nms.v1_16_R2.world;
|
package com.songoda.core.nms.v1_16_R2.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_16_R2.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +42,57 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,28 @@
|
|||||||
package com.songoda.core.nms.v1_16_R3.world;
|
package com.songoda.core.nms.v1_16_R3.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_16_R3.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +42,58 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,25 @@
|
|||||||
package com.songoda.core.nms.v1_17_R1.world;
|
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.SItemStack;
|
||||||
import com.songoda.core.nms.world.SSpawner;
|
import com.songoda.core.nms.world.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
|
import org.bukkit.craftbukkit.v1_17_R1.CraftChunk;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
@ -30,4 +43,56 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl(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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,26 @@
|
|||||||
package com.songoda.core.nms.v1_8_R1.world;
|
package com.songoda.core.nms.v1_8_R1.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_8_R1.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +40,50 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,28 @@
|
|||||||
package com.songoda.core.nms.v1_8_R2.world;
|
package com.songoda.core.nms.v1_8_R2.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_8_R2.CraftChunk;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +42,49 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,26 @@
|
|||||||
package com.songoda.core.nms.v1_8_R3.world;
|
package com.songoda.core.nms.v1_8_R3.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +40,48 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,26 @@
|
|||||||
package com.songoda.core.nms.v1_9_R1.world;
|
package com.songoda.core.nms.v1_9_R1.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_9_R1.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +40,48 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,26 @@
|
|||||||
package com.songoda.core.nms.v1_9_R2.world;
|
package com.songoda.core.nms.v1_9_R2.world;
|
||||||
|
|
||||||
import com.songoda.core.nms.world.SItemStack;
|
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.SSpawner;
|
||||||
import com.songoda.core.nms.world.SWorld;
|
import com.songoda.core.nms.world.SWorld;
|
||||||
import com.songoda.core.nms.world.WorldCore;
|
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.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.craftbukkit.v1_9_R2.CraftChunk;
|
||||||
|
|
||||||
public class WorldCoreImpl implements WorldCore {
|
public class WorldCoreImpl implements WorldCore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||||
return new SSpawnerImpl(spawner.getLocation());
|
return new SSpawnerImpl(spawner.getLocation());
|
||||||
@ -30,4 +40,47 @@ public class WorldCoreImpl implements WorldCore {
|
|||||||
public SWorld getWorld(World world) {
|
public SWorld getWorld(World world) {
|
||||||
return new SWorldImpl();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user