From 973be40324bdc6699ecada4fb3451eee93007b10 Mon Sep 17 00:00:00 2001 From: TomTheFurry Date: Mon, 25 Jul 2022 13:38:33 +0800 Subject: [PATCH] Fix and port batch generator to new Generator API. Now if we just fix up forge, and there's no bugs (impossible), then there's enough implemented to finally have something shown! Yay! --- .../lod/core/a7/level/DhClientLevel.java | 2 +- .../core/a7/level/DhClientServerLevel.java | 19 +- .../lod/core/a7/level/DhServerLevel.java | 8 +- .../a7/save/io/render/RenderFileHandler.java | 6 +- .../worldGeneration/BatchGenerator.java | 391 +++++++++--------- .../DhApiEventInjector.java | 4 +- .../com/seibel/lod/core/util/EventTimer.java | 70 ++++ .../com/seibel/lod/core/util/LodUtil.java | 6 + ...tractBatchGenerationEnvionmentWrapper.java | 4 - 9 files changed, 299 insertions(+), 211 deletions(-) create mode 100644 src/main/java/com/seibel/lod/core/util/EventTimer.java diff --git a/src/main/java/com/seibel/lod/core/a7/level/DhClientLevel.java b/src/main/java/com/seibel/lod/core/a7/level/DhClientLevel.java index ad44ea503..0b702dca3 100644 --- a/src/main/java/com/seibel/lod/core/a7/level/DhClientLevel.java +++ b/src/main/java/com/seibel/lod/core/a7/level/DhClientLevel.java @@ -37,7 +37,7 @@ public class DhClientLevel implements IClientLevel { save.getDataFolder(level).mkdirs(); save.getRenderCacheFolder(level).mkdirs(); dataFileHandler = new RemoteDataFileHandler(); - renderFileHandler = new RenderFileHandler(dataFileHandler, this, save.getRenderCacheFolder(level)); + renderFileHandler = new RenderFileHandler(dataFileHandler, this, save.getRenderCacheFolder(level), null); tree = new LodQuadTree(this, Config.Client.Graphics.Quality.lodChunkRenderDistance.get()*16, MC_CLIENT.getPlayerBlockPos().x, MC_CLIENT.getPlayerBlockPos().z, renderFileHandler); renderBufferHandler = new RenderBufferHandler(tree); diff --git a/src/main/java/com/seibel/lod/core/a7/level/DhClientServerLevel.java b/src/main/java/com/seibel/lod/core/a7/level/DhClientServerLevel.java index 77e0740eb..94038d643 100644 --- a/src/main/java/com/seibel/lod/core/a7/level/DhClientServerLevel.java +++ b/src/main/java/com/seibel/lod/core/a7/level/DhClientServerLevel.java @@ -1,6 +1,7 @@ package com.seibel.lod.core.a7.level; import com.seibel.lod.core.a7.generation.GenerationQueue; +import com.seibel.lod.core.a7.generation.IGenerator; import com.seibel.lod.core.a7.render.LodQuadTree; import com.seibel.lod.core.a7.util.FileScanner; import com.seibel.lod.core.a7.save.io.file.LocalDataFileHandler; @@ -8,6 +9,7 @@ import com.seibel.lod.core.a7.save.io.render.RenderFileHandler; import com.seibel.lod.core.a7.pos.DhBlockPos2D; import com.seibel.lod.core.a7.render.RenderBufferHandler; import com.seibel.lod.core.a7.save.structure.LocalSaveStructure; +import com.seibel.lod.core.builders.worldGeneration.BatchGenerator; import com.seibel.lod.core.config.Config; import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector; import com.seibel.lod.core.logging.DhLoggerBuilder; @@ -33,6 +35,7 @@ public class DhClientServerLevel implements IClientLevel, IServerLevel { public final ILevelWrapper level; public a7LodRenderer renderer = null; public LodQuadTree tree = null; + public IGenerator worldGenerator = null; public DhClientServerLevel(LocalSaveStructure save, ILevelWrapper level) { this.level = level; @@ -57,7 +60,7 @@ public class DhClientServerLevel implements IClientLevel, IServerLevel { return; } - generationQueue = new GenerationQueue((a,b) -> renderFileHandler.write(a,b)); // FIXME: Ops. A need B and B need A... Does this work? + generationQueue = new GenerationQueue((a,b) -> this.renderFileHandler.write(a,b)); renderFileHandler = new RenderFileHandler(dataFileHandler, this, save.getRenderCacheFolder(level), generationQueue); tree = new LodQuadTree(this, Config.Client.Graphics.Quality.lodChunkRenderDistance.get()*16, MC_CLIENT.getPlayerBlockPos().x, MC_CLIENT.getPlayerBlockPos().z, renderFileHandler); @@ -117,15 +120,27 @@ public class DhClientServerLevel implements IClientLevel, IServerLevel { //Note: saving renderFileHandler will also save the dataFileHandler. } + private BatchGenerator batchGenerator = null; @Override public void close() { + if (batchGenerator != null) batchGenerator.close(); + if (renderer != null) renderer.close(); + if (renderBufferHandler != null) renderBufferHandler.close(); + if (renderFileHandler != null) renderFileHandler.close(); dataFileHandler.close(); LOGGER.info("Closed DHLevel for {}", level); } + @Override public void doWorldGen() { - //TODO + if (worldGenerator == null) { + // TODO: Make a registry for generators for modding support. + batchGenerator = new BatchGenerator(this); + worldGenerator = batchGenerator; + } else { + batchGenerator.update(); + } } @Override diff --git a/src/main/java/com/seibel/lod/core/a7/level/DhServerLevel.java b/src/main/java/com/seibel/lod/core/a7/level/DhServerLevel.java index 8b6c2e4b1..74ba6618f 100644 --- a/src/main/java/com/seibel/lod/core/a7/level/DhServerLevel.java +++ b/src/main/java/com/seibel/lod/core/a7/level/DhServerLevel.java @@ -54,13 +54,7 @@ public class DhServerLevel implements IServerLevel { @Override public void doWorldGen() { - - } - - @Override - public void submitChunkData(DHChunkPos chunkPos, ChunkSizedData data) { - DhSectionPos sectionPos = new DhSectionPos((byte)4, chunkPos.x, chunkPos.z); - dataFileHandler.write(sectionPos, data); + // FIXME: No world gen for server side only for now } @Override diff --git a/src/main/java/com/seibel/lod/core/a7/save/io/render/RenderFileHandler.java b/src/main/java/com/seibel/lod/core/a7/save/io/render/RenderFileHandler.java index 53470e34e..b00e729e6 100644 --- a/src/main/java/com/seibel/lod/core/a7/save/io/render/RenderFileHandler.java +++ b/src/main/java/com/seibel/lod/core/a7/save/io/render/RenderFileHandler.java @@ -12,6 +12,7 @@ import com.seibel.lod.core.logging.DhLoggerBuilder; import com.seibel.lod.core.util.LodUtil; import org.apache.logging.log4j.Logger; +import javax.annotation.Nullable; import java.io.File; import java.io.IOException; import java.util.*; @@ -26,9 +27,10 @@ public class RenderFileHandler implements IRenderSourceProvider { final IClientLevel level; final File saveDir; final IDataSourceProvider dataSourceProvider; + @Nullable final PlaceHolderQueue placeHolderQueue; - public RenderFileHandler(IDataSourceProvider sourceProvider, IClientLevel level, File saveRootDir, PlaceHolderQueue placeHolderQueue) { + public RenderFileHandler(IDataSourceProvider sourceProvider, IClientLevel level, File saveRootDir, @Nullable PlaceHolderQueue placeHolderQueue) { this.dataSourceProvider = sourceProvider; this.level = level; this.saveDir = saveRootDir; @@ -114,7 +116,7 @@ public class RenderFileHandler implements IRenderSourceProvider { } if (render != null) return render; PlaceHolderRenderSource placeHolder = new PlaceHolderRenderSource(pos); - placeHolderQueue.track(placeHolder); + if (placeHolderQueue != null) placeHolderQueue.track(placeHolder); return placeHolder; } ); diff --git a/src/main/java/com/seibel/lod/core/builders/worldGeneration/BatchGenerator.java b/src/main/java/com/seibel/lod/core/builders/worldGeneration/BatchGenerator.java index 3bc3b7bb6..157ea30ef 100644 --- a/src/main/java/com/seibel/lod/core/builders/worldGeneration/BatchGenerator.java +++ b/src/main/java/com/seibel/lod/core/builders/worldGeneration/BatchGenerator.java @@ -53,8 +53,8 @@ public class BatchGenerator implements IChunkGenerator public static int previousThreadCount = Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get()<1 ? 1 : (int) Math.ceil(Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get()); private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName()); - private int estimatedSampleNeeded = 128; - private int estimatedPointsToQueue = 1; +// private int estimatedSampleNeeded = 128; +// private int estimatedPointsToQueue = 1; public BatchGenerator(ILevel targetLodLevel) { this.targetLodLevel = targetLodLevel; @@ -62,197 +62,197 @@ public class BatchGenerator implements IChunkGenerator LOGGER.info("Batch Chunk Generator initialized"); } - @SuppressWarnings("unused") - public void queueGenerationRequests() { - EDistanceGenerationMode mode = Config.Client.WorldGenerator.distanceGenerationMode.get(); - int newThreadCount = Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get()<1 ? 1 : (int) Math.ceil(Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get()); - if (newThreadCount != previousThreadCount) { - generationGroup.resizeThreadPool(newThreadCount); - previousThreadCount = newThreadCount; - } - if (estimatedPointsToQueue < newThreadCount) - estimatedPointsToQueue = newThreadCount; - - EGenerationPriority priority = Config.Client.WorldGenerator.generationPriority.get(); - if (priority == EGenerationPriority.AUTO) - priority = MC.hasSinglePlayerServer() ? EGenerationPriority.FAR_FIRST : EGenerationPriority.NEAR_FIRST; - - generationGroup.updateAllFutures(); - if (!MC.hasSinglePlayerServer()) - return; - if (!LodUtil.checkRamUsage(0.1, 64)) return; - - int eventsCount = generationGroup.getEventCount(); - // If we still all jobs running, return. - if (eventsCount >= estimatedPointsToQueue) { - estimatedPointsToQueue--; - if (estimatedPointsToQueue < newThreadCount) - estimatedPointsToQueue = newThreadCount; - return; - } - - final int targetToGenerate = estimatedPointsToQueue - eventsCount; - int toGenerate = targetToGenerate; - int positionGoneThough = 0; - - // round the player's block position down to the nearest chunk BlockPos - int playerPosX = MC.getPlayerBlockPos().getX(); - int playerPosZ = MC.getPlayerBlockPos().getZ(); - double runTimeRatio = Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get()>1 ? 1.0 : Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get(); - - //FIXME - PosToGenerateContainer posToGenerate = null;//lodDim.getPosToGenerate(estimatedSampleNeeded, playerPosX, playerPosZ, - //priority, mode); - - if (eventsCount == 0 && posToGenerate.getNumberOfPos() >= estimatedSampleNeeded) { - estimatedPointsToQueue++; - if (estimatedPointsToQueue > newThreadCount * 10) - estimatedPointsToQueue = newThreadCount * 10; - } - - // ApiShared.LOGGER.info("PosToGenerate: {}", posToGenerate); - - // Find the max number of iterations we need to go though. - // We are checking one FarPos, and one NearPos per iterations. - // This ensures we aren't just always picking one or the other. - Steps targetStep; - switch (mode) { - case NONE: - targetStep = Steps.Empty; // NOTE: Only load in existing chunks. No new chunk generation - break; - case BIOME_ONLY: - targetStep = Steps.Biomes; // NOTE: No block. Require fake height in LodBuilder - break; - case BIOME_ONLY_SIMULATE_HEIGHT: - targetStep = Steps.Noise; // NOTE: Stone only. Require fake surface - break; - case SURFACE: - targetStep = Steps.Surface; // Carvers or Surface??? - break; - case FEATURES: - case FULL: - targetStep = Steps.Features; - break; - default: - assert false; - return; - } - - if (ENABLE_GENERATOR_STATS_LOGGING) - LOGGER.info("WorldGen. Near:" + posToGenerate.getNumberOfNearPos() + " Far:" - + posToGenerate.getNumberOfFarPos()); - if (priority == EGenerationPriority.FAR_FIRST || priority == EGenerationPriority.BALANCED) { - - int nearCount = posToGenerate.getNumberOfNearPos(); - int farCount = posToGenerate.getNumberOfFarPos(); - if (ENABLE_GENERATOR_STATS_LOGGING) - LOGGER.info("WorldGen. Near:" + nearCount + " Far:" + farCount); - int maxIteration = Math.max(nearCount, farCount); - for (int i = 0; i < maxIteration; i++) { - - // We have farPos to go though - if (i < farCount && posToGenerate.getNthDetail(i, false) != 0) { - positionGoneThough++; - byte detailLevel = (byte) (posToGenerate.getNthDetail(i, false) - 1); - int chunkX = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosX(i, false)); - int chunkZ = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosZ(i, false)); - int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize; - if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep, false, runTimeRatio)) { - toGenerate--; - } - } - if (toGenerate <= 0) - break; - - // We have nearPos to go though - if (i < nearCount && posToGenerate.getNthDetail(i, true) != 0) { - positionGoneThough++; - byte detailLevel = (byte) (posToGenerate.getNthDetail(i, true) - 1); - int chunkX = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosX(i, true)); - int chunkZ = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosZ(i, true)); - int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize; - if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep, true, runTimeRatio)) { - toGenerate--; - } - } - - if (toGenerate <= 0) - break; - } - } else { - int nearCount = posToGenerate.getNumberOfNearPos(); - for (int i = 0; i < nearCount; i++) { - - // We have nearPos to go though - if (posToGenerate.getNthDetail(i, true) != 0) { - positionGoneThough++; - byte detailLevel = (byte) (posToGenerate.getNthDetail(i, true) - 1); - int chunkX = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosX(i, true)); - int chunkZ = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosZ(i, true)); - int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize; - if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep, true, runTimeRatio)) { - toGenerate--; - } - if (toGenerate <= 0) - break; - } - } - // Only do far gen if toGenerate is non 0 and that we have requested all samples - // we can get. - if (toGenerate > 0 && estimatedSampleNeeded > posToGenerate.getNumberOfPos()) { - int farCount = posToGenerate.getNumberOfFarPos(); - for (int i = 0; i < farCount; i++) { - // We have farPos to go though - if (posToGenerate.getNthDetail(i, false) != 0) { - positionGoneThough++; - byte detailLevel = (byte) (posToGenerate.getNthDetail(i, false) - 1); - int chunkX = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosX(i, false)); - int chunkZ = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosZ(i, false)); - int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize; - if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep, false, runTimeRatio)) { - toGenerate--; - } - } - if (toGenerate <= 0) - break; - } - } - } - - if (targetToGenerate != toGenerate && ENABLE_GENERATOR_STATS_LOGGING) { - if (toGenerate <= 0) { - LOGGER.info( - "WorldGenerator: Sampled " + posToGenerate.getNumberOfPos() + " out of " + estimatedSampleNeeded - + " points, started all targeted " + targetToGenerate + " generations."); - } else { - LOGGER.info("WorldGenerator: Sampled " + posToGenerate.getNumberOfPos() + " out of " - + estimatedSampleNeeded + " points, started " + (targetToGenerate - toGenerate) - + " out of targeted " + targetToGenerate + " generations."); - } - } - - if (toGenerate > 0 && estimatedSampleNeeded <= posToGenerate.getNumberOfPos()) { - // We failed to generate enough points from the samples. - // Let's increase the estimatedSampleNeeded. - estimatedSampleNeeded *= 1.3; - // Ensure wee don't go to basically infinity - if (estimatedSampleNeeded > 32768) - estimatedSampleNeeded = 32768; - if (ENABLE_GENERATOR_STATS_LOGGING) - LOGGER.info("WorldGenerator: Increasing estimatedSampleNeeded to " + estimatedSampleNeeded); - - } else if (toGenerate <= 0 && positionGoneThough * 1.5 < posToGenerate.getNumberOfPos()) { - // We haven't gone through half of them, and it's already enough. - // Let's shrink the estimatedSampleNeeded. - estimatedSampleNeeded /= 1.2; - // Ensure we don't go near zero. - if (estimatedSampleNeeded < 4) - estimatedSampleNeeded = 4; - if (ENABLE_GENERATOR_STATS_LOGGING) - LOGGER.info("WorldGenerator: Decreasing estimatedSampleNeeded to " + estimatedSampleNeeded); - } - - } +// @SuppressWarnings("unused") +// public void queueGenerationRequests() { +// EDistanceGenerationMode mode = Config.Client.WorldGenerator.distanceGenerationMode.get(); +// int newThreadCount = Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get()<1 ? 1 : (int) Math.ceil(Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get()); +// if (newThreadCount != previousThreadCount) { +// generationGroup.resizeThreadPool(newThreadCount); +// previousThreadCount = newThreadCount; +// } +// if (estimatedPointsToQueue < newThreadCount) +// estimatedPointsToQueue = newThreadCount; +// +// EGenerationPriority priority = Config.Client.WorldGenerator.generationPriority.get(); +// if (priority == EGenerationPriority.AUTO) +// priority = MC.hasSinglePlayerServer() ? EGenerationPriority.FAR_FIRST : EGenerationPriority.NEAR_FIRST; +// +// generationGroup.updateAllFutures(); +// if (!MC.hasSinglePlayerServer()) +// return; +// if (!LodUtil.checkRamUsage(0.1, 64)) return; +// +// int eventsCount = generationGroup.getEventCount(); +// // If we still all jobs running, return. +// if (eventsCount >= estimatedPointsToQueue) { +// estimatedPointsToQueue--; +// if (estimatedPointsToQueue < newThreadCount) +// estimatedPointsToQueue = newThreadCount; +// return; +// } +// +// final int targetToGenerate = estimatedPointsToQueue - eventsCount; +// int toGenerate = targetToGenerate; +// int positionGoneThough = 0; +// +// // round the player's block position down to the nearest chunk BlockPos +// int playerPosX = MC.getPlayerBlockPos().getX(); +// int playerPosZ = MC.getPlayerBlockPos().getZ(); +// double runTimeRatio = Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get()>1 ? 1.0 : Config.Client.Advanced.Threading.numberOfWorldGenerationThreads.get(); +// +// //FIXME +// PosToGenerateContainer posToGenerate = null;//lodDim.getPosToGenerate(estimatedSampleNeeded, playerPosX, playerPosZ, +// //priority, mode); +// +// if (eventsCount == 0 && posToGenerate.getNumberOfPos() >= estimatedSampleNeeded) { +// estimatedPointsToQueue++; +// if (estimatedPointsToQueue > newThreadCount * 10) +// estimatedPointsToQueue = newThreadCount * 10; +// } +// +// // ApiShared.LOGGER.info("PosToGenerate: {}", posToGenerate); +// +// // Find the max number of iterations we need to go though. +// // We are checking one FarPos, and one NearPos per iterations. +// // This ensures we aren't just always picking one or the other. +// Steps targetStep; +// switch (mode) { +// case NONE: +// targetStep = Steps.Empty; // NOTE: Only load in existing chunks. No new chunk generation +// break; +// case BIOME_ONLY: +// targetStep = Steps.Biomes; // NOTE: No block. Require fake height in LodBuilder +// break; +// case BIOME_ONLY_SIMULATE_HEIGHT: +// targetStep = Steps.Noise; // NOTE: Stone only. Require fake surface +// break; +// case SURFACE: +// targetStep = Steps.Surface; // Carvers or Surface??? +// break; +// case FEATURES: +// case FULL: +// targetStep = Steps.Features; +// break; +// default: +// assert false; +// return; +// } +// +// if (ENABLE_GENERATOR_STATS_LOGGING) +// LOGGER.info("WorldGen. Near:" + posToGenerate.getNumberOfNearPos() + " Far:" +// + posToGenerate.getNumberOfFarPos()); +// if (priority == EGenerationPriority.FAR_FIRST || priority == EGenerationPriority.BALANCED) { +// +// int nearCount = posToGenerate.getNumberOfNearPos(); +// int farCount = posToGenerate.getNumberOfFarPos(); +// if (ENABLE_GENERATOR_STATS_LOGGING) +// LOGGER.info("WorldGen. Near:" + nearCount + " Far:" + farCount); +// int maxIteration = Math.max(nearCount, farCount); +// for (int i = 0; i < maxIteration; i++) { +// +// // We have farPos to go though +// if (i < farCount && posToGenerate.getNthDetail(i, false) != 0) { +// positionGoneThough++; +// byte detailLevel = (byte) (posToGenerate.getNthDetail(i, false) - 1); +// int chunkX = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosX(i, false)); +// int chunkZ = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosZ(i, false)); +// int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize; +// if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep, false, runTimeRatio)) { +// toGenerate--; +// } +// } +// if (toGenerate <= 0) +// break; +// +// // We have nearPos to go though +// if (i < nearCount && posToGenerate.getNthDetail(i, true) != 0) { +// positionGoneThough++; +// byte detailLevel = (byte) (posToGenerate.getNthDetail(i, true) - 1); +// int chunkX = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosX(i, true)); +// int chunkZ = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosZ(i, true)); +// int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize; +// if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep, true, runTimeRatio)) { +// toGenerate--; +// } +// } +// +// if (toGenerate <= 0) +// break; +// } +// } else { +// int nearCount = posToGenerate.getNumberOfNearPos(); +// for (int i = 0; i < nearCount; i++) { +// +// // We have nearPos to go though +// if (posToGenerate.getNthDetail(i, true) != 0) { +// positionGoneThough++; +// byte detailLevel = (byte) (posToGenerate.getNthDetail(i, true) - 1); +// int chunkX = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosX(i, true)); +// int chunkZ = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosZ(i, true)); +// int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize; +// if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep, true, runTimeRatio)) { +// toGenerate--; +// } +// if (toGenerate <= 0) +// break; +// } +// } +// // Only do far gen if toGenerate is non 0 and that we have requested all samples +// // we can get. +// if (toGenerate > 0 && estimatedSampleNeeded > posToGenerate.getNumberOfPos()) { +// int farCount = posToGenerate.getNumberOfFarPos(); +// for (int i = 0; i < farCount; i++) { +// // We have farPos to go though +// if (posToGenerate.getNthDetail(i, false) != 0) { +// positionGoneThough++; +// byte detailLevel = (byte) (posToGenerate.getNthDetail(i, false) - 1); +// int chunkX = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosX(i, false)); +// int chunkZ = LevelPosUtil.getChunkPos(detailLevel, posToGenerate.getNthPosZ(i, false)); +// int genSize = detailLevel > LodUtil.CHUNK_DETAIL_LEVEL ? 0 : generationGroupSize; +// if (generationGroup.tryAddPoint(chunkX, chunkZ, genSize, targetStep, false, runTimeRatio)) { +// toGenerate--; +// } +// } +// if (toGenerate <= 0) +// break; +// } +// } +// } +// +// if (targetToGenerate != toGenerate && ENABLE_GENERATOR_STATS_LOGGING) { +// if (toGenerate <= 0) { +// LOGGER.info( +// "WorldGenerator: Sampled " + posToGenerate.getNumberOfPos() + " out of " + estimatedSampleNeeded +// + " points, started all targeted " + targetToGenerate + " generations."); +// } else { +// LOGGER.info("WorldGenerator: Sampled " + posToGenerate.getNumberOfPos() + " out of " +// + estimatedSampleNeeded + " points, started " + (targetToGenerate - toGenerate) +// + " out of targeted " + targetToGenerate + " generations."); +// } +// } +// +// if (toGenerate > 0 && estimatedSampleNeeded <= posToGenerate.getNumberOfPos()) { +// // We failed to generate enough points from the samples. +// // Let's increase the estimatedSampleNeeded. +// estimatedSampleNeeded *= 1.3; +// // Ensure wee don't go to basically infinity +// if (estimatedSampleNeeded > 32768) +// estimatedSampleNeeded = 32768; +// if (ENABLE_GENERATOR_STATS_LOGGING) +// LOGGER.info("WorldGenerator: Increasing estimatedSampleNeeded to " + estimatedSampleNeeded); +// +// } else if (toGenerate <= 0 && positionGoneThough * 1.5 < posToGenerate.getNumberOfPos()) { +// // We haven't gone through half of them, and it's already enough. +// // Let's shrink the estimatedSampleNeeded. +// estimatedSampleNeeded /= 1.2; +// // Ensure we don't go near zero. +// if (estimatedSampleNeeded < 4) +// estimatedSampleNeeded = 4; +// if (ENABLE_GENERATOR_STATS_LOGGING) +// LOGGER.info("WorldGenerator: Decreasing estimatedSampleNeeded to " + estimatedSampleNeeded); +// } +// +// } public void stop(boolean blocking) { LOGGER.info("1.18 Experimental Chunk Generator shutting down..."); @@ -315,4 +315,9 @@ public class BatchGenerator implements IChunkGenerator public void close() { stop(true); } + + public void update() { + generationGroup.updateAllFutures(); + } + } diff --git a/src/main/java/com/seibel/lod/core/handlers/dependencyInjection/DhApiEventInjector.java b/src/main/java/com/seibel/lod/core/handlers/dependencyInjection/DhApiEventInjector.java index 71e2d5150..163edd94b 100644 --- a/src/main/java/com/seibel/lod/core/handlers/dependencyInjection/DhApiEventInjector.java +++ b/src/main/java/com/seibel/lod/core/handlers/dependencyInjection/DhApiEventInjector.java @@ -102,11 +102,11 @@ public class DhApiEventInjector extends DependencyInjector * @return if any of the events returned that this event should be canceled. * @param the parameter type taken by the event handlers. */ - public boolean fireAllEvents(Class> dependencyInterface, T eventParameterObject) + public > boolean fireAllEvents(Class dependencyInterface, T eventParameterObject) { boolean cancelEvent = false; - ArrayList> eventList = this.getAll(dependencyInterface); + ArrayList eventList = this.getAll(dependencyInterface); for (IDhApiEvent event : eventList) { if (event != null) diff --git a/src/main/java/com/seibel/lod/core/util/EventTimer.java b/src/main/java/com/seibel/lod/core/util/EventTimer.java new file mode 100644 index 000000000..b07a4b359 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/util/EventTimer.java @@ -0,0 +1,70 @@ +package com.seibel.lod.core.util; + +import java.time.Duration; +import java.util.ArrayList; + +public class EventTimer { + public static class Event { + public long timeNs = -1; + public String name; + Event(String name) { + this.name = name; + } + } + long lastEventNs = -1; + + public ArrayList events = new ArrayList<>(); + + public EventTimer(String firstEventName) { + lastEventNs = System.nanoTime(); + events.add(new Event(firstEventName)); + } + + public void nextEvent(String name) { + long timeNs = System.nanoTime(); + if (lastEventNs != -1 && !events.isEmpty() && events.get(events.size()-1).timeNs == -1) { + events.get(events.size()-1).timeNs = timeNs - lastEventNs; + } + lastEventNs = timeNs; + events.add(new Event(name)); + } + + public void complete() { + long timeNs = System.nanoTime(); + if (lastEventNs != -1 && !events.isEmpty() && events.get(events.size()-1).timeNs == -1) { + events.get(events.size()-1).timeNs = timeNs - lastEventNs; + } + lastEventNs = -1; + } + + public long getEventTimeNs(String name) { + for (Event e : events) { + if (e.name.equals(name)) { + return e.timeNs; + } + } + return -1; + } + + public long getTotalTimeNs() { + long total = 0; + for (Event e : events) { + if (e.timeNs != -1) { + total += e.timeNs; + } + } + return total; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + for (Event e : events) { + if (e.timeNs != -1) { + sb.append(e.name).append(": ").append(Duration.ofNanos(e.timeNs)).append('\n'); + } else { + sb.append(e.name).append(": ").append("N/A").append('\n'); + } + } + return sb.toString(); + } +} diff --git a/src/main/java/com/seibel/lod/core/util/LodUtil.java b/src/main/java/com/seibel/lod/core/util/LodUtil.java index e8899f31f..a73cbe72f 100644 --- a/src/main/java/com/seibel/lod/core/util/LodUtil.java +++ b/src/main/java/com/seibel/lod/core/util/LodUtil.java @@ -443,6 +443,12 @@ public class LodUtil public static void assertTrue(boolean condition, String message) { if (!condition) throw new RuntimeException("Assertion failed: " + message); } + public static void assertNotReach(String message) { + throw new RuntimeException("Assert Not Reach failed: " + message); + } + public static void assertNotReach() { + throw new RuntimeException("Assert Not Reach failed"); + } public static ExecutorService makeSingleThreadPool(String name, int relativePriority) { return Executors.newSingleThreadExecutor(new LodThreadFactory(name, Thread.NORM_PRIORITY+relativePriority)); } diff --git a/src/main/java/com/seibel/lod/core/wrapperInterfaces/worldGeneration/AbstractBatchGenerationEnvionmentWrapper.java b/src/main/java/com/seibel/lod/core/wrapperInterfaces/worldGeneration/AbstractBatchGenerationEnvionmentWrapper.java index de9246b01..806e29ff6 100644 --- a/src/main/java/com/seibel/lod/core/wrapperInterfaces/worldGeneration/AbstractBatchGenerationEnvionmentWrapper.java +++ b/src/main/java/com/seibel/lod/core/wrapperInterfaces/worldGeneration/AbstractBatchGenerationEnvionmentWrapper.java @@ -35,14 +35,10 @@ public abstract class AbstractBatchGenerationEnvionmentWrapper { public abstract void resizeThreadPool(int newThreadCount); - @Deprecated public abstract void updateAllFutures(); public abstract int getEventCount(); - @Deprecated - public abstract boolean tryAddPoint(int chunkX, int chunkZ, int genSize, Steps targetStep, boolean genAllDetails, double runTimeRatio); - public abstract void stop(boolean blocking); public abstract CompletableFuture> generateChunks(int minX, int minZ, int genSize, Steps targetStep, double runTimeRatio);