diff --git a/src/main/java/com/seibel/lod/builders/GenerationRequest.java b/src/main/java/com/seibel/lod/builders/GenerationRequest.java new file mode 100644 index 000000000..d2467c4fd --- /dev/null +++ b/src/main/java/com/seibel/lod/builders/GenerationRequest.java @@ -0,0 +1,28 @@ +package com.seibel.lod.builders; + +import com.seibel.lod.enums.DistanceGenerationMode; +import com.seibel.lod.objects.LevelPos; +import com.seibel.lod.util.LodUtil; +import net.minecraft.util.math.ChunkPos; + +/** + * @author Leonardo Amato + * @version 22-08-2021 + */ +public class GenerationRequest +{ + public final LevelPos levelPos; + public final DistanceGenerationMode generationMode; + + public GenerationRequest(LevelPos levelPos, DistanceGenerationMode generationMode) + { + this.levelPos = levelPos; + this.generationMode = generationMode; + } + + public ChunkPos getChunkPos() + { + LevelPos chunkLevelPos = levelPos.convert(LodUtil.CHUNK_DETAIL_LEVEL); + return new ChunkPos(chunkLevelPos.posX, chunkLevelPos.posZ); + } +} \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java index ad398cd25..6d81b3718 100644 --- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java @@ -26,6 +26,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; +import com.seibel.lod.util.DetailUtil; import org.lwjgl.opengl.GL11; import com.seibel.lod.builders.worldGeneration.LodNodeGenWorker; @@ -177,41 +178,17 @@ public class LodBufferBuilder // we can top it off from the reserve ArrayList chunksToGenReserve = new ArrayList<>(maxChunkGenRequests); -/* - DistanceGenerationMode[] distancesGenerators = {DistanceGenerationMode.FEATURES, - DistanceGenerationMode.FEATURES, - DistanceGenerationMode.SURFACE, - DistanceGenerationMode.SURFACE, - DistanceGenerationMode.SURFACE, - DistanceGenerationMode.BIOME_ONLY, - DistanceGenerationMode.BIOME_ONLY, - DistanceGenerationMode.BIOME_ONLY, - DistanceGenerationMode.BIOME_ONLY, - DistanceGenerationMode.BIOME_ONLY} - - */ - - DistanceGenerationMode[] distancesGenerators = { - DistanceGenerationMode.SURFACE, - DistanceGenerationMode.SURFACE, - DistanceGenerationMode.SURFACE, - DistanceGenerationMode.SURFACE, - DistanceGenerationMode.SURFACE, - DistanceGenerationMode.SURFACE, - DistanceGenerationMode.SURFACE, - DistanceGenerationMode.SURFACE, - DistanceGenerationMode.SURFACE, - DistanceGenerationMode.SURFACE}; - int[] distancesLinear = {0, 200, 400, 600, 800, 1000, 1500, 2000, 3000, 4000, 8000}; - int[] distancesExponential = {0, 100, 200, 400, 800, 1600, 3200, 3200, 3200, 3200, 8000}; - startBuffers(); // used when determining which chunks are closer when queuing distance // generation int minChunkDist = Integer.MAX_VALUE; - int width; + + // =====================// + // RENDERING PART // + // =====================// + List posListToRender = new ArrayList<>(); LodDataPoint lodData; for (int xRegion = 0; xRegion < lodDim.regions.length; xRegion++) @@ -231,34 +208,38 @@ public class LodBufferBuilder /**TODO make this automatic and config dependent*/ for (byte detail = LodUtil.BLOCK_DETAIL_LEVEL; detail <= LodUtil.REGION_DETAIL_LEVEL; detail++) { - posListToRender.addAll(lodDim.getDataToRender(regionPos, playerBlockPosRounded.getX(), playerBlockPosRounded.getZ(), distancesLinear[detail], distancesLinear[detail + 1], detail)); + posListToRender.addAll(lodDim.getDataToRender( + regionPos, + playerBlockPosRounded.getX(), + playerBlockPosRounded.getZ(), + DetailUtil.getDistanceRendering(detail), + DetailUtil.getDistanceRendering(detail + 1), + detail)); } for (LevelPos pos : posListToRender) { - LevelPos chunkPos = pos.convert((byte) 2); - int chunkX = chunkPos.posX + startChunkPos.x; - int chunkZ = chunkPos.posZ + startChunkPos.z; + LevelPos chunkPos = pos.convert(LodUtil.CHUNK_DETAIL_LEVEL); // skip any chunks that Minecraft is going to render - if (isCoordInCenterArea(chunkPos.posX, chunkPos.posZ, (numbChunksWide / 2)) || renderer.vanillaRenderedChunks.contains(new ChunkPos(chunkX, chunkZ))) + + if (renderer.vanillaRenderedChunks.contains(new ChunkPos( chunkPos.posX, chunkPos.posZ))) { continue; } if (lodDim.doesDataExist(pos)) { - try - { - width = (int) Math.pow(2, pos.detailLevel); - lodData = lodDim.getData(pos); - LodConfig.CLIENT.lodTemplate.get().template.addLodToBuffer(currentBuffer, lodDim, lodData, - pos.posX * width, 0, pos.posZ * width, renderer.debugging, pos.detailLevel); - } - catch (ArrayIndexOutOfBoundsException e) - { - ClientProxy.LOGGER.warn("LodBufferBuilder ran into trouble and had to start over."); - closeBuffers(); - return; - } + try + { + width = (int) Math.pow(2, pos.detailLevel); + lodData = lodDim.getData(pos); + LodConfig.CLIENT.lodTemplate.get().template.addLodToBuffer(currentBuffer, lodDim, lodData, + pos.posX * width, 0, pos.posZ * width, renderer.debugging, pos.detailLevel); + } catch (ArrayIndexOutOfBoundsException e) + { + ClientProxy.LOGGER.warn("LodBufferBuilder ran into trouble and had to start over."); + closeBuffers(); + return; + } } } @@ -267,10 +248,15 @@ public class LodBufferBuilder } } - /**TODO make this automatic and config dependent*/ + + // =====================// + // GENERATION PART // + // =====================// + + List posListToGenerate = new ArrayList<>(); - /**TODO this order can be inverted*/ + /**TODO can give a totally different generation*/ /* for (byte detail = LodUtil.BLOCK_DETAIL_LEVEL; detail <= LodUtil.REGION_DETAIL_LEVEL; detail++) { @@ -289,139 +275,143 @@ public class LodBufferBuilder System.out.println("HERE"); } } -*/ + */ int requesting = maxChunkGenRequests; + + //we firstly make sure that the world is filled with half region wide block for (byte detailGen = LodUtil.BLOCK_DETAIL_LEVEL; detailGen <= LodUtil.REGION_DETAIL_LEVEL; detailGen++) { if (requesting == 0) break; posListToGenerate.addAll(lodDim.getDataToGenerate( playerBlockPosRounded.getX(), playerBlockPosRounded.getZ(), - (int) (distancesLinear[detailGen] * 1.5), - (int) (distancesLinear[detailGen + 1] * 1.5), - (byte) distancesGenerators[detailGen].complexity, - (byte) 8, + DetailUtil.getDistanceGeneration(detailGen), + DetailUtil.getDistanceGeneration(detailGen + 1), + DetailUtil.getDistanceGenerationMode(detailGen).complexity, + (byte) 7, requesting)); requesting = maxChunkGenRequests - posListToGenerate.size(); + + for (LevelPos levelPos : posListToGenerate) + { + } + } + + //we then fill the world with the rest of the block for (byte detailGen = LodUtil.BLOCK_DETAIL_LEVEL; detailGen <= LodUtil.REGION_DETAIL_LEVEL; detailGen++) { if (requesting == 0) break; posListToGenerate.addAll(lodDim.getDataToGenerate( playerBlockPosRounded.getX(), playerBlockPosRounded.getZ(), - (int) (distancesLinear[detailGen] * 1.5), - (int) (distancesLinear[detailGen + 1] * 1.5), - (byte) distancesGenerators[detailGen].complexity, + DetailUtil.getDistanceGeneration(detailGen), + DetailUtil.getDistanceGeneration(detailGen + 1), + DetailUtil.getDistanceGenerationMode(detailGen).complexity, (byte) 0, maxChunkGenRequests)); requesting = maxChunkGenRequests - posListToGenerate.size(); } - - - - if (LodConfig.CLIENT.distanceGenerationMode.get() != DistanceGenerationMode.NONE) - { - // determine which points in the posListToGenerate - // should actually be queued up - for (LevelPos levelPos : posListToGenerate) - { - LevelPos chunkLevelPos = levelPos.convert((byte) 3); - int chunkX = Math.floorDiv(chunkLevelPos.posX, 2); - int chunkZ = Math.floorDiv(chunkLevelPos.posZ, 2); - - if (numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests) - { - ChunkPos pos = new ChunkPos(chunkX, chunkZ); - - if (positionWaitingToBeGenerated.contains(pos)) - { - ClientProxy.LOGGER.debug(pos + " asked to be generated again."); - continue; - } - - // determine if this position is closer to the player - // than the previous - int newDistance = playerChunkPos.getChessboardDistance(pos); - - if (newDistance < minChunkDist) - { - // this chunk is closer, clear any previous - // positions and update the new minimum distance - minChunkDist = newDistance; - - // move all the old chunks into the reserve - ArrayList oldReserve = new ArrayList<>(chunksToGenReserve); - chunksToGenReserve.clear(); - chunksToGenReserve.addAll(chunksToGen); - // top off reserve with whatever was in oldReerve - for (int i = 0; i < oldReserve.size(); i++) - { - if (chunksToGenReserve.size() < maxChunkGenRequests) - chunksToGenReserve.add(oldReserve.get(i)); - else - break; - } - - chunksToGen.clear(); - chunksToGen.add(pos); - } - else if (newDistance == minChunkDist) - { - // this chunk position as close as the minimum distance - if (chunksToGen.size() < maxChunkGenRequests) - { - // we are still under the number of chunks to generate - // add this position to the list - chunksToGen.add(pos); - } - } - else - { - // this chunk is farther away than the minimum distance, - // add it to the reserve to make sure we always have a full reserve - chunksToGenReserve.add(pos); - } - - } // lod null and can generate more chunks - } // positions to generate - - - - // queue up chunks to be generated - if (mc.hasSingleplayerServer()) - { - // issue #19 - // TODO add a way for a server side mod to generate chunks requested here - ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(lodDim.dimension); - - // make sure we have as many chunks to generate as we are allowed - if (chunksToGen.size() < maxChunkGenRequests) - { - Iterator reserveIterator = chunksToGenReserve.iterator(); - while (chunksToGen.size() < maxChunkGenRequests && reserveIterator.hasNext()) - { - chunksToGen.add(reserveIterator.next()); - } - } - - // start chunk generation - for (ChunkPos chunkPos : chunksToGen) - { - // don't add null chunkPos (which shouldn't happen anyway) - // or add more to the generation queue - if (chunkPos == null || numberOfChunksWaitingToGenerate.get() >= maxChunkGenRequests) - continue; - - positionWaitingToBeGenerated.add(chunkPos); - numberOfChunksWaitingToGenerate.addAndGet(1); - LodNodeGenWorker genWorker = new LodNodeGenWorker(chunkPos, DistanceGenerationMode.SURFACE, LodDetail.FULL, renderer, LodQuadTreeNodeBuilder, this, lodDim, serverWorld); - WorldWorkerManager.addWorker(genWorker); - } - } - } // if distanceGenerationMode != DistanceGenerationMode.NONE - - + + if (LodConfig.CLIENT.distanceGenerationMode.get() != DistanceGenerationMode.NONE) + { + // determine which points in the posListToGenerate + // should actually be queued up + for (LevelPos levelPos : posListToGenerate) + { + LevelPos chunkLevelPos = levelPos.convert(LodUtil.CHUNK_DETAIL_LEVEL); + int chunkX = chunkLevelPos.posX; + int chunkZ = chunkLevelPos.posZ; + + if (numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests) + { + ChunkPos pos = new ChunkPos(chunkX, chunkZ); + + if (positionWaitingToBeGenerated.contains(pos)) + { + //ClientProxy.LOGGER.debug(pos + " asked to be generated again."); + continue; + } + + // determine if this position is closer to the player + // than the previous + int newDistance = playerChunkPos.getChessboardDistance(pos); + + if (newDistance < minChunkDist) + { + // this chunk is closer, clear any previous + // positions and update the new minimum distance + minChunkDist = newDistance; + + // move all the old chunks into the reserve + ArrayList oldReserve = new ArrayList<>(chunksToGenReserve); + chunksToGenReserve.clear(); + chunksToGenReserve.addAll(chunksToGen); + // top off reserve with whatever was in oldReerve + for (int i = 0; i < oldReserve.size(); i++) + { + if (chunksToGenReserve.size() < maxChunkGenRequests) + chunksToGenReserve.add(oldReserve.get(i)); + else + break; + } + + chunksToGen.clear(); + chunksToGen.add(pos); + } else if (newDistance == minChunkDist) + { + // this chunk position as close as the minimum distance + if (chunksToGen.size() < maxChunkGenRequests) + { + // we are still under the number of chunks to generate + // add this position to the list + chunksToGen.add(pos); + } + } else + { + // this chunk is farther away than the minimum distance, + // add it to the reserve to make sure we always have a full reserve + chunksToGenReserve.add(pos); + } + + } // lod null and can generate more chunks + } // positions to generate + + + // queue up chunks to be generated + if (mc.hasSingleplayerServer()) + { + // issue #19 + // TODO add a way for a server side mod to generate chunks requested here + ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(lodDim.dimension); + + // make sure we have as many chunks to generate as we are allowed + if (chunksToGen.size() < maxChunkGenRequests) + { + Iterator reserveIterator = chunksToGenReserve.iterator(); + while (chunksToGen.size() < maxChunkGenRequests && reserveIterator.hasNext()) + { + chunksToGen.add(reserveIterator.next()); + } + } + + // start chunk generation + for (ChunkPos chunkPos : chunksToGen) + { + // don't add null chunkPos (which shouldn't happen anyway) + // or add more to the generation queue + if (chunkPos == null || numberOfChunksWaitingToGenerate.get() >= maxChunkGenRequests) + continue; + + positionWaitingToBeGenerated.add(chunkPos); + numberOfChunksWaitingToGenerate.addAndGet(1); + LodNodeGenWorker genWorker = new LodNodeGenWorker(chunkPos, DistanceGenerationMode.SURFACE, LodDetail.FULL, renderer, LodQuadTreeNodeBuilder, this, lodDim, serverWorld); + WorldWorkerManager.addWorker(genWorker); + } + } + } // if distanceGenerationMode != DistanceGenerationMode.NONE + + // finish the buffer building closeBuffers(); @@ -434,15 +424,13 @@ public class LodBufferBuilder //ClientProxy.LOGGER.info("Buffer Build time: " + buildTime + " ms"); // mark that the buildable buffers as ready to swap - switchVbos = true; - } - catch (Exception e) - { - ClientProxy.LOGGER.warn("\"LodNodeBufferBuilder.generateLodBuffersAsync\" ran into trouble: "); - e.printStackTrace(); - } - finally - { + switchVbos = true; + } catch (Exception e) + { + ClientProxy.LOGGER.warn("\"LodNodeBufferBuilder.generateLodBuffersAsync\" ran into trouble: "); + e.printStackTrace(); + } finally + { // regardless of if we successfully created the buffers // we are done generating. generatingBuffers = false; @@ -472,11 +460,11 @@ public class LodBufferBuilder */ private boolean isCoordInCenterArea(int i, int j, int centerCoordinate) { - return (i >= centerCoordinate - mc.options.renderDistance - && i <= centerCoordinate + mc.options.renderDistance) + return (i >= centerCoordinate - (mc.options.renderDistance + 2) + && i <= centerCoordinate + (mc.options.renderDistance + 2)) && - (j >= centerCoordinate - mc.options.renderDistance - && j <= centerCoordinate + mc.options.renderDistance); + (j >= centerCoordinate - (mc.options.renderDistance + 2) + && j <= centerCoordinate + (mc.options.renderDistance + 2)); } diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 222dfbbfc..dee3cdd51 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -27,13 +27,9 @@ import com.seibel.lod.objects.LevelPos; import com.seibel.lod.objects.LodDataPoint; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.LodWorld; -//import com.seibel.lod.util.BiomeColorsUtils; import com.seibel.lod.util.LodThreadFactory; import com.seibel.lod.util.LodUtil; -//import kaptainwutax.biomeutils.source.OverworldBiomeSource; -//import kaptainwutax.mcutils.version.MCVersion; -//import kaptainwutax.terrainutils.TerrainGenerator; import net.minecraft.block.AbstractPlantBlock; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -42,7 +38,6 @@ import net.minecraft.block.GrassBlock; import net.minecraft.block.IGrowable; import net.minecraft.block.LeavesBlock; import net.minecraft.block.material.MaterialColor; -//import net.minecraft.util.math.ChunkPos; import net.minecraft.world.DimensionType; import net.minecraft.world.IWorld; import net.minecraft.world.biome.Biome; @@ -190,52 +185,6 @@ public class LodBuilder } } - /** - * Creates a LodChunk for a chunk in the given world. - * - * @throws IllegalArgumentException thrown if either the chunk or world is null. - */ - /**TODO if we want to test biome utils and terrain utils - public void generateLodNodeFromChunk(LodDimension lodDim, ChunkPos chunkPos , LodDetail detail, long seed) - throws IllegalArgumentException - { - - if (chunkPos == null) - throw new IllegalArgumentException("generateLodFromChunk given a null chunk pos"); - - int startX; - int startZ; - int endX; - int endZ; - Color color; - short height; - short depth; - LevelPos levelPos; - LodDataPoint data; - - OverworldBiomeSource biomeSource = new OverworldBiomeSource(MCVersion.v1_16_5, seed); - TerrainGenerator terrainGenerator= TerrainGenerator.of(biomeSource); - - for (int i = 0; i < detail.dataPointLengthCount * detail.dataPointLengthCount; i++) - { - startX = detail.startX[i]; - startZ = detail.startZ[i]; - endX = detail.endX[i]; - endZ = detail.endZ[i]; - - color = generateLodColorForArea(biomeSource, chunkPos, startX, startZ, endX, endZ); - height = determineHeightPoint(terrainGenerator, chunkPos, startX, startZ, endX, endZ); - levelPos = new LevelPos((byte) 0, - chunkPos.x * 16 + startX, - chunkPos.z * 16 + startZ); - data = new LodDataPoint(height, 0, color); - lodDim.addData(levelPos.convert((byte) detail.detailLevel), - data, - DistanceGenerationMode.SURFACE, - true, - false); - } - }*/ // =====================// // constructor helpers // @@ -362,26 +311,6 @@ public class LodBuilder return highest; } - /** - * Find the highest point from the Top - */ - /**TODO if we want to test biome utils and terrain utils - private short determineHeightPoint(TerrainGenerator terrainGenerator, ChunkPos chunkPos, int startX, int startZ, int endX, int endZ) - { - short newHeight = 0; - int num = 0; - for (int x = startX; x < endX; x++) - { - for (int z = startZ; z < endZ; z++) - { - num++; - newHeight += (short) terrainGenerator.getFirstHeightInColumn(chunkPos.x*16 + x,chunkPos.z*16 + z, TerrainGenerator.WORLD_SURFACE_WG);; - } - } - - return (short) (newHeight/num); - }*/ - /** * Generate the color for the given chunk using biome water color, foliage * color, and grass color. @@ -481,39 +410,6 @@ public class LodBuilder return new Color(red, green, blue); } -/**TODO if we want to test biome utils and terrain utils - private Color generateLodColorForArea(OverworldBiomeSource biomeSource, ChunkPos chunkPos, int startX, int startZ, int endX, - int endZ) - { - - int numbOfBlocks = 0; - int red = 0; - int green = 0; - int blue = 0; - - for (int x = startX; x < endX; x++) - { - for (int z = startZ; z < endZ; z++) - { - Color color = BiomeColorsUtils.getColorFromBiomeManual(biomeSource.getBiome(chunkPos.x*16 + x,0,chunkPos.z*16 + z)); - red += color.getBlue(); - green += color.getGreen(); - blue += color.getBlue(); - } - } - - if (numbOfBlocks == 0) - numbOfBlocks = 1; - - red /= numbOfBlocks; - green /= numbOfBlocks; - blue /= numbOfBlocks; - - return new Color(red, green, blue); - } - - */ - /** * Returns a color int for a given block. */ diff --git a/src/main/java/com/seibel/lod/enums/DistanceCalculatorType.java b/src/main/java/com/seibel/lod/enums/DistanceCalculatorType.java new file mode 100644 index 000000000..97f4ed09d --- /dev/null +++ b/src/main/java/com/seibel/lod/enums/DistanceCalculatorType.java @@ -0,0 +1,14 @@ +package com.seibel.lod.enums; + +/** + * @author Leonardo Amato + * @version 22-08-2021 + */ +public enum DistanceCalculatorType +{ + /** different Lod detail render and generate linearly to the distance */ + LINEAR, + + /** different Lod detail render and generate quadratically to the distance */ + QUADRATIC, +} \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/enums/DistanceGenerationMode.java b/src/main/java/com/seibel/lod/enums/DistanceGenerationMode.java index d7968af09..fb89e5edb 100644 --- a/src/main/java/com/seibel/lod/enums/DistanceGenerationMode.java +++ b/src/main/java/com/seibel/lod/enums/DistanceGenerationMode.java @@ -34,14 +34,14 @@ package com.seibel.lod.enums; public enum DistanceGenerationMode { /** Don't generate anything */ - NONE(0), + NONE((byte) 0), /** Only generate the biomes and use biome * grass/foliage color, water color, or ice color * to generate the color. * Doesn't generate height, everything is shown at sea level. * Multithreaded - Fastest (2-5 ms) */ - BIOME_ONLY(1), + BIOME_ONLY((byte) 1), /** * Same as BIOME_ONLY, except instead @@ -49,32 +49,32 @@ public enum DistanceGenerationMode * different biome types (mountain, ocean, forest, etc.) * use predetermined heights to simulate having height data. */ - BIOME_ONLY_SIMULATE_HEIGHT(2), + BIOME_ONLY_SIMULATE_HEIGHT((byte) 2), /** Generate the world surface, * this does NOT include caves, trees, * or structures. * Multithreaded - Faster (10-20 ms) */ - SURFACE(3), + SURFACE((byte) 3), /** Generate everything except structures. * NOTE: This may cause world generation bugs or instability, * since some features cause concurrentModification exceptions. * Multithreaded - Fast (15-20 ms) */ - FEATURES(4), + FEATURES((byte) 4), /** Ask the server to generate/load each chunk. * This is the most compatible, but causes server/simulation lag. * This will also show player made structures if you * are adding the mod to a pre-existing world. * Singlethreaded - Slow (15-50 ms, with spikes up to 200 ms) */ - SERVER(5); + SERVER((byte) 5); /** The higher the number the more complete the generation is. */ - public final int complexity; + public final byte complexity; - DistanceGenerationMode(int complexity) + DistanceGenerationMode(byte complexity) { this.complexity = complexity; } diff --git a/src/main/java/com/seibel/lod/handlers/LodConfig.java b/src/main/java/com/seibel/lod/handlers/LodConfig.java index aa0d91cbe..f77b1d387 100644 --- a/src/main/java/com/seibel/lod/handlers/LodConfig.java +++ b/src/main/java/com/seibel/lod/handlers/LodConfig.java @@ -20,18 +20,13 @@ package com.seibel.lod.handlers; 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.DistanceGenerationMode; -import com.seibel.lod.enums.FogDistance; -import com.seibel.lod.enums.FogDrawOverride; -import com.seibel.lod.enums.LodDetail; -import com.seibel.lod.enums.LodTemplate; -import com.seibel.lod.enums.ShadingMode; import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -77,6 +72,8 @@ public class LodConfig */ public ForgeConfigSpec.IntValue lodChunkRadiusMultiplier; + public ForgeConfigSpec.EnumValue lodDistanceCalculatorType; + public ForgeConfigSpec.IntValue lodQuality; public ForgeConfigSpec.IntValue lodChunkRenderDistane; @@ -160,6 +157,29 @@ public class LodConfig + " of LODs in each cardinal direction. \n") .defineInRange("lodChunkRadiusMultiplier", 8, 2, 16); + lodDistanceCalculatorType = builder + .comment("\n\n" + + " " + DistanceCalculatorType.LINEAR + " \n" + + " with LINEAR calculator the quality of block decrease \n" + + " linearly to the distance of the player \n" + + + "\n" + + " " + DistanceCalculatorType.QUADRATIC + " \n" + + " with LINEAR calculator the quality of block decrease \n" + + " quadratically to the distance of the player \n") + .defineEnum("lodDistanceComputation", DistanceCalculatorType.LINEAR); + + lodQuality = builder + .comment("\n\n" + + " this value is multiplied by 128 and determine \n" + + " how much the quality decrease over distance \n") + .defineInRange("lodChunkRadiusMultiplier", 1, 1, 4); + + lodChunkRenderDistane = builder + .comment("\n\n" + + " This is the render distance of the mod \n") + .defineInRange("lodChunkRadiusMultiplier", 128, 32, 128); + distanceGenerationMode = builder .comment("\n\n" + " Note: The times listed here are the amount of time it took \n" diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index b1614edaa..2164f9dad 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -321,7 +321,7 @@ public class LodDimension region = new LodRegion((byte) 0, regionPos); addOrOverwriteRegion(region); } - boolean nodeAdded = region.setData(levelPos, lodDataPoint, (byte) generationMode.complexity, true); + boolean nodeAdded = region.setData(levelPos, lodDataPoint, generationMode.complexity, true); // only save valid LODs to disk if (!dontSave && fileHandler != null) { diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index b0ee10f38..886c761c8 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -205,6 +205,8 @@ public class LodRegion implements Serializable } /** + * This method will return all the levelPos that are renderable according to the requisite given in input + * * @return */ public List> getDataToGenerate(int playerPosX, int playerPosZ, int start, int end, byte generation, byte detailLevel, int dataNumber) diff --git a/src/main/java/com/seibel/lod/proxy/ClientProxy.java b/src/main/java/com/seibel/lod/proxy/ClientProxy.java index 4d68a98c9..d10a61b11 100644 --- a/src/main/java/com/seibel/lod/proxy/ClientProxy.java +++ b/src/main/java/com/seibel/lod/proxy/ClientProxy.java @@ -17,17 +17,13 @@ */ package com.seibel.lod.proxy; +import com.seibel.lod.enums.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.seibel.lod.builders.LodBufferBuilder; import com.seibel.lod.builders.LodBuilder; import com.seibel.lod.builders.worldGeneration.LodNodeGenWorker; -import com.seibel.lod.enums.DistanceGenerationMode; -import com.seibel.lod.enums.FogDistance; -import com.seibel.lod.enums.FogDrawOverride; -import com.seibel.lod.enums.LodDetail; -import com.seibel.lod.enums.ShadingMode; import com.seibel.lod.handlers.LodConfig; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.LodWorld; @@ -151,6 +147,10 @@ public class ClientProxy LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.FEATURES); LodConfig.CLIENT.allowUnstableFeatureGeneration.set(false); + LodConfig.CLIENT.lodChunkRenderDistane.set(96); + LodConfig.CLIENT.lodDistanceCalculatorType.set(DistanceCalculatorType.LINEAR); + LodConfig.CLIENT.lodQuality.set(1); + LodConfig.CLIENT.allowUnstableFeatureGeneration.set(false); // has to be set in the config file // LodConfig.CLIENT.numberOfWorldGenerationThreads.set(16); diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java index 1b14b98d2..73e1ee615 100644 --- a/src/main/java/com/seibel/lod/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/render/LodRenderer.java @@ -229,11 +229,11 @@ public class LodRenderer // determine how far the game's render distance is currently set //farPlaneBlockDistance = mc.options.renderDistance * LodUtil.CHUNK_WIDTH; - farPlaneBlockDistance = 8 * LodUtil.CHUNK_WIDTH; + farPlaneBlockDistance = LodConfig.CLIENT.lodChunkRenderDistane.get() * LodUtil.CHUNK_WIDTH; // set how how far the LODs will go //int numbChunksWide = mc.options.renderDistance * 2 * LodConfig.CLIENT.lodChunkRadiusMultiplier.get(); - int numbChunksWide = 8 * 2 * LodConfig.CLIENT.lodChunkRadiusMultiplier.get() + 1; + int numbChunksWide =LodConfig.CLIENT.lodChunkRenderDistane.get() * 2; // determine which LODs should not be rendered close to the player HashSet chunkPosToSkip = getNearbyLodChunkPosToSkip(lodDim, player.blockPosition()); @@ -461,12 +461,12 @@ public class LodRenderer { if (fogQuality == FogQuality.FANCY) { - RenderSystem.fogStart(farPlaneBlockDistance * 0.85f * LodConfig.CLIENT.lodChunkRadiusMultiplier.get()); - RenderSystem.fogEnd(farPlaneBlockDistance * 1.0f * LodConfig.CLIENT.lodChunkRadiusMultiplier.get()); + RenderSystem.fogStart(farPlaneBlockDistance * 0.85f); + RenderSystem.fogEnd(farPlaneBlockDistance * 1.0f); } else if (fogQuality == FogQuality.FAST) { - RenderSystem.fogStart(farPlaneBlockDistance * 0.5f * LodConfig.CLIENT.lodChunkRadiusMultiplier.get()); - RenderSystem.fogEnd(farPlaneBlockDistance * 0.75f * LodConfig.CLIENT.lodChunkRadiusMultiplier.get()); + RenderSystem.fogStart(farPlaneBlockDistance * 0.5f); + RenderSystem.fogEnd(farPlaneBlockDistance * 0.75f); } } diff --git a/src/main/java/com/seibel/lod/util/BiomeColorsUtils.java b/src/main/java/com/seibel/lod/util/BiomeColorsUtils.java deleted file mode 100644 index f08d7540a..000000000 --- a/src/main/java/com/seibel/lod/util/BiomeColorsUtils.java +++ /dev/null @@ -1,719 +0,0 @@ -/* - * 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.util; - -import net.minecraft.block.Blocks; -import net.minecraft.world.biome.*; - -import java.awt.*; - -public class BiomeColorsUtils { - //public static OverworldBiomeSource overworldBiomeSource = new OverworldBiomeSource(MCVersion.v1_16_4, 64971835648254); - - public static Color getColorFromBiome(Biome biome,double x, double y){ - int color = 0; - switch(biome.getBiomeCategory()) { - case BEACH: - case DESERT: - color = Blocks.SAND.defaultMaterialColor().col; - break; - case EXTREME_HILLS: - color = Blocks.SNOW.defaultMaterialColor().col; - break; - case NONE: - break; - case FOREST: - case JUNGLE: - case TAIGA: - color = biome.getFoliageColor(); - break; - case MUSHROOM: - color = Blocks.MYCELIUM.defaultMaterialColor().col; - break; - case PLAINS: - case SAVANNA: - color = biome.getGrassColor(x,y); - break; - case OCEAN: - case RIVER: - case SWAMP: - color = biome.getWaterColor(); - break; - case ICY: - color = Blocks.PACKED_ICE.defaultMaterialColor().col; - break; - case THEEND: - color = Blocks.END_STONE.defaultMaterialColor().col; - break; - case NETHER: - color = Blocks.NETHERRACK.defaultMaterialColor().col; - break; - case MESA: - color = Blocks.RED_SAND.defaultMaterialColor().col; - break; - default: - color = 0; - } - return new Color(color); - } - - public static Color getColorFromBiome(Biome biome){ - int color = 0; - switch(biome.getBiomeCategory()) { - case BEACH: - case DESERT: - color = Blocks.SAND.defaultMaterialColor().col; - break; - case EXTREME_HILLS: - color = Blocks.SNOW.defaultMaterialColor().col; - break; - case FOREST: - case SAVANNA: - case JUNGLE: - case TAIGA: - color = biome.getFoliageColor(); - break; - case MUSHROOM: - color = Blocks.MYCELIUM.defaultMaterialColor().col; - break; - case PLAINS: - color = Blocks.GRASS_BLOCK.defaultMaterialColor().col; - break; - case OCEAN: - case RIVER: - case SWAMP: - color = biome.getWaterColor(); - break; - case ICY: - color = Blocks.PACKED_ICE.defaultMaterialColor().col; - break; - case THEEND: - color = Blocks.END_STONE.defaultMaterialColor().col; - break; - case NETHER: - color = Blocks.NETHERRACK.defaultMaterialColor().col; - break; - case MESA: - color = Blocks.RED_SAND.defaultMaterialColor().col; - break; - case NONE: - default: - color = 0; - } - return new Color(color); - } - - /** - * methods that gives the ChunkBase color of biomes - * @param biome to check - * @return color of the biome - */ - public static Color getColorFromIdRealistic(kaptainwutax.biomeutils.biome.Biome biome){ - Biome.Builder builder = new Biome.Builder(); - int color = 0; - switch(biome.getCategory()) { - case BEACH: - case DESERT: - color = Blocks.SAND.defaultMaterialColor().col; - break; - case EXTREME_HILLS: - color = Blocks.SNOW.defaultMaterialColor().col; - break; - case FOREST: - builder.biomeCategory(Biome.Category.FOREST); - color = builder.build().getFoliageColor(); - break; - case SAVANNA: - builder.biomeCategory(Biome.Category.SAVANNA); - color = builder.build().getFoliageColor(); - break; - case JUNGLE: - builder.biomeCategory(Biome.Category.JUNGLE); - color = builder.build().getFoliageColor(); - break; - case TAIGA: - builder.biomeCategory(Biome.Category.TAIGA); - color = builder.build().getFoliageColor(); - break; - case MUSHROOM: - color = Blocks.MYCELIUM.defaultMaterialColor().col; - break; - case PLAINS: - color = Blocks.GRASS_BLOCK.defaultMaterialColor().col; - break; - case OCEAN: - builder.biomeCategory(Biome.Category.OCEAN); - color = builder.build().getWaterColor(); - break; - case RIVER: - builder.biomeCategory(Biome.Category.RIVER); - color = builder.build().getWaterColor(); - break; - case SWAMP: - builder.biomeCategory(Biome.Category.SWAMP); - color = builder.build().getWaterColor(); - break; - case ICY: - color = Blocks.PACKED_ICE.defaultMaterialColor().col; - break; - case THE_END: - color = Blocks.END_STONE.defaultMaterialColor().col; - break; - case NETHER: - color = Blocks.NETHERRACK.defaultMaterialColor().col; - break; - case BADLANDS_PLATEAU: - case MESA: - color = Blocks.RED_SAND.defaultMaterialColor().col; - break; - case NONE: - default: - color = 0; - } - return new Color(color); - } - - /** - * methods that gives the ChunkBase color of biomes - * @param biome to check - * @return color of the biome - */ - public static Color getColorFromBiomeBlock(kaptainwutax.biomeutils.biome.Biome biome){ - int color = 0; - switch(biome.getCategory()) { - case BEACH: - case DESERT: - color = Blocks.SAND.defaultMaterialColor().col; - break; - case EXTREME_HILLS: - color = Blocks.SNOW.defaultMaterialColor().col; - break; - case FOREST: - color = Blocks.OAK_LEAVES.defaultMaterialColor().col; - break; - case SAVANNA: - color = Blocks.ACACIA_LEAVES.defaultMaterialColor().col; - break; - case JUNGLE: - color = Blocks.JUNGLE_LEAVES.defaultMaterialColor().col; - break; - case TAIGA: - color = Blocks.SPRUCE_LEAVES.defaultMaterialColor().col; - break; - case MUSHROOM: - color = Blocks.MYCELIUM.defaultMaterialColor().col; - break; - case PLAINS: - color = Blocks.GRASS_BLOCK.defaultMaterialColor().col; - break; - case OCEAN: - case RIVER: - color = Blocks.WATER.defaultMaterialColor().col; - case SWAMP: - color = Blocks.LILY_PAD.defaultMaterialColor().col; - break; - case ICY: - color = Blocks.PACKED_ICE.defaultMaterialColor().col; - break; - case THE_END: - color = Blocks.END_STONE.defaultMaterialColor().col; - break; - case NETHER: - color = Blocks.NETHERRACK.defaultMaterialColor().col; - break; - case BADLANDS_PLATEAU: - case MESA: - color = Blocks.RED_SAND.defaultMaterialColor().col; - break; - case NONE: - default: - color = 0; - } - return new Color(color); - } - - /** - * methods that gives the ChunkBase color of biomes - * @param biome to check - * @return color of the biome - */ - public static Color getColorFromBiomeManual(kaptainwutax.biomeutils.biome.Biome biome){ - Color color; - switch(biome.getCategory()) { - case BEACH: - case DESERT: - color = new Color(220,214,170); - break; - case EXTREME_HILLS: - color = new Color(81,129,60); - break; - case FOREST: - color = new Color(81,129,60); - break; - case SAVANNA: - color = new Color(119,113,53); - break; - case JUNGLE: - color = new Color(41,141,4); - break; - case TAIGA: - color = new Color(70,95,68); - break; - case MUSHROOM: - color = new Color(123,105,109); - break; - case PLAINS: - color = new Color(96,125,59); - break; - case OCEAN: - case RIVER: - color = new Color(54,73,229); - break; - case SWAMP: - color = new Color(83,86,67); - break; - case ICY: - color = new Color(199,217,254); - break; - case THE_END: - color = new Color(100,100,0); - break; - case NETHER: - color = new Color(100,0,0); - break; - case BADLANDS_PLATEAU: - case MESA: - color = new Color(188,103,39); - break; - case NONE: - color = new Color(96,125,59); - break; - default: - color = new Color(0,0,0,0); - } - return color; - } - - /** - * methods that gives the ChunkBase color of biomes - * @param biomeId id of the biome - * @return color of the biome - */ - public static Color getColorFromIdCB(int biomeId){ - int red=0; - int green=0; - int blue=0; - switch(biomeId) { - case 0: - red = 0; - green = 0; - blue = 112; - break; - case 1: - red = 141; - green = 179; - blue = 96; - break; - case 2: - red = 250; - green = 148; - blue = 24; - break; - case 3: - red = 96; - green = 96; - blue = 96; - break; - case 4: - red = 5; - green = 102; - blue = 33; - break; - case 5: - red = 11; - green = 2; - blue = 89; - break; - case 6: - red = 7; - green = 249; - blue = 178; - break; - case 7: - red = 0; - green = 0; - blue = 255; - break; - case 8: - red = 255; - green = 0; - blue = 0; - break; - case 9: - red = 128; - green = 128; - blue = 255; - break; - case 10: - red = 112; - green = 112; - blue = 214; - break; - case 11: - red = 160; - green = 160; - blue = 255; - break; - case 12: - red = 255; - green = 255; - blue = 255; - break; - case 13: - red = 160; - green = 160; - blue = 160; - break; - case 14: - red = 255; - green = 0; - blue = 255; - break; - case 15: - red = 160; - green = 0; - blue = 255; - break; - case 16: - red = 250; - green = 222; - blue = 85; - break; - case 17: - red = 210; - green = 95; - blue = 18; - break; - case 18: - red = 34; - green = 85; - blue = 28; - break; - case 19: - red = 22; - green = 57; - blue = 51; - break; - case 20: - red = 114; - green = 120; - blue = 154; - break; - case 21: - red = 83; - green = 123; - blue = 9; - break; - case 22: - red = 44; - green = 66; - blue = 5; - break; - case 23: - red = 98; - green = 139; - blue = 23; - break; - case 24: - red = 0; - green = 0; - blue = 48; - break; - case 25: - red = 162; - green = 162; - blue = 132; - break; - case 26: - red = 250; - green = 240; - blue = 192; - break; - case 27: - red = 48; - green = 116; - blue = 68; - break; - case 28: - red = 31; - green = 5; - blue = 50; - break; - case 29: - red = 64; - green = 81; - blue = 26; - break; - case 30: - red = 49; - green = 85; - blue = 74; - break; - case 31: - red = 36; - green = 63; - blue = 54; - break; - case 32: - red = 89; - green = 102; - blue = 81; - break; - case 33: - red = 69; - green = 7; - blue = 62; - break; - case 34: - red = 80; - green = 112; - blue = 80; - break; - case 35: - red = 189; - green = 18; - blue = 95; - break; - case 36: - red = 167; - green = 157; - blue = 100; - break; - case 37: - red = 217; - green = 69; - blue = 21; - break; - case 38: - red = 17; - green = 151; - blue = 101; - break; - case 39: - red = 202; - green = 140; - blue = 101; - break; - case 40: - red = 128; - green = 128; - blue = 255; - break; - case 41: - red = 128; - green = 128; - blue = 255; - break; - case 42: - red = 128; - green = 128; - blue = 255; - break; - case 43: - red = 128; - green = 128; - blue = 255; - break; - case 44: - red = 0; - green = 0; - blue = 172; - break; - case 45: - red = 0; - green = 0; - blue = 144; - break; - case 46: - red = 32; - green = 32; - blue = 112; - break; - case 47: - red = 0; - green = 0; - blue = 80; - break; - case 48: - red = 0; - green = 0; - blue = 64; - break; - case 49: - red = 32; - green = 32; - blue = 56; - break; - case 50: - red = 64; - green = 64; - blue = 144; - break; - case 127: - red = 0; - green = 0; - blue = 0; - break; - case 129: - red = 181; - green = 219; - blue = 136; - break; - case 130: - red = 255; - green = 188; - blue = 64; - break; - case 131: - red = 136; - green = 136; - blue = 136; - break; - case 132: - red = 45; - green = 142; - blue = 73; - break; - case 133: - red = 51; - green = 142; - blue = 19; - break; - case 134: - red = 47; - green = 255; - blue = 18; - break; - case 140: - red = 180; - green = 20; - blue = 220; - break; - case 149: - red = 123; - green = 13; - blue = 49; - break; - case 151: - red = 138; - green = 179; - blue = 63; - break; - case 155: - red = 88; - green = 156; - blue = 108; - break; - case 156: - red = 71; - green = 15; - blue = 90; - break; - case 157: - red = 104; - green = 121; - blue = 66; - break; - case 158: - red = 89; - green = 125; - blue = 114; - break; - case 160: - red = 129; - green = 142; - blue = 121; - break; - case 161: - red = 109; - green = 119; - blue = 102; - break; - case 162: - red = 120; - green = 52; - blue = 120; - break; - case 163: - red = 229; - green = 218; - blue = 135; - break; - case 164: - red = 207; - green = 197; - blue = 140; - break; - case 165: - red = 255; - green = 109; - blue = 61; - break; - case 166: - red = 216; - green = 191; - blue = 141; - break; - case 167: - red = 242; - green = 180; - blue = 141; - break; - case 168: - red = 118; - green = 142; - blue = 20; - break; - case 169: - red = 59; - green = 71; - blue = 10; - break; - case 170: - red = 82; - green = 41; - blue = 33; - break; - case 171: - red = 221; - green = 8; - blue = 8; - break; - case 172: - red = 73; - green = 144; - blue = 123; - break; - default: - red = 255; - green = 0; - blue = 0; - } - return new Color(red, green, blue); - } -} diff --git a/src/main/java/com/seibel/lod/util/DetailUtil.java b/src/main/java/com/seibel/lod/util/DetailUtil.java new file mode 100644 index 000000000..3877d2106 --- /dev/null +++ b/src/main/java/com/seibel/lod/util/DetailUtil.java @@ -0,0 +1,57 @@ +package com.seibel.lod.util; + +import com.seibel.lod.enums.DistanceCalculatorType; +import com.seibel.lod.enums.DistanceGenerationMode; +import com.seibel.lod.enums.LodQuality; +import com.seibel.lod.handlers.LodConfig; + +public class DetailUtil +{ + private static double genMultiplier = 1.5; + private static final int maxDetail = LodUtil.REGION_DETAIL_LEVEL + 1; + private static final int minDistance = 0; + private static final int maxDistance = LodConfig.CLIENT.lodChunkRenderDistane.get() * 16; + private static DistanceGenerationMode[] distancesGenerators = { + DistanceGenerationMode.SURFACE, + DistanceGenerationMode.SURFACE, + DistanceGenerationMode.SURFACE, + DistanceGenerationMode.SURFACE, + DistanceGenerationMode.SURFACE, + DistanceGenerationMode.SURFACE, + DistanceGenerationMode.SURFACE, + DistanceGenerationMode.SURFACE, + DistanceGenerationMode.SURFACE, + DistanceGenerationMode.SURFACE}; + + + public static int getDistanceRendering(int detail) + { + int distance = 0; + int initial = LodConfig.CLIENT.lodQuality.get() * 128; + switch (LodConfig.CLIENT.lodDistanceCalculatorType.get()) + { + case LINEAR: + distance = (detail * initial); + break; + case QUADRATIC: + if (detail == 0) + distance = minDistance; + else if(detail == maxDetail) + distance = maxDistance; + else + distance = (int) (Math.pow(2, detail) * initial); + break; + } + return distance; + } + + public static int getDistanceGeneration(int detail) + { + return (int) (getDistanceRendering(detail) * genMultiplier); + } + + public static DistanceGenerationMode getDistanceGenerationMode(int detail) + { + return distancesGenerators[detail]; + } +}