Skip to content

Commit

Permalink
support the cubic chunks async terrain gen api and periodically unloa…
Browse files Browse the repository at this point in the history
…d generated cubes
  • Loading branch information
DaMatrix committed Dec 29, 2021
1 parent 8e72de7 commit a2ed600
Showing 1 changed file with 33 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import io.github.opencubicchunks.cubicchunks.api.world.ICubeProviderServer;
import io.github.opencubicchunks.cubicchunks.api.world.ICubicWorldServer;
import io.github.opencubicchunks.cubicchunks.api.world.storage.ICubicStorage;
import io.github.opencubicchunks.cubicchunks.api.worldgen.ICubeGenerator;
import io.github.opencubicchunks.cubicchunks.core.asm.mixin.ICubicWorldInternal;
import io.github.opencubicchunks.cubicchunks.core.server.chunkio.AsyncBatchingCubeIO;
import io.github.opencubicchunks.cubicchunks.core.server.chunkio.ICubeIO;
Expand All @@ -38,6 +39,7 @@
import net.daporkchop.fp2.compat.cc.cube.CubeWithoutWorld;
import net.daporkchop.fp2.compat.vanilla.IBiomeAccess;
import net.daporkchop.fp2.compat.vanilla.IBlockHeightAccess;
import net.daporkchop.fp2.mode.api.ctx.IFarWorldServer;
import net.daporkchop.fp2.server.worldlistener.IWorldChangeListener;
import net.daporkchop.fp2.server.worldlistener.WorldChangeListenerManager;
import net.daporkchop.fp2.util.datastructure.Datastructures;
Expand All @@ -61,11 +63,13 @@
import net.minecraft.world.WorldType;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Stream;

Expand All @@ -82,6 +86,7 @@ public class CCAsyncBlockAccessImpl implements IAsyncBlockAccess, IWorldChangeLi
protected final WorldServer world;
protected final ICubeIO io;
protected final ICubicStorage storage;
protected final ICubeGenerator generator;

protected final ColumnCache columns = new ColumnCache();
protected final CubeCache cubes = new CubeCache();
Expand All @@ -91,10 +96,13 @@ public class CCAsyncBlockAccessImpl implements IAsyncBlockAccess, IWorldChangeLi
protected final NDimensionalIntSegtreeSet columnsExistCache;
protected final NDimensionalIntSegtreeSet cubesExistCache;

protected final AtomicInteger generatedCount = new AtomicInteger();

public CCAsyncBlockAccessImpl(@NonNull WorldServer world) {
this.world = world;
this.io = ((ICubeProviderInternal.Server) ((ICubicWorldInternal) world).getCubeCache()).getCubeIO();
this.storage = PUnsafe.getObject(AsyncBatchingCubeIO.class.cast(this.io), ASYNCBATCHINGCUBEIO_STORAGE_OFFSET);
this.generator = ((ICubicWorldServer) world).getCubeGenerator();

this.emptyStorage = new ExtendedBlockStorage(0, world.provider.hasSkyLight());

Expand Down Expand Up @@ -175,6 +183,18 @@ public void onCubeSaved(@NonNull World world, int cubeX, int cubeY, int cubeZ, @
this.cubes.notifyUpdate(new CubePos(cubeX, cubeY, cubeZ), nbt);
}

@Override
public void onTickEnd() {
//if 8192 things have been generated, run a full chunk gc!
// if we don't do this, the gc will only be triggered when a player has been moving for more than some number of ticks. the player might just be standing still
// while waiting for terrain to load in, so we need to do this to prevent a memory leak.
if (this.generatedCount.get() >= 8192) {
this.generatedCount.lazySet(0);

((ICubicWorldServer) this.world).unloadOldCubes();
}
}

@Override
public boolean anyColumnIntersects(int tileX, int tileZ, int level) {
return this.columnsExistCache.containsAny(level, tileX, tileZ);
Expand Down Expand Up @@ -262,12 +282,18 @@ protected IColumn loadFromDisk(@NonNull ChunkPos key, @NonNull Object param) {

@Override
protected void triggerGeneration(@NonNull ChunkPos key, @NonNull Object param) {
//spin until the generator reports that it's ready
while (CCAsyncBlockAccessImpl.this.generator.pollAsyncColumnGenerator(key.x, key.z) != ICubeGenerator.GeneratorReadyState.READY) {
PorkUtil.sleep(1L);
}

//load and immediately save column on server thread
ThreadingHelper.scheduleTaskInWorldThread(CCAsyncBlockAccessImpl.this.world, () -> {
Chunk column = ((ICubicWorldServer) CCAsyncBlockAccessImpl.this.world)
.getCubeCache().getColumn(key.x, key.z, ICubeProviderServer.Requirement.POPULATE);
if (column != null && !column.isEmpty()) {
CCAsyncBlockAccessImpl.this.io.saveColumn(column);
CCAsyncBlockAccessImpl.this.generatedCount.incrementAndGet();
}
}).join();
}
Expand Down Expand Up @@ -302,12 +328,19 @@ protected ICube loadFromDisk(@NonNull CubePos key, @NonNull Chunk param) {

@Override
protected void triggerGeneration(@NonNull CubePos key, @NonNull Chunk param) {
//spin until the generator reports that it's ready
while (CCAsyncBlockAccessImpl.this.generator.pollAsyncCubeGenerator(key.getX(), key.getY(), key.getZ()) != ICubeGenerator.GeneratorReadyState.READY
|| CCAsyncBlockAccessImpl.this.generator.pollAsyncCubePopulator(key.getX(), key.getY(), key.getZ()) != ICubeGenerator.GeneratorReadyState.READY) {
PorkUtil.sleep(1L);
}

ThreadingHelper.scheduleTaskInWorldThread(CCAsyncBlockAccessImpl.this.world, () -> {
//TODO: save column as well if needed
ICube cube = ((ICubicWorldServer) CCAsyncBlockAccessImpl.this.world)
.getCubeCache().getCube(key.getX(), key.getY(), key.getZ(), ICubeProviderServer.Requirement.LIGHT);
if (cube != null && cube.isInitialLightingDone()) {
CCAsyncBlockAccessImpl.this.io.saveCube((Cube) cube);
CCAsyncBlockAccessImpl.this.generatedCount.incrementAndGet();
}
}).join();
}
Expand Down

0 comments on commit a2ed600

Please sign in to comment.