Continue fixing bugs... Lots of bugs.

This commit is contained in:
TomTheFurry
2022-07-26 20:17:26 +08:00
parent a4546c63e3
commit e903ec53f5
15 changed files with 148 additions and 57 deletions
@@ -17,7 +17,7 @@ public interface LodDataSource {
void setLocalVersion(int localVer);
byte getDataVersion();
void update(DHChunkPos chunkPos, ChunkSizedData data);
void update(ChunkSizedData data);
// Saving related
void saveData(ILevel level, DataMetaFile file, OutputStream dataStream) throws IOException;
@@ -3,8 +3,14 @@ package com.seibel.lod.core.a7.datatype.full;
import com.seibel.lod.core.a7.datatype.full.accessor.FullArrayView;
public class ChunkSizedData extends FullArrayView {
public ChunkSizedData() {
public final byte dataDetail;
public final int minX;
public final int minZ;
public ChunkSizedData(byte dataDetail, int minX, int minZ) {
super(new IdBiomeBlockStateMap(), new long[16*16][0], 16);
this.dataDetail = dataDetail;
this.minX = minX;
this.minZ = minZ;
}
public void setSingleColumn(long[] data, int x, int z) {
@@ -9,6 +9,7 @@ import com.seibel.lod.core.a7.datatype.LodDataSource;
import com.seibel.lod.core.a7.util.IdMappingUtil;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.objects.DHChunkPos;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import java.io.DataOutputStream;
@@ -49,9 +50,13 @@ public class FullDataSource extends FullArrayView implements LodDataSource { //
}
@Override
public void update(DHChunkPos chunkPos, ChunkSizedData data) {
if (getDataDetail() == 0) {
DhBlockPos2D blockOffset = chunkPos.getMinBlockPos().subtract(sectionPos.getSectionBBoxPos().getCorner());
public void update(ChunkSizedData data) {
if (getDataDetail() == 0 && data.dataDetail == 0) {
DhBlockPos2D chunkBlockPos = new DhBlockPos2D(data.minX * 16, data.minZ * 16);
DhBlockPos2D blockOffset = chunkBlockPos.subtract(sectionPos.getCorner().getCorner());
LodUtil.assertTrue(blockOffset.x >= 0 && blockOffset.x < SECTION_SIZE && blockOffset.z >= 0 && blockOffset.z < SECTION_SIZE,
"ChunkWrite of {} outside section {}. (cal offset {} larger than {})",
new DHChunkPos(data.minX, data.minZ), sectionPos, blockOffset, SECTION_SIZE);
data.shadowCopyTo(this.subView(16, blockOffset.x, blockOffset.z));
} else {
//TODO;
@@ -65,4 +70,8 @@ public class FullDataSource extends FullArrayView implements LodDataSource { //
dos.writeInt(size);
}
}
public static FullDataSource createEmpty(DhSectionPos pos) {
return new FullDataSource(pos);
}
}
@@ -14,7 +14,7 @@ public class LodDataBuilder {
public static ChunkSizedData createChunkData(IChunkWrapper chunk) {
if (!canGenerateLodFromChunk(chunk)) return null;
ChunkSizedData chunkData = new ChunkSizedData();
ChunkSizedData chunkData = new ChunkSizedData((byte)0, chunk.getChunkPos().x, chunk.getChunkPos().z);
for (int x=0; x<16; x++) {
for (int z=0; z<16; z++) {
@@ -126,14 +126,18 @@ public class GenerationQueue implements PlaceHolderQueue {
+ data.gridSize + " but requested granularity was " + granularity
+ " (equals to chunks of : " + (1 << (granularity-4)) + ") @ " + chunkPosMin);
logger.info("Writing chunk {} to {} with data detail {}",
chunkPosMin, new DHChunkPos(chunkPosMin.x + (1 << (granularity-4)), chunkPosMin.z + (1 << (granularity-4))),
dataDetail);
final byte sectionDetail = (byte) (dataDetail + FullDataSource.SECTION_SIZE_OFFSET);
data.forEachPos((x,z) -> {
ChunkSizedData chunkData = data.get(x,z);
DhLodPos chunkDataPos = new DhLodPos((byte) (dataDetail + 4), x, z).convertUpwardsTo(sectionDetail);
DhSectionPos sectionPos = new DhSectionPos(chunkDataPos.detail, chunkDataPos.x, chunkDataPos.z);
logger.info("Writing chunk {} with data detail {} to section {}",
new DHChunkPos(x+chunkPosMin.x,z+chunkPosMin.z),
dataDetail, sectionPos);
//logger.info("Writing chunk {} with data detail {} to section {}",
// new DHChunkPos(x+chunkPosMin.x,z+chunkPosMin.z),
// dataDetail, sectionPos);
write(sectionPos, chunkData);
});
});
@@ -4,6 +4,8 @@ import com.seibel.lod.core.objects.DHBlockPos;
import com.seibel.lod.core.objects.Pos2D;
import com.seibel.lod.core.util.LodUtil;
import java.util.Objects;
public class DhBlockPos2D {
public final int x;
public final int z;
@@ -37,4 +39,23 @@ public class DhBlockPos2D {
public static DhBlockPos2D fromPos2D(Pos2D pos) {
return new DhBlockPos2D(pos.x, pos.y);
}
@Override
public String toString() {
return "(" + x + ", " + z + ")";
}
@Override
public boolean equals(Object obj) {
if (obj instanceof DhBlockPos2D) {
DhBlockPos2D other = (DhBlockPos2D)obj;
return x == other.x && z == other.z;
}
return false;
}
@Override
public int hashCode() {
return Integer.hashCode(x) ^ Integer.hashCode(z);
}
}
@@ -95,6 +95,13 @@ public class DhSectionPos {
sectionZ == that.sectionZ;
}
@Override
public int hashCode() {
return Integer.hashCode(sectionDetail) ^
Integer.hashCode(sectionX) ^
Integer.hashCode(sectionZ);
}
// Serialize() is different from toString() as this requires it to NEVER be changed, and should be in a short format
public String serialize() {
return "[" + sectionDetail + ',' + sectionX + ',' + sectionZ + ']';
@@ -383,29 +383,30 @@ public class LodQuadTree {
if (section == null) return;
// Cascade layers
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);
LodRenderSection child = childRingList.get(childPos.sectionX, childPos.sectionZ);
if (child == null) {
child = childRingList.setChained(childPos.sectionX, childPos.sectionZ,
new LodRenderSection(childPos));
child.childCount = 0;
} else {
LodUtil.assertTrue(child.childCount == -1,
"Self has child count 0 but an existing child's child count != -1!");
child.childCount = 0;
}
}
section.childCount = 4;
}
// 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);
// LodRenderSection child = childRingList.get(childPos.sectionX, childPos.sectionZ);
// if (child == null) {
// child = childRingList.setChained(childPos.sectionX, childPos.sectionZ,
// new LodRenderSection(childPos));
// child.childCount = 0;
// } else {
// LodUtil.assertTrue(child.childCount == -1,
// "Self has child count 0 but an existing child's child count != -1!");
// child.childCount = 0;
// }
// }
// section.childCount = 4;
// }
// Call load on new sections, and tick on existing ones, and dispose old sections
if (section.childCount == -1) {
ringList.set(pos.x, pos.y, null);
section.dispose();
return;
} else {
if (!section.isLoaded() && !section.isLoading()) {
section.load(renderSourceProvider);
@@ -418,18 +419,24 @@ public class LodQuadTree {
}
// Assertion steps
LodUtil.assertTrue(section.childCount == 4 || section.childCount == 0 || section.childCount == -1);
LodUtil.assertTrue(section.childCount == 4 || section.childCount == 0);
if (section.pos.sectionDetail == LAYER_BEGINNING_OFFSET) LodUtil.assertTrue(section.childCount == 0);
if (section.childCount == 4) LodUtil.assertTrue(
getChildSection(section.pos, 0) != null &&
getChildSection(section.pos, 1) != null &&
getChildSection(section.pos, 2) != null &&
getChildSection(section.pos, 3) != null);
getChildSection(section.pos, 3) != null,
"Sect {} child count 4 but childs have null: {} {} {} {}",
section.pos, getChildSection(section.pos, 0), getChildSection(section.pos, 1),
getChildSection(section.pos, 2), getChildSection(section.pos, 3));
if (section.childCount == 0 && section.pos.sectionDetail > LAYER_BEGINNING_OFFSET) LodUtil.assertTrue(
getChildSection(section.pos, 0) == null &&
getChildSection(section.pos, 1) == null &&
getChildSection(section.pos, 2) == null &&
getChildSection(section.pos, 3) == null);
getChildSection(section.pos, 3) == null,
"Sect {} child count 0 but childs are not null: {} {} {} {}",
section.pos, getChildSection(section.pos, 0), getChildSection(section.pos, 1),
getChildSection(section.pos, 2), getChildSection(section.pos, 3));
if (section.childCount == -1 && section.pos.sectionDetail < numbersOfSectionLevels-1) LodUtil.assertTrue(
getParentSection(section.pos).childCount == 0);
});
@@ -8,12 +8,10 @@ import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
import com.seibel.lod.core.a7.datatype.DataSourceLoader;
import com.seibel.lod.core.a7.pos.DhSectionPos;
import com.seibel.lod.core.logging.DhLoggerBuilder;
import com.seibel.lod.core.util.LodUtil;
@@ -56,7 +54,7 @@ public class MetaFile {
// Load a metaFile in this path. It also automatically read the metadata.
protected MetaFile(File path) throws IOException {
validatePath();
validateFile();
try (FileInputStream fin = new FileInputStream(path)) {
MappedByteBuffer buffer = fin.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, METADATA_SIZE);
this.path = path;
@@ -86,9 +84,7 @@ public class MetaFile {
this.pos = pos;
}
protected void save() {} //TODO: Implement
private void validatePath() throws IOException {
private void validateFile() throws IOException {
if (!path.exists()) throw new IOException("File missing");
if (!path.isFile()) throw new IOException("Not a file");
if (!path.canRead()) throw new IOException("File not readable");
@@ -96,7 +92,7 @@ public class MetaFile {
}
protected void updateMetaData() throws IOException {
validatePath();
validateFile();
try (FileChannel channel = FileChannel.open(path.toPath(), StandardOpenOption.READ)) {
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, METADATA_SIZE);
int magic = buffer.getInt();
@@ -124,7 +120,7 @@ public class MetaFile {
}
protected void writeData(Consumer<OutputStream> dataWriter) throws IOException {
validatePath();
if (path.exists()) validateFile();
File tempFile = File.createTempFile("", "tmp", path.getParentFile());
tempFile.deleteOnExit();
try (FileChannel file = FileChannel.open(tempFile.toPath(),
@@ -13,6 +13,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.seibel.lod.core.a7.datatype.LodDataSource;
import com.seibel.lod.core.a7.datatype.DataSourceLoader;
import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
import com.seibel.lod.core.a7.datatype.full.FullDataSource;
import com.seibel.lod.core.a7.datatype.full.FullFormat;
import com.seibel.lod.core.a7.save.io.MetaFile;
import com.seibel.lod.core.a7.level.ILevel;
@@ -151,7 +152,7 @@ public class DataMetaFile extends MetaFile {
private LodDataSource loadAndUpdateDataSource() {
LodDataSource data = loadFile();
if (data == null) return null;
if (data == null) data = FullDataSource.createEmpty(pos);
// Poll the write queue
// First check if write queue is empty, then swap the write queue.
@@ -161,8 +162,11 @@ public class DataMetaFile extends MetaFile {
if (!isEmpty) {
localVer = localVersion.incrementAndGet();
swapWriteQueue();
// TODO: Use _backQueue to apply the changes into the data.
for (ChunkSizedData chunk : _backQueue.queue) {
data.update(chunk);
}
write(data);
LOGGER.info("Updated Data file at {} for sect {}", path, pos);
} else localVer = localVersion.get();
data.setLocalVersion(localVer);
// Finally, return the data.
@@ -170,6 +174,7 @@ public class DataMetaFile extends MetaFile {
}
private LodDataSource loadFile() {
if (!path.exists()) return null;
// Refresh the metadata.
try {
super.updateMetaData();
@@ -1,8 +1,10 @@
package com.seibel.lod.core.a7.save.io.file;
import com.google.common.collect.HashMultimap;
import com.seibel.lod.core.a7.datatype.DataSourceLoader;
import com.seibel.lod.core.a7.datatype.LodDataSource;
import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
import com.seibel.lod.core.a7.datatype.full.FullDataSource;
import com.seibel.lod.core.a7.datatype.full.FullFormat;
import com.seibel.lod.core.a7.level.IServerLevel;
import com.seibel.lod.core.a7.pos.DhSectionPos;
@@ -117,8 +119,9 @@ public class LocalDataFileHandler implements IDataSourceProvider {
return;
}
// Slow path: if there is no file for this section, create one.
DataMetaFile newMetaFile = new DataMetaFile(level, saveDir, sectionPos);
File file = computeDefaultFilePath(sectionPos);
DataMetaFile newMetaFile = new DataMetaFile(level, file, sectionPos);
LOGGER.info("Created new Data file at {} for sect {}", newMetaFile.path, sectionPos);
// We add to the queue first so on CAS onto the map, no other thread
// will see the new file without our write entry.
@@ -109,6 +109,7 @@ public class RenderFileHandler implements IRenderSourceProvider {
dataSourceProvider::isCacheValid,
dataSourceProvider::read,
level, computeDefaultFilePath(p), p));
return metaFile.loadOrGetCached(renderCacheThread).handle(
(render, e) -> {
if (e != null) {
@@ -150,7 +150,8 @@ public class RenderMetaFile extends MetaFile {
}
} catch (IOException e) {
LOGGER.warn("Failed to read render cache at {}:", path, e);
LOGGER.warn("Will ignore cache file.");
LOGGER.warn("Will delete cache file.");
path.delete();
}
}
// Otherwise, re-query and make the RenderSource
@@ -0,0 +1,45 @@
package com.seibel.lod.core.logging.f3;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnArrayView;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Supplier;
public class F3Screen {
public static boolean renderCustomF3 = true;
private static final String[] DEFAULT_STR = {
"",
ModInfo.READABLE_NAME + " version: " + ModInfo.VERSION
};
private static final LinkedList<WeakReference<SelfUpdateMessage>> selfUpdateMessages = new LinkedList<>();
public static void addStringToDisplay(List<String> list) {
list.addAll(Arrays.asList(DEFAULT_STR));
Iterator<WeakReference<SelfUpdateMessage>> it = selfUpdateMessages.iterator();
while (it.hasNext()) {
WeakReference<SelfUpdateMessage> ref = it.next();
SelfUpdateMessage msg = ref.get();
if (msg == null) {
it.remove();
} else {
msg.print(list);
}
}
}
public static class SelfUpdateMessage {
private final Supplier<String> supplier;
public SelfUpdateMessage(Supplier<String> message) {
selfUpdateMessages.add(new WeakReference<>(this));
this.supplier = message;
}
public void print(List<String> list) {
list.add(supplier.get());
}
}
}
@@ -1,14 +0,0 @@
package com.seibel.lod.core.render;
import com.seibel.lod.core.ModInfo;
import java.util.Arrays;
import java.util.List;
public class F3Screen {
public static List<String> f3List = Arrays.asList(
"",
ModInfo.READABLE_NAME + " version: " + ModInfo.VERSION
);
public static boolean renderCustomF3 = false;
}