From 435c5ee73a64c70fe8d7f622f4d47700a7376b0e Mon Sep 17 00:00:00 2001 From: Leonardo Date: Tue, 21 Sep 2021 15:09:28 +0200 Subject: [PATCH] fixed nether roof bug --- .../com/seibel/lod/builders/LodBuilder.java | 58 +++++----- .../com/seibel/lod/objects/LodDimension.java | 42 +------- .../com/seibel/lod/objects/LodRegion.java | 101 +++++------------- .../com/seibel/lod/util/DataPointUtil.java | 49 +++++---- .../com/seibel/lod/util/ThreadMapUtil.java | 5 + 5 files changed, 93 insertions(+), 162 deletions(-) diff --git a/src/main/java/com/seibel/lod/builders/LodBuilder.java b/src/main/java/com/seibel/lod/builders/LodBuilder.java index 30bc8b7cc..37fbda159 100644 --- a/src/main/java/com/seibel/lod/builders/LodBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodBuilder.java @@ -219,8 +219,6 @@ public class LodBuilder posX = LevelPosUtil.convert((byte) 0, chunk.getPos().x * 16 + startX, detail.detailLevel); posZ = LevelPosUtil.convert((byte) 0, chunk.getPos().z * 16 + startZ, detail.detailLevel); long[] data; - boolean isServer = config.distanceGenerationMode == DistanceGenerationMode.SERVER; - switch (verticalQuality) { default: @@ -228,35 +226,41 @@ public class LodBuilder long singleData; long[] dataToMergeSingle = createSingleDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); singleData = DataPointUtil.mergeSingleData(dataToMergeSingle); - lodDim.addSingleData(detailLevel, + lodDim.addData(detailLevel, posX, posZ, + 0, singleData, - false, - isServer); + false); break; case MULTI_LOD: long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ, endX, endZ); + /*for(long dat : dataToMergeVertical){ + if(!DataPointUtil.doesItExist(dat) || DataPointUtil.isItVoid(dat)) + continue; + System.out.println(DataPointUtil.toString(dat)); + }*/ data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.WORLD_HEIGHT, DetailDistanceUtil.getMaxVerticalData(detailLevel)); - lodDim.clear(detailLevel, posX, posZ); + + + //lodDim.clear(detailLevel, posX, posZ); if (data.length != 0 || data != null) { - for (int verticalIndex = 0; (verticalIndex < data.length) && (verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ)); verticalIndex++) + for (int verticalIndex = 0; verticalIndex < lodDim.getMaxVerticalData(detailLevel, posX, posZ); verticalIndex++) { + + if (!DataPointUtil.doesItExist(data[verticalIndex])) + break; lodDim.addData(detailLevel, posX, posZ, verticalIndex, data[verticalIndex], - false, - isServer); + false); } } - break; } - - } lodDim.updateData(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, chunk.getPos().z); } catch (Exception e) @@ -287,15 +291,11 @@ public class LodBuilder int yAbs; int zAbs; boolean hasCeiling = mc.getClientWorld().dimensionType().hasCeiling(); + boolean hasSkyLight = mc.getClientWorld().dimensionType().hasSkyLight(); BlockPos.Mutable blockPos = new BlockPos.Mutable(0, 0, 0); int index; - if (dataToMerge == null) - { - dataToMerge = new long[size * size * DataPointUtil.WORLD_HEIGHT]; - } - for (index = 0; index < size * size; index++) { for (int verticalIndex = 0; verticalIndex < verticalData; verticalIndex++) @@ -308,13 +308,12 @@ public class LodBuilder zAbs = chunkPos.getMinBlockZ() + zRel; //Calculate the height of the lod - yAbs = 255; + yAbs = 1024; int count = 0; boolean topBlock = true; while (yAbs > 0) { height = determineHeightPointFrom(chunk, config, xRel, zRel, yAbs, blockPos); - //If the lod is at default, then we set this as void data if (height == DEFAULT_HEIGHT) { @@ -339,13 +338,22 @@ public class LodBuilder } lightBlock = light & 0b1111; if (!hasCeiling && topBlock) - lightSky = 15; //default max light - else + { + if (hasSkyLight) + { + lightSky = 15; //default max light + } else + { + lightSky = 0; + } + } else + { lightSky = (light >> 4) & 0b1111; - - topBlock = false; + } dataToMerge[index * verticalData + count] = DataPointUtil.createDataPoint(height, depth, color, lightSky, lightBlock, generation); + + topBlock = false; yAbs = depth - 1; count++; } @@ -883,8 +891,8 @@ public class LodBuilder } return blockState.getBlock() != Blocks.AIR - && blockState.getBlock() != Blocks.CAVE_AIR - && blockState.getBlock() != Blocks.BARRIER; + && blockState.getBlock() != Blocks.CAVE_AIR + && blockState.getBlock() != Blocks.BARRIER; } return false; } diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index 39a6b1afe..5c72c3269 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -458,7 +458,7 @@ public class LodDimension * stored in the LOD. If an LOD already exists at the given * coordinates it will be overwritten. */ - public Boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data, boolean dontSave, boolean serverQuality) + public Boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data, boolean dontSave) { // don't continue if the region can't be saved @@ -468,45 +468,7 @@ public class LodDimension LodRegion region = getRegion(regionPosX, regionPosZ); if (region == null) return false; - boolean nodeAdded = region.addData(detailLevel, posX, posZ, verticalIndex, data, 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 = (regionPosX - center.x) + halfWidth; - int zIndex = (regionPosZ - center.z) + halfWidth; - isRegionDirty[xIndex][zIndex] = true; - regionNeedsRegen[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. - } - } - return nodeAdded; - } - - - /** - * Add the given LOD to this dimension at the coordinate - * stored in the LOD. If an LOD already exists at the given - * coordinates it will be overwritten. - */ - public Boolean addSingleData(byte detailLevel, int posX, int posZ, long dataPoint, boolean dontSave, boolean serverQuality) - { - - // don't continue if the region can't be saved - int regionPosX = LevelPosUtil.getRegion(detailLevel, posX); - int regionPosZ = LevelPosUtil.getRegion(detailLevel, posZ); - - LodRegion region = getRegion(regionPosX, regionPosZ); - if (region == null) - return false; - boolean nodeAdded = region.addSingleData(detailLevel, posX, posZ, dataPoint, serverQuality); + boolean nodeAdded = region.addData(detailLevel, posX, posZ, verticalIndex, data); // only save valid LODs to disk if (!dontSave && fileHandler != null) { diff --git a/src/main/java/com/seibel/lod/objects/LodRegion.java b/src/main/java/com/seibel/lod/objects/LodRegion.java index c722e402f..657ee9a12 100644 --- a/src/main/java/com/seibel/lod/objects/LodRegion.java +++ b/src/main/java/com/seibel/lod/objects/LodRegion.java @@ -16,8 +16,6 @@ import com.seibel.lod.util.LodUtil; * if an array contain coordinate the order is the following * 0 for x, 1 for z in 2D * 0 for x, 1 for y, 2 for z in 3D - * - * */ public class LodRegion { @@ -60,7 +58,8 @@ public class LodRegion //Initialize all the different matrices for (byte lod = minDetailLevel; lod <= LodUtil.REGION_DETAIL_LEVEL; lod++) { - switch (verticalQuality){ + switch (verticalQuality) + { default: case HEIGHTMAP: dataContainer[lod] = new SingleLevelContainer(lod); @@ -71,10 +70,12 @@ public class LodRegion } } } + public VerticalQuality getLodQualityMode() { return verticalQuality; } + public DistanceGenerationMode getGenerationMode() { return generationMode; @@ -90,70 +91,15 @@ public class LodRegion * * @return if the data was added successfully */ - public boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data, boolean serverQuality) + public boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data) { posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - if (!doesDataExist(detailLevel, posX, posZ) || serverQuality) - { - //update the number of nodes present - //if (!doesDataExist(detailLevel, posX, posZ)) numberOfPoints++; - - try - { - //add the node data - this.dataContainer[detailLevel].addData(data, posX, posZ, verticalIndex); - return true; - } - catch (NullPointerException e) - { - String detailMessage = "pos: [" + posX + "," + posZ + "] dataPoint: [" + data + "] serverQuality: [" + serverQuality + "] dataContainer"; - detailMessage += this.dataContainer != null ? ": [NULL]" : " at detailLevel: [" + dataContainer[detailLevel] + "]"; - - ClientProxy.LOGGER.error("addSingleData: " + e.getMessage() + "\t" + detailMessage); - return false; - } - } - else - { - return false; - } - } - - /** - * This method can be used to insert data into the LodRegion - * - * @param dataPoint - * @return if the data was added successfully - */ - public boolean addSingleData(byte detailLevel, int posX, int posZ, long dataPoint, boolean serverQuality) - { - posX = LevelPosUtil.getRegionModule(detailLevel, posX); - posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - if (!doesDataExist(detailLevel, posX, posZ) || serverQuality) - { - //update the number of nodes present - //if (!doesDataExist(detailLevel, posX, posZ)) numberOfPoints++; - - try - { - //add the node data - this.dataContainer[detailLevel].addSingleData(dataPoint, posX, posZ); - return true; - } - catch (NullPointerException e) - { - String detailMessage = "pos: [" + posX + "," + posZ + "] dataPoint: [" + dataPoint + "] serverQuality: [" + serverQuality + "] dataContainer"; - detailMessage += this.dataContainer != null ? ": [NULL]" : " at detailLevel: [" + dataContainer[detailLevel] + "]"; - - ClientProxy.LOGGER.error("addSingleData: " + e.getMessage() + "\t" + detailMessage); - return false; - } - } - else - { - return false; - } + //update the number of nodes present + //if (!doesDataExist(detailLevel, posX, posZ)) numberOfPoints++; + //add the node data + this.dataContainer[detailLevel].addData(data, posX, posZ, verticalIndex); + return true; } /** @@ -163,7 +109,7 @@ public class LodRegion */ public long getData(byte detailLevel, int posX, int posZ, int verticalIndex) { - return dataContainer[detailLevel].getData(posX, posZ,verticalIndex); + return dataContainer[detailLevel].getData(posX, posZ, verticalIndex); } /** @@ -180,6 +126,7 @@ public class LodRegion { dataContainer[detailLevel].clear(posX, posZ); } + /** * This method will return all the levelPos that are renderable according to the requisite given in input * @@ -326,6 +273,7 @@ public class LodRegion } /** + * */ public void updateArea(byte detailLevel, int posX, int posZ) { @@ -354,6 +302,7 @@ public class LodRegion } /** + * */ private void update(byte detailLevel, int posX, int posZ) { @@ -366,10 +315,10 @@ public class LodRegion */ public boolean doesDataExist(byte detailLevel, int posX, int posZ) { - if(detailLevel < minDetailLevel) return false; + if (detailLevel < minDetailLevel) return false; posX = LevelPosUtil.getRegionModule(detailLevel, posX); posZ = LevelPosUtil.getRegionModule(detailLevel, posZ); - if(dataContainer == null || dataContainer[detailLevel] == null) + if (dataContainer == null || dataContainer[detailLevel] == null) return false; return dataContainer[detailLevel].doesItExist(posX, posZ); } @@ -379,11 +328,11 @@ public class LodRegion */ public byte getGenerationMode(byte detailLevel, int posX, int posZ) { - if(dataContainer[detailLevel].doesItExist(posX,posZ)) + if (dataContainer[detailLevel].doesItExist(posX, posZ)) { //We take the bottom information always - return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getSingleData(posX,posZ)); - }else + return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getSingleData(posX, posZ)); + } else { return DistanceGenerationMode.NONE.complexity; } @@ -445,13 +394,13 @@ public class LodRegion { if (detailLevel < minDetailLevel) { - for (byte tempLod = (byte) (minDetailLevel - 1); tempLod >= detailLevel ; tempLod--) + for (byte tempLod = (byte) (minDetailLevel - 1); tempLod >= detailLevel; tempLod--) { - if(dataContainer[tempLod + 1] == null) + if (dataContainer[tempLod + 1] == null) { dataContainer[tempLod + 1] = new SingleLevelContainer((byte) (tempLod + 1)); } - dataContainer[tempLod] = dataContainer[tempLod+1].expand(); + dataContainer[tempLod] = dataContainer[tempLod + 1].expand(); } minDetailLevel = detailLevel; } @@ -467,6 +416,7 @@ public class LodRegion /** * return needed memory in byte + * * @param template */ public int getMinMemoryNeeded(LodTemplate template) @@ -489,9 +439,10 @@ public class LodRegion return getLevel(LodUtil.REGION_DETAIL_LEVEL).toString(); } - public int getNumberOfLods(){ + public int getNumberOfLods() + { int count = 0; - for(LevelContainer container : dataContainer) + for (LevelContainer container : dataContainer) count += container.getMaxNumberOfLods(); return count; } diff --git a/src/main/java/com/seibel/lod/util/DataPointUtil.java b/src/main/java/com/seibel/lod/util/DataPointUtil.java index 662ac855d..d6be2b4d0 100644 --- a/src/main/java/com/seibel/lod/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/util/DataPointUtil.java @@ -4,7 +4,6 @@ import com.seibel.lod.enums.DistanceGenerationMode; import net.minecraft.client.renderer.texture.NativeImage; -import java.lang.reflect.Array; import java.util.Arrays; public class DataPointUtil @@ -43,7 +42,7 @@ public class DataPointUtil public final static int BLUE_SHIFT = 36; public final static int GREEN_SHIFT = BLUE_SHIFT + 8; - public final static int RED_SHIFT = BLUE_SHIFT + 16 ; + public final static int RED_SHIFT = BLUE_SHIFT + 16; public final static int ALPHA_SHIFT = BLUE_SHIFT + 24; public final static int COLOR_SHIFT = 36; @@ -98,7 +97,7 @@ public class DataPointUtil public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightSky, int lightBlock, int generationMode) { long dataPoint = 0; - dataPoint += ((alpha >>> ALPHA_DOWNSIZE_SHIFT) & ALPHA_MASK ) << ALPHA_SHIFT; + dataPoint += ((alpha >>> ALPHA_DOWNSIZE_SHIFT) & ALPHA_MASK) << ALPHA_SHIFT; dataPoint += (red & RED_MASK) << RED_SHIFT; dataPoint += (green & GREEN_MASK) << GREEN_SHIFT; dataPoint += (blue & BLUE_MASK) << BLUE_SHIFT; @@ -245,7 +244,7 @@ public class DataPointUtil tempGreen += DataPointUtil.getGreen(data); tempBlue += DataPointUtil.getBlue(data); tempHeight = Math.max(tempHeight, DataPointUtil.getHeight(data)); - tempDepth = Math.min(tempDepth, DataPointUtil.getDepth(data)); + tempDepth = Math.min(tempDepth, DataPointUtil.getDepth(data)); tempLightBlock += DataPointUtil.getLightBlock(data); tempLightSky += DataPointUtil.getLightSky(data); } @@ -277,19 +276,24 @@ public class DataPointUtil } } - public static long[] mergeMultiData(long[] dataToMerge, int inputVerticalData,int maxVerticalData) + public static long[] mergeMultiData(long[] dataToMerge, int inputVerticalData, int maxVerticalData) { int size = dataToMerge.length / inputVerticalData; - short[] projection = ThreadMapUtil.getProjectionShort((WORLD_HEIGHT) / 16 + 1); - short[] heightAndDepth = ThreadMapUtil.getHeightAndDepth(inputVerticalData * 2); + short[] projection = ThreadMapUtil.getProjectionShort((WORLD_HEIGHT) / 16 + 1); + short[] heightAndDepth = ThreadMapUtil.getHeightAndDepth((WORLD_HEIGHT + 1) * 2); long[] singleDataToMerge = ThreadMapUtil.getSingleAddDataToMerge(size); + long[] dataPoint = ThreadMapUtil.verticalDataArray(WORLD_HEIGHT + 1); + Arrays.fill(projection, (short) 0); + Arrays.fill(heightAndDepth, (short) 0); + Arrays.fill(singleDataToMerge, EMPTY_DATA); + Arrays.fill(dataPoint, EMPTY_DATA); + int genMode = DistanceGenerationMode.SERVER.complexity; boolean allEmpty = true; boolean allVoid = true; long singleData; - long[] dataPoint = ThreadMapUtil.verticalDataArray(WORLD_HEIGHT+1); - Arrays.fill(projection, (short) 0); //probably can remove + short depth; short height; @@ -314,11 +318,9 @@ public class DataPointUtil } } } - //We check if there is any data that's not empty or void if (allEmpty) { - dataPoint[0] = EMPTY_DATA; return dataPoint; } if (allVoid) @@ -326,14 +328,13 @@ public class DataPointUtil dataPoint[0] = createVoidDataPoint(genMode); return dataPoint; } - //We extract the merged data int count = 0; int i = 0; int ii = 0; while (i < projection.length) { - while (i < projection.length && projection[i] == 0) i++; + while (i < projection.length && projection[i] == 0) i++; if (i == projection.length) break; //we reached end of WORLD_HEIGHT and it's nothing more here while (ii < 15 && ((projection[i] >>> ii) & 1) == 0) ii++; @@ -343,14 +344,14 @@ public class DataPointUtil i++; continue; } - depth = (short)( i * 16 + ii); + depth = (short) (i * 16 + ii); while (ii < 15 && ((projection[i] >>> ii) & 1) == 1) ii++; if (ii >= 15 && ((projection[i] >>> ii) & 1) == 1) //if end is not in this chunk { ii = 0; i++; - while (i < projection.length && ~(projection[i]) == 0) i++; //check for big solid blocks + while (i < projection.length && ~(projection[i]) == 0) i++; //check for big solid blocks if (i == projection.length) //solid to WORLD_HEIGHT { heightAndDepth[count * 2] = depth; @@ -359,7 +360,7 @@ public class DataPointUtil } while ((((projection[i] >>> ii) & 1) == 1)) ii++; } - height = (short)(i * 16 + ii - 1); + height = (short) (i * 16 + ii - 1); heightAndDepth[count * 2] = depth; heightAndDepth[count * 2 + 1] = height; count++; @@ -379,20 +380,23 @@ public class DataPointUtil } } heightAndDepth[j * 2 + 1] = heightAndDepth[(j + 1) * 2 + 1]; - for (i = j + 1; i < count - 1; i++){ + for (i = j + 1; i < count - 1; i++) + { heightAndDepth[i * 2] = heightAndDepth[(i + 1) * 2]; heightAndDepth[i * 2 + 1] = heightAndDepth[(i + 1) * 2 + 1]; } //System.arraycopy(heightAndDepth,j + 1, heightAndDepth, j,count - j - 1); count--; } - //As standard the vertical lods are ordered from top to bottom - for (j = count - 1; j >= 0; j--) + for (j = 0; j < count; j++) { depth = heightAndDepth[j * 2]; height = heightAndDepth[j * 2 + 1]; - for(int k = 0; k < size; k++){ + if ((depth == 0 && height == 0) || j >= heightAndDepth.length / 2) + break; + for (int k = 0; k < size; k++) + { singleDataToMerge[k] = 0; } for (int index = 0; index < size; index++) @@ -405,7 +409,7 @@ public class DataPointUtil if ((depth <= getDepth(singleData) && getDepth(singleData) <= height) || (depth <= getHeight(singleData) && getHeight(singleData) <= height)) { - if(getHeight(singleData) > getHeight(singleDataToMerge[index])) + if (getHeight(singleData) > getHeight(singleDataToMerge[index])) { singleDataToMerge[index] = singleData; } @@ -414,7 +418,8 @@ public class DataPointUtil } } long data = mergeSingleData(singleDataToMerge); - dataPoint[j] = createDataPoint(height, depth, getColor(data), getLightSky(data), getLightBlock(data), getGenerationMode(data)); + + dataPoint[count - j - 1] = createDataPoint(height, depth, getColor(data), getLightSky(data), getLightBlock(data), getGenerationMode(data)); } return dataPoint; } diff --git a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java index 44de2e53a..e2ba6d016 100644 --- a/src/main/java/com/seibel/lod/util/ThreadMapUtil.java +++ b/src/main/java/com/seibel/lod/util/ThreadMapUtil.java @@ -38,6 +38,11 @@ public class ThreadMapUtil if (!threadBuilderVerticalArrayMap.containsKey(Thread.currentThread().getName()) || (threadBuilderVerticalArrayMap.get(Thread.currentThread().getName()) == null)) { long[][] array = new long[5][]; + for(int i = 0; i < array.length; i++) + { + int size = 1 << i; + array[i] = new long[size * size * DataPointUtil.WORLD_HEIGHT]; + } threadBuilderVerticalArrayMap.put(Thread.currentThread().getName(), array); } return threadBuilderVerticalArrayMap.get(Thread.currentThread().getName());