Continue refactoring, and starting to hook up all the loose pieces

This commit is contained in:
TomTheFurry
2022-06-22 22:13:08 +08:00
parent dc1c130fb9
commit 04bc771c6d
34 changed files with 396 additions and 412 deletions
@@ -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<LodSection>[] 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();
@@ -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<OldFileConverter> 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<DhSectionPos, DataFile> 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<DataFile> 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<DataFile>[] getFilesInPos(DhSectionPos pos) {
List<DataFile>[] 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<DataFile> 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<RenderDataSource> createRenderData(RenderDataSourceLoader renderSourceLoader, DhSectionPos pos) {
return CompletableFuture.supplyAsync(() -> {
List<DataFile> files = renderSourceLoader.selectFiles(pos, level, getFilesInPos(pos));
List<LodDataSource> 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));
}
}
@@ -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<File> foldersToScan(File levelFolderPath) {
return Collections.emptyList();
@@ -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<DataFile> scanAndConvert(File levelFolder, DHLevel level);
List<DataFile> scanAndConvert(File levelFolder, DhClientServerLevel level);
}
@@ -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<DataFile> scanAndConvert(File levelFolder, DHLevel level) {
public List<DataFile> scanAndConvert(File levelFolder, DhClientServerLevel level) {
List<DataFile> files = new ArrayList<>();
@@ -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());
}
@@ -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();
@@ -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<LodDataSource> dataSources, DhSectionPos sectionPos, DHLevel level) {
public RenderDataSource construct(List<LodDataSource> 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<DataFile> selectFiles(DhSectionPos sectionPos, DHLevel level, List<DataFile>[] availableFiles) {
public List<DataFile> selectFiles(DhSectionPos sectionPos, DhClientServerLevel level, List<DataFile>[] 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);
@@ -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));
}
@@ -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();
@@ -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 {
@@ -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;
}
@@ -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<LodDataSource> read(DhSectionPos pos);
void write(DhSectionPos sectionPos, FullDatatype chunkData);
CompletableFuture<Void> flushAndSave();
@@ -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
}
}
@@ -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<LodDataSource> read(DhSectionPos pos) {
return null;
}
@Override
public void write(DhSectionPos sectionPos, FullDatatype chunkData) {
}
@Override
public CompletableFuture<Void> flushAndSave() {
return null;
}
@Override
public void close() throws Exception {
}
}
@@ -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<RenderDataSource> read(DhSectionPos pos) {
@Override
public void write(DhSectionPos sectionPos, FullDatatype chunkData) {
}
@Override
public CompletableFuture<Void> flushAndSave() {
return null;
}
public void write(DhSectionPos sectionPos, FullDatatype chunkData) {
`
@Override
public void close() {
}
}
@@ -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<RenderDataSource> get(DhSectionPos pos);
public interface RenderSourceProvider extends RenderDataProvider, AutoCloseable {
void write(DhSectionPos sectionPos, FullDatatype chunkData);
CompletableFuture<Void> flushAndSave();
}
@@ -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();
}
}
}
@@ -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<Void> save() {
return renderFileHandler.flushAndSave();
}
@Override
public void close() {
renderFileHandler.close();
}
}
@@ -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<Void> 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.
}
}
@@ -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<Void> save() {
return dataFileHandler.flushAndSave();
}
}
@@ -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();
}
@@ -0,0 +1,10 @@
package com.seibel.lod.core.a7.level;
import java.util.concurrent.CompletableFuture;
public interface ILevel extends AutoCloseable {
int getMinY();
CompletableFuture<Void> save();
void dumpRamUsage();
}
@@ -0,0 +1,4 @@
package com.seibel.lod.core.a7.level;
public interface IServerLevel extends ILevel {
}
@@ -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<LodDataSource> dataSources, DhSectionPos sectionPos, DHLevel level);
public abstract RenderDataSource construct(List<LodDataSource> dataSources, DhSectionPos sectionPos, DhClientServerLevel level);
public List<DataFile> selectFiles(DhSectionPos sectionPos, DHLevel level, List<DataFile>[] availableFiles) {
public List<DataFile> selectFiles(DhSectionPos sectionPos, DhClientServerLevel level, List<DataFile>[] availableFiles) {
return Arrays.stream(availableFiles).flatMap(Collection::stream).collect(Collectors.toList());
}
@@ -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;
@@ -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);
@@ -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<ILevelWrapper, DHLevel> levels;
private final HashMap<ILevelWrapper, DhClientServerLevel> 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<DHLevel> iterator = levels.values().iterator();
Iterator<DhClientServerLevel> 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<Void> 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() {
}
}
@@ -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<ILevelWrapper, DHLevel> levels;
private final HashMap<ILevelWrapper, DhClientWorld> 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<DHLevel> iterator = levels.values().iterator();
Iterator<DhClientWorld> 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<Void> 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() {
}
}
@@ -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<ILevelWrapper, DHLevel> levels;
private final HashMap<ILevelWrapper, DhClientServerLevel> 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<DHLevel> iterator = levels.values().iterator();
Iterator<DhClientServerLevel> 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();
}
@@ -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<Void> saveAndFlush();
}
@@ -1,5 +1,4 @@
package com.seibel.lod.core.a7.world;
public interface IClientWorld {
void render();
}
@@ -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) {
@@ -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 //