Closes #134 (Add multi dimension support)
I still need to add a config and multithreading (to prevent stuttering when changing dimensions).
This commit is contained in:
@@ -27,8 +27,6 @@ import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
@@ -170,6 +168,12 @@ public class ClientApi
|
||||
ApiShared.lodBuilder.defaultDimensionWidthInRegions);
|
||||
ApiShared.lodWorld.addLodDimension(lodDim);
|
||||
}
|
||||
// if necessary attempt to get the world file handler
|
||||
if (lodDim.isFileHandlerNull())
|
||||
{
|
||||
lodDim.attemptToSetWorldFileHandler();
|
||||
}
|
||||
|
||||
if (prefLoggerEnabled) {
|
||||
lodDim.dumpRamUsage();
|
||||
lodBufferBuilderFactory.dumpBufferMemoryUsage();
|
||||
|
||||
@@ -163,8 +163,8 @@ public class LodBuilder
|
||||
// this happens if a LOD is generated after the user leaves the world.
|
||||
if (MC.getWrappedClientWorld() == null)
|
||||
return false;
|
||||
if (!chunk.isLightCorrect()) return false;
|
||||
if (!chunk.doesNearbyChunksExist()) return false;
|
||||
if (!canGenerateLodFromChunk(chunk))
|
||||
return false;
|
||||
|
||||
|
||||
// generate the LODs
|
||||
@@ -190,8 +190,8 @@ public class LodBuilder
|
||||
data[i*maxVerticalData] = DataPointUtil.createVoidDataPoint(config.distanceGenerationMode.complexity);
|
||||
}
|
||||
}
|
||||
if (!chunk.isLightCorrect()) return false;
|
||||
if (!chunk.doesNearbyChunksExist()) return false;
|
||||
if (!canGenerateLodFromChunk(chunk)) // TODO Why are we calling this again? - James
|
||||
return false;
|
||||
|
||||
if (genAll) {
|
||||
return writeAllLodNodeData(lodDim, region, chunk.getChunkPosX(), chunk.getChunkPosZ(), data, config, override);
|
||||
@@ -202,8 +202,12 @@ public class LodBuilder
|
||||
ApiShared.LOGGER.error("LodBuilder encountered an error on building lod: ", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
public static boolean canGenerateLodFromChunk(IChunkWrapper chunk)
|
||||
{
|
||||
return chunk != null && chunk.isLightCorrect() && chunk.doesNearbyChunksExist();
|
||||
}
|
||||
|
||||
|
||||
private boolean writeAllLodNodeData(LodDimension lodDim, LodRegion region, int chunkX, int chunkZ,
|
||||
long[] data, LodBuilderConfig config, boolean override)
|
||||
|
||||
@@ -37,7 +37,6 @@ import com.seibel.lod.core.api.ApiShared;
|
||||
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
|
||||
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream;
|
||||
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.VerticalQuality;
|
||||
import com.seibel.lod.core.objects.lod.LevelContainer;
|
||||
@@ -77,6 +76,8 @@ public class LodDimensionFileHandler
|
||||
/** detail- */
|
||||
private static final String DETAIL_FOLDER_NAME_PREFIX = "detail-";
|
||||
|
||||
public static final String MULTIPLAYER_FOLDER_NAME = "Distant_Horizons_server_data";
|
||||
|
||||
/**
|
||||
* .tmp <br>
|
||||
* Added to the end of the file path when saving to prevent
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
package com.seibel.lod.core.handlers;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.VerticalQuality;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.objects.lod.LodRegion;
|
||||
import com.seibel.lod.core.objects.lod.RegionPos;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Used to guess the world folder for the player's current dimension.
|
||||
* @author James Seibel
|
||||
* @version 3-17-2022
|
||||
*/
|
||||
public class LodDimensionFileHelper
|
||||
{
|
||||
private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);
|
||||
|
||||
/** Increasing this will increase accuracy but increase calculation time */
|
||||
private static final VerticalQuality VERTICAL_QUALITY_TO_TEST_WITH = VerticalQuality.LOW;
|
||||
|
||||
/**
|
||||
* The minimum percent of identical dataPoints to consider two chunks as the same. <Br>
|
||||
* 0.9 = 90%
|
||||
*/
|
||||
private static final double minimumSimilarityRequired = 0.9;
|
||||
|
||||
|
||||
/**
|
||||
* Currently this method checks a single chunk (where the player is)
|
||||
* and compares it against the same chunk position in the other dimension worlds to
|
||||
* guess which world the player is in.
|
||||
* @return the new or existing folder for this dimension, null if there was a problem
|
||||
* @throws IOException if the folder doesn't exist or can't be accessed
|
||||
*/
|
||||
public static File determineSaveFolder() throws IOException
|
||||
{
|
||||
// relevant positions
|
||||
AbstractChunkPosWrapper playerChunkPos = MC.getPlayerChunkPos();
|
||||
int startingBlockPosX = playerChunkPos.getMinBlockX();
|
||||
int startingBlockPosZ = playerChunkPos.getMinBlockZ();
|
||||
RegionPos playerRegionPos = new RegionPos(MC.getPlayerChunkPos());
|
||||
|
||||
// chunk from the newly loaded dimension
|
||||
IChunkWrapper newlyLoadedChunk = MC.getWrappedClientWorld().tryGetChunk(playerChunkPos);
|
||||
// check if this chunk is valid to test
|
||||
if (!LodDimensionFileHelper.CanDetermineDimensionFolder(newlyLoadedChunk))
|
||||
return null;
|
||||
|
||||
// create a temporary dimension to store the new LOD
|
||||
LodDimension newlyLoadedDim = new LodDimension(null, null, 1);
|
||||
newlyLoadedDim.move(playerRegionPos);
|
||||
newlyLoadedDim.regions.set(playerRegionPos.x, playerRegionPos.z, new LodRegion(LodUtil.BLOCK_DETAIL_LEVEL, playerRegionPos, VERTICAL_QUALITY_TO_TEST_WITH));
|
||||
|
||||
// generate a LOD to test against
|
||||
boolean lodGenerated = ApiShared.lodBuilder.generateLodNodeFromChunk(newlyLoadedDim, newlyLoadedChunk, new LodBuilderConfig(DistanceGenerationMode.FULL), true, true);
|
||||
if (!lodGenerated)
|
||||
return null;
|
||||
|
||||
// new chunk data
|
||||
long[][][] newChunkData = new long[LodUtil.CHUNK_WIDTH][LodUtil.CHUNK_WIDTH][];
|
||||
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
|
||||
{
|
||||
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
|
||||
{
|
||||
long[] array = newlyLoadedDim.getRegion(playerRegionPos.x, playerRegionPos.z).getAllData(LodUtil.BLOCK_DETAIL_LEVEL, x + startingBlockPosX, z + startingBlockPosZ);
|
||||
newChunkData[x][z] = array;
|
||||
}
|
||||
}
|
||||
boolean newChunkHasData = isDataEmpty(newChunkData);
|
||||
// String message = "new chunk data " + (newChunkHasData ? newChunkData[0][0][0] : "[NULL]");
|
||||
// MC.sendChatMessage(message);
|
||||
// ApiShared.LOGGER.info(message);
|
||||
|
||||
// check if the chunk is actually empty
|
||||
if (!newChunkHasData)
|
||||
{
|
||||
if (newlyLoadedChunk.getHeight() != 0)
|
||||
{
|
||||
// the chunk isn't empty but the LOD is...
|
||||
|
||||
// String message = "Error: the chunk at (" + playerChunkPos.getX() + "," + playerChunkPos.getZ() + ") has a height of [" + newlyLoadedChunk.getHeight() + "] but the LOD generated is empty!";
|
||||
// MC.sendChatMessage(message);
|
||||
// ApiShared.LOGGER.info(message);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// String message = "The chunk at (" + playerChunkPos.getX() + "," + playerChunkPos.getZ() + ") is empty.";
|
||||
// MC.sendChatMessage(message);
|
||||
// ApiShared.LOGGER.info(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// get every folder (world) we have for this dimension
|
||||
File dimensionFolder = GetDimensionFolder(newlyLoadedDim.dimension, "");
|
||||
// check if the folder exists
|
||||
if (dimensionFolder.listFiles() == null)
|
||||
{
|
||||
if (!dimensionFolder.exists())
|
||||
{
|
||||
// create the directory since it doesn't exist
|
||||
dimensionFolder.mkdirs();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// compare each world with the newly loaded one
|
||||
File mostSimilarWorldFolder = null;
|
||||
int mostEqualLines = 0;
|
||||
boolean oneDimensionIsValid = false;
|
||||
|
||||
for (File testDimFolder : dimensionFolder.listFiles())
|
||||
{
|
||||
// get a LOD from this dimension folder
|
||||
LodDimension tempLodDim = new LodDimension(null, null, 1);
|
||||
tempLodDim.move(playerRegionPos);
|
||||
LodDimensionFileHandler tempFileHandler = new LodDimensionFileHandler(testDimFolder, tempLodDim);
|
||||
LodRegion testRegion = tempFileHandler.loadRegionFromFile(LodUtil.BLOCK_DETAIL_LEVEL, playerRegionPos, VERTICAL_QUALITY_TO_TEST_WITH);
|
||||
// get data from this LOD
|
||||
long[][][] testChunkData = new long[LodUtil.CHUNK_WIDTH][LodUtil.CHUNK_WIDTH][];
|
||||
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
|
||||
{
|
||||
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
|
||||
{
|
||||
long[] array = testRegion.getAllData(LodUtil.BLOCK_DETAIL_LEVEL, x + startingBlockPosX, z + startingBlockPosZ);
|
||||
testChunkData[x][z] = array;
|
||||
}
|
||||
}
|
||||
|
||||
// check if the chunk is actually empty
|
||||
if (!isDataEmpty(newChunkData))
|
||||
{
|
||||
// String message = "The test chunk for dimension folder [" + testDimFolder.getName() + "] and chunk pos (" + playerChunkPos.getX() + "," + playerChunkPos.getZ() + ") is empty. Is that correct?";
|
||||
// MC.sendChatMessage(message);
|
||||
// ApiShared.LOGGER.info(message);
|
||||
continue;
|
||||
}
|
||||
oneDimensionIsValid = true;
|
||||
|
||||
|
||||
// compare the two LODs
|
||||
int equalLines = 0;
|
||||
int totalLineCount = 0;
|
||||
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
|
||||
{
|
||||
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
|
||||
{
|
||||
for (int y = 0; y < newChunkData[x][y].length; y++)
|
||||
{
|
||||
if (newChunkData[x][z][y] == testChunkData[x][z][y])
|
||||
{
|
||||
equalLines++;
|
||||
}
|
||||
totalLineCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// String message = "test data [" + testDimFolder.getName().substring(0, 6) + "...] " + testChunkData[0][0][0] + " equal lines: " + equalLines + "/" + totalLineCount;
|
||||
// MC.sendChatMessage(message);
|
||||
// ApiShared.LOGGER.info(message);
|
||||
|
||||
// determine if this world is closer to the newly loaded world
|
||||
double percentEqual = (double) equalLines / (double) totalLineCount;
|
||||
if (equalLines > mostEqualLines && percentEqual >= minimumSimilarityRequired)
|
||||
{
|
||||
mostEqualLines = equalLines;
|
||||
mostSimilarWorldFolder = testDimFolder;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!oneDimensionIsValid && dimensionFolder.listFiles().length != 0)
|
||||
// all the world folders were empty, and there was at least one world folder that we tested
|
||||
return null;
|
||||
|
||||
|
||||
if (mostSimilarWorldFolder != null)
|
||||
{
|
||||
// we found a world folder that is similar, use it
|
||||
|
||||
String message = "Dimension folder set to: [" + mostSimilarWorldFolder.getName().substring(0, 8) + "...]";
|
||||
// MC.sendChatMessage(message);
|
||||
ApiShared.LOGGER.info(message);
|
||||
return mostSimilarWorldFolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no world folder was found, create a new one
|
||||
|
||||
String newId = UUID.randomUUID().toString();
|
||||
String message = "No dimension folder found. Creating a new one with ID: " + newId.substring(0, 8) + "...";
|
||||
// MC.sendChatMessage(message);
|
||||
ApiShared.LOGGER.info(message);
|
||||
return GetDimensionFolder(newlyLoadedDim.dimension, newId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dimension folder with the specific ID if specified. <br>
|
||||
* If the worldId is empty or null this returns the dimension parent folder <br>
|
||||
* Example folder names: "dim_overworld/worldId", "dim_the_nether/worldId"
|
||||
*/
|
||||
public static File GetDimensionFolder(IDimensionTypeWrapper newDimensionType, String worldId)
|
||||
{
|
||||
// prevent null pointers
|
||||
if (worldId == null)
|
||||
worldId = "";
|
||||
|
||||
try
|
||||
{
|
||||
if (MC.hasSinglePlayerServer())
|
||||
{
|
||||
// local world
|
||||
IWorldWrapper serverWorld = LodUtil.getServerWorldFromDimension(newDimensionType);
|
||||
return new File(serverWorld.getSaveFolder().getCanonicalFile().getPath() + File.separatorChar + "lod" + File.separatorChar + worldId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// multiplayer
|
||||
return new File(MC.getGameDirectory().getCanonicalFile().getPath() +
|
||||
File.separatorChar + "Distant_Horizons_server_data" + File.separatorChar + MC.getCurrentDimensionId() + File.separatorChar + worldId);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ApiShared.LOGGER.error("Unable to get dimension folder for dimension [" + newDimensionType.getDimensionName() + "]", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Returns true if the given chunk is valid to test */
|
||||
public static boolean CanDetermineDimensionFolder(IChunkWrapper chunk)
|
||||
{
|
||||
// we can only guess if the given chunk can be converted into a LOD
|
||||
return LodBuilder.canGenerateLodFromChunk(chunk);
|
||||
}
|
||||
|
||||
|
||||
/** Used for debugging, returns true if every data point is 0 */
|
||||
private static boolean isDataEmpty(long[][][] chunkData)
|
||||
{
|
||||
for (long[][] xArray : chunkData)
|
||||
{
|
||||
for (long[] zArray : xArray)
|
||||
{
|
||||
for (long dataPoint : zArray)
|
||||
{
|
||||
if (dataPoint != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,23 @@
|
||||
|
||||
package com.seibel.lod.core.objects.lod;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.DropoffQuality;
|
||||
import com.seibel.lod.core.enums.config.GenerationPriority;
|
||||
import com.seibel.lod.core.enums.config.VerticalQuality;
|
||||
import com.seibel.lod.core.handlers.LodDimensionFileHandler;
|
||||
import com.seibel.lod.core.handlers.LodDimensionFileHelper;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.objects.PosToGenerateContainer;
|
||||
import com.seibel.lod.core.util.*;
|
||||
import com.seibel.lod.core.util.MovableGridRingList.Pos;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@@ -26,33 +43,6 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.DropoffQuality;
|
||||
import com.seibel.lod.core.enums.config.GenerationPriority;
|
||||
import com.seibel.lod.core.enums.config.VerticalQuality;
|
||||
import com.seibel.lod.core.handlers.LodDimensionFileHandler;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.objects.PosToGenerateContainer;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
import com.seibel.lod.core.util.LodThreadFactory;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.MovableGridRingList;
|
||||
import com.seibel.lod.core.util.MovableGridRingList.Pos;
|
||||
import com.seibel.lod.core.util.SpamReducedLogger;
|
||||
import com.seibel.lod.core.util.UnitBytes;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
|
||||
|
||||
//FIXME: Race condition on lodDim move/resize!
|
||||
|
||||
@@ -66,7 +56,7 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @author James Seibel
|
||||
* @version 11-12-2021
|
||||
* @version 3-17-2022
|
||||
*/
|
||||
public class LodDimension
|
||||
{
|
||||
@@ -89,7 +79,8 @@ public class LodDimension
|
||||
private volatile RegionPos[] iteratorList = null;
|
||||
|
||||
|
||||
private LodDimensionFileHandler fileHandler;
|
||||
private LodDimensionFileHandler fileHandler = null;
|
||||
public boolean isFileHandlerNull() { return this.fileHandler == null; }
|
||||
|
||||
public volatile int dirtiedRegionsRoughCount = 0;
|
||||
|
||||
@@ -107,37 +98,12 @@ public class LodDimension
|
||||
public LodDimension(IDimensionTypeWrapper newDimension, LodWorld lodWorld, int newWidth)
|
||||
{
|
||||
dimension = newDimension;
|
||||
width = newWidth;
|
||||
width = newWidth; // FIXME any width besides 1 causes an indexOutOfBounds Exception
|
||||
halfWidth = width / 2;
|
||||
|
||||
if (newDimension != null && lodWorld != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// determine the save folder
|
||||
File saveDir;
|
||||
if (MC.hasSinglePlayerServer())
|
||||
{
|
||||
// local world
|
||||
|
||||
IWorldWrapper serverWorld = LodUtil.getServerWorldFromDimension(newDimension);
|
||||
saveDir = new File(serverWorld.getSaveFolder().getCanonicalFile().getPath() + File.separatorChar + "lod");
|
||||
}
|
||||
else
|
||||
{
|
||||
// connected to server
|
||||
|
||||
saveDir = new File(MC.getGameDirectory().getCanonicalFile().getPath() +
|
||||
File.separatorChar + "Distant_Horizons_server_data" + File.separatorChar + MC.getCurrentDimensionId());
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
attemptToSetWorldFileHandler();
|
||||
}
|
||||
|
||||
|
||||
@@ -145,6 +111,40 @@ public class LodDimension
|
||||
generateIteratorList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to determine and set the file handler based on
|
||||
* the chunk the player is currently in.
|
||||
* @returns true if the fileHandler has been set, false otherwise
|
||||
*/
|
||||
public boolean attemptToSetWorldFileHandler()
|
||||
{
|
||||
// check if we need to get the file handler
|
||||
if (this.fileHandler != null)
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
// attempt to get the file handler
|
||||
File saveDir = LodDimensionFileHelper.determineSaveFolder();
|
||||
if (saveDir == null)
|
||||
return false;
|
||||
|
||||
this.fileHandler = new LodDimensionFileHandler(saveDir, this);
|
||||
|
||||
// clear the previous regions so we can load the LODs from file
|
||||
if (this.regions != null)
|
||||
this.regions.clear();
|
||||
return true;
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
ApiShared.LOGGER.error("Unable to set the dimension file handler for dimension type [" + this.dimension.getDimensionName() + "]. Error: " + e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void generateIteratorList()
|
||||
{
|
||||
iteratorList = null;
|
||||
|
||||
@@ -20,12 +20,13 @@
|
||||
package com.seibel.lod.core.wrapperInterfaces.chunk;
|
||||
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockDetailWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 11-17-2021
|
||||
* @version 3-16-2022
|
||||
*/
|
||||
public interface IChunkWrapper extends IBindable
|
||||
{
|
||||
@@ -70,4 +71,23 @@ public interface IChunkWrapper extends IBindable
|
||||
}
|
||||
|
||||
boolean doesNearbyChunksExist();
|
||||
|
||||
|
||||
|
||||
/** This is a bad hash algorithm, but can be used for rough debugging. */
|
||||
public default int roughHashCode()
|
||||
{
|
||||
int hash = 31;
|
||||
int primeMultiplier = 227;
|
||||
|
||||
for(int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
|
||||
{
|
||||
for(int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
|
||||
{
|
||||
hash = hash * primeMultiplier + Integer.hashCode(getMaxY(x, z));
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user