From fca926bc8f2f701be6951d93ad42c98cacada145 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 5 Oct 2021 11:25:06 +0200 Subject: [PATCH 01/14] Added some comment, fixed the thread conflict problem --- .../worldGeneration/LodNodeGenWorker.java | 8 ++--- .../worldGeneration/LodWorldGenerator.java | 29 +++++++-------- .../com/seibel/lod/proxy/ClientProxy.java | 17 +++++++-- .../com/seibel/lod/util/DataPointUtil.java | 36 ++++++++++++++----- 4 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java index 93c639b6a..18500fe7d 100644 --- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java +++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java @@ -101,9 +101,9 @@ public class LodNodeGenWorker implements IWorker if (newServerWorld == null) throw new IllegalArgumentException("LodChunkGenThread requires a non-null ServerWorld"); - - - + + + thread = new LodChunkGenThread(newPos, newGenerationMode, newLodBuilder, newLodDimension, newServerWorld); @@ -615,7 +615,7 @@ public class LodNodeGenWorker implements IWorker { genThreads.shutdownNow(); } - genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new LodThreadFactory(LodNodeGenWorker.class.getSimpleName())); + genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new ThreadFactoryBuilder().setNameFormat("Gen-Worker-Thread-%d").build()); } diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java index a81db12c0..4c7464c07 100644 --- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java +++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java @@ -126,13 +126,11 @@ public class LodWorldGenerator nearIndex++; ChunkPos chunkPos = new ChunkPos(LevelPosUtil.getChunkPos(detailLevel, posX), LevelPosUtil.getChunkPos(detailLevel, posZ)); - if (numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests) - { - // prevent generating the same chunk multiple times - if (positionsWaitingToBeGenerated.contains(chunkPos)) - continue; - } - + + // prevent generating the same chunk multiple times + if (positionsWaitingToBeGenerated.contains(chunkPos)) + continue; + // don't add more to the generation queue then allowed if (numberOfChunksWaitingToGenerate.get() >= maxChunkGenRequests) break; @@ -153,17 +151,16 @@ public class LodWorldGenerator farIndex++; ChunkPos chunkPos = new ChunkPos(LevelPosUtil.getChunkPos(detailLevel, posX), LevelPosUtil.getChunkPos(detailLevel, posZ)); - if (numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests) - { - // prevent generating the same chunk multiple times - if (positionsWaitingToBeGenerated.contains(chunkPos)) - continue; - } - + // don't add more to the generation queue then allowed if (numberOfChunksWaitingToGenerate.get() >= maxChunkGenRequests) - break; - + continue; + //break; + + // prevent generating the same chunk multiple times + if (positionsWaitingToBeGenerated.contains(chunkPos)) + continue; + positionsWaitingToBeGenerated.add(chunkPos); numberOfChunksWaitingToGenerate.addAndGet(1); LodNodeGenWorker genWorker = new LodNodeGenWorker(chunkPos, DetailDistanceUtil.getDistanceGenerationMode(detailLevel), lodBuilder, lodDim, serverWorld); diff --git a/src/main/java/com/seibel/lod/proxy/ClientProxy.java b/src/main/java/com/seibel/lod/proxy/ClientProxy.java index 795f22c5f..aa410e3ef 100644 --- a/src/main/java/com/seibel/lod/proxy/ClientProxy.java +++ b/src/main/java/com/seibel/lod/proxy/ClientProxy.java @@ -231,7 +231,8 @@ public class ClientProxy public void worldLoadEvent(WorldEvent.Load event) { DataPointUtil.worldHeight = event.getWorld().getHeight(); - ThreadMapUtil.clearMaps(); + //LodNodeGenWorker.restartExecuterService(); + //ThreadMapUtil.clearMaps(); // the player just loaded a new world/dimension lodWorld.selectWorld(LodUtil.getWorldID(event.getWorld())); @@ -254,8 +255,8 @@ public class ClientProxy // if this isn't done unfinished tasks may be left in the queue // preventing new LodChunks form being generated - LodNodeGenWorker.restartExecuterService(); - ThreadMapUtil.clearMaps(); + //LodNodeGenWorker.restartExecuterService(); + //ThreadMapUtil.clearMaps(); LodWorldGenerator.INSTANCE.numberOfChunksWaitingToGenerate.set(0); lodWorld.deselectWorld(); @@ -366,6 +367,16 @@ public class ClientProxy firstTimeSetupComplete = true; } + + /** + * this method reset some of the static data everytime we change world + **/ + private void resetMod() + { + ThreadMapUtil.clearMaps(); + LodNodeGenWorker.restartExecuterService(); + + } //================// // public getters // diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 45bff9c76..b38a97653 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -174,7 +174,13 @@ public class DataPointUtil { return (int) (((dataPoint >>> COLOR_SHIFT) & COLOR_MASK) | (((dataPoint >>> (ALPHA_SHIFT - ALPHA_DOWNSIZE_SHIFT)) | 0b1111) << 24)); } - + + /** + * This method apply the lightmap to the color to use + * @param dataPoint + * @param lightMap + * @return + */ public static int getLightColor(long dataPoint, NativeImage lightMap) { int lightBlock = getLightBlock(dataPoint); @@ -186,7 +192,12 @@ public class DataPointUtil return ColorUtil.multiplyRGBcolors(getColor(dataPoint), ColorUtil.rgbToInt(red, green, blue)); } - + + /** + * This is used to convert a dataPoint to string (usefull for the print function) + * @param dataPoint + * @return + */ public static String toString(long dataPoint) { StringBuilder s = new StringBuilder(); @@ -214,7 +225,12 @@ public class DataPointUtil s.append('\n'); return s.toString(); } - + + /** + * This method merge column of single data together + * @param dataToMerge + * @return + */ public static long mergeSingleData(long[] dataToMerge) { int numberOfChildren = 0; @@ -275,7 +291,14 @@ public class DataPointUtil return DataPointUtil.createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, tempHeight, tempDepth, tempLightSky, tempLightBlock, tempGenMode); } } - + + /** + * This method merge column of multiple data together + * @param dataToMerge + * @param inputVerticalData vertical size of an input data + * @param maxVerticalData max vertical size of the merged data + * @return + */ public static long[] mergeMultiData(long[] dataToMerge, int inputVerticalData, int maxVerticalData) { int size = dataToMerge.length / inputVerticalData; @@ -422,9 +445,4 @@ public class DataPointUtil } return dataPoint; } - - public static long[] compress(long[] data, byte detailLevel) - { - return null; - } } \ No newline at end of file From 2b15c089f4f16ac922d2b594366a1cd3b82d9b72 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 5 Oct 2021 18:59:40 +0200 Subject: [PATCH 02/14] Added back the toString in the PosToGenerateContainer --- .../lod/objects/PosToGenerateContainer.java | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java index 1943017c1..1a292ea99 100644 --- a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java +++ b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java @@ -152,48 +152,41 @@ public class PosToGenerateContainer // TOOD is this commented code still useful? // if so why have it commented out? - /* + StringBuilder builder = new StringBuilder(); - builder.append("Number of pos to generate "); - builder.append(farSize + nearSize); builder.append('\n'); - builder.append("Number of near pos to generate "); - builder.append(nearSize); - builder.append('\n'); - builder.append("Number of far pos to generate "); - builder.append(farSize); builder.append('\n'); builder.append('\n'); builder.append("near pos to generate"); builder.append('\n'); - for (int i = 0; i < nearSize; i++) + for (int i = 0; i < nearPosToGenerate.length; i++) { - builder.append(posToGenerate[i][0]-1); + builder.append(nearPosToGenerate[i][0]-1); builder.append(" "); - builder.append(posToGenerate[i][1]); + builder.append(nearPosToGenerate[i][1]); builder.append(" "); - builder.append(posToGenerate[i][2]); + builder.append(nearPosToGenerate[i][2]); builder.append(" "); - builder.append(posToGenerate[i][3]); + builder.append(nearPosToGenerate[i][3]); builder.append('\n'); } builder.append('\n'); + builder.append("far pos to generate"); builder.append('\n'); - for (int i = maxSize - 1; i >= maxSize - farSize; i--) + for (int i = 0; i < farPosToGenerate.length; i++) { - builder.append(posToGenerate[i][0]-1); + builder.append(farPosToGenerate[i][0]-1); builder.append(" "); - builder.append(posToGenerate[i][1]); + builder.append(farPosToGenerate[i][1]); builder.append(" "); - builder.append(posToGenerate[i][2]); + builder.append(farPosToGenerate[i][2]); builder.append(" "); - builder.append(posToGenerate[i][3]); + builder.append(farPosToGenerate[i][3]); builder.append('\n'); } - builder.append('\n'); return builder.toString(); - */ + return " "; } From 0c275e14954c47f0fa3ef5ee194e68a67dcc0c7e Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 5 Oct 2021 19:06:51 +0200 Subject: [PATCH 03/14] Added back the toString in the PosToGenerateContainer --- .../java/com/seibel/lod/objects/PosToGenerateContainer.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java index 1a292ea99..0a025aabf 100644 --- a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java +++ b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java @@ -186,8 +186,5 @@ public class PosToGenerateContainer builder.append('\n'); } return builder.toString(); - - - return " "; } } From e154f552c7578d08ee79aa922326dc4ddb9cb280 Mon Sep 17 00:00:00 2001 From: cola98765 Date: Wed, 6 Oct 2021 10:36:37 +0200 Subject: [PATCH 04/14] fixed bug where only some regions were saved when player was not moving --- .../seibel/lod/handlers/LodDimensionFileHandler.java | 6 +++--- src/main/java/com/seibel/lod/objects/LodDimension.java | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index 9d41b4baf..97c293fc4 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -239,10 +239,10 @@ public class LodDimensionFileHandler for (int j = 0; j < lodDimension.getWidth(); j++) { // TODO shouldn't this use lodDimension.isRegionDirty? - if (lodDimension.doesRegionNeedBufferRegen(i,j) && lodDimension.getRegionByArrayIndex(i,j) != null) + if (lodDimension.GetIsRegionDirty(i,j) && lodDimension.getRegionByArrayIndex(i,j) != null) { saveRegionToFile(lodDimension.getRegionByArrayIndex(i,j)); - lodDimension.setRegenRegionBufferByArrayIndex(i, j,false); + lodDimension.SetIsRegionDirty(i, j, false); } } } @@ -275,7 +275,7 @@ public class LodDimensionFileHandler ClientProxy.LOGGER.warn("Unable to save region [" + region.regionPosX + ", " + region.regionPosZ + "] to file, file is inaccessible."); return; } - + ClientProxy.LOGGER.info("saving region [" + region.regionPosX + ", " + region.regionPosZ + "] to file."); try { diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index 4dca1dc54..13f1d1dae 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -906,4 +906,14 @@ public class LodDimension return memoryUse; //return memoryUse; } + + public boolean GetIsRegionDirty(int i , int j) + { + return isRegionDirty[i][j]; + } + + public void SetIsRegionDirty(int i, int j, boolean val) + { + isRegionDirty[i][j] = val; + } } From 28cf2eb450e6d456b8517f30fe2d46bc70960297 Mon Sep 17 00:00:00 2001 From: cola98765 Date: Wed, 6 Oct 2021 10:37:36 +0200 Subject: [PATCH 05/14] removed debug message when saving --- .../java/com/seibel/lod/handlers/LodDimensionFileHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index 97c293fc4..78700401c 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -275,7 +275,7 @@ public class LodDimensionFileHandler ClientProxy.LOGGER.warn("Unable to save region [" + region.regionPosX + ", " + region.regionPosZ + "] to file, file is inaccessible."); return; } - ClientProxy.LOGGER.info("saving region [" + region.regionPosX + ", " + region.regionPosZ + "] to file."); + //ClientProxy.LOGGER.info("saving region [" + region.regionPosX + ", " + region.regionPosZ + "] to file."); try { From a66554f2ddcf5640725453562a472da81698d270 Mon Sep 17 00:00:00 2001 From: cola98765 Date: Wed, 6 Oct 2021 11:45:36 +0200 Subject: [PATCH 06/14] resolved todo --- .../java/com/seibel/lod/handlers/LodDimensionFileHandler.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index 78700401c..fc737b036 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -238,7 +238,6 @@ public class LodDimensionFileHandler { for (int j = 0; j < lodDimension.getWidth(); j++) { - // TODO shouldn't this use lodDimension.isRegionDirty? if (lodDimension.GetIsRegionDirty(i,j) && lodDimension.getRegionByArrayIndex(i,j) != null) { saveRegionToFile(lodDimension.getRegionByArrayIndex(i,j)); From a6f3c2478e6974225488a01bc4ef3cd5f3070282 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 7 Oct 2021 00:19:32 +0200 Subject: [PATCH 07/14] Some refactor + fixed cpu problem with near_first --- .../bufferBuilding/LodBufferBuilder.java | 2 +- .../worldGeneration/LodWorldGenerator.java | 14 +++--- .../com/seibel/lod/objects/LodDimension.java | 10 ++-- .../com/seibel/lod/objects/LodRegion.java | 48 +++++++++---------- .../com/seibel/lod/util/DataPointUtil.java | 7 +++ 5 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java index afdd8e48a..c5e30e20e 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java @@ -274,7 +274,7 @@ public class LodBufferBuilder PosToRenderContainer posToRender = setsToRender[xR][zR]; posToRender.clear(minDetail, regionPos.x, regionPos.z); - lodDim.getDataToRender( + lodDim.getPosToRender( posToRender, regionPos, playerBlockPosRounded.getX(), diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java index 4c7464c07..062114b1c 100644 --- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java +++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java @@ -100,23 +100,23 @@ public class LodWorldGenerator ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(lodDim.dimension); - PosToGenerateContainer posToGenerate = lodDim.getDataToGenerate( + PosToGenerateContainer posToGenerate = lodDim.getPosToGenerate( maxChunkGenRequests, playerPosX, playerPosZ); - - + + byte detailLevel; int posX; int posZ; int nearIndex = 0; int farIndex = 0; - + for (int i = 0; i < posToGenerate.getNumberOfPos(); i++) { // I wish there was a way to compress this code, but I'm not aware of // a easy way to do so. - + // add the near positions if (posToGenerate.getNthDetail(nearIndex, true) != 0 && nearIndex < posToGenerate.getNumberOfNearPos()) { @@ -140,8 +140,8 @@ public class LodWorldGenerator LodNodeGenWorker genWorker = new LodNodeGenWorker(chunkPos, DetailDistanceUtil.getDistanceGenerationMode(detailLevel), lodBuilder, lodDim, serverWorld); WorldWorkerManager.addWorker(genWorker); } - - + + // add the far positions if (posToGenerate.getNthDetail(farIndex, false) != 0 && farIndex < posToGenerate.getNumberOfFarPos()) { diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index 13f1d1dae..8462a1ac6 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -510,7 +510,7 @@ public class LodDimension /** * Returns every position that need to be generated based on the position of the player */ - public PosToGenerateContainer getDataToGenerate(int maxDataToGenerate, int playerBlockPosX, int playerBlockPosZ) + public PosToGenerateContainer getPosToGenerate(int maxDataToGenerate, int playerBlockPosX, int playerBlockPosZ) { PosToGenerateContainer posToGenerate; LodRegion region; @@ -599,7 +599,7 @@ public class LodDimension region = getRegion(xRegion, zRegion); if (region != null) - region.getDataToGenerate(posToGenerate, playerBlockPosX, playerBlockPosZ); + region.getPosToGenerate(posToGenerate, playerBlockPosX, playerBlockPosZ); if ((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z))) @@ -621,12 +621,12 @@ public class LodDimension * * TODO why isn't posToRender returned? it would make it a bit more clear what is happening */ - public void getDataToRender(PosToRenderContainer posToRender, RegionPos regionPos, int playerPosX, - int playerPosZ) + public void getPosToRender(PosToRenderContainer posToRender, RegionPos regionPos, int playerPosX, + int playerPosZ) { LodRegion region = getRegion(regionPos.x, regionPos.z); if (region != null) - region.getDataToRender(posToRender, playerPosX, playerPosZ, LodConfig.CLIENT.worldGenerator.generationPriority.get() == GenerationPriority.NEAR_FIRST); + region.getPosToRender(posToRender, playerPosX, playerPosZ, LodConfig.CLIENT.worldGenerator.generationPriority.get() == GenerationPriority.NEAR_FIRST); } /** diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index c8fb48944..e033698cc 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -156,10 +156,10 @@ public class LodRegion *

* TODO why don't we return the posToGenerate, it would make this easier to understand */ - public void getDataToGenerate(PosToGenerateContainer posToGenerate, - int playerBlockPosX, int playerBlockPosZ) + public void getPosToGenerate(PosToGenerateContainer posToGenerate, + int playerBlockPosX, int playerBlockPosZ) { - getDataToGenerate(posToGenerate, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerBlockPosX, playerBlockPosZ); + getPosToGenerate(posToGenerate, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerBlockPosX, playerBlockPosZ); } @@ -169,8 +169,8 @@ public class LodRegion *

* TODO why don't we return the posToGenerate, it would make this easier to understand */ - private void getDataToGenerate(PosToGenerateContainer posToGenerate, byte detailLevel, - int childOffsetPosX, int childOffsetPosZ, int playerPosX, int playerPosZ) + private void getPosToGenerate(PosToGenerateContainer posToGenerate, byte detailLevel, + int childOffsetPosX, int childOffsetPosZ, int playerPosX, int playerPosZ) { // equivalent to 2^(...) int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); @@ -223,7 +223,7 @@ public class LodRegion if (ungeneratedChildren == 0) for (int x = 0; x <= 1; x++) for (int z = 0; z <= 1; z++) - getDataToGenerate(posToGenerate, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ); + getPosToGenerate(posToGenerate, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ); } else { // The detail Level is smaller than a chunk. @@ -234,7 +234,7 @@ public class LodRegion if (!doesDataExist(childDetailLevel, childPosX, childPosZ)) posToGenerate.addPosToGenerate(childDetailLevel, childPosX + regionPosX * childSize, childPosZ + regionPosZ * childSize); else - getDataToGenerate(posToGenerate, childDetailLevel, childPosX, childPosZ, playerPosX, playerPosZ); + getPosToGenerate(posToGenerate, childDetailLevel, childPosX, childPosZ, playerPosX, playerPosZ); } } } @@ -247,10 +247,10 @@ public class LodRegion *

* TODO why don't we return the posToRender, it would make this easier to understand */ - public void getDataToRender(PosToRenderContainer posToRender, - int playerPosX, int playerPosZ, boolean requireCorrectDetailLevel) + public void getPosToRender(PosToRenderContainer posToRender, + int playerPosX, int playerPosZ, boolean requireCorrectDetailLevel) { - getDataToRender(posToRender, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ, requireCorrectDetailLevel); + getPosToRender(posToRender, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ, requireCorrectDetailLevel); } /** @@ -260,9 +260,9 @@ public class LodRegion * TODO why don't we return the posToRender, it would make this easier to understand * TODO this needs some more comments, James was only able to figure out part of it */ - private void getDataToRender(PosToRenderContainer posToRender, - byte detailLevel, int posX, int posZ, - int playerPosX, int playerPosZ, boolean requireCorrectDetailLevel) + private void getPosToRender(PosToRenderContainer posToRender, + byte detailLevel, int posX, int posZ, + int playerPosX, int playerPosZ, boolean requireCorrectDetailLevel) { // equivalent to 2^(...) int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); @@ -302,9 +302,9 @@ public class LodRegion if (stopNow) { - posToRender.addPosToRender(detailLevel, - posX + regionPosX * size, - posZ + regionPosZ * size); + posToRender.addPosToRender(detailLevel, + posX + regionPosX * size, + posZ + regionPosZ * size); } else if (desiredLevel > detailLevel) { // we have gone beyond the target Detail level @@ -312,9 +312,9 @@ public class LodRegion return; } else if (desiredLevel == detailLevel) { - posToRender.addPosToRender(detailLevel, - posX + regionPosX * size, - posZ + regionPosZ * size); + posToRender.addPosToRender(detailLevel, + posX + regionPosX * size, + posZ + regionPosZ * size); } else //case where (detailLevel > desiredLevel) { int childPosX = posX * 2; @@ -331,7 +331,7 @@ public class LodRegion if (!requireCorrectDetailLevel) childrenCount++; else - getDataToRender(posToRender, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ, requireCorrectDetailLevel); + getPosToRender(posToRender, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ, requireCorrectDetailLevel); } } } @@ -344,12 +344,12 @@ public class LodRegion { for (int x = 0; x <= 1; x++) for (int z = 0; z <= 1; z++) - getDataToRender(posToRender, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ, requireCorrectDetailLevel); + getPosToRender(posToRender, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ, requireCorrectDetailLevel); } else { - posToRender.addPosToRender(detailLevel, - posX + regionPosX * size, - posZ + regionPosZ * size); + posToRender.addPosToRender(detailLevel, + posX + regionPosX * size, + posZ + regionPosZ * size); } } } diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index b38a97653..4687c96de 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -4,6 +4,8 @@ import com.seibel.lod.enums.DistanceGenerationMode; import net.minecraft.client.renderer.texture.NativeImage; +import javax.xml.crypto.Data; + public class DataPointUtil { /* @@ -428,6 +430,7 @@ public class DataPointUtil singleData = dataToMerge[index * inputVerticalData + dataIndex]; if (doesItExist(singleData) && !isVoid(singleData)) { + if ((depth <= getDepth(singleData) && getDepth(singleData) <= height) || (depth <= getHeight(singleData) && getHeight(singleData) <= height)) { @@ -438,6 +441,10 @@ public class DataPointUtil } } } + if(!doesItExist(singleDataToMerge[index])){ + singleData = dataToMerge[index * inputVerticalData]; + singleDataToMerge[index] = createVoidDataPoint(getGenerationMode(singleData)); + } } long data = mergeSingleData(singleDataToMerge); From 6deca8e235f8ae8d2256011754f7d4c40da11841 Mon Sep 17 00:00:00 2001 From: cola98765 Date: Thu, 7 Oct 2021 10:36:30 +0200 Subject: [PATCH 08/14] resolved many warnings and applied autoformat in affected files --- .../bufferBuilding/LodBufferBuilder.java | 90 ++++----- .../bufferBuilding/lodTemplates/Box.java | 98 +++++----- .../lod/builders/lodBuilding/LodBuilder.java | 179 +++++++----------- .../worldGeneration/LodNodeGenWorker.java | 112 +++++------ .../lod/handlers/LodDimensionFileHandler.java | 38 ++-- .../com/seibel/lod/objects/LodDimension.java | 46 ++--- .../com/seibel/lod/util/ThreadMapUtil.java | 48 ++--- 7 files changed, 274 insertions(+), 337 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java index c5e30e20e..1156e84a5 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/LodBufferBuilder.java @@ -15,24 +15,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.seibel.lod.builders.bufferBuilding; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.locks.ReentrantLock; - -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL15; -import org.lwjgl.opengl.GL15C; -import org.lwjgl.opengl.GL45; - import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.seibel.lod.builders.bufferBuilding.lodTemplates.Box; import com.seibel.lod.config.LodConfig; @@ -44,18 +29,27 @@ import com.seibel.lod.objects.RegionPos; import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.proxy.GlProxy; import com.seibel.lod.render.LodRenderer; -import com.seibel.lod.util.DataPointUtil; -import com.seibel.lod.util.DetailDistanceUtil; -import com.seibel.lod.util.LevelPosUtil; -import com.seibel.lod.util.LodThreadFactory; -import com.seibel.lod.util.LodUtil; -import com.seibel.lod.util.ThreadMapUtil; - +import com.seibel.lod.util.*; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.vertex.VertexBuffer; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL15; +import org.lwjgl.opengl.GL15C; +import org.lwjgl.opengl.GL45; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.locks.ReentrantLock; /** * This object is used to create NearFarBuffer objects. @@ -135,7 +129,7 @@ public class LodBufferBuilder /** * this is used to prevent multiple threads creating, destroying, or using the buffers at the same time */ - private ReentrantLock bufferLock = new ReentrantLock(); + private final ReentrantLock bufferLock = new ReentrantLock(); private volatile Box[][] boxCache; private volatile PosToRenderContainer[][] setsToRender; @@ -322,9 +316,9 @@ public class LodBufferBuilder chunkZdist = LevelPosUtil.getChunkPos(detailLevel, zAdj) - playerChunkPos.z; if (posToRender.contains(detailLevel, xAdj, zAdj) && (gameChunkRenderDistance < Math.abs(chunkXdist) - || gameChunkRenderDistance < Math.abs(chunkZdist) - || !(vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1] - && (!LodUtil.isBorderChunk(vanillaRenderedChunks, chunkXdist + gameChunkRenderDistance + 1, chunkZdist + gameChunkRenderDistance + 1) || smallRenderDistance)))) + || gameChunkRenderDistance < Math.abs(chunkZdist) + || !(vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1] + && (!LodUtil.isBorderChunk(vanillaRenderedChunks, chunkXdist + gameChunkRenderDistance + 1, chunkZdist + gameChunkRenderDistance + 1) || smallRenderDistance)))) { for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, xAdj, zAdj); verticalIndex++) { @@ -357,7 +351,7 @@ public class LodBufferBuilder } // for pos to in list to render - // the thread executed successfully + // the thread executed successfully return true; }; @@ -390,7 +384,7 @@ public class LodBufferBuilder long buildTime = endTime - startTime; @SuppressWarnings("unused") long executeTime = executeEnd - executeStart; - + // ClientProxy.LOGGER.info("Thread Build time: " + buildTime + " ms" + '\n' + // "thread execute time: " + executeTime + " ms"); @@ -469,7 +463,7 @@ public class LodBufferBuilder } else { - numberOfBuffers = (int) Math.ceil(memoryRequired / BUFFER_MAX_CAPACITY) + 1; + numberOfBuffers = (int) memoryRequired / BUFFER_MAX_CAPACITY + 1; memoryRequired = BUFFER_MAX_CAPACITY; bufferSize[x][z] = numberOfBuffers; buildableBuffers[x][z] = new BufferBuilder[numberOfBuffers]; @@ -483,8 +477,8 @@ public class LodBufferBuilder buildableVbos[x][z][i] = new VertexBuffer(LodRenderer.LOD_VERTEX_FORMAT); drawableVbos[x][z][i] = new VertexBuffer(LodRenderer.LOD_VERTEX_FORMAT); - - + + // // buffer storage // GL15.glDeleteBuffers(buildableVbos[x][z][i].id); // GL15.glDeleteBuffers(drawableVbos[x][z][i].id); @@ -619,9 +613,9 @@ public class LodBufferBuilder { // this is how many points will be rendered vbo.vertexCount = (uploadBuffer.remaining() / vbo.format.getVertexSize()); - - - + + + // // buffer mapping // // // no stutter 50% GPU useage // // stores everything in system memory instead of GPU memory @@ -656,11 +650,11 @@ public class LodBufferBuilder // GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER); // GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); // } - - - - - + + + + + // // bufferstorage // // // to test: uncomment the bufferstorage lines in setupBuffers as well // // then reboot the game @@ -694,7 +688,7 @@ public class LodBufferBuilder // GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, 0); // } - + @@ -704,18 +698,18 @@ public class LodBufferBuilder GL45.glBindBuffer(GL45.GL_ARRAY_BUFFER, vbo.id); long size = GL45.glGetBufferParameteri64(GL45.GL_ARRAY_BUFFER, GL45.GL_BUFFER_SIZE); - if (size < uploadBuffer.capacity() * 4) + if (size < uploadBuffer.capacity() * 4L) { - GL45.glBufferData(GL45.GL_ARRAY_BUFFER, uploadBuffer.capacity() * 5, GL45.GL_STREAM_DRAW); + GL45.glBufferData(GL45.GL_ARRAY_BUFFER, uploadBuffer.capacity() * 5L, GL45.GL_STREAM_DRAW); ClientProxy.LOGGER.info("expand buffer: " + size + " -> " + (uploadBuffer.capacity() * 4)); } GL45.glBufferSubData(GL45.GL_ARRAY_BUFFER, 0, uploadBuffer); GL15.glUnmapBuffer(GL15.GL_ARRAY_BUFFER); - GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); - - - + GL15C.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); + + + // // old method - bufferData // // bad stuttering 12% GPU usage // @@ -759,7 +753,7 @@ public class LodBufferBuilder /** * A simple container to pass multiple objects back in the getVertexBuffers method. */ - public class VertexBuffersAndOffset + public static class VertexBuffersAndOffset { public VertexBuffer[][][] vbos; public ChunkPos drawableCenterChunkPos; diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/Box.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/Box.java index cab7fc516..10bcf7f93 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/Box.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/Box.java @@ -1,20 +1,19 @@ package com.seibel.lod.builders.bufferBuilding.lodTemplates; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DebugMode; import com.seibel.lod.util.ColorUtil; import com.seibel.lod.util.DataPointUtil; import com.seibel.lod.util.LodUtil; import com.seibel.lod.wrappers.MinecraftWrapper; - import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3i; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + /** * Similar to Minecraft's AxisAlignedBoundingBox. * @@ -37,57 +36,56 @@ public class Box public static final int VOID_FACE = 0; /** The six cardinal directions */ - public static final Direction[] DIRECTIONS = new Direction[]{ + public static final Direction[] DIRECTIONS = new Direction[] { Direction.UP, Direction.DOWN, Direction.WEST, Direction.EAST, Direction.NORTH, - Direction.SOUTH}; + Direction.SOUTH }; /** North, South, East, West */ - public static final Direction[] ADJ_DIRECTIONS = new Direction[]{ + public static final Direction[] ADJ_DIRECTIONS = new Direction[] { Direction.EAST, Direction.WEST, Direction.SOUTH, - Direction.NORTH}; + Direction.NORTH }; /** * All the faces and vertices of a cube. This is used to extract the vertex from the column */ - @SuppressWarnings("serial") public static final Map DIRECTION_VERTEX_MAP = new HashMap() {{ - put(Direction.UP, new int[][]{ - {0, 1, 0}, - {0, 1, 1}, - {1, 1, 1}, - {1, 1, 0}}); - put(Direction.DOWN, new int[][]{ - {1, 0, 0}, - {1, 0, 1}, - {0, 0, 1}, - {0, 0, 0}}); - put(Direction.EAST, new int[][]{ - {1, 1, 0}, - {1, 1, 1}, - {1, 0, 1}, - {1, 0, 0}}); - put(Direction.WEST, new int[][]{ - {0, 0, 0}, - {0, 0, 1}, - {0, 1, 1}, - {0, 1, 0}}); - put(Direction.SOUTH, new int[][]{ - {1, 0, 1}, - {1, 1, 1}, - {0, 1, 1}, - {0, 0, 1}}); - put(Direction.NORTH, new int[][]{ - {0, 0, 0}, - {0, 1, 0}, - {1, 1, 0}, - {1, 0, 0}}); + put(Direction.UP, new int[][] { + { 0, 1, 0 }, + { 0, 1, 1 }, + { 1, 1, 1 }, + { 1, 1, 0 } }); + put(Direction.DOWN, new int[][] { + { 1, 0, 0 }, + { 1, 0, 1 }, + { 0, 0, 1 }, + { 0, 0, 0 } }); + put(Direction.EAST, new int[][] { + { 1, 1, 0 }, + { 1, 1, 1 }, + { 1, 0, 1 }, + { 1, 0, 0 } }); + put(Direction.WEST, new int[][] { + { 0, 0, 0 }, + { 0, 0, 1 }, + { 0, 1, 1 }, + { 0, 1, 0 } }); + put(Direction.SOUTH, new int[][] { + { 1, 0, 1 }, + { 1, 1, 1 }, + { 0, 1, 1 }, + { 0, 0, 1 } }); + put(Direction.NORTH, new int[][] { + { 0, 0, 0 }, + { 0, 1, 0 }, + { 1, 1, 0 }, + { 1, 0, 0 } }); }}; @@ -95,15 +93,14 @@ public class Box * This indicate which position is invariable in the DIRECTION_VERTEX_MAP. * Is used to extract the vertex */ - @SuppressWarnings("serial") public static final Map FACE_DIRECTION = new HashMap() {{ - put(Direction.UP, new int[]{Y, MAX}); - put(Direction.DOWN, new int[]{Y, MIN}); - put(Direction.EAST, new int[]{X, MAX}); - put(Direction.WEST, new int[]{X, MIN}); - put(Direction.SOUTH, new int[]{Z, MAX}); - put(Direction.NORTH, new int[]{Z, MIN}); + put(Direction.UP, new int[] { Y, MAX }); + put(Direction.DOWN, new int[] { Y, MIN }); + put(Direction.EAST, new int[] { X, MAX }); + put(Direction.WEST, new int[] { X, MIN }); + put(Direction.SOUTH, new int[] { Z, MAX }); + put(Direction.NORTH, new int[] { Z, MIN }); }}; @@ -159,7 +156,6 @@ public class Box /** creates a empty box */ - @SuppressWarnings("serial") public Box() { boxOffset = new int[3]; @@ -248,7 +244,7 @@ public class Box playerPos = MinecraftWrapper.INSTANCE.getPlayer().blockPosition(); for (Direction direction : DIRECTIONS) { - if (direction == Direction.DOWN || direction == Direction.WEST || direction == Direction.NORTH) + if (direction == Direction.DOWN || direction == Direction.WEST || direction == Direction.NORTH) { culling[DIRECTION_INDEX.get(direction)] = playerPos.get(direction.getAxis()) > getFacePos(direction) + cullingDistance; } @@ -304,7 +300,7 @@ public class Box { singleAdjDataPoint = dataPoint[i]; - if(DataPointUtil.isVoid(singleAdjDataPoint) || !DataPointUtil.doesItExist(singleAdjDataPoint)) + if (DataPointUtil.isVoid(singleAdjDataPoint) || !DataPointUtil.doesItExist(singleAdjDataPoint)) break; height = DataPointUtil.getHeight(singleAdjDataPoint); @@ -385,7 +381,7 @@ public class Box } } - if(allAbove) + if (allAbove) { adjHeight.get(direction)[0] = getMaxY(); adjDepth.get(direction)[0] = getMinY(); diff --git a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java index ef5acc98c..7e0a0ed0e 100644 --- a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java @@ -15,15 +15,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.seibel.lod.builders.lodBuilding; -import java.awt.Color; -import java.util.List; -import java.util.Random; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +package com.seibel.lod.builders.lodBuilding; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; @@ -32,26 +25,9 @@ import com.seibel.lod.enums.VerticalQuality; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.LodRegion; import com.seibel.lod.objects.LodWorld; -import com.seibel.lod.util.ColorUtil; -import com.seibel.lod.util.DataPointUtil; -import com.seibel.lod.util.DetailDistanceUtil; -import com.seibel.lod.util.LevelPosUtil; -import com.seibel.lod.util.LodThreadFactory; -import com.seibel.lod.util.LodUtil; -import com.seibel.lod.util.ThreadMapUtil; +import com.seibel.lod.util.*; import com.seibel.lod.wrappers.MinecraftWrapper; - -import net.minecraft.block.AbstractPlantBlock; -import net.minecraft.block.AbstractTopPlantBlock; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.BushBlock; -import net.minecraft.block.FlowerBlock; -import net.minecraft.block.GrassBlock; -import net.minecraft.block.IGrowable; -import net.minecraft.block.LeavesBlock; -import net.minecraft.block.TallGrassBlock; +import net.minecraft.block.*; import net.minecraft.block.material.MaterialColor; import net.minecraft.client.renderer.model.BakedQuad; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -71,6 +47,14 @@ import net.minecraft.world.chunk.IChunk; import net.minecraft.world.gen.Heightmap; import net.minecraftforge.client.model.data.ModelDataMap; +import java.awt.*; +import java.util.List; +import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + /** * This object is in charge of creating Lod related objects. (specifically: Lod * World, Dimension, and Region objects) @@ -81,9 +65,9 @@ import net.minecraftforge.client.model.data.ModelDataMap; */ public class LodBuilder { - private static MinecraftWrapper mc = MinecraftWrapper.INSTANCE; + private static final MinecraftWrapper mc = MinecraftWrapper.INSTANCE; - private ExecutorService lodGenThreadPool = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName())); + private final ExecutorService lodGenThreadPool = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName())); public static final Direction[] directions = new Direction[] { Direction.UP, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.DOWN }; public static final int CHUNK_DATA_WIDTH = LodUtil.CHUNK_WIDTH; @@ -115,19 +99,14 @@ public class LodBuilder public LodBuilder() { - + } - - - - public void generateLodNodeAsync(IChunk chunk, LodWorld lodWorld, IWorld world) { generateLodNodeAsync(chunk, lodWorld, world, DistanceGenerationMode.SERVER); } - public void generateLodNodeAsync(IChunk chunk, LodWorld lodWorld, IWorld world, DistanceGenerationMode generationMode) { if (lodWorld == null || !lodWorld.getIsWorldLoaded()) @@ -245,7 +224,7 @@ public class LodBuilder singleData, false); break; - + case VOXEL: long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.worldHeight, DetailDistanceUtil.getMaxVerticalData(detailLevel)); @@ -366,35 +345,35 @@ public class LodBuilder private short determineBottomPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs, BlockPos.Mutable blockPos) { short depth = DEFAULT_DEPTH; - if (config.useHeightmap) + /*if (config.useHeightmap) { // when using the generated heightmap there is no data about the lowest point - depth = 0; + depth = 0; //DEFAULT_DEPTH == 0 } else + {*/ + boolean voidData = true; + ChunkSection[] chunkSections = chunk.getSections(); + for (int sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--) { - boolean voidData = true; - ChunkSection[] chunkSections = chunk.getSections(); - for (int sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--) + for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--) { - for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--) - { - if (sectionIndex * CHUNK_DATA_WIDTH + yRel > yAbs) - continue; - - blockPos.set(chunk.getPos().getMinBlockX() + xRel, sectionIndex * CHUNK_DATA_WIDTH + yRel, chunk.getPos().getMinBlockZ() + zRel); - if (!isLayerValidLodPoint(chunk, blockPos)) - { - depth = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1); - voidData = false; - break; - } - } + if (sectionIndex * CHUNK_DATA_WIDTH + yRel > yAbs) + continue; - if (!voidData) + blockPos.set(chunk.getPos().getMinBlockX() + xRel, sectionIndex * CHUNK_DATA_WIDTH + yRel, chunk.getPos().getMinBlockZ() + zRel); + if (!isLayerValidLodPoint(chunk, blockPos)) + { + depth = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1); + voidData = false; break; + } } + + if (!voidData) + break; } + //} return depth; } @@ -405,9 +384,7 @@ public class LodBuilder { short height = DEFAULT_HEIGHT; if (config.useHeightmap) - { height = (short) chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel); - } else { boolean voidData = true; @@ -509,30 +486,30 @@ public class LodBuilder { ChunkSection[] chunkSections = chunk.getSections(); short depth = DEFAULT_DEPTH; - if (config.useHeightmap) + /*if (config.useHeightmap) { - depth = 0; + depth = 0; //DEFAULT_DEPTH == 0 } else + {*/ + boolean found = false; + for (int sectionIndex = 0; sectionIndex < chunkSections.length; sectionIndex++) { - boolean found = false; - for (int sectionIndex = 0; sectionIndex < chunkSections.length; sectionIndex++) + for (int yRel = 0; yRel < CHUNK_DATA_WIDTH; yRel++) { - for (int yRel = 0; yRel < CHUNK_DATA_WIDTH; yRel++) + blockPos.set(chunk.getPos().getMinBlockX() + xRel, sectionIndex * CHUNK_DATA_WIDTH + yRel, chunk.getPos().getMinBlockZ() + zRel); + if (isLayerValidLodPoint(chunk, blockPos)) { - blockPos.set(chunk.getPos().getMinBlockX() + xRel, sectionIndex * CHUNK_DATA_WIDTH + yRel, chunk.getPos().getMinBlockZ() + zRel); - if (isLayerValidLodPoint(chunk, blockPos)) - { - depth = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel); - found = true; - break; - } - } - - if (found) + depth = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel); + found = true; break; + } } + + if (found) + break; } + //} return depth; } @@ -544,9 +521,7 @@ public class LodBuilder { short height = DEFAULT_HEIGHT; if (config.useHeightmap) - { height = (short) chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel); - } else { boolean voidData = true; @@ -610,7 +585,7 @@ public class LodBuilder private int getLightValue(IChunk chunk, BlockPos.Mutable blockPos, boolean hasCeiling, boolean hasSkyLight, boolean topBlock) { int skyLight; - int blockLight = 0; + int blockLight; if (mc.getClientWorld() == null) return 0; @@ -627,19 +602,13 @@ public class LodBuilder if (!hasSkyLight && hasCeiling) - { skyLight = 0; - } else if (topBlock) - { skyLight = DEFAULT_MAX_LIGHT; - } else { if (chunk.isLightCorrect()) - { skyLight = world.getBrightness(LightType.SKY, blockPos); - } else { // we don't know what the light here is, @@ -747,10 +716,8 @@ public class LodBuilder if (count == 0) - { // this block is entirely transparent color = 0; - } else { // determine the average color @@ -828,25 +795,17 @@ public class LodBuilder if (toTint.get(blockState.getBlock()).booleanValue()) { if (useLeafTint(blockState.getBlock())) - { // leaves colorInt = ColorUtil.multiplyRGBcolors(biome.getFoliageColor() | 0xFF000000, blockColor); - } else if (useGrassTint(blockState.getBlock())) - { // grass and green plants colorInt = ColorUtil.multiplyRGBcolors(biome.getGrassColor(x, z) | 0xFF000000, blockColor); - } else if (useWaterTint(blockState.getBlock())) - { // water colorInt = ColorUtil.multiplyRGBcolors(biome.getWaterColor() | 0xFF000000, blockColor); - } } else - { colorInt = blockColor; - } return colorInt; } @@ -907,22 +866,23 @@ public class LodBuilder tmp = tmp.darker(); colorInt = LodUtil.colorToInt(tmp); break; - + } return colorInt; } - + public static final ConcurrentMap notFullBlock = new ConcurrentHashMap<>(); public static final ConcurrentMap smallBlock = new ConcurrentHashMap<>(); + /** * Is the block at the given blockPos a valid LOD point? */ private boolean isLayerValidLodPoint(IChunk chunk, BlockPos.Mutable blockPos) { BlockState blockState = chunk.getBlockState(blockPos); - - + + if (blockState != null) { // TODO this code is dead since avoidSmallBlock and onlyUseFullBlock @@ -931,9 +891,9 @@ public class LodBuilder if (avoidSmallBlock || avoidNonFullBlock) { if (!smallBlock.containsKey(blockState.getBlock()) - || smallBlock.get(blockState.getBlock()) == null - || !notFullBlock.containsKey(blockState.getBlock()) - || notFullBlock.get(blockState.getBlock()) == null + || smallBlock.get(blockState.getBlock()) == null + || !notFullBlock.containsKey(blockState.getBlock()) + || notFullBlock.get(blockState.getBlock()) == null ) { VoxelShape voxelShape = blockState.getShape(chunk, blockPos); @@ -942,7 +902,7 @@ public class LodBuilder notFullBlock.put(blockState.getBlock(), false); smallBlock.put(blockState.getBlock(), false); } - + if (!voxelShape.isEmpty()) { AxisAlignedBB bbox = voxelShape.bounds(); @@ -953,34 +913,31 @@ public class LodBuilder notFullBlock.put(blockState.getBlock(), true); else notFullBlock.put(blockState.getBlock(), false); - + if (xWidth < 0.7 && zWidth < 0.7 && yWidth < 0.7) smallBlock.put(blockState.getBlock(), true); else smallBlock.put(blockState.getBlock(), false); - } else + } + else { notFullBlock.put(blockState.getBlock(), false); smallBlock.put(blockState.getBlock(), false); } } - + if (notFullBlock.get(blockState.getBlock()) && avoidNonFullBlock) - { return false; - } if (smallBlock.get(blockState.getBlock()) && avoidSmallBlock) - { return false; - } } - - + + return blockState.getBlock() != Blocks.AIR - && blockState.getBlock() != Blocks.CAVE_AIR - && blockState.getBlock() != Blocks.BARRIER; + && blockState.getBlock() != Blocks.CAVE_AIR + && blockState.getBlock() != Blocks.BARRIER; } - + return false; } } diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java index 18500fe7d..f7311b7f6 100644 --- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java +++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java @@ -15,16 +15,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.seibel.lod.builders.worldGeneration; -import java.util.ConcurrentModificationException; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.function.Supplier; +package com.seibel.lod.builders.worldGeneration; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.seibel.lod.builders.lodBuilding.LodBuilder; @@ -33,9 +25,7 @@ import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.proxy.ClientProxy; -import com.seibel.lod.util.LodThreadFactory; import com.seibel.lod.util.LodUtil; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.util.math.ChunkPos; @@ -48,13 +38,7 @@ import net.minecraft.world.chunk.IChunk; import net.minecraft.world.gen.ChunkGenerator; import net.minecraft.world.gen.Heightmap; import net.minecraft.world.gen.blockstateprovider.WeightedBlockStateProvider; -import net.minecraft.world.gen.feature.BlockClusterFeatureConfig; -import net.minecraft.world.gen.feature.ConfiguredFeature; -import net.minecraft.world.gen.feature.DecoratedFeatureConfig; -import net.minecraft.world.gen.feature.FeatureSpread; -import net.minecraft.world.gen.feature.FeatureSpreadConfig; -import net.minecraft.world.gen.feature.IceAndSnowFeature; -import net.minecraft.world.gen.feature.NoFeatureConfig; +import net.minecraft.world.gen.feature.*; import net.minecraft.world.gen.placement.ConfiguredPlacement; import net.minecraft.world.gen.placement.DecoratedPlacementConfig; import net.minecraft.world.gen.placement.IPlacementConfig; @@ -64,6 +48,15 @@ import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorldLightManager; import net.minecraftforge.common.WorldWorkerManager.IWorker; +import java.util.ConcurrentModificationException; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.function.Supplier; + /** * This is used to generate a LodChunk at a given ChunkPos. * @@ -75,13 +68,13 @@ public class LodNodeGenWorker implements IWorker public static ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new ThreadFactoryBuilder().setNameFormat("Gen-Worker-Thread-%d").build()); private boolean threadStarted = false; - private LodChunkGenThread thread; + private final LodChunkGenThread thread; /** If a configured feature fails for whatever reason, * add it to this list, this is to hopefully remove any * features that could cause issues down the line. */ - private static ConcurrentHashMap> configuredFeaturesToAvoid = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap> configuredFeaturesToAvoid = new ConcurrentHashMap<>(); @@ -101,9 +94,9 @@ public class LodNodeGenWorker implements IWorker if (newServerWorld == null) throw new IllegalArgumentException("LodChunkGenThread requires a non-null ServerWorld"); - - - + + + thread = new LodChunkGenThread(newPos, newGenerationMode, newLodBuilder, newLodDimension, newServerWorld); @@ -149,14 +142,14 @@ public class LodNodeGenWorker implements IWorker - private class LodChunkGenThread implements Runnable + private static class LodChunkGenThread implements Runnable { public final ServerWorld serverWorld; public final LodDimension lodDim; public final DistanceGenerationMode generationMode; public final LodBuilder lodBuilder; - private ChunkPos pos; + private final ChunkPos pos; public LodChunkGenThread(ChunkPos newPos, DistanceGenerationMode newGenerationMode, LodBuilder newLodBuilder, @@ -177,12 +170,12 @@ public class LodNodeGenWorker implements IWorker // only generate LodChunks if they can // be added to the current LodDimension - /**TODO i must disable this if, i will find a way to replace it*/ + /* TODO i must disable this if, i will find a way to replace it */ if (lodDim.regionIsInRange(pos.x / LodUtil.REGION_WIDTH_IN_CHUNKS, pos.z / LodUtil.REGION_WIDTH_IN_CHUNKS)) { // long startTime = System.currentTimeMillis(); - switch(generationMode) + switch (generationMode) { case NONE: // don't generate @@ -217,7 +210,7 @@ public class LodNodeGenWorker implements IWorker */ // shows the pool size, active threads, queued tasks and completed tasks // ClientProxy.LOGGER.info(genThreads.toString()); - + // long endTime = System.currentTimeMillis(); // System.out.println(endTime - startTime); @@ -271,20 +264,20 @@ public class LodNodeGenWorker implements IWorker // add fake heightmap data so our LODs aren't at height 0 Heightmap heightmap = new Heightmap(chunk, LodUtil.DEFAULT_HEIGHTMAP); - for(int x = 0; x < LodUtil.CHUNK_WIDTH && !inTheEnd; x++) + for (int x = 0; x < LodUtil.CHUNK_WIDTH && !inTheEnd; x++) { - for(int z = 0; z < LodUtil.CHUNK_WIDTH && !inTheEnd; z++) + for (int z = 0; z < LodUtil.CHUNK_WIDTH && !inTheEnd; z++) { if (simulateHeight) { // these heights are of course aren't super accurate, // they are just to simulate height data where there isn't any - switch(chunk.getBiomes().getNoiseBiome(x >> 2, seaLevel >> 2, z >> 2).getBiomeCategory()) + switch (chunk.getBiomes().getNoiseBiome(x >> 2, seaLevel >> 2, z >> 2).getBiomeCategory()) { case NETHER: heightmap.setHeight(x, z, serverWorld.getHeight() / 2); break; - + case EXTREME_HILLS: heightmap.setHeight(x, z, seaLevel + 30); break; @@ -300,24 +293,24 @@ public class LodNodeGenWorker implements IWorker case NONE: heightmap.setHeight(x, z, 0); break; - + case OCEAN: case RIVER: heightmap.setHeight(x, z, seaLevel); break; - + case THEEND: inTheEnd = true; break; - - // DESERT - // FOREST - // ICY - // MUSHROOM - // SAVANNA - // SWAMP - // TAIGA - // PLAINS + + // DESERT + // FOREST + // ICY + // MUSHROOM + // SAVANNA + // SWAMP + // TAIGA + // PLAINS default: heightmap.setHeight(x, z, seaLevel + 10); break; @@ -346,8 +339,8 @@ public class LodNodeGenWorker implements IWorker // generates the same and it looks really bad. lodBuilder.generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(true, true, false)); } - - + + // long startTime = System.currentTimeMillis(); // long endTime = System.currentTimeMillis(); // System.out.println(endTime - startTime); @@ -445,9 +438,9 @@ public class LodNodeGenWorker implements IWorker { List>>> featuresForState = biome.generationSettings.features(); - for(int featureStateToGenerate = 0; featureStateToGenerate < featuresForState.size(); featureStateToGenerate++) + for (int featureStateToGenerate = 0; featureStateToGenerate < featuresForState.size(); featureStateToGenerate++) { - for(Supplier> featureSupplier : featuresForState.get(featureStateToGenerate)) + for (Supplier> featureSupplier : featuresForState.get(featureStateToGenerate)) { ConfiguredFeature configuredFeature = featureSupplier.get(); @@ -460,7 +453,7 @@ public class LodNodeGenWorker implements IWorker { configuredFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition()); } - catch(ConcurrentModificationException e) + catch (ConcurrentModificationException e) { // This will happen. I'm not sure what to do about it // except pray that it doesn't effect the normal world generation @@ -480,7 +473,7 @@ public class LodNodeGenWorker implements IWorker configuredFeaturesToAvoid.put(configuredFeature.hashCode(), configuredFeature); // ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount()); } - catch(UnsupportedOperationException e) + catch (UnsupportedOperationException e) { // This will happen when the LodServerWorld // isn't able to return something that a feature @@ -490,7 +483,7 @@ public class LodNodeGenWorker implements IWorker configuredFeaturesToAvoid.put(configuredFeature.hashCode(), configuredFeature); // ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount()); } - catch(Exception e) + catch (Exception e) { // I'm not sure what happened, print to the log @@ -549,12 +542,12 @@ public class LodNodeGenWorker implements IWorker placementConfig = new FeatureSpreadConfig(oldSpread); } - else if(oldConfigClass == DecoratedPlacementConfig.class) + else if (oldConfigClass == DecoratedPlacementConfig.class) { DecoratedPlacementConfig oldPlacementConfig = (DecoratedPlacementConfig) config.decorator.config(); placementConfig = new DecoratedPlacementConfig(oldPlacementConfig.inner(), oldPlacementConfig.outer()); } - else if(oldConfigClass == NoiseDependant.class) + else if (oldConfigClass == NoiseDependant.class) { NoiseDependant oldPlacementConfig = (NoiseDependant) config.decorator.config(); placementConfig = new NoiseDependant(oldPlacementConfig.noiseLevel, oldPlacementConfig.belowNoise, oldPlacementConfig.aboveNoise); @@ -588,9 +581,18 @@ public class LodNodeGenWorker implements IWorker builder.xspread(config.xspread); builder.yspread(config.yspread); builder.zspread(config.zspread); - if(config.canReplace) { builder.canReplace(); } - if(config.needWater) { builder.needWater(); } - if(config.project) { builder.noProjection(); } + if (config.canReplace) + { + builder.canReplace(); + } + if (config.needWater) + { + builder.needWater(); + } + if (config.project) + { + builder.noProjection(); + } builder.tries(config.tries); diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index fc737b036..dd5f9cdc7 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -15,37 +15,27 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.seibel.lod.handlers; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import com.seibel.lod.enums.DistanceGenerationMode; +import com.seibel.lod.enums.VerticalQuality; +import com.seibel.lod.objects.*; +import com.seibel.lod.proxy.ClientProxy; +import com.seibel.lod.util.LodThreadFactory; +import com.seibel.lod.util.LodUtil; + +import java.io.*; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.enums.VerticalQuality; -import com.seibel.lod.objects.LodDimension; -import com.seibel.lod.objects.LodRegion; -import com.seibel.lod.objects.RegionPos; -import com.seibel.lod.objects.SingleLevelContainer; -import com.seibel.lod.objects.VerticalLevelContainer; -import com.seibel.lod.proxy.ClientProxy; -import com.seibel.lod.util.LodThreadFactory; -import com.seibel.lod.util.LodUtil; - /** * This object handles creating LodRegions * from files and saving LodRegion objects * to file. - * + * * @author James Seibel * @author Cola * @version 9-25-2021 @@ -230,7 +220,7 @@ public class LodDimensionFileHandler fileWritingThreadPool.execute(saveDirtyRegionsThread); } - private Thread saveDirtyRegionsThread = new Thread(() -> + private final Thread saveDirtyRegionsThread = new Thread(() -> { try { @@ -238,9 +228,9 @@ public class LodDimensionFileHandler { for (int j = 0; j < lodDimension.getWidth(); j++) { - if (lodDimension.GetIsRegionDirty(i,j) && lodDimension.getRegionByArrayIndex(i,j) != null) + if (lodDimension.GetIsRegionDirty(i, j) && lodDimension.getRegionByArrayIndex(i, j) != null) { - saveRegionToFile(lodDimension.getRegionByArrayIndex(i,j)); + saveRegionToFile(lodDimension.getRegionByArrayIndex(i, j)); lodDimension.SetIsRegionDirty(i, j, false); } } @@ -311,7 +301,7 @@ public class LodDimensionFileHandler // don't write anything, we don't want to accidently // delete anything the user may want. return; - } + } // if we got this far then we are good // to overwrite the old file diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index 8462a1ac6..c98add558 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -15,12 +15,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.seibel.lod.objects; -import java.io.File; -import java.io.IOException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +package com.seibel.lod.objects; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; @@ -28,27 +24,27 @@ import com.seibel.lod.enums.GenerationPriority; import com.seibel.lod.enums.LodTemplate; import com.seibel.lod.enums.VerticalQuality; import com.seibel.lod.handlers.LodDimensionFileHandler; -import com.seibel.lod.util.DataPointUtil; -import com.seibel.lod.util.DetailDistanceUtil; -import com.seibel.lod.util.LevelPosUtil; -import com.seibel.lod.util.LodThreadFactory; -import com.seibel.lod.util.LodUtil; +import com.seibel.lod.util.*; import com.seibel.lod.wrappers.MinecraftWrapper; - import net.minecraft.util.math.ChunkPos; import net.minecraft.world.DimensionType; import net.minecraft.world.server.ServerChunkProvider; import net.minecraft.world.server.ServerWorld; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + /** * This object holds all loaded LOD regions * for a given dimension.

- * + * * Coordinate Standard:
* Coordinate called posX or posZ are relative LevelPos coordinates
* unless stated otherwise.
- * + * * @author Leonardo Amato * @author James Seibel * @version 9-27-2021 @@ -82,13 +78,13 @@ public class LodDimension private LodDimensionFileHandler fileHandler; - private volatile RegionPos center; + private final RegionPos center; /** prevents the cutAndExpandThread from expanding at the same location multiple times */ private volatile ChunkPos lastExpandedChunk; /** prevents the cutAndExpandThread from cutting at the same location multiple times */ private volatile ChunkPos lastCutChunk; - private ExecutorService cutAndExpandThread = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " - Cut and Expand")); + private final ExecutorService cutAndExpandThread = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " - Cut and Expand")); /** * Creates the dimension centered at (0,0) @@ -584,8 +580,8 @@ public class LodDimension z += dz; } break; - - + + case FAR_FIRST: posToGenerate = new PosToGenerateContainer((byte) 8, maxDataToGenerate, playerBlockPosX, playerBlockPosZ); @@ -618,11 +614,11 @@ public class LodDimension /** * Returns every node that should be rendered based on the position of the player. - * + * * TODO why isn't posToRender returned? it would make it a bit more clear what is happening */ public void getPosToRender(PosToRenderContainer posToRender, RegionPos regionPos, int playerPosX, - int playerPosZ) + int playerPosZ) { LodRegion region = getRegion(regionPos.x, regionPos.z); if (region != null) @@ -709,7 +705,7 @@ public class LodDimension /** * TODO we aren't currently using this, is there a reason for that? * is this significantly different than regenRegionBuffer? - * + * * Returns if the buffer at the given array index needs * to have its buffer resized. */ @@ -762,7 +758,7 @@ public class LodDimension * Loads the region at the given RegionPos from file, * if a file exists for that region. */ - public LodRegion getRegionFromFile(RegionPos regionPos, byte detailLevel, + public LodRegion getRegionFromFile(RegionPos regionPos, byte detailLevel, DistanceGenerationMode generationMode, VerticalQuality verticalQuality) { if (fileHandler != null) @@ -901,17 +897,17 @@ public class LodDimension int levelToGen = DetailDistanceUtil.getLodDrawDetail(detail); int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - levelToGen); int maxVerticalData = DetailDistanceUtil.getMaxVerticalData(detail); - long memoryUse = LodUtil.regionRenderingMemoryUse(x,z,template); + long memoryUse = LodUtil.regionRenderingMemoryUse(x, z, template); //System.out.println(detail + " " + memoryUse + " " + template.getBufferMemoryForSingleLod(maxVerticalData)); return memoryUse; //return memoryUse; } - - public boolean GetIsRegionDirty(int i , int j) + + public boolean GetIsRegionDirty(int i, int j) { return isRegionDirty[i][j]; } - + public void SetIsRegionDirty(int i, int j, boolean val) { isRegionDirty[i][j] = val; diff --git a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java index 564e33360..69b02698d 100644 --- a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java +++ b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java @@ -13,7 +13,7 @@ import java.util.concurrent.ConcurrentMap; * Holds data used by specific threads so * the data doesn't have to be recreated every * time it is needed. - * + * * @author Leonardo Amato * @version 9-25-2021 */ @@ -28,72 +28,74 @@ public class ThreadMapUtil public static final ConcurrentMap heightAndDepthMap = new ConcurrentHashMap<>(); public static final ConcurrentMap singleDataToMergeMap = new ConcurrentHashMap<>(); public static final ConcurrentMap verticalUpdate = new ConcurrentHashMap<>(); - - + + //________________________// // used in BufferBuilder // //________________________// - + public static final ConcurrentMap adjShadeDisabled = new ConcurrentHashMap<>(); - public static final ConcurrentMap> adjDataMap = new ConcurrentHashMap<>(); + public static final ConcurrentMap> adjDataMap = new ConcurrentHashMap<>(); public static final ConcurrentMap boxMap = new ConcurrentHashMap<>(); - + /** returns the array NOT cleared every time * @return*/ public static boolean[] getAdjShadeDisabledArray() { if (!adjShadeDisabled.containsKey(Thread.currentThread().getName()) - || (adjShadeDisabled.get(Thread.currentThread().getName()) == null)) + || (adjShadeDisabled.get(Thread.currentThread().getName()) == null)) { adjShadeDisabled.put(Thread.currentThread().getName(), new boolean[Box.DIRECTIONS.length]); } Arrays.fill(adjShadeDisabled.get(Thread.currentThread().getName()), false); return adjShadeDisabled.get(Thread.currentThread().getName()); } - + /** returns the array NOT cleared every time */ - public static Map getAdjDataArray(int verticalData) + public static Map getAdjDataArray(int verticalData) { if (!adjDataMap.containsKey(Thread.currentThread().getName()) - || (adjDataMap.get(Thread.currentThread().getName()) == null) - || (adjDataMap.get(Thread.currentThread().getName()).get(Direction.UP) == null) - || (adjDataMap.get(Thread.currentThread().getName()).get(Direction.UP).length != verticalData)) + || (adjDataMap.get(Thread.currentThread().getName()) == null) + || (adjDataMap.get(Thread.currentThread().getName()).get(Direction.UP) == null) + || (adjDataMap.get(Thread.currentThread().getName()).get(Direction.UP).length != verticalData)) { adjDataMap.put(Thread.currentThread().getName(), new HashMap()); for (Direction direction : Box.ADJ_DIRECTIONS) adjDataMap.get(Thread.currentThread().getName()).put(direction, new long[verticalData]); - }else{ - + } + else + { + for (Direction direction : Box.ADJ_DIRECTIONS) - Arrays.fill(adjDataMap.get(Thread.currentThread().getName()).get(direction),DataPointUtil.EMPTY_DATA); + Arrays.fill(adjDataMap.get(Thread.currentThread().getName()).get(direction), DataPointUtil.EMPTY_DATA); } return adjDataMap.get(Thread.currentThread().getName()); } - + public static Box getBox() { if (!boxMap.containsKey(Thread.currentThread().getName()) - || (boxMap.get(Thread.currentThread().getName()) == null)) + || (boxMap.get(Thread.currentThread().getName()) == null)) { boxMap.put(Thread.currentThread().getName(), new Box()); } boxMap.get(Thread.currentThread().getName()).reset(); return boxMap.get(Thread.currentThread().getName()); } - + //________________________// // used in DataPointUtil // // mergeVerticalData // //________________________// - - + + //________________________// // used in DataPointUtil // // mergeSingleData // //________________________// - - - + + + /** returns the array NOT cleared every time */ public static long[] getSingleUpdateArray() { From 1ed36ba6c42d6aa9b77668c35f9774242a43f521 Mon Sep 17 00:00:00 2001 From: cola98765 Date: Thu, 7 Oct 2021 11:07:10 +0200 Subject: [PATCH 09/14] resolved some more warnings and applied autoformat in affected files --- .../lodTemplates/AbstractLodTemplate.java | 6 +++--- .../lodTemplates/CubicLodTemplate.java | 20 +++++++++---------- .../lodTemplates/DynamicLodTemplate.java | 10 +++++----- .../lodTemplates/TriangularLodTemplate.java | 10 +++++----- .../lod/builders/lodBuilding/LodBuilder.java | 4 ++-- .../lodBuilding/LodBuilderConfig.java | 13 ++++++------ .../worldGeneration/LodNodeGenWorker.java | 2 +- .../worldGeneration/LodWorldGenerator.java | 2 +- 8 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/AbstractLodTemplate.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/AbstractLodTemplate.java index 769a00235..42ab5583e 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/AbstractLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/AbstractLodTemplate.java @@ -15,18 +15,18 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.seibel.lod.builders.bufferBuilding.lodTemplates; -import java.util.Map; +package com.seibel.lod.builders.bufferBuilding.lodTemplates; import com.seibel.lod.enums.DebugMode; import com.seibel.lod.util.ColorUtil; - import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.texture.NativeImage; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; +import java.util.Map; + /** * This is the abstract class used to create different * BufferBuilders. diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java index 52f6f7bd2..153f71cea 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/CubicLodTemplate.java @@ -15,19 +15,19 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.seibel.lod.builders.bufferBuilding.lodTemplates; -import java.util.Map; +package com.seibel.lod.builders.bufferBuilding.lodTemplates; import com.seibel.lod.enums.DebugMode; import com.seibel.lod.util.DataPointUtil; import com.seibel.lod.util.LodUtil; - import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.texture.NativeImage; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; +import java.util.Map; + /** * Builds LODs as rectangular prisms. * @@ -39,7 +39,7 @@ public class CubicLodTemplate extends AbstractLodTemplate public CubicLodTemplate() { - + } @Override @@ -73,11 +73,11 @@ public class CubicLodTemplate extends AbstractLodTemplate addBoundingBoxToBuffer(buffer, box); } - private void generateBoundingBox(Box box, - int height, int depth, int width, - double xOffset, double yOffset, double zOffset, - BlockPos bufferCenterBlockPos, - Map adjData, + private void generateBoundingBox(Box box, + int height, int depth, int width, + double xOffset, double yOffset, double zOffset, + BlockPos bufferCenterBlockPos, + Map adjData, int color, boolean[] adjShadeDisabled) { @@ -130,7 +130,7 @@ public class CubicLodTemplate extends AbstractLodTemplate public int getBufferMemoryForSingleNode(int maxVerticalData) { // TODO, what do these magic numbers mean - return 2 * 4 * (3 + 4) + 4 * 4 * Math.max((maxVerticalData+1)/2,1) * (3 + 4); + return 2 * 4 * (3 + 4) + 4 * 4 * Math.max((maxVerticalData + 1) / 2, 1) * (3 + 4); } } diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/DynamicLodTemplate.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/DynamicLodTemplate.java index 399a7a87f..0713d9fae 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/DynamicLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/DynamicLodTemplate.java @@ -15,18 +15,18 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.seibel.lod.builders.bufferBuilding.lodTemplates; -import java.util.Map; +package com.seibel.lod.builders.bufferBuilding.lodTemplates; import com.seibel.lod.enums.DebugMode; import com.seibel.lod.proxy.ClientProxy; - import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.texture.NativeImage; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; +import java.util.Map; + /** * TODO DynamicLodTemplate * Chunks smoothly transition between @@ -40,11 +40,11 @@ public class DynamicLodTemplate extends AbstractLodTemplate { @Override public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, Map adjData, - byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, NativeImage lightMap, boolean[] adjShadeDisabled) + byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, NativeImage lightMap, boolean[] adjShadeDisabled) { ClientProxy.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!"); } - + @Override public int getBufferMemoryForSingleNode(int maxVerticalData) { diff --git a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/TriangularLodTemplate.java b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/TriangularLodTemplate.java index 874339aa0..7fa70cf61 100644 --- a/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/TriangularLodTemplate.java +++ b/src/main/java/com/seibel/lod/builders/bufferBuilding/lodTemplates/TriangularLodTemplate.java @@ -15,18 +15,18 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.seibel.lod.builders.bufferBuilding.lodTemplates; -import java.util.Map; +package com.seibel.lod.builders.bufferBuilding.lodTemplates; import com.seibel.lod.enums.DebugMode; import com.seibel.lod.proxy.ClientProxy; - import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.texture.NativeImage; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; +import java.util.Map; + /** * TODO #21 TriangularLodTemplate * Builds each LOD chunk as a singular rectangular prism. @@ -38,11 +38,11 @@ public class TriangularLodTemplate extends AbstractLodTemplate { @Override public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, Map adjData, - byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, NativeImage lightMap, boolean[] adjShadeDisabled) + byte detailLevel, int posX, int posZ, Box box, DebugMode debugging, NativeImage lightMap, boolean[] adjShadeDisabled) { ClientProxy.LOGGER.error(DynamicLodTemplate.class.getSimpleName() + " is not implemented!"); } - + @Override public int getBufferMemoryForSingleNode(int maxVerticalData) { diff --git a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java index 7e0a0ed0e..5502462a4 100644 --- a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java @@ -729,7 +729,7 @@ public class LodBuilder } // determine if this block should use the biome color tint - if (block instanceof TallGrassBlock || (useGrassTint(block) || useLeafTint(block) || useWaterTint(block)) && numberOfGreyPixel / count > 0.75f) + if (block instanceof TallGrassBlock || (useGrassTint(block) || useLeafTint(block) || useWaterTint(block)) && (float) numberOfGreyPixel / count > 0.75f) toTint.replace(block, true); // add the newly generated block color to the map for later use @@ -792,7 +792,7 @@ public class LodBuilder } blockColor = getColorTextureForBlock(blockState, blockPos, true); - if (toTint.get(blockState.getBlock()).booleanValue()) + if (toTint.get(blockState.getBlock())) { if (useLeafTint(blockState.getBlock())) // leaves diff --git a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilderConfig.java b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilderConfig.java index 679779d6e..32d099eda 100644 --- a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilderConfig.java +++ b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilderConfig.java @@ -15,6 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.seibel.lod.builders.lodBuilding; import com.seibel.lod.enums.DistanceGenerationMode; @@ -38,7 +39,7 @@ public class LodBuilderConfig public boolean useSolidBlocksInColorGen; /** default: server */ public DistanceGenerationMode distanceGenerationMode; - + /** * default settings for a normal chunk
* useHeightmap = false
@@ -53,7 +54,7 @@ public class LodBuilderConfig useSolidBlocksInColorGen = true; distanceGenerationMode = DistanceGenerationMode.SERVER; } - + /** * @param newUseHeightmap default = false * @param newUseBiomeColors default = false @@ -61,14 +62,14 @@ public class LodBuilderConfig * @param newDistanceGenerationMode default = Server */ public LodBuilderConfig(boolean newUseHeightmap, boolean newUseBiomeColors, - boolean newUseSolidBlocksInBiomeColor, DistanceGenerationMode newDistanceGenerationMode) + boolean newUseSolidBlocksInBiomeColor, DistanceGenerationMode newDistanceGenerationMode) { useHeightmap = newUseHeightmap; useBiomeColors = newUseBiomeColors; useSolidBlocksInColorGen = newUseSolidBlocksInBiomeColor; distanceGenerationMode = newDistanceGenerationMode; } - + /** * @param newUseHeightmap default = false * @param newUseBiomeColors default = false @@ -81,9 +82,9 @@ public class LodBuilderConfig useHeightmap = newUseHeightmap; useBiomeColors = newUseBiomeColors; useSolidBlocksInColorGen = newUseSolidBlocksInBiomeColor; - distanceGenerationMode = newUseHeightmap? DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT : DistanceGenerationMode.BIOME_ONLY; + distanceGenerationMode = newUseHeightmap ? DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT : DistanceGenerationMode.BIOME_ONLY; } - + /** * @param newUseHeightmap default = false * @param newUseBiomeColors default = false diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java index f7311b7f6..1678bc50d 100644 --- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java +++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java @@ -531,7 +531,7 @@ public class LodNodeGenWorker implements IWorker @SuppressWarnings({ "rawtypes", "unchecked", "unused" }) private DecoratedFeatureConfig cloneDecoratedFeatureConfig(DecoratedFeatureConfig config) { - IPlacementConfig placementConfig = null; + IPlacementConfig placementConfig; Class oldConfigClass = config.decorator.config().getClass(); diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java index 062114b1c..1d2242354 100644 --- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java +++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java @@ -33,7 +33,7 @@ public class LodWorldGenerator public MinecraftWrapper mc = MinecraftWrapper.INSTANCE; /** This holds the thread used to generate new LODs off the main thread. */ - private ExecutorService mainGenThread = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " world generator")); + private final ExecutorService mainGenThread = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName() + " world generator")); /** we only want to queue up one generator thread at a time */ private boolean generatorThreadRunning = false; From 028aed53f8735638bcb551a9e315013dd3a1c130 Mon Sep 17 00:00:00 2001 From: cola98765 Date: Thu, 7 Oct 2021 11:17:02 +0200 Subject: [PATCH 10/14] resolved some more warnings and applied autoformat in affected files --- .../lod/handlers/LodDimensionFileHandler.java | 2 +- .../lod/handlers/ReflectionHandler.java | 15 +++++----- .../seibel/lod/objects/LevelContainer.java | 29 +++++++++---------- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index dd5f9cdc7..480145d72 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -74,7 +74,7 @@ public class LodDimensionFileHandler * Allow saving asynchronously, but never try to save multiple regions * at a time */ - private ExecutorService fileWritingThreadPool = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName())); + private final ExecutorService fileWritingThreadPool = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName())); diff --git a/src/main/java/com/seibel/lod/handlers/ReflectionHandler.java b/src/main/java/com/seibel/lod/handlers/ReflectionHandler.java index cf61c965a..a6f54899e 100644 --- a/src/main/java/com/seibel/lod/handlers/ReflectionHandler.java +++ b/src/main/java/com/seibel/lod/handlers/ReflectionHandler.java @@ -15,15 +15,16 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.seibel.lod.handlers; -import java.lang.reflect.Field; -import java.lang.reflect.Method; +package com.seibel.lod.handlers; import com.seibel.lod.enums.FogQuality; import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.wrappers.MinecraftWrapper; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + /** * This object is used to get variables from methods * where they are private. Specifically the fog setting @@ -35,7 +36,7 @@ import com.seibel.lod.wrappers.MinecraftWrapper; public class ReflectionHandler { public static final ReflectionHandler INSTANCE = new ReflectionHandler(); - private MinecraftWrapper mc = MinecraftWrapper.INSTANCE; + private final MinecraftWrapper mc = MinecraftWrapper.INSTANCE; public Field ofFogField = null; public Method vertexBufferUploadMethod = null; @@ -106,9 +107,9 @@ public class ReflectionHandler // optifine's "default" option, // it should never be called in this case return FogQuality.FAST; - - - // normal options + + + // normal options case 1: return FogQuality.FAST; case 2: diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index 763e6f1cd..4eb1f048f 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -2,9 +2,6 @@ package com.seibel.lod.objects; public interface LevelContainer { - public static final char VERTICAL_DATA_DELIMITER = '\t'; - public static final char DATA_DELIMITER = ' '; - /**With this you can add data to the level container * * @param data actual data to add in a array of long format. @@ -13,7 +10,7 @@ public interface LevelContainer * @param index z position in the detail level * @return true if correctly added, false otherwise */ - public boolean addData(long data, int posX, int posZ, int index); + boolean addData(long data, int posX, int posZ, int index); /**With this you can add data to the level container * @@ -22,7 +19,7 @@ public interface LevelContainer * @param posZ z position in the detail level * @return true if correctly added, false otherwise */ - public boolean addSingleData(long data, int posX, int posZ); + boolean addSingleData(long data, int posX, int posZ); /**With this you can get data from the level container * @@ -30,7 +27,7 @@ public interface LevelContainer * @param posZ z position in the detail level * @return the data in long array format */ - public long getData(int posX, int posZ, int index); + long getData(int posX, int posZ, int index); /**With this you can get data from the level container * @@ -38,31 +35,31 @@ public interface LevelContainer * @param posZ z position in the detail level * @return the data in long array format */ - public long getSingleData(int posX, int posZ); + long getSingleData(int posX, int posZ); /** * @param posX x position in the detail level * @param posZ z position in the detail level * @return true only if the data exist */ - public boolean doesItExist(int posX, int posZ); + boolean doesItExist(int posX, int posZ); /** * @return return the deatilLevel of this level container */ - public byte getDetailLevel(); + byte getDetailLevel(); - public int getMaxVerticalData(); + int getMaxVerticalData(); /** Clears the dataPoint at the given array index */ - public void clear(int posX, int posZ); + void clear(int posX, int posZ); /**This return a level container with detail level lower than the current level. * The new level container may use information of this level. * @return the new level container */ - public LevelContainer expand(); + LevelContainer expand(); /** * @@ -70,24 +67,24 @@ public interface LevelContainer * @param posX x position in the detail level to update * @param posZ z position in the detail level to update */ - public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ); + void updateData(LevelContainer lowerLevelContainer, int posX, int posZ); /** * This will give the data to save in the file * @return data as a String */ - public byte[] toDataString(); + byte[] toDataString(); /** * This will give the data to save in the file * @return data as a String */ - public int getMaxNumberOfLods(); + int getMaxNumberOfLods(); /** * This will give the data to save in the file * @return data as a String */ - public int getMaxMemoryUse(); + int getMaxMemoryUse(); } From 78ab4b8598c00a37881cc827680fa1483392ca0f Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 7 Oct 2021 17:20:39 +0200 Subject: [PATCH 11/14] Changed configs --- .../lod/builders/lodBuilding/LodBuilder.java | 80 ++-- .../java/com/seibel/lod/config/LodConfig.java | 432 ++++++++---------- .../seibel/lod/enums/BufferRebuildTimes.java | 49 ++ .../com/seibel/lod/enums/VerticalQuality.java | 54 ++- .../lod/handlers/LodDimensionFileHandler.java | 11 +- .../com/seibel/lod/objects/LodDimension.java | 2 +- .../com/seibel/lod/objects/LodRegion.java | 16 +- .../com/seibel/lod/render/LodRenderer.java | 6 +- .../seibel/lod/util/DetailDistanceUtil.java | 20 +- 9 files changed, 341 insertions(+), 329 deletions(-) create mode 100644 src/main/java/com/seibel/lod/enums/BufferRebuildTimes.java diff --git a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java index 5502462a4..e6d9b1e59 100644 --- a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java @@ -191,7 +191,7 @@ public class LodBuilder // determine how many LODs to generate vertically - VerticalQuality verticalQuality = LodConfig.CLIENT.worldGenerator.lodQualityMode.get(); + VerticalQuality verticalQuality = LodConfig.CLIENT.worldGenerator.verticalQuality.get(); byte detailLevel = detail.detailLevel; @@ -210,43 +210,25 @@ public class LodBuilder long[] data; - switch (verticalQuality) - { - default: - case HEIGHTMAP: - long singleData; - long[] dataToMergeSingle = createSingleDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); - singleData = DataPointUtil.mergeSingleData(dataToMergeSingle); - lodDim.addData(detailLevel, - posX, - posZ, - 0, - singleData, - false); - break; + long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); + data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.worldHeight, DetailDistanceUtil.getMaxVerticalData(detailLevel)); - case VOXEL: - long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); - data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.worldHeight, DetailDistanceUtil.getMaxVerticalData(detailLevel)); - - - //lodDim.clear(detailLevel, posX, posZ); - if (data != null && data.length != 0) + + //lodDim.clear(detailLevel, posX, posZ); + if (data != null && data.length != 0) + { + for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ); verticalIndex++) { - for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ); verticalIndex++) - { - - if (!DataPointUtil.doesItExist(data[verticalIndex])) - break; - lodDim.addData(detailLevel, - posX, - posZ, - verticalIndex, - data[verticalIndex], - false); - } + + if (!DataPointUtil.doesItExist(data[verticalIndex])) + break; + lodDim.addData(detailLevel, + posX, + posZ, + verticalIndex, + data[verticalIndex], + false); } - break; } } lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z); @@ -742,19 +724,19 @@ public class LodBuilder private boolean useGrassTint(Block block) { return block instanceof GrassBlock - || block instanceof BushBlock - || block instanceof IGrowable - || block instanceof AbstractPlantBlock - || block instanceof AbstractTopPlantBlock - || block instanceof TallGrassBlock; + || block instanceof BushBlock + || block instanceof IGrowable + || block instanceof AbstractPlantBlock + || block instanceof AbstractTopPlantBlock + || block instanceof TallGrassBlock; } /** determine if the given block should use the biome's foliage color */ private boolean useLeafTint(Block block) { return block instanceof LeavesBlock - || block == Blocks.VINE - || block == Blocks.SUGAR_CANE; + || block == Blocks.VINE + || block == Blocks.SUGAR_CANE; } /** determine if the given block should use the biome's water color */ @@ -783,8 +765,8 @@ public class LodBuilder // block special cases // TODO: this needs to be replaced by a config file of some sort if (blockState == Blocks.AIR.defaultBlockState() - || blockState == Blocks.CAVE_AIR.defaultBlockState() - || blockState == Blocks.BARRIER.defaultBlockState()) + || blockState == Blocks.CAVE_AIR.defaultBlockState() + || blockState == Blocks.BARRIER.defaultBlockState()) { Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z)); tmp = tmp.darker(); @@ -891,9 +873,9 @@ public class LodBuilder if (avoidSmallBlock || avoidNonFullBlock) { if (!smallBlock.containsKey(blockState.getBlock()) - || smallBlock.get(blockState.getBlock()) == null - || !notFullBlock.containsKey(blockState.getBlock()) - || notFullBlock.get(blockState.getBlock()) == null + || smallBlock.get(blockState.getBlock()) == null + || !notFullBlock.containsKey(blockState.getBlock()) + || notFullBlock.get(blockState.getBlock()) == null ) { VoxelShape voxelShape = blockState.getShape(chunk, blockPos); @@ -934,8 +916,8 @@ public class LodBuilder return blockState.getBlock() != Blocks.AIR - && blockState.getBlock() != Blocks.CAVE_AIR - && blockState.getBlock() != Blocks.BARRIER; + && blockState.getBlock() != Blocks.CAVE_AIR + && blockState.getBlock() != Blocks.BARRIER; } return false; diff --git a/src/main/java/com/seibel/lod/config/LodConfig.java b/src/main/java/com/seibel/lod/config/LodConfig.java index 0962838c0..1438fd215 100644 --- a/src/main/java/com/seibel/lod/config/LodConfig.java +++ b/src/main/java/com/seibel/lod/config/LodConfig.java @@ -15,28 +15,19 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.seibel.lod.config; import java.nio.file.Path; import java.nio.file.Paths; +import com.seibel.lod.enums.*; import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import com.electronwill.nightconfig.core.file.CommentedFileConfig; import com.electronwill.nightconfig.core.io.WritingMode; import com.seibel.lod.ModInfo; -import com.seibel.lod.enums.DebugMode; -import com.seibel.lod.enums.DetailDropOff; -import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.enums.FogDistance; -import com.seibel.lod.enums.FogDrawOverride; -import com.seibel.lod.enums.GenerationPriority; -import com.seibel.lod.enums.HorizontalQuality; -import com.seibel.lod.enums.HorizontalResolution; -import com.seibel.lod.enums.HorizontalScale; -import com.seibel.lod.enums.LodTemplate; -import com.seibel.lod.enums.VerticalQuality; import com.seibel.lod.render.LodRenderer.FovTest; import net.minecraftforge.common.ForgeConfigSpec; @@ -81,8 +72,6 @@ public class LodConfig public static class Graphics { - public ForgeConfigSpec.BooleanValue drawLods; - public ForgeConfigSpec.EnumValue fogDistance; public ForgeConfigSpec.EnumValue fogDrawOverride; @@ -90,9 +79,6 @@ public class LodConfig public ForgeConfigSpec.EnumValue drawResolution; -// public ForgeConfigSpec.EnumValue shadingMode; - - public ForgeConfigSpec.EnumValue detailDropOff; public ForgeConfigSpec.IntValue lodChunkRenderDistance; @@ -101,6 +87,8 @@ public class LodConfig public ForgeConfigSpec.BooleanValue alwaysDrawAtMaxQuality; + public ForgeConfigSpec.BooleanValue drawLods; + public ForgeConfigSpec.EnumValue useFovSetting; @@ -109,80 +97,80 @@ public class LodConfig builder.comment("These settings control how the LODs look.").push(this.getClass().getSimpleName()); drawLods = builder - .comment("\n\n" - + " If true, the mod is enabled and LODs will be drawn. \n" - + " If false, the mod will still generate LODs, \n" - + " but they won't be rendered. \n") - .define("drawLODs", true); + .comment("\n\n" + + " If true, the mod is enabled and LODs will be drawn. \n" + + " If false, the mod will still generate LODs, \n" + + " but they won't be rendered. \n") + .define("drawLODs", true); fogDistance = builder - .comment("\n\n" - + " At what distance should Fog be drawn on the LODs? \n" - + " If the fog cuts off ubruptly or you are using Optifine's \"fast\" fog option \n" - + " set this to " + FogDistance.NEAR + " or " + FogDistance.FAR + ". \n") - .defineEnum("fogDistance", FogDistance.NEAR_AND_FAR); + .comment("\n\n" + + " At what distance should Fog be drawn on the LODs? \n" + + " If the fog cuts off ubruptly or you are using Optifine's \"fast\" fog option \n" + + " set this to " + FogDistance.NEAR + " or " + FogDistance.FAR + ". \n") + .defineEnum("fogDistance", FogDistance.NEAR_AND_FAR); fogDrawOverride = builder - .comment("\n\n" - + " When should fog be drawn? \n" - + " " + FogDrawOverride.USE_OPTIFINE_FOG_SETTING + ": Use whatever Fog setting Optifine is using. If Optifine isn't installed this defaults to " + FogDrawOverride.ALWAYS_DRAW_FOG_FANCY + ". \n" - + " " + FogDrawOverride.NEVER_DRAW_FOG + ": Never draw fog on the LODs \n" - + " " + FogDrawOverride.ALWAYS_DRAW_FOG_FAST + ": Always draw fast fog on the LODs \n" - + " " + FogDrawOverride.ALWAYS_DRAW_FOG_FANCY + ": Always draw fancy fog on the LODs (if your graphics card supports it) \n") - .defineEnum("fogDrawOverride", FogDrawOverride.ALWAYS_DRAW_FOG_FANCY); + .comment("\n\n" + + " When should fog be drawn? \n" + + " " + FogDrawOverride.USE_OPTIFINE_FOG_SETTING + ": Use whatever Fog setting Optifine is using. If Optifine isn't installed this defaults to " + FogDrawOverride.ALWAYS_DRAW_FOG_FANCY + ". \n" + + " " + FogDrawOverride.NEVER_DRAW_FOG + ": Never draw fog on the LODs \n" + + " " + FogDrawOverride.ALWAYS_DRAW_FOG_FAST + ": Always draw fast fog on the LODs \n" + + " " + FogDrawOverride.ALWAYS_DRAW_FOG_FANCY + ": Always draw fancy fog on the LODs (if your graphics card supports it) \n") + .defineEnum("fogDrawOverride", FogDrawOverride.ALWAYS_DRAW_FOG_FANCY); lodTemplate = builder - .comment("\n\n" - + " How should the LODs be drawn? \n" - + " NOTE: Currently only " + LodTemplate.CUBIC + " is implemented! \n" - + " \n" - + " " + LodTemplate.CUBIC + ": LOD Chunks are drawn as rectangular prisms (boxes). \n" - + " " + LodTemplate.TRIANGULAR + ": LOD Chunks smoothly transition between other. \n" - + " " + LodTemplate.DYNAMIC + ": LOD Chunks smoothly transition between other, \n" - + " " + " unless a neighboring chunk is at a significantly different height. \n") - .defineEnum("lodTemplate", LodTemplate.CUBIC); + .comment("\n\n" + + " How should the LODs be drawn? \n" + + " NOTE: Currently only " + LodTemplate.CUBIC + " is implemented! \n" + + " \n" + + " " + LodTemplate.CUBIC + ": LOD Chunks are drawn as rectangular prisms (boxes). \n" + + " " + LodTemplate.TRIANGULAR + ": LOD Chunks smoothly transition between other. \n" + + " " + LodTemplate.DYNAMIC + ": LOD Chunks smoothly transition between other, \n" + + " " + " unless a neighboring chunk is at a significantly different height. \n") + .defineEnum("lodTemplate", LodTemplate.CUBIC); detailDropOff = builder - .comment("\n\n" - + " How smooth should the detail transition for LODs be? \n" - + DetailDropOff.FANCY + ": quality is determined per-block (best quality option, may cause stuttering when moving)\n" - + DetailDropOff.FAST + ": quality is determined per-region (performance option)\n") - .defineEnum("detailDropOff", DetailDropOff.FANCY); + .comment("\n\n" + + " How smooth should the detail transition for LODs be? \n" + + DetailDropOff.FANCY + ": quality is determined per-block (best quality option, may cause stuttering when moving)\n" + + DetailDropOff.FAST + ": quality is determined per-region (performance option)\n") + .defineEnum("detailDropOff", DetailDropOff.FANCY); drawResolution = builder - .comment("\n\n" - + " What is the maximum detail LODs should be drawn at? \n" - + " " + HorizontalResolution.CHUNK + ": render 1 LOD for each Chunk. \n" - + " " + HorizontalResolution.HALF_CHUNK + ": render 4 LODs for each Chunk. \n" - + " " + HorizontalResolution.FOUR_BLOCKS + ": render 16 LODs for each Chunk. \n" - + " " + HorizontalResolution.TWO_BLOCKS + ": render 64 LODs for each Chunk. \n" - + " " + HorizontalResolution.BLOCK + ": render 256 LODs for each Chunk. \n") - .defineEnum("Draw resolution", HorizontalResolution.BLOCK); + .comment("\n\n" + + " What is the maximum detail LODs should be drawn at? \n" + + " " + HorizontalResolution.CHUNK + ": render 1 LOD for each Chunk. \n" + + " " + HorizontalResolution.HALF_CHUNK + ": render 4 LODs for each Chunk. \n" + + " " + HorizontalResolution.FOUR_BLOCKS + ": render 16 LODs for each Chunk. \n" + + " " + HorizontalResolution.TWO_BLOCKS + ": render 64 LODs for each Chunk. \n" + + " " + HorizontalResolution.BLOCK + ": render 256 LODs for each Chunk. \n") + .defineEnum("Draw resolution", HorizontalResolution.BLOCK); lodChunkRenderDistance = builder - .comment("\n\n" - + " The mod's render distance, measured in chunks. \n") - .defineInRange("lodChunkRenderDistance", 64, 32, 1024); + .comment("\n\n" + + " The mod's render distance, measured in chunks. \n") + .defineInRange("lodChunkRenderDistance", 64, 32, 1024); useFovSetting = builder - .comment("\n\n" - + " Experimental text value. \n" - + " " + FovTest.BOTH + ": is the normal value \n") - .defineEnum("useFovSetting", FovTest.BOTH); + .comment("\n\n" + + " Experimental text value. \n" + + " " + FovTest.BOTH + ": is the normal value \n") + .defineEnum("useFovSetting", FovTest.BOTH); disableDirectionalCulling = builder - .comment("\n\n" - + " If false LODs that are behind the player's camera \n" - + " aren't drawn, increasing performance. \n\n" - + "" - + " If true all LODs are drawn, even those behind \n" - + " the player's camera, decreasing performance. \n\n" - + "" - + " Disable this if you see LODs disapearing. \n" - + " (This may happen if you are using a camera mod) \n") - .define("disableDirectionalCulling", false); - + .comment("\n\n" + + " If false LODs that are behind the player's camera \n" + + " aren't drawn, increasing performance. \n\n" + + "" + + " If true all LODs are drawn, even those behind \n" + + " the player's camera, decreasing performance. \n\n" + + "" + + " Disable this if you see LODs disapearing. \n" + + " (This may happen if you are using a camera mod) \n") + .define("disableDirectionalCulling", false); + // shadingMode = builder // .comment("\n\n" // + " What kind of shading should the LODs have? \n" @@ -196,15 +184,15 @@ public class LodConfig // .defineEnum("lightingMode", ShadingMode.GAME_SHADING); alwaysDrawAtMaxQuality = builder - .comment("\n\n" - + " Disable LOD quality falloff, " - + " all LODs will be drawn at the highest " - + " available detail level. " - + " " - + " WARNING " - + " This could cause a Out Of Memory crash on render " - + " distances higher than 128 \n") - .define("alwaysDrawAtMaxQuality", false); + .comment("\n\n" + + " Disable LOD quality falloff, " + + " all LODs will be drawn at the highest " + + " available detail level. " + + " " + + " WARNING " + + " This could cause a Out Of Memory crash on render " + + " distances higher than 128 \n") + .define("alwaysDrawAtMaxQuality", false); builder.pop(); } @@ -212,7 +200,7 @@ public class LodConfig public static class WorldGenerator { - public ForgeConfigSpec.EnumValue lodQualityMode; + public ForgeConfigSpec.EnumValue verticalQuality; public ForgeConfigSpec.EnumValue generationResolution; public ForgeConfigSpec.EnumValue distanceGenerationMode; public ForgeConfigSpec.EnumValue generationPriority; @@ -224,118 +212,120 @@ public class LodConfig { builder.comment("These settings control how LODs outside your normal view range are generated.").push(this.getClass().getSimpleName()); - lodQualityMode = builder - .comment("\n\n" - + " Use 3d lods or 2d lods? \n" - + " " + VerticalQuality.HEIGHTMAP + ": LODs are solid from the lowest point to the highest. Creates pillars for floating islands. Faster \n" - + " " + VerticalQuality.VOXEL + ": LODs have gaps between vertical blocks. Good for floating islands and caves. Slower \n" - + " " + "(Yes we know voxels are generally cubes, but voxel sounds better than rectangular_prism) \n") - .defineEnum("lodQualityMode", VerticalQuality.HEIGHTMAP); + verticalQuality = builder + .comment("\n\n" + + " this indicate how complex the vertical data will be \n" + + " the higher value will take more memory and lower the performance \n" + + " " + VerticalQuality.LOW + ": uses at max 2 column per position. (performance option)\n" + + " " + VerticalQuality.MEDIUM + ": uses at max 4 column per position. \n" + + " " + VerticalQuality.HIGH + ": uses at max 8 column per position. \n" + + " " + "(Yes we know voxels are generally cubes, but voxel sounds better than rectangular_prism) \n") + .defineEnum("Vertical Quality", VerticalQuality.MEDIUM); generationResolution = builder - .comment("\n\n" - + " What is the maximum detail level that LODs should be generated at? \n" - + " " + HorizontalResolution.CHUNK + ": render 1 LOD for each Chunk. \n" - + " " + HorizontalResolution.HALF_CHUNK + ": render 4 LODs for each Chunk. \n" - + " " + HorizontalResolution.FOUR_BLOCKS + ": render 16 LODs for each Chunk. \n" - + " " + HorizontalResolution.TWO_BLOCKS + ": render 64 LODs for each Chunk. \n" - + " " + HorizontalResolution.BLOCK + ": render 256 LODs for each Chunk. \n") - .defineEnum("Generation Resolution", HorizontalResolution.BLOCK); + .comment("\n\n" + + " What is the maximum detail level that LODs should be generated at? \n" + + " " + HorizontalResolution.CHUNK + ": render 1 LOD for each Chunk. \n" + + " " + HorizontalResolution.HALF_CHUNK + ": render 4 LODs for each Chunk. \n" + + " " + HorizontalResolution.FOUR_BLOCKS + ": render 16 LODs for each Chunk. \n" + + " " + HorizontalResolution.TWO_BLOCKS + ": render 64 LODs for each Chunk. \n" + + " " + HorizontalResolution.BLOCK + ": render 256 LODs for each Chunk. \n") + .defineEnum("Generation Resolution", HorizontalResolution.BLOCK); horizontalScale = builder - .comment("\n\n" - + " This indicates how quickly LODs drop off in quality. \n" - + " " + HorizontalScale.LOW + ": quality drops every " + HorizontalScale.LOW.distanceUnit / 16 + " chunks. \n" - + " " + HorizontalScale.MEDIUM + ": quality drops every " + HorizontalScale.MEDIUM.distanceUnit / 16 + " chunks. \n" - + " " + HorizontalScale.HIGH + ": quality drops every " + HorizontalScale.HIGH.distanceUnit / 16 + " chunks. \n") - .defineEnum("horizontal scale", HorizontalScale.MEDIUM); + .comment("\n\n" + + " This indicates how quickly LODs drop off in quality. \n" + + " " + HorizontalScale.LOW + ": quality drops every " + HorizontalScale.LOW.distanceUnit / 16 + " chunks. \n" + + " " + HorizontalScale.MEDIUM + ": quality drops every " + HorizontalScale.MEDIUM.distanceUnit / 16 + " chunks. \n" + + " " + HorizontalScale.HIGH + ": quality drops every " + HorizontalScale.HIGH.distanceUnit / 16 + " chunks. \n") + .defineEnum("horizontal scale", HorizontalScale.MEDIUM); horizontalQuality = builder - .comment("\n\n" - + " This indicates the exponential base of the quadratic drop-off \n" - + " " + HorizontalQuality.LINEAR + ": base " + HorizontalQuality.LINEAR.quadraticBase + ". \n" - + " " + HorizontalQuality.LOW + ": base " + HorizontalQuality.LOW.quadraticBase + ". \n" - + " " + HorizontalQuality.MEDIUM + ": base " + HorizontalQuality.MEDIUM.quadraticBase + ". \n" - + " " + HorizontalQuality.HIGH + ": base " + HorizontalQuality.HIGH.quadraticBase + ". \n") - .defineEnum("horizontal quality", HorizontalQuality.MEDIUM); + .comment("\n\n" + + " This indicates the exponential base of the quadratic drop-off \n" + + " " + HorizontalQuality.LINEAR + ": base " + HorizontalQuality.LINEAR.quadraticBase + ". \n" + + " " + HorizontalQuality.LOW + ": base " + HorizontalQuality.LOW.quadraticBase + ". \n" + + " " + HorizontalQuality.MEDIUM + ": base " + HorizontalQuality.MEDIUM.quadraticBase + ". \n" + + " " + HorizontalQuality.HIGH + ": base " + HorizontalQuality.HIGH.quadraticBase + ". \n") + .defineEnum("horizontal quality", HorizontalQuality.MEDIUM); generationPriority = builder - .comment("\n\n" - + " " + GenerationPriority.FAR_FIRST + " \n" - + " LODs are generated from low to high detail\n" - + " with a small priority for far regions. \n" - + " This fills in the world fastest. \n" + .comment("\n\n" + + " " + GenerationPriority.FAR_FIRST + " \n" + + " LODs are generated from low to high detail\n" + + " with a small priority for far regions. \n" + + " This fills in the world fastest. \n" - + "\n" - + " " + GenerationPriority.NEAR_FIRST + " \n" - + " LODs are generated around the player \n" - + " in a spiral, similar to vanilla minecraft. \n") - .defineEnum("Generation priority", GenerationPriority.NEAR_FIRST); + + "\n" + + " " + GenerationPriority.NEAR_FIRST + " \n" + + " LODs are generated around the player \n" + + " in a spiral, similar to vanilla minecraft. \n") + .defineEnum("Generation priority", GenerationPriority.NEAR_FIRST); distanceGenerationMode = builder - .comment("\n\n" - + " Note: The times listed here are the amount of time it took \n" - + " one of the developer's PC to generate 1 chunk, \n" - + " and are included so you can compare the \n" - + " different generation options. Your mileage may vary. \n" - + "\n" + .comment("\n\n" + + " Note: The times listed here are the amount of time it took \n" + + " one of the developer's PC to generate 1 chunk, \n" + + " and are included so you can compare the \n" + + " different generation options. Your mileage may vary. \n" + + "\n" - + " " + DistanceGenerationMode.NONE + " \n" - + " Don't run the distance generator. \n" + + " " + DistanceGenerationMode.NONE + " \n" + + " Don't run the distance generator. \n" - + " " + DistanceGenerationMode.BIOME_ONLY + " \n" - + " Only generate the biomes and use the biome's \n" - + " grass color, water color, or snow color. \n" - + " Doesn't generate height, everything is shown at sea level. \n" - + " Multithreaded - Fastest (2-5 ms) \n" + + " " + DistanceGenerationMode.BIOME_ONLY + " \n" + + " Only generate the biomes and use the biome's \n" + + " grass color, water color, or snow color. \n" + + " Doesn't generate height, everything is shown at sea level. \n" + + " Multithreaded - Fastest (2-5 ms) \n" - + "\n" - + " " + DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT + " \n" - + " Same as BIOME_ONLY, except instead \n" - + " of always using sea level as the LOD height \n" - + " different biome types (mountain, ocean, forest, etc.) \n" - + " use predetermined heights to simulate having height data. \n" - + " Multithreaded - Fastest (2-5 ms) \n" + + "\n" + + " " + DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT + " \n" + + " Same as BIOME_ONLY, except instead \n" + + " of always using sea level as the LOD height \n" + + " different biome types (mountain, ocean, forest, etc.) \n" + + " use predetermined heights to simulate having height data. \n" + + " Multithreaded - Fastest (2-5 ms) \n" - + "\n" - + " " + DistanceGenerationMode.SURFACE + " \n" - + " Generate the world surface, \n" - + " this does NOT include caves, trees, \n" - + " or structures. \n" - + " Multithreaded - Faster (10-20 ms) \n" + + "\n" + + " " + DistanceGenerationMode.SURFACE + " \n" + + " Generate the world surface, \n" + + " this does NOT include caves, trees, \n" + + " or structures. \n" + + " Multithreaded - Faster (10-20 ms) \n" - + "\n" - + " " + DistanceGenerationMode.FEATURES + " \n" - + " Generate everything except structures. \n" - + " WARNING: This may cause world generation bugs or instability! \n" - + " Multithreaded - Fast (15-20 ms) \n" + + "\n" + + " " + DistanceGenerationMode.FEATURES + " \n" + + " Generate everything except structures. \n" + + " WARNING: This may cause world generation bugs or instability! \n" + + " Multithreaded - Fast (15-20 ms) \n" - + "\n" - + " " + DistanceGenerationMode.SERVER + " \n" - + " Ask the server to generate/load each chunk. \n" - + " This is the most compatible, but causes server/simulation lag. \n" - + " This will show player made structures, which can \n" - + " be useful if you are adding the mod to a pre-existing world. \n" - + " Singlethreaded - Slow (15-50 ms, with spikes up to 200 ms) \n") - .defineEnum("distanceGenerationMode", DistanceGenerationMode.SURFACE); + + "\n" + + " " + DistanceGenerationMode.SERVER + " \n" + + " Ask the server to generate/load each chunk. \n" + + " This is the most compatible, but causes server/simulation lag. \n" + + " This will show player made structures, which can \n" + + " be useful if you are adding the mod to a pre-existing world. \n" + + " Singlethreaded - Slow (15-50 ms, with spikes up to 200 ms) \n") + .defineEnum("distanceGenerationMode", DistanceGenerationMode.SURFACE); allowUnstableFeatureGeneration = builder - .comment("\n\n" - + " When using the " + DistanceGenerationMode.FEATURES + " generation mode \n" - + " some features may not be thread safe, which could \n" - + " cause instability and crashes. \n" - + " By default (false) those features are skipped, \n" - + " improving stability, but decreasing how many features are \n" - + " actually generated. \n" - + " (for example: some tree generation is unstable, \n" - + " so some trees may not be generated.) \n" - + " By setting this to true, all features will be generated, \n" - + " but your game will be more unstable and crashes may occur. \n" - + " \n" - + " I would love to remove this option and always generate everything, \n" - + " but I'm not sure how to do that. \n" - + " If you are a Java wizard, check out the git issue here: \n" - + " https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues/35 \n") - .define("allowUnstableFeatureGeneration", false); + .comment("\n\n" + + " When using the " + DistanceGenerationMode.FEATURES + " generation mode \n" + + " some features may not be thread safe, which could \n" + + " cause instability and crashes. \n" + + " By default (false) those features are skipped, \n" + + " improving stability, but decreasing how many features are \n" + + " actually generated. \n" + + " (for example: some tree generation is unstable, \n" + + " so some trees may not be generated.) \n" + + " By setting this to true, all features will be generated, \n" + + " but your game will be more unstable and crashes may occur. \n" + + " \n" + + " I would love to remove this option and always generate everything, \n" + + " but I'm not sure how to do that. \n" + + " If you are a Java wizard, check out the git issue here: \n" + + " https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues/35 \n") + .define("allowUnstableFeatureGeneration", false); builder.pop(); } @@ -351,27 +341,27 @@ public class LodConfig builder.comment("These settings control how many CPU threads the mod uses for different tasks.").push(this.getClass().getSimpleName()); numberOfWorldGenerationThreads = builder - .comment("\n\n" - + " This is how many threads are used when generating LODs outside \n" - + " the normal render distance. \n" - + " If you experience stuttering when generating distant LODs, decrease \n" - + " this number. If you want to increase LOD generation speed, \n" - + " increase this number. \n" - + " \n" - + " The maximum value is the number of logical processors on your CPU. \n" - + " Requires a restart to take effect. \n") - .defineInRange("numberOfWorldGenerationThreads", Runtime.getRuntime().availableProcessors() / 2, 1, Runtime.getRuntime().availableProcessors()); + .comment("\n\n" + + " This is how many threads are used when generating LODs outside \n" + + " the normal render distance. \n" + + " If you experience stuttering when generating distant LODs, decrease \n" + + " this number. If you want to increase LOD generation speed, \n" + + " increase this number. \n" + + " \n" + + " The maximum value is the number of logical processors on your CPU. \n" + + " Requires a restart to take effect. \n") + .defineInRange("numberOfWorldGenerationThreads", Runtime.getRuntime().availableProcessors() / 2, 1, Runtime.getRuntime().availableProcessors()); numberOfBufferBuilderThreads = builder - .comment("\n\n" - + " This is how many threads are used when building vertex buffers \n" - + " (The things sent to your GPU to draw the LODs). \n" - + " If you experience high CPU useage when NOT generating distant \n" - + " LODs, lower this number. \n" - + " \n" - + " The maximum value is the number of logical processors on your CPU. \n" - + " Requires a restart to take effect. \n") - .defineInRange("numberOfBufferBuilderThreads", Runtime.getRuntime().availableProcessors(), 1, Runtime.getRuntime().availableProcessors()); + .comment("\n\n" + + " This is how many threads are used when building vertex buffers \n" + + " (The things sent to your GPU to draw the LODs). \n" + + " If you experience high CPU useage when NOT generating distant \n" + + " LODs, lower this number. \n" + + " \n" + + " The maximum value is the number of logical processors on your CPU. \n" + + " Requires a restart to take effect. \n") + .defineInRange("numberOfBufferBuilderThreads", Runtime.getRuntime().availableProcessors(), 1, Runtime.getRuntime().availableProcessors()); builder.pop(); } @@ -387,17 +377,17 @@ public class LodConfig builder.comment("These settings can be used to look for bugs, or see how certain aspects of the mod work.").push(this.getClass().getSimpleName()); debugMode = builder - .comment("\n\n" - + " " + DebugMode.OFF + ": LODs will draw with their normal colors. \n" - + " " + DebugMode.SHOW_DETAIL + ": LOD colors will be based on their detail level. \n" - + " " + DebugMode.SHOW_DETAIL_WIREFRAME + ": LOD colors will be based on their detail level, drawn as a wireframe. \n") - .defineEnum("debugMode", DebugMode.OFF); + .comment("\n\n" + + " " + DebugMode.OFF + ": LODs will draw with their normal colors. \n" + + " " + DebugMode.SHOW_DETAIL + ": LOD colors will be based on their detail level. \n" + + " " + DebugMode.SHOW_DETAIL_WIREFRAME + ": LOD colors will be based on their detail level, drawn as a wireframe. \n") + .defineEnum("debugMode", DebugMode.OFF); enableDebugKeybindings = builder - .comment("\n\n" - + " If true the F4 key can be used to cycle through the different debug modes. \n" - + " and the F6 key can be used to enable and disable LOD rendering.") - .define("enableDebugKeybinding", false); + .comment("\n\n" + + " If true the F4 key can be used to cycle through the different debug modes. \n" + + " and the F6 key can be used to enable and disable LOD rendering.") + .define("enableDebugKeybinding", false); builder.pop(); } @@ -405,33 +395,17 @@ public class LodConfig public static class Buffers { - public ForgeConfigSpec.IntValue bufferRebuildPlayerMoveTimeout; - public ForgeConfigSpec.IntValue bufferRebuildChunkChangeTimeout; - public ForgeConfigSpec.IntValue bufferRebuildLodChangeTimeout; + public ForgeConfigSpec.EnumValue rebuildTimes; Buffers(ForgeConfigSpec.Builder builder) { builder.comment("These settings affect when Vertex Buffers are built.").push(this.getClass().getSimpleName()); - bufferRebuildPlayerMoveTimeout = builder - .comment("\n\n" - + " How long in milliseconds should we wait to \n" - + " rebuild the vertex buffers when the player moves \n" - + " a chunk or more? \n") - .defineInRange("bufferRebuildPlayerMoveTimeout", 2000, 1, 60000); - - bufferRebuildChunkChangeTimeout = builder - .comment("\n\n" - + " How long in milliseconds should we wait to \n" - + " rebuild the vertex buffers when the vanilla rendered \n" - + " chunks change? \n") - .defineInRange("bufferRebuildChunkChangeTimeout", 1000, 1, 60000); - - bufferRebuildLodChangeTimeout = builder - .comment("\n\n" - + " How long in milliseconds should we wait to \n" - + " rebuild the vertex buffers when the LOD regions change? \n") - .defineInRange("bufferRebuildLodChangeTimeout", 5000, 1, 60000); + rebuildTimes = builder + .comment("\n\n" + + "How frequently we rebuild the buffers?" + "\n" + + "more frequent rebuild implies more stuttering" + "\n") + .defineEnum("rebuildFrequency", BufferRebuildTimes.NORMAL); builder.pop(); } @@ -451,8 +425,8 @@ public class LodConfig CLIENT_SPEC = specPair.getRight(); CLIENT = specPair.getLeft(); CommentedFileConfig clientConfig = CommentedFileConfig.builder(CONFIG_PATH) - .writingMode(WritingMode.REPLACE) - .build(); + .writingMode(WritingMode.REPLACE) + .build(); clientConfig.load(); clientConfig.save(); CLIENT_SPEC.setConfig(clientConfig); diff --git a/src/main/java/com/seibel/lod/enums/BufferRebuildTimes.java b/src/main/java/com/seibel/lod/enums/BufferRebuildTimes.java new file mode 100644 index 000000000..026c6b17f --- /dev/null +++ b/src/main/java/com/seibel/lod/enums/BufferRebuildTimes.java @@ -0,0 +1,49 @@ +/* + * This file is part of the LOD Mod, licensed under the GNU GPL v3 License. + * + * Copyright (C) 2020 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.seibel.lod.enums; + +import net.minecraftforge.common.ForgeConfigSpec; + +/** + * Near_First
+ * Far_First
+ *
+ * Determines how fast the buffers need to be regenerated + * + * @author Leonardo Amato + * @version 9-25-2021 + */ +public enum BufferRebuildTimes +{ + FREQUENT(1000, 500, 2500), + + NORMAL(2000, 1000, 5000), + + RARE(5000, 2000, 10000); + + public int playerMoveTimeout; + public int renderdChunkTimeout; + public int chunkChangeTimeout; + + BufferRebuildTimes(int playerMoveTimeout, int renderdChunkTimeout, int chunkChangeTimeout) + { + this.playerMoveTimeout = playerMoveTimeout; + this.renderdChunkTimeout = renderdChunkTimeout; + this.chunkChangeTimeout = chunkChangeTimeout; + } +} diff --git a/src/main/java/com/seibel/lod/enums/VerticalQuality.java b/src/main/java/com/seibel/lod/enums/VerticalQuality.java index 43fec9e5c..500bcf3be 100644 --- a/src/main/java/com/seibel/lod/enums/VerticalQuality.java +++ b/src/main/java/com/seibel/lod/enums/VerticalQuality.java @@ -26,9 +26,53 @@ package com.seibel.lod.enums; */ public enum VerticalQuality { - /** Lods only have height and depth data */ - HEIGHTMAP, - - /** Lods expand in three dimensions */ - VOXEL; + LOW( + new int[]{2, + 2, + 2, + 2, + 1, + 1, + 1, + 1, + 1, + 1, + 1} + ), + + MEDIUM( + new int[]{4, + 4, + 2, + 2, + 2, + 1, + 1, + 1, + 1, + 1, + 1} + ), + + HIGH( + new int[]{ + 8, + 8, + 4, + 4, + 2, + 2, + 2, + 1, + 1, + 1, + 1} + ); + + public final int[] maxVerticalData; + + VerticalQuality(int[] maxVerticalData) + { + this.maxVerticalData = maxVerticalData; + } } \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index 480145d72..04c74dcb6 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -174,16 +174,7 @@ public class LodDimensionFileHandler // add the data to our region - switch (region.getVerticalQuality()) - { - default: - case HEIGHTMAP: - region.addLevelContainer(new SingleLevelContainer(data)); - break; - case VOXEL: - region.addLevelContainer(new VerticalLevelContainer(data)); - break; - } + region.addLevelContainer(new VerticalLevelContainer(data)); } catch (IOException ioEx) { diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index c98add558..432c245bd 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -387,7 +387,7 @@ public class LodDimension { DistanceGenerationMode generationMode = LodConfig.CLIENT.worldGenerator.distanceGenerationMode.get(); ChunkPos newPlayerChunk = new ChunkPos(LevelPosUtil.getChunkPos((byte) 0, playerPosX), LevelPosUtil.getChunkPos((byte) 0, playerPosZ)); - VerticalQuality verticalQuality = LodConfig.CLIENT.worldGenerator.lodQualityMode.get(); + VerticalQuality verticalQuality = LodConfig.CLIENT.worldGenerator.verticalQuality.get(); if (lastExpandedChunk == null) diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index e033698cc..669f3e22f 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -79,16 +79,7 @@ public class LodRegion // Initialize all the different matrices for (byte lod = minDetailLevel; lod <= LodUtil.REGION_DETAIL_LEVEL; lod++) { - switch (verticalQuality) - { - default: - case HEIGHTMAP: - dataContainer[lod] = new SingleLevelContainer(lod); - break; - case VOXEL: - dataContainer[lod] = new VerticalLevelContainer(lod); - break; - } + dataContainer[lod] = new VerticalLevelContainer(lod); } } @@ -109,10 +100,7 @@ public class LodRegion // detailLevel changes. if (this.dataContainer[detailLevel] == null) { - if (verticalQuality == VerticalQuality.HEIGHTMAP) - this.dataContainer[detailLevel] = new SingleLevelContainer(detailLevel); - else - this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel); + this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel); } this.dataContainer[detailLevel].addData(data, posX, posZ, verticalIndex); diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index 60ea1e2c2..856a8bb7e 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -798,7 +798,7 @@ public class LodRenderer if (LodConfig.CLIENT.graphics.detailDropOff.get() == DetailDropOff.FANCY) { // check if the player has moved - if (newTime - prevPlayerPosTime > LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.get()) + if (newTime - prevPlayerPosTime > LodConfig.CLIENT.buffers.rebuildTimes.get().playerMoveTimeout) { if (LevelPosUtil.getDetailLevel(previousPos) == 0 || mc.getPlayer().xChunk != LevelPosUtil.getPosX(previousPos) @@ -819,7 +819,7 @@ public class LodRenderer // check if the vanilla rendered chunks changed - if (newTime - prevVanillaChunkTime > LodConfig.CLIENT.buffers.bufferRebuildChunkChangeTimeout.get()) + if (newTime - prevVanillaChunkTime > LodConfig.CLIENT.buffers.rebuildTimes.get().renderdChunkTimeout) { if (vanillaRenderedChunksChanged) { @@ -832,7 +832,7 @@ public class LodRenderer // check if there is any newly generated terrain to show - if (newTime - prevChunkTime > LodConfig.CLIENT.buffers.bufferRebuildLodChangeTimeout.get()) + if (newTime - prevChunkTime > LodConfig.CLIENT.buffers.rebuildTimes.get().chunkChangeTimeout) { if (lodDim.regenDimensionBuffers) { diff --git a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java index 9dd57a706..ff8b66a66 100644 --- a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java +++ b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java @@ -3,7 +3,6 @@ package com.seibel.lod.util; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; import com.seibel.lod.enums.HorizontalResolution; -import com.seibel.lod.enums.VerticalQuality; public class DetailDistanceUtil { @@ -16,20 +15,7 @@ public class DetailDistanceUtil private static int minDistance = 0; private static int maxDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * 16 * 2; - private static int[] maxVerticalData = { - 4, - 4, - 4, - 2, - 2, - 1, - 1, - 1, - 1, - 1, - 1}; - - + private static HorizontalResolution[] lodGenDetails = { HorizontalResolution.BLOCK, HorizontalResolution.TWO_BLOCKS, @@ -165,9 +151,7 @@ public class DetailDistanceUtil public static int getMaxVerticalData(int detail) { - if(LodConfig.CLIENT.worldGenerator.lodQualityMode.get() == VerticalQuality.HEIGHTMAP) - return 1; - return maxVerticalData[LodUtil.clamp(minGenDetail, detail, LodUtil.REGION_DETAIL_LEVEL)]; + return LodConfig.CLIENT.worldGenerator.verticalQuality.get().maxVerticalData[LodUtil.clamp(minGenDetail, detail, LodUtil.REGION_DETAIL_LEVEL)]; } } From 443da5eede5063d181b781df6cf1d109048fcea3 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 7 Oct 2021 17:37:02 +0200 Subject: [PATCH 12/14] other config change, set roofed dimension max distance to 64 --- src/main/java/com/seibel/lod/enums/VerticalQuality.java | 2 +- src/main/java/com/seibel/lod/proxy/ClientProxy.java | 7 ++++++- src/main/java/com/seibel/lod/render/LodRenderer.java | 7 +++++-- src/main/java/com/seibel/lod/util/DetailDistanceUtil.java | 4 ++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/seibel/lod/enums/VerticalQuality.java b/src/main/java/com/seibel/lod/enums/VerticalQuality.java index 500bcf3be..a709854c4 100644 --- a/src/main/java/com/seibel/lod/enums/VerticalQuality.java +++ b/src/main/java/com/seibel/lod/enums/VerticalQuality.java @@ -22,7 +22,7 @@ package com.seibel.lod.enums; * multi_lod
* * @author Leonardo Amato - * @version 9-27-2021 + * @version 10-07-2021 */ public enum VerticalQuality { diff --git a/src/main/java/com/seibel/lod/proxy/ClientProxy.java b/src/main/java/com/seibel/lod/proxy/ClientProxy.java index aa410e3ef..19627cc8d 100644 --- a/src/main/java/com/seibel/lod/proxy/ClientProxy.java +++ b/src/main/java/com/seibel/lod/proxy/ClientProxy.java @@ -333,7 +333,12 @@ public class ClientProxy private void viewDistanceChangedEvent() { // calculate how wide the dimension(s) should be in regions - int chunksWide = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * 2 + 1; + int chunksWide; + if(mc.getClientWorld().dimensionType().hasCeiling()) + chunksWide = Math.max(LodConfig.CLIENT.graphics.lodChunkRenderDistance.get(),64) * 2 + 1; + else + chunksWide = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * 2 + 1; + int newWidth = (int) Math.ceil(chunksWide / (float) LodUtil.REGION_WIDTH_IN_CHUNKS); newWidth = (newWidth % 2 == 0) ? (newWidth += 1) : (newWidth += 2); // make sure we have a odd number of regions diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index 856a8bb7e..269661782 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -241,8 +241,11 @@ public class LodRenderer Matrix4f modelViewMatrix = offsetTheModelViewMatrix(mcMatrixStack, partialTicks); // required for setupFog and setupProjectionMatrix - farPlaneBlockDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH; - + if(lodDim.dimension.hasCeiling()) + farPlaneBlockDistance = Math.max(LodConfig.CLIENT.graphics.lodChunkRenderDistance.get(), 64)* LodUtil.CHUNK_WIDTH; + else + farPlaneBlockDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH; + setupProjectionMatrix(mcProjectionMatrix, partialTicks); // commented out until we can add shaders to handle lighting //setupLighting(lodDim, partialTicks); diff --git a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java index ff8b66a66..f1b51f01d 100644 --- a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java +++ b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java @@ -13,7 +13,7 @@ public class DetailDistanceUtil private static int minDrawDetail = Math.max(LodConfig.CLIENT.graphics.drawResolution.get().detailLevel,LodConfig.CLIENT.worldGenerator.generationResolution.get().detailLevel); private static int maxDetail = LodUtil.REGION_DETAIL_LEVEL + 1; private static int minDistance = 0; - private static int maxDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * 16 * 2; + private static int maxDistance = Integer.MAX_VALUE; private static HorizontalResolution[] lodGenDetails = { @@ -34,7 +34,7 @@ public class DetailDistanceUtil public static void updateSettings(){ minGenDetail = LodConfig.CLIENT.worldGenerator.generationResolution.get().detailLevel; minDrawDetail = Math.max(LodConfig.CLIENT.graphics.drawResolution.get().detailLevel,LodConfig.CLIENT.worldGenerator.generationResolution.get().detailLevel); - maxDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * 16 * 8; + //maxDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * 16 * 8; } public static int baseDistanceFunction(int detail) From 61cb27020cc28624c44812559c7124e9ec3ca80e Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 7 Oct 2021 18:03:09 +0200 Subject: [PATCH 13/14] small change to a print --- .../java/com/seibel/lod/objects/PosToGenerateContainer.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java index 0a025aabf..95dfeb915 100644 --- a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java +++ b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java @@ -161,6 +161,8 @@ public class PosToGenerateContainer builder.append('\n'); for (int i = 0; i < nearPosToGenerate.length; i++) { + if(nearPosToGenerate[i][0] == 0) + break; builder.append(nearPosToGenerate[i][0]-1); builder.append(" "); builder.append(nearPosToGenerate[i][1]); @@ -176,6 +178,8 @@ public class PosToGenerateContainer builder.append('\n'); for (int i = 0; i < farPosToGenerate.length; i++) { + if(farPosToGenerate[i][0] == 0) + break; builder.append(farPosToGenerate[i][0]-1); builder.append(" "); builder.append(farPosToGenerate[i][1]); From b02d58227ca1633a9a40664febe892f81b233fd8 Mon Sep 17 00:00:00 2001 From: cola98765 Date: Thu, 7 Oct 2021 20:17:37 +0200 Subject: [PATCH 14/14] reworked mergeMultiData --- .../com/seibel/lod/util/DataPointUtil.java | 181 +++++++++++++----- 1 file changed, 129 insertions(+), 52 deletions(-) diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 4687c96de..1ff06e842 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -293,6 +293,31 @@ public class DataPointUtil return DataPointUtil.createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, tempHeight, tempDepth, tempLightSky, tempLightBlock, tempGenMode); } } + + public static void shrinkArray(short[] array, int packetSize, int start, int length, int arraySize) + { + start *= packetSize; + length *= packetSize; + arraySize *= packetSize; + for (int i = 0; i < arraySize - start; i++) + { + array[start + i] = array[start + length + i]; + //remove comment to not leave garbage at the end + //array[start + packetSize + i] = 0; + } + } + + public static void extendArray(short[] array, int packetSize, int start, int length, int arraySize) + { + start *= packetSize; + length *= packetSize; + arraySize *= packetSize; + for (int i = arraySize - start - 1; i >= 0; i--) + { + array[start + length + i] = array[start + i]; + array[start + i] = 0; + } + } /** * This method merge column of multiple data together @@ -306,7 +331,6 @@ public class DataPointUtil int size = dataToMerge.length / inputVerticalData; // We initialize the arrays that are going to be used - short[] projection = ThreadMapUtil.getProjectionArray((worldHeight) / 16 + 1); short[] heightAndDepth = ThreadMapUtil.getHeightAndDepth((worldHeight + 1) * 2); long[] singleDataToMerge = ThreadMapUtil.getSingleAddDataToMerge(size); long[] dataPoint = ThreadMapUtil.getVerticalDataArray(worldHeight + 1); @@ -320,28 +344,119 @@ public class DataPointUtil short depth; short height; - + int count = 0; + int i; + int ii; //We collect the indexes of the data, ordered by the depth - for (int index = 0; index < size; index++) + for (int index = 0; index < dataToMerge.length; index++) { - for (int dataIndex = 0; dataIndex < inputVerticalData; dataIndex++) + singleData = dataToMerge[index]; + if (doesItExist(singleData)) { - singleData = dataToMerge[index * inputVerticalData + dataIndex]; - if (doesItExist(singleData)) + genMode = Math.min(genMode, getGenerationMode(singleData)); + allEmpty = false; + if (!isVoid(singleData)) { - genMode = Math.min(genMode, getGenerationMode(singleData)); - allEmpty = false; - if (!isVoid(singleData)) + allVoid = false; + depth = getDepth(singleData); + height = getHeight(singleData); + + int botPos = -1; + int topPos = -1; + //values fall in between and possibly require extension of array + boolean botExtend = false; + boolean topExtend = false; + for (i = 0; i < count; i++) { - allVoid = false; - depth = getDepth(singleData); - height = getHeight(singleData); - for (int y = depth; y <= height; y++) - projection[y / 16] |= 1 << (y & 0xf); + if (depth >= heightAndDepth[i * 2] && depth <= heightAndDepth[i * 2 + 1]) + { + botPos = i; + break; + } + else if (((i + 1 < count && depth < heightAndDepth[(i + 1) * 2]) || i + 1 == count) && depth > heightAndDepth[i * 2 + 1]) + { + botPos = i; + botExtend = true; + break; + } + } + for (i = 0; i < count; i++) + { + if (height >= heightAndDepth[i * 2] && height <= heightAndDepth[i * 2 + 1]) + { + topPos = i; + break; + } + else if (((i + 1 < count && height < heightAndDepth[(i + 1) * 2]) || i + 1 == count) && height > heightAndDepth[i * 2 + 1]) + { + topPos = i; + topExtend = true; + break; + } + } + if (botPos == -1) + { + if (topPos == -1) + { + //whole block falls below + extendArray(heightAndDepth, 2, 0, 1, count); + heightAndDepth[0] = depth; + heightAndDepth[1] = height; + count++; + } + else if (!topExtend) + { + //only bottom falls below extending it there, while top is inside existing + shrinkArray(heightAndDepth, 2, 0, topPos, count); + heightAndDepth[0] = depth; + count -= topPos; + } + else + { + //top falls between some blocks, extending those as well + shrinkArray(heightAndDepth, 2, 0, topPos, count); + heightAndDepth[0] = depth; + heightAndDepth[1] = height; + count -= topPos; + } + } + else if (!botExtend) + { + if (!topExtend) + //both top and bottom are within some exiting blocks, possibly merging them + heightAndDepth[botPos * 2 + 1] = heightAndDepth[topPos * 2 + 1]; + else + //top falls between some blocks, extending it there + heightAndDepth[botPos * 2 + 1] = height; + shrinkArray(heightAndDepth, 2, botPos + 1, topPos - botPos, count); + count -= topPos - botPos; + } + else + { + if (!topExtend) + { + //only top is within some exiting block, extending it + botPos++; //to make it easier + heightAndDepth[botPos * 2] = depth; + heightAndDepth[botPos * 2 + 1] = heightAndDepth[topPos * 2 + 1]; + shrinkArray(heightAndDepth, 2, botPos + 1, topPos - botPos, count); + count -= topPos - botPos; + } + else + { + //both top and bottom are outside existing blocks + shrinkArray(heightAndDepth, 2, botPos + 1, topPos - botPos, count); + count -= topPos - botPos; + extendArray(heightAndDepth, 2, botPos + 1, 1, count); + count++; + heightAndDepth[botPos * 2 + 2] = depth; + heightAndDepth[botPos * 2 + 3] = height; + } } } } } + //We check if there is any data that's not empty or void if (allEmpty) { @@ -352,44 +467,6 @@ public class DataPointUtil dataPoint[0] = createVoidDataPoint(genMode); return dataPoint; } - //We extract the merged data - int count = 0; - int i = 0; - int ii = 0; - while (i < projection.length) - { - while (i < projection.length && projection[i] == 0) i++; - if (i == projection.length) - break; //we reached end of WORLD_HEIGHT and it's nothing more here - while (ii < 15 && ((projection[i] >>> ii) & 1) == 0) ii++; - if (ii >= 15 && ((projection[i] >>> ii) & 1) == 0) //there is nothing more in this chunk - { - ii = 0; - i++; - continue; - } - depth = (short) (i * 16 + ii); - - while (ii < 15 && ((projection[i] >>> ii) & 1) == 1) ii++; - if (ii >= 15 && ((projection[i] >>> ii) & 1) == 1) //if end is not in this chunk - { - ii = 0; - i++; - while (i < projection.length && ~(projection[i]) == 0) i++; //check for big solid blocks - if (i == projection.length) //solid to WORLD_HEIGHT - { - heightAndDepth[count * 2] = depth; - heightAndDepth[count * 2 + 1] = (short) (worldHeight - 1); - break; - } - while ((((projection[i] >>> ii) & 1) == 1)) ii++; - } - height = (short) (i * 16 + ii - 1); - heightAndDepth[count * 2] = depth; - heightAndDepth[count * 2 + 1] = height; - count++; - } - //we limit the vertical portion to maxVerticalData int j = 0; while (count > maxVerticalData)