diff --git a/build.gradle b/build.gradle
index 860d930f6..64ad3ee48 100644
--- a/build.gradle
+++ b/build.gradle
@@ -31,7 +31,7 @@ compileJava {
// release 8 is needed because otherwise FloatBuffer.flip() will crash
// on some machines
// example thread: https://github.com/eclipse/jetty.project/issues/3244
- options.compilerArgs.addAll(['--release', '8', '-Xlint:unchecked', '-Xlint:deprecation'])
+ options.compilerArgs.addAll(['-Xlint:unchecked', '-Xlint:deprecation'])
}
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
diff --git a/src/main/java/com/seibel/lod/Main.java b/src/main/java/com/seibel/lod/Main.java
new file mode 100644
index 000000000..e51463c7b
--- /dev/null
+++ b/src/main/java/com/seibel/lod/Main.java
@@ -0,0 +1,32 @@
+package com.seibel.lod;
+
+import com.google.common.primitives.UnsignedLong;
+import com.seibel.lod.objects.PosToGenerateContainer;
+import com.seibel.lod.util.DataPointUtil;
+
+import javax.xml.crypto.Data;
+import java.math.BigInteger;
+
+public class Main
+{
+ public static void main(String[] args)
+ {
+ /*
+ try
+ {
+ long[][] dataToMerge = new long[][]{
+ {DataPointUtil.createDataPoint(10, 5, 0, 0, 0)},
+ {DataPointUtil.createDataPoint(15, 5, 0, 0, 0)},
+ {DataPointUtil.createDataPoint(40, 20, 0, 0, 0)},
+ {DataPointUtil.createDataPoint(1, 0, 0, 0, 0)}};
+ long[] data = DataPointUtil.mergeVerticalData(dataToMerge);
+ for (long dataPoint : data)
+ {
+ System.out.println("depth " + DataPointUtil.getDepth(dataPoint));
+ System.out.println("height " + DataPointUtil.getHeight(dataPoint));
+ }
+ }catch (Exception e){
+ e.printStackTrace();
+ }*/
+ }
+}
diff --git a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java
index ad24f4f68..7e502783d 100644
--- a/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java
+++ b/src/main/java/com/seibel/lod/builders/LodBufferBuilder.java
@@ -32,8 +32,6 @@ import org.lwjgl.opengl.GL15C;
import com.seibel.lod.builders.lodTemplates.Box;
import com.seibel.lod.config.LodConfig;
-import com.seibel.lod.objects.DataPoint;
-import com.seibel.lod.objects.LevelPosUtil;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.LodRegion;
import com.seibel.lod.objects.PosToRenderContainer;
@@ -42,10 +40,13 @@ import com.seibel.lod.proxy.ClientProxy;
import com.seibel.lod.proxy.GlProxy;
import com.seibel.lod.proxy.GlProxy.GlProxyContext;
import com.seibel.lod.render.LodRenderer;
+import com.seibel.lod.util.DataPointUtil;
+import com.seibel.lod.util.LevelPosUtil;
import com.seibel.lod.util.LodThreadFactory;
import com.seibel.lod.util.LodUtil;
import net.minecraft.client.renderer.BufferBuilder;
+import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.vertex.VertexBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
@@ -117,8 +118,10 @@ public class LodBufferBuilder
private volatile PosToRenderContainer[][] setsToRender;
private volatile RegionPos center;
- /** This is the ChunkPos the player was at the last time the buffers were built.
- * IE the center of the buffers last time they were built */
+ /**
+ * This is the ChunkPos the player was at the last time the buffers were built.
+ * IE the center of the buffers last time they were built
+ */
private volatile ChunkPos drawableCenterChunkPos = new ChunkPos(0, 0);
private volatile ChunkPos buildableCenterChunkPos = new ChunkPos(0, 0);
@@ -142,6 +145,20 @@ public class LodBufferBuilder
public void generateLodBuffersAsync(LodRenderer renderer, LodDimension lodDim,
BlockPos playerBlockPos, boolean fullRegen)
{
+
+
+ for(int i = 0; i<16; i++)
+ {
+ for(int j = 0; j<16; j++)
+ {
+ int lightTint = LightTexture.pack(i,j);
+ //System.out.print(ColorUtil.getRed(lightTint) + " " + ColorUtil.getGreen(lightTint) + " " + ColorUtil.getBlue(lightTint) + " ");
+ System.out.print(Integer.toHexString(lightTint) + " ");
+ }
+ System.out.println();
+ }
+
+
// only allow one generation process to happen at a time
if (generatingBuffers)
return;
@@ -246,8 +263,9 @@ public class LodBufferBuilder
int chunkXdist;
int chunkZdist;
short gameChunkRenderDistance = (short) (renderer.vanillaRenderedChunks.length / 2 - 1);
- long dataPoint;
- long[] adjData;
+ //long dataPoint;
+ long[] adjData = new long[NUMBER_OF_DIRECTION];
+
for (int index = 0; index < posToRender.getNumberOfPos(); index++)
{
detailLevel = posToRender.getNthDetailLevel(index);
@@ -266,12 +284,13 @@ public class LodBufferBuilder
// skip any chunks that Minecraft is going to render
try
{
- if (lodDim.doesDataExist(detailLevel, posX, posZ))
+ //dataPoint = lodDim.getData(detailLevel, posX, posZ)[0];
+ for(long dataPoint : lodDim.getData(detailLevel, posX, posZ))
{
- dataPoint = lodDim.getData(detailLevel, posX, posZ);
- if (DataPoint.getHeight(dataPoint) == LodBuilder.DEFAULT_HEIGHT && DataPoint.getDepth(dataPoint) == LodBuilder.DEFAULT_DEPTH)
- continue;
- adjData = new long[NUMBER_OF_DIRECTION];
+
+ if (!DataPointUtil.isItVoid(dataPoint) && DataPointUtil.doesItExist(dataPoint))
+ {
+ /*
for (int direction = 0; direction < NUMBER_OF_DIRECTION; direction++)
{
xAdj = posX + ADJ_DIRECTION[direction][0];
@@ -284,22 +303,27 @@ public class LodBufferBuilder
if (!renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]
&& posToRender.contains(detailLevel, xAdj, zAdj))
{
- adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj);
+ adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj)[0];
+ } else
+ {
+ adjData[direction] = 0;
}
- }
- else
+ } else
{
if (posToRender.contains(detailLevel, xAdj, zAdj))
{
- adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj);
+ adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj)[0];
+ } else
+ {
+ adjData[direction] = 0;
}
}
- }
+ }*/
LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, dataPoint, adjData,
detailLevel, posX, posZ, boxCache[xR][zR], renderer.previousDebugMode);
}
- }
- catch (ArrayIndexOutOfBoundsException e)
+ }
+ } catch (ArrayIndexOutOfBoundsException e)
{
e.printStackTrace();
return false;
diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java
index c12985cc2..46100c328 100644
--- a/src/main/java/com/seibel/lod/builders/LodBuilder.java
+++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java
@@ -23,27 +23,21 @@ import java.util.concurrent.Executors;
import com.seibel.lod.enums.DistanceGenerationMode;
import com.seibel.lod.enums.LodDetail;
-import com.seibel.lod.objects.DataPoint;
-import com.seibel.lod.objects.LevelPosUtil;
+import com.seibel.lod.util.*;
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.DetailDistanceUtil;
-import com.seibel.lod.util.LodThreadFactory;
-import com.seibel.lod.util.LodUtil;
import com.seibel.lod.wrappers.MinecraftWrapper;
-import net.minecraft.block.AbstractPlantBlock;
-import net.minecraft.block.BlockState;
-import net.minecraft.block.Blocks;
-import net.minecraft.block.BushBlock;
-import net.minecraft.block.GrassBlock;
-import net.minecraft.block.IGrowable;
-import net.minecraft.block.LeavesBlock;
+import net.minecraft.block.*;
import net.minecraft.block.material.MaterialColor;
+import net.minecraft.util.math.AxisAlignedBB;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.ChunkPos;
+import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.DimensionType;
import net.minecraft.world.IWorld;
+import net.minecraft.world.LightType;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.IChunk;
@@ -169,9 +163,9 @@ public class LodBuilder
int endX;
int endZ;
int color;
+ byte light;
short height;
short depth;
- long data;
try
{
LodDetail detail;
@@ -191,28 +185,31 @@ public class LodBuilder
endX = detail.endX[i];
endZ = detail.endZ[i];
- color = generateLodColorForArea(chunk, config, startX, startZ, endX, endZ);
-
- if (!config.useHeightmap)
- {
- height = determineHeightPointForArea(chunk.getSections(), startX, startZ, endX, endZ);
- depth = determineBottomPointForArea(chunk.getSections(), startX, startZ, endX, endZ);
- } else
- {
- height = determineHeightPoint(chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP), startX,
- startZ, endX, endZ);
- depth = 0;
- }
posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel);
posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel);
+ long[] data;
+ long[][] dataToMerge;
+ //data = ThreadMapUtil.getSingleAddDataArray();
+ //dataToMerge = createSingleDataToMerge(detail, chunk, config, startX, startZ, endX, endZ);
+ /*long[][] dataToMerge2 = new long[dataToMerge.length][];
+ for (int index = 0; index < dataToMerge.length; index++)
+ {
+ dataToMerge2[index] = new long[]{dataToMerge[index]};
+ }*/
+ //data[0] = DataPointUtil.mergeSingleData(dataToMerge);
+
+ dataToMerge = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ);
+ data = DataPointUtil.mergeVerticalData(dataToMerge);
+ if (data.length == 0 || data == null)
+ data = new long[]{DataPointUtil.EMPTY_DATA};
boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER;
- data = DataPoint.createDataPoint(height, depth, ColorUtil.getRed(color), ColorUtil.getGreen(color), ColorUtil.getBlue(color));
lodDim.addData(detailLevel,
posX,
posZ,
data,
false,
isServer);
+
}
lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z);
} catch (Exception e)
@@ -222,7 +219,199 @@ public class LodBuilder
}
+ private long[][] createVerticalDataToMerge(LodDetail detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ)
+ {
+ long[][] dataToMerge = ThreadMapUtil.getBuilderVerticalArray()[detail.detailLevel];
+ ChunkPos chunkPos = chunk.getPos();
+ int size = 1 << detail.detailLevel;
+ int height = 0;
+ int depth = 0;
+ int color = 0;
+ int light = 0;
+ int generation = config.distanceGenerationMode.complexity;
+
+ int xRel;
+ int zRel;
+ int xAbs;
+ int yAbs;
+ int zAbs;
+
+ BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0);
+ int index = 0;
+ if(dataToMerge == null){
+ dataToMerge = new long[size * size][DataPointUtil.WORLD_HEIGHT];
+ }
+ //dataToMerge = new long[size * size][1024];
+
+ for (index = 0; index < size * size; index++)
+ {
+ for(int i = 0; i < dataToMerge[index].length; i++)
+ {
+ dataToMerge[index][i] = 0;
+ }
+ xRel = Math.floorMod(index, size) + startX;
+ zRel = Math.floorDiv(index, size) + startZ;
+ xAbs = chunkPos.getMinBlockX() + xRel;
+ zAbs = chunkPos.getMinBlockZ() + zRel;
+
+ //Calculate the height of the lod
+ yAbs = 255;
+ int count = 0;
+ while (yAbs > 0)
+ {
+ height = determineHeightPointFrom(chunk, config, xRel, zRel, yAbs, blockPos);
+
+ //If the lod is at default, then we set this as void data
+ if (height == DEFAULT_HEIGHT)
+ {
+ dataToMerge[index][0] = DataPointUtil.createVoidDataPoint(generation);
+ break;
+ }
+
+ yAbs = height - 1;
+ // We search light on above air block
+ color = generateLodColor(chunk, config, xRel, yAbs, zRel);
+ depth = determineBottomPointFrom(chunk, config, xRel, zRel, yAbs, blockPos);
+ blockPos.set(xAbs, yAbs + 1, zAbs);
+ light = getLightValue(chunk, blockPos);
+
+ //System.out.println(dataToMerge.length + " " + index +" " + count + " " + yAbs);
+ //System.out.println(dataToMerge.length + " " + dataToMerge[index].length);
+ dataToMerge[index][count] = DataPointUtil.createDataPoint(height, depth, color, (light >> 4) & 0b1111, light & 0b1111, generation);
+ yAbs = depth - 1;
+ count++;
+ }
+ }
+ return dataToMerge;
+ }
+
+ /**
+ * Find the lowest valid point from the bottom.
+ */
+ private short determineBottomPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs, BlockPos.Mutable blockPos)
+ {
+ short depth = DEFAULT_DEPTH;
+ if (config.useHeightmap)
+ {
+ depth = 0;
+ } else
+ {
+ 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--)
+ {
+ 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 (!voidData)
+ {
+ break;
+ }
+ }
+ }
+ return depth;
+ }
+
+ /**
+ * Find the highest valid point from the Top
+ */
+ private short determineHeightPointFrom(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, int yAbs, BlockPos.Mutable blockPos)
+ {
+ short height = DEFAULT_HEIGHT;
+ if (config.useHeightmap)
+ {
+ height = (short) chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
+ } else
+ {
+ 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--)
+ {
+ 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))
+ {
+ height = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1);
+ voidData = false;
+ break;
+ }
+ }
+ if (!voidData)
+ {
+ break;
+ }
+ }
+ }
+ return height;
+ }
+
+ private long[] createSingleDataToMerge(LodDetail detail, IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ)
+ {
+ long[] dataToMerge = ThreadMapUtil.getBuilderArray()[detail.detailLevel];
+ ChunkPos chunkPos = chunk.getPos();
+
+ int size = 1 << detail.detailLevel;
+ int height = 0;
+ int depth = 0;
+ int color = 0;
+ int light = 0;
+ int generation = config.distanceGenerationMode.complexity;
+
+ int xRel;
+ int zRel;
+ int xAbs;
+ int yAbs;
+ int zAbs;
+
+ BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0);
+ int index = 0;
+ if (dataToMerge == null)
+ {
+ dataToMerge = new long[size * size];
+ }
+ for (index = 0; index < size * size; index++)
+ {
+ xRel = Math.floorMod(index, size) + startX;
+ zRel = Math.floorDiv(index, size) + startZ;
+ xAbs = chunkPos.getMinBlockX() + xRel;
+ zAbs = chunkPos.getMinBlockZ() + zRel;
+
+ //Calculate the height of the lod
+ height = determineHeightPoint(chunk, config, xRel, zRel, blockPos);
+
+ //If the lod is at default, then we set this as void data
+ if (height == DEFAULT_HEIGHT)
+ {
+ dataToMerge[index] = DataPointUtil.createVoidDataPoint(generation);
+ continue;
+ }
+
+ yAbs = height - 1;
+ // We search light on above air block
+
+ color = generateLodColor(chunk, config, xRel, yAbs, zRel);
+ depth = determineBottomPoint(chunk, config, xRel, zRel, blockPos);
+
+ blockPos.set(xAbs, yAbs + 1, zAbs);
+ light = getLightValue(chunk, blockPos);
+
+ dataToMerge[index] = DataPointUtil.createDataPoint(height, depth, color, (light >> 4) & 0b1111, light & 0b1111, generation);
+ }
+ return dataToMerge;
+ }
// =====================//
// constructor helpers //
// =====================//
@@ -230,208 +419,118 @@ public class LodBuilder
/**
* Find the lowest valid point from the bottom.
*/
- private short determineBottomPointForArea(ChunkSection[] chunkSections, int startX, int startZ, int endX, int endZ)
+ private short determineBottomPoint(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, BlockPos.Mutable blockPos)
{
- int numberOfBlocksRequired = ((endX - startX) * (endZ - startZ) / 2);
-
- // search from the bottom up
- for (int section = 0; section < CHUNK_DATA_WIDTH; section++)
+ ChunkSection[] chunkSections = chunk.getSections();
+ short depth = DEFAULT_DEPTH;
+ if (config.useHeightmap)
{
- for (int y = 0; y < CHUNK_SECTION_HEIGHT; y++)
+ depth = 0;
+ } else
+ {
+ boolean found = false;
+ for (int sectionIndex = 0; sectionIndex < chunkSections.length; sectionIndex++)
{
- int numberOfBlocksFound = 0;
-
- for (int x = startX; x < endX; x++)
+ for (int yRel = 0; yRel < CHUNK_DATA_WIDTH; yRel++)
{
- for (int z = startZ; z < endZ; z++)
+ if (isLayerValidLodPoint(chunk, blockPos))
{
- if (isLayerValidLodPoint(chunkSections, section, y, x, z))
- {
- numberOfBlocksFound++;
-
- if (numberOfBlocksFound >= numberOfBlocksRequired)
- {
- // we found
- // enough blocks in this
- // layer to count as an
- // LOD point
- return (short) (y + (section * CHUNK_SECTION_HEIGHT));
- }
- }
+ depth = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel);
+ found = true;
+ break;
}
}
+ if (found)
+ {
+ break;
+ }
}
}
-
- // we never found a valid LOD point
- return DEFAULT_DEPTH;
+ return depth;
}
- /**
- * Find the lowest valid point from the bottom.
- */
- @SuppressWarnings("unused")
- private short determineBottomPoint(Heightmap heightmap)
- {
- // the heightmap only shows how high the blocks go, it
- // doesn't have any info about how low they go
- return 0;
- }
-
/**
* Find the highest valid point from the Top
*/
- private short determineHeightPointForArea(ChunkSection[] chunkSections, int startX, int startZ, int endX, int endZ)
+ private short determineHeightPoint(IChunk chunk, LodBuilderConfig config, int xRel, int zRel, BlockPos.Mutable blockPos)
{
- int numberOfBlocksRequired = ((endX - startX) * (endZ - startZ) / 2);
- // search from the top down
- for (int section = chunkSections.length - 1; section >= 0; section--)
+ short height = DEFAULT_HEIGHT;
+ if (config.useHeightmap)
{
- for (int y = CHUNK_DATA_WIDTH - 1; y >= 0; y--)
+ height = (short) chunk.getOrCreateHeightmapUnprimed(LodUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
+ } else
+ {
+ boolean voidData = true;
+ ChunkSection[] chunkSections = chunk.getSections();
+ for (int sectionIndex = chunkSections.length - 1; sectionIndex >= 0; sectionIndex--)
{
- int numberOfBlocksFound = 0;
-
- for (int x = startX; x < endX; x++)
+ for (int yRel = CHUNK_DATA_WIDTH - 1; yRel >= 0; yRel--)
{
- for (int z = startZ; z < endZ; z++)
+ if (isLayerValidLodPoint(chunk, blockPos))
{
- if (isLayerValidLodPoint(chunkSections, section, y, x, z))
- {
- numberOfBlocksFound++;
-
- if (numberOfBlocksFound >= numberOfBlocksRequired)
- {
- // we found
- // enough blocks in this
- // layer to count as an
- // LOD point
- return (short) (y + 1 + (section * CHUNK_SECTION_HEIGHT));
- }
- }
+ height = (short) (sectionIndex * CHUNK_DATA_WIDTH + yRel + 1);
+ voidData = false;
+ break;
}
}
+ if (!voidData)
+ {
+ break;
+ }
}
}
-
- // we never found a valid LOD point
- return DEFAULT_HEIGHT;
- }
-
-
- /**
- * Find the highest point from the Top
- */
- private short determineHeightPoint(Heightmap heightmap, int startX, int startZ, int endX, int endZ)
- {
- short highest = 0;
- for (int x = startX; x < endX; x++)
- {
- for (int z = startZ; z < endZ; z++)
- {
- short newHeight = (short) heightmap.getFirstAvailable(x, z);
- if (newHeight > highest)
- highest = newHeight;
- }
- }
-
- return highest;
+ return height;
}
/**
* Generate the color for the given chunk using biome water color, foliage
* color, and grass color.
- *
- * @param config_useSolidBlocksInColorGen
- * If true we look down from the top of
- * the
- * chunk until we find a non-invisible
- * block, and then use
- * its color. If false we generate the
- * color immediately for
- * each x and z.
- * @param config_useBiomeColors
- * If true use biome foliage, water, and
- * grass colors,
- * otherwise only use the block's
- * material color
*/
- private int generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX,
- int endZ)
+ private int generateLodColor(IChunk chunk, LodBuilderConfig config, int xRel, int yAbs, int zRel)
{
ChunkSection[] chunkSections = chunk.getSections();
-
- int numbOfBlocks = 0;
- int red = 0;
- int green = 0;
- int blue = 0;
-
- for (int x = startX; x < endX; x++)
+ int colorInt = 0;
+ if (config.useBiomeColors)
{
- for (int z = startZ; z < endZ; z++)
+ // I have no idea why I need to bit shift to the right, but
+ // if I don't the biomes don't show up correctly.
+ Biome biome = chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2);
+ colorInt = getColorForBiome(xRel, zRel, biome);
+ } else
+ {
+ int sectionIndex = Math.floorDiv(yAbs, CHUNK_SECTION_HEIGHT);
+ int yRel = Math.floorMod(yAbs, CHUNK_SECTION_HEIGHT);
+ if (chunkSections[sectionIndex] != null)
{
- boolean foundBlock = false;
+ BlockState blockState = chunkSections[sectionIndex].getBlockState(xRel, yRel, zRel);
- // go top down
- for (int i = chunkSections.length - 1; !foundBlock && i >= 0; i--)
- {
- if (!foundBlock && (chunkSections[i] != null || !config.useSolidBlocksInColorGen))
- {
- for (int y = CHUNK_SECTION_HEIGHT - 1; !foundBlock && y >= 0; y--)
- {
- int colorInt = 0;
- BlockState blockState = null;
+ // the bit shift is equivalent to dividing by 4
+ Biome biome = chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2);
- if (chunkSections[i] != null)
- {
- blockState = chunkSections[i].getBlockState(x, y, z);
- colorInt = blockState.materialColor.col;
- }
-
- if (colorInt == 0 && config.useSolidBlocksInColorGen)
- {
- // skip air or invisible blocks
- continue;
- }
-
- if (config.useBiomeColors)
- {
- // I have no idea why I need to bit shift to the right, but
- // if I don't the biomes don't show up correctly.
- Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, y + 1 * chunkSections.length >> 2,
- z >> 2);
- colorInt = getColorForBiome(x, z, biome);
- } else
- {
-
- // the bit shift is equivalent to dividing by 4
- Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, y + i * chunkSections.length >> 2,
- z >> 2);
- colorInt = getColorForBlock(x, z, blockState, biome);
- }
-
- red += ColorUtil.getRed(colorInt);
- green += ColorUtil.getGreen(colorInt);
- blue += ColorUtil.getBlue(colorInt);
-
- numbOfBlocks++;
-
- // we found a valid block, skip to the
- // next x and z
- foundBlock = true;
- }
- }
- }
+ colorInt = getColorForBlock(xRel, zRel, blockState, biome);
+ }
+ if (colorInt == 0 && yAbs > 0)
+ {
+ //invisible case
+ colorInt = generateLodColor(chunk, config, xRel, yAbs - 1, zRel);
}
}
+ return colorInt;
+ }
- if (numbOfBlocks == 0)
- numbOfBlocks = 1;
+ private int getLightValue(IChunk chunk, BlockPos.Mutable blockPos)
+ {
+ int light;
- red /= numbOfBlocks;
- green /= numbOfBlocks;
- blue /= numbOfBlocks;
- return ColorUtil.rgbToInt(red,green,blue);
+ //*TODO choose the best one between those options*/
+ //lightBlock = MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().getLayerListener(LightType.BLOCK).getLightValue(blockPos);
+ //lightBlock = (byte) MinecraftWrapper.INSTANCE.getPlayer().level.getLightEngine().blockEngine.getLightValue(blockPos);
+ light = MinecraftWrapper.INSTANCE.getPlayer().level.getBrightness(LightType.BLOCK, blockPos);
+ light += MinecraftWrapper.INSTANCE.getPlayer().level.getBrightness(LightType.SKY, blockPos) << 4;
+ //BlockState blockState = chunk.getBlockState(blockPos);
+ //lightBlock = (byte) blockState.getLightBlock(chunk, blockPos);
+ return light;
}
/**
@@ -442,9 +541,9 @@ public class LodBuilder
int colorInt = 0;
// block special cases
- if (blockState == Blocks.AIR.defaultBlockState()
- || blockState == Blocks.CAVE_AIR.defaultBlockState()
- || blockState == Blocks.BARRIER.defaultBlockState())
+ if (blockState == Blocks.AIR.defaultBlockState()
+ || blockState == Blocks.CAVE_AIR.defaultBlockState()
+ || blockState == Blocks.BARRIER.defaultBlockState())
{
Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z));
tmp = tmp.darker();
@@ -452,11 +551,36 @@ public class LodBuilder
} else if (blockState == Blocks.STONE.defaultBlockState())
{
colorInt = LodUtil.STONE_COLOR_INT;
+ } else if (blockState == Blocks.NETHERRACK.defaultBlockState())
+ {
+ colorInt = LodUtil.NETHERRACK_COLOR_INT;
+ } else if (blockState == Blocks.WARPED_NYLIUM.defaultBlockState())
+ {
+ colorInt = LodUtil.WARPED_NYLIUM_COLOR_INT;
+ } else if (blockState == Blocks.CRIMSON_NYLIUM.defaultBlockState())
+ {
+ colorInt = LodUtil.CRIMSON_NYLIUM_COLOR_INT;
+ } else if (blockState == Blocks.BEDROCK.defaultBlockState())
+ {
+ colorInt = getColorForBiome(x, z, biome);
} else if (blockState == Blocks.MYCELIUM.defaultBlockState())
{
colorInt = LodUtil.MYCELIUM_COLOR_INT;
+ } else if (blockState == Blocks.SOUL_TORCH.defaultBlockState()
+ || blockState == Blocks.SOUL_WALL_TORCH.defaultBlockState())
+ {
+ colorInt = Blocks.WARPED_PLANKS.defaultMaterialColor().col;
+ } else if (blockState == Blocks.TORCH.defaultBlockState()
+ || blockState == Blocks.WALL_TORCH.defaultBlockState())
+ {
+ colorInt = Blocks.OAK_PLANKS.defaultMaterialColor().col;
+ } else if (blockState == Blocks.REDSTONE_TORCH.defaultBlockState()
+ || blockState == Blocks.REDSTONE_WALL_TORCH.defaultBlockState())
+ {
+ colorInt = Blocks.CRIMSON_PLANKS.defaultMaterialColor().col;
}
+
// plant life
else if (blockState.getBlock() instanceof LeavesBlock || blockState.getBlock() == Blocks.VINE)
{
@@ -481,7 +605,7 @@ public class LodBuilder
// everything else
else
{
- colorInt = blockState.materialColor.col;
+ colorInt = blockState.getBlock().defaultMaterialColor().col;
}
return colorInt;
@@ -498,7 +622,7 @@ public class LodBuilder
{
case NETHER:
- colorInt = Blocks.BEDROCK.defaultBlockState().materialColor.col;
+ colorInt = LodUtil.NETHERRACK_COLOR_INT;
break;
case THEEND:
@@ -552,19 +676,34 @@ public class LodBuilder
/**
* Is the layer between the given X, Z, and dataIndex values a valid LOD point?
*/
- private boolean isLayerValidLodPoint(ChunkSection[] chunkSections, int sectionIndex, int y, int x, int z)
+ private boolean isLayerValidLodPoint(IChunk chunk, BlockPos.Mutable blockPos)
{
- if (chunkSections[sectionIndex] == null)
+
+ BlockState blockState = chunk.getBlockState(blockPos);
+ if (blockState != null)
{
- // this section doesn't have any blocks,
- // it is not a valid section
- return false;
- } else
- {
- if (chunkSections[sectionIndex].getBlockState(x, y, z) != null
- && chunkSections[sectionIndex].getBlockState(x, y, z).getBlock() != Blocks.AIR
- && chunkSections[sectionIndex].getBlockState(x, y, z).getBlock() != Blocks.CAVE_AIR
- && chunkSections[sectionIndex].getBlockState(x, y, z).getBlock() != Blocks.BARRIER)
+ if (!blockState.getFluidState().isEmpty())
+ {
+ return true;
+ }
+ VoxelShape voxelShape = blockState.getShape(chunk, blockPos);
+ if (!voxelShape.isEmpty())
+ {
+ AxisAlignedBB bbox = voxelShape.bounds();
+ int xWidth = (int) (bbox.maxX - bbox.minX);
+ int yWidth = (int) (bbox.maxY - bbox.minY);
+ int zWidth = (int) (bbox.maxZ - bbox.minZ);
+ if (xWidth < 0.7 && zWidth < 0.7 && yWidth < 1)
+ {
+ return false;
+ }
+ } else
+ {
+ return false;
+ }
+ if (blockState.getBlock() != Blocks.AIR
+ && blockState.getBlock() != Blocks.CAVE_AIR
+ && blockState.getBlock() != Blocks.BARRIER)
{
return true;
}
diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java
index b44d75756..73d7e2e2d 100644
--- a/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java
+++ b/src/main/java/com/seibel/lod/builders/lodTemplates/AbstractLodTemplate.java
@@ -20,6 +20,7 @@ package com.seibel.lod.builders.lodTemplates;
import com.seibel.lod.enums.DebugMode;
import net.minecraft.client.renderer.BufferBuilder;
+import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
/**
@@ -31,6 +32,8 @@ import net.minecraft.util.math.BlockPos;
*/
public abstract class AbstractLodTemplate
{
+
+
public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData,
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging);
@@ -41,6 +44,7 @@ public abstract class AbstractLodTemplate
double x, double y, double z,
int red, int green, int blue, int alpha)
{
+
buffer.vertex(x, y, z).color(red, green, blue, alpha).endVertex();
}
diff --git a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java
index 133e544f5..441ddb1a6 100644
--- a/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java
+++ b/src/main/java/com/seibel/lod/builders/lodTemplates/CubicLodTemplate.java
@@ -20,10 +20,11 @@ package com.seibel.lod.builders.lodTemplates;
import com.seibel.lod.config.LodConfig;
import com.seibel.lod.enums.DebugMode;
import com.seibel.lod.enums.ShadingMode;
-import com.seibel.lod.objects.DataPoint;
+import com.seibel.lod.util.DataPointUtil;
import com.seibel.lod.util.ColorUtil;
import com.seibel.lod.util.LodUtil;
+import com.seibel.lod.wrappers.MinecraftWrapper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.Direction;
@@ -53,21 +54,29 @@ public class CubicLodTemplate extends AbstractLodTemplate
// add each LOD for the detail level
generateBoundingBox(
box,
- DataPoint.getHeight(data),
- DataPoint.getDepth(data),
+ DataPointUtil.getHeight(data),
+ DataPointUtil.getDepth(data),
width,
posX * width,
0,
posZ * width,
bufferCenterBlockPos);
+ int color;
+ boolean hasSkyLight = MinecraftWrapper.INSTANCE.getPlayer().level.dimensionType().hasSkyLight();
+ boolean hasRoof = MinecraftWrapper.INSTANCE.getPlayer().level.dimensionType().hasSkyLight();
+ int time = (int) (MinecraftWrapper.INSTANCE.getPlayer().level.getDayTime() - 13000);
+ boolean isDay = time < 0;
+ //USE THIS IN THE boolean hasCeiling = MinecraftWrapper.INSTANCE.getPlayer().level.dimensionType().hasCeiling();
+ color = DataPointUtil.getLightColor(data, (hasRoof & hasSkyLight), isDay);
- int color = DataPoint.getColor(data);
if (debugging != DebugMode.OFF)
+
{
color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB();
}
if (box != null)
+
{
addBoundingBoxToBuffer(buffer, box, color, bufferCenterBlockPos, adjData);
}
@@ -208,10 +217,10 @@ public class CubicLodTemplate extends AbstractLodTemplate
addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha);
addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha);
addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha);
- }else
+ } else
{
maxY = box.getMaxY();
- tempMaxY = DataPoint.getHeight(data);
+ tempMaxY = DataPointUtil.getHeight(data);
if (tempMaxY < maxY)
{
minY = Math.max(tempMaxY, minY);
@@ -220,7 +229,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha);
addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha);
}
- tempMinY = DataPoint.getDepth(data);
+ tempMinY = DataPointUtil.getDepth(data);
minY = box.getMinY();
if (tempMinY > minY)
{
@@ -253,11 +262,10 @@ public class CubicLodTemplate extends AbstractLodTemplate
addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha);
addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha);
addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha);
- }
- else
+ } else
{
maxY = box.getMaxY();
- tempMaxY = DataPoint.getHeight(data);
+ tempMaxY = DataPointUtil.getHeight(data);
if (tempMaxY < maxY)
{
minY = Math.max(tempMaxY, minY);
@@ -266,7 +274,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha);
addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha);
}
- tempMinY = DataPoint.getDepth(data);
+ tempMinY = DataPointUtil.getDepth(data);
minY = box.getMinY();
if (tempMinY > minY)
{
@@ -299,11 +307,10 @@ public class CubicLodTemplate extends AbstractLodTemplate
addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha);
addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha);
addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha);
- }
- else
+ } else
{
maxY = box.getMaxY();
- tempMaxY = DataPoint.getHeight(data);
+ tempMaxY = DataPointUtil.getHeight(data);
if (tempMaxY < maxY)
{
minY = Math.max(tempMaxY, minY);
@@ -312,7 +319,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha);
addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha);
}
- tempMinY = DataPoint.getDepth(data);
+ tempMinY = DataPointUtil.getDepth(data);
minY = box.getMinY();
if (tempMinY > minY)
{
@@ -345,11 +352,10 @@ public class CubicLodTemplate extends AbstractLodTemplate
addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha);
addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha);
addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha);
- }
- else
+ } else
{
maxY = box.getMaxY();
- tempMaxY = DataPoint.getHeight(data);
+ tempMaxY = DataPointUtil.getHeight(data);
if (tempMaxY < maxY)
{
minY = Math.max(tempMaxY, minY);
@@ -358,7 +364,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha);
addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha);
}
- tempMinY = DataPoint.getDepth(data);
+ tempMinY = DataPointUtil.getDepth(data);
minY = box.getMinY();
if (tempMinY > minY)
{
diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java
index 64880f35c..ffd5ea5b1 100644
--- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java
+++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java
@@ -24,8 +24,10 @@ import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
import java.util.function.Supplier;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.seibel.lod.builders.LodBuilder;
import com.seibel.lod.builders.LodBuilderConfig;
import com.seibel.lod.config.LodConfig;
@@ -72,7 +74,8 @@ import net.minecraftforge.common.WorldWorkerManager.IWorker;
*/
public class LodNodeGenWorker implements IWorker
{
- public static ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new LodThreadFactory(LodNodeGenWorker.class.getSimpleName()));
+ public static ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new ThreadFactoryBuilder().setNameFormat("Gen-Worker-Thread-%d").build());
+ //public static ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.threading.numberOfWorldGenerationThreads.get(), new LodThreadFactory(LodNodeGenWorker.class.getSimpleName()));
private boolean threadStarted = false;
private LodChunkGenThread thread;
@@ -126,7 +129,7 @@ public class LodNodeGenWorker implements IWorker
// Every other method can
// be done asynchronously
Thread newThread = new Thread(thread);
- newThread.setPriority(3);
+ newThread.setPriority(5);
genThreads.execute(newThread);
}
diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java
index 187fe079e..7f8c991e2 100644
--- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java
+++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodWorldGenerator.java
@@ -9,7 +9,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import com.seibel.lod.builders.LodBuilder;
import com.seibel.lod.config.LodConfig;
import com.seibel.lod.enums.DistanceGenerationMode;
-import com.seibel.lod.objects.LevelPosUtil;
+import com.seibel.lod.util.LevelPosUtil;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.PosToGenerateContainer;
import com.seibel.lod.render.LodRenderer;
diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java
index 6d21d34d5..0df076916 100644
--- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java
+++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java
@@ -28,10 +28,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.seibel.lod.enums.DistanceGenerationMode;
-import com.seibel.lod.objects.LevelContainer;
-import com.seibel.lod.objects.LodDimension;
-import com.seibel.lod.objects.LodRegion;
-import com.seibel.lod.objects.RegionPos;
+import com.seibel.lod.objects.*;
import com.seibel.lod.proxy.ClientProxy;
import com.seibel.lod.util.LodThreadFactory;
import com.seibel.lod.util.LodUtil;
@@ -46,11 +43,6 @@ import com.seibel.lod.util.LodUtil;
*/
public class LodDimensionFileHandler
{
- /**
- * This is what separates each piece of data
- */
- public static final char DATA_DELIMITER = ',';
-
private LodDimension loadedDimension = null;
public long regionLastWriteTime[][];
@@ -84,7 +76,7 @@ public class LodDimensionFileHandler
* file handler, older versions (smaller numbers) will be deleted and overwritten,
* newer versions (larger numbers) will be ignored and won't be read.
*/
- public static final int LOD_SAVE_FILE_VERSION = 5;
+ public static final int LOD_SAVE_FILE_VERSION = 6;
/**
* This is the string written before the file version
@@ -200,7 +192,8 @@ public class LodDimensionFileHandler
data = bufferedReader.readLine();
bufferedReader.close();
- region.addLevel(new LevelContainer(data));
+ //region.addLevel(new SingleLevelContainer(data));
+ region.addLevel(new VerticalLevelContainer(data));
} catch (Exception e)
{
// the buffered reader encountered a
@@ -331,7 +324,7 @@ public class LodDimensionFileHandler
fw.write(LOD_FILE_VERSION_PREFIX + " " + LOD_SAVE_FILE_VERSION + "\n");
// add each LodChunk to the file
- fw.write(region.getLevel(detailLevel).toString());
+ fw.write(region.getLevel(detailLevel).toDataString());
fw.close();
// overwrite the old file with the new one
diff --git a/src/main/java/com/seibel/lod/objects/DataPoint.java b/src/main/java/com/seibel/lod/objects/DataPoint.java
deleted file mode 100644
index 397f23375..000000000
--- a/src/main/java/com/seibel/lod/objects/DataPoint.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package com.seibel.lod.objects;
-
-public class DataPoint
-{
- public final static int HEIGHT_SHIFT = 54;
- public final static int DEPTH_SHIFT = 44;
- public final static int RED_SHIFT = 36;
- public final static int GREEN_SHIFT = 28;
- public final static int BLUE_SHIFT = 20;
- public final static int GEN_TYPE_SHIFT = 17;
- public final static int LIGHT_SHIFT = 13;
- public final static int EXISTENCE_SHIFT = 0;
-
- public final static long HEIGHT_MASK = Long.parseUnsignedLong("1111111111", 2);
- public final static long DEPTH_MASK = Long.parseUnsignedLong("1111111111", 2);
- public final static long RED_MASK = Long.parseUnsignedLong("11111111", 2);
- public final static long GREEN_MASK = Long.parseUnsignedLong("11111111", 2);
- public final static long BLUE_MASK = Long.parseUnsignedLong("11111111", 2);
- public final static long GEN_TYPE_MASK = Long.parseUnsignedLong("111", 2);
- public final static long LIGHT_MASK = Long.parseUnsignedLong("1111", 2);
- public final static long EXISTENCE_MASK = 1;
-
- public static long createDataPoint(int height, int depth, int color)
- {
- int red = (getRed(color) << 16) & 0x00FF0000;
- int green = (getGreen(color) << 8) & 0x0000FF00;
- int blue = getBlue(color)& 0x000000FF;
- return createDataPoint(height, depth, red, green, blue);
- }
- public static long createDataPoint(int height, int depth, int red, int green, int blue)
- {
- long dataPoint = 0;
- dataPoint += (height & HEIGHT_MASK) << HEIGHT_SHIFT;
- dataPoint += (depth & DEPTH_MASK) << DEPTH_SHIFT;
- dataPoint += (red & RED_MASK) << RED_SHIFT;
- dataPoint += (green & GREEN_MASK) << GREEN_SHIFT;
- dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT;
- dataPoint += 1;
- return dataPoint;
- }
-
- public static short getHeight(long dataPoint)
- {
- return (short) ((dataPoint >> HEIGHT_SHIFT) & HEIGHT_MASK);
- }
-
- public static short getDepth(long dataPoint)
- {
-
- return (short) ((dataPoint >> DEPTH_SHIFT) & DEPTH_MASK);
- }
-
- public static short getRed(long dataPoint)
- {
-
- return (short) ((dataPoint >> RED_SHIFT) & RED_MASK);
- }
-
- public static short getGreen(long dataPoint)
- {
- return (short) ((dataPoint >> GREEN_SHIFT) & GREEN_MASK);
- }
-
- public static short getBlue(long dataPoint)
- {
- return (short) ((dataPoint >> BLUE_SHIFT) & BLUE_MASK);
- }
-
- public static boolean doesItExist(long dataPoint)
- {
- return ((dataPoint & EXISTENCE_MASK) == 1);
- }
-
- public static int getColor(long dataPoint)
- {
- int R = (getRed(dataPoint) << 16) & 0x00FF0000;
- int G = (getGreen(dataPoint) << 8) & 0x0000FF00;
- int B = getBlue(dataPoint)& 0x000000FF;
- return 0xFF000000 | R | G | B;
- }
-
- public static String toString(long dataPoint)
- {
- StringBuilder s = new StringBuilder();
- s.append(getHeight(dataPoint));
- s.append(" ");
- s.append(getDepth(dataPoint));
- s.append(" ");
- s.append(getRed(dataPoint));
- s.append(" ");
- s.append(getBlue(dataPoint));
- s.append(" ");
- s.append(getGreen(dataPoint));
- s.append('\n');
- return s.toString();
- }
-}
diff --git a/src/main/java/com/seibel/lod/objects/LevelContainer.java b/src/main/java/com/seibel/lod/objects/LevelContainer.java
index ffadb459c..94bcd2c36 100644
--- a/src/main/java/com/seibel/lod/objects/LevelContainer.java
+++ b/src/main/java/com/seibel/lod/objects/LevelContainer.java
@@ -1,67 +1,61 @@
package com.seibel.lod.objects;
-import java.io.Serializable;
-
+import com.seibel.lod.util.LevelPosUtil;
import com.seibel.lod.util.LodUtil;
-public class LevelContainer implements Serializable
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+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.
+ * @param posX x position in the detail level
+ * @param posZ z position in the detail level
+ * @return true if correctly added, false otherwise
+ */
+ public boolean addData(long[] data, int posX, int posZ);
- /** This is here so that Eclipse doesn't complain */
- private static final long serialVersionUID = -4930855068717998385L;
+ /**With this you can get data from the level container
+ *
+ * @param posX x position in the detail level
+ * @param posZ z position in the detail level
+ * @return the data in long array format
+ */
+ public long[] getData(int posX, int posZ);
- public static final char DATA_DELIMITER = ',';
+ /**
+ * @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);
- public final byte detailLevel;
+ /**
+ * @return return the deatilLevel of this level container
+ */
+ public byte getDetailLevel();
- public final long[][] data;
+ /**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();
- public LevelContainer(byte detailLevel, long[][] data)
- {
- this.detailLevel = detailLevel;
- this.data = data;
- }
+ /**
+ *
+ * @param lowerLevelContainer lower level where we extract the data
+ * @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);
- public LevelContainer(String inputString)
- {
-
- int index = 0;
- int lastIndex = 0;
-
-
- index = inputString.indexOf(DATA_DELIMITER, 0);
- this.detailLevel = (byte) Integer.parseInt(inputString.substring(0, index));
- int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
-
- this.data = new long[size][size];
- for (int x = 0; x < size; x++)
- {
- for (int z = 0; z < size; z++)
- {
- lastIndex = index;
- index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1);
- data[x][z] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16);
- }
- }
-
- }
-
- @Override
- public String toString()
- {
- StringBuilder stringBuilder = new StringBuilder();
- int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
- stringBuilder.append(detailLevel);
- stringBuilder.append(DATA_DELIMITER);
- for (int x = 0; x < size; x++)
- {
- for (int z = 0; z < size; z++)
- {
- //Converting the dataToHex
- stringBuilder.append(Long.toHexString(data[x][z]));
- stringBuilder.append(DATA_DELIMITER);
- }
- }
- return stringBuilder.toString();
- }
+ /**
+ * This will give the data to save in the file
+ * @return data as a String
+ */
+ public String toDataString();
}
diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java
index 2343ff682..127d541f7 100644
--- a/src/main/java/com/seibel/lod/objects/LodDimension.java
+++ b/src/main/java/com/seibel/lod/objects/LodDimension.java
@@ -25,9 +25,7 @@ import java.util.concurrent.Executors;
import com.seibel.lod.config.LodConfig;
import com.seibel.lod.enums.DistanceGenerationMode;
import com.seibel.lod.handlers.LodDimensionFileHandler;
-import com.seibel.lod.util.DetailDistanceUtil;
-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;
@@ -435,7 +433,7 @@ public class LodDimension
* stored in the LOD. If an LOD already exists at the given
* coordinates it will be overwritten.
*/
- public synchronized Boolean addData(byte detailLevel, int posX, int posZ, long lodDataPoint, boolean dontSave, boolean serverQuality)
+ public Boolean addData(byte detailLevel, int posX, int posZ, long[] dataPoint, boolean dontSave, boolean serverQuality)
{
// don't continue if the region can't be saved
@@ -445,7 +443,7 @@ public class LodDimension
LodRegion region = getRegion(regionPosX, regionPosZ);
if (region == null)
return false;
- boolean nodeAdded = region.addData(detailLevel, posX, posZ, lodDataPoint, serverQuality);
+ boolean nodeAdded = region.addData(detailLevel, posX, posZ, dataPoint, serverQuality);
// only save valid LODs to disk
if (!dontSave && fileHandler != null)
{
@@ -520,7 +518,7 @@ public class LodDimension
* Returns null if the LodChunk doesn't exist or
* is outside the loaded area.
*/
- public long getData(byte detailLevel, int posX, int posZ)
+ public long[] getData(byte detailLevel, int posX, int posZ)
{
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
@@ -529,7 +527,7 @@ public class LodDimension
if (region == null)
{
- return 0;
+ return new long[]{DataPointUtil.EMPTY_DATA};
}
return region.getData(detailLevel, posX, posZ);
diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java
index c0d4fbb18..b21efdd06 100644
--- a/src/main/java/com/seibel/lod/objects/LodRegion.java
+++ b/src/main/java/com/seibel/lod/objects/LodRegion.java
@@ -3,7 +3,9 @@ package com.seibel.lod.objects;
import com.seibel.lod.builders.LodBuilder;
import com.seibel.lod.enums.DistanceGenerationMode;
+import com.seibel.lod.util.DataPointUtil;
import com.seibel.lod.util.DetailDistanceUtil;
+import com.seibel.lod.util.LevelPosUtil;
import com.seibel.lod.util.LodUtil;
/**
@@ -20,65 +22,61 @@ public class LodRegion
private byte minDetailLevel;
private static final byte POSSIBLE_LOD = 10;
//private int numberOfPoints;
- private DistanceGenerationMode generationMode;
//For each of the following field the first slot is for the level of detail
//Important: byte have a [-128, 127] range. When converting from or to int a 128 should be added or removed
//If there is a bug with color then it's probably caused by this.
//in the future other fields like transparency and light level could be added
- private long[][][] data;
+ private LevelContainer[] dataContainer;
+ private DistanceGenerationMode generationMode;
+
public final int regionPosX;
public final int regionPosZ;
- public LodRegion(LevelContainer levelContainer, RegionPos regionPos, DistanceGenerationMode generationMode)
+ public LodRegion(RegionPos regionPos)
{
- this.generationMode = generationMode;
+ this.minDetailLevel = LodUtil.REGION_DETAIL_LEVEL;
this.regionPosX = regionPos.x;
this.regionPosZ = regionPos.z;
- this.minDetailLevel = levelContainer.detailLevel;
-
- //Arrays of matrices
- data = new long[POSSIBLE_LOD][][];
-
- data[minDetailLevel] = levelContainer.data;
-
- //Initialize all the different matrices
- for (byte lod = (byte) (minDetailLevel + 1); lod <= LodUtil.REGION_DETAIL_LEVEL; lod++)
- {
- int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - lod);
- data[lod] = new long[size][size];
- }
- updateArea(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ);
+ dataContainer = new LevelContainer[POSSIBLE_LOD];
}
public LodRegion(byte minDetailLevel, RegionPos regionPos, DistanceGenerationMode generationMode)
{
- this.generationMode = generationMode;
this.minDetailLevel = minDetailLevel;
this.regionPosX = regionPos.x;
this.regionPosZ = regionPos.z;
-
- data = new long[POSSIBLE_LOD][][];
+ this.generationMode = generationMode;
+ dataContainer = new LevelContainer[POSSIBLE_LOD];
//Initialize all the different matrices
for (byte lod = minDetailLevel; lod <= LodUtil.REGION_DETAIL_LEVEL; lod++)
{
- int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - lod);
- data[lod] = new long[size][size];
-
+ //dataContainer[lod] = new SingleLevelContainer(lod);
+ dataContainer[lod] = new VerticalLevelContainer(lod);
+ /*if(twoDimension){
+ dataContainer[lod] = new SingleLevelContainer(lod);
+ }else{
+ dataContainer[lod] = new VerticalLevelContainer.java(lod);
+ }*/
}
}
+ public DistanceGenerationMode getGenerationMode()
+ {
+ return generationMode;
+ }
+
/**
* This method can be used to insert data into the LodRegion
*
* @param dataPoint
* @return
*/
- public boolean addData(byte detailLevel, int posX, int posZ, long dataPoint, boolean serverQuality)
+ public boolean addData(byte detailLevel, int posX, int posZ, long[] dataPoint, boolean serverQuality)
{
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
@@ -89,7 +87,7 @@ public class LodRegion
//if (!doesDataExist(detailLevel, posX, posZ)) numberOfPoints++;
//add the node data
- this.data[detailLevel][posX][posZ] = dataPoint;
+ this.dataContainer[detailLevel].addData(dataPoint, posX, posZ);
return true;
} else
{
@@ -102,11 +100,11 @@ public class LodRegion
*
* @return the data at the relative pos and level
*/
- public long getData(byte detailLevel, int posX, int posZ)
+ public long[] getData(byte detailLevel, int posX, int posZ)
{
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
- return data[detailLevel][posX][posZ];
+ return dataContainer[detailLevel].getData(posX, posZ);
}
/**
@@ -135,11 +133,11 @@ public class LodRegion
int childSize = 1 << (LodUtil.REGION_DETAIL_LEVEL - childDetailLevel);
//we have reached the target detail level
-
- if (DetailDistanceUtil.getDistanceGenerationInverse(maxDistance) > detailLevel)
+ byte targetDetailLevel = DetailDistanceUtil.getLodGenDetail(DetailDistanceUtil.getDistanceGenerationInverse(maxDistance)).detailLevel;
+ if (targetDetailLevel > detailLevel)
{
return;
- } else if (DetailDistanceUtil.getDistanceGenerationInverse(maxDistance) == detailLevel)
+ } else if (targetDetailLevel == detailLevel)
{
if (!doesDataExist(detailLevel, posX, posZ))
{
@@ -286,63 +284,7 @@ public class LodRegion
*/
private void update(byte detailLevel, int posX, int posZ)
{
- int numberOfChildren = 0;
- int numberOfVoidChildren = 0;
-
- int tempRed = 0;
- int tempGreen = 0;
- int tempBlue = 0;
- int tempHeight = 0;
- int tempDepth = 0;
- int childPosX;
- int childPosZ;
- byte childDetailLevel;
- posX = LevelPosUtil.getRegionModule(detailLevel, posX);
- posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
- for (int x = 0; x <= 1; x++)
- {
- for (int z = 0; z <= 1; z++)
- {
- childPosX = 2 * posX + x;
- childPosZ = 2 * posZ + z;
- childDetailLevel = (byte) (detailLevel - 1);
- if (doesDataExist(childDetailLevel, childPosX, childPosZ))
- {
- if (!(DataPoint.getHeight(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_HEIGHT
- && DataPoint.getDepth(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_DEPTH))
- {
- numberOfChildren++;
-
- tempRed += DataPoint.getRed(data[childDetailLevel][childPosX][childPosZ]);
- tempGreen += DataPoint.getGreen(data[childDetailLevel][childPosX][childPosZ]);
- tempBlue += DataPoint.getBlue(data[childDetailLevel][childPosX][childPosZ]);
- tempHeight += DataPoint.getHeight(data[childDetailLevel][childPosX][childPosZ]);
- tempDepth += DataPoint.getDepth(data[childDetailLevel][childPosX][childPosZ]);
- } else
- {
- // void children have the default height (most likely -1)
- // and represent a LOD with no blocks in it
- numberOfVoidChildren++;
- }
- }
- }
- }
- if (numberOfChildren > 0)
- {
- tempRed = tempRed / numberOfChildren;
- tempGreen = tempGreen / numberOfChildren;
- tempBlue = tempBlue / numberOfChildren;
- tempHeight = tempHeight / numberOfChildren;
- tempDepth = tempDepth / numberOfChildren;
- } else if (numberOfVoidChildren > 0)
- {
- tempRed = (byte) 0;
- tempGreen = (byte) 0;
- tempBlue = (byte) 0;
- tempHeight = LodBuilder.DEFAULT_HEIGHT;
- tempDepth = LodBuilder.DEFAULT_DEPTH;
- }
- data[detailLevel][posX][posZ] = DataPoint.createDataPoint(tempHeight, tempDepth, tempRed, tempGreen, tempBlue);
+ dataContainer[detailLevel].updateData(dataContainer[detailLevel - 1], posX, posZ);
}
@@ -354,15 +296,24 @@ public class LodRegion
if(detailLevel < minDetailLevel) return false;
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
- return DataPoint.doesItExist(data[detailLevel][posX][posZ]);
+ if(dataContainer == null || dataContainer[detailLevel] == null)
+ return false;
+ return dataContainer[detailLevel].doesItExist(posX, posZ);
}
/**
* @return
*/
- public DistanceGenerationMode getGenerationMode()
+ public byte getGenerationMode(byte detailLevel, int posX, int posZ)
{
- return generationMode;
+ if(dataContainer[detailLevel].doesItExist(posX,posZ))
+ {
+ //We take the bottom information always
+ return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getData(posX,posZ)[0]);
+ }else
+ {
+ return DistanceGenerationMode.NONE.complexity;
+ }
}
public byte getMinDetailLevel()
@@ -382,7 +333,7 @@ public class LodRegion
{
throw new IllegalArgumentException("getLevel asked for a level that does not exist: minimum " + minDetailLevel + " level requested " + detailLevel);
}
- return new LevelContainer(detailLevel, data[detailLevel]);
+ return dataContainer[detailLevel];
}
/**
@@ -390,12 +341,12 @@ public class LodRegion
*/
public void addLevel(LevelContainer levelContainer)
{
- if (levelContainer.detailLevel < minDetailLevel - 1)
+ if (levelContainer.getDetailLevel() < minDetailLevel - 1)
{
throw new IllegalArgumentException("addLevel requires a level that is at least the minimum level of the region -1 ");
}
- if (levelContainer.detailLevel == minDetailLevel - 1) minDetailLevel = levelContainer.detailLevel;
- data[levelContainer.detailLevel] = levelContainer.data;
+ if (levelContainer.getDetailLevel() == minDetailLevel - 1) minDetailLevel = levelContainer.getDetailLevel();
+ dataContainer[levelContainer.getDetailLevel()] = levelContainer;
}
@@ -408,7 +359,7 @@ public class LodRegion
{
for (byte tempLod = 0; tempLod < detailLevel; tempLod++)
{
- data[tempLod] = new long[0][0];
+ dataContainer[tempLod] = null;
}
minDetailLevel = detailLevel;
}
@@ -421,10 +372,13 @@ public class LodRegion
{
if (detailLevel < minDetailLevel)
{
- for (byte tempLod = detailLevel; tempLod < minDetailLevel; tempLod++)
+ for (byte tempLod = (byte) (minDetailLevel - 1); tempLod >= detailLevel ; tempLod--)
{
- int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - tempLod);
- data[tempLod] = new long[size][size];
+ if(dataContainer[tempLod + 1] == null)
+ {
+ dataContainer[tempLod + 1] = new SingleLevelContainer((byte) (tempLod + 1));
+ }
+ dataContainer[tempLod] = dataContainer[tempLod+1].expand();
}
minDetailLevel = detailLevel;
}
diff --git a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java
index 405ee2b77..2f05f75dc 100644
--- a/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java
+++ b/src/main/java/com/seibel/lod/objects/PosToGenerateContainer.java
@@ -1,5 +1,7 @@
package com.seibel.lod.objects;
+import com.seibel.lod.util.LevelPosUtil;
+
public class PosToGenerateContainer
{
private int playerPosX;
diff --git a/src/main/java/com/seibel/lod/objects/PosToRenderContainer.java b/src/main/java/com/seibel/lod/objects/PosToRenderContainer.java
index ef056a13d..2ec972613 100644
--- a/src/main/java/com/seibel/lod/objects/PosToRenderContainer.java
+++ b/src/main/java/com/seibel/lod/objects/PosToRenderContainer.java
@@ -1,5 +1,6 @@
package com.seibel.lod.objects;
+import com.seibel.lod.util.LevelPosUtil;
import com.seibel.lod.util.LodUtil;
public class PosToRenderContainer
diff --git a/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java
new file mode 100644
index 000000000..88984802e
--- /dev/null
+++ b/src/main/java/com/seibel/lod/objects/SingleLevelContainer.java
@@ -0,0 +1,153 @@
+package com.seibel.lod.objects;
+
+import com.seibel.lod.builders.LodBuilder;
+import com.seibel.lod.enums.DistanceGenerationMode;
+import com.seibel.lod.util.*;
+
+public class SingleLevelContainer implements LevelContainer
+{
+ public final byte detailLevel;
+ public final int size;
+
+ public final long[][] data;
+
+ public SingleLevelContainer(byte detailLevel)
+ {
+ this.detailLevel = detailLevel;
+ size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
+ data = new long[size][size];
+ }
+
+ public boolean addData(long[] newData, int posX, int posZ){
+
+ posX = LevelPosUtil.getRegionModule(detailLevel, posX);
+ posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
+ data[posX][posZ] = newData[0];
+ return true;
+ }
+
+ private boolean addSingleData(long newData, int posX, int posZ){
+ posX = LevelPosUtil.getRegionModule(detailLevel, posX);
+ posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
+ data[posX][posZ] = newData;
+ return true;
+ }
+
+ public long[] getData(int posX, int posZ){
+ long[] dataArray = ThreadMapUtil.getSingleGetDataArray();
+ posX = LevelPosUtil.getRegionModule(detailLevel, posX);
+ posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
+ //Improve this using a thread map to long[]
+ dataArray[0] = data[posX][posZ];
+ return dataArray;
+ }
+
+ private long getSingleData(int posX, int posZ){
+ posX = LevelPosUtil.getRegionModule(detailLevel, posX);
+ posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
+ //Improve this using a thread map to long[]
+ return data[posX][posZ];
+ }
+
+ public byte getDetailLevel(){
+ return detailLevel;
+ }
+
+ public LevelContainer expand(){
+ return new SingleLevelContainer((byte) (getDetailLevel() - 1));
+ }
+
+ public SingleLevelContainer(String inputString)
+ {
+ int tempIndex;
+ int shift = 0;
+ int index = 0;
+ int digit;
+ char currentChar;
+ long newData;
+ currentChar = inputString.charAt(index);
+ digit = Character.digit(currentChar,16);
+ detailLevel = (byte) digit;
+ size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
+ this.data = new long[size][size];
+ for (int x = 0; x < size; x++)
+ {
+ for (int z = 0; z < size; z++)
+ {
+ newData = 0;
+ for(tempIndex = 0; tempIndex < 16; tempIndex++)
+ {
+ if(index+tempIndex >= inputString.length())
+ break;
+ currentChar = inputString.charAt(index+tempIndex);
+ if(currentChar == DATA_DELIMITER){
+ break;
+ }
+ shift = (15-tempIndex)*4;
+ digit = Character.digit(currentChar,16);
+ newData += ((((long) digit & 0xf)) << shift);
+ }
+ newData = newData >>> (shift);
+ data[x][z] = newData;
+ index = index + tempIndex;
+ }
+ }
+ }
+
+ public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ)
+ {
+ //We reset the array
+ long[] dataToMerge = ThreadMapUtil.getSingleUpdateArray();
+
+ int childPosX;
+ int childPosZ;
+ long data = 0;
+ posX = LevelPosUtil.getRegionModule(detailLevel, posX);
+ posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
+ for (int x = 0; x <= 1; x++)
+ {
+ for (int z = 0; z <= 1; z++)
+ {
+ childPosX = 2 * posX + x;
+ childPosZ = 2 * posZ + z;
+ dataToMerge[2*x + z] = ((SingleLevelContainer) lowerLevelContainer).getSingleData(childPosX, childPosZ);
+ }
+ }
+ data = DataPointUtil.mergeSingleData(dataToMerge);
+ addSingleData(data,posX,posZ);
+ }
+
+
+ public boolean doesItExist(int posX, int posZ){
+ posX = LevelPosUtil.getRegionModule(detailLevel, posX);
+ posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
+ //Improve this using a thread map to long[]
+ return DataPointUtil.doesItExist(getSingleData(posX, posZ));
+ }
+
+ public String toDataString()
+ {
+ StringBuilder stringBuilder = new StringBuilder();
+ int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
+ stringBuilder.append(detailLevel);
+ stringBuilder.append(DATA_DELIMITER);
+ for (int x = 0; x < size; x++)
+ {
+ for (int z = 0; z < size; z++)
+ {
+ //Converting the dataToHex
+ stringBuilder.append(Long.toHexString(data[x][z]));
+ stringBuilder.append(DATA_DELIMITER);
+ }
+ }
+ return stringBuilder.toString();
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append(detailLevel);
+ return stringBuilder.toString();
+ }
+}
diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java
new file mode 100644
index 000000000..3de5e291b
--- /dev/null
+++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java
@@ -0,0 +1,129 @@
+package com.seibel.lod.objects;
+
+import com.seibel.lod.util.DataPointUtil;
+import com.seibel.lod.util.LevelPosUtil;
+import com.seibel.lod.util.LodUtil;
+import com.seibel.lod.util.ThreadMapUtil;
+
+import java.security.InvalidParameterException;
+
+public class VerticalLevelContainer implements LevelContainer
+{
+
+ public final byte detailLevel;
+
+ public final long[][][] dataContainer;
+
+ public VerticalLevelContainer(byte detailLevel)
+ {
+ this.detailLevel = detailLevel;
+ int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
+ dataContainer = new long[size][size][1];
+ }
+
+ @Override
+ public byte getDetailLevel()
+ {
+ return detailLevel;
+ }
+
+ public boolean addData(long[] newData, int posX, int posZ){
+ posX = LevelPosUtil.getRegionModule(detailLevel, posX);
+ posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
+ dataContainer[posX][posZ] = newData;
+ return true;
+ }
+
+ public long[] getData(int posX, int posZ){
+ posX = LevelPosUtil.getRegionModule(detailLevel, posX);
+ posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
+ return dataContainer[posX][posZ];
+ }
+
+ public boolean doesItExist(int posX, int posZ){
+ long[] data = getData(posX,posZ);
+ if(data == null)
+ return false;
+ return DataPointUtil.doesItExist(data[0]);
+ }
+
+ public VerticalLevelContainer(String inputString)
+ {
+
+ throw new InvalidParameterException("loading not yet implemented");
+
+/*
+ int index = 0;
+ int lastIndex = 0;
+
+
+ index = inputString.indexOf(DATA_DELIMITER, 0);
+ this.detailLevel = (byte) Integer.parseInt(inputString.substring(0, index));
+ int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
+
+ this.dataContainer = new long[size][size][1];
+ for (int x = 0; x < size; x++)
+ {
+ for (int z = 0; z < size; z++)
+ {
+ lastIndex = index;
+ index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1);
+ dataContainer[x][z][0] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16);
+ }
+ }*/
+ }
+
+ public LevelContainer expand(){
+ return new VerticalLevelContainer((byte) (getDetailLevel() - 1));
+ }
+
+ public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ)
+ {
+ //We reset the array
+ long[][] dataToMerge = ThreadMapUtil.getVerticalUpdateArray();
+
+ int childPosX;
+ int childPosZ;
+ long[] data;
+ posX = LevelPosUtil.getRegionModule(detailLevel, posX);
+ posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
+ for (int x = 0; x <= 1; x++)
+ {
+ for (int z = 0; z <= 1; z++)
+ {
+ childPosX = 2 * posX + x;
+ childPosZ = 2 * posZ + z;
+ dataToMerge[2*z + x] = lowerLevelContainer.getData(childPosX, childPosZ);
+ }
+ }
+ data = DataPointUtil.mergeVerticalData(dataToMerge);
+ addData(data,posX,posZ);
+ }
+
+ public String toDataString()
+ {
+ return toString();
+ }
+
+ @Override
+ public String toString()
+ {
+ /*
+ StringBuilder stringBuilder = new StringBuilder();
+ int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
+ stringBuilder.append(detailLevel);
+ stringBuilder.append(DATA_DELIMITER);
+ for (int x = 0; x < size; x++)
+ {
+ for (int z = 0; z < size; z++)
+ {
+ //Converting the dataToHex
+ stringBuilder.append(Long.toHexString(dataContainer[x][z][0]));
+ stringBuilder.append(DATA_DELIMITER);
+ }
+ }
+ return stringBuilder.toString();
+ */
+ return " ";
+ }
+}
diff --git a/src/main/java/com/seibel/lod/proxy/ClientProxy.java b/src/main/java/com/seibel/lod/proxy/ClientProxy.java
index 68f2918a1..551a8ca72 100644
--- a/src/main/java/com/seibel/lod/proxy/ClientProxy.java
+++ b/src/main/java/com/seibel/lod/proxy/ClientProxy.java
@@ -101,7 +101,7 @@ public class ClientProxy
public void renderLods(float partialTicks)
{
// only run the first time setup once
- if (firstTimeSetupComplete)
+ if (!firstTimeSetupComplete)
{
firstFrameSetup();
}
diff --git a/src/main/java/com/seibel/lod/render/LodRenderer.java b/src/main/java/com/seibel/lod/render/LodRenderer.java
index 918281b1f..b2601ae00 100644
--- a/src/main/java/com/seibel/lod/render/LodRenderer.java
+++ b/src/main/java/com/seibel/lod/render/LodRenderer.java
@@ -39,7 +39,7 @@ import com.seibel.lod.enums.FogDistance;
import com.seibel.lod.enums.FogDrawOverride;
import com.seibel.lod.enums.FogQuality;
import com.seibel.lod.handlers.ReflectionHandler;
-import com.seibel.lod.objects.LevelPosUtil;
+import com.seibel.lod.util.LevelPosUtil;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.NearFarFogSettings;
import com.seibel.lod.objects.RegionPos;
@@ -551,7 +551,7 @@ public class LodRenderer
// it is possible to see the near clip plane, but
// you have to be flying quickly in spectator mode through ungenerated
// terrain, so I don't think it is much of an issue.
- mc.getRenderDistance(),
+ mc.getRenderDistance()/2,
farPlaneBlockDistance * LodUtil.CHUNK_WIDTH * 2);
// add the screen space distortions
diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java
new file mode 100644
index 000000000..7df1df24c
--- /dev/null
+++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java
@@ -0,0 +1,390 @@
+package com.seibel.lod.util;
+
+import com.seibel.lod.enums.DistanceGenerationMode;
+import net.minecraft.client.renderer.LightTexture;
+
+public class DataPointUtil
+{
+ /*
+ |a |a |a |a |r |r |r |r |
+
+ |r |r |r |r |g |g |g |g |
+
+ |g |g |g |g |b |b |b |b |
+
+ |b |b |b |b |h |h |h |h |
+
+ |h |h |h |h |h |h |d |d |
+
+ |d |d |d |d |d |d |d |d |
+
+ |bl |bl |bl |bl |sl |sl |sl |sl |
+
+ |l |l |f |g |g |g |v |e |
+
+
+ */
+ //To be used in the future for negative value
+ //public final static int MIN_DEPTH = -64;
+ //public final static int MIN_HEIGHT = -64;
+ public final static int EMPTY_DATA = 0;
+ public final static int WORLD_HEIGHT = 256;
+
+ public final static int ALPHA_DOWNSIZE_SHIFT = 4;
+
+ public final static int BLUE_COLOR_SHIFT = 0;
+ public final static int GREEN_COLOR_SHIFT = 8;
+ public final static int RED_COLOR_SHIFT = 16;
+ public final static int ALPHA_COLOR_SHIFT = 24;
+
+ public final static int BLUE_SHIFT = 36;
+ public final static int GREEN_SHIFT = BLUE_SHIFT + 8;
+ public final static int RED_SHIFT = BLUE_SHIFT + 16 ;
+ public final static int ALPHA_SHIFT = BLUE_SHIFT + 24;
+
+ public final static int COLOR_SHIFT = 36;
+
+ public final static int HEIGHT_SHIFT = 26;
+ public final static int DEPTH_SHIFT = 16;
+ public final static int BLOCK_LIGHT_SHIFT = 12;
+ public final static int SKY_LIGHT_SHIFT = 8;
+ public final static int LIGHTS_SHIFT = SKY_LIGHT_SHIFT;
+ public final static int VERTICAL_INDEX_SHIFT = 6;
+ public final static int FLAG_SHIFT = 5;
+ public final static int GEN_TYPE_SHIFT = 2;
+ public final static int VOID_SHIFT = 1;
+ public final static int EXISTENCE_SHIFT = 0;
+
+ public final static long ALPHA_MASK = 0b1111;
+ public final static long RED_MASK = 0b1111_1111;
+ public final static long GREEN_MASK = 0b1111_1111;
+ public final static long BLUE_MASK = 0b1111_1111;
+ public final static long COLOR_MASK = 0b11111111_11111111_11111111;
+ public final static long HEIGHT_MASK = 0b11_1111_1111;
+ public final static long DEPTH_MASK = 0b11_1111_1111;
+ public final static long LIGHTS_MASK = 0b1111_1111;
+ public final static long BLOCK_LIGHT_MASK = 0b1111;
+ public final static long SKY_LIGHT_MASK = 0b1111;
+ public final static long VERTICAL_INDEX_MASK = 0b11;
+ public final static long FLAG_MASK = 0b1;
+ public final static long GEN_TYPE_MASK = 0b111;
+ public final static long VOID_MASK = 1;
+ public final static long EXISTENCE_MASK = 1;
+
+
+ public static long createVoidDataPoint(int generationMode)
+ {
+ long dataPoint = 0;
+ dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT;
+ dataPoint += VOID_MASK << VOID_SHIFT;
+ dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT;
+ return dataPoint;
+ }
+
+ public static long createDataPoint(int height, int depth, int color, int lightSky, int lightBlock, int generationMode)
+ {
+ return createDataPoint(
+ ColorUtil.getAlpha(color),
+ ColorUtil.getRed(color),
+ ColorUtil.getGreen(color),
+ ColorUtil.getBlue(color),
+ height, depth, lightSky, lightBlock, generationMode);
+ }
+
+ public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightSky, int lightBlock, int generationMode)
+ {
+ long dataPoint = 0;
+ dataPoint += ((alpha & ALPHA_MASK) >>> ALPHA_DOWNSIZE_SHIFT) << ALPHA_SHIFT;
+ dataPoint += (red & RED_MASK) << RED_SHIFT;
+ dataPoint += (green & GREEN_MASK) << GREEN_SHIFT;
+ dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT;
+ dataPoint += (height & HEIGHT_MASK) << HEIGHT_SHIFT;
+ dataPoint += (depth & DEPTH_MASK) << DEPTH_SHIFT;
+ dataPoint += (lightBlock & BLOCK_LIGHT_MASK) << BLOCK_LIGHT_SHIFT;
+ dataPoint += (lightSky & SKY_LIGHT_MASK) << SKY_LIGHT_SHIFT;
+ dataPoint += (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT;
+ dataPoint += EXISTENCE_MASK << EXISTENCE_SHIFT;
+ return dataPoint;
+ }
+
+ public static short getHeight(long dataPoint)
+ {
+ return (short) ((dataPoint >>> HEIGHT_SHIFT) & HEIGHT_MASK);
+ }
+
+ public static short getDepth(long dataPoint)
+ {
+
+ return (short) ((dataPoint >>> DEPTH_SHIFT) & DEPTH_MASK);
+ }
+
+ public static short getAlpha(long dataPoint)
+ {
+ return (short) (((dataPoint >>> ALPHA_SHIFT) & ALPHA_MASK) << ALPHA_DOWNSIZE_SHIFT);
+ }
+
+ public static short getRed(long dataPoint)
+ {
+ return (short) ((dataPoint >>> RED_SHIFT) & RED_MASK);
+ }
+
+ public static short getGreen(long dataPoint)
+ {
+ return (short) ((dataPoint >>> GREEN_SHIFT) & GREEN_MASK);
+ }
+
+ public static short getBlue(long dataPoint)
+ {
+ return (short) ((dataPoint >>> BLUE_SHIFT) & BLUE_MASK);
+ }
+
+ public static int getLightSky(long dataPoint)
+ {
+ return (int) ((dataPoint >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK);
+ }
+
+ public static int getLightBlock(long dataPoint)
+ {
+ return (int) ((dataPoint >>> BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK);
+ }
+
+ public static byte getGenerationMode(long dataPoint)
+ {
+ return (byte) ((dataPoint >>> GEN_TYPE_SHIFT) & GEN_TYPE_MASK);
+ }
+
+
+ public static boolean isItVoid(long dataPoint)
+ {
+ return (((dataPoint >>> VOID_SHIFT) & VOID_MASK) == 1);
+ }
+
+ public static boolean doesItExist(long dataPoint)
+ {
+ return (((dataPoint >>> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1);
+ }
+
+ public static int getColor(long dataPoint)
+ {
+ int color = getBlue(dataPoint) << BLUE_COLOR_SHIFT;
+ color += getRed(dataPoint) << BLUE_COLOR_SHIFT;
+ return (int) (dataPoint >>> COLOR_SHIFT);
+ }
+
+ public static int getLightColor(long dataPoint, boolean roof, boolean day)
+ {
+ int lightBlock = getLightBlock(dataPoint);
+ int lightSky = getLightSky(dataPoint);
+ int lightTint = LightTexture.pack(lightSky,lightBlock);
+
+ int red = (ColorUtil.getRed(lightTint) + getRed(dataPoint))/2;
+ int green = (ColorUtil.getGreen(lightTint) + getGreen(dataPoint))/2;
+ int blue = (ColorUtil.getBlue(lightTint) + getBlue(dataPoint))/2;
+ /*
+ red = LodUtil.clamp(0, getRed(dataPoint) + red, 255);
+ green = LodUtil.clamp(0, getGreen(dataPoint) + green, 255);
+ blue = LodUtil.clamp(0, getBlue(dataPoint) + blue, 255);*/
+
+ return ColorUtil.rgbToInt(red, green, blue);
+ }
+
+ public static String toString(long dataPoint)
+ {
+ StringBuilder s = new StringBuilder();
+ s.append(getHeight(dataPoint));
+ s.append(" ");
+ s.append(getDepth(dataPoint));
+ s.append(" ");
+ s.append(getAlpha(dataPoint));
+ s.append(" ");
+ s.append(getRed(dataPoint));
+ s.append(" ");
+ s.append(getBlue(dataPoint));
+ s.append(" ");
+ s.append(getGreen(dataPoint));
+ s.append(" ");
+ s.append(getLightBlock(dataPoint));
+ s.append(" ");
+ s.append(getLightSky(dataPoint));
+ s.append(" ");
+ s.append(getGenerationMode(dataPoint));
+ s.append(" ");
+ s.append(isItVoid(dataPoint));
+ s.append(" ");
+ s.append(doesItExist(dataPoint));
+ s.append('\n');
+ return s.toString();
+ }
+
+ public static long mergeSingleData(long[] dataToMerge)
+ {
+ int numberOfChildren = 0;
+ int numberOfVoidChildren = 0;
+
+ int tempAlpha = 0;
+ int tempRed = 0;
+ int tempGreen = 0;
+ int tempBlue = 0;
+ int tempHeight = 0;
+ int tempDepth = 0;
+ int tempLightBlock = 0;
+ int tempLightSky = 0;
+ byte tempGenMode = DistanceGenerationMode.SERVER.complexity;
+ boolean allEmpty = true;
+ boolean allVoid = true;
+ for (long data : dataToMerge)
+ {
+ if (DataPointUtil.doesItExist(data))
+ {
+ allEmpty = false;
+ if (!(DataPointUtil.isItVoid(data)))
+ {
+ numberOfChildren++;
+ allVoid = false;
+ tempAlpha += DataPointUtil.getAlpha(data);
+ tempRed += DataPointUtil.getRed(data);
+ tempGreen += DataPointUtil.getGreen(data);
+ tempBlue += DataPointUtil.getBlue(data);
+ tempHeight += DataPointUtil.getHeight(data);
+ tempDepth += DataPointUtil.getDepth(data);
+ tempLightBlock += DataPointUtil.getLightBlock(data);
+ tempLightSky += DataPointUtil.getLightSky(data);
+ }
+ tempGenMode = (byte) Math.min(tempGenMode, DataPointUtil.getGenerationMode(data));
+ } else
+ {
+ tempGenMode = (byte) Math.min(tempGenMode, DistanceGenerationMode.NONE.complexity);
+ }
+ }
+
+ if (allEmpty)
+ {
+ //no child has been initialized
+ return DataPointUtil.EMPTY_DATA;
+ } else if (allVoid)
+ {
+ //all the children are void
+ return DataPointUtil.createVoidDataPoint(tempGenMode);
+ } else
+ {
+ //we have at least 1 child
+ tempAlpha = tempAlpha / numberOfChildren;
+ tempRed = tempRed / numberOfChildren;
+ tempGreen = tempGreen / numberOfChildren;
+ tempBlue = tempBlue / numberOfChildren;
+ tempHeight = tempHeight / numberOfChildren;
+ tempDepth = tempDepth / numberOfChildren;
+ tempLightBlock = tempLightBlock / numberOfChildren;
+ tempLightSky = tempLightSky / numberOfChildren;
+ return DataPointUtil.createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, tempHeight, tempDepth, tempLightSky, tempLightBlock, tempGenMode);
+ }
+ }
+
+ public static long[] mergeVerticalData(long[][] dataToMerge)
+ {
+ boolean[] projection = ThreadMapUtil.getProjection(WORLD_HEIGHT + 1);
+ int[][] heightAndDepth = ThreadMapUtil.getHeightAndDepth(WORLD_HEIGHT + 1);
+ long[] singleDataToMerge = ThreadMapUtil.getSingleAddDataToMerge(dataToMerge.length);
+ int genMode = DistanceGenerationMode.SERVER.complexity;
+ boolean allEmpty = true;
+ boolean allVoid = true;
+ long singleData;
+
+ for(int k=0; k < projection.length; k++)
+ projection[k] = false;
+ int depth = 0;
+ int height = 0;
+ //We collect the indexes of the data, ordered by the depth
+ for (int index = 0; index < dataToMerge.length; index++)
+ {
+ for (int dataIndex = 0; dataIndex < dataToMerge[index].length; dataIndex++)
+ {
+ singleData = dataToMerge[index][dataIndex];
+ if (doesItExist(singleData))
+ {
+ genMode = Math.min(genMode, getGenerationMode(singleData));
+ allEmpty = false;
+ if (!isItVoid(singleData))
+ {
+ allVoid = false;
+ depth = getDepth(singleData);
+ height = getHeight(singleData);
+ for (int y = depth; y <= height; y++)
+ {
+ projection[y] = true;
+ }
+ }
+ }
+ }
+ }
+
+
+ //We check if there is any data that's not empty or void
+ if (allEmpty)
+ {
+ return new long[]{EMPTY_DATA};
+ }
+ if (allVoid)
+ {
+ return new long[]{createVoidDataPoint(genMode)};
+ }
+
+ int count = 0;
+ int i = 0;
+ while (i < projection.length)
+ {
+ while (i < projection.length && !projection[i])
+ {
+ i++;
+ }
+ depth = i;
+ while (i < projection.length && projection[i])
+ {
+ height = i;
+ i++;
+ }
+ if(!(i < projection.length))
+ break;
+ heightAndDepth[count][0] = depth;
+ heightAndDepth[count][1] = height;
+ count++;
+ }
+ //As standard the vertical lods are ordered from top to bottom
+ long[] dataPoint = new long[count];
+ for (int j = count - 1; j >= 0; j--)
+ {
+ depth = heightAndDepth[j][0];
+ height = heightAndDepth[j][1];
+ for(int k = 0; k < dataToMerge.length; k++){
+ singleDataToMerge[k] = 0;
+ }
+ for (int index = 0; index < dataToMerge.length; index++)
+ {
+ for (int dataIndex = 0; dataIndex < dataToMerge[index].length; dataIndex++)
+ {
+ singleData = dataToMerge[index][dataIndex];
+ if (doesItExist(singleData) && !isItVoid(singleData))
+ {
+ if ((depth <= getDepth(singleData) && getDepth(singleData) <= height)
+ || (depth <= getHeight(singleData) && getHeight(singleData) <= height))
+ {
+ if(getHeight(singleData) > getHeight(singleDataToMerge[index]))
+ {
+ singleDataToMerge[index] = singleData;
+ }
+ }
+ }
+ }
+ }
+ long data = mergeSingleData(singleDataToMerge);
+ dataPoint[j] = createDataPoint(height, depth, getColor(data), getLightSky(data), getLightBlock(data), getGenerationMode(data));
+ }
+
+ return dataPoint;
+ }
+
+ public static long[] compress(long[] data, byte detailLevel)
+ {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java
index 860000a17..a98fc9ec5 100644
--- a/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java
+++ b/src/main/java/com/seibel/lod/util/DetailDistanceUtil.java
@@ -19,6 +19,19 @@ public class DetailDistanceUtil
private static int base = 2;
private static double logBase = Math.log(2);
+ private static int[] maxVerticalData = {
+ 8,
+ 4,
+ 4,
+ 2,
+ 2,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,};
+
private static LodDetail[] lodGenDetails = {
LodDetail.FULL,
LodDetail.HALF,
@@ -147,7 +160,13 @@ public class DetailDistanceUtil
public static byte getLodDrawDetail(int detail)
{
- return (byte) Math.max(detail, minDrawDetail);
+ if (detail < minGenDetail)
+ {
+ return lodGenDetails[minGenDetail].detailLevel;
+ } else
+ {
+ return lodGenDetails[detail].detailLevel;
+ }
}
public static LodDetail getLodGenDetail(int detail)
@@ -176,6 +195,10 @@ public class DetailDistanceUtil
}
}
+ public static int getMaxVerticalData(int detail)
+ {
+ return maxVerticalData[LodUtil.clamp(minGenDetail, detail, LodUtil.REGION_DETAIL_LEVEL)];
+ }
public static boolean regionInView(int playerPosX, int playerPosY, int playerPosZ, int xRot, int yRot, int fov, RegionPos regionPos)
{
diff --git a/src/main/java/com/seibel/lod/objects/LevelPosUtil.java b/src/main/java/com/seibel/lod/util/LevelPosUtil.java
similarity index 99%
rename from src/main/java/com/seibel/lod/objects/LevelPosUtil.java
rename to src/main/java/com/seibel/lod/util/LevelPosUtil.java
index a3cf7628e..af3bc7547 100644
--- a/src/main/java/com/seibel/lod/objects/LevelPosUtil.java
+++ b/src/main/java/com/seibel/lod/util/LevelPosUtil.java
@@ -1,4 +1,4 @@
-package com.seibel.lod.objects;
+package com.seibel.lod.util;
import com.seibel.lod.util.LodUtil;
diff --git a/src/main/java/com/seibel/lod/util/LodUtil.java b/src/main/java/com/seibel/lod/util/LodUtil.java
index 57410a96d..915eb7bab 100644
--- a/src/main/java/com/seibel/lod/util/LodUtil.java
+++ b/src/main/java/com/seibel/lod/util/LodUtil.java
@@ -21,7 +21,6 @@ import java.awt.Color;
import java.io.File;
import java.util.HashSet;
-import com.seibel.lod.objects.DataPoint;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.RegionPos;
import com.seibel.lod.wrappers.MinecraftWrapper;
@@ -64,7 +63,10 @@ public class LodUtil
* and/or add a method to generate colors based on texture
* issue #64 */
public static final int STONE_COLOR_INT = LodUtil.colorToInt(new Color(150, 150, 150));
-
+ public static final int NETHERRACK_COLOR_INT = LodUtil.colorToInt(new Color(95, 38, 38));
+ public static final int WARPED_NYLIUM_COLOR_INT = LodUtil.colorToInt(new Color(34, 94, 85));
+ public static final int CRIMSON_NYLIUM_COLOR_INT = LodUtil.colorToInt(new Color(126, 27, 27));
+
/**
* In order of nearest to farthest:
* Red, Orange, Yellow, Green, Cyan, Blue, Magenta, white, gray, black
@@ -337,17 +339,19 @@ public class LodUtil
{
if (!lodDim.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, x, z))
continue;
+ /*
+ long[] dataVertical = lodDim.getData(LodUtil.CHUNK_DETAIL_LEVEL, x, z);
+ long data = dataVertical[dataVertical.length - 1];
- long data = lodDim.getData(LodUtil.CHUNK_DETAIL_LEVEL, x, z);
-
- short lodAverageHeight = DataPoint.getHeight(data);
+ short lodAverageHeight = DataPointUtil.getHeight(data);
if (playerPos.getY() <= lodAverageHeight)
{
// don't draw Lod's that are taller than the player
// to prevent LODs being drawn on top of the player
posToSkip.add(new ChunkPos(x, z));
- }
+ }*/
+ posToSkip.add(new ChunkPos(x, z));
}
}
diff --git a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java
new file mode 100644
index 000000000..39ea8f798
--- /dev/null
+++ b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java
@@ -0,0 +1,123 @@
+package com.seibel.lod.util;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class ThreadMapUtil
+{
+ public static final ConcurrentMap threadSingleAddDataMap = new ConcurrentHashMap();
+ public static final ConcurrentMap threadSingleGetDataMap = new ConcurrentHashMap();
+ public static final ConcurrentMap threadSingleUpdateMap = new ConcurrentHashMap();
+ public static final ConcurrentMap threadBuilderArrayMap = new ConcurrentHashMap();
+ public static final ConcurrentMap threadBuilderVerticalArrayMap = new ConcurrentHashMap();
+ public static final ConcurrentMap threadVerticalAddDataMap = new ConcurrentHashMap();
+ public static final ConcurrentMap threadVerticalGetDataMap = new ConcurrentHashMap();
+ public static final ConcurrentMap threadVerticalUpdateMap = new ConcurrentHashMap();
+ public static final ConcurrentMap threadVerticalIndexesMap = new ConcurrentHashMap();
+
+
+ public static final ConcurrentMap projectionMap = new ConcurrentHashMap();
+ public static final ConcurrentMap heightAndDepthMap = new ConcurrentHashMap();
+ public static final ConcurrentMap singleDataToMergeMap = new ConcurrentHashMap();
+
+
+ public static long[] getSingleAddDataArray(){
+ if(!threadSingleAddDataMap.containsKey(Thread.currentThread().getName()) || (threadSingleAddDataMap.get(Thread.currentThread().getName()) == null))
+ {
+ threadSingleAddDataMap.put(Thread.currentThread().getName(), new long[1]);
+ }
+ return threadSingleAddDataMap.get(Thread.currentThread().getName());
+ }
+
+ public static long[] getSingleGetDataArray(){
+ if(!threadSingleGetDataMap.containsKey(Thread.currentThread().getName()) || (threadSingleGetDataMap.get(Thread.currentThread().getName()) == null))
+ {
+ threadSingleGetDataMap.put(Thread.currentThread().getName(), new long[1]);
+ }
+ return threadSingleGetDataMap.get(Thread.currentThread().getName());
+ }
+
+ public static long[] getSingleUpdateArray(){
+ if(!threadSingleUpdateMap.containsKey(Thread.currentThread().getName()) || (threadSingleUpdateMap.get(Thread.currentThread().getName()) == null))
+ {
+ threadSingleUpdateMap.put(Thread.currentThread().getName(), new long[4]);
+ }
+ return threadSingleUpdateMap.get(Thread.currentThread().getName());
+ }
+
+ public static long[][] getBuilderArray(){
+ if(!threadBuilderArrayMap.containsKey(Thread.currentThread().getName()) || (threadBuilderArrayMap.get(Thread.currentThread().getName()) == null))
+ {
+ long[][] array = new long[5][];
+ threadBuilderArrayMap.put(Thread.currentThread().getName(), array);
+ }
+ return threadBuilderArrayMap.get(Thread.currentThread().getName());
+ }
+
+ public static long[][][] getBuilderVerticalArray(){
+ if(!threadBuilderVerticalArrayMap.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMap.get(Thread.currentThread().getName()) == null))
+ {
+ long[][][] array = new long[5][][];
+ threadBuilderVerticalArrayMap.put(Thread.currentThread().getName(), array);
+ }
+ return threadBuilderVerticalArrayMap.get(Thread.currentThread().getName());
+ }
+
+ public static long[] addVerticalDataArray(){
+ if(!threadVerticalAddDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMap.get(Thread.currentThread().getName()) == null))
+ {
+ threadVerticalAddDataMap.put(Thread.currentThread().getName(), new long[16]);
+ }
+ return threadVerticalAddDataMap.get(Thread.currentThread().getName());
+ }
+
+ public static long[] getVerticalGetDataArray(){
+ if(!threadVerticalGetDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalGetDataMap.get(Thread.currentThread().getName()) == null))
+ {
+ threadVerticalGetDataMap.put(Thread.currentThread().getName(), new long[16]);
+ }
+ return threadVerticalGetDataMap.get(Thread.currentThread().getName());
+ }
+
+ public static long[][] getVerticalUpdateArray(){
+ if(!threadVerticalUpdateMap.containsKey(Thread.currentThread().getName()) || (threadVerticalUpdateMap.get(Thread.currentThread().getName()) == null))
+ {
+ threadVerticalUpdateMap.put(Thread.currentThread().getName(), new long[4][]);
+ }
+ return threadVerticalUpdateMap.get(Thread.currentThread().getName());
+ }
+
+ public static int[] getVerticalIndexesArray(){
+ if(!threadVerticalIndexesMap.containsKey(Thread.currentThread().getName()) || (threadVerticalIndexesMap.get(Thread.currentThread().getName()) == null))
+ {
+ threadVerticalIndexesMap.put(Thread.currentThread().getName(), new int[4]);
+ }
+ return threadVerticalIndexesMap.get(Thread.currentThread().getName());
+ }
+
+
+
+ public static boolean[] getProjection(int size){
+ if(!projectionMap.containsKey(Thread.currentThread().getName()) || (projectionMap.get(Thread.currentThread().getName()) == null) || (projectionMap.get(Thread.currentThread().getName()).length != size))
+ {
+ projectionMap.put(Thread.currentThread().getName(), new boolean[size]);
+ }
+ return projectionMap.get(Thread.currentThread().getName());
+ }
+
+ public static int[][] getHeightAndDepth(int size){
+ if(!heightAndDepthMap.containsKey(Thread.currentThread().getName()) || (heightAndDepthMap.get(Thread.currentThread().getName()) == null) || (heightAndDepthMap.get(Thread.currentThread().getName()).length != size))
+ {
+ heightAndDepthMap.put(Thread.currentThread().getName(), new int[size][2]);
+ }
+ return heightAndDepthMap.get(Thread.currentThread().getName());
+ }
+
+ public static long[] getSingleAddDataToMerge(int size){
+ if(!singleDataToMergeMap.containsKey(Thread.currentThread().getName()) || (singleDataToMergeMap.get(Thread.currentThread().getName()) == null) || (singleDataToMergeMap.get(Thread.currentThread().getName()).length != size))
+ {
+ singleDataToMergeMap.put(Thread.currentThread().getName(), new long[size]);
+ }
+ return singleDataToMergeMap.get(Thread.currentThread().getName());
+ }
+}