diff --git a/src/main/java/com/seibel/lod/core/objects/PosToGenerateContainer.java b/src/main/java/com/seibel/lod/core/objects/PosToGenerateContainer.java index b51d777cd..bd7bc3711 100644 --- a/src/main/java/com/seibel/lod/core/objects/PosToGenerateContainer.java +++ b/src/main/java/com/seibel/lod/core/objects/PosToGenerateContainer.java @@ -53,21 +53,22 @@ public class PosToGenerateContainer // TODO what is going on in this method? public void addNearPosToGenerate(byte detailLevel, int posX, int posZ, boolean sort) { - int distance = LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ); + // FIXME: This is a cast from double to int!!! OVERFLOW MAY HAPPEN! + int distance = (int)LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ); int index; //We are introducing a position in the near array index = nearSize; if (index == nearPosToGenerate.length) { - if (LevelPosUtil.compareDistance(distance, nearPosToGenerate[index - 1][3]) > 0) { + if (Integer.compare(distance, nearPosToGenerate[index - 1][3]) > 0) { return; } index--; } else nearSize++; if (sort) { - while (index > 0 && LevelPosUtil.compareDistance(distance, nearPosToGenerate[index - 1][3]) <= 0) + while (index > 0 && Integer.compare(distance, nearPosToGenerate[index - 1][3]) <= 0) { nearPosToGenerate[index][0] = nearPosToGenerate[index - 1][0]; nearPosToGenerate[index][1] = nearPosToGenerate[index - 1][1]; @@ -85,21 +86,22 @@ public class PosToGenerateContainer // TODO what is going on in this method? public void addFarPosToGenerate(byte detailLevel, int posX, int posZ, boolean sort) { - int distance = LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ); + // FIXME: This is a cast from double to int!!! OVERFLOW MAY HAPPEN! + int distance = (int)LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ); int index; // We are introducing a position in the far array index = farSize; if (index == farPosToGenerate.length) { - if (LevelPosUtil.compareDistance(distance, farPosToGenerate[index - 1][3]) > 0) { + if (Integer.compare(distance, farPosToGenerate[index - 1][3]) > 0) { return; } index--; } else farSize++; if (sort) { - while (index > 0 && LevelPosUtil.compareDistance(distance, farPosToGenerate[index - 1][3]) <= 0) + while (index > 0 && Integer.compare(distance, farPosToGenerate[index - 1][3]) <= 0) { farPosToGenerate[index][0] = farPosToGenerate[index - 1][0]; farPosToGenerate[index][1] = farPosToGenerate[index - 1][1]; diff --git a/src/main/java/com/seibel/lod/core/objects/lod/LodDimension.java b/src/main/java/com/seibel/lod/core/objects/lod/LodDimension.java index e315e1025..042f51f0f 100644 --- a/src/main/java/com/seibel/lod/core/objects/lod/LodDimension.java +++ b/src/main/java/com/seibel/lod/core/objects/lod/LodDimension.java @@ -290,7 +290,7 @@ public class LodDimension Pos minPos = regions.getMinInRange(); // go over every region in the dimension iterateWithSpiral((int x, int z) -> { - int minDistance; + double minDistance; byte detail; LodRegion region = regions.get(x+minPos.x, z+minPos.y); @@ -358,8 +358,8 @@ public class LodDimension int regionX; int regionZ; LodRegion region; - int minDistance; - int maxDistance; + double minDistance; + double maxDistance; byte minDetail; byte maxDetail; regionX = x + minPos.x; @@ -372,6 +372,19 @@ public class LodDimension playerPosZ); maxDistance = LevelPosUtil.maxDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ, playerPosX, playerPosZ); + { + double debugRPosX = LevelPosUtil.convert(LodUtil.REGION_DETAIL_LEVEL, regionX, (byte) 0) + LodUtil.REGION_WIDTH/2; + double debugRPosZ = LevelPosUtil.convert(LodUtil.REGION_DETAIL_LEVEL, regionZ, (byte) 0) + LodUtil.REGION_WIDTH/2; + double deltaRPosX = debugRPosX - playerPosX; + double deltaRPosZ = debugRPosZ - playerPosZ; + double debugDistance = Math.sqrt(deltaRPosX*deltaRPosX + deltaRPosZ*deltaRPosZ); + if (minDistance > debugDistance || maxDistance < debugDistance || minDistance > maxDistance) { + ClientApi.LOGGER.error("MinDistance/MaxDistance is WRONG!!! minDist: [{}], maxDist: [{}], centerDist: [{}]\n" + + "At center block pos: {} {}, region pos: {}", + minDistance, maxDistance, debugDistance, debugRPosX, debugRPosZ, regionPos); + return; + } + } minDetail = DetailDistanceUtil.getDetailLevelFromDistance(minDistance); maxDetail = DetailDistanceUtil.getDetailLevelFromDistance(maxDistance); boolean updated = false; @@ -695,6 +708,7 @@ public class LodDimension ramLogger.info("Dumping Ram Usage for LodDim in {} with {} regions...", dimension.getDimensionName(), regionCount); int nonNullRegionCount = 0; int dirtiedRegionCount = 0; + int writingRegionCount = 0; long totalUsage = 0; int[] detailCount = new int[LodUtil.DETAIL_OPTIONS]; long[] detailUsage = new long[LodUtil.DETAIL_OPTIONS]; @@ -702,11 +716,15 @@ public class LodDimension if (r==null) continue; nonNullRegionCount++; if (r.needSaving) dirtiedRegionCount++; + if (r.isWriting != 0) writingRegionCount++; LevelContainer[] container = r.debugGetDataContainers().clone(); if (container == null || container.length != LodUtil.DETAIL_OPTIONS) { ClientApi.LOGGER.warn("DumpRamUsage encountered an invalid region!"); continue; } + + + for (int i = 0; i < LodUtil.DETAIL_OPTIONS; i++) { if (container[i] == null) continue; detailCount[i]++; @@ -716,8 +734,8 @@ public class LodDimension } } ramLogger.info("================================================"); - ramLogger.info("Non Null Regions: [{}], Dirtied Regions: [{}], Bytes: [{}]", - nonNullRegionCount, dirtiedRegionCount, new UnitBytes(totalUsage)); + ramLogger.info("Non Null Regions: [{}], Dirtied Regions: [{}], Writing Regions: [{}], Bytes: [{}]", + nonNullRegionCount, dirtiedRegionCount, writingRegionCount, new UnitBytes(totalUsage)); ramLogger.info("------------------------------------------------"); for (int i = 0; i < LodUtil.DETAIL_OPTIONS; i++) { ramLogger.info("DETAIL {}: Containers: [{}], Bytes: [{}]", i, detailCount[i], new UnitBytes(detailUsage[i])); diff --git a/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java b/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java index d2ebb8e91..aba1b2cf0 100644 --- a/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java +++ b/src/main/java/com/seibel/lod/core/objects/lod/LodRegion.java @@ -228,7 +228,7 @@ public class LodRegion { int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); // calculate what LevelPos are in range to generate - int minDistance = LevelPosUtil.minDistance(detailLevel, offsetPosX + regionPosX*size, offsetPosZ + regionPosZ*size, playerPosX, playerPosZ); + double minDistance = LevelPosUtil.minDistance(detailLevel, offsetPosX + regionPosX*size, offsetPosZ + regionPosZ*size, playerPosX, playerPosZ); // determine this child's levelPos byte childDetailLevel = (byte) (detailLevel - 1); @@ -276,14 +276,14 @@ public class LodRegion { */ public void getPosToRender(PosToRenderContainer posToRender, int playerPosX, int playerPosZ, GenerationPriority priority, DropoffQuality dropoffQuality) { - int minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ, playerPosX, playerPosZ); + double minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ, playerPosX, playerPosZ); byte targetLevel = DetailDistanceUtil.getDetailLevelFromDistance(minDistance); if (targetLevel <= dropoffQuality.fastModeSwitch) { getPosToRender(posToRender, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerPosX, playerPosZ, priority); } else { // FarModeSwitchLevel or above is the level where a giant block of lod is not acceptable even if not all child data exist. - int maxDistance = LevelPosUtil.maxDistance(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ, playerPosX, playerPosZ); + double maxDistance = LevelPosUtil.maxDistance(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ, playerPosX, playerPosZ); byte farModeSwitchLevel = (priority == GenerationPriority.NEAR_FIRST) ? 0 : calculateFarModeSwitch(DetailDistanceUtil.getDetailLevelFromDistance(maxDistance)); if (priority == GenerationPriority.FAR_FIRST) farModeSwitchLevel = 8; @@ -305,7 +305,7 @@ public class LodRegion { int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); // calculate the LevelPos that are in range - int minDistance = LevelPosUtil.minDistance(detailLevel, offsetPosX + regionPosX*size, offsetPosZ + regionPosZ*size, playerPosX, playerPosZ); + double minDistance = LevelPosUtil.minDistance(detailLevel, offsetPosX + regionPosX*size, offsetPosZ + regionPosZ*size, playerPosX, playerPosZ); byte minLevel = DetailDistanceUtil.getDetailLevelFromDistance(minDistance); // FarModeSwitchLevel or above is the level where a giant block of lod is not acceptable even if not all child data exist. byte farModeSwitchLevel = (priority == GenerationPriority.NEAR_FIRST) ? 0 : calculateFarModeSwitch(minLevel); diff --git a/src/main/java/com/seibel/lod/core/util/DetailDistanceUtil.java b/src/main/java/com/seibel/lod/core/util/DetailDistanceUtil.java index 7cfda903c..0eb04d8df 100644 --- a/src/main/java/com/seibel/lod/core/util/DetailDistanceUtil.java +++ b/src/main/java/com/seibel/lod/core/util/DetailDistanceUtil.java @@ -19,6 +19,7 @@ package com.seibel.lod.core.util; +import com.seibel.lod.core.api.ClientApi; import com.seibel.lod.core.enums.config.HorizontalQuality; import com.seibel.lod.core.enums.config.HorizontalResolution; import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton; @@ -42,10 +43,10 @@ public class DetailDistanceUtil private static final double treeCutMultiplier = 1.0; private static byte minGenDetail = CONFIG.client().graphics().quality().getDrawResolution().detailLevel; private static byte minDrawDetail = CONFIG.client().graphics().quality().getDrawResolution().detailLevel; - private static final int maxDetail = LodUtil.REGION_DETAIL_LEVEL + 1; - private static final int minDistance = 0; - private static int minDetailDistance = (int) (MC_RENDER.getRenderDistance()*16 * 1.42f); - private static int maxDistance = CONFIG.client().graphics().quality().getLodChunkRenderDistance() * 16 * 2; + private static final byte maxDetail = LodUtil.DETAIL_OPTIONS; + private static final double minDistance = 0; + private static double minDetailDistance = (int) (MC_RENDER.getRenderDistance()*16 * 1.42f); + private static double maxDistance = CONFIG.client().graphics().quality().getLodChunkRenderDistance() * 16 * 2; public static void updateSettings() @@ -56,8 +57,7 @@ public class DetailDistanceUtil maxDistance = CONFIG.client().graphics().quality().getLodChunkRenderDistance() * 16 * 8; } - /*// Need UPDATE and BUG FIX - public static int baseDistanceFunction(int detail) + public static double baseDistanceFunction(int detail) { if (detail <= minGenDetail) return minDistance; @@ -69,21 +69,27 @@ public class DetailDistanceUtil int distanceUnit = CONFIG.client().graphics().quality().getHorizontalScale() * 16; if (CONFIG.client().graphics().quality().getHorizontalQuality() == HorizontalQuality.LOWEST) - return (detail * distanceUnit); + return ((double)detail * distanceUnit); else { double base = CONFIG.client().graphics().quality().getHorizontalQuality().quadraticBase; - return (int) (Math.pow(base, detail) * distanceUnit); + return Math.pow(base, detail) * distanceUnit; } } - public static int getDrawDistanceFromDetail(int detail) + public static double getDrawDistanceFromDetail(int detail) { return baseDistanceFunction(detail); - }*/ + } - public static byte baseInverseFunction(int distance, byte minDetail) + public static byte baseInverseFunction(double distance, byte minDetail) { + double maxDetailDistance = getDrawDistanceFromDetail(maxDetail-1); + if (distance > maxDetailDistance) { + //ClientApi.LOGGER.info("DEBUG: Scale as max: {}", distance); + return maxDetail-1; + } + int detail; distance -= minDetailDistance; @@ -103,34 +109,10 @@ public class DetailDistanceUtil return (byte) LodUtil.clamp(minDetail, detail+minDetail, maxDetail - 1); } - public static byte getDetailLevelFromDistance(int distance) + public static byte getDetailLevelFromDistance(double distance) { return baseInverseFunction(distance, minDrawDetail); } - - @Deprecated //Reason: All merged into `getDetailLevelFromDistance` - public static byte getDrawDetailFromDistance(int distance) - { - return baseInverseFunction(distance, minDrawDetail); - } - - @Deprecated //Reason: Same as 'getDrawDetailFromDistance' - public static byte getGenerationDetailFromDistance(int distance) - { - return baseInverseFunction((int) (distance * genMultiplier), minGenDetail); - } - - @Deprecated //Reason: Same as 'getDrawDetailFromDistance' - public static byte getTreeCutDetailFromDistance(int distance) - { - return baseInverseFunction((int) (distance * treeCutMultiplier), minGenDetail); - } - - @Deprecated //Reason: Same as 'getDrawDetailFromDistance' - public static byte getTreeGenDetailFromDistance(int distance) - { - return baseInverseFunction((int) (distance * treeGenMultiplier), minGenDetail); - } // NOTE: The recent LodWorldGenerator changes assumes that this value doesn't change with 'detail'. @@ -141,15 +123,6 @@ public class DetailDistanceUtil return CONFIG.client().worldGenerator().getDistanceGenerationMode(); }*/ - @Deprecated - public static byte getLodDrawDetail(byte detail) - { - detail += minDrawDetail; - if (detail > 10) - detail = 10; - return detail; - } - public static int getMaxVerticalData(int detail) { return CONFIG.client().graphics().quality().getVerticalQuality().maxVerticalData[LodUtil.clamp(minGenDetail, detail, LodUtil.REGION_DETAIL_LEVEL)]; diff --git a/src/main/java/com/seibel/lod/core/util/LevelPosUtil.java b/src/main/java/com/seibel/lod/core/util/LevelPosUtil.java index 626e8f03d..cbef70b8c 100644 --- a/src/main/java/com/seibel/lod/core/util/LevelPosUtil.java +++ b/src/main/java/com/seibel/lod/core/util/LevelPosUtil.java @@ -149,32 +149,32 @@ public class LevelPosUtil return convert(detailLevel, pos, LodUtil.CHUNK_DETAIL_LEVEL); } - public static int myPow2(int x) + public static double myPow2(double x) { return x*x; } - public static int maxDistance(byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ) + public static double maxDistance(byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ) { int width = 1 << detailLevel; - int startPosX = posX * width; - int startPosZ = posZ * width; - int endPosX = myPow2(playerPosX - startPosX - width); - int endPosZ = myPow2(playerPosZ - startPosZ - width); + double startPosX = posX * width; + double startPosZ = posZ * width; + double endPosX = myPow2(playerPosX - startPosX - width); + double endPosZ = myPow2(playerPosZ - startPosZ - width); startPosX = myPow2(playerPosX - startPosX); startPosZ = myPow2(playerPosZ - startPosZ); - int maxDistance = (int) Math.sqrt(startPosX + startPosZ); - maxDistance = Math.max(maxDistance, (int) Math.sqrt(startPosX + endPosZ)); - maxDistance = Math.max(maxDistance, (int) Math.sqrt(endPosX + startPosZ)); - maxDistance = Math.max(maxDistance, (int) Math.sqrt(endPosX + endPosZ)); + double maxDistance = Math.sqrt(startPosX + startPosZ); + maxDistance = Math.max(maxDistance, Math.sqrt(startPosX + endPosZ)); + maxDistance = Math.max(maxDistance, Math.sqrt(endPosX + startPosZ)); + maxDistance = Math.max(maxDistance, Math.sqrt(endPosX + endPosZ)); return maxDistance; } - public static int minDistance(byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ) + public static double minDistance(byte detailLevel, int posX, int posZ, int playerPosX, int playerPosZ) { int width = 1 << detailLevel; @@ -203,35 +203,27 @@ public class LevelPosUtil } else { - startPosX = myPow2(playerPosX - startPosX); - startPosZ = myPow2(playerPosZ - startPosZ); - endPosX = myPow2(playerPosX - endPosX); - endPosZ = myPow2(playerPosZ - endPosZ); + double startPosX2 = myPow2(playerPosX - startPosX); + double startPosZ2 = myPow2(playerPosZ - startPosZ); + double endPosX2 = myPow2(playerPosX - endPosX); + double endPosZ2 = myPow2(playerPosZ - endPosZ); - int minDistance = (int) Math.sqrt(startPosX + startPosZ); - minDistance = Math.min(minDistance, (int) Math.sqrt(startPosX + endPosZ)); - minDistance = Math.min(minDistance, (int) Math.sqrt(endPosX + startPosZ)); - minDistance = Math.min(minDistance, (int) Math.sqrt(endPosX + endPosZ)); + double minDistance = Math.sqrt(startPosX2 + startPosZ2); + minDistance = Math.min(minDistance, Math.sqrt(startPosX2 + endPosZ2)); + minDistance = Math.min(minDistance, Math.sqrt(endPosX2 + startPosZ2)); + minDistance = Math.min(minDistance, Math.sqrt(endPosX2 + endPosZ2)); return minDistance; } } - public static int compareDistance(int firstDistance, int secondDistance) + public static double compareLevelAndDistance(byte firstDetail, double firstDistance, byte secondDetail, double secondDistance) { - return Integer.compare( - firstDistance, - secondDistance); - } - - - public static int compareLevelAndDistance(byte firstDetail, int firstDistance, byte secondDetail, int secondDistance) - { - int compareResult = Integer.compare( + int compareResult = Byte.compare( secondDetail, firstDetail); if (compareResult == 0) { - compareResult = Integer.compare( + compareResult = Double.compare( firstDistance, secondDistance); }