make DhClientServerLevel extends DhClientLevel

This commit is contained in:
James Seibel
2023-02-25 17:17:27 -06:00
parent 5579b1dc95
commit ea41fbc664
14 changed files with 177 additions and 313 deletions
@@ -104,7 +104,7 @@ public class ServerApi
{
if (ENABLE_EVENT_LOGGING)
{
LOGGER.info("Server Level {} loading", level);
LOGGER.info("Server Level "+level+" loading");
}
AbstractDhWorld serverWorld = SharedApi.getAbstractDhWorld();
@@ -25,12 +25,12 @@ public abstract class AbstractSaveStructure implements AutoCloseable
* This will always return a folder, however that folder may not be the best match
* if multiverse support is enabled.
* */
public abstract File tryGetOrCreateLevelFolder(ILevelWrapper wrapper);
public abstract File getLevelFolder(ILevelWrapper wrapper);
/** Will return null if no parent folder exists for the given {@link ILevelWrapper}.*/
public abstract File getRenderCacheFolder(ILevelWrapper world);
/** Will return null if no parent folder exists for the given {@link ILevelWrapper}.*/
public abstract File getDataFolder(ILevelWrapper world);
public abstract File getFullDataFolder(ILevelWrapper world);
}
@@ -54,7 +54,7 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure
//================//
@Override
public File tryGetOrCreateLevelFolder(ILevelWrapper level)
public File getLevelFolder(ILevelWrapper level)
{
return this.levelToFileMap.computeIfAbsent(level, (newLevel) ->
{
@@ -139,7 +139,7 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure
}
@Override
public File getDataFolder(ILevelWrapper level)
public File getFullDataFolder(ILevelWrapper level)
{
File levelFolder = this.levelToFileMap.get(level);
if (levelFolder == null)
@@ -27,7 +27,7 @@ public class LocalSaveStructure extends AbstractSaveStructure
//================//
@Override
public File tryGetOrCreateLevelFolder(ILevelWrapper wrapper)
public File getLevelFolder(ILevelWrapper wrapper)
{
IServerLevelWrapper serverSide = (IServerLevelWrapper) wrapper;
this.debugPath = new File(serverSide.getSaveFolder(), "Distant_Horizons");
@@ -43,11 +43,11 @@ public class LocalSaveStructure extends AbstractSaveStructure
}
@Override
public File getDataFolder(ILevelWrapper level)
public File getFullDataFolder(ILevelWrapper level)
{
IServerLevelWrapper serverSide = (IServerLevelWrapper) level;
this.debugPath = new File(serverSide.getSaveFolder(), SERVER_FOLDER_NAME);
return new File(new File(serverSide.getSaveFolder(), SERVER_FOLDER_NAME), DATA_FOLDER);
IServerLevelWrapper serverLevelWrapper = (IServerLevelWrapper) level;
this.debugPath = new File(serverLevelWrapper.getSaveFolder(), SERVER_FOLDER_NAME);
return new File(new File(serverLevelWrapper.getSaveFolder(), SERVER_FOLDER_NAME), DATA_FOLDER);
}
@@ -3,7 +3,9 @@ package com.seibel.lod.core.level;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.FullDataSource;
import com.seibel.lod.core.dataObjects.transformers.ChunkToLodBuilder;
import com.seibel.lod.core.file.fullDatafile.FullDataFileHandler;
import com.seibel.lod.core.file.fullDatafile.IFullDataSourceProvider;
import com.seibel.lod.core.file.structure.AbstractSaveStructure;
import com.seibel.lod.core.level.states.ClientRenderState;
import com.seibel.lod.core.logging.f3.F3Screen;
import com.seibel.lod.core.pos.DhLodPos;
@@ -11,7 +13,6 @@ import com.seibel.lod.core.pos.DhSectionPos;
import com.seibel.lod.core.util.FileScanUtil;
import com.seibel.lod.core.file.fullDatafile.RemoteFullDataFileHandler;
import com.seibel.lod.core.pos.DhBlockPos2D;
import com.seibel.lod.core.file.structure.ClientOnlySaveStructure;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.DhLoggerBuilder;
@@ -35,60 +36,55 @@ public class DhClientLevel implements IDhClientLevel
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
public final ClientOnlySaveStructure saveStructure;
public final RemoteFullDataFileHandler fullDataFileHandler;
public final IClientLevelWrapper clientLevelWrapper;
public final AbstractSaveStructure saveStructure;
public final ChunkToLodBuilder chunkToLodBuilder;
public final IClientLevelWrapper clientLevel;
public F3Screen.NestedMessage f3Message;
public final F3Screen.NestedMessage f3Message;
public FullDataFileHandler fullDataFileHandler;
public final AtomicReference<ClientRenderState> ClientRenderStateRef = new AtomicReference<>();
public DhClientLevel(ClientOnlySaveStructure saveStructure, IClientLevelWrapper clientLevel)
//=============//
// constructor //
//=============//
public DhClientLevel(AbstractSaveStructure saveStructure, IClientLevelWrapper clientLevelWrapper)
{
this.clientLevel = clientLevel;
this(saveStructure, clientLevelWrapper, null);
this.fullDataFileHandler = new RemoteFullDataFileHandler(this, this.saveStructure.getFullDataFolder(this.clientLevelWrapper));
FileScanUtil.scanFiles(saveStructure, this.clientLevelWrapper, this.fullDataFileHandler, null);
}
public DhClientLevel(AbstractSaveStructure saveStructure, IClientLevelWrapper clientLevelWrapper, FullDataFileHandler fullDataFileHandler)
{
this.clientLevelWrapper = clientLevelWrapper;
this.saveStructure = saveStructure;
saveStructure.getDataFolder(clientLevel).mkdirs();
saveStructure.getRenderCacheFolder(clientLevel).mkdirs();
if (this.saveStructure.getFullDataFolder(this.clientLevelWrapper).mkdirs())
{
LOGGER.warn("unable to create full data folder.");
}
if (this.saveStructure.getRenderCacheFolder(this.clientLevelWrapper).mkdirs())
{
LOGGER.warn("unable to create cache folder.");
}
this.fullDataFileHandler = new RemoteFullDataFileHandler(this, saveStructure.getDataFolder(clientLevel));
FileScanUtil.scanFiles(saveStructure, clientLevel, this.fullDataFileHandler, null);
// TODO not a great way of handling this, but it works for now
if (fullDataFileHandler != null)
{
this.fullDataFileHandler = fullDataFileHandler;
FileScanUtil.scanFiles(saveStructure, this.clientLevelWrapper, this.fullDataFileHandler, null);
}
this.f3Message = new F3Screen.NestedMessage(this::f3Log);
this.chunkToLodBuilder = new ChunkToLodBuilder();
LOGGER.info("Started DHLevel for "+clientLevel+" with saves at "+saveStructure);
}
//=======================//
// misc helper functions //
//=======================//
/** Returns what should be displayed in Minecraft's F3 debug menu */
private String[] f3Log()
{
ClientRenderState rs = this.ClientRenderStateRef.get();
if (rs == null)
{
return new String[] { LodUtil.formatLog("level @ {}: Inactive", this.clientLevel.getDimensionType().getDimensionName()) };
}
else
{
return new String[] {
LodUtil.formatLog("level @ {}: Active", this.clientLevel.getDimensionType().getDimensionName())
};
}
}
@Override
public void dumpRamUsage()
{
//TODO
LOGGER.info("Started DHLevel for "+this.clientLevelWrapper+" with saves at "+this.saveStructure);
}
@@ -99,18 +95,31 @@ public class DhClientLevel implements IDhClientLevel
@Override
public void clientTick()
{
if (!this.baseClientTick())
{
return;
}
this.chunkToLodBuilder.tick();
}
/**
* Includes logic used by both {@link DhClientServerLevel} and {@link DhClientServerLevel}
* @return whether the tick method completed
*/
protected boolean baseClientTick()
{
ClientRenderState clientRenderState = this.ClientRenderStateRef.get();
if (clientRenderState == null)
{
return;
return false;
}
if (clientRenderState.quadtree.blockRenderDistance != Config.Client.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH)
{
if (!this.ClientRenderStateRef.compareAndSet(clientRenderState, null))
{
return; //If we fail, we'll just wait for the next tick
return false; //If we fail, we'll just wait for the next tick
}
IClientLevelWrapper levelWrapper = clientRenderState.clientLevel;
@@ -121,14 +130,14 @@ public class DhClientLevel implements IDhClientLevel
//FIXME: How to handle this?
LOGGER.warn("Failed to set render state due to concurrency after changing view distance");
clientRenderState.closeAsync();
return;
return false;
}
}
clientRenderState.quadtree.tick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos()));
clientRenderState.renderer.bufferHandler.update();
this.chunkToLodBuilder.tick();
return true;
}
@@ -140,11 +149,21 @@ public class DhClientLevel implements IDhClientLevel
public void startRenderer(IClientLevelWrapper clientLevel)
{
LOGGER.info("Starting renderer for "+this);
ClientRenderState ClientRenderState = new ClientRenderState(this, clientLevel);
this.setAndStartRenderer();
}
/** @return if the {@link ClientRenderState} was successfully swapped */
protected boolean setAndStartRenderer()
{
ClientRenderState ClientRenderState = new ClientRenderState(this, this.clientLevelWrapper);
if (!this.ClientRenderStateRef.compareAndSet(null, ClientRenderState))
{
LOGGER.warn("Failed to start renderer due to concurrency");
ClientRenderState.closeAsync();
return false;
}
else
{
return true;
}
}
@@ -180,7 +199,6 @@ public class DhClientLevel implements IDhClientLevel
}
}
ClientRenderState.closeAsync().join(); //TODO: Make it async.
}
@@ -190,31 +208,15 @@ public class DhClientLevel implements IDhClientLevel
//================//
@Override
public int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper block)
{
IClientLevelWrapper clientLevel = this.getClientLevelWrapper();
if (clientLevel == null)
{
return 0;
}
else
{
return clientLevel.computeBaseColor(pos, biome, block);
}
}
public int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper block) { return this.clientLevelWrapper.computeBaseColor(pos, biome, block); }
@Override
public IClientLevelWrapper getClientLevelWrapper()
{
ClientRenderState ClientRenderState = this.ClientRenderStateRef.get();
return ClientRenderState == null ? null : ClientRenderState.clientLevel;
}
public IClientLevelWrapper getClientLevelWrapper() { return this.clientLevelWrapper; }
@Override
public ILevelWrapper getLevelWrapper() { return this.clientLevelWrapper; }
@Override
public ILevelWrapper getLevelWrapper() { return this.clientLevel; }
@Override
public int getMinY() { return this.clientLevel.getMinHeight(); }
public int getMinY() { return this.clientLevelWrapper.getMinHeight(); }
@@ -263,25 +265,62 @@ public class DhClientLevel implements IDhClientLevel
@Override
public void close()
{
this.baseClose();
LOGGER.info("Closed "+DhClientLevel.class.getSimpleName()+" for "+this.clientLevelWrapper);
}
/** Includes logic used by both {@link DhClientServerLevel} and {@link DhClientServerLevel} */
protected void baseClose()
{
ClientRenderState ClientRenderState = this.ClientRenderStateRef.get();
if (ClientRenderState != null)
{
// TODO does this have to be in a while loop, if so why?
while (!this.ClientRenderStateRef.compareAndSet(ClientRenderState, null))
{
ClientRenderState = this.ClientRenderStateRef.get();
if (ClientRenderState == null)
{
return;
break;
}
}
ClientRenderState.closeAsync().join(); //TODO: Make this async.
if (ClientRenderState != null)
{
ClientRenderState.closeAsync().join(); //TODO: Make this async.
}
}
LOGGER.info("Closed DHLevel for "+this.clientLevel);
}
//=======================//
// misc helper functions //
//=======================//
/** Returns what should be displayed in Minecraft's F3 debug menu */
protected String[] f3Log()
{
ClientRenderState renderState = this.ClientRenderStateRef.get();
if (renderState == null)
{
return new String[] { LodUtil.formatLog("level @ {}: Inactive", this.clientLevelWrapper.getDimensionType().getDimensionName()) };
}
else
{
return new String[] {
LodUtil.formatLog("level @ {}: Active", this.clientLevelWrapper.getDimensionType().getDimensionName())
};
}
}
@Override
public void dumpRamUsage()
{
//TODO
}
@Override
public IFullDataSourceProvider getFileHandler() { return this.fullDataFileHandler; }
@@ -296,4 +335,5 @@ public class DhClientLevel implements IDhClientLevel
}
}
@@ -3,30 +3,19 @@ package com.seibel.lod.core.level;
import com.seibel.lod.api.interfaces.override.worldGenerator.IDhApiWorldGenerator;
import com.seibel.lod.core.DependencyInjection.WorldGeneratorInjector;
import com.seibel.lod.core.config.AppliedConfigState;
import com.seibel.lod.core.dataObjects.fullData.sources.ChunkSizedFullDataSource;
import com.seibel.lod.core.dataObjects.fullData.sources.FullDataSource;
import com.seibel.lod.core.dataObjects.transformers.ChunkToLodBuilder;
import com.seibel.lod.core.file.fullDatafile.IFullDataSourceProvider;
import com.seibel.lod.core.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.file.fullDatafile.FullDataFileHandler;
import com.seibel.lod.core.file.structure.AbstractSaveStructure;
import com.seibel.lod.core.generation.BatchGenerator;
import com.seibel.lod.core.generation.WorldGenerationQueue;
import com.seibel.lod.core.level.states.ClientRenderState;
import com.seibel.lod.core.pos.DhLodPos;
import com.seibel.lod.core.pos.DhSectionPos;
import com.seibel.lod.core.file.fullDatafile.GeneratedFullDataFileHandler;
import com.seibel.lod.core.util.FileScanUtil;
import com.seibel.lod.core.pos.DhBlockPos2D;
import com.seibel.lod.core.file.structure.LocalSaveStructure;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.logging.f3.F3Screen;
import com.seibel.lod.core.pos.DhBlockPos;
import com.seibel.lod.core.util.math.Mat4f;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockStateWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IClientLevelWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
@@ -37,69 +26,38 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
/** The level used on a singleplayer world */
public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
public class DhClientServerLevel extends DhClientLevel implements IDhClientLevel, IDhServerLevel
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
public final LocalSaveStructure saveStructure;
public final GeneratedFullDataFileHandler fullDataFileHandler;
public final ChunkToLodBuilder chunkToLodBuilder;
public final IServerLevelWrapper serverLevel;
private final AppliedConfigState<Boolean> worldGeneratorEnabledConfig;
public F3Screen.NestedMessage f3Message;
public final IServerLevelWrapper serverLevelWrapper;
private final AtomicReference<ClientRenderState> ClientRenderStateRef = new AtomicReference<>();
/**
* This is separate from {@link DhClientLevel#fullDataFileHandler} and included
* since the base {@link FullDataFileHandler} doesn't support world generation
*/
public final GeneratedFullDataFileHandler generatedFullDataFileHandler;
private final AppliedConfigState<Boolean> worldGeneratorEnabledConfig;
private final AtomicReference<WorldGenState> worldGenStateRef = new AtomicReference<>();
public DhClientServerLevel(LocalSaveStructure saveStructure, IServerLevelWrapper serverLevel)
public DhClientServerLevel(AbstractSaveStructure saveStructure, IServerLevelWrapper serverLevelWrapper)
{
this.serverLevel = serverLevel;
super(saveStructure, serverLevelWrapper.tryGetClientLevelWrapper(), null);
this.saveStructure = saveStructure;
saveStructure.getDataFolder(serverLevel).mkdirs();
saveStructure.getRenderCacheFolder(serverLevel).mkdirs();
this.serverLevelWrapper = serverLevelWrapper;
this.fullDataFileHandler = new GeneratedFullDataFileHandler(this, saveStructure.getDataFolder(serverLevel));
FileScanUtil.scanFiles(saveStructure, this.serverLevel, this.fullDataFileHandler, null);
this.f3Message = new F3Screen.NestedMessage(this::f3Log);
this.chunkToLodBuilder = new ChunkToLodBuilder();
this.generatedFullDataFileHandler = new GeneratedFullDataFileHandler(this, saveStructure.getFullDataFolder(serverLevelWrapper));
this.fullDataFileHandler = this.generatedFullDataFileHandler;
FileScanUtil.scanFiles(saveStructure, this.serverLevelWrapper, this.fullDataFileHandler, null);
this.worldGeneratorEnabledConfig = new AppliedConfigState<>(Config.Client.WorldGenerator.enableDistantGeneration);
LOGGER.info("Started DHLevel for "+serverLevel+" with saves at "+saveStructure);
}
//=======================//
// misc helper functions //
//=======================//
/** Returns what should be displayed in Minecraft's F3 debug menu */
private String[] f3Log()
{
ClientRenderState rs = this.ClientRenderStateRef.get();
if (rs == null)
{
return new String[] { LodUtil.formatLog("level @ {}: Inactive", this.serverLevel.getDimensionType().getDimensionName()) };
}
else
{
return new String[] {
LodUtil.formatLog("level @ {}: Active", this.serverLevel.getDimensionType().getDimensionName())
};
}
}
@Override
public void dumpRamUsage()
{
//TODO
LOGGER.info("Started "+DhClientServerLevel.class.getSimpleName()+" for "+ serverLevelWrapper +" with saves at "+saveStructure);
}
@@ -111,33 +69,12 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
@Override
public void clientTick()
{
ClientRenderState clientRenderState = this.ClientRenderStateRef.get();
if (clientRenderState == null)
if (!super.baseClientTick())
{
return;
}
if (clientRenderState.quadtree.blockRenderDistance != Config.Client.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH)
{
if (!this.ClientRenderStateRef.compareAndSet(clientRenderState, null))
{
return; //If we fail, we'll just wait for the next tick
}
IClientLevelWrapper levelWrapper = clientRenderState.clientLevel;
clientRenderState.closeAsync().join(); //TODO: Make it async.
clientRenderState = new ClientRenderState(this, levelWrapper);
if (!this.ClientRenderStateRef.compareAndSet(null, clientRenderState))
{
//FIXME: How to handle this?
LOGGER.warn("Failed to set render state due to concurrency after changing view distance");
clientRenderState.closeAsync();
return;
}
}
clientRenderState.quadtree.tick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos()));
clientRenderState.renderer.bufferHandler.update();
// additional tick logic can be added if necessary
}
@Override
@@ -195,13 +132,7 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
public void startRenderer(IClientLevelWrapper clientLevel)
{
LOGGER.info("Starting renderer for "+this);
ClientRenderState ClientRenderState = new ClientRenderState(this, clientLevel);
if (!this.ClientRenderStateRef.compareAndSet(null, ClientRenderState))
{
LOGGER.warn("Failed to start renderer due to concurrency");
ClientRenderState.closeAsync();
}
else
if (super.setAndStartRenderer())
{
this.worldGeneratorEnabledConfig.pollNewValue();
if (this.worldGeneratorEnabledConfig.get() && this.worldGenStateRef.get() == null)
@@ -217,38 +148,9 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
}
}
@Override
public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler)
{
ClientRenderState ClientRenderState = this.ClientRenderStateRef.get();
if (ClientRenderState == null)
{
LOGGER.error("Tried to call render() on "+this+" when renderer has not been started!");
return;
}
ClientRenderState.renderer.drawLODs(mcModelViewMatrix, mcProjectionMatrix, partialTicks, profiler);
}
public void stopRenderer()
{
LOGGER.info("Stopping renderer for "+this);
ClientRenderState ClientRenderState = this.ClientRenderStateRef.get();
if (ClientRenderState == null)
{
LOGGER.warn("Tried to stop renderer for "+this+" when it was not started!");
return;
}
// stop the render state
while (!this.ClientRenderStateRef.compareAndSet(ClientRenderState, null)) // TODO why is there a while loop here?
{
ClientRenderState = this.ClientRenderStateRef.get();
if (ClientRenderState == null)
{
return;
}
}
ClientRenderState.closeAsync().join(); //TODO: Make it async.
super.stopRenderer();
// stop the world generator
WorldGenState worldGenState = this.worldGenStateRef.get();
@@ -272,7 +174,7 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
// level handling //
//================//
@Override //FIXME // why is this labeled "fixme"?
@Override //FIXME this can fail if the clientLevel hasn't been created yet
public int computeBaseColor(DhBlockPos pos, IBiomeWrapper biome, IBlockStateWrapper block)
{
IClientLevelWrapper clientLevel = this.getClientLevelWrapper();
@@ -287,19 +189,12 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
}
@Override
public IClientLevelWrapper getClientLevelWrapper()
{
ClientRenderState ClientRenderState = this.ClientRenderStateRef.get();
return ClientRenderState == null ? null : ClientRenderState.clientLevel;
}
public IServerLevelWrapper getServerLevelWrapper() { return this.serverLevelWrapper; }
@Override
public IServerLevelWrapper getServerLevelWrapper() { return this.serverLevel; }
public ILevelWrapper getLevelWrapper() { return this.serverLevelWrapper; }
@Override
public ILevelWrapper getLevelWrapper() { return this.serverLevel; }
@Override
public int getMinY() { return this.serverLevel.getMinHeight(); }
public int getMinY() { return this.serverLevelWrapper.getMinHeight(); }
@@ -307,89 +202,31 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
// data handling //
//===============//
@Override
public void updateChunkAsync(IChunkWrapper chunk)
{
CompletableFuture<ChunkSizedFullDataSource> future = this.chunkToLodBuilder.tryGenerateData(chunk);
if (future != null)
{
future.thenAccept(this::saveWrites);
}
}
private void saveWrites(ChunkSizedFullDataSource data)
{
ClientRenderState ClientRenderState = this.ClientRenderStateRef.get();
DhLodPos pos = data.getBBoxLodPos().convertToDetailLevel(FullDataSource.SECTION_SIZE_OFFSET);
if (ClientRenderState != null)
{
ClientRenderState.renderSourceFileHandler.write(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data);
}
else
{
this.fullDataFileHandler.write(new DhSectionPos(pos.detailLevel, pos.x, pos.z), data);
}
}
@Override
public CompletableFuture<Void> saveAsync()
{
ClientRenderState ClientRenderState = this.ClientRenderStateRef.get();
if (ClientRenderState != null)
{
return ClientRenderState.renderSourceFileHandler.flushAndSave().thenCombine(this.fullDataFileHandler.flushAndSave(), (voidA, voidB) -> null);
}
else
{
return this.fullDataFileHandler.flushAndSave();
}
}
@Override
public void close()
{
ClientRenderState ClientRenderState = this.ClientRenderStateRef.get();
if (ClientRenderState != null)
super.baseClose();
WorldGenState worldGenState = this.worldGenStateRef.get();
if (worldGenState != null)
{
while (!this.ClientRenderStateRef.compareAndSet(ClientRenderState, null))
// TODO does this have to be in a while loop, if so why?
while (!this.worldGenStateRef.compareAndSet(worldGenState, null))
{
ClientRenderState = this.ClientRenderStateRef.get();
if (ClientRenderState == null)
worldGenState = this.worldGenStateRef.get();
if (worldGenState == null)
{
return;
break;
}
}
ClientRenderState.closeAsync().join(); //TODO: Make this async.
}
WorldGenState wgs = this.worldGenStateRef.get();
if (wgs != null)
{
while (!this.worldGenStateRef.compareAndSet(wgs, null))
if (worldGenState != null)
{
wgs = this.worldGenStateRef.get();
if (wgs == null)
{
return;
}
worldGenState.closeAsync(true).join(); //TODO: Make it async.
}
wgs.closeAsync(true).join(); //TODO: Make it async.
}
LOGGER.info("Closed "+this);
}
@Override
public IFullDataSourceProvider getFileHandler() { return this.fullDataFileHandler; }
@Override
public void clearRenderDataCache()
{
ClientRenderState ClientRenderState = this.ClientRenderStateRef.get();
if (ClientRenderState != null && ClientRenderState.quadtree != null)
{
ClientRenderState.quadtree.clearRenderDataCache();
}
LOGGER.info("Closed "+DhClientLevel.class.getSimpleName()+" for "+this.serverLevelWrapper);
}
@@ -420,14 +257,14 @@ public class DhClientServerLevel implements IDhClientLevel, IDhServerLevel
this.chunkGenerator = worldGenerator;
this.worldGenerationQueue = new WorldGenerationQueue(this.chunkGenerator);
DhClientServerLevel.this.fullDataFileHandler.setGenerationQueue(this.worldGenerationQueue);
DhClientServerLevel.this.generatedFullDataFileHandler.setGenerationQueue(this.worldGenerationQueue);
}
CompletableFuture<Void> closeAsync(boolean doInterrupt)
{
DhClientServerLevel.this.fullDataFileHandler.clearGenerationQueue();
DhClientServerLevel.this.generatedFullDataFileHandler.clearGenerationQueue();
return this.worldGenerationQueue.startClosing(true, doInterrupt)
.exceptionally(ex ->
{
@@ -24,8 +24,8 @@ public class DhServerLevel implements IDhServerLevel
{
this.save = save;
this.level = level;
save.getDataFolder(level).mkdirs();
this.dataFileHandler = new FullDataFileHandler(this, save.getDataFolder(level)); //FIXME: GenerationQueue
save.getFullDataFolder(level).mkdirs();
this.dataFileHandler = new FullDataFileHandler(this, save.getFullDataFolder(level)); //FIXME: GenerationQueue
FileScanUtil.scanFiles(save, level, this.dataFileHandler, null);
LOGGER.info("Started DHLevel for {} with saves at {}", level, save);
}
@@ -9,7 +9,6 @@ import com.seibel.lod.core.wrapperInterfaces.world.IClientLevelWrapper;
public interface IDhClientLevel extends IDhLevel
{
/** Return whether the level needs to be reloaded */
void clientTick();
void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler);
@@ -28,29 +28,17 @@ public class ClientRenderState
public final LodRenderer renderer;
// TODO combine
public ClientRenderState(DhClientServerLevel parent, IClientLevelWrapper clientLevel)
{
this.clientLevel = clientLevel;
this.renderSourceFileHandler = new RenderSourceFileHandler(parent.fullDataFileHandler, parent, parent.saveStructure.getRenderCacheFolder(parent.serverLevel));
this.quadtree = new LodQuadTree(parent, Config.Client.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH,
MC_CLIENT.getPlayerBlockPos().x, MC_CLIENT.getPlayerBlockPos().z, this.renderSourceFileHandler);
RenderBufferHandler renderBufferHandler = new RenderBufferHandler(this.quadtree);
FileScanUtil.scanFiles(parent.saveStructure, parent.serverLevel, null, this.renderSourceFileHandler);
this.renderer = new LodRenderer(renderBufferHandler);
}
public ClientRenderState(DhClientLevel parent, IClientLevelWrapper clientLevel)
{
this.clientLevel = clientLevel;
this.renderSourceFileHandler = new RenderSourceFileHandler(parent.fullDataFileHandler, parent, parent.saveStructure.getRenderCacheFolder(parent.clientLevel));
this.renderSourceFileHandler = new RenderSourceFileHandler(parent.fullDataFileHandler, parent, parent.saveStructure.getRenderCacheFolder(parent.getLevelWrapper()));
this.quadtree = new LodQuadTree(parent, Config.Client.Graphics.Quality.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH,
MC_CLIENT.getPlayerBlockPos().x, MC_CLIENT.getPlayerBlockPos().z, this.renderSourceFileHandler);
RenderBufferHandler renderBufferHandler = new RenderBufferHandler(this.quadtree);
FileScanUtil.scanFiles(parent.saveStructure, parent.clientLevel, null, this.renderSourceFileHandler);
FileScanUtil.scanFiles(parent.saveStructure, parent.getLevelWrapper(), null, this.renderSourceFileHandler);
this.renderer = new LodRenderer(renderBufferHandler);
}
@@ -26,7 +26,7 @@ public class FileScanUtil
{
if (dataSourceProvider != null)
{
try (Stream<Path> pathStream = Files.walk(saveStructure.getDataFolder(levelWrapper).toPath(), MAX_SCAN_DEPTH))
try (Stream<Path> pathStream = Files.walk(saveStructure.getFullDataFolder(levelWrapper).toPath(), MAX_SCAN_DEPTH))
{
dataSourceProvider.addScannedFile(pathStream.filter(
path -> path.toFile().getName().endsWith(LOD_FILE_POSTFIX) && path.toFile().isFile()
@@ -35,7 +35,7 @@ public class FileScanUtil
}
catch (Exception e)
{
LOGGER.error("Failed to scan and collect data files for {} in {}", levelWrapper, saveStructure, e);
LOGGER.error("Failed to scan and collect full data files for "+levelWrapper+" in "+saveStructure, e);
}
}
@@ -50,7 +50,7 @@ public class FileScanUtil
}
catch (Exception e)
{
LOGGER.error("Failed to scan and collect data files for {} in {}", levelWrapper, saveStructure, e);
LOGGER.error("Failed to scan and collect cache files for "+levelWrapper+" in "+saveStructure, e);
}
}
}
@@ -50,7 +50,7 @@ public class DhClientServerWorld extends AbstractDhWorld implements IDhClientWor
{
return this.levelObjMap.computeIfAbsent(wrapper, (levelWrapper) ->
{
File levelFile = this.saveStructure.tryGetOrCreateLevelFolder(levelWrapper);
File levelFile = this.saveStructure.getLevelFolder(levelWrapper);
LodUtil.assertTrue(levelFile != null);
DhClientServerLevel level = new DhClientServerLevel(this.saveStructure, (IServerLevelWrapper) levelWrapper);
this.dhLevels.add(level);
@@ -132,7 +132,7 @@ public class DhClientServerWorld extends AbstractDhWorld implements IDhClientWor
for (DhClientServerLevel level : this.dhLevels)
{
LOGGER.info("Unloading level " + level.serverLevel.getDimensionType().getDimensionName());
LOGGER.info("Unloading level " + level.serverLevelWrapper.getDimensionType().getDimensionName());
level.close();
}
@@ -46,7 +46,7 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld
return this.levels.computeIfAbsent((IClientLevelWrapper) wrapper, (clientLevelWrapper) ->
{
File file = this.saveStructure.tryGetOrCreateLevelFolder(wrapper);
File file = this.saveStructure.getLevelFolder(wrapper);
if (file == null)
{
return null;
@@ -121,7 +121,7 @@ public class DhClientWorld extends AbstractDhWorld implements IDhClientWorld
this.saveAndFlush().join();
for (DhClientLevel level : this.levels.values())
{
LOGGER.info("Unloading level " + level.clientLevel.getDimensionType().getDimensionName());
LOGGER.info("Unloading level " + level.clientLevelWrapper.getDimensionType().getDimensionName());
level.close();
}
@@ -40,7 +40,7 @@ public class DhServerWorld extends AbstractDhWorld implements IDhServerWorld
return this.levels.computeIfAbsent((IServerLevelWrapper) wrapper, (w) ->
{
File levelFile = this.saveStructure.tryGetOrCreateLevelFolder(wrapper);
File levelFile = this.saveStructure.getLevelFolder(wrapper);
LodUtil.assertTrue(levelFile != null);
return new DhServerLevel(this.saveStructure, w);
});
@@ -5,7 +5,7 @@ import java.io.File;
public interface IServerLevelWrapper extends ILevelWrapper {
@Nullable
IClientLevelWrapper tryGetClientSideWrapper();
IClientLevelWrapper tryGetClientLevelWrapper();
File getSaveFolder();
}