Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b1bcdb24f0 | |||
| cbd7f4300e | |||
| 4d8e30121e | |||
| fbe39542fc | |||
| 6a1f448b41 | |||
| e13b23832c | |||
| 4c9e0edf32 | |||
| 8664a06d3b | |||
| 18b8359f0d | |||
| 7de4c7c72a | |||
| b4bbabae42 | |||
| 40321d6e21 | |||
| cf1702bd0c | |||
| a9b50cdb32 | |||
| 7eed472029 | |||
| 0262e452c7 | |||
| 30287d5a7d | |||
| 83346fed1f | |||
| e897c3edba | |||
| bd9e2acaf6 | |||
| 1e15d372c4 | |||
| 849d563425 | |||
| aa5a8aa3b8 | |||
| b096cc53aa | |||
| 94d994e761 | |||
| f76fa17e25 | |||
| 53a66268cb | |||
| 139867d4b8 | |||
| 81cf05ba19 | |||
| 13a1e7ed56 | |||
| 42bd0fbde9 |
Binary file not shown.
+1
-1
@@ -21,7 +21,7 @@ apply plugin: 'eclipse'
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'java' // needed for compileJava
|
||||
|
||||
version = 'a1.4'
|
||||
version = 'a1.4.1'
|
||||
group = 'com.seibel.lod'
|
||||
archivesBaseName = 'lod_1.16.5'
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.seibel.lod.builders;
|
||||
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
/**
|
||||
* @author Leonardo Amato
|
||||
* @version 22-08-2021
|
||||
*/
|
||||
public class GenerationRequest
|
||||
{
|
||||
public final LevelPos levelPos;
|
||||
public final DistanceGenerationMode generationMode;
|
||||
|
||||
public GenerationRequest(LevelPos levelPos, DistanceGenerationMode generationMode)
|
||||
{
|
||||
this.levelPos = levelPos;
|
||||
this.generationMode = generationMode;
|
||||
}
|
||||
|
||||
public ChunkPos getChunkPos()
|
||||
{
|
||||
LevelPos chunkLevelPos = levelPos.getConvertedLevelPos(LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
return new ChunkPos(chunkLevelPos.posX, chunkLevelPos.posZ);
|
||||
}
|
||||
}
|
||||
@@ -20,20 +20,21 @@ package com.seibel.lod.builders;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
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;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.render.LodRenderer;
|
||||
import com.seibel.lod.util.LodThreadFactory;
|
||||
@@ -105,9 +106,21 @@ public class LodBufferBuilder
|
||||
*/
|
||||
private ReentrantLock bufferLock = new ReentrantLock();
|
||||
|
||||
private volatile Object[][] setsToRender;
|
||||
private static final int NUMBER_OF_DIRECTION = 4;
|
||||
//in order -x, +x, -z, +z
|
||||
private static final int[][] ADJ_DIRECTION = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
|
||||
|
||||
private volatile Box[][] boxCache;
|
||||
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 */
|
||||
private volatile ChunkPos drawableCenterChunkPos = new ChunkPos(0,0);
|
||||
private volatile ChunkPos buildableCenterChunkPos = new ChunkPos(0,0);
|
||||
|
||||
|
||||
|
||||
public LodBufferBuilder()
|
||||
{
|
||||
|
||||
@@ -169,17 +182,19 @@ public class LodBufferBuilder
|
||||
center = playerRegionPos;
|
||||
|
||||
if (setsToRender == null)
|
||||
setsToRender = new Object[lodDim.regions.length][lodDim.regions.length];
|
||||
setsToRender = new PosToRenderContainer[lodDim.regions.length][lodDim.regions.length];
|
||||
|
||||
if (setsToRender.length != lodDim.regions.length)
|
||||
setsToRender = new Object[lodDim.regions.length][lodDim.regions.length];
|
||||
setsToRender = new PosToRenderContainer[lodDim.regions.length][lodDim.regions.length];
|
||||
|
||||
if (boxCache == null)
|
||||
boxCache = new Box[lodDim.regions.length][lodDim.regions.length];
|
||||
|
||||
RegionPos worldRegionOffset = new RegionPos(playerRegionPos.x - lodDim.getCenterX(), playerRegionPos.z - lodDim.getCenterZ());
|
||||
if (worldRegionOffset.x != 0 || worldRegionOffset.z != 0)
|
||||
{
|
||||
move(worldRegionOffset, Math.floorDiv(lodDim.getWidth(), 2));
|
||||
}
|
||||
if (boxCache.length != lodDim.regions.length)
|
||||
boxCache = new Box[lodDim.regions.length][lodDim.regions.length];
|
||||
|
||||
// this will be the center of the VBOs once they have been built
|
||||
buildableCenterChunkPos = playerChunkPos;
|
||||
|
||||
for (int xRegion = 0; xRegion < lodDim.regions.length; xRegion++)
|
||||
{
|
||||
@@ -193,117 +208,104 @@ public class LodBufferBuilder
|
||||
|
||||
// local position in the vbo and bufferBuilder arrays
|
||||
BufferBuilder currentBuffer = buildableBuffers[xRegion][zRegion];
|
||||
|
||||
LodRegion region = lodDim.getRegion(regionPos.x, regionPos.z);
|
||||
if (region == null) continue;
|
||||
byte minDetail = region.getMinDetailLevel();
|
||||
// make sure the buffers weren't
|
||||
// changed while we were running this method
|
||||
if (currentBuffer == null || (currentBuffer != null && !currentBuffer.building()))
|
||||
return;
|
||||
|
||||
//previous setToRender chache
|
||||
if (setsToRender[xRegion][zRegion] == null)
|
||||
{
|
||||
setsToRender[xRegion][zRegion] = new ConcurrentHashMap<LevelPos, MutableBoolean>();
|
||||
}
|
||||
ConcurrentMap<LevelPos, MutableBoolean> nodeToRender = (ConcurrentMap<LevelPos, MutableBoolean>) setsToRender[xRegion][zRegion];
|
||||
final int xR = xRegion;
|
||||
final int zR = zRegion;
|
||||
Callable<Boolean> dataToRenderThread = () ->
|
||||
{
|
||||
|
||||
//previous setToRender chache
|
||||
if (setsToRender[xR][zR] == null)
|
||||
{
|
||||
setsToRender[xR][zR] = new PosToRenderContainer(minDetail, regionPos.x, regionPos.z);
|
||||
}
|
||||
|
||||
if (boxCache[xR][zR] == null)
|
||||
{
|
||||
boxCache[xR][zR] = new Box();
|
||||
}
|
||||
PosToRenderContainer posToRender = setsToRender[xR][zR];
|
||||
posToRender.clear(minDetail, regionPos.x, regionPos.z);
|
||||
|
||||
lodDim.getDataToRender(
|
||||
nodeToRender,
|
||||
posToRender,
|
||||
regionPos,
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ());
|
||||
|
||||
byte detailLevel;
|
||||
int posX;
|
||||
int posZ;
|
||||
byte detailLevel;
|
||||
int xAdj;
|
||||
int zAdj;
|
||||
int chunkXdist;
|
||||
int chunkZdist;
|
||||
short gameChunkRenderDistance = (short) (renderer.vanillaRenderedChunks.length/2 - 1);
|
||||
for (LevelPos posToRender : nodeToRender.keySet())
|
||||
short gameChunkRenderDistance = (short) (renderer.vanillaRenderedChunks.length / 2 - 1);
|
||||
long dataPoint;
|
||||
long[] adjData;
|
||||
for (int index = 0; index < posToRender.getNumberOfPos(); index++)
|
||||
{
|
||||
if (!nodeToRender.get(posToRender).booleanValue())
|
||||
detailLevel = posToRender.getNthDetailLevel(index);
|
||||
posX = posToRender.getNthPosX(index);
|
||||
posZ = posToRender.getNthPosZ(index);
|
||||
// skip any chunks that Minecraft is going to render
|
||||
chunkXdist = LevelPosUtil.getChunkPos(detailLevel, posX) - playerChunkPos.x;
|
||||
chunkZdist = LevelPosUtil.getChunkPos(detailLevel, posZ) - playerChunkPos.z;
|
||||
if (gameChunkRenderDistance >= Math.abs(chunkXdist)
|
||||
&& gameChunkRenderDistance >= Math.abs(chunkZdist)
|
||||
&& detailLevel <= LodUtil.CHUNK_DETAIL_LEVEL
|
||||
&& renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1])
|
||||
{
|
||||
nodeToRender.remove(posToRender);
|
||||
continue;
|
||||
}
|
||||
nodeToRender.get(posToRender).setFalse();
|
||||
// skip any chunks that Minecraft is going to render
|
||||
chunkXdist = posToRender.getChunkPosX() - playerChunkPos.x;
|
||||
chunkZdist = posToRender.getChunkPosZ() - playerChunkPos.z;
|
||||
if(gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist) && posToRender.detailLevel <= LodUtil.CHUNK_DETAIL_LEVEL)
|
||||
{
|
||||
if (renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
posX = posToRender.posX;
|
||||
posZ = posToRender.posZ;
|
||||
detailLevel = posToRender.detailLevel;
|
||||
// skip any chunks that Minecraft is going to render
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
boolean disableFix = false;
|
||||
if (lodDim.doesDataExist(posToRender.clone()))
|
||||
if (lodDim.doesDataExist(detailLevel, posX, posZ))
|
||||
{
|
||||
short[] lodData = lodDim.getData(posToRender);
|
||||
short[][][] adjData = new short[2][2][];
|
||||
/**TODO The following two for are too complex*/
|
||||
for (int x : new int[]{0, 1})
|
||||
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];
|
||||
for (int direction = 0; direction < NUMBER_OF_DIRECTION; direction++)
|
||||
{
|
||||
posToRender.changeParameters(detailLevel, posX + x * 2 - 1, posZ);
|
||||
chunkXdist = posToRender.getChunkPosX() - playerChunkPos.x;
|
||||
chunkZdist = posToRender.getChunkPosZ() - playerChunkPos.z;
|
||||
if(gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist))
|
||||
xAdj = posX + ADJ_DIRECTION[direction][0];
|
||||
zAdj = posZ + ADJ_DIRECTION[direction][1];
|
||||
chunkXdist = LevelPosUtil.getChunkPos(detailLevel,xAdj) - playerChunkPos.x;
|
||||
chunkZdist = LevelPosUtil.getChunkPos(detailLevel,zAdj) - playerChunkPos.z;
|
||||
|
||||
if (gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist))
|
||||
{
|
||||
if (!renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1]
|
||||
&& (nodeToRender.containsKey(posToRender) || disableFix))
|
||||
&& posToRender.contains(detailLevel, xAdj, zAdj))
|
||||
{
|
||||
adjData[0][x] = lodDim.getData(posToRender);
|
||||
adjData[direction]= lodDim.getData(detailLevel, xAdj, zAdj);
|
||||
}
|
||||
}else{
|
||||
if (nodeToRender.containsKey(posToRender) || disableFix)
|
||||
{
|
||||
adjData[0][x] = lodDim.getData(posToRender);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int z : new int[]{0, 1})
|
||||
{
|
||||
posToRender.changeParameters(detailLevel, posX, posZ + z * 2 - 1);
|
||||
chunkXdist = posToRender.getChunkPosX() - playerChunkPos.x;
|
||||
chunkZdist = posToRender.getChunkPosZ() - playerChunkPos.z;
|
||||
if(gameChunkRenderDistance >= Math.abs(chunkXdist) && gameChunkRenderDistance >= Math.abs(chunkZdist))
|
||||
} else
|
||||
{
|
||||
if (!renderer.vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance+ 1]
|
||||
&& (nodeToRender.containsKey(posToRender) || disableFix))
|
||||
if (posToRender.contains(detailLevel, xAdj, zAdj))
|
||||
{
|
||||
adjData[1][z] = lodDim.getData(posToRender);
|
||||
}
|
||||
}else{
|
||||
if (nodeToRender.containsKey(posToRender) || disableFix)
|
||||
{
|
||||
adjData[1][z] = lodDim.getData(posToRender);
|
||||
|
||||
adjData[direction] = lodDim.getData(detailLevel, xAdj, zAdj);
|
||||
}
|
||||
}
|
||||
}
|
||||
posToRender.changeParameters(detailLevel, posX, posZ);
|
||||
|
||||
LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPos, lodData, adjData,
|
||||
posToRender, renderer.previousDebugMode);
|
||||
LodConfig.CLIENT.graphics.lodTemplate.get().template.addLodToBuffer(currentBuffer, playerBlockPosRounded, dataPoint, adjData,
|
||||
detailLevel, posX, posZ, boxCache[xR][zR],renderer.previousDebugMode);
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
}// for pos to in list to render
|
||||
|
||||
// the thread executed successfully
|
||||
return true;
|
||||
};
|
||||
@@ -367,104 +369,6 @@ public class LodBufferBuilder
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Move the center of this LodDimension and move all owned
|
||||
* regions over by the given x and z offset. <br><br>
|
||||
* <p>
|
||||
* Synchronized to prevent multiple moves happening on top of each other.
|
||||
*/
|
||||
public void move(RegionPos regionOffset, int width)
|
||||
{
|
||||
int xOffset = regionOffset.x;
|
||||
int zOffset = regionOffset.z;
|
||||
|
||||
// if the x or z offset is equal to or greater than
|
||||
// the total size, just delete the current data
|
||||
// and update the centerX and/or centerZ
|
||||
if (Math.abs(xOffset) >= width || Math.abs(zOffset) >= width)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
for (int z = 0; z < width; z++)
|
||||
{
|
||||
setsToRender[x][z] = null;
|
||||
}
|
||||
}
|
||||
|
||||
// update the new center
|
||||
center.x += xOffset;
|
||||
center.z += zOffset;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// X
|
||||
if (xOffset > 0)
|
||||
{
|
||||
// move everything over to the left (as the center moves to the right)
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
for (int z = 0; z < width; z++)
|
||||
{
|
||||
if (x + xOffset < width)
|
||||
setsToRender[x][z] = setsToRender[x + xOffset][z];
|
||||
else
|
||||
setsToRender[x][z] = null;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
// move everything over to the right (as the center moves to the left)
|
||||
for (int x = width - 1; x >= 0; x--)
|
||||
{
|
||||
for (int z = 0; z < width; z++)
|
||||
{
|
||||
if (x + xOffset >= 0)
|
||||
setsToRender[x][z] = setsToRender[x + xOffset][z];
|
||||
else
|
||||
setsToRender[x][z] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Z
|
||||
if (zOffset > 0)
|
||||
{
|
||||
// move everything up (as the center moves down)
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
for (int z = 0; z < width; z++)
|
||||
{
|
||||
if (z + zOffset < width)
|
||||
setsToRender[x][z] = setsToRender[x][z + zOffset];
|
||||
else
|
||||
setsToRender[x][z] = null;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
// move everything down (as the center moves up)
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
for (int z = width - 1; z >= 0; z--)
|
||||
{
|
||||
if (z + zOffset >= 0)
|
||||
setsToRender[x][z] = setsToRender[x][z + zOffset];
|
||||
else
|
||||
setsToRender[x][z] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// update the new center
|
||||
center.x += xOffset;
|
||||
center.z += zOffset;
|
||||
}
|
||||
|
||||
//===============================//
|
||||
// BufferBuilder related methods //
|
||||
//===============================//
|
||||
@@ -568,10 +472,11 @@ public class LodBufferBuilder
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the newly created VBOs
|
||||
*/
|
||||
public VertexBuffer[][] getVertexBuffers()
|
||||
public VertexBuffersAndOffset getVertexBuffers()
|
||||
{
|
||||
// don't wait for the lock to open
|
||||
// since this is called on the main render thread
|
||||
@@ -581,12 +486,28 @@ public class LodBufferBuilder
|
||||
drawableVbos = buildableVbos;
|
||||
buildableVbos = tmp;
|
||||
|
||||
drawableCenterChunkPos = buildableCenterChunkPos;
|
||||
|
||||
// the vbos have been swapped
|
||||
switchVbos = false;
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
return drawableVbos;
|
||||
return new VertexBuffersAndOffset(drawableVbos, drawableCenterChunkPos);
|
||||
}
|
||||
/**
|
||||
* A simple container to pass multiple objects back in the getVertexBuffers method.
|
||||
*/
|
||||
public class VertexBuffersAndOffset
|
||||
{
|
||||
public VertexBuffer[][] vbos;
|
||||
public ChunkPos drawableCenterChunkPos;
|
||||
|
||||
public VertexBuffersAndOffset(VertexBuffer[][] newVbos, ChunkPos newDrawableCenterChunkPos)
|
||||
{
|
||||
vbos = newVbos;
|
||||
drawableCenterChunkPos = newDrawableCenterChunkPos;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,17 +21,18 @@ import java.awt.Color;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
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.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LodRegion;
|
||||
import com.seibel.lod.objects.LodWorld;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
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;
|
||||
@@ -41,7 +42,6 @@ import net.minecraft.block.GrassBlock;
|
||||
import net.minecraft.block.IGrowable;
|
||||
import net.minecraft.block.LeavesBlock;
|
||||
import net.minecraft.block.material.MaterialColor;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
@@ -55,7 +55,7 @@ import net.minecraft.world.gen.Heightmap;
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @author James Seibel
|
||||
* @version 8-29-2021
|
||||
* @version 9-7-2021
|
||||
*/
|
||||
public class LodBuilder
|
||||
{
|
||||
@@ -68,11 +68,11 @@ public class LodBuilder
|
||||
/**
|
||||
* If no blocks are found in the area in determineBottomPointForArea return this
|
||||
*/
|
||||
public static final short DEFAULT_DEPTH = -1;
|
||||
public static final short DEFAULT_DEPTH = 0;
|
||||
/**
|
||||
* If no blocks are found in the area in determineHeightPointForArea return this
|
||||
*/
|
||||
public static final short DEFAULT_HEIGHT = -1;
|
||||
public static final short DEFAULT_HEIGHT = 0;
|
||||
|
||||
/**
|
||||
* How wide LodDimensions should be in regions
|
||||
@@ -111,7 +111,7 @@ public class LodBuilder
|
||||
|
||||
int playerPosX;
|
||||
int playerPosZ;
|
||||
if (Minecraft.getInstance().player == null)
|
||||
if (MinecraftWrapper.INSTANCE.getPlayer() == null)
|
||||
{
|
||||
playerPosX = chunk.getPos().getMinBlockX();
|
||||
playerPosZ = chunk.getPos().getMinBlockZ();
|
||||
@@ -132,7 +132,6 @@ public class LodBuilder
|
||||
generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(generationMode));
|
||||
} catch (IllegalArgumentException | NullPointerException e)
|
||||
{
|
||||
System.out.println("Chunk pos " + chunk.getPos());
|
||||
e.printStackTrace();
|
||||
// if the world changes while LODs are being generated
|
||||
// they will throw errors as they try to access things that no longer
|
||||
@@ -162,7 +161,6 @@ public class LodBuilder
|
||||
public void generateLodNodeFromChunk(LodDimension lodDim, IChunk chunk, LodBuilderConfig config)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
|
||||
if (chunk == null)
|
||||
throw new IllegalArgumentException("generateLodFromChunk given a null chunk");
|
||||
|
||||
@@ -170,17 +168,22 @@ public class LodBuilder
|
||||
int startZ;
|
||||
int endX;
|
||||
int endZ;
|
||||
short[] color;
|
||||
int color;
|
||||
short height;
|
||||
short depth;
|
||||
short[] data;
|
||||
LevelPos levelPos = new LevelPos((byte) 0, 0, 0);
|
||||
levelPos.changeParameters(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z);
|
||||
levelPos.convert(LodUtil.REGION_DETAIL_LEVEL);
|
||||
long data;
|
||||
try
|
||||
{
|
||||
byte minDetailLevel = lodDim.getRegion(levelPos).getMinDetailLevel();
|
||||
LodDetail detail = DetailDistanceUtil.getLodGenDetail(minDetailLevel);
|
||||
LodDetail detail;
|
||||
LodRegion region = lodDim.getRegion(chunk.getPos().getRegionX(), chunk.getPos().getRegionZ());
|
||||
if (region == null)
|
||||
return;
|
||||
byte minDetailLevel = region.getMinDetailLevel();
|
||||
detail = DetailDistanceUtil.getLodGenDetail(minDetailLevel);
|
||||
|
||||
byte detailLevel = detail.detailLevel;
|
||||
int posX;
|
||||
int posZ;
|
||||
for (int i = 0; i < detail.dataPointLengthCount * detail.dataPointLengthCount; i++)
|
||||
{
|
||||
startX = detail.startX[i];
|
||||
@@ -200,23 +203,23 @@ public class LodBuilder
|
||||
startZ, endX, endZ);
|
||||
depth = 0;
|
||||
}
|
||||
levelPos.changeParameters((byte) 0,
|
||||
chunk.getPos().x * 16 + startX,
|
||||
chunk.getPos().z * 16 + startZ);
|
||||
levelPos.convert(detail.detailLevel);
|
||||
posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel);
|
||||
posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel);
|
||||
boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER;
|
||||
data = DataPoint.createDataPoint(height, depth, color[0], color[1], color[2]);
|
||||
lodDim.addData(levelPos,
|
||||
data = DataPoint.createDataPoint(height, depth, ColorUtil.getRed(color), ColorUtil.getGreen(color), ColorUtil.getBlue(color));
|
||||
lodDim.addData(detailLevel,
|
||||
posX,
|
||||
posZ,
|
||||
data,
|
||||
false,
|
||||
isServer);
|
||||
}
|
||||
levelPos.changeParameters(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z);
|
||||
lodDim.updateData(levelPos);
|
||||
lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z);
|
||||
} catch (Exception e)
|
||||
{
|
||||
//e.printStackTrace();
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -353,8 +356,8 @@ public class LodBuilder
|
||||
* otherwise only use the block's
|
||||
* material color
|
||||
*/
|
||||
private short[] generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX,
|
||||
int endZ)
|
||||
private int generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX,
|
||||
int endZ)
|
||||
{
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
|
||||
@@ -428,8 +431,7 @@ public class LodBuilder
|
||||
red /= numbOfBlocks;
|
||||
green /= numbOfBlocks;
|
||||
blue /= numbOfBlocks;
|
||||
|
||||
return new short[]{(short) red, (short) green, (short) blue};
|
||||
return ColorUtil.rgbToInt(red,green,blue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -440,7 +442,9 @@ public class LodBuilder
|
||||
int colorInt = 0;
|
||||
|
||||
// block special cases
|
||||
if (blockState == Blocks.AIR.defaultBlockState() || blockState == Blocks.CAVE_AIR.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();
|
||||
@@ -559,7 +563,8 @@ public class LodBuilder
|
||||
{
|
||||
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.CAVE_AIR
|
||||
&& chunkSections[sectionIndex].getBlockState(x, y, z).getBlock() != Blocks.BARRIER)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
package com.seibel.lod.builders.lodTemplates;
|
||||
|
||||
import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -32,8 +31,8 @@ import net.minecraft.util.math.BlockPos;
|
||||
*/
|
||||
public abstract class AbstractLodTemplate
|
||||
{
|
||||
public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, short[] data, short[][][] adjData,
|
||||
LevelPos levelPos, DebugMode debugging);
|
||||
public abstract void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging);
|
||||
|
||||
/**
|
||||
* add the given position and color to the buffer
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.seibel.lod.builders.lodTemplates;
|
||||
|
||||
public class Box
|
||||
{
|
||||
public static final int DOWN = 0;
|
||||
public static final int UP = 1;
|
||||
public static final int EAST = 2;
|
||||
public static final int WEST = 3;
|
||||
public static final int SOUTH = 4;
|
||||
public static final int NORTH = 5;
|
||||
|
||||
public static final int OFFSET = 0;
|
||||
public static final int WIDTH = 1;
|
||||
|
||||
public static final int X = 0;
|
||||
public static final int Y = 1;
|
||||
public static final int Z = 2;
|
||||
|
||||
public int[][] box;
|
||||
|
||||
public Box(){
|
||||
box = new int[2][3];
|
||||
}
|
||||
|
||||
public void set(int xWidth, int yWidth, int zWidth){
|
||||
box[OFFSET][X] = 0;
|
||||
box[OFFSET][Y] = 0;
|
||||
box[OFFSET][Z] = 0;
|
||||
|
||||
box[WIDTH][X] = xWidth;
|
||||
box[WIDTH][Y] = yWidth;
|
||||
box[WIDTH][Z] = zWidth;
|
||||
}
|
||||
|
||||
public void move(int xOffset, int yOffset, int zOffset){
|
||||
box[OFFSET][X] = xOffset;
|
||||
box[OFFSET][Y] = yOffset;
|
||||
box[OFFSET][Z] = zOffset;
|
||||
}
|
||||
|
||||
public int getMinX(){
|
||||
return box[OFFSET][X];
|
||||
}
|
||||
|
||||
public int getMaxX(){
|
||||
return box[OFFSET][X] + box[WIDTH][X];
|
||||
}
|
||||
|
||||
public int getMinY(){
|
||||
return box[OFFSET][Y];
|
||||
}
|
||||
|
||||
public int getMaxY(){
|
||||
return box[OFFSET][Y] + box[WIDTH][Y];
|
||||
}
|
||||
|
||||
public int getMinZ(){
|
||||
return box[OFFSET][Z];
|
||||
}
|
||||
|
||||
public int getMaxZ(){
|
||||
return box[OFFSET][Z] + box[WIDTH][Z];
|
||||
}
|
||||
}
|
||||
@@ -21,14 +21,12 @@ 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.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.util.ColorUtil;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
@@ -40,59 +38,65 @@ import net.minecraft.util.math.BlockPos;
|
||||
public class CubicLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
private final int CULL_OFFSET = 16;
|
||||
|
||||
|
||||
public CubicLodTemplate()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, short[] data, short[][][] adjData,
|
||||
LevelPos levelPos, DebugMode debugging)
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging)
|
||||
{
|
||||
AxisAlignedBB bbox;
|
||||
|
||||
int width = 1 << levelPos.detailLevel;
|
||||
|
||||
int width = 1 << detailLevel;
|
||||
|
||||
// add each LOD for the detail level
|
||||
bbox = generateBoundingBox(
|
||||
generateBoundingBox(
|
||||
box,
|
||||
DataPoint.getHeight(data),
|
||||
DataPoint.getDepth(data),
|
||||
width,
|
||||
levelPos.posX * width,
|
||||
posX * width,
|
||||
0,
|
||||
levelPos.posZ * width);
|
||||
|
||||
posZ * width,
|
||||
bufferCenterBlockPos);
|
||||
|
||||
int color = DataPoint.getColor(data);
|
||||
if (debugging != DebugMode.OFF)
|
||||
{
|
||||
color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[levelPos.detailLevel].getRGB();
|
||||
color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB();
|
||||
}
|
||||
|
||||
if (bbox != null)
|
||||
|
||||
if (box != null)
|
||||
{
|
||||
addBoundingBoxToBuffer(buffer, bbox, color, playerBlockPos, adjData);
|
||||
addBoundingBoxToBuffer(buffer, box, color, bufferCenterBlockPos, adjData);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private AxisAlignedBB generateBoundingBox(int height, int depth, int width, double xOffset, double yOffset, double zOffset)
|
||||
|
||||
private void generateBoundingBox(Box box, int height, int depth, int width, double xOffset, double yOffset, double zOffset, BlockPos bufferCenterBlockPos)
|
||||
{
|
||||
// don't add an LOD if it is empty
|
||||
if (height == -1 && depth == -1)
|
||||
return null;
|
||||
|
||||
return;
|
||||
|
||||
if (depth == height)
|
||||
{
|
||||
// if the top and bottom points are at the same height
|
||||
// render this LOD as 1 block thick
|
||||
height++;
|
||||
}
|
||||
|
||||
return new AxisAlignedBB(0, depth, 0, width, height, width).move(xOffset, yOffset, zOffset);
|
||||
|
||||
// offset the AABB by it's x/z position in the world since
|
||||
// it uses doubles to specify its location, unlike the model view matrix
|
||||
// which only uses floats
|
||||
double x = -bufferCenterBlockPos.getX();
|
||||
double z = -bufferCenterBlockPos.getZ();;
|
||||
box.set(width, height - depth, width);
|
||||
box.move((int) (xOffset + x), (int) (yOffset + depth), (int) (zOffset + z));
|
||||
}
|
||||
|
||||
private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, int c, BlockPos playerBlockPos, short[][][] adjData)
|
||||
|
||||
private void addBoundingBoxToBuffer(BufferBuilder buffer, Box box, int c, BlockPos playerBlockPos, long[] adjData)
|
||||
{
|
||||
int topColor = c;
|
||||
int bottomColor = c;
|
||||
@@ -100,7 +104,7 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
int southColor = c;
|
||||
int westColor = c;
|
||||
int eastColor = c;
|
||||
|
||||
|
||||
// darken the bottom and side colors if requested
|
||||
if (LodConfig.CLIENT.graphics.shadingMode.get() == ShadingMode.DARKEN_SIDES)
|
||||
{
|
||||
@@ -116,11 +120,11 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
westColor = ColorUtil.applyShade(c, mc.level.getShade(Direction.WEST, true));
|
||||
eastColor = ColorUtil.applyShade(c, mc.level.getShade(Direction.EAST, true));
|
||||
}
|
||||
|
||||
|
||||
// apply the user specified saturation and brightness
|
||||
float saturationMultiplier = LodConfig.CLIENT.graphics.saturationMultiplier.get().floatValue();
|
||||
float brightnessMultiplier = LodConfig.CLIENT.graphics.brightnessMultiplier.get().floatValue();
|
||||
|
||||
|
||||
if (saturationMultiplier != 1 || brightnessMultiplier != 1)
|
||||
{
|
||||
topColor = ColorUtil.applySaturationAndBrightnessMultipliers(topColor, saturationMultiplier, brightnessMultiplier);
|
||||
@@ -130,199 +134,249 @@ public class CubicLodTemplate extends AbstractLodTemplate
|
||||
westColor = ColorUtil.applySaturationAndBrightnessMultipliers(westColor, saturationMultiplier, brightnessMultiplier);
|
||||
eastColor = ColorUtil.applySaturationAndBrightnessMultipliers(eastColor, saturationMultiplier, brightnessMultiplier);
|
||||
}
|
||||
int minX;
|
||||
int maxX;
|
||||
int minY;
|
||||
int maxY;
|
||||
short[] data;
|
||||
|
||||
int minZ;
|
||||
int maxZ;
|
||||
long data;
|
||||
int tempMinY;
|
||||
int tempMaxY;
|
||||
|
||||
int red;
|
||||
int green;
|
||||
int blue;
|
||||
int alpha;
|
||||
boolean disableCulling = true;
|
||||
/**TODO make all of this more automatic if possible*/
|
||||
if (playerBlockPos.getY() > bb.maxY - CULL_OFFSET || disableCulling)
|
||||
if (playerBlockPos.getY() > box.getMaxY() - CULL_OFFSET || disableCulling)
|
||||
{
|
||||
red = ColorUtil.getRed(topColor);
|
||||
green = ColorUtil.getGreen(topColor);
|
||||
blue = ColorUtil.getBlue(topColor);
|
||||
alpha = ColorUtil.getAlpha(topColor);
|
||||
// top (facing up)
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
minX = box.getMinX();
|
||||
maxX = box.getMaxX();
|
||||
minY = box.getMinY();
|
||||
maxY = box.getMaxY();
|
||||
minZ = box.getMinZ();
|
||||
maxZ = box.getMaxZ();
|
||||
addPosAndColor(buffer, minX, maxY, minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, minX, maxY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, maxX, maxY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha);
|
||||
}
|
||||
if (playerBlockPos.getY() < bb.minY + CULL_OFFSET || disableCulling)
|
||||
if (playerBlockPos.getY() < box.getMinY() + CULL_OFFSET || disableCulling)
|
||||
{
|
||||
red = ColorUtil.getRed(bottomColor);
|
||||
green = ColorUtil.getGreen(bottomColor);
|
||||
blue = ColorUtil.getBlue(bottomColor);
|
||||
alpha = ColorUtil.getAlpha(bottomColor);
|
||||
// bottom (facing down)
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
minX = box.getMinX();
|
||||
maxX = box.getMaxX();
|
||||
minY = box.getMinY();
|
||||
maxY = box.getMaxY();
|
||||
minZ = box.getMinZ();
|
||||
maxZ = box.getMaxZ();
|
||||
addPosAndColor(buffer, maxX, minY, minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, minX, minY, maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha);
|
||||
}
|
||||
|
||||
if (playerBlockPos.getZ() > bb.minZ - CULL_OFFSET || disableCulling)
|
||||
{
|
||||
red = ColorUtil.getRed(northColor);
|
||||
green = ColorUtil.getGreen(northColor);
|
||||
blue = ColorUtil.getBlue(northColor);
|
||||
alpha = ColorUtil.getAlpha(northColor);
|
||||
// south (facing -Z)
|
||||
data = adjData[1][1];
|
||||
if (data == null)
|
||||
{
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
maxY = DataPoint.getHeight(data);
|
||||
if (maxY < bb.maxY)
|
||||
{
|
||||
minY = (int) Math.max(maxY, bb.minY);
|
||||
addPosAndColor(buffer, bb.maxX, minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, minY, bb.maxZ, red, green, blue, alpha);
|
||||
}
|
||||
minY = DataPoint.getDepth(data);
|
||||
if (minY > bb.minY)
|
||||
{
|
||||
maxY = (int) Math.min(minY, bb.maxY);
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (playerBlockPos.getZ() < bb.maxZ + CULL_OFFSET || disableCulling)
|
||||
{
|
||||
red = ColorUtil.getRed(southColor);
|
||||
green = ColorUtil.getGreen(southColor);
|
||||
blue = ColorUtil.getBlue(southColor);
|
||||
alpha = ColorUtil.getAlpha(southColor);
|
||||
data = adjData[1][0];
|
||||
// north (facing +Z)
|
||||
if (data == null)
|
||||
{
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
maxY = DataPoint.getHeight(data);
|
||||
if (maxY < bb.maxY)
|
||||
{
|
||||
minY = (int) Math.max(maxY, bb.minY);
|
||||
addPosAndColor(buffer, bb.minX, minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, minY, bb.minZ, red, green, blue, alpha);
|
||||
}
|
||||
minY = DataPoint.getDepth(data);
|
||||
if (minY > bb.minY)
|
||||
{
|
||||
maxY = (int) Math.min(minY, bb.maxY);
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (playerBlockPos.getX() < bb.maxX + CULL_OFFSET || disableCulling)
|
||||
|
||||
if (playerBlockPos.getX() < box.getMaxX() + CULL_OFFSET || disableCulling)
|
||||
{
|
||||
red = ColorUtil.getRed(westColor);
|
||||
green = ColorUtil.getGreen(westColor);
|
||||
blue = ColorUtil.getBlue(westColor);
|
||||
alpha = ColorUtil.getAlpha(westColor);
|
||||
// west (facing -X)
|
||||
data = adjData[0][0];
|
||||
if (data == null)
|
||||
data = adjData[0];
|
||||
|
||||
minX = box.getMinX();
|
||||
maxX = box.getMaxX();
|
||||
minY = box.getMinY();
|
||||
maxY = box.getMaxY();
|
||||
minZ = box.getMinZ();
|
||||
maxZ = box.getMaxZ();
|
||||
if (data == 0)
|
||||
{
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
}
|
||||
else
|
||||
addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha);
|
||||
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
|
||||
{
|
||||
maxY = DataPoint.getHeight(data);
|
||||
if (maxY < bb.maxY)
|
||||
maxY = box.getMaxY();
|
||||
tempMaxY = DataPoint.getHeight(data);
|
||||
if (tempMaxY < maxY)
|
||||
{
|
||||
minY = (int) Math.max(maxY, bb.minY);
|
||||
addPosAndColor(buffer, bb.minX, minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
minY = Math.max(tempMaxY, minY);
|
||||
addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha);
|
||||
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);
|
||||
}
|
||||
minY = DataPoint.getDepth(data);
|
||||
if (minY > bb.minY)
|
||||
tempMinY = DataPoint.getDepth(data);
|
||||
minY = box.getMinY();
|
||||
if (tempMinY > minY)
|
||||
{
|
||||
maxY = (int) Math.min(minY, bb.maxY);
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.minX, maxY, bb.minZ, red, green, blue, alpha);
|
||||
maxY = Math.min(tempMinY, maxY);
|
||||
addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (playerBlockPos.getX() > bb.minX - CULL_OFFSET || disableCulling)
|
||||
|
||||
if (playerBlockPos.getX() > box.getMinX() - CULL_OFFSET || disableCulling)
|
||||
{
|
||||
red = ColorUtil.getRed(eastColor);
|
||||
green = ColorUtil.getGreen(eastColor);
|
||||
blue = ColorUtil.getBlue(eastColor);
|
||||
alpha = ColorUtil.getAlpha(eastColor);
|
||||
// east (facing +X)
|
||||
data = adjData[0][1];
|
||||
if (data == null)
|
||||
data = adjData[1];
|
||||
minX = box.getMinX();
|
||||
maxX = box.getMaxX();
|
||||
minY = box.getMinY();
|
||||
maxY = box.getMaxY();
|
||||
minZ = box.getMinZ();
|
||||
maxZ = box.getMaxZ();
|
||||
if (data == 0)
|
||||
{
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha);
|
||||
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
|
||||
{
|
||||
maxY = DataPoint.getHeight(data);
|
||||
if (maxY < bb.maxY)
|
||||
maxY = box.getMaxY();
|
||||
tempMaxY = DataPoint.getHeight(data);
|
||||
if (tempMaxY < maxY)
|
||||
{
|
||||
minY = (int) Math.max(maxY, bb.minY);
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, minY, bb.minZ, red, green, blue, alpha);
|
||||
minY = Math.max(tempMaxY, minY);
|
||||
addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha);
|
||||
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);
|
||||
}
|
||||
minY = DataPoint.getDepth(data);
|
||||
if (minY > bb.minY)
|
||||
tempMinY = DataPoint.getDepth(data);
|
||||
minY = box.getMinY();
|
||||
if (tempMinY > minY)
|
||||
{
|
||||
maxY = (int) Math.min(minY, bb.maxY);
|
||||
addPosAndColor(buffer, bb.maxX, maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
maxY = Math.min(tempMinY, maxY);
|
||||
addPosAndColor(buffer, maxX, maxY, minZ, red, green, blue, alpha);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (playerBlockPos.getZ() > box.getMinZ() - CULL_OFFSET || disableCulling)
|
||||
{
|
||||
red = ColorUtil.getRed(northColor);
|
||||
green = ColorUtil.getGreen(northColor);
|
||||
blue = ColorUtil.getBlue(northColor);
|
||||
alpha = ColorUtil.getAlpha(northColor);
|
||||
data = adjData[3];
|
||||
minX = box.getMinX();
|
||||
maxX = box.getMaxX();
|
||||
minY = box.getMinY();
|
||||
maxY = box.getMaxY();
|
||||
minZ = box.getMinZ();
|
||||
maxZ = box.getMaxZ();
|
||||
// north (facing +Z)
|
||||
if (data == 0)
|
||||
{
|
||||
addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha);
|
||||
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
|
||||
{
|
||||
maxY = box.getMaxY();
|
||||
tempMaxY = DataPoint.getHeight(data);
|
||||
if (tempMaxY < maxY)
|
||||
{
|
||||
minY = Math.max(tempMaxY, minY);
|
||||
addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha);
|
||||
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);
|
||||
}
|
||||
tempMinY = DataPoint.getDepth(data);
|
||||
minY = box.getMinY();
|
||||
if (tempMinY > minY)
|
||||
{
|
||||
maxY = Math.min(tempMinY, maxY);
|
||||
addPosAndColor(buffer, maxX, minY, maxZ, red, green, blue, alpha);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (playerBlockPos.getZ() < box.getMaxZ() + CULL_OFFSET || disableCulling)
|
||||
{
|
||||
red = ColorUtil.getRed(southColor);
|
||||
green = ColorUtil.getGreen(southColor);
|
||||
blue = ColorUtil.getBlue(southColor);
|
||||
alpha = ColorUtil.getAlpha(southColor);
|
||||
data = adjData[2];
|
||||
minX = box.getMinX();
|
||||
maxX = box.getMaxX();
|
||||
minY = box.getMinY();
|
||||
maxY = box.getMaxY();
|
||||
minZ = box.getMinZ();
|
||||
maxZ = box.getMaxZ();
|
||||
// south (facing -Z)
|
||||
if (data == 0)
|
||||
{
|
||||
addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha);
|
||||
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
|
||||
{
|
||||
maxY = box.getMaxY();
|
||||
tempMaxY = DataPoint.getHeight(data);
|
||||
if (tempMaxY < maxY)
|
||||
{
|
||||
minY = Math.max(tempMaxY, minY);
|
||||
addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha);
|
||||
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);
|
||||
}
|
||||
tempMinY = DataPoint.getDepth(data);
|
||||
minY = box.getMinY();
|
||||
if (tempMinY > minY)
|
||||
{
|
||||
maxY = Math.min(tempMinY, maxY);
|
||||
addPosAndColor(buffer, minX, minY, minZ, red, green, blue, alpha);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getBufferMemoryForSingleNode()
|
||||
{
|
||||
// (sidesOnACube * pointsInASquare * (positionPoints + colorPoints)))
|
||||
return (6 * 4 * (3 + 4));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
package com.seibel.lod.builders.lodTemplates;
|
||||
|
||||
import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -35,8 +34,8 @@ import net.minecraft.util.math.BlockPos;
|
||||
public class DynamicLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@Override
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, short[] data, short[][][] adjData,
|
||||
LevelPos levelPos, DebugMode debugging)
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging)
|
||||
{
|
||||
System.err.println("DynamicLodTemplate not implemented!");
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
package com.seibel.lod.builders.lodTemplates;
|
||||
|
||||
import com.seibel.lod.enums.DebugMode;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -33,8 +32,8 @@ import net.minecraft.util.math.BlockPos;
|
||||
public class TriangularLodTemplate extends AbstractLodTemplate
|
||||
{
|
||||
@Override
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos playerBlockPos, short[] data, short[][][] adjData,
|
||||
LevelPos levelPos, DebugMode debugging)
|
||||
public void addLodToBuffer(BufferBuilder buffer, BlockPos bufferCenterBlockPos, long data, long[] adjData,
|
||||
byte detailLevel, int posX, int posZ, Box box, DebugMode debugging)
|
||||
{
|
||||
System.err.println("DynamicLodTemplate not implemented!");
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ 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.render.LodRenderer;
|
||||
import com.seibel.lod.util.LodThreadFactory;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
@@ -69,7 +68,7 @@ import net.minecraftforge.common.WorldWorkerManager.IWorker;
|
||||
* This is used to generate a LodChunk at a given ChunkPos.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 8-26-2021
|
||||
* @version 9-7-2021
|
||||
*/
|
||||
public class LodNodeGenWorker implements IWorker
|
||||
{
|
||||
@@ -86,7 +85,7 @@ public class LodNodeGenWorker implements IWorker
|
||||
|
||||
|
||||
|
||||
public LodNodeGenWorker(ChunkPos newPos, DistanceGenerationMode newGenerationMode, LodRenderer newLodRenderer,
|
||||
public LodNodeGenWorker(ChunkPos newPos, DistanceGenerationMode newGenerationMode,
|
||||
LodBuilder newLodBuilder,
|
||||
LodDimension newLodDimension, ServerWorld newServerWorld)
|
||||
{
|
||||
@@ -94,9 +93,6 @@ public class LodNodeGenWorker implements IWorker
|
||||
if (newPos == null)
|
||||
throw new IllegalArgumentException("LodChunkGenWorker must have a non-null ChunkPos");
|
||||
|
||||
if (newLodRenderer == null)
|
||||
throw new IllegalArgumentException("LodChunkGenWorker must have a non-null LodRenderer");
|
||||
|
||||
if (newLodBuilder == null)
|
||||
throw new IllegalArgumentException("LodChunkGenThread requires a non-null LodChunkBuilder");
|
||||
|
||||
@@ -108,7 +104,7 @@ public class LodNodeGenWorker implements IWorker
|
||||
|
||||
|
||||
|
||||
thread = new LodChunkGenThread(newPos, newGenerationMode, newLodRenderer,
|
||||
thread = new LodChunkGenThread(newPos, newGenerationMode,
|
||||
newLodBuilder,
|
||||
newLodDimension, newServerWorld);
|
||||
}
|
||||
@@ -159,17 +155,15 @@ public class LodNodeGenWorker implements IWorker
|
||||
public final LodDimension lodDim;
|
||||
public final DistanceGenerationMode generationMode;
|
||||
public final LodBuilder lodBuilder;
|
||||
public final LodRenderer lodRenderer;
|
||||
|
||||
private ChunkPos pos;
|
||||
|
||||
public LodChunkGenThread(ChunkPos newPos, DistanceGenerationMode newGenerationMode, LodRenderer newLodRenderer,
|
||||
public LodChunkGenThread(ChunkPos newPos, DistanceGenerationMode newGenerationMode,
|
||||
LodBuilder newLodBuilder,
|
||||
LodDimension newLodDimension, ServerWorld newServerWorld)
|
||||
{
|
||||
pos = newPos;
|
||||
generationMode = newGenerationMode;
|
||||
lodRenderer = newLodRenderer;
|
||||
lodBuilder = newLodBuilder;
|
||||
lodDim = newLodDimension;
|
||||
serverWorld = newServerWorld;
|
||||
|
||||
@@ -1,33 +1,23 @@
|
||||
package com.seibel.lod.builders.worldGeneration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
|
||||
import com.seibel.lod.builders.GenerationRequest;
|
||||
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.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.objects.PosToGenerateContainer;
|
||||
import com.seibel.lod.render.LodRenderer;
|
||||
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.client.Minecraft;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.common.WorldWorkerManager;
|
||||
@@ -40,7 +30,7 @@ import net.minecraftforge.common.WorldWorkerManager;
|
||||
*/
|
||||
public class LodWorldGenerator
|
||||
{
|
||||
public Minecraft mc = Minecraft.getInstance();
|
||||
public MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
|
||||
|
||||
/**
|
||||
* This holds the thread used to generate new LODs off the main thread.
|
||||
@@ -75,10 +65,6 @@ public class LodWorldGenerator
|
||||
*/
|
||||
public static final LodWorldGenerator INSTANCE = new LodWorldGenerator();
|
||||
|
||||
public volatile ConcurrentMap<LevelPos, MutableBoolean> nodeToGenerate;
|
||||
|
||||
SortedSet<LevelPos> nodeToGenerateListNear;
|
||||
SortedSet<LevelPos> nodeToGenerateListFar;
|
||||
|
||||
private LodWorldGenerator()
|
||||
{
|
||||
@@ -108,14 +94,9 @@ public class LodWorldGenerator
|
||||
try
|
||||
{
|
||||
// round the player's block position down to the nearest chunk BlockPos
|
||||
ChunkPos playerChunkPos = new ChunkPos(mc.player.blockPosition());
|
||||
BlockPos playerBlockPosRounded = playerChunkPos.getWorldPosition();
|
||||
int playerPosX = mc.getPlayer().blockPosition().getX();
|
||||
int playerPosZ = mc.getPlayer().blockPosition().getZ();
|
||||
|
||||
// used when determining which chunks are closer when queuing distance
|
||||
// generation
|
||||
int minChunkDist = Integer.MAX_VALUE;
|
||||
|
||||
ArrayList<GenerationRequest> chunksToGen = new ArrayList<>(maxChunkGenRequests);
|
||||
// if we don't have a full number of chunks to generate in chunksToGen
|
||||
// we can top it off from this reserve
|
||||
|
||||
@@ -123,92 +104,34 @@ public class LodWorldGenerator
|
||||
//=======================================//
|
||||
// create the generation Request objects //
|
||||
//=======================================//
|
||||
List<GenerationRequest> generationRequestList = new ArrayList<>(maxChunkGenRequests);
|
||||
|
||||
if (nodeToGenerate == null)
|
||||
nodeToGenerate = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
Comparator<LevelPos> posNearComparator = LevelPos.getPosComparator(
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ());
|
||||
Comparator<LevelPos> posFarComparator = LevelPos.getPosAndDetailComparator(
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ());
|
||||
nodeToGenerateListNear = new TreeSet(posNearComparator);
|
||||
nodeToGenerateListFar = new TreeSet(posFarComparator);
|
||||
|
||||
lodDim.getDataToGenerate(
|
||||
nodeToGenerate,
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ());
|
||||
|
||||
ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(lodDim.dimension);
|
||||
|
||||
byte farDetail = (byte) 8;
|
||||
PosToGenerateContainer posToGenerate = lodDim.getDataToGenerate(
|
||||
farDetail,
|
||||
maxChunkGenRequests,
|
||||
0.25,
|
||||
playerPosX,
|
||||
playerPosZ);
|
||||
//System.out.println(posToGenerate);
|
||||
//here we prepare two sorted set
|
||||
//the first contains the near pos to render
|
||||
//the second contain the far pos to render
|
||||
byte farDetail = (byte) 7;
|
||||
for (LevelPos pos : nodeToGenerate.keySet())
|
||||
byte detailLevel;
|
||||
int posX;
|
||||
int posZ;
|
||||
int[] levelPos;
|
||||
for (int index = 0; index < posToGenerate.getNumberOfPos(); index++)
|
||||
{
|
||||
if (!nodeToGenerate.get(pos).booleanValue())
|
||||
{
|
||||
nodeToGenerate.remove(pos);
|
||||
} else
|
||||
{
|
||||
if (pos.detailLevel > farDetail){
|
||||
nodeToGenerateListFar.add(pos);
|
||||
}
|
||||
nodeToGenerateListNear.add(pos);
|
||||
nodeToGenerate.get(pos).setFalse();
|
||||
}
|
||||
}
|
||||
levelPos = posToGenerate.getNthPos(index);
|
||||
if(levelPos[0] == 0)
|
||||
continue;
|
||||
detailLevel = (byte) (levelPos[0] -1);
|
||||
posX = levelPos[1];
|
||||
posZ = levelPos[2];
|
||||
|
||||
int maxDistance;
|
||||
byte circle;
|
||||
LevelPos levelPos;
|
||||
int requesting = maxChunkGenRequests;
|
||||
int requestingFar = maxChunkGenRequests / 4;
|
||||
while (requesting > 0 && !nodeToGenerateListNear.isEmpty())
|
||||
{
|
||||
levelPos = nodeToGenerateListNear.first();
|
||||
//.out.println(levelPos);
|
||||
nodeToGenerate.remove(levelPos);
|
||||
nodeToGenerateListNear.remove(levelPos);
|
||||
nodeToGenerateListFar.remove(levelPos);
|
||||
|
||||
//maxDistance = levelPos.maxDistance(
|
||||
// playerBlockPosRounded.getX(),
|
||||
// playerBlockPosRounded.getZ());
|
||||
//circle = DetailDistanceUtil.getDistanceGenerationInverse(maxDistance);
|
||||
generationRequestList.add(new GenerationRequest(levelPos, DetailDistanceUtil.getDistanceGenerationMode(levelPos.detailLevel)));
|
||||
requesting--;
|
||||
if (requestingFar > 0 && !nodeToGenerateListFar.isEmpty())
|
||||
{
|
||||
levelPos = nodeToGenerateListFar.first();
|
||||
nodeToGenerate.remove(levelPos);
|
||||
nodeToGenerateListNear.remove(levelPos);
|
||||
nodeToGenerateListFar.remove(levelPos);
|
||||
if (levelPos.detailLevel >= farDetail)
|
||||
{
|
||||
//maxDistance = levelPos.maxDistance( playerBlockPosRounded.getX(), playerBlockPosRounded.getZ());
|
||||
//circle = DetailDistanceUtil.getDistanceGenerationInverse(maxDistance);
|
||||
generationRequestList.add(new GenerationRequest(levelPos, DetailDistanceUtil.getDistanceGenerationMode(levelPos.detailLevel)));
|
||||
requestingFar--;
|
||||
requesting--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//====================================//
|
||||
// get the closet generation requests //
|
||||
//====================================//
|
||||
|
||||
// determine which points in the posListToGenerate
|
||||
// should actually be queued to generate
|
||||
for (GenerationRequest generationRequest : generationRequestList)
|
||||
{
|
||||
ChunkPos chunkPos = generationRequest.getChunkPos();
|
||||
ChunkPos chunkPos = new ChunkPos(LevelPosUtil.getChunkPos(detailLevel,posX), LevelPosUtil.getChunkPos(detailLevel,posZ));
|
||||
if (numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests)
|
||||
{
|
||||
// prevent generating the same chunk multiple times
|
||||
@@ -216,32 +139,16 @@ public class LodWorldGenerator
|
||||
{
|
||||
continue;
|
||||
}
|
||||
chunksToGen.add(generationRequest);
|
||||
}
|
||||
|
||||
} // lod null and can generate more chunks
|
||||
} // positions to generate
|
||||
|
||||
|
||||
//=============================//
|
||||
// start the LodNodeGenWorkers //
|
||||
//=============================//
|
||||
|
||||
// issue #19
|
||||
// TODO add a way for a server side mod to generate chunks requested here
|
||||
ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(lodDim.dimension);
|
||||
|
||||
// start chunk generation
|
||||
for (GenerationRequest generationRequest : generationRequestList)
|
||||
{
|
||||
// don't add null chunkPos (which shouldn't happen anyway)
|
||||
// or add more to the generation queue
|
||||
ChunkPos chunkPos = generationRequest.getChunkPos();
|
||||
if (chunkPos == null || numberOfChunksWaitingToGenerate.get() >= maxChunkGenRequests)
|
||||
continue;
|
||||
|
||||
positionWaitingToBeGenerated.add(chunkPos);
|
||||
numberOfChunksWaitingToGenerate.addAndGet(1);
|
||||
LodNodeGenWorker genWorker = new LodNodeGenWorker(chunkPos, generationRequest.generationMode, renderer, lodBuilder, lodDim, serverWorld);
|
||||
LodNodeGenWorker genWorker = new LodNodeGenWorker(chunkPos, DetailDistanceUtil.getDistanceGenerationMode(detailLevel), lodBuilder, lodDim, serverWorld);
|
||||
WorldWorkerManager.addWorker(genWorker);
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ public class LodConfig
|
||||
lodChunkRenderDistance = builder
|
||||
.comment("\n\n"
|
||||
+ " This is the render distance of the mod \n")
|
||||
.defineInRange("lodChunkRenderDistane", 64, 32, 512);
|
||||
.defineInRange("lodChunkRenderDistance", 64, 32, 512);
|
||||
|
||||
shadingMode = builder
|
||||
.comment("\n\n"
|
||||
|
||||
@@ -42,7 +42,7 @@ import com.seibel.lod.util.LodUtil;
|
||||
* to file.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 8-24-2021
|
||||
* @version 9-7-2021
|
||||
*/
|
||||
public class LodDimensionFileHandler
|
||||
{
|
||||
@@ -65,10 +65,6 @@ public class LodDimensionFileHandler
|
||||
* .txt
|
||||
*/
|
||||
private static final String FILE_EXTENSION = ".txt";
|
||||
/**
|
||||
* lod/
|
||||
*/
|
||||
private static final String LOD_FOLDER_NAME = "lod";
|
||||
/**
|
||||
* detail-#
|
||||
*/
|
||||
@@ -88,7 +84,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 = 4;
|
||||
public static final int LOD_SAVE_FILE_VERSION = 5;
|
||||
|
||||
/**
|
||||
* This is the string written before the file version
|
||||
@@ -133,14 +129,14 @@ public class LodDimensionFileHandler
|
||||
LodRegion region = new LodRegion(LodUtil.REGION_DETAIL_LEVEL,regionPos, generationMode);
|
||||
for (byte tempDetailLevel = LodUtil.REGION_DETAIL_LEVEL; tempDetailLevel >= detailLevel; tempDetailLevel--)
|
||||
{
|
||||
String fileName = getFileNameAndPathForRegion(regionX, regionZ, generationMode, tempDetailLevel);
|
||||
|
||||
try
|
||||
{
|
||||
String fileName = getFileNameAndPathForRegion(regionX, regionZ, generationMode, tempDetailLevel);
|
||||
|
||||
// if the fileName was null that means the folder is inaccessible
|
||||
// for some reason
|
||||
if (fileName == null)
|
||||
throw new IllegalArgumentException("Game folder is not accessible");
|
||||
throw new IllegalArgumentException("Unable to read region [" + regionX + ", " + regionZ + "] file, no fileName.");
|
||||
|
||||
|
||||
File f = new File(fileName);
|
||||
@@ -176,7 +172,7 @@ public class LodDimensionFileHandler
|
||||
// close the reader and delete the file.
|
||||
bufferedReader.close();
|
||||
f.delete();
|
||||
ClientProxy.LOGGER.info("Outdated LOD region file for region: (" + regionX + "," + regionZ + ") version: " + fileVersion +
|
||||
ClientProxy.LOGGER.info("Outdated LOD region file for region: (" + regionX + "," + regionZ + ") version found: " + fileVersion +
|
||||
", version requested: " + LOD_SAVE_FILE_VERSION +
|
||||
" File was been deleted.");
|
||||
|
||||
@@ -187,7 +183,7 @@ public class LodDimensionFileHandler
|
||||
// close the reader and ignore the file, we don't
|
||||
// want to accidently delete anything the user may want.
|
||||
bufferedReader.close();
|
||||
ClientProxy.LOGGER.info("Newer LOD region file for region: (" + regionX + "," + regionZ + ") version: " + fileVersion +
|
||||
ClientProxy.LOGGER.info("Newer LOD region file for region: (" + regionX + "," + regionZ + ") version found: " + fileVersion +
|
||||
", version requested: " + LOD_SAVE_FILE_VERSION +
|
||||
" this region will not be written to in order to protect the newer file.");
|
||||
|
||||
@@ -209,7 +205,7 @@ public class LodDimensionFileHandler
|
||||
{
|
||||
// the buffered reader encountered a
|
||||
// problem reading the file
|
||||
|
||||
ClientProxy.LOGGER.error("LOD file read error. Unable to read to [" + fileName + "] error [" + e.getMessage() + "]: ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -274,7 +270,7 @@ public class LodDimensionFileHandler
|
||||
// for some reason
|
||||
if (fileName == null)
|
||||
{
|
||||
ClientProxy.LOGGER.warn("Unable to save region [" + x + ", " + z + "] to file.");
|
||||
ClientProxy.LOGGER.warn("Unable to save region [" + x + ", " + z + "] to file, no fileName.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -342,7 +338,7 @@ public class LodDimensionFileHandler
|
||||
Files.move(newFile.toPath(), oldFile.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (Exception e)
|
||||
{
|
||||
ClientProxy.LOGGER.error("LOD file write error: ");
|
||||
ClientProxy.LOGGER.error("LOD file write error. Unable to write to [" + fileName + "] error [" + e.getMessage() + "]: ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
package com.seibel.lod.handlers;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import com.seibel.lod.enums.FogQuality;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
/**
|
||||
* This object is used to get variables from methods
|
||||
@@ -29,27 +29,32 @@ import net.minecraft.client.Minecraft;
|
||||
* in Optifine.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 7-03-2021
|
||||
* @version 9-7-2021
|
||||
*/
|
||||
public class ReflectionHandler
|
||||
{
|
||||
private Minecraft mc = Minecraft.getInstance();
|
||||
public static final ReflectionHandler INSTANCE = new ReflectionHandler();
|
||||
private MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
|
||||
|
||||
public Field ofFogField = null;
|
||||
|
||||
public ReflectionHandler()
|
||||
public Method vertexBufferUploadMethod = null;
|
||||
|
||||
|
||||
|
||||
private ReflectionHandler()
|
||||
{
|
||||
setupFogField();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Similar to setupFovMethod.
|
||||
* finds the Optifine fog type field
|
||||
*/
|
||||
private void setupFogField()
|
||||
{
|
||||
// get every variable from the entity renderer
|
||||
Field[] optionFields = mc.options.getClass().getDeclaredFields();
|
||||
|
||||
Field[] optionFields = mc.getOptions().getClass().getDeclaredFields();
|
||||
|
||||
// try and find the ofFogType variable in gameSettings
|
||||
for (Field field : optionFields)
|
||||
{
|
||||
@@ -59,14 +64,15 @@ public class ReflectionHandler
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// we didn't find the field,
|
||||
// either optifine isn't installed, or
|
||||
// optifine changed the name of the variable
|
||||
ofFogField = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get what type of fog optifine is currently set to render.
|
||||
*/
|
||||
@@ -79,35 +85,34 @@ public class ReflectionHandler
|
||||
// the setup method wasn't called yet.
|
||||
return FogQuality.FANCY;
|
||||
}
|
||||
|
||||
|
||||
int returnNum = 0;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
returnNum = (int) ofFogField.get(mc.options);
|
||||
returnNum = (int) ofFogField.get(mc.getOptions());
|
||||
} catch (IllegalArgumentException | IllegalAccessException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
switch (returnNum)
|
||||
{
|
||||
// optifine's "default" option,
|
||||
// it should never be called in this case
|
||||
case 0:
|
||||
return FogQuality.FAST;
|
||||
|
||||
// optifine's "default" option,
|
||||
// it should never be called in this case
|
||||
case 0:
|
||||
return FogQuality.FAST;
|
||||
|
||||
// normal options
|
||||
case 1:
|
||||
return FogQuality.FAST;
|
||||
case 2:
|
||||
return FogQuality.FANCY;
|
||||
case 3:
|
||||
return FogQuality.OFF;
|
||||
|
||||
default:
|
||||
return FogQuality.FAST;
|
||||
case 1:
|
||||
return FogQuality.FAST;
|
||||
case 2:
|
||||
return FogQuality.FANCY;
|
||||
case 3:
|
||||
return FogQuality.OFF;
|
||||
|
||||
default:
|
||||
return FogQuality.FAST;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,47 +2,96 @@ 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 static short[] createDataPoint(int height, int depth, int red, int green, int blue)
|
||||
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)
|
||||
{
|
||||
return new short[]{(short) height, (short) depth, (short) red, (short) green, (short) blue};
|
||||
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(short[] dataPoint)
|
||||
public static short getHeight(long dataPoint)
|
||||
{
|
||||
return dataPoint[0];
|
||||
return (short) ((dataPoint >> HEIGHT_SHIFT) & HEIGHT_MASK);
|
||||
}
|
||||
|
||||
public static short getDepth(short[] dataPoint)
|
||||
public static short getDepth(long dataPoint)
|
||||
{
|
||||
return dataPoint[1];
|
||||
|
||||
return (short) ((dataPoint >> DEPTH_SHIFT) & DEPTH_MASK);
|
||||
}
|
||||
|
||||
public static short getRed(short[] dataPoint)
|
||||
public static short getRed(long dataPoint)
|
||||
{
|
||||
return dataPoint[2];
|
||||
|
||||
return (short) ((dataPoint >> RED_SHIFT) & RED_MASK);
|
||||
}
|
||||
|
||||
public static short getGreen(short[] dataPoint)
|
||||
public static short getGreen(long dataPoint)
|
||||
{
|
||||
return dataPoint[3];
|
||||
return (short) ((dataPoint >> GREEN_SHIFT) & GREEN_MASK);
|
||||
}
|
||||
|
||||
public static short getBlue(short[] dataPoint)
|
||||
public static short getBlue(long dataPoint)
|
||||
{
|
||||
return dataPoint[4];
|
||||
return (short) ((dataPoint >> BLUE_SHIFT) & BLUE_MASK);
|
||||
}
|
||||
|
||||
public static short[] getHeightDepth(short[] dataPoint)
|
||||
public static boolean doesItExist(long dataPoint)
|
||||
{
|
||||
return new short[]{dataPoint[0], dataPoint[1]};
|
||||
return ((dataPoint & EXISTENCE_MASK) == 1);
|
||||
}
|
||||
|
||||
public static int getColor(short[] dataPoint)
|
||||
public static int getColor(long dataPoint)
|
||||
{
|
||||
int R = (dataPoint[2] << 16) & 0x00FF0000;
|
||||
int G = (dataPoint[3] << 8) & 0x0000FF00;
|
||||
int B = dataPoint[4] & 0x000000FF;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,65 +7,40 @@ import com.seibel.lod.util.LodUtil;
|
||||
public class LevelContainer implements Serializable
|
||||
{
|
||||
|
||||
/** This is here so that Eclipse doesn't complain */
|
||||
private static final long serialVersionUID = -4930855068717998385L;
|
||||
|
||||
public static final char DATA_DELIMITER = ',';
|
||||
|
||||
public final byte detailLevel;
|
||||
|
||||
public final byte[][][] colors;
|
||||
public final long[][] data;
|
||||
|
||||
public final short[][] height;
|
||||
|
||||
public final short[][] depth;
|
||||
|
||||
public final boolean[][] dataExistence;
|
||||
|
||||
public LevelContainer(byte detailLevel, byte[][][] colors, short[][] height, short[][] depth, boolean[][] dataExistence)
|
||||
public LevelContainer(byte detailLevel, long[][] data)
|
||||
{
|
||||
this.detailLevel = detailLevel;
|
||||
this.colors = colors;
|
||||
this.height = height;
|
||||
this.depth = depth;
|
||||
this.dataExistence = dataExistence;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public LevelContainer(String data)
|
||||
public LevelContainer(String inputString)
|
||||
{
|
||||
|
||||
int index = 0;
|
||||
int lastIndex = 0;
|
||||
|
||||
|
||||
index = data.indexOf(DATA_DELIMITER, 0);
|
||||
this.detailLevel = (byte) Integer.parseInt(data.substring(0, index));
|
||||
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.colors = new byte[size][size][3];
|
||||
this.height = new short[size][size];
|
||||
this.depth = new short[size][size];
|
||||
this.dataExistence = new boolean[size][size];
|
||||
int intCol;
|
||||
this.data = new long[size][size];
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
intCol = Integer.parseInt(data.substring(lastIndex + 1, index), 16);
|
||||
colors[x][z][0] = (byte) ((intCol >> 16) - 128);
|
||||
colors[x][z][1] = (byte) ((intCol >> 8) - 128);
|
||||
colors[x][z][2] = (byte) (intCol - 128);
|
||||
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
height[x][z] = Short.parseShort(data.substring(lastIndex + 1, index), 16);
|
||||
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
depth[x][z] = Short.parseShort(data.substring(lastIndex + 1, index), 16);
|
||||
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
dataExistence[x][z] = Boolean.parseBoolean(data.substring(lastIndex + 1, index));
|
||||
index = inputString.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
data[x][z] = Long.parseLong(inputString.substring(lastIndex + 1, index), 16);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +50,6 @@ public class LevelContainer implements Serializable
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
int combinedCol;
|
||||
int size = (int) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
stringBuilder.append(detailLevel);
|
||||
stringBuilder.append(DATA_DELIMITER);
|
||||
@@ -83,15 +57,8 @@ public class LevelContainer implements Serializable
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
//Converting the colors to intColor and then to HEX
|
||||
combinedCol = ((colors[x][z][0] + 128) << 16) | ((colors[x][z][1] + 128) << 8) | ((colors[x][z][2] + 128));
|
||||
stringBuilder.append(Integer.toHexString(combinedCol));
|
||||
stringBuilder.append(DATA_DELIMITER);
|
||||
stringBuilder.append(Integer.toHexString(height[x][z] & 0xffff));
|
||||
stringBuilder.append(DATA_DELIMITER);
|
||||
stringBuilder.append(Integer.toHexString(depth[x][z] & 0xffff));
|
||||
stringBuilder.append(DATA_DELIMITER);
|
||||
stringBuilder.append(dataExistence[x][z]);
|
||||
//Converting the dataToHex
|
||||
stringBuilder.append(Long.toHexString(data[x][z]));
|
||||
stringBuilder.append(DATA_DELIMITER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.seibel.lod.objects.LevelPos;
|
||||
|
||||
public interface ImmutableLevelPos
|
||||
{
|
||||
public LevelPos getConvertedLevelPos(byte newDetailLevel);
|
||||
public LevelPos getRegionModuleLevelPos();
|
||||
}
|
||||
@@ -1,415 +0,0 @@
|
||||
package com.seibel.lod.objects.LevelPos;
|
||||
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class LevelPos implements Cloneable, ImmutableLevelPos, MutableLevelPos, Comparable<LevelPos>
|
||||
{
|
||||
public byte detailLevel;
|
||||
public int posX;
|
||||
public int posZ;
|
||||
public boolean flag;
|
||||
|
||||
public LevelPos()
|
||||
{
|
||||
}
|
||||
|
||||
public LevelPos(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
this.posX = posX;
|
||||
this.posZ = posZ;
|
||||
this.detailLevel = detailLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* this operation does not change the state
|
||||
*/
|
||||
public LevelPos getConvertedLevelPos(byte newDetailLevel)
|
||||
{
|
||||
if (newDetailLevel >= detailLevel)
|
||||
{
|
||||
int width = 1 << (newDetailLevel - detailLevel);
|
||||
return new LevelPos(
|
||||
newDetailLevel,
|
||||
Math.floorDiv(posX, width),
|
||||
Math.floorDiv(posZ, width));
|
||||
} else
|
||||
{
|
||||
int width = 1 << (detailLevel - newDetailLevel);
|
||||
return new LevelPos(
|
||||
newDetailLevel,
|
||||
posX * width,
|
||||
posZ * width);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this operation does not change the state
|
||||
*/
|
||||
public LevelPos getRegionModuleLevelPos()
|
||||
{
|
||||
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
return new LevelPos(
|
||||
detailLevel,
|
||||
Math.floorMod(posX, width),
|
||||
Math.floorMod(posZ, width));
|
||||
}
|
||||
|
||||
/**
|
||||
* this operation changes the state
|
||||
*/
|
||||
public void convert(byte newDetailLevel)
|
||||
{
|
||||
if (newDetailLevel >= detailLevel)
|
||||
{
|
||||
int width = 1 << (newDetailLevel - detailLevel);
|
||||
detailLevel = newDetailLevel;
|
||||
posX = Math.floorDiv(posX, width);
|
||||
posZ = Math.floorDiv(posZ, width);
|
||||
} else
|
||||
{
|
||||
int width = 1 << (detailLevel - newDetailLevel);
|
||||
detailLevel = newDetailLevel;
|
||||
posX = posX * width;
|
||||
posZ = posZ * width;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this operation changes the state
|
||||
*/
|
||||
public void performRegionModule()
|
||||
{
|
||||
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
posX = Math.floorMod(posX, width);
|
||||
posZ = Math.floorMod(posZ, width);
|
||||
}
|
||||
|
||||
/**
|
||||
* this operation changes the state
|
||||
*/
|
||||
public void applyOffset(int xOffset, int zOffset)
|
||||
{
|
||||
posX = posX + xOffset;
|
||||
posX = posZ + zOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* this operation changes the state
|
||||
*/
|
||||
public void changeParameters(byte newDetailLevel, int newPosX, int newPosZ)
|
||||
{
|
||||
detailLevel = newDetailLevel;
|
||||
posX = newPosX;
|
||||
posZ = newPosZ;
|
||||
}
|
||||
|
||||
public RegionPos getRegionPos()
|
||||
{
|
||||
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
return new RegionPos(
|
||||
Math.floorDiv(posX, width),
|
||||
Math.floorDiv(posZ, width));
|
||||
}
|
||||
|
||||
public int getRegionPosX()
|
||||
{
|
||||
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
return Math.floorDiv(posX, width);
|
||||
}
|
||||
|
||||
public int getRegionPosZ()
|
||||
{
|
||||
int width = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
return Math.floorDiv(posZ, width);
|
||||
}
|
||||
|
||||
public int getChunkPosX()
|
||||
{
|
||||
if (LodUtil.CHUNK_DETAIL_LEVEL >= detailLevel)
|
||||
{
|
||||
int width = 1 << (LodUtil.CHUNK_DETAIL_LEVEL - detailLevel);
|
||||
return Math.floorDiv(posX, width);
|
||||
} else
|
||||
{
|
||||
int width = 1 << (detailLevel - LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
return posX * width;
|
||||
}
|
||||
}
|
||||
|
||||
public int getChunkPosZ()
|
||||
{
|
||||
if (LodUtil.CHUNK_DETAIL_LEVEL >= detailLevel)
|
||||
{
|
||||
int width = 1 << (LodUtil.CHUNK_DETAIL_LEVEL - detailLevel);
|
||||
return Math.floorDiv(posZ, width);
|
||||
} else
|
||||
{
|
||||
int width = 1 << (detailLevel - LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
return posZ * width;
|
||||
}
|
||||
}
|
||||
|
||||
public ChunkPos getChunkPos()
|
||||
{
|
||||
if (LodUtil.CHUNK_DETAIL_LEVEL >= detailLevel)
|
||||
{
|
||||
int width = 1 << (LodUtil.CHUNK_DETAIL_LEVEL - detailLevel);
|
||||
return new ChunkPos(
|
||||
Math.floorDiv(posX, width),
|
||||
Math.floorDiv(posZ, width));
|
||||
} else
|
||||
{
|
||||
int width = 1 << (detailLevel - LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
return new ChunkPos(
|
||||
posX * width,
|
||||
posZ * width);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO fix the region disappearing for a second
|
||||
*/
|
||||
|
||||
public int maxDistance(int playerPosX, int playerPosZ, int regionPosX, int regionPosZ)
|
||||
{
|
||||
int width = 1 << detailLevel;
|
||||
|
||||
int startPosX = regionPosX * 512 + posX * width;
|
||||
int startPosZ = regionPosZ * 512 + posZ * width;
|
||||
int endPosX = startPosX + width;
|
||||
int endPosZ = startPosZ + width;
|
||||
|
||||
int maxDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
|
||||
return maxDistance;
|
||||
}
|
||||
|
||||
public int maxDistance(int playerPosX, int playerPosZ)
|
||||
{
|
||||
int width = 1 << detailLevel;
|
||||
|
||||
int startPosX = posX * width;
|
||||
int startPosZ = posZ * width;
|
||||
int endPosX = startPosX + width;
|
||||
int endPosZ = startPosZ + width;
|
||||
|
||||
int maxDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
|
||||
return maxDistance;
|
||||
}
|
||||
|
||||
public int minDistance(int playerPosX, int playerPosZ, int regionPosX, int regionPosZ)
|
||||
{
|
||||
int width = 1 << detailLevel;
|
||||
|
||||
int startPosX = regionPosX * 512 + posX * width;
|
||||
int startPosZ = regionPosZ * 512 + posZ * width;
|
||||
int endPosX = startPosX + width;
|
||||
int endPosZ = startPosZ + width;
|
||||
|
||||
boolean inXArea = playerPosX >= startPosX && playerPosX <= endPosX;
|
||||
boolean inZArea = playerPosZ >= startPosZ && playerPosZ <= endPosZ;
|
||||
if (inXArea && inZArea)
|
||||
{
|
||||
return 0;
|
||||
} else if (inXArea)
|
||||
{
|
||||
return Math.min(
|
||||
Math.abs(playerPosZ - startPosZ),
|
||||
Math.abs(playerPosZ - endPosZ)
|
||||
);
|
||||
} else if (inZArea)
|
||||
{
|
||||
return Math.min(
|
||||
Math.abs(playerPosX - startPosX),
|
||||
Math.abs(playerPosX - endPosX)
|
||||
);
|
||||
} else
|
||||
{
|
||||
int minDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2));
|
||||
minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)));
|
||||
minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
return minDistance;
|
||||
}
|
||||
}
|
||||
|
||||
public int minDistance(int playerPosX, int playerPosZ)
|
||||
{
|
||||
int width = 1 << detailLevel;
|
||||
|
||||
int startPosX = posX * width;
|
||||
int startPosZ = posZ * width;
|
||||
int endPosX = startPosX + width;
|
||||
int endPosZ = startPosZ + width;
|
||||
|
||||
boolean inXArea = playerPosX >= startPosX && playerPosX <= endPosX;
|
||||
boolean inZArea = playerPosZ >= startPosZ && playerPosZ <= endPosZ;
|
||||
if (inXArea && inZArea)
|
||||
{
|
||||
return 0;
|
||||
} else if (inXArea)
|
||||
{
|
||||
return Math.min(
|
||||
Math.abs(playerPosZ - startPosZ),
|
||||
Math.abs(playerPosZ - endPosZ)
|
||||
);
|
||||
} else if (inZArea)
|
||||
{
|
||||
return Math.min(
|
||||
Math.abs(playerPosX - startPosX),
|
||||
Math.abs(playerPosX - endPosX)
|
||||
);
|
||||
} else
|
||||
{
|
||||
int minDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2));
|
||||
minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)));
|
||||
minDistance = Math.min(minDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
return minDistance;
|
||||
}
|
||||
}
|
||||
|
||||
public static LevelPosDistanceComparator getPosComparator(int playerPosX, int playerPosZ)
|
||||
{
|
||||
return new LevelPosDistanceComparator(playerPosX, playerPosZ);
|
||||
}
|
||||
|
||||
public static LevelPosDetailComparator getPosAndDetailComparator(int playerPosX, int playerPosZ)
|
||||
{
|
||||
return new LevelPosDetailComparator(playerPosX, playerPosZ);
|
||||
}
|
||||
|
||||
public static class LevelPosDistanceComparator implements Comparator<LevelPos>
|
||||
{
|
||||
int playerPosX;
|
||||
int playerPosZ;
|
||||
|
||||
public LevelPosDistanceComparator(int playerPosX, int playerPosZ)
|
||||
{
|
||||
this.playerPosX = playerPosX;
|
||||
this.playerPosZ = playerPosZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(LevelPos first, LevelPos second)
|
||||
{
|
||||
return Integer.compare(
|
||||
first.minDistance(playerPosX, playerPosZ),
|
||||
second.minDistance(playerPosX, playerPosZ));
|
||||
}
|
||||
}
|
||||
|
||||
public static class LevelPosDetailComparator implements Comparator<LevelPos>
|
||||
{
|
||||
int playerPosX;
|
||||
int playerPosZ;
|
||||
|
||||
public LevelPosDetailComparator(int playerPosX, int playerPosZ)
|
||||
{
|
||||
this.playerPosX = playerPosX;
|
||||
this.playerPosZ = playerPosZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(LevelPos first, LevelPos second)
|
||||
{
|
||||
int compareResult = Integer.compare(second.detailLevel, first.detailLevel);
|
||||
if (compareResult == 0)
|
||||
{
|
||||
compareResult = Integer.compare(
|
||||
first.minDistance(playerPosX, playerPosZ),
|
||||
second.minDistance(playerPosX, playerPosZ));
|
||||
}
|
||||
return compareResult;
|
||||
}
|
||||
}
|
||||
|
||||
public static LevelPosComparator getComparator()
|
||||
{
|
||||
return new LevelPosComparator();
|
||||
}
|
||||
|
||||
public static class LevelPosComparator implements Comparator<LevelPos>
|
||||
{
|
||||
@Override
|
||||
public int compare(LevelPos first, LevelPos second)
|
||||
{
|
||||
int compareResult = Integer.compare(first.detailLevel, second.detailLevel);
|
||||
if (compareResult == 0)
|
||||
{
|
||||
compareResult = Integer.compare(
|
||||
first.posX,
|
||||
second.posX);
|
||||
}
|
||||
if (compareResult == 0)
|
||||
{
|
||||
compareResult = Integer.compare(
|
||||
first.posZ,
|
||||
second.posZ);
|
||||
}
|
||||
return compareResult;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(LevelPos other)
|
||||
{
|
||||
int compareResult = Integer.compare(this.detailLevel, other.detailLevel);
|
||||
if (compareResult == 0)
|
||||
{
|
||||
compareResult = Integer.compare(
|
||||
this.posX,
|
||||
other.posX);
|
||||
}
|
||||
if (compareResult == 0)
|
||||
{
|
||||
compareResult = Integer.compare(
|
||||
this.posZ,
|
||||
other.posZ);
|
||||
}
|
||||
return compareResult;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public LevelPos clone()
|
||||
{
|
||||
return new LevelPos(detailLevel, posX, posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 7;
|
||||
hash = 31 * hash + (int) detailLevel;
|
||||
hash = 31 * hash + posX;
|
||||
hash = 31 * hash + posZ;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
return (this.detailLevel == ((LevelPos) other).detailLevel &&
|
||||
this.posX == ((LevelPos) other).posX &&
|
||||
this.posZ == ((LevelPos) other).posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String s = (detailLevel + " " + posX + " " + posZ);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.seibel.lod.objects.LevelPos;
|
||||
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
public interface MutableLevelPos
|
||||
{
|
||||
public void convert(byte newDetailLevel);
|
||||
|
||||
public void performRegionModule();
|
||||
|
||||
public void applyOffset(int xOffset, int zOffset);
|
||||
|
||||
public void changeParameters(byte newDetailLevel, int newPosX, int newPosZ);
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class LevelPosUtil
|
||||
{
|
||||
@@ -37,11 +34,29 @@ public class LevelPosUtil
|
||||
return new int[]{detailLevel, posX, posZ};
|
||||
}
|
||||
|
||||
public static int[] createLevelPos(byte detailLevel, int posX, int posZ, int distance)
|
||||
public static int convert(byte detailLevel, int pos, byte newDetailLevel)
|
||||
{
|
||||
return new int[]{detailLevel, posX, posZ, distance};
|
||||
int width;
|
||||
if (newDetailLevel >= detailLevel)
|
||||
{
|
||||
width = 1 << (newDetailLevel - detailLevel);
|
||||
return Math.floorDiv(pos, width);
|
||||
} else
|
||||
{
|
||||
width = 1 << (detailLevel - newDetailLevel);
|
||||
return pos * width;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getRegion(byte detailLevel, int pos)
|
||||
{
|
||||
return Math.floorDiv(pos, 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel));
|
||||
}
|
||||
|
||||
public static int getRegionModule(byte detailLevel, int pos)
|
||||
{
|
||||
return Math.floorMod(pos, 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel));
|
||||
}
|
||||
|
||||
public static byte getDetailLevel(int[] levelPos)
|
||||
{
|
||||
@@ -105,6 +120,11 @@ public class LevelPosUtil
|
||||
return Math.floorDiv(getPosZ(levelPos), width);
|
||||
}
|
||||
|
||||
public static int getChunkPos(byte detailLevel, int pos)
|
||||
{
|
||||
return convert(detailLevel,pos, LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
}
|
||||
|
||||
public static int getChunkPosX(int[] levelPos)
|
||||
{
|
||||
levelPos = convert(levelPos, LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
@@ -139,6 +159,23 @@ public class LevelPosUtil
|
||||
return maxDistance;
|
||||
}
|
||||
|
||||
public static int maxDistance(byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ, int xRegion, int zRegion)
|
||||
{
|
||||
int width = 1 << detailLevel;
|
||||
|
||||
int startPosX = xRegion * 512 + posX * width;
|
||||
int startPosZ = zRegion * 512 + posZ * width;
|
||||
int endPosX = startPosX + width;
|
||||
int endPosZ = startPosZ + width;
|
||||
|
||||
int maxDistance = (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - startPosZ, 2));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - startPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - startPosZ, 2)));
|
||||
maxDistance = Math.max(maxDistance, (int) Math.sqrt(Math.pow(playerPosX - endPosX, 2) + Math.pow(playerPosZ - endPosZ, 2)));
|
||||
|
||||
return maxDistance;
|
||||
}
|
||||
|
||||
|
||||
public static int minDistance(int[] levelPos, int playerPosX, int playerPosZ)
|
||||
{
|
||||
@@ -181,40 +218,26 @@ public class LevelPosUtil
|
||||
}
|
||||
}
|
||||
|
||||
public static int compareDistance(int posX, int posZ, int[] first, int[] second)
|
||||
public static int compareDistance(int firstDistance, int secondDistance)
|
||||
{
|
||||
return Integer.compare(
|
||||
minDistance(first, posX, posZ),
|
||||
minDistance(second, posX, posZ));
|
||||
firstDistance,
|
||||
secondDistance);
|
||||
}
|
||||
|
||||
public static int compareDistance(int[] first, int[] second)
|
||||
{
|
||||
return Integer.compare(
|
||||
getDistance(first),
|
||||
getDistance(second));
|
||||
}
|
||||
|
||||
public static int compareLevelAndDistance(int[] first, int[] second)
|
||||
public static int compareLevelAndDistance(byte firstDetail, int firstDistance, byte secondDetail, int secondDistance)
|
||||
{
|
||||
int compareResult = Integer.compare(getDetailLevel(second), getDetailLevel(first));
|
||||
int compareResult = Integer.compare(
|
||||
secondDetail,
|
||||
firstDetail);
|
||||
// System.out.println("comparing level "+ firstDetail + " " + secondDetail + " " + compareResult);
|
||||
if (compareResult == 0)
|
||||
{
|
||||
compareResult = Integer.compare(
|
||||
getDistance(first),
|
||||
getDistance(second));
|
||||
}
|
||||
return compareResult;
|
||||
}
|
||||
|
||||
public static int compareLevelAndDistance(int posX, int posZ, int[] first, int[] second)
|
||||
{
|
||||
int compareResult = Integer.compare(getDetailLevel(second), getDetailLevel(first));
|
||||
if (compareResult == 0)
|
||||
{
|
||||
compareResult = Integer.compare(
|
||||
minDistance(first, posX, posZ),
|
||||
minDistance(second, posX, posZ));
|
||||
compareResult = compareDistance(
|
||||
firstDistance,
|
||||
secondDistance);
|
||||
// System.out.println("Equal level "+ firstDistance + " " + secondDistance + " " + compareResult);
|
||||
}
|
||||
return compareResult;
|
||||
}
|
||||
@@ -223,4 +246,8 @@ public class LevelPosUtil
|
||||
{
|
||||
return (getDetailLevel(levelPos) + " " + getPosX(levelPos) + " " + getPosZ(levelPos));
|
||||
}
|
||||
public static String toString(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
return (detailLevel + " " + posX + " " + posZ);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,22 +19,17 @@ package com.seibel.lod.objects;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.handlers.LodDimensionFileHandler;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
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.client.Minecraft;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
@@ -67,8 +62,10 @@ public class LodDimension
|
||||
public volatile LodRegion regions[][];
|
||||
public volatile boolean isRegionDirty[][];
|
||||
public volatile boolean regen[][];
|
||||
/** if true that means there are regions in this dimension
|
||||
* that need to have their buffers rebuilt. */
|
||||
/**
|
||||
* if true that means there are regions in this dimension
|
||||
* that need to have their buffers rebuilt.
|
||||
*/
|
||||
public volatile boolean regenDimension = false;
|
||||
|
||||
private volatile RegionPos center;
|
||||
@@ -89,7 +86,7 @@ public class LodDimension
|
||||
dimension = newDimension;
|
||||
width = newWidth;
|
||||
halfWidth = (int) Math.floor(width / 2);
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
|
||||
if (newDimension != null && lodWorld != null)
|
||||
{
|
||||
try
|
||||
@@ -110,8 +107,8 @@ public class LodDimension
|
||||
{
|
||||
// connected to server
|
||||
|
||||
saveDir = new File(mc.gameDirectory.getCanonicalFile().getPath() +
|
||||
File.separatorChar + "lod server data" + File.separatorChar + LodUtil.getDimensionIDFromWorld(mc.level));
|
||||
saveDir = new File(mc.getGameDirectory().getCanonicalFile().getPath() +
|
||||
File.separatorChar + "lod server data" + File.separatorChar + mc.getCurrentDimensionId());
|
||||
}
|
||||
|
||||
fileHandler = new LodDimensionFileHandler(saveDir, this);
|
||||
@@ -243,8 +240,6 @@ public class LodDimension
|
||||
*/
|
||||
public int getMinMemoryNeeded()
|
||||
{
|
||||
int regionX;
|
||||
int regionZ;
|
||||
int count = 0;
|
||||
LodRegion region;
|
||||
|
||||
@@ -262,25 +257,29 @@ public class LodDimension
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the region at the given X and Z
|
||||
* <br>
|
||||
* Returns null if the region doesn't exist
|
||||
* or is outside the loaded area.
|
||||
*/
|
||||
public LodRegion getRegion(LevelPos levelPos)
|
||||
public LodRegion getRegion(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
int xRegion = LevelPosUtil.getRegion(detailLevel, posX);
|
||||
int zRegion = LevelPosUtil.getRegion(detailLevel, posZ);
|
||||
int xIndex = (xRegion - center.x) + halfWidth;
|
||||
int zIndex = (zRegion - center.z) + halfWidth;
|
||||
|
||||
RegionPos regionPos = levelPos.getRegionPos();
|
||||
int xIndex = (regionPos.x - center.x) + halfWidth;
|
||||
int zIndex = (regionPos.z - center.z) + halfWidth;
|
||||
|
||||
if (!regionIsInRange(regionPos.x, regionPos.z))
|
||||
throw new ArrayIndexOutOfBoundsException("Region for level pos " + levelPos + " out of range");
|
||||
if (!regionIsInRange(xRegion, zRegion))
|
||||
return null;
|
||||
//throw new ArrayIndexOutOfBoundsException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " out of range");
|
||||
else if (regions[xIndex][zIndex] == null)
|
||||
throw new InvalidParameterException("Region for level pos " + levelPos + " not currently initialized");
|
||||
else if (regions[xIndex][zIndex].getMinDetailLevel() > levelPos.detailLevel)
|
||||
throw new InvalidParameterException("Region for level pos " + levelPos + " currently only reach level " + regions[xIndex][zIndex].getMinDetailLevel());
|
||||
return null;
|
||||
//throw new InvalidParameterException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " not currently initialized");
|
||||
else if (regions[xIndex][zIndex].getMinDetailLevel() > detailLevel)
|
||||
return null;
|
||||
//throw new InvalidParameterException("Region for level pos " + LevelPosUtil.toString(detailLevel, posX, posZ) + " currently only reach level " + regions[xIndex][zIndex].getMinDetailLevel());
|
||||
return regions[xIndex][zIndex];
|
||||
}
|
||||
|
||||
@@ -290,15 +289,17 @@ public class LodDimension
|
||||
* Returns null if the region doesn't exist
|
||||
* or is outside the loaded area.
|
||||
*/
|
||||
public LodRegion getRegion(RegionPos regionPos)
|
||||
public LodRegion getRegion(int regionPosX, int regionPosZ)
|
||||
{
|
||||
int xIndex = (regionPos.x - center.x) + halfWidth;
|
||||
int zIndex = (regionPos.z - center.z) + halfWidth;
|
||||
int xIndex = (regionPosX - center.x) + halfWidth;
|
||||
int zIndex = (regionPosZ - center.z) + halfWidth;
|
||||
|
||||
if (!regionIsInRange(regionPos.x, regionPos.z))
|
||||
throw new ArrayIndexOutOfBoundsException("Region " + regionPos + " out of range");
|
||||
if (!regionIsInRange(regionPosX, regionPosZ))
|
||||
return null;
|
||||
//throw new ArrayIndexOutOfBoundsException("Region " + regionPosX + " " + regionPosZ + " out of range");
|
||||
else if (regions[xIndex][zIndex] == null)
|
||||
throw new InvalidParameterException("Region " + regionPos + " not currently initialized");
|
||||
return null;
|
||||
//throw new InvalidParameterException("Region " + regionPosX + " " + regionPosZ + " not currently initialized");
|
||||
return regions[xIndex][zIndex];
|
||||
}
|
||||
|
||||
@@ -310,7 +311,7 @@ public class LodDimension
|
||||
public synchronized void addOrOverwriteRegion(LodRegion newRegion) throws ArrayIndexOutOfBoundsException
|
||||
{
|
||||
int xIndex = (newRegion.regionPosX - center.x) + halfWidth;
|
||||
int zIndex = (center.z - newRegion.regionPosZ) + halfWidth;
|
||||
int zIndex = (newRegion.regionPosZ - center.z) + halfWidth;
|
||||
|
||||
if (!regionIsInRange(newRegion.regionPosX, newRegion.regionPosZ))
|
||||
// out of range
|
||||
@@ -325,7 +326,7 @@ public class LodDimension
|
||||
*/
|
||||
public void treeCutter(int playerPosX, int playerPosZ)
|
||||
{
|
||||
ChunkPos newPlayerChunk = (new LevelPos((byte) 0, playerPosX, playerPosZ)).getChunkPos();
|
||||
ChunkPos newPlayerChunk = new ChunkPos(LevelPosUtil.getChunkPos((byte) 0, playerPosX), LevelPosUtil.getChunkPos((byte) 0, playerPosZ));
|
||||
if (lastCutChunk == null)
|
||||
lastCutChunk = new ChunkPos(newPlayerChunk.x + 1, newPlayerChunk.z - 1);
|
||||
if (newPlayerChunk.x != lastCutChunk.x || newPlayerChunk.z != lastCutChunk.z)
|
||||
@@ -338,7 +339,6 @@ public class LodDimension
|
||||
int minDistance;
|
||||
byte detail;
|
||||
byte levelToCut;
|
||||
LevelPos levelPos = new LevelPos();
|
||||
|
||||
for (int x = 0; x < regions.length; x++)
|
||||
{
|
||||
@@ -351,8 +351,7 @@ public class LodDimension
|
||||
//if this is not the case w
|
||||
if (regions[x][z] != null)
|
||||
{
|
||||
levelPos.changeParameters(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ);
|
||||
minDistance = levelPos.minDistance(playerPosX, playerPosZ);
|
||||
minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ, playerPosX, playerPosZ);
|
||||
detail = DetailDistanceUtil.getDistanceTreeCutInverse(minDistance);
|
||||
levelToCut = DetailDistanceUtil.getCutLodDetail(detail);
|
||||
if (regions[x][z].getMinDetailLevel() > levelToCut)
|
||||
@@ -375,7 +374,7 @@ public class LodDimension
|
||||
public void treeGenerator(int playerPosX, int playerPosZ)
|
||||
{
|
||||
DistanceGenerationMode generationMode = LodConfig.CLIENT.worldGenerator.distanceGenerationMode.get();
|
||||
ChunkPos newPlayerChunk = (new LevelPos((byte) 0, playerPosX, playerPosZ)).getChunkPos();
|
||||
ChunkPos newPlayerChunk = new ChunkPos(LevelPosUtil.getChunkPos((byte) 0, playerPosX), LevelPosUtil.getChunkPos((byte) 0, playerPosZ));
|
||||
|
||||
if (lastGenChunk == null)
|
||||
lastGenChunk = new ChunkPos(newPlayerChunk.x + 1, newPlayerChunk.z - 1);
|
||||
@@ -390,20 +389,17 @@ public class LodDimension
|
||||
int minDistance;
|
||||
byte detail;
|
||||
byte levelToGen;
|
||||
LevelPos levelPos = new LevelPos();
|
||||
for (int x = 0; x < regions.length; x++)
|
||||
{
|
||||
for (int z = 0; z < regions.length; z++)
|
||||
{
|
||||
regionX = (x + center.x) - halfWidth;
|
||||
regionZ = (z + center.z) - halfWidth;
|
||||
levelPos.changeParameters(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ);
|
||||
final RegionPos regionPos = new RegionPos(regionX, regionZ);
|
||||
region = regions[x][z];
|
||||
//We require that the region we are checking is loaded with at least this level
|
||||
|
||||
levelPos.changeParameters(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ);
|
||||
minDistance = levelPos.minDistance(playerPosX, playerPosZ);
|
||||
minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ, playerPosX, playerPosZ);
|
||||
detail = DetailDistanceUtil.getDistanceTreeGenInverse(minDistance);
|
||||
levelToGen = DetailDistanceUtil.getLodGenDetail(detail).detailLevel;
|
||||
if (region == null || region.getGenerationMode() != generationMode)
|
||||
@@ -439,32 +435,31 @@ public class LodDimension
|
||||
* stored in the LOD. If an LOD already exists at the given
|
||||
* coordinates it will be overwritten.
|
||||
*/
|
||||
public synchronized Boolean addData(LevelPos levelPos, short[] lodDataPoint, boolean dontSave, boolean serverQuality)
|
||||
public synchronized Boolean addData(byte detailLevel, int posX, int posZ, long lodDataPoint, boolean dontSave, boolean serverQuality)
|
||||
{
|
||||
|
||||
// don't continue if the region can't be saved
|
||||
RegionPos regionPos = levelPos.getRegionPos();
|
||||
if (!regionIsInRange(regionPos.x, regionPos.z))
|
||||
{
|
||||
int regionPosX = LevelPosUtil.getRegion(detailLevel, posX);
|
||||
int regionPosZ = LevelPosUtil.getRegion(detailLevel, posZ);
|
||||
|
||||
LodRegion region = getRegion(regionPosX, regionPosZ);
|
||||
if (region == null)
|
||||
return false;
|
||||
}
|
||||
|
||||
LodRegion region = getRegion(levelPos);
|
||||
|
||||
boolean nodeAdded = region.addData(levelPos, lodDataPoint, serverQuality);
|
||||
boolean nodeAdded = region.addData(detailLevel, posX, posZ, lodDataPoint, serverQuality);
|
||||
// only save valid LODs to disk
|
||||
if (!dontSave && fileHandler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// mark the region as dirty so it will be saved to disk
|
||||
int xIndex = (regionPos.x - center.x) + halfWidth;
|
||||
int zIndex = (regionPos.z - center.z) + halfWidth;
|
||||
int xIndex = (regionPosX - center.x) + halfWidth;
|
||||
int zIndex = (regionPosZ - center.z) + halfWidth;
|
||||
isRegionDirty[xIndex][zIndex] = true;
|
||||
regen[xIndex][zIndex] = true;
|
||||
regenDimension = true;
|
||||
} catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
// This method was probably called when the dimension was changing size.
|
||||
// Hopefully this shouldn't be an issue.
|
||||
}
|
||||
@@ -472,7 +467,8 @@ public class LodDimension
|
||||
return nodeAdded;
|
||||
}
|
||||
|
||||
public void setToRegen(int xRegion, int zRegion){
|
||||
public void setToRegen(int xRegion, int zRegion)
|
||||
{
|
||||
int xIndex = (xRegion - center.x) + halfWidth;
|
||||
int zIndex = (zRegion - center.z) + halfWidth;
|
||||
regen[xIndex][zIndex] = true;
|
||||
@@ -483,32 +479,26 @@ public class LodDimension
|
||||
*
|
||||
* @return list of quadTrees
|
||||
*/
|
||||
public void getDataToGenerate(ConcurrentMap<LevelPos, MutableBoolean> dataToGenerate, int playerPosX, int playerPosZ)
|
||||
public PosToGenerateContainer getDataToGenerate(byte farDetail, int maxDataToGenerate, double farRatio, int playerPosX, int playerPosZ)
|
||||
{
|
||||
|
||||
PosToGenerateContainer posToGenerate = new PosToGenerateContainer(farDetail, maxDataToGenerate, (int) (maxDataToGenerate * farRatio), playerPosX, playerPosZ);
|
||||
int n = regions.length;
|
||||
int xIndex;
|
||||
int zIndex;
|
||||
LodRegion region;
|
||||
RegionPos regionPos;
|
||||
for (int xRegion = 0; xRegion < n; xRegion++)
|
||||
{
|
||||
for (int zRegion = 0; zRegion < n; zRegion++)
|
||||
{
|
||||
try
|
||||
{
|
||||
xIndex = (xRegion + center.x) - halfWidth;
|
||||
zIndex = (zRegion + center.z) - halfWidth;
|
||||
regionPos = new RegionPos(xIndex, zIndex);
|
||||
region = getRegion(regionPos);
|
||||
region.getDataToGenerate(dataToGenerate, playerPosX, playerPosZ);
|
||||
xIndex = (xRegion + center.x) - halfWidth;
|
||||
zIndex = (zRegion + center.z) - halfWidth;
|
||||
region = getRegion(xIndex, zIndex);
|
||||
if (region != null)
|
||||
region.getDataToGenerate(posToGenerate, playerPosX, playerPosZ);
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return posToGenerate;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -516,33 +506,11 @@ public class LodDimension
|
||||
*
|
||||
* @return list of nodes
|
||||
*/
|
||||
public void getDataToRender(ConcurrentMap<LevelPos, MutableBoolean> dataToRender, RegionPos regionPos, int playerPosX, int playerPosZ)
|
||||
public void getDataToRender(PosToRenderContainer posToRender, RegionPos regionPos, int playerPosX, int playerPosZ)
|
||||
{
|
||||
try
|
||||
{
|
||||
LodRegion region = getRegion(regionPos);
|
||||
region.getDataToRender(dataToRender, playerPosX, playerPosZ);
|
||||
} catch (NullPointerException e)
|
||||
{
|
||||
System.out.println(regionPos);
|
||||
e.printStackTrace();
|
||||
} catch (Exception e)
|
||||
{
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the LodNodeData at the given X and Z coordinates
|
||||
* in this dimension.
|
||||
* <br>
|
||||
* Returns null if the LodChunk doesn't exist or
|
||||
* is outside the loaded area.
|
||||
*/
|
||||
public short[] getData(ChunkPos chunkPos)
|
||||
{
|
||||
LevelPos levelPos = new LevelPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, chunkPos.z);
|
||||
return getData(levelPos);
|
||||
LodRegion region = getRegion(regionPos.x, regionPos.z);
|
||||
if (region != null)
|
||||
region.getDataToRender(posToRender, playerPosX, playerPosZ);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -552,26 +520,19 @@ public class LodDimension
|
||||
* Returns null if the LodChunk doesn't exist or
|
||||
* is outside the loaded area.
|
||||
*/
|
||||
public short[] getData(LevelPos levelPos)
|
||||
public long getData(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
if (levelPos.detailLevel > LodUtil.REGION_DETAIL_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + levelPos.detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
|
||||
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
|
||||
|
||||
try
|
||||
LodRegion region = getRegion(detailLevel, posX, posZ);
|
||||
|
||||
if (region == null)
|
||||
{
|
||||
LodRegion region = getRegion(levelPos);
|
||||
|
||||
if (region == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return region.getData(levelPos);
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return region.getData(detailLevel, posX, posZ);
|
||||
}
|
||||
|
||||
|
||||
@@ -582,40 +543,34 @@ public class LodDimension
|
||||
* Returns null if the LodChunk doesn't exist or
|
||||
* is outside the loaded area.
|
||||
*/
|
||||
public void updateData(LevelPos levelPos)
|
||||
public void updateData(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
if (levelPos.detailLevel > LodUtil.REGION_DETAIL_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + levelPos.detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
|
||||
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
|
||||
|
||||
LodRegion region = getRegion(levelPos);
|
||||
LodRegion region = getRegion(detailLevel, posX, posZ);
|
||||
|
||||
|
||||
if (region == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
region.updateArea(levelPos);
|
||||
region.updateArea(detailLevel, posX, posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if and only if the node at that position exist
|
||||
*/
|
||||
public boolean doesDataExist(LevelPos levelPos)
|
||||
public boolean doesDataExist(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
try
|
||||
{
|
||||
LodRegion region = getRegion(levelPos);
|
||||
LodRegion region = getRegion(detailLevel, posX, posZ);
|
||||
|
||||
if (region == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return region.doesDataExist(levelPos.clone());
|
||||
} catch (Exception e)
|
||||
if (region == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return region.doesDataExist(detailLevel, posX, posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -696,9 +651,6 @@ public class LodDimension
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
int regionX;
|
||||
int regionZ;
|
||||
LevelPos levelPos;
|
||||
LodRegion region;
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
@@ -721,7 +673,6 @@ public class LodDimension
|
||||
}
|
||||
stringBuilder.append("\n");
|
||||
}
|
||||
System.out.println(stringBuilder);
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
|
||||
import com.seibel.lod.builders.LodBuilder;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
@@ -20,24 +14,19 @@ import com.seibel.lod.util.LodUtil;
|
||||
* 0 for x, 1 for y, 2 for z in 3D
|
||||
*/
|
||||
|
||||
public class LodRegion implements Serializable
|
||||
public class LodRegion
|
||||
{
|
||||
//x coord,
|
||||
private byte minDetailLevel;
|
||||
private static final byte POSSIBLE_LOD = 10;
|
||||
private int numberOfPoints;
|
||||
//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 byte[][][][] colors;
|
||||
|
||||
private short[][][] height;
|
||||
|
||||
private short[][][] depth;
|
||||
|
||||
private boolean[][][] dataExistence;
|
||||
private long[][][] data;
|
||||
|
||||
|
||||
public final int regionPosX;
|
||||
@@ -50,42 +39,18 @@ public class LodRegion implements Serializable
|
||||
this.regionPosZ = regionPos.z;
|
||||
this.minDetailLevel = levelContainer.detailLevel;
|
||||
|
||||
//Array of matrices of arrays
|
||||
colors = new byte[POSSIBLE_LOD][][][];
|
||||
|
||||
//Arrays of matrices
|
||||
height = new short[POSSIBLE_LOD][][];
|
||||
depth = new short[POSSIBLE_LOD][][];
|
||||
dataExistence = new boolean[POSSIBLE_LOD][][];
|
||||
data = new long[POSSIBLE_LOD][][];
|
||||
|
||||
colors[minDetailLevel] = levelContainer.colors;
|
||||
height[minDetailLevel] = levelContainer.height;
|
||||
depth[minDetailLevel] = levelContainer.depth;
|
||||
dataExistence[minDetailLevel] = levelContainer.dataExistence;
|
||||
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);
|
||||
colors[lod] = new byte[size][size][3];
|
||||
height[lod] = new short[size][size];
|
||||
depth[lod] = new short[size][size];
|
||||
dataExistence[lod] = new boolean[size][size];
|
||||
}
|
||||
int width;
|
||||
LevelPos levelPos = new LevelPos();
|
||||
for (byte tempLod = (byte) (minDetailLevel + 1); tempLod <= LodUtil.REGION_DETAIL_LEVEL; tempLod++)
|
||||
{
|
||||
width = 1 << (LodUtil.REGION_DETAIL_LEVEL - tempLod);
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
for (int z = 0; z < width; z++)
|
||||
{
|
||||
levelPos.changeParameters(tempLod, x, z);
|
||||
update(levelPos);
|
||||
}
|
||||
}
|
||||
data[lod] = new long[size][size];
|
||||
}
|
||||
updateArea(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ);
|
||||
}
|
||||
|
||||
public LodRegion(byte minDetailLevel, RegionPos regionPos, DistanceGenerationMode generationMode)
|
||||
@@ -95,23 +60,14 @@ public class LodRegion implements Serializable
|
||||
this.regionPosX = regionPos.x;
|
||||
this.regionPosZ = regionPos.z;
|
||||
|
||||
//Array of matrices of arrays
|
||||
colors = new byte[POSSIBLE_LOD][][][];
|
||||
|
||||
//Arrays of matrices
|
||||
height = new short[POSSIBLE_LOD][][];
|
||||
depth = new short[POSSIBLE_LOD][][];
|
||||
dataExistence = new boolean[POSSIBLE_LOD][][];
|
||||
data = new long[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);
|
||||
colors[lod] = new byte[size][size][3];
|
||||
height[lod] = new short[size][size];
|
||||
depth[lod] = new short[size][size];
|
||||
dataExistence[lod] = new boolean[size][size];
|
||||
data[lod] = new long[size][size];
|
||||
|
||||
}
|
||||
}
|
||||
@@ -119,26 +75,21 @@ public class LodRegion implements Serializable
|
||||
/**
|
||||
* This method can be used to insert data into the LodRegion
|
||||
*
|
||||
* @param levelPos
|
||||
* @param dataPoint
|
||||
* @return
|
||||
*/
|
||||
public boolean addData(LevelPos levelPos, short[] dataPoint, boolean serverQuality)
|
||||
public boolean addData(byte detailLevel, int posX, int posZ, long dataPoint, boolean serverQuality)
|
||||
{
|
||||
levelPos.performRegionModule();
|
||||
if (!doesDataExist(levelPos) || serverQuality)
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
if (!doesDataExist(detailLevel, posX, posZ) || serverQuality)
|
||||
{
|
||||
|
||||
//update the number of node present
|
||||
if (this.dataExistence[levelPos.detailLevel][levelPos.posX][levelPos.posZ]) numberOfPoints++;
|
||||
//if (!doesDataExist(detailLevel, posX, posZ)) numberOfPoints++;
|
||||
|
||||
//add the node data
|
||||
this.height[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = DataPoint.getHeight(dataPoint);
|
||||
this.depth[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = DataPoint.getDepth(dataPoint);
|
||||
this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][0] = (byte) (DataPoint.getRed(dataPoint) - 128);
|
||||
this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][1] = (byte) (DataPoint.getGreen(dataPoint) - 128);
|
||||
this.colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][2] = (byte) (DataPoint.getBlue(dataPoint) - 128);
|
||||
this.dataExistence[levelPos.detailLevel][levelPos.posX][levelPos.posZ] = true;
|
||||
this.data[detailLevel][posX][posZ] = dataPoint;
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
@@ -149,18 +100,13 @@ public class LodRegion implements Serializable
|
||||
/**
|
||||
* This method will return the data in the position relative to the level of detail
|
||||
*
|
||||
* @param levelPos
|
||||
* @return the data at the relative pos and level
|
||||
*/
|
||||
public short[] getData(LevelPos levelPos)
|
||||
public long getData(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
levelPos = levelPos.getRegionModuleLevelPos();
|
||||
return new short[]{height[levelPos.detailLevel][levelPos.posX][levelPos.posZ],
|
||||
depth[levelPos.detailLevel][levelPos.posX][levelPos.posZ],
|
||||
(short) (colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][0] + 128),
|
||||
(short) (colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][1] + 128),
|
||||
(short) (colors[levelPos.detailLevel][levelPos.posX][levelPos.posZ][2] + 128)
|
||||
};
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return data[detailLevel][posX][posZ];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,25 +114,21 @@ public class LodRegion implements Serializable
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public void getDataToGenerate(ConcurrentMap<LevelPos, MutableBoolean> dataToGenerate, int playerPosX, int playerPosZ)
|
||||
public void getDataToGenerate(PosToGenerateContainer posToGenerate, int playerPosX, int playerPosZ)
|
||||
{
|
||||
LevelPos levelPos = new LevelPos(LodUtil.REGION_DETAIL_LEVEL, 0, 0);
|
||||
getDataToGenerate(dataToGenerate, levelPos, playerPosX, playerPosZ);
|
||||
getDataToGenerate(posToGenerate, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ);
|
||||
|
||||
}
|
||||
|
||||
private void getDataToGenerate(ConcurrentMap<LevelPos, MutableBoolean> dataToGenerate, LevelPos levelPos, int playerPosX, int playerPosZ)
|
||||
private void getDataToGenerate(PosToGenerateContainer posToGenerate, byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ)
|
||||
{
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - levelPos.detailLevel);
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
|
||||
//here i calculate the the LevelPos is in range
|
||||
//This is important to avoid any kind of hole in the generation
|
||||
int minDistance = levelPos.minDistance(playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
//nt minDistance = LevelPosUtil.minDistance(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size, playerPosX, playerPosZ);
|
||||
int maxDistance = LevelPosUtil.maxDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
|
||||
|
||||
int posX = levelPos.posX;
|
||||
int posZ = levelPos.posZ;
|
||||
byte detailLevel = levelPos.detailLevel;
|
||||
byte childDetailLevel = (byte) (detailLevel - 1);
|
||||
int childPosX = posX * 2;
|
||||
int childPosZ = posZ * 2;
|
||||
@@ -194,21 +136,14 @@ public class LodRegion implements Serializable
|
||||
int childSize = 1 << (LodUtil.REGION_DETAIL_LEVEL - childDetailLevel);
|
||||
//we have reached the target detail level
|
||||
|
||||
if (DetailDistanceUtil.getDistanceGenerationInverse(minDistance) > detailLevel)
|
||||
if (DetailDistanceUtil.getDistanceGenerationInverse(maxDistance) > detailLevel)
|
||||
{
|
||||
return;
|
||||
} else if (DetailDistanceUtil.getDistanceGenerationInverse(minDistance) == detailLevel)
|
||||
} else if (DetailDistanceUtil.getDistanceGenerationInverse(maxDistance) == detailLevel)
|
||||
{
|
||||
if (!doesDataExist(levelPos))
|
||||
if (!doesDataExist(detailLevel, posX, posZ))
|
||||
{
|
||||
levelPos.changeParameters(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size);
|
||||
if (dataToGenerate.containsKey(levelPos))
|
||||
{
|
||||
dataToGenerate.get(levelPos).setTrue();
|
||||
} else
|
||||
{
|
||||
dataToGenerate.put(levelPos.clone(), new MutableBoolean(true));
|
||||
}
|
||||
posToGenerate.addPosToGenerate(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size);
|
||||
}
|
||||
} else
|
||||
{
|
||||
@@ -221,19 +156,11 @@ public class LodRegion implements Serializable
|
||||
{
|
||||
for (int z = 0; z <= 1; z++)
|
||||
{
|
||||
levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x, childPosZ + z);
|
||||
|
||||
if (!doesDataExist(levelPos))
|
||||
if (!doesDataExist(childDetailLevel, childPosX + x, childPosZ + z))
|
||||
{
|
||||
num++;
|
||||
levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x + regionPosX * childSize, childPosZ + z + regionPosZ * childSize);
|
||||
if (dataToGenerate.containsKey(levelPos))
|
||||
{
|
||||
dataToGenerate.get(levelPos).setTrue();
|
||||
} else
|
||||
{
|
||||
dataToGenerate.put(levelPos.clone(), new MutableBoolean(true));
|
||||
}
|
||||
posToGenerate.addPosToGenerate(childDetailLevel, childPosX + x + regionPosX * childSize, childPosZ + z + regionPosZ * childSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,8 +172,7 @@ public class LodRegion implements Serializable
|
||||
{
|
||||
for (int z = 0; z <= 1; z++)
|
||||
{
|
||||
levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x, childPosZ + z);
|
||||
getDataToGenerate(dataToGenerate, levelPos, playerPosX, playerPosZ);
|
||||
getDataToGenerate(posToGenerate, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -255,21 +181,12 @@ public class LodRegion implements Serializable
|
||||
{
|
||||
if (DetailDistanceUtil.getLodGenDetail(childDetailLevel).detailLevel <= (childDetailLevel))
|
||||
{
|
||||
levelPos.changeParameters(detailLevel, posX, posZ);
|
||||
levelPos.convert(childDetailLevel);
|
||||
if (!doesDataExist(levelPos))
|
||||
if (!doesDataExist(childDetailLevel, childPosX, childPosZ))
|
||||
{
|
||||
levelPos.changeParameters(levelPos.detailLevel, levelPos.posX + regionPosX * childSize, levelPos.posZ + regionPosZ * childSize);
|
||||
if (dataToGenerate.containsKey(levelPos))
|
||||
{
|
||||
dataToGenerate.get(levelPos).setTrue();
|
||||
} else
|
||||
{
|
||||
dataToGenerate.put(levelPos.clone(), new MutableBoolean(true));
|
||||
}
|
||||
posToGenerate.addPosToGenerate(childDetailLevel, childPosX + regionPosX * childSize, childPosZ + regionPosZ * childSize);
|
||||
} else
|
||||
{
|
||||
getDataToGenerate(dataToGenerate, levelPos, playerPosX, playerPosZ);
|
||||
getDataToGenerate(posToGenerate, childDetailLevel, childPosX, childPosZ, playerPosX, playerPosZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,60 +197,41 @@ public class LodRegion implements Serializable
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public void getDataToRender(ConcurrentMap<LevelPos, MutableBoolean> dataToRender, int playerPosX, int playerPosZ)
|
||||
public void getDataToRender(PosToRenderContainer posToRender, int playerPosX, int playerPosZ)
|
||||
{
|
||||
LevelPos levelPos = new LevelPos(LodUtil.REGION_DETAIL_LEVEL, 0, 0);
|
||||
getDataToRender(dataToRender, levelPos, playerPosX, playerPosZ);
|
||||
getDataToRender(posToRender, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
private void getDataToRender(ConcurrentMap<LevelPos, MutableBoolean> dataToRender, LevelPos levelPos, int playerPosX, int playerPosZ)
|
||||
private void getDataToRender(PosToRenderContainer posToRender, byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ)
|
||||
{
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - levelPos.detailLevel);
|
||||
|
||||
int posX = levelPos.posX;
|
||||
int posZ = levelPos.posZ;
|
||||
byte detailLevel = levelPos.detailLevel;
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
|
||||
//here i calculate the the LevelPos is in range
|
||||
//This is important to avoid any kind of hole in the rendering
|
||||
int maxDistance = levelPos.maxDistance(playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
int maxDistance = LevelPosUtil.maxDistance(detailLevel, posX, posZ, playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
|
||||
byte supposedLevel = DetailDistanceUtil.getLodDrawDetail(DetailDistanceUtil.getDistanceRenderingInverse(maxDistance));
|
||||
if (supposedLevel > detailLevel)
|
||||
return;
|
||||
else if (supposedLevel == detailLevel)
|
||||
{
|
||||
if (dataToRender.containsKey(levelPos))
|
||||
{
|
||||
levelPos.changeParameters(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size);
|
||||
try
|
||||
{
|
||||
dataToRender.get(levelPos).setTrue();
|
||||
}catch (Exception e){
|
||||
/*TODO Fix this exception*/
|
||||
// This seems to happen more often when using an elytra in an amplified world
|
||||
// maybe it has something to do with the dimensions moving?
|
||||
ClientProxy.LOGGER.error("getDataToRender had a error at " + levelPos.getRegionPos() + ". Exception: " + e.getMessage());
|
||||
dataToRender.put(new LevelPos(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size), new MutableBoolean(true));
|
||||
}
|
||||
} else
|
||||
{
|
||||
dataToRender.put(new LevelPos(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size), new MutableBoolean(true));
|
||||
}
|
||||
posToRender.addPosToRender(detailLevel,
|
||||
posX + regionPosX * size,
|
||||
posZ + regionPosZ * size);
|
||||
} else //case where (detailLevel > supposedLevel)
|
||||
{
|
||||
int childPosX = posX * 2;
|
||||
int childPosZ = posZ * 2;
|
||||
byte childDetailLevel = (byte) (detailLevel - 1);
|
||||
int childrenCount = 0;
|
||||
for (int x = 0; x <= 1; x++)
|
||||
{
|
||||
for (int z = 0; z <= 1; z++)
|
||||
{
|
||||
levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x, childPosZ + z);
|
||||
if (doesDataExist(levelPos)) childrenCount++;
|
||||
if (doesDataExist(childDetailLevel, childPosX + x, childPosZ + z)) childrenCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,68 +242,50 @@ public class LodRegion implements Serializable
|
||||
{
|
||||
for (int z = 0; z <= 1; z++)
|
||||
{
|
||||
levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x, childPosZ + z);
|
||||
getDataToRender(dataToRender, levelPos, playerPosX, playerPosZ);
|
||||
getDataToRender(posToRender, childDetailLevel, childPosX + x, childPosZ + z, playerPosX, playerPosZ);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
|
||||
levelPos.changeParameters(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size);
|
||||
if (dataToRender.containsKey(levelPos))
|
||||
{
|
||||
if (dataToRender.get(levelPos) == null)
|
||||
dataToRender.replace(levelPos, new MutableBoolean());
|
||||
dataToRender.get(levelPos).setTrue();
|
||||
} else
|
||||
{
|
||||
dataToRender.put(new LevelPos(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size), new MutableBoolean(true));
|
||||
}
|
||||
posToRender.addPosToRender(detailLevel,
|
||||
posX + regionPosX * size,
|
||||
posZ + regionPosZ * size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param levelPos
|
||||
*/
|
||||
public void updateArea(LevelPos levelPos)
|
||||
public void updateArea(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
int width;
|
||||
int startX;
|
||||
int startZ;
|
||||
byte detailLevel = levelPos.detailLevel;
|
||||
int posX = levelPos.posX;
|
||||
int posZ = levelPos.posZ;
|
||||
for (byte bottom = (byte) (minDetailLevel + 1); bottom <= detailLevel; bottom++)
|
||||
{
|
||||
levelPos.convert(bottom);
|
||||
startX = levelPos.posX;
|
||||
startZ = levelPos.posZ;
|
||||
startX = LevelPosUtil.convert(detailLevel, posX, bottom);
|
||||
startZ = LevelPosUtil.convert(detailLevel, posZ, bottom);
|
||||
width = 1 << (detailLevel - bottom);
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
for (int z = 0; z < width; z++)
|
||||
{
|
||||
levelPos.changeParameters(bottom, startX + x, startZ + z);
|
||||
update(levelPos);
|
||||
update(bottom, startX + x, startZ + z);
|
||||
}
|
||||
}
|
||||
levelPos.changeParameters(detailLevel, posX, posZ);
|
||||
}
|
||||
for (byte tempLod = (byte) (detailLevel + 1); tempLod <= LodUtil.REGION_DETAIL_LEVEL; tempLod++)
|
||||
for (byte up = (byte) (detailLevel + 1); up <= LodUtil.REGION_DETAIL_LEVEL; up++)
|
||||
{
|
||||
levelPos.convert(tempLod);
|
||||
update(levelPos);
|
||||
update(up,
|
||||
LevelPosUtil.convert(detailLevel, posX, up),
|
||||
LevelPosUtil.convert(detailLevel, posZ, up));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param levelPos
|
||||
*/
|
||||
private void update(LevelPos levelPos)
|
||||
private void update(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
levelPos.performRegionModule();
|
||||
int numberOfChildren = 0;
|
||||
int numberOfVoidChildren = 0;
|
||||
|
||||
@@ -414,32 +294,30 @@ public class LodRegion implements Serializable
|
||||
int tempBlue = 0;
|
||||
int tempHeight = 0;
|
||||
int tempDepth = 0;
|
||||
int newPosX;
|
||||
int newPosZ;
|
||||
byte newDetailLevel;
|
||||
int detailLevel = levelPos.detailLevel;
|
||||
int posX = levelPos.posX;
|
||||
int posZ = levelPos.posZ;
|
||||
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++)
|
||||
{
|
||||
newPosX = 2 * posX + x;
|
||||
newPosZ = 2 * posZ + z;
|
||||
newDetailLevel = (byte) (detailLevel - 1);
|
||||
levelPos.changeParameters(newDetailLevel, newPosX, newPosZ);
|
||||
if (doesDataExist(levelPos))
|
||||
childPosX = 2 * posX + x;
|
||||
childPosZ = 2 * posZ + z;
|
||||
childDetailLevel = (byte) (detailLevel - 1);
|
||||
if (doesDataExist(childDetailLevel, childPosX, childPosZ))
|
||||
{
|
||||
if (height[newDetailLevel][newPosX][newPosZ] != LodBuilder.DEFAULT_HEIGHT
|
||||
&& depth[newDetailLevel][newPosX][newPosZ] != LodBuilder.DEFAULT_DEPTH)
|
||||
if (!(DataPoint.getHeight(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_HEIGHT
|
||||
&& DataPoint.getDepth(data[childDetailLevel][childPosX][childPosZ]) == LodBuilder.DEFAULT_DEPTH))
|
||||
{
|
||||
numberOfChildren++;
|
||||
|
||||
tempRed += colors[newDetailLevel][newPosX][newPosZ][0];
|
||||
tempGreen += colors[newDetailLevel][newPosX][newPosZ][1];
|
||||
tempBlue += colors[newDetailLevel][newPosX][newPosZ][2];
|
||||
tempHeight += height[newDetailLevel][newPosX][newPosZ];
|
||||
tempDepth += depth[newDetailLevel][newPosX][newPosZ];
|
||||
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)
|
||||
@@ -449,42 +327,34 @@ public class LodRegion implements Serializable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numberOfChildren > 0)
|
||||
{
|
||||
colors[detailLevel][posX][posZ][0] = (byte) (tempRed / numberOfChildren);
|
||||
colors[detailLevel][posX][posZ][1] = (byte) (tempGreen / numberOfChildren);
|
||||
colors[detailLevel][posX][posZ][2] = (byte) (tempBlue / numberOfChildren);
|
||||
height[detailLevel][posX][posZ] = (short) (tempHeight / numberOfChildren);
|
||||
depth[detailLevel][posX][posZ] = (short) (tempDepth / numberOfChildren);
|
||||
dataExistence[detailLevel][posX][posZ] = true;
|
||||
tempRed = tempRed / numberOfChildren;
|
||||
tempGreen = tempGreen / numberOfChildren;
|
||||
tempBlue = tempBlue / numberOfChildren;
|
||||
tempHeight = tempHeight / numberOfChildren;
|
||||
tempDepth = tempDepth / numberOfChildren;
|
||||
} else if (numberOfVoidChildren > 0)
|
||||
{
|
||||
colors[detailLevel][posX][posZ][0] = (byte) 0;
|
||||
colors[detailLevel][posX][posZ][1] = (byte) 0;
|
||||
colors[detailLevel][posX][posZ][2] = (byte) 0;
|
||||
|
||||
height[detailLevel][posX][posZ] = LodBuilder.DEFAULT_HEIGHT;
|
||||
depth[detailLevel][posX][posZ] = LodBuilder.DEFAULT_DEPTH;
|
||||
|
||||
dataExistence[detailLevel][posX][posZ] = true;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param levelPos
|
||||
* @return
|
||||
*/
|
||||
public boolean doesDataExist(LevelPos levelPos)
|
||||
public boolean doesDataExist(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
try
|
||||
{
|
||||
levelPos = levelPos.getRegionModuleLevelPos();
|
||||
return dataExistence[levelPos.detailLevel][levelPos.posX][levelPos.posZ];
|
||||
} catch (NullPointerException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(detailLevel < minDetailLevel) return false;
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return DataPoint.doesItExist(data[detailLevel][posX][posZ]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -512,7 +382,7 @@ public class LodRegion implements Serializable
|
||||
{
|
||||
throw new IllegalArgumentException("getLevel asked for a level that does not exist: minimum " + minDetailLevel + " level requested " + detailLevel);
|
||||
}
|
||||
return new LevelContainer(detailLevel, colors[detailLevel], height[detailLevel], depth[detailLevel], dataExistence[detailLevel]);
|
||||
return new LevelContainer(detailLevel, data[detailLevel]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,10 +395,7 @@ public class LodRegion implements Serializable
|
||||
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;
|
||||
colors[levelContainer.detailLevel] = levelContainer.colors;
|
||||
height[levelContainer.detailLevel] = levelContainer.height;
|
||||
depth[levelContainer.detailLevel] = levelContainer.depth;
|
||||
dataExistence[levelContainer.detailLevel] = levelContainer.dataExistence;
|
||||
data[levelContainer.detailLevel] = levelContainer.data;
|
||||
|
||||
}
|
||||
|
||||
@@ -541,10 +408,7 @@ public class LodRegion implements Serializable
|
||||
{
|
||||
for (byte tempLod = 0; tempLod < detailLevel; tempLod++)
|
||||
{
|
||||
colors[tempLod] = new byte[0][0][0];
|
||||
height[tempLod] = new short[0][0];
|
||||
depth[tempLod] = new short[0][0];
|
||||
dataExistence[tempLod] = new boolean[0][0];
|
||||
data[tempLod] = new long[0][0];
|
||||
}
|
||||
minDetailLevel = detailLevel;
|
||||
}
|
||||
@@ -560,10 +424,7 @@ public class LodRegion implements Serializable
|
||||
for (byte tempLod = detailLevel; tempLod < minDetailLevel; tempLod++)
|
||||
{
|
||||
int size = (short) Math.pow(2, LodUtil.REGION_DETAIL_LEVEL - tempLod);
|
||||
colors[tempLod] = new byte[size][size][3];
|
||||
height[tempLod] = new short[size][size];
|
||||
depth[tempLod] = new short[size][size];
|
||||
dataExistence[tempLod] = new boolean[size][size];
|
||||
data[tempLod] = new long[size][size];
|
||||
}
|
||||
minDetailLevel = detailLevel;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import org.lwjgl.system.CallbackI;
|
||||
|
||||
public class PosToGenerateContainer
|
||||
{
|
||||
private int playerPosX;
|
||||
@@ -27,20 +25,10 @@ public class PosToGenerateContainer
|
||||
posToGenerate = new int[maxDataToGenerate][4];
|
||||
}
|
||||
|
||||
public void addPosToGenerate(int[] levelPos)
|
||||
{
|
||||
addPosToGenerate(LevelPosUtil.getDetailLevel(levelPos), LevelPosUtil.getPosX(levelPos), LevelPosUtil.getPosZ(levelPos));
|
||||
}
|
||||
|
||||
public void addPosToGenerate(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
int distance = LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ);
|
||||
int index;
|
||||
int[] tempPos = new int[]{
|
||||
detailLevel,
|
||||
posX,
|
||||
posZ,
|
||||
distance};
|
||||
if (detailLevel >= farMinDetail)
|
||||
{//We are introducing a position in the far array
|
||||
if (farSize < maxFarSize)
|
||||
@@ -53,26 +41,42 @@ public class PosToGenerateContainer
|
||||
maxNearSize--;
|
||||
}
|
||||
index = posToGenerate.length - farSize;
|
||||
while (index < posToGenerate.length - 1 && LevelPosUtil.compareLevelAndDistance(tempPos, posToGenerate[index + 1]) <= 0)
|
||||
while (index < posToGenerate.length - 1 && LevelPosUtil.compareLevelAndDistance(detailLevel, distance, (byte) (posToGenerate[index + 1][0] - 1), posToGenerate[index + 1][3]) <= 0)
|
||||
{
|
||||
posToGenerate[index] = posToGenerate[index + 1];
|
||||
posToGenerate[index][0] = posToGenerate[index + 1][0];
|
||||
posToGenerate[index][1] = posToGenerate[index + 1][1];
|
||||
posToGenerate[index][2] = posToGenerate[index + 1][2];
|
||||
posToGenerate[index][3] = posToGenerate[index + 1][3];
|
||||
index++;
|
||||
}
|
||||
if (index <= posToGenerate.length - 1)
|
||||
posToGenerate[index] = tempPos;
|
||||
{
|
||||
posToGenerate[index][0] = detailLevel + 1;
|
||||
posToGenerate[index][1] = posX;
|
||||
posToGenerate[index][2] = posZ;
|
||||
posToGenerate[index][3] = distance;
|
||||
}
|
||||
} else
|
||||
{//We are introducing a position in the near array
|
||||
if (nearSize < maxNearSize)
|
||||
nearSize++;
|
||||
index = nearSize - 1;
|
||||
|
||||
while (index > 0 && LevelPosUtil.compareDistance(tempPos, posToGenerate[index - 1]) <= 0)
|
||||
while (index > 0 && LevelPosUtil.compareDistance(distance, posToGenerate[index - 1][3]) <= 0)
|
||||
{
|
||||
posToGenerate[index] = posToGenerate[index - 1];
|
||||
posToGenerate[index][0] = posToGenerate[index - 1][0];
|
||||
posToGenerate[index][1] = posToGenerate[index - 1][1];
|
||||
posToGenerate[index][2] = posToGenerate[index - 1][2];
|
||||
posToGenerate[index][3] = posToGenerate[index - 1][3];
|
||||
index--;
|
||||
}
|
||||
if (index >= 0)
|
||||
posToGenerate[index] = tempPos;
|
||||
{
|
||||
posToGenerate[index][0] = detailLevel + 1;
|
||||
posToGenerate[index][1] = posX;
|
||||
posToGenerate[index][2] = posZ;
|
||||
posToGenerate[index][3] = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +88,10 @@ public class PosToGenerateContainer
|
||||
|
||||
public int[] getNthPos(int n)
|
||||
{
|
||||
/*if(n < farSize)
|
||||
return posToGenerate[maxSize - n - 1];
|
||||
else
|
||||
return posToGenerate[n - farSize];*/
|
||||
int index;
|
||||
if (n > farSize * 2)
|
||||
index = n - farSize;
|
||||
@@ -111,7 +119,7 @@ public class PosToGenerateContainer
|
||||
builder.append('\n');
|
||||
for (int i = 0; i < nearSize; i++)
|
||||
{
|
||||
builder.append(posToGenerate[i][0]);
|
||||
builder.append(posToGenerate[i][0]-1);
|
||||
builder.append(" ");
|
||||
builder.append(posToGenerate[i][1]);
|
||||
builder.append(" ");
|
||||
@@ -125,7 +133,7 @@ public class PosToGenerateContainer
|
||||
builder.append('\n');
|
||||
for (int i = maxSize - 1; i >= maxSize - farSize; i--)
|
||||
{
|
||||
builder.append(posToGenerate[i][0]);
|
||||
builder.append(posToGenerate[i][0]-1);
|
||||
builder.append(" ");
|
||||
builder.append(posToGenerate[i][1]);
|
||||
builder.append(" ");
|
||||
|
||||
@@ -2,39 +2,73 @@ package com.seibel.lod.objects;
|
||||
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class PosToRenderContainer
|
||||
{
|
||||
private byte minDetail;
|
||||
public byte minDetail;
|
||||
private int regionPosX;
|
||||
private int regionPosZ;
|
||||
private int numberOfPosToRender;
|
||||
private int[][] posToRender;
|
||||
/*TODO this population matrix could be converted to boolean to improve memory use*/
|
||||
private byte[][] population;
|
||||
|
||||
public PosToRenderContainer(byte minDetail)
|
||||
public PosToRenderContainer(byte minDetail, int regionPosX, int regionPosZ)
|
||||
{
|
||||
this.minDetail = minDetail;
|
||||
this.numberOfPosToRender = 0;
|
||||
posToRender = new int[1][4];
|
||||
this.regionPosX = regionPosX;
|
||||
this.regionPosZ = regionPosZ;
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - minDetail);
|
||||
posToRender = new int[size*size][3];
|
||||
population = new byte[size][size];
|
||||
}
|
||||
|
||||
public void addPosToRender(int[] levelPos)
|
||||
public void addPosToRender(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
if(numberOfPosToRender >= posToRender.length)
|
||||
posToRender = Arrays.copyOf(posToRender, posToRender.length*2);
|
||||
posToRender[numberOfPosToRender] = levelPos;
|
||||
//if(numberOfPosToRender >= posToRender.length)
|
||||
// posToRender = Arrays.copyOf(posToRender, posToRender.length*2);
|
||||
posToRender[numberOfPosToRender][0] = detailLevel;
|
||||
posToRender[numberOfPosToRender][1] = posX;
|
||||
posToRender[numberOfPosToRender][2] = posZ;
|
||||
numberOfPosToRender++;
|
||||
int[] newLevelPos = LevelPosUtil.getRegionModule(LevelPosUtil.convert(levelPos, minDetail));
|
||||
population[LevelPosUtil.getPosZ(newLevelPos)][LevelPosUtil.getPosZ(newLevelPos)] = (byte) (LevelPosUtil.getDetailLevel(levelPos) + 1);
|
||||
population[LevelPosUtil.getRegionModule(minDetail, LevelPosUtil.convert(detailLevel,posX,minDetail))]
|
||||
[LevelPosUtil.getRegionModule(minDetail, LevelPosUtil.convert(detailLevel,posZ,minDetail))] = (byte) (detailLevel + 1);
|
||||
}
|
||||
|
||||
public boolean contains(int[] levelPos)
|
||||
public boolean contains(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
int[] newLevelPos = LevelPosUtil.convert(LevelPosUtil.getRegionModule(levelPos), minDetail);
|
||||
return (population[LevelPosUtil.getPosZ(newLevelPos)][LevelPosUtil.getPosZ(newLevelPos)] == (LevelPosUtil.getDetailLevel(levelPos) + 1));
|
||||
if(LevelPosUtil.getRegion(detailLevel, posX) == regionPosX && LevelPosUtil.getRegion(detailLevel, posZ) == regionPosZ)
|
||||
{
|
||||
return (population[LevelPosUtil.getRegionModule(minDetail, LevelPosUtil.convert(detailLevel,posX,minDetail))]
|
||||
[LevelPosUtil.getRegionModule(minDetail, LevelPosUtil.convert(detailLevel,posZ,minDetail))] == (detailLevel + 1));
|
||||
}else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public void clear(byte minDetail, int regionPosX, int regionPosZ){
|
||||
this.numberOfPosToRender = 0;
|
||||
this.regionPosX = regionPosX;
|
||||
this.regionPosZ = regionPosZ;
|
||||
if(this.minDetail == minDetail)
|
||||
{
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - minDetail);
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
posToRender[0][0] = 0;
|
||||
posToRender[0][1] = 0;
|
||||
posToRender[0][2] = 0;
|
||||
population[x][z] = 0;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
this.minDetail = minDetail;
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - minDetail);
|
||||
posToRender = new int[size*size][3];
|
||||
population = new byte[size][size];
|
||||
}
|
||||
}
|
||||
|
||||
public int getNumberOfPos()
|
||||
@@ -42,15 +76,32 @@ public class PosToRenderContainer
|
||||
return numberOfPosToRender;
|
||||
}
|
||||
|
||||
public byte getNthDetailLevel(int n)
|
||||
{
|
||||
return (byte) posToRender[n][0];
|
||||
}
|
||||
public int getNthPosX(int n)
|
||||
{
|
||||
return posToRender[n][1];
|
||||
}
|
||||
public int getNthPosZ(int n)
|
||||
{
|
||||
return posToRender[n][2];
|
||||
}
|
||||
|
||||
public int[] getNthPos(int n)
|
||||
{
|
||||
return posToRender[n];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("To render ");
|
||||
builder.append(numberOfPosToRender);
|
||||
builder.append('\n');
|
||||
for(int i = 0; i < numberOfPosToRender; i++)
|
||||
{
|
||||
builder.append(posToRender[i][0]);
|
||||
|
||||
@@ -26,20 +26,16 @@ import com.seibel.lod.builders.LodBuilder;
|
||||
import com.seibel.lod.builders.worldGeneration.LodNodeGenWorker;
|
||||
import com.seibel.lod.builders.worldGeneration.LodWorldGenerator;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DistanceCalculatorType;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.FogDistance;
|
||||
import com.seibel.lod.enums.FogDrawOverride;
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.enums.ShadingMode;
|
||||
import com.seibel.lod.objects.LodDimension;
|
||||
import com.seibel.lod.objects.LodWorld;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
import com.seibel.lod.render.LodRenderer;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraftforge.client.event.InputEvent;
|
||||
@@ -68,7 +64,7 @@ public class ClientProxy
|
||||
|
||||
private boolean configOverrideReminderPrinted = false;
|
||||
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
|
||||
|
||||
|
||||
/**
|
||||
@@ -104,12 +100,12 @@ public class ClientProxy
|
||||
public void renderLods(float partialTicks)
|
||||
{
|
||||
DetailDistanceUtil.updateSettings();
|
||||
if (mc == null || mc.player == null || !lodWorld.getIsWorldLoaded())
|
||||
if (mc == null || mc.getPlayer() == null || !lodWorld.getIsWorldLoaded())
|
||||
return;
|
||||
|
||||
viewDistanceChangedEvent();
|
||||
|
||||
LodDimension lodDim = lodWorld.getLodDimension(mc.player.level.dimensionType());
|
||||
LodDimension lodDim = lodWorld.getLodDimension(mc.getCurrentDimension());
|
||||
if (lodDim == null)
|
||||
return;
|
||||
|
||||
@@ -118,8 +114,8 @@ public class ClientProxy
|
||||
//System.out.println("memory needed " + lodDim.getMinMemoryNeeded() + " byte");
|
||||
//System.out.println(lodDim);
|
||||
|
||||
lodDim.treeCutter((int) mc.player.getX(), (int) mc.player.getZ());
|
||||
lodDim.treeGenerator((int) mc.player.getX(), (int) mc.player.getZ());
|
||||
lodDim.treeCutter((int) mc.getPlayer().getX(), (int) mc.getPlayer().getZ());
|
||||
lodDim.treeGenerator((int) mc.getPlayer().getX(), (int) mc.getPlayer().getZ());
|
||||
|
||||
|
||||
// comment out when creating a release
|
||||
@@ -141,7 +137,7 @@ public class ClientProxy
|
||||
|
||||
// these can't be set until after the buffers are built (in renderer.drawLODs)
|
||||
// otherwise the buffers may be set to the wrong size, or not changed at all
|
||||
previousChunkRenderDistance = mc.options.renderDistance;
|
||||
previousChunkRenderDistance = mc.getRenderDistance();
|
||||
previousLodRenderDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get();
|
||||
}
|
||||
|
||||
@@ -151,7 +147,7 @@ public class ClientProxy
|
||||
// remind the developer(s). that config override is active
|
||||
if (!configOverrideReminderPrinted)
|
||||
{
|
||||
mc.player.sendMessage(new StringTextComponent("Debug settings enabled!"), mc.player.getUUID());
|
||||
mc.getPlayer().sendMessage(new StringTextComponent("Debug settings enabled!"), mc.getPlayer().getUUID());
|
||||
configOverrideReminderPrinted = true;
|
||||
}
|
||||
|
||||
@@ -161,21 +157,21 @@ public class ClientProxy
|
||||
LodConfig.CLIENT.graphics.maxDrawDetail.set(LodDetail.FULL);
|
||||
LodConfig.CLIENT.worldGenerator.maxGenerationDetail.set(LodDetail.FULL);
|
||||
|
||||
LodConfig.CLIENT.graphics.fogDistance.set(FogDistance.FAR);
|
||||
LodConfig.CLIENT.graphics.fogDrawOverride.set(FogDrawOverride.ALWAYS_DRAW_FOG_FANCY);
|
||||
LodConfig.CLIENT.graphics.shadingMode.set(ShadingMode.DARKEN_SIDES);
|
||||
LodConfig.CLIENT.graphics.brightnessMultiplier.set(1.0);
|
||||
LodConfig.CLIENT.graphics.saturationMultiplier.set(1.0);
|
||||
// LodConfig.CLIENT.graphics.fogDistance.set(FogDistance.FAR);
|
||||
// LodConfig.CLIENT.graphics.fogDrawOverride.set(FogDrawOverride.ALWAYS_DRAW_FOG_FANCY);
|
||||
// LodConfig.CLIENT.graphics.shadingMode.set(ShadingMode.DARKEN_SIDES);
|
||||
// LodConfig.CLIENT.graphics.brightnessMultiplier.set(1.0);
|
||||
// LodConfig.CLIENT.graphics.saturationMultiplier.set(1.0);
|
||||
|
||||
LodConfig.CLIENT.worldGenerator.distanceGenerationMode.set(DistanceGenerationMode.SURFACE);
|
||||
LodConfig.CLIENT.graphics.lodChunkRenderDistance.set(256);
|
||||
LodConfig.CLIENT.worldGenerator.lodDistanceCalculatorType.set(DistanceCalculatorType.LINEAR);
|
||||
LodConfig.CLIENT.graphics.lodQuality.set(3);
|
||||
LodConfig.CLIENT.worldGenerator.allowUnstableFeatureGeneration.set(false);
|
||||
// LodConfig.CLIENT.worldGenerator.distanceGenerationMode.set(DistanceGenerationMode.SURFACE);
|
||||
// LodConfig.CLIENT.graphics.lodChunkRenderDistance.set(256);
|
||||
// LodConfig.CLIENT.worldGenerator.lodDistanceCalculatorType.set(DistanceCalculatorType.LINEAR);
|
||||
// LodConfig.CLIENT.graphics.lodQuality.set(3);
|
||||
// LodConfig.CLIENT.worldGenerator.allowUnstableFeatureGeneration.set(false);
|
||||
|
||||
LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.set(2000); // 2000
|
||||
LodConfig.CLIENT.buffers.bufferRebuildChunkChangeTimeout.set(1000); // 1000
|
||||
LodConfig.CLIENT.buffers.bufferRebuildLodChangeTimeout.set(50); // 5000
|
||||
// LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.set(2000); // 2000
|
||||
// LodConfig.CLIENT.buffers.bufferRebuildChunkChangeTimeout.set(1000); // 1000
|
||||
// LodConfig.CLIENT.buffers.bufferRebuildLodChangeTimeout.set(50); // 5000
|
||||
|
||||
LodConfig.CLIENT.debugging.enableDebugKeybinding.set(true);
|
||||
}
|
||||
@@ -188,10 +184,10 @@ public class ClientProxy
|
||||
@SubscribeEvent
|
||||
public void serverTickEvent(TickEvent.ServerTickEvent event)
|
||||
{
|
||||
if (mc == null || mc.player == null || !lodWorld.getIsWorldLoaded())
|
||||
if (mc == null || mc.getPlayer() == null || !lodWorld.getIsWorldLoaded())
|
||||
return;
|
||||
|
||||
LodDimension lodDim = lodWorld.getLodDimension(mc.player.level.dimensionType());
|
||||
LodDimension lodDim = lodWorld.getLodDimension(mc.getPlayer().level.dimensionType());
|
||||
if (lodDim == null)
|
||||
return;
|
||||
|
||||
@@ -225,7 +221,6 @@ public class ClientProxy
|
||||
public void worldUnloadEvent(WorldEvent.Unload event)
|
||||
{
|
||||
// the player just unloaded a world/dimension
|
||||
|
||||
if (mc.getConnection().getLevel() == null)
|
||||
{
|
||||
// if this isn't done unfinished tasks may be left in the queue
|
||||
@@ -280,7 +275,7 @@ public class ClientProxy
|
||||
private void playerMoveEvent(LodDimension lodDim)
|
||||
{
|
||||
// make sure the dimension is centered
|
||||
RegionPos playerRegionPos = new RegionPos(mc.player.blockPosition());
|
||||
RegionPos playerRegionPos = new RegionPos(mc.getPlayer().blockPosition());
|
||||
RegionPos worldRegionOffset = new RegionPos(playerRegionPos.x - lodDim.getCenterX(), playerRegionPos.z - lodDim.getCenterZ());
|
||||
if (worldRegionOffset.x != 0 || worldRegionOffset.z != 0)
|
||||
{
|
||||
|
||||
@@ -31,30 +31,33 @@ import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.seibel.lod.builders.LodBufferBuilder;
|
||||
import com.seibel.lod.builders.LodBufferBuilder.VertexBuffersAndOffset;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DebugMode;
|
||||
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.objects.LodDimension;
|
||||
import com.seibel.lod.objects.NearFarFogSettings;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
import com.seibel.lod.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.proxy.ClientProxy;
|
||||
import com.seibel.lod.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.client.renderer.vertex.VertexBuffer;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.potion.EffectInstance;
|
||||
import net.minecraft.potion.Effects;
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
@@ -67,7 +70,7 @@ import net.minecraft.util.math.vector.Vector3f;
|
||||
* This is where LODs are draw to the world.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 8-31-2021
|
||||
* @version 9-7-2021
|
||||
*/
|
||||
public class LodRenderer
|
||||
{
|
||||
@@ -102,11 +105,10 @@ public class LodRenderer
|
||||
*/
|
||||
public DebugMode previousDebugMode = DebugMode.OFF;
|
||||
|
||||
private Minecraft mc;
|
||||
private MinecraftWrapper mc;
|
||||
private GameRenderer gameRender;
|
||||
private IProfiler profiler;
|
||||
private int farPlaneBlockDistance;
|
||||
private ReflectionHandler reflectionHandler;
|
||||
|
||||
|
||||
/**
|
||||
@@ -119,12 +121,12 @@ public class LodRenderer
|
||||
*/
|
||||
private VertexBuffer[][] vbos;
|
||||
public static final VertexFormat LOD_VERTEX_FORMAT = DefaultVertexFormats.POSITION_COLOR;
|
||||
|
||||
private ChunkPos vbosCenter = new ChunkPos(0,0);
|
||||
|
||||
/**
|
||||
* This is used to determine if the LODs should be regenerated
|
||||
*/
|
||||
private LevelPos previousPos = new LevelPos((byte) 0, 0, 0);
|
||||
private int[] previousPos = new int[]{0,0,0};
|
||||
private int prevRenderDistance = 0;
|
||||
private long prevPlayerPosTime = 0;
|
||||
private long prevVanillaChunkTime = 0;
|
||||
@@ -153,10 +155,9 @@ public class LodRenderer
|
||||
|
||||
public LodRenderer(LodBufferBuilder newLodNodeBufferBuilder)
|
||||
{
|
||||
mc = Minecraft.getInstance();
|
||||
gameRender = mc.gameRenderer;
|
||||
mc = MinecraftWrapper.INSTANCE;
|
||||
gameRender = mc.getGameRenderer();
|
||||
|
||||
reflectionHandler = new ReflectionHandler();
|
||||
lodBufferBuilder = newLodNodeBufferBuilder;
|
||||
}
|
||||
|
||||
@@ -198,7 +199,7 @@ public class LodRenderer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead)
|
||||
// starting here...
|
||||
determineIfLodsShouldRegenerate(lodDim);
|
||||
@@ -215,7 +216,7 @@ public class LodRenderer
|
||||
if ((partialRegen || fullRegen) && !lodBufferBuilder.generatingBuffers && !lodBufferBuilder.newBuffersAvaliable())
|
||||
{
|
||||
// generate the LODs on a separate thread to prevent stuttering or freezing
|
||||
lodBufferBuilder.generateLodBuffersAsync(this, lodDim, mc.player.blockPosition(), true);
|
||||
lodBufferBuilder.generateLodBuffersAsync(this, lodDim, mc.getPlayer().blockPosition(), true);
|
||||
|
||||
// the regen process has been started,
|
||||
// it will be done when lodBufferBuilder.newBuffersAvaliable()
|
||||
@@ -223,20 +224,12 @@ public class LodRenderer
|
||||
fullRegen = false;
|
||||
partialRegen = false;
|
||||
}
|
||||
|
||||
|
||||
// TODO move the buffer regeneration logic into its own class (probably called in the client proxy instead)
|
||||
// ...ending here
|
||||
|
||||
// replace the buffers used to draw and build,
|
||||
// this is only done when the createLodBufferGenerationThread
|
||||
// has finished executing on a parallel thread.
|
||||
if (lodBufferBuilder.newBuffersAvaliable())
|
||||
{
|
||||
swapBuffers();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===========================//
|
||||
// GL settings for rendering //
|
||||
//===========================//
|
||||
@@ -247,7 +240,7 @@ public class LodRenderer
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
|
||||
else
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||
|
||||
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
|
||||
@@ -263,15 +256,15 @@ public class LodRenderer
|
||||
GL11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, defaultProjMatrix);
|
||||
|
||||
Matrix4f modelViewMatrix = generateModelViewMatrix(partialTicks);
|
||||
|
||||
|
||||
// required for setupFog and setupProjectionMatrix
|
||||
farPlaneBlockDistance = LodConfig.CLIENT.graphics.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH;
|
||||
|
||||
|
||||
setupProjectionMatrix(partialTicks);
|
||||
setupLighting(lodDim, partialTicks);
|
||||
|
||||
NearFarFogSettings fogSettings = determineFogSettings();
|
||||
|
||||
|
||||
// determine the current fog settings so they can be
|
||||
// reset after drawing the LODs
|
||||
float defaultFogStartDist = GL11.glGetFloat(GL11.GL_FOG_START);
|
||||
@@ -287,8 +280,10 @@ public class LodRenderer
|
||||
|
||||
if (vbos != null)
|
||||
{
|
||||
Vector3d cameraDir = mc.cameraEntity.getLookAngle().normalize();
|
||||
cameraDir = mc.options.getCameraType().isMirrored() ? cameraDir.reverse() : cameraDir;
|
||||
Entity cameraEntity = mc.getCameraEntity();
|
||||
Vector3d cameraDir = cameraEntity.getLookAngle().normalize();
|
||||
cameraDir = mc.getOptions().getCameraType().isMirrored() ? cameraDir.reverse() : cameraDir;
|
||||
|
||||
|
||||
|
||||
// used to determine what type of fog to render
|
||||
@@ -300,7 +295,7 @@ public class LodRenderer
|
||||
for (int j = 0; j < vbos.length; j++)
|
||||
{
|
||||
RegionPos vboPos = new RegionPos(i + lodDim.getCenterX() - lodDim.getWidth() / 2, j + lodDim.getCenterZ() - lodDim.getWidth() / 2);
|
||||
if (RenderUtil.isRegionInViewFrustum(mc.cameraEntity.blockPosition(), cameraDir, vboPos.blockPos()))
|
||||
if (RenderUtil.isRegionInViewFrustum(cameraEntity.blockPosition(), cameraDir, vboPos.blockPos()))
|
||||
{
|
||||
if ((i > halfWidth - quarterWidth && i < halfWidth + quarterWidth) && (j > halfWidth - quarterWidth && j < halfWidth + quarterWidth))
|
||||
setupFog(fogSettings.near.distance, fogSettings.near.quality);
|
||||
@@ -344,11 +339,23 @@ public class LodRenderer
|
||||
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
|
||||
// replace the buffers used to draw and build,
|
||||
// this is only done when the createLodBufferGenerationThread
|
||||
// has finished executing on a parallel thread.
|
||||
if (lodBufferBuilder.newBuffersAvaliable())
|
||||
{
|
||||
// this has to be called after the VBOs have been drawn
|
||||
// otherwise rubber banding may occur
|
||||
swapBuffers();
|
||||
}
|
||||
|
||||
|
||||
// end of internal LOD profiling
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is where the actual drawing happens.
|
||||
*/
|
||||
@@ -381,12 +388,12 @@ public class LodRenderer
|
||||
RenderSystem.disableFog();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (fogDistance == FogDistance.NEAR_AND_FAR)
|
||||
{
|
||||
throw new IllegalArgumentException("setupFog doesn't accept the NEAR_AND_FAR fog distance.");
|
||||
}
|
||||
|
||||
|
||||
// determine the fog distance mode to use
|
||||
int glFogDistanceMode;
|
||||
if (fogQuality == FogQuality.FANCY)
|
||||
@@ -399,7 +406,7 @@ public class LodRenderer
|
||||
// fast fog (frustum distance based fog)
|
||||
glFogDistanceMode = NVFogDistance.GL_EYE_PLANE_ABSOLUTE_NV;
|
||||
}
|
||||
|
||||
|
||||
// the multipliers are percentages
|
||||
// of the regular view distance.
|
||||
if (fogDistance == FogDistance.FAR)
|
||||
@@ -408,7 +415,7 @@ public class LodRenderer
|
||||
// is because we are using fog backwards to how
|
||||
// it is normally used, with it hiding near objects
|
||||
// instead of far objects.
|
||||
|
||||
|
||||
if (fogQuality == FogQuality.FANCY)
|
||||
{
|
||||
// for more realistic fog when using FAR
|
||||
@@ -434,16 +441,16 @@ public class LodRenderer
|
||||
{
|
||||
if (fogQuality == FogQuality.FANCY)
|
||||
{
|
||||
RenderSystem.fogEnd(mc.options.renderDistance * 16 * 1.41f);
|
||||
RenderSystem.fogStart(mc.options.renderDistance * 16 * 1.6f);
|
||||
RenderSystem.fogEnd(mc.getRenderDistance() * 16 * 1.41f);
|
||||
RenderSystem.fogStart(mc.getRenderDistance() * 16 * 1.6f);
|
||||
}
|
||||
else if (fogQuality == FogQuality.FAST)
|
||||
{
|
||||
RenderSystem.fogEnd(mc.options.renderDistance * 16 * 1.0f);
|
||||
RenderSystem.fogStart(mc.options.renderDistance * 16 * 1.5f);
|
||||
RenderSystem.fogEnd(mc.getRenderDistance() * 16 * 1.0f);
|
||||
RenderSystem.fogStart(mc.getRenderDistance() * 16 * 1.5f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GL11.glEnable(GL11.GL_FOG);
|
||||
RenderSystem.enableFog();
|
||||
RenderSystem.setupNvFogDistance();
|
||||
@@ -466,8 +473,8 @@ public class LodRenderer
|
||||
// disable fog if Minecraft wasn't rendering fog
|
||||
// but we were
|
||||
if (!fogSettings.vanillaIsRenderingFog &&
|
||||
(fogSettings.near.quality != FogQuality.OFF ||
|
||||
fogSettings.far.quality != FogQuality.OFF))
|
||||
(fogSettings.near.quality != FogQuality.OFF ||
|
||||
fogSettings.far.quality != FogQuality.OFF))
|
||||
{
|
||||
GL11.glDisable(GL11.GL_FOG);
|
||||
}
|
||||
@@ -481,17 +488,24 @@ public class LodRenderer
|
||||
private Matrix4f generateModelViewMatrix(float partialTicks)
|
||||
{
|
||||
// get all relevant camera info
|
||||
ActiveRenderInfo renderInfo = mc.gameRenderer.getMainCamera();
|
||||
ActiveRenderInfo renderInfo = mc.getGameRenderer().getMainCamera();
|
||||
Vector3d projectedView = renderInfo.getPosition();
|
||||
|
||||
|
||||
// generate the model view matrix
|
||||
MatrixStack matrixStack = new MatrixStack();
|
||||
matrixStack.pushPose();
|
||||
// translate and rotate to the current camera location
|
||||
// rotate to the current camera's direction
|
||||
matrixStack.mulPose(Vector3f.XP.rotationDegrees(renderInfo.getXRot()));
|
||||
matrixStack.mulPose(Vector3f.YP.rotationDegrees(renderInfo.getYRot() + 180));
|
||||
matrixStack.translate(-projectedView.x, -projectedView.y, -projectedView.z);
|
||||
// translate the camera relative to the regions' center
|
||||
// (AxisAlignedBoundingBoxes (LODs) use doubles and thus have a higher
|
||||
// accuracy vs the model view matrix, which only uses floats)
|
||||
BlockPos bufferPos = vbosCenter.getWorldPosition();
|
||||
Vector3d eyePos = mc.getPlayer().getEyePosition(partialTicks);
|
||||
double xDiff = eyePos.x - bufferPos.getX();
|
||||
double zDiff = eyePos.z - bufferPos.getZ();
|
||||
matrixStack.translate(-xDiff, -projectedView.y, -zDiff);
|
||||
|
||||
return matrixStack.last().pose();
|
||||
}
|
||||
@@ -519,16 +533,16 @@ public class LodRenderer
|
||||
matrixStack.pushPose();
|
||||
|
||||
gameRender.bobHurt(matrixStack, partialTicks);
|
||||
if (this.mc.options.bobView)
|
||||
if (this.mc.getOptions().bobView)
|
||||
{
|
||||
gameRender.bobView(matrixStack, partialTicks);
|
||||
}
|
||||
|
||||
// potion and nausea effects
|
||||
float f = MathHelper.lerp(partialTicks, this.mc.player.oPortalTime, this.mc.player.portalTime) * this.mc.options.screenEffectScale * this.mc.options.screenEffectScale;
|
||||
float f = MathHelper.lerp(partialTicks, this.mc.getPlayer().oPortalTime, this.mc.getPlayer().portalTime) * this.mc.getOptions().screenEffectScale * this.mc.getOptions().screenEffectScale;
|
||||
if (f > 0.0F)
|
||||
{
|
||||
int i = this.mc.player.hasEffect(Effects.CONFUSION) ? 7 : 20;
|
||||
int i = this.mc.getPlayer().hasEffect(Effects.CONFUSION) ? 7 : 20;
|
||||
float f1 = 5.0F / (f * f + 5.0F) - f * 0.04F;
|
||||
f1 = f1 * f1;
|
||||
Vector3f vector3f = new Vector3f(0.0F, MathHelper.SQRT_OF_TWO / 2.0F, MathHelper.SQRT_OF_TWO / 2.0F);
|
||||
@@ -548,7 +562,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.options.renderDistance,
|
||||
mc.getRenderDistance(),
|
||||
farPlaneBlockDistance * LodUtil.CHUNK_WIDTH * 2);
|
||||
|
||||
// add the screen space distortions
|
||||
@@ -565,9 +579,9 @@ public class LodRenderer
|
||||
{
|
||||
// Determine if the player has night vision
|
||||
boolean playerHasNightVision = false;
|
||||
if (this.mc.player != null)
|
||||
if (this.mc.getPlayer() != null)
|
||||
{
|
||||
Iterator<EffectInstance> iterator = this.mc.player.getActiveEffects().iterator();
|
||||
Iterator<EffectInstance> iterator = this.mc.getPlayer().getActiveEffects().iterator();
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
EffectInstance instance = iterator.next();
|
||||
@@ -580,9 +594,9 @@ public class LodRenderer
|
||||
}
|
||||
|
||||
|
||||
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.level.getSkyDarken(partialTicks) : 0.2f;
|
||||
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.getSkyDarken(partialTicks) : 0.2f;
|
||||
sunBrightness = playerHasNightVision ? 1.0f : sunBrightness;
|
||||
float gammaMultiplyer = (float) mc.options.gamma - 0.5f;
|
||||
float gammaMultiplyer = (float) mc.getOptions().gamma - 0.5f;
|
||||
float lightStrength = ((sunBrightness / 2f) - 0.2f) + (gammaMultiplyer * 0.3f);
|
||||
|
||||
float lightAmbient[] = {lightStrength, lightStrength, lightStrength, 1.0f};
|
||||
@@ -636,13 +650,18 @@ public class LodRenderer
|
||||
|
||||
/**
|
||||
* Replace the current Vertex Buffers with the newly
|
||||
* created buffers from the lodBufferBuilder.
|
||||
* created buffers from the lodBufferBuilder. <br><br>
|
||||
*
|
||||
* For some reason this has to be called after the frame has been rendered,
|
||||
* otherwise visual stuttering/rubber banding may happen. I'm not sure why...
|
||||
*/
|
||||
private void swapBuffers()
|
||||
{
|
||||
// replace the drawable buffers with
|
||||
// the newly created buffers from the lodBufferBuilder
|
||||
vbos = lodBufferBuilder.getVertexBuffers();
|
||||
VertexBuffersAndOffset result = lodBufferBuilder.getVertexBuffers();
|
||||
vbos = result.vbos;
|
||||
vbosCenter = result.drawableCenterChunkPos;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -656,7 +675,7 @@ public class LodRenderer
|
||||
|
||||
private double getFov(float partialTicks, boolean useFovSetting)
|
||||
{
|
||||
return mc.gameRenderer.getFov(mc.gameRenderer.getMainCamera(), partialTicks, useFovSetting);
|
||||
return mc.getGameRenderer().getFov(mc.getGameRenderer().getMainCamera(), partialTicks, useFovSetting);
|
||||
}
|
||||
|
||||
|
||||
@@ -668,7 +687,7 @@ public class LodRenderer
|
||||
NearFarFogSettings fogSettings = new NearFarFogSettings();
|
||||
|
||||
|
||||
FogQuality quality = reflectionHandler.getFogQuality();
|
||||
FogQuality quality = ReflectionHandler.INSTANCE.getFogQuality();
|
||||
FogDrawOverride override = LodConfig.CLIENT.graphics.fogDrawOverride.get();
|
||||
|
||||
|
||||
@@ -770,65 +789,65 @@ public class LodRenderer
|
||||
|
||||
return fogSettings;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determines if the LODs should have a fullRegen or partialRegen
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void determineIfLodsShouldRegenerate(LodDimension lodDim)
|
||||
{
|
||||
|
||||
short renderDistance = (short) mc.options.renderDistance;
|
||||
short renderDistance = (short) mc.getRenderDistance();
|
||||
|
||||
//=============//
|
||||
// full regens //
|
||||
//=============//
|
||||
|
||||
// check if the view distance changed
|
||||
if (ClientProxy.previousLodRenderDistance != LodConfig.CLIENT.graphics.lodChunkRenderDistance.get()
|
||||
|| mc.options.renderDistance != prevRenderDistance
|
||||
|| prevFogDistance != LodConfig.CLIENT.graphics.fogDistance.get())
|
||||
|| mc.getRenderDistance() != prevRenderDistance
|
||||
|| prevFogDistance != LodConfig.CLIENT.graphics.fogDistance.get())
|
||||
{
|
||||
DetailDistanceUtil.updateSettings();
|
||||
fullRegen = true;
|
||||
previousPos.changeParameters((byte) 4, mc.player.xChunk, mc.player.zChunk);
|
||||
previousPos = LevelPosUtil.createLevelPos((byte) 4, mc.getPlayer().xChunk, mc.getPlayer().zChunk);
|
||||
prevFogDistance = LodConfig.CLIENT.graphics.fogDistance.get();
|
||||
prevRenderDistance = mc.options.renderDistance;
|
||||
prevRenderDistance = mc.getRenderDistance();
|
||||
//should use this when it's ready
|
||||
vanillaRenderedChunks = new boolean[renderDistance*2+2][renderDistance*2+2];
|
||||
}
|
||||
|
||||
|
||||
// did the user change the debug setting?
|
||||
if (LodConfig.CLIENT.debugging.debugMode.get() != previousDebugMode)
|
||||
{
|
||||
previousDebugMode = LodConfig.CLIENT.debugging.debugMode.get();
|
||||
fullRegen = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
long newTime = System.currentTimeMillis();
|
||||
|
||||
|
||||
// check if the player has moved
|
||||
if (newTime - prevPlayerPosTime > LodConfig.CLIENT.buffers.bufferRebuildPlayerMoveTimeout.get())
|
||||
{
|
||||
if (previousPos.detailLevel == 0
|
||||
|| mc.player.xChunk != previousPos.posX
|
||||
|| mc.player.zChunk != previousPos.posZ)
|
||||
if (LevelPosUtil.getDetailLevel(previousPos) == 0
|
||||
|| mc.getPlayer().xChunk != LevelPosUtil.getPosX(previousPos)
|
||||
|| mc.getPlayer().zChunk != LevelPosUtil.getPosZ(previousPos))
|
||||
{
|
||||
fullRegen = true;
|
||||
previousPos.changeParameters((byte) 4, mc.player.xChunk, mc.player.zChunk);
|
||||
previousPos = LevelPosUtil.createLevelPos((byte) 4, mc.getPlayer().xChunk, mc.getPlayer().zChunk);
|
||||
//should use this when it's ready
|
||||
vanillaRenderedChunks = new boolean[renderDistance*2+2][renderDistance*2+2];
|
||||
}
|
||||
prevPlayerPosTime = newTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// partial regens //
|
||||
//================//
|
||||
|
||||
|
||||
|
||||
|
||||
// check if the vanilla rendered chunks changed
|
||||
if (newTime - prevVanillaChunkTime > LodConfig.CLIENT.buffers.bufferRebuildChunkChangeTimeout.get())
|
||||
{
|
||||
@@ -840,8 +859,8 @@ public class LodRenderer
|
||||
}
|
||||
prevVanillaChunkTime = newTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// check if there is any newly generated terrain to show
|
||||
if (newTime - prevChunkTime > LodConfig.CLIENT.buffers.bufferRebuildLodChangeTimeout.get())
|
||||
{
|
||||
@@ -852,22 +871,22 @@ public class LodRenderer
|
||||
}
|
||||
prevChunkTime = newTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// LOD skipping //
|
||||
//==============//
|
||||
|
||||
|
||||
// determine which LODs should not be rendered close to the player
|
||||
HashSet<ChunkPos> chunkPosToSkip = LodUtil.getNearbyLodChunkPosToSkip(lodDim, mc.player.blockPosition());
|
||||
HashSet<ChunkPos> chunkPosToSkip = LodUtil.getNearbyLodChunkPosToSkip(lodDim, mc.getPlayer().blockPosition());
|
||||
int chunkX;
|
||||
int chunkZ;
|
||||
for (ChunkPos pos : chunkPosToSkip)
|
||||
{
|
||||
chunkX = pos.x - mc.player.xChunk + renderDistance + 1;
|
||||
chunkZ = pos.z - mc.player.zChunk + renderDistance + 1;
|
||||
chunkX = pos.x - mc.getPlayer().xChunk + renderDistance + 1;
|
||||
chunkZ = pos.z - mc.getPlayer().zChunk + renderDistance + 1;
|
||||
try
|
||||
{
|
||||
if (!vanillaRenderedChunks[chunkX][chunkZ])
|
||||
@@ -881,14 +900,14 @@ public class LodRenderer
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// if the player is high enough, draw all LODs
|
||||
if(chunkPosToSkip.isEmpty() && mc.player.position().y > 256)
|
||||
if(chunkPosToSkip.isEmpty() && mc.getPlayer().position().y > 256)
|
||||
{
|
||||
vanillaRenderedChunks = new boolean[renderDistance*2+2][renderDistance*2+2];
|
||||
vanillaRenderedChunksChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ package com.seibel.lod.render;
|
||||
import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.LodTemplate;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
@@ -35,7 +35,7 @@ import net.minecraft.util.math.vector.Vector3d;
|
||||
*/
|
||||
public class RenderUtil
|
||||
{
|
||||
private static final Minecraft mc = Minecraft.getInstance();
|
||||
private static final MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
|
||||
|
||||
|
||||
/**
|
||||
@@ -44,28 +44,24 @@ public class RenderUtil
|
||||
*/
|
||||
public static boolean isChunkPosInLoadedArea(ChunkPos pos, ChunkPos center)
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
return (pos.x >= center.x - mc.options.renderDistance
|
||||
&& pos.x <= center.x + mc.options.renderDistance)
|
||||
return (pos.x >= center.x - mc.getRenderDistance()
|
||||
&& pos.x <= center.x + mc.getRenderDistance())
|
||||
&&
|
||||
(pos.z >= center.z - mc.options.renderDistance
|
||||
&& pos.z <= center.z + mc.options.renderDistance);
|
||||
(pos.z >= center.z - mc.getRenderDistance()
|
||||
&& pos.z <= center.z + mc.getRenderDistance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the given coordinate is in the loaded area of the world.
|
||||
* @param centerCoordinate the center of the loaded world
|
||||
*/
|
||||
public static boolean isCoordinateInLoadedArea(int i, int j, int centerCoordinate)
|
||||
public static boolean isCoordinateInLoadedArea(int x, int z, int centerCoordinate)
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
return (i >= centerCoordinate - mc.options.renderDistance
|
||||
&& i <= centerCoordinate + mc.options.renderDistance)
|
||||
return (x >= centerCoordinate - mc.getRenderDistance()
|
||||
&& x <= centerCoordinate + mc.getRenderDistance())
|
||||
&&
|
||||
(j >= centerCoordinate - mc.options.renderDistance
|
||||
&& j <= centerCoordinate + mc.options.renderDistance);
|
||||
(z >= centerCoordinate - mc.getRenderDistance()
|
||||
&& z <= centerCoordinate + mc.getRenderDistance());
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +105,7 @@ public class RenderUtil
|
||||
int maxNumberOfLods = LodRenderer.MAX_ALOCATEABLE_DIRECT_MEMORY / lodTemplate.getBufferMemoryForSingleLod();
|
||||
int numbLodsWide = (int) Math.sqrt(maxNumberOfLods);
|
||||
|
||||
return numbLodsWide / (2 * mc.options.renderDistance);
|
||||
return numbLodsWide / (2 * mc.getRenderDistance());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,8 +4,7 @@ import com.seibel.lod.config.LodConfig;
|
||||
import com.seibel.lod.enums.DistanceGenerationMode;
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.objects.RegionPos;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
public class DetailDistanceUtil
|
||||
{
|
||||
@@ -20,7 +19,7 @@ public class DetailDistanceUtil
|
||||
private static int base = 2;
|
||||
private static double logBase = Math.log(2);
|
||||
|
||||
private static LodDetail[] lodDetails = {
|
||||
private static LodDetail[] lodGenDetails = {
|
||||
LodDetail.FULL,
|
||||
LodDetail.HALF,
|
||||
LodDetail.QUAD,
|
||||
@@ -34,6 +33,7 @@ public class DetailDistanceUtil
|
||||
LodDetail.SINGLE};
|
||||
|
||||
|
||||
|
||||
public static void updateSettings(){
|
||||
minGenDetail = LodConfig.CLIENT.worldGenerator.maxGenerationDetail.get().detailLevel;
|
||||
minDrawDetail = Math.max(LodConfig.CLIENT.graphics.maxDrawDetail.get().detailLevel,LodConfig.CLIENT.worldGenerator.maxGenerationDetail.get().detailLevel);
|
||||
@@ -59,7 +59,7 @@ public class DetailDistanceUtil
|
||||
initial = LodConfig.CLIENT.graphics.lodQuality.get() * 128;
|
||||
return (int) (Math.pow(base, detail) * initial);
|
||||
case RENDER_DEPENDANT:
|
||||
int realRenderDistance = Minecraft.getInstance().options.renderDistance * 16;
|
||||
int realRenderDistance = MinecraftWrapper.INSTANCE.getRenderDistance() * 16;
|
||||
int border = 64;
|
||||
byte detailAtBorder = (byte) 4;
|
||||
if (detail > detailAtBorder)
|
||||
@@ -154,10 +154,10 @@ public class DetailDistanceUtil
|
||||
{
|
||||
if (detail < minGenDetail)
|
||||
{
|
||||
return lodDetails[minGenDetail];
|
||||
return lodGenDetails[minGenDetail];
|
||||
} else
|
||||
{
|
||||
return lodDetails[detail];
|
||||
return lodGenDetails[detail];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,13 +166,13 @@ public class DetailDistanceUtil
|
||||
{
|
||||
if (detail < minGenDetail)
|
||||
{
|
||||
return lodDetails[minGenDetail].detailLevel;
|
||||
return lodGenDetails[minGenDetail].detailLevel;
|
||||
} else if (detail == maxDetail)
|
||||
{
|
||||
return LodUtil.REGION_DETAIL_LEVEL;
|
||||
} else
|
||||
{
|
||||
return lodDetails[detail].detailLevel;
|
||||
return lodGenDetails[detail].detailLevel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,13 +21,15 @@ 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.objects.LevelPos.LevelPos;
|
||||
import com.seibel.lod.wrappers.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectList;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.client.renderer.WorldRenderer.LocalRenderInformationContainer;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
@@ -43,11 +45,11 @@ import net.minecraft.world.server.ServerWorld;
|
||||
* This class holds methods and constants that may be used in multiple places.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 8-29-2021
|
||||
* @version 9-7-2021
|
||||
*/
|
||||
public class LodUtil
|
||||
{
|
||||
private static Minecraft mc = Minecraft.getInstance();
|
||||
private static MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
|
||||
|
||||
|
||||
/** alpha used when drawing chunks in debug mode */
|
||||
@@ -98,6 +100,9 @@ public class LodUtil
|
||||
/** If we ever need to use a heightmap for any reason, use this one. */
|
||||
public static final Heightmap.Type DEFAULT_HEIGHTMAP = Heightmap.Type.WORLD_SURFACE_WG;
|
||||
|
||||
/** This regex finds any characters that are invalid for use in a windows
|
||||
* (and by extension mac and linux) file path */
|
||||
public static final String INVALID_FILE_CHARACTERS_REGEX = "[\\\\\\/:*?\\\"<>|]";
|
||||
|
||||
|
||||
|
||||
@@ -207,10 +212,7 @@ public class LodUtil
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerData server = mc.getCurrentServer();
|
||||
return server.name + ", IP " +
|
||||
server.ip + ", GameVersion " +
|
||||
server.version.getString();
|
||||
return getServerId();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,15 +221,13 @@ public class LodUtil
|
||||
/**
|
||||
* If on single player this will return the name of the user's
|
||||
* world and the dimensional save folder, if in multiplayer
|
||||
* it will return the server name, game version, and dimension.<br>
|
||||
* it will return the server name, ip, game version, and dimension.<br>
|
||||
* <br>
|
||||
* This can be used to determine where to save files for a given
|
||||
* dimension.
|
||||
*/
|
||||
public static String getDimensionIDFromWorld(IWorld world)
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
if(mc.hasSingleplayerServer())
|
||||
{
|
||||
// this will return the world save location
|
||||
@@ -245,14 +245,25 @@ public class LodUtil
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerData server = mc.getCurrentServer();
|
||||
return server.name + ", IP " +
|
||||
server.ip + ", GameVersion " +
|
||||
server.version.getString() + File.separatorChar
|
||||
+ "dim_" + world.dimensionType().effectsLocation().getPath() + File.separatorChar;
|
||||
return getServerId() + File.separatorChar + "dim_" + world.dimensionType().effectsLocation().getPath() + File.separatorChar;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the server name, IP and game version.
|
||||
*/
|
||||
public static String getServerId()
|
||||
{
|
||||
ServerData server = mc.getCurrentServer();
|
||||
|
||||
String serverName = server.name.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
|
||||
String serverIp = server.ip.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
|
||||
String serverMcVersion = server.version.getString().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
|
||||
|
||||
String serverId = serverName + ", IP " + serverIp + ", GameVersion " + serverMcVersion;
|
||||
|
||||
return serverId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -313,7 +324,7 @@ public class LodUtil
|
||||
*/
|
||||
public static HashSet<ChunkPos> getNearbyLodChunkPosToSkip(LodDimension lodDim, BlockPos playerPos)
|
||||
{
|
||||
int chunkRenderDist = mc.options.renderDistance;
|
||||
int chunkRenderDist = mc.getRenderDistance();
|
||||
ChunkPos centerChunk = new ChunkPos(playerPos);
|
||||
|
||||
// skip chunks that are already going to be rendered by Minecraft
|
||||
@@ -324,13 +335,13 @@ public class LodUtil
|
||||
{
|
||||
for (int z = centerChunk.z - chunkRenderDist; z < centerChunk.z + chunkRenderDist; z++)
|
||||
{
|
||||
LevelPos levelPos = new LevelPos(LodUtil.CHUNK_DETAIL_LEVEL, x, z);
|
||||
if (!lodDim.doesDataExist(levelPos.clone()))
|
||||
if (!lodDim.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, x, z))
|
||||
continue;
|
||||
|
||||
short[] data = lodDim.getData(levelPos);
|
||||
|
||||
short lodAverageHeight = data[0];
|
||||
|
||||
long data = lodDim.getData(LodUtil.CHUNK_DETAIL_LEVEL, x, z);
|
||||
|
||||
short lodAverageHeight = DataPoint.getHeight(data);
|
||||
|
||||
if (playerPos.getY() <= lodAverageHeight)
|
||||
{
|
||||
// don't draw Lod's that are taller than the player
|
||||
@@ -355,12 +366,12 @@ public class LodUtil
|
||||
{
|
||||
HashSet<ChunkPos> loadedPos = new HashSet<>();
|
||||
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
// Wow those are some long names!
|
||||
|
||||
// go through every RenderInfo to get the compiled chunks
|
||||
for (WorldRenderer.LocalRenderInformationContainer worldrenderer$localrenderinformationcontainer : mc.levelRenderer.renderChunks)
|
||||
WorldRenderer renderer = mc.getLevelRenderer();
|
||||
ObjectList<LocalRenderInformationContainer> chunks = renderer.renderChunks;
|
||||
for (WorldRenderer.LocalRenderInformationContainer worldrenderer$localrenderinformationcontainer : chunks)
|
||||
{
|
||||
if (!worldrenderer$localrenderinformationcontainer.chunk.getCompiledChunk().hasNoRenderableLayers())
|
||||
{
|
||||
@@ -371,6 +382,7 @@ public class LodUtil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return loadedPos;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.seibel.lod.wrappers;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
import net.minecraft.client.GameSettings;
|
||||
import net.minecraft.client.MainWindow;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.client.network.play.ClientPlayNetHandler;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.world.DimensionType;
|
||||
|
||||
/**
|
||||
* A singleton that wraps the Minecraft class
|
||||
* to allow for easier movement between Minecraft versions.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 9-6-2021
|
||||
*/
|
||||
public class MinecraftWrapper
|
||||
{
|
||||
public static MinecraftWrapper INSTANCE = new MinecraftWrapper();
|
||||
|
||||
private Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
private MinecraftWrapper()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// method wrappers //
|
||||
//=================//
|
||||
|
||||
public float getShading(Direction direction)
|
||||
{
|
||||
return mc.level.getShade(Direction.UP, true);
|
||||
}
|
||||
|
||||
public boolean hasSingleplayerServer()
|
||||
{
|
||||
return mc.hasSingleplayerServer();
|
||||
}
|
||||
|
||||
public DimensionType getCurrentDimension()
|
||||
{
|
||||
return mc.player.level.dimensionType();
|
||||
}
|
||||
|
||||
public String getCurrentDimensionId()
|
||||
{
|
||||
return LodUtil.getDimensionIDFromWorld(mc.level);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// Simple gets //
|
||||
//=============//
|
||||
|
||||
public ClientPlayerEntity getPlayer()
|
||||
{
|
||||
return mc.player;
|
||||
}
|
||||
|
||||
public GameSettings getOptions()
|
||||
{
|
||||
return mc.options;
|
||||
}
|
||||
|
||||
/** Measured in chunks */
|
||||
public int getRenderDistance()
|
||||
{
|
||||
return mc.options.renderDistance;
|
||||
}
|
||||
|
||||
public File getGameDirectory()
|
||||
{
|
||||
return mc.gameDirectory;
|
||||
}
|
||||
|
||||
public IProfiler getProfiler()
|
||||
{
|
||||
return mc.getProfiler();
|
||||
}
|
||||
|
||||
public ClientPlayNetHandler getConnection()
|
||||
{
|
||||
return mc.getConnection();
|
||||
}
|
||||
|
||||
public GameRenderer getGameRenderer()
|
||||
{
|
||||
return mc.gameRenderer;
|
||||
}
|
||||
|
||||
public Entity getCameraEntity()
|
||||
{
|
||||
return mc.cameraEntity;
|
||||
}
|
||||
|
||||
public MainWindow getWindow()
|
||||
{
|
||||
return mc.getWindow();
|
||||
}
|
||||
|
||||
public float getSkyDarken(float partialTicks)
|
||||
{
|
||||
return mc.level.getSkyDarken(partialTicks);
|
||||
}
|
||||
|
||||
public IntegratedServer getSingleplayerServer()
|
||||
{
|
||||
return mc.getSingleplayerServer();
|
||||
}
|
||||
|
||||
public ServerData getCurrentServer()
|
||||
{
|
||||
return mc.getCurrentServer();
|
||||
}
|
||||
|
||||
public WorldRenderer getLevelRenderer()
|
||||
{
|
||||
return mc.levelRenderer;
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ modId="lod" #mandatory
|
||||
#// The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
|
||||
#//${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata
|
||||
#// see the associated build.gradle script for how to populate this completely automatically during a build
|
||||
version="a1.4" #mandatory
|
||||
version="a1.4.1" #mandatory
|
||||
|
||||
#// A display name for the mod
|
||||
displayName="LOD" #mandatory
|
||||
|
||||
Reference in New Issue
Block a user