This commit is contained in:
James Seibel
2022-07-01 21:21:56 -05:00
26 changed files with 223 additions and 260 deletions
@@ -1,13 +1,9 @@
package com.seibel.lod.core.a7;
import com.seibel.lod.core.a7.datatype.column.ColumnRenderLoader;
import com.seibel.lod.core.a7.render.LodQuadTree;
public class Initializer {
public static void init() {
ColumnRenderLoader columnRenderLoader = new ColumnRenderLoader();
LodQuadTree.registerLayerLoader(columnRenderLoader, (byte) 7); // 7 or above
ColumnRenderLoader unused = new ColumnRenderLoader(); // Auto register into the loader system
}
}
@@ -47,7 +47,11 @@ public class EmptyRenderSource implements LodRenderSource {
}
@Override
public void update(DHChunkPos chunkPos, ChunkSizedData chunkData) {
public void update(ChunkSizedData chunkData) {
}
@Override
public byte getRenderVersion() {
return 0;
}
}
@@ -10,11 +10,10 @@ import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.a7.render.RenderBuffer;
import com.seibel.lod.core.a7.save.io.render.RenderMetaFile;
import com.seibel.lod.core.enums.ELodDirection;
import com.seibel.lod.core.objects.DHChunkPos;
import com.seibel.lod.core.objects.LodDataView;
import com.seibel.lod.core.a7.level.ILevel;
import com.seibel.lod.core.a7.render.LodQuadTree;
import com.seibel.lod.core.a7.render.LodSection;
import com.seibel.lod.core.a7.render.LodRenderSection;
import com.seibel.lod.core.a7.datatype.LodRenderSource;
import java.io.DataInputStream;
@@ -256,7 +255,7 @@ public class ColumnRenderSource implements LodRenderSource, IColumnDatatype {
if (inBuildRenderBuffer == null) {
ColumnRenderSource[] data = new ColumnRenderSource[ELodDirection.ADJ_DIRECTIONS.length];
for (ELodDirection direction : ELodDirection.ADJ_DIRECTIONS) {
LodSection section = quadTree.getSection(sectionPos.getAdjacent(direction)); //FIXME: Handle traveling through different detail levels
LodRenderSection section = quadTree.getSection(sectionPos.getAdjacent(direction)); //FIXME: Handle traveling through different detail levels
if (section.getRenderContainer() != null && section.getRenderContainer() instanceof ColumnRenderBuffer) {
data[direction.ordinal()-2] = ((ColumnRenderSource) section.getRenderContainer());
}
@@ -9,15 +9,18 @@ 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.logging.DhLoggerBuilder;
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 org.apache.logging.log4j.Logger;
import java.util.concurrent.CompletableFuture;
public class DhClientLevel implements IClientLevel {
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private static final IMinecraftClientWrapper MC_CLIENT = SingletonHandler.get(IMinecraftClientWrapper.class);
public final ClientOnlySaveStructure save;
public final RemoteDataFileHandler dataFileHandler;
@@ -29,18 +32,16 @@ public class DhClientLevel implements IClientLevel {
public DhClientLevel(ClientOnlySaveStructure save, ILevelWrapper level) {
this.save = save;
save.getDataFolder(level).mkdirs();
save.getRenderCacheFolder(level).mkdirs();
dataFileHandler = new RemoteDataFileHandler();
renderFileHandler = new RenderFileHandler(dataFileHandler, save.getRenderCacheFolder(level));
renderFileHandler = new RenderFileHandler(dataFileHandler, this, 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;
FileScanner.scanFile(save, level, dataFileHandler, renderFileHandler);
}
public void tick() {
tree.tick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos()));
renderBufferHandler.update();
LOGGER.info("Started DHLevel for {} with saves at {}", level, save);
}
@Override
@@ -48,6 +49,12 @@ public class DhClientLevel implements IClientLevel {
//TODO
}
@Override
public void clientTick() {
tree.tick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos()));
renderBufferHandler.update();
}
@Override
public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) {
if (renderer == null) {
@@ -74,5 +81,6 @@ public class DhClientLevel implements IClientLevel {
@Override
public void close() {
renderFileHandler.close();
LOGGER.info("Closed DHLevel for {}", level);
}
}
@@ -9,49 +9,62 @@ 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.logging.DhLoggerBuilder;
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 org.apache.logging.log4j.Logger;
import java.util.concurrent.CompletableFuture;
public class DhClientServerLevel implements IClientLevel, IServerLevel {
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
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 RenderFileHandler renderFileHandler = null;
public RenderBufferHandler renderBufferHandler = null; //TODO: Should this be owned by renderer?
public final ILevelWrapper level;
public a7LodRenderer renderer = null;
public LodQuadTree tree;
public LodQuadTree tree = null;
public DhClientServerLevel(LocalSaveStructure save, ILevelWrapper level) {
this.level = level;
this.save = save;
save.getDataFolder(level).mkdirs();
save.getRenderCacheFolder(level).mkdirs();
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);
FileScanner.scanFile(save, level, dataFileHandler, renderFileHandler);
LOGGER.info("Started DHLevel for {} with saves at {}", level, save);
}
public void clientTick() {
tree.tick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos()));
renderBufferHandler.update();
if (tree != null) tree.tick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos()));
if (renderBufferHandler != null) renderBufferHandler.update();
}
public void serverTick() {
//TODO Update network packet and stuff or state or etc..
}
public void startRenderer() {
//TODO
if (renderBufferHandler != null) {
LOGGER.warn("Tried to call startRenderer() on the clientServerLevel {} when renderer is already setup!", level);
return;
}
renderFileHandler = new RenderFileHandler(dataFileHandler, this, 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);
FileScanner.scanFile(save, level, dataFileHandler, renderFileHandler);
}
@Override
public void render(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler) {
if (renderBufferHandler == null) {
LOGGER.error("Tried to call render() on the clientServerLevel {} when renderer has not been started!", level);
return;
}
if (renderer == null) {
renderer = new a7LodRenderer(this);
}
@@ -59,8 +72,16 @@ public class DhClientServerLevel implements IClientLevel, IServerLevel {
}
public void stopRenderer() {
if (renderBufferHandler == null) {
LOGGER.warn("Tried to call stopRenderer() on the clientServerLevel {} when renderer is already closed!", level);
return;
}
renderBufferHandler.close();
renderBufferHandler = null;
tree = null; //TODO Close the tree
renderFileHandler.flushAndSave(); //Ignore the completion feature so that this action is async
//TODO
renderFileHandler.close();
renderFileHandler = null;
}
@Override
@@ -80,14 +101,14 @@ public class DhClientServerLevel implements IClientLevel, IServerLevel {
@Override
public CompletableFuture<Void> save() {
return renderFileHandler.flushAndSave();
return renderFileHandler == null ? dataFileHandler.flushAndSave() : renderFileHandler.flushAndSave();
//Note: saving renderFileHandler will also save the dataFileHandler.
}
@Override
public void close() {
renderFileHandler.close();
//Note: Closing renderFileHandler will also close the dataFileHandler.
dataFileHandler.close();
LOGGER.info("Closed DHLevel for {}", level);
}
@Override
@@ -3,11 +3,15 @@ package com.seibel.lod.core.a7.level;
import com.seibel.lod.core.a7.util.FileScanner;
import com.seibel.lod.core.a7.save.io.file.LocalDataFileHandler;
import com.seibel.lod.core.a7.save.structure.LocalSaveStructure;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import org.apache.logging.log4j.Logger;
import java.util.concurrent.CompletableFuture;
public class DhServerLevel implements IServerLevel {
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public final LocalSaveStructure save;
public final LocalDataFileHandler dataFileHandler;
public final ILevelWrapper level;
@@ -15,8 +19,10 @@ public class DhServerLevel implements IServerLevel {
public DhServerLevel(LocalSaveStructure save, ILevelWrapper level) {
this.save = save;
this.level = level;
save.getDataFolder(level).mkdirs();
dataFileHandler = new LocalDataFileHandler(this, save.getDataFolder(level));
FileScanner.scanFile(save, level, dataFileHandler, null);
LOGGER.info("Started DHLevel for {} with saves at {}", level, save);
}
public void serverTick() {
@@ -35,6 +41,7 @@ public class DhServerLevel implements IServerLevel {
@Override
public void close() {
dataFileHandler.close();
LOGGER.info("Closed DHLevel for {}", level);
}
@Override
public CompletableFuture<Void> save() {
@@ -1,6 +1,6 @@
package com.seibel.lod.core.a7.render;
import com.seibel.lod.core.a7.datatype.RenderSourceLoader;
import com.seibel.lod.core.a7.datatype.column.ColumnRenderSource;
import com.seibel.lod.core.a7.pos.DhBlockPos2D;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.a7.save.io.render.IRenderSourceProvider;
@@ -10,8 +10,6 @@ import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.util.gridList.MovableGridRingList;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
// QuadTree built from several layers of 2d ring buffers
/**
@@ -29,71 +27,24 @@ public class LodQuadTree {
* Note: all config value should be via the class that extends this class, and
* by implementing different abstract methods
*/
private static final byte LAYER_BEGINNING_OFFSET = ColumnRenderSource.SECTION_SIZE_OFFSET;
public final byte getLayerDataDetailOffset(byte sectionDetail) {
return ColumnRenderSource.SECTION_SIZE_OFFSET;
}
public final byte getLayerSectionDetailOffset(byte dataDetail) {
return ColumnRenderSource.SECTION_SIZE_OFFSET;
}
public final byte getLayerDataDetail(byte sectionDetail) {
return (byte) (sectionDetail - getLayerDataDetailOffset(sectionDetail));
}
public final byte getLayerSectionDetail(byte dataDetail) {
return (byte) (dataDetail + getLayerSectionDetailOffset(dataDetail));
}
private static final Logger LOGGER = DhLoggerBuilder.getLogger("LodQuadTree");
public final byte numbersOfSectionLevels;
public final byte startingSectionLevel;
private final MovableGridRingList<LodSection>[] ringLists;
static final ArrayList<RenderSourceLoader> layerLoaderConfig = new ArrayList<>();
static final Logger LOGGER = DhLoggerBuilder.getLogger("LodQuadTree");
public static void registerLayerLoader(RenderSourceLoader loader, byte sectionLevel) {
LOGGER.info("Registering loader for section level " + sectionLevel + " for " + loader.getClass().getSimpleName());
while (layerLoaderConfig.size() <= sectionLevel) {
layerLoaderConfig.add(null);
}
if (layerLoaderConfig.set(sectionLevel, loader) != null) {
throw new RuntimeException("Layer loader for level " + sectionLevel + " has a registry conflict!");
}
}
// static {
// Collections.addAll(layerLoaderConfig,
// null,
// null, //1
// null, //2
// null, //3
// new ContainerTypeConfigEntry(FullDatatype.class, (byte) 4), //4 -> 0
// null, //5 force breaks down to 4 -> 0
// null, //6 force breaks down to 4 -> 0
// new ContainerTypeConfigEntry(ColumnDatatype.class, ColumnDatatype.SECTION_SIZE_OFFSET), //7 -> 1
// new ContainerTypeConfigEntry(ColumnDatatype.class, ColumnDatatype.SECTION_SIZE_OFFSET) //8 -> 2
// // ... And same onwards
// );
// }
static class SectionDetailLayer {
final byte targetDataDetail;
final RenderSourceLoader containerType;
public SectionDetailLayer(byte targetDataDetail, RenderSourceLoader containerType) {
this.targetDataDetail = targetDataDetail;
this.containerType = containerType;
}
}
static void assertContainerTypeConfigCorrect() {
boolean isInFront = true;
for (int i = 0; i < layerLoaderConfig.size(); i++) {
if (layerLoaderConfig.get(i) == null) continue;
isInFront = false;
RenderSourceLoader entry = layerLoaderConfig.get(i);
if (i - entry.detailOffset < 0) {
throw new RuntimeException("ContainerTypeConfigEntry " + i + " has a levelOffset of "
+ entry.detailOffset + " which makes the dataDetail be " + (i - entry.detailOffset) + "," +
" which is less than 0!");
}
if (entry.detailOffset < 0) {
throw new RuntimeException("ContainerTypeConfigEntry " + i + " has a levelOffset of "
+ entry.detailOffset + " which is less than 0!");
}
}
if (layerLoaderConfig.get(layerLoaderConfig.size()-1) == null) {
throw new RuntimeException("The last ContainerTypeConfigEntry is null, which is invalid!");
}
}
final SectionDetailLayer[] sectionDetailLayers;
private final MovableGridRingList<LodRenderSection>[] ringLists;
public final int viewDistance;
private final IRenderSourceProvider renderSourceProvider;
@@ -105,63 +56,21 @@ public class LodQuadTree {
*/
public LodQuadTree(int viewDistance, int initialPlayerX, int initialPlayerZ, IRenderSourceProvider provider) {
renderSourceProvider = provider;
assertContainerTypeConfigCorrect();
this.viewDistance = viewDistance;
//FIXME: Rework this mess of code!
{ // Calculate the max section detail
byte maxDetailLevel = getMaxDetailInRange(viewDistance * Math.sqrt(2));
RenderSourceLoader finalEntry = null;
byte topSectionLevel = 0;
byte firstLevel = -1;
for (; topSectionLevel < layerLoaderConfig.size(); topSectionLevel++) {
if (layerLoaderConfig.get(topSectionLevel) == null) continue;
finalEntry = layerLoaderConfig.get(topSectionLevel);
if (firstLevel == -1) firstLevel = topSectionLevel;
if (topSectionLevel - finalEntry.detailOffset >= maxDetailLevel) break;
}
if (finalEntry == null) throw new RuntimeException("No container type found!");
if (topSectionLevel == layerLoaderConfig.size())
topSectionLevel = (byte) (maxDetailLevel + finalEntry.detailOffset);
byte maxDataDetailLevel = getMaxDetailInRange(viewDistance * Math.sqrt(2));
byte topSectionLevel = getLayerSectionDetail(maxDataDetailLevel);
numbersOfSectionLevels = (byte) (topSectionLevel + 1);
startingSectionLevel = firstLevel;
LOGGER.info("MaxLevel: " + maxDetailLevel + ", StartingLevel: " + startingSectionLevel + ", NumberOfLevels: " + numbersOfSectionLevels
+ ", TopSectionLevel: " + topSectionLevel + ", FinalEntry: " + finalEntry);
sectionDetailLayers = new SectionDetailLayer[numbersOfSectionLevels - startingSectionLevel];
ringLists = new MovableGridRingList[numbersOfSectionLevels - startingSectionLevel];
ringLists = new MovableGridRingList[numbersOfSectionLevels - LAYER_BEGINNING_OFFSET];
}
{ // Fill in the sectionDetailLayers info and construct the ringLists
byte lastNonNullEntry = -1;
for (byte i = startingSectionLevel; i < numbersOfSectionLevels; i++) {
byte targetDataDetail;
RenderSourceLoader containerType;
if (i < layerLoaderConfig.size()) {
if (layerLoaderConfig.get(i) == null) {
if (lastNonNullEntry == -1) continue;
targetDataDetail = sectionDetailLayers[lastNonNullEntry].targetDataDetail;
containerType = null;
} else {
lastNonNullEntry = i;
RenderSourceLoader entry = layerLoaderConfig.get(i);
targetDataDetail = (byte) (i - entry.detailOffset);
containerType = entry;
}
} else {
LodUtil.assertTrue(layerLoaderConfig.get(layerLoaderConfig.size() - 1) != null,
"The last entry must not be null!");
RenderSourceLoader entry = layerLoaderConfig.get(layerLoaderConfig.size() - 1);
targetDataDetail = (byte) (i - entry.detailOffset);
containerType = entry;
}
LodUtil.assertTrue(targetDataDetail >= 0, "dataDetail must be >= 0!");
{ // Construct the ringLists
for (byte i = LAYER_BEGINNING_OFFSET; i < numbersOfSectionLevels; i++) {
byte targetDataDetail = getLayerDataDetail(i);
int maxDist = getFurthestDistance(targetDataDetail);
int halfSize = LodUtil.ceilDiv(maxDist, (1 << i) + 2);
sectionDetailLayers[i - startingSectionLevel] = new SectionDetailLayer(targetDataDetail, containerType);
ringLists[i - startingSectionLevel] = new MovableGridRingList<LodSection>(halfSize,
ringLists[i - LAYER_BEGINNING_OFFSET] = new MovableGridRingList<>(halfSize,
initialPlayerX >> i, initialPlayerZ >> i);
}
}
@@ -173,29 +82,18 @@ public class LodQuadTree {
* @param pos the section positon.
* @return the LodSection
*/
public LodSection getSection(DhSectionPos pos) {
public LodRenderSection getSection(DhSectionPos pos) {
return getSection(pos.sectionDetail, pos.sectionX, pos.sectionZ);
}
public byte getFirstSectionDetailFromDataDetail(byte dataDetail) {
if (dataDetail <= startingSectionLevel) return startingSectionLevel;
for (byte i = 0; i < sectionDetailLayers.length; i++) {
if (sectionDetailLayers[i].targetDataDetail >= dataDetail) return (byte) (i + startingSectionLevel);
}
throw new RuntimeException("No section detail for dataDetail " + dataDetail+ " found!");
}
public byte getDataDetail(byte sectionDetail) {
return sectionDetailLayers[sectionDetail - startingSectionLevel].targetDataDetail;
}
/**
* This method returns the RingList of a given detail level
* @apiNote The returned ringList should not be modified!
* @param detailLevel the detail level
* @return the RingList
*/
public MovableGridRingList<LodSection> getRingList(byte detailLevel) {
return ringLists[detailLevel - startingSectionLevel];
public MovableGridRingList<LodRenderSection> getRingList(byte detailLevel) {
return ringLists[detailLevel - LAYER_BEGINNING_OFFSET];
}
/**
@@ -207,7 +105,7 @@ public class LodQuadTree {
}
public byte getStartingSectionLevel() {
return startingSectionLevel;
return LAYER_BEGINNING_OFFSET;
}
/**
@@ -217,8 +115,8 @@ public class LodQuadTree {
* @param z z coordinate of the section
* @return the LodSection
*/
public LodSection getSection(byte detailLevel, int x, int z) {
return ringLists[detailLevel - startingSectionLevel].get(x, z);
public LodRenderSection getSection(byte detailLevel, int x, int z) {
return ringLists[detailLevel - LAYER_BEGINNING_OFFSET].get(x, z);
}
@@ -263,7 +161,7 @@ public class LodQuadTree {
* @param pos the section positon
* @return the parent LodSection
*/
public LodSection getParentSection(DhSectionPos pos) {
public LodRenderSection getParentSection(DhSectionPos pos) {
return getSection(pos.getParent());
}
@@ -274,7 +172,7 @@ public class LodQuadTree {
* @param child0to3 since there are 4 possible children this index identify which one we are getting
* @return one of the child LodSection
*/
public LodSection getChildSection(DhSectionPos pos, int child0to3) {
public LodRenderSection getChildSection(DhSectionPos pos, int child0to3) {
return getSection(pos.getChild(child0to3));
}
@@ -283,10 +181,10 @@ public class LodQuadTree {
* @param playerPos the reference position for the player
*/
public void tick(DhBlockPos2D playerPos) {
for (int sectLevel = startingSectionLevel; sectLevel < numbersOfSectionLevels; sectLevel++) {
ringLists[sectLevel - startingSectionLevel]
for (int sectLevel = LAYER_BEGINNING_OFFSET; sectLevel < numbersOfSectionLevels; sectLevel++) {
ringLists[sectLevel - LAYER_BEGINNING_OFFSET]
.move(playerPos.x >> sectLevel, playerPos.z >> sectLevel,
LodSection::dispose);
LodRenderSection::dispose);
}
// First tick pass: update all sections' childCount from bottom level to top level. Step:
@@ -318,14 +216,13 @@ public class LodQuadTree {
// - If targetLevel < dataLevel@(sectLevel+1) && section == null: (use the next level's dataLevel)
// - create new section with childCount = 0
// - Parent's childCount++ (Create parent if needed)
for (byte sectLevel = startingSectionLevel; sectLevel < numbersOfSectionLevels; sectLevel++) {
final MovableGridRingList<LodSection> ringList = ringLists[sectLevel - startingSectionLevel];
final MovableGridRingList<LodSection> childRingList =
sectLevel == startingSectionLevel ? null : ringLists[sectLevel - startingSectionLevel - 1];
final MovableGridRingList<LodSection> parentRingList =
sectLevel == numbersOfSectionLevels - 1 ? null : ringLists[sectLevel - startingSectionLevel + 1];
for (byte sectLevel = LAYER_BEGINNING_OFFSET; sectLevel < numbersOfSectionLevels; sectLevel++) {
final MovableGridRingList<LodRenderSection> ringList = ringLists[sectLevel - LAYER_BEGINNING_OFFSET];
final MovableGridRingList<LodRenderSection> childRingList =
sectLevel == LAYER_BEGINNING_OFFSET ? null : ringLists[sectLevel - LAYER_BEGINNING_OFFSET - 1];
final MovableGridRingList<LodRenderSection> parentRingList =
sectLevel == numbersOfSectionLevels - 1 ? null : ringLists[sectLevel - LAYER_BEGINNING_OFFSET + 1];
final byte f_sectLevel = sectLevel;
RenderSourceLoader containerType = sectionDetailLayers[sectLevel - startingSectionLevel].containerType;
ringList.forEachPosOrdered((section, pos) -> {
if (f_sectLevel == 0 && section != null) {
section.childCount = 0;
@@ -333,19 +230,19 @@ public class LodQuadTree {
if (section != null && section.childCount != 0) {
// Section will be in the unloaded state.
LodUtil.assertTrue(parentRingList != null);
LodSection parent = parentRingList.get(pos.x >> 1, pos.y >> 1);
LodRenderSection parent = parentRingList.get(pos.x >> 1, pos.y >> 1);
if (parent == null) {
parent = parentRingList.setChained(pos.x >> 1, pos.y >> 1,
new LodSection(section.pos.getParent()));
new LodRenderSection(section.pos.getParent()));
parent.childCount++;
}
LodUtil.assertTrue(parent.childCount <= 4 && parent.childCount > 0);
for (byte i = 0; i < 4; i++) {
DhSectionPos childPos = section.pos.getChild(i);
LodSection child = childRingList.get(childPos.sectionX, childPos.sectionZ);
LodRenderSection child = childRingList.get(childPos.sectionX, childPos.sectionZ);
if (child == null) {
child = childRingList.setChained(childPos.sectionX, childPos.sectionZ,
new LodSection(childPos));
new LodRenderSection(childPos));
child.childCount = 0;
} else if (child.childCount == -1) {
child.childCount = 0;
@@ -357,31 +254,31 @@ public class LodQuadTree {
byte targetLevel = calculateExpectedDetailLevel(playerPos, sectPos);
if (f_sectLevel == numbersOfSectionLevels -1) {
// Section is in the top level.
if (targetLevel > getDataDetail(f_sectLevel) && section != null) {
if (targetLevel > getLayerDataDetail(f_sectLevel) && section != null) {
section.childCount = -1;
}
if (targetLevel <= getDataDetail(f_sectLevel) && section == null) {
if (targetLevel <= getLayerDataDetail(f_sectLevel) && section == null) {
section = ringList.setChained(pos.x, pos.y,
new LodSection(sectPos));
new LodRenderSection(sectPos));
}
} else {
// Section is not the top level. So we also need to consider the parent.
if (targetLevel >= getDataDetail((byte) (f_sectLevel+1)) && section != null) {
if (targetLevel >= getLayerDataDetail((byte) (f_sectLevel+1)) && section != null) {
LodUtil.assertTrue(parentRingList != null);
LodSection parent = parentRingList.get(pos.x >> 1, pos.y >> 1);
LodRenderSection parent = parentRingList.get(pos.x >> 1, pos.y >> 1);
LodUtil.assertTrue(parent != null);
LodUtil.assertTrue(parent.childCount <= 4 && parent.childCount > 0);
parent.childCount--;
section.childCount = -1;
}
if (targetLevel < getDataDetail((byte) (f_sectLevel+1)) && section == null) {
if (targetLevel < getLayerDataDetail((byte) (f_sectLevel+1)) && section == null) {
section = ringList.setChained(pos.x, pos.y,
new LodSection(sectPos));
new LodRenderSection(sectPos));
LodUtil.assertTrue(parentRingList != null);
LodSection parent = parentRingList.get(pos.x >> 1, pos.y >> 1);
LodRenderSection parent = parentRingList.get(pos.x >> 1, pos.y >> 1);
if (parent == null) {
parent = parentRingList.setChained(pos.x >> 1, pos.y >> 1,
new LodSection(sectPos.getParent()));
new LodRenderSection(sectPos.getParent()));
}
parent.childCount++;
}
@@ -397,7 +294,7 @@ public class LodQuadTree {
}
// Second tick pass:
// Cascade the layers that is in Always Cascade Mode from top to bottom. (layer's containerType == null)
// Cascade the layers that is in Always Cascade Mode from top to bottom. (Not yet exposed or used)
// At the same time, load and unload sections (and can also be used to assert everything is working). Step:
// ===Assertion steps===
// assert childCount == 4 || childCount == 0 || childCount == -1
@@ -412,26 +309,24 @@ public class LodQuadTree {
// if childCount == -1: // (section can be loaded or unloaded, due to fast movement)
// - set this section to null (TODO: Is this needed to be first or last or don't matter for concurrency?)
// - If loaded unload section
for (byte sectLevel = (byte) (numbersOfSectionLevels - 1); sectLevel >= startingSectionLevel; sectLevel--) {
final MovableGridRingList<LodSection> ringList = ringLists[sectLevel - startingSectionLevel];
final MovableGridRingList<LodSection> childRingList =
sectLevel == startingSectionLevel ? null : ringLists[sectLevel - startingSectionLevel - 1];
final boolean doCacsade = sectionDetailLayers[sectLevel - startingSectionLevel].containerType == null;
RenderSourceLoader containerType = sectionDetailLayers[sectLevel - startingSectionLevel].containerType;
for (byte sectLevel = (byte) (numbersOfSectionLevels - 1); sectLevel >= LAYER_BEGINNING_OFFSET; sectLevel--) {
final MovableGridRingList<LodRenderSection> ringList = ringLists[sectLevel - LAYER_BEGINNING_OFFSET];
final MovableGridRingList<LodRenderSection> childRingList =
sectLevel == LAYER_BEGINNING_OFFSET ? null : ringLists[sectLevel - LAYER_BEGINNING_OFFSET - 1];
final boolean doCascade = false; // TODO: Utilize this cascade mode or at least expose this option
ringList.forEachPosOrdered((section, pos) -> {
if (section == null) return;
// Cascade layers
if (doCacsade && section.childCount == 0) {
if (doCascade && section.childCount == 0) {
LodUtil.assertTrue(childRingList != null);
// Create childs to cascade the layer.
for (byte i = 0; i < 4; i++) {
DhSectionPos childPos = section.pos.getChild(i);
LodSection child = childRingList.get(childPos.sectionX, childPos.sectionZ);
LodRenderSection child = childRingList.get(childPos.sectionX, childPos.sectionZ);
if (child == null) {
child = childRingList.setChained(childPos.sectionX, childPos.sectionZ,
new LodSection(childPos));
new LodRenderSection(childPos));
child.childCount = 0;
} else {
LodUtil.assertTrue(child.childCount == -1,
@@ -463,7 +358,7 @@ public class LodQuadTree {
section.dispose();
} else {
if (!section.isLoaded() && !section.isLoading()) {
section.load(renderSourceProvider, containerType);
section.load(renderSourceProvider);
}
if (section.childCount == 4) section.enableRender(this);
if (section.childCount == 0) section.disableRender();
@@ -1,15 +1,12 @@
package com.seibel.lod.core.a7.render;
import com.seibel.lod.core.a7.datatype.RenderSourceLoader;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.a7.datatype.LodRenderSource;
import com.seibel.lod.core.a7.save.io.render.IRenderSourceProvider;
import java.util.concurrent.CompletableFuture;
public class LodSection {
public static final int SUB_REGION_DATA_WIDTH = 16*16;
public class LodRenderSection {
public final DhSectionPos pos;
/* Following used for LodQuadTree tick() method, and ONLY for that method! */
@@ -23,7 +20,7 @@ public class LodSection {
private boolean isRenderEnabled = false;
// Create sub region
public LodSection(DhSectionPos pos) {
public LodRenderSection(DhSectionPos pos) {
this.pos = pos;
}
@@ -42,7 +39,7 @@ public class LodSection {
isRenderEnabled = false;
}
public void load(IRenderSourceProvider renderDataProvider, RenderSourceLoader renderDataSourceClass) {
public void load(IRenderSourceProvider renderDataProvider) {
if (loadFuture != null || lodRenderSource != null) throw new IllegalStateException("Reloading is not supported!");
loadFuture = renderDataProvider.read(pos);
}
@@ -40,25 +40,28 @@ public class RenderBufferHandler {
// the buffer is only unloaded if all children's buffers are ready. This will make the
// transition between buffers no longer causing any flicker.
public void update() {
LodSection section = target.getSection(pos);
LodRenderSection section = target.getSection(pos);
// If this fails, there may be concurrent modification of the quad tree
// (as this update() should be called from the same thread that calls update() on the quad tree)
LodUtil.assertTrue(section != null);
LodRenderSource container = section.getRenderContainer();
// Update self's render buffer state
boolean shouldRender = section.isLoaded();
boolean shouldRender = section.canRender();
if (!shouldRender) {
RenderBuffer buff = renderBufferSlot.getAndSet(null);
if (buff != null) {
buff.close();
}
//TODO: Does this really need to force the old buffer to not be rendered?
// RenderBuffer buff = renderBufferSlot.getAndSet(null);
// if (buff != null) {
// buff.close();
// }
} else {
LodUtil.assertTrue(container != null); // section.isLoaded() should have ensured this
container.trySwapRenderBuffer(target, renderBufferSlot);
}
// Update children's render buffer state
// TODO: Improve this! (Checking section.isLoaded() as if its not loaded, it can only be because
// it has children. (But this logic is... really hard to read!)
boolean shouldHaveChildren = !section.isLoaded();
if (shouldHaveChildren) {
if (children == null) {
@@ -73,6 +76,9 @@ public class RenderBufferHandler {
}
} else {
if (children != null) {
//FIXME: Concurrency issue here: If render thread is concurrently using the child's buffer,
// and this thread got priority to close the buffer, it causes a bug wher the render thread
// will be using a closed buffer!!!!
RenderBufferNode[] childs = children;
children = null;
for (RenderBufferNode child : childs) {
@@ -98,7 +104,7 @@ public class RenderBufferHandler {
public RenderBufferHandler(LodQuadTree target) {
this.target = target;
MovableGridRingList<LodSection> referenceList = target.getRingList((byte) (target.getNumbersOfSectionLevels() - 1));
MovableGridRingList<LodRenderSection> referenceList = target.getRingList((byte) (target.getNumbersOfSectionLevels() - 1));
Pos2D center = referenceList.getCenter();
renderBufferNodes = new MovableGridRingList<>(referenceList.getHalfSize(), center);
}
@@ -113,12 +119,12 @@ public class RenderBufferHandler {
public void update() {
byte topDetail = (byte) (target.getNumbersOfSectionLevels() - 1);
MovableGridRingList<LodSection> referenceList = target.getRingList(topDetail);
MovableGridRingList<LodRenderSection> referenceList = target.getRingList(topDetail);
Pos2D center = referenceList.getCenter();
renderBufferNodes.move(center.x, center.y, RenderBufferNode::close); // Note: may lock the list
renderBufferNodes.forEachPosOrdered((node, pos) -> {
DhSectionPos sectPos = new DhSectionPos(topDetail, pos.x, pos.y);
LodSection section = target.getSection(sectPos);
LodRenderSection section = target.getSection(sectPos);
if (section == null) {
// If section is null, but node exists, remove node
@@ -1,6 +1,7 @@
package com.seibel.lod.core.a7.save.io.render;
import com.google.common.collect.HashMultimap;
import com.seibel.lod.core.a7.datatype.EmptyRenderSource;
import com.seibel.lod.core.a7.datatype.LodDataSource;
import com.seibel.lod.core.a7.datatype.LodRenderSource;
import com.seibel.lod.core.a7.datatype.RenderSourceLoader;
@@ -111,7 +112,15 @@ public class RenderFileHandler implements IRenderSourceProvider {
dataSourceProvider::isCacheValid,
dataSourceProvider::read,
level, computeDefaultFilePath(p), p));
return metaFile.loadOrGetCached(renderCacheThread);
return metaFile.loadOrGetCached(renderCacheThread).handle(
(render, e) -> {
if (e != null) {
LOGGER.error("Uncaught error on {}:", pos, e);
}
if (render != null) return render;
return EmptyRenderSource.INSTANCE;
}
);
}
/*
@@ -11,22 +11,27 @@ import java.io.File;
public class LocalSaveStructure extends SaveStructure {
private static final IMinecraftSharedWrapper MC = SingletonHandler.get(IMinecraftSharedWrapper.class);
private File debugPath = new File("");
// Fit for Client_Server & Server_Only environment
public LocalSaveStructure() {
}
@Override
public File tryGetLevelFolder(ILevelWrapper wrapper) {
debugPath = new File(wrapper.getSaveFolder(), "Distant_Horizons");
return new File(wrapper.getSaveFolder(), "Distant_Horizons");
}
@Override
public File getRenderCacheFolder(ILevelWrapper level) {
debugPath = new File(level.getSaveFolder(), "Distant_Horizons");
return new File(new File(level.getSaveFolder(), "Distant_Horizons"), RENDER_CACHE_FOLDER);
}
@Override
public File getDataFolder(ILevelWrapper level) {
debugPath = new File(level.getSaveFolder(), "Distant_Horizons");
return new File(new File(level.getSaveFolder(), "Distant_Horizons"), DATA_FOLDER);
}
@@ -37,6 +42,6 @@ public class LocalSaveStructure extends SaveStructure {
@Override
public String toString() {
return "[LocalSave]";
return "[LocalSave at ["+debugPath+"] ]";
}
}
@@ -28,7 +28,7 @@ public class FileScanner {
).map(Path::toFile).collect(Collectors.toList())
);
} catch (Exception e) {
LOGGER.error("Failed to scan and collect data files for {} in {}", level, save);
LOGGER.error("Failed to scan and collect data files for {} in {}", level, save, e);
}
}
if (renderSource != null) {
@@ -38,7 +38,7 @@ public class FileScanner {
).map(Path::toFile).collect(Collectors.toList())
);
} catch (Exception e) {
LOGGER.error("Failed to scan and collect data files for {} in {}", level, save);
LOGGER.error("Failed to scan and collect data files for {} in {}", level, save, e);
}
}
}
@@ -23,6 +23,7 @@ public class DhClientServerWorld extends DhWorld implements IClientWorld, IServe
super(WorldEnvironment.Client_Server);
saveStructure = new LocalSaveStructure();
levels = new HashMap<>();
LOGGER.info("Started DhWorld of type {}", environment);
}
@Override
@@ -86,6 +87,7 @@ public class DhClientServerWorld extends DhWorld implements IClientWorld, IServe
level.close();
}
levels.clear();
LOGGER.info("Closed DhWorld of type {}", environment);
}
public void enableRendering(ILevelWrapper wrapper) {
@@ -25,6 +25,7 @@ public class DhClientWorld extends DhWorld implements IClientWorld {
super(WorldEnvironment.Client_Only);
saveStructure = new ClientOnlySaveStructure();
levels = new HashMap<>();
LOGGER.info("Started DhWorld of type {}", environment);
}
@Override
@@ -81,5 +82,6 @@ public class DhClientWorld extends DhWorld implements IClientWorld {
level.close();
}
levels.clear();
LOGGER.info("Closed DhWorld of type {}", environment);
}
}
@@ -17,6 +17,7 @@ public class DhServerWorld extends DhWorld implements IServerWorld {
super(WorldEnvironment.Server_Only);
saveStructure = new LocalSaveStructure();
levels = new HashMap<>();
LOGGER.info("Started DhWorld of type {}", environment);
}
@Override
@@ -63,6 +64,7 @@ public class DhServerWorld extends DhWorld implements IServerWorld {
level.close();
}
levels.clear();
LOGGER.info("Closed DhWorld of type {}", environment);
}
@@ -22,7 +22,7 @@ package com.seibel.lod.core.api.internal;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.builders.worldGeneration.BatchGenerator;
import com.seibel.lod.core.config.Config;
import com.seibel.lod.core.enums.EWorldType;
import com.seibel.lod.core.enums.ELevelType;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.objects.DHChunkPos;
@@ -129,14 +129,14 @@ public class EventApi
if (ENABLE_STACK_DUMP_LOGGING)
LOGGER.info(
"WorldLoadEvent called here for "
+ (world.getWorldType() == EWorldType.ClientWorld ? "clientLevel" : "serverLevel"),
+ (world.getLevelType() == ELevelType.ClientLevel ? "clientLevel" : "serverLevel"),
new RuntimeException());
// Always ignore ServerWorld event
if (world.getWorldType() == EWorldType.ServerWorld)
if (world.getLevelType() == ELevelType.ServerLevel)
return;
isCurrentlyOnSinglePlayerServer = MC.hasSinglePlayerServer();
if (!InternalApiShared.isShuttingDown) LOGGER.warn("WorldLoadEvent called on {} while another world is loaded!",
(world.getWorldType() == EWorldType.ClientWorld ? "clientLevel" : "serverLevel"));
(world.getLevelType() == ELevelType.ClientLevel ? "clientLevel" : "serverLevel"));
InternalApiShared.isShuttingDown = false;
//DataPointUtil.WORLD_HEIGHT = world.getHeight();
LodBuilder.MIN_WORLD_HEIGHT = world.getMinHeight(); // This updates the World height
@@ -162,13 +162,13 @@ public class EventApi
if (ENABLE_STACK_DUMP_LOGGING)
LOGGER.info(
"WorldUnloadEvent called here for "
+ (world.getWorldType() == EWorldType.ClientWorld ? "clientLevel" : "serverLevel"),
+ (world.getLevelType() == ELevelType.ClientLevel ? "clientLevel" : "serverLevel"),
new RuntimeException());
// If it's single player, ignore the client side world unload event
// Note: using isCurrentlyOnSinglePlayerServer as often API call unload event
// AFTER setting MC to not be in a singlePlayerServer
if (isCurrentlyOnSinglePlayerServer && world.getWorldType() == EWorldType.ClientWorld)
if (isCurrentlyOnSinglePlayerServer && world.getLevelType() == ELevelType.ClientLevel)
return;
// if this isn't done unfinished tasks may be left in the queue
@@ -179,18 +179,20 @@ public class ClientApi
profiler.pop();
}
public void renderLods(ILevelWrapper world, Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks)
public void renderLods(ILevelWrapper levelWrapper, Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks)
{
IProfilerWrapper profiler = MC.getProfiler();
profiler.pop(); // get out of "terrain"
profiler.push("DH-RenderLevel");
try {
if (!MC.playerExists()) return;
if (world == null) return;
DhWorld DhWorld = SharedApi.currentWorld;
if (DhWorld == null) return;
if (levelWrapper == null) return;
DhWorld dhWorld = SharedApi.currentWorld;
if (dhWorld == null) return;
if (!(SharedApi.currentWorld instanceof IClientWorld)) return;
IClientLevel level = (IClientLevel)SharedApi.currentWorld;
//FIXME: Improve class hierarchy of DhWorld, IClientWorld, IServerWorld to fix all this hard casting
IClientLevel level = (IClientLevel) dhWorld.getOrLoadLevel(levelWrapper);
if (level == null) return; //Level is not ready yet.
if (prefLoggerEnabled) {
level.dumpRamUsage();
@@ -1,5 +1,6 @@
package com.seibel.lod.core.api.internal.a7;
import com.seibel.lod.core.a7.Initializer;
import com.seibel.lod.core.a7.world.WorldEnvironment;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.a7.world.DhWorld;
@@ -7,10 +8,14 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
import org.apache.logging.log4j.Logger;
public class SharedApi {
public static DhWorld currentWorld;
public static final Logger LOGGER = DhLoggerBuilder.getLogger("DH Events");
public static IMinecraftSharedWrapper MC;
public static Logger LOGGER = DhLoggerBuilder.getLogger("DH Events");
public static DhWorld currentWorld;
public static WorldEnvironment getEnvironment() {
return currentWorld==null ? null : currentWorld.environment;
}
public static void init() {
Initializer.init();
}
}
@@ -8,6 +8,7 @@ import com.seibel.lod.core.config.types.AbstractConfigType;
import com.seibel.lod.core.config.types.ConfigEntry;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
@@ -23,7 +24,7 @@ import java.nio.file.Path;
* @version 2022-5-26
*/
public class ConfigFileHandling {
public static final Path ConfigPath = SingletonHandler.get(IMinecraftClientWrapper.class).getGameDirectory().toPath().resolve("config").resolve(ModInfo.NAME+".toml");
public static final Path ConfigPath = SingletonHandler.get(IMinecraftSharedWrapper.class).getInstallationDirectory().toPath().resolve("config").resolve(ModInfo.NAME+".toml");
/** Saves the config to the file */
public static void saveToFile() {
@@ -25,9 +25,9 @@ package com.seibel.lod.core.enums;
* @author James Seibel
* @version 11-12-2021
*/
public enum EWorldType
public enum ELevelType
{
ServerWorld,
ClientWorld,
ServerLevel,
ClientLevel,
Unknown
}
@@ -70,7 +70,7 @@ public class LodDimensionFinder
public static final String THREAD_NAME = "Sub-Dimension-Finder";
public static final String DEFAULT_SAVE_DIMENSION_FOLDER = "_Default-Sub-Dimension";
private PlayerData playerData = new PlayerData(MC);
private PlayerData playerData = null;//new PlayerData(MC);
private PlayerData firstSeenPlayerData = null;
private volatile LodDimension foundLodDimension = null;
@@ -218,7 +218,7 @@ public class LodDimensionFinder
if (firstSeenPlayerData == null)
{
firstSeenPlayerData = playerData;
playerData = new PlayerData(MC);
playerData = null;//new PlayerData(MC);
}
// relevant positions
@@ -571,7 +571,7 @@ public class LodDimensionFinder
// determine the playerData
IMinecraftClientWrapper mc = SingletonHandler.get(IMinecraftClientWrapper.class);
PlayerData playerdata = new PlayerData(mc);
PlayerData playerdata = null;//new PlayerData(mc);
// write the data to file
CommentedFileConfig toml = CommentedFileConfig.builder(file).build();
@@ -70,8 +70,11 @@ public class SingletonHandler
return foundObject;
}
public static <T> T getOrNull(Class<T> interfaceClass) throws ClassCastException
{
return dependencyHandler.get(interfaceClass);
}
/**
* Should only be called after all Binds have been done.
* Calls the delayedSetup method for each dependency. <br> <br>
@@ -41,8 +41,6 @@ public class ColorUtil
public static final int RED = rgbToInt(255,0,0);
private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);
public static int rgbToInt(int red, int green, int blue)
{
return (0xFF << 24) | (red << 16) | (green << 8) | blue;
@@ -41,8 +41,11 @@ import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
/**
* This class holds methods and constants that may be used in multiple places.
@@ -52,11 +55,8 @@ import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
*/
public class LodUtil
{
private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class);
private static final IWrapperFactory FACTORY = SingletonHandler.get(IWrapperFactory.class);
private static final IReflectionHandler REFLECTION_HANDLER = SingletonHandler.get(IReflectionHandler.class);
private static final IVersionConstants VERSION_CONSTANTS = SingletonHandler.get(IVersionConstants.class);
private static final IMinecraftClientWrapper MC_CLIENT = SingletonHandler.getOrNull(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.getOrNull(IMinecraftRenderWrapper.class);
/**
* Vanilla render distances less than or equal to this will not allow partial
@@ -167,10 +167,10 @@ public class LodUtil
*/
public static ILevelWrapper getServerWorldFromDimension(IDimensionTypeWrapper newDimension)
{
if(!MC.hasSinglePlayerServer())
if(!MC_CLIENT.hasSinglePlayerServer())
return null;
Iterable<ILevelWrapper> worlds = MC.getAllServerWorlds();
Iterable<ILevelWrapper> worlds = MC_CLIENT.getAllServerWorlds();
ILevelWrapper returnWorld = null;
for (ILevelWrapper world : worlds)
@@ -202,7 +202,7 @@ public class LodUtil
*/
public static String getWorldID(ILevelWrapper world)
{
if (MC.hasSinglePlayerServer())
if (MC_CLIENT.hasSinglePlayerServer())
{
// chop off the dimension ID as it is not needed/wanted
String dimId = getDimensionIDFromWorld(world);
@@ -231,7 +231,7 @@ public class LodUtil
@Deprecated // FIXME: There are soooo many duplicated methods doing the same thing everywhere
public static String getDimensionIDFromWorld(ILevelWrapper world)
{
if (MC.hasSinglePlayerServer())
if (MC_CLIENT.hasSinglePlayerServer())
{
// this will return the world save location
// and the dimension folder
@@ -254,7 +254,7 @@ public class LodUtil
public static String getServerFolderName()
{
// parse the current server's IP
ParsedIp parsedIp = new ParsedIp(MC.getCurrentServerIp());
ParsedIp parsedIp = new ParsedIp(MC_CLIENT.getCurrentServerIp());
String serverIpCleaned = parsedIp.ip.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
String serverPortCleaned = parsedIp.port != null ? parsedIp.port.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "") : "";
@@ -276,8 +276,8 @@ public class LodUtil
}
String serverName = MC.getCurrentServerName().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
String serverMcVersion = MC.getCurrentServerVersion().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
String serverName = MC_CLIENT.getCurrentServerName().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
String serverMcVersion = MC_CLIENT.getCurrentServerVersion().replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
// generate the folder name
String folderName = "";
@@ -387,8 +387,8 @@ public class LodUtil
return new Pos2D(pos.getX(), pos.getZ());
}
},
MC.getPlayerChunkPos().getX() - renderDist,
MC.getPlayerChunkPos().getZ() - renderDist,
MC_CLIENT.getPlayerChunkPos().getX() - renderDist,
MC_CLIENT.getPlayerChunkPos().getZ() - renderDist,
renderDist * 2 + 1);
}
@@ -6,7 +6,8 @@ import java.io.File;
//TODO: Maybe have IMCClientWrapper & IMCDedicatedWrapper extend this interface???
public interface IMinecraftSharedWrapper extends IBindable {
boolean isServerJar();
boolean isDedicatedServer();
File getInstallationDirectory();
}
@@ -21,7 +21,7 @@ package com.seibel.lod.core.wrapperInterfaces.world;
import java.io.File;
import com.seibel.lod.core.enums.EWorldType;
import com.seibel.lod.core.enums.ELevelType;
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
import com.seibel.lod.core.objects.DHChunkPos;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
@@ -36,7 +36,7 @@ public interface ILevelWrapper extends IBindable
{
IDimensionTypeWrapper getDimensionType();
EWorldType getWorldType();
ELevelType getLevelType();
int getBlockLight(int x, int y, int z);