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;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public interface WorldCore {
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public interface WorldCore {
|
||||
SSpawner getSpawner(CreatureSpawner spawner);
|
||||
|
||||
SSpawner getSpawner(Location location);
|
||||
@ -14,4 +17,39 @@ public interface WorldCore {
|
||||
SItemStack getItemStack(ItemStack item);
|
||||
|
||||
SWorld getWorld(World world);
|
||||
|
||||
BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException;
|
||||
|
||||
/**
|
||||
* Performs random ticks on a specific chunks.
|
||||
* <br><br>
|
||||
* More information: <a href="https://minecraft.fandom.com/wiki/Tick#Random_tick">https://minecraft.fandom.com/wiki/Tick#Random_tick</a>
|
||||
*
|
||||
* @param bukkitChunk The chunk to tick
|
||||
* @param tickAmount The number of blocks to tick per ChunkSection, normally referred to as <code>randomTickSpeed</code>
|
||||
*/
|
||||
void randomTickChunk(Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException;
|
||||
|
||||
/**
|
||||
* Ticks all inactive spawners in a specific chunk ignoring the minimum required players within a specific range.<br>
|
||||
* A spawner is deemed inactive if no player is within its activation range.
|
||||
*
|
||||
* @param chunk The chunk to tick the spawners in
|
||||
* @param amount The amount of ticks to execute for each spawner
|
||||
*/
|
||||
default void tickInactiveSpawners(Chunk chunk, int amount) throws NoSuchFieldException, IllegalAccessException, InvocationTargetException {
|
||||
if (amount <= 0) return;
|
||||
|
||||
for (BlockState tileEntity : chunk.getTileEntities()) {
|
||||
if (tileEntity instanceof CreatureSpawner) {
|
||||
BBaseSpawner spawner = getBaseSpawner((CreatureSpawner) tileEntity);
|
||||
|
||||
if (!spawner.isNearPlayer()) {
|
||||
for (int i = 0; i < amount; ++i) {
|
||||
spawner.tick();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,26 @@
|
||||
package com.songoda.core.nms.v1_10_R1.world;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_10_R1.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_10_R1.Block;
|
||||
import net.minecraft.server.v1_10_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_10_R1.Chunk;
|
||||
import net.minecraft.server.v1_10_R1.ChunkSection;
|
||||
import net.minecraft.server.v1_10_R1.IBlockData;
|
||||
import net.minecraft.server.v1_10_R1.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_10_R1.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_10_R1.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +40,47 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#j()}.
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
int j = chunk.locX * 16;
|
||||
int k = chunk.locZ * 16;
|
||||
|
||||
for (ChunkSection chunksection : chunk.getSections()) {
|
||||
if (chunksection != net.minecraft.server.v1_10_R1.Chunk.a && chunksection.shouldTick()) {
|
||||
for (int i = 0; i < tickAmount; ++i) {
|
||||
int worldL = (int) ReflectionUtils.getFieldValue(chunk.world, "l");
|
||||
worldL = worldL * 3 + 1013904223;
|
||||
ReflectionUtils.setFieldValue(chunk.world, "l", worldL);
|
||||
|
||||
int l1 = worldL >> 2;
|
||||
int i2 = l1 & 15;
|
||||
int j2 = l1 >> 8 & 15;
|
||||
int k2 = l1 >> 16 & 15;
|
||||
|
||||
IBlockData iblockdata = chunksection.getType(i2, k2, j2);
|
||||
Block block = iblockdata.getBlock();
|
||||
|
||||
if (block.isTicking()) {
|
||||
block.a(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), iblockdata, chunk.world.random);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_11_R1.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_11_R1.Block;
|
||||
import net.minecraft.server.v1_11_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_11_R1.Chunk;
|
||||
import net.minecraft.server.v1_11_R1.ChunkSection;
|
||||
import net.minecraft.server.v1_11_R1.IBlockData;
|
||||
import net.minecraft.server.v1_11_R1.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_11_R1.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_11_R1.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +40,47 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#j()}.
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
int j = chunk.locX * 16;
|
||||
int k = chunk.locZ * 16;
|
||||
|
||||
for (ChunkSection chunksection : chunk.getSections()) {
|
||||
if (chunksection != net.minecraft.server.v1_11_R1.Chunk.a && chunksection.shouldTick()) {
|
||||
for (int i = 0; i < tickAmount; ++i) {
|
||||
int worldL = (int) ReflectionUtils.getFieldValue(chunk.world, "l");
|
||||
worldL = worldL * 3 + 1013904223;
|
||||
ReflectionUtils.setFieldValue(chunk.world, "l", worldL);
|
||||
|
||||
int l1 = worldL >> 2;
|
||||
int i2 = l1 & 15;
|
||||
int j2 = l1 >> 8 & 15;
|
||||
int k2 = l1 >> 16 & 15;
|
||||
|
||||
IBlockData iblockdata = chunksection.getType(i2, k2, j2);
|
||||
Block block = iblockdata.getBlock();
|
||||
|
||||
if (block.isTicking()) {
|
||||
block.a(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), iblockdata, chunk.world.random);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_12_R1.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_12_R1.Block;
|
||||
import net.minecraft.server.v1_12_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_12_R1.Chunk;
|
||||
import net.minecraft.server.v1_12_R1.ChunkSection;
|
||||
import net.minecraft.server.v1_12_R1.IBlockData;
|
||||
import net.minecraft.server.v1_12_R1.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_12_R1.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_12_R1.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +40,47 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#j()}.
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
int j = chunk.locX * 16;
|
||||
int k = chunk.locZ * 16;
|
||||
|
||||
for (ChunkSection chunksection : chunk.getSections()) {
|
||||
if (chunksection != net.minecraft.server.v1_12_R1.Chunk.a && chunksection.shouldTick()) {
|
||||
for (int k1 = 0; k1 < tickAmount; ++k1) {
|
||||
int worldL = (int) ReflectionUtils.getFieldValue(chunk.world, "l");
|
||||
worldL = worldL * 3 + 1013904223;
|
||||
ReflectionUtils.setFieldValue(chunk.world, "l", worldL);
|
||||
|
||||
int l1 = worldL >> 2;
|
||||
int i2 = l1 & 15;
|
||||
int j2 = l1 >> 8 & 15;
|
||||
int k2 = l1 >> 16 & 15;
|
||||
|
||||
IBlockData iblockdata = chunksection.getType(i2, k2, j2);
|
||||
Block block = iblockdata.getBlock();
|
||||
|
||||
if (block.isTicking()) {
|
||||
block.a(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), iblockdata, chunk.world.random);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_13_R1.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_13_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_13_R1.Chunk;
|
||||
import net.minecraft.server.v1_13_R1.ChunkSection;
|
||||
import net.minecraft.server.v1_13_R1.Fluid;
|
||||
import net.minecraft.server.v1_13_R1.IBlockData;
|
||||
import net.minecraft.server.v1_13_R1.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_13_R1.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_13_R1.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +40,51 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#l()}.
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
int j = chunk.locX * 16;
|
||||
int k = chunk.locZ * 16;
|
||||
|
||||
for (ChunkSection chunksection : chunk.getSections()) {
|
||||
if (chunksection != net.minecraft.server.v1_13_R1.Chunk.a && chunksection.b()) {
|
||||
for (int i = 0; i < tickAmount; ++i) {
|
||||
int worldM = (int) ReflectionUtils.getFieldValue(chunk.world, "m");
|
||||
worldM = worldM * 3 + 1013904223;
|
||||
ReflectionUtils.setFieldValue(chunk.world, "m", worldM);
|
||||
|
||||
int l1 = worldM >> 2;
|
||||
int i2 = l1 & 15;
|
||||
int j2 = l1 >> 8 & 15;
|
||||
int k2 = l1 >> 16 & 15;
|
||||
|
||||
IBlockData iblockdata = chunksection.getType(i2, k2, j2);
|
||||
Fluid fluid = chunksection.b(i2, k2, j2);
|
||||
|
||||
if (iblockdata.t()) {
|
||||
iblockdata.b(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), chunk.world.random);
|
||||
}
|
||||
|
||||
if (fluid.h()) {
|
||||
fluid.b(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), chunk.world.random);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_13_R2.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_13_R2.BlockPosition;
|
||||
import net.minecraft.server.v1_13_R2.Chunk;
|
||||
import net.minecraft.server.v1_13_R2.ChunkSection;
|
||||
import net.minecraft.server.v1_13_R2.Fluid;
|
||||
import net.minecraft.server.v1_13_R2.IBlockData;
|
||||
import net.minecraft.server.v1_13_R2.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_13_R2.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_13_R2.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +40,58 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#n_()}.
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
int j = chunk.locX * 16;
|
||||
int k = chunk.locZ * 16;
|
||||
|
||||
chunk.world.methodProfiler.enter("tickBlocks");
|
||||
for (ChunkSection chunksection : chunk.getSections()) {
|
||||
if (chunksection != net.minecraft.server.v1_13_R2.Chunk.a && chunksection.b()) {
|
||||
for (int k1 = 0; k1 < tickAmount; ++k1) {
|
||||
int worldM = (int) ReflectionUtils.getFieldValue(chunk.world, "m");
|
||||
worldM = worldM * 3 + 1013904223;
|
||||
ReflectionUtils.setFieldValue(chunk.world, "m", worldM);
|
||||
|
||||
int l1 = worldM >> 2;
|
||||
int i2 = l1 & 15;
|
||||
int j2 = l1 >> 8 & 15;
|
||||
int k2 = l1 >> 16 & 15;
|
||||
|
||||
IBlockData iblockdata = chunksection.getType(i2, k2, j2);
|
||||
Fluid fluid = chunksection.b(i2, k2, j2);
|
||||
|
||||
chunk.world.methodProfiler.enter("randomTick");
|
||||
|
||||
if (iblockdata.t()) {
|
||||
iblockdata.b(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), chunk.world.random);
|
||||
}
|
||||
|
||||
if (fluid.h()) {
|
||||
fluid.b(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), chunk.world.random);
|
||||
}
|
||||
|
||||
chunk.world.methodProfiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chunk.world.methodProfiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_14_R1.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_14_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_14_R1.Chunk;
|
||||
import net.minecraft.server.v1_14_R1.ChunkCoordIntPair;
|
||||
import net.minecraft.server.v1_14_R1.ChunkSection;
|
||||
import net.minecraft.server.v1_14_R1.Fluid;
|
||||
import net.minecraft.server.v1_14_R1.GameProfilerFiller;
|
||||
import net.minecraft.server.v1_14_R1.IBlockData;
|
||||
import net.minecraft.server.v1_14_R1.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_14_R1.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +42,53 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#a(Chunk, int)}.
|
||||
*/
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
|
||||
int j = chunkcoordintpair.d();
|
||||
int k = chunkcoordintpair.e();
|
||||
|
||||
GameProfilerFiller profiler = chunk.world.getMethodProfiler();
|
||||
|
||||
profiler.enter("tickBlocks");
|
||||
for (ChunkSection chunksection : chunk.getSections()) {
|
||||
if (chunksection != net.minecraft.server.v1_14_R1.Chunk.a && chunksection.d()) {
|
||||
int j1 = chunksection.getYPosition();
|
||||
|
||||
for (int i = 0; i < tickAmount; ++i) {
|
||||
BlockPosition blockposition2 = chunk.world.a(j, j1, k, 15);
|
||||
profiler.enter("randomTick");
|
||||
IBlockData iblockdata = chunksection.getType(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k);
|
||||
|
||||
if (iblockdata.q()) {
|
||||
iblockdata.b(chunk.world, blockposition2, chunk.world.random);
|
||||
}
|
||||
|
||||
Fluid fluid = iblockdata.p();
|
||||
if (fluid.h()) {
|
||||
fluid.b(chunk.world, blockposition2, chunk.world.random);
|
||||
}
|
||||
|
||||
profiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
profiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_15_R1.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_15_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_15_R1.Chunk;
|
||||
import net.minecraft.server.v1_15_R1.ChunkCoordIntPair;
|
||||
import net.minecraft.server.v1_15_R1.ChunkSection;
|
||||
import net.minecraft.server.v1_15_R1.Fluid;
|
||||
import net.minecraft.server.v1_15_R1.GameProfilerFiller;
|
||||
import net.minecraft.server.v1_15_R1.IBlockData;
|
||||
import net.minecraft.server.v1_15_R1.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_15_R1.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +42,56 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#a(net.minecraft.server.v1_15_R1.Chunk, int)}.
|
||||
*/
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
|
||||
int j = chunkcoordintpair.d();
|
||||
int k = chunkcoordintpair.e();
|
||||
GameProfilerFiller profiler = chunk.world.getMethodProfiler();
|
||||
|
||||
profiler.enter("tickBlocks");
|
||||
|
||||
for (ChunkSection chunksection : chunk.getSections()) {
|
||||
if (chunksection != Chunk.a && chunksection.d()) {
|
||||
int j1 = chunksection.getYPosition();
|
||||
|
||||
for (int k1 = 0; k1 < tickAmount; ++k1) {
|
||||
BlockPosition blockposition2 = chunk.world.a(j, j1, k, 15);
|
||||
profiler.enter("randomTick");
|
||||
IBlockData iblockdata = chunksection.getType(
|
||||
blockposition2.getX() - j,
|
||||
blockposition2.getY() - j1,
|
||||
blockposition2.getZ() - k);
|
||||
|
||||
if (iblockdata.q()) {
|
||||
iblockdata.b((WorldServer) chunk.world, blockposition2, chunk.world.random);
|
||||
}
|
||||
|
||||
Fluid fluid = iblockdata.getFluid();
|
||||
if (fluid.h()) {
|
||||
fluid.b(chunk.world, blockposition2, chunk.world.random);
|
||||
}
|
||||
|
||||
profiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
profiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_16_R1.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_16_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_16_R1.Chunk;
|
||||
import net.minecraft.server.v1_16_R1.ChunkCoordIntPair;
|
||||
import net.minecraft.server.v1_16_R1.ChunkSection;
|
||||
import net.minecraft.server.v1_16_R1.Fluid;
|
||||
import net.minecraft.server.v1_16_R1.GameProfilerFiller;
|
||||
import net.minecraft.server.v1_16_R1.IBlockData;
|
||||
import net.minecraft.server.v1_16_R1.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_16_R1.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_16_R1.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +42,57 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#a(Chunk, int)}.
|
||||
*/
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
|
||||
int j = chunkcoordintpair.d();
|
||||
int k = chunkcoordintpair.e();
|
||||
|
||||
GameProfilerFiller profiler = chunk.world.getMethodProfiler();
|
||||
|
||||
profiler.enter("tickBlocks");
|
||||
for (ChunkSection chunksection : chunk.getSections()) {
|
||||
if (chunksection != Chunk.a && chunksection.d()) {
|
||||
int j1 = chunksection.getYPosition();
|
||||
|
||||
for (int k1 = 0; k1 < tickAmount; ++k1) {
|
||||
BlockPosition blockposition2 = chunk.world.a(j, j1, k, 15);
|
||||
profiler.enter("randomTick");
|
||||
|
||||
IBlockData iblockdata = chunksection.getType(
|
||||
blockposition2.getX() - j,
|
||||
blockposition2.getY() - j1,
|
||||
blockposition2.getZ() - k);
|
||||
|
||||
if (iblockdata.isTicking()) {
|
||||
iblockdata.b(chunk.world, blockposition2, chunk.world.random);
|
||||
}
|
||||
|
||||
Fluid fluid = iblockdata.getFluid();
|
||||
if (fluid.f()) {
|
||||
fluid.b(chunk.world, blockposition2, chunk.world.random);
|
||||
}
|
||||
|
||||
profiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
profiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_16_R2.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_16_R2.BlockPosition;
|
||||
import net.minecraft.server.v1_16_R2.Chunk;
|
||||
import net.minecraft.server.v1_16_R2.ChunkCoordIntPair;
|
||||
import net.minecraft.server.v1_16_R2.ChunkSection;
|
||||
import net.minecraft.server.v1_16_R2.Fluid;
|
||||
import net.minecraft.server.v1_16_R2.GameProfilerFiller;
|
||||
import net.minecraft.server.v1_16_R2.IBlockData;
|
||||
import net.minecraft.server.v1_16_R2.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_16_R2.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_16_R2.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +42,57 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#a(Chunk, int)}.
|
||||
*/
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
|
||||
int j = chunkcoordintpair.d();
|
||||
int k = chunkcoordintpair.e();
|
||||
|
||||
GameProfilerFiller profiler = chunk.world.getMethodProfiler();
|
||||
|
||||
profiler.enter("tickBlocks");
|
||||
for (ChunkSection chunksection : chunk.getSections()) {
|
||||
if (chunksection != Chunk.a && chunksection.d()) {
|
||||
int j1 = chunksection.getYPosition();
|
||||
|
||||
for (int i = 0; i < tickAmount; ++i) {
|
||||
BlockPosition blockposition2 = chunk.world.a(j, j1, k, 15);
|
||||
profiler.enter("randomTick");
|
||||
|
||||
IBlockData iblockdata = chunksection.getType(
|
||||
blockposition2.getX() - j,
|
||||
blockposition2.getY() - j1,
|
||||
blockposition2.getZ() - k);
|
||||
|
||||
if (iblockdata.isTicking()) {
|
||||
iblockdata.b(chunk.world, blockposition2, chunk.world.random);
|
||||
}
|
||||
|
||||
Fluid fluid = iblockdata.getFluid();
|
||||
if (fluid.f()) {
|
||||
fluid.b(chunk.world, blockposition2, chunk.world.random);
|
||||
}
|
||||
|
||||
profiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
profiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_16_R3.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_16_R3.BlockPosition;
|
||||
import net.minecraft.server.v1_16_R3.Chunk;
|
||||
import net.minecraft.server.v1_16_R3.ChunkCoordIntPair;
|
||||
import net.minecraft.server.v1_16_R3.ChunkSection;
|
||||
import net.minecraft.server.v1_16_R3.Fluid;
|
||||
import net.minecraft.server.v1_16_R3.GameProfilerFiller;
|
||||
import net.minecraft.server.v1_16_R3.IBlockData;
|
||||
import net.minecraft.server.v1_16_R3.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_16_R3.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_16_R3.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +42,58 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#a(Chunk, int)}.
|
||||
*/
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
GameProfilerFiller profiler = chunk.world.getMethodProfiler();
|
||||
|
||||
ChunkCoordIntPair chunkPos = chunk.getPos();
|
||||
int minBlockX = chunkPos.d();
|
||||
int minBlockZ = chunkPos.e();
|
||||
|
||||
profiler.enter("tickBlocks");
|
||||
for (ChunkSection cSection : chunk.getSections()) {
|
||||
if (cSection != Chunk.a && // cSection != Chunk.EMPTY_SECTION
|
||||
cSection.d()) { // #isRandomlyTicking()
|
||||
int bottomBlockY = cSection.getYPosition();
|
||||
|
||||
for (int i = 0; i < tickAmount; ++i) {
|
||||
BlockPosition randomBlockPos = chunk.world.a(minBlockX, bottomBlockY, minBlockZ, 15); // getBlockRandomPos
|
||||
profiler.enter("randomTick");
|
||||
|
||||
IBlockData blockState = cSection.getType(
|
||||
randomBlockPos.getX() - minBlockX,
|
||||
randomBlockPos.getY() - bottomBlockY,
|
||||
randomBlockPos.getZ() - minBlockZ); // #getBlockState
|
||||
|
||||
if (blockState.isTicking()) { // #isRandomlyTicking()
|
||||
blockState.b(chunk.world, randomBlockPos, chunk.world.random); // #randomTick
|
||||
}
|
||||
|
||||
Fluid fluidState = blockState.getFluid(); // #getFluidState()
|
||||
if (fluidState.f()) { // #isRandomlyTicking()
|
||||
fluidState.b(chunk.world, randomBlockPos, chunk.world.random); // #randomTick
|
||||
}
|
||||
|
||||
profiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
profiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_17_R1.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.core.BlockPosition;
|
||||
import net.minecraft.server.level.WorldServer;
|
||||
import net.minecraft.util.profiling.GameProfilerFiller;
|
||||
import net.minecraft.world.level.ChunkCoordIntPair;
|
||||
import net.minecraft.world.level.MobSpawnerAbstract;
|
||||
import net.minecraft.world.level.block.state.IBlockData;
|
||||
import net.minecraft.world.level.chunk.Chunk;
|
||||
import net.minecraft.world.level.chunk.ChunkSection;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftChunk;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
@ -30,4 +43,56 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "tileEntity");
|
||||
|
||||
return new BBaseSpawnerImpl(spawner, (MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#a(Chunk, int)}.
|
||||
*/
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
WorldServer world = (WorldServer) chunk.getWorld();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
GameProfilerFiller profiler = world.getMethodProfiler();
|
||||
|
||||
ChunkCoordIntPair chunkPos = chunk.getPos();
|
||||
int minBlockX = chunkPos.d();
|
||||
int minBlockZ = chunkPos.e();
|
||||
|
||||
profiler.enter("tickBlocks");
|
||||
for (ChunkSection cSection : chunk.getSections()) {
|
||||
if (cSection != Chunk.a && // cSection != Chunk.EMPTY_SECTION
|
||||
cSection.d()) { // #isRandomlyTicking
|
||||
int bottomBlockY = cSection.getYPosition();
|
||||
|
||||
for (int k1 = 0; k1 < tickAmount; ++k1) {
|
||||
BlockPosition bPos = world.a(minBlockX, bottomBlockY, minBlockZ, 15);
|
||||
profiler.enter("randomTick");
|
||||
|
||||
IBlockData blockState = cSection.getType(bPos.getX() - minBlockX, bPos.getY() - bottomBlockY, bPos.getZ() - minBlockZ);
|
||||
|
||||
if (blockState.isTicking()) {
|
||||
blockState.b(world, bPos, chunk.getWorld().w); // #randomTick
|
||||
}
|
||||
|
||||
Fluid fluid = blockState.getFluid();
|
||||
if (fluid.f()) { // #isRandomlyTicking
|
||||
fluid.b(world, bPos, chunk.getWorld().w); // #randomTick
|
||||
}
|
||||
|
||||
profiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
profiler.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_8_R1.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_8_R1.Block;
|
||||
import net.minecraft.server.v1_8_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_8_R1.Chunk;
|
||||
import net.minecraft.server.v1_8_R1.ChunkSection;
|
||||
import net.minecraft.server.v1_8_R1.IBlockData;
|
||||
import net.minecraft.server.v1_8_R1.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_8_R1.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_8_R1.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +40,50 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#h()}.
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
int k = chunk.locX * 16;
|
||||
int l = chunk.locZ * 16;
|
||||
|
||||
for (ChunkSection cSection : chunk.getSections()) {
|
||||
if (cSection != null && cSection.shouldTick()) {
|
||||
|
||||
for (int i = 0; i < tickAmount; ++i) {
|
||||
int m = (int) ReflectionUtils.getFieldValue(chunk.world, "m");
|
||||
|
||||
m = m * 3 + 1013904223;
|
||||
ReflectionUtils.setFieldValue(chunk.world, "m", m);
|
||||
|
||||
int i2 = m >> 2;
|
||||
int j2 = i2 & 15;
|
||||
int k2 = i2 >> 8 & 15;
|
||||
int l2 = i2 >> 16 & 15;
|
||||
|
||||
BlockPosition blockposition2 = new BlockPosition(j2 + k, l2 + cSection.getYPosition(), k2 + l);
|
||||
IBlockData iblockdata = cSection.getType(j2, l2, k2);
|
||||
Block block = iblockdata.getBlock();
|
||||
|
||||
if (block.isTicking()) {
|
||||
block.a(chunk.world, blockposition2, iblockdata, chunk.world.random);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_8_R2.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_8_R2.Block;
|
||||
import net.minecraft.server.v1_8_R2.BlockPosition;
|
||||
import net.minecraft.server.v1_8_R2.Chunk;
|
||||
import net.minecraft.server.v1_8_R2.ChunkSection;
|
||||
import net.minecraft.server.v1_8_R2.IBlockData;
|
||||
import net.minecraft.server.v1_8_R2.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_8_R2.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_8_R2.CraftChunk;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +42,49 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#h()}.
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
int k = chunk.locX * 16;
|
||||
int l = chunk.locZ * 16;
|
||||
|
||||
for (ChunkSection cSection : chunk.getSections()) {
|
||||
if (cSection != null && cSection.shouldTick()) {
|
||||
for (int i = 0; i < tickAmount; ++i) {
|
||||
int m = (int) ReflectionUtils.getFieldValue(chunk.world, "m");
|
||||
|
||||
m = m * 3 + 1013904223;
|
||||
ReflectionUtils.setFieldValue(chunk.world, "m", m);
|
||||
|
||||
int i2 = m >> 2;
|
||||
int j2 = i2 & 15;
|
||||
int k2 = i2 >> 8 & 15;
|
||||
int l2 = i2 >> 16 & 15;
|
||||
|
||||
BlockPosition blockposition2 = new BlockPosition(j2 + k, l2 + cSection.getYPosition(), k2 + l);
|
||||
IBlockData iblockdata = cSection.getType(j2, l2, k2);
|
||||
Block block = iblockdata.getBlock();
|
||||
|
||||
if (block.isTicking()) {
|
||||
block.a(chunk.world, blockposition2, iblockdata, chunk.world.random);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_8_R3.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_8_R3.Block;
|
||||
import net.minecraft.server.v1_8_R3.BlockPosition;
|
||||
import net.minecraft.server.v1_8_R3.Chunk;
|
||||
import net.minecraft.server.v1_8_R3.ChunkSection;
|
||||
import net.minecraft.server.v1_8_R3.IBlockData;
|
||||
import net.minecraft.server.v1_8_R3.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_8_R3.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +40,48 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#h()}.
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
int k = chunk.locX * 16;
|
||||
int l = chunk.locZ * 16;
|
||||
|
||||
for (ChunkSection chunksection : chunk.getSections()) {
|
||||
if (chunksection != null && chunksection.shouldTick()) {
|
||||
for (int l1 = 0; l1 < tickAmount; ++l1) {
|
||||
int m = (int) ReflectionUtils.getFieldValue(chunk.world, "m");
|
||||
|
||||
m = m * 3 + 1013904223;
|
||||
ReflectionUtils.setFieldValue(chunk.world, "m", m);
|
||||
|
||||
int i2 = m >> 2;
|
||||
int j2 = i2 & 15;
|
||||
int k2 = i2 >> 8 & 15;
|
||||
int l2 = i2 >> 16 & 15;
|
||||
|
||||
IBlockData iblockdata = chunksection.getType(j2, l2, k2);
|
||||
Block block = iblockdata.getBlock();
|
||||
|
||||
if (block.isTicking()) {
|
||||
block.a(chunk.world, new BlockPosition(j2 + k, l2 + chunksection.getYPosition(), k2 + l), iblockdata, chunk.world.random);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_9_R1.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_9_R1.Block;
|
||||
import net.minecraft.server.v1_9_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_9_R1.Chunk;
|
||||
import net.minecraft.server.v1_9_R1.ChunkSection;
|
||||
import net.minecraft.server.v1_9_R1.IBlockData;
|
||||
import net.minecraft.server.v1_9_R1.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_9_R1.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_9_R1.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +40,48 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#j()}.
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
int j = chunk.locX * 16;
|
||||
int k = chunk.locZ * 16;
|
||||
|
||||
for (ChunkSection chunksection : chunk.getSections()) {
|
||||
if (chunksection != net.minecraft.server.v1_9_R1.Chunk.a && chunksection.shouldTick()) {
|
||||
for (int i = 0; i < tickAmount; ++i) {
|
||||
int worldL = (int) ReflectionUtils.getFieldValue(chunk.world, "l");
|
||||
|
||||
worldL = worldL * 3 + 1013904223;
|
||||
ReflectionUtils.setFieldValue(chunk.world, "l", worldL);
|
||||
|
||||
int l1 = worldL >> 2;
|
||||
int i2 = l1 & 15;
|
||||
int j2 = l1 >> 8 & 15;
|
||||
int k2 = l1 >> 16 & 15;
|
||||
|
||||
IBlockData iblockdata = chunksection.getType(i2, k2, j2);
|
||||
Block block = iblockdata.getBlock();
|
||||
|
||||
if (block.isTicking()) {
|
||||
block.a(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), iblockdata, chunk.world.random);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.songoda.core.nms.world.SItemStack;
|
||||
import com.songoda.core.nms.ReflectionUtils;
|
||||
import com.songoda.core.nms.v1_9_R2.world.spawner.BBaseSpawnerImpl;
|
||||
import com.songoda.core.nms.world.BBaseSpawner;
|
||||
import com.songoda.core.nms.world.SSpawner;
|
||||
import com.songoda.core.nms.world.SWorld;
|
||||
import com.songoda.core.nms.world.WorldCore;
|
||||
import net.minecraft.server.v1_9_R2.Block;
|
||||
import net.minecraft.server.v1_9_R2.BlockPosition;
|
||||
import net.minecraft.server.v1_9_R2.Chunk;
|
||||
import net.minecraft.server.v1_9_R2.ChunkSection;
|
||||
import net.minecraft.server.v1_9_R2.IBlockData;
|
||||
import net.minecraft.server.v1_9_R2.MobSpawnerAbstract;
|
||||
import net.minecraft.server.v1_9_R2.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.craftbukkit.v1_9_R2.CraftChunk;
|
||||
|
||||
public class WorldCoreImpl implements WorldCore {
|
||||
|
||||
@Override
|
||||
public SSpawner getSpawner(CreatureSpawner spawner) {
|
||||
return new SSpawnerImpl(spawner.getLocation());
|
||||
@ -30,4 +40,47 @@ public class WorldCoreImpl implements WorldCore {
|
||||
public SWorld getWorld(World world) {
|
||||
return new SWorldImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BBaseSpawner getBaseSpawner(CreatureSpawner spawner) throws NoSuchFieldException, IllegalAccessException {
|
||||
Object cTileEntity = ReflectionUtils.getFieldValue(spawner, "spawner");
|
||||
|
||||
return new BBaseSpawnerImpl((MobSpawnerAbstract) ReflectionUtils.getFieldValue(cTileEntity, "a"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method is based on {@link WorldServer#j()}.
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
@Override
|
||||
public void randomTickChunk(org.bukkit.Chunk bukkitChunk, int tickAmount) throws NoSuchFieldException, IllegalAccessException {
|
||||
Chunk chunk = ((CraftChunk) bukkitChunk).getHandle();
|
||||
|
||||
if (tickAmount > 0) {
|
||||
int j = chunk.locX * 16;
|
||||
int k = chunk.locZ * 16;
|
||||
|
||||
for (ChunkSection chunksection : chunk.getSections()) {
|
||||
if (chunksection != net.minecraft.server.v1_9_R2.Chunk.a && chunksection.shouldTick()) {
|
||||
for (int k1 = 0; k1 < tickAmount; ++k1) {
|
||||
int worldL = (int) ReflectionUtils.getFieldValue(chunk.world, "l");
|
||||
worldL = worldL * 3 + 1013904223;
|
||||
ReflectionUtils.setFieldValue(chunk.world, "l", worldL);
|
||||
|
||||
int l1 = worldL >> 2;
|
||||
int i2 = l1 & 15;
|
||||
int j2 = l1 >> 8 & 15;
|
||||
int k2 = l1 >> 16 & 15;
|
||||
|
||||
IBlockData iblockdata = chunksection.getType(i2, k2, j2);
|
||||
Block block = iblockdata.getBlock();
|
||||
|
||||
if (block.isTicking()) {
|
||||
block.a(chunk.world, new BlockPosition(i2 + j, k2 + chunksection.getYPosition(), j2 + k), iblockdata, chunk.world.random);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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