From cdc6635a7634a2e57d25817bd5290b9f44b01f70 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Fri, 25 Aug 2023 21:05:47 -0500 Subject: [PATCH] Refactor --- .../core/api/internal/ClientApi.java | 2 + .../generation/IWorldGenerationQueue.java | 3 + .../core/generation/WorldGenerationQueue.java | 2 +- .../core/level/DhClientServerLevel.java | 4 +- .../core/level/DhServerLevel.java | 2 +- .../core/level/ServerLevelModule.java | 21 +- .../core/level/WorldGenModule.java | 222 ++++++++++-------- 7 files changed, 139 insertions(+), 117 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java index 6934834b1..cfcaf8881 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java @@ -322,7 +322,9 @@ public class ClientApi // Ignore local world gen, as it's managed by server ticking if (!(clientWorld instanceof DhClientServerWorld)) + { SharedApi.worldGenTick(clientWorld::doWorldGen); + } } profiler.pop(); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/IWorldGenerationQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/IWorldGenerationQueue.java index e1aa2e376..7181ae80e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/IWorldGenerationQueue.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/IWorldGenerationQueue.java @@ -11,11 +11,13 @@ import java.util.concurrent.CompletableFuture; public interface IWorldGenerationQueue extends Closeable { + /** the largest numerical detail level */ byte largestDataDetail(); CompletableFuture submitGenTask(DhLodPos pos, byte requiredDataDetail, IWorldGenTaskTracker tracker); void cancelGenTasks(Iterable positions); + /** @param targetPos the position that world generation should be centered around, generally this will be the player's position. */ void runCurrentGenTasksUntilBusy(DhBlockPos2D targetPos); int getWaitingTaskCount(); @@ -23,4 +25,5 @@ public interface IWorldGenerationQueue extends Closeable CompletableFuture startClosing(boolean cancelCurrentGeneration, boolean alsoInterruptRunning); void close(); + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java index 0a3c8477f..51e34783f 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java @@ -160,7 +160,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender @Override public void cancelGenTasks(Iterable positions) { - // TODO Should anything be here? + // TODO Should we cancel generation of chunks that were loaded by the player? } //===============// diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index acc6ce14a..8417a7f74 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -42,7 +42,7 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS LOGGER.warn("unable to create data folder."); } this.serverLevelWrapper = serverLevelWrapper; - this.serverside = new ServerLevelModule(this, serverLevelWrapper, saveStructure); + this.serverside = new ServerLevelModule(this, saveStructure); this.clientside = new ClientLevelModule(this); LOGGER.info("Started " + DhClientServerLevel.class.getSimpleName() + " for " + serverLevelWrapper + " with saves at " + saveStructure); } @@ -129,7 +129,7 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS } @Override - public IClientLevelWrapper getClientLevelWrapper() { return serverside.levelWrapper.tryGetClientLevelWrapper(); } + public IClientLevelWrapper getClientLevelWrapper() { return this.serverLevelWrapper.tryGetClientLevelWrapper(); } @Override public void clearRenderCache() diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java index 907dac539..36a950644 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java @@ -27,7 +27,7 @@ public class DhServerLevel extends DhLevel implements IDhServerLevel LOGGER.warn("unable to create data folder."); } this.serverLevelWrapper = serverLevelWrapper; - serverside = new ServerLevelModule(this, serverLevelWrapper, saveStructure); + this.serverside = new ServerLevelModule(this, saveStructure); LOGGER.info("Started DHLevel for {} with saves at {}", serverLevelWrapper, saveStructure); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/ServerLevelModule.java b/core/src/main/java/com/seibel/distanthorizons/core/level/ServerLevelModule.java index adc85dcca..f3537f03c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/ServerLevelModule.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/ServerLevelModule.java @@ -16,8 +16,7 @@ public class ServerLevelModule { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public final IServerLevelWrapper levelWrapper; - public final IDhServerLevel parent; + public final IDhServerLevel parentServerLevel; public final AbstractSaveStructure saveStructure; public final GeneratedFullDataFileHandler dataFileHandler; public final AppliedConfigState worldGeneratorEnabledConfig; @@ -26,24 +25,22 @@ public class ServerLevelModule - public ServerLevelModule(IDhServerLevel parent, IServerLevelWrapper levelWrapper, AbstractSaveStructure saveStructure) + public ServerLevelModule(IDhServerLevel parentServerLevel, AbstractSaveStructure saveStructure) { - this.parent = parent; - this.levelWrapper = levelWrapper; + this.parentServerLevel = parentServerLevel; this.saveStructure = saveStructure; - this.dataFileHandler = new GeneratedFullDataFileHandler(parent, saveStructure); + this.dataFileHandler = new GeneratedFullDataFileHandler(parentServerLevel, saveStructure); this.worldGeneratorEnabledConfig = new AppliedConfigState<>(Config.Client.Advanced.WorldGenerator.enableDistantGeneration); - this.worldGenModule = new WorldGenModule(this.dataFileHandler, this.parent); + this.worldGenModule = new WorldGenModule(this.dataFileHandler, this.parentServerLevel); } - //===============// - // data handling // - //===============// + + public void close() { // shutdown the world-gen this.worldGenModule.close(); - dataFileHandler.close(); + this.dataFileHandler.close(); } @@ -52,7 +49,7 @@ public class ServerLevelModule // helper classes // //================// - public static class WorldGenState extends WorldGenModule.WorldGenState + public static class WorldGenState extends WorldGenModule.AbstractWorldGenState { WorldGenState(IDhServerLevel level) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/WorldGenModule.java b/core/src/main/java/com/seibel/distanthorizons/core/level/WorldGenModule.java index 97b0c9232..1f3b26c1b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/WorldGenModule.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/WorldGenModule.java @@ -18,10 +18,127 @@ public class WorldGenModule implements Closeable private final GeneratedFullDataFileHandler dataFileHandler; private final GeneratedFullDataFileHandler.IOnWorldGenCompleteListener onWorldGenCompleteListener; - private final AtomicReference worldGenStateRef = new AtomicReference<>(); + private final AtomicReference worldGenStateRef = new AtomicReference<>(); private final F3Screen.DynamicMessage worldGenF3Message; - public static abstract class WorldGenState + + + public WorldGenModule(GeneratedFullDataFileHandler dataFileHandler, GeneratedFullDataFileHandler.IOnWorldGenCompleteListener onWorldGenCompleteListener) + { + this.dataFileHandler = dataFileHandler; + this.onWorldGenCompleteListener = onWorldGenCompleteListener; + this.worldGenF3Message = new F3Screen.DynamicMessage(() -> + { + AbstractWorldGenState worldGenState = this.worldGenStateRef.get(); + if (worldGenState != null) + { + int waitingCount = worldGenState.worldGenerationQueue.getWaitingTaskCount(); + int inProgressCount = worldGenState.worldGenerationQueue.getInProgressTaskCount(); + + return "World Gen Tasks: "+waitingCount+", (in progress: "+inProgressCount+")"; + } + else + { + return "World Gen Disabled"; + } + }); + + } + + + + //===================// + // world gen control // + //===================// + + public void startWorldGen(GeneratedFullDataFileHandler dataFileHandler, AbstractWorldGenState 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(this.onWorldGenCompleteListener); + dataFileHandler.setGenerationQueue(newWgs.worldGenerationQueue); + } + + public void stopWorldGen(GeneratedFullDataFileHandler dataFileHandler) + { + AbstractWorldGenState 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(this.onWorldGenCompleteListener); + } + + /** @param targetPosForGeneration the position that world generation should be centered around */ + public void worldGenTick(DhBlockPos2D targetPosForGeneration) + { + AbstractWorldGenState worldGenState = this.worldGenStateRef.get(); + if (worldGenState != null) + { + // queue new world generation requests + worldGenState.tick(targetPosForGeneration); + } + } + + @Override + public void close() + { + // shutdown the world-gen + AbstractWorldGenState 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(); + } + + + + //=========// + // getters // + //=========// + + public boolean isWorldGenRunning() { return this.worldGenStateRef.get() != null; } + + + + //================// + // helper classes // + //================// + + /** Handles the {@link IWorldGenerationQueue} and any other necessary world gen information. */ + public static abstract class AbstractWorldGenState { public IWorldGenerationQueue worldGenerationQueue; @@ -41,105 +158,8 @@ public class WorldGenModule implements Closeable }); } - public void tick(DhBlockPos2D targetPosForGeneration) - { - worldGenerationQueue.runCurrentGenTasksUntilBusy(targetPosForGeneration); - } + /** @param targetPosForGeneration the position that world generation should be centered around */ + public void tick(DhBlockPos2D targetPosForGeneration) { this.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(); - } }