From 04bc771c6d978a03979b54164112da092cd2f8ac Mon Sep 17 00:00:00 2001 From: TomTheFurry Date: Wed, 22 Jun 2022 22:13:08 +0800 Subject: [PATCH] Continue refactoring, and starting to hook up all the loose pieces --- .../com/seibel/lod/core/a7/LodQuadTree.java | 23 +-- .../lod/core/a7/data/DataFileHandler.java | 158 ------------------ .../lod/core/a7/data/DataSourceLoader.java | 5 +- .../lod/core/a7/data/OldFileConverter.java | 4 +- .../a7/datatype/column/Alpha6DataLoader.java | 6 +- .../a7/datatype/column/ColumnDataLoader.java | 8 +- .../a7/datatype/column/ColumnDatatype.java | 4 +- .../datatype/column/ColumnRenderLoader.java | 6 +- .../a7/datatype/column/DataSourceSaver.java | 7 +- .../a7/datatype/column/OldColumnDatatype.java | 4 +- .../lod/core/a7/io/LevelToFileMatcher.java | 19 +-- .../lod/core/a7/io/file/DataMetaFile.java | 10 +- .../core/a7/io/file/DataSourceProvider.java | 2 +- .../core/a7/io/file/LocalDataFileHandler.java | 12 +- .../a7/io/file/RemoteDataFileHandler.java | 29 ++++ .../core/a7/io/render/RenderFileHandler.java | 15 +- .../a7/io/render/RenderSourceProvider.java | 6 +- .../com/seibel/lod/core/a7/level/DHLevel.java | 105 ------------ .../lod/core/a7/level/DhClientLevel.java | 88 ++++++++++ .../core/a7/level/DhClientServerLevel.java | 89 ++++++++++ .../lod/core/a7/level/DhServerLevel.java | 41 +++++ .../lod/core/a7/level/IClientLevel.java | 14 ++ .../com/seibel/lod/core/a7/level/ILevel.java | 10 ++ .../lod/core/a7/level/IServerLevel.java | 4 + .../a7/render/RenderDataSourceLoader.java | 6 +- .../structure/ClientOnlySaveStructure.java | 12 +- .../core/a7/save/structure/SaveStructure.java | 6 +- .../core/a7/world/DhClientServerWorld.java | 31 ++-- .../lod/core/a7/world/DhClientWorld.java | 32 ++-- .../lod/core/a7/world/DhServerWorld.java | 20 +-- .../com/seibel/lod/core/a7/world/DhWorld.java | 18 +- .../lod/core/a7/world/IClientWorld.java | 1 - .../lod/core/api/internal/a7/ClientApi.java | 4 +- .../seibel/lod/core/render/a7LodRenderer.java | 9 +- 34 files changed, 396 insertions(+), 412 deletions(-) delete mode 100644 src/main/java/com/seibel/lod/core/a7/data/DataFileHandler.java create mode 100644 src/main/java/com/seibel/lod/core/a7/io/file/RemoteDataFileHandler.java delete mode 100644 src/main/java/com/seibel/lod/core/a7/level/DHLevel.java create mode 100644 src/main/java/com/seibel/lod/core/a7/level/DhClientLevel.java create mode 100644 src/main/java/com/seibel/lod/core/a7/level/DhClientServerLevel.java create mode 100644 src/main/java/com/seibel/lod/core/a7/level/DhServerLevel.java create mode 100644 src/main/java/com/seibel/lod/core/a7/level/IClientLevel.java create mode 100644 src/main/java/com/seibel/lod/core/a7/level/ILevel.java create mode 100644 src/main/java/com/seibel/lod/core/a7/level/IServerLevel.java diff --git a/src/main/java/com/seibel/lod/core/a7/LodQuadTree.java b/src/main/java/com/seibel/lod/core/a7/LodQuadTree.java index 7ab266684..525c63061 100644 --- a/src/main/java/com/seibel/lod/core/a7/LodQuadTree.java +++ b/src/main/java/com/seibel/lod/core/a7/LodQuadTree.java @@ -23,17 +23,13 @@ import java.util.ArrayList; * -by loading from file * -by adding data with the lodBuilder */ -public abstract class LodQuadTree { - +public class LodQuadTree { /** - * //TODO add static configs here - * //These configs are updated someway - * Comment: all config value should be via the class that extends this class, and - * by implementing different abstract methods - LeeTom + * Note: all config value should be via the class that extends this class, and + * by implementing different abstract methods */ - public final byte numbersOfSectionLevels; public final byte startingSectionLevel; private final MovableGridRingList[] ringLists; @@ -99,6 +95,7 @@ public abstract class LodQuadTree { final SectionDetailLayer[] sectionDetailLayers; public final int viewDistance; + private final RenderDataProvider renderDataProvider; /** * Constructor of the quadTree @@ -106,8 +103,9 @@ public abstract class LodQuadTree { * @param initialPlayerX player x coordinate * @param initialPlayerZ player z coordinate */ - public LodQuadTree(int viewDistance, int initialPlayerX, int initialPlayerZ) { + public LodQuadTree(int viewDistance, int initialPlayerX, int initialPlayerZ, RenderDataProvider provider) { ColumnDatatype.REGISTER(); //FIXME: This is a hack to make sure the datatype is registered + renderDataProvider = provider; assertContainerTypeConfigCorrect(); this.viewDistance = viewDistance; @@ -260,9 +258,6 @@ public abstract class LodQuadTree { public int getFurthestDistance(byte detailLevel) { return (int)Math.ceil(DetailDistanceUtil.getDrawDistanceFromDetail(detailLevel)); } - - public abstract RenderDataProvider getRenderDataProvider(); - /** * Given a section pos at level n this method returns the parent section at level n+1 @@ -295,10 +290,6 @@ public abstract class LodQuadTree { LodSection::dispose); } - - - - // First tick pass: update all sections' childCount from bottom level to top level. Step: // If sectLevel is bottom && section != null: // - set childCount to 0 @@ -473,7 +464,7 @@ public abstract class LodQuadTree { section.dispose(); } else { if (!section.isLoaded() && !section.isLoading()) { - section.load(getRenderDataProvider(), containerType); + section.load(renderDataProvider, containerType); } if (section.childCount == 4) section.enableRender(this); if (section.childCount == 0) section.disableRender(); diff --git a/src/main/java/com/seibel/lod/core/a7/data/DataFileHandler.java b/src/main/java/com/seibel/lod/core/a7/data/DataFileHandler.java deleted file mode 100644 index 9d0d9ab89..000000000 --- a/src/main/java/com/seibel/lod/core/a7/data/DataFileHandler.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.seibel.lod.core.a7.data; - -import com.google.common.collect.HashMultimap; -import com.seibel.lod.core.a7.RenderDataProvider; -import com.seibel.lod.core.a7.level.DHLevel; -import com.seibel.lod.core.a7.datatype.column.DataSourceSaver; -import com.seibel.lod.core.a7.pos.DhSectionPos; -import com.seibel.lod.core.a7.render.RenderDataSource; -import com.seibel.lod.core.a7.render.RenderDataSourceLoader; -import com.seibel.lod.core.util.LodUtil; - -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -public class DataFileHandler implements RenderDataProvider, Closeable { - public static final List CONVERTERS = new ArrayList<>(); - public static final String FILE_EXTENSION = ".lod"; - - public final DHLevel level; - - public final File folder; - // A hash map of all data files. - - public final ExecutorService IO_MANAGER = LodUtil.makeSingleThreadPool("DataFileHandler IO Manager"); - - private byte maxDataLevel = 0; - - private final HashMultimap dataFiles; - - public static final String[] FoldersToScan = { - "data", - }; // TODO: Add more folders to scan - - public DataFileHandler(File folderPath, DHLevel level) { - this.folder = folderPath; - this.level = level; - dataFiles = HashMultimap.create(); - // Handle converting old files that doesn't have the meta data and stuff - List oldFiles = new ArrayList<>(); - for (OldFileConverter converter : CONVERTERS) oldFiles.addAll(converter.scanAndConvert(folder, level)); - oldFiles.forEach(this::_addFile); - - // Scan for files - File[] foldersToScan = new File[FoldersToScan.length + 1]; - for (int i = 0; i < FoldersToScan.length; i++) { - foldersToScan[i] = new File(folder, FoldersToScan[i]); - } - foldersToScan[FoldersToScan.length] = folder; - scanFiles(foldersToScan); - } - private List[] getFilesInPos(DhSectionPos pos) { - List[] files = new LinkedList[maxDataLevel + 1]; - for (DhSectionPos p : dataFiles.keySet()) { - if (p.overlaps(pos)) { - for (DataFile f : dataFiles.get(p)) { - files[f.dataLevel].add(f); - } - } - } - return files; - } - private void _addFile(DataFile file) { - if (dataFiles.containsKey(file.pos)) { - Set fileSet = dataFiles.get(file.pos); - if (fileSet.stream().anyMatch(f -> f.dataType.equals(file.dataType))) { - // A file with the same type and same position already exists - // TODO: Handle this case - return; - } - } - maxDataLevel = LodUtil.max(maxDataLevel, file.dataLevel); - dataFiles.put(file.pos, file); - } - - public void scanFiles(File[] foldersToScan) { - // Scan all files in the folder and read their metadata - for (File folder : foldersToScan) { - if (!folder.exists() || !folder.isDirectory()) continue; - File[] files = folder.listFiles(); - if (files == null) throw new RuntimeException("Could not list files in folder: " + folder.getAbsolutePath()); - - for (File file : files) { - if (file.isFile()) { - String fileName = file.getName(); - if (fileName.endsWith(FILE_EXTENSION)) { - DataFile dataFile; - try { - dataFile = DataFile.readMeta(file); - } catch (IOException e) { - // FIXME: Log error - continue; - } - _addFile(dataFile); - } - } - } - } - } - - public DataFile registerNewLodDataSource(LodDataSource dataSource, DataSourceSaver saver) { - DhSectionPos pos = dataSource.getSectionPos(); - File newFile = saver.generateFilePathAndName(folder, level, pos); - if (!newFile.getName().endsWith(FILE_EXTENSION)) { - //TODO: Log warning - newFile = new File(newFile.getParentFile(), newFile.getName() + FILE_EXTENSION); - } - - if (newFile.exists()) { - //TODO: Log warning - String fileStr = newFile.getPath().substring(0, newFile.getPath().length() - FILE_EXTENSION.length()); - int i = 1; - do { - newFile = new File(fileStr + "_" + i + FILE_EXTENSION); - i++; - } while (newFile.exists()); - } - DataFile dataFile = new DataFile(newFile, saver, dataSource); - dataFiles.put(pos, dataFile); - try { - dataFile.save(level, false); - } catch (Exception e) { - dataFiles.remove(pos, dataFile); - //TODO: Log error - return null; - } - return dataFile; - } - - - @Override - public CompletableFuture createRenderData(RenderDataSourceLoader renderSourceLoader, DhSectionPos pos) { - return CompletableFuture.supplyAsync(() -> { - List files = renderSourceLoader.selectFiles(pos, level, getFilesInPos(pos)); - List dataSource = files.stream().map(f -> f.load(level)).filter(Objects::nonNull).collect(Collectors.toList()); - return renderSourceLoader.construct(dataSource, pos, level); - }); - } - - @Override - public void close() { - IO_MANAGER.shutdown(); - try { - IO_MANAGER.awaitTermination(10, TimeUnit.SECONDS); - } catch (InterruptedException ignored) {} - dataFiles.values().forEach((f) -> f.close(level)); - } - - public void save() { - //TODO: Make it free memory that is not needed - dataFiles.values().forEach(f -> f.saveIfNeeded(level, false)); - } -} diff --git a/src/main/java/com/seibel/lod/core/a7/data/DataSourceLoader.java b/src/main/java/com/seibel/lod/core/a7/data/DataSourceLoader.java index a8b31ac10..4422d1ad3 100644 --- a/src/main/java/com/seibel/lod/core/a7/data/DataSourceLoader.java +++ b/src/main/java/com/seibel/lod/core/a7/data/DataSourceLoader.java @@ -1,8 +1,9 @@ package com.seibel.lod.core.a7.data; import com.google.common.collect.HashMultimap; -import com.seibel.lod.core.a7.level.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import com.seibel.lod.core.a7.io.file.DataMetaFile; +import com.seibel.lod.core.a7.level.ILevel; import java.io.File; import java.io.IOException; @@ -44,7 +45,7 @@ public abstract class DataSourceLoader { } // Can return null as meaning the requirement is not met - public abstract LodDataSource loadData(DataMetaFile dataFile, InputStream data, DHLevel level) throws IOException; + public abstract LodDataSource loadData(DataMetaFile dataFile, InputStream data, ILevel level) throws IOException; public List foldersToScan(File levelFolderPath) { return Collections.emptyList(); diff --git a/src/main/java/com/seibel/lod/core/a7/data/OldFileConverter.java b/src/main/java/com/seibel/lod/core/a7/data/OldFileConverter.java index d2cde00a6..d14668a29 100644 --- a/src/main/java/com/seibel/lod/core/a7/data/OldFileConverter.java +++ b/src/main/java/com/seibel/lod/core/a7/data/OldFileConverter.java @@ -1,10 +1,10 @@ package com.seibel.lod.core.a7.data; -import com.seibel.lod.core.a7.level.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import java.io.File; import java.util.List; public interface OldFileConverter { - List scanAndConvert(File levelFolder, DHLevel level); + List scanAndConvert(File levelFolder, DhClientServerLevel level); } diff --git a/src/main/java/com/seibel/lod/core/a7/datatype/column/Alpha6DataLoader.java b/src/main/java/com/seibel/lod/core/a7/datatype/column/Alpha6DataLoader.java index 4e0651f86..f4b9b6167 100644 --- a/src/main/java/com/seibel/lod/core/a7/datatype/column/Alpha6DataLoader.java +++ b/src/main/java/com/seibel/lod/core/a7/datatype/column/Alpha6DataLoader.java @@ -5,7 +5,7 @@ import com.seibel.lod.core.a7.data.LodDataSource; import com.seibel.lod.core.a7.data.OldFileConverter; import com.seibel.lod.core.a7.pos.DhSectionPos; import com.seibel.lod.core.enums.config.EVerticalQuality; -import com.seibel.lod.core.a7.level.DHLevel; +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 org.apache.commons.compress.compressors.xz.XZCompressorInputStream; @@ -24,7 +24,7 @@ public class Alpha6DataLoader extends OldDataSourceLoader implements OldFileConv } @Override - public LodDataSource loadData(DataMetaFile dataFile, InputStream data, DHLevel level) { + public LodDataSource loadData(DataMetaFile dataFile, InputStream data, DhClientServerLevel level) { //TODO: Add decompressor here try ( XZCompressorInputStream xzIn = new XZCompressorInputStream(data); @@ -70,7 +70,7 @@ public class Alpha6DataLoader extends OldDataSourceLoader implements OldFileConv } @Override - public List scanAndConvert(File levelFolder, DHLevel level) { + public List scanAndConvert(File levelFolder, DhClientServerLevel level) { List files = new ArrayList<>(); diff --git a/src/main/java/com/seibel/lod/core/a7/datatype/column/ColumnDataLoader.java b/src/main/java/com/seibel/lod/core/a7/datatype/column/ColumnDataLoader.java index 06293ba86..ab2d75001 100644 --- a/src/main/java/com/seibel/lod/core/a7/datatype/column/ColumnDataLoader.java +++ b/src/main/java/com/seibel/lod/core/a7/datatype/column/ColumnDataLoader.java @@ -6,7 +6,7 @@ import com.seibel.lod.core.a7.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.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import com.seibel.lod.core.a7.io.file.DataMetaFile; import java.io.*; @@ -22,7 +22,7 @@ public class ColumnDataLoader extends DataSourceSaver { } @Override - public LodDataSource loadData(DataMetaFile dataFile, InputStream data, DHLevel level) { + public LodDataSource loadData(DataMetaFile dataFile, InputStream data, DhClientServerLevel level) { try ( //TODO: Add decompressor here DataInputStream dis = new DataInputStream(data); @@ -35,7 +35,7 @@ public class ColumnDataLoader extends DataSourceSaver { } @Override - public void saveData(DHLevel level, LodDataSource loadedData, MetaFile file, OutputStream out) throws IOException { + public void saveData(DhClientServerLevel level, LodDataSource loadedData, MetaFile file, OutputStream out) throws IOException { //TODO: Add compressor here try (DataOutputStream dos = new DataOutputStream(out)) { ((ColumnDatatype) loadedData).writeData(dos); @@ -43,7 +43,7 @@ public class ColumnDataLoader extends DataSourceSaver { } @Override - public File generateFilePathAndName(File levelFolderPath, DHLevel level, DhSectionPos sectionPos) { + public File generateFilePathAndName(File levelFolderPath, DhClientServerLevel level, DhSectionPos sectionPos) { return generateFilePathAndName(levelFolderPath, sectionPos, Config.Client.Graphics.Quality.verticalQuality.get()); } diff --git a/src/main/java/com/seibel/lod/core/a7/datatype/column/ColumnDatatype.java b/src/main/java/com/seibel/lod/core/a7/datatype/column/ColumnDatatype.java index eeacbb0b8..208bb2d2a 100644 --- a/src/main/java/com/seibel/lod/core/a7/datatype/column/ColumnDatatype.java +++ b/src/main/java/com/seibel/lod/core/a7/datatype/column/ColumnDatatype.java @@ -5,7 +5,7 @@ import com.seibel.lod.core.a7.pos.DhSectionPos; import com.seibel.lod.core.a7.render.RenderBuffer; import com.seibel.lod.core.enums.ELodDirection; import com.seibel.lod.core.objects.LodDataView; -import com.seibel.lod.core.a7.level.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import com.seibel.lod.core.a7.LodQuadTree; import com.seibel.lod.core.a7.LodSection; import com.seibel.lod.core.a7.render.RenderDataSource; @@ -70,7 +70,7 @@ public class ColumnDatatype implements RenderDataSource, IColumnDatatype { return result; } // Load from data stream with maxVerticalSize loaded from the data stream - public ColumnDatatype(DhSectionPos sectionPos, DataInputStream inputData, int version, DHLevel level) throws IOException { + public ColumnDatatype(DhSectionPos sectionPos, DataInputStream inputData, int version, DhClientServerLevel level) throws IOException { this.sectionPos = sectionPos; yOffset = level.getMinY(); byte detailLevel = inputData.readByte(); diff --git a/src/main/java/com/seibel/lod/core/a7/datatype/column/ColumnRenderLoader.java b/src/main/java/com/seibel/lod/core/a7/datatype/column/ColumnRenderLoader.java index 0b2ba37eb..dbaccc082 100644 --- a/src/main/java/com/seibel/lod/core/a7/datatype/column/ColumnRenderLoader.java +++ b/src/main/java/com/seibel/lod/core/a7/datatype/column/ColumnRenderLoader.java @@ -5,7 +5,7 @@ import com.seibel.lod.core.a7.datatype.full.FullDatatype; import com.seibel.lod.core.a7.pos.DhSectionPos; import com.seibel.lod.core.a7.render.RenderDataSource; import com.seibel.lod.core.a7.render.RenderDataSourceLoader; -import com.seibel.lod.core.a7.level.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import com.seibel.lod.core.objects.a7.data.DataFile; import com.seibel.lod.core.util.DetailDistanceUtil; import com.seibel.lod.core.util.LodUtil; @@ -21,7 +21,7 @@ class ColumnRenderLoader extends RenderDataSourceLoader { } @Override - public RenderDataSource construct(List dataSources, DhSectionPos sectionPos, DHLevel level) { + public RenderDataSource construct(List dataSources, DhSectionPos sectionPos, DhClientServerLevel level) { if (dataSources.size() == 0) return null; // Check for direct casting @@ -111,7 +111,7 @@ class ColumnRenderLoader extends RenderDataSourceLoader { } @Override - public List selectFiles(DhSectionPos sectionPos, DHLevel level, List[] availableFiles) { + public List selectFiles(DhSectionPos sectionPos, DhClientServerLevel level, List[] availableFiles) { byte targetDataLevel = (byte) (sectionPos.sectionDetail - ColumnDatatype.SECTION_SIZE_OFFSET); //No support for loading higher than the target level yet. byte maxDataLevel = LodUtil.min((byte) (availableFiles.length - 1), targetDataLevel); diff --git a/src/main/java/com/seibel/lod/core/a7/datatype/column/DataSourceSaver.java b/src/main/java/com/seibel/lod/core/a7/datatype/column/DataSourceSaver.java index fd2c6c14b..5d63803dd 100644 --- a/src/main/java/com/seibel/lod/core/a7/datatype/column/DataSourceSaver.java +++ b/src/main/java/com/seibel/lod/core/a7/datatype/column/DataSourceSaver.java @@ -4,8 +4,9 @@ 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.level.ILevel; import com.seibel.lod.core.a7.pos.DhSectionPos; -import com.seibel.lod.core.a7.level.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import java.io.File; import java.io.IOException; @@ -16,10 +17,10 @@ public abstract class DataSourceSaver extends DataSourceLoader { super(clazz, datatypeId, loaderSupportedVersions); } - public abstract void saveData(DHLevel level, LodDataSource loadedData, MetaFile file, OutputStream dataStream) throws IOException; + public abstract void saveData(ILevel level, LodDataSource loadedData, MetaFile file, OutputStream dataStream) throws IOException; // generate the default file path and file name based on various parameters. // Ensure the file extension is '.lod'! - public File generateFilePathAndName(File levelFolderPath, DHLevel level, DhSectionPos sectionPos) { + public File generateFilePathAndName(File levelFolderPath, DhClientServerLevel level, DhSectionPos sectionPos) { return new File(levelFolderPath, String.format("%s_v%d-%s%s", clazz.getSimpleName(), getSaverVersion(), sectionPos.serialize(), DataFileHandler.FILE_EXTENSION)); } diff --git a/src/main/java/com/seibel/lod/core/a7/datatype/column/OldColumnDatatype.java b/src/main/java/com/seibel/lod/core/a7/datatype/column/OldColumnDatatype.java index 1495f6888..5178616d8 100644 --- a/src/main/java/com/seibel/lod/core/a7/datatype/column/OldColumnDatatype.java +++ b/src/main/java/com/seibel/lod/core/a7/datatype/column/OldColumnDatatype.java @@ -3,7 +3,7 @@ package com.seibel.lod.core.a7.datatype.column; import com.seibel.lod.core.a7.data.DataSourceLoader; import com.seibel.lod.core.a7.pos.DhSectionPos; import com.seibel.lod.core.objects.LodDataView; -import com.seibel.lod.core.a7.level.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import java.io.DataInputStream; import java.io.IOException; @@ -54,7 +54,7 @@ public class OldColumnDatatype implements IColumnDatatype { } // Load from data stream with maxVerticalSize loaded from the data stream - public OldColumnDatatype(DhSectionPos sectionPos, DataInputStream inputData, int version, DHLevel level, int sectionSizeOffset) throws IOException { + public OldColumnDatatype(DhSectionPos sectionPos, DataInputStream inputData, int version, DhClientServerLevel level, int sectionSizeOffset) throws IOException { this.sectionSizeOffset = (byte) sectionSizeOffset; this.sectionPos = sectionPos; yOffset = level.getMinY(); diff --git a/src/main/java/com/seibel/lod/core/a7/io/LevelToFileMatcher.java b/src/main/java/com/seibel/lod/core/a7/io/LevelToFileMatcher.java index e8d71e941..ccfc95021 100644 --- a/src/main/java/com/seibel/lod/core/a7/io/LevelToFileMatcher.java +++ b/src/main/java/com/seibel/lod/core/a7/io/LevelToFileMatcher.java @@ -1,24 +1,15 @@ package com.seibel.lod.core.a7.io; import com.seibel.lod.core.a7.world.DhClientWorld; -import com.seibel.lod.core.api.internal.InternalApiShared; import com.seibel.lod.core.builders.lodBuilding.LodBuilder; -import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig; import com.seibel.lod.core.config.Config; -import com.seibel.lod.core.enums.config.EDistanceGenerationMode; -import com.seibel.lod.core.enums.config.EVerticalQuality; -import com.seibel.lod.core.handlers.LodDimensionFileHandler; import com.seibel.lod.core.handlers.LodDimensionFinder; import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; import com.seibel.lod.core.handlers.dimensionFinder.PlayerData; import com.seibel.lod.core.handlers.dimensionFinder.SubDimCompare; import com.seibel.lod.core.logging.ConfigBasedLogger; import com.seibel.lod.core.objects.DHChunkPos; -import com.seibel.lod.core.objects.DHRegionPos; -import com.seibel.lod.core.a7.level.DHLevel; -import com.seibel.lod.core.objects.lod.LodDimension; -import com.seibel.lod.core.objects.lod.LodRegion; -import com.seibel.lod.core.util.DataPointUtil; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import com.seibel.lod.core.util.LodUtil; import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; @@ -46,7 +37,7 @@ public class LevelToFileMatcher implements AutoCloseable { private final AtomicBoolean determiningWorldFolder = new AtomicBoolean(false); private final ILevelWrapper currentLevel; private final DhClientWorld world; - private volatile DHLevel foundLevel = null; + private volatile DhClientServerLevel foundLevel = null; private final File[] potentialFiles; private final File levelsFolder; @@ -60,12 +51,12 @@ public class LevelToFileMatcher implements AutoCloseable { 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 DHLevel(world, folder, targetWorld); + foundLevel = new DhClientServerLevel(world, folder, targetWorld); } } // May return null, where at this moment the level is not yet known - public DHLevel tryGetLevel() { + public DhClientServerLevel tryGetLevel() { tick(); return foundLevel; } @@ -84,7 +75,7 @@ public class LevelToFileMatcher implements AutoCloseable { // attempt to get the file handler File saveDir = attemptToDetermineSubDimensionFolder(); if (saveDir == null) return; - foundLevel = new DHLevel(world, saveDir, currentLevel); + foundLevel = new DhClientServerLevel(world, saveDir, currentLevel); } catch (IOException e) { LOGGER.error("Unable to set the dimension file handler for level [" + currentLevel + "]. Error: ", e); } finally { diff --git a/src/main/java/com/seibel/lod/core/a7/io/file/DataMetaFile.java b/src/main/java/com/seibel/lod/core/a7/io/file/DataMetaFile.java index 1b6a3f3b3..38865b196 100644 --- a/src/main/java/com/seibel/lod/core/a7/io/file/DataMetaFile.java +++ b/src/main/java/com/seibel/lod/core/a7/io/file/DataMetaFile.java @@ -15,9 +15,11 @@ 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.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.DHLevel; +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; @@ -26,7 +28,7 @@ import org.apache.logging.log4j.Logger; public class DataMetaFile extends MetaFile { public static Logger LOGGER = DhLoggerBuilder.getLogger("FileMetadata"); - private final DHLevel level; + private final ILevel level; AtomicInteger localVersion = new AtomicInteger(); // This MUST be atomic // The '?' type should either be: @@ -72,13 +74,13 @@ public class DataMetaFile extends MetaFile { } // Load a metaFile in this path. It also automatically read the metadata. - public DataMetaFile(DHLevel level, File path) throws IOException { + public DataMetaFile(ILevel level, File path) throws IOException { super(path); this.level = level; } // Make a new MetaFile. It doesn't load or write any metadata itself. - public DataMetaFile(DHLevel level, File path, DhSectionPos pos) { + public DataMetaFile(ILevel level, File path, DhSectionPos pos) { super(path, pos); this.level = level; } diff --git a/src/main/java/com/seibel/lod/core/a7/io/file/DataSourceProvider.java b/src/main/java/com/seibel/lod/core/a7/io/file/DataSourceProvider.java index f5b615c02..58b8fec6c 100644 --- a/src/main/java/com/seibel/lod/core/a7/io/file/DataSourceProvider.java +++ b/src/main/java/com/seibel/lod/core/a7/io/file/DataSourceProvider.java @@ -6,7 +6,7 @@ import com.seibel.lod.core.a7.pos.DhSectionPos; import java.util.concurrent.CompletableFuture; -public interface DataSourceProvider { +public interface DataSourceProvider extends AutoCloseable { CompletableFuture read(DhSectionPos pos); void write(DhSectionPos sectionPos, FullDatatype chunkData); CompletableFuture flushAndSave(); diff --git a/src/main/java/com/seibel/lod/core/a7/io/file/LocalDataFileHandler.java b/src/main/java/com/seibel/lod/core/a7/io/file/LocalDataFileHandler.java index 3acbc4869..9696ccece 100644 --- a/src/main/java/com/seibel/lod/core/a7/io/file/LocalDataFileHandler.java +++ b/src/main/java/com/seibel/lod/core/a7/io/file/LocalDataFileHandler.java @@ -3,9 +3,10 @@ package com.seibel.lod.core.a7.io.file; import com.google.common.collect.HashMultimap; import com.seibel.lod.core.a7.data.LodDataSource; 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.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import com.seibel.lod.core.util.LodUtil; import org.apache.logging.log4j.Logger; @@ -29,8 +30,8 @@ public class LocalDataFileHandler implements DataSourceProvider { boolean isScanned = false; File saveDir; - final DHLevel level; - public LocalDataFileHandler(DHLevel level, File saveRootDir) { + final IServerLevel level; + public LocalDataFileHandler(IServerLevel level, File saveRootDir) { this.saveDir = saveRootDir; this.level = level; } @@ -144,4 +145,9 @@ public class LocalDataFileHandler implements DataSourceProvider { private File computeDefaultFilePath(DhSectionPos pos) { //TODO: Temp code as we haven't decided on the file naming & location yet. return new File(saveDir, pos.serialize() + ".lod"); } + + @Override + public void close() { + //TODO + } } diff --git a/src/main/java/com/seibel/lod/core/a7/io/file/RemoteDataFileHandler.java b/src/main/java/com/seibel/lod/core/a7/io/file/RemoteDataFileHandler.java new file mode 100644 index 000000000..b0b1b8eed --- /dev/null +++ b/src/main/java/com/seibel/lod/core/a7/io/file/RemoteDataFileHandler.java @@ -0,0 +1,29 @@ +package com.seibel.lod.core.a7.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.util.concurrent.CompletableFuture; + +public class RemoteDataFileHandler implements DataSourceProvider { + @Override + public CompletableFuture read(DhSectionPos pos) { + return null; + } + + @Override + public void write(DhSectionPos sectionPos, FullDatatype chunkData) { + + } + + @Override + public CompletableFuture flushAndSave() { + return null; + } + + @Override + public void close() throws Exception { + + } +} diff --git a/src/main/java/com/seibel/lod/core/a7/io/render/RenderFileHandler.java b/src/main/java/com/seibel/lod/core/a7/io/render/RenderFileHandler.java index a9063b284..3ed788f0e 100644 --- a/src/main/java/com/seibel/lod/core/a7/io/render/RenderFileHandler.java +++ b/src/main/java/com/seibel/lod/core/a7/io/render/RenderFileHandler.java @@ -14,7 +14,7 @@ import java.io.File; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; -public class RenderFileHandler implements RenderDataProvider { +public class RenderFileHandler implements RenderSourceProvider { final File renderCacheFolder; final DataSourceProvider dataSourceProvider; ExecutorService renderCacheThread = LodUtil.makeSingleThreadPool("RenderCacheThread"); @@ -30,11 +30,18 @@ public class RenderFileHandler implements RenderDataProvider { return null; } - public CompletableFuture read(DhSectionPos pos) { + @Override + public void write(DhSectionPos sectionPos, FullDatatype chunkData) { + + } + + @Override + public CompletableFuture flushAndSave() { return null; } - public void write(DhSectionPos sectionPos, FullDatatype chunkData) { - ` + @Override + public void close() { + } } diff --git a/src/main/java/com/seibel/lod/core/a7/io/render/RenderSourceProvider.java b/src/main/java/com/seibel/lod/core/a7/io/render/RenderSourceProvider.java index 17946860c..1781e7747 100644 --- a/src/main/java/com/seibel/lod/core/a7/io/render/RenderSourceProvider.java +++ b/src/main/java/com/seibel/lod/core/a7/io/render/RenderSourceProvider.java @@ -1,14 +1,12 @@ package com.seibel.lod.core.a7.io.render; -import com.seibel.lod.core.a7.data.LodDataSource; +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 com.seibel.lod.core.a7.render.RenderDataSource; import java.util.concurrent.CompletableFuture; -public interface RenderSourceProvider { - CompletableFuture get(DhSectionPos pos); +public interface RenderSourceProvider extends RenderDataProvider, AutoCloseable { void write(DhSectionPos sectionPos, FullDatatype chunkData); CompletableFuture flushAndSave(); } diff --git a/src/main/java/com/seibel/lod/core/a7/level/DHLevel.java b/src/main/java/com/seibel/lod/core/a7/level/DHLevel.java deleted file mode 100644 index dbec7dc16..000000000 --- a/src/main/java/com/seibel/lod/core/a7/level/DHLevel.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.seibel.lod.core.a7.level; - -import com.seibel.lod.core.a7.world.DhWorld; -import com.seibel.lod.core.a7.LodQuadTree; -import com.seibel.lod.core.a7.RenderDataProvider; -import com.seibel.lod.core.a7.data.DataFileHandler; -import com.seibel.lod.core.a7.pos.DhBlockPos2D; -import com.seibel.lod.core.a7.render.RenderBufferHandler; -import com.seibel.lod.core.config.Config; -import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; -import com.seibel.lod.core.objects.math.Mat4f; -import com.seibel.lod.core.render.a7LodRenderer; -import com.seibel.lod.core.util.EventLoop; -import com.seibel.lod.core.util.LodUtil; -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.io.Closeable; -import java.io.File; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicBoolean; - -public class DHLevel extends LodQuadTree implements Closeable { - private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class); - public final File saveFolder; // Could be null, for no saving - public final DataFileHandler dataFileHandler; // Could be null, for no saving - public final RenderBufferHandler renderBufferHandler; - public final ExecutorService dhTickerThread = LodUtil.makeSingleThreadPool("DHLevelTickerThread", 2); - private final AtomicBoolean isRunning = new AtomicBoolean(false); - public final ILevelWrapper level; - public a7LodRenderer renderer; - public final DhWorld world; - public EventLoop eventLoop; - - public DHLevel(DhWorld world, File saveFolder, ILevelWrapper level) { - super(Config.Client.Graphics.Quality.lodChunkRenderDistance.get()*16, - MC.getPlayerBlockPos().x, - MC.getPlayerBlockPos().z); - this.world = world; - this.saveFolder = saveFolder; - if (saveFolder != null) { - dataFileHandler = new DataFileHandler(saveFolder, this); - } else { - dataFileHandler = null; - } - renderBufferHandler = new RenderBufferHandler(this); - this.level = level; - eventLoop = new EventLoop(world.dhTickerThread, this::tick); - } - - // Should be called by server tick thread, or called by render thread but only 20 times per second, or less? - public void update() { - - if (!isRunning.getAndSet(true)) { - dhTickerThread.submit(() -> { - try { - tick(); - } catch (Exception e) { - e.printStackTrace(); - } finally { - isRunning.set(false); - } - }); - } - } - - private void tick() { - super.tick(new DhBlockPos2D(MC.getPlayerBlockPos())); - renderBufferHandler.update(); - } - - @Override - public RenderDataProvider getRenderDataProvider() { - return dataFileHandler; - } - - public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) { - if (renderer == null) { - renderer = new a7LodRenderer(this); - } - renderer.drawLODs(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); - } - - public int getMinY() { - return level.getMinHeight(); - } - public void dumpRamUsage() { - //TODO - } - public void asyncTick() { - eventLoop.tick(); - } - public void close() { - eventLoop.halt(); - if (dataFileHandler != null) { - dataFileHandler.close(); - } - } - public void saveFlush() { - if (dataFileHandler != null) { - dataFileHandler.save(); - } - } -} diff --git a/src/main/java/com/seibel/lod/core/a7/level/DhClientLevel.java b/src/main/java/com/seibel/lod/core/a7/level/DhClientLevel.java new file mode 100644 index 000000000..c9c972883 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/a7/level/DhClientLevel.java @@ -0,0 +1,88 @@ +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.pos.DhBlockPos2D; +import com.seibel.lod.core.a7.render.RenderBufferHandler; +import com.seibel.lod.core.a7.save.structure.ClientOnlySaveStructure; +import com.seibel.lod.core.config.Config; +import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; +import com.seibel.lod.core.objects.math.Mat4f; +import com.seibel.lod.core.render.a7LodRenderer; +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.concurrent.CompletableFuture; + +public class DhClientLevel implements IClientLevel { + private static final IMinecraftClientWrapper MC_CLIENT = SingletonHandler.get(IMinecraftClientWrapper.class); + public final ClientOnlySaveStructure save; + public final RemoteDataFileHandler dataFileHandler; + public final RenderFileHandler renderFileHandler; + public final RenderBufferHandler renderBufferHandler; //TODO: Should this be owned by renderer? + public final ILevelWrapper level; + public a7LodRenderer renderer = null; + public LodQuadTree tree; + + public DhClientLevel(ClientOnlySaveStructure save, ILevelWrapper level) { + this.save = save; + dataFileHandler = new RemoteDataFileHandler(); + renderFileHandler = new RenderFileHandler(dataFileHandler, save.getRenderCacheFolder(level)); + tree = new LodQuadTree(Config.Client.Graphics.Quality.lodChunkRenderDistance.get()*16, + MC_CLIENT.getPlayerBlockPos().x, MC_CLIENT.getPlayerBlockPos().z, renderFileHandler); + renderBufferHandler = new RenderBufferHandler(tree); + this.level = level; + } + + public void tick() { + tree.tick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos())); + renderBufferHandler.update(); + } + + @Override + public void dumpRamUsage() { + //TODO + } + + @Override + public void startRenderer() { + //TODO + + } + + @Override + public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) { + if (renderer == null) { + renderer = new a7LodRenderer(this); + } + renderer.drawLODs(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); + } + + @Override + public void stopRenderer() { + //TODO + + } + + @Override + public RenderBufferHandler getRenderBufferHandler() { + return renderBufferHandler; + } + + @Override + public int getMinY() { + return level.getMinHeight(); + } + + @Override + public CompletableFuture save() { + return renderFileHandler.flushAndSave(); + } + + @Override + public void close() { + renderFileHandler.close(); + } +} diff --git a/src/main/java/com/seibel/lod/core/a7/level/DhClientServerLevel.java b/src/main/java/com/seibel/lod/core/a7/level/DhClientServerLevel.java new file mode 100644 index 000000000..9b6fe778c --- /dev/null +++ b/src/main/java/com/seibel/lod/core/a7/level/DhClientServerLevel.java @@ -0,0 +1,89 @@ +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.pos.DhBlockPos2D; +import com.seibel.lod.core.a7.render.RenderBufferHandler; +import com.seibel.lod.core.a7.save.structure.LocalSaveStructure; +import com.seibel.lod.core.config.Config; +import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; +import com.seibel.lod.core.objects.math.Mat4f; +import com.seibel.lod.core.render.a7LodRenderer; +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.concurrent.CompletableFuture; + +public class DhClientServerLevel implements IClientLevel, IServerLevel { + private static final IMinecraftClientWrapper MC_CLIENT = SingletonHandler.get(IMinecraftClientWrapper.class); + public final LocalSaveStructure save; + public final LocalDataFileHandler dataFileHandler; + public final RenderFileHandler renderFileHandler; + public final RenderBufferHandler renderBufferHandler; //TODO: Should this be owned by renderer? + public final ILevelWrapper level; + public a7LodRenderer renderer = null; + public LodQuadTree tree; + + public DhClientServerLevel(LocalSaveStructure save, ILevelWrapper level) { + this.level = level; + this.save = save; + dataFileHandler = new LocalDataFileHandler(this, save.getDataFolder(level)); + renderFileHandler = new RenderFileHandler(dataFileHandler, save.getRenderCacheFolder(level)); + tree = new LodQuadTree(Config.Client.Graphics.Quality.lodChunkRenderDistance.get()*16, + MC_CLIENT.getPlayerBlockPos().x, MC_CLIENT.getPlayerBlockPos().z, renderFileHandler); + renderBufferHandler = new RenderBufferHandler(tree); + } + + public void tick() { + tree.tick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos())); + renderBufferHandler.update(); + } + + @Override + public void startRenderer() { + //TODO + } + + @Override + public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) { + if (renderer == null) { + renderer = new a7LodRenderer(this); + } + renderer.drawLODs(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler); + } + + @Override + public void stopRenderer() { + renderFileHandler.flushAndSave(); //Ignore the completion feature so that this action is async + //TODO + } + + @Override + public RenderBufferHandler getRenderBufferHandler() { + return renderBufferHandler; + } + + @Override + public void dumpRamUsage() { + //TODO + } + + @Override + public int getMinY() { + return level.getMinHeight(); + } + + @Override + public CompletableFuture save() { + return renderFileHandler.flushAndSave(); + //Note: saving renderFileHandler will also save the dataFileHandler. + } + + @Override + public void close() { + renderFileHandler.close(); + //Note: Closing renderFileHandler will also close the dataFileHandler. + } +} diff --git a/src/main/java/com/seibel/lod/core/a7/level/DhServerLevel.java b/src/main/java/com/seibel/lod/core/a7/level/DhServerLevel.java new file mode 100644 index 000000000..1d2736c89 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/a7/level/DhServerLevel.java @@ -0,0 +1,41 @@ +package com.seibel.lod.core.a7.level; + +import com.seibel.lod.core.a7.io.file.LocalDataFileHandler; +import com.seibel.lod.core.a7.save.structure.LocalSaveStructure; +import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper; + +import java.util.concurrent.CompletableFuture; + +public class DhServerLevel implements IServerLevel { + public final LocalSaveStructure save; + public final LocalDataFileHandler dataFileHandler; + public final ILevelWrapper level; + + public DhServerLevel(LocalSaveStructure save, ILevelWrapper level) { + this.save = save; + this.level = level; + dataFileHandler = new LocalDataFileHandler(this, save.getDataFolder(level)); + } + + public void tick() { + //Nothing for now + } + + @Override + public int getMinY() { + return level.getMinHeight(); + } + + @Override + public void dumpRamUsage() { + //TODO + } + @Override + public void close() { + dataFileHandler.close(); + } + @Override + public CompletableFuture save() { + return dataFileHandler.flushAndSave(); + } +} diff --git a/src/main/java/com/seibel/lod/core/a7/level/IClientLevel.java b/src/main/java/com/seibel/lod/core/a7/level/IClientLevel.java new file mode 100644 index 000000000..18dd695da --- /dev/null +++ b/src/main/java/com/seibel/lod/core/a7/level/IClientLevel.java @@ -0,0 +1,14 @@ +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; + +public interface IClientLevel extends ILevel { + void startRenderer(); + void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler); + void stopRenderer(); + + RenderBufferHandler getRenderBufferHandler(); +} diff --git a/src/main/java/com/seibel/lod/core/a7/level/ILevel.java b/src/main/java/com/seibel/lod/core/a7/level/ILevel.java new file mode 100644 index 000000000..b3bfe8dd2 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/a7/level/ILevel.java @@ -0,0 +1,10 @@ +package com.seibel.lod.core.a7.level; + +import java.util.concurrent.CompletableFuture; + +public interface ILevel extends AutoCloseable { + int getMinY(); + CompletableFuture save(); + + void dumpRamUsage(); +} diff --git a/src/main/java/com/seibel/lod/core/a7/level/IServerLevel.java b/src/main/java/com/seibel/lod/core/a7/level/IServerLevel.java new file mode 100644 index 000000000..dc379ff00 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/a7/level/IServerLevel.java @@ -0,0 +1,4 @@ +package com.seibel.lod.core.a7.level; + +public interface IServerLevel extends ILevel { +} diff --git a/src/main/java/com/seibel/lod/core/a7/render/RenderDataSourceLoader.java b/src/main/java/com/seibel/lod/core/a7/render/RenderDataSourceLoader.java index 64efa9bb4..90dc8e8fa 100644 --- a/src/main/java/com/seibel/lod/core/a7/render/RenderDataSourceLoader.java +++ b/src/main/java/com/seibel/lod/core/a7/render/RenderDataSourceLoader.java @@ -2,7 +2,7 @@ package com.seibel.lod.core.a7.render; import com.seibel.lod.core.a7.data.LodDataSource; import com.seibel.lod.core.a7.pos.DhSectionPos; -import com.seibel.lod.core.a7.level.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import com.seibel.lod.core.a7.data.DataFile; import java.util.*; @@ -14,9 +14,9 @@ public abstract class RenderDataSourceLoader { this.detailOffset = detailOffset; } - public abstract RenderDataSource construct(List dataSources, DhSectionPos sectionPos, DHLevel level); + public abstract RenderDataSource construct(List dataSources, DhSectionPos sectionPos, DhClientServerLevel level); - public List selectFiles(DhSectionPos sectionPos, DHLevel level, List[] availableFiles) { + public List selectFiles(DhSectionPos sectionPos, DhClientServerLevel level, List[] availableFiles) { return Arrays.stream(availableFiles).flatMap(Collection::stream).collect(Collectors.toList()); } diff --git a/src/main/java/com/seibel/lod/core/a7/save/structure/ClientOnlySaveStructure.java b/src/main/java/com/seibel/lod/core/a7/save/structure/ClientOnlySaveStructure.java index c85e9456c..40919de2f 100644 --- a/src/main/java/com/seibel/lod/core/a7/save/structure/ClientOnlySaveStructure.java +++ b/src/main/java/com/seibel/lod/core/a7/save/structure/ClientOnlySaveStructure.java @@ -1,9 +1,9 @@ package com.seibel.lod.core.a7.save.structure; import com.seibel.lod.core.a7.io.LevelToFileMatcher; -import com.seibel.lod.core.a7.level.DHLevel; +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.world.DhWorld; import com.seibel.lod.core.config.Config; import com.seibel.lod.core.enums.config.EServerFolderNameMode; import com.seibel.lod.core.enums.config.EVerticalQuality; @@ -17,7 +17,6 @@ import javax.annotation.Nullable; import java.io.File; import java.util.Arrays; import java.util.Optional; -import java.util.stream.Collectors; import java.util.stream.Stream; public class ClientOnlySaveStructure extends SaveStructure { @@ -83,14 +82,15 @@ public class ClientOnlySaveStructure extends SaveStructure { this.world = world; } + //FIXME: how do i deal with either creating a ClientServerLevel, or a ServerLevel here??? @Override - public DHLevel tryGetLevel(ILevelWrapper wrapper) { + public IServerLevel tryGetLevel(ILevelWrapper wrapper) { if (Config.Client.Multiplayer.multiDimensionRequiredSimilarity.get() == 0) { if (fileMatcher != null) { fileMatcher.close(); fileMatcher = null; } - return new DHLevel(world, getLevelFolderWithoutSimilarityMatching(wrapper), wrapper); + return new DhClientServerLevel(world, getLevelFolderWithoutSimilarityMatching(wrapper), wrapper); } if (fileMatcher == null || !fileMatcher.isFindingLevel(wrapper)) { @@ -99,7 +99,7 @@ public class ClientOnlySaveStructure extends SaveStructure { (File[]) getMatchingLevelFolders(wrapper).toArray()); } - DHLevel level = fileMatcher.tryGetLevel(); + DhClientServerLevel level = fileMatcher.tryGetLevel(); if (level != null) { fileMatcher.close(); fileMatcher = null; diff --git a/src/main/java/com/seibel/lod/core/a7/save/structure/SaveStructure.java b/src/main/java/com/seibel/lod/core/a7/save/structure/SaveStructure.java index 5824c18ad..9d1ecaec2 100644 --- a/src/main/java/com/seibel/lod/core/a7/save/structure/SaveStructure.java +++ b/src/main/java/com/seibel/lod/core/a7/save/structure/SaveStructure.java @@ -1,9 +1,7 @@ package com.seibel.lod.core.a7.save.structure; -import com.seibel.lod.core.a7.io.LevelToFileMatcher; -import com.seibel.lod.core.a7.level.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import com.seibel.lod.core.logging.DhLoggerBuilder; -import com.seibel.lod.core.util.LodUtil; import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper; import org.apache.logging.log4j.Logger; @@ -13,7 +11,7 @@ public abstract class SaveStructure implements AutoCloseable { protected static final Logger LOGGER = DhLoggerBuilder.getLogger(); - public abstract DHLevel tryGetLevel(ILevelWrapper wrapper); + public abstract DhClientServerLevel tryGetLevel(ILevelWrapper wrapper); protected abstract File getRenderCacheFolder(ILevelWrapper world); protected abstract File getDataFolder(ILevelWrapper world); diff --git a/src/main/java/com/seibel/lod/core/a7/world/DhClientServerWorld.java b/src/main/java/com/seibel/lod/core/a7/world/DhClientServerWorld.java index e74500418..5e113f793 100644 --- a/src/main/java/com/seibel/lod/core/a7/world/DhClientServerWorld.java +++ b/src/main/java/com/seibel/lod/core/a7/world/DhClientServerWorld.java @@ -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.DHLevel; +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; @@ -9,9 +9,10 @@ import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper; import java.util.HashMap; import java.util.Iterator; +import java.util.concurrent.CompletableFuture; public class DhClientServerWorld extends DhWorld implements IClientWorld, IServerWorld { - private final HashMap levels; + private final HashMap levels; public final LocalSaveStructure saveStructure; public DhClientServerWorld() { @@ -21,9 +22,9 @@ public class DhClientServerWorld extends DhWorld implements IClientWorld, IServe } @Override - public DHLevel getOrLoadLevel(ILevelWrapper wrapper) { + public DhClientServerLevel getOrLoadLevel(ILevelWrapper wrapper) { if (!levels.containsKey(wrapper)) { - DHLevel level = saveStructure.tryGetLevel(wrapper); + DhClientServerLevel level = saveStructure.tryGetLevel(wrapper); if (level != null) { levels.put(wrapper, level); } @@ -32,7 +33,7 @@ public class DhClientServerWorld extends DhWorld implements IClientWorld, IServe } @Override - public DHLevel getLevel(ILevelWrapper wrapper) { + public DhClientServerLevel getLevel(ILevelWrapper wrapper) { return levels.get(wrapper); } @@ -47,10 +48,10 @@ public class DhClientServerWorld extends DhWorld implements IClientWorld, IServe public void tick() { int newViewDistance = Config.Client.Graphics.Quality.lodChunkRenderDistance.get() * 16; - Iterator iterator = levels.values().iterator(); + Iterator iterator = levels.values().iterator(); while (iterator.hasNext()) { - DHLevel level = iterator.next(); - if (level.viewDistance != newViewDistance) { + DhClientServerLevel level = iterator.next(); + if (level.tree.viewDistance != newViewDistance) { level.close(); iterator.remove(); } @@ -63,23 +64,17 @@ public class DhClientServerWorld extends DhWorld implements IClientWorld, IServe } @Override - public void saveAndFlush() { - for (DHLevel level : levels.values()) { - level.saveFlush(); - } + public CompletableFuture saveAndFlush() { + return CompletableFuture.allOf(levels.values().stream().map(DhClientServerLevel::save).toArray(CompletableFuture[]::new)); } @Override public void close() { - for (DHLevel level : levels.values()) { + saveAndFlush().join(); + for (DhClientServerLevel level : levels.values()) { LOGGER.info("Unloading level for world " + level.level.getDimensionType().getDimensionName()); level.close(); } levels.clear(); } - - @Override - public void render() { - - } } diff --git a/src/main/java/com/seibel/lod/core/a7/world/DhClientWorld.java b/src/main/java/com/seibel/lod/core/a7/world/DhClientWorld.java index af48bd2f8..08b42a2db 100644 --- a/src/main/java/com/seibel/lod/core/a7/world/DhClientWorld.java +++ b/src/main/java/com/seibel/lod/core/a7/world/DhClientWorld.java @@ -1,10 +1,8 @@ package com.seibel.lod.core.a7.world; import com.seibel.lod.core.a7.WorldEnvironment; -import com.seibel.lod.core.a7.io.LevelToFileMatcher; -import com.seibel.lod.core.a7.level.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import com.seibel.lod.core.a7.save.structure.ClientOnlySaveStructure; -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.EventLoop; @@ -13,11 +11,12 @@ import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper; import java.util.HashMap; import java.util.Iterator; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; public class DhClientWorld extends DhWorld implements IClientWorld { - private final HashMap levels; + private final HashMap levels; public final ClientOnlySaveStructure saveStructure; public ExecutorService dhTickerThread = LodUtil.makeSingleThreadPool("DHTickerThread", 2); @@ -30,9 +29,9 @@ public class DhClientWorld extends DhWorld implements IClientWorld { } @Override - public DHLevel getOrLoadLevel(ILevelWrapper wrapper) { + public DhClientServerLevel getOrLoadLevel(ILevelWrapper wrapper) { if (!levels.containsKey(wrapper)) { - DHLevel level = saveStructure.tryGetLevel(wrapper); + DhClientWorld level = saveStructure.tryGetLevel(wrapper); if (level != null) { levels.put(wrapper, level); } @@ -41,7 +40,7 @@ public class DhClientWorld extends DhWorld implements IClientWorld { } @Override - public DHLevel getLevel(ILevelWrapper wrapper) { + public DhClientServerLevel getLevel(ILevelWrapper wrapper) { return levels.get(wrapper); } @@ -56,9 +55,9 @@ public class DhClientWorld extends DhWorld implements IClientWorld { private void tick() { int newViewDistance = Config.Client.Graphics.Quality.lodChunkRenderDistance.get() * 16; - Iterator iterator = levels.values().iterator(); + Iterator iterator = levels.values().iterator(); while (iterator.hasNext()) { - DHLevel level = iterator.next(); + DhClientWorld level = iterator.next(); if (level.viewDistance != newViewDistance) { level.close(); iterator.remove(); @@ -72,24 +71,17 @@ public class DhClientWorld extends DhWorld implements IClientWorld { } @Override - public void saveAndFlush() { - for (DHLevel level : levels.values()) { - level.saveFlush(); - } + public CompletableFuture saveAndFlush() { + return CompletableFuture.allOf(levels.values().stream().map(DhClientServerLevel::save).toArray(CompletableFuture[]::new)); } @Override public void close() { - eventLoop.halt(); - for (DHLevel level : levels.values()) { + saveAndFlush().join(); + for (DhClientServerLevel level : levels.values()) { LOGGER.info("Unloading level for world " + level.level.getDimensionType().getDimensionName()); level.close(); } levels.clear(); } - - @Override - public void render() { - - } } diff --git a/src/main/java/com/seibel/lod/core/a7/world/DhServerWorld.java b/src/main/java/com/seibel/lod/core/a7/world/DhServerWorld.java index f10b07eee..0c3b31e3e 100644 --- a/src/main/java/com/seibel/lod/core/a7/world/DhServerWorld.java +++ b/src/main/java/com/seibel/lod/core/a7/world/DhServerWorld.java @@ -1,9 +1,7 @@ package com.seibel.lod.core.a7.world; import com.seibel.lod.core.a7.WorldEnvironment; -import com.seibel.lod.core.a7.io.LevelToFileMatcher; -import com.seibel.lod.core.a7.level.DHLevel; -import com.seibel.lod.core.a7.save.structure.ClientOnlySaveStructure; +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; @@ -13,7 +11,7 @@ import java.util.HashMap; import java.util.Iterator; public class DhServerWorld extends DhWorld implements IServerWorld { - private final HashMap levels; + private final HashMap levels; public final LocalSaveStructure saveStructure; public DhServerWorld() { @@ -23,9 +21,9 @@ public class DhServerWorld extends DhWorld implements IServerWorld { } @Override - public DHLevel getOrLoadLevel(ILevelWrapper wrapper) { + public DhClientServerLevel getOrLoadLevel(ILevelWrapper wrapper) { if (!levels.containsKey(wrapper)) { - DHLevel level = saveStructure.tryGetLevel(wrapper); + DhClientServerLevel level = saveStructure.tryGetLevel(wrapper); if (level != null) { levels.put(wrapper, level); } @@ -34,7 +32,7 @@ public class DhServerWorld extends DhWorld implements IServerWorld { } @Override - public DHLevel getLevel(ILevelWrapper wrapper) { + public DhClientServerLevel getLevel(ILevelWrapper wrapper) { return levels.get(wrapper); } @@ -49,9 +47,9 @@ public class DhServerWorld extends DhWorld implements IServerWorld { public void tick() { int newViewDistance = Config.Client.Graphics.Quality.lodChunkRenderDistance.get() * 16; - Iterator iterator = levels.values().iterator(); + Iterator iterator = levels.values().iterator(); while (iterator.hasNext()) { - DHLevel level = iterator.next(); + DhClientServerLevel level = iterator.next(); if (level.viewDistance != newViewDistance) { level.close(); iterator.remove(); @@ -66,14 +64,14 @@ public class DhServerWorld extends DhWorld implements IServerWorld { @Override public void saveAndFlush() { - for (DHLevel level : levels.values()) { + for (DhClientServerLevel level : levels.values()) { level.saveFlush(); } } @Override public void close() { - for (DHLevel level : levels.values()) { + for (DhClientServerLevel level : levels.values()) { LOGGER.info("Unloading level for world " + level.level.getDimensionType().getDimensionName()); level.close(); } diff --git a/src/main/java/com/seibel/lod/core/a7/world/DhWorld.java b/src/main/java/com/seibel/lod/core/a7/world/DhWorld.java index 356f45e7c..3d0e4ac3b 100644 --- a/src/main/java/com/seibel/lod/core/a7/world/DhWorld.java +++ b/src/main/java/com/seibel/lod/core/a7/world/DhWorld.java @@ -1,21 +1,13 @@ package com.seibel.lod.core.a7.world; import com.seibel.lod.core.a7.WorldEnvironment; -import com.seibel.lod.core.a7.io.LevelToFileMatcher; -import com.seibel.lod.core.a7.level.DHLevel; -import com.seibel.lod.core.a7.save.structure.SaveStructure; -import com.seibel.lod.core.config.Config; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import com.seibel.lod.core.logging.DhLoggerBuilder; -import com.seibel.lod.core.util.DetailDistanceUtil; -import com.seibel.lod.core.util.EventLoop; -import com.seibel.lod.core.util.LodUtil; import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper; import org.apache.logging.log4j.Logger; import java.io.Closeable; -import java.util.HashMap; -import java.util.Iterator; -import java.util.concurrent.ExecutorService; +import java.util.concurrent.CompletableFuture; public abstract class DhWorld implements Closeable { protected static final Logger LOGGER = DhLoggerBuilder.getLogger(); @@ -25,10 +17,10 @@ public abstract class DhWorld implements Closeable { protected DhWorld(WorldEnvironment environment) { this.environment = environment; } - public abstract DHLevel getOrLoadLevel(ILevelWrapper wrapper); + public abstract DhClientServerLevel getOrLoadLevel(ILevelWrapper wrapper); - public abstract DHLevel getLevel(ILevelWrapper wrapper); + public abstract DhClientServerLevel getLevel(ILevelWrapper wrapper); public abstract void unloadLevel(ILevelWrapper wrapper); - public abstract void saveAndFlush(); + public abstract CompletableFuture saveAndFlush(); } diff --git a/src/main/java/com/seibel/lod/core/a7/world/IClientWorld.java b/src/main/java/com/seibel/lod/core/a7/world/IClientWorld.java index 9b639d059..0377e7f38 100644 --- a/src/main/java/com/seibel/lod/core/a7/world/IClientWorld.java +++ b/src/main/java/com/seibel/lod/core/a7/world/IClientWorld.java @@ -1,5 +1,4 @@ package com.seibel.lod.core.a7.world; public interface IClientWorld { - void render(); } diff --git a/src/main/java/com/seibel/lod/core/api/internal/a7/ClientApi.java b/src/main/java/com/seibel/lod/core/api/internal/a7/ClientApi.java index 22513036d..f03ab1338 100644 --- a/src/main/java/com/seibel/lod/core/api/internal/a7/ClientApi.java +++ b/src/main/java/com/seibel/lod/core/api/internal/a7/ClientApi.java @@ -27,7 +27,7 @@ import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; import com.seibel.lod.core.logging.ConfigBasedLogger; import com.seibel.lod.core.logging.ConfigBasedSpamLogger; import com.seibel.lod.core.logging.SpamReducedLogger; -import com.seibel.lod.core.a7.level.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import com.seibel.lod.core.a7.world.DhWorld; import com.seibel.lod.core.a7.Server; import com.seibel.lod.core.objects.math.Mat4f; @@ -199,7 +199,7 @@ public class ClientApi if (world == null) return; DhWorld DhWorld = SharedApi.currentWorld; if (DhWorld == null) return; - DHLevel level = (SharedApi.currentServer == null) ? DhWorld.getOrLoadLevel(world) : DhWorld.getLevel(world); + DhClientServerLevel level = (SharedApi.currentServer == null) ? DhWorld.getOrLoadLevel(world) : DhWorld.getLevel(world); if (level == null) return; if (prefLoggerEnabled) { diff --git a/src/main/java/com/seibel/lod/core/render/a7LodRenderer.java b/src/main/java/com/seibel/lod/core/render/a7LodRenderer.java index 4ebc506c1..c31e1fedc 100644 --- a/src/main/java/com/seibel/lod/core/render/a7LodRenderer.java +++ b/src/main/java/com/seibel/lod/core/render/a7LodRenderer.java @@ -19,6 +19,7 @@ package com.seibel.lod.core.render; +import com.seibel.lod.core.a7.level.IClientLevel; import com.seibel.lod.core.config.Config; import com.seibel.lod.core.builders.lodBuilding.bufferBuilding.LodBufferBuilderFactory; import com.seibel.lod.core.config.types.ConfigEntry; @@ -28,7 +29,7 @@ import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler; import com.seibel.lod.core.logging.ConfigBasedLogger; import com.seibel.lod.core.logging.ConfigBasedSpamLogger; import com.seibel.lod.core.objects.DHBlockPos; -import com.seibel.lod.core.a7.level.DHLevel; +import com.seibel.lod.core.a7.level.DhClientServerLevel; import com.seibel.lod.core.a7.render.RenderBufferHandler; import com.seibel.lod.core.objects.math.Mat4f; import com.seibel.lod.core.objects.math.Vec3d; @@ -82,14 +83,14 @@ public class a7LodRenderer private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class); public EDebugMode previousDebugMode = null; - public final DHLevel level; + public final IClientLevel level; // The shader program LodRenderProgram shaderProgram = null; public QuadElementBuffer quadIBO = null; public boolean isSetupComplete = false; - public a7LodRenderer(DHLevel level) + public a7LodRenderer(IClientLevel level) { this.level = level; } @@ -127,7 +128,7 @@ public class a7LodRenderer MC_RENDER.tryDisableVanillaFog(); // The Buffer manager - RenderBufferHandler bufferHandler = level.renderBufferHandler; + RenderBufferHandler bufferHandler = level.getRenderBufferHandler(); //===================// // draw params setup //