Fixed Overdraw, mergeVertData error, wrong vanillaDist math.
This commit is contained in:
@@ -96,7 +96,7 @@ public class EventApi
|
||||
|
||||
public void chunkLoadEvent(IChunkWrapper chunk, IDimensionTypeWrapper dimType)
|
||||
{
|
||||
ApiShared.lodBuilder.generateLodNodeAsync(chunk, ApiShared.lodWorld, dimType, DistanceGenerationMode.FULL);
|
||||
ApiShared.lodBuilder.generateLodNodeAsync(chunk, ApiShared.lodWorld, dimType, DistanceGenerationMode.FULL, true);
|
||||
}
|
||||
|
||||
public void worldSaveEvent()
|
||||
|
||||
+22
-32
@@ -461,21 +461,22 @@ public class LodBufferBuilderFactory
|
||||
int chunkXdist = LevelPosUtil.getChunkPos(detailLevel, posX) - playerChunkX;
|
||||
int chunkZdist = LevelPosUtil.getChunkPos(detailLevel, posZ) - playerChunkZ;
|
||||
|
||||
// Currently fixing below
|
||||
// FIXME: We don't need to ignore rendered chunks! Just build it and leave it for the renderer to decide!
|
||||
//We don't want to render this fake block if
|
||||
//The block is inside the render distance with, is not bigger than a chunk and is positioned in a chunk set as vanilla rendered
|
||||
//
|
||||
//The block is in the player chunk or in a chunk adjacent to the player
|
||||
//if(isThisPositionGoingToBeRendered(detailLevel, posX, posZ, playerChunkX, playerChunkZ, vanillaRenderedChunks, gameChunkRenderDistance))
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
// TODO: In the future, We don't need to ignore rendered chunks! Just build it and leave it for the renderer to decide!
|
||||
// We don't want to render this fake block if
|
||||
// The block is inside the render distance with, is not bigger than a chunk and is positioned in a chunk set as vanilla rendered
|
||||
|
||||
// The block is in the player chunk or in a chunk adjacent to the player
|
||||
if(detailLevel <= LodUtil.CHUNK_DETAIL_LEVEL &&
|
||||
isThisPositionGoingToBeRendered(LevelPosUtil.getChunkPos(detailLevel, posX),
|
||||
LevelPosUtil.getChunkPos(detailLevel, posZ)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//we check if the block to render is not in player chunk
|
||||
boolean posNotInPlayerChunk = !(chunkXdist == 0 && chunkZdist == 0);
|
||||
|
||||
// We extract the adj data in the four cardinal direction
|
||||
|
||||
// We extract the adj data in the four cardinal direction
|
||||
|
||||
// we first reset the adjShadeDisabled. This is used to disable the shade on the border when we have transparent block like water or glass
|
||||
// to avoid having a "darker border" underground
|
||||
@@ -558,31 +559,20 @@ public class LodBufferBuilderFactory
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Will be removed in a1.7
|
||||
@Deprecated
|
||||
private boolean isThisPositionGoingToBeRendered(byte detailLevel, int posX, int posZ, int chunkPosX, int chunkPosZ, boolean[][] vanillaRenderedChunks, int gameChunkRenderDistance){
|
||||
private boolean isThisPositionGoingToBeRendered(int chunkX, int chunkZ){
|
||||
MovableGridList<Boolean> chunkGrid = ClientApi.renderer.vanillaRenderedChunks;
|
||||
Boolean isRendered = chunkGrid.get(chunkX, chunkZ);
|
||||
|
||||
// skip any chunks that Minecraft is going to render
|
||||
int chunkXdist = LevelPosUtil.getChunkPos(detailLevel, posX) - chunkPosX;
|
||||
int chunkZdist = LevelPosUtil.getChunkPos(detailLevel, posZ) - chunkPosZ;
|
||||
|
||||
if (isRendered == null || !isRendered) return false;
|
||||
|
||||
// check if the chunk is on the border
|
||||
boolean isItBorderPos;
|
||||
if (CONFIG.client().graphics().advancedGraphics().getVanillaOverdraw() == VanillaOverdraw.BORDER)
|
||||
isItBorderPos = LodUtil.isBorderChunk(vanillaRenderedChunks, chunkXdist + gameChunkRenderDistance + 1, chunkZdist + gameChunkRenderDistance + 1);
|
||||
return !LodUtil.isBorderChunk(ClientApi.renderer.vanillaRenderedChunks, chunkX, chunkZ);
|
||||
else
|
||||
isItBorderPos = false;
|
||||
|
||||
|
||||
//boolean smallRenderDistance = gameChunkRenderDistance <= LodUtil.MINIMUM_RENDER_DISTANCE_FOR_PARTIAL_OVERDRAW;
|
||||
|
||||
// get the positions that will be rendered
|
||||
|
||||
return (gameChunkRenderDistance >= Math.abs(chunkXdist)
|
||||
&& gameChunkRenderDistance >= Math.abs(chunkZdist)
|
||||
&& detailLevel <= LodUtil.CHUNK_DETAIL_LEVEL
|
||||
&& vanillaRenderedChunks[chunkXdist + gameChunkRenderDistance + 1][chunkZdist + gameChunkRenderDistance + 1])
|
||||
&& (!isItBorderPos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -90,10 +90,10 @@ public class LodBuilder
|
||||
|
||||
public void generateLodNodeAsync(IChunkWrapper chunk, LodWorld lodWorld, IDimensionTypeWrapper dim)
|
||||
{
|
||||
generateLodNodeAsync(chunk, lodWorld, dim, DistanceGenerationMode.FULL);
|
||||
generateLodNodeAsync(chunk, lodWorld, dim, DistanceGenerationMode.FULL, false);
|
||||
}
|
||||
|
||||
public void generateLodNodeAsync(IChunkWrapper chunk, LodWorld lodWorld, IDimensionTypeWrapper dim, DistanceGenerationMode generationMode)
|
||||
public void generateLodNodeAsync(IChunkWrapper chunk, LodWorld lodWorld, IDimensionTypeWrapper dim, DistanceGenerationMode generationMode, boolean override)
|
||||
{
|
||||
if (lodWorld == null || lodWorld.getIsWorldNotLoaded())
|
||||
return;
|
||||
@@ -130,7 +130,7 @@ public class LodBuilder
|
||||
{
|
||||
lodDim = lodWorld.getLodDimension(dim);
|
||||
}
|
||||
generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(generationMode));
|
||||
generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(generationMode), override);
|
||||
//}
|
||||
//catch (IllegalArgumentException | NullPointerException e)
|
||||
//{
|
||||
@@ -149,14 +149,14 @@ public class LodBuilder
|
||||
*/
|
||||
public void generateLodNodeFromChunk(LodDimension lodDim, IChunkWrapper chunk) throws IllegalArgumentException
|
||||
{
|
||||
generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig());
|
||||
generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a LodNode for a chunk in the given world.
|
||||
* @throws IllegalArgumentException thrown if either the chunk or world is null.
|
||||
*/
|
||||
public void generateLodNodeFromChunk(LodDimension lodDim, IChunkWrapper chunk, LodBuilderConfig config)
|
||||
public void generateLodNodeFromChunk(LodDimension lodDim, IChunkWrapper chunk, LodBuilderConfig config, boolean override)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
//long executeTime = System.currentTimeMillis();
|
||||
@@ -204,7 +204,9 @@ public class LodBuilder
|
||||
{
|
||||
posX = LevelPosUtil.convert((byte) 0, chunk.getChunkPosX() * 16 + startX, minDetailLevel);
|
||||
posZ = LevelPosUtil.convert((byte) 0, chunk.getChunkPosZ() * 16 + startZ, minDetailLevel);
|
||||
if (!lodDim.doesDataExist(minDetailLevel, posX, posZ)) {
|
||||
long oldData = lodDim.getSingleData(minDetailLevel, posX, posZ);
|
||||
if (override || !DataPointUtil.doesItExist(oldData) ||
|
||||
DataPointUtil.getGenerationMode(oldData)<config.distanceGenerationMode.complexity) {
|
||||
lodDim.addVerticalData(minDetailLevel, posX, posZ, data);
|
||||
lodDim.updateData(minDetailLevel, posX, posZ);
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ public class LodDimensionFileHandler
|
||||
// (Corresponding call is the this::writerMain(...)::...setRelease(false);)
|
||||
//boolean haventStarted = !isFileWritingThreadRunning.compareAndExchangeAcquire(false, true);
|
||||
// The above needs java 9!
|
||||
boolean haventStarted = !isFileWritingThreadRunning.compareAndSet(false, true);
|
||||
boolean haventStarted = isFileWritingThreadRunning.compareAndSet(false, true);
|
||||
|
||||
if (haventStarted) {
|
||||
// We acquired the atomic lock.
|
||||
|
||||
@@ -152,6 +152,7 @@ public class VertexOptimizer
|
||||
* This is a map from Direction to the relative normal vector
|
||||
* we are using this since I'm not sure if the getNormal create new object at every call
|
||||
*/
|
||||
// FIXME: No. It doesn't. Just remove this.
|
||||
@SuppressWarnings("serial")
|
||||
public static final Map<LodDirection, Vec3i> DIRECTION_NORMAL_MAP = new HashMap<LodDirection, Vec3i>()
|
||||
{{
|
||||
|
||||
@@ -210,14 +210,14 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
}
|
||||
|
||||
private static long[] downgradeVerticalSize(int oldVertSize, int newVertSize, long[] data) {
|
||||
long[] dataToMerge = new long[oldVertSize];
|
||||
int size = data.length/oldVertSize;
|
||||
long[] dataToMerge = new long[oldVertSize];
|
||||
long[] newData = new long[size * newVertSize];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
System.arraycopy(oldVertSize, i * oldVertSize, dataToMerge, 0, oldVertSize);
|
||||
dataToMerge = DataPointUtil.mergeMultiData(dataToMerge, oldVertSize, newVertSize);
|
||||
System.arraycopy(dataToMerge, 0, newData, i * newVertSize, newVertSize);
|
||||
System.arraycopy(data, i * oldVertSize, dataToMerge, 0, oldVertSize);
|
||||
long[] tempBuffer = DataPointUtil.mergeMultiData(dataToMerge, oldVertSize, newVertSize);
|
||||
System.arraycopy(tempBuffer, 0, newData, i * newVertSize, newVertSize);
|
||||
}
|
||||
return newData;
|
||||
}
|
||||
|
||||
@@ -59,21 +59,6 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
*/
|
||||
public class LodRenderer
|
||||
{
|
||||
public static class VanillaRenderedChunksList extends GridList<Boolean> {
|
||||
private static final long serialVersionUID = -5448501880911391315L;
|
||||
|
||||
public final int centerX;
|
||||
public final int centerZ;
|
||||
|
||||
public VanillaRenderedChunksList(int range, int centerX, int centerZ) {
|
||||
super(range);
|
||||
this.centerX = centerX;
|
||||
this.centerZ = centerZ;
|
||||
for (int i=0; i<gridSize*gridSize; i++) {
|
||||
add(i, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static class LagSpikeCatcher {
|
||||
|
||||
long timer = System.nanoTime();
|
||||
@@ -109,7 +94,7 @@ public class LodRenderer
|
||||
LodRenderProgram shaderProgram = null;
|
||||
|
||||
/** This is used to determine if the LODs should be regenerated */
|
||||
private AbstractBlockPosWrapper previousPos = null;
|
||||
private AbstractBlockPosWrapper lastUpdatedPos = null;
|
||||
|
||||
// these variables are used to determine if the buffers should be rebuilt
|
||||
private int prevRenderDistance = 0;
|
||||
@@ -133,7 +118,7 @@ public class LodRenderer
|
||||
* This HashSet contains every chunk that Vanilla Minecraft
|
||||
* is going to render
|
||||
*/
|
||||
public VanillaRenderedChunksList vanillaRenderedChunks;
|
||||
public MovableGridList<Boolean> vanillaRenderedChunks;
|
||||
public int vanillaRenderedChunksCenterX;
|
||||
public int vanillaRenderedChunksCenterZ;
|
||||
public int vanillaRenderedChunksRefreshTimer;
|
||||
@@ -504,50 +489,43 @@ public class LodRenderer
|
||||
// returns whether anything changed
|
||||
private boolean updateVanillaRenderedChunks(LodDimension lodDim, boolean recreateChunks) {
|
||||
short chunkRenderDistance = (short) MC_RENDER.getRenderDistance();
|
||||
int chunkX = Math.floorDiv(previousPos.getX(), 16);
|
||||
int chunkZ = Math.floorDiv(previousPos.getZ(), 16);
|
||||
int chunkX = Math.floorDiv(lastUpdatedPos.getX(), 16);
|
||||
int chunkZ = Math.floorDiv(lastUpdatedPos.getZ(), 16);
|
||||
// if the player is high enough, draw all LODs
|
||||
if (previousPos.getY() > 256) {
|
||||
vanillaRenderedChunks = new VanillaRenderedChunksList(
|
||||
if (lastUpdatedPos.getY() > 256) {
|
||||
vanillaRenderedChunks = new MovableGridList<Boolean>(
|
||||
chunkRenderDistance, chunkX, chunkZ);
|
||||
return true;
|
||||
}
|
||||
VanillaRenderedChunksList chunkList;
|
||||
|
||||
if (recreateChunks) {
|
||||
vanillaRenderedChunks = new VanillaRenderedChunksList(chunkRenderDistance, chunkX, chunkZ);
|
||||
return true;
|
||||
} else {
|
||||
chunkList = vanillaRenderedChunks;
|
||||
chunkX = chunkList.centerX;
|
||||
chunkZ = chunkList.centerZ;
|
||||
chunkRenderDistance = (short) vanillaRenderedChunks.gridCentreToEdge;
|
||||
}
|
||||
MovableGridList<Boolean> chunkList;
|
||||
|
||||
boolean anyChanged = false;
|
||||
if (recreateChunks || vanillaRenderedChunks.gridCentreToEdge != chunkRenderDistance) {
|
||||
chunkList = new MovableGridList<Boolean>(chunkRenderDistance, chunkX, chunkZ);
|
||||
anyChanged = true;
|
||||
} else {
|
||||
// anyChanged = vanillaRenderedChunks.move(chunkX, chunkZ);
|
||||
// chunkList = vanillaRenderedChunks;
|
||||
chunkList = new MovableGridList<Boolean>(chunkRenderDistance, chunkX, chunkZ);
|
||||
anyChanged = true;
|
||||
}
|
||||
|
||||
LagSpikeCatcher getChunks = new LagSpikeCatcher();
|
||||
Set<AbstractChunkPosWrapper> chunkPosToSkip = LodUtil.getNearbyLodChunkPosToSkip(lodDim, previousPos);
|
||||
Set<AbstractChunkPosWrapper> chunkPosToSkip = LodUtil.getNearbyLodChunkPosToSkip(lodDim, lastUpdatedPos);
|
||||
getChunks.end("LodDrawSetup:UpdateStatus:UpdateVanillaChunks:getChunks");
|
||||
for (AbstractChunkPosWrapper pos : chunkPosToSkip)
|
||||
{
|
||||
int xIndex = (pos.getX() - chunkX) + (chunkRenderDistance + 1);
|
||||
int zIndex = (pos.getZ() - chunkZ) + (chunkRenderDistance + 1);
|
||||
|
||||
// sometimes we are given chunks that are outside the render distance,
|
||||
// This prevents index out of bounds exceptions
|
||||
if (xIndex >= 0 && zIndex >= 0
|
||||
&& xIndex < vanillaRenderedChunks.gridSize
|
||||
&& zIndex < vanillaRenderedChunks.gridSize)
|
||||
if (!chunkList.inRange(pos.getX(), pos.getZ())) continue;
|
||||
Boolean oldBool = chunkList.swap(pos.getX(), pos.getZ(), true);
|
||||
if (oldBool == null || !oldBool)
|
||||
{
|
||||
if (!chunkList.get(chunkList.calculateOffset(xIndex, zIndex)))
|
||||
{
|
||||
chunkList.set(chunkList.calculateOffset(xIndex, zIndex), true);
|
||||
anyChanged = true;
|
||||
lodDim.markRegionBufferToRegen(pos.getRegionX(), pos.getRegionZ());
|
||||
}
|
||||
anyChanged = true;
|
||||
lodDim.markRegionBufferToRegen(pos.getRegionX(), pos.getRegionZ());
|
||||
}
|
||||
}
|
||||
vanillaRenderedChunks = chunkList;
|
||||
if (anyChanged) vanillaRenderedChunks = chunkList;
|
||||
return anyChanged;
|
||||
}
|
||||
|
||||
@@ -577,12 +555,12 @@ public class LodRenderer
|
||||
|
||||
// check if the player has moved
|
||||
if (newTime - prevPlayerPosTime > CONFIG.client().advanced().buffers().getRebuildTimes().playerMoveTimeout) {
|
||||
if (previousPos == null
|
||||
|| Math.abs(newPos.getX() - previousPos.getX()) > CONFIG.client().advanced().buffers().getRebuildTimes().playerMoveDistance*16
|
||||
|| Math.abs(newPos.getZ() - previousPos.getZ()) > CONFIG.client().advanced().buffers().getRebuildTimes().playerMoveDistance*16)
|
||||
if (lastUpdatedPos == null
|
||||
|| Math.abs(newPos.getX() - lastUpdatedPos.getX()) > CONFIG.client().advanced().buffers().getRebuildTimes().playerMoveDistance*16
|
||||
|| Math.abs(newPos.getZ() - lastUpdatedPos.getZ()) > CONFIG.client().advanced().buffers().getRebuildTimes().playerMoveDistance*16)
|
||||
{
|
||||
tryPartialGen = true;
|
||||
previousPos = newPos;
|
||||
lastUpdatedPos = newPos;
|
||||
posUpdated = true;
|
||||
}
|
||||
prevPlayerPosTime = newTime;
|
||||
@@ -604,7 +582,7 @@ public class LodRenderer
|
||||
|
||||
|
||||
if (tryFullGen && !posUpdated) {
|
||||
previousPos = newPos;
|
||||
lastUpdatedPos = newPos;
|
||||
posUpdated = true;
|
||||
}
|
||||
shouldUpdateChunks |= posUpdated;
|
||||
|
||||
@@ -394,6 +394,7 @@ public class LodUtil
|
||||
* @param z relative (to the matrix) z chunk to check
|
||||
* @return true if and only if the chunk is a border of the renderable chunks
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isBorderChunk(boolean[][] vanillaRenderedChunks, int x, int z)
|
||||
{
|
||||
if (x < 0 || z < 0 || x >= vanillaRenderedChunks.length || z >= vanillaRenderedChunks[0].length)
|
||||
@@ -410,6 +411,17 @@ public class LodUtil
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static boolean isBorderChunk(MovableGridList<Boolean> vanillaRenderedChunks, int chunkX, int chunkZ)
|
||||
{
|
||||
for (LodDirection lodDirection : VertexOptimizer.ADJ_DIRECTIONS)
|
||||
{
|
||||
int tempX = chunkX + lodDirection.getNormal().x;
|
||||
int tempZ = chunkZ + lodDirection.getNormal().z;
|
||||
Boolean b = vanillaRenderedChunks.get(tempX, tempZ);
|
||||
if (b == null || !b) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/** This is copied from Minecraft's MathHelper class */
|
||||
|
||||
@@ -67,11 +67,25 @@ public class MovableGridList<T> extends ArrayList<T> implements List<T> {
|
||||
}
|
||||
|
||||
// return null if x,y is outside of the grid
|
||||
// Otherwise, return the new value (for chaining)
|
||||
public T setAndGet(int x, int y, T t) {
|
||||
x = x-centerX+gridCentreToEdge;
|
||||
y = y-centerY+gridCentreToEdge;
|
||||
return _setDirect(x,y, t) ? t : null;
|
||||
}
|
||||
// return null if x,y is outside of the grid
|
||||
// Otherwise, return the old value
|
||||
public T swap(int x, int y, T t) {
|
||||
x = x-centerX+gridCentreToEdge;
|
||||
y = y-centerY+gridCentreToEdge;
|
||||
return _swapDirect(x,y, t);
|
||||
}
|
||||
|
||||
public boolean inRange(int x, int y) {
|
||||
x = x-centerX+gridCentreToEdge;
|
||||
y = y-centerY+gridCentreToEdge;
|
||||
return (x>=0 && x<gridSize && y>=0 && y<gridSize);
|
||||
}
|
||||
|
||||
private final T _getDirect(int x, int y) {
|
||||
if (x<0 || x>=gridSize || y<0 || y>=gridSize) return null;
|
||||
@@ -82,9 +96,14 @@ public class MovableGridList<T> extends ArrayList<T> implements List<T> {
|
||||
super.set(x + y * gridSize, t);
|
||||
return true;
|
||||
}
|
||||
private final T _swapDirect(int x, int y, T t) {
|
||||
if (x<0 || x>=gridSize || y<0 || y>=gridSize) return null;
|
||||
return super.set(x + y * gridSize, t);
|
||||
}
|
||||
|
||||
public void move(int newCenterX, int newCenterY) {
|
||||
if (centerX == newCenterX && centerY == newCenterY) return;
|
||||
// Return false if haven't changed. Return true if it did
|
||||
public boolean move(int newCenterX, int newCenterY) {
|
||||
if (centerX == newCenterX && centerY == newCenterY) return false;
|
||||
int deltaX = newCenterX - centerX;
|
||||
int deltaY = newCenterY - centerY;
|
||||
|
||||
@@ -97,7 +116,7 @@ public class MovableGridList<T> extends ArrayList<T> implements List<T> {
|
||||
// update the new center
|
||||
centerX = newCenterX;
|
||||
centerY = newCenterY;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
centerX = newCenterX;
|
||||
centerY = newCenterY;
|
||||
@@ -147,6 +166,7 @@ public class MovableGridList<T> extends ArrayList<T> implements List<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void move(int newCenterX, int newCenterY, Consumer<? super T> d) {
|
||||
|
||||
+2
-5
@@ -101,9 +101,6 @@ public interface IMinecraftRenderWrapper
|
||||
IWrapperFactory factory = SingletonHandler.get(IWrapperFactory.class);
|
||||
|
||||
int chunkRenderDist = this.getRenderDistance();
|
||||
// if we have a odd render distance, we'll have a empty gap. This way we'll overlap by 1 instead,
|
||||
// which is preferable to having a hole in the world
|
||||
chunkRenderDist = chunkRenderDist % 2 == 0 ? chunkRenderDist : chunkRenderDist - 1;
|
||||
|
||||
AbstractChunkPosWrapper centerChunkPos = mcWrapper.getPlayerChunkPos();
|
||||
int startChunkX = centerChunkPos.getX() - chunkRenderDist;
|
||||
@@ -111,9 +108,9 @@ public interface IMinecraftRenderWrapper
|
||||
|
||||
// add every position within render distance
|
||||
HashSet<AbstractChunkPosWrapper> renderedPos = new HashSet<AbstractChunkPosWrapper>();
|
||||
for (int chunkX = 0; chunkX < (chunkRenderDist * 2); chunkX++)
|
||||
for (int chunkX = 0; chunkX < (chunkRenderDist * 2+1); chunkX++)
|
||||
{
|
||||
for(int chunkZ = 0; chunkZ < (chunkRenderDist * 2); chunkZ++)
|
||||
for(int chunkZ = 0; chunkZ < (chunkRenderDist * 2+1); chunkZ++)
|
||||
{
|
||||
renderedPos.add(factory.createChunkPos(startChunkX + chunkX, startChunkZ + chunkZ));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user