use of io.xol.chunkstories.api.world.WorldUser in project chunkstories by Hugobros3.
the class MultithreadedOfflineWorldConverter method stepThreeSpreadLightning.
protected void stepThreeSpreadLightning(WorldTool csWorld) {
verbose("Entering step three: spreading light");
csWorld.setLightning(true);
WorldSize size = csWorld.getWorldInfo().getSize();
int maxHeightPossible = 256;
int done = 0;
int todo = (size.sizeInChunks) * (size.sizeInChunks);
double completion = 0.0;
long lastPercentageShow = System.currentTimeMillis();
Set<ChunkHolder> registeredCS_Holders = new HashSet<ChunkHolder>();
Set<Heightmap> registeredCS_Summaries = new HashSet<Heightmap>();
int chunksAquired = 0;
WorldUser worldUser = this;
int waveSize = this.threadsCount * 32;
int wave = 0;
CompoundFence waveFence = new CompoundFence();
for (int chunkX = 0; chunkX < size.sizeInChunks; chunkX++) {
for (int chunkZ = 0; chunkZ < size.sizeInChunks; chunkZ++) {
wave++;
CompoundFence loadRelevantData = new CompoundFence();
Heightmap sum = csWorld.getRegionsSummariesHolder().aquireHeightmapChunkCoordinates(worldUser, chunkX, chunkZ);
registeredCS_Summaries.add(sum);
loadRelevantData.add(sum.waitForLoading());
// Loads 3x3 arround relevant chunks
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
for (int chunkY = 0; chunkY <= maxHeightPossible / 32; chunkY++) {
ChunkHolder chunkHolder = csWorld.aquireChunkHolder(worldUser, chunkX + i, chunkY, chunkZ + j);
if (chunkHolder != null) {
loadRelevantData.add(chunkHolder.waitForLoading());
if (registeredCS_Holders.add(chunkHolder))
chunksAquired++;
}
}
}
}
assert chunksAquired == registeredCS_Holders.size();
// Wait for everything to actually load
loadRelevantData.traverse();
// Spreads lightning, from top to botton
for (int chunkY = maxHeightPossible / 32; chunkY >= 0; chunkY--) {
CubicChunk chunk = csWorld.getChunk(chunkX, chunkY, chunkZ);
Fence fence = chunk.lightBaker.requestLightningUpdate();
// TaskLightChunk task = new TaskLightChunk(chunk, true);
// workers.scheduleTask(task);
waveFence.add(fence);
}
if (wave >= waveSize) {
waveFence.traverse();
waveFence.clear();
while (true) {
if (workers.size() > 0) {
// endless tasks
try {
Thread.sleep(50L);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else
break;
}
wave = 0;
// Show progress
done += waveSize;
if (Math.floor(((double) done / (double) todo) * 100) > completion) {
completion = Math.floor(((double) done / (double) todo) * 100);
if (completion >= 100.0 || (System.currentTimeMillis() - lastPercentageShow > 5000)) {
verbose(completion + "% ... using " + Runtime.getRuntime().freeMemory() / 1024 / 1024 + "/" + Runtime.getRuntime().maxMemory() / 1024 / 1024 + "Mb ");
lastPercentageShow = System.currentTimeMillis();
}
}
if (registeredCS_Holders.size() > targetChunksToKeepInRam) {
for (ChunkHolder holder : registeredCS_Holders) {
holder.unregisterUser(worldUser);
chunksAquired--;
}
for (Heightmap summary : registeredCS_Summaries) summary.unregisterUser(worldUser);
registeredCS_Summaries.clear();
registeredCS_Holders.clear();
csWorld.unloadUselessData().traverse();
// verbose("Done.");
}
}
}
}
waveFence.traverse();
wave = 0;
// Terminate
for (ChunkHolder holder : registeredCS_Holders) {
holder.unregisterUser(worldUser);
chunksAquired--;
}
for (Heightmap summary : registeredCS_Summaries) summary.unregisterUser(worldUser);
registeredCS_Summaries.clear();
registeredCS_Holders.clear();
csWorld.unloadUselessData().traverse();
/*csWorld.saveEverything();
for (ChunkHolder holder : registeredCS_Holders)
holder.unregisterUser(worldUser);
csWorld.unloadUselessData().traverse();*/
}
use of io.xol.chunkstories.api.world.WorldUser in project chunkstories by Hugobros3.
the class ChunkHolderImplementation method unregisterUser.
@Override
public /**
* Unregisters user and if there is no remaining user, unloads the chunk
*/
boolean unregisterUser(WorldUser user) {
try {
usersLock.lock();
Iterator<WorldUser> i = users.iterator();
while (i.hasNext()) {
WorldUser u = i.next();
;
if (u.equals(user))
i.remove();
}
if (users.isEmpty()) {
unloadChunk();
return true;
}
return false;
} finally {
usersLock.unlock();
}
}
use of io.xol.chunkstories.api.world.WorldUser in project chunkstories by Hugobros3.
the class CubicChunk method pokeInternal.
/**
* The 'core' of the core, this private function is responsible for placing and
* keeping everyone up to snuff on block modifications. It all comes back to this really.
*/
private ActualChunkVoxelContext pokeInternal(final int worldX, final int worldY, final int worldZ, Voxel newVoxel, final int sunlight, final int blocklight, final int metadata, int raw_data, final boolean use_raw_data, final boolean update, final boolean return_context, final WorldModificationCause cause) {
int x = sanitizeCoordinate(worldX);
int y = sanitizeCoordinate(worldY);
int z = sanitizeCoordinate(worldZ);
ActualChunkVoxelContext cell_pre = peek(x, y, z);
Voxel formerVoxel = cell_pre.getVoxel();
assert formerVoxel != null;
FreshFutureCell future = new FreshFutureCell(cell_pre);
if (use_raw_data) {
// We need this for voxel placement logic
newVoxel = world.getContentTranslator().getVoxelForId(VoxelFormat.id(raw_data));
// Build the future from parsing the raw data
future.setVoxel(newVoxel);
future.setSunlight(VoxelFormat.sunlight(raw_data));
future.setBlocklight(VoxelFormat.blocklight(raw_data));
future.setMetaData(VoxelFormat.meta(raw_data));
} else {
// Build the raw data from the set parameters by editing the in-place data
// (because we allow only editing some aspects of the cell data)
raw_data = cell_pre.getData();
if (newVoxel != null) {
raw_data = VoxelFormat.changeId(raw_data, world.getContentTranslator().getIdForVoxel(newVoxel));
future.setVoxel(newVoxel);
}
if (sunlight >= 0) {
raw_data = VoxelFormat.changeSunlight(raw_data, sunlight);
future.setSunlight(sunlight);
}
if (blocklight >= 0) {
raw_data = VoxelFormat.changeBlocklight(raw_data, blocklight);
future.setBlocklight(blocklight);
}
if (metadata >= 0) {
raw_data = VoxelFormat.changeMeta(raw_data, metadata);
future.setMetaData(metadata);
}
}
try {
if (newVoxel == null || formerVoxel.equals(newVoxel)) {
formerVoxel.onModification(cell_pre, future, cause);
} else {
formerVoxel.onRemove(cell_pre, cause);
newVoxel.onPlace(future, cause);
}
} catch (WorldException e) {
// Abort !
if (return_context)
return cell_pre;
else
return null;
}
// Allocate if it makes sense
if (chunkVoxelData == null)
chunkVoxelData = atomicalyCreateInternalData();
chunkVoxelData[x * 32 * 32 + y * 32 + z] = raw_data;
if (newVoxel != null && !formerVoxel.equals(newVoxel))
newVoxel.whenPlaced(future);
// Update lightning
if (update)
lightBaker.computeLightSpread(x, y, z, cell_pre.raw_data, raw_data);
// Increment the modifications counter
compr_uncomittedBlockModifications.incrementAndGet();
// Don't spam the thread creation spawn
occlusion.unbakedUpdates.incrementAndGet();
// Update related summary
if (update)
world.getRegionsSummariesHolder().updateOnBlockPlaced(x, y, z, future);
// Mark the nearby chunks to be re-rendered
if (update) {
int sx = chunkX;
int ex = sx;
int sy = chunkY;
int ey = sy;
int sz = chunkZ;
int ez = sz;
if (x == 0)
sx--;
else if (x == 31)
ex++;
if (y == 0)
sy--;
else if (y == 31)
ey++;
if (z == 0)
sz--;
else if (z == 31)
ez++;
for (int ix = sx; ix <= ex; ix++) for (int iy = sy; iy <= ey; iy++) for (int iz = sz; iz <= ez; iz++) {
Chunk chunk = world.getChunk(ix, iy, iz);
if (chunk != null && chunk instanceof ChunkRenderable)
((ChunkRenderable) chunk).meshUpdater().requestMeshUpdate();
}
}
// If this is a 'master' world, notify remote users of the change !
if (update && world instanceof WorldMaster && !(world instanceof WorldTool)) {
PacketVoxelUpdate packet = new PacketVoxelUpdate(new ActualChunkVoxelContext(chunkX * 32 + x, chunkY * 32 + y, chunkZ * 32 + z, raw_data));
Iterator<WorldUser> pi = this.chunkHolder.users.iterator();
while (pi.hasNext()) {
WorldUser user = pi.next();
if (!(user instanceof RemotePlayer))
continue;
RemotePlayer player = (RemotePlayer) user;
Entity clientEntity = player.getControlledEntity();
if (clientEntity == null)
// Ignore clients that aren't playing
continue;
player.pushPacket(packet);
}
}
if (return_context)
return new ActualChunkVoxelContext(chunkX * 32 + x, chunkY * 32 + y, chunkZ * 32 + z, raw_data);
else
return null;
}
Aggregations