diff --git a/src/main/java/com/seibel/lod/QuadTreeImage.java b/src/main/java/com/seibel/lod/QuadTreeImage.java index c62106e3f..791af77e0 100644 --- a/src/main/java/com/seibel/lod/QuadTreeImage.java +++ b/src/main/java/com/seibel/lod/QuadTreeImage.java @@ -189,7 +189,7 @@ public class QuadTreeImage extends JPanel //int[] distances2 = {100000, 8000, 4000, 2000, 1000, 500, 250, 0}; int[] distances2 = {0, 250, 500, 1000, 2000, 4000, 8000, 100000}; for (int h = 0; h <= (9 - 3); h++) { - lodList.addAll(dim.getNodeToRender(new BlockPos(playerX, 0, playerZ), (byte) (3+h), complexityMask, distances2[h+1], distances2[h])); + lodList.addAll(dim.getNodesToRender(new BlockPos(playerX, 0, playerZ), (byte) (3+h), complexityMask, distances2[h+1], distances2[h])); } System.out.println("Number of node to render " + lodList.size()); listOfList.add(lodList); diff --git a/src/main/java/com/seibel/lod/builders/LodNodeBuilder.java b/src/main/java/com/seibel/lod/builders/LodNodeBuilder.java index a0d95e05a..a13d29fa0 100644 --- a/src/main/java/com/seibel/lod/builders/LodNodeBuilder.java +++ b/src/main/java/com/seibel/lod/builders/LodNodeBuilder.java @@ -89,7 +89,9 @@ public class LodNodeBuilder { } lodDim.addNode(node); - } catch (IllegalArgumentException | NullPointerException e) { + } + catch (IllegalArgumentException | NullPointerException e) + { e.printStackTrace(); // if the world changes while LODs are being generated // they will throw errors as they try to access things that no longer diff --git a/src/main/java/com/seibel/lod/builders/lodNodeTemplates/AbstractLodNodeTemplate.java b/src/main/java/com/seibel/lod/builders/lodNodeTemplates/AbstractLodNodeTemplate.java index 49f564e53..5afb5d092 100644 --- a/src/main/java/com/seibel/lod/builders/lodNodeTemplates/AbstractLodNodeTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodNodeTemplates/AbstractLodNodeTemplate.java @@ -30,7 +30,7 @@ import net.minecraft.client.renderer.BufferBuilder; * BufferBuilders. * * @author James Seibel - * @version 06-16-2021 + * @version 8-8-2021 */ public abstract class AbstractLodNodeTemplate { diff --git a/src/main/java/com/seibel/lod/builders/lodNodeTemplates/CubicLodNodeTemplate.java b/src/main/java/com/seibel/lod/builders/lodNodeTemplates/CubicLodNodeTemplate.java index b82324582..9cf91b5d3 100644 --- a/src/main/java/com/seibel/lod/builders/lodNodeTemplates/CubicLodNodeTemplate.java +++ b/src/main/java/com/seibel/lod/builders/lodNodeTemplates/CubicLodNodeTemplate.java @@ -31,7 +31,7 @@ import net.minecraft.util.math.AxisAlignedBB; * Builds LODs as rectangular prisms. * * @author James Seibel - * @version 06-16-2021 + * @version 8-8-2021 */ public class CubicLodNodeTemplate extends AbstractLodNodeTemplate { diff --git a/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java b/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java index 7fd4e2e6e..6f7e4ceee 100644 --- a/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java +++ b/src/main/java/com/seibel/lod/builders/worldGeneration/LodNodeGenWorker.java @@ -35,6 +35,7 @@ import com.seibel.lod.objects.LodChunk; import com.seibel.lod.objects.LodQuadTreeDimension; import com.seibel.lod.objects.LodQuadTreeNode; import com.seibel.lod.objects.LodRegion; +import com.seibel.lod.proxy.ClientProxy; import com.seibel.lod.render.LodNodeRenderer; import net.minecraft.block.Block; @@ -159,7 +160,7 @@ public class LodNodeGenWorker implements IWorker { public final ServerWorld serverWorld; public final LodQuadTreeDimension lodDim; - public final LodNodeBuilder lodChunkBuilder; + public final LodNodeBuilder lodNodeBuilder; public final LodNodeRenderer lodRenderer; private LodNodeBufferBuilder lodBufferBuilder; @@ -171,7 +172,7 @@ public class LodNodeGenWorker implements IWorker { pos = newPos; lodRenderer = newLodRenderer; - lodChunkBuilder = newLodBuilder; + lodNodeBuilder = newLodBuilder; lodBufferBuilder = newLodBufferBuilder; lodDim = newLodDimension; serverWorld = newServerWorld; @@ -337,14 +338,14 @@ public class LodNodeGenWorker implements IWorker LodQuadTreeNode lod; if (!inTheEnd) { - lod = lodChunkBuilder.generateLodNodeFromChunk(chunk, new LodBuilderConfig(true, true, false)); + lod = lodNodeBuilder.generateLodNodeFromChunk(chunk, new LodBuilderConfig(true, true, false)); } else { // if we are in the end, don't generate any chunks. // Since we don't know where the islands are, everything // generates the same and it looks really bad. - lod = lodChunkBuilder.generateLodNodeFromChunk(chunk, new LodBuilderConfig(true, true, false)); + lod = lodNodeBuilder.generateLodNodeFromChunk(chunk, new LodBuilderConfig(true, true, false)); } lodDim.addNode(lod); } @@ -377,7 +378,7 @@ public class LodNodeGenWorker implements IWorker IceAndSnowFeature snowFeature = new IceAndSnowFeature(NoFeatureConfig.CODEC); snowFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition(), null); - LodQuadTreeNode lod = lodChunkBuilder.generateLodNodeFromChunk(chunk, new LodBuilderConfig(true, true, false)); + LodQuadTreeNode lod = lodNodeBuilder.generateLodNodeFromChunk(chunk, new LodBuilderConfig(true, true, false)); lodDim.addNode(lod); } @@ -504,7 +505,7 @@ public class LodNodeGenWorker implements IWorker // generate a Lod like normal - LodQuadTreeNode lod = lodChunkBuilder.generateLodNodeFromChunk(chunk, new LodBuilderConfig(true, true, false)); + LodQuadTreeNode lod = lodNodeBuilder.generateLodNodeFromChunk(chunk, new LodBuilderConfig(true, true, false)); lodDim.addNode(lod); } @@ -518,8 +519,9 @@ public class LodNodeGenWorker implements IWorker * Note this should not be multithreaded and does cause server/simulation lag * (Higher lag for generating than loading) */ - private void generateWithServer() { - //lodChunkBuilder.generateLodNodeAsync(serverWorld.getChunk(pos.x, pos.z, ChunkStatus.FEATURES), ClientProxy.getLodWorld(), serverWorld); + private void generateWithServer() + { + lodNodeBuilder.generateLodNodeAsync(serverWorld.getChunk(pos.x, pos.z, ChunkStatus.FEATURES), ClientProxy.getLodWorld(), serverWorld); } diff --git a/src/main/java/com/seibel/lod/handlers/LodQuadTreeDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodQuadTreeDimensionFileHandler.java index 3966f12b6..737e8dc53 100644 --- a/src/main/java/com/seibel/lod/handlers/LodQuadTreeDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodQuadTreeDimensionFileHandler.java @@ -34,6 +34,8 @@ import com.seibel.lod.objects.LodQuadTreeNode; import com.seibel.lod.objects.RegionPos; import com.seibel.lod.proxy.ClientProxy; +import net.minecraft.util.math.ChunkPos; + /** * This object handles creating LodRegions * from files and saving LodRegion objects @@ -199,7 +201,7 @@ public class LodQuadTreeDimensionFileHandler // problem reading the file return null; } - return new LodQuadTree(dataList,regionX, regionZ); + return new LodQuadTree(dataList, regionX, regionZ); } @@ -246,10 +248,10 @@ public class LodQuadTreeDimensionFileHandler */ private void saveRegionToDisk(LodQuadTree region) { - // convert chunk coordinates to region - // coordinates - int x = region.getLodNodeData().posX; - int z = region.getLodNodeData().posX; + // convert to region coordinates + RegionPos regionPos = new RegionPos(new ChunkPos(region.getLodNodeData().center)); + int x = regionPos.x; + int z = regionPos.z; File f = new File(getFileNameAndPathForRegion(x, z)); @@ -310,7 +312,8 @@ public class LodQuadTreeDimensionFileHandler fw.write(LOD_FILE_VERSION_PREFIX + " " + LOD_SAVE_FILE_VERSION + "\n"); // add each LodChunk to the file - for (LodQuadTreeNode lodQuadTreeNode : Collections.unmodifiableList(region.getNodeListWithMask(LodQuadTreeDimension.FULL_COMPLEXITY_MASK , true, true))) + List nodesToSave = Collections.unmodifiableList(region.getNodeListWithMask(LodQuadTreeDimension.FULL_COMPLEXITY_MASK, false, true)); + for (LodQuadTreeNode lodQuadTreeNode : nodesToSave) { fw.write(lodQuadTreeNode.toData() + "\n"); lodQuadTreeNode.dirty = false; @@ -350,7 +353,7 @@ public class LodQuadTreeDimensionFileHandler // or // ".\Super Flat\data" return dimensionDataSaveFolder.getCanonicalPath() + File.separatorChar + - FILE_NAME_PREFIX + regionX + "." + regionZ + FILE_EXTENSION; + FILE_NAME_PREFIX + "." + regionX + "." + regionZ + FILE_EXTENSION; } catch(IOException e) { diff --git a/src/main/java/com/seibel/lod/objects/LodDimension.java b/src/main/java/com/seibel/lod/objects/LodDimension.java index ac1e095ac..703d5aabb 100644 --- a/src/main/java/com/seibel/lod/objects/LodDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodDimension.java @@ -259,7 +259,7 @@ public class LodDimension */ public void addLod(LodChunk lod) { - RegionPos pos = LodUtil.convertChunkPosToRegionPos(new ChunkPos(lod.x, lod.z)); + RegionPos pos = new RegionPos(new ChunkPos(lod.x, lod.z)); // don't continue if the region can't be saved if (!regionIsInRange(pos.x, pos.z)) @@ -298,7 +298,7 @@ public class LodDimension */ public LodChunk getLodFromCoordinates(int chunkX, int chunkZ) { - RegionPos pos = LodUtil.convertChunkPosToRegionPos(new ChunkPos(chunkX, chunkZ)); + RegionPos pos = new RegionPos(new ChunkPos(chunkX, chunkZ)); LodRegion region = getRegion(pos.x, pos.z); diff --git a/src/main/java/com/seibel/lod/objects/LodQuadTree.java b/src/main/java/com/seibel/lod/objects/LodQuadTree.java index e09ab48e7..830e24040 100644 --- a/src/main/java/com/seibel/lod/objects/LodQuadTree.java +++ b/src/main/java/com/seibel/lod/objects/LodQuadTree.java @@ -129,20 +129,6 @@ public class LodQuadTree this(parent, new LodQuadTreeNode(level, regionPos.x, regionPos.z)); } - /** - * Constructor for a generic world via the LodNodeData - * - * @param newLodNode LodQuadTreeNode containing all the information of this node - */ - public LodQuadTree(LodQuadTree newParent, LodQuadTreeNode newLodNode) - { - parent = newParent; - lodNode = newLodNode; - children = new LodQuadTree[2][2]; - treeEmpty = true; - treeFull = false; - } - /** * Constructor using a dataList * @@ -156,6 +142,20 @@ public class LodQuadTree setNodesAtLowerLevel(dataList); } + /** + * Constructor for a generic LodQuadTree using a LodNodeData + * + * @param newLodNode LodQuadTreeNode containing all the information of this node + */ + public LodQuadTree(LodQuadTree newParent, LodQuadTreeNode newLodNode) + { + parent = newParent; + lodNode = newLodNode; + children = new LodQuadTree[2][2]; + treeEmpty = true; + treeFull = false; + } + /** * @param dataList list of data to put in the node @@ -564,11 +564,13 @@ public class LodQuadTree public String toString() { String s = lodNode.toString(); - return s; - /* - if(isThereAnyChild()){ - for (int NS = 0; NS <= 1; NS++) { - for (int WE = 0; WE <= 1; WE++) { + + if(hasChildren()) + { + for (int NS = 0; NS <= 1; NS++) + { + for (int WE = 0; WE <= 1; WE++) + { LodQuadTree child = children[NS][WE]; if (child != null) { s += '\n' + child.toString(); @@ -576,7 +578,8 @@ public class LodQuadTree } } } + + return s; - */ } } \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/objects/LodQuadTreeDimension.java b/src/main/java/com/seibel/lod/objects/LodQuadTreeDimension.java index 57d29cf3d..cba728b30 100644 --- a/src/main/java/com/seibel/lod/objects/LodQuadTreeDimension.java +++ b/src/main/java/com/seibel/lod/objects/LodQuadTreeDimension.java @@ -44,7 +44,7 @@ import net.minecraft.world.server.ServerWorld; * * @author Leonardo Amato * @author James Seibel - * @version 8-7-2021 + * @version 8-8-2021 */ public class LodQuadTreeDimension { @@ -77,7 +77,6 @@ public class LodQuadTreeDimension public volatile LodQuadTree regions[][]; public volatile boolean isRegionDirty[][]; - /** a chunk Position */ private volatile RegionPos center; private LodQuadTreeDimensionFileHandler fileHandler; @@ -145,7 +144,9 @@ public class LodQuadTreeDimension /** * Move the center of this LodDimension and move all owned - * regions over by the given x and z offset. + * regions over by the given x and z offset.

