change the packages from com.backsun.lod... to com.seibel.lod...
This commit is contained in:
@@ -0,0 +1,313 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import com.seibel.lod.enums.ColorDirection;
|
||||
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
/**
|
||||
* This object contains position
|
||||
* and color data for an LOD object.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 05-29-2021
|
||||
*/
|
||||
public class LodChunk
|
||||
{
|
||||
/** how many different pieces of data are in one line */
|
||||
private static final int DATA_DELIMITER_COUNT = 22;
|
||||
|
||||
/** This is what separates each piece of data in the toData method */
|
||||
public static final char DATA_DELIMITER = ',';
|
||||
|
||||
/** Width of a Minecraft Chunk */
|
||||
public static final int WIDTH = 16;
|
||||
|
||||
private static final Color INVISIBLE = new Color(0,0,0,0);
|
||||
|
||||
|
||||
|
||||
/** The x coordinate of the chunk. */
|
||||
public int x = 0;
|
||||
/** The z coordinate of the chunk. */
|
||||
public int z = 0;
|
||||
|
||||
/*
|
||||
* The reason we are only using 1 height and depth point
|
||||
* instead of multiple is because:
|
||||
* 1. more points would drastically increase the amount of
|
||||
* memory and disk space needed
|
||||
* 2. more height/depth points require more color points,
|
||||
* which can get out of hand quickly
|
||||
* 3. with the increased disk space reading/writing would
|
||||
* take far too long
|
||||
* 4. the increased resolution is generally not worth it,
|
||||
* 4 LODs per chunk is the limit of diminishing returns.
|
||||
* And some of that could potentially be faked through
|
||||
* smart LodTemplates
|
||||
*/
|
||||
private short height;
|
||||
private short depth;
|
||||
|
||||
/** The average color for the 6 cardinal directions */
|
||||
public Color colors[];
|
||||
|
||||
/** If true then this LodChunk contains no data */
|
||||
private boolean empty = false;
|
||||
|
||||
|
||||
/**
|
||||
* Create an empty invisible LodChunk at (0,0)
|
||||
*/
|
||||
public LodChunk()
|
||||
{
|
||||
empty = true;
|
||||
|
||||
x = 0;
|
||||
z = 0;
|
||||
|
||||
height = 0;
|
||||
depth = 0;
|
||||
colors = new Color[ColorDirection.values().length];
|
||||
|
||||
// by default have the colors invisible
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
colors[dir.value] = INVISIBLE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an LodChunk from the string
|
||||
* generated by the toData method.
|
||||
*
|
||||
* @throws IllegalArgumentException if the data isn't valid to create a LodChunk
|
||||
* @throws NumberFormatException if any piece of data can't be converted at any point
|
||||
*/
|
||||
public LodChunk(String data) throws IllegalArgumentException, NumberFormatException
|
||||
{
|
||||
/*
|
||||
* data format:
|
||||
* x, z, height, depth, rgb color data
|
||||
*
|
||||
* example:
|
||||
* 5,8, 4, 0, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
|
||||
*/
|
||||
|
||||
// make sure there are the correct number of entries
|
||||
// in the data string (28)
|
||||
int count = 0;
|
||||
|
||||
for(int i = 0; i < data.length(); i++)
|
||||
if(data.charAt(i) == DATA_DELIMITER)
|
||||
count++;
|
||||
|
||||
if(count != DATA_DELIMITER_COUNT)
|
||||
throw new IllegalArgumentException("LodChunk constructor givin an invalid string. The data given had " + count + " delimiters when it should have had " + DATA_DELIMITER_COUNT + ".");
|
||||
|
||||
|
||||
|
||||
// index we will use when going through the String
|
||||
int index = 0;
|
||||
int lastIndex = 0;
|
||||
|
||||
|
||||
|
||||
// x and z position
|
||||
index = data.indexOf(DATA_DELIMITER, 0);
|
||||
x = Integer.parseInt(data.substring(0,index));
|
||||
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex+1);
|
||||
z = Integer.parseInt(data.substring(lastIndex+1,index));
|
||||
|
||||
// height
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex+1);
|
||||
height = Short.parseShort(data.substring(lastIndex+1,index));
|
||||
|
||||
// depth
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex+1);
|
||||
depth = Short.parseShort(data.substring(lastIndex+1,index));
|
||||
|
||||
|
||||
|
||||
// color
|
||||
colors = new Color[6];
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
{
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
|
||||
// get r,g,b
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
|
||||
String raw = "";
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
raw = data.substring(lastIndex+1,index);
|
||||
red = Short.parseShort(raw);
|
||||
break;
|
||||
case 1:
|
||||
raw = data.substring(lastIndex+1,index);
|
||||
green = Short.parseShort(raw);
|
||||
break;
|
||||
case 2:
|
||||
raw = data.substring(lastIndex+1,index);
|
||||
blue = Short.parseShort(raw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
colors[dir.value] = new Color(red, green, blue);
|
||||
}
|
||||
|
||||
|
||||
// after going through all this
|
||||
// is this LOD empty?
|
||||
empty = determineIfEmtpy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a LodChunk from the given values.
|
||||
*/
|
||||
public LodChunk(ChunkPos pos, short newHeight, short newDepth, Color[] newColors)
|
||||
{
|
||||
x = pos.x;
|
||||
z = pos.z;
|
||||
|
||||
height = newHeight;
|
||||
depth = newDepth;
|
||||
colors = newColors;
|
||||
|
||||
empty = determineIfEmtpy();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// misc functions //
|
||||
//================//
|
||||
|
||||
/**
|
||||
* Returns true if this LodChunk is an emptyPlaceholder
|
||||
*/
|
||||
public boolean isPlaceholder()
|
||||
{
|
||||
return empty;
|
||||
}
|
||||
|
||||
public boolean isLodEmpty()
|
||||
{
|
||||
return empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this LOD is either invisible
|
||||
* from every direction or doesn't have a valid height.
|
||||
*/
|
||||
private boolean determineIfEmtpy()
|
||||
{
|
||||
// we don't check the depth since the
|
||||
// height should always be greater than or equal
|
||||
// to the depth
|
||||
if(height >= 0)
|
||||
{
|
||||
// the height is valid,
|
||||
// do we have at least 1 non-invisible color?
|
||||
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
if(!colors[dir.value].equals(INVISIBLE))
|
||||
// at least one direction has a non-invisible color
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the height is negative,
|
||||
// this LodChunk is empty
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// output //
|
||||
//========//
|
||||
|
||||
/** Returns the color for the given direction */
|
||||
public Color getColor(ColorDirection dir)
|
||||
{
|
||||
return colors[dir.value];
|
||||
}
|
||||
|
||||
public short getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
public short getDepth()
|
||||
{
|
||||
return depth;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Outputs all data in csv format
|
||||
* with the given delimiter.
|
||||
* <br>
|
||||
* Exports data in the form:
|
||||
* <br>
|
||||
* x, z, height, depth, rgb color data
|
||||
*
|
||||
* <br>
|
||||
* example output:
|
||||
* <br>
|
||||
* 5,8, 4, 0, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
|
||||
*/
|
||||
public String toData()
|
||||
{
|
||||
String s = "";
|
||||
|
||||
s += Integer.toString(x) + DATA_DELIMITER + Integer.toString(z) + DATA_DELIMITER;
|
||||
|
||||
s += Short.toString(height) + DATA_DELIMITER;
|
||||
|
||||
s += Short.toString(depth) + DATA_DELIMITER;
|
||||
|
||||
for(int i = 0; i < colors.length; i++)
|
||||
{
|
||||
s += Integer.toString(colors[i].getRed()) + DATA_DELIMITER + Integer.toString(colors[i].getGreen()) + DATA_DELIMITER + Integer.toString(colors[i].getBlue()) + DATA_DELIMITER;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String s = "";
|
||||
|
||||
s += "x: " + x + " z: " + z + "\t";
|
||||
|
||||
s += "(" + colors[ColorDirection.TOP.value].getRed() + ", " + colors[ColorDirection.TOP.value].getGreen() + ", " + colors[ColorDirection.TOP.value].getBlue() + ")";
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,407 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.seibel.lod.handlers.LodDimensionFileHandler;
|
||||
import com.seibel.lod.util.LodUtils;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
/**
|
||||
* This object holds all loaded LOD regions
|
||||
* for a given dimension.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 03-19-2021
|
||||
*/
|
||||
public class LodDimension
|
||||
{
|
||||
public final DimensionType dimension;
|
||||
|
||||
private volatile int width;
|
||||
private volatile int halfWidth;
|
||||
|
||||
public LodRegion regions[][];
|
||||
public boolean isRegionDirty[][];
|
||||
|
||||
private int centerX;
|
||||
private int centerZ;
|
||||
|
||||
private LodDimensionFileHandler fileHandler;
|
||||
|
||||
|
||||
public LodDimension(DimensionType newDimension, LodWorld lodWorld, int newMaxWidth)
|
||||
{
|
||||
dimension = newDimension;
|
||||
width = newMaxWidth;
|
||||
|
||||
try
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
File saveDir;
|
||||
if(mc.isIntegratedServerRunning())
|
||||
{
|
||||
// local world
|
||||
|
||||
ServerWorld serverWorld = LodUtils.getServerWorldFromDimension(newDimension);
|
||||
// provider needs a separate variable to prevent
|
||||
// the compiler from complaining
|
||||
ServerChunkProvider provider = serverWorld.getChunkProvider();
|
||||
saveDir = new File(provider.getSavedData().folder.getCanonicalFile() + "\\lod");
|
||||
}
|
||||
else
|
||||
{
|
||||
// connected to server
|
||||
|
||||
saveDir = new File(mc.gameDir.getCanonicalFile() +
|
||||
"\\lod server data\\" + LodUtils.getDimensionIDFromWorld(mc.world));
|
||||
}
|
||||
|
||||
fileHandler = new LodDimensionFileHandler(saveDir, this);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
// the file handler wasn't able to be created
|
||||
// we won't be able to read or write any files
|
||||
}
|
||||
|
||||
|
||||
regions = new LodRegion[width][width];
|
||||
isRegionDirty = new boolean[width][width];
|
||||
|
||||
// populate isRegionDirty
|
||||
for(int i = 0; i < width; i++)
|
||||
for(int j = 0; j < width; j++)
|
||||
isRegionDirty[i][j] = false;
|
||||
|
||||
centerX = 0;
|
||||
centerZ = 0;
|
||||
|
||||
halfWidth = (int)Math.floor(width / 2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
// the total size, just delete the current data
|
||||
// and update the centerX and/or centerZ
|
||||
if (Math.abs(xOffset) >= width || Math.abs(zOffset) >= width)
|
||||
{
|
||||
for(int x = 0; x < width; x++)
|
||||
{
|
||||
for(int z = 0; z < width; z++)
|
||||
{
|
||||
regions[x][z] = null;
|
||||
}
|
||||
}
|
||||
|
||||
// update the new center
|
||||
centerX += xOffset;
|
||||
centerZ += zOffset;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// X
|
||||
if(xOffset > 0)
|
||||
{
|
||||
// move everything over to the left (as the center moves to the right)
|
||||
for(int x = 0; x < width; x++)
|
||||
{
|
||||
for(int z = 0; z < width; z++)
|
||||
{
|
||||
if(x + xOffset < width)
|
||||
regions[x][z] = regions[x + xOffset][z];
|
||||
else
|
||||
regions[x][z] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// move everything over to the right (as the center moves to the left)
|
||||
for(int x = width - 1; x >= 0; x--)
|
||||
{
|
||||
for(int z = 0; z < width; z++)
|
||||
{
|
||||
if(x + xOffset >= 0)
|
||||
regions[x][z] = regions[x + xOffset][z];
|
||||
else
|
||||
regions[x][z] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Z
|
||||
if(zOffset > 0)
|
||||
{
|
||||
// move everything up (as the center moves down)
|
||||
for(int x = 0; x < width; x++)
|
||||
{
|
||||
for(int z = 0; z < width; z++)
|
||||
{
|
||||
if(z + zOffset < width)
|
||||
regions[x][z] = regions[x][z + zOffset];
|
||||
else
|
||||
regions[x][z] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// move everything down (as the center moves up)
|
||||
for(int x = 0; x < width; x++)
|
||||
{
|
||||
for(int z = width - 1; z >= 0; z--)
|
||||
{
|
||||
if(z + zOffset >= 0)
|
||||
regions[x][z] = regions[x][z + zOffset];
|
||||
else
|
||||
regions[x][z] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// update the new center
|
||||
centerX += xOffset;
|
||||
centerZ += zOffset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
int zIndex = (regionZ - centerZ) + halfWidth;
|
||||
|
||||
if (!regionIsInRange(regionX, regionZ))
|
||||
// out of range
|
||||
return null;
|
||||
|
||||
if (regions[xIndex][zIndex] == null)
|
||||
{
|
||||
regions[xIndex][zIndex] = getRegionFromFile(regionX, regionZ);
|
||||
if (regions[xIndex][zIndex] == null)
|
||||
{
|
||||
regions[xIndex][zIndex] = new LodRegion(regionX, regionZ);
|
||||
}
|
||||
}
|
||||
|
||||
return regions[xIndex][zIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite the LodRegion at the location of newRegion with newRegion.
|
||||
* @throws ArrayIndexOutOfBoundsException if newRegion is outside what can be stored in this LodDimension.
|
||||
*/
|
||||
public void setRegion(LodRegion newRegion) throws ArrayIndexOutOfBoundsException
|
||||
{
|
||||
int xIndex = (newRegion.x - centerX) + halfWidth;
|
||||
int zIndex = (centerZ - newRegion.z) + halfWidth;
|
||||
|
||||
if (!regionIsInRange(newRegion.x, newRegion.z))
|
||||
// out of range
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
|
||||
regions[xIndex][zIndex] = newRegion;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
RegionPos pos = LodUtils.convertChunkPosToRegionPos(new ChunkPos(lod.x, lod.z));
|
||||
|
||||
// don't continue if the region can't be saved
|
||||
if (!regionIsInRange(pos.x, pos.z))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LodRegion region = getRegion(pos.x, pos.z);
|
||||
|
||||
if (region == null)
|
||||
{
|
||||
// if no region exists, create it
|
||||
region = new LodRegion(pos.x, pos.z);
|
||||
setRegion(region);
|
||||
}
|
||||
|
||||
region.addLod(lod);
|
||||
|
||||
// don't save empty place holders to disk
|
||||
if (!lod.isPlaceholder() && fileHandler != null)
|
||||
{
|
||||
// mark the region as dirty so it will be saved to disk
|
||||
int xIndex = (pos.x - centerX) + halfWidth;
|
||||
int zIndex = (pos.z - centerZ) + halfWidth;
|
||||
isRegionDirty[xIndex][zIndex] = true;
|
||||
fileHandler.saveDirtyRegionsToFileAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
RegionPos pos = LodUtils.convertChunkPosToRegionPos(new ChunkPos(chunkX, chunkZ));
|
||||
|
||||
LodRegion region = getRegion(pos.x, pos.z);
|
||||
|
||||
if(region == null)
|
||||
return null;
|
||||
|
||||
return region.getLod(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the region at the given X and Z coordinates from the
|
||||
* RegionFileHandler.
|
||||
*/
|
||||
public LodRegion getRegionFromFile(int regionX, int regionZ)
|
||||
{
|
||||
if (fileHandler != null)
|
||||
return fileHandler.loadRegionFromFile(regionX, regionZ);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the region at the given X and Z coordinates
|
||||
* is within the loaded range.
|
||||
*/
|
||||
public boolean regionIsInRange(int regionX, int regionZ)
|
||||
{
|
||||
int xIndex = (regionX - centerX) + halfWidth;
|
||||
int zIndex = (regionZ - centerZ) + halfWidth;
|
||||
|
||||
return xIndex >= 0 && xIndex < width && zIndex >= 0 && zIndex < width;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public int getCenterX()
|
||||
{
|
||||
return centerX;
|
||||
}
|
||||
|
||||
public int getCenterZ()
|
||||
{
|
||||
return centerZ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns how many non-null LodChunks
|
||||
* are stored in this LodDimension.
|
||||
*/
|
||||
public int getNumberOfLods()
|
||||
{
|
||||
int numbLods = 0;
|
||||
for (LodRegion[] regions : regions)
|
||||
{
|
||||
if(regions == null)
|
||||
continue;
|
||||
|
||||
for (LodRegion region : regions)
|
||||
{
|
||||
if(region == null)
|
||||
continue;
|
||||
|
||||
for(LodChunk[] lods : region.getAllLods())
|
||||
{
|
||||
if(lods == null)
|
||||
continue;
|
||||
|
||||
for(LodChunk lod : lods)
|
||||
{
|
||||
if (lod != null)
|
||||
numbLods++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return numbLods;
|
||||
}
|
||||
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setRegionWidth(int newWidth)
|
||||
{
|
||||
width = newWidth;
|
||||
halfWidth = (int)Math.floor(width / 2);
|
||||
|
||||
regions = new LodRegion[width][width];
|
||||
isRegionDirty = new boolean[width][width];
|
||||
|
||||
// populate isRegionDirty
|
||||
for(int i = 0; i < width; i++)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
/**
|
||||
* A LodRegion is the a 32x32
|
||||
* 2D array of LodChunk objects.
|
||||
* Each LodRegion corresponds to
|
||||
* one file in the file system.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 1-22-2021
|
||||
*/
|
||||
public class LodRegion
|
||||
{
|
||||
/** number of chunks wide */
|
||||
public static final int SIZE = 32;
|
||||
|
||||
/** X coordinate of this region */
|
||||
public final int x;
|
||||
/** Z coordinate of this region */
|
||||
public final int z;
|
||||
|
||||
private LodChunk chunks[][];
|
||||
|
||||
|
||||
public LodRegion(int regionX, int regionZ)
|
||||
{
|
||||
x = regionX;
|
||||
z = regionZ;
|
||||
|
||||
chunks = new LodChunk[SIZE][SIZE];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
// the region will negative first, therefore we don't have to
|
||||
// store the LOD chunks at negative indexes since we search
|
||||
// LOD the region first
|
||||
int xIndex = Math.abs(lod.x % SIZE);
|
||||
int zIndex = Math.abs(lod.z % SIZE);
|
||||
|
||||
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
|
||||
int arrayX = Math.abs(chunkX % SIZE);
|
||||
int arrayZ = Math.abs(chunkZ % SIZE);
|
||||
|
||||
if(arrayX >= SIZE || arrayZ >= SIZE)
|
||||
return null;
|
||||
|
||||
return chunks[arrayX][arrayZ];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns all LodChunks in this region
|
||||
*/
|
||||
public LodChunk[][] getAllLods()
|
||||
{
|
||||
return chunks;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String s = "";
|
||||
|
||||
s += "x: " + x + " z: " + z + "\t";
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.world.DimensionType;
|
||||
|
||||
/**
|
||||
* This stores all LODs for a given world.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 04-01-2021
|
||||
*/
|
||||
public class LodWorld
|
||||
{
|
||||
private String worldName;
|
||||
|
||||
private Map<DimensionType, LodDimension> lodDimensions;
|
||||
/** If true then the LOD world is setup and ready to use */
|
||||
private boolean isWorldLoaded = false;
|
||||
|
||||
public static final String NO_WORLD_LOADED = "No world loaded";
|
||||
|
||||
public LodWorld()
|
||||
{
|
||||
worldName = NO_WORLD_LOADED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the LodWorld with the given newWorldName. <br>
|
||||
* This should be done whenever loading a new world.
|
||||
* @param newWorldName
|
||||
*/
|
||||
public void selectWorld(String newWorldName)
|
||||
{
|
||||
if(newWorldName.isEmpty())
|
||||
{
|
||||
deselectWorld();
|
||||
return;
|
||||
}
|
||||
|
||||
if (worldName.equals(newWorldName))
|
||||
// don't recreate everything if we
|
||||
// didn't actually change worlds
|
||||
return;
|
||||
|
||||
worldName = newWorldName;
|
||||
lodDimensions = new Hashtable<DimensionType, LodDimension>();
|
||||
isWorldLoaded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the worldName to "No world loaded"
|
||||
* and clear the lodDimensions Map. <br>
|
||||
* This should be done whenever unloaded a world.
|
||||
*/
|
||||
public void deselectWorld()
|
||||
{
|
||||
worldName = NO_WORLD_LOADED;
|
||||
lodDimensions = null;
|
||||
isWorldLoaded = false;
|
||||
}
|
||||
|
||||
|
||||
public void addLodDimension(LodDimension newStorage)
|
||||
{
|
||||
if (lodDimensions == null)
|
||||
throw new IllegalStateException("LodWorld hasn't been given a world yet.");
|
||||
|
||||
lodDimensions.put(newStorage.dimension, newStorage);
|
||||
}
|
||||
|
||||
public LodDimension getLodDimension(DimensionType dimension)
|
||||
{
|
||||
if (lodDimensions == null)
|
||||
throw new IllegalStateException("LodWorld hasn't been given a world yet.");
|
||||
|
||||
return lodDimensions.get(dimension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the max width in regions that each LodDimension
|
||||
* should use.
|
||||
*/
|
||||
public void resizeDimensionRegionWidth(int newWidth)
|
||||
{
|
||||
if (lodDimensions == null)
|
||||
throw new IllegalStateException("LodWorld hasn't been given a world yet.");
|
||||
|
||||
for(DimensionType key : lodDimensions.keySet())
|
||||
lodDimensions.get(key).setRegionWidth(newWidth);
|
||||
}
|
||||
|
||||
|
||||
public boolean getIsWorldLoaded()
|
||||
{
|
||||
return isWorldLoaded;
|
||||
}
|
||||
|
||||
public String getWorldName()
|
||||
{
|
||||
return worldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "World name: " + worldName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.seibel.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 03-25-2021
|
||||
*/
|
||||
public class NearFarBuffer
|
||||
{
|
||||
public BufferBuilder nearBuffer;
|
||||
|
||||
public BufferBuilder farBuffer;
|
||||
|
||||
/**
|
||||
* @param newNearBuffer
|
||||
* @param newFarBuffer
|
||||
*/
|
||||
public NearFarBuffer(BufferBuilder newNearBuffer, BufferBuilder newFarBuffer)
|
||||
{
|
||||
nearBuffer = newNearBuffer;
|
||||
farBuffer = newFarBuffer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import com.seibel.lod.enums.FogDistance;
|
||||
|
||||
/**
|
||||
* This object is just a replacement for an array
|
||||
* to make things easier to understand in the LodRenderer.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-27-2021
|
||||
*/
|
||||
public class NearFarFogSetting
|
||||
{
|
||||
public FogDistance nearFogSetting = FogDistance.NEAR;
|
||||
public FogDistance farFogSetting = FogDistance.FAR;
|
||||
|
||||
|
||||
public NearFarFogSetting()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NearFarFogSetting(FogDistance newNearFogSetting, FogDistance newFarFogSetting)
|
||||
{
|
||||
nearFogSetting = newNearFogSetting;
|
||||
farFogSetting = newFarFogSetting;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
/**
|
||||
* This object is similar to ChunkPos or BlockPos.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 03-19-2021
|
||||
*/
|
||||
public class RegionPos
|
||||
{
|
||||
public int x;
|
||||
public int z;
|
||||
|
||||
|
||||
/**
|
||||
* Default Constructor <br>
|
||||
*
|
||||
* Sets x and z to 0
|
||||
*/
|
||||
public RegionPos()
|
||||
{
|
||||
x = 0;
|
||||
z = 0;
|
||||
}
|
||||
|
||||
public RegionPos(int newX, int newZ)
|
||||
{
|
||||
x = newX;
|
||||
z = newZ;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user