Continue fixing bugs... Lots of bugs.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user