changed the generation. Added re-use of levelPos
This commit is contained in:
@@ -1,13 +1,9 @@
|
||||
package com.seibel.lod.builders.worldGeneration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.seibel.lod.builders.GenerationRequest;
|
||||
import com.seibel.lod.builders.LodBuilder;
|
||||
@@ -20,11 +16,13 @@ import com.seibel.lod.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.util.LodThreadFactory;
|
||||
import com.seibel.lod.util.LodUtil;
|
||||
|
||||
import javafx.collections.transformation.SortedList;
|
||||
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;
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
|
||||
/**
|
||||
* A singleton that handles all long distance LOD world generation.
|
||||
@@ -69,6 +67,11 @@ public class LodWorldGenerator
|
||||
*/
|
||||
public static final LodWorldGenerator INSTANCE = new LodWorldGenerator();
|
||||
|
||||
public volatile ConcurrentMap<LevelPos, MutableBoolean> nodeToGenerate;
|
||||
|
||||
SortedSet<LevelPos> nodeToGenerateListNear;
|
||||
SortedSet<LevelPos> nodeToGenerateListFar;
|
||||
|
||||
private LodWorldGenerator()
|
||||
{
|
||||
|
||||
@@ -107,72 +110,84 @@ public class LodWorldGenerator
|
||||
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
|
||||
ArrayList<GenerationRequest> chunksToGenReserve = new ArrayList<>(maxChunkGenRequests);
|
||||
|
||||
// how many level positions to
|
||||
int requesting = maxChunkGenRequests;
|
||||
|
||||
|
||||
//=======================================//
|
||||
// create the generation Request objects //
|
||||
//=======================================//
|
||||
List<GenerationRequest> generationRequestList = new ArrayList<>(maxChunkGenRequests);
|
||||
|
||||
List<LevelPos> farLevelPosListToGen;
|
||||
List<LevelPos> nearLevelPosListToGen;
|
||||
List<GenerationRequest> generationRequestList = new ArrayList<>();
|
||||
if (nodeToGenerate == null)
|
||||
nodeToGenerate = new ConcurrentHashMap<>();
|
||||
|
||||
// start by generating half-region sized blocks...
|
||||
int farRequesting = maxChunkGenRequests / 4;
|
||||
byte maxDetailFar = (byte) 8;
|
||||
//int farRequest = maxChunkGenRequests / 4;
|
||||
//int nearRequest = maxChunkGenRequests * 3 /4;
|
||||
//we firstly make sure that the world is filled with half region wide block
|
||||
|
||||
farLevelPosListToGen = lodDim.getDataToGenerate(
|
||||
Comparator<LevelPos> posComparator = LevelPos.getPosComparator(
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ(),
|
||||
DetailDistanceUtil.getDistanceGenerationMode(maxDetailFar).complexity,
|
||||
maxDetailFar,
|
||||
farRequesting);
|
||||
farRequesting = farRequesting - farLevelPosListToGen.size();
|
||||
|
||||
playerBlockPosRounded.getZ());
|
||||
Comparator<LevelPos> posLevelComparator = LevelPos.getPosAndDetailComparator(
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ());
|
||||
nodeToGenerateListNear = new TreeSet(posComparator);
|
||||
nodeToGenerateListFar = new TreeSet(posLevelComparator);
|
||||
// ...then once the world is filled with big sized blocks
|
||||
// fill in the rest
|
||||
int nearRequesting = maxChunkGenRequests - maxChunkGenRequests / 4 + farRequesting;
|
||||
//int nearRequesting = maxChunkGenRequests - maxChunkGenRequests / 4 + farRequesting;
|
||||
//we then fill the world with the rest of the block
|
||||
|
||||
nearLevelPosListToGen = lodDim.getDataToGenerate(
|
||||
lodDim.getDataToGenerate(
|
||||
nodeToGenerate,
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ(),
|
||||
DetailDistanceUtil.getDistanceGenerationMode(0).complexity,
|
||||
DetailDistanceUtil.getLodDetail(0).detailLevel,
|
||||
nearRequesting);
|
||||
playerBlockPosRounded.getZ());
|
||||
|
||||
// how many level positions to
|
||||
int requesting = maxChunkGenRequests;
|
||||
|
||||
byte farDetail = (byte) 7;
|
||||
//We alternate the generation between fast and near to make everything more smooth
|
||||
for (LevelPos pos : nodeToGenerate.keySet())
|
||||
{
|
||||
if (!nodeToGenerate.get(pos).booleanValue())
|
||||
{
|
||||
nodeToGenerate.remove(pos);
|
||||
} else
|
||||
{
|
||||
if (pos.detailLevel > farDetail){
|
||||
nodeToGenerateListFar.add(pos);
|
||||
}
|
||||
nodeToGenerateListNear.add(pos);
|
||||
nodeToGenerate.get(pos).setFalse();
|
||||
}
|
||||
}
|
||||
|
||||
byte minDetail;
|
||||
int maxDistance;
|
||||
byte circle;
|
||||
LevelPos levelPos;
|
||||
//We alternate the generation between fast and near to make everything more smooth
|
||||
while(!nearLevelPosListToGen.isEmpty() || !farLevelPosListToGen.isEmpty()){
|
||||
if(!nearLevelPosListToGen.isEmpty())
|
||||
int requestingFar = maxChunkGenRequests / 4;
|
||||
while (requesting > 0 && !nodeToGenerateListNear.isEmpty())
|
||||
{
|
||||
levelPos = nodeToGenerateListNear.first();
|
||||
nodeToGenerate.remove(levelPos);
|
||||
nodeToGenerateListNear.remove(levelPos);
|
||||
|
||||
maxDistance = levelPos.maxDistance( playerBlockPosRounded.getX(), playerBlockPosRounded.getZ());
|
||||
circle = DetailDistanceUtil.getDistanceGenerationInverse(maxDistance);
|
||||
generationRequestList.add(new GenerationRequest(levelPos, DetailDistanceUtil.getDistanceGenerationMode(circle), DetailDistanceUtil.getLodDetail(circle)));
|
||||
requesting--;
|
||||
if (requestingFar > 0 && !nodeToGenerateListFar.isEmpty())
|
||||
{
|
||||
levelPos = nearLevelPosListToGen.get(0);
|
||||
nearLevelPosListToGen.remove(0);
|
||||
minDetail = (byte) 0;
|
||||
maxDistance = levelPos.maxDistance(
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ());
|
||||
circle = DetailDistanceUtil.getDistanceGenerationInverse(maxDistance, minDetail);
|
||||
generationRequestList.add(new GenerationRequest(levelPos, DetailDistanceUtil.getDistanceGenerationMode(circle), DetailDistanceUtil.getLodDetail(circle)));
|
||||
}
|
||||
if(!farLevelPosListToGen.isEmpty())
|
||||
{
|
||||
levelPos = farLevelPosListToGen.get(0);
|
||||
farLevelPosListToGen.remove(0);
|
||||
minDetail = maxDetailFar;
|
||||
maxDistance = levelPos.maxDistance(
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ());
|
||||
circle = DetailDistanceUtil.getDistanceGenerationInverse(maxDistance, minDetail);
|
||||
generationRequestList.add(new GenerationRequest(levelPos, DetailDistanceUtil.getDistanceGenerationMode(circle), DetailDistanceUtil.getLodDetail(circle)));
|
||||
levelPos = nodeToGenerateListFar.first();
|
||||
if (levelPos.detailLevel >= farDetail)
|
||||
{
|
||||
maxDistance = levelPos.maxDistance( playerBlockPosRounded.getX(), playerBlockPosRounded.getZ());
|
||||
circle = DetailDistanceUtil.getDistanceGenerationInverse(maxDistance);
|
||||
generationRequestList.add(new GenerationRequest(levelPos, DetailDistanceUtil.getDistanceGenerationMode(circle), DetailDistanceUtil.getLodDetail(circle)));
|
||||
requestingFar--;
|
||||
requesting--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,71 +201,18 @@ public class LodWorldGenerator
|
||||
for (GenerationRequest generationRequest : generationRequestList)
|
||||
{
|
||||
ChunkPos chunkPos = generationRequest.getChunkPos();
|
||||
|
||||
if (numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests)
|
||||
{
|
||||
// prevent generating the same chunk multiple times
|
||||
if (positionWaitingToBeGenerated.contains(chunkPos))
|
||||
{
|
||||
// ClientProxy.LOGGER.debug(pos + " asked to be generated again.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// determine if this position is closer to the player
|
||||
// than the previous
|
||||
int newDistance = playerChunkPos.getChessboardDistance(chunkPos);
|
||||
|
||||
if (newDistance < minChunkDist)
|
||||
{
|
||||
// this chunk is closer, clear any previous
|
||||
// positions and update the new minimum distance
|
||||
minChunkDist = newDistance;
|
||||
|
||||
// move all the old chunks into the reserve
|
||||
ArrayList<GenerationRequest> oldReserve = new ArrayList<>(chunksToGenReserve);
|
||||
chunksToGenReserve.clear();
|
||||
chunksToGenReserve.addAll(chunksToGen);
|
||||
// top off reserve with whatever was in oldReerve
|
||||
for (int i = 0; i < oldReserve.size(); i++)
|
||||
{
|
||||
if (chunksToGenReserve.size() < maxChunkGenRequests)
|
||||
chunksToGenReserve.add(oldReserve.get(i));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
chunksToGen.clear();
|
||||
chunksToGen.add(generationRequest);
|
||||
} else if (newDistance == minChunkDist)
|
||||
{
|
||||
// this chunk position as close as the minimum distance
|
||||
if (chunksToGen.size() < maxChunkGenRequests)
|
||||
{
|
||||
// we are still under the number of chunks to generate
|
||||
// add this position to the list
|
||||
chunksToGen.add(generationRequest);
|
||||
}
|
||||
} else
|
||||
{
|
||||
// this chunk is farther away than the minimum distance,
|
||||
// add it to the reserve to make sure we always have a full reserve
|
||||
chunksToGenReserve.add(generationRequest);
|
||||
}
|
||||
chunksToGen.add(generationRequest);
|
||||
|
||||
} // lod null and can generate more chunks
|
||||
} // positions to generate
|
||||
|
||||
// fill up chunksToGen from the reserve if it isn't full
|
||||
// already
|
||||
if (chunksToGen.size() < maxChunkGenRequests)
|
||||
{
|
||||
Iterator<GenerationRequest> reserveIterator = chunksToGenReserve.iterator();
|
||||
while (chunksToGen.size() < maxChunkGenRequests && reserveIterator.hasNext())
|
||||
{
|
||||
chunksToGen.add(reserveIterator.next());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================//
|
||||
// start the LodNodeGenWorkers //
|
||||
|
||||
@@ -179,12 +179,12 @@ public class LodConfig
|
||||
.comment("\n\n"
|
||||
+ " this value is multiplied by 128 and determine \n"
|
||||
+ " how much the quality decrease over distance \n")
|
||||
.defineInRange("lodQuality", 1, 2, 4);
|
||||
.defineInRange("lodQuality", 1, 1, 4);
|
||||
|
||||
lodChunkRenderDistance = builder
|
||||
.comment("\n\n"
|
||||
+ " This is the render distance of the mod \n")
|
||||
.defineInRange("lodChunkRenderDistane", 64, 32, 256);
|
||||
.defineInRange("lodChunkRenderDistane", 64, 32, 512);
|
||||
|
||||
distanceGenerationMode = builder
|
||||
.comment("\n\n"
|
||||
|
||||
@@ -11,7 +11,7 @@ public class LevelPos implements Cloneable, ImmutableLevelPos, MutableLevelPos,
|
||||
public byte detailLevel;
|
||||
public int posX;
|
||||
public int posZ;
|
||||
|
||||
public boolean flag;
|
||||
|
||||
public LevelPos()
|
||||
{
|
||||
@@ -298,7 +298,7 @@ public class LevelPos implements Cloneable, ImmutableLevelPos, MutableLevelPos,
|
||||
@Override
|
||||
public int compare(LevelPos first, LevelPos second)
|
||||
{
|
||||
int compareResult = Integer.compare(first.detailLevel, second.detailLevel);
|
||||
int compareResult = Integer.compare(second.detailLevel, first.detailLevel);
|
||||
if (compareResult == 0)
|
||||
{
|
||||
compareResult = Integer.compare(
|
||||
|
||||
@@ -20,10 +20,7 @@ package com.seibel.lod.objects;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -484,7 +481,7 @@ public class LodDimension
|
||||
*
|
||||
* @return list of quadTrees
|
||||
*/
|
||||
public List<LevelPos> getDataToGenerate(int playerPosX, int playerPosZ, byte generation, byte detailLevel, int dataNumber)
|
||||
public void getDataToGenerate(ConcurrentMap<LevelPos, MutableBoolean> dataToGenerate, int playerPosX, int playerPosZ)
|
||||
{
|
||||
|
||||
int n = regions.length;
|
||||
@@ -492,7 +489,6 @@ public class LodDimension
|
||||
int zIndex;
|
||||
LodRegion region;
|
||||
RegionPos regionPos;
|
||||
List<LevelPos> listOfData = new ArrayList<>();
|
||||
for (int xRegion = 0; xRegion < n; xRegion++)
|
||||
{
|
||||
for (int zRegion = 0; zRegion < n; zRegion++)
|
||||
@@ -503,7 +499,7 @@ public class LodDimension
|
||||
zIndex = (zRegion + center.z) - halfWidth;
|
||||
regionPos = new RegionPos(xIndex, zIndex);
|
||||
region = getRegion(regionPos);
|
||||
listOfData.addAll(region.getDataToGenerate(playerPosX, playerPosZ, generation, detailLevel, dataNumber));
|
||||
region.getDataToGenerate(dataToGenerate, playerPosX, playerPosZ);
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
@@ -511,17 +507,6 @@ public class LodDimension
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<LevelPos> levelMinPosList = new ArrayList<>();
|
||||
dataNumber = Math.min(dataNumber, listOfData.size());
|
||||
|
||||
for (int i = 0; i < dataNumber; i++)
|
||||
{
|
||||
LevelPos min = Collections.min(listOfData, LevelPos.getPosComparator(playerPosX, playerPosZ));
|
||||
listOfData.remove(min);
|
||||
levelMinPosList.add(min);
|
||||
}
|
||||
return levelMinPosList;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -172,33 +172,20 @@ public class LodRegion implements Serializable
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<LevelPos> getDataToGenerate(int playerPosX, int playerPosZ, byte generation, byte detailLevel, int dataNumber)
|
||||
public void getDataToGenerate(ConcurrentMap<LevelPos, MutableBoolean> dataToGenerate, int playerPosX, int playerPosZ)
|
||||
{
|
||||
LevelPos levelPos = new LevelPos(LodUtil.REGION_DETAIL_LEVEL, 0, 0);
|
||||
List<LevelPos> levelPosList = new ArrayList<>();
|
||||
getDataToGenerate(levelPosList, levelPos, playerPosX, playerPosZ, generation, detailLevel);
|
||||
List<LevelPos> levelMinPosList = new ArrayList<>();
|
||||
dataNumber = Math.min(dataNumber, levelPosList.size());
|
||||
|
||||
LevelPos min;
|
||||
for (int i = 0; i < dataNumber; i++)
|
||||
{
|
||||
min = Collections.min(levelPosList, LevelPos.getPosComparator(playerPosX, playerPosZ));
|
||||
levelPosList.remove(min);
|
||||
levelMinPosList.add(min);
|
||||
}
|
||||
|
||||
return levelMinPosList;
|
||||
getDataToGenerate(dataToGenerate, levelPos, playerPosX, playerPosZ);
|
||||
|
||||
}
|
||||
|
||||
private void getDataToGenerate(List<LevelPos> levelPosList, LevelPos levelPos, int playerPosX, int playerPosZ, byte generation, byte targetDetailLevel)
|
||||
private void getDataToGenerate(ConcurrentMap<LevelPos, MutableBoolean> dataToGenerate, LevelPos levelPos, int playerPosX, int playerPosZ)
|
||||
{
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - levelPos.detailLevel);
|
||||
|
||||
//here i calculate the the LevelPos is in range
|
||||
//This is important to avoid any kind of hole in the generation
|
||||
int maxDistance = levelPos.maxDistance(playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
int minDistance = levelPos.minDistance(playerPosX, playerPosZ, regionPosX, regionPosZ);
|
||||
|
||||
|
||||
int posX = levelPos.posX;
|
||||
@@ -210,15 +197,21 @@ public class LodRegion implements Serializable
|
||||
int childSize = 1 << (LodUtil.REGION_DETAIL_LEVEL - levelPos.detailLevel + 1);
|
||||
//we have reached the target detail level
|
||||
|
||||
if (DetailDistanceUtil.getDistanceGenerationInverse(maxDistance,targetDetailLevel) > detailLevel)
|
||||
if (DetailDistanceUtil.getDistanceGenerationInverse(minDistance) > detailLevel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (DetailDistanceUtil.getDistanceGenerationInverse(maxDistance,targetDetailLevel) == levelPos.detailLevel)
|
||||
else if (DetailDistanceUtil.getDistanceGenerationInverse(minDistance) == detailLevel)
|
||||
{
|
||||
if (!doesDataExist(levelPos))
|
||||
{
|
||||
levelPosList.add(new LevelPos(detailLevel, posX + regionPosX * size, posZ + regionPosZ * size));
|
||||
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));
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
@@ -236,7 +229,13 @@ public class LodRegion implements Serializable
|
||||
if (!doesDataExist(levelPos))
|
||||
{
|
||||
num++;
|
||||
levelPosList.add(new LevelPos(levelPos.detailLevel, levelPos.posX + regionPosX * childSize, levelPos.posZ + regionPosZ * childSize));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,25 +248,25 @@ public class LodRegion implements Serializable
|
||||
for (int z = 0; z <= 1; z++)
|
||||
{
|
||||
levelPos.changeParameters((byte) (detailLevel - 1), childPosX + x, childPosZ + z);
|
||||
getDataToGenerate(levelPosList, levelPos,
|
||||
playerPosX, playerPosZ, generation, targetDetailLevel);
|
||||
getDataToGenerate(dataToGenerate, levelPos, playerPosX, playerPosZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
//now we keep exploring the top right child
|
||||
{
|
||||
levelPos.changeParameters(levelPos.detailLevel, levelPos.posX, levelPos.posZ);
|
||||
levelPos.convert((byte) (levelPos.detailLevel - 1));
|
||||
levelPos.changeParameters((byte) (detailLevel-1), levelPos.posX*2 + regionPosX * childSize, levelPos.posZ*2 + regionPosZ * childSize);
|
||||
if (!doesDataExist(levelPos))
|
||||
{
|
||||
levelPosList.add(new LevelPos(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));
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (levelPos.detailLevel != targetDetailLevel)
|
||||
{
|
||||
getDataToGenerate(levelPosList, levelPos, playerPosX, playerPosZ, generation, targetDetailLevel);
|
||||
}
|
||||
getDataToGenerate(dataToGenerate, levelPos, playerPosX, playerPosZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ public class LodRenderer
|
||||
// should LODs be regenerated?
|
||||
long newTime = System.currentTimeMillis();
|
||||
//We check if the player has moved
|
||||
if (newTime - prevPlayerPosTime > 2000)
|
||||
if (newTime - prevPlayerPosTime > 5000)
|
||||
{
|
||||
if (previousPos.detailLevel == 0 ||
|
||||
player.xChunk != previousPos.posX ||
|
||||
@@ -233,7 +233,7 @@ public class LodRenderer
|
||||
prevPlayerPosTime = newTime;
|
||||
}
|
||||
//We check if the vanilla rendered chunks are changed
|
||||
if (newTime - prevVanillaChunkTime > 1000)
|
||||
if (newTime - prevVanillaChunkTime > 5000)
|
||||
{
|
||||
if (previousVanillaRenderedChunks.equals(vanillaRenderedChunks))
|
||||
{
|
||||
|
||||
@@ -98,13 +98,11 @@ public class DetailDistanceUtil
|
||||
return (byte) Math.min(detail, LodUtil.REGION_DETAIL_LEVEL);
|
||||
}
|
||||
|
||||
public static byte getDistanceGenerationInverse(int distance, byte minDetailLevel)
|
||||
public static byte getDistanceGenerationInverse(int distance)
|
||||
{
|
||||
return (byte) Math.max(getDistanceRenderingInverse((int) (distance * genMultiplier))
|
||||
,minDetailLevel);
|
||||
return getDistanceRenderingInverse((int) (distance * genMultiplier));
|
||||
}
|
||||
|
||||
|
||||
public static byte getDistanceTreeCutInverse(int distance)
|
||||
{
|
||||
return getDistanceRenderingInverse((int) (distance * treeCutMultiplier));
|
||||
|
||||
Reference in New Issue
Block a user