aboutsummaryrefslogtreecommitdiffhomepage
path: root/patch-remap/mache-spigotflower/net/minecraft/world/level/Level.java.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patch-remap/mache-spigotflower/net/minecraft/world/level/Level.java.patch')
-rw-r--r--patch-remap/mache-spigotflower/net/minecraft/world/level/Level.java.patch1327
1 files changed, 1327 insertions, 0 deletions
diff --git a/patch-remap/mache-spigotflower/net/minecraft/world/level/Level.java.patch b/patch-remap/mache-spigotflower/net/minecraft/world/level/Level.java.patch
new file mode 100644
index 0000000000..247952ce1c
--- /dev/null
+++ b/patch-remap/mache-spigotflower/net/minecraft/world/level/Level.java.patch
@@ -0,0 +1,1327 @@
+--- a/net/minecraft/world/level/Level.java
++++ b/net/minecraft/world/level/Level.java
+@@ -28,6 +28,7 @@
+ import net.minecraft.resources.ResourceLocation;
+ import net.minecraft.server.MinecraftServer;
+ import net.minecraft.server.level.FullChunkStatus;
++import net.minecraft.server.level.ServerLevel;
+ import net.minecraft.sounds.SoundEvent;
+ import net.minecraft.sounds.SoundEvents;
+ import net.minecraft.sounds.SoundSource;
+@@ -42,6 +43,7 @@
+ import net.minecraft.world.entity.Entity;
+ import net.minecraft.world.entity.boss.EnderDragonPart;
+ import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
++import net.minecraft.world.entity.item.ItemEntity;
+ import net.minecraft.world.entity.player.Player;
+ import net.minecraft.world.item.ItemStack;
+ import net.minecraft.world.item.crafting.RecipeManager;
+@@ -52,13 +54,15 @@
+ import net.minecraft.world.level.block.Blocks;
+ import net.minecraft.world.level.block.entity.BlockEntity;
+ import net.minecraft.world.level.block.entity.TickingBlockEntity;
+-import net.minecraft.world.level.block.state.BlockState;
++import net.minecraft.world.level.block.state.IBlockData;
++import net.minecraft.world.level.border.BorderChangeListener;
+ import net.minecraft.world.level.border.WorldBorder;
+ import net.minecraft.world.level.chunk.ChunkAccess;
+ import net.minecraft.world.level.chunk.ChunkSource;
+ import net.minecraft.world.level.chunk.ChunkStatus;
+ import net.minecraft.world.level.chunk.LevelChunk;
+ import net.minecraft.world.level.dimension.DimensionType;
++import net.minecraft.world.level.dimension.LevelStem;
+ import net.minecraft.world.level.entity.EntityTypeTest;
+ import net.minecraft.world.level.entity.LevelEntityGetter;
+ import net.minecraft.world.level.gameevent.GameEvent;
+@@ -75,6 +79,27 @@
+ import net.minecraft.world.phys.Vec3;
+ import net.minecraft.world.scores.Scoreboard;
+
++// CraftBukkit start
++import java.util.HashMap;
++import java.util.Map;
++import net.minecraft.network.protocol.game.ClientboundSetBorderCenterPacket;
++import net.minecraft.network.protocol.game.ClientboundSetBorderLerpSizePacket;
++import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket;
++import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDelayPacket;
++import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePacket;
++import org.bukkit.Bukkit;
++import org.bukkit.Location;
++import org.bukkit.craftbukkit.CraftServer;
++import org.bukkit.craftbukkit.CraftWorld;
++import org.bukkit.craftbukkit.block.CapturedBlockState;
++import org.bukkit.craftbukkit.block.data.CraftBlockData;
++import org.bukkit.craftbukkit.util.CraftSpawnCategory;
++import org.bukkit.craftbukkit.util.CraftNamespacedKey;
++import org.bukkit.entity.SpawnCategory;
++import org.bukkit.event.block.BlockPhysicsEvent;
++import org.bukkit.event.world.GenericGameEvent;
++// CraftBukkit end
++
+ public abstract class Level implements LevelAccessor, AutoCloseable {
+
+ public static final Codec<ResourceKey<Level>> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION);
+@@ -92,22 +117,22 @@
+ protected final NeighborUpdater neighborUpdater;
+ private final List<TickingBlockEntity> pendingBlockEntityTickers = Lists.newArrayList();
+ private boolean tickingBlockEntities;
+- private final Thread thread;
++ public final Thread thread;
+ private final boolean isDebug;
+ private int skyDarken;
+ protected int randValue = RandomSource.create().nextInt();
+ protected final int addend = 1013904223;
+ protected float oRainLevel;
+- protected float rainLevel;
++ public float rainLevel;
+ protected float oThunderLevel;
+- protected float thunderLevel;
++ public float thunderLevel;
+ public final RandomSource random = RandomSource.create();
+ /** @deprecated */
+ @Deprecated
+ private final RandomSource threadSafeRandom = RandomSource.createThreadSafe();
+ private final ResourceKey<DimensionType> dimensionTypeId;
+ private final Holder<DimensionType> dimensionTypeRegistration;
+- protected final WritableLevelData levelData;
++ public final WritableLevelData levelData;
+ private final Supplier<ProfilerFiller> profiler;
+ public final boolean isClientSide;
+ private final WorldBorder worldBorder;
+@@ -117,29 +142,63 @@
+ private final DamageSources damageSources;
+ private long subTickCount;
+
+- protected Level(WritableLevelData writableleveldata, ResourceKey<Level> resourcekey, RegistryAccess registryaccess, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, int j) {
++ // CraftBukkit start Added the following
++ private final CraftWorld world;
++ public boolean pvpMode;
++ public boolean keepSpawnInMemory = true;
++ public org.bukkit.generator.ChunkGenerator generator;
++
++ public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710
++ public boolean captureBlockStates = false;
++ public boolean captureTreeGeneration = false;
++ public Map<BlockPos, CapturedBlockState> capturedBlockStates = new java.util.LinkedHashMap<>();
++ public Map<BlockPos, BlockEntity> capturedTileEntities = new HashMap<>();
++ public List<ItemEntity> captureDrops;
++ public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<SpawnCategory> ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>();
++ public boolean populating;
++
++ public CraftWorld getWorld() {
++ return this.world;
++ }
++
++ public CraftServer getCraftServer() {
++ return (CraftServer) Bukkit.getServer();
++ }
++
++ public abstract ResourceKey<LevelStem> getTypeKey();
++
++ protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, RegistryAccess iregistrycustom, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env) {
++ this.generator = gen;
++ this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env);
++
++ // CraftBukkit Ticks things
++ for (SpawnCategory spawnCategory : SpawnCategory.values()) {
++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) {
++ this.ticksPerSpawnCategory.put(spawnCategory, (long) this.getCraftServer().getTicksPerSpawns(spawnCategory));
++ }
++ }
++
++ // CraftBukkit end
+ this.profiler = supplier;
+- this.levelData = writableleveldata;
++ this.levelData = worlddatamutable;
+ this.dimensionTypeRegistration = holder;
+ this.dimensionTypeId = (ResourceKey) holder.unwrapKey().orElseThrow(() -> {
+ return new IllegalArgumentException("Dimension must be registered, got " + holder);
+ });
+- final DimensionType dimensiontype = (DimensionType) holder.value();
++ final DimensionType dimensionmanager = (DimensionType) holder.value();
+
+ this.dimension = resourcekey;
+ this.isClientSide = flag;
+- if (dimensiontype.coordinateScale() != 1.0D) {
++ if (dimensionmanager.coordinateScale() != 1.0D) {
+ this.worldBorder = new WorldBorder() {
+ @Override
+- @Override
+ public double getCenterX() {
+- return super.getCenterX() / dimensiontype.coordinateScale();
++ return super.getCenterX(); // CraftBukkit
+ }
+
+ @Override
+- @Override
+ public double getCenterZ() {
+- return super.getCenterZ() / dimensiontype.coordinateScale();
++ return super.getCenterZ(); // CraftBukkit
+ }
+ };
+ } else {
+@@ -150,189 +209,299 @@
+ this.biomeManager = new BiomeManager(this, i);
+ this.isDebug = flag1;
+ this.neighborUpdater = new CollectingNeighborUpdater(this, j);
+- this.registryAccess = registryaccess;
+- this.damageSources = new DamageSources(registryaccess);
++ this.registryAccess = iregistrycustom;
++ this.damageSources = new DamageSources(iregistrycustom);
++ // CraftBukkit start
++ getWorldBorder().world = (ServerLevel) this;
++ // From PlayerList.setPlayerFileData
++ getWorldBorder().addListener(new BorderChangeListener() {
++ @Override
++ public void onBorderSizeSet(WorldBorder border, double size) {
++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderSizePacket(border), border.world);
++ }
++
++ @Override
++ public void onBorderSizeLerping(WorldBorder border, double oldSize, double d1, long newSize) {
++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderLerpSizePacket(border), border.world);
++ }
++
++ @Override
++ public void onBorderCenterSet(WorldBorder border, double x, double d1) {
++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderCenterPacket(border), border.world);
++ }
++
++ @Override
++ public void onBorderSetWarningTime(WorldBorder border, int warningTime) {
++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDelayPacket(border), border.world);
++ }
++
++ @Override
++ public void onBorderSetWarningBlocks(WorldBorder border, int warningBlocks) {
++ getCraftServer().getHandle().broadcastAll(new ClientboundSetBorderWarningDistancePacket(border), border.world);
++ }
++
++ @Override
++ public void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) {}
++
++ @Override
++ public void onBorderSetDamageSafeZOne(WorldBorder border, double damageSafeZone) {}
++ });
++ // CraftBukkit end
+ }
+
+ @Override
+- @Override
+ public boolean isClientSide() {
+ return this.isClientSide;
+ }
+
+ @Nullable
+ @Override
+- @Override
+ public MinecraftServer getServer() {
+ return null;
+ }
+
+- public boolean isInWorldBounds(BlockPos blockpos) {
+- return !this.isOutsideBuildHeight(blockpos) && isInWorldBoundsHorizontal(blockpos);
++ public boolean isInWorldBounds(BlockPos pos) {
++ return !this.isOutsideBuildHeight(pos) && isInWorldBoundsHorizontal(pos);
+ }
+
+- public static boolean isInSpawnableBounds(BlockPos blockpos) {
+- return !isOutsideSpawnableHeight(blockpos.getY()) && isInWorldBoundsHorizontal(blockpos);
++ public static boolean isInSpawnableBounds(BlockPos pos) {
++ return !isOutsideSpawnableHeight(pos.getY()) && isInWorldBoundsHorizontal(pos);
+ }
+
+- private static boolean isInWorldBoundsHorizontal(BlockPos blockpos) {
+- return blockpos.getX() >= -30000000 && blockpos.getZ() >= -30000000 && blockpos.getX() < 30000000 && blockpos.getZ() < 30000000;
++ private static boolean isInWorldBoundsHorizontal(BlockPos pos) {
++ return pos.getX() >= -30000000 && pos.getZ() >= -30000000 && pos.getX() < 30000000 && pos.getZ() < 30000000;
+ }
+
+- private static boolean isOutsideSpawnableHeight(int i) {
+- return i < -20000000 || i >= 20000000;
++ private static boolean isOutsideSpawnableHeight(int y) {
++ return y < -20000000 || y >= 20000000;
+ }
+
+- public LevelChunk getChunkAt(BlockPos blockpos) {
+- return this.getChunk(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ()));
++ public LevelChunk getChunkAt(BlockPos pos) {
++ return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()));
+ }
+
+ @Override
+- @Override
+- public LevelChunk getChunk(int i, int j) {
+- return (LevelChunk) this.getChunk(i, j, ChunkStatus.FULL);
++ public LevelChunk getChunk(int chunkX, int chunkZ) {
++ return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL);
+ }
+
+ @Nullable
+ @Override
+- @Override
+- public ChunkAccess getChunk(int i, int j, ChunkStatus chunkstatus, boolean flag) {
+- ChunkAccess chunkaccess = this.getChunkSource().getChunk(i, j, chunkstatus, flag);
++ public ChunkAccess getChunk(int x, int z, ChunkStatus requiredStatus, boolean nonnull) {
++ ChunkAccess ichunkaccess = this.getChunkSource().getChunk(x, z, requiredStatus, nonnull);
+
+- if (chunkaccess == null && flag) {
++ if (ichunkaccess == null && nonnull) {
+ throw new IllegalStateException("Should always be able to create a chunk!");
+ } else {
+- return chunkaccess;
++ return ichunkaccess;
+ }
+ }
+
+ @Override
+- @Override
+- public boolean setBlock(BlockPos blockpos, BlockState blockstate, int i) {
+- return this.setBlock(blockpos, blockstate, i, 512);
++ public boolean setBlock(BlockPos pos, IBlockData newState, int flags) {
++ return this.setBlock(pos, newState, flags, 512);
+ }
+
+ @Override
+- @Override
+- public boolean setBlock(BlockPos blockpos, BlockState blockstate, int i, int j) {
+- if (this.isOutsideBuildHeight(blockpos)) {
++ public boolean setBlock(BlockPos pos, IBlockData state, int flags, int recursionLeft) {
++ // CraftBukkit start - tree generation
++ if (this.captureTreeGeneration) {
++ CapturedBlockState blockstate = capturedBlockStates.get(pos);
++ if (blockstate == null) {
++ blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags);
++ this.capturedBlockStates.put(pos.immutable(), blockstate);
++ }
++ blockstate.setData(state);
++ return true;
++ }
++ // CraftBukkit end
++ if (this.isOutsideBuildHeight(pos)) {
+ return false;
+ } else if (!this.isClientSide && this.isDebug()) {
+ return false;
+ } else {
+- LevelChunk levelchunk = this.getChunkAt(blockpos);
+- Block block = blockstate.getBlock();
+- BlockState blockstate1 = levelchunk.setBlockState(blockpos, blockstate, (i & 64) != 0);
++ LevelChunk chunk = this.getChunkAt(pos);
++ Block block = state.getBlock();
+
+- if (blockstate1 == null) {
++ // CraftBukkit start - capture blockstates
++ boolean captured = false;
++ if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) {
++ CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, pos, flags);
++ this.capturedBlockStates.put(pos.immutable(), blockstate);
++ captured = true;
++ }
++ // CraftBukkit end
++
++ IBlockData iblockdata1 = chunk.setBlockState(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag
++
++ if (iblockdata1 == null) {
++ // CraftBukkit start - remove blockstate if failed (or the same)
++ if (this.captureBlockStates && captured) {
++ this.capturedBlockStates.remove(pos);
++ }
++ // CraftBukkit end
+ return false;
+ } else {
+- BlockState blockstate2 = this.getBlockState(blockpos);
++ IBlockData iblockdata2 = this.getBlockState(pos);
+
+- if (blockstate2 == blockstate) {
+- if (blockstate1 != blockstate2) {
+- this.setBlocksDirty(blockpos, blockstate1, blockstate2);
++ /*
++ if (iblockdata2 == iblockdata) {
++ if (iblockdata1 != iblockdata2) {
++ this.setBlocksDirty(blockposition, iblockdata1, iblockdata2);
+ }
+
+- if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || levelchunk.getFullStatus() != null && levelchunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING))) {
+- this.sendBlockUpdated(blockpos, blockstate1, blockstate, i);
++ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING))) {
++ this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i);
+ }
+
+ if ((i & 1) != 0) {
+- this.blockUpdated(blockpos, blockstate1.getBlock());
+- if (!this.isClientSide && blockstate.hasAnalogOutputSignal()) {
+- this.updateNeighbourForOutputSignal(blockpos, block);
++ this.blockUpdated(blockposition, iblockdata1.getBlock());
++ if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) {
++ this.updateNeighbourForOutputSignal(blockposition, block);
+ }
+ }
+
+ if ((i & 16) == 0 && j > 0) {
+ int k = i & -34;
+
+- blockstate1.updateIndirectNeighbourShapes(this, blockpos, k, j - 1);
+- blockstate.updateNeighbourShapes(this, blockpos, k, j - 1);
+- blockstate.updateIndirectNeighbourShapes(this, blockpos, k, j - 1);
++ iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1);
++ iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1);
++ iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1);
+ }
+
+- this.onBlockStateChange(blockpos, blockstate1, blockstate2);
++ this.onBlockStateChange(blockposition, iblockdata1, iblockdata2);
+ }
++ */
+
++ // CraftBukkit start
++ if (!this.captureBlockStates) { // Don't notify clients or update physics while capturing blockstates
++ // Modularize client and physic updates
++ notifyAndUpdatePhysics(pos, chunk, iblockdata1, state, iblockdata2, flags, recursionLeft);
++ }
++ // CraftBukkit end
++
+ return true;
+ }
+ }
+ }
+
+- public void onBlockStateChange(BlockPos blockpos, BlockState blockstate, BlockState blockstate1) {}
++ // CraftBukkit start - Split off from above in order to directly send client and physic updates
++ public void notifyAndUpdatePhysics(BlockPos blockposition, LevelChunk chunk, IBlockData oldBlock, IBlockData newBlock, IBlockData actualBlock, int i, int j) {
++ IBlockData iblockdata = newBlock;
++ IBlockData iblockdata1 = oldBlock;
++ IBlockData iblockdata2 = actualBlock;
++ if (iblockdata2 == iblockdata) {
++ if (iblockdata1 != iblockdata2) {
++ this.setBlocksDirty(blockposition, iblockdata1, iblockdata2);
++ }
+
++ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement
++ this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i);
++ }
++
++ if ((i & 1) != 0) {
++ this.blockUpdated(blockposition, iblockdata1.getBlock());
++ if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) {
++ this.updateNeighbourForOutputSignal(blockposition, newBlock.getBlock());
++ }
++ }
++
++ if ((i & 16) == 0 && j > 0) {
++ int k = i & -34;
++
++ // CraftBukkit start
++ iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam
++ CraftWorld world = ((ServerLevel) this).getWorld();
++ if (world != null) {
++ BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata));
++ this.getCraftServer().getPluginManager().callEvent(event);
++
++ if (event.isCancelled()) {
++ return;
++ }
++ }
++ // CraftBukkit end
++ iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1);
++ iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1);
++ }
++
++ // CraftBukkit start - SPIGOT-5710
++ if (!preventPoiUpdated) {
++ this.onBlockStateChange(blockposition, iblockdata1, iblockdata2);
++ }
++ // CraftBukkit end
++ }
++ }
++ // CraftBukkit end
++
++ public void onBlockStateChange(BlockPos pos, IBlockData blockState, IBlockData newState) {}
++
+ @Override
+- @Override
+- public boolean removeBlock(BlockPos blockpos, boolean flag) {
+- FluidState fluidstate = this.getFluidState(blockpos);
++ public boolean removeBlock(BlockPos pos, boolean isMoving) {
++ FluidState fluid = this.getFluidState(pos);
+
+- return this.setBlock(blockpos, fluidstate.createLegacyBlock(), 3 | (flag ? 64 : 0));
++ return this.setBlock(pos, fluid.createLegacyBlock(), 3 | (isMoving ? 64 : 0));
+ }
+
+ @Override
+- @Override
+- public boolean destroyBlock(BlockPos blockpos, boolean flag, @Nullable Entity entity, int i) {
+- BlockState blockstate = this.getBlockState(blockpos);
++ public boolean destroyBlock(BlockPos pos, boolean dropBlock, @Nullable Entity entity, int recursionLeft) {
++ IBlockData iblockdata = this.getBlockState(pos);
+
+- if (blockstate.isAir()) {
++ if (iblockdata.isAir()) {
+ return false;
+ } else {
+- FluidState fluidstate = this.getFluidState(blockpos);
++ FluidState fluid = this.getFluidState(pos);
+
+- if (!(blockstate.getBlock() instanceof BaseFireBlock)) {
+- this.levelEvent(2001, blockpos, Block.getId(blockstate));
++ if (!(iblockdata.getBlock() instanceof BaseFireBlock)) {
++ this.levelEvent(2001, pos, Block.getId(iblockdata));
+ }
+
+- if (flag) {
+- BlockEntity blockentity = blockstate.hasBlockEntity() ? this.getBlockEntity(blockpos) : null;
++ if (dropBlock) {
++ BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null;
+
+- Block.dropResources(blockstate, this, blockpos, blockentity, entity, ItemStack.EMPTY);
++ Block.dropResources(iblockdata, this, pos, tileentity, entity, ItemStack.EMPTY);
+ }
+
+- boolean flag1 = this.setBlock(blockpos, fluidstate.createLegacyBlock(), 3, i);
++ boolean flag1 = this.setBlock(pos, fluid.createLegacyBlock(), 3, recursionLeft);
+
+ if (flag1) {
+- this.gameEvent(GameEvent.BLOCK_DESTROY, blockpos, GameEvent.Context.of(entity, blockstate));
++ this.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(entity, iblockdata));
+ }
+
+ return flag1;
+ }
+ }
+
+- public void addDestroyBlockEffect(BlockPos blockpos, BlockState blockstate) {}
++ public void addDestroyBlockEffect(BlockPos pos, IBlockData state) {}
+
+- public boolean setBlockAndUpdate(BlockPos blockpos, BlockState blockstate) {
+- return this.setBlock(blockpos, blockstate, 3);
++ public boolean setBlockAndUpdate(BlockPos pos, IBlockData state) {
++ return this.setBlock(pos, state, 3);
+ }
+
+- public abstract void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags);
++ public abstract void sendBlockUpdated(BlockPos pos, IBlockData oldState, IBlockData newState, int flags);
+
+- public void setBlocksDirty(BlockPos blockpos, BlockState blockstate, BlockState blockstate1) {}
++ public void setBlocksDirty(BlockPos blockPos, IBlockData oldState, IBlockData newState) {}
+
+- public void updateNeighborsAt(BlockPos blockpos, Block block) {}
++ public void updateNeighborsAt(BlockPos pos, Block block) {}
+
+- public void updateNeighborsAtExceptFromFacing(BlockPos blockpos, Block block, Direction direction) {}
++ public void updateNeighborsAtExceptFromFacing(BlockPos pos, Block blockType, Direction skipSide) {}
+
+- public void neighborChanged(BlockPos blockpos, Block block, BlockPos blockpos1) {}
++ public void neighborChanged(BlockPos pos, Block block, BlockPos fromPos) {}
+
+- public void neighborChanged(BlockState blockstate, BlockPos blockpos, Block block, BlockPos blockpos1, boolean flag) {}
++ public void neighborChanged(IBlockData state, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) {}
+
+ @Override
+- @Override
+- public void neighborShapeChanged(Direction direction, BlockState blockstate, BlockPos blockpos, BlockPos blockpos1, int i, int j) {
+- this.neighborUpdater.shapeUpdate(direction, blockstate, blockpos, blockpos1, i, j);
++ public void neighborShapeChanged(Direction direction, IBlockData queried, BlockPos pos, BlockPos offsetPos, int flags, int recursionLevel) {
++ this.neighborUpdater.shapeUpdate(direction, queried, pos, offsetPos, flags, recursionLevel);
+ }
+
+ @Override
+- @Override
+- public int getHeight(Heightmap.Types heightmap_types, int i, int j) {
++ public int getHeight(Heightmap.Types heightmapType, int x, int z) {
+ int k;
+
+- if (i >= -30000000 && j >= -30000000 && i < 30000000 && j < 30000000) {
+- if (this.hasChunk(SectionPos.blockToSectionCoord(i), SectionPos.blockToSectionCoord(j))) {
+- k = this.getChunk(SectionPos.blockToSectionCoord(i), SectionPos.blockToSectionCoord(j)).getHeight(heightmap_types, i & 15, j & 15) + 1;
++ if (x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000) {
++ if (this.hasChunk(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(z))) {
++ k = this.getChunk(SectionPos.blockToSectionCoord(x), SectionPos.blockToSectionCoord(z)).getHeight(heightmapType, x & 15, z & 15) + 1;
+ } else {
+ k = this.getMinBuildHeight();
+ }
+@@ -344,32 +513,37 @@
+ }
+
+ @Override
+- @Override
+ public LevelLightEngine getLightEngine() {
+ return this.getChunkSource().getLightEngine();
+ }
+
+ @Override
+- @Override
+- public BlockState getBlockState(BlockPos blockpos) {
+- if (this.isOutsideBuildHeight(blockpos)) {
++ public IBlockData getBlockState(BlockPos pos) {
++ // CraftBukkit start - tree generation
++ if (captureTreeGeneration) {
++ CapturedBlockState previous = capturedBlockStates.get(pos);
++ if (previous != null) {
++ return previous.getHandle();
++ }
++ }
++ // CraftBukkit end
++ if (this.isOutsideBuildHeight(pos)) {
+ return Blocks.VOID_AIR.defaultBlockState();
+ } else {
+- LevelChunk levelchunk = this.getChunk(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ()));
++ LevelChunk chunk = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()));
+
+- return levelchunk.getBlockState(blockpos);
++ return chunk.getBlockState(pos);
+ }
+ }
+
+ @Override
+- @Override
+- public FluidState getFluidState(BlockPos blockpos) {
+- if (this.isOutsideBuildHeight(blockpos)) {
++ public FluidState getFluidState(BlockPos pos) {
++ if (this.isOutsideBuildHeight(pos)) {
+ return Fluids.EMPTY.defaultFluidState();
+ } else {
+- LevelChunk levelchunk = this.getChunkAt(blockpos);
++ LevelChunk chunk = this.getChunkAt(pos);
+
+- return levelchunk.getFluidState(blockpos);
++ return chunk.getFluidState(pos);
+ }
+ }
+
+@@ -381,78 +555,76 @@
+ return !this.dimensionType().hasFixedTime() && !this.isDay();
+ }
+
+- public void playSound(@Nullable Entity entity, BlockPos blockpos, SoundEvent soundevent, SoundSource soundsource, float f, float f1) {
+- Player player;
++ public void playSound(@Nullable Entity entity, BlockPos pos, SoundEvent sound, SoundSource category, float volume, float pitch) {
++ Player entityhuman;
+
+ if (entity instanceof Player) {
+- Player player1 = (Player) entity;
++ Player entityhuman1 = (Player) entity;
+
+- player = player1;
++ entityhuman = entityhuman1;
+ } else {
+- player = null;
++ entityhuman = null;
+ }
+
+- this.playSound(player, blockpos, soundevent, soundsource, f, f1);
++ this.playSound(entityhuman, pos, sound, category, volume, pitch);
+ }
+
+ @Override
+- @Override
+- public void playSound(@Nullable Player player, BlockPos blockpos, SoundEvent soundevent, SoundSource soundsource, float f, float f1) {
+- this.playSound(player, (double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, soundevent, soundsource, f, f1);
++ public void playSound(@Nullable Player player, BlockPos pos, SoundEvent sound, SoundSource category, float volume, float pitch) {
++ this.playSound(player, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, sound, category, volume, pitch);
+ }
+
+- public abstract void playSeededSound(@Nullable Player player, double x, double d, double y, Holder<SoundEvent> holder, SoundSource z, float f, float sound, long source);
++ public abstract void playSeededSound(@Nullable Player player, double x, double d1, double y, Holder<SoundEvent> holder, SoundSource z, float f, float sound, long source);
+
+- public void playSeededSound(@Nullable Player player, double d0, double d1, double d2, SoundEvent soundevent, SoundSource soundsource, float f, float f1, long i) {
+- this.playSeededSound(player, d0, d1, d2, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(soundevent), soundsource, f, f1, i);
++ public void playSeededSound(@Nullable Player player, double x, double d1, double y, SoundEvent soundeffect, SoundSource z, float f, float sound, long source) {
++ this.playSeededSound(player, x, d1, y, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(soundeffect), z, f, sound, source);
+ }
+
+ public abstract void playSeededSound(@Nullable Player player, Entity entity, Holder<SoundEvent> sound, SoundSource category, float volume, float pitch, long seed);
+
+- public void playSound(@Nullable Player player, double d0, double d1, double d2, SoundEvent soundevent, SoundSource soundsource) {
+- this.playSound(player, d0, d1, d2, soundevent, soundsource, 1.0F, 1.0F);
++ public void playSound(@Nullable Player entityhuman, double d0, double d1, double d2, SoundEvent soundeffect, SoundSource soundcategory) {
++ this.playSound(entityhuman, d0, d1, d2, soundeffect, soundcategory, 1.0F, 1.0F);
+ }
+
+- public void playSound(@Nullable Player player, double d0, double d1, double d2, SoundEvent soundevent, SoundSource soundsource, float f, float f1) {
+- this.playSeededSound(player, d0, d1, d2, soundevent, soundsource, f, f1, this.threadSafeRandom.nextLong());
++ public void playSound(@Nullable Player player, double x, double d1, double y, SoundEvent soundeffect, SoundSource z, float f, float sound) {
++ this.playSeededSound(player, x, d1, y, soundeffect, z, f, sound, this.threadSafeRandom.nextLong());
+ }
+
+- public void playSound(@Nullable Player player, Entity entity, SoundEvent soundevent, SoundSource soundsource, float f, float f1) {
+- this.playSeededSound(player, entity, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(soundevent), soundsource, f, f1, this.threadSafeRandom.nextLong());
++ public void playSound(@Nullable Player player, Entity entity, SoundEvent event, SoundSource category, float volume, float pitch) {
++ this.playSeededSound(player, entity, BuiltInRegistries.SOUND_EVENT.wrapAsHolder(event), category, volume, pitch, this.threadSafeRandom.nextLong());
+ }
+
+- public void playLocalSound(BlockPos blockpos, SoundEvent soundevent, SoundSource soundsource, float f, float f1, boolean flag) {
+- this.playLocalSound((double) blockpos.getX() + 0.5D, (double) blockpos.getY() + 0.5D, (double) blockpos.getZ() + 0.5D, soundevent, soundsource, f, f1, flag);
++ public void playLocalSound(BlockPos pos, SoundEvent sound, SoundSource category, float volume, float pitch, boolean distanceDelay) {
++ this.playLocalSound((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, sound, category, volume, pitch, distanceDelay);
+ }
+
+- public void playLocalSound(Entity entity, SoundEvent soundevent, SoundSource soundsource, float f, float f1) {}
++ public void playLocalSound(Entity entity, SoundEvent soundeffect, SoundSource soundcategory, float f, float f1) {}
+
+- public void playLocalSound(double d0, double d1, double d2, SoundEvent soundevent, SoundSource soundsource, float f, float f1, boolean flag) {}
++ public void playLocalSound(double x, double d1, double y, SoundEvent soundeffect, SoundSource z, float f, float sound, boolean category) {}
+
+ @Override
+- @Override
+- public void addParticle(ParticleOptions particleoptions, double d0, double d1, double d2, double d3, double d4, double d5) {}
++ public void addParticle(ParticleOptions particleData, double x, double d1, double y, double d3, double z, double d5) {}
+
+- public void addParticle(ParticleOptions particleoptions, boolean flag, double d0, double d1, double d2, double d3, double d4, double d5) {}
++ public void addParticle(ParticleOptions particleData, boolean forceAlwaysRender, double x, double d1, double y, double d3, double z, double d5) {}
+
+- public void addAlwaysVisibleParticle(ParticleOptions particleoptions, double d0, double d1, double d2, double d3, double d4, double d5) {}
++ public void addAlwaysVisibleParticle(ParticleOptions particleData, double x, double d1, double y, double d3, double z, double d5) {}
+
+- public void addAlwaysVisibleParticle(ParticleOptions particleoptions, boolean flag, double d0, double d1, double d2, double d3, double d4, double d5) {}
++ public void addAlwaysVisibleParticle(ParticleOptions particleData, boolean ignoreRange, double x, double d1, double y, double d3, double z, double d5) {}
+
+- public float getSunAngle(float f) {
+- float f1 = this.getTimeOfDay(f);
++ public float getSunAngle(float partialTicks) {
++ float f1 = this.getTimeOfDay(partialTicks);
+
+ return f1 * 6.2831855F;
+ }
+
+- public void addBlockEntityTicker(TickingBlockEntity tickingblockentity) {
+- (this.tickingBlockEntities ? this.pendingBlockEntityTickers : this.blockEntityTickers).add(tickingblockentity);
++ public void addBlockEntityTicker(TickingBlockEntity ticker) {
++ (this.tickingBlockEntities ? this.pendingBlockEntityTickers : this.blockEntityTickers).add(ticker);
+ }
+
+ protected void tickBlockEntities() {
+- ProfilerFiller profilerfiller = this.getProfiler();
++ ProfilerFiller gameprofilerfiller = this.getProfiler();
+
+- profilerfiller.push("blockEntities");
++ gameprofilerfiller.push("blockEntities");
+ this.tickingBlockEntities = true;
+ if (!this.pendingBlockEntityTickers.isEmpty()) {
+ this.blockEntityTickers.addAll(this.pendingBlockEntityTickers);
+@@ -473,17 +645,17 @@
+ }
+
+ this.tickingBlockEntities = false;
+- profilerfiller.pop();
++ gameprofilerfiller.pop();
+ }
+
+- public <T extends Entity> void guardEntityTick(Consumer<T> consumer, T t0) {
++ public <T extends Entity> void guardEntityTick(Consumer<T> consumerEntity, T entity) {
+ try {
+- consumer.accept(t0);
++ consumerEntity.accept(entity);
+ } catch (Throwable throwable) {
+ CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity");
+- CrashReportCategory crashreportcategory = crashreport.addCategory("Entity being ticked");
++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked");
+
+- t0.fillCrashReportCategory(crashreportcategory);
++ entity.fillCrashReportCategory(crashreportsystemdetails);
+ throw new ReportedException(crashreport);
+ }
+ }
+@@ -492,108 +664,123 @@
+ return true;
+ }
+
+- public boolean shouldTickBlocksAt(long i) {
++ public boolean shouldTickBlocksAt(long chunkPos) {
+ return true;
+ }
+
+- public boolean shouldTickBlocksAt(BlockPos blockpos) {
+- return this.shouldTickBlocksAt(ChunkPos.asLong(blockpos));
++ public boolean shouldTickBlocksAt(BlockPos pos) {
++ return this.shouldTickBlocksAt(ChunkPos.asLong(pos));
+ }
+
+- public Explosion explode(@Nullable Entity entity, double d0, double d1, double d2, float f, Level.ExplosionInteraction level_explosioninteraction) {
+- return this.explode(entity, Explosion.getDefaultDamageSource(this, entity), (ExplosionDamageCalculator) null, d0, d1, d2, f, false, level_explosioninteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE);
++ public Explosion explode(@Nullable Entity source, double x, double d1, double y, float f, Level.a z) {
++ return this.explode(source, Explosion.getDefaultDamageSource(this, source), (ExplosionDamageCalculator) null, x, d1, y, f, false, z, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE);
+ }
+
+- public Explosion explode(@Nullable Entity entity, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction) {
+- return this.explode(entity, Explosion.getDefaultDamageSource(this, entity), (ExplosionDamageCalculator) null, d0, d1, d2, f, flag, level_explosioninteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE);
++ public Explosion explode(@Nullable Entity source, double x, double d1, double y, float f, boolean z, Level.a world_a) {
++ return this.explode(source, Explosion.getDefaultDamageSource(this, source), (ExplosionDamageCalculator) null, x, d1, y, f, z, world_a, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE);
+ }
+
+- public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, Vec3 vec3, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction) {
+- return this.explode(entity, damagesource, explosiondamagecalculator, vec3.x(), vec3.y(), vec3.z(), f, flag, level_explosioninteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE);
++ public Explosion explode(@Nullable Entity source, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator damageCalculator, Vec3 pos, float radius, boolean fire, Level.a explosionInteraction) {
++ return this.explode(source, damageSource, damageCalculator, pos.x(), pos.y(), pos.z(), radius, fire, explosionInteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE);
+ }
+
+- public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction) {
+- return this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, level_explosioninteraction, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE);
++ public Explosion explode(@Nullable Entity source, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator damageCalculator, double x, double d1, double y, float f, boolean z, Level.a world_a) {
++ return this.explode(source, damageSource, damageCalculator, x, d1, y, f, z, world_a, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE);
+ }
+
+- public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction, ParticleOptions particleoptions, ParticleOptions particleoptions1, SoundEvent soundevent) {
+- return this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, level_explosioninteraction, true, particleoptions, particleoptions1, soundevent);
++ public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.a world_a, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) {
++ return this.explode(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, world_a, true, particleparam, particleparam1, soundeffect);
+ }
+
+- public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.ExplosionInteraction level_explosioninteraction, boolean flag1, ParticleOptions particleoptions, ParticleOptions particleoptions1, SoundEvent soundevent) {
+- Explosion.BlockInteraction explosion_blockinteraction;
++ public Explosion explode(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Level.a world_a, boolean flag1, ParticleOptions particleparam, ParticleOptions particleparam1, SoundEvent soundeffect) {
++ Explosion.Effect explosion_effect;
+
+- switch (level_explosioninteraction) {
++ switch (world_a) {
+ case NONE:
+- explosion_blockinteraction = Explosion.BlockInteraction.KEEP;
++ explosion_effect = Explosion.Effect.KEEP;
+ break;
+ case BLOCK:
+- explosion_blockinteraction = this.getDestroyType(GameRules.RULE_BLOCK_EXPLOSION_DROP_DECAY);
++ explosion_effect = this.getDestroyType(GameRules.RULE_BLOCK_EXPLOSION_DROP_DECAY);
+ break;
+ case MOB:
+- explosion_blockinteraction = this.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? this.getDestroyType(GameRules.RULE_MOB_EXPLOSION_DROP_DECAY) : Explosion.BlockInteraction.KEEP;
++ explosion_effect = this.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? this.getDestroyType(GameRules.RULE_MOB_EXPLOSION_DROP_DECAY) : Explosion.Effect.KEEP;
+ break;
+ case TNT:
+- explosion_blockinteraction = this.getDestroyType(GameRules.RULE_TNT_EXPLOSION_DROP_DECAY);
++ explosion_effect = this.getDestroyType(GameRules.RULE_TNT_EXPLOSION_DROP_DECAY);
+ break;
+ case BLOW:
+- explosion_blockinteraction = Explosion.BlockInteraction.TRIGGER_BLOCK;
++ explosion_effect = Explosion.Effect.TRIGGER_BLOCK;
+ break;
+ default:
+ throw new IncompatibleClassChangeError();
+ }
+
+- Explosion.BlockInteraction explosion_blockinteraction1 = explosion_blockinteraction;
+- Explosion explosion = new Explosion(this, entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, explosion_blockinteraction1, particleoptions, particleoptions1, soundevent);
++ Explosion.Effect explosion_effect1 = explosion_effect;
++ Explosion explosion = new Explosion(this, entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, explosion_effect1, particleparam, particleparam1, soundeffect);
+
+ explosion.explode();
+ explosion.finalizeExplosion(flag1);
+ return explosion;
+ }
+
+- private Explosion.BlockInteraction getDestroyType(GameRules.Key<GameRules.BooleanValue> gamerules_key) {
+- return this.getGameRules().getBoolean(gamerules_key) ? Explosion.BlockInteraction.DESTROY_WITH_DECAY : Explosion.BlockInteraction.DESTROY;
++ private Explosion.Effect getDestroyType(GameRules.Key<GameRules.BooleanValue> gameRule) {
++ return this.getGameRules().getBoolean(gameRule) ? Explosion.Effect.DESTROY_WITH_DECAY : Explosion.Effect.DESTROY;
+ }
+
+ public abstract String gatherChunkSourceStats();
+
+ @Nullable
+ @Override
+- @Override
+- public BlockEntity getBlockEntity(BlockPos blockpos) {
+- return this.isOutsideBuildHeight(blockpos) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockpos).getBlockEntity(blockpos, LevelChunk.EntityCreationType.IMMEDIATE));
++ public BlockEntity getBlockEntity(BlockPos pos) {
++ // CraftBukkit start
++ return getBlockEntity(pos, true);
+ }
+
+- public void setBlockEntity(BlockEntity blockentity) {
+- BlockPos blockpos = blockentity.getBlockPos();
++ @Nullable
++ public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) {
++ if (capturedTileEntities.containsKey(blockposition)) {
++ return capturedTileEntities.get(blockposition);
++ }
++ // CraftBukkit end
++ return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EnumTileEntityState.IMMEDIATE));
++ }
+
+- if (!this.isOutsideBuildHeight(blockpos)) {
+- this.getChunkAt(blockpos).addAndRegisterBlockEntity(blockentity);
++ public void setBlockEntity(BlockEntity blockEntity) {
++ BlockPos blockposition = blockEntity.getBlockPos();
++
++ if (!this.isOutsideBuildHeight(blockposition)) {
++ // CraftBukkit start
++ if (captureBlockStates) {
++ capturedTileEntities.put(blockposition.immutable(), blockEntity);
++ return;
++ }
++ // CraftBukkit end
++ this.getChunkAt(blockposition).addAndRegisterBlockEntity(blockEntity);
+ }
+ }
+
+- public void removeBlockEntity(BlockPos blockpos) {
+- if (!this.isOutsideBuildHeight(blockpos)) {
+- this.getChunkAt(blockpos).removeBlockEntity(blockpos);
++ public void removeBlockEntity(BlockPos pos) {
++ if (!this.isOutsideBuildHeight(pos)) {
++ this.getChunkAt(pos).removeBlockEntity(pos);
+ }
+ }
+
+- public boolean isLoaded(BlockPos blockpos) {
+- return this.isOutsideBuildHeight(blockpos) ? false : this.getChunkSource().hasChunk(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ()));
++ public boolean isLoaded(BlockPos pos) {
++ return this.isOutsideBuildHeight(pos) ? false : this.getChunkSource().hasChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()));
+ }
+
+- public boolean loadedAndEntityCanStandOnFace(BlockPos blockpos, Entity entity, Direction direction) {
+- if (this.isOutsideBuildHeight(blockpos)) {
++ public boolean loadedAndEntityCanStandOnFace(BlockPos pos, Entity entity, Direction direction) {
++ if (this.isOutsideBuildHeight(pos)) {
+ return false;
+ } else {
+- ChunkAccess chunkaccess = this.getChunk(SectionPos.blockToSectionCoord(blockpos.getX()), SectionPos.blockToSectionCoord(blockpos.getZ()), ChunkStatus.FULL, false);
++ ChunkAccess ichunkaccess = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false);
+
+- return chunkaccess == null ? false : chunkaccess.getBlockState(blockpos).entityCanStandOnFace(this, blockpos, entity, direction);
++ return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).entityCanStandOnFace(this, pos, entity, direction);
+ }
+ }
+
+- public boolean loadedAndEntityCanStandOn(BlockPos blockpos, Entity entity) {
+- return this.loadedAndEntityCanStandOnFace(blockpos, entity, Direction.UP);
++ public boolean loadedAndEntityCanStandOn(BlockPos pos, Entity entity) {
++ return this.loadedAndEntityCanStandOnFace(pos, entity, Direction.UP);
+ }
+
+ public void updateSkyBrightness() {
+@@ -604,18 +791,18 @@
+ this.skyDarken = (int) ((1.0D - d2 * d0 * d1) * 11.0D);
+ }
+
+- public void setSpawnSettings(boolean flag, boolean flag1) {
+- this.getChunkSource().setSpawnSettings(flag, flag1);
++ public void setSpawnSettings(boolean hostile, boolean peaceful) {
++ this.getChunkSource().setSpawnSettings(hostile, peaceful);
+ }
+
+ public BlockPos getSharedSpawnPos() {
+- BlockPos blockpos = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn());
++ BlockPos blockposition = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn());
+
+- if (!this.getWorldBorder().isWithinBounds(blockpos)) {
+- blockpos = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, BlockPos.containing(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ()));
++ if (!this.getWorldBorder().isWithinBounds(blockposition)) {
++ blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, BlockPos.containing(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ()));
+ }
+
+- return blockpos;
++ return blockposition;
+ }
+
+ public float getSharedSpawnAngle() {
+@@ -632,38 +819,35 @@
+
+ }
+
+- @Override
+ public void close() throws IOException {
+ this.getChunkSource().close();
+ }
+
+ @Nullable
+ @Override
+- @Override
+- public BlockGetter getChunkForCollisions(int i, int j) {
+- return this.getChunk(i, j, ChunkStatus.FULL, false);
++ public BlockGetter getChunkForCollisions(int chunkX, int chunkZ) {
++ return this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, false);
+ }
+
+ @Override
+- @Override
+- public List<Entity> getEntities(@Nullable Entity entity, AABB aabb, Predicate<? super Entity> predicate) {
++ public List<Entity> getEntities(@Nullable Entity entity, AABB boundingBox, Predicate<? super Entity> predicate) {
+ this.getProfiler().incrementCounter("getEntities");
+ List<Entity> list = Lists.newArrayList();
+
+- this.getEntities().get(aabb, (entity1) -> {
++ this.getEntities().get(boundingBox, (entity1) -> {
+ if (entity1 != entity && predicate.test(entity1)) {
+ list.add(entity1);
+ }
+
+ if (entity1 instanceof EnderDragon) {
+- EnderDragonPart[] aenderdragonpart = ((EnderDragon) entity1).getSubEntities();
+- int i = aenderdragonpart.length;
++ EnderDragonPart[] aentitycomplexpart = ((EnderDragon) entity1).getSubEntities();
++ int i = aentitycomplexpart.length;
+
+ for (int j = 0; j < i; ++j) {
+- EnderDragonPart enderdragonpart = aenderdragonpart[j];
++ EnderDragonPart entitycomplexpart = aentitycomplexpart[j];
+
+- if (entity1 != entity && predicate.test(enderdragonpart)) {
+- list.add(enderdragonpart);
++ if (entity1 != entity && predicate.test(entitycomplexpart)) {
++ list.add(entitycomplexpart);
+ }
+ }
+ }
+@@ -673,62 +857,60 @@
+ }
+
+ @Override
+- @Override
+- public <T extends Entity> List<T> getEntities(EntityTypeTest<Entity, T> entitytypetest, AABB aabb, Predicate<? super T> predicate) {
++ public <T extends Entity> List<T> getEntities(EntityTypeTest<Entity, T> entityTypeTest, AABB bounds, Predicate<? super T> predicate) {
+ List<T> list = Lists.newArrayList();
+
+- this.getEntities(entitytypetest, aabb, predicate, list);
++ this.getEntities(entityTypeTest, bounds, predicate, list);
+ return list;
+ }
+
+- public <T extends Entity> void getEntities(EntityTypeTest<Entity, T> entitytypetest, AABB aabb, Predicate<? super T> predicate, List<? super T> list) {
+- this.getEntities(entitytypetest, aabb, predicate, list, Integer.MAX_VALUE);
++ public <T extends Entity> void getEntities(EntityTypeTest<Entity, T> entityTypeTest, AABB bounds, Predicate<? super T> predicate, List<? super T> output) {
++ this.getEntities(entityTypeTest, bounds, predicate, output, Integer.MAX_VALUE);
+ }
+
+- public <T extends Entity> void getEntities(EntityTypeTest<Entity, T> entitytypetest, AABB aabb, Predicate<? super T> predicate, List<? super T> list, int i) {
++ public <T extends Entity> void getEntities(EntityTypeTest<Entity, T> entityTypeTest, AABB bounds, Predicate<? super T> predicate, List<? super T> output, int maxResults) {
+ this.getProfiler().incrementCounter("getEntities");
+- this.getEntities().get(entitytypetest, aabb, (entity) -> {
++ this.getEntities().get(entityTypeTest, bounds, (entity) -> {
+ if (predicate.test(entity)) {
+- list.add(entity);
+- if (list.size() >= i) {
+- return AbortableIterationConsumer.Continuation.ABORT;
++ output.add(entity);
++ if (output.size() >= maxResults) {
++ return AbortableIterationConsumer.a.ABORT;
+ }
+ }
+
+ if (entity instanceof EnderDragon) {
+- EnderDragon enderdragon = (EnderDragon) entity;
+- EnderDragonPart[] aenderdragonpart = enderdragon.getSubEntities();
+- int j = aenderdragonpart.length;
++ EnderDragon entityenderdragon = (EnderDragon) entity;
++ EnderDragonPart[] aentitycomplexpart = entityenderdragon.getSubEntities();
++ int j = aentitycomplexpart.length;
+
+ for (int k = 0; k < j; ++k) {
+- EnderDragonPart enderdragonpart = aenderdragonpart[k];
+- T t0 = (Entity) entitytypetest.tryCast(enderdragonpart);
++ EnderDragonPart entitycomplexpart = aentitycomplexpart[k];
++ T t0 = entityTypeTest.tryCast(entitycomplexpart); // CraftBukkit - decompile error
+
+ if (t0 != null && predicate.test(t0)) {
+- list.add(t0);
+- if (list.size() >= i) {
+- return AbortableIterationConsumer.Continuation.ABORT;
++ output.add(t0);
++ if (output.size() >= maxResults) {
++ return AbortableIterationConsumer.a.ABORT;
+ }
+ }
+ }
+ }
+
+- return AbortableIterationConsumer.Continuation.CONTINUE;
++ return AbortableIterationConsumer.a.CONTINUE;
+ });
+ }
+
+ @Nullable
+ public abstract Entity getEntity(int id);
+
+- public void blockEntityChanged(BlockPos blockpos) {
+- if (this.hasChunkAt(blockpos)) {
+- this.getChunkAt(blockpos).setUnsaved(true);
++ public void blockEntityChanged(BlockPos pos) {
++ if (this.hasChunkAt(pos)) {
++ this.getChunkAt(pos).setUnsaved(true);
+ }
+
+ }
+
+ @Override
+- @Override
+ public int getSeaLevel() {
+ return 63;
+ }
+@@ -743,20 +925,19 @@
+ return this.levelData.getDayTime();
+ }
+
+- public boolean mayInteract(Player player, BlockPos blockpos) {
++ public boolean mayInteract(Player player, BlockPos pos) {
+ return true;
+ }
+
+- public void broadcastEntityEvent(Entity entity, byte b0) {}
++ public void broadcastEntityEvent(Entity entity, byte state) {}
+
+- public void broadcastDamageEvent(Entity entity, DamageSource damagesource) {}
++ public void broadcastDamageEvent(Entity entity, DamageSource damageSource) {}
+
+- public void blockEvent(BlockPos blockpos, Block block, int i, int j) {
+- this.getBlockState(blockpos).triggerEvent(this, blockpos, i, j);
++ public void blockEvent(BlockPos pos, Block block, int eventID, int eventParam) {
++ this.getBlockState(pos).triggerEvent(this, pos, eventID, eventParam);
+ }
+
+ @Override
+- @Override
+ public LevelData getLevelData() {
+ return this.levelData;
+ }
+@@ -767,23 +948,23 @@
+
+ public abstract TickRateManager tickRateManager();
+
+- public float getThunderLevel(float f) {
+- return Mth.lerp(f, this.oThunderLevel, this.thunderLevel) * this.getRainLevel(f);
++ public float getThunderLevel(float delta) {
++ return Mth.lerp(delta, this.oThunderLevel, this.thunderLevel) * this.getRainLevel(delta);
+ }
+
+- public void setThunderLevel(float f) {
+- float f1 = Mth.clamp(f, 0.0F, 1.0F);
++ public void setThunderLevel(float strength) {
++ float f1 = Mth.clamp(strength, 0.0F, 1.0F);
+
+ this.oThunderLevel = f1;
+ this.thunderLevel = f1;
+ }
+
+- public float getRainLevel(float f) {
+- return Mth.lerp(f, this.oRainLevel, this.rainLevel);
++ public float getRainLevel(float delta) {
++ return Mth.lerp(delta, this.oRainLevel, this.rainLevel);
+ }
+
+- public void setRainLevel(float f) {
+- float f1 = Mth.clamp(f, 0.0F, 1.0F);
++ public void setRainLevel(float strength) {
++ float f1 = Mth.clamp(strength, 0.0F, 1.0F);
+
+ this.oRainLevel = f1;
+ this.rainLevel = f1;
+@@ -797,17 +978,17 @@
+ return (double) this.getRainLevel(1.0F) > 0.2D;
+ }
+
+- public boolean isRainingAt(BlockPos blockpos) {
++ public boolean isRainingAt(BlockPos pos) {
+ if (!this.isRaining()) {
+ return false;
+- } else if (!this.canSeeSky(blockpos)) {
++ } else if (!this.canSeeSky(pos)) {
+ return false;
+- } else if (this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockpos).getY() > blockpos.getY()) {
++ } else if (this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos).getY() > pos.getY()) {
+ return false;
+ } else {
+- Biome biome = (Biome) this.getBiome(blockpos).value();
++ Biome biomebase = (Biome) this.getBiome(pos).value();
+
+- return biome.getPrecipitationAt(blockpos) == Biome.Precipitation.RAIN;
++ return biomebase.getPrecipitationAt(pos) == Biome.Precipitation.RAIN;
+ }
+ }
+
+@@ -818,56 +999,56 @@
+
+ public abstract int getFreeMapId();
+
+- public void globalLevelEvent(int i, BlockPos blockpos, int j) {}
++ public void globalLevelEvent(int id, BlockPos pos, int data) {}
+
+- public CrashReportCategory fillReportDetails(CrashReport crashreport) {
+- CrashReportCategory crashreportcategory = crashreport.addCategory("Affected level", 1);
++ public CrashReportCategory fillReportDetails(CrashReport report) {
++ CrashReportCategory crashreportsystemdetails = report.addCategory("Affected level", 1);
+
+- crashreportcategory.setDetail("All players", () -> {
++ crashreportsystemdetails.setDetail("All players", () -> {
+ int i = this.players().size();
+
+ return i + " total; " + this.players();
+ });
+- ChunkSource chunksource = this.getChunkSource();
++ ChunkSource ichunkprovider = this.getChunkSource();
+
+- Objects.requireNonNull(chunksource);
+- crashreportcategory.setDetail("Chunk stats", chunksource::gatherStats);
+- crashreportcategory.setDetail("Level dimension", () -> {
++ Objects.requireNonNull(ichunkprovider);
++ crashreportsystemdetails.setDetail("Chunk stats", ichunkprovider::gatherStats);
++ crashreportsystemdetails.setDetail("Level dimension", () -> {
+ return this.dimension().location().toString();
+ });
+
+ try {
+- this.levelData.fillCrashReportCategory(crashreportcategory, this);
++ this.levelData.fillCrashReportCategory(crashreportsystemdetails, this);
+ } catch (Throwable throwable) {
+- crashreportcategory.setDetailError("Level Data Unobtainable", throwable);
++ crashreportsystemdetails.setDetailError("Level Data Unobtainable", throwable);
+ }
+
+- return crashreportcategory;
++ return crashreportsystemdetails;
+ }
+
+ public abstract void destroyBlockProgress(int breakerId, BlockPos pos, int progress);
+
+- public void createFireworks(double d0, double d1, double d2, double d3, double d4, double d5, @Nullable CompoundTag compoundtag) {}
++ public void createFireworks(double x, double d1, double y, double d3, double z, double d5, @Nullable CompoundTag motionX) {}
+
+ public abstract Scoreboard getScoreboard();
+
+- public void updateNeighbourForOutputSignal(BlockPos blockpos, Block block) {
++ public void updateNeighbourForOutputSignal(BlockPos pos, Block block) {
+ Iterator iterator = Direction.Plane.HORIZONTAL.iterator();
+
+ while (iterator.hasNext()) {
+- Direction direction = (Direction) iterator.next();
+- BlockPos blockpos1 = blockpos.relative(direction);
++ Direction enumdirection = (Direction) iterator.next();
++ BlockPos blockposition1 = pos.relative(enumdirection);
+
+- if (this.hasChunkAt(blockpos1)) {
+- BlockState blockstate = this.getBlockState(blockpos1);
++ if (this.hasChunkAt(blockposition1)) {
++ IBlockData iblockdata = this.getBlockState(blockposition1);
+
+- if (blockstate.is(Blocks.COMPARATOR)) {
+- this.neighborChanged(blockstate, blockpos1, block, blockpos, false);
+- } else if (blockstate.isRedstoneConductor(this, blockpos1)) {
+- blockpos1 = blockpos1.relative(direction);
+- blockstate = this.getBlockState(blockpos1);
+- if (blockstate.is(Blocks.COMPARATOR)) {
+- this.neighborChanged(blockstate, blockpos1, block, blockpos, false);
++ if (iblockdata.is(Blocks.COMPARATOR)) {
++ this.neighborChanged(iblockdata, blockposition1, block, pos, false);
++ } else if (iblockdata.isRedstoneConductor(this, blockposition1)) {
++ blockposition1 = blockposition1.relative(enumdirection);
++ iblockdata = this.getBlockState(blockposition1);
++ if (iblockdata.is(Blocks.COMPARATOR)) {
++ this.neighborChanged(iblockdata, blockposition1, block, pos, false);
+ }
+ }
+ }
+@@ -876,29 +1057,26 @@
+ }
+
+ @Override
+- @Override
+- public DifficultyInstance getCurrentDifficultyAt(BlockPos blockpos) {
++ public DifficultyInstance getCurrentDifficultyAt(BlockPos pos) {
+ long i = 0L;
+ float f = 0.0F;
+
+- if (this.hasChunkAt(blockpos)) {
++ if (this.hasChunkAt(pos)) {
+ f = this.getMoonBrightness();
+- i = this.getChunkAt(blockpos).getInhabitedTime();
++ i = this.getChunkAt(pos).getInhabitedTime();
+ }
+
+ return new DifficultyInstance(this.getDifficulty(), this.getDayTime(), i, f);
+ }
+
+ @Override
+- @Override
+ public int getSkyDarken() {
+ return this.skyDarken;
+ }
+
+- public void setSkyFlashTime(int i) {}
++ public void setSkyFlashTime(int timeFlash) {}
+
+ @Override
+- @Override
+ public WorldBorder getWorldBorder() {
+ return this.worldBorder;
+ }
+@@ -908,7 +1086,6 @@
+ }
+
+ @Override
+- @Override
+ public DimensionType dimensionType() {
+ return (DimensionType) this.dimensionTypeRegistration.value();
+ }
+@@ -926,30 +1103,27 @@
+ }
+
+ @Override
+- @Override
+ public RandomSource getRandom() {
+ return this.random;
+ }
+
+ @Override
+- @Override
+- public boolean isStateAtPosition(BlockPos blockpos, Predicate<BlockState> predicate) {
+- return predicate.test(this.getBlockState(blockpos));
++ public boolean isStateAtPosition(BlockPos pos, Predicate<IBlockData> state) {
++ return state.test(this.getBlockState(pos));
+ }
+
+ @Override
+- @Override
+- public boolean isFluidAtPosition(BlockPos blockpos, Predicate<FluidState> predicate) {
+- return predicate.test(this.getFluidState(blockpos));
++ public boolean isFluidAtPosition(BlockPos pos, Predicate<FluidState> predicate) {
++ return predicate.test(this.getFluidState(pos));
+ }
+
+ public abstract RecipeManager getRecipeManager();
+
+- public BlockPos getBlockRandomPos(int i, int j, int k, int l) {
++ public BlockPos getBlockRandomPos(int x, int y, int z, int yMask) {
+ this.randValue = this.randValue * 3 + 1013904223;
+ int i1 = this.randValue >> 2;
+
+- return new BlockPos(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15));
++ return new BlockPos(x + (i1 & 15), y + (i1 >> 16 & yMask), z + (i1 >> 8 & 15));
+ }
+
+ public boolean noSave() {
+@@ -965,7 +1139,6 @@
+ }
+
+ @Override
+- @Override
+ public BiomeManager getBiomeManager() {
+ return this.biomeManager;
+ }
+@@ -974,16 +1147,14 @@
+ return this.isDebug;
+ }
+
+- protected abstract LevelEntityGetter<Entity> getEntities();
++ public abstract LevelEntityGetter<Entity> getEntities();
+
+ @Override
+- @Override
+ public long nextSubTickCount() {
+ return (long) (this.subTickCount++);
+ }
+
+ @Override
+- @Override
+ public RegistryAccess registryAccess() {
+ return this.registryAccess;
+ }
+@@ -992,10 +1163,10 @@
+ return this.damageSources;
+ }
+
+- public static enum ExplosionInteraction {
++ public static enum a {
+
+ NONE, BLOCK, MOB, TNT, BLOW;
+
+- private ExplosionInteraction() {}
++ private a() {}
+ }
+ }