
net.minecraft.server.World Maven / Gradle / Ivy
package net.minecraft.server;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.bukkit.Bukkit;
import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.SpigotTimings;
import org.bukkit.craftbukkit.event.CraftEventFactory;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.event.block.BlockCanBuildEvent;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.generator.ChunkGenerator;
import java.util.*;
import java.util.concurrent.Callable;
// CraftBukkit end
public abstract class World implements IBlockAccess {
public static boolean haveWeSilencedAPhysicsCrash;
public static String blockLocation;
public final List h = Lists.newArrayList();
public final List tileEntityList = Lists.newArrayList();
public final List players = Lists.newArrayList();
public final List k = Lists.newArrayList();
public final Random random = new Random();
public final MethodProfiler methodProfiler;
public final boolean isClientSide;
public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot
public final SpigotTimings.WorldTimingsHandler timings; // Spigot
// Spigot end
protected final List g = Lists.newArrayList();
protected final IntHashMap entitiesById = new IntHashMap();
protected final int n = 1013904223;
protected final IDataManager dataManager;
protected final gnu.trove.map.hash.TLongShortHashMap chunkTickList;
private final List b = Lists.newArrayList();
private final List c = Lists.newArrayList();
private final Calendar K = Calendar.getInstance();
private final WorldBorder N;
// CraftBukkit start Added the following
private final CraftWorld world;
private final byte chunkTickRadius;
public WorldProvider worldProvider; // CraftBukkit - remove final
public WorldData worldData; // CraftBukkit - public
public PersistentCollection worldMaps; // CraftBukkit - public
public Scoreboard scoreboard = new Scoreboard(); // CraftBukkit - public
public boolean allowMonsters; // CraftBukkit - public
public boolean allowAnimals; // CraftBukkit - public
public boolean pvpMode;
public boolean keepSpawnInMemory = true;
public ChunkGenerator generator;
public boolean captureBlockStates = false;
public boolean captureTreeGeneration = false;
public ArrayList capturedBlockStates = new ArrayList() {
@Override
public boolean add(BlockState blockState) {
for (BlockState blockState1 : this) {
if (blockState1.getLocation().equals(blockState.getLocation())) {
return false;
}
}
return super.add(blockState);
}
};
public long ticksPerAnimalSpawns;
public long ticksPerMonsterSpawns;
public boolean populating;
public Map capturedTileEntities = Maps.newHashMap();
protected boolean e;
protected int m = (new Random()).nextInt();
protected float o;
protected float p;
protected float q;
protected float r;
protected List u = Lists.newArrayList();
protected IChunkProvider chunkProvider;
protected boolean isLoading;
protected PersistentVillage villages;
protected float growthOdds = 100;
protected float modifiedOdds = 100;
int[] H;
private int a = 63;
private final long d = 16777215L;
private int I;
private int J;
// CraftBukkit - longhashset
// protected LongHashSet chunkTickList = new LongHashSet(); // Spigot
private int L;
private boolean M;
private int tickPosition;
// Spigot start
private boolean guardEntityList;
// Spigot start - guard entity list from removals
public final List entityList = new java.util.ArrayList() {
@Override
public Entity remove(int index) {
guard();
return super.remove(index);
}
@Override
public boolean remove(Object o) {
guard();
return super.remove(o);
}
private void guard() {
if (guardEntityList) {
throw new java.util.ConcurrentModificationException();
}
}
};
private final org.spigotmc.TickLimiter entityLimiter;
private final org.spigotmc.TickLimiter tileLimiter;
private int tileTickPosition;
// Spigot end
protected World(IDataManager idatamanager, WorldData worlddata, WorldProvider worldprovider, MethodProfiler methodprofiler, boolean flag, ChunkGenerator gen, org.bukkit.World.Environment env) {
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(worlddata.getName()); // Spigot
this.generator = gen;
this.world = new CraftWorld((WorldServer) this, gen, env);
this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit
this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns(); // CraftBukkit
// CraftBukkit end
// Spigot start
this.chunkTickRadius = (byte) ((this.getServer().getViewDistance() < 7) ? this.getServer().getViewDistance() : 7);
this.chunkTickList = new gnu.trove.map.hash.TLongShortHashMap(spigotConfig.chunksPerTick * 5, 0.7f, Long.MIN_VALUE, Short.MIN_VALUE);
this.chunkTickList.setAutoCompactionFactor(0);
// Spigot end
this.L = this.random.nextInt(12000);
this.allowMonsters = true;
this.allowAnimals = true;
this.H = new int['\u8000'];
this.dataManager = idatamanager;
this.methodProfiler = methodprofiler;
this.worldData = worlddata;
this.worldProvider = worldprovider;
this.isClientSide = flag;
this.N = worldprovider.getWorldBorder();
// CraftBukkit start
// Moved from PlayerList
this.N.a(new IWorldBorderListener() {
public void a(WorldBorder worldborder, double d0) {
getServer().getHandle().sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.SET_SIZE), World.this);
}
public void a(WorldBorder worldborder, double d0, double d1, long i) {
getServer().getHandle().sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.LERP_SIZE), World.this);
}
public void a(WorldBorder worldborder, double d0, double d1) {
getServer().getHandle().sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.SET_CENTER), World.this);
}
public void a(WorldBorder worldborder, int i) {
getServer().getHandle().sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.SET_WARNING_TIME), World.this);
}
public void b(WorldBorder worldborder, int i) {
getServer().getHandle().sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.SET_WARNING_BLOCKS), World.this);
}
public void b(WorldBorder worldborder, double d0) {
}
public void c(WorldBorder worldborder, double d0) {
}
});
this.getServer().addWorld(this.world);
// CraftBukkit end
timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings
this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime);
this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime);
}
public static long chunkToKey(int x, int z) {
long k = ((((long) x) & 0xFFFF0000L) << 16) | ((((long) x) & 0x0000FFFFL) << 0);
k |= ((((long) z) & 0xFFFF0000L) << 32) | ((((long) z) & 0x0000FFFFL) << 16);
return k;
}
public static int keyToX(long k) {
return (int) (((k >> 16) & 0xFFFF0000) | (k & 0x0000FFFF));
}
public static int keyToZ(long k) {
return (int) (((k >> 32) & 0xFFFF0000L) | ((k >> 16) & 0x0000FFFF));
}
public static boolean a(IBlockAccess iblockaccess, BlockPosition blockposition) {
IBlockData iblockdata = iblockaccess.getType(blockposition);
Block block = iblockdata.getBlock();
return block.getMaterial().k() && block.d() || (block instanceof BlockStairs ? iblockdata.get(BlockStairs.HALF) == BlockStairs.EnumHalf.TOP : (block instanceof BlockStepAbstract ? iblockdata.get(BlockStepAbstract.HALF) == BlockStepAbstract.EnumSlabHalf.TOP : (block instanceof BlockHopper || (block instanceof BlockSnow && iblockdata.get(BlockSnow.LAYERS).intValue() == 7))));
}
public CraftWorld getWorld() {
return this.world;
}
public CraftServer getServer() {
return (CraftServer) Bukkit.getServer();
}
public Chunk getChunkIfLoaded(int x, int z) {
return ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(x, z);
}
public World b() {
return this;
}
public BiomeBase getBiome(final BlockPosition blockposition) {
if (this.isLoaded(blockposition)) {
Chunk chunk = this.getChunkAtWorldCoords(blockposition);
try {
return chunk.getBiome(blockposition, this.worldProvider.m());
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.a(throwable, "Getting biome");
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Coordinates of biome request");
crashreportsystemdetails.a("Location", new Callable() {
public String a() throws Exception {
return CrashReportSystemDetails.a(blockposition);
}
public Object call() throws Exception {
return this.a();
}
});
throw new ReportedException(crashreport);
}
} else {
return this.worldProvider.m().getBiome(blockposition, BiomeBase.PLAINS);
}
}
public WorldChunkManager getWorldChunkManager() {
return this.worldProvider.m();
}
protected abstract IChunkProvider k();
public void a(WorldSettings worldsettings) {
this.worldData.d(true);
}
public Block c(BlockPosition blockposition) {
BlockPosition blockposition1;
for (blockposition1 = new BlockPosition(blockposition.getX(), this.F(), blockposition.getZ()); !this.isEmpty(blockposition1.up()); blockposition1 = blockposition1.up()) {
}
return this.getType(blockposition1).getBlock();
}
private boolean isValidLocation(BlockPosition blockposition) {
return blockposition.getX() >= -30000000 && blockposition.getZ() >= -30000000 && blockposition.getX() < 30000000 && blockposition.getZ() < 30000000 && blockposition.getY() >= 0 && blockposition.getY() < 256;
}
public boolean isEmpty(BlockPosition blockposition) {
return this.getType(blockposition).getBlock().getMaterial() == Material.AIR;
}
public boolean isLoaded(BlockPosition blockposition) {
return this.a(blockposition, true);
}
public boolean a(BlockPosition blockposition, boolean flag) {
return this.isValidLocation(blockposition) && this.isChunkLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4, flag);
}
public boolean areChunksLoaded(BlockPosition blockposition, int i) {
return this.areChunksLoaded(blockposition, i, true);
}
public boolean areChunksLoaded(BlockPosition blockposition, int i, boolean flag) {
return this.isAreaLoaded(blockposition.getX() - i, blockposition.getY() - i, blockposition.getZ() - i, blockposition.getX() + i, blockposition.getY() + i, blockposition.getZ() + i, flag);
}
public boolean areChunksLoadedBetween(BlockPosition blockposition, BlockPosition blockposition1) {
return this.areChunksLoadedBetween(blockposition, blockposition1, true);
}
public boolean areChunksLoadedBetween(BlockPosition blockposition, BlockPosition blockposition1, boolean flag) {
return this.isAreaLoaded(blockposition.getX(), blockposition.getY(), blockposition.getZ(), blockposition1.getX(), blockposition1.getY(), blockposition1.getZ(), flag);
}
public boolean a(StructureBoundingBox structureboundingbox) {
return this.b(structureboundingbox, true);
}
public boolean b(StructureBoundingBox structureboundingbox, boolean flag) {
return this.isAreaLoaded(structureboundingbox.a, structureboundingbox.b, structureboundingbox.c, structureboundingbox.d, structureboundingbox.e, structureboundingbox.f, flag);
}
private boolean isAreaLoaded(int i, int j, int k, int l, int i1, int j1, boolean flag) {
if (i1 >= 0 && j < 256) {
i >>= 4;
k >>= 4;
l >>= 4;
j1 >>= 4;
for (int k1 = i; k1 <= l; ++k1) {
for (int l1 = k; l1 <= j1; ++l1) {
if (!this.isChunkLoaded(k1, l1, flag)) {
return false;
}
}
}
return true;
} else {
return false;
}
}
protected boolean isChunkLoaded(int i, int j, boolean flag) {
return this.chunkProvider.isChunkLoaded(i, j) && (flag || !this.chunkProvider.getOrCreateChunk(i, j).isEmpty());
}
public Chunk getChunkAtWorldCoords(BlockPosition blockposition) {
return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4);
}
public Chunk getChunkAt(int i, int j) {
return this.chunkProvider.getOrCreateChunk(i, j);
}
// CraftBukkit end
public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) {
// CraftBukkit start - tree generation
if (this.captureTreeGeneration) {
BlockState blockstate = null;
Iterator it = capturedBlockStates.iterator();
while (it.hasNext()) {
BlockState previous = it.next();
if (previous.getX() == blockposition.getX() && previous.getY() == blockposition.getY() && previous.getZ() == blockposition.getZ()) {
blockstate = previous;
it.remove();
break;
}
}
if (blockstate == null) {
blockstate = org.bukkit.craftbukkit.block.CraftBlockState.getBlockState(this, blockposition.getX(), blockposition.getY(), blockposition.getZ(), i);
}
blockstate.setTypeId(CraftMagicNumbers.getId(iblockdata.getBlock()));
blockstate.setRawData((byte) iblockdata.getBlock().toLegacyData(iblockdata));
this.capturedBlockStates.add(blockstate);
return true;
}
// CraftBukkit end
if (!this.isValidLocation(blockposition)) {
return false;
} else if (!this.isClientSide && this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) {
return false;
} else {
Chunk chunk = this.getChunkAtWorldCoords(blockposition);
Block block = iblockdata.getBlock();
// CraftBukkit start - capture blockstates
BlockState blockstate = null;
if (this.captureBlockStates) {
blockstate = org.bukkit.craftbukkit.block.CraftBlockState.getBlockState(this, blockposition.getX(), blockposition.getY(), blockposition.getZ(), i);
this.capturedBlockStates.add(blockstate);
}
// CraftBukkit end
IBlockData iblockdata1 = chunk.a(blockposition, iblockdata);
if (iblockdata1 == null) {
// CraftBukkit start - remove blockstate if failed
if (this.captureBlockStates) {
this.capturedBlockStates.remove(blockstate);
}
// CraftBukkit end
return false;
} else {
Block block1 = iblockdata1.getBlock();
if (block.p() != block1.p() || block.r() != block1.r()) {
this.methodProfiler.a("checkLight");
this.x(blockposition);
this.methodProfiler.b();
}
/*
if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && chunk.isReady()) {
this.notify(blockposition);
}
if (!this.isClientSide && (i & 1) != 0) {
this.update(blockposition, iblockdata1.getBlock());
if (block.isComplexRedstone()) {
this.updateAdjacentComparators(blockposition, block);
}
}
*/
// CraftBukkit start
if (!this.captureBlockStates) { // Don't notify clients or update physics while capturing blockstates
// Modularize client and physic updates
notifyAndUpdatePhysics(blockposition, chunk, block1, block, i);
}
// CraftBukkit end
return true;
}
}
}
// CraftBukkit start - Split off from original setTypeAndData(int i, int j, int k, Block block, int l, int i1) method in order to directly send client and physic updates
public void notifyAndUpdatePhysics(BlockPosition blockposition, Chunk chunk, Block oldBlock, Block newBLock, int flag) {
if ((flag & 2) != 0 && (chunk == null || chunk.isReady())) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement
this.notify(blockposition);
}
if (!this.isClientSide && (flag & 1) != 0) {
this.update(blockposition, oldBlock);
if (newBLock.isComplexRedstone()) {
this.updateAdjacentComparators(blockposition, newBLock);
}
}
}
public boolean setAir(BlockPosition blockposition) {
return this.setTypeAndData(blockposition, Blocks.AIR.getBlockData(), 3);
}
public boolean setAir(BlockPosition blockposition, boolean flag) {
IBlockData iblockdata = this.getType(blockposition);
Block block = iblockdata.getBlock();
if (block.getMaterial() == Material.AIR) {
return false;
} else {
this.triggerEffect(2001, blockposition, Block.getCombinedId(iblockdata));
if (flag) {
block.b(this, blockposition, iblockdata, 0);
}
return this.setTypeAndData(blockposition, Blocks.AIR.getBlockData(), 3);
}
}
public boolean setTypeUpdate(BlockPosition blockposition, IBlockData iblockdata) {
return this.setTypeAndData(blockposition, iblockdata, 3);
}
public void notify(BlockPosition blockposition) {
for (IWorldAccess iWorldAccess : this.u) {
iWorldAccess.a(blockposition);
}
}
public void update(BlockPosition blockposition, Block block) {
if (this.worldData.getType() != WorldType.DEBUG_ALL_BLOCK_STATES) {
// CraftBukkit start
if (populating) {
return;
}
// CraftBukkit end
this.applyPhysics(blockposition, block);
}
}
public void a(int i, int j, int k, int l) {
int i1;
if (k > l) {
i1 = l;
l = k;
k = i1;
}
if (!this.worldProvider.o()) {
for (i1 = k; i1 <= l; ++i1) {
this.c(EnumSkyBlock.SKY, new BlockPosition(i, i1, j));
}
}
this.b(i, k, j, i, l, j);
}
public void b(BlockPosition blockposition, BlockPosition blockposition1) {
this.b(blockposition.getX(), blockposition.getY(), blockposition.getZ(), blockposition1.getX(), blockposition1.getY(), blockposition1.getZ());
}
public void b(int i, int j, int k, int l, int i1, int j1) {
for (int k1 = 0; k1 < this.u.size(); ++k1) {
this.u.get(k1).a(i, j, k, l, i1, j1);
}
}
public void applyPhysics(BlockPosition blockposition, Block block) {
this.d(blockposition.west(), block);
this.d(blockposition.east(), block);
this.d(blockposition.down(), block);
this.d(blockposition.up(), block);
this.d(blockposition.north(), block);
this.d(blockposition.south(), block);
spigotConfig.antiXrayInstance.updateNearbyBlocks(this, blockposition); // Spigot
}
public void a(BlockPosition blockposition, Block block, EnumDirection enumdirection) {
if (enumdirection != EnumDirection.WEST) {
this.d(blockposition.west(), block);
}
if (enumdirection != EnumDirection.EAST) {
this.d(blockposition.east(), block);
}
if (enumdirection != EnumDirection.DOWN) {
this.d(blockposition.down(), block);
}
if (enumdirection != EnumDirection.UP) {
this.d(blockposition.up(), block);
}
if (enumdirection != EnumDirection.NORTH) {
this.d(blockposition.north(), block);
}
if (enumdirection != EnumDirection.SOUTH) {
this.d(blockposition.south(), block);
}
}
public void d(BlockPosition blockposition, final Block block) {
if (!this.isClientSide) {
IBlockData iblockdata = this.getType(blockposition);
try {
// CraftBukkit start
CraftWorld world = this.getWorld();
if (world != null) {
BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftMagicNumbers.getId(block));
this.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
}
// CraftBukkit end
iblockdata.getBlock().doPhysics(this, blockposition, iblockdata, block);
} catch (StackOverflowError stackoverflowerror) { // Spigot Start
haveWeSilencedAPhysicsCrash = true;
blockLocation = blockposition.getX() + ", " + blockposition.getY() + ", " + blockposition.getZ(); // Spigot End
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.a(throwable, "Exception while updating neighbours");
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being updated");
crashreportsystemdetails.a("Source block type", new Callable() {
public String a() throws Exception {
try {
return String.format("ID #%d (%s // %s)", Integer.valueOf(Block.getId(block)), block.a(), block.getClass().getCanonicalName());
} catch (Throwable throwable) {
return "ID #" + Block.getId(block);
}
}
public Object call() throws Exception {
return this.a();
}
});
CrashReportSystemDetails.a(crashreportsystemdetails, blockposition, iblockdata);
throw new ReportedException(crashreport);
}
}
}
public boolean a(BlockPosition blockposition, Block block) {
return false;
}
public boolean i(BlockPosition blockposition) {
return this.getChunkAtWorldCoords(blockposition).d(blockposition);
}
public boolean j(BlockPosition blockposition) {
if (blockposition.getY() >= this.F()) {
return this.i(blockposition);
} else {
BlockPosition blockposition1 = new BlockPosition(blockposition.getX(), this.F(), blockposition.getZ());
if (!this.i(blockposition1)) {
return false;
} else {
for (blockposition1 = blockposition1.down(); blockposition1.getY() > blockposition.getY(); blockposition1 = blockposition1.down()) {
Block block = this.getType(blockposition1).getBlock();
if (block.p() > 0 && !block.getMaterial().isLiquid()) {
return false;
}
}
return true;
}
}
}
public int k(BlockPosition blockposition) {
if (blockposition.getY() < 0) {
return 0;
} else {
if (blockposition.getY() >= 256) {
blockposition = new BlockPosition(blockposition.getX(), 255, blockposition.getZ());
}
return this.getChunkAtWorldCoords(blockposition).a(blockposition, 0);
}
}
public int getLightLevel(BlockPosition blockposition) {
return this.c(blockposition, true);
}
public int c(BlockPosition blockposition, boolean flag) {
if (blockposition.getX() >= -30000000 && blockposition.getZ() >= -30000000 && blockposition.getX() < 30000000 && blockposition.getZ() < 30000000) {
if (flag && this.getType(blockposition).getBlock().s()) {
int i = this.c(blockposition.up(), false);
int j = this.c(blockposition.east(), false);
int k = this.c(blockposition.west(), false);
int l = this.c(blockposition.south(), false);
int i1 = this.c(blockposition.north(), false);
if (j > i) {
i = j;
}
if (k > i) {
i = k;
}
if (l > i) {
i = l;
}
if (i1 > i) {
i = i1;
}
return i;
} else if (blockposition.getY() < 0) {
return 0;
} else {
if (blockposition.getY() >= 256) {
blockposition = new BlockPosition(blockposition.getX(), 255, blockposition.getZ());
}
Chunk chunk = this.getChunkAtWorldCoords(blockposition);
return chunk.a(blockposition, this.I);
}
} else {
return 15;
}
}
public BlockPosition getHighestBlockYAt(BlockPosition blockposition) {
int i;
if (blockposition.getX() >= -30000000 && blockposition.getZ() >= -30000000 && blockposition.getX() < 30000000 && blockposition.getZ() < 30000000) {
if (this.isChunkLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4, true)) {
i = this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4).b(blockposition.getX() & 15, blockposition.getZ() & 15);
} else {
i = 0;
}
} else {
i = this.F() + 1;
}
return new BlockPosition(blockposition.getX(), i, blockposition.getZ());
}
public int b(int i, int j) {
if (i >= -30000000 && j >= -30000000 && i < 30000000 && j < 30000000) {
if (!this.isChunkLoaded(i >> 4, j >> 4, true)) {
return 0;
} else {
Chunk chunk = this.getChunkAt(i >> 4, j >> 4);
return chunk.v();
}
} else {
return this.F() + 1;
}
}
public int b(EnumSkyBlock enumskyblock, BlockPosition blockposition) {
if (blockposition.getY() < 0) {
blockposition = new BlockPosition(blockposition.getX(), 0, blockposition.getZ());
}
if (!this.isValidLocation(blockposition)) {
return enumskyblock.c;
} else if (!this.isLoaded(blockposition)) {
return enumskyblock.c;
} else {
Chunk chunk = this.getChunkAtWorldCoords(blockposition);
return chunk.getBrightness(enumskyblock, blockposition);
}
}
public void a(EnumSkyBlock enumskyblock, BlockPosition blockposition, int i) {
if (this.isValidLocation(blockposition)) {
if (this.isLoaded(blockposition)) {
Chunk chunk = this.getChunkAtWorldCoords(blockposition);
chunk.a(enumskyblock, blockposition, i);
this.n(blockposition);
}
}
}
public void n(BlockPosition blockposition) {
for (int i = 0; i < this.u.size(); ++i) {
this.u.get(i).b(blockposition);
}
}
public float o(BlockPosition blockposition) {
return this.worldProvider.p()[this.getLightLevel(blockposition)];
}
// Spigot start
public IBlockData getType(BlockPosition blockposition) {
return getType(blockposition, true);
}
public IBlockData getType(BlockPosition blockposition, boolean useCaptured) {
// CraftBukkit start - tree generation
if (captureTreeGeneration && useCaptured) {
// Spigot end
for (BlockState previous : capturedBlockStates) {
if (previous.getX() == blockposition.getX() && previous.getY() == blockposition.getY() && previous.getZ() == blockposition.getZ()) {
return CraftMagicNumbers.getBlock(previous.getTypeId()).fromLegacyData(previous.getRawData());
}
}
}
// CraftBukkit end
if (!this.isValidLocation(blockposition)) {
return Blocks.AIR.getBlockData();
} else {
Chunk chunk = this.getChunkAtWorldCoords(blockposition);
return chunk.getBlockData(blockposition);
}
}
public boolean w() {
return this.I < 4;
}
public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1) {
return this.rayTrace(vec3d, vec3d1, false, false, false);
}
public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag) {
return this.rayTrace(vec3d, vec3d1, flag, false, false);
}
public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag, boolean flag1, boolean flag2) {
if (!Double.isNaN(vec3d.a) && !Double.isNaN(vec3d.b) && !Double.isNaN(vec3d.c)) {
if (!Double.isNaN(vec3d1.a) && !Double.isNaN(vec3d1.b) && !Double.isNaN(vec3d1.c)) {
int i = MathHelper.floor(vec3d1.a);
int j = MathHelper.floor(vec3d1.b);
int k = MathHelper.floor(vec3d1.c);
int l = MathHelper.floor(vec3d.a);
int i1 = MathHelper.floor(vec3d.b);
int j1 = MathHelper.floor(vec3d.c);
BlockPosition blockposition = new BlockPosition(l, i1, j1);
IBlockData iblockdata = this.getType(blockposition);
Block block = iblockdata.getBlock();
if ((!flag1 || block.a(this, blockposition, iblockdata) != null) && block.a(iblockdata, flag)) {
MovingObjectPosition movingobjectposition = block.a(this, blockposition, vec3d, vec3d1);
if (movingobjectposition != null) {
return movingobjectposition;
}
}
MovingObjectPosition movingobjectposition1 = null;
int k1 = 200;
while (k1-- >= 0) {
if (Double.isNaN(vec3d.a) || Double.isNaN(vec3d.b) || Double.isNaN(vec3d.c)) {
return null;
}
if (l == i && i1 == j && j1 == k) {
return flag2 ? movingobjectposition1 : null;
}
boolean flag3 = true;
boolean flag4 = true;
boolean flag5 = true;
double d0 = 999.0D;
double d1 = 999.0D;
double d2 = 999.0D;
if (i > l) {
d0 = (double) l + 1.0D;
} else if (i < l) {
d0 = (double) l + 0.0D;
} else {
flag3 = false;
}
if (j > i1) {
d1 = (double) i1 + 1.0D;
} else if (j < i1) {
d1 = (double) i1 + 0.0D;
} else {
flag4 = false;
}
if (k > j1) {
d2 = (double) j1 + 1.0D;
} else if (k < j1) {
d2 = (double) j1 + 0.0D;
} else {
flag5 = false;
}
double d3 = 999.0D;
double d4 = 999.0D;
double d5 = 999.0D;
double d6 = vec3d1.a - vec3d.a;
double d7 = vec3d1.b - vec3d.b;
double d8 = vec3d1.c - vec3d.c;
if (flag3) {
d3 = (d0 - vec3d.a) / d6;
}
if (flag4) {
d4 = (d1 - vec3d.b) / d7;
}
if (flag5) {
d5 = (d2 - vec3d.c) / d8;
}
if (d3 == -0.0D) {
d3 = -1.0E-4D;
}
if (d4 == -0.0D) {
d4 = -1.0E-4D;
}
if (d5 == -0.0D) {
d5 = -1.0E-4D;
}
EnumDirection enumdirection;
if (d3 < d4 && d3 < d5) {
enumdirection = i > l ? EnumDirection.WEST : EnumDirection.EAST;
vec3d = new Vec3D(d0, vec3d.b + d7 * d3, vec3d.c + d8 * d3);
} else if (d4 < d5) {
enumdirection = j > i1 ? EnumDirection.DOWN : EnumDirection.UP;
vec3d = new Vec3D(vec3d.a + d6 * d4, d1, vec3d.c + d8 * d4);
} else {
enumdirection = k > j1 ? EnumDirection.NORTH : EnumDirection.SOUTH;
vec3d = new Vec3D(vec3d.a + d6 * d5, vec3d.b + d7 * d5, d2);
}
l = MathHelper.floor(vec3d.a) - (enumdirection == EnumDirection.EAST ? 1 : 0);
i1 = MathHelper.floor(vec3d.b) - (enumdirection == EnumDirection.UP ? 1 : 0);
j1 = MathHelper.floor(vec3d.c) - (enumdirection == EnumDirection.SOUTH ? 1 : 0);
blockposition = new BlockPosition(l, i1, j1);
IBlockData iblockdata1 = this.getType(blockposition);
Block block1 = iblockdata1.getBlock();
if (!flag1 || block1.a(this, blockposition, iblockdata1) != null) {
if (block1.a(iblockdata1, flag)) {
MovingObjectPosition movingobjectposition2 = block1.a(this, blockposition, vec3d, vec3d1);
if (movingobjectposition2 != null) {
return movingobjectposition2;
}
} else {
movingobjectposition1 = new MovingObjectPosition(MovingObjectPosition.EnumMovingObjectType.MISS, vec3d, enumdirection, blockposition);
}
}
}
return flag2 ? movingobjectposition1 : null;
} else {
return null;
}
} else {
return null;
}
}
public void makeSound(Entity entity, String s, float f, float f1) {
for (int i = 0; i < this.u.size(); ++i) {
this.u.get(i).a(s, entity.locX, entity.locY, entity.locZ, f, f1);
}
}
public void a(EntityHuman entityhuman, String s, float f, float f1) {
for (int i = 0; i < this.u.size(); ++i) {
this.u.get(i).a(entityhuman, s, entityhuman.locX, entityhuman.locY, entityhuman.locZ, f, f1);
}
}
public void makeSound(double d0, double d1, double d2, String s, float f, float f1) {
for (int i = 0; i < this.u.size(); ++i) {
this.u.get(i).a(s, d0, d1, d2, f, f1);
}
}
public void a(double d0, double d1, double d2, String s, float f, float f1, boolean flag) {
}
public void a(BlockPosition blockposition, String s) {
for (int i = 0; i < this.u.size(); ++i) {
this.u.get(i).a(s, blockposition);
}
}
public void addParticle(EnumParticle enumparticle, double d0, double d1, double d2, double d3, double d4, double d5, int... aint) {
this.a(enumparticle.c(), enumparticle.e(), d0, d1, d2, d3, d4, d5, aint);
}
private void a(int i, boolean flag, double d0, double d1, double d2, double d3, double d4, double d5, int... aint) {
for (int j = 0; j < this.u.size(); ++j) {
this.u.get(j).a(i, flag, d0, d1, d2, d3, d4, d5, aint);
}
}
public boolean strikeLightning(Entity entity) {
this.k.add(entity);
return true;
}
public boolean addEntity(Entity entity) {
// CraftBukkit start - Used for entities other than creatures
return addEntity(entity, SpawnReason.DEFAULT);
}
public boolean addEntity(Entity entity, SpawnReason spawnReason) { // Changed signature, added SpawnReason
org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
if (entity == null) return false;
// ChestMC start.
if (!entity.onSpawn())
return false;
// ChestMC end.
// CraftBukkit end
int i = MathHelper.floor(entity.locX / 16.0D);
int j = MathHelper.floor(entity.locZ / 16.0D);
boolean flag = entity.attachedToPlayer;
if (entity instanceof EntityHuman) {
flag = true;
}
// CraftBukkit start
org.bukkit.event.Cancellable event = null;
if (entity instanceof EntityLiving && !(entity instanceof EntityPlayer)) {
boolean isAnimal = entity instanceof EntityAnimal || entity instanceof EntityWaterAnimal || entity instanceof EntityGolem;
boolean isMonster = entity instanceof EntityMonster || entity instanceof EntityGhast || entity instanceof EntitySlime;
if (spawnReason != SpawnReason.CUSTOM) {
if (isAnimal && !allowAnimals || isMonster && !allowMonsters) {
entity.dead = true;
return false;
}
}
event = CraftEventFactory.callCreatureSpawnEvent((EntityLiving) entity, spawnReason);
} else if (entity instanceof EntityItem) {
event = CraftEventFactory.callItemSpawnEvent((EntityItem) entity);
} else if (entity.getBukkitEntity() instanceof org.bukkit.entity.Projectile) {
// Not all projectiles extend EntityProjectile, so check for Bukkit interface instead
event = CraftEventFactory.callProjectileLaunchEvent(entity);
}
// Spigot start
else if (entity instanceof EntityExperienceOrb) {
EntityExperienceOrb xp = (EntityExperienceOrb) entity;
double radius = spigotConfig.expMerge;
if (radius > 0) {
List entities = this.getEntities(entity, entity.getBoundingBox().grow(radius, radius, radius));
for (Entity e : entities) {
if (e instanceof EntityExperienceOrb) {
EntityExperienceOrb loopItem = (EntityExperienceOrb) e;
if (!loopItem.dead) {
xp.value += loopItem.value;
loopItem.die();
}
}
}
}
} // Spigot end
if (event != null && (event.isCancelled() || entity.dead)) {
entity.dead = true;
return false;
}
// CraftBukkit end
if (!flag && !this.isChunkLoaded(i, j, true)) {
entity.dead = true;
return false;
} else {
if (entity instanceof EntityHuman) {
EntityHuman entityhuman = (EntityHuman) entity;
this.players.add(entityhuman);
this.everyoneSleeping();
}
this.getChunkAt(i, j).a(entity);
this.entityList.add(entity);
this.a(entity);
entity.onPostSpawn(); // ChestMC.
return true;
}
}
protected void a(Entity entity) {
for (IWorldAccess iWorldAccess : this.u) {
iWorldAccess.a(entity);
}
entity.valid = true; // CraftBukkit
}
protected void b(Entity entity) {
for (IWorldAccess iWorldAccess : this.u) {
iWorldAccess.b(entity);
}
entity.valid = false; // CraftBukkit
}
public void kill(Entity entity) {
if (entity.passenger != null) {
entity.passenger.mount(null);
}
if (entity.vehicle != null) {
entity.mount(null);
}
entity.die();
if (entity instanceof EntityHuman) {
this.players.remove(entity);
// Spigot start
for (Object o : worldMaps.c) {
if (o instanceof WorldMap) {
WorldMap map = (WorldMap) o;
map.i.remove(entity);
map.g.removeIf(worldMapHumanTracker -> worldMapHumanTracker.trackee == entity);
}
}
// Spigot end
this.everyoneSleeping();
this.b(entity);
}
}
public void removeEntity(Entity entity) {
org.spigotmc.AsyncCatcher.catchOp("entity remove"); // Spigot
entity.die();
if (entity instanceof EntityHuman) {
this.players.remove(entity);
this.everyoneSleeping();
}
if (!guardEntityList) { // Spigot - It will get removed after the tick if we are ticking
int i = entity.ae;
int j = entity.ag;
if (entity.ad && this.isChunkLoaded(i, j, true)) {
this.getChunkAt(i, j).b(entity);
}
// CraftBukkit start - Decrement loop variable field if we've already ticked this entity
int index = this.entityList.indexOf(entity);
if (index != -1) {
if (index <= this.tickPosition) {
this.tickPosition--;
}
this.entityList.remove(index);
}
// CraftBukkit end
} // Spigot
this.b(entity);
}
public void addIWorldAccess(IWorldAccess iworldaccess) {
this.u.add(iworldaccess);
}
public List getCubes(Entity entity, AxisAlignedBB axisalignedbb) {
ArrayList arraylist = Lists.newArrayList();
int i = MathHelper.floor(axisalignedbb.a);
int j = MathHelper.floor(axisalignedbb.d + 1.0D);
int k = MathHelper.floor(axisalignedbb.b);
int l = MathHelper.floor(axisalignedbb.e + 1.0D);
int i1 = MathHelper.floor(axisalignedbb.c);
int j1 = MathHelper.floor(axisalignedbb.f + 1.0D);
WorldBorder worldborder = this.getWorldBorder();
boolean flag = entity.aT();
boolean flag1 = this.a(worldborder, entity);
IBlockData iblockdata = Blocks.STONE.getBlockData();
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
// Spigot start
int ystart = ((k - 1) < 0) ? 0 : (k - 1);
for (int chunkx = (i >> 4); chunkx <= ((j - 1) >> 4); chunkx++) {
int cx = chunkx << 4;
for (int chunkz = (i1 >> 4); chunkz <= ((j1 - 1) >> 4); chunkz++) {
if (!this.isChunkLoaded(chunkx, chunkz, true)) {
continue;
}
int cz = chunkz << 4;
Chunk chunk = this.getChunkAt(chunkx, chunkz);
// Compute ranges within chunk
int xstart = (i < cx) ? cx : i;
int xend = (j < (cx + 16)) ? j : (cx + 16);
int zstart = (i1 < cz) ? cz : i1;
int zend = (j1 < (cz + 16)) ? j1 : (cz + 16);
// Loop through blocks within chunk
for (int x = xstart; x < xend; x++) {
for (int z = zstart; z < zend; z++) {
for (int y = ystart; y < l; y++) {
BlockPosition blockposition = new BlockPosition(x, y, z);
if (flag && flag1) {
entity.h(false);
} else if (!flag && !flag1) {
entity.h(true);
}
IBlockData block;
if (!this.getWorldBorder().a(blockposition) && flag1) {
block = Blocks.STONE.getBlockData();
} else {
block = chunk.getBlockData(blockposition);
}
if (block != null) {
block.getBlock().a(this, blockposition, block, axisalignedbb, arraylist, entity);
}
}
}
}
}
}
// Spigot end
double d0 = 0.25D;
List list = this.getEntities(entity, axisalignedbb.grow(d0, d0, d0));
for (int j2 = 0; j2 < list.size(); ++j2) {
if (entity.passenger != list && entity.vehicle != list) {
AxisAlignedBB axisalignedbb1 = ((Entity) list.get(j2)).S();
if (axisalignedbb1 != null && axisalignedbb1.b(axisalignedbb)) {
arraylist.add(axisalignedbb1);
}
axisalignedbb1 = entity.j((Entity) list.get(j2));
if (axisalignedbb1 != null && axisalignedbb1.b(axisalignedbb)) {
arraylist.add(axisalignedbb1);
}
}
}
return arraylist;
}
public boolean a(WorldBorder worldborder, Entity entity) {
double d0 = worldborder.b();
double d1 = worldborder.c();
double d2 = worldborder.d();
double d3 = worldborder.e();
if (entity.aT()) {
++d0;
++d1;
--d2;
--d3;
} else {
--d0;
--d1;
++d2;
++d3;
}
return entity.locX > d0 && entity.locX < d2 && entity.locZ > d1 && entity.locZ < d3;
}
public List a(AxisAlignedBB axisalignedbb) {
ArrayList arraylist = Lists.newArrayList();
int i = MathHelper.floor(axisalignedbb.a);
int j = MathHelper.floor(axisalignedbb.d + 1.0D);
int k = MathHelper.floor(axisalignedbb.b);
int l = MathHelper.floor(axisalignedbb.e + 1.0D);
int i1 = MathHelper.floor(axisalignedbb.c);
int j1 = MathHelper.floor(axisalignedbb.f + 1.0D);
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
for (int k1 = i; k1 < j; ++k1) {
for (int l1 = i1; l1 < j1; ++l1) {
if (this.isLoaded(blockposition_mutableblockposition.c(k1, 64, l1))) {
for (int i2 = k - 1; i2 < l; ++i2) {
blockposition_mutableblockposition.c(k1, i2, l1);
IBlockData iblockdata;
if (k1 >= -30000000 && k1 < 30000000 && l1 >= -30000000 && l1 < 30000000) {
iblockdata = this.getType(blockposition_mutableblockposition);
} else {
iblockdata = Blocks.BEDROCK.getBlockData();
}
iblockdata.getBlock().a(this, blockposition_mutableblockposition, iblockdata, axisalignedbb, arraylist, null);
}
}
}
}
return arraylist;
}
public int a(float f) {
float f1 = this.c(f);
float f2 = 1.0F - (MathHelper.cos(f1 * 3.1415927F * 2.0F) * 2.0F + 0.5F);
f2 = MathHelper.a(f2, 0.0F, 1.0F);
f2 = 1.0F - f2;
f2 = (float) ((double) f2 * (1.0D - (double) (this.j(f) * 5.0F) / 16.0D));
f2 = (float) ((double) f2 * (1.0D - (double) (this.h(f) * 5.0F) / 16.0D));
f2 = 1.0F - f2;
return (int) (f2 * 11.0F);
}
public float c(float f) {
return this.worldProvider.a(this.worldData.getDayTime(), f);
}
public float y() {
return WorldProvider.a[this.worldProvider.a(this.worldData.getDayTime())];
}
public float d(float f) {
float f1 = this.c(f);
return f1 * 3.1415927F * 2.0F;
}
public BlockPosition q(BlockPosition blockposition) {
return this.getChunkAtWorldCoords(blockposition).h(blockposition);
}
public BlockPosition r(BlockPosition blockposition) {
Chunk chunk = this.getChunkAtWorldCoords(blockposition);
BlockPosition blockposition1;
BlockPosition blockposition2;
for (blockposition1 = new BlockPosition(blockposition.getX(), chunk.g() + 16, blockposition.getZ()); blockposition1.getY() >= 0; blockposition1 = blockposition2) {
blockposition2 = blockposition1.down();
Material material = chunk.getType(blockposition2).getMaterial();
if (material.isSolid() && material != Material.LEAVES) {
break;
}
}
return blockposition1;
}
public void a(BlockPosition blockposition, Block block, int i) {
}
public void a(BlockPosition blockposition, Block block, int i, int j) {
}
public void b(BlockPosition blockposition, Block block, int i, int j) {
}
public void tickEntities() {
this.methodProfiler.a("entities");
this.methodProfiler.a("global");
int i;
Entity entity;
CrashReport crashreport;
CrashReportSystemDetails crashreportsystemdetails;
for (i = 0; i < this.k.size(); ++i) {
entity = this.k.get(i);
// CraftBukkit start - Fixed an NPE
if (entity == null) {
continue;
}
// CraftBukkit end
try {
++entity.ticksLived;
entity.t_();
} catch (Throwable throwable) {
crashreport = CrashReport.a(throwable, "Ticking entity");
crashreportsystemdetails = crashreport.a("Entity being ticked");
if (entity == null) {
crashreportsystemdetails.a("Entity", "~~NULL~~");
} else {
entity.appendEntityCrashDetails(crashreportsystemdetails);
}
throw new ReportedException(crashreport);
}
if (entity.dead) {
this.k.remove(i--);
}
}
this.methodProfiler.c("remove");
this.entityList.removeAll(this.g);
int j;
int k;
for (i = 0; i < this.g.size(); ++i) {
entity = this.g.get(i);
j = entity.ae;
k = entity.ag;
if (entity.ad && this.isChunkLoaded(j, k, true)) {
this.getChunkAt(j, k).b(entity);
}
}
for (i = 0; i < this.g.size(); ++i) {
this.b(this.g.get(i));
}
this.g.clear();
this.methodProfiler.c("regular");
org.spigotmc.ActivationRange.activateEntities(this); // Spigot
timings.entityTick.startTiming(); // Spigot
guardEntityList = true; // Spigot
// CraftBukkit start - Use field for loop variable
int entitiesThisCycle = 0;
if (tickPosition < 0) tickPosition = 0;
for (entityLimiter.initTick();
entitiesThisCycle < entityList.size() && (entitiesThisCycle % 10 != 0 || entityLimiter.shouldContinue());
tickPosition++, entitiesThisCycle++) {
tickPosition = (tickPosition < entityList.size()) ? tickPosition : 0;
entity = this.entityList.get(this.tickPosition);
// CraftBukkit end
if (entity.vehicle != null) {
if (!entity.vehicle.dead && entity.vehicle.passenger == entity) {
continue;
}
entity.vehicle.passenger = null;
entity.vehicle = null;
}
this.methodProfiler.a("tick");
if (!entity.dead) {
try {
SpigotTimings.tickEntityTimer.startTiming(); // Spigot
this.g(entity);
SpigotTimings.tickEntityTimer.stopTiming(); // Spigot
} catch (Throwable throwable1) {
crashreport = CrashReport.a(throwable1, "Ticking entity");
crashreportsystemdetails = crashreport.a("Entity being ticked");
entity.appendEntityCrashDetails(crashreportsystemdetails);
throw new ReportedException(crashreport);
}
}
this.methodProfiler.b();
this.methodProfiler.a("remove");
if (entity.dead) {
j = entity.ae;
k = entity.ag;
if (entity.ad && this.isChunkLoaded(j, k, true)) {
this.getChunkAt(j, k).b(entity);
}
guardEntityList = false; // Spigot
this.entityList.remove(this.tickPosition--); // CraftBukkit - Use field for loop variable
guardEntityList = true; // Spigot
this.b(entity);
}
this.methodProfiler.b();
}
guardEntityList = false; // Spigot
timings.entityTick.stopTiming(); // Spigot
this.methodProfiler.c("blockEntities");
timings.tileEntityTick.startTiming(); // Spigot
this.M = true;
// CraftBukkit start - From below, clean up tile entities before ticking them
if (!this.c.isEmpty()) {
this.tileEntityList.removeAll(this.c);
this.h.removeAll(this.c);
this.c.clear();
}
// CraftBukkit end
// Spigot start
int tilesThisCycle = 0;
for (tileLimiter.initTick();
tilesThisCycle < tileEntityList.size() && (tilesThisCycle % 10 != 0 || tileLimiter.shouldContinue());
tileTickPosition++, tilesThisCycle++) {
tileTickPosition = (tileTickPosition < tileEntityList.size()) ? tileTickPosition : 0;
TileEntity tileentity = this.tileEntityList.get(tileTickPosition);
// Spigot start
if (tileentity == null) {
getServer().getLogger().severe("Spigot has detected a null entity and has removed it, preventing a crash");
tilesThisCycle--;
this.tileEntityList.remove(tileTickPosition--);
continue;
}
// Spigot end
if (!tileentity.x() && tileentity.t()) {
BlockPosition blockposition = tileentity.getPosition();
if (this.isLoaded(blockposition) && this.N.a(blockposition)) {
try {
tileentity.tickTimer.startTiming(); // Spigot
((IUpdatePlayerListBox) tileentity).c();
} catch (Throwable throwable2) {
CrashReport crashreport1 = CrashReport.a(throwable2, "Ticking block entity");
CrashReportSystemDetails crashreportsystemdetails1 = crashreport1.a("Block entity being ticked");
tileentity.a(crashreportsystemdetails1);
throw new ReportedException(crashreport1);
}
// Spigot start
finally {
tileentity.tickTimer.stopTiming();
}
// Spigot end
}
}
if (tileentity.x()) {
tilesThisCycle--;
this.tileEntityList.remove(tileTickPosition--);
this.h.remove(tileentity);
if (this.isLoaded(tileentity.getPosition())) {
this.getChunkAtWorldCoords(tileentity.getPosition()).e(tileentity.getPosition());
}
}
}
timings.tileEntityTick.stopTiming(); // Spigot
timings.tileEntityPending.startTiming(); // Spigot
this.M = false;
/* CraftBukkit start - Moved up
if (!this.c.isEmpty()) {
this.tileEntityList.removeAll(this.c);
this.h.removeAll(this.c);
this.c.clear();
}
// CraftBukkit end */
this.methodProfiler.c("pendingBlockEntities");
if (!this.b.isEmpty()) {
for (TileEntity tileentity1 : this.b) {
if (!tileentity1.x()) {
/* CraftBukkit start - Order matters, moved down
if (!this.h.contains(tileentity1)) {
this.a(tileentity1);
}
// CraftBukkit end */
if (this.isLoaded(tileentity1.getPosition())) {
this.getChunkAtWorldCoords(tileentity1.getPosition()).a(tileentity1.getPosition(), tileentity1);
}
this.notify(tileentity1.getPosition());
}
}
this.b.clear();
}
timings.tileEntityPending.stopTiming(); // Spigot
this.methodProfiler.b();
this.methodProfiler.b();
}
public boolean a(TileEntity tileentity) {
boolean flag = this.h.add(tileentity);
if (flag && tileentity instanceof IUpdatePlayerListBox) {
this.tileEntityList.add(tileentity);
}
return flag;
}
public void a(Collection collection) {
if (this.M) {
this.b.addAll(collection);
} else {
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
TileEntity tileentity = (TileEntity) iterator.next();
this.h.add(tileentity);
if (tileentity instanceof IUpdatePlayerListBox) {
this.tileEntityList.add(tileentity);
}
}
}
}
public void g(Entity entity) {
this.entityJoinedWorld(entity, true);
}
public void entityJoinedWorld(Entity entity, boolean flag) {
int i = MathHelper.floor(entity.locX);
int j = MathHelper.floor(entity.locZ);
byte b0 = 32;
// Spigot start
if (!org.spigotmc.ActivationRange.checkIfActive(entity)) {
entity.ticksLived++;
entity.inactiveTick();
} else {
entity.tickTimer.startTiming(); // Spigot
// CraftBukkit end
entity.P = entity.locX;
entity.Q = entity.locY;
entity.R = entity.locZ;
entity.lastYaw = entity.yaw;
entity.lastPitch = entity.pitch;
if (flag && entity.ad) {
++entity.ticksLived;
if (entity.vehicle != null) {
entity.ak();
} else {
entity.t_();
}
}
this.methodProfiler.a("chunkCheck");
if (Double.isNaN(entity.locX) || Double.isInfinite(entity.locX)) {
entity.locX = entity.P;
}
if (Double.isNaN(entity.locY) || Double.isInfinite(entity.locY)) {
entity.locY = entity.Q;
}
if (Double.isNaN(entity.locZ) || Double.isInfinite(entity.locZ)) {
entity.locZ = entity.R;
}
if (Double.isNaN(entity.pitch) || Double.isInfinite(entity.pitch)) {
entity.pitch = entity.lastPitch;
}
if (Double.isNaN(entity.yaw) || Double.isInfinite(entity.yaw)) {
entity.yaw = entity.lastYaw;
}
int k = MathHelper.floor(entity.locX / 16.0D);
int l = MathHelper.floor(entity.locY / 16.0D);
int i1 = MathHelper.floor(entity.locZ / 16.0D);
if (!entity.ad || entity.ae != k || entity.af != l || entity.ag != i1) {
if (entity.ad && this.isChunkLoaded(entity.ae, entity.ag, true)) {
this.getChunkAt(entity.ae, entity.ag).a(entity, entity.af);
}
if (this.isChunkLoaded(k, i1, true)) {
entity.ad = true;
this.getChunkAt(k, i1).a(entity);
} else {
entity.ad = false;
}
}
this.methodProfiler.b();
if (flag && entity.ad && entity.passenger != null) {
if (!entity.passenger.dead && entity.passenger.vehicle == entity) {
this.g(entity.passenger);
} else {
entity.passenger.vehicle = null;
entity.passenger = null;
}
}
entity.tickTimer.stopTiming(); // Spigot
}
}
public boolean b(AxisAlignedBB axisalignedbb) {
return this.a(axisalignedbb, (Entity) null);
}
public boolean a(AxisAlignedBB axisalignedbb, Entity entity) {
List list = this.getEntities(null, axisalignedbb);
for (int i = 0; i < list.size(); ++i) {
Entity entity1 = (Entity) list.get(i);
if (!entity1.dead && entity1.k && entity1 != entity && (entity == null || entity.vehicle != entity1 && entity.passenger != entity1)) {
return false;
}
}
return true;
}
public boolean c(AxisAlignedBB axisalignedbb) {
int i = MathHelper.floor(axisalignedbb.a);
int j = MathHelper.floor(axisalignedbb.d);
int k = MathHelper.floor(axisalignedbb.b);
int l = MathHelper.floor(axisalignedbb.e);
int i1 = MathHelper.floor(axisalignedbb.c);
int j1 = MathHelper.floor(axisalignedbb.f);
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
for (int k1 = i; k1 <= j; ++k1) {
for (int l1 = k; l1 <= l; ++l1) {
for (int i2 = i1; i2 <= j1; ++i2) {
Block block = this.getType(blockposition_mutableblockposition.c(k1, l1, i2)).getBlock();
if (block.getMaterial() != Material.AIR) {
return true;
}
}
}
}
return false;
}
public boolean containsLiquid(AxisAlignedBB axisalignedbb) {
int i = MathHelper.floor(axisalignedbb.a);
int j = MathHelper.floor(axisalignedbb.d);
int k = MathHelper.floor(axisalignedbb.b);
int l = MathHelper.floor(axisalignedbb.e);
int i1 = MathHelper.floor(axisalignedbb.c);
int j1 = MathHelper.floor(axisalignedbb.f);
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
for (int k1 = i; k1 <= j; ++k1) {
for (int l1 = k; l1 <= l; ++l1) {
for (int i2 = i1; i2 <= j1; ++i2) {
Block block = this.getType(blockposition_mutableblockposition.c(k1, l1, i2)).getBlock();
if (block.getMaterial().isLiquid()) {
return true;
}
}
}
}
return false;
}
public boolean e(AxisAlignedBB axisalignedbb) {
int i = MathHelper.floor(axisalignedbb.a);
int j = MathHelper.floor(axisalignedbb.d + 1.0D);
int k = MathHelper.floor(axisalignedbb.b);
int l = MathHelper.floor(axisalignedbb.e + 1.0D);
int i1 = MathHelper.floor(axisalignedbb.c);
int j1 = MathHelper.floor(axisalignedbb.f + 1.0D);
if (this.isAreaLoaded(i, k, i1, j, l, j1, true)) {
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
for (int k1 = i; k1 < j; ++k1) {
for (int l1 = k; l1 < l; ++l1) {
for (int i2 = i1; i2 < j1; ++i2) {
Block block = this.getType(blockposition_mutableblockposition.c(k1, l1, i2)).getBlock();
if (block == Blocks.FIRE || block == Blocks.FLOWING_LAVA || block == Blocks.LAVA) {
return true;
}
}
}
}
}
return false;
}
public boolean a(AxisAlignedBB axisalignedbb, Material material, Entity entity) {
int i = MathHelper.floor(axisalignedbb.a);
int j = MathHelper.floor(axisalignedbb.d + 1.0D);
int k = MathHelper.floor(axisalignedbb.b);
int l = MathHelper.floor(axisalignedbb.e + 1.0D);
int i1 = MathHelper.floor(axisalignedbb.c);
int j1 = MathHelper.floor(axisalignedbb.f + 1.0D);
if (!this.isAreaLoaded(i, k, i1, j, l, j1, true)) {
return false;
} else {
boolean flag = false;
Vec3D vec3d = new Vec3D(0.0D, 0.0D, 0.0D);
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
for (int k1 = i; k1 < j; ++k1) {
for (int l1 = k; l1 < l; ++l1) {
for (int i2 = i1; i2 < j1; ++i2) {
blockposition_mutableblockposition.c(k1, l1, i2);
IBlockData iblockdata = this.getType(blockposition_mutableblockposition);
Block block = iblockdata.getBlock();
if (block.getMaterial() == material) {
double d0 = (float) (l1 + 1) - BlockFluids.b(iblockdata.get(BlockFluids.LEVEL).intValue());
if ((double) l >= d0) {
flag = true;
vec3d = block.a(this, blockposition_mutableblockposition, entity, vec3d);
}
}
}
}
}
if (vec3d.b() > 0.0D && entity.aL()) {
vec3d = vec3d.a();
double d1 = 0.014D;
entity.motX += vec3d.a * d1;
entity.motY += vec3d.b * d1;
entity.motZ += vec3d.c * d1;
}
return flag;
}
}
public boolean a(AxisAlignedBB axisalignedbb, Material material) {
int i = MathHelper.floor(axisalignedbb.a);
int j = MathHelper.floor(axisalignedbb.d + 1.0D);
int k = MathHelper.floor(axisalignedbb.b);
int l = MathHelper.floor(axisalignedbb.e + 1.0D);
int i1 = MathHelper.floor(axisalignedbb.c);
int j1 = MathHelper.floor(axisalignedbb.f + 1.0D);
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
for (int k1 = i; k1 < j; ++k1) {
for (int l1 = k; l1 < l; ++l1) {
for (int i2 = i1; i2 < j1; ++i2) {
if (this.getType(blockposition_mutableblockposition.c(k1, l1, i2)).getBlock().getMaterial() == material) {
return true;
}
}
}
}
return false;
}
public boolean b(AxisAlignedBB axisalignedbb, Material material) {
int i = MathHelper.floor(axisalignedbb.a);
int j = MathHelper.floor(axisalignedbb.d + 1.0D);
int k = MathHelper.floor(axisalignedbb.b);
int l = MathHelper.floor(axisalignedbb.e + 1.0D);
int i1 = MathHelper.floor(axisalignedbb.c);
int j1 = MathHelper.floor(axisalignedbb.f + 1.0D);
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
for (int k1 = i; k1 < j; ++k1) {
for (int l1 = k; l1 < l; ++l1) {
for (int i2 = i1; i2 < j1; ++i2) {
IBlockData iblockdata = this.getType(blockposition_mutableblockposition.c(k1, l1, i2));
Block block = iblockdata.getBlock();
if (block.getMaterial() == material) {
int j2 = iblockdata.get(BlockFluids.LEVEL).intValue();
double d0 = l1 + 1;
if (j2 < 8) {
d0 = (double) (l1 + 1) - (double) j2 / 8.0D;
}
if (d0 >= axisalignedbb.b) {
return true;
}
}
}
}
}
return false;
}
public Explosion explode(Entity entity, double d0, double d1, double d2, float f, boolean flag) {
return this.createExplosion(entity, d0, d1, d2, f, false, flag);
}
public Explosion createExplosion(Entity entity, double d0, double d1, double d2, float f, boolean flag, boolean flag1) {
Explosion explosion = new Explosion(this, entity, d0, d1, d2, f, flag, flag1);
explosion.a();
explosion.a(true);
return explosion;
}
public float a(Vec3D vec3d, AxisAlignedBB axisalignedbb) {
double d0 = 1.0D / ((axisalignedbb.d - axisalignedbb.a) * 2.0D + 1.0D);
double d1 = 1.0D / ((axisalignedbb.e - axisalignedbb.b) * 2.0D + 1.0D);
double d2 = 1.0D / ((axisalignedbb.f - axisalignedbb.c) * 2.0D + 1.0D);
double d3 = (1.0D - Math.floor(1.0D / d0) * d0) / 2.0D;
double d4 = (1.0D - Math.floor(1.0D / d2) * d2) / 2.0D;
if (d0 >= 0.0D && d1 >= 0.0D && d2 >= 0.0D) {
int i = 0;
int j = 0;
for (float f = 0.0F; f <= 1.0F; f = (float) ((double) f + d0)) {
for (float f1 = 0.0F; f1 <= 1.0F; f1 = (float) ((double) f1 + d1)) {
for (float f2 = 0.0F; f2 <= 1.0F; f2 = (float) ((double) f2 + d2)) {
double d5 = axisalignedbb.a + (axisalignedbb.d - axisalignedbb.a) * (double) f;
double d6 = axisalignedbb.b + (axisalignedbb.e - axisalignedbb.b) * (double) f1;
double d7 = axisalignedbb.c + (axisalignedbb.f - axisalignedbb.c) * (double) f2;
if (this.rayTrace(new Vec3D(d5 + d3, d6, d7 + d4), vec3d) == null) {
++i;
}
++j;
}
}
}
return (float) i / (float) j;
} else {
return 0.0F;
}
}
public boolean douseFire(EntityHuman entityhuman, BlockPosition blockposition, EnumDirection enumdirection) {
blockposition = blockposition.shift(enumdirection);
if (this.getType(blockposition).getBlock() == Blocks.FIRE) {
this.a(entityhuman, 1004, blockposition, 0);
this.setAir(blockposition);
return true;
} else {
return false;
}
}
public TileEntity getTileEntity(BlockPosition blockposition) {
if (!this.isValidLocation(blockposition)) {
return null;
} else {
// CraftBukkit start
if (capturedTileEntities.containsKey(blockposition)) {
return capturedTileEntities.get(blockposition);
}
// CraftBukkit end
TileEntity tileentity = null;
int i;
TileEntity tileentity1;
if (this.M) {
for (i = 0; i < this.b.size(); ++i) {
tileentity1 = this.b.get(i);
if (!tileentity1.x() && tileentity1.getPosition().equals(blockposition)) {
tileentity = tileentity1;
break;
}
}
}
if (tileentity == null) {
tileentity = this.getChunkAtWorldCoords(blockposition).a(blockposition, Chunk.EnumTileEntityState.IMMEDIATE);
}
if (tileentity == null) {
for (i = 0; i < this.b.size(); ++i) {
tileentity1 = this.b.get(i);
if (!tileentity1.x() && tileentity1.getPosition().equals(blockposition)) {
tileentity = tileentity1;
break;
}
}
}
return tileentity;
}
}
public void setTileEntity(BlockPosition blockposition, TileEntity tileentity) {
if (tileentity != null && !tileentity.x()) {
// CraftBukkit start
if (captureBlockStates) {
tileentity.a(this);
tileentity.a(blockposition);
capturedTileEntities.put(blockposition, tileentity);
return;
}
// CraftBukkit end
if (this.M) {
tileentity.a(blockposition);
Iterator iterator = this.b.iterator();
while (iterator.hasNext()) {
TileEntity tileentity1 = (TileEntity) iterator.next();
if (tileentity1.getPosition().equals(blockposition)) {
tileentity1.y();
iterator.remove();
}
}
tileentity.a(this); // Spigot - No null worlds
this.b.add(tileentity);
} else {
this.a(tileentity);
this.getChunkAtWorldCoords(blockposition).a(blockposition, tileentity);
}
}
}
public void t(BlockPosition blockposition) {
TileEntity tileentity = this.getTileEntity(blockposition);
if (tileentity != null && this.M) {
tileentity.y();
this.b.remove(tileentity);
} else {
if (tileentity != null) {
this.b.remove(tileentity);
this.h.remove(tileentity);
this.tileEntityList.remove(tileentity);
}
this.getChunkAtWorldCoords(blockposition).e(blockposition);
}
}
public void b(TileEntity tileentity) {
this.c.add(tileentity);
}
public boolean u(BlockPosition blockposition) {
IBlockData iblockdata = this.getType(blockposition);
AxisAlignedBB axisalignedbb = iblockdata.getBlock().a(this, blockposition, iblockdata);
return axisalignedbb != null && axisalignedbb.a() >= 1.0D;
}
public boolean d(BlockPosition blockposition, boolean flag) {
if (!this.isValidLocation(blockposition)) {
return flag;
} else {
Chunk chunk = this.chunkProvider.getChunkAt(blockposition);
if (chunk.isEmpty()) {
return flag;
} else {
Block block = this.getType(blockposition).getBlock();
return block.getMaterial().k() && block.d();
}
}
}
public void B() {
int i = this.a(1.0F);
if (i != this.I) {
this.I = i;
}
}
public void setSpawnFlags(boolean flag, boolean flag1) {
this.allowMonsters = flag;
this.allowAnimals = flag1;
}
public void doTick() {
this.p();
}
protected void C() {
if (this.worldData.hasStorm()) {
this.p = 1.0F;
if (this.worldData.isThundering()) {
this.r = 1.0F;
}
}
}
protected void p() {
if (!this.worldProvider.o()) {
if (!this.isClientSide) {
int i = this.worldData.A();
if (i > 0) {
--i;
this.worldData.i(i);
this.worldData.setThunderDuration(this.worldData.isThundering() ? 1 : 2);
this.worldData.setWeatherDuration(this.worldData.hasStorm() ? 1 : 2);
}
int j = this.worldData.getThunderDuration();
if (j <= 0) {
if (this.worldData.isThundering()) {
this.worldData.setThunderDuration(this.random.nextInt(12000) + 3600);
} else {
this.worldData.setThunderDuration(this.random.nextInt(168000) + 12000);
}
} else {
--j;
this.worldData.setThunderDuration(j);
if (j <= 0) {
this.worldData.setThundering(!this.worldData.isThundering());
}
}
this.q = this.r;
if (this.worldData.isThundering()) {
this.r = (float) ((double) this.r + 0.01D);
} else {
this.r = (float) ((double) this.r - 0.01D);
}
this.r = MathHelper.a(this.r, 0.0F, 1.0F);
int k = this.worldData.getWeatherDuration();
if (k <= 0) {
if (this.worldData.hasStorm()) {
this.worldData.setWeatherDuration(this.random.nextInt(12000) + 12000);
} else {
this.worldData.setWeatherDuration(this.random.nextInt(168000) + 12000);
}
} else {
--k;
this.worldData.setWeatherDuration(k);
if (k <= 0) {
this.worldData.setStorm(!this.worldData.hasStorm());
}
}
this.o = this.p;
if (this.worldData.hasStorm()) {
this.p = (float) ((double) this.p + 0.01D);
} else {
this.p = (float) ((double) this.p - 0.01D);
}
this.p = MathHelper.a(this.p, 0.0F, 1.0F);
// CraftBukkit start
for (int idx = 0; idx < this.players.size(); ++idx) {
if (this.players.get(idx).world == this) {
((EntityPlayer) this.players.get(idx)).tickWeather();
}
}
// CraftBukkit end
}
}
}
protected void D() {
// this.chunkTickList.clear(); // CraftBukkit - removed
this.methodProfiler.a("buildList");
int i;
EntityHuman entityhuman;
int j;
int k;
int l;
// Spigot start
int optimalChunks = spigotConfig.chunksPerTick;
// Quick conditions to allow us to exist early
if (optimalChunks > 0) {
// Keep chunks with growth inside of the optimal chunk range
int chunksPerPlayer = Math.min(200, Math.max(1, (int) (((optimalChunks - players.size()) / (double) players.size()) + 0.5)));
int randRange = 3 + chunksPerPlayer / 30;
// Limit to normal tick radius - including view distance
randRange = (randRange > chunkTickRadius) ? chunkTickRadius : randRange;
// odds of growth happening vs growth happening in vanilla
this.growthOdds = this.modifiedOdds = Math.max(35, Math.min(100, ((chunksPerPlayer + 1) * 100F) / 15F));
// Spigot end
for (i = 0; i < this.players.size(); ++i) {
entityhuman = this.players.get(i);
j = MathHelper.floor(entityhuman.locX / 16.0D);
k = MathHelper.floor(entityhuman.locZ / 16.0D);
l = this.q();
// Spigot start - Always update the chunk the player is on
long key = chunkToKey(j, k);
int existingPlayers = Math.max(0, chunkTickList.get(key)); // filter out -1
chunkTickList.put(key, (short) (existingPlayers + 1));
// Check and see if we update the chunks surrounding the player this tick
for (int chunk = 0; chunk < chunksPerPlayer; chunk++) {
int dx = (random.nextBoolean() ? 1 : -1) * random.nextInt(randRange);
int dz = (random.nextBoolean() ? 1 : -1) * random.nextInt(randRange);
long hash = chunkToKey(dx + j, dz + k);
if (!chunkTickList.contains(hash) && this.chunkProvider.isChunkLoaded(dx + j, dz + k)) {
chunkTickList.put(hash, (short) -1); // no players
}
}
}
// Spigot End
}
this.methodProfiler.b();
if (this.L > 0) {
--this.L;
}
this.methodProfiler.a("playerCheckLight");
if (spigotConfig.randomLightUpdates && !this.players.isEmpty()) { // Spigot
i = this.random.nextInt(this.players.size());
entityhuman = this.players.get(i);
j = MathHelper.floor(entityhuman.locX) + this.random.nextInt(11) - 5;
k = MathHelper.floor(entityhuman.locY) + this.random.nextInt(11) - 5;
l = MathHelper.floor(entityhuman.locZ) + this.random.nextInt(11) - 5;
this.x(new BlockPosition(j, k, l));
}
this.methodProfiler.b();
}
protected abstract int q();
protected void a(int i, int j, Chunk chunk) {
this.methodProfiler.c("moodSound");
if (this.L == 0 && !this.isClientSide) {
this.m = this.m * 3 + 1013904223;
int k = this.m >> 2;
int l = k & 15;
int i1 = k >> 8 & 15;
int j1 = k >> 16 & 255;
BlockPosition blockposition = new BlockPosition(l, j1, i1);
Block block = chunk.getType(blockposition);
l += i;
i1 += j;
if (block.getMaterial() == Material.AIR && this.k(blockposition) <= this.random.nextInt(8) && this.b(EnumSkyBlock.SKY, blockposition) <= 0) {
EntityHuman entityhuman = this.findNearbyPlayer((double) l + 0.5D, (double) j1 + 0.5D, (double) i1 + 0.5D, 8.0D);
if (entityhuman != null && entityhuman.e((double) l + 0.5D, (double) j1 + 0.5D, (double) i1 + 0.5D) > 4.0D) {
this.makeSound((double) l + 0.5D, (double) j1 + 0.5D, (double) i1 + 0.5D, "ambient.cave.cave", 0.7F, 0.8F + this.random.nextFloat() * 0.2F);
this.L = this.random.nextInt(12000) + 6000;
}
}
}
this.methodProfiler.c("checkLight");
chunk.m();
}
protected void h() {
this.D();
}
public void a(Block block, BlockPosition blockposition, Random random) {
this.e = true;
block.b(this, blockposition, this.getType(blockposition), random);
this.e = false;
}
public boolean v(BlockPosition blockposition) {
return this.e(blockposition, false);
}
public boolean w(BlockPosition blockposition) {
return this.e(blockposition, true);
}
public boolean e(BlockPosition blockposition, boolean flag) {
BiomeBase biomebase = this.getBiome(blockposition);
float f = biomebase.a(blockposition);
if (f > 0.15F) {
return false;
} else {
if (blockposition.getY() >= 0 && blockposition.getY() < 256 && this.b(EnumSkyBlock.BLOCK, blockposition) < 10) {
IBlockData iblockdata = this.getType(blockposition);
Block block = iblockdata.getBlock();
if ((block == Blocks.WATER || block == Blocks.FLOWING_WATER) && iblockdata.get(BlockFluids.LEVEL).intValue() == 0) {
if (!flag) {
return true;
}
boolean flag1 = this.F(blockposition.west()) && this.F(blockposition.east()) && this.F(blockposition.north()) && this.F(blockposition.south());
return !flag1;
}
}
return false;
}
}
private boolean F(BlockPosition blockposition) {
return this.getType(blockposition).getBlock().getMaterial() == Material.WATER;
}
public boolean f(BlockPosition blockposition, boolean flag) {
BiomeBase biomebase = this.getBiome(blockposition);
float f = biomebase.a(blockposition);
if (f > 0.15F) {
return false;
} else if (!flag) {
return true;
} else {
if (blockposition.getY() >= 0 && blockposition.getY() < 256 && this.b(EnumSkyBlock.BLOCK, blockposition) < 10) {
Block block = this.getType(blockposition).getBlock();
return block.getMaterial() == Material.AIR && Blocks.SNOW_LAYER.canPlace(this, blockposition);
}
return false;
}
}
public boolean x(BlockPosition blockposition) {
boolean flag = false;
if (!this.worldProvider.o()) {
flag |= this.c(EnumSkyBlock.SKY, blockposition);
}
flag |= this.c(EnumSkyBlock.BLOCK, blockposition);
return flag;
}
private int a(BlockPosition blockposition, EnumSkyBlock enumskyblock) {
if (enumskyblock == EnumSkyBlock.SKY && this.i(blockposition)) {
return 15;
} else {
Block block = this.getType(blockposition).getBlock();
int i = enumskyblock == EnumSkyBlock.SKY ? 0 : block.r();
int j = block.p();
if (j >= 15 && block.r() > 0) {
j = 1;
}
if (j < 1) {
j = 1;
}
if (j >= 15) {
return 0;
} else if (i >= 14) {
return i;
} else {
EnumDirection[] aenumdirection = EnumDirection.values();
int k = aenumdirection.length;
for (int l = 0; l < k; ++l) {
EnumDirection enumdirection = aenumdirection[l];
BlockPosition blockposition1 = blockposition.shift(enumdirection);
int i1 = this.b(enumskyblock, blockposition1) - j;
if (i1 > i) {
i = i1;
}
if (i >= 14) {
return i;
}
}
return i;
}
}
}
public boolean c(EnumSkyBlock enumskyblock, BlockPosition blockposition) {
// CraftBukkit start - Use neighbor cache instead of looking up
Chunk chunk = this.getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4);
if (chunk == null || !chunk.areNeighborsLoaded(1) /*!this.areChunksLoaded(blockposition, 17, false)*/) {
// CraftBukkit end
return false;
} else {
int i = 0;
int j = 0;
this.methodProfiler.a("getBrightness");
int k = this.b(enumskyblock, blockposition);
int l = this.a(blockposition, enumskyblock);
int i1 = blockposition.getX();
int j1 = blockposition.getY();
int k1 = blockposition.getZ();
int l1;
int i2;
int j2;
int k2;
int l2;
int i3;
int j3;
int k3;
if (l > k) {
this.H[j++] = 133152;
} else if (l < k) {
this.H[j++] = 133152 | k << 18;
while (i < j) {
l1 = this.H[i++];
i2 = (l1 & 63) - 32 + i1;
j2 = (l1 >> 6 & 63) - 32 + j1;
k2 = (l1 >> 12 & 63) - 32 + k1;
int l3 = l1 >> 18 & 15;
BlockPosition blockposition1 = new BlockPosition(i2, j2, k2);
l2 = this.b(enumskyblock, blockposition1);
if (l2 == l3) {
this.a(enumskyblock, blockposition1, 0);
if (l3 > 0) {
i3 = MathHelper.a(i2 - i1);
j3 = MathHelper.a(j2 - j1);
k3 = MathHelper.a(k2 - k1);
if (i3 + j3 + k3 < 17) {
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
EnumDirection[] aenumdirection = EnumDirection.values();
int i4 = aenumdirection.length;
for (int j4 = 0; j4 < i4; ++j4) {
EnumDirection enumdirection = aenumdirection[j4];
int k4 = i2 + enumdirection.getAdjacentX();
int l4 = j2 + enumdirection.getAdjacentY();
int i5 = k2 + enumdirection.getAdjacentZ();
blockposition_mutableblockposition.c(k4, l4, i5);
int j5 = Math.max(1, this.getType(blockposition_mutableblockposition).getBlock().p());
l2 = this.b(enumskyblock, blockposition_mutableblockposition);
if (l2 == l3 - j5 && j < this.H.length) {
this.H[j++] = k4 - i1 + 32 | l4 - j1 + 32 << 6 | i5 - k1 + 32 << 12 | l3 - j5 << 18;
}
}
}
}
}
}
i = 0;
}
this.methodProfiler.b();
this.methodProfiler.a("checkedPosition < toCheckCount");
while (i < j) {
l1 = this.H[i++];
i2 = (l1 & 63) - 32 + i1;
j2 = (l1 >> 6 & 63) - 32 + j1;
k2 = (l1 >> 12 & 63) - 32 + k1;
BlockPosition blockposition2 = new BlockPosition(i2, j2, k2);
int k5 = this.b(enumskyblock, blockposition2);
l2 = this.a(blockposition2, enumskyblock);
if (l2 != k5) {
this.a(enumskyblock, blockposition2, l2);
if (l2 > k5) {
i3 = Math.abs(i2 - i1);
j3 = Math.abs(j2 - j1);
k3 = Math.abs(k2 - k1);
boolean flag = j < this.H.length - 6;
if (i3 + j3 + k3 < 17 && flag) {
if (this.b(enumskyblock, blockposition2.west()) < l2) {
this.H[j++] = i2 - 1 - i1 + 32 + (j2 - j1 + 32 << 6) + (k2 - k1 + 32 << 12);
}
if (this.b(enumskyblock, blockposition2.east()) < l2) {
this.H[j++] = i2 + 1 - i1 + 32 + (j2 - j1 + 32 << 6) + (k2 - k1 + 32 << 12);
}
if (this.b(enumskyblock, blockposition2.down()) < l2) {
this.H[j++] = i2 - i1 + 32 + (j2 - 1 - j1 + 32 << 6) + (k2 - k1 + 32 << 12);
}
if (this.b(enumskyblock, blockposition2.up()) < l2) {
this.H[j++] = i2 - i1 + 32 + (j2 + 1 - j1 + 32 << 6) + (k2 - k1 + 32 << 12);
}
if (this.b(enumskyblock, blockposition2.north()) < l2) {
this.H[j++] = i2 - i1 + 32 + (j2 - j1 + 32 << 6) + (k2 - 1 - k1 + 32 << 12);
}
if (this.b(enumskyblock, blockposition2.south()) < l2) {
this.H[j++] = i2 - i1 + 32 + (j2 - j1 + 32 << 6) + (k2 + 1 - k1 + 32 << 12);
}
}
}
}
}
this.methodProfiler.b();
return true;
}
}
public boolean a(boolean flag) {
return false;
}
public List a(Chunk chunk, boolean flag) {
return null;
}
public List a(StructureBoundingBox structureboundingbox, boolean flag) {
return null;
}
public List getEntities(Entity entity, AxisAlignedBB axisalignedbb) {
return this.a(entity, axisalignedbb, IEntitySelector.d);
}
public List a(Entity entity, AxisAlignedBB axisalignedbb, Predicate super Entity> predicate) {
ArrayList arraylist = Lists.newArrayList();
int i = MathHelper.floor((axisalignedbb.a - 2.0D) / 16.0D);
int j = MathHelper.floor((axisalignedbb.d + 2.0D) / 16.0D);
int k = MathHelper.floor((axisalignedbb.c - 2.0D) / 16.0D);
int l = MathHelper.floor((axisalignedbb.f + 2.0D) / 16.0D);
for (int i1 = i; i1 <= j; ++i1) {
for (int j1 = k; j1 <= l; ++j1) {
if (this.isChunkLoaded(i1, j1, true)) {
this.getChunkAt(i1, j1).a(entity, axisalignedbb, arraylist, predicate);
}
}
}
return arraylist;
}
public List a(Class extends T> oclass, Predicate super T> predicate) {
ArrayList arraylist = Lists.newArrayList();
Iterator iterator = this.entityList.iterator();
while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next();
if (oclass.isAssignableFrom(entity.getClass()) && predicate.apply((T) entity)) { // CraftBukkit - fix decompile error
arraylist.add(entity);
}
}
return arraylist;
}
public List b(Class extends T> oclass, Predicate super T> predicate) {
ArrayList arraylist = Lists.newArrayList();
Iterator iterator = this.players.iterator();
while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next();
if (oclass.isAssignableFrom(entity.getClass()) && predicate.apply((T) entity)) { // CraftBukkit - fix decompile error
arraylist.add(entity);
}
}
return arraylist;
}
public List a(Class extends T> oclass, AxisAlignedBB axisalignedbb) {
return this.a(oclass, axisalignedbb, IEntitySelector.d);
}
public List a(Class extends T> oclass, AxisAlignedBB axisalignedbb, Predicate super T> predicate) {
int i = MathHelper.floor((axisalignedbb.a - 2.0D) / 16.0D);
int j = MathHelper.floor((axisalignedbb.d + 2.0D) / 16.0D);
int k = MathHelper.floor((axisalignedbb.c - 2.0D) / 16.0D);
int l = MathHelper.floor((axisalignedbb.f + 2.0D) / 16.0D);
ArrayList arraylist = Lists.newArrayList();
for (int i1 = i; i1 <= j; ++i1) {
for (int j1 = k; j1 <= l; ++j1) {
if (this.isChunkLoaded(i1, j1, true)) {
this.getChunkAt(i1, j1).a(oclass, axisalignedbb, arraylist, predicate);
}
}
}
return arraylist;
}
public T a(Class extends T> oclass, AxisAlignedBB axisalignedbb, T t0) {
List list = this.a(oclass, axisalignedbb);
Entity entity = null;
double d0 = Double.MAX_VALUE;
for (int i = 0; i < list.size(); ++i) {
Entity entity1 = (Entity) list.get(i);
if (entity1 != t0 && IEntitySelector.d.apply(entity1)) {
double d1 = t0.h(entity1);
if (d1 <= d0) {
entity = entity1;
d0 = d1;
}
}
}
return (T) entity; // CraftBukkit fix decompile error
}
public Entity a(int i) {
return this.entitiesById.get(i);
}
public void b(BlockPosition blockposition, TileEntity tileentity) {
if (this.isLoaded(blockposition)) {
this.getChunkAtWorldCoords(blockposition).e();
}
}
public int a(Class> oclass) {
int i = 0;
Iterator iterator = this.entityList.iterator();
while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next();
// CraftBukkit start - Split out persistent check, don't apply it to special persistent mobs
if (entity instanceof EntityInsentient) {
EntityInsentient entityinsentient = (EntityInsentient) entity;
if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) {
continue;
}
}
if (oclass.isAssignableFrom(entity.getClass())) {
// if ((!(entity instanceof EntityInsentient) || !((EntityInsentient) entity).isPersistent()) && oclass.isAssignableFrom(entity.getClass())) {
// CraftBukkit end
++i;
}
}
return i;
}
public void b(Collection collection) {
org.spigotmc.AsyncCatcher.catchOp("entity world add"); // Spigot
// CraftBukkit start
// this.entityList.addAll(collection);
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next();
if (entity == null) {
continue;
}
this.entityList.add(entity);
// CraftBukkit end
this.a(entity);
}
}
public void c(Collection collection) {
this.g.addAll(collection);
}
public boolean a(Block block, BlockPosition blockposition, boolean flag, EnumDirection enumdirection, Entity entity, ItemStack itemstack) {
Block block1 = this.getType(blockposition).getBlock();
AxisAlignedBB axisalignedbb = flag ? null : block.a(this, blockposition, block.getBlockData());
// CraftBukkit start - store default return
boolean defaultReturn = (axisalignedbb == null || this.a(axisalignedbb, entity)) && (block1.getMaterial() == Material.ORIENTABLE && block == Blocks.ANVIL || block1.getMaterial().isReplaceable() && block.canPlace(this, blockposition, enumdirection, itemstack));
BlockCanBuildEvent event = new BlockCanBuildEvent(this.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftMagicNumbers.getId(block), defaultReturn);
this.getServer().getPluginManager().callEvent(event);
return event.isBuildable();
// CraftBukkit end
}
public int F() {
return this.a;
}
public void b(int i) {
this.a = i;
}
public int getBlockPower(BlockPosition blockposition, EnumDirection enumdirection) {
IBlockData iblockdata = this.getType(blockposition);
return iblockdata.getBlock().b(this, blockposition, iblockdata, enumdirection);
}
public WorldType G() {
return this.worldData.getType();
}
public int getBlockPower(BlockPosition blockposition) {
byte b0 = 0;
int i = Math.max(b0, this.getBlockPower(blockposition.down(), EnumDirection.DOWN));
if (i >= 15) {
return i;
} else {
i = Math.max(i, this.getBlockPower(blockposition.up(), EnumDirection.UP));
if (i >= 15) {
return i;
} else {
i = Math.max(i, this.getBlockPower(blockposition.north(), EnumDirection.NORTH));
if (i >= 15) {
return i;
} else {
i = Math.max(i, this.getBlockPower(blockposition.south(), EnumDirection.SOUTH));
if (i >= 15) {
return i;
} else {
i = Math.max(i, this.getBlockPower(blockposition.west(), EnumDirection.WEST));
if (i >= 15) {
return i;
} else {
i = Math.max(i, this.getBlockPower(blockposition.east(), EnumDirection.EAST));
return i >= 15 ? i : i;
}
}
}
}
}
}
public boolean isBlockFacePowered(BlockPosition blockposition, EnumDirection enumdirection) {
return this.getBlockFacePower(blockposition, enumdirection) > 0;
}
public int getBlockFacePower(BlockPosition blockposition, EnumDirection enumdirection) {
IBlockData iblockdata = this.getType(blockposition);
Block block = iblockdata.getBlock();
return block.isOccluding() ? this.getBlockPower(blockposition) : block.a(this, blockposition, iblockdata, enumdirection);
}
public boolean isBlockIndirectlyPowered(BlockPosition blockposition) {
return this.getBlockFacePower(blockposition.down(), EnumDirection.DOWN) > 0 || (this.getBlockFacePower(blockposition.up(), EnumDirection.UP) > 0 || (this.getBlockFacePower(blockposition.north(), EnumDirection.NORTH) > 0 || (this.getBlockFacePower(blockposition.south(), EnumDirection.SOUTH) > 0 || (this.getBlockFacePower(blockposition.west(), EnumDirection.WEST) > 0 || this.getBlockFacePower(blockposition.east(), EnumDirection.EAST) > 0))));
}
public int A(BlockPosition blockposition) {
int i = 0;
EnumDirection[] aenumdirection = EnumDirection.values();
int j = aenumdirection.length;
for (int k = 0; k < j; ++k) {
EnumDirection enumdirection = aenumdirection[k];
int l = this.getBlockFacePower(blockposition.shift(enumdirection), enumdirection);
if (l >= 15) {
return 15;
}
if (l > i) {
i = l;
}
}
return i;
}
public EntityHuman findNearbyPlayer(Entity entity, double d0) {
return this.findNearbyPlayer(entity.locX, entity.locY, entity.locZ, d0);
}
public EntityHuman findNearbyPlayer(double d0, double d1, double d2, double d3) {
double d4 = -1.0D;
EntityHuman entityhuman = null;
for (int i = 0; i < this.players.size(); ++i) {
EntityHuman entityhuman1 = this.players.get(i);
// CraftBukkit start - Fixed an NPE
if (entityhuman1 == null || entityhuman1.dead) {
continue;
}
// CraftBukkit end
if (IEntitySelector.d.apply(entityhuman1)) {
double d5 = entityhuman1.e(d0, d1, d2);
if ((d3 < 0.0D || d5 < d3 * d3) && (d4 == -1.0D || d5 < d4)) {
d4 = d5;
entityhuman = entityhuman1;
}
}
}
return entityhuman;
}
public boolean isPlayerNearby(double d0, double d1, double d2, double d3) {
for (int i = 0; i < this.players.size(); ++i) {
EntityHuman entityhuman = this.players.get(i);
if (IEntitySelector.d.apply(entityhuman)) {
double d4 = entityhuman.e(d0, d1, d2);
if (d3 < 0.0D || d4 < d3 * d3) {
return true;
}
}
}
return false;
}
public EntityHuman a(String s) {
for (int i = 0; i < this.players.size(); ++i) {
EntityHuman entityhuman = this.players.get(i);
if (s.equals(entityhuman.getName())) {
return entityhuman;
}
}
return null;
}
public EntityHuman b(UUID uuid) {
for (int i = 0; i < this.players.size(); ++i) {
EntityHuman entityhuman = this.players.get(i);
if (uuid.equals(entityhuman.getUniqueID())) {
return entityhuman;
}
}
return null;
}
public void checkSession() throws ExceptionWorldConflict {
this.dataManager.checkSession();
}
public long getSeed() {
return this.worldData.getSeed();
}
public long getTime() {
return this.worldData.getTime();
}
public long getDayTime() {
return this.worldData.getDayTime();
}
public void setDayTime(long i) {
this.worldData.setDayTime(i);
}
public BlockPosition getSpawn() {
BlockPosition blockposition = new BlockPosition(this.worldData.c(), this.worldData.d(), this.worldData.e());
if (!this.getWorldBorder().a(blockposition)) {
blockposition = this.getHighestBlockYAt(new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ()));
}
return blockposition;
}
public void B(BlockPosition blockposition) {
this.worldData.setSpawn(blockposition);
}
public boolean a(EntityHuman entityhuman, BlockPosition blockposition) {
return true;
}
public void broadcastEntityEffect(Entity entity, byte b0) {
}
public IChunkProvider N() {
return this.chunkProvider;
}
public void playBlockAction(BlockPosition blockposition, Block block, int i, int j) {
block.a(this, blockposition, this.getType(blockposition), i, j);
}
public IDataManager getDataManager() {
return this.dataManager;
}
public WorldData getWorldData() {
return this.worldData;
}
public GameRules getGameRules() {
return this.worldData.x();
}
public void everyoneSleeping() {
}
// CraftBukkit start
// Calls the method that checks to see if players are sleeping
// Called by CraftPlayer.setPermanentSleeping()
public void checkSleepStatus() {
if (!this.isClientSide) {
this.everyoneSleeping();
}
}
// CraftBukkit end
public float h(float f) {
return (this.q + (this.r - this.q) * f) * this.j(f);
}
public float j(float f) {
return this.o + (this.p - this.o) * f;
}
public boolean R() {
return (double) this.h(1.0F) > 0.9D;
}
public boolean S() {
return (double) this.j(1.0F) > 0.2D;
}
public boolean isRainingAt(BlockPosition blockposition) {
if (!this.S()) {
return false;
} else if (!this.i(blockposition)) {
return false;
} else if (this.q(blockposition).getY() > blockposition.getY()) {
return false;
} else {
BiomeBase biomebase = this.getBiome(blockposition);
return !biomebase.d() && (!this.f(blockposition, false) && biomebase.e());
}
}
public boolean D(BlockPosition blockposition) {
BiomeBase biomebase = this.getBiome(blockposition);
return biomebase.f();
}
public PersistentCollection T() {
return this.worldMaps;
}
public void a(String s, PersistentBase persistentbase) {
this.worldMaps.a(s, persistentbase);
}
public PersistentBase a(Class extends PersistentBase> oclass, String s) {
return this.worldMaps.get(oclass, s);
}
public int b(String s) {
return this.worldMaps.a(s);
}
public void a(int i, BlockPosition blockposition, int j) {
for (int k = 0; k < this.u.size(); ++k) {
this.u.get(k).a(i, blockposition, j);
}
}
public void triggerEffect(int i, BlockPosition blockposition, int j) {
this.a(null, i, blockposition, j);
}
public void a(EntityHuman entityhuman, int i, BlockPosition blockposition, int j) {
try {
for (int k = 0; k < this.u.size(); ++k) {
this.u.get(k).a(entityhuman, i, blockposition, j);
}
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.a(throwable, "Playing level event");
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Level event being played");
crashreportsystemdetails.a("Block coordinates", CrashReportSystemDetails.a(blockposition));
crashreportsystemdetails.a("Event source", entityhuman);
crashreportsystemdetails.a("Event type", Integer.valueOf(i));
crashreportsystemdetails.a("Event data", Integer.valueOf(j));
throw new ReportedException(crashreport);
}
}
public int getHeight() {
return 256;
}
public int V() {
return this.worldProvider.o() ? 128 : 256;
}
public Random a(int i, int j, int k) {
long l = (long) i * 341873128712L + (long) j * 132897987541L + this.getWorldData().getSeed() + (long) k;
this.random.setSeed(l);
return this.random;
}
public BlockPosition a(String s, BlockPosition blockposition) {
return this.N().findNearestMapFeature(this, s, blockposition);
}
public CrashReportSystemDetails a(CrashReport crashreport) {
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Affected level", 1);
crashreportsystemdetails.a("Level name", this.worldData == null ? "????" : this.worldData.getName());
crashreportsystemdetails.a("All players", new Callable() {
public String a() {
return World.this.players.size() + " total; " + World.this.players;
}
public Object call() throws Exception {
return this.a();
}
});
crashreportsystemdetails.a("Chunk stats", new Callable() {
public String a() {
return World.this.chunkProvider.getName();
}
public Object call() throws Exception {
return this.a();
}
});
try {
this.worldData.a(crashreportsystemdetails);
} catch (Throwable throwable) {
crashreportsystemdetails.a("Level Data Unobtainable", throwable);
}
return crashreportsystemdetails;
}
public void c(int i, BlockPosition blockposition, int j) {
for (int k = 0; k < this.u.size(); ++k) {
IWorldAccess iworldaccess = this.u.get(k);
iworldaccess.b(i, blockposition, j);
}
}
public Calendar Y() {
if (this.getTime() % 600L == 0L) {
this.K.setTimeInMillis(MinecraftServer.az());
}
return this.K;
}
public Scoreboard getScoreboard() {
return this.scoreboard;
}
public void updateAdjacentComparators(BlockPosition blockposition, Block block) {
Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator();
while (iterator.hasNext()) {
EnumDirection enumdirection = iterator.next();
BlockPosition blockposition1 = blockposition.shift(enumdirection);
if (this.isLoaded(blockposition1)) {
IBlockData iblockdata = this.getType(blockposition1);
if (Blocks.UNPOWERED_COMPARATOR.e(iblockdata.getBlock())) {
iblockdata.getBlock().doPhysics(this, blockposition1, iblockdata, block);
} else if (iblockdata.getBlock().isOccluding()) {
blockposition1 = blockposition1.shift(enumdirection);
iblockdata = this.getType(blockposition1);
if (Blocks.UNPOWERED_COMPARATOR.e(iblockdata.getBlock())) {
iblockdata.getBlock().doPhysics(this, blockposition1, iblockdata, block);
}
}
}
}
}
public DifficultyDamageScaler E(BlockPosition blockposition) {
long i = 0L;
float f = 0.0F;
if (this.isLoaded(blockposition)) {
f = this.y();
i = this.getChunkAtWorldCoords(blockposition).w();
}
return new DifficultyDamageScaler(this.getDifficulty(), this.getDayTime(), i, f);
}
public EnumDifficulty getDifficulty() {
return this.getWorldData().getDifficulty();
}
public int ab() {
return this.I;
}
public void c(int i) {
this.I = i;
}
public void d(int i) {
this.J = i;
}
public boolean ad() {
return this.isLoading;
}
public PersistentVillage ae() {
return this.villages;
}
public WorldBorder getWorldBorder() {
return this.N;
}
public boolean c(int i, int j) {
BlockPosition blockposition = this.getSpawn();
int k = i * 16 + 8 - blockposition.getX();
int l = j * 16 + 8 - blockposition.getZ();
short short0 = 128;
return k >= -short0 && k <= short0 && l >= -short0 && l <= short0 && this.keepSpawnInMemory; // CraftBukkit - Added 'this.keepSpawnInMemory'
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy