Refactored chunk and world generation handling

- common world generator class
- load default chunk date during generation
- prevent loading chunk with invalid data
- add a few logs to catch bad transitions
This commit is contained in:
LemADEC 2017-08-14 00:10:18 +02:00
parent 9bd098bd4f
commit aa3d1b665e
7 changed files with 171 additions and 92 deletions

View file

@ -118,6 +118,7 @@ import cr0s.warpdrive.data.JumpgatesRegistry;
import cr0s.warpdrive.data.StarMapRegistry; import cr0s.warpdrive.data.StarMapRegistry;
import cr0s.warpdrive.event.ChunkHandler; import cr0s.warpdrive.event.ChunkHandler;
import cr0s.warpdrive.event.ClientHandler; import cr0s.warpdrive.event.ClientHandler;
import cr0s.warpdrive.event.CommonWorldGenerator;
import cr0s.warpdrive.event.LivingHandler; import cr0s.warpdrive.event.LivingHandler;
import cr0s.warpdrive.event.WorldHandler; import cr0s.warpdrive.event.WorldHandler;
import cr0s.warpdrive.item.ItemAirTank; import cr0s.warpdrive.item.ItemAirTank;
@ -141,9 +142,7 @@ import cr0s.warpdrive.render.RenderOverlayAir;
import cr0s.warpdrive.render.RenderOverlayCamera; import cr0s.warpdrive.render.RenderOverlayCamera;
import cr0s.warpdrive.render.RenderOverlayLocation; import cr0s.warpdrive.render.RenderOverlayLocation;
import cr0s.warpdrive.world.BiomeSpace; import cr0s.warpdrive.world.BiomeSpace;
import cr0s.warpdrive.world.HyperSpaceWorldGenerator;
import cr0s.warpdrive.world.HyperSpaceWorldProvider; import cr0s.warpdrive.world.HyperSpaceWorldProvider;
import cr0s.warpdrive.world.SpaceWorldGenerator;
import cr0s.warpdrive.world.SpaceWorldProvider; import cr0s.warpdrive.world.SpaceWorldProvider;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -274,9 +273,7 @@ public class WarpDrive implements LoadingCallback {
public static BiomeGenBase spaceBiome; public static BiomeGenBase spaceBiome;
@SuppressWarnings("FieldCanBeLocal") @SuppressWarnings("FieldCanBeLocal")
private SpaceWorldGenerator spaceWorldGenerator; private CommonWorldGenerator commonWorldGenerator;
@SuppressWarnings("FieldCanBeLocal")
private HyperSpaceWorldGenerator hyperSpaceWorldGenerator;
public static Field fieldBlockHardness = null; public static Field fieldBlockHardness = null;
@ -683,10 +680,8 @@ public class WarpDrive implements LoadingCallback {
ForgeChunkManager.setForcedChunkLoadingCallback(instance, instance); ForgeChunkManager.setForcedChunkLoadingCallback(instance, instance);
spaceWorldGenerator = new SpaceWorldGenerator(); commonWorldGenerator = new CommonWorldGenerator();
GameRegistry.registerWorldGenerator(spaceWorldGenerator, 0); GameRegistry.registerWorldGenerator(commonWorldGenerator, 0);
hyperSpaceWorldGenerator = new HyperSpaceWorldGenerator();
GameRegistry.registerWorldGenerator(hyperSpaceWorldGenerator, 0);
spaceBiome = (new BiomeSpace(WarpDriveConfig.G_SPACE_BIOME_ID)).setColor(0).setDisableRain().setBiomeName("Space"); spaceBiome = (new BiomeSpace(WarpDriveConfig.G_SPACE_BIOME_ID)).setColor(0).setDisableRain().setBiomeName("Space");
BiomeDictionary.registerBiomeType(spaceBiome, BiomeDictionary.Type.DEAD, BiomeDictionary.Type.WASTELAND); BiomeDictionary.registerBiomeType(spaceBiome, BiomeDictionary.Type.DEAD, BiomeDictionary.Type.WASTELAND);

View file

@ -1,6 +1,7 @@
package cr0s.warpdrive.compat; package cr0s.warpdrive.compat;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IBlockTransformer; import cr0s.warpdrive.api.IBlockTransformer;
import cr0s.warpdrive.api.ITransformation; import cr0s.warpdrive.api.ITransformation;
import cr0s.warpdrive.block.breathing.BlockAirFlow; import cr0s.warpdrive.block.breathing.BlockAirFlow;
@ -8,6 +9,7 @@ import cr0s.warpdrive.block.breathing.BlockAirSource;
import cr0s.warpdrive.block.energy.TileEntityEnergyBank; import cr0s.warpdrive.block.energy.TileEntityEnergyBank;
import cr0s.warpdrive.block.hull.BlockHullSlab; import cr0s.warpdrive.block.hull.BlockHullSlab;
import cr0s.warpdrive.config.WarpDriveConfig; import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.ChunkData;
import cr0s.warpdrive.data.StateAir; import cr0s.warpdrive.data.StateAir;
import cr0s.warpdrive.event.ChunkHandler; import cr0s.warpdrive.event.ChunkHandler;
@ -15,7 +17,6 @@ import net.minecraft.block.Block;
import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.IWorldAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
public class CompatWarpDrive implements IBlockTransformer { public class CompatWarpDrive implements IBlockTransformer {
@ -39,7 +40,14 @@ public class CompatWarpDrive implements IBlockTransformer {
public NBTBase saveExternals(final World world, final int x, final int y, final int z, public NBTBase saveExternals(final World world, final int x, final int y, final int z,
final Block block, final int blockMeta, final TileEntity tileEntity) { final Block block, final int blockMeta, final TileEntity tileEntity) {
if (block instanceof BlockAirFlow || block instanceof BlockAirSource) { if (block instanceof BlockAirFlow || block instanceof BlockAirSource) {
final int dataAir = ChunkHandler.getChunkData(world, x, y, z).getDataAir(x, y, z); final ChunkData chunkData = ChunkHandler.getChunkData(world, x, y, z, false);
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);
return null;
}
final int dataAir = chunkData.getDataAir(x, y, z);
if (dataAir == StateAir.AIR_DEFAULT) { if (dataAir == StateAir.AIR_DEFAULT) {
return null; return null;
} }
@ -115,7 +123,14 @@ public class CompatWarpDrive implements IBlockTransformer {
} }
if (((NBTTagCompound) nbtBase).hasKey("dataAir")) { if (((NBTTagCompound) nbtBase).hasKey("dataAir")) {
final int dataAir = ((NBTTagCompound) nbtBase).getInteger("dataAir"); final int dataAir = ((NBTTagCompound) nbtBase).getInteger("dataAir");
ChunkHandler.getChunkData(world, x, y, z).setDataAir(x, y, z, dataAir); final ChunkData chunkData = ChunkHandler.getChunkData(world, x, y, z, false);
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);
return;
}
chunkData.setDataAir(x, y, z, dataAir);
} }
} }
} }

View file

@ -63,21 +63,21 @@ public class ChunkData {
&& time - timeUnloaded < RELOAD_DELAY_MIN_MS ) { && time - timeUnloaded < RELOAD_DELAY_MIN_MS ) {
WarpDrive.logger.warn(String.format("Chunk %s (%d %d %d) is reloading after only %d ms", WarpDrive.logger.warn(String.format("Chunk %s (%d %d %d) is reloading after only %d ms",
chunkCoordIntPair, chunkCoordIntPair,
getChunkPosition().chunkPosX, getChunkPosition().chunkPosY, getChunkPosition().chunkPosZ, getChunkPosition().chunkPosX, getChunkPosition().chunkPosY, getChunkPosition().chunkPosZ,
time - timeUnloaded)); time - timeUnloaded));
} }
// load defaults
Arrays.fill(dataAirSegments, null);
Arrays.fill(tickAirSegments, null);
isModified = false;
// check version // check version
if (nbtTagCompoundChunk.hasKey(TAG_CHUNK_MOD_DATA)) { if (nbtTagCompoundChunk.hasKey(TAG_CHUNK_MOD_DATA)) {
final NBTTagCompound nbtTagCompound = nbtTagCompoundChunk.getCompoundTag(TAG_CHUNK_MOD_DATA); final NBTTagCompound nbtTagCompound = nbtTagCompoundChunk.getCompoundTag(TAG_CHUNK_MOD_DATA);
final int version = nbtTagCompound.getInteger(TAG_VERSION); final int version = nbtTagCompound.getInteger(TAG_VERSION);
assert (version == 0 || version == 1); assert (version == 0 || version == 1);
// load defaults
Arrays.fill(dataAirSegments, null);
Arrays.fill(tickAirSegments, null);
isModified = false;
// load from NBT data // load from NBT data
if (version == 1) { if (version == 1) {
final NBTTagList nbtTagList = nbtTagCompound.getTagList(TAG_AIR, Constants.NBT.TAG_COMPOUND); final NBTTagList nbtTagList = nbtTagCompound.getTagList(TAG_AIR, Constants.NBT.TAG_COMPOUND);
@ -142,7 +142,7 @@ public class ChunkData {
// mark as loaded // mark as loaded
timeLoaded = time; timeLoaded = time;
isLoaded = true; isLoaded = true;
if (WarpDrive.isDev && WarpDriveConfig.LOGGING_CHUNK_HANDLER) { if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
WarpDrive.logger.info(String.format("Chunk %s (%d %d %d) is now loaded", WarpDrive.logger.info(String.format("Chunk %s (%d %d %d) is now loaded",
chunkCoordIntPair, chunkCoordIntPair,
getChunkPosition().chunkPosX, getChunkPosition().chunkPosY, getChunkPosition().chunkPosZ)); getChunkPosition().chunkPosX, getChunkPosition().chunkPosY, getChunkPosition().chunkPosZ));
@ -496,10 +496,10 @@ public class ChunkData {
@Override @Override
public String toString() { public String toString() {
final ChunkPosition chunkPosition = getChunkPosition(); final ChunkPosition chunkPosition = getChunkPosition();
return String.format("%s (%d %d @ %d %d %d) hasAir %s isNotEmpty %s )", return String.format("%s (%d %d @ %d %d %d) isLoaded %s hasAir %s isNotEmpty %s )",
getClass().getSimpleName(), getClass().getSimpleName(),
chunkCoordIntPair.chunkXPos, chunkCoordIntPair.chunkZPos, chunkCoordIntPair.chunkXPos, chunkCoordIntPair.chunkZPos,
chunkPosition.chunkPosX, chunkPosition.chunkPosY, chunkPosition.chunkPosZ, chunkPosition.chunkPosX, chunkPosition.chunkPosY, chunkPosition.chunkPosZ,
hasAir(), isNotEmpty()); isLoaded, hasAir(), isNotEmpty());
} }
} }

View file

@ -91,7 +91,12 @@ public class StateAir {
private void refresh(final World world) { private void refresh(final World world) {
// update chunk cache // update chunk cache
if (chunkData == null || !chunkData.isInside(x, y, z)) { if (chunkData == null || !chunkData.isInside(x, y, z)) {
chunkData = ChunkHandler.getChunkData(world, x, y, z); chunkData = ChunkHandler.getChunkData(world, x, y, z, false);
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));
assert(false);
}
chunk = null; chunk = null;
} }
if (chunk == null) { if (chunk == null) {

View file

@ -23,7 +23,6 @@ import cpw.mods.fml.common.gameevent.TickEvent.WorldTickEvent;
import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.Side;
import net.minecraftforge.event.world.ChunkDataEvent; import net.minecraftforge.event.world.ChunkDataEvent;
import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.ChunkWatchEvent;
import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.event.world.WorldEvent;
public class ChunkHandler { public class ChunkHandler {
@ -40,48 +39,72 @@ public class ChunkHandler {
/* event catchers */ /* event catchers */
@SubscribeEvent @SubscribeEvent
public void onLoadWorld(WorldEvent.Load event) { public void onLoadWorld(WorldEvent.Load event) {
if (event.world.isRemote || event.world.provider.dimensionId != 0) { if (event.world.isRemote || event.world.provider.dimensionId == 0) {
return; if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
} WarpDrive.logger.info(String.format("%s world %s load.",
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) { event.world.isRemote ? "Client" : "Server",
WarpDrive.logger.info(String.format("World %s load.", event.world.provider.getDimensionName()));
event.world.provider.getDimensionName())); }
} }
// load star map if ( !event.world.isRemote
final String filename = String.format("%s/%s.dat", event.world.getSaveHandler().getWorldDirectory().getPath(), WarpDrive.MODID); && event.world.provider.dimensionId == 0 ) {
final NBTTagCompound tagCompound = Commons.readNBTFromFile(filename); // load star map
WarpDrive.starMap.readFromNBT(tagCompound); final String filename = String.format("%s/%s.dat", event.world.getSaveHandler().getWorldDirectory().getPath(), WarpDrive.MODID);
final NBTTagCompound tagCompound = Commons.readNBTFromFile(filename);
WarpDrive.starMap.readFromNBT(tagCompound);
}
}
// new chunks aren't loaded
public static void onGenerated(final World world, final int chunkX, final int chunkZ) {
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
WarpDrive.logger.info(String.format("%s world %s chunk [%d, %d] generating",
world.isRemote ? "Client" : "Server",
world.provider.getDimensionName(),
chunkX, chunkZ));
}
final ChunkData chunkData = getChunkData(world.isRemote, world.provider.dimensionId, chunkX, chunkZ, true);
assert(chunkData != null);
// (world can load a non-generated chunk, or the chunk be regenerated, so we reset only as needed)
if (!chunkData.isLoaded()) {
chunkData.load(new NBTTagCompound());
}
} }
// (server side only) // (server side only)
@SubscribeEvent @SubscribeEvent
public void onLoadChunkData(ChunkDataEvent.Load event) { public void onLoadChunkData(ChunkDataEvent.Load event) {
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) { if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
WarpDrive.logger.info(String.format("World %s chunk %s loading data", WarpDrive.logger.info(String.format("%s world %s chunk %s loading data (1)",
event.world.isRemote ? "Client" : "Server",
event.world.provider.getDimensionName(), event.world.provider.getDimensionName(),
event.getChunk().getChunkCoordIntPair())); event.getChunk().getChunkCoordIntPair()));
} }
final ChunkData chunkData = getChunkData(event.world.isRemote, event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition); final ChunkData chunkData = getChunkData(event.world.isRemote, event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition, true);
assert(chunkData != null);
chunkData.load(event.getData()); chunkData.load(event.getData());
} }
// (called after data loading, only useful client side) // (called after data loading, only useful client side)
@SubscribeEvent @SubscribeEvent
public void onLoadChunk(ChunkEvent.Load event) { public void onLoadChunk(ChunkEvent.Load event) {
if (event.world.isRemote) { if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) { WarpDrive.logger.info(String.format("%s world %s chunk %s loaded (2)",
WarpDrive.logger.info(String.format("World %s chunk %s loaded", event.world.isRemote ? "Client" : "Server",
event.world.provider.getDimensionName(), event.world.provider.getDimensionName(),
event.getChunk().getChunkCoordIntPair())); event.getChunk().getChunkCoordIntPair()));
} }
final ChunkData chunkData = getChunkData(event.world.isRemote, event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition); if (event.world.isRemote) {
final ChunkData chunkData = getChunkData(event.world.isRemote, event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition, true);
assert(chunkData != null);
chunkData.load(new NBTTagCompound()); chunkData.load(new NBTTagCompound());
} }
} }
/*
// (server side only) // (server side only)
@SubscribeEvent @SubscribeEvent
public void onWatchChunk(ChunkWatchEvent.Watch event) { public void onWatchChunk(ChunkWatchEvent.Watch event) {
@ -92,31 +115,44 @@ public class ChunkHandler {
event.player)); event.player));
} }
} }
/**/
// (server side only) // (server side only)
// not called when chunk wasn't changed since last save? // not called when chunk wasn't changed since last save?
@SubscribeEvent @SubscribeEvent
public void onSaveChunkData(ChunkDataEvent.Save event) { public void onSaveChunkData(ChunkDataEvent.Save event) {
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) { if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
WarpDrive.logger.info(String.format("World %s chunk %s save data", WarpDrive.logger.info(String.format("%s world %s chunk %s save data",
event.world.isRemote ? "Client" : "Server",
event.world.provider.getDimensionName(), event.world.provider.getDimensionName(),
event.getChunk().getChunkCoordIntPair())); event.getChunk().getChunkCoordIntPair()));
} }
final ChunkData chunkData = getChunkData(event.world.isRemote, event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition); final ChunkData chunkData = getChunkData(event.world.isRemote, event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition, false);
chunkData.save(event.getData()); if (chunkData != null) {
chunkData.save(event.getData());
} else {
WarpDrive.logger.error(String.format("%s world %s chunk %s is saving data without loading it first!",
event.world.isRemote ? "Client" : "Server",
event.world.provider.getDimensionName(),
event.getChunk().getChunkCoordIntPair()));
}
} }
// (server side only) // (server side only)
@SubscribeEvent @SubscribeEvent
public void onSaveWorld(WorldEvent.Save event) { public void onSaveWorld(WorldEvent.Save event) {
if (event.world.isRemote || event.world.provider.dimensionId != 0) { if (event.world.provider.dimensionId != 0) {
return; return;
} }
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) { if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
WarpDrive.logger.info(String.format("World %s saved.", WarpDrive.logger.info(String.format("%s world %s saved.",
event.world.isRemote ? "Client" : "Server",
event.world.provider.getDimensionName())); event.world.provider.getDimensionName()));
} }
if (event.world.isRemote) {
return;
}
// save star map // save star map
final String filename = String.format("%s/%s.dat", event.world.getSaveHandler().getWorldDirectory().getPath(), WarpDrive.MODID); final String filename = String.format("%s/%s.dat", event.world.getSaveHandler().getWorldDirectory().getPath(), WarpDrive.MODID);
final NBTTagCompound tagCompound = new NBTTagCompound(); final NBTTagCompound tagCompound = new NBTTagCompound();
@ -127,7 +163,8 @@ public class ChunkHandler {
@SubscribeEvent @SubscribeEvent
public void onUnloadWorld(WorldEvent.Unload event) { public void onUnloadWorld(WorldEvent.Unload event) {
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) { if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
WarpDrive.logger.info(String.format("World %s unload", WarpDrive.logger.info(String.format("%s world %s unload",
event.world.isRemote ? "Client" : "Server",
event.world.provider.getDimensionName())); event.world.provider.getDimensionName()));
} }
@ -144,10 +181,6 @@ public class ChunkHandler {
} }
} }
if (event.world.isRemote || event.world.provider.dimensionId != 0) {
return;
}
// @TODO unload star map // @TODO unload star map
} }
@ -156,25 +189,36 @@ public class ChunkHandler {
@SubscribeEvent @SubscribeEvent
public void onUnloadChunk(ChunkEvent.Unload event) { public void onUnloadChunk(ChunkEvent.Unload event) {
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) { if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
WarpDrive.logger.info(String.format("World %s chunk %s unload", WarpDrive.logger.info(String.format("%s world %s chunk %s unload",
event.world.isRemote ? "Client" : "Server",
event.world.provider.getDimensionName(), event.world.provider.getDimensionName(),
event.getChunk().getChunkCoordIntPair())); event.getChunk().getChunkCoordIntPair()));
} }
getChunkData(event.world.isRemote, event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition).unload(); final ChunkData chunkData = getChunkData(event.world.isRemote, event.world.provider.dimensionId, event.getChunk().xPosition, event.getChunk().zPosition, false);
if (chunkData != null) {
chunkData.unload();
} else {
WarpDrive.logger.error(String.format("%s world %s chunk %s is unloading without loading it first!",
event.world.isRemote ? "Client" : "Server",
event.world.provider.getDimensionName(),
event.getChunk().getChunkCoordIntPair()));
}
} }
/*
// (not called when closing SSP game) // (not called when closing SSP game)
// warning: will return invalid world when switching dimensions
@SubscribeEvent @SubscribeEvent
public void onUnwatchChunk(ChunkWatchEvent.UnWatch event) { public void onUnwatchChunk(ChunkWatchEvent.UnWatch event) {
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) { if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
WarpDrive.logger.info(String.format("World %s chunk %s unwatch by %s", WarpDrive.logger.info(String.format("%s world %s chunk %s unwatch by %s",
event.player.worldObj.isRemote ? "Client" : "Server",
event.player.worldObj.provider.getDimensionName(), event.player.worldObj.provider.getDimensionName(),
event.chunk, event.chunk,
event.player)); event.player));
} }
} }
/**/
@SubscribeEvent @SubscribeEvent
public void onWorldTick(WorldTickEvent event) { public void onWorldTick(WorldTickEvent event) {
if (event.side != Side.SERVER || event.phase != Phase.END) { if (event.side != Side.SERVER || event.phase != Phase.END) {
@ -186,21 +230,29 @@ public class ChunkHandler {
public static void onBlockUpdated(final World world, final int x, final int y, final int z) { public static void onBlockUpdated(final World world, final int x, final int y, final int z) {
if (!world.isRemote) { if (!world.isRemote) {
getChunkData(world, x, y, z).onBlockUpdated(x, y, z); final ChunkData chunkData = getChunkData(world, x, y, z, false);
if (chunkData != null) {
chunkData.onBlockUpdated(x, y, z);
} else {
WarpDrive.logger.error(String.format("%s world %s block updating at (%d %d %d), while chunk isn't loaded!",
world.isRemote ? "Client" : "Server",
world.provider.getDimensionName(),
x, y, z));
}
} }
} }
/* internal access */ /* internal access */
public static ChunkData getChunkData(final World world, final int x, final int y, final int z) { 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); return getChunkData(world.isRemote, world.provider.dimensionId, x, y, z, doCreate);
} }
private static ChunkData getChunkData(final boolean isRemote, final int dimensionId, final int x, final int y, final int z) { private static ChunkData getChunkData(final boolean isRemote, final int dimensionId, final int x, final int y, final int z, final boolean doCreate) {
assert (y >= 0 && y <= 255); assert (y >= 0 && y <= 255);
return getChunkData(isRemote, dimensionId, x >> 4, z >> 4); return getChunkData(isRemote, dimensionId, x >> 4, z >> 4, doCreate);
} }
private static ChunkData getChunkData(final boolean isRemote, final int dimensionId, final int xChunk, final int zChunk) { private static ChunkData getChunkData(final boolean isRemote, final int dimensionId, final int xChunk, final int zChunk, final boolean doCreate) {
// get dimension data // get dimension data
LocalProfiler.updateCallStat("getChunkData"); LocalProfiler.updateCallStat("getChunkData");
final Map<Integer, Map<Long, ChunkData>> registry = isRemote ? registryClient : registryServer; final Map<Integer, Map<Long, ChunkData>> registry = isRemote ? registryClient : registryServer;
@ -208,6 +260,9 @@ public class ChunkHandler {
// (lambda expressions are forcing synchronisation, so we don't use them here) // (lambda expressions are forcing synchronisation, so we don't use them here)
//noinspection Java8MapApi //noinspection Java8MapApi
if (mapRegistryItems == null) { if (mapRegistryItems == null) {
if (!doCreate) {
return null;
}
// TLongObjectMap<ChunkData> m = TCollections.synchronizedMap(new TLongObjectHashMap<ChunkData>(2048) ); // TLongObjectMap<ChunkData> m = TCollections.synchronizedMap(new TLongObjectHashMap<ChunkData>(2048) );
// @TODO: http://trove4j.sourceforge.net/javadocs/gnu/trove/TCollections.html#synchronizedMap(gnu.trove.map.TLongObjectMap) // @TODO: http://trove4j.sourceforge.net/javadocs/gnu/trove/TCollections.html#synchronizedMap(gnu.trove.map.TLongObjectMap)
mapRegistryItems = new LinkedHashMap<>(2048); // Collections.synchronizedMap(new LinkedHashMap<>(2048)); mapRegistryItems = new LinkedHashMap<>(2048); // Collections.synchronizedMap(new LinkedHashMap<>(2048));
@ -219,7 +274,16 @@ public class ChunkHandler {
// (lambda expressions are forcing synchronisation, so we don't use them here) // (lambda expressions are forcing synchronisation, so we don't use them here)
//noinspection Java8MapApi //noinspection Java8MapApi
if (chunkData == null) { if (chunkData == null) {
if (!doCreate) {
return null;
}
chunkData = new ChunkData(xChunk, zChunk); chunkData = new ChunkData(xChunk, zChunk);
if (WarpDriveConfig.LOGGING_CHUNK_HANDLER) {
WarpDrive.logger.info(String.format("%s world DIM%d chunk %s is being added to the registry",
isRemote ? "Client" : "Server",
dimensionId,
chunkData.getChunkCoords()));
}
mapRegistryItems.put(index, chunkData); mapRegistryItems.put(index, chunkData);
} }
return chunkData; return chunkData;
@ -234,12 +298,13 @@ public class ChunkHandler {
/* commons */ /* commons */
public static boolean isLoaded(final World world, final int x, final int y, final int z) { public static boolean isLoaded(final World world, final int x, final int y, final int z) {
return getChunkData(world, x, y, z).isLoaded(); final ChunkData chunkData = getChunkData(world, x, y, z, false);
return chunkData != null && chunkData.isLoaded();
} }
/* air handling */ /* air handling */
public static StateAir getStateAir(final World world, final int x, final int y, final int z) { public static StateAir getStateAir(final World world, final int x, final int y, final int z) {
return getChunkData(world, x, y, z).getStateAir(world, x, y, z); return getChunkData(world, x, y, z, true).getStateAir(world, x, y, z);
} }
public static void updateTick(final World world) { public static void updateTick(final World world) {
@ -251,15 +316,25 @@ public class ChunkHandler {
return; return;
} }
int countLoaded = 0; int countLoaded = 0;
final long time = System.currentTimeMillis() - CHUNK_HANDLER_UNLOADED_CHUNK_MAX_AGE_MS; final long timeForRemoval = System.currentTimeMillis() - CHUNK_HANDLER_UNLOADED_CHUNK_MAX_AGE_MS;
for(Iterator<Entry<Long, ChunkData>> entryIterator = mapRegistryItems.entrySet().iterator(); entryIterator.hasNext(); ) { 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 Map.Entry<Long, ChunkData> entryChunkData = entryIterator.next();
final ChunkData chunkData = entryChunkData.getValue(); final ChunkData chunkData = entryChunkData.getValue();
// update loaded chunks, remove old unloaded chunks // update loaded chunks, remove old unloaded chunks
if (chunkData.isLoaded()) { if (chunkData.isLoaded()) {
updateTickLoopStep(world, mapRegistryItems, entryChunkData.getValue());
countLoaded++; countLoaded++;
} else if (chunkData.timeUnloaded < time) { 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(); entryIterator.remove();
} }
} }

View file

@ -1,4 +1,4 @@
package cr0s.warpdrive.world; package cr0s.warpdrive.event;
import cr0s.warpdrive.data.CelestialObjectManager; import cr0s.warpdrive.data.CelestialObjectManager;
import cr0s.warpdrive.config.WarpDriveConfig; import cr0s.warpdrive.config.WarpDriveConfig;
@ -7,6 +7,7 @@ import cr0s.warpdrive.config.structures.Orb.OrbShell;
import cr0s.warpdrive.config.structures.OrbInstance; import cr0s.warpdrive.config.structures.OrbInstance;
import cr0s.warpdrive.config.structures.StructureGroup; import cr0s.warpdrive.config.structures.StructureGroup;
import cr0s.warpdrive.data.CelestialObject; import cr0s.warpdrive.data.CelestialObject;
import cr0s.warpdrive.event.ChunkHandler;
import java.util.Random; import java.util.Random;
@ -15,10 +16,14 @@ import net.minecraft.world.chunk.IChunkProvider;
import cpw.mods.fml.common.IWorldGenerator; import cpw.mods.fml.common.IWorldGenerator;
public class SpaceWorldGenerator implements IWorldGenerator { public class CommonWorldGenerator implements IWorldGenerator {
@Override @Override
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) {
// chunk data creation
ChunkHandler.onGenerated(world, chunkX, chunkZ);
// actual structure generation
try { try {
final int x = (chunkX * 16) + (5 - random.nextInt(10)); final int x = (chunkX * 16) + (5 - random.nextInt(10));
final int z = (chunkZ * 16) + (5 - random.nextInt(10)); final int z = (chunkZ * 16) + (5 - random.nextInt(10));
@ -45,6 +50,7 @@ public class SpaceWorldGenerator implements IWorldGenerator {
exception.printStackTrace(); exception.printStackTrace();
} }
} }
/** /**
* *
* @deprecated reference design for EntitySphereGenerator * @deprecated reference design for EntitySphereGenerator

View file

@ -1,17 +0,0 @@
package cr0s.warpdrive.world;
import java.util.Random;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import cpw.mods.fml.common.IWorldGenerator;
public class HyperSpaceWorldGenerator implements IWorldGenerator {
@Override
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) {
if (world.provider.dimensionId != 0) {
// ...
}
}
}