Merge branch 'distant-horizons-core-refactor/world-gen-module'
This commit is contained in:
@@ -319,6 +319,10 @@ public class ClientApi
|
||||
if (clientWorld != null)
|
||||
{
|
||||
clientWorld.clientTick();
|
||||
|
||||
// Ignore local world gen, as it's managed by server ticking
|
||||
if (!(clientWorld instanceof DhClientServerWorld))
|
||||
SharedApi.worldGenTick(clientWorld::doWorldGen);
|
||||
}
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
@@ -78,12 +78,7 @@ public class ServerApi
|
||||
if (serverWorld != null)
|
||||
{
|
||||
serverWorld.serverTick();
|
||||
this.lastWorldGenTickDelta--;
|
||||
if (this.lastWorldGenTickDelta <= 0)
|
||||
{
|
||||
serverWorld.doWorldGen();
|
||||
this.lastWorldGenTickDelta = 20;
|
||||
}
|
||||
SharedApi.worldGenTick(serverWorld::doWorldGen);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.seibel.distanthorizons.core.world.*;
|
||||
public class SharedApi
|
||||
{
|
||||
private static AbstractDhWorld currentWorld;
|
||||
private static int lastWorldGenTickDelta = 0;
|
||||
|
||||
|
||||
|
||||
@@ -52,6 +53,16 @@ public class SharedApi
|
||||
}
|
||||
}
|
||||
|
||||
public static void worldGenTick(Runnable worldGenRunnable)
|
||||
{
|
||||
lastWorldGenTickDelta--;
|
||||
if (lastWorldGenTickDelta <= 0)
|
||||
{
|
||||
worldGenRunnable.run();
|
||||
lastWorldGenTickDelta = 20;
|
||||
}
|
||||
}
|
||||
|
||||
public static AbstractDhWorld getAbstractDhWorld() { return currentWorld; }
|
||||
/** returns null if the {@link SharedApi#currentWorld} isn't a {@link DhClientServerWorld} */
|
||||
public static DhClientServerWorld getDhClientServerWorld() { return (currentWorld != null && DhClientServerWorld.class.isInstance(currentWorld)) ? (DhClientServerWorld) currentWorld : null; }
|
||||
|
||||
+8
-8
@@ -5,11 +5,11 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.CompleteFull
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IIncompleteFullDataSource;
|
||||
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
||||
import com.seibel.distanthorizons.core.generation.WorldGenerationQueue;
|
||||
import com.seibel.distanthorizons.core.generation.IWorldGenerationQueue;
|
||||
import com.seibel.distanthorizons.core.generation.tasks.IWorldGenTaskTracker;
|
||||
import com.seibel.distanthorizons.core.generation.tasks.WorldGenResult;
|
||||
import com.seibel.distanthorizons.core.level.DhLevel;
|
||||
import com.seibel.distanthorizons.core.level.IDhServerLevel;
|
||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
@@ -28,14 +28,14 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
private final AtomicReference<WorldGenerationQueue> worldGenQueueRef = new AtomicReference<>(null);
|
||||
private final AtomicReference<IWorldGenerationQueue> worldGenQueueRef = new AtomicReference<>(null);
|
||||
|
||||
private final ArrayList<IOnWorldGenCompleteListener> onWorldGenTaskCompleteListeners = new ArrayList<>();
|
||||
|
||||
// Use to hold onto incomplete data sources that are waiting for generation, so that they don't get GC'd before they are generated
|
||||
private final ConcurrentHashMap<DhSectionPos, IIncompleteFullDataSource> incompleteDataSources = new ConcurrentHashMap<>();
|
||||
|
||||
public GeneratedFullDataFileHandler(IDhServerLevel level, AbstractSaveStructure saveStructure) { super(level, saveStructure); }
|
||||
public GeneratedFullDataFileHandler(IDhLevel level, AbstractSaveStructure saveStructure) { super(level, saveStructure); }
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
|
||||
//==================//
|
||||
|
||||
/** Assumes there isn't a pre-existing queue. */
|
||||
public void setGenerationQueue(WorldGenerationQueue newWorldGenQueue)
|
||||
public void setGenerationQueue(IWorldGenerationQueue newWorldGenQueue)
|
||||
{
|
||||
boolean oldQueueExists = this.worldGenQueueRef.compareAndSet(null, newWorldGenQueue);
|
||||
LodUtil.assertTrue(oldQueueExists, "previous world gen queue is still here!");
|
||||
@@ -115,13 +115,13 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
|
||||
@Nullable
|
||||
private CompletableFuture<IFullDataSource> tryStartGenTask(FullDataMetaFile file, IIncompleteFullDataSource dataSource)
|
||||
{
|
||||
WorldGenerationQueue worldGenQueue = this.worldGenQueueRef.get();
|
||||
IWorldGenerationQueue worldGenQueue = this.worldGenQueueRef.get();
|
||||
// breaks down the missing positions into the desired detail level that the gen queue could accept
|
||||
if (worldGenQueue != null && !file.genQueueChecked)
|
||||
{
|
||||
DhSectionPos pos = file.pos;
|
||||
file.genQueueChecked = true;
|
||||
byte maxSectDataDetailLevel = worldGenQueue.largestDataDetail;
|
||||
byte maxSectDataDetailLevel = worldGenQueue.largestDataDetail();
|
||||
byte targetDataDetailLevel = dataSource.getDataDetailLevel();
|
||||
|
||||
if (targetDataDetailLevel > maxSectDataDetailLevel)
|
||||
@@ -222,7 +222,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
|
||||
|
||||
if (source instanceof IIncompleteFullDataSource && !file.genQueueChecked)
|
||||
{
|
||||
WorldGenerationQueue worldGenQueue = this.worldGenQueueRef.get();
|
||||
IWorldGenerationQueue worldGenQueue = this.worldGenQueueRef.get();
|
||||
if (worldGenQueue != null)
|
||||
{
|
||||
CompletableFuture<IFullDataSource> future = this.updateFromExistingDataSources(file, (IIncompleteFullDataSource) source);
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.seibel.distanthorizons.core.generation;
|
||||
|
||||
import com.seibel.distanthorizons.core.generation.tasks.IWorldGenTaskTracker;
|
||||
import com.seibel.distanthorizons.core.generation.tasks.WorldGenResult;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface IWorldGenerationQueue extends Closeable
|
||||
{
|
||||
byte largestDataDetail();
|
||||
|
||||
CompletableFuture<WorldGenResult> submitGenTask(DhLodPos pos, byte requiredDataDetail, IWorldGenTaskTracker tracker);
|
||||
void cancelGenTasks(Iterable<DhSectionPos> positions);
|
||||
|
||||
void runCurrentGenTasksUntilBusy(DhBlockPos2D targetPos);
|
||||
|
||||
int getWaitingTaskCount();
|
||||
int getInProgressTaskCount();
|
||||
|
||||
CompletableFuture<Void> startClosing(boolean cancelCurrentGeneration, boolean alsoInterruptRunning);
|
||||
void close();
|
||||
}
|
||||
+8
-1
@@ -31,7 +31,7 @@ import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class WorldGenerationQueue implements Closeable, IDebugRenderable
|
||||
public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRenderable
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
@@ -51,6 +51,8 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable
|
||||
|
||||
/** largest numerical detail level allowed */
|
||||
public final byte largestDataDetail;
|
||||
@Override
|
||||
public byte largestDataDetail() { return this.largestDataDetail; }
|
||||
/** lowest numerical detail level allowed */
|
||||
public final byte smallestDataDetail;
|
||||
|
||||
@@ -155,6 +157,11 @@ public class WorldGenerationQueue implements Closeable, IDebugRenderable
|
||||
//}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelGenTasks(Iterable<DhSectionPos> positions)
|
||||
{
|
||||
// TODO Should anything be here?
|
||||
}
|
||||
|
||||
//===============//
|
||||
// running tasks //
|
||||
|
||||
@@ -76,26 +76,26 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS
|
||||
{
|
||||
serverside.worldGeneratorEnabledConfig.pollNewValue();
|
||||
boolean shouldDoWorldGen = serverside.worldGeneratorEnabledConfig.get() && clientside.isRendering();
|
||||
boolean isWorldGenRunning = serverside.isWorldGenRunning();
|
||||
boolean isWorldGenRunning = serverside.worldGenModule.isWorldGenRunning();
|
||||
if (shouldDoWorldGen && !isWorldGenRunning)
|
||||
{
|
||||
// start world gen
|
||||
serverside.startWorldGen();
|
||||
serverside.worldGenModule.startWorldGen(serverside.dataFileHandler, new ServerLevelModule.WorldGenState(this));
|
||||
}
|
||||
else if (!shouldDoWorldGen && isWorldGenRunning)
|
||||
{
|
||||
// stop world gen
|
||||
serverside.stopWorldGen();
|
||||
serverside.worldGenModule.stopWorldGen(serverside.dataFileHandler);
|
||||
}
|
||||
|
||||
if (serverside.isWorldGenRunning())
|
||||
|
||||
if (serverside.worldGenModule.isWorldGenRunning())
|
||||
{
|
||||
ClientLevelModule.ClientRenderState renderState = clientside.ClientRenderStateRef.get();
|
||||
if (renderState != null && renderState.quadtree != null)
|
||||
{
|
||||
serverside.dataFileHandler.removeGenRequestIf(p -> !renderState.quadtree.isSectionPosInBounds(p));
|
||||
}
|
||||
serverside.worldGenTick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos()));
|
||||
serverside.worldGenModule.worldGenTick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,21 +67,21 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel
|
||||
public void doWorldGen()
|
||||
{
|
||||
boolean shouldDoWorldGen = true; //todo;
|
||||
boolean isWorldGenRunning = serverside.isWorldGenRunning();
|
||||
boolean isWorldGenRunning = serverside.worldGenModule.isWorldGenRunning();
|
||||
if (shouldDoWorldGen && !isWorldGenRunning)
|
||||
{
|
||||
// start world gen
|
||||
serverside.startWorldGen();
|
||||
serverside.worldGenModule.startWorldGen(serverside.dataFileHandler, new ServerLevelModule.WorldGenState(this));
|
||||
}
|
||||
else if (!shouldDoWorldGen && isWorldGenRunning)
|
||||
{
|
||||
// stop world gen
|
||||
serverside.stopWorldGen();
|
||||
serverside.worldGenModule.stopWorldGen(serverside.dataFileHandler);
|
||||
}
|
||||
|
||||
if (serverside.isWorldGenRunning())
|
||||
if (serverside.worldGenModule.isWorldGenRunning())
|
||||
{
|
||||
serverside.worldGenTick(new DhBlockPos2D(0, 0)); // todo;
|
||||
serverside.worldGenModule.worldGenTick(new DhBlockPos2D(0, 0)); // todo;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,9 @@ package com.seibel.distanthorizons.core.level;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.GeneratedFullDataFileHandler;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
|
||||
public interface IDhServerLevel extends IDhLevel, GeneratedFullDataFileHandler.IOnWorldGenCompleteListener
|
||||
public interface IDhServerLevel extends IDhWorldGenLevel
|
||||
{
|
||||
void serverTick();
|
||||
void doWorldGen();
|
||||
|
||||
IServerLevelWrapper getServerLevelWrapper();
|
||||
void serverTick();
|
||||
|
||||
IServerLevelWrapper getServerLevelWrapper();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.seibel.distanthorizons.core.level;
|
||||
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.GeneratedFullDataFileHandler;
|
||||
|
||||
public interface IDhWorldGenLevel extends IDhLevel, GeneratedFullDataFileHandler.IOnWorldGenCompleteListener
|
||||
{
|
||||
void doWorldGen();
|
||||
|
||||
}
|
||||
@@ -8,15 +8,10 @@ import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
||||
import com.seibel.distanthorizons.core.generation.BatchGenerator;
|
||||
import com.seibel.distanthorizons.core.generation.WorldGenerationQueue;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.WorldGeneratorInjector;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class ServerLevelModule
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
@@ -27,8 +22,7 @@ public class ServerLevelModule
|
||||
public final GeneratedFullDataFileHandler dataFileHandler;
|
||||
public final AppliedConfigState<Boolean> worldGeneratorEnabledConfig;
|
||||
|
||||
private final AtomicReference<WorldGenState> worldGenStateRef = new AtomicReference<>();
|
||||
private final F3Screen.DynamicMessage worldGenF3Message;
|
||||
public final WorldGenModule worldGenModule;
|
||||
|
||||
|
||||
|
||||
@@ -39,109 +33,17 @@ public class ServerLevelModule
|
||||
this.saveStructure = saveStructure;
|
||||
this.dataFileHandler = new GeneratedFullDataFileHandler(parent, saveStructure);
|
||||
this.worldGeneratorEnabledConfig = new AppliedConfigState<>(Config.Client.Advanced.WorldGenerator.enableDistantGeneration);
|
||||
|
||||
this.worldGenF3Message = new F3Screen.DynamicMessage(() ->
|
||||
{
|
||||
WorldGenState worldGenState = this.worldGenStateRef.get();
|
||||
if (worldGenState != null)
|
||||
{
|
||||
int waiting = worldGenState.worldGenerationQueue.getWaitingTaskCount();
|
||||
int inProgress = worldGenState.worldGenerationQueue.getInProgressTaskCount();
|
||||
|
||||
return "World Gen Tasks: "+waiting+", (in progress: "+inProgress+")";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "World Gen Disabled";
|
||||
}
|
||||
});
|
||||
this.worldGenModule = new WorldGenModule(this.dataFileHandler, this.parent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// tick methods //
|
||||
//==============//
|
||||
|
||||
public void startWorldGen()
|
||||
{
|
||||
// create the new world generator
|
||||
WorldGenState newWgs = new WorldGenState(parent);
|
||||
if (!this.worldGenStateRef.compareAndSet(null, newWgs))
|
||||
{
|
||||
LOGGER.warn("Failed to start world gen due to concurrency");
|
||||
newWgs.closeAsync(false);
|
||||
}
|
||||
dataFileHandler.addWorldGenCompleteListener(parent);
|
||||
dataFileHandler.setGenerationQueue(newWgs.worldGenerationQueue);
|
||||
}
|
||||
|
||||
public void stopWorldGen()
|
||||
{
|
||||
WorldGenState worldGenState = this.worldGenStateRef.get();
|
||||
if (worldGenState == null)
|
||||
{
|
||||
LOGGER.warn("Attempted to stop world gen when it was not running");
|
||||
return;
|
||||
}
|
||||
|
||||
// shut down the world generator
|
||||
while (!this.worldGenStateRef.compareAndSet(worldGenState, null))
|
||||
{
|
||||
worldGenState = this.worldGenStateRef.get();
|
||||
if (worldGenState == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
dataFileHandler.clearGenerationQueue();
|
||||
worldGenState.closeAsync(true).join(); //TODO: Make it async.
|
||||
dataFileHandler.removeWorldGenCompleteListener(parent);
|
||||
}
|
||||
|
||||
public boolean isWorldGenRunning()
|
||||
{
|
||||
return this.worldGenStateRef.get() != null;
|
||||
}
|
||||
|
||||
public void worldGenTick(DhBlockPos2D targetPosForGeneration)
|
||||
{
|
||||
WorldGenState worldGenState = this.worldGenStateRef.get();
|
||||
if (worldGenState != null)
|
||||
{
|
||||
// queue new world generation requests
|
||||
worldGenState.tick(targetPosForGeneration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// data handling //
|
||||
//===============//
|
||||
public void close()
|
||||
{
|
||||
// shutdown the world-gen
|
||||
WorldGenState worldGenState = this.worldGenStateRef.get();
|
||||
if (worldGenState != null)
|
||||
{
|
||||
while (!this.worldGenStateRef.compareAndSet(worldGenState, null))
|
||||
{
|
||||
worldGenState = this.worldGenStateRef.get();
|
||||
if (worldGenState == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (worldGenState != null)
|
||||
{
|
||||
worldGenState.closeAsync(true).join(); //TODO: Make it async.
|
||||
}
|
||||
}
|
||||
|
||||
this.dataFileHandler.close();
|
||||
this.worldGenF3Message.close();
|
||||
this.worldGenModule.close();
|
||||
dataFileHandler.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -150,9 +52,8 @@ public class ServerLevelModule
|
||||
// helper classes //
|
||||
//================//
|
||||
|
||||
private static class WorldGenState
|
||||
public static class WorldGenState extends WorldGenModule.WorldGenState
|
||||
{
|
||||
public final WorldGenerationQueue worldGenerationQueue;
|
||||
WorldGenState(IDhServerLevel level)
|
||||
{
|
||||
IDhApiWorldGenerator worldGenerator = WorldGeneratorInjector.INSTANCE.get(level.getLevelWrapper());
|
||||
@@ -167,27 +68,6 @@ public class ServerLevelModule
|
||||
this.worldGenerationQueue = new WorldGenerationQueue(worldGenerator);
|
||||
}
|
||||
|
||||
CompletableFuture<Void> closeAsync(boolean doInterrupt)
|
||||
{
|
||||
return this.worldGenerationQueue.startClosing(true, doInterrupt)
|
||||
.exceptionally(ex ->
|
||||
{
|
||||
LOGGER.error("Error closing generation queue", ex);
|
||||
return null;
|
||||
}
|
||||
).thenRun(this.worldGenerationQueue::close)
|
||||
.exceptionally(ex ->
|
||||
{
|
||||
LOGGER.error("Error closing world gen", ex);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public void tick(DhBlockPos2D targetPosForGeneration)
|
||||
{
|
||||
worldGenerationQueue.runCurrentGenTasksUntilBusy(targetPosForGeneration);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.seibel.distanthorizons.core.level;
|
||||
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.GeneratedFullDataFileHandler;
|
||||
import com.seibel.distanthorizons.core.generation.IWorldGenerationQueue;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class WorldGenModule implements Closeable
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
private final GeneratedFullDataFileHandler dataFileHandler;
|
||||
private final GeneratedFullDataFileHandler.IOnWorldGenCompleteListener onWorldGenCompleteListener;
|
||||
|
||||
private final AtomicReference<WorldGenState> worldGenStateRef = new AtomicReference<>();
|
||||
private final F3Screen.DynamicMessage worldGenF3Message;
|
||||
|
||||
public static abstract class WorldGenState
|
||||
{
|
||||
public IWorldGenerationQueue worldGenerationQueue;
|
||||
|
||||
CompletableFuture<Void> closeAsync(boolean doInterrupt)
|
||||
{
|
||||
return this.worldGenerationQueue.startClosing(true, doInterrupt)
|
||||
.exceptionally(ex ->
|
||||
{
|
||||
LOGGER.error("Error closing generation queue", ex);
|
||||
return null;
|
||||
}
|
||||
).thenRun(this.worldGenerationQueue::close)
|
||||
.exceptionally(ex ->
|
||||
{
|
||||
LOGGER.error("Error closing world gen", ex);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public void tick(DhBlockPos2D targetPosForGeneration)
|
||||
{
|
||||
worldGenerationQueue.runCurrentGenTasksUntilBusy(targetPosForGeneration);
|
||||
}
|
||||
}
|
||||
|
||||
public WorldGenModule(GeneratedFullDataFileHandler dataFileHandler, GeneratedFullDataFileHandler.IOnWorldGenCompleteListener onWorldGenCompleteListener)
|
||||
{
|
||||
this.dataFileHandler = dataFileHandler;
|
||||
this.onWorldGenCompleteListener = onWorldGenCompleteListener;
|
||||
this.worldGenF3Message = new F3Screen.DynamicMessage(() ->
|
||||
{
|
||||
WorldGenState worldGenState = this.worldGenStateRef.get();
|
||||
if (worldGenState != null)
|
||||
{
|
||||
int waiting = worldGenState.worldGenerationQueue.getWaitingTaskCount();
|
||||
int inProgress = worldGenState.worldGenerationQueue.getInProgressTaskCount();
|
||||
|
||||
return "World Gen Tasks: "+waiting+", (in progress: "+inProgress+")";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "World Gen Disabled";
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void startWorldGen(GeneratedFullDataFileHandler dataFileHandler, WorldGenState newWgs)
|
||||
{
|
||||
// create the new world generator
|
||||
if (!this.worldGenStateRef.compareAndSet(null, newWgs))
|
||||
{
|
||||
LOGGER.warn("Failed to start world gen due to concurrency");
|
||||
newWgs.closeAsync(false);
|
||||
}
|
||||
dataFileHandler.addWorldGenCompleteListener(onWorldGenCompleteListener);
|
||||
dataFileHandler.setGenerationQueue(newWgs.worldGenerationQueue);
|
||||
}
|
||||
|
||||
public void stopWorldGen(GeneratedFullDataFileHandler dataFileHandler)
|
||||
{
|
||||
WorldGenState worldGenState = this.worldGenStateRef.get();
|
||||
if (worldGenState == null)
|
||||
{
|
||||
LOGGER.warn("Attempted to stop world gen when it was not running");
|
||||
return;
|
||||
}
|
||||
|
||||
// shut down the world generator
|
||||
while (!this.worldGenStateRef.compareAndSet(worldGenState, null))
|
||||
{
|
||||
worldGenState = this.worldGenStateRef.get();
|
||||
if (worldGenState == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
dataFileHandler.clearGenerationQueue();
|
||||
worldGenState.closeAsync(true).join(); //TODO: Make it async.
|
||||
dataFileHandler.removeWorldGenCompleteListener(onWorldGenCompleteListener);
|
||||
}
|
||||
|
||||
public boolean isWorldGenRunning()
|
||||
{
|
||||
return this.worldGenStateRef.get() != null;
|
||||
}
|
||||
|
||||
public void worldGenTick(DhBlockPos2D targetPosForGeneration)
|
||||
{
|
||||
WorldGenState worldGenState = this.worldGenStateRef.get();
|
||||
if (worldGenState != null)
|
||||
{
|
||||
// queue new world generation requests
|
||||
worldGenState.tick(targetPosForGeneration);
|
||||
}
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
// shutdown the world-gen
|
||||
WorldGenState worldGenState = this.worldGenStateRef.get();
|
||||
if (worldGenState != null)
|
||||
{
|
||||
while (!this.worldGenStateRef.compareAndSet(worldGenState, null))
|
||||
{
|
||||
worldGenState = this.worldGenStateRef.get();
|
||||
if (worldGenState == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (worldGenState != null)
|
||||
{
|
||||
worldGenState.closeAsync(true).join(); //TODO: Make it async.
|
||||
}
|
||||
}
|
||||
dataFileHandler.close();
|
||||
this.worldGenF3Message.close();
|
||||
}
|
||||
}
|
||||
@@ -149,8 +149,12 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld
|
||||
|
||||
public void clientTick() { this.eventLoop.tick(); }
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> saveAndFlush()
|
||||
public void doWorldGen() {
|
||||
// Not implemented
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> saveAndFlush()
|
||||
{
|
||||
return CompletableFuture.allOf(this.levels.values().stream().map(DhClientLevel::saveAsync).toArray(CompletableFuture[]::new));
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ public interface IDhClientWorld extends IDhWorld
|
||||
{
|
||||
void clientTick();
|
||||
|
||||
void doWorldGen();
|
||||
|
||||
default IDhClientLevel getOrLoadClientLevel(ILevelWrapper levelWrapper) { return (IDhClientLevel) this.getOrLoadLevel(levelWrapper); }
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user