Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5
This commit is contained in:
@@ -77,7 +77,7 @@ public class LodBufferBuilder
|
||||
public volatile boolean fullRegeneration = false;
|
||||
|
||||
/** the capacity of each buffer in bytes */
|
||||
public volatile int[][] bufferCount;
|
||||
public volatile int[][] bufferSize;
|
||||
|
||||
/** Used when building the vbos */
|
||||
public volatile BufferBuilder[][][] buildableBuffers;
|
||||
@@ -254,7 +254,7 @@ public class LodBufferBuilder
|
||||
PosToRenderContainer posToRender = setsToRender[xR][zR];
|
||||
posToRender.clear(minDetail, regionPos.x, regionPos.z);
|
||||
|
||||
lodDim.getDataToRender(
|
||||
lodDim.getPosToRender(
|
||||
posToRender,
|
||||
regionPos,
|
||||
playerBlockPosRounded.getX(),
|
||||
@@ -428,7 +428,7 @@ public class LodBufferBuilder
|
||||
int numberOfBuffers;
|
||||
|
||||
previousRegionWidth = numbRegionsWide;
|
||||
bufferCount = new int[numbRegionsWide][numbRegionsWide];
|
||||
bufferSize = new int[numbRegionsWide][numbRegionsWide];
|
||||
buildableBuffers = new BufferBuilder[numbRegionsWide][numbRegionsWide][];
|
||||
|
||||
buildableVbos = new VertexBuffer[numbRegionsWide][numbRegionsWide][];
|
||||
@@ -447,7 +447,7 @@ public class LodBufferBuilder
|
||||
// if the memory required is greater than the max buffer capacity divide the memory across multiple buffers
|
||||
if (memoryRequired < LodUtil.MAX_ALOCATEABLE_DIRECT_MEMORY)
|
||||
{
|
||||
bufferCount[x][z] = 1;
|
||||
bufferSize[x][z] = 1;
|
||||
buildableBuffers[x][z] = new BufferBuilder[1];
|
||||
buildableVbos[x][z] = new VertexBuffer[1];
|
||||
drawableVbos[x][z] = new VertexBuffer[1];
|
||||
@@ -456,14 +456,14 @@ public class LodBufferBuilder
|
||||
{
|
||||
numberOfBuffers = (int) Math.ceil(memoryRequired / LodUtil.MAX_ALOCATEABLE_DIRECT_MEMORY) + 1;
|
||||
memoryRequired = LodUtil.MAX_ALOCATEABLE_DIRECT_MEMORY;
|
||||
bufferCount[x][z] = numberOfBuffers;
|
||||
bufferSize[x][z] = numberOfBuffers;
|
||||
buildableBuffers[x][z] = new BufferBuilder[numberOfBuffers];
|
||||
buildableVbos[x][z] = new VertexBuffer[numberOfBuffers];
|
||||
drawableVbos[x][z] = new VertexBuffer[numberOfBuffers];
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < bufferCount[x][z]; i++)
|
||||
for (int i = 0; i < bufferSize[x][z]; i++)
|
||||
{
|
||||
buildableBuffers[x][z][i] = new BufferBuilder((int) memoryRequired);
|
||||
|
||||
|
||||
+3
-3
@@ -15,18 +15,18 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -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, int[][]> DIRECTION_VERTEX_MAP = new HashMap<Direction, int[][]>()
|
||||
{{
|
||||
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<Direction, int[]> FACE_DIRECTION = new HashMap<Direction, int[]>()
|
||||
{{
|
||||
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();
|
||||
|
||||
+10
-10
@@ -15,19 +15,19 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<Direction, long[]> adjData,
|
||||
private void generateBoundingBox(Box box,
|
||||
int height, int depth, int width,
|
||||
double xOffset, double yOffset, double zOffset,
|
||||
BlockPos bufferCenterBlockPos,
|
||||
Map<Direction, long[]> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-5
@@ -15,18 +15,18 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<Direction, long[]> 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)
|
||||
{
|
||||
|
||||
+5
-5
@@ -15,18 +15,18 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<Direction, long[]> 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)
|
||||
{
|
||||
|
||||
@@ -15,15 +15,8 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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())
|
||||
@@ -212,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;
|
||||
|
||||
|
||||
@@ -231,43 +210,25 @@ public class LodBuilder
|
||||
|
||||
|
||||
long[] data;
|
||||
switch (verticalQuality)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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)
|
||||
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);
|
||||
@@ -366,35 +327,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 +366,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 +468,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 +503,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 +567,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 +584,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 +698,8 @@ public class LodBuilder
|
||||
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
// this block is entirely transparent
|
||||
color = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// determine the average color
|
||||
@@ -762,7 +711,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
|
||||
@@ -775,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 */
|
||||
@@ -816,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();
|
||||
@@ -825,28 +774,20 @@ public class LodBuilder
|
||||
}
|
||||
|
||||
blockColor = getColorTextureForBlock(blockState, blockPos, true);
|
||||
if (toTint.get(blockState.getBlock()).booleanValue())
|
||||
if (toTint.get(blockState.getBlock()))
|
||||
{
|
||||
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 +848,23 @@ public class LodBuilder
|
||||
tmp = tmp.darker();
|
||||
colorInt = LodUtil.colorToInt(tmp);
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
return colorInt;
|
||||
}
|
||||
|
||||
|
||||
public static final ConcurrentMap<Block, Boolean> notFullBlock = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<Block, Boolean> 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 +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);
|
||||
@@ -942,7 +884,7 @@ public class LodBuilder
|
||||
notFullBlock.put(blockState.getBlock(), false);
|
||||
smallBlock.put(blockState.getBlock(), false);
|
||||
}
|
||||
|
||||
|
||||
if (!voxelShape.isEmpty())
|
||||
{
|
||||
AxisAlignedBB bbox = voxelShape.bounds();
|
||||
@@ -953,34 +895,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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 <br>
|
||||
* useHeightmap = false <br>
|
||||
@@ -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
|
||||
|
||||
@@ -15,16 +15,8 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<Integer, ConfiguredFeature<?, ?>> configuredFeaturesToAvoid = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<Integer, ConfiguredFeature<?, ?>> configuredFeaturesToAvoid = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
|
||||
@@ -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<List<Supplier<ConfiguredFeature<?, ?>>>> featuresForState = biome.generationSettings.features();
|
||||
|
||||
for(int featureStateToGenerate = 0; featureStateToGenerate < featuresForState.size(); featureStateToGenerate++)
|
||||
for (int featureStateToGenerate = 0; featureStateToGenerate < featuresForState.size(); featureStateToGenerate++)
|
||||
{
|
||||
for(Supplier<ConfiguredFeature<?, ?>> featureSupplier : featuresForState.get(featureStateToGenerate))
|
||||
for (Supplier<ConfiguredFeature<?, ?>> 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
|
||||
|
||||
@@ -538,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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -615,7 +617,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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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())
|
||||
{
|
||||
@@ -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;
|
||||
@@ -142,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())
|
||||
{
|
||||
@@ -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);
|
||||
|
||||
@@ -15,28 +15,19 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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> fogDistance;
|
||||
public ForgeConfigSpec.EnumValue<FogDrawOverride> fogDrawOverride;
|
||||
|
||||
@@ -90,9 +79,6 @@ public class LodConfig
|
||||
|
||||
public ForgeConfigSpec.EnumValue<HorizontalResolution> drawResolution;
|
||||
|
||||
// public ForgeConfigSpec.EnumValue<ShadingMode> shadingMode;
|
||||
|
||||
|
||||
public ForgeConfigSpec.EnumValue<DetailDropOff> detailDropOff;
|
||||
|
||||
public ForgeConfigSpec.IntValue lodChunkRenderDistance;
|
||||
@@ -101,6 +87,8 @@ public class LodConfig
|
||||
|
||||
public ForgeConfigSpec.BooleanValue alwaysDrawAtMaxQuality;
|
||||
|
||||
public ForgeConfigSpec.BooleanValue drawLods;
|
||||
|
||||
public ForgeConfigSpec.EnumValue<FovTest> 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<VerticalQuality> lodQualityMode;
|
||||
public ForgeConfigSpec.EnumValue<VerticalQuality> verticalQuality;
|
||||
public ForgeConfigSpec.EnumValue<HorizontalResolution> generationResolution;
|
||||
public ForgeConfigSpec.EnumValue<DistanceGenerationMode> distanceGenerationMode;
|
||||
public ForgeConfigSpec.EnumValue<GenerationPriority> 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<BufferRebuildTimes> 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);
|
||||
|
||||
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.seibel.lod.enums;
|
||||
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
|
||||
/**
|
||||
* Near_First <br>
|
||||
* Far_First <br>
|
||||
* <br>
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -22,13 +22,57 @@ package com.seibel.lod.enums;
|
||||
* multi_lod <br>
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version 9-27-2021
|
||||
* @version 10-07-2021
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -15,37 +15,27 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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
|
||||
@@ -84,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()));
|
||||
|
||||
|
||||
|
||||
@@ -184,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)
|
||||
{
|
||||
@@ -230,7 +211,7 @@ public class LodDimensionFileHandler
|
||||
fileWritingThreadPool.execute(saveDirtyRegionsThread);
|
||||
}
|
||||
|
||||
private Thread saveDirtyRegionsThread = new Thread(() ->
|
||||
private final Thread saveDirtyRegionsThread = new Thread(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -238,11 +219,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);
|
||||
saveRegionToFile(lodDimension.getRegionByArrayIndex(i, j));
|
||||
lodDimension.SetIsRegionDirty(i, j, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,7 +255,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
|
||||
{
|
||||
@@ -312,7 +292,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
|
||||
|
||||
@@ -15,15 +15,16 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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:
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -15,12 +15,8 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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. <Br><Br>
|
||||
*
|
||||
*
|
||||
* <strong>Coordinate Standard: </strong><br>
|
||||
* Coordinate called posX or posZ are relative LevelPos coordinates <br>
|
||||
* unless stated otherwise. <br>
|
||||
*
|
||||
*
|
||||
* @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)
|
||||
@@ -391,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)
|
||||
@@ -510,7 +506,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;
|
||||
@@ -584,8 +580,8 @@ public class LodDimension
|
||||
z += dz;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
case FAR_FIRST:
|
||||
posToGenerate = new PosToGenerateContainer((byte) 8, maxDataToGenerate, playerBlockPosX, playerBlockPosZ);
|
||||
|
||||
@@ -599,7 +595,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)))
|
||||
@@ -618,15 +614,15 @@ 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 getDataToRender(PosToRenderContainer posToRender, RegionPos regionPos, int playerPosX,
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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)
|
||||
@@ -890,8 +886,18 @@ 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;
|
||||
}
|
||||
|
||||
public boolean GetIsRegionDirty(int i, int j)
|
||||
{
|
||||
return isRegionDirty[i][j];
|
||||
}
|
||||
|
||||
public void SetIsRegionDirty(int i, int j, boolean val)
|
||||
{
|
||||
isRegionDirty[i][j] = val;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -156,10 +144,10 @@ public class LodRegion
|
||||
* <p>
|
||||
* 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 +157,8 @@ public class LodRegion
|
||||
* <p>
|
||||
* 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 +211,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 +222,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 +235,10 @@ public class LodRegion
|
||||
* <p>
|
||||
* 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 +248,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 +290,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 +300,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 +319,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 +332,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,49 +152,43 @@ 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);
|
||||
if(nearPosToGenerate[i][0] == 0)
|
||||
break;
|
||||
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);
|
||||
if(farPosToGenerate[i][0] == 0)
|
||||
break;
|
||||
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 " ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
@@ -332,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
|
||||
|
||||
@@ -366,6 +372,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 //
|
||||
|
||||
@@ -291,7 +291,7 @@ public class LodRenderer
|
||||
setupFog(fogSettings.far.distance, fogSettings.far.quality);
|
||||
|
||||
|
||||
for (int i = 0; i < lodBufferBuilder.bufferCount[x][z]; i++)
|
||||
for (int i = 0; i < lodBufferBuilder.bufferSize[x][z]; i++)
|
||||
{
|
||||
sendLodsToGpuAndDraw(vbos[x][z][i], storageBufferIds[x][z], modelViewMatrix);
|
||||
}
|
||||
@@ -804,7 +804,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)
|
||||
@@ -825,7 +825,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)
|
||||
{
|
||||
@@ -838,7 +838,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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/*
|
||||
@@ -174,7 +176,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 +194,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 +227,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;
|
||||
@@ -276,12 +294,43 @@ public class DataPointUtil
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
* @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;
|
||||
|
||||
// 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);
|
||||
@@ -295,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)
|
||||
{
|
||||
@@ -327,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)
|
||||
@@ -405,6 +507,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))
|
||||
{
|
||||
@@ -415,6 +518,10 @@ public class DataPointUtil
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!doesItExist(singleDataToMerge[index])){
|
||||
singleData = dataToMerge[index * inputVerticalData];
|
||||
singleDataToMerge[index] = createVoidDataPoint(getGenerationMode(singleData));
|
||||
}
|
||||
}
|
||||
long data = mergeSingleData(singleDataToMerge);
|
||||
|
||||
@@ -422,9 +529,4 @@ public class DataPointUtil
|
||||
}
|
||||
return dataPoint;
|
||||
}
|
||||
|
||||
public static long[] compress(long[] data, byte detailLevel)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
@@ -167,9 +166,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)];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<String, short[]> heightAndDepthMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, long[]> singleDataToMergeMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, long[][]> verticalUpdate = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
|
||||
|
||||
//________________________//
|
||||
// used in BufferBuilder //
|
||||
//________________________//
|
||||
|
||||
|
||||
public static final ConcurrentMap<String, boolean[]> adjShadeDisabled = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, Map<Direction ,long[]>> adjDataMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, Map<Direction, long[]>> adjDataMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentMap<String, Box> 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<Direction ,long[]> getAdjDataArray(int verticalData)
|
||||
public static Map<Direction, long[]> 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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user