From 2ee76a413ff2df3fb4d0a5d6d50ec78d634b1f7f Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 23 Feb 2021 08:19:37 -0600 Subject: [PATCH] Refactor, comment, and clean up everything This adds comments to almost every class, removes a few classes that weren't being used, improves the names of a number of methods, and does a bunch of random polishing/cleaning. --- src/main/java/com/backsun/lod/LodMain.java | 4 + .../lod/builders/BuildBufferThread.java | 32 ++- .../com/backsun/lod/builders/LodBuilder.java | 19 +- ...dler.java => LodDimensionFileHandler.java} | 83 ++----- .../lod/handlers/ReflectionHandler.java | 3 +- .../com/backsun/lod/objects/LodChunk.java | 178 ++++++++------ .../com/backsun/lod/objects/LodDimension.java | 87 ++++--- .../com/backsun/lod/objects/LodRegion.java | 21 +- .../com/backsun/lod/objects/LodWorld.java | 30 ++- .../com/backsun/lod/proxy/ClientProxy.java | 13 +- .../com/backsun/lod/proxy/CommonProxy.java | 2 +- .../com/backsun/lod/renderer/LodRenderer.java | 228 ++++++++++-------- .../com/backsun/lod/renderer/RenderUtil.java | 45 ---- .../java/com/backsun/lod/util/LodConfig.java | 1 + .../java/com/backsun/lod/util/Reference.java | 1 + .../lod/util/enums/ColorDirection.java | 4 +- .../com/backsun/lod/util/enums/DrawMode.java | 32 --- .../backsun/lod/util/enums/FogDistance.java | 4 +- .../{LodLocation.java => LodCorner.java} | 7 +- src/main/resources/mcmod.info | 2 +- 20 files changed, 424 insertions(+), 372 deletions(-) rename src/main/java/com/backsun/lod/handlers/{LodFileHandler.java => LodDimensionFileHandler.java} (74%) delete mode 100644 src/main/java/com/backsun/lod/renderer/RenderUtil.java delete mode 100644 src/main/java/com/backsun/lod/util/enums/DrawMode.java rename src/main/java/com/backsun/lod/util/enums/{LodLocation.java => LodCorner.java} (82%) diff --git a/src/main/java/com/backsun/lod/LodMain.java b/src/main/java/com/backsun/lod/LodMain.java index 78411042c..61ceebbf8 100644 --- a/src/main/java/com/backsun/lod/LodMain.java +++ b/src/main/java/com/backsun/lod/LodMain.java @@ -16,6 +16,10 @@ import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; /** + * Initialize and setup the Mod. + *
+ * If you are looking for the real start of the mod + * check out the ClientProxy. * * @author James Seibel * @version 02-07-2021 diff --git a/src/main/java/com/backsun/lod/builders/BuildBufferThread.java b/src/main/java/com/backsun/lod/builders/BuildBufferThread.java index 809a3445f..df540e497 100644 --- a/src/main/java/com/backsun/lod/builders/BuildBufferThread.java +++ b/src/main/java/com/backsun/lod/builders/BuildBufferThread.java @@ -5,7 +5,6 @@ import java.util.concurrent.Callable; import org.lwjgl.opengl.GL11; import com.backsun.lod.objects.NearFarBuffer; -import com.backsun.lod.renderer.RenderUtil; import com.backsun.lod.util.enums.FogDistance; import net.minecraft.client.renderer.BufferBuilder; @@ -13,10 +12,12 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.math.AxisAlignedBB; /** - * + * This object is used to create NearFarBuffer objects + * in a thread independent way, so multiple of these objects can be + * created and executed in parallel to populate BufferBuilders. * * @author James Seibel - * @version 02-21-2021 + * @version 02-22-2021 */ public class BuildBufferThread implements Callable { @@ -70,6 +71,9 @@ public class BuildBufferThread implements Callable int blue; int alpha; + // this is done if the FogDistance is either + // NEAR or FAR, if it is NEAR_AND_FAR + // the buffer is determined for each LOD if (distanceMode == FogDistance.NEAR) { currentBuffer = nearBuffer; @@ -97,10 +101,10 @@ public class BuildBufferThread implements Callable blue = colors[i][j].getBlue(); alpha = colors[i][j].getAlpha(); - // choose which buffer to add these LODs too + if (distanceMode == FogDistance.NEAR_AND_FAR) { - if (RenderUtil.isCoordinateInNearFogArea(i, j, numbChunksWide / 2)) + if (isCoordinateInNearFogArea(i, j, numbChunksWide / 2)) currentBuffer = nearBuffer; else currentBuffer = farBuffer; @@ -193,6 +197,22 @@ public class BuildBufferThread implements Callable { buffer.pos(x, y, z).color(red, green, blue, alpha).endVertex(); } - + + + + /** + * Find the coordinates that are in the center half of the given + * 2D matrix, starting at (0,0) and going to (2 * lodRadius, 2 * lodRadius). + */ + private static boolean isCoordinateInNearFogArea(int chunkX, int chunkZ, int lodRadius) + { + int halfRadius = lodRadius / 2; + + return (chunkX >= lodRadius - halfRadius + && chunkX <= lodRadius + halfRadius) + && + (chunkZ >= lodRadius - halfRadius + && chunkZ <= lodRadius + halfRadius); + } } \ No newline at end of file diff --git a/src/main/java/com/backsun/lod/builders/LodBuilder.java b/src/main/java/com/backsun/lod/builders/LodBuilder.java index ac310ef32..57e720997 100644 --- a/src/main/java/com/backsun/lod/builders/LodBuilder.java +++ b/src/main/java/com/backsun/lod/builders/LodBuilder.java @@ -3,7 +3,7 @@ package com.backsun.lod.builders; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import com.backsun.lod.handlers.LodFileHandler; +import com.backsun.lod.handlers.LodDimensionFileHandler; import com.backsun.lod.objects.LodChunk; import com.backsun.lod.objects.LodDimension; import com.backsun.lod.objects.LodWorld; @@ -20,12 +20,12 @@ import net.minecraft.world.chunk.storage.ExtendedBlockStorage; * (specifically: Lod World, Dimension, Region, and Chunk objects) * * @author James Seibel - * @version 2-21-2021 + * @version 2-22-2021 */ public class LodBuilder { - private ExecutorService lodGenThreadPool = Executors.newFixedThreadPool(1); - public LodWorld lodWorld; + private ExecutorService lodGenThreadPool = Executors.newSingleThreadExecutor(); + public volatile LodWorld lodWorld; /** Default size of any LOD regions we use */ public int regionWidth = 5; @@ -41,7 +41,7 @@ public class LodBuilder * Returns LodWorld so that it can be passed * to the LodRenderer. */ - public LodWorld generateLodChunk(Chunk chunk) + public LodWorld generateLodChunkAsync(Chunk chunk) { Minecraft mc = Minecraft.getMinecraft(); @@ -68,13 +68,13 @@ public class LodBuilder if (lodWorld == null) { - lodWorld = new LodWorld(LodFileHandler.getWorldName()); + lodWorld = new LodWorld(LodDimensionFileHandler.getWorldName()); } else { // if we have a lodWorld make sure // it is for this minecraft world - if (!lodWorld.worldName.equals(LodFileHandler.getWorldName())) + if (!lodWorld.worldName.equals(LodDimensionFileHandler.getWorldName())) { // this lodWorld isn't for this minecraft world // delete it so we can get a new one @@ -106,7 +106,6 @@ public class LodBuilder // they will throw errors as they try to access things that no longer // exist. } - }); lodGenThreadPool.execute(thread); @@ -119,9 +118,9 @@ public class LodBuilder */ public boolean isValidChunk(Chunk chunk) { - ExtendedBlockStorage[] data = chunk.getBlockStorageArray(); + ExtendedBlockStorage[] blockStorage = chunk.getBlockStorageArray(); - for(ExtendedBlockStorage e : data) + for(ExtendedBlockStorage e : blockStorage) { if(e != null && !e.isEmpty()) { diff --git a/src/main/java/com/backsun/lod/handlers/LodFileHandler.java b/src/main/java/com/backsun/lod/handlers/LodDimensionFileHandler.java similarity index 74% rename from src/main/java/com/backsun/lod/handlers/LodFileHandler.java rename to src/main/java/com/backsun/lod/handlers/LodDimensionFileHandler.java index fe666080f..574a3a69c 100644 --- a/src/main/java/com/backsun/lod/handlers/LodFileHandler.java +++ b/src/main/java/com/backsun/lod/handlers/LodDimensionFileHandler.java @@ -23,9 +23,9 @@ import net.minecraft.world.storage.ISaveHandler; * @author James Seibel * @version 01-30-2021 */ -public class LodFileHandler +public class LodDimensionFileHandler { - private LodDimension loadedRegion = null; + private LodDimension loadedDimension = null; public long regionLastWriteTime[][]; // String s = Minecraft.getMinecraftDir().getCanonicalPath() + "/saves/" + world.getSaveHandler().getSaveDirectoryName() + "/data/AA/World" + world.provider.dimensionId + ".dat"; @@ -36,19 +36,17 @@ public class LodFileHandler private final String FILE_EXTENSION = ".txt"; private ExecutorService fileWritingThreadPool = Executors.newFixedThreadPool(1); - /** Is true if the readyToReadAndWrite is false */ - private boolean waitingToSaveRegions = false; - public LodFileHandler(ISaveHandler newSaveHandler, LodDimension newLoadedRegion) + public LodDimensionFileHandler(ISaveHandler newSaveHandler, LodDimension newLoadedDimension) { saveHandler = newSaveHandler; - loadedRegion = newLoadedRegion; + loadedDimension = newLoadedDimension; // these two variable are used in sync with the LodDimension - regionLastWriteTime = new long[loadedRegion.getWidth()][loadedRegion.getWidth()]; - for(int i = 0; i < loadedRegion.getWidth(); i++) - for(int j = 0; j < loadedRegion.getWidth(); j++) + regionLastWriteTime = new long[loadedDimension.getWidth()][loadedDimension.getWidth()]; + for(int i = 0; i < loadedDimension.getWidth(); i++) + for(int j = 0; j < loadedDimension.getWidth(); j++) regionLastWriteTime[i][j] = -1; if (saveHandler != null && saveHandler.getWorldDirectory() != null) @@ -141,8 +139,10 @@ public class LodFileHandler // Save to File // //==============// - - public synchronized void saveDirtyRegionsToFile() + /** + * Save all dirty regions in this LodDimension to file. + */ + public synchronized void saveDirtyRegionsToFileAsync() { // we don't currently support reading or writing // files when connected to a server @@ -150,64 +150,31 @@ public class LodFileHandler return; if (!readyToReadAndWrite()) - { // we aren't ready to read and write yet - if(!waitingToSaveRegions) - { - waitingToSaveRegions = true; - - // retry until we are able to read and write - // then wake up the fileWritingThreadPool - Thread retryReady = new Thread(() -> - { - try - { - // check once every so often so see - // if anything has changed so we can - // start reading and writing files - while(!readyToReadAndWrite()) - { - this.wait(1000); - // get the save handler again, if for some - // reason the original handler was null - saveHandler = Minecraft.getMinecraft().getIntegratedServer().getWorld(0).getSaveHandler(); - save_dir = getWorldSaveDirectory(); - } - - // we can start writing files now - fileWritingThreadPool.execute(saveDirtyRegionsThread); - waitingToSaveRegions = false; - } - catch (InterruptedException e) - { /* should never be called */} - }); - - retryReady.run(); - } - return; - } fileWritingThreadPool.execute(saveDirtyRegionsThread); } private Thread saveDirtyRegionsThread = new Thread(() -> { - for(int i = 0; i < loadedRegion.getWidth(); i++) + for(int i = 0; i < loadedDimension.getWidth(); i++) { - for(int j = 0; j < loadedRegion.getWidth(); j++) + for(int j = 0; j < loadedDimension.getWidth(); j++) { - if(loadedRegion.isRegionDirty[i][j]) + if(loadedDimension.isRegionDirty[i][j]) { - saveRegionToDisk(loadedRegion.regions[i][j]); - loadedRegion.isRegionDirty[i][j] = false; + saveRegionToDisk(loadedDimension.regions[i][j]); + loadedDimension.isRegionDirty[i][j] = false; } } } - - waitingToSaveRegions = false; }); - + /** + * Save a specific region to disk.
+ * Note: it will save to the LodDimension that this + * handler is associated with. + */ private void saveRegionToDisk(LodRegion region) { if (!readyToReadAndWrite() || region == null) @@ -258,15 +225,13 @@ public class LodFileHandler * Return the name of the file that should contain the * region at the given x and z.
* Returns null if this object isn't ready to read and write. - * @param regionX - * @param regionZ */ private String getFileNameForRegion(int regionX, int regionZ) { if (!readyToReadAndWrite()) return null; - return save_dir + "\\lod_data\\DIM" + loadedRegion.dimension.getId() + "\\" + + return save_dir + "\\lod_data\\DIM" + loadedDimension.dimension.getId() + "\\" + FILE_NAME_PREFIX + "." + regionX + "." + regionZ + FILE_EXTENSION; } @@ -274,6 +239,8 @@ public class LodFileHandler /** * Returns if this FileHandler is ready to read * and write files. + *
+ * This returns true when the world save directory is known. */ public boolean readyToReadAndWrite() { @@ -306,6 +273,8 @@ public class LodFileHandler /** + * Gets the canonical path to the world save folder. + *
* Returns null if there was an IO Exception */ private String getWorldSaveDirectory() diff --git a/src/main/java/com/backsun/lod/handlers/ReflectionHandler.java b/src/main/java/com/backsun/lod/handlers/ReflectionHandler.java index 65a3d9788..12215fda5 100644 --- a/src/main/java/com/backsun/lod/handlers/ReflectionHandler.java +++ b/src/main/java/com/backsun/lod/handlers/ReflectionHandler.java @@ -11,7 +11,8 @@ import net.minecraft.client.Minecraft; /** * This object is used to get variables from methods - * where they are private. + * where they are private. Specifically the fog setting + * in Optifine. * * @author James Seibel * @version 09-21-2020 diff --git a/src/main/java/com/backsun/lod/objects/LodChunk.java b/src/main/java/com/backsun/lod/objects/LodChunk.java index 0069d7403..2064fceb5 100644 --- a/src/main/java/com/backsun/lod/objects/LodChunk.java +++ b/src/main/java/com/backsun/lod/objects/LodChunk.java @@ -3,7 +3,7 @@ package com.backsun.lod.objects; import java.awt.Color; import com.backsun.lod.util.enums.ColorDirection; -import com.backsun.lod.util.enums.LodLocation; +import com.backsun.lod.util.enums.LodCorner; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; @@ -73,7 +73,7 @@ public class LodChunk //==============// /** - * Create an empty LodChunk + * Create an empty invisible LodChunk at (0,0) */ public LodChunk() { @@ -145,7 +145,7 @@ public class LodChunk // top top = new short[4]; - for(LodLocation loc : LodLocation.values()) + for(LodCorner loc : LodCorner.values()) { lastIndex = index; index = data.indexOf(DATA_DELIMITER, lastIndex + 1); @@ -156,7 +156,7 @@ public class LodChunk // bottom bottom = new short[4]; - for(LodLocation loc : LodLocation.values()) + for(LodCorner loc : LodCorner.values()) { lastIndex = index; index = data.indexOf(DATA_DELIMITER, lastIndex + 1); @@ -202,11 +202,11 @@ public class LodChunk } /** - * Illegal argument is thrown if either the - * chunk or world is null. The reason the world - * can't be null is because it's required to determine - * a block's color. - * @throws IllegalArgumentException + * Creates a LodChunk for a chunk in the given world.
+ * Note: The world is required to determine each block's color + * + * @throws IllegalArgumentException + * thrown if either the chunk or world is null. */ public LodChunk(Chunk chunk, World world) throws IllegalArgumentException { @@ -228,16 +228,16 @@ public class LodChunk colors = new Color[6]; // generate the top and bottom points of this LOD - for(LodLocation loc : LodLocation.values()) + for(LodCorner loc : LodCorner.values()) { - top[loc.value] = generateLodSection(chunk, true, loc); - bottom[loc.value] = generateLodSection(chunk, false, loc); + top[loc.value] = generateLodCorner(chunk, SectionGenerationMode.GENERATE_TOP, loc); + bottom[loc.value] = generateLodCorner(chunk, SectionGenerationMode.GENERATE_BOTTOM, loc); } // determine the average color for each direction for(ColorDirection dir : ColorDirection.values()) { - colors[dir.value] = generateLodColorSection(chunk, world, dir); + colors[dir.value] = generateLodColor(chunk, world, dir); } } @@ -253,15 +253,17 @@ public class LodChunk /** + * Generate the height for the given LodLocation, either the top or bottom. + *

* If invalid/null/empty chunks are given * crashes may occur. */ - public short generateLodSection(Chunk chunk, boolean getTopSection, LodLocation lodLoc) + private short generateLodCorner(Chunk chunk, SectionGenerationMode generationMode, LodCorner lodLoc) { // should have a length of 16 // (each storage is 16x16x16 and the // world height is 256) - ExtendedBlockStorage[] data = chunk.getBlockStorageArray(); + ExtendedBlockStorage[] blockStorage = chunk.getBlockStorageArray(); @@ -313,21 +315,29 @@ public class LodChunk } - if(getTopSection) - return determineTopPoint(data, startX, endX, startZ, endZ); + if(generationMode == SectionGenerationMode.GENERATE_TOP) + return determineTopPoint(blockStorage, startX, endX, startZ, endZ); else - return determineBottomPoint(data, startX, endX, startZ, endZ); + return determineBottomPoint(blockStorage, startX, endX, startZ, endZ); + } + /** GENERATE_TOP, GENERATE_BOTTOM */ + private enum SectionGenerationMode + { + GENERATE_TOP, + GENERATE_BOTTOM; } - private short determineBottomPoint(ExtendedBlockStorage[] data, int startX, int endX, int startZ, int endZ) + /** + * Find the lowest valid point from the bottom. + */ + private short determineBottomPoint(ExtendedBlockStorage[] blockStorage, int startX, int endX, int startZ, int endZ) { // search from the bottom up - for(int i = 0; i < data.length; i++) + for(int i = 0; i < blockStorage.length; i++) { for(int y = 0; y < CHUNK_DATA_HEIGHT; y++) { - - if(isLayerValidLodPoint(data, startX, endX, startZ, endZ, i, y)) + if(isLayerValidLodPoint(blockStorage, startX, endX, startZ, endZ, i, y)) { // we found // enough blocks in this @@ -335,23 +345,24 @@ public class LodChunk // LOD point return (short) (y + (i * CHUNK_DATA_HEIGHT)); } - - } // y - } // data - + } + } // we never found a valid LOD point return -1; } - private short determineTopPoint(ExtendedBlockStorage[] data, int startX, int endX, int startZ, int endZ) + /** + * Find the highest valid point from the Top + */ + private short determineTopPoint(ExtendedBlockStorage[] blockStorage, int startX, int endX, int startZ, int endZ) { // search from the top down - for(int i = data.length - 1; i >= 0; i--) + for(int i = blockStorage.length - 1; i >= 0; i--) { for(int y = CHUNK_DATA_WIDTH - 1; y >= 0; y--) { - if(isLayerValidLodPoint(data, startX, endX, startZ, endZ, i, y)) + if(isLayerValidLodPoint(blockStorage, startX, endX, startZ, endZ, i, y)) { // we found // enough blocks in this @@ -359,10 +370,8 @@ public class LodChunk // LOD point return (short) (y + (i * CHUNK_DATA_HEIGHT)); } - } // y - } // data - - + } + } // we never found a valid LOD point return -1; @@ -373,7 +382,7 @@ public class LodChunk * values a valid LOD point? */ private boolean isLayerValidLodPoint( - ExtendedBlockStorage[] data, + ExtendedBlockStorage[] blockStorage, int startX, int endX, int startZ, int endZ, int dataIndex, int y) @@ -385,7 +394,7 @@ public class LodChunk { for(int z = startZ; z < endZ; z++) { - if(data[dataIndex] == null) + if(blockStorage[dataIndex] == null) { // this section doesn't have any blocks, // it is not a valid section @@ -393,7 +402,7 @@ public class LodChunk } else { - if(data[dataIndex].get(x, y, z) != null && Block.getIdFromBlock(data[dataIndex].get(x, y, z).getBlock()) != airBlockId) + if(blockStorage[dataIndex].get(x, y, z) != null && Block.getIdFromBlock(blockStorage[dataIndex].get(x, y, z).getBlock()) != airBlockId) { // we found a valid block in // in this layer @@ -412,9 +421,11 @@ public class LodChunk return false; } - - - private Color generateLodColorSection(Chunk chunk, World world, ColorDirection colorDir) + /** + * Generate the color of the given ColorDirection at the given chunk + * in the given world. + */ + private Color generateLodColor(Chunk chunk, World world, ColorDirection colorDir) { Minecraft mc = Minecraft.getMinecraft(); BlockColors bc = mc.getBlockColors(); @@ -441,11 +452,18 @@ public class LodChunk } /** - * Only accepts TOP and BOTTOM as ColorPositions + * Generates the color of the top or bottom of a given chunk in the given world. + * + * @throws IllegalArgumentException if given a ColorDirection other than TOP or BOTTOM */ private Color generateLodColorVertical(Chunk chunk, ColorDirection colorDir, World world, BlockColors bc) { - ExtendedBlockStorage[] data = chunk.getBlockStorageArray(); + if(colorDir != ColorDirection.TOP && colorDir != ColorDirection.BOTTOM) + { + throw new IllegalArgumentException("generateLodColorVertical only accepts the ColorDirection TOP or BOTTOM"); + } + + ExtendedBlockStorage[] blockStorage = chunk.getBlockStorageArray(); int numbOfBlocks = 0; int red = 0; @@ -456,8 +474,8 @@ public class LodChunk // either go top down or bottom up - int dataStart = goTopDown? data.length - 1 : 0; - int dataMax = data.length; + int dataStart = goTopDown? blockStorage.length - 1 : 0; + int dataMax = blockStorage.length; int dataMin = 0; int dataIncrement = goTopDown? -1 : 1; @@ -474,16 +492,16 @@ public class LodChunk for(int di = dataStart; !foundBlock && di >= dataMin && di < dataMax; di += dataIncrement) { - if(!foundBlock && data[di] != null) + if(!foundBlock && blockStorage[di] != null) { for(int y = topStart; !foundBlock && y >= topMin && y < topMax; y += topIncrement) { int ci; - if(Block.getIdFromBlock(data[di].get(x, y, z).getBlock()) == waterBlockId) + if(Block.getIdFromBlock(blockStorage[di].get(x, y, z).getBlock()) == waterBlockId) // this is a special case since getColor on water generally returns white ci = waterColor; else - ci = bc.getColor(data[di].get(x, y, z), world, new BlockPos(x,y,z)); + ci = bc.getColor(blockStorage[di].get(x, y, z), world, new BlockPos(x,y,z)); if(ci == 0) { @@ -519,10 +537,20 @@ public class LodChunk return new Color(red, green, blue); } - + + /** + * Generates the color of the side of a given chunk in the given world for the given ColorDirection. + * + * @throws IllegalArgumentException if given a ColorDirection other than N, S, W, E (North, South, East, West) + */ private Color generateLodColorHorizontal(Chunk chunk, ColorDirection colorDir, World world, BlockColors bc) { - ExtendedBlockStorage[] data = chunk.getBlockStorageArray(); + if(colorDir != ColorDirection.N && colorDir != ColorDirection.S && colorDir != ColorDirection.E && colorDir != ColorDirection.W) + { + throw new IllegalArgumentException("generateLodColorHorizontal only accepts the ColorDirection N (North), S (South), E (East), or W (West)"); + } + + ExtendedBlockStorage[] blockStorage = chunk.getBlockStorageArray(); int numbOfBlocks = 0; int red = 0; @@ -563,9 +591,9 @@ public class LodChunk } - for (int di = 0; di < data.length; di++) + for (int di = 0; di < blockStorage.length; di++) { - if (data[di] != null) + if (blockStorage[di] != null) { for (int y = 0; y < CHUNK_DATA_HEIGHT; y++) { @@ -607,11 +635,11 @@ public class LodChunk } int ci; - if(Block.getIdFromBlock(data[di].get(x, y, z).getBlock()) == waterBlockId) + if(Block.getIdFromBlock(blockStorage[di].get(x, y, z).getBlock()) == waterBlockId) // this is a special case since getColor on water generally returns white ci = waterColor; else - ci = bc.getColor(data[di].get(x, y, z), world, new BlockPos(x,y,z)); + ci = bc.getColor(blockStorage[di].get(x, y, z), world, new BlockPos(x,y,z)); if (ci == 0) { // skip air or invisible blocks @@ -671,6 +699,30 @@ public class LodChunk + //================// + // misc functions // + //================// + + /** + * If this LOD is either invisible from every + * direction or doesn't have a valid height + * it is empty. + */ + public boolean isLodEmpty() + { + for(LodCorner corner : LodCorner.values()) + if(top[corner.value] != -1 || bottom[corner.value] != -1) + // at least one corner is valid + return false; + + Color invisible = new Color(0,0,0,0); + for(ColorDirection dir : ColorDirection.values()) + if(!colors[dir.value].equals(invisible)) + // at least one direction has a non-invisible color + return false; + + return true; + } @@ -681,7 +733,6 @@ public class LodChunk //========// - /** * Outputs all data in csv format * with the given delimiter. @@ -727,27 +778,6 @@ public class LodChunk s += "x: " + x + " z: " + z + "\t"; -// s += "top: "; -// for(int i = 0; i < top.length; i++) -// { -// s += top[i] + " "; -// } -// s += "\t"; - -// s += "bottom: "; -// for(int i = 0; i < bottom.length; i++) -// { -// s += bottom[i] + " "; -// } -// s += "\t"; - -// s += "colors "; -// for(int i = 0; i < colors.length; i++) -// { -// if(colors[i] != null) -// s += "(" + colors[i].getRed() + ", " + colors[i].getGreen() + ", " + colors[i].getBlue() + "), "; -// } - s += "(" + colors[ColorDirection.TOP.value].getRed() + ", " + colors[ColorDirection.TOP.value].getGreen() + ", " + colors[ColorDirection.TOP.value].getBlue() + "), "; return s; diff --git a/src/main/java/com/backsun/lod/objects/LodDimension.java b/src/main/java/com/backsun/lod/objects/LodDimension.java index e645da3a1..f6be82e56 100644 --- a/src/main/java/com/backsun/lod/objects/LodDimension.java +++ b/src/main/java/com/backsun/lod/objects/LodDimension.java @@ -1,6 +1,6 @@ package com.backsun.lod.objects; -import com.backsun.lod.handlers.LodFileHandler; +import com.backsun.lod.handlers.LodDimensionFileHandler; import net.minecraft.client.Minecraft; import net.minecraft.world.DimensionType; @@ -10,13 +10,13 @@ import net.minecraft.world.DimensionType; * for a given dimension. * * @author James Seibel - * @version 01-31-2021 + * @version 02-23-2021 */ public class LodDimension { public final DimensionType dimension; - private volatile int width; // if this ever changes make sure to update the halfWidth too + private volatile int width; private volatile int halfWidth; public LodRegion regions[][]; @@ -25,7 +25,8 @@ public class LodDimension private int centerX; private int centerZ; - private LodFileHandler rfHandler; + private LodDimensionFileHandler fileHandler; + public LodDimension(DimensionType newDimension, int newMaxWidth) { @@ -33,7 +34,7 @@ public class LodDimension width = newMaxWidth; // dimension 0 works here since we are just looking for the save handler anyway - rfHandler = new LodFileHandler(Minecraft.getMinecraft().getIntegratedServer().getWorld(0).getSaveHandler(), this); + fileHandler = new LodDimensionFileHandler(Minecraft.getMinecraft().getIntegratedServer().getWorld(0).getSaveHandler(), this); regions = new LodRegion[width][width]; isRegionDirty = new boolean[width][width]; @@ -50,7 +51,10 @@ public class LodDimension } - + /** + * Move the center of this LodDimension and move all owned + * regions over by the given x and z offset. + */ public void move(int xOffset, int zOffset) { // if the x or z offset is equal to or greater than @@ -144,22 +148,16 @@ public class LodDimension } - public int getCenterX() - { - return centerX; - } - - public int getCenterZ() - { - return centerZ; - } - - - + /** + * Gets the region at the given X and Z + *
+ * Returns null if the region doesn't exist + * or is outside the loaded area. + */ public LodRegion getRegion(int regionX, int regionZ) { int xIndex = (regionX - centerX) + halfWidth; @@ -201,7 +199,11 @@ public class LodDimension - + /** + * Add the given LOD to this dimension at the coordinate + * stored in the LOD. If an LOD already exists at the given + * coordinates it will be overwritten. + */ public void addLod(LodChunk lod) { int regionX = (lod.x + centerX) / LodRegion.SIZE; @@ -236,14 +238,15 @@ public class LodDimension int xIndex = (regionX - centerX) + halfWidth; int zIndex = (regionZ - centerZ) + halfWidth; isRegionDirty[xIndex][zIndex] = true; - - - - rfHandler.saveDirtyRegionsToFile(); + fileHandler.saveDirtyRegionsToFileAsync(); } /** - * Returns null if the LodChunk isn't loaded + * Get the LodChunk at the given X and Z coordinates + * in this dimension. + *
+ * Returns null if the LodChunk doesn't exist or + * is outside the loaded area. */ public LodChunk getLodFromCoordinates(int chunkX, int chunkZ) { @@ -271,11 +274,13 @@ public class LodDimension } - - + /** + * Get the region at the given X and Z coordinates from the + * RegionFileHandler. + */ public LodRegion getRegionFromFile(int regionX, int regionZ) { - return rfHandler.loadRegionFromFile(regionX, regionZ); + return fileHandler.loadRegionFromFile(regionX, regionZ); } @@ -293,6 +298,22 @@ public class LodDimension + + + + + public int getCenterX() + { + return centerX; + } + + public int getCenterZ() + { + return centerZ; + } + + + public int getWidth() { return width; @@ -311,6 +332,18 @@ public class LodDimension for(int j = 0; j < width; j++) isRegionDirty[i][j] = false; } + + + @Override + public String toString() + { + String s = ""; + + s += "dim: " + dimension.getName() + "\t"; + s += "(" + centerX + "," + centerZ + ")"; + + return s; + } } diff --git a/src/main/java/com/backsun/lod/objects/LodRegion.java b/src/main/java/com/backsun/lod/objects/LodRegion.java index 7e826ddec..88c7a9b90 100644 --- a/src/main/java/com/backsun/lod/objects/LodRegion.java +++ b/src/main/java/com/backsun/lod/objects/LodRegion.java @@ -7,7 +7,7 @@ package com.backsun.lod.objects; * one file in the file system. * * @author James Seibel - * @version 1-20-2021 + * @version 1-22-2021 */ public class LodRegion { @@ -31,6 +31,11 @@ public class LodRegion } + /** + * Add the given LOD to this region at the coordinate + * stored in the LOD. If an LOD already exists at the given + * coordinates it will be overwritten. + */ public void addLod(LodChunk lod) { // we use ABS since LODs can be negative, but if they are @@ -43,6 +48,13 @@ public class LodRegion chunks[xIndex][zIndex] = lod; } + /** + * Get the LodChunk at the given X and Z coordinates + * in this region. + *
+ * Returns null if the LodChunk doesn't exist or + * is outside the loaded area. + */ public LodChunk getLod(int chunkX, int chunkZ) { // since we add LOD's with ABS, we get them the same way @@ -52,11 +64,16 @@ public class LodRegion if(arrayX >= SIZE || arrayZ >= SIZE) return null; + // TODO fix some LOD strips showing up in the wrong location + // issue #2 + // maybe this has to do with ABS being used incorrectly? return chunks[arrayX][arrayZ]; } - + /** + * Returns all LodChunks in this region + */ public LodChunk[][] getAllLods() { return chunks; diff --git a/src/main/java/com/backsun/lod/objects/LodWorld.java b/src/main/java/com/backsun/lod/objects/LodWorld.java index d961388fd..f7bcfa52b 100644 --- a/src/main/java/com/backsun/lod/objects/LodWorld.java +++ b/src/main/java/com/backsun/lod/objects/LodWorld.java @@ -1,14 +1,13 @@ package com.backsun.lod.objects; -import java.util.Dictionary; -import java.util.Enumeration; import java.util.Hashtable; +import java.util.Map; /** * This stores all LODs for a given world. * * @author James Seibel - * @version 01-31-2021 + * @version 02-22-2021 */ public class LodWorld { @@ -17,7 +16,7 @@ public class LodWorld /** * Key = Dimension id (as an int) */ - private Dictionary lodDimensions; + private Map lodDimensions; public LodWorld(String newWorldName) @@ -38,12 +37,27 @@ public class LodWorld return lodDimensions.get(dimensionId); } - + /** + * Resizes the max width in regions that each LodDimension + * should use. + */ public void resizeDimensionRegionWidth(int newWidth) { - Enumeration keys = lodDimensions.keys(); + for(Integer key : lodDimensions.keySet()) + lodDimensions.get(key).setRegionWidth(newWidth); + } + + + + @Override + public String toString() + { + String s = ""; - while(keys.hasMoreElements()) - lodDimensions.get(keys.nextElement()).setRegionWidth(newWidth); + s += worldName + "\t - dimensions: "; + for(Integer key : lodDimensions.keySet()) + s += lodDimensions.get(key).dimension.getName() + ", "; + + return s; } } diff --git a/src/main/java/com/backsun/lod/proxy/ClientProxy.java b/src/main/java/com/backsun/lod/proxy/ClientProxy.java index c52d66a4f..9785338f4 100644 --- a/src/main/java/com/backsun/lod/proxy/ClientProxy.java +++ b/src/main/java/com/backsun/lod/proxy/ClientProxy.java @@ -22,10 +22,11 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; // Minecraft.getMinecraft().getIntegratedServer() /** - * This is used by the client. + * This handles all events sent to the client, + * and is the starting point for most of this program. * * @author James_Seibel - * @version 02-21-2021 + * @version 02-23-2021 */ public class ClientProxy extends CommonProxy { @@ -57,6 +58,10 @@ public class ClientProxy extends CommonProxy GL11.glDisable(GL11.GL_STENCIL_TEST); } + /** + * Do any setup that is required to draw LODs + * and then tell the LodRenderer to draw. + */ public void renderLods(float partialTicks) { int newWidth = Math.max(4, (Minecraft.getMinecraft().gameSettings.renderDistanceChunks * LodChunk.WIDTH * 2) / LodRegion.SIZE); @@ -116,7 +121,7 @@ public class ClientProxy extends CommonProxy @SubscribeEvent public void chunkLoadEvent(ChunkEvent event) { - lodWorld = lodBuilder.generateLodChunk(event.getChunk()); + lodWorld = lodBuilder.generateLodChunkAsync(event.getChunk()); } /** @@ -132,7 +137,7 @@ public class ClientProxy extends CommonProxy if(world != null) { - lodWorld = lodBuilder.generateLodChunk(world.getChunkFromChunkCoords(event.getChunkX(), event.getChunkZ())); + lodWorld = lodBuilder.generateLodChunkAsync(world.getChunkFromChunkCoords(event.getChunkX(), event.getChunkZ())); } } } diff --git a/src/main/java/com/backsun/lod/proxy/CommonProxy.java b/src/main/java/com/backsun/lod/proxy/CommonProxy.java index 0b0498ad5..5362c2e93 100644 --- a/src/main/java/com/backsun/lod/proxy/CommonProxy.java +++ b/src/main/java/com/backsun/lod/proxy/CommonProxy.java @@ -1,7 +1,7 @@ package com.backsun.lod.proxy; /** - * This is used by the server. + * This handles any events sent to the server. * * @author James_Seibel * @version 08-31-2020 diff --git a/src/main/java/com/backsun/lod/renderer/LodRenderer.java b/src/main/java/com/backsun/lod/renderer/LodRenderer.java index e3e5bbb85..10a559da2 100644 --- a/src/main/java/com/backsun/lod/renderer/LodRenderer.java +++ b/src/main/java/com/backsun/lod/renderer/LodRenderer.java @@ -24,7 +24,7 @@ import com.backsun.lod.util.LodConfig; import com.backsun.lod.util.enums.ColorDirection; import com.backsun.lod.util.enums.FogDistance; import com.backsun.lod.util.enums.FogQuality; -import com.backsun.lod.util.enums.LodLocation; +import com.backsun.lod.util.enums.LodCorner; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; @@ -41,6 +41,10 @@ import net.minecraft.util.math.MathHelper; */ public class LodRenderer { + /** this is the light used when rendering the LODs, + * it should be something different than what is used by Minecraft */ + private static final int LOD_GL_LIGHT_NUMBER = GL11.GL_LIGHT2; + /** If true the LODs colors will be replaced with * a checkerboard, this can be used for debugging. */ public boolean debugging = false; @@ -98,23 +102,22 @@ public class LodRenderer mc = Minecraft.getMinecraft(); // for some reason "Tessellator.getInstance()" won't work here, we have to create a new one - tessellator = new Tessellator(2097152); + tessellator = new Tessellator(2097152); // the number here is what is used by the default Tessellator bufferBuilder = tessellator.getBuffer(); reflectionHandler = new ReflectionHandler(); } - + /** + * Besides drawing the LODs this method also starts + * the async process of generating the Buffers that hold those LODs. + * + * @param newDimension The dimension to draw, if null doesn't replace the current dimension. + * @param partialTicks how far into the current tick this method was called. + */ public void drawLODs(LodDimension newDimension, float partialTicks) { - if (reflectionHandler.fovMethod == null) - { - // don't continue if we can't get the - // user's FOV - return; - } - if (reflectionHandler.fovMethod == null) { // we aren't able to get the user's @@ -131,6 +134,19 @@ public class LodRenderer + + + //===============// + // initial setup // + //===============// + + + // used for debugging and viewing how long different processes take + mc.mcProfiler.endSection(); + mc.mcProfiler.startSection("LOD"); + mc.mcProfiler.startSection("LOD setup"); + + // should LODs be regenerated? if ((int)Minecraft.getMinecraft().player.posX / LodChunk.WIDTH != prevChunkX || (int)Minecraft.getMinecraft().player.posZ / LodChunk.WIDTH != prevChunkZ || @@ -138,6 +154,7 @@ public class LodRenderer prevFogDistance != LodConfig.fogDistance || lodDimension != newDimension) { + // yes regen = true; prevChunkX = (int)Minecraft.getMinecraft().player.posX / LodChunk.WIDTH; @@ -152,17 +169,9 @@ public class LodRenderer regen = false; } - lodDimension = newDimension; + if (newDimension != null) + lodDimension = newDimension; - - - - - - // used for debugging and viewing how long different processes take - mc.mcProfiler.endSection(); - mc.mcProfiler.startSection("LOD"); - mc.mcProfiler.startSection("LOD setup"); if (LodConfig.drawCheckerBoard) { if (debugging != LodConfig.drawCheckerBoard) @@ -183,9 +192,6 @@ public class LodRenderer double cameraX = player.lastTickPosX + (player.posX - player.lastTickPosX) * partialTicks; double cameraY = player.lastTickPosY + (player.posY - player.lastTickPosY) * partialTicks; double cameraZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialTicks; - - - // determine how far the game's render distance is currently set int renderDistWidth = mc.gameSettings.renderDistanceChunks; @@ -204,29 +210,32 @@ public class LodRenderer // create the LODs // //=================// - // only regenerate LODs if: + // only regenerate the LODs if: // 1. we want to regenerate LODs - // 2. we aren't already regenerating LODs + // 2. we aren't already regenerating the LODs // 3. we aren't waiting for the build and draw buffers to swap + // (this is to prevent thread conflicts) if (regen && !regenerating && !switchBuffers) { mc.mcProfiler.endStartSection("LOD generation"); regenerating = true; - + // this will only be called once, unless the numbBufferThreads changes if (numbBufferThreads != bufferThreads.size()) setupBufferThreads(); + // this will mainly happen when the view distance is changed if (drawableNearBuffers == null || drawableFarBuffers == null || previousChunkRenderDistance != mc.gameSettings.renderDistanceChunks) setupBuffers(numbChunksWide); - + // generate the LODs on a separate thread to prevent stuttering or freezing genThread.execute(createLodBufferGenerationThread(cameraX, cameraZ, numbChunksWide)); } // replace the buffers used to draw and build, - // this is done to keep everything thread safe + // this is only done when the createLodBufferGenerationThread + // has finished executing on a parallel thread. if (switchBuffers) { swapBuffers(); @@ -242,13 +251,13 @@ public class LodRenderer //===========================// // set the required open GL settings + GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glLineWidth(2.0f); GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_CULL_FACE); - GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); - + // move the LODs so they are in the correct place relative to the camera GlStateManager.translate(-cameraX, -cameraY, -cameraZ); setProjectionMatrix(partialTicks); @@ -266,21 +275,26 @@ public class LodRenderer switch(LodConfig.fogDistance) { case NEAR_AND_FAR: - mc.mcProfiler.endStartSection("LOD draw setup"); + // when drawing NEAR_AND_FAR fog we need 2 draw + // calls since fog can only go in one direction at a time + + mc.mcProfiler.endStartSection("LOD draw"); setupFog(FogDistance.NEAR, reflectionHandler.getFogQuality()); sendLodsToGpuAndDraw(drawableNearBuffers); - mc.mcProfiler.endStartSection("LOD draw setup"); + mc.mcProfiler.endStartSection("LOD draw"); setupFog(FogDistance.FAR, reflectionHandler.getFogQuality()); sendLodsToGpuAndDraw(drawableFarBuffers); break; + case NEAR: - mc.mcProfiler.endStartSection("LOD draw setup"); + mc.mcProfiler.endStartSection("LOD draw"); setupFog(FogDistance.NEAR, reflectionHandler.getFogQuality()); sendLodsToGpuAndDraw(drawableNearBuffers); break; + case FAR: - mc.mcProfiler.endStartSection("LOD draw setup"); + mc.mcProfiler.endStartSection("LOD draw"); setupFog(FogDistance.FAR, reflectionHandler.getFogQuality()); sendLodsToGpuAndDraw(drawableFarBuffers); break; @@ -302,7 +316,7 @@ public class LodRenderer GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glDisable(GL11.GL_LIGHT2); + GL11.glDisable(LOD_GL_LIGHT_NUMBER); GL11.glDisable(GL11.GL_COLOR_MATERIAL); // change the perspective matrix back to prevent incompatibilities @@ -319,49 +333,11 @@ public class LodRenderer } - - - /** - * draw an array of cubes (or squares) with the given colors. - * @param lods bounding boxes to draw - * @param colors color of each box to draw + * This is where the actual drawing happens. + * + * @param buffers the buffers sent to the GPU to draw */ - private void generateLodBuffers(AxisAlignedBB[][] lods, Color[][] colors, FogDistance fogDistance) - { - List> bufferFutures = new ArrayList<>(); - - for(int i = 0; i < numbBufferThreads; i++) - { - bufferThreads.get(i).setNewData(buildableNearBuffers[i], buildableFarBuffers[i], fogDistance, lods, colors, i, numbBufferThreads); - } - - try - { - bufferFutures = bufferThreadPool.invokeAll(bufferThreads); - } - catch (InterruptedException e) - { - // this should never happen, but just in case - e.printStackTrace(); - } - - for(int i = 0; i < numbBufferThreads; i++) - { - try - { - buildableNearBuffers[i] = bufferFutures.get(i).get().nearBuffer; - buildableFarBuffers[i] = bufferFutures.get(i).get().farBuffer; - } - catch(CancellationException | ExecutionException| InterruptedException e) - { - // this should never happen, but just in case - e.printStackTrace(); - } - } - - } - private void sendLodsToGpuAndDraw(BufferBuilder[] buffers) { for(int i = 0; i < numbBufferThreads; i++) @@ -371,11 +347,10 @@ public class LodRenderer bufferBuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); bufferBuilder.getByteBuffer().clear(); + // replace the data in bufferBuilder with the data from the given buffer bufferBuilder.putBulkData(buffers[i].getByteBuffer()); - mc.mcProfiler.endStartSection("LOD draw"); tessellator.draw(); - mc.mcProfiler.endStartSection("LOD draw setup"); bufferBuilder.getByteBuffer().clear(); // this is required otherwise nothing is drawn } @@ -451,7 +426,6 @@ public class LodRenderer /** * create a new projection matrix and send it over to the GPU * @param partialTicks how many ticks into the frame we are - * @return true if the matrix was successfully created and sent to the GPU, false otherwise */ private void setProjectionMatrix(float partialTicks) { @@ -483,16 +457,18 @@ public class LodRenderer float gammaMultiplyer = (mc.gameSettings.gammaSetting * 0.5f + 0.5f); float lightStrength = sunBrightness * skyHasLight * gammaMultiplyer; float lightAmbient[] = {lightStrength, lightStrength, lightStrength, 1.0f}; - + ByteBuffer temp = ByteBuffer.allocateDirect(16); temp.order(ByteOrder.nativeOrder()); - GL11.glLight(GL11.GL_LIGHT2, GL11.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip()); - GL11.glEnable(GL11.GL_LIGHT2); // Enable the above lighting + GL11.glLight(LOD_GL_LIGHT_NUMBER, GL11.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip()); + GL11.glEnable(LOD_GL_LIGHT_NUMBER); // Enable the above lighting GlStateManager.enableLighting(); } - + /** + * create the BuildBufferThreads + */ private void setupBufferThreads() { bufferThreads.clear(); @@ -501,7 +477,7 @@ public class LodRenderer } /** - * + * Create all buffers that will be used. */ private void setupBuffers(int numbChunksWide) { @@ -540,17 +516,17 @@ public class LodRenderer /** - * Returns -1 if there are no valid points + * @Returns -1 if there are no valid points */ - private int getHighestPointInLod(short[] heightPoints) + private int getValidHeightPoint(short[] heightPoints) { - if (heightPoints[LodLocation.NE.value] != -1) - return heightPoints[LodLocation.NE.value]; - if (heightPoints[LodLocation.NW.value] != -1) - return heightPoints[LodLocation.NW.value]; - if (heightPoints[LodLocation.SE.value] != -1) - return heightPoints[LodLocation.NE.value]; - return heightPoints[LodLocation.NE.value]; + if (heightPoints[LodCorner.NE.value] != -1) + return heightPoints[LodCorner.NE.value]; + if (heightPoints[LodCorner.NW.value] != -1) + return heightPoints[LodCorner.NW.value]; + if (heightPoints[LodCorner.SE.value] != -1) + return heightPoints[LodCorner.NE.value]; + return heightPoints[LodCorner.NE.value]; } @@ -603,7 +579,7 @@ public class LodRenderer // this is just how chunk loading/unloading works. This can hopefully // be hidden with careful use of fog) int middle = (numbChunksWide / 2); - if (RenderUtil.isCoordinateInLoadedArea(i, j, middle)) + if (isCoordInCenterArea(i, j, middle)) { continue; } @@ -660,8 +636,8 @@ public class LodRenderer // add the new box to the array - int topPoint = getHighestPointInLod(lod.top); - int bottomPoint = getHighestPointInLod(lod.bottom); + int topPoint = getValidHeightPoint(lod.top); + int bottomPoint = getValidHeightPoint(lod.bottom); // don't draw an LOD if it is empty if (topPoint == -1 && bottomPoint == -1) @@ -679,6 +655,54 @@ public class LodRenderer return t; } + /** + * draw an array of boxes with the given colors. + *

+ * Currently only one color per box is supported. + * + * @param lods bounding boxes to draw + * @param colors color of each box to draw + */ + private void generateLodBuffers(AxisAlignedBB[][] lods, Color[][] colors, FogDistance fogDistance) + { + List> bufferFutures = new ArrayList<>(); + + // update the information that the bufferThreads are using + for(int i = 0; i < numbBufferThreads; i++) + { + bufferThreads.get(i).setNewData(buildableNearBuffers[i], buildableFarBuffers[i], fogDistance, lods, colors, i, numbBufferThreads); + } + + // run all the bufferThreads and get their results + try + { + bufferFutures = bufferThreadPool.invokeAll(bufferThreads); + } + catch (InterruptedException e) + { + // this should never happen, but just in case + e.printStackTrace(); + } + + // update our buildable buffers + for(int i = 0; i < numbBufferThreads; i++) + { + try + { + buildableNearBuffers[i] = bufferFutures.get(i).get().nearBuffer; + buildableFarBuffers[i] = bufferFutures.get(i).get().farBuffer; + } + catch(CancellationException | ExecutionException| InterruptedException e) + { + // this should never happen, but just in case + e.printStackTrace(); + } + } + } + + + + /** * Swap buildable and drawable buffers. */ @@ -705,4 +729,16 @@ public class LodRenderer + /** + * Returns if the given coordinate is in the loaded area of the world. + * @param centerCoordinate the center of the loaded world + */ + private boolean isCoordInCenterArea(int i, int j, int centerCoordinate) + { + return (i >= centerCoordinate - mc.gameSettings.renderDistanceChunks + && i <= centerCoordinate + mc.gameSettings.renderDistanceChunks) + && + (j >= centerCoordinate - mc.gameSettings.renderDistanceChunks + && j <= centerCoordinate + mc.gameSettings.renderDistanceChunks); + } } \ No newline at end of file diff --git a/src/main/java/com/backsun/lod/renderer/RenderUtil.java b/src/main/java/com/backsun/lod/renderer/RenderUtil.java deleted file mode 100644 index 8a9950c39..000000000 --- a/src/main/java/com/backsun/lod/renderer/RenderUtil.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.backsun.lod.renderer; - -import net.minecraft.client.Minecraft; - -/** - * This holds miscellaneous helper code - * to be used in the rendering process. - * - * @author James Seibel - * @version 2-13-2021 - */ -public class RenderUtil -{ - /** - * Returns if the given coordinate is in the loaded area of the world. - * @param centerCoordinate the center of the loaded world - */ - public static boolean isCoordinateInLoadedArea(int i, int j, int centerCoordinate) - { - Minecraft mc = Minecraft.getMinecraft(); - - return (i >= centerCoordinate - mc.gameSettings.renderDistanceChunks - && i <= centerCoordinate + mc.gameSettings.renderDistanceChunks) - && - (j >= centerCoordinate - mc.gameSettings.renderDistanceChunks - && j <= centerCoordinate + mc.gameSettings.renderDistanceChunks); - } - - - /** - * Find the coordinates that are in the center half of the given - * 2D matrix, starting at (0,0) and going to (2 * lodRadius, 2 * lodRadius). - */ - public static boolean isCoordinateInNearFogArea(int i, int j, int lodRadius) - { - int halfRadius = lodRadius / 2; - - return (i >= lodRadius - halfRadius - && i <= lodRadius + halfRadius) - && - (j >= lodRadius - halfRadius - && j <= lodRadius + halfRadius); - } - -} diff --git a/src/main/java/com/backsun/lod/util/LodConfig.java b/src/main/java/com/backsun/lod/util/LodConfig.java index 3cc12cbcb..4f5c02f86 100644 --- a/src/main/java/com/backsun/lod/util/LodConfig.java +++ b/src/main/java/com/backsun/lod/util/LodConfig.java @@ -9,6 +9,7 @@ import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; /** + * This is linked to Forge's mod config GUI. * * @author James Seibel * @version 02-14-2021 diff --git a/src/main/java/com/backsun/lod/util/Reference.java b/src/main/java/com/backsun/lod/util/Reference.java index fdb79e37b..f0bb4024c 100644 --- a/src/main/java/com/backsun/lod/util/Reference.java +++ b/src/main/java/com/backsun/lod/util/Reference.java @@ -1,6 +1,7 @@ package com.backsun.lod.util; /** + * This holds meta information about the mod. * * @author James Seibel * @version 04-16-2020 diff --git a/src/main/java/com/backsun/lod/util/enums/ColorDirection.java b/src/main/java/com/backsun/lod/util/enums/ColorDirection.java index 49a188951..9d4aa782f 100644 --- a/src/main/java/com/backsun/lod/util/enums/ColorDirection.java +++ b/src/main/java/com/backsun/lod/util/enums/ColorDirection.java @@ -1,10 +1,10 @@ package com.backsun.lod.util.enums; /** + * TOP, N, S, E, W, BOTTOM + * * @author James Seibel * @version 10-17-2020 - * - * TOP, N, S, E, W, BOTTOM */ public enum ColorDirection { diff --git a/src/main/java/com/backsun/lod/util/enums/DrawMode.java b/src/main/java/com/backsun/lod/util/enums/DrawMode.java deleted file mode 100644 index aee54e7d2..000000000 --- a/src/main/java/com/backsun/lod/util/enums/DrawMode.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.backsun.lod.util.enums; - -/** - * @author James Seibel - * @version 1-23-2021 - */ -public enum DrawMode -{ - /** Draw the LOD objects in groups. - *
- *
- * Fancy fog: render the center and outside LOD - * objects in 2 different groups. - *
- * Fast fog: render all LOD objects at one time. - */ - BATCH(0), - - /** Draw each LOD objects separately. - *
- *
- * Not suggested normally since draw calls are GPU expensive. - */ - INDIVIDUAL(5); - - public final int value; - - private DrawMode(int newValue) - { - value = newValue; - } -} diff --git a/src/main/java/com/backsun/lod/util/enums/FogDistance.java b/src/main/java/com/backsun/lod/util/enums/FogDistance.java index a3046993d..87dd8c3f0 100644 --- a/src/main/java/com/backsun/lod/util/enums/FogDistance.java +++ b/src/main/java/com/backsun/lod/util/enums/FogDistance.java @@ -8,9 +8,9 @@ package com.backsun.lod.util.enums; */ public enum FogDistance { - /** valid for both fast and fancy fog qualities. */ + /** good for fast or fancy fog qualities. */ NEAR, - /** valid for both fast and fancy fog qualities. */ + /** good for fast or fancy fog qualities. */ FAR, /** only looks good if the fog quality is set to Fancy. */ NEAR_AND_FAR; diff --git a/src/main/java/com/backsun/lod/util/enums/LodLocation.java b/src/main/java/com/backsun/lod/util/enums/LodCorner.java similarity index 82% rename from src/main/java/com/backsun/lod/util/enums/LodLocation.java rename to src/main/java/com/backsun/lod/util/enums/LodCorner.java index 47b03fc98..ac686f31f 100644 --- a/src/main/java/com/backsun/lod/util/enums/LodLocation.java +++ b/src/main/java/com/backsun/lod/util/enums/LodCorner.java @@ -1,13 +1,12 @@ package com.backsun.lod.util.enums; /** + * NE, SE, SW, NW * * @author James Seibel * @version 1-20-2020 - * - * NE, SE, SW, NW */ -public enum LodLocation +public enum LodCorner { // used for position @@ -22,7 +21,7 @@ public enum LodLocation public final int value; - private LodLocation(int newValue) + private LodCorner(int newValue) { value = newValue; } diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index a18922536..9b62a4086 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -3,7 +3,7 @@ "modid": "lod", "name": "Level Of Details", "description": "Generates and renders simplified chunks beyond the normal view distance, at a low performance cost.", - "version": "0.1", + "version": "1.0", "mcversion": "1.12.2", "url": "", "updateUrl": "",