1
0
Fork 0
hoosiertransfer-mod-saigevers/src/main/java/net/minecraft/world/chunk/Chunk.java

1711 lines
52 KiB
Java

package net.minecraft.world.chunk;
import com.google.common.base.Predicate;
import com.google.common.collect.Maps;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import net.hoosiertransfer.Alfheim.IChunkLightingData;
import net.hoosiertransfer.Alfheim.ILightingEngineProvider;
import net.hoosiertransfer.Alfheim.lighting.LightUtil;
import net.hoosiertransfer.Alfheim.lighting.LightingEngine;
import net.hoosiertransfer.Alfheim.util.EnumBoundaryFacing;
import net.hoosiertransfer.Alfheim.util.WorldChunkSlice;
import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom;
import java.util.concurrent.Callable;
import net.lax1dude.eaglercraft.v1_8.sp.server.EaglerMinecraftServer;
import net.minecraft.block.Block;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.entity.Entity;
import net.minecraft.init.Blocks;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.BlockPos;
import net.minecraft.util.ClassInheritanceMultiMap;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ReportedException;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.biome.WorldChunkManager;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager;
/**
* +
* This portion of EaglercraftX contains deobfuscated Minecraft 1.8 source code.
*
* Minecraft 1.8.8 bytecode is (c) 2015 Mojang AB. "Do not distribute!"
* Mod Coder Pack v9.18 deobfuscation configs are (c) Copyright by the MCP Team
*
* EaglercraftX 1.8 patch files (c) 2022-2024 lax1dude, hoosiertransfer,
* ayunami2000. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public class Chunk {
private static final Logger logger = LogManager.getLogger();
private final ExtendedBlockStorage[] storageArrays;
private final byte[] blockBiomeArray;
private final int[] precipitationHeightMap;
private final boolean[] updateSkylightColumns;
private boolean isChunkLoaded;
private final World worldObj;
private final int[] heightMap;
public final int xPosition;
public final int zPosition;
private boolean isGapLightingUpdated;
private final Map<BlockPos, TileEntity> chunkTileEntityMap;
private final ClassInheritanceMultiMap<Entity>[] entityLists;
private boolean isTerrainPopulated;
private boolean isLightPopulated;
private boolean field_150815_m;
private boolean isModified;
private boolean hasEntities;
private long lastSaveTime;
private int heightMapMinimum;
private long inhabitedTime;
private int queuedLightChecks;
private List<BlockPos> tileEntityPosQueue;
public static final ExtendedBlockStorage NULL_BLOCK_STORAGE = null;
private LightingEngine alfheim$lightingEngine;
private boolean alfheim$isLightInitialized;
private short[] alfheim$neighborLightChecks;
private static final EnumSkyBlock[] ENUM_SKY_BLOCK_VALUES = EnumSkyBlock.values();
private static final EnumFacing[] ENUM_FACING_HORIZONTAL = EnumFacing.Plane.HORIZONTAL.facings();
private static final EnumFacing.AxisDirection[] ENUM_AXIS_DIRECTION_VALUES = EnumFacing.AxisDirection.values();
public Chunk(World worldIn, int x, int z) {
this.storageArrays = new ExtendedBlockStorage[16];
this.blockBiomeArray = new byte[256];
this.precipitationHeightMap = new int[256];
this.updateSkylightColumns = new boolean[256];
this.chunkTileEntityMap = Maps.newHashMap();
this.queuedLightChecks = 4096;
this.tileEntityPosQueue = new LinkedList();
this.entityLists = (ClassInheritanceMultiMap[]) (new ClassInheritanceMultiMap[16]);
this.worldObj = worldIn;
this.xPosition = x;
this.zPosition = z;
this.heightMap = new int[256];
for (int i = 0; i < this.entityLists.length; ++i) {
this.entityLists[i] = new ClassInheritanceMultiMap(Entity.class);
}
Arrays.fill(this.precipitationHeightMap, -999);
Arrays.fill(this.blockBiomeArray, (byte) -1);
alfheim$lightingEngine = worldIn.alfheim$getLightingEngine();
}
public Chunk(World worldIn, ChunkPrimer primer, int x, int z) {
this(worldIn, x, z);
short short1 = 256;
boolean flag = !worldIn.provider.getHasNoSky();
for (int i = 0; i < 16; ++i) {
for (int j = 0; j < 16; ++j) {
for (int k = 0; k < short1; ++k) {
int l = i * short1 * 16 | j * short1 | k;
IBlockState iblockstate = primer.getBlockState(l);
if (iblockstate.getBlock().getMaterial() != Material.air) {
int i1 = k >> 4;
if (this.storageArrays[i1] == null) {
this.storageArrays[i1] = new ExtendedBlockStorage(i1 << 4, flag);
}
this.storageArrays[i1].set(i, k & 15, j, iblockstate);
}
}
}
}
}
/**
* +
* Checks whether the chunk is at the X/Z location specified
*/
public boolean isAtLocation(int i, int j) {
return i == this.xPosition && j == this.zPosition;
}
public int getHeight(BlockPos pos) {
return this.getHeightValue(pos.getX() & 15, pos.getZ() & 15);
}
/**
* +
* Returns the value in the height map at this x, z coordinate
* in the chunk
*/
public int getHeightValue(int i, int j) {
return this.heightMap[j << 4 | i];
}
/**
* +
* Returns the topmost ExtendedBlockStorage instance for this
* Chunk that actually contains a block.
*/
public int getTopFilledSegment() {
for (int i = this.storageArrays.length - 1; i >= 0; --i) {
if (this.storageArrays[i] != null) {
return this.storageArrays[i].getYLocation();
}
}
return 0;
}
/**
* +
* Returns the ExtendedBlockStorage array for this Chunk.
*/
public ExtendedBlockStorage[] getBlockStorageArray() {
return this.storageArrays;
}
/**
* +
* Generates the height map for a chunk from scratch
*/
protected void generateHeightMap() {
int i = this.getTopFilledSegment();
this.heightMapMinimum = Integer.MAX_VALUE;
for (int j = 0; j < 16; ++j) {
for (int k = 0; k < 16; ++k) {
this.precipitationHeightMap[j + (k << 4)] = -999;
for (int l = i + 16; l > 0; --l) {
Block block = this.getBlock0(j, l - 1, k);
if (block.getLightOpacity() != 0) {
this.heightMap[k << 4 | j] = l;
if (l < this.heightMapMinimum) {
this.heightMapMinimum = l;
}
break;
}
}
}
}
this.isModified = true;
}
/**
* +
* Generates the initial skylight map for the chunk upon
* generation or load.
*/
public void generateSkylightMap() {
int i = this.getTopFilledSegment();
this.heightMapMinimum = Integer.MAX_VALUE;
for (int j = 0; j < 16; ++j) {
for (int k = 0; k < 16; ++k) {
this.precipitationHeightMap[j + (k << 4)] = -999;
for (int l = i + 16; l > 0; --l) {
if (this.getBlockLightOpacity(j, l - 1, k) != 0) {
this.heightMap[k << 4 | j] = l;
if (l < this.heightMapMinimum) {
this.heightMapMinimum = l;
}
break;
}
}
if (!this.worldObj.provider.getHasNoSky()) {
int k1 = 15;
int i1 = i + 16 - 1;
while (true) {
int j1 = this.getBlockLightOpacity(j, i1, k);
if (j1 == 0 && k1 != 15) {
j1 = 1;
}
k1 -= j1;
if (k1 > 0) {
ExtendedBlockStorage extendedblockstorage = this.storageArrays[i1 >> 4];
if (extendedblockstorage != null) {
extendedblockstorage.setExtSkylightValue(j, i1 & 15, k, k1);
alfheim$initSkylightForSection(storageArrays[i1 >> 4]);
// do i comment this out?
// this.worldObj.notifyLightSet(
// new BlockPos((this.xPosition << 4) + j, i1, (this.zPosition << 4) + k));
}
}
--i1;
if (i1 <= 0 || k1 <= 0) {
break;
}
}
}
}
}
if (!this.worldObj.isRemote) {
++EaglerMinecraftServer.counterLightUpdate;
}
this.isModified = true;
}
/**
* +
* Propagates a given sky-visible block's light value downward
* and upward to neighboring blocks as necessary.
*/
private void propagateSkylightOcclusion(int x, int z) {
this.updateSkylightColumns[x + z * 16] = true;
this.isGapLightingUpdated = true;
}
private void recheckGaps(boolean parFlag) {
if (!worldObj.isAreaLoaded(new BlockPos((xPosition << 4) + 8, 0, (zPosition << 4) + 8), 16))
return;
final WorldChunkSlice slice = new WorldChunkSlice(worldObj.getChunkProvider(), xPosition, zPosition);
for (int x = 0; x < 16; ++x) {
for (int z = 0; z < 16; ++z) {
if (!alfheim$recheckGapsForColumn(slice, x, z))
continue;
if (parFlag)
return;
}
}
isGapLightingUpdated = false;
}
/**
* +
* Checks the height of a block next to a sky-visible block and
* schedules a lighting update as necessary.
*/
private void checkSkylightNeighborHeight(int x, int z, int maxValue) {
int i = this.worldObj.getHeight(new BlockPos(x, 0, z)).getY();
if (i > maxValue) {
this.updateSkylightNeighborHeight(x, z, maxValue, i + 1);
} else if (i < maxValue) {
this.updateSkylightNeighborHeight(x, z, i, maxValue + 1);
}
}
private void updateSkylightNeighborHeight(int x, int z, int startY, int endY) {
if (endY > startY && this.worldObj.isAreaLoaded(new BlockPos(x, 0, z), 16)) {
for (int i = startY; i < endY; ++i) {
this.worldObj.checkLightFor(EnumSkyBlock.SKY, new BlockPos(x, i, z));
}
this.isModified = true;
}
}
/**
* +
* Initiates the recalculation of both the block-light and
* sky-light for a given block inside a chunk.
*/
private void relightBlock(int x, int y, int z) {
int heightMapY = heightMap[z << 4 | x] & 255;
int newHeightMapY = Math.max(y, heightMapY);
while (newHeightMapY > 0 && getBlockLightOpacity(x, newHeightMapY - 1, z) == 0)
--newHeightMapY;
if (newHeightMapY == heightMapY)
return;
heightMap[z << 4 | x] = newHeightMapY;
if (!worldObj.provider.getHasNoSky())
alfheim$relightSkylightColumn(x, z, heightMapY, newHeightMapY);
final int heightMapY1 = heightMap[z << 4 | x];
if (heightMapY1 < heightMapMinimum)
heightMapMinimum = heightMapY1;
}
public int getBlockLightOpacity(BlockPos blockpos) {
return this.getBlock(blockpos).getLightOpacity();
}
private int getBlockLightOpacity(int x, int y, int z) {
return this.getBlock0(x, y, z).getLightOpacity();
}
/**
* +
* Returns the block corresponding to the given coordinates
* inside a chunk.
*/
private Block getBlock0(int x, int y, int z) {
Block block = Blocks.air;
if (y >= 0 && y >> 4 < this.storageArrays.length) {
ExtendedBlockStorage extendedblockstorage = this.storageArrays[y >> 4];
if (extendedblockstorage != null) {
try {
block = extendedblockstorage.getBlockByExtId(x, y & 15, z);
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Getting block");
throw new ReportedException(crashreport);
}
}
}
return block;
}
public Block getBlock(final int x, final int y, final int z) {
try {
return this.getBlock0(x & 15, y, z & 15);
} catch (ReportedException reportedexception) {
CrashReportCategory crashreportcategory = reportedexception.getCrashReport()
.makeCategory("Block being got");
crashreportcategory.addCrashSectionCallable("Location", new Callable<String>() {
public String call() throws Exception {
return CrashReportCategory.getCoordinateInfo(
new BlockPos(Chunk.this.xPosition * 16 + x, y, Chunk.this.zPosition * 16 + z));
}
});
throw reportedexception;
}
}
public Block getBlock(final BlockPos blockpos) {
try {
return this.getBlock0(blockpos.getX() & 15, blockpos.getY(), blockpos.getZ() & 15);
} catch (ReportedException reportedexception) {
CrashReportCategory crashreportcategory = reportedexception.getCrashReport()
.makeCategory("Block being got");
crashreportcategory.addCrashSectionCallable("Location", new Callable<String>() {
public String call() throws Exception {
return CrashReportCategory.getCoordinateInfo(blockpos);
}
});
throw reportedexception;
}
}
public IBlockState getBlockState(final BlockPos pos) {
try {
if (pos.getY() >= 0 && pos.getY() >> 4 < this.storageArrays.length) {
ExtendedBlockStorage extendedblockstorage = this.storageArrays[pos.getY() >> 4];
if (extendedblockstorage != null) {
int j = pos.getX() & 15;
int k = pos.getY() & 15;
int i = pos.getZ() & 15;
return extendedblockstorage.get(j, k, i);
}
}
return Blocks.air.getDefaultState();
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Getting block state");
CrashReportCategory crashreportcategory = crashreport.makeCategory("Block being got");
crashreportcategory.addCrashSectionCallable("Location", new Callable<String>() {
public String call() throws Exception {
return CrashReportCategory.getCoordinateInfo(pos);
}
});
throw new ReportedException(crashreport);
}
}
/**
* only use with a regular "net.minecraft.util.BlockPos"!
*/
public IBlockState getBlockStateFaster(final BlockPos pos) {
try {
if (pos.y >= 0 && pos.y >> 4 < this.storageArrays.length) {
ExtendedBlockStorage extendedblockstorage = this.storageArrays[pos.getY() >> 4];
if (extendedblockstorage != null) {
int j = pos.x & 15;
int k = pos.y & 15;
int i = pos.z & 15;
return extendedblockstorage.get(j, k, i);
}
}
return Blocks.air.getDefaultState();
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Getting block state");
CrashReportCategory crashreportcategory = crashreport.makeCategory("Block being got");
crashreportcategory.addCrashSectionCallable("Location", new Callable<String>() {
public String call() throws Exception {
return CrashReportCategory.getCoordinateInfo(pos);
}
});
throw new ReportedException(crashreport);
}
}
/**
* +
* Return the metadata corresponding to the given coordinates
* inside a chunk.
*/
private int getBlockMetadata(int x, int y, int z) {
if (y >> 4 >= this.storageArrays.length) {
return 0;
} else {
ExtendedBlockStorage extendedblockstorage = this.storageArrays[y >> 4];
return extendedblockstorage != null ? extendedblockstorage.getExtBlockMetadata(x, y & 15, z) : 0;
}
}
/**
* +
* Return the metadata corresponding to the given coordinates
* inside a chunk.
*/
public int getBlockMetadata(BlockPos blockpos) {
return this.getBlockMetadata(blockpos.getX() & 15, blockpos.getY(), blockpos.getZ() & 15);
}
public IBlockState setBlockState(BlockPos pos, IBlockState state) {
int i = pos.getX() & 15;
int j = pos.getY();
int k = pos.getZ() & 15;
int l = k << 4 | i;
if (j >= this.precipitationHeightMap[l] - 1) {
this.precipitationHeightMap[l] = -999;
}
int i1 = this.heightMap[l];
IBlockState iblockstate = this.getBlockState(pos);
if (iblockstate == state) {
return null;
} else {
Block block = state.getBlock();
Block block1 = iblockstate.getBlock();
ExtendedBlockStorage extendedblockstorage = this.storageArrays[j >> 4];
boolean flag = false;
if (extendedblockstorage == null) {
if (block == Blocks.air) {
return null;
}
extendedblockstorage = this.storageArrays[j >> 4] = new ExtendedBlockStorage(j >> 4 << 4,
!this.worldObj.provider.getHasNoSky());
alfheim$initSkylightForSection(extendedblockstorage);
// flag = j >= i1;
}
extendedblockstorage.set(i, j & 15, k, state);
if (block1 != block) {
if (!this.worldObj.isRemote) {
block1.breakBlock(this.worldObj, pos, iblockstate);
} else if (block1 instanceof ITileEntityProvider) {
this.worldObj.removeTileEntity(pos);
}
}
if (extendedblockstorage.getBlockByExtId(i, j & 15, k) != block) {
return null;
} else {
if (flag) {
this.generateSkylightMap();
} else {
int j1 = block.getLightOpacity();
int k1 = block1.getLightOpacity();
if (j1 > 0) {
if (j >= i1) {
this.relightBlock(i, j + 1, k);
}
} else if (j == i1 - 1) {
this.relightBlock(i, j, k);
}
// if (j1 != k1 && (j1 < k1 || this.getLightFor(EnumSkyBlock.SKY, pos) > 0
// || this.getLightFor(EnumSkyBlock.BLOCK, pos) > 0)) {
// this.propagateSkylightOcclusion(i, k);
// }
}
if (block1 instanceof ITileEntityProvider) {
TileEntity tileentity = this.getTileEntity(pos, Chunk.EnumCreateEntityType.CHECK);
if (tileentity != null) {
tileentity.updateContainingBlockInfo();
}
}
if (!this.worldObj.isRemote && block1 != block) {
block.onBlockAdded(this.worldObj, pos, state);
}
if (block instanceof ITileEntityProvider) {
TileEntity tileentity1 = this.getTileEntity(pos, Chunk.EnumCreateEntityType.CHECK);
if (tileentity1 == null) {
tileentity1 = ((ITileEntityProvider) block).createNewTileEntity(this.worldObj,
block.getMetaFromState(state));
this.worldObj.setTileEntity(pos, tileentity1);
}
if (tileentity1 != null) {
tileentity1.updateContainingBlockInfo();
}
}
this.isModified = true;
return iblockstate;
}
}
}
public int getLightFor(EnumSkyBlock enumskyblock, BlockPos blockpos) {
alfheim$lightingEngine.processLightUpdatesForType(enumskyblock);
return alfheim$getCachedLightFor(enumskyblock, blockpos);
}
public void setLightFor(EnumSkyBlock enumskyblock, BlockPos blockpos, int i) {
int j = blockpos.getX() & 15;
int k = blockpos.getY();
int l = blockpos.getZ() & 15;
ExtendedBlockStorage extendedblockstorage = this.storageArrays[k >> 4];
if (extendedblockstorage == null) {
extendedblockstorage = this.storageArrays[k >> 4] = new ExtendedBlockStorage(k >> 4 << 4,
!this.worldObj.provider.getHasNoSky());
this.generateSkylightMap();
}
this.isModified = true;
if (enumskyblock == EnumSkyBlock.SKY) {
if (!this.worldObj.provider.getHasNoSky()) {
extendedblockstorage.setExtSkylightValue(j, k & 15, l, i);
}
} else if (enumskyblock == EnumSkyBlock.BLOCK) {
extendedblockstorage.setExtBlocklightValue(j, k & 15, l, i);
}
}
public int getLightSubtracted(BlockPos blockpos, int i) {
alfheim$lightingEngine.processLightUpdates();
int j = blockpos.getX() & 15;
int k = blockpos.getY();
int l = blockpos.getZ() & 15;
ExtendedBlockStorage extendedblockstorage = this.storageArrays[k >> 4];
if (extendedblockstorage == null) {
return !this.worldObj.provider.getHasNoSky() && i < EnumSkyBlock.SKY.defaultLightValue
? EnumSkyBlock.SKY.defaultLightValue - i
: getNoSkyLightValue();
} else {
int i1 = this.worldObj.provider.getHasNoSky() ? getNoSkyLightValue()
: extendedblockstorage.getExtSkylightValue(j, k & 15, l);
i1 = i1 - i;
int j1 = extendedblockstorage.getExtBlocklightValue(j, k & 15, l);
if (j1 > i1) {
i1 = j1;
}
return i1;
}
}
public static int getNoSkyLightValue() {
return DeferredStateManager.isDeferredRenderer() ? 5 : 0;
}
/**
* +
* Adds an entity to the chunk. Args: entity
*/
public void addEntity(Entity entity) {
this.hasEntities = true;
int i = MathHelper.floor_double(entity.posX / 16.0D);
int j = MathHelper.floor_double(entity.posZ / 16.0D);
if (i != this.xPosition || j != this.zPosition) {
logger.warn("Wrong location! (" + i + ", " + j + ") should be (" + this.xPosition + ", " + this.zPosition
+ "), " + entity, new Object[] { entity });
entity.setDead();
}
int k = MathHelper.floor_double(entity.posY / 16.0D);
if (k < 0) {
k = 0;
}
if (k >= this.entityLists.length) {
k = this.entityLists.length - 1;
}
entity.addedToChunk = true;
entity.chunkCoordX = this.xPosition;
entity.chunkCoordY = k;
entity.chunkCoordZ = this.zPosition;
this.entityLists[k].add(entity);
}
/**
* +
* removes entity using its y chunk coordinate as its index
*/
public void removeEntity(Entity entity) {
this.removeEntityAtIndex(entity, entity.chunkCoordY);
}
/**
* +
* Removes entity at the specified index from the entity array.
*/
public void removeEntityAtIndex(Entity entity, int i) {
if (i < 0) {
i = 0;
}
if (i >= this.entityLists.length) {
i = this.entityLists.length - 1;
}
this.entityLists[i].remove(entity);
}
public boolean canSeeSky(BlockPos blockpos) {
int i = blockpos.getX() & 15;
int j = blockpos.getY();
int k = blockpos.getZ() & 15;
return j >= this.heightMap[k << 4 | i];
}
private TileEntity createNewTileEntity(BlockPos pos) {
Block block = this.getBlock(pos);
return !block.hasTileEntity() ? null
: ((ITileEntityProvider) block).createNewTileEntity(this.worldObj, this.getBlockMetadata(pos));
}
public TileEntity getTileEntity(BlockPos blockpos, Chunk.EnumCreateEntityType chunk$enumcreateentitytype) {
TileEntity tileentity = (TileEntity) this.chunkTileEntityMap.get(blockpos);
if (tileentity == null) {
if (chunk$enumcreateentitytype == Chunk.EnumCreateEntityType.IMMEDIATE) {
tileentity = this.createNewTileEntity(blockpos);
this.worldObj.setTileEntity(blockpos, tileentity);
} else if (chunk$enumcreateentitytype == Chunk.EnumCreateEntityType.QUEUED) {
this.tileEntityPosQueue.add(blockpos);
}
} else if (tileentity.isInvalid()) {
this.chunkTileEntityMap.remove(blockpos);
return null;
}
return tileentity;
}
public void addTileEntity(TileEntity tileentity) {
this.addTileEntity(tileentity.getPos(), tileentity);
if (this.isChunkLoaded) {
this.worldObj.addTileEntity(tileentity);
}
}
public void addTileEntity(BlockPos blockpos, TileEntity tileentity) {
tileentity.setWorldObj(this.worldObj);
tileentity.setPos(blockpos);
if (this.getBlock(blockpos) instanceof ITileEntityProvider) {
if (this.chunkTileEntityMap.containsKey(blockpos)) {
((TileEntity) this.chunkTileEntityMap.get(blockpos)).invalidate();
}
tileentity.validate();
this.chunkTileEntityMap.put(blockpos, tileentity);
}
}
public void removeTileEntity(BlockPos blockpos) {
if (this.isChunkLoaded) {
TileEntity tileentity = (TileEntity) this.chunkTileEntityMap.remove(blockpos);
if (tileentity != null) {
tileentity.invalidate();
}
}
}
/**
* +
* Called when this Chunk is loaded by the ChunkProvider
*/
public void onChunkLoad() {
this.isChunkLoaded = true;
this.worldObj.addTileEntities(this.chunkTileEntityMap.values());
for (int i = 0; i < this.entityLists.length; ++i) {
for (Entity entity : this.entityLists[i]) {
entity.onChunkLoad();
}
this.worldObj.loadEntities(this.entityLists[i]);
}
final Chunk chunk = (Chunk) (Object) this;
for (final EnumFacing facing : EnumFacing.HORIZONTALS) {
final int xOffset = facing.getXOffset();
final int zOffset = facing.getZOffset();
final Chunk nChunk = worldObj.getChunkProvider().getLoadedChunk(chunk.xPosition + xOffset,
chunk.zPosition + zOffset);
if (nChunk == null)
continue;
for (final EnumSkyBlock lightType : ENUM_SKY_BLOCK_VALUES) {
for (final EnumFacing.AxisDirection axisDir : ENUM_AXIS_DIRECTION_VALUES) {
// Merge flags upon loading of a chunk. This ensures that all flags are always
// already on the IN boundary below
alfheim$mergeFlags(lightType, chunk, nChunk, facing, axisDir);
alfheim$mergeFlags(lightType, nChunk, chunk, facing.getOpposite(), axisDir);
// Check everything that might have been canceled due to this chunk not being
// loaded.
// Also, pass in chunks if already known
// The boundary to the neighbor chunk (both ways)
alfheim$scheduleRelightChecksForBoundary(chunk, nChunk, null, lightType, xOffset, zOffset, axisDir);
alfheim$scheduleRelightChecksForBoundary(nChunk, chunk, null, lightType, -xOffset, -zOffset,
axisDir);
// The boundary to the diagonal neighbor (since the checks in that chunk were
// aborted if this chunk wasn't loaded, see
// alfheim$scheduleRelightChecksForBoundary)
alfheim$scheduleRelightChecksForBoundary(nChunk, null, chunk, lightType,
(zOffset != 0 ? axisDir.getOffset() : 0), (xOffset != 0 ? axisDir.getOffset() : 0),
facing.getAxisDirection() == EnumFacing.AxisDirection.POSITIVE
? EnumFacing.AxisDirection.NEGATIVE
: EnumFacing.AxisDirection.POSITIVE);
}
}
}
}
/**
* +
* Called when this Chunk is unloaded by the ChunkProvider
*/
public void onChunkUnload() {
this.isChunkLoaded = false;
for (TileEntity tileentity : this.chunkTileEntityMap.values()) {
this.worldObj.markTileEntityForRemoval(tileentity);
}
for (int i = 0; i < this.entityLists.length; ++i) {
this.worldObj.unloadEntities(this.entityLists[i]);
}
}
/**
* +
* Sets the isModified flag for this Chunk
*/
public void setChunkModified() {
this.isModified = true;
}
/**
* +
* Fills the given list of all entities that intersect within
* the given bounding box that aren't the passed entity.
*/
public void getEntitiesWithinAABBForEntity(Entity entity, AxisAlignedBB axisalignedbb, List<Entity> list,
Predicate<? super Entity> predicate) {
int i = MathHelper.floor_double((axisalignedbb.minY - 2.0D) / 16.0D);
int j = MathHelper.floor_double((axisalignedbb.maxY + 2.0D) / 16.0D);
i = MathHelper.clamp_int(i, 0, this.entityLists.length - 1);
j = MathHelper.clamp_int(j, 0, this.entityLists.length - 1);
for (int k = i; k <= j; ++k) {
if (!this.entityLists[k].isEmpty()) {
for (Entity entity1 : this.entityLists[k]) {
if (entity1.getEntityBoundingBox().intersectsWith(axisalignedbb) && entity1 != entity) {
if (predicate == null || predicate.apply(entity1)) {
list.add(entity1);
}
Entity[] aentity = entity1.getParts();
if (aentity != null) {
for (int l = 0; l < aentity.length; ++l) {
entity1 = aentity[l];
if (entity1 != entity && entity1.getEntityBoundingBox().intersectsWith(axisalignedbb)
&& (predicate == null || predicate.apply(entity1))) {
list.add(entity1);
}
}
}
}
}
}
}
}
public <T extends Entity> void getEntitiesOfTypeWithinAAAB(Class<? extends T> oclass, AxisAlignedBB axisalignedbb,
List<T> list, Predicate<? super T> predicate) {
int i = MathHelper.floor_double((axisalignedbb.minY - 2.0D) / 16.0D);
int j = MathHelper.floor_double((axisalignedbb.maxY + 2.0D) / 16.0D);
i = MathHelper.clamp_int(i, 0, this.entityLists.length - 1);
j = MathHelper.clamp_int(j, 0, this.entityLists.length - 1);
for (int k = i; k <= j; ++k) {
for (Entity entity : this.entityLists[k].getByClass(oclass)) {
if (entity.getEntityBoundingBox().intersectsWith(axisalignedbb)
&& (predicate == null || predicate.apply((T) entity))) {
list.add((T) entity);
}
}
}
}
/**
* +
* Returns true if this Chunk needs to be saved
*/
public boolean needsSaving(boolean flag) {
if (flag) {
if (this.hasEntities && this.worldObj.getTotalWorldTime() != this.lastSaveTime || this.isModified) {
return true;
}
} else if (this.hasEntities && this.worldObj.getTotalWorldTime() >= this.lastSaveTime + 600L) {
return true;
}
return this.isModified;
}
public EaglercraftRandom getRandomWithSeed(long i) {
return new EaglercraftRandom(this.worldObj.getSeed() + (long) (this.xPosition * this.xPosition * 4987142)
+ (long) (this.xPosition * 5947611) + (long) (this.zPosition * this.zPosition) * 4392871L
+ (long) (this.zPosition * 389711) ^ i);
}
public boolean isEmpty() {
return false;
}
public void populateChunk(IChunkProvider parIChunkProvider, IChunkProvider parIChunkProvider2, int parInt1,
int parInt2) {
boolean flag = parIChunkProvider.chunkExists(parInt1, parInt2 - 1);
boolean flag1 = parIChunkProvider.chunkExists(parInt1 + 1, parInt2);
boolean flag2 = parIChunkProvider.chunkExists(parInt1, parInt2 + 1);
boolean flag3 = parIChunkProvider.chunkExists(parInt1 - 1, parInt2);
boolean flag4 = parIChunkProvider.chunkExists(parInt1 - 1, parInt2 - 1);
boolean flag5 = parIChunkProvider.chunkExists(parInt1 + 1, parInt2 + 1);
boolean flag6 = parIChunkProvider.chunkExists(parInt1 - 1, parInt2 + 1);
boolean flag7 = parIChunkProvider.chunkExists(parInt1 + 1, parInt2 - 1);
if (flag1 && flag2 && flag5) {
if (!this.isTerrainPopulated) {
parIChunkProvider.populate(parIChunkProvider2, parInt1, parInt2);
} else {
parIChunkProvider.func_177460_a(parIChunkProvider2, this, parInt1, parInt2);
}
}
if (flag3 && flag2 && flag6) {
Chunk chunk = parIChunkProvider.provideChunk(parInt1 - 1, parInt2);
if (!chunk.isTerrainPopulated) {
parIChunkProvider.populate(parIChunkProvider2, parInt1 - 1, parInt2);
} else {
parIChunkProvider.func_177460_a(parIChunkProvider2, chunk, parInt1 - 1, parInt2);
}
}
if (flag && flag1 && flag7) {
Chunk chunk1 = parIChunkProvider.provideChunk(parInt1, parInt2 - 1);
if (!chunk1.isTerrainPopulated) {
parIChunkProvider.populate(parIChunkProvider2, parInt1, parInt2 - 1);
} else {
parIChunkProvider.func_177460_a(parIChunkProvider2, chunk1, parInt1, parInt2 - 1);
}
}
if (flag4 && flag && flag3) {
Chunk chunk2 = parIChunkProvider.provideChunk(parInt1 - 1, parInt2 - 1);
if (!chunk2.isTerrainPopulated) {
parIChunkProvider.populate(parIChunkProvider2, parInt1 - 1, parInt2 - 1);
} else {
parIChunkProvider.func_177460_a(parIChunkProvider2, chunk2, parInt1 - 1, parInt2 - 1);
}
}
}
public BlockPos getPrecipitationHeight(BlockPos pos) {
int i = pos.getX() & 15;
int j = pos.getZ() & 15;
int k = i | j << 4;
BlockPos blockpos = new BlockPos(pos.getX(), this.precipitationHeightMap[k], pos.getZ());
if (blockpos.getY() == -999) {
int l = this.getTopFilledSegment() + 15;
blockpos = new BlockPos(pos.getX(), l, pos.getZ());
int i1 = -1;
while (blockpos.getY() > 0 && i1 == -1) {
Block block = this.getBlock(blockpos);
Material material = block.getMaterial();
if (!material.blocksMovement() && !material.isLiquid()) {
blockpos = blockpos.down();
} else {
i1 = blockpos.getY() + 1;
}
}
this.precipitationHeightMap[k] = i1;
}
return new BlockPos(pos.getX(), this.precipitationHeightMap[k], pos.getZ());
}
public void func_150804_b(boolean parFlag) {
if (this.isGapLightingUpdated && !this.worldObj.provider.getHasNoSky() && !parFlag) {
this.recheckGaps(this.worldObj.isRemote);
}
this.field_150815_m = true;
if (!this.isLightPopulated && this.isTerrainPopulated) {
this.checkLight();
}
while (!this.tileEntityPosQueue.isEmpty()) {
BlockPos blockpos = (BlockPos) this.tileEntityPosQueue.remove(0);
if (this.getTileEntity(blockpos, Chunk.EnumCreateEntityType.CHECK) == null
&& this.getBlock(blockpos).hasTileEntity()) {
TileEntity tileentity = this.createNewTileEntity(blockpos);
this.worldObj.setTileEntity(blockpos, tileentity);
this.worldObj.markBlockRangeForRenderUpdate(blockpos, blockpos);
}
}
}
public boolean isPopulated() {
return this.field_150815_m && this.isTerrainPopulated && this.isLightPopulated;
}
/**
* +
* Gets a ChunkCoordIntPair representing the Chunk's position.
*/
public ChunkCoordIntPair getChunkCoordIntPair() {
return new ChunkCoordIntPair(this.xPosition, this.zPosition);
}
/**
* +
* Returns whether the ExtendedBlockStorages containing levels
* (in blocks) from arg 1 to arg 2 are fully empty (true) or not
* (false).
*/
public boolean getAreLevelsEmpty(int i, int j) {
if (i < 0) {
i = 0;
}
if (j >= 256) {
j = 255;
}
for (int k = i; k <= j; k += 16) {
ExtendedBlockStorage extendedblockstorage = this.storageArrays[k >> 4];
if (extendedblockstorage != null && !extendedblockstorage.isEmpty()) {
return false;
}
}
return true;
}
public void setStorageArrays(ExtendedBlockStorage[] newStorageArrays) {
if (this.storageArrays.length != newStorageArrays.length) {
logger.warn("Could not set level chunk sections, array length is " + newStorageArrays.length
+ " instead of " + this.storageArrays.length);
} else {
for (int i = 0; i < this.storageArrays.length; ++i) {
this.storageArrays[i] = newStorageArrays[i];
}
}
}
/**
* +
* Initialize this chunk with new binary data.
*/
public void fillChunk(PacketBuffer buf, int p_186033_2_, boolean p_186033_3_) {
boolean flag = !this.worldObj.provider.getHasNoSky();
for (int i = 0; i < this.storageArrays.length; ++i) {
ExtendedBlockStorage extendedblockstorage = this.storageArrays[i];
if ((p_186033_2_ & 1 << i) == 0) {
if (p_186033_3_ && extendedblockstorage != NULL_BLOCK_STORAGE) {
this.storageArrays[i] = NULL_BLOCK_STORAGE;
}
} else {
if (extendedblockstorage == NULL_BLOCK_STORAGE) {
extendedblockstorage = new ExtendedBlockStorage(i << 4, flag);
this.storageArrays[i] = extendedblockstorage;
}
extendedblockstorage.getData().read(buf);
buf.readBytes(extendedblockstorage.getBlocklightArray().getData());
if (flag) {
buf.readBytes(extendedblockstorage.getSkylightArray().getData());
}
}
}
if (p_186033_3_) {
buf.readBytes(this.blockBiomeArray);
}
for (int j = 0; j < this.storageArrays.length; ++j) {
if (this.storageArrays[j] != NULL_BLOCK_STORAGE && (p_186033_2_ & 1 << j) != 0) {
this.storageArrays[j].removeInvalidBlocks();
}
}
this.isLightPopulated = true;
this.isTerrainPopulated = true;
this.generateHeightMap();
for (TileEntity tileentity : this.chunkTileEntityMap.values()) {
tileentity.updateContainingBlockInfo();
}
}
public BiomeGenBase getBiome(BlockPos pos, WorldChunkManager chunkManager) {
int i = pos.getX() & 15;
int j = pos.getZ() & 15;
int k = this.blockBiomeArray[j << 4 | i] & 255;
if (chunkManager != null && k == 255) {
BiomeGenBase biomegenbase = chunkManager.getBiomeGenerator(pos, BiomeGenBase.plains);
k = biomegenbase.biomeID;
this.blockBiomeArray[j << 4 | i] = (byte) (k & 255);
}
BiomeGenBase biomegenbase1 = BiomeGenBase.getBiome(k);
return biomegenbase1 == null ? BiomeGenBase.plains : biomegenbase1;
}
/**
* +
* Returns an array containing a 16x16 mapping on the X/Z of
* block positions in this Chunk to biome IDs.
*/
public byte[] getBiomeArray() {
return this.blockBiomeArray;
}
/**
* +
* Accepts a 256-entry array that contains a 16x16 mapping on
* the X/Z plane of block positions in this Chunk to biome IDs.
*/
public void setBiomeArray(byte[] biomeArray) {
if (this.blockBiomeArray.length != biomeArray.length) {
logger.warn("Could not set level chunk biomes, array length is " + biomeArray.length + " instead of "
+ this.blockBiomeArray.length);
} else {
for (int i = 0; i < this.blockBiomeArray.length; ++i) {
this.blockBiomeArray[i] = biomeArray[i];
}
}
}
/**
* +
* Resets the relight check index to 0 for this Chunk.
*/
public void resetRelightChecks() {
this.queuedLightChecks = 0;
}
/**
* +
* Called once-per-chunk-per-tick, and advances the round-robin
* relight check index by up to 8 blocks at a time. In a
* worst-case scenario, can potentially take up to 25.6 seconds,
* calculated via (4096/8)/20, to re-check all blocks in a
* chunk, which may explain lagging light updates on initial
* world generation.
*/
public void enqueueRelightChecks() {
BlockPos blockpos = new BlockPos(this.xPosition << 4, 0, this.zPosition << 4);
for (int i = 0; i < 8; ++i) {
if (this.queuedLightChecks >= 4096) {
return;
}
int j = this.queuedLightChecks % 16;
int k = this.queuedLightChecks / 16 % 16;
int l = this.queuedLightChecks / 256;
++this.queuedLightChecks;
EnumFacing[] facings = EnumFacing._VALUES;
for (int i1 = 0; i1 < 16; ++i1) {
BlockPos blockpos1 = blockpos.add(k, (j << 4) + i1, l);
boolean flag = i1 == 0 || i1 == 15 || k == 0 || k == 15 || l == 0 || l == 15;
if (this.storageArrays[j] == null && flag || this.storageArrays[j] != null
&& this.storageArrays[j].getBlockByExtId(k, i1, l).getMaterial() == Material.air) {
for (int m = 0; m < facings.length; ++m) {
BlockPos blockpos2 = blockpos1.offset(facings[m]);
if (this.worldObj.getBlockState(blockpos2).getBlock().getLightValue() > 0) {
this.worldObj.checkLight(blockpos2);
}
}
this.worldObj.checkLight(blockpos1);
}
}
}
}
public void checkLight() {
this.isTerrainPopulated = true;
final Chunk chunk = (Chunk) (Object) this;
if (!chunk.alfheim$isLightInitialized())
alfheim$initChunkLighting(chunk, worldObj);
for (int x = -1; x <= 1; x++) {
for (int z = -1; z <= 1; z++) {
if (x == 0 && z == 0)
continue;
final Chunk nChunk = worldObj.getChunkProvider().getLoadedChunk(chunk.xPosition + x,
chunk.zPosition + z);
if (nChunk == null || !nChunk.alfheim$isLightInitialized())
return;
}
}
chunk.setLightPopulated(true);
}
private void func_177441_y() {
for (int i = 0; i < this.updateSkylightColumns.length; ++i) {
this.updateSkylightColumns[i] = true;
}
this.recheckGaps(false);
}
private void func_180700_a(EnumFacing parEnumFacing) {
if (this.isTerrainPopulated) {
if (parEnumFacing == EnumFacing.EAST) {
for (int i = 0; i < 16; ++i) {
this.func_150811_f(15, i);
}
} else if (parEnumFacing == EnumFacing.WEST) {
for (int j = 0; j < 16; ++j) {
this.func_150811_f(0, j);
}
} else if (parEnumFacing == EnumFacing.SOUTH) {
for (int k = 0; k < 16; ++k) {
this.func_150811_f(k, 15);
}
} else if (parEnumFacing == EnumFacing.NORTH) {
for (int l = 0; l < 16; ++l) {
this.func_150811_f(l, 0);
}
}
}
}
private boolean func_150811_f(int x, int z) {
int i = this.getTopFilledSegment();
boolean flag = false;
boolean flag1 = false;
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos((this.xPosition << 4) + x, 0,
(this.zPosition << 4) + z);
for (int j = i + 16 - 1; j > this.worldObj.func_181545_F() || j > 0 && !flag1; --j) {
blockpos$mutableblockpos.func_181079_c(blockpos$mutableblockpos.getX(), j, blockpos$mutableblockpos.getZ());
int k = this.getBlockLightOpacity(blockpos$mutableblockpos);
if (k == 255 && blockpos$mutableblockpos.getY() < this.worldObj.func_181545_F()) {
flag1 = true;
}
if (!flag && k > 0) {
flag = true;
} else if (flag && k == 0 && !this.worldObj.checkLight(blockpos$mutableblockpos)) {
return false;
}
}
for (int l = blockpos$mutableblockpos.getY(); l > 0; --l) {
blockpos$mutableblockpos.func_181079_c(blockpos$mutableblockpos.getX(), l, blockpos$mutableblockpos.getZ());
if (this.getBlock(blockpos$mutableblockpos).getLightValue() > 0) {
this.worldObj.checkLight(blockpos$mutableblockpos);
}
}
return true;
}
public boolean isLoaded() {
return this.isChunkLoaded;
}
public void setChunkLoaded(boolean loaded) {
this.isChunkLoaded = loaded;
}
public World getWorld() {
return this.worldObj;
}
public int[] getHeightMap() {
return this.heightMap;
}
public void setHeightMap(int[] newHeightMap) {
if (this.heightMap.length != newHeightMap.length) {
logger.warn("Could not set level chunk heightmap, array length is " + newHeightMap.length + " instead of "
+ this.heightMap.length);
} else {
for (int i = 0; i < this.heightMap.length; ++i) {
this.heightMap[i] = newHeightMap[i];
}
}
}
public Map<BlockPos, TileEntity> getTileEntityMap() {
return this.chunkTileEntityMap;
}
public ClassInheritanceMultiMap<Entity>[] getEntityLists() {
return this.entityLists;
}
public boolean isTerrainPopulated() {
return this.isTerrainPopulated;
}
public void setTerrainPopulated(boolean terrainPopulated) {
this.isTerrainPopulated = terrainPopulated;
}
public boolean isLightPopulated() {
return this.isLightPopulated;
}
public void setLightPopulated(boolean lightPopulated) {
this.isLightPopulated = lightPopulated;
}
public void setModified(boolean modified) {
this.isModified = modified;
}
public void setHasEntities(boolean hasEntitiesIn) {
this.hasEntities = hasEntitiesIn;
}
public void setLastSaveTime(long saveTime) {
this.lastSaveTime = saveTime;
}
public int getLowestHeight() {
return this.heightMapMinimum;
}
public long getInhabitedTime() {
return this.inhabitedTime;
}
public void setInhabitedTime(long newInhabitedTime) {
this.inhabitedTime = newInhabitedTime;
}
public static enum EnumCreateEntityType {
IMMEDIATE, QUEUED, CHECK;
}
private boolean alfheim$recheckGapsForColumn(final WorldChunkSlice slice, final int x, final int z) {
final int i = x + z * 16;
if (updateSkylightColumns[i]) {
updateSkylightColumns[i] = false;
final int x1 = this.xPosition * 16 + x;
final int z1 = this.zPosition * 16 + z;
alfheim$recheckGapsSkylightNeighborHeight(slice, x1, z1, getHeightValue(x, z),
alfheim$recheckGapsGetLowestHeight(slice, x1, z1));
return true;
}
return false;
}
private int alfheim$recheckGapsGetLowestHeight(final WorldChunkSlice slice, final int x, final int z) {
int max = Integer.MAX_VALUE;
for (final EnumFacing facing : ENUM_FACING_HORIZONTAL) {
final Chunk chunk = slice.getChunkFromWorldCoords(x + facing.getXOffset(), z + facing.getZOffset());
if (chunk != null)
max = Math.min(max, chunk.getLowestHeight());
}
return max;
}
private void alfheim$recheckGapsSkylightNeighborHeight(final WorldChunkSlice slice, final int x, final int z,
final int height, final int max) {
alfheim$checkSkylightNeighborHeight(slice, x, z, max);
for (final EnumFacing facing : ENUM_FACING_HORIZONTAL)
alfheim$checkSkylightNeighborHeight(slice, x + facing.getXOffset(), z + facing.getFrontOffsetZ(), height);
}
private void alfheim$checkSkylightNeighborHeight(final WorldChunkSlice slice, final int x, final int z,
final int maxValue) {
if (slice.getChunkFromWorldCoords(x, z) == null)
return;
final int y = slice.getChunkFromWorldCoords(x, z).getHeightValue(x & 15, z & 15);
if (y > maxValue)
alfheim$updateSkylightNeighborHeight(slice, x, z, maxValue, y + 1);
else if (y < maxValue)
alfheim$updateSkylightNeighborHeight(slice, x, z, y, maxValue + 1);
}
private void alfheim$updateSkylightNeighborHeight(final WorldChunkSlice slice, final int x, final int z,
final int startY, final int endY) {
if (endY < startY)
return;
if (!slice.isLoaded(x, z, 16))
return;
for (int y = startY; y < endY; ++y)
worldObj.checkLightFor(EnumSkyBlock.SKY, new BlockPos(x, y, z));
isModified = true;
}
private static void alfheim$mergeFlags(final EnumSkyBlock lightType, final Chunk inChunk, final Chunk outChunk,
final EnumFacing dir, final EnumFacing.AxisDirection axisDirection) {
// final IChunkLightingData outChunkLightingData = (IChunkLightingData)
// outChunk; // I REALLY NEED TO SUBMIT A BUG REPORT FOR THIS WEIRD PROBLEM
// WHERE FUNCTIONS GET DELETED IF YOU DO THIS IN TEAVM
if (outChunk.alfheim$getNeighborLightChecks() == null)
return;
inChunk.alfheim$initNeighborLightChecks();
final int inIndex = alfheim$getFlagIndex(lightType, dir, axisDirection, EnumBoundaryFacing.IN);
final int outIndex = alfheim$getFlagIndex(lightType, dir.getOpposite(), axisDirection, EnumBoundaryFacing.OUT);
inChunk.alfheim$getNeighborLightChecks()[inIndex] |= outChunk.alfheim$getNeighborLightChecks()[outIndex];
// No need to call Chunk.setModified() since checks are not deleted from
// outChunk
}
private void alfheim$scheduleRelightChecksForBoundary(final Chunk chunk, Chunk nChunk, Chunk sChunk,
final EnumSkyBlock lightType, final int xOffset, final int zOffset,
final EnumFacing.AxisDirection axisDirection) {
if (chunk.alfheim$getNeighborLightChecks() == null)
return;
final int flagIndex = alfheim$getFlagIndex(lightType, xOffset, zOffset, axisDirection, EnumBoundaryFacing.IN); // OUT
// checks
// from
// neighbor
// are
// already
// merged
final int flags = chunk.alfheim$getNeighborLightChecks()[flagIndex];
if (flags == 0)
return;
if (nChunk == null) {
nChunk = worldObj.getChunkProvider().getLoadedChunk(chunk.xPosition + xOffset, chunk.zPosition + zOffset);
if (nChunk == null)
return;
}
if (sChunk == null) {
sChunk = worldObj.getChunkProvider()
.getLoadedChunk(chunk.xPosition + (zOffset != 0 ? axisDirection.getOffset() : 0),
chunk.zPosition + (xOffset != 0 ? axisDirection.getOffset() : 0));
if (sChunk == null)
return; // Cancel, since the checks in the corner columns require the corner column of
// sChunk
}
final int reverseIndex = alfheim$getFlagIndex(lightType, -xOffset, -zOffset, axisDirection,
EnumBoundaryFacing.OUT);
chunk.alfheim$getNeighborLightChecks()[flagIndex] = 0;
if (nChunk.alfheim$getNeighborLightChecks() != null)
nChunk.alfheim$getNeighborLightChecks()[reverseIndex] = 0; // Clear only now that it's clear that the checks
// are processed
chunk.setChunkModified();
nChunk.setChunkModified();
// Get the area to check
// Start in the corner...
int xMin = chunk.xPosition << 4;
int zMin = chunk.zPosition << 4;
// Move to other side of chunk if the direction is positive
if ((xOffset | zOffset) > 0) {
xMin += 15 * xOffset;
zMin += 15 * zOffset;
}
// Shift to other half if necessary (shift perpendicular to dir)
if (axisDirection == EnumFacing.AxisDirection.POSITIVE) {
xMin += 8 * (zOffset & 1); // x & 1 is same as abs(x) for x=-1,0,1
zMin += 8 * (xOffset & 1);
}
// Get maximal values (shift perpendicular to dir)
final int xMax = xMin + 7 * (zOffset & 1);
final int zMax = zMin + 7 * (xOffset & 1);
for (int y = 0; y < 16; ++y)
if ((flags & (1 << y)) != 0)
for (int x = xMin; x <= xMax; ++x)
for (int z = zMin; z <= zMax; ++z)
alfheim$scheduleRelightChecksForColumn(lightType, x, z, y << 4, (y << 4) + 15);
}
private void alfheim$initSkylightForSection(final ExtendedBlockStorage extendedBlockStorage) {
if (worldObj.provider.getHasNoSky())
return;
for (int x = 0; x < 16; ++x) {
for (int z = 0; z < 16; ++z) {
if (((Chunk) (Object) this).getHeightValue(x, z) > extendedBlockStorage.getYLocation())
continue;
for (int y = 0; y < 16; ++y)
extendedBlockStorage.setExtSkylightValue(x, y, z, EnumSkyBlock.SKY.defaultLightValue);
}
}
}
private void alfheim$scheduleRelightChecksForColumn(final EnumSkyBlock lightType, final int x, final int z,
final int yMin, final int yMax) {
final BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
for (int y = yMin; y <= yMax; ++y)
worldObj.checkLightFor(lightType, mutableBlockPos.setPos(x, y, z));
}
private static int alfheim$getFlagIndex(final EnumSkyBlock lightType, final int xOffset, final int zOffset,
final EnumFacing.AxisDirection axisDirection, final EnumBoundaryFacing boundaryFacing) {
return (lightType == EnumSkyBlock.BLOCK ? 0 : 16) | ((xOffset + 1) << 2) | ((zOffset + 1) << 1)
| (axisDirection.getOffset() + 1) | boundaryFacing.ordinal();
}
private static int alfheim$getFlagIndex(final EnumSkyBlock lightType, final EnumFacing facing,
final EnumFacing.AxisDirection axisDirection, final EnumBoundaryFacing boundaryFacing) {
return alfheim$getFlagIndex(lightType, facing.getXOffset(), facing.getZOffset(), axisDirection, boundaryFacing);
}
private static void alfheim$initChunkLighting(final Chunk chunk, final World world) {
final int xBase = chunk.xPosition << 4;
final int zBase = chunk.zPosition << 4;
final BlockPos.PooledMutableBlockPos mutableBlockPos = BlockPos.PooledMutableBlockPos.retain(xBase, 0, zBase);
if (world.isAreaLoaded(mutableBlockPos.add(-16, 0, -16), mutableBlockPos.add(31, 255, 31), false)) {
final ExtendedBlockStorage[] extendedBlockStorage = chunk.getBlockStorageArray();
for (int i = 0; i < extendedBlockStorage.length; ++i) {
final ExtendedBlockStorage storage = extendedBlockStorage[i];
if (storage == Chunk.NULL_BLOCK_STORAGE)
continue;
int yBase = i * 16;
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
mutableBlockPos.setPos(xBase + x, yBase + y, zBase + z);
if (LightUtil.getLightValueForState(storage.get(x, y, z), world, mutableBlockPos) > 0)
world.checkLightFor(EnumSkyBlock.BLOCK, mutableBlockPos);
}
}
}
}
if (!world.provider.getHasNoSky())
chunk.alfheim$setSkylightUpdatedPublic();
chunk.alfheim$setLightInitialized(true);
}
mutableBlockPos.release();
}
private void alfheim$relightSkylightColumn(final int x, final int z, final int height1, final int height2) {
final int yMin = Math.min(height1, height2);
final int yMax = Math.max(height1, height2) - 1;
final Chunk chunk = ((Chunk) (Object) this);
final ExtendedBlockStorage[] sections = chunk.getBlockStorageArray();
final int xBase = (chunk.xPosition << 4) + x;
final int zBase = (chunk.zPosition << 4) + z;
alfheim$scheduleRelightChecksForColumn(EnumSkyBlock.SKY, xBase, zBase, yMin, yMax);
if (sections[yMin >> 4] == Chunk.NULL_BLOCK_STORAGE && yMin > 0) {
worldObj.checkLightFor(EnumSkyBlock.SKY, new BlockPos(xBase, yMin - 1, zBase));
}
short emptySections = 0;
for (int sec = yMax >> 4; sec >= yMin >> 4; --sec) {
if (sections[sec] == Chunk.NULL_BLOCK_STORAGE) {
emptySections |= (short) (1 << sec);
}
}
if (emptySections != 0) {
for (final EnumFacing facing : EnumFacing.HORIZONTALS) {
final int xOffset = facing.getXOffset();
final int zOffset = facing.getZOffset();
final boolean neighborColumnExists = (((x + xOffset) | (z + zOffset)) & 16) == 0
// Checks whether the position is at the specified border (the 16 bit is set for
// both 15+1 and 0-1)
|| worldObj.getChunkProvider().getLoadedChunk(chunk.xPosition + xOffset,
chunk.zPosition + zOffset) != null;
if (neighborColumnExists) {
for (int sec = yMax >> 4; sec >= yMin >> 4; --sec) {
if ((emptySections & (1 << sec)) != 0)
alfheim$scheduleRelightChecksForColumn(EnumSkyBlock.SKY, xBase + xOffset, zBase + zOffset,
sec << 4, (sec << 4) + 15);
}
} else {
chunk.alfheim$initNeighborLightChecks();
final EnumFacing.AxisDirection axisDirection = ((facing.getAxis() == EnumFacing.Axis.X ? z : x)
& 15) < 8 ? EnumFacing.AxisDirection.NEGATIVE : EnumFacing.AxisDirection.POSITIVE;
chunk.alfheim$getNeighborLightChecks()[alfheim$getFlagIndex(EnumSkyBlock.SKY, facing, axisDirection,
EnumBoundaryFacing.OUT)] |= emptySections;
chunk.setChunkModified();
}
}
}
}
public short[] alfheim$getNeighborLightChecks() {
return alfheim$neighborLightChecks;
}
public void alfheim$setNeighborLightChecks(final short[] data) {
alfheim$neighborLightChecks = data;
}
public LightingEngine alfheim$getLightingEngine() {
return alfheim$lightingEngine;
}
public boolean alfheim$isLightInitialized() {
return alfheim$isLightInitialized;
}
public void alfheim$setLightInitialized(final boolean lightInitialized) {
alfheim$isLightInitialized = lightInitialized;
}
public void alfheim$setSkylightUpdatedPublic() {
func_177441_y();
}
public void alfheim$initNeighborLightChecks() {
if (alfheim$getNeighborLightChecks() == null)
alfheim$setNeighborLightChecks(new short[32]);
}
public byte alfheim$getCachedLightFor(final EnumSkyBlock lightType, final BlockPos blockPos) {
final int x = blockPos.getX() & 15;
final int y = blockPos.getY();
final int z = blockPos.getZ() & 15;
final ExtendedBlockStorage extendedblockstorage = storageArrays[y >> 4];
if (extendedblockstorage == Chunk.NULL_BLOCK_STORAGE)
return canSeeSky(blockPos) ? (byte) lightType.defaultLightValue : 0;
else if (lightType == EnumSkyBlock.SKY)
return !worldObj.provider.getHasNoSky() ? (byte) extendedblockstorage.getExtSkylightValue(x, y & 15, z) : 0;
else
return lightType == EnumSkyBlock.BLOCK ? (byte) extendedblockstorage.getExtBlocklightValue(x, y & 15, z)
: (byte) lightType.defaultLightValue;
}
}