It... builds?

This commit is contained in:
TomTheFurry
2022-07-01 15:05:34 +08:00
parent c77f8e254b
commit bdc8384c49
11 changed files with 119 additions and 207 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());
}
@@ -30,7 +30,7 @@ public class DhClientLevel implements IClientLevel {
public DhClientLevel(ClientOnlySaveStructure save, ILevelWrapper level) {
this.save = save;
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);
@@ -38,16 +38,17 @@ public class DhClientLevel implements IClientLevel {
FileScanner.scanFile(save, level, dataFileHandler, renderFileHandler);
}
public void tick() {
tree.tick(new DhBlockPos2D(MC_CLIENT.getPlayerBlockPos()));
renderBufferHandler.update();
}
@Override
public void dumpRamUsage() {
//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) {
@@ -31,7 +31,7 @@ public class DhClientServerLevel implements IClientLevel, IServerLevel {
this.level = level;
this.save = save;
dataFileHandler = new LocalDataFileHandler(this, save.getDataFolder(level));
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);
@@ -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;
}
);
}
/*
@@ -7,9 +7,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;
//TODO: Should this be in core and able to be accessed by core, or should this be in common, and only effect
// how common calls back into the internal APIs?
public static boolean inDedicatedEnvironment;
public static WorldEnvironment getEnvironment() {
return currentWorld==null ? null : currentWorld.environment;
}
@@ -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();