Finish up the level split of 3 type of levels: ClientOnly, ClientServer, and ServerOnly

This commit is contained in:
TomTheFurry
2022-06-23 11:19:57 +08:00
parent 04bc771c6d
commit 74e58f5043
30 changed files with 227 additions and 161 deletions
@@ -1,8 +1,7 @@
package com.seibel.lod.core.a7.data;
import com.google.common.collect.HashMultimap;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
import com.seibel.lod.core.a7.io.file.DataMetaFile;
import com.seibel.lod.core.a7.save.io.file.DataMetaFile;
import com.seibel.lod.core.a7.level.ILevel;
import java.io.File;
@@ -7,7 +7,7 @@ import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.enums.config.EVerticalQuality;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
import com.seibel.lod.core.objects.a7.data.*;
import com.seibel.lod.core.a7.io.file.DataMetaFile;
import com.seibel.lod.core.a7.save.io.file.DataMetaFile;
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
import java.io.*;
@@ -2,12 +2,12 @@ package com.seibel.lod.core.a7.datatype.column;
import com.seibel.lod.core.a7.data.DataFileHandler;
import com.seibel.lod.core.a7.data.LodDataSource;
import com.seibel.lod.core.a7.io.MetaFile;
import com.seibel.lod.core.a7.save.io.MetaFile;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.enums.config.EVerticalQuality;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
import com.seibel.lod.core.a7.io.file.DataMetaFile;
import com.seibel.lod.core.a7.save.io.file.DataMetaFile;
import java.io.*;
import java.util.ArrayList;
@@ -3,7 +3,7 @@ package com.seibel.lod.core.a7.datatype.column;
import com.seibel.lod.core.a7.data.DataFileHandler;
import com.seibel.lod.core.a7.data.DataSourceLoader;
import com.seibel.lod.core.a7.data.LodDataSource;
import com.seibel.lod.core.a7.io.MetaFile;
import com.seibel.lod.core.a7.save.io.MetaFile;
import com.seibel.lod.core.a7.level.ILevel;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
@@ -1,4 +0,0 @@
package com.seibel.lod.core.a7.io;
public class FileScanner {
}
@@ -1,4 +0,0 @@
package com.seibel.lod.core.a7.io;
public class LevelFileHandler {
}
@@ -1,8 +1,9 @@
package com.seibel.lod.core.a7.level;
import com.seibel.lod.core.a7.LodQuadTree;
import com.seibel.lod.core.a7.io.file.RemoteDataFileHandler;
import com.seibel.lod.core.a7.io.render.RenderFileHandler;
import com.seibel.lod.core.a7.save.io.FileScanner;
import com.seibel.lod.core.a7.save.io.file.RemoteDataFileHandler;
import com.seibel.lod.core.a7.save.io.render.RenderFileHandler;
import com.seibel.lod.core.a7.pos.DhBlockPos2D;
import com.seibel.lod.core.a7.render.RenderBufferHandler;
import com.seibel.lod.core.a7.save.structure.ClientOnlySaveStructure;
@@ -14,6 +15,7 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import java.util.Scanner;
import java.util.concurrent.CompletableFuture;
public class DhClientLevel implements IClientLevel {
@@ -34,6 +36,7 @@ public class DhClientLevel implements IClientLevel {
MC_CLIENT.getPlayerBlockPos().x, MC_CLIENT.getPlayerBlockPos().z, renderFileHandler);
renderBufferHandler = new RenderBufferHandler(tree);
this.level = level;
FileScanner.scanFile(save, level, dataFileHandler, renderFileHandler);
}
public void tick() {
@@ -1,8 +1,9 @@
package com.seibel.lod.core.a7.level;
import com.seibel.lod.core.a7.LodQuadTree;
import com.seibel.lod.core.a7.io.file.LocalDataFileHandler;
import com.seibel.lod.core.a7.io.render.RenderFileHandler;
import com.seibel.lod.core.a7.save.io.FileScanner;
import com.seibel.lod.core.a7.save.io.file.LocalDataFileHandler;
import com.seibel.lod.core.a7.save.io.render.RenderFileHandler;
import com.seibel.lod.core.a7.pos.DhBlockPos2D;
import com.seibel.lod.core.a7.render.RenderBufferHandler;
import com.seibel.lod.core.a7.save.structure.LocalSaveStructure;
@@ -34,6 +35,7 @@ public class DhClientServerLevel implements IClientLevel, IServerLevel {
tree = new LodQuadTree(Config.Client.Graphics.Quality.lodChunkRenderDistance.get()*16,
MC_CLIENT.getPlayerBlockPos().x, MC_CLIENT.getPlayerBlockPos().z, renderFileHandler);
renderBufferHandler = new RenderBufferHandler(tree);
FileScanner.scanFile(save, level, dataFileHandler, renderFileHandler);
}
public void tick() {
@@ -86,4 +88,9 @@ public class DhClientServerLevel implements IClientLevel, IServerLevel {
renderFileHandler.close();
//Note: Closing renderFileHandler will also close the dataFileHandler.
}
@Override
public void doWorldGen() {
//TODO
}
}
@@ -1,6 +1,7 @@
package com.seibel.lod.core.a7.level;
import com.seibel.lod.core.a7.io.file.LocalDataFileHandler;
import com.seibel.lod.core.a7.save.io.FileScanner;
import com.seibel.lod.core.a7.save.io.file.LocalDataFileHandler;
import com.seibel.lod.core.a7.save.structure.LocalSaveStructure;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
@@ -15,6 +16,7 @@ public class DhServerLevel implements IServerLevel {
this.save = save;
this.level = level;
dataFileHandler = new LocalDataFileHandler(this, save.getDataFolder(level));
FileScanner.scanFile(save, level, dataFileHandler, null);
}
public void tick() {
@@ -38,4 +40,9 @@ public class DhServerLevel implements IServerLevel {
public CompletableFuture<Void> save() {
return dataFileHandler.flushAndSave();
}
@Override
public void doWorldGen() {
}
}
@@ -1,6 +1,5 @@
package com.seibel.lod.core.a7.level;
import com.seibel.lod.core.a7.io.render.RenderSourceProvider;
import com.seibel.lod.core.a7.render.RenderBufferHandler;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
@@ -1,4 +1,5 @@
package com.seibel.lod.core.a7.level;
public interface IServerLevel extends ILevel {
void doWorldGen();
}
@@ -1,4 +1,4 @@
package com.seibel.lod.core.a7.io;
package com.seibel.lod.core.a7.save.io;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.enums.config.EServerFolderNameMode;
@@ -0,0 +1,45 @@
package com.seibel.lod.core.a7.save.io;
import com.seibel.lod.core.a7.save.io.file.DataSourceProvider;
import com.seibel.lod.core.a7.save.io.render.RenderSourceProvider;
import com.seibel.lod.core.a7.save.structure.SaveStructure;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Collectors;
import java.util.stream.Stream;
// Static util class??
public class FileScanner {
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public static final int MAX_SCAN_DEPTH = 5;
public static final String LOD_FILE_POSTFIX = ".lod";
public static void scanFile(SaveStructure save, ILevelWrapper level,
@Nullable DataSourceProvider dataSource,
@Nullable RenderSourceProvider renderSource) {
if (dataSource != null) {
try (Stream<Path> pathStream = Files.walk(save.getDataFolder(level).toPath(), MAX_SCAN_DEPTH)) {
dataSource.addScannedFile(pathStream.filter((
path -> path.endsWith(LOD_FILE_POSTFIX) && path.toFile().isFile())
).map(Path::toFile).collect(Collectors.toList())
);
} catch (Exception e) {
LOGGER.error("Failed to scan and collect data files for {} in {}", level, save);
}
}
if (renderSource != null) {
try (Stream<Path> pathStream = Files.walk(save.getRenderCacheFolder(level).toPath(), MAX_SCAN_DEPTH)) {
renderSource.addScannedFile(pathStream.filter((
path -> path.endsWith(LOD_FILE_POSTFIX) && path.toFile().isFile())
).map(Path::toFile).collect(Collectors.toList())
);
} catch (Exception e) {
LOGGER.error("Failed to scan and collect data files for {} in {}", level, save);
}
}
}
}
@@ -0,0 +1,4 @@
package com.seibel.lod.core.a7.save.io;
public class LevelFileHandler {
}
@@ -1,4 +1,4 @@
package com.seibel.lod.core.a7.io;
package com.seibel.lod.core.a7.save.io;
import com.seibel.lod.core.a7.world.DhClientWorld;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
@@ -36,27 +36,24 @@ public class LevelToFileMatcher implements AutoCloseable {
/** If true the LodDimensionFileHelper is attempting to determine the folder for this dimension */
private final AtomicBoolean determiningWorldFolder = new AtomicBoolean(false);
private final ILevelWrapper currentLevel;
private final DhClientWorld world;
private volatile DhClientServerLevel foundLevel = null;
private volatile File foundLevel = null;
private final File[] potentialFiles;
private final File levelsFolder;
public LevelToFileMatcher(DhClientWorld DhWorld, ILevelWrapper targetWorld, File levelsFolder, File[] potentialFiles) {
public LevelToFileMatcher(ILevelWrapper targetWorld, File levelsFolder, File[] potentialFiles) {
this.currentLevel = targetWorld;
this.world = DhWorld;
this.potentialFiles = potentialFiles;
this.levelsFolder = levelsFolder;
if (potentialFiles.length == 0) {
String newId = UUID.randomUUID().toString();
LOGGER.info("No potential level files found. Creating a new sub dimension with ID {}...",
LodUtil.shortenString(newId, 8));
File folder = new File(levelsFolder, newId);
foundLevel = new DhClientServerLevel(world, folder, targetWorld);
foundLevel = new File(levelsFolder, newId);
}
}
// May return null, where at this moment the level is not yet known
public DhClientServerLevel tryGetLevel() {
public File tryGetLevel() {
tick();
return foundLevel;
}
@@ -74,8 +71,7 @@ public class LevelToFileMatcher implements AutoCloseable {
try {
// attempt to get the file handler
File saveDir = attemptToDetermineSubDimensionFolder();
if (saveDir == null) return;
foundLevel = new DhClientServerLevel(world, saveDir, currentLevel);
if (saveDir != null) foundLevel = saveDir;
} catch (IOException e) {
LOGGER.error("Unable to set the dimension file handler for level [" + currentLevel + "]. Error: ", e);
} finally {
@@ -1,4 +1,4 @@
package com.seibel.lod.core.a7.io;
package com.seibel.lod.core.a7.save.io;
import java.io.*;
import java.nio.ByteBuffer;
@@ -1,4 +1,4 @@
package com.seibel.lod.core.a7.io.file;
package com.seibel.lod.core.a7.save.io.file;
import java.io.*;
import java.lang.ref.SoftReference;
@@ -14,12 +14,10 @@ import java.util.function.BiConsumer;
import com.seibel.lod.core.a7.data.DataSourceLoader;
import com.seibel.lod.core.a7.data.LodDataSource;
import com.seibel.lod.core.a7.datatype.full.FullDatatype;
import com.seibel.lod.core.a7.io.MetaFile;
import com.seibel.lod.core.a7.save.io.MetaFile;
import com.seibel.lod.core.a7.level.ILevel;
import com.seibel.lod.core.a7.level.IServerLevel;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
import com.seibel.lod.core.a7.datatype.column.DataSourceSaver;
import com.seibel.lod.core.a7.datatype.column.OldDataSourceLoader;
import com.seibel.lod.core.util.LodUtil;
@@ -1,12 +1,16 @@
package com.seibel.lod.core.a7.io.file;
package com.seibel.lod.core.a7.save.io.file;
import com.seibel.lod.core.a7.data.LodDataSource;
import com.seibel.lod.core.a7.datatype.full.FullDatatype;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import java.io.File;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
public interface DataSourceProvider extends AutoCloseable {
void addScannedFile(Collection<File> detectedFiles);
CompletableFuture<LodDataSource> read(DhSectionPos pos);
void write(DhSectionPos sectionPos, FullDatatype chunkData);
CompletableFuture<Void> flushAndSave();
@@ -1,4 +1,4 @@
package com.seibel.lod.core.a7.io.file;
package com.seibel.lod.core.a7.save.io.file;
import com.google.common.collect.HashMultimap;
import com.seibel.lod.core.a7.data.LodDataSource;
@@ -6,7 +6,6 @@ import com.seibel.lod.core.a7.datatype.full.FullDatatype;
import com.seibel.lod.core.a7.level.IServerLevel;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
import com.seibel.lod.core.util.LodUtil;
import org.apache.logging.log4j.Logger;
@@ -40,6 +39,7 @@ public class LocalDataFileHandler implements DataSourceProvider {
* Caller must ensure that this method is called only once,
* and that this object is not used before this method is called.
*/
@Override
public void addScannedFile(Collection<File> detectedFiles) {
HashMultimap<DhSectionPos, DataMetaFile> filesByPos = HashMultimap.create();
{ // Sort files by pos.
@@ -1,12 +1,19 @@
package com.seibel.lod.core.a7.io.file;
package com.seibel.lod.core.a7.save.io.file;
import com.seibel.lod.core.a7.data.LodDataSource;
import com.seibel.lod.core.a7.datatype.full.FullDatatype;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import java.io.File;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
public class RemoteDataFileHandler implements DataSourceProvider {
@Override
public void addScannedFile(Collection<File> detectedFiles) {
}
@Override
public CompletableFuture<LodDataSource> read(DhSectionPos pos) {
return null;
@@ -1,8 +1,7 @@
package com.seibel.lod.core.a7.io.render;
package com.seibel.lod.core.a7.save.io.render;
import com.seibel.lod.core.a7.RenderDataProvider;
import com.seibel.lod.core.a7.datatype.full.FullDatatype;
import com.seibel.lod.core.a7.io.file.DataSourceProvider;
import com.seibel.lod.core.a7.save.io.file.DataSourceProvider;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.a7.render.RenderDataSource;
@@ -11,6 +10,7 @@ import com.seibel.lod.core.util.LodUtil;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
@@ -30,6 +30,11 @@ public class RenderFileHandler implements RenderSourceProvider {
return null;
}
@Override
public void addScannedFile(Collection<File> detectedFiles) {
}
@Override
public void write(DhSectionPos sectionPos, FullDatatype chunkData) {
@@ -1,6 +1,6 @@
package com.seibel.lod.core.a7.io.render;
package com.seibel.lod.core.a7.save.io.render;
import com.seibel.lod.core.a7.io.MetaFile;
import com.seibel.lod.core.a7.save.io.MetaFile;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import java.io.File;
@@ -1,12 +1,15 @@
package com.seibel.lod.core.a7.io.render;
package com.seibel.lod.core.a7.save.io.render;
import com.seibel.lod.core.a7.RenderDataProvider;
import com.seibel.lod.core.a7.datatype.full.FullDatatype;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import java.io.File;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
public interface RenderSourceProvider extends RenderDataProvider, AutoCloseable {
void addScannedFile(Collection<File> detectedFiles);
void write(DhSectionPos sectionPos, FullDatatype chunkData);
CompletableFuture<Void> flushAndSave();
}
@@ -1,12 +1,8 @@
package com.seibel.lod.core.a7.save.structure;
import com.seibel.lod.core.a7.io.LevelToFileMatcher;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
import com.seibel.lod.core.a7.level.IServerLevel;
import com.seibel.lod.core.a7.world.DhClientWorld;
import com.seibel.lod.core.a7.save.io.LevelToFileMatcher;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.enums.config.EServerFolderNameMode;
import com.seibel.lod.core.enums.config.EVerticalQuality;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.objects.ParsedIp;
import com.seibel.lod.core.util.LodUtil;
@@ -16,6 +12,7 @@ import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import javax.annotation.Nullable;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Optional;
import java.util.stream.Stream;
@@ -72,39 +69,37 @@ public class ClientOnlySaveStructure extends SaveStructure {
}
LevelToFileMatcher fileMatcher = null;
final DhClientWorld world;
final HashMap<ILevelWrapper, File> levelToFileMap = new HashMap<>();
// Fit for Client_Only environment
public ClientOnlySaveStructure(DhClientWorld world) {
public ClientOnlySaveStructure() {
folder = new File(MC_CLIENT.getGameDirectory().getPath() +
File.separatorChar + "Distant_Horizons_server_data" + File.separatorChar + getServerFolderName());
if (!folder.exists()) folder.mkdirs(); //TODO: Deal with errors
this.world = world;
}
//FIXME: how do i deal with either creating a ClientServerLevel, or a ServerLevel here???
@Override
public IServerLevel tryGetLevel(ILevelWrapper wrapper) {
if (Config.Client.Multiplayer.multiDimensionRequiredSimilarity.get() == 0) {
if (fileMatcher != null) {
public File tryGetLevelFolder(ILevelWrapper level) {
return levelToFileMap.computeIfAbsent(level, (l) -> {
if (Config.Client.Multiplayer.multiDimensionRequiredSimilarity.get() == 0) {
if (fileMatcher != null) {
fileMatcher.close();
fileMatcher = null;
}
return getLevelFolderWithoutSimilarityMatching(l);
}
if (fileMatcher == null || !fileMatcher.isFindingLevel(l)) {
LOGGER.info("Loading level for world " + l.getDimensionType().getDimensionName());
fileMatcher = new LevelToFileMatcher(l, folder,
(File[]) getMatchingLevelFolders(l).toArray());
}
File levelFile = fileMatcher.tryGetLevel();
if (levelFile != null) {
fileMatcher.close();
fileMatcher = null;
}
return new DhClientServerLevel(world, getLevelFolderWithoutSimilarityMatching(wrapper), wrapper);
}
if (fileMatcher == null || !fileMatcher.isFindingLevel(wrapper)) {
LOGGER.info("Loading level for world " + wrapper.getDimensionType().getDimensionName());
fileMatcher = new LevelToFileMatcher(world, wrapper, folder,
(File[]) getMatchingLevelFolders(wrapper).toArray());
}
DhClientServerLevel level = fileMatcher.tryGetLevel();
if (level != null) {
fileMatcher.close();
fileMatcher = null;
}
return level;
return levelFile;
});
}
private File getLevelFolderWithoutSimilarityMatching(ILevelWrapper level)
@@ -139,36 +134,34 @@ public class ClientOnlySaveStructure extends SaveStructure {
// it needs to be a folder
return false;
if (potentialFolder.listFiles() == null)
// it needs to have folders in it
return false;
// check if there is at least one VerticalQuality folder in this directory
for (File internalFolder : potentialFolder.listFiles())
{
if (EVerticalQuality.getByName(internalFolder.getName()) != null)
{
// one of the internal folders is a VerticalQuality folder
return true;
}
}
return false;
File[] files = potentialFolder.listFiles((f) -> f.isDirectory() &&
(f.getName().equalsIgnoreCase(RENDER_CACHE_FOLDER) || f.getName().equalsIgnoreCase(DATA_FOLDER)));
// it needs to have folders with specified names in it
return files != null && files.length != 0;
}
@Override
public File getRenderCacheFolder(ILevelWrapper world) {
return null;
public File getRenderCacheFolder(ILevelWrapper level) {
File levelFolder = levelToFileMap.get(level);
if (levelFolder == null) return null;
return new File(levelFolder, RENDER_CACHE_FOLDER);
}
@Override
public File getDataFolder(ILevelWrapper world) {
return null;
public File getDataFolder(ILevelWrapper level) {
File levelFolder = levelToFileMap.get(level);
if (levelFolder == null) return null;
return new File(levelFolder, DATA_FOLDER);
}
@Override
public void close() {
fileMatcher.close();
}
@Override
public String toString() {
return "[ClientOnlySave@"+folder.getName()+"]";
}
}
@@ -1,6 +1,7 @@
package com.seibel.lod.core.a7.save.structure;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
@@ -10,20 +11,32 @@ import java.io.File;
public class LocalSaveStructure extends SaveStructure {
private static final IMinecraftSharedWrapper MC = SingletonHandler.get(IMinecraftSharedWrapper.class);
private final File folder;
// Fit for Client_Server & Server_Only environment
public LocalSaveStructure() {
folder = MC.getInstallationDirectory();
}
@Override
public File getRenderCacheFolder(ILevelWrapper world) {
return null;
public File tryGetLevelFolder(ILevelWrapper wrapper) {
return new File(wrapper.getSaveFolder(), "Distant_Horizons");
}
@Override
public File getDataFolder(ILevelWrapper world) {
return null;
public File getRenderCacheFolder(ILevelWrapper level) {
return new File(new File(level.getSaveFolder(), "Distant_Horizons"), RENDER_CACHE_FOLDER);
}
@Override
public File getDataFolder(ILevelWrapper level) {
return new File(new File(level.getSaveFolder(), "Distant_Horizons"), DATA_FOLDER);
}
@Override
public void close() throws Exception {
}
@Override
public String toString() {
return "[LocalSave]";
}
}
@@ -1,6 +1,5 @@
package com.seibel.lod.core.a7.save.structure;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import org.apache.logging.log4j.Logger;
@@ -9,11 +8,14 @@ import java.io.File;
public abstract class SaveStructure implements AutoCloseable {
public static final String RENDER_CACHE_FOLDER = "cache";
public static final String DATA_FOLDER = "data";
protected static final Logger LOGGER = DhLoggerBuilder.getLogger();
public abstract DhClientServerLevel tryGetLevel(ILevelWrapper wrapper);
public abstract File tryGetLevelFolder(ILevelWrapper wrapper);
protected abstract File getRenderCacheFolder(ILevelWrapper world);
protected abstract File getDataFolder(ILevelWrapper world);
public abstract File getRenderCacheFolder(ILevelWrapper world);
public abstract File getDataFolder(ILevelWrapper world);
}
@@ -4,9 +4,10 @@ import com.seibel.lod.core.a7.WorldEnvironment;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
import com.seibel.lod.core.a7.save.structure.LocalSaveStructure;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.util.DetailDistanceUtil;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.CompletableFuture;
@@ -23,13 +24,11 @@ public class DhClientServerWorld extends DhWorld implements IClientWorld, IServe
@Override
public DhClientServerLevel getOrLoadLevel(ILevelWrapper wrapper) {
if (!levels.containsKey(wrapper)) {
DhClientServerLevel level = saveStructure.tryGetLevel(wrapper);
if (level != null) {
levels.put(wrapper, level);
}
return level;
} else return levels.get(wrapper);
return levels.computeIfAbsent(wrapper, (w) -> {
File levelFile = saveStructure.tryGetLevelFolder(w);
LodUtil.assertTrue(levelFile != null);
return new DhClientServerLevel(saveStructure, w);
});
}
@Override
@@ -56,11 +55,12 @@ public class DhClientServerWorld extends DhWorld implements IClientWorld, IServe
iterator.remove();
}
}
DetailDistanceUtil.updateSettings();
//DetailDistanceUtil.updateSettings();
levels.values().forEach(DhClientServerLevel::tick);
}
public void doWorldGen() {
levels.values().forEach(DhClientServerLevel::doWorldGen);
}
@Override
@@ -1,7 +1,7 @@
package com.seibel.lod.core.a7.world;
import com.seibel.lod.core.a7.WorldEnvironment;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
import com.seibel.lod.core.a7.level.DhClientLevel;
import com.seibel.lod.core.a7.save.structure.ClientOnlySaveStructure;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.util.DetailDistanceUtil;
@@ -9,6 +9,7 @@ import com.seibel.lod.core.util.EventLoop;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.CompletableFuture;
@@ -16,7 +17,7 @@ import java.util.concurrent.ExecutorService;
public class DhClientWorld extends DhWorld implements IClientWorld {
private final HashMap<ILevelWrapper, DhClientWorld> levels;
private final HashMap<ILevelWrapper, DhClientLevel> levels;
public final ClientOnlySaveStructure saveStructure;
public ExecutorService dhTickerThread = LodUtil.makeSingleThreadPool("DHTickerThread", 2);
@@ -24,23 +25,21 @@ public class DhClientWorld extends DhWorld implements IClientWorld {
public DhClientWorld() {
super(WorldEnvironment.Client_Only);
saveStructure = new ClientOnlySaveStructure(this);
saveStructure = new ClientOnlySaveStructure();
levels = new HashMap<>();
}
@Override
public DhClientServerLevel getOrLoadLevel(ILevelWrapper wrapper) {
if (!levels.containsKey(wrapper)) {
DhClientWorld level = saveStructure.tryGetLevel(wrapper);
if (level != null) {
levels.put(wrapper, level);
}
return level;
} else return levels.get(wrapper);
public DhClientLevel getOrLoadLevel(ILevelWrapper wrapper) {
return levels.computeIfAbsent(wrapper, (w) -> {
File level = saveStructure.tryGetLevelFolder(wrapper);
if (level == null) return null;
return new DhClientLevel(saveStructure, w);
});
}
@Override
public DhClientServerLevel getLevel(ILevelWrapper wrapper) {
public DhClientLevel getLevel(ILevelWrapper wrapper) {
return levels.get(wrapper);
}
@@ -55,10 +54,10 @@ public class DhClientWorld extends DhWorld implements IClientWorld {
private void tick() {
int newViewDistance = Config.Client.Graphics.Quality.lodChunkRenderDistance.get() * 16;
Iterator<DhClientWorld> iterator = levels.values().iterator();
Iterator<DhClientLevel> iterator = levels.values().iterator();
while (iterator.hasNext()) {
DhClientWorld level = iterator.next();
if (level.viewDistance != newViewDistance) {
DhClientLevel level = iterator.next();
if (level.tree.viewDistance != newViewDistance) {
level.close();
iterator.remove();
}
@@ -72,13 +71,13 @@ public class DhClientWorld extends DhWorld implements IClientWorld {
@Override
public CompletableFuture<Void> saveAndFlush() {
return CompletableFuture.allOf(levels.values().stream().map(DhClientServerLevel::save).toArray(CompletableFuture[]::new));
return CompletableFuture.allOf(levels.values().stream().map(DhClientLevel::save).toArray(CompletableFuture[]::new));
}
@Override
public void close() {
saveAndFlush().join();
for (DhClientServerLevel level : levels.values()) {
for (DhClientLevel level : levels.values()) {
LOGGER.info("Unloading level for world " + level.level.getDimensionType().getDimensionName());
level.close();
}
@@ -1,17 +1,17 @@
package com.seibel.lod.core.a7.world;
import com.seibel.lod.core.a7.WorldEnvironment;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
import com.seibel.lod.core.a7.level.DhServerLevel;
import com.seibel.lod.core.a7.save.structure.LocalSaveStructure;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.util.DetailDistanceUtil;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.CompletableFuture;
public class DhServerWorld extends DhWorld implements IServerWorld {
private final HashMap<ILevelWrapper, DhClientServerLevel> levels;
private final HashMap<ILevelWrapper, DhServerLevel> levels;
public final LocalSaveStructure saveStructure;
public DhServerWorld() {
@@ -21,18 +21,16 @@ public class DhServerWorld extends DhWorld implements IServerWorld {
}
@Override
public DhClientServerLevel getOrLoadLevel(ILevelWrapper wrapper) {
if (!levels.containsKey(wrapper)) {
DhClientServerLevel level = saveStructure.tryGetLevel(wrapper);
if (level != null) {
levels.put(wrapper, level);
}
return level;
} else return levels.get(wrapper);
public DhServerLevel getOrLoadLevel(ILevelWrapper wrapper) {
return levels.computeIfAbsent(wrapper, (w) -> {
File levelFile = saveStructure.tryGetLevelFolder(wrapper);
LodUtil.assertTrue(levelFile != null);
return new DhServerLevel(saveStructure, w);
});
}
@Override
public DhClientServerLevel getLevel(ILevelWrapper wrapper) {
public DhServerLevel getLevel(ILevelWrapper wrapper) {
return levels.get(wrapper);
}
@@ -46,32 +44,22 @@ public class DhServerWorld extends DhWorld implements IServerWorld {
}
public void tick() {
int newViewDistance = Config.Client.Graphics.Quality.lodChunkRenderDistance.get() * 16;
Iterator<DhClientServerLevel> iterator = levels.values().iterator();
while (iterator.hasNext()) {
DhClientServerLevel level = iterator.next();
if (level.viewDistance != newViewDistance) {
level.close();
iterator.remove();
}
}
DetailDistanceUtil.updateSettings();
levels.values().forEach(DhServerLevel::tick);
}
public void doWorldGen() {
levels.values().forEach(DhServerLevel::doWorldGen);
}
@Override
public void saveAndFlush() {
for (DhClientServerLevel level : levels.values()) {
level.saveFlush();
}
public CompletableFuture<Void> saveAndFlush() {
return CompletableFuture.allOf(levels.values().stream().map(DhServerLevel::save).toArray(CompletableFuture[]::new));
}
@Override
public void close() {
for (DhClientServerLevel level : levels.values()) {
for (DhServerLevel level : levels.values()) {
LOGGER.info("Unloading level for world " + level.level.getDimensionType().getDimensionName());
level.close();
}
@@ -2,6 +2,7 @@ package com.seibel.lod.core.a7.world;
import com.seibel.lod.core.a7.WorldEnvironment;
import com.seibel.lod.core.a7.level.DhClientServerLevel;
import com.seibel.lod.core.a7.level.ILevel;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import org.apache.logging.log4j.Logger;
@@ -17,9 +18,9 @@ public abstract class DhWorld implements Closeable {
protected DhWorld(WorldEnvironment environment) {
this.environment = environment;
}
public abstract DhClientServerLevel getOrLoadLevel(ILevelWrapper wrapper);
public abstract ILevel getOrLoadLevel(ILevelWrapper wrapper);
public abstract DhClientServerLevel getLevel(ILevelWrapper wrapper);
public abstract ILevel getLevel(ILevelWrapper wrapper);
public abstract void unloadLevel(ILevelWrapper wrapper);
public abstract CompletableFuture<Void> saveAndFlush();