diff --git a/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java b/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java index bc4f86e54..62115a4f5 100644 --- a/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java +++ b/sources/src/main/java/io/akarin/server/core/AkarinGlobalConfig.java @@ -284,9 +284,4 @@ public class AkarinGlobalConfig { private static void forceHardcoreDifficulty() { forceHardcoreDifficulty = getBoolean("alternative.force-difficulty-on-hardcore", true); } - - public static boolean useAsyncLighting; - private static void useAsyncLighting() { - useAsyncLighting = getBoolean("core.async-lighting.enable", true); - } } diff --git a/sources/src/main/java/io/akarin/server/mixin/cps/MixinChunkProviderServer.java b/sources/src/main/java/io/akarin/server/mixin/cps/MixinChunkProviderServer.java index c85915f23..b8de638df 100644 --- a/sources/src/main/java/io/akarin/server/mixin/cps/MixinChunkProviderServer.java +++ b/sources/src/main/java/io/akarin/server/mixin/cps/MixinChunkProviderServer.java @@ -8,7 +8,6 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import io.akarin.server.core.AkarinGlobalConfig; import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectIterator; @@ -23,7 +22,6 @@ public abstract class MixinChunkProviderServer { @Shadow public Long2ObjectOpenHashMap chunks; public void unload(Chunk chunk) { - if (AkarinGlobalConfig.useAsyncLighting && chunk != null && (chunk.pendingLightUpdates.get() > 0 || chunk.world.getTime() - chunk.lightUpdateTime < 20)) return; // Akarin start - Re-add asynchronous lighting updates if (this.world.worldProvider.c(chunk.locX, chunk.locZ)) { // Akarin - avoid using the queue and simply check the unloaded flag during unloads // this.unloadQueue.add(Long.valueOf(ChunkCoordIntPair.a(chunk.locX, chunk.locZ))); diff --git a/sources/src/main/java/net/minecraft/server/Chunk.java b/sources/src/main/java/net/minecraft/server/Chunk.java deleted file mode 100644 index b32c09ba2..000000000 --- a/sources/src/main/java/net/minecraft/server/Chunk.java +++ /dev/null @@ -1,1578 +0,0 @@ -package net.minecraft.server; - -import com.destroystokyo.paper.PaperWorldConfig.DuplicateUUIDMode; -import com.destroystokyo.paper.exception.ServerInternalException; -import com.google.common.base.Predicate; -import com.google.common.collect.Queues; - -import io.akarin.server.core.AkarinGlobalConfig; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.UUID; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.annotation.Nullable; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import com.google.common.collect.Lists; // CraftBukkit -import org.bukkit.Server; // CraftBukkit -import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper - -/** - * Akarin Changes Note - * 1) Async lighting (performance) - */ -public class Chunk { - - private static final Logger e = LogManager.getLogger(); - public static final ChunkSection a = null; public static final ChunkSection EMPTY_CHUNK_SECTION = Chunk.a; // Paper - OBFHELPER - private final ChunkSection[] sections; - private final byte[] g; - private final int[] h; - private final boolean[] i; - private boolean j; public boolean isLoaded() { return j; } // Paper - OBFHELPER - public final World world; - public final int[] heightMap; - public Long scheduledForUnload; // Paper - delay chunk unloads - private static final Logger logger = LogManager.getLogger(); // Paper - public final int locX; - public final int locZ; - private boolean m; - public final Map tileEntities; - public final List[] entitySlices; // Spigot - // Paper start - public final co.aikar.util.Counter entityCounts = new co.aikar.util.Counter<>(); - public final co.aikar.util.Counter tileEntityCounts = new co.aikar.util.Counter<>(); - private class TileEntityHashMap extends java.util.HashMap { - @Override - public TileEntity put(BlockPosition key, TileEntity value) { - TileEntity replaced = super.put(key, value); - if (replaced != null) { - replaced.setCurrentChunk(null); - tileEntityCounts.decrement(replaced.getMinecraftKeyString()); - } - if (value != null) { - value.setCurrentChunk(Chunk.this); - tileEntityCounts.increment(value.getMinecraftKeyString()); - } - return replaced; - } - - @Override - public TileEntity remove(Object key) { - TileEntity removed = super.remove(key); - if (removed != null) { - removed.setCurrentChunk(null); - tileEntityCounts.decrement(removed.getMinecraftKeyString()); - } - return removed; - } - } - final PaperLightingQueue.LightingQueue lightingQueue = new PaperLightingQueue.LightingQueue(this); - // Paper end - private boolean done; - private boolean lit; - private boolean r; private boolean isTicked() { return r; }; // Paper - OBFHELPER - private boolean s; - private boolean t; - private long lastSaved; - private int v; - private long w; - private int x; - private final ConcurrentLinkedQueue y; - public boolean d; public void setShouldUnload(boolean unload) { this.d = unload; } public boolean isUnloading() { return d; } // Paper - OBFHELPER - protected gnu.trove.map.hash.TObjectIntHashMap entityCount = new gnu.trove.map.hash.TObjectIntHashMap(); // Spigot - - // Paper start - // Track the number of minecarts and items - // Keep this synced with entitySlices.add() and entitySlices.remove() - private final int[] itemCounts = new int[16]; - private final int[] inventoryEntityCounts = new int[16]; - // Paper end - - // CraftBukkit start - Neighbor loaded cache for chunk lighting and entity ticking - private int neighbors = 0x1 << 12; - public long chunkKey; - - public boolean areNeighborsLoaded(final int radius) { - switch (radius) { - case 2: - return this.neighbors == Integer.MAX_VALUE >> 6; - case 1: - final int mask = - // x z offset x z offset x z offset - (0x1 << (1 * 5 + 1 + 12)) | (0x1 << (0 * 5 + 1 + 12)) | (0x1 << (-1 * 5 + 1 + 12)) | - (0x1 << (1 * 5 + 0 + 12)) | (0x1 << (0 * 5 + 0 + 12)) | (0x1 << (-1 * 5 + 0 + 12)) | - (0x1 << (1 * 5 + -1 + 12)) | (0x1 << (0 * 5 + -1 + 12)) | (0x1 << (-1 * 5 + -1 + 12)); - return (this.neighbors & mask) == mask; - default: - throw new UnsupportedOperationException(String.valueOf(radius)); - } - } - - public void setNeighborLoaded(final int x, final int z) { - this.neighbors |= 0x1 << (x * 5 + 12 + z); - } - - public void setNeighborUnloaded(final int x, final int z) { - this.neighbors &= ~(0x1 << (x * 5 + 12 + z)); - } - // CraftBukkit end - // Akarin start - Re-add asynchronous light updates - public AtomicInteger pendingLightUpdates = new AtomicInteger(); - public long lightUpdateTime; - // Akarin end - - public Chunk(World world, int i, int j) { - this.sections = new ChunkSection[16]; - this.g = new byte[256]; - this.h = new int[256]; - this.i = new boolean[256]; - this.tileEntities = new TileEntityHashMap(); // Paper - this.x = 4096; - this.y = Queues.newConcurrentLinkedQueue(); - this.entitySlices = (List[]) (new List[16]); // Spigot - this.world = world; - this.locX = i; - this.locZ = j; - this.heightMap = new int[256]; - - for (int k = 0; k < this.entitySlices.length; ++k) { - this.entitySlices[k] = new org.bukkit.craftbukkit.util.UnsafeList(); // Spigot - } - - Arrays.fill(this.h, -999); - Arrays.fill(this.g, (byte) -1); - // CraftBukkit start - this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); - this.chunkKey = ChunkCoordIntPair.a(this.locX, this.locZ); - } - - public org.bukkit.Chunk bukkitChunk; - public boolean mustSave; - // CraftBukkit end - - public Chunk(World world, ChunkSnapshot chunksnapshot, int i, int j) { - this(world, i, j); - boolean flag = true; - boolean flag1 = world.worldProvider.m(); - - for (int k = 0; k < 16; ++k) { - for (int l = 0; l < 16; ++l) { - for (int i1 = 0; i1 < 256; ++i1) { - IBlockData iblockdata = chunksnapshot.a(k, i1, l); - - if (iblockdata.getMaterial() != Material.AIR) { - int j1 = i1 >> 4; - - if (this.sections[j1] == Chunk.a) { - this.sections[j1] = new ChunkSection(j1 << 4, flag1, world.chunkPacketBlockController.getPredefinedBlockData(this, j1)); // Paper - Anti-Xray - Add predefined block data - } - - this.sections[j1].setType(k, i1 & 15, l, iblockdata); - } - } - } - } - - } - - public boolean a(int i, int j) { - return i == this.locX && j == this.locZ; - } - - public int e(BlockPosition blockposition) { - return this.b(blockposition.getX() & 15, blockposition.getZ() & 15); - } - - public int b(int i, int j) { - return this.heightMap[j << 4 | i]; - } - - @Nullable - private ChunkSection y() { - for (int i = this.sections.length - 1; i >= 0; --i) { - if (this.sections[i] != Chunk.a) { - return this.sections[i]; - } - } - - return null; - } - - public int g() { - ChunkSection chunksection = this.y(); - - return chunksection == null ? 0 : chunksection.getYPosition(); - } - - public ChunkSection[] getSections() { - return this.sections; - } - - public void initLighting() { - int i = this.g(); - - this.v = Integer.MAX_VALUE; - - for (int j = 0; j < 16; ++j) { - int k = 0; - - while (k < 16) { - this.h[j + (k << 4)] = -999; - int l = i + 16; - - while (true) { - if (l > 0) { - if (this.d(j, l - 1, k) == 0) { - --l; - continue; - } - - this.heightMap[k << 4 | j] = l; - if (l < this.v) { - this.v = l; - } - } - - if (this.world.worldProvider.m()) { - l = 15; - int i1 = i + 16 - 1; - - do { - int j1 = this.d(j, i1, k); - - if (j1 == 0 && l != 15) { - j1 = 1; - } - - l -= j1; - if (l > 0) { - ChunkSection chunksection = this.sections[i1 >> 4]; - - if (chunksection != Chunk.a) { - chunksection.a(j, i1 & 15, k, l); - this.world.m(new BlockPosition((this.locX << 4) + j, i1, (this.locZ << 4) + k)); - } - } - - --i1; - } while (i1 > 0 && l > 0); - } - - ++k; - break; - } - } - } - - this.s = true; - } - - private void d(int i, int j) { - this.i[i + j * 16] = true; - this.m = true; - } - - private void h(boolean flag) { - this.world.methodProfiler.a("recheckGaps"); - if (this.world.areChunksLoaded(new BlockPosition(this.locX * 16 + 8, 0, this.locZ * 16 + 8), 16)) { - this.runOrQueueLightUpdate(() -> recheckGaps(flag)); // Paper - Queue light update - } - } - - private void recheckGaps(boolean flag) { - if (true) { - // Paper end - for (int i = 0; i < 16; ++i) { - for (int j = 0; j < 16; ++j) { - if (this.i[i + j * 16]) { - this.i[i + j * 16] = false; - int k = this.b(i, j); - int l = this.locX * 16 + i; - int i1 = this.locZ * 16 + j; - int j1 = Integer.MAX_VALUE; - - Iterator iterator; - EnumDirection enumdirection; - - for (iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); iterator.hasNext(); j1 = Math.min(j1, this.world.d(l + enumdirection.getAdjacentX(), i1 + enumdirection.getAdjacentZ()))) { - enumdirection = (EnumDirection) iterator.next(); - } - - this.b(l, i1, j1); - iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); - - while (iterator.hasNext()) { - enumdirection = (EnumDirection) iterator.next(); - this.b(l + enumdirection.getAdjacentX(), i1 + enumdirection.getAdjacentZ(), k); - } - - if (flag) { - this.world.methodProfiler.b(); - return; - } - } - } - } - - this.m = false; - } - - this.world.methodProfiler.b(); - } - - private void b(int i, int j, int k) { - int l = this.world.getHighestBlockYAt(new BlockPosition(i, 0, j)).getY(); - - if (l > k) { - this.a(i, j, k, l + 1); - } else if (l < k) { - this.a(i, j, l, k + 1); - } - - } - - private void a(int i, int j, int k, int l) { - if (l > k && this.world.areChunksLoaded(new BlockPosition(i, 0, j), 16)) { - for (int i1 = k; i1 < l; ++i1) { - this.world.updateLight(EnumSkyBlock.SKY, new BlockPosition(i, i1, j)); // Akarin - Re-add asynchronous lighting updates - } - - this.s = true; - } - - } - - private void c(int i, int j, int k) { - int l = this.heightMap[k << 4 | i] & 255; - int i1 = l; - - if (j > l) { - i1 = j; - } - - while (i1 > 0 && this.d(i, i1 - 1, k) == 0) { - --i1; - } - - if (i1 != l) { - this.world.a(i + this.locX * 16, k + this.locZ * 16, i1, l); - this.heightMap[k << 4 | i] = i1; - int j1 = this.locX * 16 + i; - int k1 = this.locZ * 16 + k; - int l1; - int i2; - - if (this.world.worldProvider.m()) { - ChunkSection chunksection; - - if (i1 < l) { - for (l1 = i1; l1 < l; ++l1) { - chunksection = this.sections[l1 >> 4]; - if (chunksection != Chunk.a) { - chunksection.a(i, l1 & 15, k, 15); - this.world.m(new BlockPosition((this.locX << 4) + i, l1, (this.locZ << 4) + k)); - } - } - } else { - for (l1 = l; l1 < i1; ++l1) { - chunksection = this.sections[l1 >> 4]; - if (chunksection != Chunk.a) { - chunksection.a(i, l1 & 15, k, 0); - this.world.m(new BlockPosition((this.locX << 4) + i, l1, (this.locZ << 4) + k)); - } - } - } - - l1 = 15; - - while (i1 > 0 && l1 > 0) { - --i1; - i2 = this.d(i, i1, k); - if (i2 == 0) { - i2 = 1; - } - - l1 -= i2; - if (l1 < 0) { - l1 = 0; - } - - ChunkSection chunksection1 = this.sections[i1 >> 4]; - - if (chunksection1 != Chunk.a) { - chunksection1.a(i, i1 & 15, k, l1); - } - } - } - - l1 = this.heightMap[k << 4 | i]; - i2 = l; - int j2 = l1; - - if (l1 < l) { - i2 = l1; - j2 = l; - } - - if (l1 < this.v) { - this.v = l1; - } - - if (this.world.worldProvider.m()) { - Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); - - while (iterator.hasNext()) { - EnumDirection enumdirection = (EnumDirection) iterator.next(); - - this.a(j1 + enumdirection.getAdjacentX(), k1 + enumdirection.getAdjacentZ(), i2, j2); - } - - this.a(j1, k1, i2, j2); - } - - this.s = true; - } - } - - public int b(BlockPosition blockposition) { - return this.getBlockData(blockposition).c(); - } - - private int d(int i, int j, int k) { - return this.a(i, j, k).c(); - } - - // Paper start - Optimize getBlockData to reduce instructions - public final IBlockData getBlockData(final BlockPosition pos) { - return getBlockData(pos.getX(), pos.getY(), pos.getZ()); - } - - public final IBlockData getBlockData(final int x, final int y, final int z) { - // Method body / logic copied from below - final int i = y >> 4; - if (y >= 0 && i < this.sections.length && this.sections[i] != null) { - // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) - return this.sections[i].blockIds.a((y & 15) << 8 | (z & 15) << 4 | x & 15); - } - return Blocks.AIR.getBlockData(); - } - - public IBlockData a(final int i, final int j, final int k) { - return getBlockData(i, j, k); - } - - public IBlockData unused(final int i, final int j, final int k) { - // Paper end - if (this.world.N() == WorldType.DEBUG_ALL_BLOCK_STATES) { - IBlockData iblockdata = null; - - if (j == 60) { - iblockdata = Blocks.BARRIER.getBlockData(); - } - - if (j == 70) { - iblockdata = ChunkProviderDebug.c(i, k); - } - - return iblockdata == null ? Blocks.AIR.getBlockData() : iblockdata; - } else { - try { - if (j >= 0 && j >> 4 < this.sections.length) { - ChunkSection chunksection = this.sections[j >> 4]; - - if (chunksection != Chunk.a) { - return chunksection.getType(i & 15, j & 15, k & 15); - } - } - - return Blocks.AIR.getBlockData(); - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Getting block state"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being got"); - - crashreportsystemdetails.a("Location", new CrashReportCallable() { - public String a() throws Exception { - return CrashReportSystemDetails.a(i, j, k); - } - - public Object call() throws Exception { - return this.a(); - } - }); - throw new ReportedException(crashreport); - } - } - } - - @Nullable - public IBlockData a(BlockPosition blockposition, IBlockData iblockdata) { - int i = blockposition.getX() & 15; - int j = blockposition.getY(); - int k = blockposition.getZ() & 15; - int l = k << 4 | i; - - if (j >= this.h[l] - 1) { - this.h[l] = -999; - } - - int i1 = this.heightMap[l]; - IBlockData iblockdata1 = this.getBlockData(blockposition); - - if (iblockdata1 == iblockdata) { - return null; - } else { - Block block = iblockdata.getBlock(); - Block block1 = iblockdata1.getBlock(); - ChunkSection chunksection = this.sections[j >> 4]; - boolean flag = false; - - if (chunksection == Chunk.a) { - if (block == Blocks.AIR) { - return null; - } - - chunksection = new ChunkSection(j >> 4 << 4, this.world.worldProvider.m(), this.world.chunkPacketBlockController.getPredefinedBlockData(this, j >> 4)); // Paper - Anti-Xray - Add predefined block data - this.sections[j >> 4] = chunksection; - flag = j >= i1; - } - - chunksection.setType(i, j & 15, k, iblockdata); - if (block1 != block) { - if (!this.world.isClientSide) { - block1.remove(this.world, blockposition, iblockdata1); - } else if (block1 instanceof ITileEntity) { - this.world.s(blockposition); - } - } - - if (chunksection.getType(i, j & 15, k).getBlock() != block) { - return null; - } else { - if (flag) { - this.initLighting(); - } else { - this.runOrQueueLightUpdate(() -> { // Paper - Queue light update - int j1 = iblockdata.c(); - int k1 = iblockdata1.c(); - - if (j1 > 0) { - if (j >= i1) { - this.c(i, j + 1, k); - } - } else if (j == i1 - 1) { - this.c(i, j, k); - } - - if (j1 != k1 && (j1 < k1 || this.getBrightness(EnumSkyBlock.SKY, blockposition) > 0 || this.getBrightness(EnumSkyBlock.BLOCK, blockposition) > 0)) { - this.d(i, k); - } - }); // Paper - } - - TileEntity tileentity; - - if (block1 instanceof ITileEntity) { - tileentity = this.a(blockposition, Chunk.EnumTileEntityState.CHECK); - if (tileentity != null) { - tileentity.invalidateBlockCache(); - } - } - - // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. - if (!this.world.isClientSide && block1 != block && (!this.world.captureBlockStates || block instanceof BlockTileEntity)) { - block.onPlace(this.world, blockposition, iblockdata); - } - - if (block instanceof ITileEntity) { - tileentity = this.a(blockposition, Chunk.EnumTileEntityState.CHECK); - if (tileentity == null) { - tileentity = ((ITileEntity) block).a(this.world, block.toLegacyData(iblockdata)); - this.world.setTileEntity(blockposition, tileentity); - } - - if (tileentity != null) { - tileentity.invalidateBlockCache(); - } - } - - this.s = true; - return iblockdata1; - } - } - } - - public int getBrightness(EnumSkyBlock enumskyblock, BlockPosition blockposition) { - int i = blockposition.getX() & 15; - int j = blockposition.getY(); - int k = blockposition.getZ() & 15; - ChunkSection chunksection = this.sections[j >> 4]; - - return chunksection == Chunk.a ? (this.c(blockposition) ? enumskyblock.c : 0) : (enumskyblock == EnumSkyBlock.SKY ? (!this.world.worldProvider.m() ? 0 : chunksection.b(i, j & 15, k)) : (enumskyblock == EnumSkyBlock.BLOCK ? chunksection.c(i, j & 15, k) : enumskyblock.c)); - } - - public void a(EnumSkyBlock enumskyblock, BlockPosition blockposition, int i) { - int j = blockposition.getX() & 15; - int k = blockposition.getY(); - int l = blockposition.getZ() & 15; - ChunkSection chunksection = this.sections[k >> 4]; - - if (chunksection == Chunk.a) { - chunksection = new ChunkSection(k >> 4 << 4, this.world.worldProvider.m(), this.world.chunkPacketBlockController.getPredefinedBlockData(this, k >> 4)); // Paper - Anti-Xray - Add predefined block data - this.sections[k >> 4] = chunksection; - this.initLighting(); - } - - this.s = true; - if (enumskyblock == EnumSkyBlock.SKY) { - if (this.world.worldProvider.m()) { - chunksection.a(j, k & 15, l, i); - } - } else if (enumskyblock == EnumSkyBlock.BLOCK) { - chunksection.b(j, k & 15, l, i); - } - - } - - public final int getLightSubtracted(BlockPosition blockposition, int i) { return this.a(blockposition, i); } // Paper - OBFHELPER - public int a(BlockPosition blockposition, int i) { - int j = blockposition.getX() & 15; - int k = blockposition.getY(); - int l = blockposition.getZ() & 15; - ChunkSection chunksection = this.sections[k >> 4]; - - if (chunksection == Chunk.a) { - return this.world.worldProvider.m() && i < EnumSkyBlock.SKY.c ? EnumSkyBlock.SKY.c - i : 0; - } else { - int i1 = !this.world.worldProvider.m() ? 0 : chunksection.b(j, k & 15, l); - - i1 -= i; - int j1 = chunksection.c(j, k & 15, l); - - if (j1 > i1) { - i1 = j1; - } - - return i1; - } - } - - public void a(Entity entity) { - this.t = true; - int i = MathHelper.floor(entity.locX / 16.0D); - int j = MathHelper.floor(entity.locZ / 16.0D); - - if (i != this.locX || j != this.locZ) { - Chunk.e.warn("Wrong location! ({}, {}) should be ({}, {}), {}", Integer.valueOf(i), Integer.valueOf(j), Integer.valueOf(this.locX), Integer.valueOf(this.locZ), entity); - entity.die(); - } - - int k = MathHelper.floor(entity.locY / 16.0D); - - if (k < 0) { - k = 0; - } - - if (k >= this.entitySlices.length) { - k = this.entitySlices.length - 1; - } - - entity.aa = true; - entity.ab = this.locX; - entity.ac = k; - entity.ad = this.locZ; - - // Paper start - List entitySlice = this.entitySlices[k]; - boolean inThis = entitySlice.contains(entity); - if (entity.entitySlice != null || inThis) { - if (entity.entitySlice == entitySlice || inThis) { - LogManager.getLogger().warn(entity + " was already in this chunk section! Report this to https://github.com/PaperMC/Paper/issues/1223"); - new Throwable().printStackTrace(); - return; - } else { - LogManager.getLogger().warn(entity + " is still in another ChunkSection! Report this to https://github.com/PaperMC/Paper/issues/1223"); - - Chunk chunk = entity.getCurrentChunk(); - if (chunk != null) { - if (chunk != this) { - LogManager.getLogger().warn(entity + " was in another chunk at that! " + chunk.locX + "," + chunk.locZ); - } - chunk.removeEntity(entity); - } else { - removeEntity(entity); - } - new Throwable().printStackTrace(); - } - } - entity.entitySlice = entitySlice; - entitySlice.add(entity); - - this.markDirty(); - entity.setCurrentChunk(this); - entityCounts.increment(entity.getMinecraftKeyString()); - if (entity instanceof EntityItem) { - itemCounts[k]++; - } else if (entity instanceof IInventory) { - inventoryEntityCounts[k]++; - } - // Paper end - // Spigot start - increment creature type count - // Keep this synced up with World.a(Class) - if (entity instanceof EntityInsentient) { - EntityInsentient entityinsentient = (EntityInsentient) entity; - if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) { - return; - } - } - for ( EnumCreatureType creatureType : EnumCreatureType.values() ) - { - if ( creatureType.a().isAssignableFrom( entity.getClass() ) ) - { - this.entityCount.adjustOrPutValue( creatureType.a(), 1, 1 ); - } - } - // Spigot end - } - - public void removeEntity(Entity entity) { b(entity); } // Paper - OBFHELPER - public void b(Entity entity) { - this.a(entity, entity.ac); - } - - public void a(Entity entity, int i) { - if (i < 0) { - i = 0; - } - - if (i >= this.entitySlices.length) { - i = this.entitySlices.length - 1; - } - - // Paper start - if (!this.entitySlices[i].remove(entity)) { return; } - if (entitySlices[i] == entity.entitySlice) { - entity.entitySlice = null; - } else { - LogManager.getLogger().warn(entity + " was removed from a entitySlice we did not expect. Report this to https://github.com/PaperMC/Paper/issues/1223"); - new Throwable().printStackTrace(); - } - this.markDirty(); - entity.setCurrentChunk(null); - entityCounts.decrement(entity.getMinecraftKeyString()); - if (entity instanceof EntityItem) { - itemCounts[i]--; - } else if (entity instanceof IInventory) { - inventoryEntityCounts[i]--; - } - // Paper end - // Spigot start - decrement creature type count - // Keep this synced up with World.a(Class) - if (entity instanceof EntityInsentient) { - EntityInsentient entityinsentient = (EntityInsentient) entity; - if (entityinsentient.isTypeNotPersistent() && entityinsentient.isPersistent()) { - return; - } - } - for ( EnumCreatureType creatureType : EnumCreatureType.values() ) - { - if ( creatureType.a().isAssignableFrom( entity.getClass() ) ) - { - this.entityCount.adjustValue( creatureType.a(), -1 ); - } - } - // Spigot end - } - - public boolean c(BlockPosition blockposition) { - int i = blockposition.getX() & 15; - int j = blockposition.getY(); - int k = blockposition.getZ() & 15; - - return j >= this.heightMap[k << 4 | i]; - } - - @Nullable - private TileEntity g(BlockPosition blockposition) { - IBlockData iblockdata = this.getBlockData(blockposition); - Block block = iblockdata.getBlock(); - - return !block.isTileEntity() ? null : ((ITileEntity) block).a(this.world, iblockdata.getBlock().toLegacyData(iblockdata)); - } - - @Nullable public final TileEntity getTileEntityImmediately(BlockPosition pos) { return this.a(pos, EnumTileEntityState.IMMEDIATE); } // Paper - OBFHELPER - @Nullable - public TileEntity a(BlockPosition blockposition, Chunk.EnumTileEntityState chunk_enumtileentitystate) { - // CraftBukkit start - TileEntity tileentity = null; - if (world.captureBlockStates) { - tileentity = world.capturedTileEntities.get(blockposition); - } - if (tileentity == null) { - tileentity = (TileEntity) this.tileEntities.get(blockposition); - } - // CraftBukkit end - - if (tileentity == null) { - if (chunk_enumtileentitystate == Chunk.EnumTileEntityState.IMMEDIATE) { - tileentity = this.g(blockposition); - this.world.setTileEntity(blockposition, tileentity); - } else if (chunk_enumtileentitystate == Chunk.EnumTileEntityState.QUEUED) { - this.y.add(blockposition); - } - } else if (tileentity.y()) { - this.tileEntities.remove(blockposition); - return null; - } - - return tileentity; - } - - public void a(TileEntity tileentity) { - this.a(tileentity.getPosition(), tileentity); - if (this.j) { - this.world.a(tileentity); - } - - } - - public void a(BlockPosition blockposition, TileEntity tileentity) { - tileentity.a(this.world); - tileentity.setPosition(blockposition); - if (this.getBlockData(blockposition).getBlock() instanceof ITileEntity) { - if (this.tileEntities.containsKey(blockposition)) { - ((TileEntity) this.tileEntities.get(blockposition)).z(); - } - - tileentity.A(); - this.tileEntities.put(blockposition, tileentity); - // CraftBukkit start - // Paper start - Remove invalid mob spawner tile entities - } else if (tileentity instanceof TileEntityMobSpawner && org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(getBlockData(blockposition).getBlock()) != org.bukkit.Material.MOB_SPAWNER) { - this.tileEntities.remove(blockposition); - // Paper end - } else { - // Paper start - ServerInternalException e = new ServerInternalException( - "Attempted to place a tile entity (" + tileentity + ") at " + tileentity.position.getX() + "," - + tileentity.position.getY() + "," + tileentity.position.getZ() - + " (" + CraftMagicNumbers.getMaterial(getBlockData(blockposition).getBlock()) + ") where there was no entity tile!\n" + - "Chunk coordinates: " + (this.locX * 16) + "," + (this.locZ * 16)); - e.printStackTrace(); - ServerInternalException.reportInternalException(e); - - if (this.world.paperConfig.removeCorruptTEs) { - this.removeTileEntity(tileentity.getPosition()); - this.markDirty(); - org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); - } - // Paper end - // CraftBukkit end - } - } - - public void removeTileEntity(BlockPosition blockposition) { this.d(blockposition); } // Paper - OBFHELPER - public void d(BlockPosition blockposition) { - if (this.j) { - TileEntity tileentity = (TileEntity) this.tileEntities.remove(blockposition); - - if (tileentity != null) { - tileentity.z(); - } - } - - } - - public void addEntities() { - this.j = true; - this.world.b(this.tileEntities.values()); - List[] aentityslice = this.entitySlices; // Spigot - int i = aentityslice.length; - - for (int j = 0; j < i; ++j) { - List entityslice = aentityslice[j]; // Spigot - // Paper start - DuplicateUUIDMode mode = world.paperConfig.duplicateUUIDMode; - if (mode == DuplicateUUIDMode.WARN | mode == DuplicateUUIDMode.DELETE || mode == DuplicateUUIDMode.REGEN) { - Map thisChunk = new HashMap<>(); - for (Iterator iterator = ((List) entityslice).iterator(); iterator.hasNext(); ) { - Entity entity = iterator.next(); - if (entity.dead) continue; - Entity other = ((WorldServer) world).entitiesByUUID.get(entity.uniqueID); - if (other == null || other.dead || world.getEntityUnloadQueue().contains(other)) { - other = thisChunk.get(entity.uniqueID); - } - if (other != null && !other.dead) { - switch (mode) { - case REGEN: { - entity.setUUID(UUID.randomUUID()); - logger.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", regenerated UUID for " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); - break; - } - case DELETE: { - logger.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); - entity.die(); - iterator.remove(); - break; - } - default: - logger.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", doing nothing to " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); - break; - } - } - thisChunk.put(entity.uniqueID, entity); - } - } - // Paper end - - this.world.a((Collection) entityslice); - } - - } - - public void removeEntities() { - this.j = false; - Iterator iterator = this.tileEntities.values().iterator(); - - while (iterator.hasNext()) { - TileEntity tileentity = (TileEntity) iterator.next(); - // Spigot Start - if ( tileentity instanceof IInventory ) - { - for ( org.bukkit.entity.HumanEntity h : Lists.newArrayList((List) ( (IInventory) tileentity ).getViewers() ) ) - { - if ( h instanceof org.bukkit.craftbukkit.entity.CraftHumanEntity ) - { - ( (org.bukkit.craftbukkit.entity.CraftHumanEntity) h).getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - } - } - } - // Spigot End - - this.world.b(tileentity); - } - - List[] aentityslice = this.entitySlices; // Spigot - int i = aentityslice.length; - - for (int j = 0; j < i; ++j) { - // CraftBukkit start - List newList = Lists.newArrayList(aentityslice[j]); - java.util.Iterator iter = newList.iterator(); - while (iter.hasNext()) { - Entity entity = iter.next(); - // Spigot Start - if ( entity instanceof IInventory ) - { - for ( org.bukkit.entity.HumanEntity h : Lists.newArrayList( (List) ( (IInventory) entity ).getViewers() ) ) - { - if ( h instanceof org.bukkit.craftbukkit.entity.CraftHumanEntity ) - { - ( (org.bukkit.craftbukkit.entity.CraftHumanEntity) h).getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - } - } - } - // Spigot End - entity.setCurrentChunk(null); // Paper - entity.entitySlice = null; // Paper - - // Do not pass along players, as doing so can get them stuck outside of time. - // (which for example disables inventory icon updates and prevents block breaking) - if (entity instanceof EntityPlayer) { - iter.remove(); - } - } - - this.world.c(newList); - // CraftBukkit end - } - - } - - public void markDirty() { - this.s = true; - } - - public void a(@Nullable Entity entity, AxisAlignedBB axisalignedbb, List list, Predicate predicate) { - int i = MathHelper.floor((axisalignedbb.b - 2.0D) / 16.0D); - int j = MathHelper.floor((axisalignedbb.e + 2.0D) / 16.0D); - - i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); - j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); - - for (int k = i; k <= j; ++k) { - if (!this.entitySlices[k].isEmpty()) { - Iterator iterator = this.entitySlices[k].iterator(); - - // Paper start - Don't search for inventories if we have none, and that is all we want - /* - * We check if they want inventories by seeing if it is the static `IEntitySelector.c` - * - * Make sure the inventory selector stays in sync. - * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` - */ - if (predicate == IEntitySelector.c && inventoryEntityCounts[k] <= 0) continue; - // Paper end - while (iterator.hasNext()) { - Entity entity1 = (Entity) iterator.next(); - - if (entity1.getBoundingBox().c(axisalignedbb) && entity1 != entity) { - if (predicate == null || predicate.apply(entity1)) { - list.add(entity1); - } - - Entity[] aentity = entity1.bb(); - - if (aentity != null) { - Entity[] aentity1 = aentity; - int l = aentity.length; - - for (int i1 = 0; i1 < l; ++i1) { - Entity entity2 = aentity1[i1]; - - if (entity2 != entity && entity2.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.apply(entity2))) { - list.add(entity2); - } - } - } - } - } - } - } - - } - - public void a(Class oclass, AxisAlignedBB axisalignedbb, List list, Predicate predicate) { - int i = MathHelper.floor((axisalignedbb.b - 2.0D) / 16.0D); - int j = MathHelper.floor((axisalignedbb.e + 2.0D) / 16.0D); - - i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); - j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); - - // Paper start - int[] counts; - if (EntityItem.class.isAssignableFrom(oclass)) { - counts = itemCounts; - } else if (IInventory.class.isAssignableFrom(oclass)) { - counts = inventoryEntityCounts; - } else { - counts = null; - } - // Paper end - for (int k = i; k <= j; ++k) { - if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for - Iterator iterator = this.entitySlices[k].iterator(); // Spigot - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); - - if (oclass.isInstance(entity) && entity.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.apply((T) entity))) { // CraftBukkit - fix decompile error // Spigot - instance check - list.add((T) entity); // Fix decompile error - } - } - } - - } - - public boolean a(boolean flag) { - if (flag) { - if (this.t && this.world.getTime() != this.lastSaved || this.s) { - return true; - } - } - // This !flag section should say if s(isModified) or t(hasEntities), then check auto save - return ((this.s || this.t) && this.world.getTime() >= this.lastSaved + world.paperConfig.autoSavePeriod); // Paper - Make world configurable and incremental - } - - public Random a(long i) { - return new Random(this.world.getSeed() + (long) (this.locX * this.locX * 4987142) + (long) (this.locX * 5947611) + (long) (this.locZ * this.locZ) * 4392871L + (long) (this.locZ * 389711) ^ i); - } - - public boolean isEmpty() { - return false; - } - - // CraftBukkit start - public void loadNearby(IChunkProvider ichunkprovider, ChunkGenerator chunkgenerator, boolean newChunk) { - world.timings.syncChunkLoadPostTimer.startTiming(); // Paper - Server server = world.getServer(); - if (server != null) { - /* - * If it's a new world, the first few chunks are generated inside - * the World constructor. We can't reliably alter that, so we have - * no way of creating a CraftWorld/CraftServer at that point. - */ - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(bukkitChunk, newChunk)); - } - - // Update neighbor counts - for (int x = -2; x < 3; x++) { - for (int z = -2; z < 3; z++) { - if (x == 0 && z == 0) { - continue; - } - - Chunk neighbor = getWorld().getChunkIfLoaded(locX + x, locZ + z); - if (neighbor != null) { - neighbor.setNeighborLoaded(-x, -z); - setNeighborLoaded(x, z); - } - } - } - // CraftBukkit end - world.timings.syncChunkLoadPostTimer.stopTiming(); // Paper - world.timings.syncChunkLoadPopulateNeighbors.startTiming(); // Paper - Chunk chunk = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX, this.locZ - 1); // Paper - Chunk chunk1 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX + 1, this.locZ); // Paper - Chunk chunk2 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX, this.locZ + 1); // Paper - Chunk chunk3 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX - 1, this.locZ); // Paper - - if (chunk1 != null && chunk2 != null && MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX + 1, this.locZ + 1) != null) { // Paper - this.a(chunkgenerator); - } - - if (chunk3 != null && chunk2 != null && MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX - 1, this.locZ + 1) != null) { // Paper - chunk3.a(chunkgenerator); - } - - if (chunk != null && chunk1 != null && MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX + 1, this.locZ - 1) != null) { // Paper - chunk.a(chunkgenerator); - } - - if (chunk != null && chunk3 != null) { - Chunk chunk4 = MCUtil.getLoadedChunkWithoutMarkingActive(ichunkprovider,this.locX - 1, this.locZ - 1); // Paper - - if (chunk4 != null) { - chunk4.a(chunkgenerator); - } - } - world.timings.syncChunkLoadPopulateNeighbors.stopTiming(); // Paper - - } - - protected void a(ChunkGenerator chunkgenerator) { - if (this.isDone()) { - if (chunkgenerator.a(this, this.locX, this.locZ)) { - this.markDirty(); - } - } else { - this.o(); - chunkgenerator.recreateStructures(this.locX, this.locZ); - - // CraftBukkit start - BlockSand.instaFall = true; - Random random = new Random(); - random.setSeed(world.getSeed()); - long xRand = random.nextLong() / 2L * 2L + 1L; - long zRand = random.nextLong() / 2L * 2L + 1L; - random.setSeed((long) locX * xRand + (long) locZ * zRand ^ world.getSeed()); - - org.bukkit.World world = this.world.getWorld(); - if (world != null) { - this.world.populating = true; - try { - for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) { - populator.populate(world, random, bukkitChunk); - } - } finally { - this.world.populating = false; - } - } - BlockSand.instaFall = false; - this.world.getServer().getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); - // CraftBukkit end - this.markDirty(); - } - - } - - public BlockPosition f(BlockPosition blockposition) { - int i = blockposition.getX() & 15; - int j = blockposition.getZ() & 15; - int k = i | j << 4; - BlockPosition blockposition1 = new BlockPosition(blockposition.getX(), this.h[k], blockposition.getZ()); - - if (blockposition1.getY() == -999) { - int l = this.g() + 15; - - blockposition1 = new BlockPosition(blockposition.getX(), l, blockposition.getZ()); - int i1 = -1; - - while (blockposition1.getY() > 0 && i1 == -1) { - IBlockData iblockdata = this.getBlockData(blockposition1); - Material material = iblockdata.getMaterial(); - - if (!material.isSolid() && !material.isLiquid()) { - blockposition1 = blockposition1.down(); - } else { - i1 = blockposition1.getY() + 1; - } - } - - this.h[k] = i1; - } - - return new BlockPosition(blockposition.getX(), this.h[k], blockposition.getZ()); - } - - public void b(boolean flag) { - if (this.m && this.world.worldProvider.m() && !flag) { - this.recheckGaps(this.world.isClientSide); // Akarin - Re-add asynchronous lighting updates - } - - this.r = true; - if (!this.lit && this.done && this.world.spigotConfig.randomLightUpdates) { // Spigot - also use random light updates setting to determine if we should relight - this.o(); - } - - while (!this.y.isEmpty()) { - BlockPosition blockposition = (BlockPosition) this.y.poll(); - - if (this.a(blockposition, Chunk.EnumTileEntityState.CHECK) == null && this.getBlockData(blockposition).getBlock().isTileEntity()) { - TileEntity tileentity = this.g(blockposition); - - this.world.setTileEntity(blockposition, tileentity); - this.world.b(blockposition, blockposition); - } - } - - } - - // Akarin start - Recheck gaps asynchronously. - public void recheckGapsAsync(final boolean isClientSide) { - if (!AkarinGlobalConfig.useAsyncLighting) { - this.h(isClientSide); - return; - } - - world.lightingExecutor.submit(new Runnable() { - @Override - public void run() { - Chunk.this.h(isClientSide); - } - }); - } - // Akarin end - - public boolean isReady() { - // Spigot Start - /* - * As of 1.7, Mojang added a check to make sure that only chunks which have been lit are sent to the client. - * Unfortunately this interferes with our modified chunk ticking algorithm, which will only tick chunks distant from the player on a very infrequent basis. - * We cannot unfortunately do this lighting stage during chunk gen as it appears to put a lot more noticeable load on the server, than when it is done at play time. - * For now at least we will simply send all chunks, in accordance with pre 1.7 behaviour. - */ - // Paper Start - // if randomLightUpdates are disabled, we should always return true, otherwise chunks may never send - // to the client due to not being lit, otherwise retain standard behavior and only send properly lit chunks. - return !this.world.spigotConfig.randomLightUpdates || (this.isTicked() && this.done && this.lit); - // Paper End - // Spigot End - } - - public boolean j() { - return this.r; - } - - public ChunkCoordIntPair k() { - return new ChunkCoordIntPair(this.locX, this.locZ); - } - - public boolean c(int i, int j) { - if (i < 0) { - i = 0; - } - - if (j >= 256) { - j = 255; - } - - for (int k = i; k <= j; k += 16) { - ChunkSection chunksection = this.sections[k >> 4]; - - if (chunksection != Chunk.a && !chunksection.a()) { - return false; - } - } - - return true; - } - - public void a(ChunkSection[] achunksection) { - if (this.sections.length != achunksection.length) { - Chunk.e.warn("Could not set level chunk sections, array length is {} instead of {}", Integer.valueOf(achunksection.length), Integer.valueOf(this.sections.length)); - } else { - System.arraycopy(achunksection, 0, this.sections, 0, this.sections.length); - } - } - - public BiomeBase getBiome(BlockPosition blockposition, WorldChunkManager worldchunkmanager) { - int i = blockposition.getX() & 15; - int j = blockposition.getZ() & 15; - int k = this.g[j << 4 | i] & 255; - BiomeBase biomebase; - - if (k == 255) { - biomebase = worldchunkmanager.getBiome(blockposition, Biomes.c); - k = BiomeBase.a(biomebase); - this.g[j << 4 | i] = (byte) (k & 255); - } - - biomebase = BiomeBase.getBiome(k); - return biomebase == null ? Biomes.c : biomebase; - } - - public byte[] getBiomeIndex() { - return this.g; - } - - public void a(byte[] abyte) { - if (this.g.length != abyte.length) { - Chunk.e.warn("Could not set level chunk biomes, array length is {} instead of {}", Integer.valueOf(abyte.length), Integer.valueOf(this.g.length)); - } else { - System.arraycopy(abyte, 0, this.g, 0, this.g.length); - } - } - - public void m() { - this.x = 0; - } - - public void n() { - if (this.x < 4096) { - BlockPosition blockposition = new BlockPosition(this.locX << 4, 0, this.locZ << 4); - - for (int i = 0; i < 8; ++i) { - if (this.x >= 4096) { - return; - } - - int j = this.x % 16; - int k = this.x / 16 % 16; - int l = this.x / 256; - - ++this.x; - - for (int i1 = 0; i1 < 16; ++i1) { - BlockPosition blockposition1 = blockposition.a(k, (j << 4) + i1, l); - boolean flag = i1 == 0 || i1 == 15 || k == 0 || k == 15 || l == 0 || l == 15; - - if (this.sections[j] == Chunk.a && flag || this.sections[j] != Chunk.a && this.sections[j].getType(k, i1, l).getMaterial() == Material.AIR) { - EnumDirection[] aenumdirection = EnumDirection.values(); - int j1 = aenumdirection.length; - - for (int k1 = 0; k1 < j1; ++k1) { - EnumDirection enumdirection = aenumdirection[k1]; - BlockPosition blockposition2 = blockposition1.shift(enumdirection); - - if (this.world.getType(blockposition2).d() > 0) { - this.world.w(blockposition2); - } - } - - this.world.w(blockposition1); - } - } - } - - } - } - - public void o() { - world.timings.lightChunk.startTiming(); // Paper - this.done = true; - this.lit = true; - BlockPosition blockposition = new BlockPosition(this.locX << 4, 0, this.locZ << 4); - - if (this.world.worldProvider.m()) { - if (this.world.areChunksLoadedBetween(blockposition.a(-1, 0, -1), blockposition.a(16, this.world.getSeaLevel(), 16))) { - label42: - for (int i = 0; i < 16; ++i) { - for (int j = 0; j < 16; ++j) { - if (!this.e(i, j)) { - this.lit = false; - break label42; - } - } - } - - if (this.lit) { - Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); - - while (iterator.hasNext()) { - EnumDirection enumdirection = (EnumDirection) iterator.next(); - int k = enumdirection.c() == EnumDirection.EnumAxisDirection.POSITIVE ? 16 : 1; - - this.world.getChunkAtWorldCoords(blockposition.shift(enumdirection, k)).a(enumdirection.opposite()); - } - - this.z(); - } - } else { - this.lit = false; - } - } - - world.timings.lightChunk.stopTiming(); // Paper - } - - private void z() { - for (int i = 0; i < this.i.length; ++i) { - this.i[i] = true; - } - - this.h(false); - } - - private void a(EnumDirection enumdirection) { - if (this.done) { - int i; - - if (enumdirection == EnumDirection.EAST) { - for (i = 0; i < 16; ++i) { - this.e(15, i); - } - } else if (enumdirection == EnumDirection.WEST) { - for (i = 0; i < 16; ++i) { - this.e(0, i); - } - } else if (enumdirection == EnumDirection.SOUTH) { - for (i = 0; i < 16; ++i) { - this.e(i, 15); - } - } else if (enumdirection == EnumDirection.NORTH) { - for (i = 0; i < 16; ++i) { - this.e(i, 0); - } - } - - } - } - - private boolean e(int i, int j) { - int k = this.g(); - boolean flag = false; - boolean flag1 = false; - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition((this.locX << 4) + i, 0, (this.locZ << 4) + j); - - int l; - - for (l = k + 16 - 1; l > this.world.getSeaLevel() || l > 0 && !flag1; --l) { - blockposition_mutableblockposition.c(blockposition_mutableblockposition.getX(), l, blockposition_mutableblockposition.getZ()); - int i1 = this.b((BlockPosition) blockposition_mutableblockposition); - - if (i1 == 255 && blockposition_mutableblockposition.getY() < this.world.getSeaLevel()) { - flag1 = true; - } - - if (!flag && i1 > 0) { - flag = true; - } else if (flag && i1 == 0 && !this.world.w(blockposition_mutableblockposition)) { - return false; - } - } - - for (l = blockposition_mutableblockposition.getY(); l > 0; --l) { - blockposition_mutableblockposition.c(blockposition_mutableblockposition.getX(), l, blockposition_mutableblockposition.getZ()); - if (this.getBlockData(blockposition_mutableblockposition).d() > 0) { - this.world.w(blockposition_mutableblockposition); - } - } - - return true; - } - - public boolean p() { - return this.j; - } - - public World getWorld() { - return this.world; - } - - public int[] r() { - return this.heightMap; - } - - public void a(int[] aint) { - if (this.heightMap.length != aint.length) { - Chunk.e.warn("Could not set level chunk heightmap, array length is {} instead of {}", Integer.valueOf(aint.length), Integer.valueOf(this.heightMap.length)); - } else { - System.arraycopy(aint, 0, this.heightMap, 0, this.heightMap.length); - } - } - - public Map getTileEntities() { - return this.tileEntities; - } - - public List[] getEntitySlices() { - return this.entitySlices; - } - - public boolean isDone() { - return this.done; - } - - public void d(boolean flag) { - this.done = flag; - } - - public boolean v() { - return this.lit; - } - - public void e(boolean flag) { - this.lit = flag; - } - - public void f(boolean flag) { - this.s = flag; - } - - public void g(boolean flag) { - this.t = flag; - } - - public void setLastSaved(long i) { - this.lastSaved = i; - } - - public int w() { - return this.v; - } - - public long x() { - return world.paperConfig.useInhabitedTime ? this.w : 0; // Paper - } - - public void c(long i) { - this.w = i; - } - - // Paper start - public void runOrQueueLightUpdate(Runnable runnable) { - if (this.world.paperConfig.queueLightUpdates) { - lightingQueue.add(runnable); - } else { - runnable.run(); - } - } - // Paper end - - public static enum EnumTileEntityState { - - IMMEDIATE, QUEUED, CHECK; - - private EnumTileEntityState() {} - } -} diff --git a/sources/src/main/java/net/minecraft/server/ChunkProviderServer.java b/sources/src/main/java/net/minecraft/server/ChunkProviderServer.java deleted file mode 100644 index fd47c4d3d..000000000 --- a/sources/src/main/java/net/minecraft/server/ChunkProviderServer.java +++ /dev/null @@ -1,453 +0,0 @@ -package net.minecraft.server; - -import com.google.common.collect.Sets; - -import io.akarin.server.core.AkarinGlobalConfig; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectIterator; -import java.io.IOException; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import javax.annotation.Nullable; -import com.destroystokyo.paper.exception.ServerInternalException; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -// CraftBukkit start -import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor; -import org.bukkit.event.world.ChunkUnloadEvent; -// CraftBukkit end - -/** - * Akarin Changes Note - * 1) Async lighting (performance) - */ -public class ChunkProviderServer implements IChunkProvider { - - private static final Logger a = LogManager.getLogger(); - public final Set unloadQueue = Sets.newHashSet(); - public final ChunkGenerator chunkGenerator; - private final IChunkLoader chunkLoader; - // Paper start - chunk save stats - private long lastQueuedSaves = 0L; // Paper - private long lastProcessedSaves = 0L; // Paper - private long lastSaveStatPrinted = System.currentTimeMillis(); - // Paper end - // Paper start - protected Chunk lastChunkByPos = null; - public Long2ObjectOpenHashMap chunks = new Long2ObjectOpenHashMap(8192) { - - @Override - public Chunk get(long key) { - if (lastChunkByPos != null && key == lastChunkByPos.chunkKey) { - return lastChunkByPos; - } - return lastChunkByPos = super.get(key); - } - - @Override - public Chunk remove(long key) { - if (lastChunkByPos != null && key == lastChunkByPos.chunkKey) { - lastChunkByPos = null; - } - return super.remove(key); - } - }; // CraftBukkit - // Paper end - public final WorldServer world; - - public ChunkProviderServer(WorldServer worldserver, IChunkLoader ichunkloader, ChunkGenerator chunkgenerator) { - this.world = worldserver; - this.chunkLoader = ichunkloader; - this.chunkGenerator = chunkgenerator; - } - - public Collection a() { - return this.chunks.values(); - } - - public void unload(Chunk chunk) { - if (AkarinGlobalConfig.useAsyncLighting && chunk != null && (chunk.pendingLightUpdates.get() > 0 || chunk.world.getTime() - chunk.lightUpdateTime < 20)) return; // Akarin start - Re-add asynchronous lighting updates - if (this.world.worldProvider.c(chunk.locX, chunk.locZ)) { - this.unloadQueue.add(Long.valueOf(ChunkCoordIntPair.a(chunk.locX, chunk.locZ))); - chunk.d = true; - } - - } - - public void b() { - ObjectIterator objectiterator = this.chunks.values().iterator(); - - while (objectiterator.hasNext()) { - Chunk chunk = (Chunk) objectiterator.next(); - - this.unload(chunk); - } - - } - - @Nullable - public Chunk getLoadedChunkAt(int i, int j) { - long k = ChunkCoordIntPair.a(i, j); - Chunk chunk = (Chunk) this.chunks.get(k); - - if (chunk != null) { - chunk.d = false; - } - - return chunk; - } - - @Nullable - public Chunk getOrLoadChunkAt(int i, int j) { - Chunk chunk = this.getLoadedChunkAt(i, j); - - if (chunk == null) { - // CraftBukkit start - ChunkRegionLoader loader = null; - - if (this.chunkLoader instanceof ChunkRegionLoader) { - loader = (ChunkRegionLoader) this.chunkLoader; - } - if (loader != null && loader.chunkExists(i, j)) { - chunk = ChunkIOExecutor.syncChunkLoad(world, loader, this, i, j); - } - } - - return chunk; - } - - @Nullable - public Chunk originalGetOrLoadChunkAt(int i, int j) { - // CraftBukkit end - Chunk chunk = this.getLoadedChunkAt(i, j); - - if (chunk == null) { - chunk = this.loadChunk(i, j); - if (chunk != null) { - this.chunks.put(ChunkCoordIntPair.a(i, j), chunk); - chunk.addEntities(); - chunk.loadNearby(this, this.chunkGenerator, false); // CraftBukkit - } - } - - return chunk; - } - - // CraftBukkit start - public Chunk getChunkIfLoaded(int x, int z) { - return chunks.get(ChunkCoordIntPair.a(x, z)); - } - // CraftBukkit end - - public Chunk getChunkAt(int i, int j) { - return getChunkAt(i, j, null); - } - - public Chunk getChunkAt(int i, int j, Runnable runnable) { - return getChunkAt(i, j, runnable, true); - } - - public Chunk getChunkAt(int i, int j, Runnable runnable, boolean generate) { - Chunk chunk = world.paperConfig.allowPermaChunkLoaders ? getLoadedChunkAt(i, j) : getChunkIfLoaded(i, j); // Paper - Configurable perma chunk loaders - ChunkRegionLoader loader = null; - - if (this.chunkLoader instanceof ChunkRegionLoader) { - loader = (ChunkRegionLoader) this.chunkLoader; - - } - // We can only use the queue for already generated chunks - if (chunk == null && loader != null && loader.chunkExists(i, j)) { - if (runnable != null) { - ChunkIOExecutor.queueChunkLoad(world, loader, this, i, j, runnable); - return null; - } else { - chunk = ChunkIOExecutor.syncChunkLoad(world, loader, this, i, j); - - // Paper start - If there was an issue loading the chunk from region, stage1 will fail and stage2 will load it sync - // all we need to do is fetch an instance - if (chunk == null) { - chunk = getChunkIfLoaded(i, j); - } - // Paper end - } - } else if (chunk == null && generate) { - chunk = originalGetChunkAt(i, j); - } - - // If we didn't load the chunk async and have a callback run it now - if (runnable != null) { - runnable.run(); - } - - return chunk; - } - - public Chunk originalGetChunkAt(int i, int j) { - Chunk chunk = this.originalGetOrLoadChunkAt(i, j); - // CraftBukkit end - - if (chunk == null) { - world.timings.syncChunkLoadTimer.startTiming(); // Spigot - long k = ChunkCoordIntPair.a(i, j); - - try { - chunk = this.chunkGenerator.getOrCreateChunk(i, j); - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Exception generating new chunk"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Chunk to be generated"); - - crashreportsystemdetails.a("Location", (Object) String.format("%d,%d", new Object[] { Integer.valueOf(i), Integer.valueOf(j)})); - crashreportsystemdetails.a("Position hash", (Object) Long.valueOf(k)); - crashreportsystemdetails.a("Generator", (Object) this.chunkGenerator); - throw new ReportedException(crashreport); - } - - this.chunks.put(k, chunk); - chunk.addEntities(); - chunk.loadNearby(this, this.chunkGenerator, true); // CraftBukkit - world.timings.syncChunkLoadTimer.stopTiming(); // Spigot - } - - return chunk; - } - - @Nullable - public Chunk loadChunk(int i, int j) { - try { - Chunk chunk = this.chunkLoader.a(this.world, i, j); - - if (chunk != null) { - chunk.setLastSaved(this.world.getTime()); - this.chunkGenerator.recreateStructures(chunk, i, j); - } - - return chunk; - } catch (Exception exception) { - // Paper start - String msg = "Couldn\'t load chunk"; - ChunkProviderServer.a.error(msg, exception); - ServerInternalException.reportInternalException(exception); - // Paper end - return null; - } - } - - public void saveChunkNOP(Chunk chunk) { - try { - // this.chunkLoader.b(this.world, chunk); // Spigot - } catch (Exception exception) { - // Paper start - String msg = "Couldn\'t save entities"; - ChunkProviderServer.a.error(msg, exception); - ServerInternalException.reportInternalException(exception); - // Paper end - } - - } - - public void saveChunk(Chunk chunk, boolean unloaded) { // Spigot - try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { - chunk.setLastSaved(this.world.getTime()); - this.chunkLoader.saveChunk(this.world, chunk, unloaded); // Spigot - } catch (IOException ioexception) { - // Paper start - String msg = "Couldn\'t save chunk"; - ChunkProviderServer.a.error(msg, ioexception); - ServerInternalException.reportInternalException(ioexception); - } catch (ExceptionWorldConflict exceptionworldconflict) { - String msg = "Couldn\'t save chunk; already in use by another instance of Minecraft?"; - ChunkProviderServer.a.error(msg, exceptionworldconflict); - ServerInternalException.reportInternalException(exceptionworldconflict); - } - - } - - public boolean a(boolean flag) { - int i = 0; - - // CraftBukkit start - // Paper start - final ChunkRegionLoader chunkLoader = (ChunkRegionLoader) world.getChunkProviderServer().chunkLoader; - final int queueSize = chunkLoader.getQueueSize(); - - final long now = System.currentTimeMillis(); - final long timeSince = (now - lastSaveStatPrinted) / 1000; - final Integer printRateSecs = Integer.getInteger("printSaveStats"); - if (printRateSecs != null && timeSince >= printRateSecs) { - final String timeStr = "/" + timeSince +"s"; - final long queuedSaves = chunkLoader.getQueuedSaves(); - long queuedDiff = queuedSaves - lastQueuedSaves; - lastQueuedSaves = queuedSaves; - - final long processedSaves = chunkLoader.getProcessedSaves(); - long processedDiff = processedSaves - lastProcessedSaves; - lastProcessedSaves = processedSaves; - - lastSaveStatPrinted = now; - if (processedDiff > 0 || queueSize > 0 || queuedDiff > 0) { - System.out.println("[Chunk Save Stats] " + world.worldData.getName() + - " - Current: " + queueSize + - " - Queued: " + queuedDiff + timeStr + - " - Processed: " +processedDiff + timeStr - ); - } - } - - if (queueSize > world.paperConfig.queueSizeAutoSaveThreshold){ - return false; - } - final int autoSaveLimit = world.paperConfig.maxAutoSaveChunksPerTick; - // Paper end - Iterator iterator = this.chunks.values().iterator(); - while (iterator.hasNext()) { - Chunk chunk = (Chunk) iterator.next(); - // CraftBukkit end - - if (flag) { - this.saveChunkNOP(chunk); - } - - if (chunk.a(flag)) { - this.saveChunk(chunk, false); // Spigot - chunk.f(false); - ++i; - if (!flag && i >= autoSaveLimit) { // Spigot - // Paper - Incremental Auto Save - cap max per tick - return false; - } - } - } - - return true; - } - - public void c() { - this.chunkLoader.c(); - } - - private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; - - public boolean unloadChunks() { - if (!this.world.savingDisabled) { - if (!this.unloadQueue.isEmpty()) { - // Spigot start - org.spigotmc.SlackActivityAccountant activityAccountant = this.world.getMinecraftServer().slackActivityAccountant; - activityAccountant.startActivity(0.5); - int targetSize = Math.min(this.unloadQueue.size() - 100, (int) (this.unloadQueue.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive - // Spigot end - - Iterator iterator = this.unloadQueue.iterator(); - - while (iterator.hasNext()) { // Spigot - Long olong = (Long) iterator.next(); - iterator.remove(); // Spigot - Chunk chunk = (Chunk) this.chunks.get(olong); - - if (chunk != null && chunk.d) { - // CraftBukkit start - move unload logic to own method - chunk.setShouldUnload(false); // Paper - if (!unloadChunk(chunk, true)) { - continue; - } - // CraftBukkit end - - // Spigot start - if (this.unloadQueue.size() <= targetSize && activityAccountant.activityTimeIsExhausted()) { - break; - } - // Spigot end - } - } - - activityAccountant.endActivity(); // Spigot - } - // Paper start - delayed chunk unloads - long now = System.currentTimeMillis(); - long unloadAfter = world.paperConfig.delayChunkUnloadsBy; - if (unloadAfter > 0) { - //noinspection Convert2streamapi - for (Chunk chunk : chunks.values()) { - if (chunk.scheduledForUnload != null && now - chunk.scheduledForUnload > unloadAfter) { - chunk.scheduledForUnload = null; - unload(chunk); - } - } - } - // Paper end - - this.chunkLoader.b(); - } - - return false; - } - - // CraftBukkit start - public boolean unloadChunk(Chunk chunk, boolean save) { - ChunkUnloadEvent event = new ChunkUnloadEvent(chunk.bukkitChunk, save); - this.world.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return false; - } - save = event.isSaveChunk(); - chunk.lightingQueue.processUnload(); // Paper - - // Update neighbor counts - for (int x = -2; x < 3; x++) { - for (int z = -2; z < 3; z++) { - if (x == 0 && z == 0) { - continue; - } - - Chunk neighbor = this.getChunkIfLoaded(chunk.locX + x, chunk.locZ + z); - if (neighbor != null) { - neighbor.setNeighborUnloaded(-x, -z); - chunk.setNeighborUnloaded(x, z); - } - } - } - // Moved from unloadChunks above - chunk.removeEntities(); - if (save) { - this.saveChunk(chunk, true); // Spigot - this.saveChunkNOP(chunk); - } - this.chunks.remove(chunk.chunkKey); - return true; - } - // CraftBukkit end - - public boolean e() { - return !this.world.savingDisabled; - } - - public String getName() { - return "ServerChunkCache: " + this.chunks.size() + " Drop: " + this.unloadQueue.size(); - } - - public List a(EnumCreatureType enumcreaturetype, BlockPosition blockposition) { - return this.chunkGenerator.getMobsFor(enumcreaturetype, blockposition); - } - - @Nullable - public BlockPosition a(World world, String s, BlockPosition blockposition, boolean flag) { - return this.chunkGenerator.findNearestMapFeature(world, s, blockposition, flag); - } - - public boolean a(World world, String s, BlockPosition blockposition) { - return this.chunkGenerator.a(world, s, blockposition); - } - - public int g() { - return this.chunks.size(); - } - - public boolean isLoaded(int i, int j) { - return this.chunks.containsKey(ChunkCoordIntPair.a(i, j)); - } - - public boolean e(int i, int j) { - return this.chunks.containsKey(ChunkCoordIntPair.a(i, j)) || this.chunkLoader.chunkExists(i, j); - } -} diff --git a/sources/src/main/java/net/minecraft/server/NetworkManager.java b/sources/src/main/java/net/minecraft/server/NetworkManager.java index 047c67c29..6ad889847 100644 --- a/sources/src/main/java/net/minecraft/server/NetworkManager.java +++ b/sources/src/main/java/net/minecraft/server/NetworkManager.java @@ -21,7 +21,6 @@ import io.netty.util.concurrent.GenericFutureListener; import java.net.SocketAddress; import java.util.Queue; -import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.annotation.Nullable; import javax.crypto.SecretKey; import org.apache.commons.lang3.ArrayUtils; diff --git a/sources/src/main/java/net/minecraft/server/PlayerConnection.java b/sources/src/main/java/net/minecraft/server/PlayerConnection.java index f892a865e..f46487d5e 100644 --- a/sources/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/sources/src/main/java/net/minecraft/server/PlayerConnection.java @@ -81,6 +81,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { // CraftBukkit start - multithreaded fields private volatile int chatThrottle; private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); + private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits // CraftBukkit end private int j; private final IntHashMap k = new IntHashMap(); @@ -212,6 +213,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.minecraftServer.methodProfiler.b(); // CraftBukkit start for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; + if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable /* Use thread-safe field access instead if (this.chatThrottle > 0) { --this.chatThrottle; @@ -2293,7 +2295,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { // Paper start - async tab completion public void a(PacketPlayInTabComplete packet) { // CraftBukkit start - if (chatSpamField.addAndGet(this, 10) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { + if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { // Paper start - split and make configurable minecraftServer.postToMainThread(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); return; } diff --git a/sources/src/main/java/net/minecraft/server/RegistryID.java b/sources/src/main/java/net/minecraft/server/RegistryID.java index abae69b1e..91861e32a 100644 --- a/sources/src/main/java/net/minecraft/server/RegistryID.java +++ b/sources/src/main/java/net/minecraft/server/RegistryID.java @@ -7,7 +7,7 @@ import javax.annotation.Nullable; /** * Akarin Changes Note - * 1) BitSet for faster access (performance) + * 1) FastBitSet for faster access (performance) */ public class RegistryID implements Registry { diff --git a/sources/src/main/java/net/minecraft/server/World.java b/sources/src/main/java/net/minecraft/server/World.java deleted file mode 100644 index 54c2ce191..000000000 --- a/sources/src/main/java/net/minecraft/server/World.java +++ /dev/null @@ -1,3457 +0,0 @@ -package net.minecraft.server; - -import com.destroystokyo.paper.event.server.ServerExceptionEvent; -import com.destroystokyo.paper.exception.ServerInternalException; -import com.google.common.base.Function; -import com.google.common.base.MoreObjects; -import com.google.common.base.Predicate; -import com.google.common.collect.Lists; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Random; -import java.util.UUID; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import javax.annotation.Nullable; - -// CraftBukkit start -import com.google.common.collect.Maps; -import java.util.HashMap; // Paper -import java.util.Map; -import org.bukkit.Bukkit; -import org.bukkit.block.BlockState; -import org.bukkit.craftbukkit.CraftServer; -import org.bukkit.craftbukkit.CraftWorld; -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; -// CraftBukkit end - -// Paper start -import java.util.Set; -import com.destroystokyo.paper.antixray.ChunkPacketBlockController; // Anti-Xray -import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray; // Anti-Xray -import com.google.common.collect.Sets; -// Paper end -import com.google.common.util.concurrent.ThreadFactoryBuilder; - -import io.akarin.launcher.AkarinMixinConfig; -import io.akarin.server.core.AkarinGlobalConfig; - -/** - * Akarin Changes Note - * 1) Async lighting (performance) - */ -public abstract class World implements IBlockAccess { - - private int a = 63; - protected boolean d; - // 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(); - } - } - }; - // Spigot end - protected final Set f = Sets.newHashSet(); public Set getEntityUnloadQueue() { return f; };// Paper - OBFHELPER - //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list - public final List tileEntityListTick = Lists.newArrayList(); - private final List b = Lists.newArrayList(); - private final Set tileEntityListUnload = Sets.newHashSet(); // Paper - public final List players = Lists.newArrayList(); - public final List j = Lists.newArrayList(); - protected final IntHashMap entitiesById = new IntHashMap(); - private final long K = 16777215L; - private int L; private int getSkylightSubtracted() { return this.L; } // Paper - OBFHELPER - protected int l = (new Random()).nextInt(); - protected final int m = 1013904223; - protected float n; - protected float o; - protected float p; - protected float q; - private int M; - public final Random random = new Random(); - public WorldProvider worldProvider; - protected NavigationListener t = new NavigationListener(); - protected List u; - protected IChunkProvider chunkProvider; - protected final IDataManager dataManager; - public WorldData worldData; - protected boolean isLoading; - public PersistentCollection worldMaps; - protected PersistentVillage villages; - protected LootTableRegistry B; - protected AdvancementDataWorld C; - protected CustomFunctionData D; - public final MethodProfiler methodProfiler; - private final Calendar N; - public Scoreboard scoreboard; - public final boolean isClientSide; - public boolean allowMonsters; - public boolean allowAnimals; - private boolean O; - private final WorldBorder P; - int[] J; - - // CraftBukkit start Added the following - private final CraftWorld world; - 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 ) { - Iterator blockStateIterator = this.iterator(); - while( blockStateIterator.hasNext() ) { - BlockState blockState1 = blockStateIterator.next(); - if ( blockState1.getLocation().equals( blockState.getLocation() ) ) { - return false; - } - } - - return super.add( blockState ); - } - }; - public List captureDrops; - public long ticksPerAnimalSpawns; - public long ticksPerMonsterSpawns; - public boolean populating; - private int tickPosition; - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - - public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper - public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray - - public final co.aikar.timings.WorldTimingsHandler timings; // Paper - private boolean guardEntityList; // Spigot - public static boolean haveWeSilencedAPhysicsCrash; - public static String blockLocation; - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; - private int tileTickPosition; - public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions - - public CraftWorld getWorld() { - return this.world; - } - - public CraftServer getServer() { - return (CraftServer) Bukkit.getServer(); - } - - // Paper start - public Chunk getChunkIfLoaded(BlockPosition blockposition) { - return ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); - } - // Paper end - - public Chunk getChunkIfLoaded(int x, int z) { - return ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(x, z); - } - - // Akarin - Re-add asynchronous lighting updates - public ExecutorService lightingExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("Akarin - Async Lighting Thread").build()); - public boolean updateLight(final EnumSkyBlock enumskyblock, final BlockPosition position) { - int x = position.getX(); - int z = position.getZ(); - final Chunk chunk = this.getChunkIfLoaded(x >> 4, z >> 4); - if (chunk == null || !chunk.areNeighborsLoaded(1)) { - return false; - } - - if (!AkarinGlobalConfig.useAsyncLighting) { - return this.c(enumskyblock, position, chunk, null); - } - - chunk.pendingLightUpdates.incrementAndGet(); - chunk.lightUpdateTime = chunk.world.getTime(); - - final List neighbors = new ArrayList(); - for (int cx = (x >> 4) - 1; cx <= (x >> 4) + 1; ++cx) { - for (int cz = (z >> 4) - 1; cz <= (z >> 4) + 1; ++cz) { - if (cx != x >> 4 && cz != z >> 4) { - Chunk neighbor = this.getChunkIfLoaded(cx, cz); - if (neighbor != null) { - neighbor.pendingLightUpdates.incrementAndGet(); - neighbor.lightUpdateTime = chunk.world.getTime(); - neighbors.add(neighbor); - } - } - } - } - - if (!Bukkit.isPrimaryThread()) { - return this.c(enumskyblock, position, chunk, neighbors); - } - - lightingExecutor.submit(new Runnable() { - @Override - public void run() { - World.this.c(enumskyblock, position, chunk, neighbors); - } - }); - return true; - } - private int getLightForAsync(EnumSkyBlock lightType, BlockPosition pos, Chunk currentChunk, List neighbors) { - if (pos.getY() < 0) { - pos = new BlockPosition(pos.getX(), 0, pos.getZ()); - } - if (!pos.isValidLocation()) { - return lightType.c; // OBFHELPER: defaultLightValue - } - - final Chunk chunk = this.getLightChunk(pos, currentChunk, neighbors); - if (chunk == null || chunk.isUnloading()) { - return lightType.c; // OBFHELPER: defaultLightValue - } - - return chunk.getBrightness(lightType, pos); - } - public Chunk getLightChunk(BlockPosition pos, Chunk currentChunk, List neighbors) { - if (currentChunk.a(pos.getX() >> 4, pos.getZ() >> 4)) { // OBFHELPER: isAtLocation - if (currentChunk.isUnloading()) { - return null; - } - return currentChunk; - } - for (Chunk neighbor : neighbors) { - if (neighbor.a(pos.getX() >> 4, pos.getZ() >> 4)) { // OBFHELPER: isAtLocation - if (neighbor.isUnloading()) { - return null; - } - return neighbor; - } - } - - return null; - } - public void setLightForAsync(EnumSkyBlock type, BlockPosition pos, int lightValue, Chunk currentChunk, List neighbors) { - if (pos.isValidLocation()) { - final Chunk chunk = this.getLightChunk(pos, currentChunk, neighbors); - if (chunk != null && !chunk.isUnloading()) { - chunk.a(type, pos, lightValue); // OBFHELPER: setLightFor - // this.notifyLightSet(pos); // client side - } - } - } - private int getRawBlockLightAsync(BlockPosition pos, EnumSkyBlock lightType, Chunk currentChunk, List neighbors) { - final Chunk chunk = getLightChunk(pos, currentChunk, neighbors); - if (chunk == null || chunk.isUnloading()) { - return lightType.c; // OBFHELPER: defaultLightValue - } - if (lightType == EnumSkyBlock.SKY && chunk.c(pos)) { // OBFHELPER: canSeeSky - return 15; - } else { - IBlockData blockData = chunk.getBlockData(pos); - int blockLight = blockData.d(); // getLightValue - int rawLight = lightType == EnumSkyBlock.SKY ? 0 : blockLight; - int opacity = blockData.c(); // OBFHELPER: getLightOpacity - - if (opacity >= 15 && blockLight > 0) { - opacity = 1; - } - - if (opacity < 1) { - opacity = 1; - } - - if (opacity >= 15) { - return 0; - } else if (rawLight >= 14) { - return rawLight; - } else { - for (EnumDirection facing : EnumDirection.values()) { - BlockPosition blockpos = pos.shift(facing); - int current = this.getLightForAsync(lightType, blockpos, currentChunk, neighbors) - opacity; - - if (current > rawLight) { - rawLight = current; - } - - if (rawLight >= 14) { - return rawLight; - } - } - - return rawLight; - } - } - } - // Akarin 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.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(worlddata.getName(), this.spigotConfig); // Paper - this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this.paperConfig) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray - 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 - this.u = Lists.newArrayList(new IWorldAccess[] { this.t}); - this.N = Calendar.getInstance(); - this.scoreboard = new Scoreboard(); - this.allowMonsters = true; - this.allowAnimals = true; - this.J = new int['\u8000']; - this.dataManager = idatamanager; - this.methodProfiler = methodprofiler; - this.worldData = worlddata; - this.worldProvider = worldprovider; - this.isClientSide = flag; - this.P = worldprovider.getWorldBorder(); - // CraftBukkit start - getWorldBorder().world = (WorldServer) this; - // From PlayerList.setPlayerFileData - getWorldBorder().a(new IWorldBorderListener() { - public void a(WorldBorder worldborder, double d0) { - getServer().getHandle().sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.SET_SIZE), worldborder.world); - } - - public void a(WorldBorder worldborder, double d0, double d1, long i) { - getServer().getHandle().sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.LERP_SIZE), worldborder.world); - } - - public void a(WorldBorder worldborder, double d0, double d1) { - getServer().getHandle().sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.SET_CENTER), worldborder.world); - } - - public void a(WorldBorder worldborder, int i) { - getServer().getHandle().sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.SET_WARNING_TIME), worldborder.world); - } - - public void b(WorldBorder worldborder, int i) { - getServer().getHandle().sendAll(new PacketPlayOutWorldBorder(worldborder, PacketPlayOutWorldBorder.EnumWorldBorderAction.SET_WARNING_BLOCKS), worldborder.world); - } - - public void b(WorldBorder worldborder, double d0) {} - - public void c(WorldBorder worldborder, double d0) {} - }); - this.getServer().addWorld(this.world); - // CraftBukkit end - timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings - this.keepSpawnInMemory = this.paperConfig.keepSpawnInMemory; // Paper - this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } - - 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.k()); - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Getting biome"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Coordinates of biome request"); - - crashreportsystemdetails.a("Location", new CrashReportCallable() { - 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.k().getBiome(blockposition, Biomes.c); - } - } - - public WorldChunkManager getWorldChunkManager() { - return this.worldProvider.k(); - } - - protected abstract IChunkProvider n(); - - public void a(WorldSettings worldsettings) { - this.worldData.d(true); - } - - @Nullable - public MinecraftServer getMinecraftServer() { - return null; - } - - public IBlockData c(BlockPosition blockposition) { - BlockPosition blockposition1; - - for (blockposition1 = new BlockPosition(blockposition.getX(), this.getSeaLevel(), blockposition.getZ()); !this.isEmpty(blockposition1.up()); blockposition1 = blockposition1.up()) { - ; - } - - return this.getType(blockposition1); - } - - private static boolean isValidLocation(BlockPosition blockposition) { // Paper - unused but incase reflection / future uses - return blockposition.isValidLocation(); // Paper - } - - private static boolean E(BlockPosition blockposition) { // Paper - unused but incase reflection / future uses - return blockposition.isInvalidYLocation(); // Paper - } - - public boolean isEmpty(BlockPosition blockposition) { - return this.getType(blockposition).getMaterial() == Material.AIR; - } - - public boolean isLoaded(BlockPosition blockposition) { - return getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; // Paper - } - - public boolean a(BlockPosition blockposition, boolean flag) { - return 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 abstract boolean isChunkLoaded(int i, int j, boolean flag); - - public Chunk getChunkAtWorldCoords(BlockPosition blockposition) { - return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); - } - - public Chunk getChunkAt(int i, int j) { - return this.chunkProvider.getChunkAt(i, j); - } - - public boolean b(int i, int j) { - return this.isChunkLoaded(i, j, false) ? true : this.chunkProvider.e(i, j); - } - - 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 (blockposition.isInvalidYLocation()) { // Paper - 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); // Paper - blockstate = world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()).getState(); // Paper - use CB getState to get a suitable snapshot - 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 { - if (iblockdata.c() != iblockdata1.c() || iblockdata.d() != iblockdata1.d()) { - this.methodProfiler.a("checkLight"); - chunk.runOrQueueLightUpdate(() -> this.w(blockposition)); // Paper - Queue light update - this.methodProfiler.b(); - } - - /* - if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && chunk.isReady()) { - this.notify(blockposition, iblockdata1, iblockdata, i); - } - - if (!this.isClientSide && (i & 1) != 0) { - this.update(blockposition, iblockdata1.getBlock(), true); - if (iblockdata.n()) { - this.updateAdjacentComparators(blockposition, block); - } - } else if (!this.isClientSide && (i & 16) == 0) { - this.c(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, iblockdata1, iblockdata, i); - } - // CraftBukkit end - - return true; - } - } - } - - // CraftBukkit start - Split off from above in order to directly send client and physic updates - public void notifyAndUpdatePhysics(BlockPosition blockposition, Chunk chunk, IBlockData oldBlock, IBlockData newBlock, int i) { - if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 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, oldBlock, newBlock, i); - } - - if (!this.isClientSide && (i & 1) != 0) { - this.update(blockposition, oldBlock.getBlock(), true); - if (newBlock.n()) { - this.updateAdjacentComparators(blockposition, newBlock.getBlock()); - } - } else if (!this.isClientSide && (i & 16) == 0) { - this.c(blockposition, newBlock.getBlock()); - } - } - // CraftBukkit end - - 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 (iblockdata.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, IBlockData iblockdata, IBlockData iblockdata1, int i) { - for (int j = 0; j < this.u.size(); ++j) { - ((IWorldAccess) this.u.get(j)).a(this, blockposition, iblockdata, iblockdata1, i); - } - - } - - public void update(BlockPosition blockposition, Block block, boolean flag) { - if (this.worldData.getType() != WorldType.DEBUG_ALL_BLOCK_STATES) { - // CraftBukkit start - if (populating) { - return; - } - // CraftBukkit end - this.applyPhysics(blockposition, block, flag); - } - - } - - 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.m()) { - for (i1 = k; i1 <= l; ++i1) { - this.updateLight(EnumSkyBlock.SKY, new BlockPosition(i, i1, j)); // Akarin - Re-add asynchronous lighting updates - } - } - - 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) { - ((IWorldAccess) this.u.get(k1)).a(i, j, k, l, i1, j1); - } - - } - - public void c(BlockPosition blockposition, Block block) { - this.b(blockposition.west(), block, blockposition); - this.b(blockposition.east(), block, blockposition); - this.b(blockposition.down(), block, blockposition); - this.b(blockposition.up(), block, blockposition); - this.b(blockposition.north(), block, blockposition); - this.b(blockposition.south(), block, blockposition); - } - - public void applyPhysics(BlockPosition blockposition, Block block, boolean flag) { - if (captureBlockStates) { return; } // Paper - Cancel all physics during placement - this.a(blockposition.west(), block, blockposition); - this.a(blockposition.east(), block, blockposition); - this.a(blockposition.down(), block, blockposition); - this.a(blockposition.up(), block, blockposition); - this.a(blockposition.north(), block, blockposition); - this.a(blockposition.south(), block, blockposition); - if (flag) { - this.c(blockposition, block); - } - - this.chunkPacketBlockController.updateNearbyBlocks(this, blockposition); // Paper - Anti-Xray - } - - public void a(BlockPosition blockposition, Block block, EnumDirection enumdirection) { - if (enumdirection != EnumDirection.WEST) { - this.a(blockposition.west(), block, blockposition); - } - - if (enumdirection != EnumDirection.EAST) { - this.a(blockposition.east(), block, blockposition); - } - - if (enumdirection != EnumDirection.DOWN) { - this.a(blockposition.down(), block, blockposition); - } - - if (enumdirection != EnumDirection.UP) { - this.a(blockposition.up(), block, blockposition); - } - - if (enumdirection != EnumDirection.NORTH) { - this.a(blockposition.north(), block, blockposition); - } - - if (enumdirection != EnumDirection.SOUTH) { - this.a(blockposition.south(), block, blockposition); - } - - } - - public void a(BlockPosition blockposition, final Block block, BlockPosition blockposition1) { - if (!this.isClientSide) { - IBlockData iblockdata = this.getType(blockposition); - - try { - // CraftBukkit start - CraftWorld world = ((WorldServer) this).getWorld(); - if (world != null && !((WorldServer)this).stopPhysicsEvent) { // Paper - 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.doPhysics(this, blockposition, block, blockposition1); - } 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 CrashReportCallable() { - public String a() throws Exception { - try { - return String.format("ID #%d (%s // %s)", new Object[] { 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 void b(BlockPosition blockposition, final Block block, BlockPosition blockposition1) { - if (!this.isClientSide) { - IBlockData iblockdata = this.getType(blockposition); - - if (iblockdata.getBlock() == Blocks.dk) { - try { - ((BlockObserver) iblockdata.getBlock()).b(iblockdata, this, blockposition, block, blockposition1); - } 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 CrashReportCallable() { - public String a() throws Exception { - try { - return String.format("ID #%d (%s // %s)", new Object[] { 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 h(BlockPosition blockposition) { - return this.getChunkAtWorldCoords(blockposition).c(blockposition); - } - - public boolean i(BlockPosition blockposition) { - if (blockposition.getY() >= this.getSeaLevel()) { - return this.h(blockposition); - } else { - BlockPosition blockposition1 = new BlockPosition(blockposition.getX(), this.getSeaLevel(), blockposition.getZ()); - - if (!this.h(blockposition1)) { - return false; - } else { - for (blockposition1 = blockposition1.down(); blockposition1.getY() > blockposition.getY(); blockposition1 = blockposition1.down()) { - IBlockData iblockdata = this.getType(blockposition1); - - if (iblockdata.c() > 0 && !iblockdata.getMaterial().isLiquid()) { - return false; - } - } - - return true; - } - } - } - - public int j(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); - } - } - - // Paper start - test if meets light level, return faster - // logic copied from below - public boolean isLightLevel(BlockPosition blockposition, int level) { - if (blockposition.isValidLocation()) { - if (this.getType(blockposition).f()) { - if (this.c(blockposition.up(), false) >= level) { - return true; - } - if (this.c(blockposition.east(), false) >= level) { - return true; - } - if (this.c(blockposition.west(), false) >= level) { - return true; - } - if (this.c(blockposition.south(), false) >= level) { - return true; - } - if (this.c(blockposition.north(), false) >= level) { - return true; - } - return false; - } else { - if (blockposition.getY() >= 256) { - blockposition = new BlockPosition(blockposition.getX(), 255, blockposition.getZ()); - } - - Chunk chunk = this.getChunkAtWorldCoords(blockposition); - return chunk.getLightSubtracted(blockposition, this.getSkylightSubtracted()) >= level; - } - } else { - return true; - } - } - // Paper end - - public int getLightLevel(BlockPosition blockposition) { - return this.c(blockposition, true); - } - - public final int getLight(BlockPosition blockposition, boolean checkNeighbors) { return this.c(blockposition, checkNeighbors); } // Paper - OBFHELPER - 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).f()) { - 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()); - } - if (!this.isLoaded(blockposition)) return 0; // Paper - - Chunk chunk = this.getChunkAtWorldCoords(blockposition); - - return chunk.a(blockposition, this.L); - } - } else { - return 15; - } - } - - public BlockPosition getHighestBlockYAt(BlockPosition blockposition) { - return new BlockPosition(blockposition.getX(), this.c(blockposition.getX(), blockposition.getZ()), blockposition.getZ()); - } - - public int c(int i, int j) { - int k; - - if (i >= -30000000 && j >= -30000000 && i < 30000000 && j < 30000000) { - if (this.isChunkLoaded(i >> 4, j >> 4, true)) { - k = this.getChunkAt(i >> 4, j >> 4).b(i & 15, j & 15); - } else { - k = 0; - } - } else { - k = this.getSeaLevel() + 1; - } - - return k; - } - - @Deprecated - public int d(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.w(); - } - } else { - return this.getSeaLevel() + 1; - } - } - - public int getBrightness(EnumSkyBlock enumskyblock, BlockPosition blockposition) { - if (blockposition.getY() < 0) { - blockposition = new BlockPosition(blockposition.getX(), 0, blockposition.getZ()); - } - - if (!blockposition.isValidLocation()) { // Paper - 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 (blockposition.isValidLocation()) { // Paper - if (this.isLoaded(blockposition)) { - Chunk chunk = this.getChunkAtWorldCoords(blockposition); - - chunk.a(enumskyblock, blockposition, i); - this.m(blockposition); - } - } - } - - public void m(BlockPosition blockposition) { - for (int i = 0; i < this.u.size(); ++i) { - ((IWorldAccess) this.u.get(i)).a(blockposition); - } - - } - - public float n(BlockPosition blockposition) { - return this.worldProvider.o()[this.getLightLevel(blockposition)]; - } - - // Paper start - reduces need to do isLoaded before getType - public IBlockData getTypeIfLoaded(BlockPosition blockposition) { - // CraftBukkit start - tree generation - final int x = blockposition.getX(); - final int y = blockposition.getY(); - final int z = blockposition.getZ(); - if (captureTreeGeneration) { - final IBlockData previous = getCapturedBlockType(x, y, z); - if (previous != null) { - return previous; - } - } - // CraftBukkit end - Chunk chunk = ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(x >> 4, z >> 4); - if (chunk != null) { - return chunk.getBlockData(x, y, z); - } - return null; - } - // Paper end - - public IBlockData getType(BlockPosition blockposition) { - // CraftBukkit start - tree generation - // Paper start - optimize getType lookup to reduce instructions - getBlockData already enforces valid Y, move tree out - final int x = blockposition.getX(); - final int y = blockposition.getY(); - final int z = blockposition.getZ(); - if (captureTreeGeneration) { - final IBlockData previous = getCapturedBlockType(x, y, z); - if (previous != null) { - return previous; - } - } - // CraftBukkit end - return this.chunkProvider.getChunkAt(x >> 4, z >> 4).getBlockData(x, y, z); - // Paper end - } - - // Paper start - private IBlockData getCapturedBlockType(int x, int y, int z) { - Iterator it = capturedBlockStates.iterator(); - while (it.hasNext()) { - BlockState previous = it.next(); - if (previous.getX() == x && previous.getY() == y && previous.getZ() == z) { - return CraftMagicNumbers.getBlock(previous.getTypeId()).fromLegacyData(previous.getRawData()); - } - } - return null; - } - // Paper end - - public boolean D() { - return this.L < 4; - } - - @Nullable - public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1) { - return this.rayTrace(vec3d, vec3d1, false, false, false); - } - - @Nullable - public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag) { - return this.rayTrace(vec3d, vec3d1, flag, false, false); - } - - @Nullable - public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag, boolean flag1, boolean flag2) { - if (!Double.isNaN(vec3d.x) && !Double.isNaN(vec3d.y) && !Double.isNaN(vec3d.z)) { - if (!Double.isNaN(vec3d1.x) && !Double.isNaN(vec3d1.y) && !Double.isNaN(vec3d1.z)) { - int i = MathHelper.floor(vec3d1.x); - int j = MathHelper.floor(vec3d1.y); - int k = MathHelper.floor(vec3d1.z); - int l = MathHelper.floor(vec3d.x); - int i1 = MathHelper.floor(vec3d.y); - int j1 = MathHelper.floor(vec3d.z); - BlockPosition blockposition = new BlockPosition(l, i1, j1); - IBlockData iblockdata = this.getType(blockposition); - Block block = iblockdata.getBlock(); - - if ((!flag1 || iblockdata.d(this, blockposition) != Block.k) && block.a(iblockdata, flag)) { - MovingObjectPosition movingobjectposition = iblockdata.a(this, blockposition, vec3d, vec3d1); - - if (movingobjectposition != null) { - return movingobjectposition; - } - } - - MovingObjectPosition movingobjectposition1 = null; - int k1 = 200; - - while (k1-- >= 0) { - if (Double.isNaN(vec3d.x) || Double.isNaN(vec3d.y) || Double.isNaN(vec3d.z)) { - 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.x - vec3d.x; - double d7 = vec3d1.y - vec3d.y; - double d8 = vec3d1.z - vec3d.z; - - if (flag3) { - d3 = (d0 - vec3d.x) / d6; - } - - if (flag4) { - d4 = (d1 - vec3d.y) / d7; - } - - if (flag5) { - d5 = (d2 - vec3d.z) / 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.y + d7 * d3, vec3d.z + d8 * d3); - } else if (d4 < d5) { - enumdirection = j > i1 ? EnumDirection.DOWN : EnumDirection.UP; - vec3d = new Vec3D(vec3d.x + d6 * d4, d1, vec3d.z + d8 * d4); - } else { - enumdirection = k > j1 ? EnumDirection.NORTH : EnumDirection.SOUTH; - vec3d = new Vec3D(vec3d.x + d6 * d5, vec3d.y + d7 * d5, d2); - } - - l = MathHelper.floor(vec3d.x) - (enumdirection == EnumDirection.EAST ? 1 : 0); - i1 = MathHelper.floor(vec3d.y) - (enumdirection == EnumDirection.UP ? 1 : 0); - j1 = MathHelper.floor(vec3d.z) - (enumdirection == EnumDirection.SOUTH ? 1 : 0); - blockposition = new BlockPosition(l, i1, j1); - IBlockData iblockdata1 = this.getType(blockposition); - Block block1 = iblockdata1.getBlock(); - - if (!flag1 || iblockdata1.getMaterial() == Material.PORTAL || iblockdata1.d(this, blockposition) != Block.k) { - if (block1.a(iblockdata1, flag)) { - MovingObjectPosition movingobjectposition2 = iblockdata1.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 a(@Nullable EntityHuman entityhuman, BlockPosition blockposition, SoundEffect soundeffect, SoundCategory soundcategory, float f, float f1) { - this.a(entityhuman, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, soundeffect, soundcategory, f, f1); - } - - // Paper start - OBFHELPER - public final void sendSoundEffect(@Nullable EntityHuman fromEntity, double x, double y, double z, SoundEffect soundeffect, SoundCategory soundcategory, float volume, float pitch) { - this.a(fromEntity, x, y, z, soundeffect, soundcategory, volume, pitch); - } - // Paper end - - public void a(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, SoundEffect soundeffect, SoundCategory soundcategory, float f, float f1) { - for (int i = 0; i < this.u.size(); ++i) { - ((IWorldAccess) this.u.get(i)).a(entityhuman, soundeffect, soundcategory, d0, d1, d2, f, f1); - } - - } - - public void a(double d0, double d1, double d2, SoundEffect soundeffect, SoundCategory soundcategory, float f, float f1, boolean flag) {} - - public void a(BlockPosition blockposition, @Nullable SoundEffect soundeffect) { - for (int i = 0; i < this.u.size(); ++i) { - ((IWorldAccess) this.u.get(i)).a(soundeffect, 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); - } - - public void a(int i, double d0, double d1, double d2, double d3, double d4, double d5, int... aint) { - for (int j = 0; j < this.u.size(); ++j) { - ((IWorldAccess) this.u.get(j)).a(i, false, true, 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) { - ((IWorldAccess) this.u.get(j)).a(i, flag, d0, d1, d2, d3, d4, d5, aint); - } - - } - - public boolean strikeLightning(Entity entity) { - this.j.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; - if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper - - 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; - boolean isNpc = entity instanceof NPC; - - if (spawnReason != SpawnReason.CUSTOM) { - if (isAnimal && !allowAnimals || isMonster && !allowMonsters || isNpc && !getServer().getServer().getSpawnNPCs()) { - 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); - } else if (entity.getBukkitEntity() instanceof org.bukkit.entity.Vehicle){ - event = CraftEventFactory.callVehicleCreateEvent(entity); - } - // Spigot start - else if (entity instanceof EntityExperienceOrb) { - EntityExperienceOrb xp = (EntityExperienceOrb) entity; - double radius = spigotConfig.expMerge; - if (radius > 0) { - // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics - final int maxValue = paperConfig.expMergeMaxValue; - final boolean mergeUnconditionally = maxValue <= 0; - if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary - - 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 && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper - xp.value += loopItem.value; - // Paper start - if (!mergeUnconditionally && xp.value > maxValue) { - loopItem.value = xp.value - maxValue; - xp.value = maxValue; - break; - } - // Paper end - loopItem.die(); - } - } - } - - } // Paper end - End iteration skip check - All tweaking ends here - } - } // Spigot end - - if (event != null && (event.isCancelled() || entity.dead)) { - entity.dead = true; - return false; - } - // CraftBukkit end - - int i = MathHelper.floor(entity.locX / 16.0D); - int j = MathHelper.floor(entity.locZ / 16.0D); - boolean flag = entity.attachedToPlayer; - - // Paper start - Set origin location when the entity is being added to the world - if (entity.origin == null) { - entity.origin = entity.getBukkitEntity().getLocation(); - } - // Paper end - - if (entity instanceof EntityHuman) { - flag = true; - } - - if (!flag && !this.isChunkLoaded(i, j, false)) { - return false; - } else { - if (entity instanceof EntityHuman) { - EntityHuman entityhuman = (EntityHuman) entity; - - this.players.add(entityhuman); - this.everyoneSleeping(); - } - - this.getChunkAt(i, j).a(entity); - if (!entity.dead) this.entityList.add(entity); // Paper - don't add dead entities, chunk registration may of killed it - this.b(entity); - return true; - } - } - - protected void b(Entity entity) { - for (int i = 0; i < this.u.size(); ++i) { - ((IWorldAccess) this.u.get(i)).a(entity); - } - - entity.valid = true; // CraftBukkit - new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - } - - protected void c(Entity entity) { - for (int i = 0; i < this.u.size(); ++i) { - ((IWorldAccess) this.u.get(i)).b(entity); - } - - new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - entity.valid = false; // CraftBukkit - } - - public void kill(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp( "entity kill"); // Spigot - if (entity.isVehicle()) { - entity.ejectPassengers(); - } - - if (entity.isPassenger()) { - entity.stopRiding(); - } - - 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.k.remove( entity ); - for ( Iterator iter = (Iterator) map.i.iterator(); iter.hasNext(); ) - { - if ( iter.next().trackee == entity ) - { - map.decorations.remove(entity.getUniqueID()); // Paper - iter.remove(); - } - } - } - } - // Spigot end - this.everyoneSleeping(); - this.c(entity); - } - - } - - public void removeEntity(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp( "entity remove"); // Spigot - entity.b(false); - 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 // Paper - move down - int i = entity.ab; - int j = entity.ad; - - if (entity.aa && this.isChunkLoaded(i, j, true)) { - this.getChunkAt(i, j).b(entity); - } - entity.shouldBeRemoved = true; // Paper - - if (!guardEntityList) { // Spigot - It will get removed after the tick if we are ticking // Paper - always remove from current chunk above - // 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.c(entity); - } - - public void addIWorldAccess(IWorldAccess iworldaccess) { - this.u.add(iworldaccess); - } - - private boolean a(@Nullable Entity entity, AxisAlignedBB axisalignedbb, boolean flag, @Nullable List list) { - int i = MathHelper.floor(axisalignedbb.a) - 1; - int j = MathHelper.f(axisalignedbb.d) + 1; - int k = MathHelper.floor(axisalignedbb.b) - 1; - int l = MathHelper.f(axisalignedbb.e) + 1; - int i1 = MathHelper.floor(axisalignedbb.c) - 1; - int j1 = MathHelper.f(axisalignedbb.f) + 1; - WorldBorder worldborder = this.getWorldBorder(); - boolean flag1 = entity != null && entity.bz(); - boolean flag2 = entity != null && this.g(entity); - IBlockData iblockdata = Blocks.STONE.getBlockData(); - BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.s(); - - try { - for (int k1 = i; k1 < j; ++k1) { - for (int l1 = i1; l1 < j1; ++l1) { - boolean flag3 = k1 == i || k1 == j - 1; - boolean flag4 = l1 == i1 || l1 == j1 - 1; - - if ((!flag3 || !flag4) && this.isLoaded(blockposition_pooledblockposition.f(k1, 64, l1))) { - for (int i2 = k; i2 < l; ++i2) { - if (!flag3 && !flag4 || i2 != l - 1) { - if (flag) { - if (k1 < -30000000 || k1 >= 30000000 || l1 < -30000000 || l1 >= 30000000) { - boolean flag5 = true; - - return flag5; - } - } else if (entity != null && flag1 == flag2) { - entity.k(!flag2); - } - - blockposition_pooledblockposition.f(k1, i2, l1); - IBlockData iblockdata1; - - if (!flag && !worldborder.a((BlockPosition) blockposition_pooledblockposition) && flag2) { - iblockdata1 = iblockdata; - } else { - iblockdata1 = this.getType(blockposition_pooledblockposition); - } - - iblockdata1.a(this, blockposition_pooledblockposition, axisalignedbb, list, entity, false); - if (flag && !list.isEmpty()) { - boolean flag6 = true; - - return flag6; - } - } - } - } - } - } - - return !list.isEmpty(); - } finally { - blockposition_pooledblockposition.t(); - } - } - - public List getCubes(@Nullable Entity entity, AxisAlignedBB axisalignedbb) { - ArrayList arraylist = Lists.newArrayList(); - - this.a(entity, axisalignedbb, false, arraylist); - if (entity != null) { - if (entity instanceof EntityArmorStand && !entity.world.paperConfig.armorStandEntityLookups) return arraylist; // Paper - List list = this.getEntities(entity, axisalignedbb.g(0.25D)); - - for (int i = 0; i < list.size(); ++i) { - Entity entity1 = (Entity) list.get(i); - - if (!entity.x(entity1)) { - AxisAlignedBB axisalignedbb1 = entity1.al(); - - if (axisalignedbb1 != null && axisalignedbb1.c(axisalignedbb)) { - arraylist.add(axisalignedbb1); - } - - axisalignedbb1 = entity.j(entity1); - if (axisalignedbb1 != null && axisalignedbb1.c(axisalignedbb)) { - arraylist.add(axisalignedbb1); - } - } - } - } - - return arraylist; - } - - public boolean g(Entity entity) { - double d0 = this.P.b(); - double d1 = this.P.c(); - double d2 = this.P.d(); - double d3 = this.P.e(); - - if (entity.bz()) { - ++d0; - ++d1; - --d2; - --d3; - } else { - --d0; - --d1; - ++d2; - ++d3; - } - - return entity.locX > d0 && entity.locX < d2 && entity.locZ > d1 && entity.locZ < d3; - } - - public boolean a(AxisAlignedBB axisalignedbb) { - return this.a((Entity) null, axisalignedbb, true, Lists.newArrayList()); // CraftBukkit - decompile error - } - - public int a(float f) { - float f1 = this.c(f); - float f2 = 1.0F - (MathHelper.cos(f1 * 6.2831855F) * 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 G() { - return WorldProvider.a[this.worldProvider.a(this.worldData.getDayTime())]; - } - - public float d(float f) { - float f1 = this.c(f); - - return f1 * 6.2831855F; - } - - public BlockPosition p(BlockPosition blockposition) { - return this.getChunkAtWorldCoords(blockposition).f(blockposition); - } - - public BlockPosition q(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.getBlockData(blockposition2).getMaterial(); - - if (material.isSolid() && material != Material.LEAVES) { - break; - } - } - - return blockposition1; - } - - public boolean b(BlockPosition blockposition, Block block) { - return true; - } - - 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; - - for (i = 0; i < this.j.size(); ++i) { - entity = (Entity) this.j.get(i); - // CraftBukkit start - Fixed an NPE - if (entity == null) { - continue; - } - // CraftBukkit end - - try { - ++entity.ticksLived; - entity.B_(); - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Ticking entity"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being ticked"); - - if (entity == null) { - crashreportsystemdetails.a("Entity", (Object) "~~NULL~~"); - } else { - entity.appendEntityCrashDetails(crashreportsystemdetails); - } - - throw new ReportedException(crashreport); - } - - if (entity.dead) { - this.j.remove(i--); - } - } - - this.methodProfiler.c("remove"); - timings.entityRemoval.startTiming(); // Paper - this.entityList.removeAll(this.f); - - int j; - // Paper start - Set based removal lists - for (Entity e : this.f) { - /* - j = e.getChunkZ(); - int k = e.getChunkX(); - - if (e.isAddedToChunk() && this.isChunkLoaded(k, j, true)) { - this.getChunkAt(k, j).b(e); - }*/ - Chunk chunk = e.isAddedToChunk() ? e.getCurrentChunk() : null; - if (chunk != null) chunk.removeEntity(e); - } - - for (Entity e : this.f) { - this.c(e); - } - // Paper end - - this.f.clear(); - this.l(); - timings.entityRemoval.stopTiming(); // Paper - this.methodProfiler.c("regular"); - - CrashReportSystemDetails crashreportsystemdetails1; - CrashReport crashreport1; - - org.spigotmc.ActivationRange.activateEntities(this); // Spigot - timings.entityTick.startTiming(); // Spigot - guardEntityList = true; // Spigot - // CraftBukkit start - Use field for loop variable - co.aikar.timings.TimingHistory.entityTicks += this.entityList.size(); // Paper - int entitiesThisCycle = 0; - // Paper start - Disable tick limiters - //if (tickPosition < 0) tickPosition = 0; - for (tickPosition = 0; tickPosition < entityList.size(); tickPosition++) { - // Paper end - tickPosition = (tickPosition < entityList.size()) ? tickPosition : 0; - entity = (Entity) this.entityList.get(this.tickPosition); - // CraftBukkit end - Entity entity1 = entity.bJ(); - - if (entity1 != null) { - if (!entity1.dead && entity1.w(entity)) { - continue; - } - - entity.stopRiding(); - } - - this.methodProfiler.a("tick"); - if (!entity.dead && !(entity instanceof EntityPlayer)) { - try { - entity.tickTimer.startTiming(); // Paper - this.h(entity); - entity.tickTimer.stopTiming(); // Paper - } catch (Throwable throwable1) { - entity.tickTimer.stopTiming(); - // Paper start - Prevent tile entity and entity crashes - String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX + "," + entity.locY + "," + entity.locZ; - System.err.println(msg); - throwable1.printStackTrace(); - getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable1))); - entity.dead = true; - continue; - // Paper end - } - } - - this.methodProfiler.b(); - this.methodProfiler.a("remove"); - if (entity.dead) { - // Paper start - /* - j = entity.ab; - int l = entity.ad; - - /*if (entity.aa && this.isChunkLoaded(j, l, true)) { - this.getChunkAt(j, l).b(entity); - }*/ - Chunk chunk = entity.isAddedToChunk() ? entity.getCurrentChunk() : null; - if (chunk != null) chunk.removeEntity(entity); - // Paper end - - guardEntityList = false; // Spigot - this.entityList.remove(this.tickPosition--); // CraftBukkit - Use field for loop variable - guardEntityList = true; // Spigot - this.c(entity); - } - - this.methodProfiler.b(); - } - guardEntityList = false; // Spigot - - timings.entityTick.stopTiming(); // Spigot - this.methodProfiler.c("blockEntities"); - timings.tileEntityTick.startTiming(); // Spigot - if (!this.tileEntityListUnload.isEmpty()) { - // Paper start - Use alternate implementation with faster contains - java.util.Set toRemove = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); - toRemove.addAll(tileEntityListUnload); - this.tileEntityListTick.removeAll(toRemove); - // Paper end - //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list - this.tileEntityListUnload.clear(); - } - - this.O = true; - // Spigot start - // Iterator iterator = this.tileEntityListTick.iterator(); - int tilesThisCycle = 0; - for (tileTickPosition = 0; tileTickPosition < tileEntityListTick.size(); tileTickPosition++) { // Paper - Disable tick limiters - tileTickPosition = (tileTickPosition < tileEntityListTick.size()) ? tileTickPosition : 0; - TileEntity tileentity = (TileEntity) this.tileEntityListTick.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.tileEntityListTick.remove(tileTickPosition--); - continue; - } - // Spigot end - - if (!tileentity.y() && tileentity.u()) { - BlockPosition blockposition = tileentity.getPosition(); - - // Paper start - Skip ticking in chunks scheduled for unload - net.minecraft.server.Chunk chunk = tileentity.getCurrentChunk(); - boolean shouldTick = chunk != null; - if(this.paperConfig.skipEntityTickingInChunksScheduledForUnload) - shouldTick = shouldTick && !chunk.isUnloading() && chunk.scheduledForUnload == null; - if (shouldTick && this.P.a(blockposition)) { - // Paper end - try { - this.methodProfiler.a(() -> { - return String.valueOf(TileEntity.a(tileentity.getClass())); - }); - tileentity.tickTimer.startTiming(); // Spigot - ((ITickable) tileentity).e(); - this.methodProfiler.b(); - } catch (Throwable throwable2) { - // Paper start - Prevent tile entity and entity crashes - String msg = "TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ(); - System.err.println(msg); - throwable2.printStackTrace(); - getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable2))); - tilesThisCycle--; - this.tileEntityListTick.remove(tileTickPosition--); - continue; - // Paper end - } - // Spigot start - finally { - tileentity.tickTimer.stopTiming(); - } - // Spigot end - } - } - - if (tileentity.y()) { - tilesThisCycle--; - this.tileEntityListTick.remove(tileTickPosition--); - //this.tileEntityList.remove(tileentity); // Paper - remove unused list - // Paper start - net.minecraft.server.Chunk chunk = tileentity.getCurrentChunk(); - if (chunk != null) { - chunk.removeTileEntity(tileentity.getPosition()); - // Paper end - } - } - } - - timings.tileEntityTick.stopTiming(); // Spigot - timings.tileEntityPending.startTiming(); // Spigot - this.O = false; - this.methodProfiler.c("pendingBlockEntities"); - if (!this.b.isEmpty()) { - for (int i1 = 0; i1 < this.b.size(); ++i1) { - TileEntity tileentity1 = (TileEntity) this.b.get(i1); - - if (!tileentity1.y()) { - /* CraftBukkit start - Order matters, moved down - if (!this.tileEntityList.contains(tileentity1)) { - this.a(tileentity1); - } - // CraftBukkit end */ - - if (this.isLoaded(tileentity1.getPosition())) { - Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); - IBlockData iblockdata = chunk.getBlockData(tileentity1.getPosition()); - - chunk.a(tileentity1.getPosition(), tileentity1); - this.notify(tileentity1.getPosition(), iblockdata, iblockdata, 3); - // CraftBukkit start - // From above, don't screw this up - SPIGOT-1746 - if (true) { // Paper - remove unused list - this.a(tileentity1); - } - // CraftBukkit end - } - } - } - - this.b.clear(); - } - - timings.tileEntityPending.stopTiming(); // Spigot - co.aikar.timings.TimingHistory.tileEntityTicks += this.tileEntityListTick.size(); // Paper - this.methodProfiler.b(); - this.methodProfiler.b(); - } - - protected void l() {} - - public boolean a(TileEntity tileentity) { - boolean flag = true; // Paper - remove unused list - - if (flag && tileentity instanceof ITickable && !this.tileEntityListTick.contains(tileentity)) { // Paper - this.tileEntityListTick.add(tileentity); - } - - if (this.isClientSide) { - BlockPosition blockposition = tileentity.getPosition(); - IBlockData iblockdata = this.getType(blockposition); - - this.notify(blockposition, iblockdata, iblockdata, 2); - } - - return flag; - } - - public void b(Collection collection) { - if (this.O) { - this.b.addAll(collection); - } else { - Iterator iterator = collection.iterator(); - - while (iterator.hasNext()) { - TileEntity tileentity = (TileEntity) iterator.next(); - - this.a(tileentity); - } - } - - } - - public void h(Entity entity) { - this.entityJoinedWorld(entity, true); - } - - public void entityJoinedWorld(Entity entity, boolean flag) { - int i; - int j; - - // CraftBukkit start - check if chunks are loaded as done in previous versions - // TODO: Go back to Vanilla behaviour when comfortable - // Spigot start - // Chunk startingChunk = this.getChunkIfLoaded(MathHelper.floor(entity.locX) >> 4, MathHelper.floor(entity.locZ) >> 4); - if (flag && !org.spigotmc.ActivationRange.checkIfActive(entity)) { - entity.ticksLived++; - entity.inactiveTick(); - // Spigot end - return; - } - // CraftBukkit end - - entity.M = entity.locX; - entity.N = entity.locY; - entity.O = entity.locZ; - entity.lastYaw = entity.yaw; - entity.lastPitch = entity.pitch; - if (flag && entity.aa) { - ++entity.ticksLived; - ++co.aikar.timings.TimingHistory.activatedEntityTicks; // Paper - if (entity.isPassenger()) { - entity.aE(); - } else { - entity.B_(); - entity.postTick(); // CraftBukkit - } - } - - this.methodProfiler.a("chunkCheck"); - if (Double.isNaN(entity.locX) || Double.isInfinite(entity.locX)) { - entity.locX = entity.M; - } - - if (Double.isNaN(entity.locY) || Double.isInfinite(entity.locY)) { - entity.locY = entity.N; - } - - if (Double.isNaN(entity.locZ) || Double.isInfinite(entity.locZ)) { - entity.locZ = entity.O; - } - - if (Double.isNaN((double) entity.pitch) || Double.isInfinite((double) entity.pitch)) { - entity.pitch = entity.lastPitch; - } - - if (Double.isNaN((double) entity.yaw) || Double.isInfinite((double) entity.yaw)) { - entity.yaw = entity.lastYaw; - } - - i = MathHelper.floor(entity.locX / 16.0D); - j = Math.min(15, Math.max(0, MathHelper.floor(entity.locY / 16.0D))); // Paper - stay consistent with chunk add/remove behavior - int k = MathHelper.floor(entity.locZ / 16.0D); - - if (!entity.aa || entity.ab != i || entity.ac != j || entity.ad != k) { - if (entity.aa && this.isChunkLoaded(entity.ab, entity.ad, true)) { - this.getChunkAt(entity.ab, entity.ad).a(entity, entity.ac); - } - - if (false && !entity.bD() && !this.isChunkLoaded(i, k, true)) { // Paper - Always send entities into a new chunk, never lose them - entity.aa = false; - } else { - this.getChunkAt(i, k).a(entity); - } - } - - this.methodProfiler.b(); - if (flag && entity.aa) { - Iterator iterator = entity.bF().iterator(); - - while (iterator.hasNext()) { - Entity entity1 = (Entity) iterator.next(); - - if (!entity1.dead && entity1.bJ() == entity) { - this.h(entity1); - } else { - entity1.stopRiding(); - } - } - } - } - - public boolean b(AxisAlignedBB axisalignedbb) { - return this.a(axisalignedbb, (Entity) null); - } - - // Paper start - Based on method below - /** - * @param axisalignedbb area to search within - * @param entity causing the action ex. block placer - * @return if there are no visible players colliding - */ - public boolean checkNoVisiblePlayerCollisions(AxisAlignedBB axisalignedbb, @Nullable Entity entity) { - List list = this.getEntities((Entity) null, axisalignedbb); - - for (int i = 0; i < list.size(); ++i) { - Entity entity1 = (Entity) list.get(i); - - if (entity instanceof EntityPlayer && entity1 instanceof EntityPlayer) { - if (!((EntityPlayer) entity).getBukkitEntity().canSee(((EntityPlayer) entity1).getBukkitEntity())) { - continue; - } - } - - if (!entity1.dead && entity1.blocksEntitySpawning()) { - return false; - } - } - - return true; - } - // Paper end - - public boolean a(AxisAlignedBB axisalignedbb, @Nullable Entity entity) { - List list = this.getEntities((Entity) null, axisalignedbb); - - for (int i = 0; i < list.size(); ++i) { - Entity entity1 = (Entity) list.get(i); - - if (!entity1.dead && entity1.i && entity1 != entity && (entity == null || entity1.x(entity))) { - return false; - } - } - - return true; - } - - public boolean c(AxisAlignedBB axisalignedbb) { - int i = MathHelper.floor(axisalignedbb.a); - int j = MathHelper.f(axisalignedbb.d); - int k = MathHelper.floor(axisalignedbb.b); - int l = MathHelper.f(axisalignedbb.e); - int i1 = MathHelper.floor(axisalignedbb.c); - int j1 = MathHelper.f(axisalignedbb.f); - BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.s(); - - 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_pooledblockposition.f(k1, l1, i2)); - - if (iblockdata.getMaterial() != Material.AIR) { - blockposition_pooledblockposition.t(); - return true; - } - } - } - } - - blockposition_pooledblockposition.t(); - return false; - } - - public boolean containsLiquid(AxisAlignedBB axisalignedbb) { - int i = MathHelper.floor(axisalignedbb.a); - int j = MathHelper.f(axisalignedbb.d); - int k = MathHelper.floor(axisalignedbb.b); - int l = MathHelper.f(axisalignedbb.e); - int i1 = MathHelper.floor(axisalignedbb.c); - int j1 = MathHelper.f(axisalignedbb.f); - BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.s(); - - 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_pooledblockposition.f(k1, l1, i2)); - - if (iblockdata.getMaterial().isLiquid()) { - blockposition_pooledblockposition.t(); - return true; - } - } - } - } - - blockposition_pooledblockposition.t(); - return false; - } - - public boolean e(AxisAlignedBB axisalignedbb) { - int i = MathHelper.floor(axisalignedbb.a); - int j = MathHelper.f(axisalignedbb.d); - int k = MathHelper.floor(axisalignedbb.b); - int l = MathHelper.f(axisalignedbb.e); - int i1 = MathHelper.floor(axisalignedbb.c); - int j1 = MathHelper.f(axisalignedbb.f); - - if (this.isAreaLoaded(i, k, i1, j, l, j1, true)) { - BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.s(); - int k1 = i; - - while (true) { - if (k1 >= j) { - blockposition_pooledblockposition.t(); - break; - } - - for (int l1 = k; l1 < l; ++l1) { - for (int i2 = i1; i2 < j1; ++i2) { - Block block = this.getType(blockposition_pooledblockposition.f(k1, l1, i2)).getBlock(); - - if (block == Blocks.FIRE || block == Blocks.FLOWING_LAVA || block == Blocks.LAVA) { - blockposition_pooledblockposition.t(); - return true; - } - } - } - - ++k1; - } - } - - return false; - } - - public boolean a(AxisAlignedBB axisalignedbb, Material material, Entity entity) { - int i = MathHelper.floor(axisalignedbb.a); - int j = MathHelper.f(axisalignedbb.d); - int k = MathHelper.floor(axisalignedbb.b); - int l = MathHelper.f(axisalignedbb.e); - int i1 = MathHelper.floor(axisalignedbb.c); - int j1 = MathHelper.f(axisalignedbb.f); - - if (!this.isAreaLoaded(i, k, i1, j, l, j1, true)) { - return false; - } else { - boolean flag = false; - Vec3D vec3d = Vec3D.a; - BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.s(); - - for (int k1 = i; k1 < j; ++k1) { - for (int l1 = k; l1 < l; ++l1) { - for (int i2 = i1; i2 < j1; ++i2) { - blockposition_pooledblockposition.f(k1, l1, i2); - IBlockData iblockdata = this.getType(blockposition_pooledblockposition); - Block block = iblockdata.getBlock(); - - if (iblockdata.getMaterial() == material) { - double d0 = (double) ((float) (l1 + 1) - BlockFluids.b(((Integer) iblockdata.get(BlockFluids.LEVEL)).intValue())); - - if ((double) l >= d0) { - flag = true; - vec3d = block.a(this, (BlockPosition) blockposition_pooledblockposition, entity, vec3d); - } - } - } - } - } - - blockposition_pooledblockposition.t(); - if (vec3d.b() > 0.0D && entity.bo()) { - vec3d = vec3d.a(); - double d1 = 0.014D; - - entity.motX += vec3d.x * 0.014D; - entity.motY += vec3d.y * 0.014D; - entity.motZ += vec3d.z * 0.014D; - } - - return flag; - } - } - - public boolean a(AxisAlignedBB axisalignedbb, Material material) { - int i = MathHelper.floor(axisalignedbb.a); - int j = MathHelper.f(axisalignedbb.d); - int k = MathHelper.floor(axisalignedbb.b); - int l = MathHelper.f(axisalignedbb.e); - int i1 = MathHelper.floor(axisalignedbb.c); - int j1 = MathHelper.f(axisalignedbb.f); - BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.s(); - - 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_pooledblockposition.f(k1, l1, i2)).getMaterial() == material) { - blockposition_pooledblockposition.t(); - return true; - } - } - } - } - - blockposition_pooledblockposition.t(); - return false; - } - - public Explosion explode(@Nullable 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(@Nullable 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(@Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumDirection enumdirection) { - blockposition = blockposition.shift(enumdirection); - if (this.getType(blockposition).getBlock() == Blocks.FIRE) { - this.a(entityhuman, 1009, blockposition, 0); - this.setAir(blockposition); - return true; - } else { - return false; - } - } - - public Map capturedTileEntities = Maps.newHashMap(); - @Nullable - public TileEntity getTileEntity(BlockPosition blockposition) { - if (blockposition.isInvalidYLocation()) { // Paper - return null; - } else { - // CraftBukkit start - if (capturedTileEntities.containsKey(blockposition)) { - return capturedTileEntities.get(blockposition); - } - // CraftBukkit end - - TileEntity tileentity = null; - - if (this.O) { - tileentity = this.F(blockposition); - } - - if (tileentity == null) { - tileentity = this.getChunkAtWorldCoords(blockposition).a(blockposition, Chunk.EnumTileEntityState.IMMEDIATE); - } - - if (tileentity == null) { - tileentity = this.F(blockposition); - } - - return tileentity; - } - } - - @Nullable - private TileEntity F(BlockPosition blockposition) { - for (int i = 0; i < this.b.size(); ++i) { - TileEntity tileentity = (TileEntity) this.b.get(i); - - if (!tileentity.y() && tileentity.getPosition().equals(blockposition)) { - return tileentity; - } - } - - return null; - } - - public void setTileEntity(BlockPosition blockposition, @Nullable TileEntity tileentity) { - if (!blockposition.isInvalidYLocation()) { - if (tileentity != null && !tileentity.y()) { - // CraftBukkit start - if (captureBlockStates) { - tileentity.a(this); - tileentity.setPosition(blockposition); - capturedTileEntities.put(blockposition, tileentity); - return; - } - // CraftBukkit end - if (this.O) { - tileentity.setPosition(blockposition); - Iterator iterator = this.b.iterator(); - - while (iterator.hasNext()) { - TileEntity tileentity1 = (TileEntity) iterator.next(); - - if (tileentity1.getPosition().equals(blockposition)) { - tileentity1.z(); - iterator.remove(); - } - } - - tileentity.a(this); // Spigot - No null worlds - this.b.add(tileentity); - } else { - this.getChunkAtWorldCoords(blockposition).a(blockposition, tileentity); - this.a(tileentity); - } - } - - } - } - - public void s(BlockPosition blockposition) { - TileEntity tileentity = this.getTileEntity(blockposition); - - if (tileentity != null && this.O) { - tileentity.z(); - this.b.remove(tileentity); - } else { - if (tileentity != null) { - this.b.remove(tileentity); - //this.tileEntityList.remove(tileentity); // Paper - remove unused list - this.tileEntityListTick.remove(tileentity); - } - - this.getChunkAtWorldCoords(blockposition).d(blockposition); - } - - } - - public void b(TileEntity tileentity) { - this.tileEntityListUnload.add(tileentity); - } - - public boolean t(BlockPosition blockposition) { - AxisAlignedBB axisalignedbb = this.getType(blockposition).d(this, blockposition); - - return axisalignedbb != Block.k && axisalignedbb.a() >= 1.0D; - } - - public boolean d(BlockPosition blockposition, boolean flag) { - if (blockposition.isInvalidYLocation()) { // Paper - return false; - } else { - Chunk chunk = this.chunkProvider.getLoadedChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); - - if (chunk != null && !chunk.isEmpty()) { - IBlockData iblockdata = this.getType(blockposition); - - return iblockdata.getMaterial().k() && iblockdata.g(); - } else { - return flag; - } - } - } - - public void J() { - int i = this.a(1.0F); - - if (i != this.L) { - this.L = i; - } - - } - - public void setSpawnFlags(boolean flag, boolean flag1) { - this.allowMonsters = flag; - this.allowAnimals = flag1; - } - - public void doTick() { - this.t(); - } - - protected void K() { - if (this.worldData.hasStorm()) { - this.o = 1.0F; - if (this.worldData.isThundering()) { - this.q = 1.0F; - } - } - - } - - protected void t() { - if (this.worldProvider.m()) { - if (!this.isClientSide) { - boolean flag = this.getGameRules().getBoolean("doWeatherCycle"); - - if (flag) { - int i = this.worldData.z(); - - 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()); - } - } - - 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.p = this.q; - if (this.worldData.isThundering()) { - this.q = (float) ((double) this.q + 0.01D); - } else { - this.q = (float) ((double) this.q - 0.01D); - } - - this.q = MathHelper.a(this.q, 0.0F, 1.0F); - this.n = this.o; - if (this.worldData.hasStorm()) { - this.o = (float) ((double) this.o + 0.01D); - } else { - this.o = (float) ((double) this.o - 0.01D); - } - - this.o = MathHelper.a(this.o, 0.0F, 1.0F); - - // CraftBukkit start - for (int idx = 0; idx < this.players.size(); ++idx) { - if (((EntityPlayer) this.players.get(idx)).world == this) { - ((EntityPlayer) this.players.get(idx)).tickWeather(); - } - } - // CraftBukkit end - } - } - } - - protected void j() {} - - public void a(BlockPosition blockposition, IBlockData iblockdata, Random random) { - this.d = true; - iblockdata.getBlock().b(this, blockposition, iblockdata, random); - this.d = false; - } - - public boolean u(BlockPosition blockposition) { - return this.e(blockposition, false); - } - - public boolean v(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.getBrightness(EnumSkyBlock.BLOCK, blockposition) < 10) { - IBlockData iblockdata = this.getType(blockposition); - Block block = iblockdata.getBlock(); - - if ((block == Blocks.WATER || block == Blocks.FLOWING_WATER) && ((Integer) iblockdata.get(BlockFluids.LEVEL)).intValue() == 0) { - if (!flag) { - return true; - } - - boolean flag1 = this.G(blockposition.west()) && this.G(blockposition.east()) && this.G(blockposition.north()) && this.G(blockposition.south()); - - if (!flag1) { - return true; - } - } - } - - return false; - } - } - - private boolean G(BlockPosition blockposition) { - return this.getType(blockposition).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.getBrightness(EnumSkyBlock.BLOCK, blockposition) < 10) { - IBlockData iblockdata = this.getType(blockposition); - - if (iblockdata.getMaterial() == Material.AIR && Blocks.SNOW_LAYER.canPlace(this, blockposition)) { - return true; - } - } - - return false; - } - } - - public boolean w(BlockPosition blockposition) { - boolean flag = false; - - if (this.worldProvider.m()) { - flag |= this.updateLight(EnumSkyBlock.SKY, blockposition); // Akarin - Re-add asynchronous lighting updates - } - - flag |= this.updateLight(EnumSkyBlock.BLOCK, blockposition); // Akarin - Re-add asynchronous lighting updates - return flag; - } - - private int a(BlockPosition blockposition, EnumSkyBlock enumskyblock) { - if (enumskyblock == EnumSkyBlock.SKY && this.h(blockposition)) { - return 15; - } else { - IBlockData iblockdata = this.getType(blockposition); - int i = enumskyblock == EnumSkyBlock.SKY ? 0 : iblockdata.d(); - int j = iblockdata.c(); - - if (j >= 15 && iblockdata.d() > 0) { - j = 1; - } - - if (j < 1) { - j = 1; - } - - if (j >= 15) { - return 0; - } else if (i >= 14) { - return i; - } else { - BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.s(); - - try { - EnumDirection[] aenumdirection = EnumDirection.values(); - int k = aenumdirection.length; - - for (int l = 0; l < k; ++l) { - EnumDirection enumdirection = aenumdirection[l]; - - blockposition_pooledblockposition.j(blockposition).d(enumdirection); - int i1 = this.getBrightness(enumskyblock, blockposition_pooledblockposition) - j; - - if (i1 > i) { - i = i1; - } - - if (i >= 14) { - int j1 = i; - - return j1; - } - } - - return i; - } finally { - blockposition_pooledblockposition.t(); - } - } - } - } - - public boolean c(EnumSkyBlock enumskyblock, BlockPosition blockposition, Chunk chunk, List neighbors) { // Akarin - // CraftBukkit start - Use neighbor cache instead of looking up - // Chunk chunk = this.getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Akarin - if (chunk == null /*|| !chunk.areNeighborsLoaded(1)*/ /*!this.areChunksLoaded(blockposition, 17, false)*/) { // Akarin - // CraftBukkit end - return false; - } else { - int i = 0; - int j = 0; - - this.methodProfiler.a("getBrightness"); - int k = this.getLightForAsync(enumskyblock, blockposition, chunk, neighbors); // Akarin - int l = this.getRawBlockLightAsync(blockposition, enumskyblock, chunk, neighbors); // Akarin - 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.J[j++] = 133152; - } else if (l < k) { - this.J[j++] = 133152 | k << 18; - - while (i < j) { - l1 = this.J[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.getLightForAsync(enumskyblock, blockposition1, chunk, neighbors); // Akarin - if (l2 == l3) { - this.setLightForAsync(enumskyblock, blockposition1, 0, chunk, neighbors); // Akarin - if (l3 > 0) { - i3 = MathHelper.a(i2 - i1); - j3 = MathHelper.a(j2 - j1); - k3 = MathHelper.a(k2 - k1); - if (i3 + j3 + k3 < 17) { - BlockPosition.PooledBlockPosition blockposition_pooledblockposition = BlockPosition.PooledBlockPosition.s(); - 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_pooledblockposition.f(k4, l4, i5); - // Akarin start - final Chunk pooledChunk = this.getLightChunk(blockposition_pooledblockposition, chunk, neighbors); - if (pooledChunk == null) { - continue; - } - int j5 = Math.max(1, pooledChunk.getBlockData(blockposition_pooledblockposition).c()); // OBFHELPER: getLightOpacity - // Akarin end - - l2 = this.getLightForAsync(enumskyblock, blockposition_pooledblockposition, chunk, neighbors); // Akarin - if (l2 == l3 - j5 && j < this.J.length) { - this.J[j++] = k4 - i1 + 32 | l4 - j1 + 32 << 6 | i5 - k1 + 32 << 12 | l3 - j5 << 18; - } - } - - blockposition_pooledblockposition.t(); - } - } - } - } - - i = 0; - } - - this.methodProfiler.b(); - this.methodProfiler.a("checkedPosition < toCheckCount"); - - while (i < j) { - l1 = this.J[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.getLightForAsync(enumskyblock, blockposition2, chunk, neighbors); // Akarin - - l2 = this.getRawBlockLightAsync(blockposition2, enumskyblock, chunk, neighbors); // Akarin - if (l2 != k5) { - this.setLightForAsync(enumskyblock, blockposition2, l2, chunk, neighbors); // Akarin - if (l2 > k5) { - i3 = Math.abs(i2 - i1); - j3 = Math.abs(j2 - j1); - k3 = Math.abs(k2 - k1); - boolean flag = j < this.J.length - 6; - - if (i3 + j3 + k3 < 17 && flag) { - if (this.getLightForAsync(enumskyblock, blockposition2.west(), chunk, neighbors) < l2) { - this.J[j++] = i2 - 1 - i1 + 32 + (j2 - j1 + 32 << 6) + (k2 - k1 + 32 << 12); - } - - if (this.getLightForAsync(enumskyblock, blockposition2.east(), chunk, neighbors) < l2) { - this.J[j++] = i2 + 1 - i1 + 32 + (j2 - j1 + 32 << 6) + (k2 - k1 + 32 << 12); - } - - if (this.getLightForAsync(enumskyblock, blockposition2.down(), chunk, neighbors) < l2) { - this.J[j++] = i2 - i1 + 32 + (j2 - 1 - j1 + 32 << 6) + (k2 - k1 + 32 << 12); - } - - if (this.getLightForAsync(enumskyblock, blockposition2.up(), chunk, neighbors) < l2) { - this.J[j++] = i2 - i1 + 32 + (j2 + 1 - j1 + 32 << 6) + (k2 - k1 + 32 << 12); - } - - if (this.getLightForAsync(enumskyblock, blockposition2.north(), chunk, neighbors) < l2) { - this.J[j++] = i2 - i1 + 32 + (j2 - j1 + 32 << 6) + (k2 - 1 - k1 + 32 << 12); - } - - if (this.getLightForAsync(enumskyblock, blockposition2.south(), chunk, neighbors) < l2) { - this.J[j++] = i2 - i1 + 32 + (j2 - j1 + 32 << 6) + (k2 + 1 - k1 + 32 << 12); - } - } - } - } - } - - // Akarin start - Re-add asynchronous light updates - if (AkarinGlobalConfig.useAsyncLighting) { - chunk.pendingLightUpdates.decrementAndGet(); - if (neighbors != null) { - for (Chunk neighbor : neighbors) { - neighbor.pendingLightUpdates.decrementAndGet(); - } - } - } - // Akarin end - this.methodProfiler.b(); - return true; - } - } - - public boolean a(boolean flag) { - return false; - } - - @Nullable - public List a(Chunk chunk, boolean flag) { - return null; - } - - @Nullable - public List a(StructureBoundingBox structureboundingbox, boolean flag) { - return null; - } - - public List getEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb) { - return this.getEntities(entity, axisalignedbb, IEntitySelector.e); - } - - public List getEntities(@Nullable Entity entity, AxisAlignedBB axisalignedbb, @Nullable Predicate 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 oclass, Predicate predicate) { - ArrayList arraylist = Lists.newArrayList(); - Iterator iterator = this.entityList.iterator(); - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); - if (entity.shouldBeRemoved) continue; // Paper - - if (oclass.isAssignableFrom(entity.getClass()) && predicate.apply((T) entity)) { - arraylist.add(entity); - } - } - - return arraylist; - } - - public List b(Class oclass, Predicate 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 oclass, AxisAlignedBB axisalignedbb) { - return this.a(oclass, axisalignedbb, IEntitySelector.e); - } - - public List a(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { - int i = MathHelper.floor((axisalignedbb.a - 2.0D) / 16.0D); - int j = MathHelper.f((axisalignedbb.d + 2.0D) / 16.0D); - int k = MathHelper.floor((axisalignedbb.c - 2.0D) / 16.0D); - int l = MathHelper.f((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; - } - - @Nullable - public T a(Class 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.e.apply(entity1)) { - double d1 = t0.h(entity1); - - if (d1 <= d0) { - entity = entity1; - d0 = d1; - } - } - } - - return (T) entity; // CraftBukkit fix decompile error - } - - @Nullable - public Entity getEntity(int i) { - return (Entity) this.entitiesById.get(i); - } - - public void b(BlockPosition blockposition, TileEntity tileentity) { - if (this.isLoaded(blockposition)) { - this.getChunkAtWorldCoords(blockposition).markDirty(); - } - - } - - public int a(Class oclass) { - int i = 0; - Iterator iterator = this.entityList.iterator(); - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); - if (entity.shouldBeRemoved) continue; // Paper - // 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 a(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.b(entity); - } - - } - - public void c(Collection collection) { - this.f.addAll(collection); - } - - public boolean a(Block block, BlockPosition blockposition, boolean flag, EnumDirection enumdirection, @Nullable Entity entity) { - IBlockData iblockdata = this.getType(blockposition); - AxisAlignedBB axisalignedbb = flag ? null : block.getBlockData().d(this, blockposition); - - // CraftBukkit start - store default return - boolean defaultReturn = axisalignedbb != Block.k && !this.checkNoVisiblePlayerCollisions(axisalignedbb.a(blockposition), entity) ? false : (iblockdata.getMaterial() == Material.ORIENTABLE && block == Blocks.ANVIL ? true : iblockdata.getMaterial().isReplaceable() && block.canPlace(this, blockposition, enumdirection)); // Paper - Use our entity search - 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 getSeaLevel() { - return this.a; - } - - public void b(int i) { - this.a = i; - } - - public int getBlockPower(BlockPosition blockposition, EnumDirection enumdirection) { - return this.getType(blockposition).b(this, blockposition, enumdirection); - } - - public WorldType N() { - 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); - - return iblockdata.l() ? this.getBlockPower(blockposition) : iblockdata.a((IBlockAccess) this, blockposition, enumdirection); - } - - public boolean isBlockIndirectlyPowered(BlockPosition blockposition) { - return this.getBlockFacePower(blockposition.down(), EnumDirection.DOWN) > 0 ? true : (this.getBlockFacePower(blockposition.up(), EnumDirection.UP) > 0 ? true : (this.getBlockFacePower(blockposition.north(), EnumDirection.NORTH) > 0 ? true : (this.getBlockFacePower(blockposition.south(), EnumDirection.SOUTH) > 0 ? true : (this.getBlockFacePower(blockposition.west(), EnumDirection.WEST) > 0 ? true : this.getBlockFacePower(blockposition.east(), EnumDirection.EAST) > 0)))); - } - - public int z(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; - } - - @Nullable - public EntityHuman findNearbyPlayer(Entity entity, double d0) { - return this.a(entity.locX, entity.locY, entity.locZ, d0, false); - } - - @Nullable - public EntityHuman b(Entity entity, double d0) { - return this.a(entity.locX, entity.locY, entity.locZ, d0, true); - } - - @Nullable - public EntityHuman a(double d0, double d1, double d2, double d3, boolean flag) { - Predicate predicate = flag ? IEntitySelector.d : IEntitySelector.e; - - return this.a(d0, d1, d2, d3, predicate); - } - - @Nullable - public EntityHuman a(double d0, double d1, double d2, double d3, Predicate predicate) { - double d4 = -1.0D; - EntityHuman entityhuman = null; - - for (int i = 0; i < this.players.size(); ++i) { - EntityHuman entityhuman1 = (EntityHuman) this.players.get(i); - // CraftBukkit start - Fixed an NPE - if (entityhuman1 == null || entityhuman1.dead) { - continue; - } - // CraftBukkit end - - if (predicate.apply(entityhuman1)) { - double d5 = entityhuman1.d(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 = (EntityHuman) this.players.get(i); - - if (IEntitySelector.e.apply(entityhuman) && entityhuman.affectsSpawning) { // Paper - Affects Spawning API - double d4 = entityhuman.d(d0, d1, d2); - - if (d3 < 0.0D || d4 < d3 * d3) { - return true; - } - } - } - - return false; - } - - @Nullable - public EntityHuman a(Entity entity, double d0, double d1) { - return this.a(entity.locX, entity.locY, entity.locZ, d0, d1, (Function) null, (Predicate) null); - } - - @Nullable - public EntityHuman a(BlockPosition blockposition, double d0, double d1) { - return this.a((double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.5F), (double) ((float) blockposition.getZ() + 0.5F), d0, d1, (Function) null, (Predicate) null); - } - - @Nullable - public EntityHuman a(double d0, double d1, double d2, double d3, double d4, @Nullable Function function, @Nullable Predicate predicate) { - double d5 = -1.0D; - EntityHuman entityhuman = null; - - for (int i = 0; i < this.players.size(); ++i) { - EntityHuman entityhuman1 = (EntityHuman) this.players.get(i); - - if (!entityhuman1.abilities.isInvulnerable && entityhuman1.isAlive() && !entityhuman1.isSpectator() && (predicate == null || predicate.apply(entityhuman1))) { - double d6 = entityhuman1.d(d0, entityhuman1.locY, d2); - double d7 = d3; - - if (entityhuman1.isSneaking()) { - d7 = d3 * 0.800000011920929D; - } - - if (entityhuman1.isInvisible()) { - float f = entityhuman1.cW(); - - if (f < 0.1F) { - f = 0.1F; - } - - d7 *= (double) (0.7F * f); - } - - if (function != null) { - d7 *= ((Double) MoreObjects.firstNonNull(function.apply(entityhuman1), Double.valueOf(1.0D))).doubleValue(); - } - - if ((d4 < 0.0D || Math.abs(entityhuman1.locY - d1) < d4 * d4) && (d3 < 0.0D || d6 < d7 * d7) && (d5 == -1.0D || d6 < d5)) { - d5 = d6; - entityhuman = entityhuman1; - } - } - } - - return entityhuman; - } - - @Nullable - public EntityHuman a(String s) { - for (int i = 0; i < this.players.size(); ++i) { - EntityHuman entityhuman = (EntityHuman) this.players.get(i); - - if (s.equals(entityhuman.getName())) { - return entityhuman; - } - } - - return null; - } - - @Nullable - public EntityHuman b(UUID uuid) { - for (int i = 0; i < this.players.size(); ++i) { - EntityHuman 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.b(), this.worldData.c(), this.worldData.d()); - - if (!this.getWorldBorder().a(blockposition)) { - blockposition = this.getHighestBlockYAt(new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); - } - - return blockposition; - } - - public void A(BlockPosition blockposition) { - this.worldData.setSpawn(blockposition); - } - - public boolean a(EntityHuman entityhuman, BlockPosition blockposition) { - return true; - } - - public void broadcastEntityEffect(Entity entity, byte b0) {} - - public IChunkProvider getChunkProvider() { - return this.chunkProvider; - } - - public void playBlockAction(BlockPosition blockposition, Block block, int i, int j) { - this.getType(blockposition).a(this, blockposition, i, j); - } - - public IDataManager getDataManager() { - return this.dataManager; - } - - public WorldData getWorldData() { - return this.worldData; - } - - public GameRules getGameRules() { - return this.worldData.w(); - } - - 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.p + (this.q - this.p) * f) * this.j(f); - } - - public float j(float f) { - return this.n + (this.o - this.n) * f; - } - - public boolean X() { - return (double) this.h(1.0F) > 0.9D; - } - - public boolean isRaining() { - return (double) this.j(1.0F) > 0.2D; - } - - public boolean isRainingAt(BlockPosition blockposition) { - if (!this.isRaining()) { - return false; - } else if (!this.h(blockposition)) { - return false; - } else if (this.p(blockposition).getY() > blockposition.getY()) { - return false; - } else { - BiomeBase biomebase = this.getBiome(blockposition); - - return biomebase.c() ? false : (this.f(blockposition, false) ? false : biomebase.d()); - } - } - - public boolean C(BlockPosition blockposition) { - BiomeBase biomebase = this.getBiome(blockposition); - - return biomebase.e(); - } - - @Nullable - public PersistentCollection Z() { - return this.worldMaps; - } - - public void a(String s, PersistentBase persistentbase) { - this.worldMaps.a(s, persistentbase); - } - - @Nullable - public PersistentBase a(Class 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) { - ((IWorldAccess) this.u.get(k)).a(i, blockposition, j); - } - - } - - public void triggerEffect(int i, BlockPosition blockposition, int j) { - this.a((EntityHuman) null, i, blockposition, j); - } - - public void a(@Nullable EntityHuman entityhuman, int i, BlockPosition blockposition, int j) { - try { - for (int k = 0; k < this.u.size(); ++k) { - ((IWorldAccess) 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", (Object) CrashReportSystemDetails.a(blockposition)); - crashreportsystemdetails.a("Event source", (Object) entityhuman); - crashreportsystemdetails.a("Event type", (Object) Integer.valueOf(i)); - crashreportsystemdetails.a("Event data", (Object) Integer.valueOf(j)); - throw new ReportedException(crashreport); - } - } - - public int getHeight() { - return 256; - } - - public int ab() { - return this.worldProvider.n() ? 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 CrashReportSystemDetails a(CrashReport crashreport) { - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Affected level", 1); - - crashreportsystemdetails.a("Level name", (Object) (this.worldData == null ? "????" : this.worldData.getName())); - crashreportsystemdetails.a("All players", new CrashReportCallable() { - 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 CrashReportCallable() { - 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 = (IWorldAccess) this.u.get(k); - - iworldaccess.b(i, blockposition, j); - } - - } - - public Calendar ae() { - if (this.getTime() % 600L == 0L) { - this.N.setTimeInMillis(MinecraftServer.aw()); - } - - return this.N; - } - - public Scoreboard getScoreboard() { - return this.scoreboard; - } - - public void updateAdjacentComparators(BlockPosition blockposition, Block block) { - Iterator iterator = EnumDirection.EnumDirectionLimit.HORIZONTAL.iterator(); - - while (iterator.hasNext()) { - EnumDirection enumdirection = (EnumDirection) iterator.next(); - BlockPosition blockposition1 = blockposition.shift(enumdirection); - - if (this.isLoaded(blockposition1)) { - IBlockData iblockdata = this.getType(blockposition1); - - if (Blocks.UNPOWERED_COMPARATOR.D(iblockdata)) { - iblockdata.doPhysics(this, blockposition1, block, blockposition); - } else if (iblockdata.l()) { - blockposition1 = blockposition1.shift(enumdirection); - iblockdata = this.getType(blockposition1); - if (Blocks.UNPOWERED_COMPARATOR.D(iblockdata)) { - iblockdata.doPhysics(this, blockposition1, block, blockposition); - } - } - } - } - - } - - public DifficultyDamageScaler D(BlockPosition blockposition) { - long i = 0L; - float f = 0.0F; - - if (this.isLoaded(blockposition)) { - f = this.G(); - i = this.getChunkAtWorldCoords(blockposition).x(); - } - - return new DifficultyDamageScaler(this.getDifficulty(), this.getDayTime(), i, f); - } - - public EnumDifficulty getDifficulty() { - return this.getWorldData().getDifficulty(); - } - - public int ah() { - return this.L; - } - - public void c(int i) { - this.L = i; - } - - public void d(int i) { - this.M = i; - } - - public PersistentVillage ak() { - return this.villages; - } - - public WorldBorder getWorldBorder() { - return this.P; - } - - public boolean shouldStayLoaded(int i, int j) { return e(i, j); } // Paper - OBFHELPER - public boolean e(int i, int j) { - BlockPosition blockposition = this.getSpawn(); - int k = i * 16 + 8 - blockposition.getX(); - int l = j * 16 + 8 - blockposition.getZ(); - boolean flag = true; - short keepLoadedRange = paperConfig.keepLoadedRange; // Paper - - return k >= -keepLoadedRange && k <= keepLoadedRange && l >= -keepLoadedRange && l <= keepLoadedRange && this.keepSpawnInMemory; // CraftBukkit - Added 'this.keepSpawnInMemory' // Paper - Re-add range var // Akarin - } - - public void a(Packet packet) { - throw new UnsupportedOperationException("Can\'t send packets to server unless you\'re on the client."); - } - - public LootTableRegistry getLootTableRegistry() { - return this.B; - } - - @Nullable - public BlockPosition a(String s, BlockPosition blockposition, boolean flag) { - return null; - } -} diff --git a/work/Paper b/work/Paper index cfb71ab96..6d8a9763c 160000 --- a/work/Paper +++ b/work/Paper @@ -1 +1 @@ -Subproject commit cfb71ab9668944593ce618f7dbb0ee3aa0356030 +Subproject commit 6d8a9763c3cb522734bb3f39d5d04503e5e43113