Fixed CME crash in air simulation
This commit is contained in:
parent
dd69616a68
commit
8380d9873c
8 changed files with 90 additions and 47 deletions
|
@ -96,8 +96,9 @@ public class BreathingManager {
|
|||
vAirBlock = vPosition;
|
||||
break;
|
||||
} else if (block != Blocks.air) {
|
||||
StateAir stateAir = ChunkHandler.getStateAir(entityLivingBase.worldObj, vPosition.x, vPosition.y, vPosition.z);
|
||||
if (stateAir.concentration > 0) {
|
||||
final StateAir stateAir = ChunkHandler.getStateAir(entityLivingBase.worldObj, vPosition.x, vPosition.y, vPosition.z);
|
||||
if ( stateAir == null
|
||||
|| stateAir.concentration > 0 ) {
|
||||
vAirBlock = vPosition;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class LocalProfiler {
|
|||
}
|
||||
}
|
||||
|
||||
private static void printCallStats() {
|
||||
public static void printCallStats() {
|
||||
WarpDrive.logger.info("Dumping chunk stats:");
|
||||
for (Entry<String, Integer> entryStat : stats.entrySet()) {
|
||||
WarpDrive.logger.info(String.format("%10d x %s",
|
||||
|
|
|
@ -16,7 +16,8 @@ public class BlockAirFlow extends BlockAbstractAir {
|
|||
public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) {
|
||||
if (!world.isRemote) {
|
||||
final StateAir stateAir = ChunkHandler.getStateAir(world, x, y, z);
|
||||
if (!stateAir.isAirFlow() || stateAir.concentration == 0) {
|
||||
if ( stateAir != null
|
||||
&& (!stateAir.isAirFlow() || stateAir.concentration == 0) ) {
|
||||
world.setBlockToAir(x, y, z);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,9 @@ public class BlockAirSource extends BlockAbstractAir {
|
|||
@Override
|
||||
public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) {
|
||||
if (!world.isRemote) {
|
||||
StateAir stateAir = ChunkHandler.getStateAir(world, x, y, z);
|
||||
if (!stateAir.isAirSource() || stateAir.concentration == 0) {
|
||||
final StateAir stateAir = ChunkHandler.getStateAir(world, x, y, z);
|
||||
if ( stateAir != null
|
||||
&& (!stateAir.isAirSource() || stateAir.concentration == 0) ) {
|
||||
world.setBlockToAir(x, y, z);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,10 @@ public class TileEntityAirGeneratorTiered extends TileEntityAbstractEnergy {
|
|||
final int y = yCoord + direction.offsetY;
|
||||
final int z = zCoord + direction.offsetZ;
|
||||
|
||||
StateAir stateAir = ChunkHandler.getStateAir(worldObj, x, y, z);
|
||||
final StateAir stateAir = ChunkHandler.getStateAir(worldObj, x, y, z);
|
||||
if (stateAir == null) {// chunk isn't loaded
|
||||
return;
|
||||
}
|
||||
stateAir.updateBlockCache(worldObj);
|
||||
if (stateAir.isAir()) {// can be air
|
||||
final short range = (short) (WarpDriveConfig.BREATHING_AIR_GENERATION_RANGE_BLOCKS[tier - 1] - 1);
|
||||
|
|
|
@ -46,11 +46,9 @@ public class CompatWarpDrive implements IBlockTransformer {
|
|||
public NBTBase saveExternals(final World world, final int x, final int y, final int z,
|
||||
final Block block, final int blockMeta, final TileEntity tileEntity) {
|
||||
if (block instanceof BlockAirFlow || block instanceof BlockAirSource) {
|
||||
final ChunkData chunkData = ChunkHandler.getChunkData(world, x, y, z, false);
|
||||
final ChunkData chunkData = ChunkHandler.getChunkData(world, x, y, z);
|
||||
if (chunkData == null) {
|
||||
WarpDrive.logger.error(String.format("CompatWarpDrive trying to get data from an non-loaded chunk in %s @ (%d %d %d)",
|
||||
world.provider.getDimensionName(), x, y, z));
|
||||
assert(false);
|
||||
// chunk isn't loaded, skip it
|
||||
return null;
|
||||
}
|
||||
final int dataAir = chunkData.getDataAir(x, y, z);
|
||||
|
@ -68,11 +66,9 @@ public class CompatWarpDrive implements IBlockTransformer {
|
|||
public void removeExternals(final World world, final int x, final int y, final int z,
|
||||
final Block block, final int blockMeta, final TileEntity tileEntity) {
|
||||
if (block instanceof BlockAirFlow || block instanceof BlockAirSource) {
|
||||
final ChunkData chunkData = ChunkHandler.getChunkData(world, x, y, z, false);
|
||||
final ChunkData chunkData = ChunkHandler.getChunkData(world, x, y, z);
|
||||
if (chunkData == null) {
|
||||
WarpDrive.logger.error(String.format("CompatWarpDrive trying to get data from an non-loaded chunk in %s @ (%d %d %d)",
|
||||
world.provider.getDimensionName(), x, y, z));
|
||||
assert(false);
|
||||
// chunk isn't loaded, skip it
|
||||
return;
|
||||
}
|
||||
chunkData.setDataAir(x, y, z, StateAir.AIR_DEFAULT);
|
||||
|
@ -188,11 +184,9 @@ public class CompatWarpDrive implements IBlockTransformer {
|
|||
if (((NBTTagCompound) nbtBase).hasKey("dataAir")) {
|
||||
final byte rotationSteps = transformation.getRotationSteps();
|
||||
final int dataAir = ((NBTTagCompound) nbtBase).getInteger("dataAir");
|
||||
final ChunkData chunkData = ChunkHandler.getChunkData(world, x, y, z, false);
|
||||
final ChunkData chunkData = ChunkHandler.getChunkData(world, x, y, z);
|
||||
if (chunkData == null) {
|
||||
WarpDrive.logger.error(String.format("CompatWarpDrive trying to set data from an non-loaded chunk in %s @ (%d %d %d)",
|
||||
world.provider.getDimensionName(), x, y, z));
|
||||
assert(false);
|
||||
// chunk isn't loaded, skip it
|
||||
return;
|
||||
}
|
||||
final int dataAirRotated = StateAir.rotate(dataAir, rotationSteps);
|
||||
|
|
|
@ -91,10 +91,9 @@ public class StateAir {
|
|||
private void refresh(final World world) {
|
||||
// update chunk cache
|
||||
if (chunkData == null || !chunkData.isInside(x, y, z)) {
|
||||
chunkData = ChunkHandler.getChunkData(world, x, y, z, false);
|
||||
chunkData = ChunkHandler.getChunkData(world, x, y, z);
|
||||
if (chunkData == null) {
|
||||
WarpDrive.logger.error(String.format("State air trying to get data from an non-loaded chunk in %s @ (%d %d %d)",
|
||||
world.provider.getDimensionName(), x, y, z));
|
||||
// chunk isn't loaded, skip it
|
||||
assert(false);
|
||||
}
|
||||
chunk = null;
|
||||
|
|
|
@ -7,6 +7,7 @@ import cr0s.warpdrive.config.WarpDriveConfig;
|
|||
import cr0s.warpdrive.data.ChunkData;
|
||||
import cr0s.warpdrive.data.StateAir;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
|
@ -230,7 +231,7 @@ public class ChunkHandler {
|
|||
|
||||
public static void onBlockUpdated(final World world, final int x, final int y, final int z) {
|
||||
if (!world.isRemote) {
|
||||
final ChunkData chunkData = getChunkData(world, x, y, z, false);
|
||||
final ChunkData chunkData = getChunkData(world, x, y, z);
|
||||
if (chunkData != null) {
|
||||
chunkData.onBlockUpdated(x, y, z);
|
||||
} else {
|
||||
|
@ -246,13 +247,28 @@ public class ChunkHandler {
|
|||
}
|
||||
|
||||
/* internal access */
|
||||
public static ChunkData getChunkData(final World world, final int x, final int y, final int z, final boolean doCreate) {
|
||||
return getChunkData(world.isRemote, world.provider.dimensionId, x, y, z, doCreate);
|
||||
/**
|
||||
* Return null and spam logs if chunk isn't already generated or loaded
|
||||
*/
|
||||
public static ChunkData getChunkData(final World world, final int x, final int y, final int z) {
|
||||
final ChunkData chunkData = getChunkData(world.isRemote, world.provider.dimensionId, x, y, z);
|
||||
if (chunkData == null) {
|
||||
WarpDrive.logger.error(String.format("Trying to get data from an non-loaded chunk in %s world %s @ (%d %d %d)",
|
||||
world.isRemote ? "Client" : "Server",
|
||||
world.provider.getDimensionName(), x, y, z));
|
||||
LocalProfiler.printCallStats();
|
||||
Commons.dumpAllThreads();
|
||||
assert(false);
|
||||
}
|
||||
return chunkData;
|
||||
}
|
||||
|
||||
private static ChunkData getChunkData(final boolean isRemote, final int dimensionId, final int x, final int y, final int z, final boolean doCreate) {
|
||||
/**
|
||||
* Return null if chunk isn't already generated or loaded
|
||||
*/
|
||||
private static ChunkData getChunkData(final boolean isRemote, final int dimensionId, final int x, final int y, final int z) {
|
||||
assert (y >= 0 && y <= 255);
|
||||
return getChunkData(isRemote, dimensionId, x >> 4, z >> 4, doCreate);
|
||||
return getChunkData(isRemote, dimensionId, x >> 4, z >> 4, false);
|
||||
}
|
||||
|
||||
private static ChunkData getChunkData(final boolean isRemote, final int dimensionId, final int xChunk, final int zChunk, final boolean doCreate) {
|
||||
|
@ -287,7 +303,16 @@ public class ChunkHandler {
|
|||
dimensionId,
|
||||
chunkData.getChunkCoords()));
|
||||
}
|
||||
mapRegistryItems.put(index, chunkData);
|
||||
if (Commons.isSafeThread()) {
|
||||
mapRegistryItems.put(index, chunkData);
|
||||
} else {
|
||||
WarpDrive.logger.error(String.format("%s world DIM%d chunk %s is being added to the registry outside main thread!",
|
||||
isRemote ? "Client" : "Server",
|
||||
dimensionId,
|
||||
chunkData.getChunkCoords()));
|
||||
Commons.dumpAllThreads();
|
||||
mapRegistryItems.put(index, chunkData);
|
||||
}
|
||||
}
|
||||
return chunkData;
|
||||
}
|
||||
|
@ -301,13 +326,18 @@ public class ChunkHandler {
|
|||
|
||||
/* commons */
|
||||
public static boolean isLoaded(final World world, final int x, final int y, final int z) {
|
||||
final ChunkData chunkData = getChunkData(world, x, y, z, false);
|
||||
final ChunkData chunkData = getChunkData(world.isRemote, world.provider.dimensionId, x, y, z);
|
||||
return chunkData != null && chunkData.isLoaded();
|
||||
}
|
||||
|
||||
/* air handling */
|
||||
public static StateAir getStateAir(final World world, final int x, final int y, final int z) {
|
||||
return getChunkData(world, x, y, z, true).getStateAir(world, x, y, z);
|
||||
final ChunkData chunkData = getChunkData(world, x, y, z);
|
||||
if (chunkData == null) {
|
||||
// chunk isn't loaded, skip it
|
||||
return null;
|
||||
}
|
||||
return chunkData.getStateAir(world, x, y, z);
|
||||
}
|
||||
|
||||
public static void updateTick(final World world) {
|
||||
|
@ -321,26 +351,40 @@ public class ChunkHandler {
|
|||
int countLoaded = 0;
|
||||
final long timeForRemoval = System.currentTimeMillis() - CHUNK_HANDLER_UNLOADED_CHUNK_MAX_AGE_MS;
|
||||
final long timeForThrottle = System.currentTimeMillis() + 200;
|
||||
for(final Iterator<Entry<Long, ChunkData>> entryIterator = mapRegistryItems.entrySet().iterator(); entryIterator.hasNext(); ) {
|
||||
final Map.Entry<Long, ChunkData> entryChunkData = entryIterator.next();
|
||||
final ChunkData chunkData = entryChunkData.getValue();
|
||||
// update loaded chunks, remove old unloaded chunks
|
||||
if (chunkData.isLoaded()) {
|
||||
countLoaded++;
|
||||
if (System.currentTimeMillis() < timeForThrottle) {
|
||||
updateTickLoopStep(world, mapRegistryItems, entryChunkData.getValue());
|
||||
final long sizeBefore = mapRegistryItems.size();
|
||||
|
||||
try {
|
||||
|
||||
for (final Iterator<Entry<Long, ChunkData>> entryIterator = mapRegistryItems.entrySet().iterator(); entryIterator.hasNext(); ) {
|
||||
final Map.Entry<Long, ChunkData> entryChunkData = entryIterator.next();
|
||||
final ChunkData chunkData = entryChunkData.getValue();
|
||||
// update loaded chunks, remove old unloaded chunks
|
||||
if (chunkData.isLoaded()) {
|
||||
countLoaded++;
|
||||
if (System.currentTimeMillis() < timeForThrottle) {
|
||||
updateTickLoopStep(world, mapRegistryItems, entryChunkData.getValue());
|
||||
}
|
||||
} else if (chunkData.timeUnloaded < timeForRemoval) {
|
||||
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
|
||||
WarpDrive.logger.info(String.format("%s world %s chunk %s is being removed from updateTick (size is %d)",
|
||||
world.isRemote ? "Client" : "Server",
|
||||
world.provider.getDimensionName(),
|
||||
chunkData.getChunkCoords(),
|
||||
mapRegistryItems.size()));
|
||||
}
|
||||
entryIterator.remove();
|
||||
}
|
||||
} else if (chunkData.timeUnloaded < timeForRemoval) {
|
||||
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
|
||||
WarpDrive.logger.info(String.format("%s world %s chunk %s is being removed from updateTick (size is %d)",
|
||||
world.isRemote ? "Client" : "Server",
|
||||
world.provider.getDimensionName(),
|
||||
chunkData.getChunkCoords(),
|
||||
mapRegistryItems.size()));
|
||||
}
|
||||
entryIterator.remove();
|
||||
}
|
||||
|
||||
} catch (ConcurrentModificationException exception) {
|
||||
WarpDrive.logger.error(String.format("%s world %s had some chunks changed outside main thread? (size %d -> %d)",
|
||||
world.isRemote ? "Client" : "Server",
|
||||
world.provider.getDimensionName(),
|
||||
sizeBefore, mapRegistryItems.size()));
|
||||
exception.printStackTrace();
|
||||
LocalProfiler.printCallStats();
|
||||
}
|
||||
|
||||
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
|
||||
if (world.provider.dimensionId == 0) {
|
||||
delayLogging = (delayLogging + 1) % 4096;
|
||||
|
|
Loading…
Add table
Reference in a new issue