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 66393a5cf..da2a42865 100644 --- a/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java @@ -110,10 +110,6 @@ public class LodBuilder /** Minecraft's max light value */ public static final short DEFAULT_MAX_LIGHT = 15; - /** TODO is this needed / used? */ - public static final boolean avoidNonFullBlock = false; - /** TODO is this needed / used? */ - public static final boolean avoidSmallBlock = false; /** * How wide LodDimensions should be in regions
@@ -788,18 +784,17 @@ public class LodBuilder private boolean isLayerValidLodPoint(IChunk chunk, BlockPos.Mutable blockPos) { BlockState blockState = chunk.getBlockState(blockPos); - - + boolean avoidNonFullBlock = LodConfig.CLIENT.worldGenerator.avoidNonFullBlock.get(); + boolean avoidBlockWithNoCollision = LodConfig.CLIENT.worldGenerator.avoidBlockWithNoCollision.get(); if (blockState != null) { // TODO this code is dead since avoidSmallBlock and onlyUseFullBlock // are set to false and are never changed. // should this code be changed? - if (avoidSmallBlock || avoidNonFullBlock) + + if (avoidNonFullBlock) { - if (!smallBlock.containsKey(blockState.getBlock()) - || smallBlock.get(blockState.getBlock()) == null - || !notFullBlock.containsKey(blockState.getBlock()) + if (!notFullBlock.containsKey(blockState.getBlock()) || notFullBlock.get(blockState.getBlock()) == null ) { @@ -807,7 +802,6 @@ public class LodBuilder if (!blockState.getFluidState().isEmpty()) { notFullBlock.put(blockState.getBlock(), false); - smallBlock.put(blockState.getBlock(), false); } if (!voxelShape.isEmpty()) @@ -820,22 +814,55 @@ 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 { notFullBlock.put(blockState.getBlock(), false); - smallBlock.put(blockState.getBlock(), false); } } - if (notFullBlock.get(blockState.getBlock()) && avoidNonFullBlock) + if (notFullBlock.get(blockState.getBlock())) return false; - if (smallBlock.get(blockState.getBlock()) && avoidSmallBlock) + } + + if (avoidBlockWithNoCollision) + { + if (!smallBlock.containsKey(blockState.getBlock()) + || smallBlock.get(blockState.getBlock()) == null + ) + { + if(!blockState.getFluidState().isEmpty()) + smallBlock.put(blockState.getBlock(), false); + + VoxelShape voxelShape = blockState.getCollisionShape(chunk, blockPos); + if (!blockState.getFluidState().isEmpty()) + { + smallBlock.put(blockState.getBlock(), false); + } + else + { + + if (voxelShape.isEmpty()) + { + smallBlock.put(blockState.getBlock(), true); + /*AxisAlignedBB bbox = voxelShape.bounds(); + int xWidth = (int) (bbox.maxX - bbox.minX); + int yWidth = (int) (bbox.maxY - bbox.minY); + int zWidth = (int) (bbox.maxZ - bbox.minZ); + + if (xWidth < 0.7 && zWidth < 0.7 && yWidth < 0.7) + smallBlock.put(blockState.getBlock(), true); + else + smallBlock.put(blockState.getBlock(), false);*/ + } + else + { + smallBlock.put(blockState.getBlock(), false); + } + } + } + + if (smallBlock.get(blockState.getBlock())) 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 6cae3b764..a6938d688 100644 --- a/src/main/java/com/seibel/lod/config/LodConfig.java +++ b/src/main/java/com/seibel/lod/config/LodConfig.java @@ -108,95 +108,95 @@ 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 abruptly 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 abruptly 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 each 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 each 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-chunk (best quality option, may cause stuttering when moving)\n" - + DetailDropOff.FAST + ": quality is determined per-region \n") - .defineEnum("detailDropOff", DetailDropOff.FANCY); + .comment("\n\n" + + " How smooth should the detail transition for LODs be? \n" + + DetailDropOff.FANCY + ": quality is determined per-chunk (best quality option, may cause stuttering when moving)\n" + + DetailDropOff.FAST + ": quality is determined per-region \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); 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 disappearing. \n" - + " (Which 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 disappearing. \n" + + " (Which may happen if you are using a camera mod) \n") + .define("disableDirectionalCulling", false); alwaysDrawAtMaxQuality = builder - .comment("\n\n" - + " Disable LOD quality falloff, \n" - + " all LODs will be drawn at the highest \n" - + " available detail level. \n\n" - + " " - + " WARNING: \n" - + " This could cause a Out Of Memory crash on render \n" - + " distances higher than 128 \n") - .define("alwaysDrawAtMaxQuality", false); + .comment("\n\n" + + " Disable LOD quality falloff, \n" + + " all LODs will be drawn at the highest \n" + + " available detail level. \n\n" + + " " + + " WARNING: \n" + + " This could cause a Out Of Memory crash on render \n" + + " distances higher than 128 \n") + .define("alwaysDrawAtMaxQuality", false); vanillaOverdraw = builder - .comment("\n\n" - + " How often should LODs be drawn on top of regular chunks? \n" - + " HALF and ALWAYS will prevent holes in the world, but may look odd for transparent blocks or in caves. \n\n" - + " " + VanillaOverdraw.NEVER + ": LODs won't render on top of vanilla chunks. \n" - + " " + VanillaOverdraw.DYNAMIC + ": LODs will render on top of distant vanilla chunks to hide delayed loading. \n" - + " " + " More effective on higher render distances. \n" - + " " + " For vanilla render distances less than or equal to " + LodUtil.MINIMUM_RENDER_DISTANCE_FOR_PARTIAL_OVERDRAW + " \n" - + " " + " " + VanillaOverdraw.NEVER + " or " + VanillaOverdraw.ALWAYS + " may be used depending on the dimension. \n" - + " " + VanillaOverdraw.ALWAYS + ": LODs will render on all vanilla chunks preventing holes in the world. \n") - .defineEnum("vanillaOverdraw", VanillaOverdraw.DYNAMIC); + .comment("\n\n" + + " How often should LODs be drawn on top of regular chunks? \n" + + " HALF and ALWAYS will prevent holes in the world, but may look odd for transparent blocks or in caves. \n\n" + + " " + VanillaOverdraw.NEVER + ": LODs won't render on top of vanilla chunks. \n" + + " " + VanillaOverdraw.DYNAMIC + ": LODs will render on top of distant vanilla chunks to hide delayed loading. \n" + + " " + " More effective on higher render distances. \n" + + " " + " For vanilla render distances less than or equal to " + LodUtil.MINIMUM_RENDER_DISTANCE_FOR_PARTIAL_OVERDRAW + " \n" + + " " + " " + VanillaOverdraw.NEVER + " or " + VanillaOverdraw.ALWAYS + " may be used depending on the dimension. \n" + + " " + VanillaOverdraw.ALWAYS + ": LODs will render on all vanilla chunks preventing holes in the world. \n") + .defineEnum("vanillaOverdraw", VanillaOverdraw.DYNAMIC); builder.pop(); } @@ -211,126 +211,141 @@ public class LodConfig public final ForgeConfigSpec.BooleanValue allowUnstableFeatureGeneration; public final ForgeConfigSpec.EnumValue horizontalScale; public final ForgeConfigSpec.EnumValue horizontalQuality; + public final ForgeConfigSpec.BooleanValue avoidBlockWithNoCollision; + public final ForgeConfigSpec.BooleanValue avoidNonFullBlock; WorldGenerator(ForgeConfigSpec.Builder builder) { builder.comment("These settings control how LODs outside your normal view range are generated.").push(this.getClass().getSimpleName()); verticalQuality = builder - .comment("\n\n" - + " This indicates how detailed the LODs will be in representing \n" - + " overhangs, caves, floating islands, ect. \n" - + " Higher options will use more memory and lower performance. \n" - + " " + VerticalQuality.LOW + ": uses at max 2 columns per position. \n" - + " " + VerticalQuality.HIGH + ": uses at max 8 columns per position. \n") - .defineEnum("Vertical Quality", VerticalQuality.MEDIUM); + .comment("\n\n" + + " This indicates how detailed the LODs will be in representing \n" + + " overhangs, caves, floating islands, ect. \n" + + " Higher options will use more memory and lower performance. \n" + + " " + VerticalQuality.LOW + ": uses at max 2 columns per position. \n" + + " " + VerticalQuality.HIGH + ": uses at max 8 columns per position. \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 away 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); + .comment("\n\n" + + " " + GenerationPriority.FAR_FIRST + " \n" + + " LODs are generated from low to high detail \n" + + " with a small priority for far away 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); 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" - + "\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 + " \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 trees, \n" - + " or structures. \n" - + " Multithreaded - Faster (10-20 ms) \n" + + "\n" + + " " + DistanceGenerationMode.SURFACE + " \n" + + " Generate the world surface, \n" + + " this does NOT include 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 will show player made structures, which can \n" - + " be useful if you are adding the mod to a pre-existing world. \n" - + " This is the most compatible, but causes server/simulation lag. \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 will show player made structures, which can \n" + + " be useful if you are adding the mod to a pre-existing world. \n" + + " This is the most compatible, but causes server/simulation lag. \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); + avoidBlockWithNoCollision = builder + .comment("\n\n" + + " if true avoid block that have no collision box in the generation \n" + + " grass, \n") + .define("avoid Block With No Collision", false); + + avoidNonFullBlock = builder + .comment("\n\n" + + " If you are a Java wizard, check out the git issue here: \n" + + " If you are a Java wizard, check out the git issue here: \n") + .define("avoid Non Full Block", false); builder.pop(); } } @@ -345,27 +360,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 usage 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 usage 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(); } @@ -381,17 +396,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(); } @@ -406,10 +421,10 @@ public class LodConfig builder.comment("These settings affect when Vertex Buffers are built.").push(this.getClass().getSimpleName()); rebuildTimes = builder - .comment("\n\n" - + " How frequently should geometry be rebuilt and sent to the GPU? \n" - + " Faster settings may cause stuttering, but will prevent holes in the world \n") - .defineEnum("rebuildFrequency", BufferRebuildTimes.NORMAL); + .comment("\n\n" + + " How frequently should geometry be rebuilt and sent to the GPU? \n" + + " Faster settings may cause stuttering, but will prevent holes in the world \n") + .defineEnum("rebuildFrequency", BufferRebuildTimes.NORMAL); builder.pop(); } @@ -429,8 +444,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/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java index 0d1c83820..9ba605086 100644 --- a/src/main/java/com/seibel/lod/objects/LevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java @@ -1,5 +1,8 @@ package com.seibel.lod.objects; +/** + * A level container is a quad tree level + */ public interface LevelContainer { /**With this you can add data to the level container @@ -81,10 +84,4 @@ public interface LevelContainer * @return data as a String */ int getMaxNumberOfLods(); - - /** - * This will give the data to save in the file - * @return data as a String - */ - int getMaxMemoryUse(); } diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index 94ac415d2..dd01a9186 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -10,7 +10,7 @@ import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; /** - * This object holds all loaded LevelContainers + * This object holds all loaded LevelContainers acting as a quad tree * for a given region.

* * Coordinate Standard:
@@ -500,7 +500,7 @@ public class LodRegion for (byte detailLevelIndex = (byte) (minDetailLevel - 1); detailLevelIndex >= detailLevel; detailLevelIndex--) { if (dataContainer[detailLevelIndex + 1] == null) - dataContainer[detailLevelIndex + 1] = new SingleLevelContainer((byte) (detailLevelIndex + 1)); + dataContainer[detailLevelIndex + 1] = new VerticalLevelContainer((byte) (detailLevelIndex + 1)); dataContainer[detailLevelIndex] = dataContainer[detailLevelIndex + 1].expand(); } diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java deleted file mode 100644 index 8ce158e1e..000000000 --- a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java +++ /dev/null @@ -1,233 +0,0 @@ -package com.seibel.lod.objects; - -import com.seibel.lod.util.DataPointUtil; -import com.seibel.lod.util.LevelPosUtil; -import com.seibel.lod.util.LodUtil; -import com.seibel.lod.util.ThreadMapUtil; - -import java.util.Arrays; - -/** - * This object holds the LOD data for a single dataPoint. - * - * @author Leonardo Amato - * @version 9-28-2021 - */ -public class SingleLevelContainer implements LevelContainer -{ - /** The detailLevel of this LevelContainer */ - public final byte detailLevel; - /** How many dataPoints wide is this LevelContainer? */ - public final int dataWidthCount; - - /** This holds all the dataPoints for this LevelContainer */ - public final long[][] dataContainer; - - - - /** Constructor */ - public SingleLevelContainer(byte newDetailLevel) - { - this.detailLevel = newDetailLevel; - - // equivalent to 2^(...) - dataWidthCount = 1 << (LodUtil.REGION_DETAIL_LEVEL - newDetailLevel); - dataContainer = new long[dataWidthCount][dataWidthCount]; - } - - /** */ - public SingleLevelContainer(byte[] inputData) - { - int tempIndex; - int index = 0; - long newData; - detailLevel = inputData[index]; - index++; - dataWidthCount = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel); - this.dataContainer = new long[dataWidthCount][dataWidthCount]; - - for (int x = 0; x < dataWidthCount; x++) - { - for (int z = 0; z < dataWidthCount; z++) - { - newData = 0; - if (inputData[index] == 0) - { - index++; - } - else if (inputData[index] == 3) - { - newData = 3; - index++; - } - else if (index + 7 >= inputData.length) - { - break; - } - else - { - for (tempIndex = 0; tempIndex < 8; tempIndex++) - newData += (((long) inputData[index + tempIndex]) & 0xff) << (8 * tempIndex); - index = index + 8; - } - - dataContainer[x][z] = newData; - } - } - } - - - - - - @Override - public void clear(int posX, int posZ) - { - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - dataContainer[posX][posZ] = DataPointUtil.EMPTY_DATA; - } - - @Override - public boolean addData(long data, int posX, int posZ, int index) - { - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - dataContainer[posX][posZ] = data; - return true; - } - - @Override - public boolean addSingleData(long newData, int posX, int posZ) - { - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - dataContainer[posX][posZ] = newData; - return true; - } - - @Override - public long getData(int posX, int posZ, int index) - { - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - // TODO Improve this using a thread map to long[] - return dataContainer[posX][posZ]; - } - - @Override - public long getSingleData(int posX, int posZ) - { - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - // TODO Improve this using a thread map to long[] - return dataContainer[posX][posZ]; - } - - @Override - public byte getDetailLevel() - { - return detailLevel; - } - - @Override - public LevelContainer expand() - { - return new SingleLevelContainer((byte) (getDetailLevel() - 1)); - } - - - - /** TODO could this be renamed mergeData? */ - @Override - public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ) - { - //We reset the array - long[] dataToMerge = ThreadMapUtil.getSingleUpdateArray(); - - int childPosX; - int childPosZ; - long data; - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - for (int x = 0; x <= 1; x++) - { - for (int z = 0; z <= 1; z++) - { - childPosX = 2 * posX + x; - childPosZ = 2 * posZ + z; - dataToMerge[2 * x + z] = lowerLevelContainer.getSingleData(childPosX, childPosZ); - } - } - data = DataPointUtil.mergeSingleData(dataToMerge); - addSingleData(data, posX, posZ); - } - - @Override - public int getMaxVerticalData() - { - return 1; - } - - @Override - public boolean doesItExist(int posX, int posZ) - { - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - //Improve this using a thread map to long[] - return DataPointUtil.doesItExist(getSingleData(posX, posZ)); - } - - @Override - public byte[] toDataString() - { - int index = 0; - int tempIndex; - byte[] tempData = ThreadMapUtil.getSaveContainer(1 + (dataWidthCount * dataWidthCount * 8)); - - tempData[index] = detailLevel; - index++; - for (int x = 0; x < dataWidthCount; x++) - { - for (int z = 0; z < dataWidthCount; z++) - { - if (dataContainer[x][z] == 0) - { - tempData[index] = 0; - index++; - } - else if (dataContainer[x][z] == 3) - { - tempData[index] = 3; - index++; - } - else - { - for (tempIndex = 0; tempIndex < 8; tempIndex++) - tempData[index + tempIndex] = (byte) (dataContainer[x][z] >>> (8 * tempIndex)); - index += 8; - } - } - } - return Arrays.copyOfRange(tempData, 0, index); - } - - @Override - public String toString() - { - return String.valueOf(detailLevel); - } - - - @Override - public int getMaxNumberOfLods() - { - return dataWidthCount * dataWidthCount * getMaxVerticalData(); - } - - @Override - public int getMaxMemoryUse() - { - return getMaxNumberOfLods() * 2; //2 byte - } -} diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java index 2526b5523..633cb68e0 100644 --- a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java @@ -8,6 +8,9 @@ import com.seibel.lod.util.LevelPosUtil; import com.seibel.lod.util.LodUtil; import com.seibel.lod.util.ThreadMapUtil; +/** + * a VerticalLevelContainer is a quadTree level that can contain multiple voxel column per position. + */ public class VerticalLevelContainer implements LevelContainer { @@ -254,8 +257,4 @@ public class VerticalLevelContainer implements LevelContainer return size*size*getMaxVerticalData(); } - @Override - public int getMaxMemoryUse(){ - return getMaxNumberOfLods() * 2; //2 byte - } }