From efd1d67f3f8c8799983c5f5a6e473f84d07ae352 Mon Sep 17 00:00:00 2001 From: tom lee Date: Mon, 10 Jan 2022 22:03:54 +0800 Subject: [PATCH] Render: Fixed mistakes and added more GridList stuff --- .../seibel/lod/core/render/LodRenderer.java | 31 +-- .../lod/core/util/BooleanMovableGridList.java | 248 ++++++++++++++++++ .../seibel/lod/core/util/MovableGridList.java | 9 +- 3 files changed, 268 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/seibel/lod/core/util/BooleanMovableGridList.java diff --git a/src/main/java/com/seibel/lod/core/render/LodRenderer.java b/src/main/java/com/seibel/lod/core/render/LodRenderer.java index b80ed2bac..233737f92 100644 --- a/src/main/java/com/seibel/lod/core/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/core/render/LodRenderer.java @@ -49,6 +49,7 @@ import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper; import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper; +import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper; /** * This is where all the magic happens.
@@ -487,12 +488,13 @@ public class LodRenderer } // returns whether anything changed - private boolean updateVanillaRenderedChunks(LodDimension lodDim, boolean recreateChunks) { - short chunkRenderDistance = (short) MC_RENDER.getRenderDistance(); + private boolean updateVanillaRenderedChunks(LodDimension lodDim) { + int chunkRenderDistance = MC_RENDER.getRenderDistance()+2; int chunkX = Math.floorDiv(lastUpdatedPos.getX(), 16); int chunkZ = Math.floorDiv(lastUpdatedPos.getZ(), 16); // if the player is high enough, draw all LODs - if (lastUpdatedPos.getY() > 256) { + IWorldWrapper world = MC.getWrappedClientWorld(); + if (lastUpdatedPos.getY() > world.getHeight()-world.getMinHeight()) { vanillaRenderedChunks = new MovableGridList( chunkRenderDistance, chunkX, chunkZ); return true; @@ -500,14 +502,12 @@ public class LodRenderer MovableGridList chunkList; boolean anyChanged = false; - if (recreateChunks || vanillaRenderedChunks.gridCentreToEdge != chunkRenderDistance) { + if (vanillaRenderedChunks == null || vanillaRenderedChunks.gridCentreToEdge != chunkRenderDistance || + vanillaRenderedChunks.getCenterX()!=chunkX || vanillaRenderedChunks.getCenterY()!=chunkZ) { chunkList = new MovableGridList(chunkRenderDistance, chunkX, chunkZ); anyChanged = true; } else { - // anyChanged = vanillaRenderedChunks.move(chunkX, chunkZ); - // chunkList = vanillaRenderedChunks; - chunkList = new MovableGridList(chunkRenderDistance, chunkX, chunkZ); - anyChanged = true; + chunkList = vanillaRenderedChunks; } LagSpikeCatcher getChunks = new LagSpikeCatcher(); @@ -534,7 +534,6 @@ public class LodRenderer long newTime = System.currentTimeMillis(); AbstractBlockPosWrapper newPos = MC.getPlayerBlockPos(); boolean shouldUpdateChunks = false; - boolean posUpdated = false; boolean tryPartialGen = false; boolean tryFullGen = false; @@ -559,9 +558,7 @@ public class LodRenderer || 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; - lastUpdatedPos = newPos; - posUpdated = true; + shouldUpdateChunks = true; } prevPlayerPosTime = newTime; } @@ -580,14 +577,10 @@ public class LodRenderer prevChunkTime = newTime; } - - if (tryFullGen && !posUpdated) { - lastUpdatedPos = newPos; - posUpdated = true; - } - shouldUpdateChunks |= posUpdated; + shouldUpdateChunks |= tryFullGen; if (shouldUpdateChunks) { - tryPartialGen |= updateVanillaRenderedChunks(lodDim, posUpdated); + lastUpdatedPos = newPos; + tryPartialGen |= updateVanillaRenderedChunks(lodDim); } if (tryFullGen) { diff --git a/src/main/java/com/seibel/lod/core/util/BooleanMovableGridList.java b/src/main/java/com/seibel/lod/core/util/BooleanMovableGridList.java new file mode 100644 index 000000000..2cdb5058f --- /dev/null +++ b/src/main/java/com/seibel/lod/core/util/BooleanMovableGridList.java @@ -0,0 +1,248 @@ +package com.seibel.lod.core.util; + +/*Layout: + * 0,1,2, + * 3,4,5, + * 6,7,8 + */ + +public class BooleanMovableGridList { + + private int centerX; + private int centerY; + + public final int gridCentreToEdge; + public final int gridSize; + private boolean[] b; + + public BooleanMovableGridList(int gridCentreToEdge, int centerX, int centerY) { + gridSize = gridCentreToEdge * 2 + 1; + this.gridCentreToEdge = gridCentreToEdge; + this.centerX = centerX; + this.centerY = centerY; + clear(); + } + + public void clear() { + b = new boolean[gridSize*gridSize]; + } + + public int getCenterX() {return centerX;} + public int getCenterY() {return centerY;} + + private void assertIndex(int ix, int iy) { + if (ix<0 || ix>=gridSize || iy<0 || iy>=gridSize) + throw new IndexOutOfBoundsException("BooleanMovableGridList index position out of bound"); + } + + public boolean isInBound(int x, int y) { + x = x-centerX+gridCentreToEdge; + y = y-centerY+gridCentreToEdge; + return !(x<0 || x>=gridSize || y<0 || y>=gridSize); + } + + // return onFail if x,y is outside of the grid + public boolean get(int x, int y) { + x = x-centerX+gridCentreToEdge; + y = y-centerY+gridCentreToEdge; + return _getDirect(x,y); + } + + // return false if x,y is outside of the grid + public void set(int x, int y, boolean t) { + x = x-centerX+gridCentreToEdge; + y = y-centerY+gridCentreToEdge; + _setDirect(x,y,t); + } + + // return onFail if x,y is outside of the grid + // Otherwise, return the new value (for chaining) + public boolean setAndGet(int x, int y, boolean t) { + x = x-centerX+gridCentreToEdge; + y = y-centerY+gridCentreToEdge; + _setDirect(x,y,t); + return t; + } + // return null if x,y is outside of the grid + // Otherwise, return the old value + public boolean swap(int x, int y, boolean t, boolean onFail) { + x = x-centerX+gridCentreToEdge; + y = y-centerY+gridCentreToEdge; + return _swapDirect(x,y, t); + } + + private final boolean _getDirect(int x, int y) { + assertIndex(x,y); + return b[x + y * gridSize]; + } + private final void _setDirect(int x, int y, boolean t) { + assertIndex(x,y); + b[x + y * gridSize] = t; + } + private final boolean _swapDirect(int x, int y, boolean t) { + assertIndex(x,y); + boolean r = b[x + y * gridSize]; + b[x + y * gridSize] = t; + return r; + } + + interface BoolTransformer { + boolean transform(boolean oldValue, int x, int y); + } + + // Transform the list via the function. The data can still be accessed + // inside the function, and the returned value will not be applied + // until all elements have done the transform. + public void twoStageTransform(BoolTransformer transformer) { + boolean[] nb = new boolean[b.length]; + int i=0; + for (int y=0; y { + if (v!=t) return v; + boolean r = false; + r |= (isInBound(x-1,y) ? get(x-1,y)==!t : false); + r |= (isInBound(x,y-1) ? get(x,y-1)==!t : false); + r |= (isInBound(x+1,y) ? get(x+1,y)==!t : false); + r |= (isInBound(x,y+1) ? get(x,y+1)==!t : false); + return r ? !t : t; + }; + twoStageTransform(tran); + } + public void flipBorderCorner(boolean valueToBeFlipped) { + boolean t = valueToBeFlipped; + BoolTransformer tran = (v, x, y) -> { + if (v!=t) return v; + boolean r = false; + r |= (isInBound(x-1,y) ? get(x-1,y)==!t : false); + r |= (isInBound(x,y-1) ? get(x,y-1)==!t : false); + r |= (isInBound(x+1,y) ? get(x+1,y)==!t : false); + r |= (isInBound(x,y+1) ? get(x,y+1)==!t : false); + r |= (isInBound(x-1,y-1) ? get(x-1,y-1)==!t : false); + r |= (isInBound(x+1,y-1) ? get(x+1,y-1)==!t : false); + r |= (isInBound(x+1,y+1) ? get(x+1,y+1)==!t : false); + r |= (isInBound(x-1,y+1) ? get(x-1,y+1)==!t : false); + return r ? !t : t; + }; + twoStageTransform(tran); + } + public void flipBorderCorner(boolean valueToBeFlipped, int range) { + boolean t = valueToBeFlipped; + BoolTransformer tran = (v, x, y) -> { + if (v!=t) return v; + boolean r = false; + for (int dx=-range;dx<=range;dx++) + for (int dy=-range;dy<=range;dy++) + r |= (isInBound(x+dx,y+dy) ? get(x+dx,y+dy)==!t : false); + return r ? !t : t; + }; + twoStageTransform(tran); + } + + + // Return false if haven't changed. Return true if it did + public boolean move(int newCenterX, int newCenterY) { + return move(newCenterX, newCenterY, false); + } + + // Return false if haven't changed. Return true if it did + public boolean move(int newCenterX, int newCenterY, boolean value) { + if (centerX == newCenterX && centerY == newCenterY) return false; + int deltaX = newCenterX - centerX; + int deltaY = newCenterY - centerY; + + // if the x or z offset is equal to or greater than + // the total width, just delete the current data + // and update the centerX and/or centerZ + if (Math.abs(deltaX) >= gridSize || Math.abs(deltaY) >= gridSize) + { + clear(); + // update the new center + centerX = newCenterX; + centerY = newCenterY; + return true; + } + centerX = newCenterX; + centerY = newCenterY; + + // X + if (deltaX >= 0 && deltaY >= 0) + { + // move everything over to the left-up (as the center moves to the right-down) + for (int x = 0; x < gridSize; x++) + { + for (int y = 0; y < gridSize; y++) + { + _setDirect(x, y, _getDirect(x+deltaX, y+deltaY)); + } + } + } + else if (deltaX < 0 && deltaY >= 0) + { + // move everything over to the right-up (as the center moves to the left-down) + for (int x = gridSize - 1; x >= 0; x--) + { + for (int y = 0; y < gridSize; y++) + { + _setDirect(x, y, _getDirect(x+deltaX, y+deltaY)); + } + } + } + else if (deltaX >= 0 && deltaY < 0) + { + // move everything over to the left-down (as the center moves to the right-up) + for (int x = 0; x < gridSize; x++) + { + for (int y = gridSize - 1; y >= 0; y--) + { + _setDirect(x, y, _getDirect(x+deltaX, y+deltaY)); + } + } + } + else //if (deltaX < 0 && deltaY < 0) + { + // move everything over to the right-down (as the center moves to the left-up) + for (int x = gridSize - 1; x >= 0; x--) + { + for (int y = gridSize - 1; y >= 0; y--) + { + _setDirect(x, y, _getDirect(x+deltaX, y+deltaY)); + } + } + } + return true; + } + + + @Override + public String toString() { + return "MovableGridList[" + centerX + "," + centerY + "] " + gridSize + "*" + gridSize + "[" + b.length + "]"; + } + + public String toDetailString() { + StringBuilder str = new StringBuilder("\n"); + int i = 0; + str.append(toString()); + str.append("\n"); + for (boolean t : b) { + str.append(t ? "#" : "."); + i++; + if (i % gridSize == 0) { + str.append("\n"); + } else { + //str.append(", "); + } + } + return str.toString(); + } +} diff --git a/src/main/java/com/seibel/lod/core/util/MovableGridList.java b/src/main/java/com/seibel/lod/core/util/MovableGridList.java index d620321da..79d6093f2 100644 --- a/src/main/java/com/seibel/lod/core/util/MovableGridList.java +++ b/src/main/java/com/seibel/lod/core/util/MovableGridList.java @@ -66,6 +66,13 @@ public class MovableGridList extends ArrayList implements List { return _getDirect(x,y); } + // return false if x,y is outside of the grid + public boolean set(int x, int y, T t) { + x = x-centerX+gridCentreToEdge; + y = y-centerY+gridCentreToEdge; + return _setDirect(x,y, 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) { @@ -244,7 +251,7 @@ public class MovableGridList extends ArrayList implements List { } } } - + // TODO: This is unused but may be useful later on. /*