+ * + * Synchronized to prevent multiple moves happening on top of each other. */ public synchronized void move(RegionPos regionOffset) { @@ -329,7 +330,7 @@ public class LodQuadTreeDimension */ public Boolean addNode(LodQuadTreeNode lodNode) { - RegionPos regionPos = LodUtil.convertChunkPosToRegionPos(new ChunkPos(lodNode.center.getX(), lodNode.center.getZ())); + RegionPos regionPos = new RegionPos(new ChunkPos(lodNode.center.getX(), lodNode.center.getZ())); // don't continue if the region can't be saved if (!regionIsInRange(regionPos.x, regionPos.z)) @@ -412,7 +413,7 @@ public class LodQuadTreeDimension * method to get all the nodes that have to be rendered based on the position of the player * @return list of nodes */ - public List getNodeToRender(BlockPos playerPos, int detailLevel, + public List getNodesToRender(BlockPos playerPos, int detailLevel, Set complexityMask, int maxDistance, int minDistance) { List listOfData = new ArrayList<>(); @@ -430,7 +431,7 @@ public class LodQuadTreeDimension } /** - * method to get all the quadtree levels that have to be generated based on the position of the player + * Returns all LodQuadTreeNodes that need to be generated based on the position of the player * @return list of quadTrees */ public List getNodesToGenerate(BlockPos playerPos, byte level, DistanceGenerationMode complexity, diff --git a/src/main/java/com/seibel/lod/objects/LodQuadTreeNode.java b/src/main/java/com/seibel/lod/objects/LodQuadTreeNode.java index c3457229a..eb8c0e327 100644 --- a/src/main/java/com/seibel/lod/objects/LodQuadTreeNode.java +++ b/src/main/java/com/seibel/lod/objects/LodQuadTreeNode.java @@ -38,7 +38,7 @@ import net.minecraft.world.gen.Heightmap; public class LodQuadTreeNode { /** This is what separates each piece of data in the toData method */ - private static final char DATA_DELIMITER_COUNT = LodQuadTreeDimensionFileHandler.DATA_DELIMITER; + private static final char DATA_DELIMITER = LodQuadTreeDimensionFileHandler.DATA_DELIMITER; /** If we ever have to use a heightmap for any reason, use this one. */ public static final Heightmap.Type DEFAULT_HEIGHTMAP = Heightmap.Type.WORLD_SURFACE_WG; @@ -52,8 +52,6 @@ public class LodQuadTreeNode * the empty string */ public boolean dontSave = false; - // these 2 values indicate the position of the LOD in the relative Level - // this will be useful in the generation process /** X position relative to the Quad tree. */ public final int posX; /** Z position relative to the Quad tree */ @@ -215,11 +213,11 @@ public class LodQuadTreeNode int count = 0; for(int i = 0; i < data.length(); i++) - if(data.charAt(i) == DATA_DELIMITER_COUNT) + if(data.charAt(i) == DATA_DELIMITER) count++; - if(count != DATA_DELIMITER_COUNT) - throw new IllegalArgumentException("LodQuadTreeNode constructor givin an invalid string. The data given had " + count + " delimiters when it should have had " + DATA_DELIMITER_COUNT + "."); + if(count != NUMBER_OF_DELIMITERS) + throw new IllegalArgumentException("LodQuadTreeNode constructor givin an invalid string. The data given had " + count + " delimiters when it should have had " + NUMBER_OF_DELIMITERS + "."); // start reading the data string @@ -227,46 +225,46 @@ public class LodQuadTreeNode int index = 0; int lastIndex = 0; - index = data.indexOf(DATA_DELIMITER_COUNT, 0); + index = data.indexOf(DATA_DELIMITER, 0); this.detailLevel = (byte) Integer.parseInt(data.substring(0,index)); lastIndex = index; - index = data.indexOf(DATA_DELIMITER_COUNT, lastIndex+1); + index = data.indexOf(DATA_DELIMITER, lastIndex+1); this.posX = Integer.parseInt(data.substring(lastIndex+1,index)); lastIndex = index; - index = data.indexOf(DATA_DELIMITER_COUNT, lastIndex+1); + index = data.indexOf(DATA_DELIMITER, lastIndex+1); this.posZ = Integer.parseInt(data.substring(lastIndex+1,index)); lastIndex = index; - index = data.indexOf(DATA_DELIMITER_COUNT, lastIndex+1); + index = data.indexOf(DATA_DELIMITER, lastIndex+1); this.complexity = DistanceGenerationMode.valueOf(data.substring(lastIndex+1,index)); lastIndex = index; - index = data.indexOf(DATA_DELIMITER_COUNT, lastIndex+1); + index = data.indexOf(DATA_DELIMITER, lastIndex+1); short height = (short) Integer.parseInt(data.substring(lastIndex+1,index)); lastIndex = index; - index = data.indexOf(DATA_DELIMITER_COUNT, lastIndex+1); + index = data.indexOf(DATA_DELIMITER, lastIndex+1); short depth = (short) Integer.parseInt(data.substring(lastIndex+1,index)); lastIndex = index; - index = data.indexOf(DATA_DELIMITER_COUNT, lastIndex+1); - int r = Integer.parseInt(data.substring(lastIndex+1,index)); + index = data.indexOf(DATA_DELIMITER, lastIndex+1); + int red = Integer.parseInt(data.substring(lastIndex+1,index)); lastIndex = index; - index = data.indexOf(DATA_DELIMITER_COUNT, lastIndex+1); - int g = Integer.parseInt(data.substring(lastIndex+1,index)); + index = data.indexOf(DATA_DELIMITER, lastIndex+1); + int green = Integer.parseInt(data.substring(lastIndex+1,index)); lastIndex = index; - index = data.indexOf(DATA_DELIMITER_COUNT, lastIndex+1); - int b = Integer.parseInt(data.substring(lastIndex+1,index)); + index = data.indexOf(DATA_DELIMITER, lastIndex+1); + int blue = Integer.parseInt(data.substring(lastIndex+1,index)); lastIndex = index; - index = data.indexOf(DATA_DELIMITER_COUNT, lastIndex+1); - int a = Integer.parseInt(data.substring(lastIndex+1,index)); - Color color = new Color(r,g,b,a); + index = data.indexOf(DATA_DELIMITER, lastIndex+1); + int alpha = Integer.parseInt(data.substring(lastIndex+1,index)); + Color color = new Color(red,green,blue,alpha); lodDataPoint = new LodDataPoint(height,depth,color); - int val = Integer.parseInt(data.substring(lastIndex+1,index)); - this.voidNode = (val == 1); + int isVoid = Integer.parseInt(data.substring(lastIndex+1,index)); + this.voidNode = (isVoid == 1); width = (short) Math.pow(2, detailLevel); @@ -419,16 +417,16 @@ public class LodQuadTreeNode if (dontSave) return ""; - String s = Integer.toString(detailLevel) + DATA_DELIMITER_COUNT - + Integer.toString(posX) + DATA_DELIMITER_COUNT - + Integer.toString(posZ) + DATA_DELIMITER_COUNT - + complexity.toString() + DATA_DELIMITER_COUNT - + Integer.toString((lodDataPoint.height)) + DATA_DELIMITER_COUNT - + Integer.toString((lodDataPoint.depth)) + DATA_DELIMITER_COUNT - + Integer.toString(lodDataPoint.color.getRed()) + DATA_DELIMITER_COUNT - + Integer.toString(lodDataPoint.color.getGreen()) + DATA_DELIMITER_COUNT - + Integer.toString(lodDataPoint.color.getBlue()) + DATA_DELIMITER_COUNT - + Integer.toString(lodDataPoint.color.getAlpha()) + DATA_DELIMITER_COUNT + String s = Integer.toString(detailLevel) + DATA_DELIMITER + + Integer.toString(posX) + DATA_DELIMITER + + Integer.toString(posZ) + DATA_DELIMITER + + complexity.toString() + DATA_DELIMITER + + Integer.toString((lodDataPoint.height)) + DATA_DELIMITER + + Integer.toString((lodDataPoint.depth)) + DATA_DELIMITER + + Integer.toString(lodDataPoint.color.getRed()) + DATA_DELIMITER + + Integer.toString(lodDataPoint.color.getGreen()) + DATA_DELIMITER + + Integer.toString(lodDataPoint.color.getBlue()) + DATA_DELIMITER + + Integer.toString(lodDataPoint.color.getAlpha()) + DATA_DELIMITER + Integer.toString(voidNode ? 1 : 0); return s; } diff --git a/src/main/java/com/seibel/lod/objects/RegionPos.java b/src/main/java/com/seibel/lod/objects/RegionPos.java index de4b4aae0..641dc42d5 100644 --- a/src/main/java/com/seibel/lod/objects/RegionPos.java +++ b/src/main/java/com/seibel/lod/objects/RegionPos.java @@ -17,11 +17,13 @@ */ package com.seibel.lod.objects; +import net.minecraft.util.math.ChunkPos; + /** * This object is similar to ChunkPos or BlockPos. * * @author James Seibel - * @version 03-19-2021 + * @version 8-8-2021 */ public class RegionPos { @@ -45,4 +47,22 @@ public class RegionPos x = newX; z = newZ; } + + public RegionPos(ChunkPos pos) + { + RegionPos rPos = new RegionPos(); + x = pos.x / LodQuadTreeNode.REGION_WIDTH; + z = pos.z / LodQuadTreeNode.REGION_WIDTH; + + // prevent issues if X/Z is negative and less than 16 + if (pos.x < 0) + { + x = (Math.abs(rPos.x) * -1) - 1; + } + if (pos.z < 0) + { + z = (Math.abs(rPos.z) * -1) - 1; + } + } + }