Bring over improvements and changes from the master branch
This commit is contained in:
@@ -15,6 +15,10 @@ import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
|
||||
/**
|
||||
* Initialize and setup the Mod.
|
||||
* <br>
|
||||
* If you are looking for the real start of the mod
|
||||
* check out the ClientProxy.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-07-2021
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
package com.backsun.lod.builders;
|
||||
import java.awt.Color;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.backsun.lod.objects.NearFarBuffer;
|
||||
import com.backsun.lod.util.enums.FogDistance;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
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-23-2021
|
||||
*/
|
||||
public class BuildBufferThread implements Callable<NearFarBuffer>
|
||||
{
|
||||
public BufferBuilder nearBuffer;
|
||||
public BufferBuilder farBuffer;
|
||||
public FogDistance distanceMode;
|
||||
public AxisAlignedBB[][] lods;
|
||||
public Color[][] colors;
|
||||
|
||||
private int startLodIndex = 0;
|
||||
private int endLodIndex = -1;
|
||||
|
||||
|
||||
|
||||
public BuildBufferThread()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public BuildBufferThread(BufferBuilder newNearBufferBuilder,
|
||||
BufferBuilder newFarBufferBuilder, AxisAlignedBB[][] newLods,
|
||||
Color[][] newColors, FogDistance newDistanceMode, int newStartingIndex,
|
||||
int numberOfRowsToGenerate)
|
||||
{
|
||||
setNewData(newNearBufferBuilder, newFarBufferBuilder, distanceMode,
|
||||
newLods, newColors, newStartingIndex, numberOfRowsToGenerate);
|
||||
}
|
||||
|
||||
public void setNewData(BufferBuilder newNearBufferBuilder,
|
||||
BufferBuilder newFarBufferBuilder, FogDistance newDistanceMode,
|
||||
AxisAlignedBB[][] newLods, Color[][] newColors,
|
||||
int newStartingIndex, int numberOfRowsToGenerate)
|
||||
{
|
||||
nearBuffer = newNearBufferBuilder;
|
||||
farBuffer = newFarBufferBuilder;
|
||||
distanceMode = newDistanceMode;
|
||||
lods = newLods;
|
||||
colors = newColors;
|
||||
|
||||
startLodIndex = newStartingIndex;
|
||||
endLodIndex = newStartingIndex + numberOfRowsToGenerate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NearFarBuffer call()
|
||||
{
|
||||
nearBuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
|
||||
farBuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
|
||||
|
||||
int numbChunksWide = lods.length;
|
||||
|
||||
BufferBuilder currentBuffer;
|
||||
AxisAlignedBB bb;
|
||||
int red;
|
||||
int green;
|
||||
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;
|
||||
}
|
||||
else // if (distanceMode == FogDistance.FAR)
|
||||
{
|
||||
currentBuffer = farBuffer;
|
||||
}
|
||||
|
||||
|
||||
// x axis
|
||||
for (int i = startLodIndex; i < endLodIndex; i++)
|
||||
{
|
||||
// z axis
|
||||
for (int j = 0; j < numbChunksWide; j++)
|
||||
{
|
||||
if (lods[i][j] == null || colors[i][j] == null)
|
||||
continue;
|
||||
|
||||
bb = lods[i][j];
|
||||
|
||||
// get the color of this LOD object
|
||||
red = colors[i][j].getRed();
|
||||
green = colors[i][j].getGreen();
|
||||
blue = colors[i][j].getBlue();
|
||||
alpha = colors[i][j].getAlpha();
|
||||
|
||||
|
||||
if (distanceMode == FogDistance.NEAR_AND_FAR)
|
||||
{
|
||||
if (isCoordinateInNearFogArea(i, j, numbChunksWide / 2))
|
||||
currentBuffer = nearBuffer;
|
||||
else
|
||||
currentBuffer = farBuffer;
|
||||
}
|
||||
|
||||
|
||||
if (bb.minY != bb.maxY)
|
||||
{
|
||||
// top (facing up)
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
// bottom (facing down)
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
|
||||
// south (facing -Z)
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
// north (facing +Z)
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
|
||||
// west (facing -X)
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
// east (facing +X)
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
// render this LOD as one block thick
|
||||
|
||||
// top (facing up)
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY+1, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY+1, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY+1, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY+1, bb.minZ, red, green, blue, alpha);
|
||||
// bottom (facing down)
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
|
||||
// south (facing -Z)
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY+1, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY+1, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
// north (facing +Z)
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY+1, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY+1, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
|
||||
// west (facing -X)
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY+1, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY+1, bb.minZ, red, green, blue, alpha);
|
||||
// east (facing +X)
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY+1, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY+1, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
}
|
||||
|
||||
} // z axis
|
||||
} // x axis
|
||||
|
||||
nearBuffer.finishDrawing();
|
||||
farBuffer.finishDrawing();
|
||||
|
||||
return new NearFarBuffer(nearBuffer, farBuffer);
|
||||
}
|
||||
|
||||
private void addPosAndColor(BufferBuilder buffer, double x, double y, double z, int red, int green, int blue, int alpha)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.backsun.lod.builders;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.backsun.lod.handlers.LodDimensionFileHandler;
|
||||
import com.backsun.lod.objects.LodChunk;
|
||||
import com.backsun.lod.objects.LodDimension;
|
||||
import com.backsun.lod.objects.LodWorld;
|
||||
import com.backsun.lod.util.LodUtils;
|
||||
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.ChunkSection;
|
||||
|
||||
/**
|
||||
* This object is in charge of creating Lod
|
||||
* related objects.
|
||||
* (specifically: Lod World, Dimension, Region, and Chunk objects)
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2-22-2021
|
||||
*/
|
||||
public class LodBuilder
|
||||
{
|
||||
private ExecutorService lodGenThreadPool = Executors.newSingleThreadExecutor();
|
||||
public volatile LodWorld lodWorld;
|
||||
|
||||
/** Default size of any LOD regions we use */
|
||||
public int regionWidth = 5;
|
||||
|
||||
public LodBuilder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns LodWorld so that it can be passed
|
||||
* to the LodRenderer.
|
||||
*/
|
||||
public LodWorld generateLodChunkAsync(Chunk chunk)
|
||||
{
|
||||
// don't try to create an LOD object
|
||||
// if for some reason we aren't
|
||||
// given a valid chunk object
|
||||
// (Minecraft often gives back empty
|
||||
// or null chunks in this method)
|
||||
if (chunk == null || !isValidChunk(chunk))
|
||||
return lodWorld;
|
||||
|
||||
|
||||
DimensionType dim = chunk.getWorld().getDimensionType();
|
||||
World world = LodUtils.getServerWorldFromDimension(dim);
|
||||
|
||||
|
||||
if (world == null)
|
||||
return lodWorld;
|
||||
|
||||
Thread thread = new Thread(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
LodChunk lod = new LodChunk(chunk, world);
|
||||
LodDimension lodDim;
|
||||
|
||||
if (lodWorld == null)
|
||||
{
|
||||
lodWorld = new LodWorld(LodDimensionFileHandler.getWorldName());
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we have a lodWorld make sure
|
||||
// it is for this minecraft world
|
||||
if (!lodWorld.worldName.equals(LodDimensionFileHandler.getWorldName()))
|
||||
{
|
||||
// this lodWorld isn't for this minecraft world
|
||||
// delete it so we can get a new one
|
||||
lodWorld = null;
|
||||
|
||||
// skip this frame
|
||||
// we'll get this set up next time
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (lodWorld.getLodDimension(dim) == null)
|
||||
{
|
||||
lodDim = new LodDimension(dim, regionWidth);
|
||||
lodWorld.addLodDimension(lodDim);
|
||||
}
|
||||
else
|
||||
{
|
||||
lodDim = lodWorld.getLodDimension(dim);
|
||||
}
|
||||
|
||||
lodDim.addLod(lod);
|
||||
}
|
||||
catch(IllegalArgumentException | NullPointerException e)
|
||||
{
|
||||
// if the world changes while LODs are being generated
|
||||
// they will throw errors as they try to access things that no longer
|
||||
// exist.
|
||||
}
|
||||
});
|
||||
lodGenThreadPool.execute(thread);
|
||||
|
||||
return lodWorld;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given chunk
|
||||
* has any data in it.
|
||||
*/
|
||||
public boolean isValidChunk(Chunk chunk)
|
||||
{
|
||||
ChunkSection[] blockStorage = chunk.getSections();
|
||||
|
||||
for(ChunkSection section : blockStorage)
|
||||
{
|
||||
if(section != null && !section.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+103
-39
@@ -1,4 +1,4 @@
|
||||
package com.backsun.lod.util;
|
||||
package com.backsun.lod.handlers;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
@@ -11,8 +11,10 @@ import java.util.concurrent.Executors;
|
||||
import com.backsun.lod.objects.LodChunk;
|
||||
import com.backsun.lod.objects.LodDimension;
|
||||
import com.backsun.lod.objects.LodRegion;
|
||||
import com.backsun.lod.util.LodUtils;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
/**
|
||||
* This object handles creating LodRegions
|
||||
@@ -22,26 +24,29 @@ import net.minecraft.client.Minecraft;
|
||||
* @author James Seibel
|
||||
* @version 01-30-2021
|
||||
*/
|
||||
public class LodFileHandler
|
||||
public class LodDimensionFileHandler
|
||||
{
|
||||
// TODO this object needs to be changed to use NBT data instead of writing to files
|
||||
private static final boolean IMPLEMENTED = false;
|
||||
|
||||
private Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
private LodDimension loadedRegion = null;
|
||||
private LodDimension loadedDimension = null;
|
||||
public long regionLastWriteTime[][];
|
||||
|
||||
private ExecutorService fileWritingThreadPool = Executors.newSingleThreadExecutor();
|
||||
private File saveFolder;
|
||||
private String saveDir;
|
||||
|
||||
private final String FILE_NAME_PREFIX = "lod";
|
||||
private final String FILE_EXTENSION = ".txt";
|
||||
|
||||
private ExecutorService fileWritingThreadPool = Executors.newFixedThreadPool(1);
|
||||
|
||||
|
||||
public LodFileHandler(LodDimension newLoadedRegion)
|
||||
public LodDimensionFileHandler(File newSaveFolder, LodDimension newLoadedDimension)
|
||||
{
|
||||
loadedRegion = newLoadedRegion;
|
||||
saveFolder = newSaveFolder;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -61,15 +66,15 @@ public class LodFileHandler
|
||||
*/
|
||||
public LodRegion loadRegionFromFile(int regionX, int regionZ)
|
||||
{
|
||||
if (!IMPLEMENTED)
|
||||
return null;
|
||||
|
||||
// we don't currently support reading or writing
|
||||
// files when connected to a server
|
||||
if (!mc.isIntegratedServerRunning())
|
||||
if (!Minecraft.getInstance().isIntegratedServerRunning())
|
||||
return null;
|
||||
|
||||
String fileName = "";
|
||||
if (!readyToReadAndWrite())
|
||||
return null;
|
||||
|
||||
String fileName = getFileNameForRegion(regionX, regionZ);
|
||||
|
||||
File f = new File(fileName);
|
||||
|
||||
@@ -131,47 +136,53 @@ public class LodFileHandler
|
||||
// Save to File //
|
||||
//==============//
|
||||
|
||||
|
||||
public synchronized void saveDirtyRegionsToFile()
|
||||
/**
|
||||
* Save all dirty regions in this LodDimension to file.
|
||||
*/
|
||||
public synchronized void saveDirtyRegionsToFileAsync()
|
||||
{
|
||||
if (!IMPLEMENTED)
|
||||
return;
|
||||
|
||||
// we don't currently support reading or writing
|
||||
// files when connected to a server
|
||||
if (!mc.isIntegratedServerRunning())
|
||||
if (!Minecraft.getInstance().isIntegratedServerRunning())
|
||||
return;
|
||||
|
||||
if (!readyToReadAndWrite())
|
||||
// we aren't ready to read and write yet
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Save a specific region to disk.<br>
|
||||
* Note: it will save to the LodDimension that this
|
||||
* handler is associated with.
|
||||
*/
|
||||
private void saveRegionToDisk(LodRegion region)
|
||||
{
|
||||
if (!IMPLEMENTED)
|
||||
if (!readyToReadAndWrite() || region == null)
|
||||
return;
|
||||
|
||||
if (region == null)
|
||||
return;
|
||||
// convert chunk coordinates to region
|
||||
// coordinates
|
||||
int x = region.x;
|
||||
int z = region.z;
|
||||
|
||||
// int x = region.x;
|
||||
// int z = region.z;
|
||||
|
||||
File f = new File("");
|
||||
File f = new File(getFileNameForRegion(x, z));
|
||||
|
||||
try
|
||||
{
|
||||
@@ -207,6 +218,33 @@ public class LodFileHandler
|
||||
//================//
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the file that should contain the
|
||||
* region at the given x and z. <br>
|
||||
* Returns null if this object isn't ready to read and write.
|
||||
*/
|
||||
private String getFileNameForRegion(int regionX, int regionZ)
|
||||
{
|
||||
if (!readyToReadAndWrite())
|
||||
return null;
|
||||
|
||||
return saveDir + "\\lod_data\\DIM" + loadedDimension.dimension.toString() + "\\" +
|
||||
FILE_NAME_PREFIX + "." + regionX + "." + regionZ + FILE_EXTENSION;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns if this FileHandler is ready to read
|
||||
* and write files.
|
||||
* <br>
|
||||
* This returns true when the world save directory is known.
|
||||
*/
|
||||
public boolean readyToReadAndWrite()
|
||||
{
|
||||
return saveFolder != null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -220,7 +258,11 @@ public class LodFileHandler
|
||||
|
||||
if(mc.isIntegratedServerRunning())
|
||||
{
|
||||
return mc.getIntegratedServer().getName();
|
||||
ServerWorld world = LodUtils.getFirstValidServerWorld();
|
||||
if(world != null)
|
||||
return world.getServer().getDataDirectory().toString();
|
||||
|
||||
return "";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -229,4 +271,26 @@ public class LodFileHandler
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the canonical path to the world save folder.
|
||||
* <br>
|
||||
* Returns null if there was an IO Exception
|
||||
*/
|
||||
private String getWorldSaveDirectory()
|
||||
{
|
||||
ServerWorld world = LodUtils.getFirstValidServerWorld();
|
||||
|
||||
try
|
||||
{
|
||||
if(world != null)
|
||||
return world.getServer().getDataDirectory().getCanonicalPath();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.backsun.lod.handlers;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import com.backsun.lod.util.enums.FogQuality;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
/**
|
||||
* This object is used to get variables from methods
|
||||
* where they are private. Specifically the fog setting
|
||||
* in Optifine.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 09-21-2020
|
||||
*/
|
||||
public class ReflectionHandler
|
||||
{
|
||||
private Minecraft mc = Minecraft.getInstance();
|
||||
public Field ofFogField = null;
|
||||
|
||||
|
||||
public ReflectionHandler()
|
||||
{
|
||||
setupFogField();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Similar to setupFovMethod.
|
||||
*/
|
||||
private void setupFogField()
|
||||
{
|
||||
// get every variable from the entity renderer
|
||||
Field[] vars = mc.gameSettings.getClass().getDeclaredFields();
|
||||
|
||||
// try and find the ofFogType variable in gameSettings
|
||||
for(Field f : vars)
|
||||
{
|
||||
if(f.getName().equals("ofFogType"))
|
||||
{
|
||||
ofFogField = f;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// we didn't find the field,
|
||||
// either optifine isn't installed, or
|
||||
// optifine changed the name of the variable
|
||||
ofFogField = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get what type of fog optifine is currently set to render.
|
||||
*/
|
||||
public FogQuality getFogQuality()
|
||||
{
|
||||
if (ofFogField == null)
|
||||
{
|
||||
// either optifine isn't installed,
|
||||
// the variable name was changed, or
|
||||
// the setup method wasn't called yet.
|
||||
return FogQuality.FANCY;
|
||||
}
|
||||
|
||||
int returnNum = 0;
|
||||
|
||||
try
|
||||
{
|
||||
returnNum = (int)ofFogField.get(mc.gameSettings);
|
||||
}
|
||||
catch (IllegalArgumentException | IllegalAccessException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
switch (returnNum)
|
||||
{
|
||||
case 0:
|
||||
return FogQuality.FAST;
|
||||
case 1:
|
||||
return FogQuality.FAST;
|
||||
case 2:
|
||||
return FogQuality.FANCY;
|
||||
case 3:
|
||||
return FogQuality.OFF;
|
||||
|
||||
default:
|
||||
return FogQuality.FAST;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.backsun.lod.objects;
|
||||
import java.awt.Color;
|
||||
|
||||
import com.backsun.lod.util.enums.ColorDirection;
|
||||
import com.backsun.lod.util.enums.LodCorner;
|
||||
import com.backsun.lod.util.enums.LodLocation;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
@@ -71,7 +72,7 @@ public class LodChunk
|
||||
//==============//
|
||||
|
||||
/**
|
||||
* Create an empty LodChunk
|
||||
* Create an empty invisible LodChunk at (0,0)
|
||||
*/
|
||||
public LodChunk()
|
||||
{
|
||||
@@ -200,11 +201,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. <br>
|
||||
* 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
|
||||
{
|
||||
@@ -251,6 +252,8 @@ public class LodChunk
|
||||
|
||||
|
||||
/**
|
||||
* Generate the height for the given LodLocation, either the top or bottom.
|
||||
* <br><br>
|
||||
* If invalid/null/empty chunks are given
|
||||
* crashes may occur.
|
||||
*/
|
||||
@@ -316,7 +319,16 @@ public class LodChunk
|
||||
else
|
||||
return determineBottomPoint(chunkSections, startX, endX, startZ, endZ);
|
||||
}
|
||||
/** GENERATE_TOP, GENERATE_BOTTOM */
|
||||
private enum SectionGenerationMode
|
||||
{
|
||||
GENERATE_TOP,
|
||||
GENERATE_BOTTOM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the lowest valid point from the bottom.
|
||||
*/
|
||||
private short determineBottomPoint(ChunkSection[] chunkSections, int startX, int endX, int startZ, int endZ)
|
||||
{
|
||||
// search from the bottom up
|
||||
@@ -333,15 +345,16 @@ public class LodChunk
|
||||
// LOD point
|
||||
return (short) (y + (i * CHUNK_DATA_HEIGHT));
|
||||
}
|
||||
|
||||
} // y
|
||||
} // data
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// we never found a valid LOD point
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the highest valid point from the Top
|
||||
*/
|
||||
private short determineTopPoint(ChunkSection[] chunkSections, int startX, int endX, int startZ, int endZ)
|
||||
{
|
||||
// search from the top down
|
||||
@@ -357,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;
|
||||
@@ -410,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 generateLodColorSection(Chunk chunk, World world, ColorDirection colorDir)
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
BlockColors bc = mc.getBlockColors();
|
||||
@@ -439,10 +452,17 @@ 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)
|
||||
{
|
||||
if(colorDir != ColorDirection.TOP && colorDir != ColorDirection.BOTTOM)
|
||||
{
|
||||
throw new IllegalArgumentException("generateLodColorVertical only accepts the ColorDirection TOP or BOTTOM");
|
||||
}
|
||||
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
|
||||
int numbOfBlocks = 0;
|
||||
@@ -517,9 +537,19 @@ 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)
|
||||
{
|
||||
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)");
|
||||
}
|
||||
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
|
||||
int numbOfBlocks = 0;
|
||||
@@ -669,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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -725,28 +779,7 @@ 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() + "), ";
|
||||
s += "(" + colors[ColorDirection.TOP.value].getRed() + ", " + colors[ColorDirection.TOP.value].getGreen() + ", " + colors[ColorDirection.TOP.value].getBlue() + ")";
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
package com.backsun.lod.objects;
|
||||
|
||||
import com.backsun.lod.util.LodFileHandler;
|
||||
import com.backsun.lod.handlers.LodDimensionFileHandler;
|
||||
import com.backsun.lod.util.LodUtils;
|
||||
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
|
||||
/**
|
||||
* This object holds all loaded LOD regions
|
||||
* 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[][];
|
||||
@@ -24,15 +26,16 @@ public class LodDimension
|
||||
private int centerX;
|
||||
private int centerZ;
|
||||
|
||||
private LodFileHandler rfHandler;
|
||||
private LodDimensionFileHandler fileHandler;
|
||||
|
||||
|
||||
public LodDimension(DimensionType newDimension, int newMaxWidth)
|
||||
{
|
||||
dimension = newDimension;
|
||||
width = newMaxWidth;
|
||||
|
||||
// dimension 0 works here since we are just looking for the save handler anyway
|
||||
rfHandler = new LodFileHandler(this);
|
||||
ServerChunkProvider provider = LodUtils.getServerWorldFromDimension(newDimension).getChunkProvider();
|
||||
fileHandler = new LodDimensionFileHandler(provider.getSavedData().folder, this);
|
||||
|
||||
regions = new LodRegion[width][width];
|
||||
isRegionDirty = new boolean[width][width];
|
||||
@@ -49,7 +52,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
|
||||
@@ -143,22 +149,16 @@ public class LodDimension
|
||||
}
|
||||
|
||||
|
||||
public int getCenterX()
|
||||
{
|
||||
return centerX;
|
||||
}
|
||||
|
||||
public int getCenterZ()
|
||||
{
|
||||
return centerZ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the region at the given X and Z
|
||||
* <br>
|
||||
* 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;
|
||||
@@ -200,11 +200,15 @@ 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;
|
||||
int regionZ = (lod.z + centerZ) / LodRegion.SIZE;
|
||||
int regionX = lod.x / LodRegion.SIZE;
|
||||
int regionZ = lod.z / LodRegion.SIZE;
|
||||
|
||||
// prevent issues if X/Z is negative and less than 16
|
||||
if (lod.x < 0)
|
||||
@@ -235,20 +239,20 @@ 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.
|
||||
* <br>
|
||||
* Returns null if the LodChunk doesn't exist or
|
||||
* is outside the loaded area.
|
||||
*/
|
||||
public LodChunk getLodFromCoordinates(int chunkX, int chunkZ)
|
||||
{
|
||||
// (chunkX + centerX) % width
|
||||
int regionX = (chunkX + centerX) / LodRegion.SIZE;
|
||||
int regionZ = (chunkZ + centerZ) / LodRegion.SIZE;
|
||||
int regionX = chunkX / LodRegion.SIZE;
|
||||
int regionZ = chunkZ / LodRegion.SIZE;
|
||||
|
||||
// prevent issues if chunkX/Z is negative and less than width
|
||||
if (chunkX < 0)
|
||||
@@ -262,7 +266,6 @@ public class LodDimension
|
||||
|
||||
LodRegion region = getRegion(regionX, regionZ);
|
||||
|
||||
// TODO fix small render distances sometimes not having all regions loaded
|
||||
if(region == null)
|
||||
return null;
|
||||
|
||||
@@ -270,11 +273,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -292,6 +297,22 @@ public class LodDimension
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public int getCenterX()
|
||||
{
|
||||
return centerX;
|
||||
}
|
||||
|
||||
public int getCenterZ()
|
||||
{
|
||||
return centerZ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return width;
|
||||
@@ -310,6 +331,18 @@ public class LodDimension
|
||||
for(int j = 0; j < width; j++)
|
||||
isRegionDirty[i][j] = false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String s = "";
|
||||
|
||||
s += "dim: " + dimension.toString() + "\t";
|
||||
s += "(" + centerX + "," + centerZ + ")";
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
* <br>
|
||||
* 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
|
||||
@@ -56,7 +68,9 @@ public class LodRegion
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns all LodChunks in this region
|
||||
*/
|
||||
public LodChunk[][] getAllLods()
|
||||
{
|
||||
return chunks;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package com.backsun.lod.objects;
|
||||
|
||||
import java.util.Dictionary;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.world.DimensionType;
|
||||
|
||||
@@ -10,7 +9,7 @@ import net.minecraft.world.DimensionType;
|
||||
* This stores all LODs for a given world.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 01-31-2021
|
||||
* @version 02-22-2021
|
||||
*/
|
||||
public class LodWorld
|
||||
{
|
||||
@@ -19,13 +18,13 @@ public class LodWorld
|
||||
/**
|
||||
* Key = Dimension id (as an int)
|
||||
*/
|
||||
private Dictionary<DimensionType, LodDimension> lodDimensions;
|
||||
private Map<DimensionType, LodDimension> lodDimensions;
|
||||
|
||||
|
||||
public LodWorld(String newWorldName)
|
||||
{
|
||||
worldName = newWorldName;
|
||||
lodDimensions = new Hashtable<>();
|
||||
lodDimensions = new Hashtable<DimensionType, LodDimension>();
|
||||
}
|
||||
|
||||
|
||||
@@ -40,12 +39,27 @@ public class LodWorld
|
||||
return lodDimensions.get(dimension);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resizes the max width in regions that each LodDimension
|
||||
* should use.
|
||||
*/
|
||||
public void resizeDimensionRegionWidth(int newWidth)
|
||||
{
|
||||
Enumeration<DimensionType> keys = lodDimensions.keys();
|
||||
for(DimensionType 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(DimensionType key : lodDimensions.keySet())
|
||||
s += lodDimensions.get(key).dimension.toString() + ", ";
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.backsun.lod.objects;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
|
||||
/**
|
||||
* This object is just a replacement for an array
|
||||
* to make things easier to understand in the LodRenderer
|
||||
* and BuildBufferThread.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-21-2021
|
||||
*/
|
||||
public class NearFarBuffer
|
||||
{
|
||||
public BufferBuilder nearBuffer;
|
||||
|
||||
public BufferBuilder farBuffer;
|
||||
|
||||
|
||||
public NearFarBuffer(BufferBuilder newNearBuffer, BufferBuilder newFarBuffer)
|
||||
{
|
||||
nearBuffer = newNearBuffer;
|
||||
farBuffer = newFarBuffer;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
package com.backsun.lod.proxy;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.backsun.lod.builders.LodBuilder;
|
||||
import com.backsun.lod.objects.LodChunk;
|
||||
import com.backsun.lod.objects.LodDimension;
|
||||
import com.backsun.lod.objects.LodRegion;
|
||||
@@ -12,39 +10,33 @@ import com.backsun.lod.objects.LodWorld;
|
||||
import com.backsun.lod.renderer.LodRenderer;
|
||||
import com.backsun.lod.renderer.RenderGlobalHook;
|
||||
import com.backsun.lod.util.LodConfig;
|
||||
import com.backsun.lod.util.LodFileHandler;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.ChunkSection;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
//TODO Find a way to replace getIntegratedServer so this mod could be used on non-local worlds.
|
||||
// Minecraft.getInstance().getIntegratedServer()
|
||||
// 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 01-31-2021
|
||||
* @version 02-23-2021
|
||||
*/
|
||||
public class ClientProxy
|
||||
{
|
||||
private LodRenderer renderer;
|
||||
private LodWorld lodWorld;
|
||||
private ExecutorService lodGenThreadPool = Executors.newFixedThreadPool(1);
|
||||
private LodBuilder lodBuilder;
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
/** Default size of any LOD regions we use */
|
||||
private int regionWidth = 5;
|
||||
|
||||
public ClientProxy()
|
||||
{
|
||||
|
||||
lodBuilder = new LodBuilder();
|
||||
}
|
||||
|
||||
|
||||
@@ -66,13 +58,17 @@ public class ClientProxy
|
||||
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, (mc.gameSettings.renderDistanceChunks * LodChunk.WIDTH * 2) / LodRegion.SIZE);
|
||||
if (lodWorld != null && regionWidth != newWidth)
|
||||
if (lodWorld != null && lodBuilder.regionWidth != newWidth)
|
||||
{
|
||||
lodWorld.resizeDimensionRegionWidth(newWidth);
|
||||
regionWidth = newWidth;
|
||||
lodBuilder.regionWidth = newWidth;
|
||||
|
||||
// skip this frame, hopefully the lodWorld
|
||||
// should have everything set up by then
|
||||
@@ -86,8 +82,6 @@ public class ClientProxy
|
||||
if (lodDim == null)
|
||||
return;
|
||||
|
||||
mc.getProfiler().endSection();
|
||||
mc.getProfiler().startSection("LOD");
|
||||
|
||||
double playerX = mc.player.getPosX();
|
||||
double playerZ = mc.player.getPosZ();
|
||||
@@ -100,7 +94,6 @@ public class ClientProxy
|
||||
lodDim.move(xOffset, zOffset);
|
||||
}
|
||||
|
||||
|
||||
// we wait to create the renderer until the first frame
|
||||
// to make sure that the EntityRenderer has
|
||||
// been created, that way we can get the fovModifer
|
||||
@@ -113,118 +106,41 @@ public class ClientProxy
|
||||
{
|
||||
renderer.drawLODs(lodDim, partialTicks, mc.getProfiler());
|
||||
}
|
||||
|
||||
// end of profiler tracking
|
||||
mc.getProfiler().endSection();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// update events //
|
||||
//===============//
|
||||
|
||||
@SubscribeEvent
|
||||
public void chunkLoadEvent(ChunkEvent.Load event)
|
||||
public void chunkLoadEvent(ChunkEvent event)
|
||||
{
|
||||
if (mc != null && event != null)
|
||||
{
|
||||
World world = mc.world;
|
||||
|
||||
if(world != null)
|
||||
{
|
||||
generateLodChunk((Chunk)event.getChunk());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateLodChunk(Chunk chunk)
|
||||
{
|
||||
// don't try to create an LOD object
|
||||
// if for some reason we aren't
|
||||
// given a valid chunk object
|
||||
// (Minecraft often gives back empty
|
||||
// or null chunks in this method)
|
||||
if (chunk == null || chunk.getWorld() == null || !isValidChunk(chunk))
|
||||
return;
|
||||
|
||||
Thread thread = new Thread(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
DimensionType dim = chunk.getWorldForge().getDimensionType();
|
||||
World world = chunk.getWorld();
|
||||
LodChunk lod = new LodChunk(chunk, world);
|
||||
LodDimension lodDim;
|
||||
|
||||
if (lodWorld == null)
|
||||
{
|
||||
lodWorld = new LodWorld(LodFileHandler.getWorldName());
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we have a lodWorld make sure
|
||||
// it is for this minecraft world
|
||||
if (!lodWorld.worldName.equals(LodFileHandler.getWorldName()))
|
||||
{
|
||||
// this lodWorld isn't for this minecraft world
|
||||
// delete it so we can get a new one
|
||||
lodWorld = null;
|
||||
|
||||
// skip this frame
|
||||
// we'll get this set up next time
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (lodWorld.getLodDimension(dim) == null)
|
||||
{
|
||||
lodDim = new LodDimension(dim, regionWidth);
|
||||
lodWorld.addLodDimension(lodDim);
|
||||
}
|
||||
else
|
||||
{
|
||||
lodDim = lodWorld.getLodDimension(dim);
|
||||
}
|
||||
|
||||
lodDim.addLod(lod);
|
||||
}
|
||||
catch(IllegalArgumentException | NullPointerException e)
|
||||
{
|
||||
// if the world changes while LODs are being generated
|
||||
// they will throw errors as they try to access things that no longer
|
||||
// exist.
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
lodGenThreadPool.execute(thread);
|
||||
lodWorld = lodBuilder.generateLodChunkAsync((Chunk) event.getChunk());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given chunk
|
||||
* has any data in it.
|
||||
* this event is called whenever a chunk is created for the first time.
|
||||
*/
|
||||
private boolean isValidChunk(Chunk chunk)
|
||||
{
|
||||
ChunkSection[] sections = chunk.getSections();
|
||||
|
||||
for(ChunkSection section : sections)
|
||||
{
|
||||
if(section != null && !section.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// @SubscribeEvent
|
||||
// public void onChunkPopulate(PopulateChunkEvent event)
|
||||
// {
|
||||
// Minecraft mc = Minecraft.getMinecraft();
|
||||
// if (mc != null && event != null)
|
||||
// {
|
||||
// WorldClient world = mc.world;
|
||||
//
|
||||
// if(world != null)
|
||||
// {
|
||||
// lodWorld = lodBuilder.generateLodChunkAsync(world.getChunkFromChunkCoords(event.getChunkX(), event.getChunkZ()));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.backsun.lod.proxy;
|
||||
|
||||
/**
|
||||
* This handles any events sent to the server.
|
||||
*
|
||||
* @author James_Seibel
|
||||
* @version 08-31-2020
|
||||
*/
|
||||
public class CommonProxy
|
||||
{
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
||||
package com.backsun.lod.util;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
/**
|
||||
* This class holds methods that may be used in multiple places.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-26-2021
|
||||
*/
|
||||
public class LodUtils
|
||||
{
|
||||
private static Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the first valid ServerWorld.
|
||||
*
|
||||
* @return null if there are no ServerWorlds
|
||||
*/
|
||||
public static ServerWorld getFirstValidServerWorld()
|
||||
{
|
||||
Iterable<ServerWorld> worlds = mc.getIntegratedServer().getWorlds();
|
||||
|
||||
for (ServerWorld world : worlds)
|
||||
return world;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ServerWorld for the relevant dimension.
|
||||
*
|
||||
* @return null if there is no ServerWorld for the given dimension
|
||||
*/
|
||||
public static ServerWorld getServerWorldFromDimension(DimensionType dimension)
|
||||
{
|
||||
Iterable<ServerWorld> worlds = mc.getIntegratedServer().getWorlds();
|
||||
ServerWorld returnWorld = null;
|
||||
|
||||
for (ServerWorld world : worlds)
|
||||
{
|
||||
if(world.getDimensionType() == dimension)
|
||||
{
|
||||
returnWorld = world;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return returnWorld;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.backsun.lod.util;
|
||||
|
||||
/**
|
||||
* This holds meta information about the mod.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 04-16-2020
|
||||
@@ -14,7 +15,7 @@ public class Reference
|
||||
/** the mod's version */
|
||||
public static final String VERSION = "1.0";
|
||||
/** the version of minecraft this mod is built for */
|
||||
public static final String ACCEPTED_VERSIONS = "[1.12.2]";
|
||||
public static final String ACCEPTED_VERSIONS = "[1.16.4]";
|
||||
|
||||
/** where the client proxy class is */
|
||||
public static final String CLIENT_PROXY_CLASS = "com.backsun.lod.proxy.ClientProxy";
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.backsun.lod.util.enums;
|
||||
|
||||
/**
|
||||
* NE, SE, SW, NW
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 1-20-2020
|
||||
*/
|
||||
public enum LodCorner
|
||||
{
|
||||
// used for position
|
||||
|
||||
/** -Z, +X */
|
||||
NE(0),
|
||||
/** +Z, +X */
|
||||
SE(1),
|
||||
/** +Z, -X */
|
||||
SW(2),
|
||||
/** -Z, -X */
|
||||
NW(3);
|
||||
|
||||
public final int value;
|
||||
|
||||
private LodCorner(int newValue)
|
||||
{
|
||||
value = newValue;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user