last = new KMap<>();
+
+ public static void add(String key, String value)
+ {
+ stuff.put(key, value);
+ }
+
+ public static void saveLast()
+ {
+ last = stuff.copy();
+ }
+
+ public static void lastPanic()
+ {
+ for(String i : last.keySet())
+ {
+ Iris.error("Last Panic " + i + ": " + stuff.get(i));
+ }
+ }
+
+ public static void panic()
+ {
+ lastPanic();
+ for(String i : stuff.keySet())
+ {
+ Iris.error("Engine Panic " + i + ": " + stuff.get(i));
+ }
+ }
+}
diff --git a/src/main/java/com/volmit/iris/util/data/DUTF.java b/src/main/java/com/volmit/iris/util/data/DUTF.java
new file mode 100644
index 000000000..54ba81a01
--- /dev/null
+++ b/src/main/java/com/volmit/iris/util/data/DUTF.java
@@ -0,0 +1,55 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2021 Arcane Arts (Volmit Software)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.volmit.iris.util.data;
+
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Encodes signed and unsigned values using a common variable-length
+ * scheme, found for example in
+ *
+ * Google's Protocol Buffers. It uses fewer bytes to encode smaller values,
+ * but will use slightly more bytes to encode large values.
+ *
+ * Signed values are further encoded using so-called zig-zag encoding
+ * in order to make them "compatible" with variable-length encoding.
+ */
+public final class DUTF {
+
+ private DUTF() {
+ }
+
+ public static void write(String s, DataOutputStream dos) throws IOException {
+ byte[] b = s.getBytes(StandardCharsets.UTF_8);
+ dos.writeShort(b.length);
+ dos.write(b);
+ }
+
+ public static String read(DataInputStream din) throws IOException {
+ byte[] d = new byte[din.readShort()];
+ din.read(d);
+ return new String(d, StandardCharsets.UTF_8);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/volmit/iris/util/hunk/bits/DataContainer.java b/src/main/java/com/volmit/iris/util/hunk/bits/DataContainer.java
index 65c7fcbf7..ca236c6ed 100644
--- a/src/main/java/com/volmit/iris/util/hunk/bits/DataContainer.java
+++ b/src/main/java/com/volmit/iris/util/hunk/bits/DataContainer.java
@@ -30,8 +30,8 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class DataContainer {
- protected static final int INITIAL_BITS = 2;
- protected static final int LINEAR_BITS_LIMIT = 5;
+ protected static final int INITIAL_BITS = 3;
+ protected static final int LINEAR_BITS_LIMIT = 4;
protected static final int LINEAR_INITIAL_LENGTH = (int) Math.pow(2, LINEAR_BITS_LIMIT) + 1;
protected static final int[] BIT = computeBitLimits();
private final AtomicReference> palette;
@@ -56,6 +56,51 @@ public class DataContainer {
this.bits = new AtomicInteger(palette.get().bits());
}
+ public static String readBitString(DataInputStream din) throws IOException
+ {
+ DataContainer c = new DataContainer<>(din, new Writable() {
+ @Override
+ public Character readNodeData(DataInputStream din) throws IOException {
+ return din.readChar();
+ }
+
+ @Override
+ public void writeNodeData(DataOutputStream dos, Character character) throws IOException {
+ dos.writeChar(character);
+ }
+ });
+
+ StringBuilder sb = new StringBuilder();
+
+ for(int i = c.size()-1; i >= 0; i--)
+ {
+ sb.setCharAt(i, c.get(i));
+ }
+
+ return sb.toString();
+ }
+
+ public static void writeBitString(String s, DataOutputStream dos) throws IOException {
+ DataContainer c = new DataContainer<>(new Writable() {
+ @Override
+ public Character readNodeData(DataInputStream din) throws IOException {
+ return din.readChar();
+ }
+
+ @Override
+ public void writeNodeData(DataOutputStream dos, Character character) throws IOException {
+ dos.writeChar(character);
+ }
+ }, s.length());
+
+ for(int i = 0; i < s.length(); i++)
+ {
+ c.set(i, s.charAt(i));
+ }
+
+ c.writeDos(dos);
+ }
+
public DataBits getData()
{
return data.get();
@@ -125,7 +170,7 @@ public class DataContainer {
}
private void expandOne() {
- if (palette.get().size() + 1 >= BIT[bits.get()] - 1) {
+ if (palette.get().size() + 1 >= BIT[bits.get()]) {
setBits(bits.get() + 1);
}
}
diff --git a/src/main/java/com/volmit/iris/util/hunk/bits/TecTest.java b/src/main/java/com/volmit/iris/util/hunk/bits/TecTest.java
index b8dded4a8..8b840ccec 100644
--- a/src/main/java/com/volmit/iris/util/hunk/bits/TecTest.java
+++ b/src/main/java/com/volmit/iris/util/hunk/bits/TecTest.java
@@ -18,10 +18,93 @@
package com.volmit.iris.util.hunk.bits;
+import com.volmit.iris.Iris;
+import com.volmit.iris.util.collection.KList;
+import com.volmit.iris.util.collection.KSet;
+import com.volmit.iris.util.format.Form;
+import com.volmit.iris.util.io.IO;
+import com.volmit.iris.util.math.RNG;
+import com.volmit.iris.util.matter.slices.BlockMatter;
+import org.bukkit.Material;
+import org.bukkit.block.data.BlockData;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Set;
+
public class TecTest {
+ public static Set randomBlocks(int max)
+ {
+ KSet d = new KSet<>();
+
+ while(d.size() < max)
+ {
+ Material m = Material.values()[RNG.r.i(Material.values().length - 1)];
+ if(m.isBlock())
+ {
+ d.add(m.createBlockData());
+ }
+ }
+
+ return d;
+ }
+
public static void go()
{
+ }
+ public static boolean test(int size, int pal)
+ {
+ try
+ {
+ Iris.info("Test? " + size + " " + pal);
+ KList blocks = new KList<>(randomBlocks(pal));
+ Iris.info("Fill " + pal + " -> " + size + " Entries");
+ Writable writer = new BlockMatter();
+ DataContainer dc = new DataContainer<>(writer, size);
+
+ for(int i = 0; i < dc.size(); i++)
+ {
+ dc.set(i, blocks.getRandom());
+ }
+
+ Iris.info(dc.toString());
+ byte[] dat = dc.write();
+ DataContainer dx = new DataContainer<>(new DataInputStream(new ByteArrayInputStream(dat)), writer);
+ Iris.info(dx.toString());
+ byte[] dat2 = dx.write();
+ Iris.info("Size: " + Form.memSize(dat.length, 2) + " -> " + Form.memSize(dat2.length, 2));
+
+ if(Arrays.equals(dat, dat2)) {
+ Iris.info("MATCH");
+ return true;
+ }
+ else
+ {
+ for(int i = 0; i < dc.size(); i++)
+ {
+ if(!dx.get(i).equals(dc.get(i)))
+ {
+ Iris.info("FAIL Expected " + dc.get(i).getAsString(true) + " but got " + dx.get(i).getAsString(true));
+ return false;
+ }
+ }
+ Iris.info("MATCH but different output?");
+
+ return true;
+ }
+ }
+
+ catch(Throwable e)
+ {
+ e.printStackTrace();
+ return false;
+ }
}
}
diff --git a/src/main/java/com/volmit/iris/util/mantle/Mantle.java b/src/main/java/com/volmit/iris/util/mantle/Mantle.java
index 6c843699a..7e593927c 100644
--- a/src/main/java/com/volmit/iris/util/mantle/Mantle.java
+++ b/src/main/java/com/volmit/iris/util/mantle/Mantle.java
@@ -476,6 +476,7 @@ public class Mantle {
if (file.exists()) {
try {
+ Iris.addPanic("reading.tectonic-plate", file.getAbsolutePath());
region = TectonicPlate.read(worldHeight, file);
if (region.getX() != x || region.getZ() != z) {
@@ -488,6 +489,7 @@ public class Mantle {
Iris.error("Failed to read Tectonic Plate " + file.getAbsolutePath() + " creating a new chunk instead.");
Iris.reportError(e);
e.printStackTrace();
+ Iris.panic();
region = new TectonicPlate(worldHeight, x, z);
loadedRegions.put(k, region);
Iris.debug("Created new Tectonic Plate (Due to Load Failure) " + C.DARK_GREEN + x + " " + z);
diff --git a/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java b/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java
index fc341f687..f7123e7d3 100644
--- a/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java
+++ b/src/main/java/com/volmit/iris/util/mantle/MantleChunk.java
@@ -18,6 +18,8 @@
package com.volmit.iris.util.mantle;
+import com.volmit.iris.Iris;
+import com.volmit.iris.engine.EnginePanic;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.function.Consumer4;
import com.volmit.iris.util.matter.IrisMatter;
@@ -77,8 +79,9 @@ public class MantleChunk {
}
for (int i = 0; i < s; i++) {
+ Iris.addPanic("read.section", "Section[" + i + "]");
if (din.readBoolean()) {
- sections.set(i, Matter.read(din));
+ sections.set(i, Matter.readDin(din));
}
}
}
diff --git a/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java b/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java
index e88ffb593..d404710a6 100644
--- a/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java
+++ b/src/main/java/com/volmit/iris/util/mantle/TectonicPlate.java
@@ -19,6 +19,7 @@
package com.volmit.iris.util.mantle;
import com.volmit.iris.Iris;
+import com.volmit.iris.engine.EnginePanic;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.format.C;
@@ -74,7 +75,9 @@ public class TectonicPlate {
this(worldHeight, din.readInt(), din.readInt());
for (int i = 0; i < chunks.length(); i++) {
if (din.readBoolean()) {
+ Iris.addPanic("read-chunk", "Chunk[" + i + "]");
chunks.set(i, new MantleChunk(sectionHeight, din));
+ EnginePanic.saveLast();
}
}
}
diff --git a/src/main/java/com/volmit/iris/util/matter/IrisMatter.java b/src/main/java/com/volmit/iris/util/matter/IrisMatter.java
index f8ccd8692..1e4893192 100644
--- a/src/main/java/com/volmit/iris/util/matter/IrisMatter.java
+++ b/src/main/java/com/volmit/iris/util/matter/IrisMatter.java
@@ -44,6 +44,11 @@ public class IrisMatter extends IrisRegistrant implements Matter {
private final KMap, MatterSlice>> sliceMap;
public IrisMatter(int width, int height, int depth) {
+ if(width < 1 || height < 1 || depth < 1)
+ {
+ throw new RuntimeException("Invalid Matter Size " + width + "x" + height + "x" + depth);
+ }
+
this.width = width;
this.height = height;
this.depth = depth;
diff --git a/src/main/java/com/volmit/iris/util/matter/Matter.java b/src/main/java/com/volmit/iris/util/matter/Matter.java
index 14a3cec48..1254822cb 100644
--- a/src/main/java/com/volmit/iris/util/matter/Matter.java
+++ b/src/main/java/com/volmit/iris/util/matter/Matter.java
@@ -18,6 +18,7 @@
package com.volmit.iris.util.matter;
+import com.volmit.iris.Iris;
import com.volmit.iris.engine.object.IrisObject;
import com.volmit.iris.engine.object.IrisPosition;
import com.volmit.iris.util.collection.KSet;
@@ -95,6 +96,10 @@ public interface Matter {
return read(in, (b) -> new IrisMatter(b.getX(), b.getY(), b.getZ()));
}
+ static Matter readDin(DataInputStream in) throws IOException, ClassNotFoundException {
+ return readDin(in, (b) -> new IrisMatter(b.getX(), b.getY(), b.getZ()));
+ }
+
/**
* Reads the input stream into a matter object using a matter factory.
* Does not close the input stream. Be a man, close it yourself.
@@ -105,16 +110,26 @@ public interface Matter {
* @throws IOException shit happens yo
*/
static Matter read(InputStream in, Function matterFactory) throws IOException, ClassNotFoundException {
- DataInputStream din = new DataInputStream(in);
- Matter matter = matterFactory.apply(new BlockPosition(
- Varint.readUnsignedVarInt(din),
- Varint.readUnsignedVarInt(din),
- Varint.readUnsignedVarInt(din)));
- int sliceCount = din.readByte();
- matter.getHeader().read(din);
+ return readDin(new DataInputStream(in), matterFactory);
+ }
- while (sliceCount-- > 0) {
+ static Matter readDin(DataInputStream din, Function matterFactory) throws IOException, ClassNotFoundException {
+ Matter matter = matterFactory.apply(new BlockPosition(
+ din.readInt(),
+ din.readInt(),
+ din.readInt()));
+ Iris.addPanic("read.matter.size", matter.getWidth() + "x" + matter.getHeight() + "x" + matter.getDepth());
+ int sliceCount = din.readByte();
+ Iris.addPanic("read.matter.slicecount", sliceCount + "");
+
+ matter.getHeader().read(din);
+ Iris.addPanic("read.matter.header", matter.getHeader().toString());
+
+ for(int i = 0; i < sliceCount; i++)
+ {
+ Iris.addPanic("read.matter.slice", i + "");
String cn = din.readUTF();
+ Iris.addPanic("read.matter.slice.class", cn);
try {
Class> type = Class.forName(cn);
MatterSlice> slice = matter.createSlice(type, matter);
@@ -336,10 +351,6 @@ public interface Matter {
Map, MatterSlice>> getSliceMap();
default void write(File f) throws IOException {
- write(f, true);
- }
-
- default void write(File f, boolean compression) throws IOException {
OutputStream out = new FileOutputStream(f);
write(out);
out.close();
@@ -381,9 +392,9 @@ public interface Matter {
default void writeDos(DataOutputStream dos) throws IOException {
trimSlices();
- Varint.writeUnsignedVarInt(getWidth(), dos);
- Varint.writeUnsignedVarInt(getHeight(), dos);
- Varint.writeUnsignedVarInt(getDepth(), dos);
+ dos.writeInt(getWidth());
+ dos.writeInt(getHeight());
+ dos.writeInt(getDepth());
dos.writeByte(getSliceTypes().size());
getHeader().write(dos);
diff --git a/src/main/java/com/volmit/iris/util/matter/MatterHeader.java b/src/main/java/com/volmit/iris/util/matter/MatterHeader.java
index a00a53d75..d6852eb1b 100644
--- a/src/main/java/com/volmit/iris/util/matter/MatterHeader.java
+++ b/src/main/java/com/volmit/iris/util/matter/MatterHeader.java
@@ -34,13 +34,13 @@ public class MatterHeader {
public void write(DataOutputStream out) throws IOException {
out.writeUTF(author);
- Varint.writeUnsignedVarLong(createdAt, out);
- Varint.writeUnsignedVarInt(version, out);
+ out.writeLong(createdAt);
+ out.writeShort(version);
}
public void read(DataInputStream din) throws IOException {
setAuthor(din.readUTF());
- setCreatedAt(Varint.readUnsignedVarLong(din));
- setVersion(Varint.readUnsignedVarInt(din));
+ setCreatedAt(din.readLong());
+ setVersion(din.readShort());
}
}
diff --git a/src/main/java/com/volmit/iris/util/matter/MatterSlice.java b/src/main/java/com/volmit/iris/util/matter/MatterSlice.java
index 08333fd4e..24c8c5b48 100644
--- a/src/main/java/com/volmit/iris/util/matter/MatterSlice.java
+++ b/src/main/java/com/volmit/iris/util/matter/MatterSlice.java
@@ -160,6 +160,7 @@ public interface MatterSlice extends Hunk, PaletteType, Writable {
default void write(DataOutputStream dos) throws IOException {
dos.writeUTF(getType().getCanonicalName());
+
if ((this instanceof PaletteOrHunk f && f.isPalette())) {
f.palette().writeDos(dos);
return;
@@ -185,15 +186,7 @@ public interface MatterSlice extends Hunk, PaletteType, Writable {
default void read(DataInputStream din) throws IOException {
if ((this instanceof PaletteOrHunk f && f.isPalette())) {
- try {
- f.setPalette(new DataContainer<>(din, this));
- }
-
- catch(Throwable e)
- {
- Iris.error("Failed to read " + getType() + " Matter! ?? ");
- throw new IOException(e);
- }
+ f.setPalette(new DataContainer<>(din, this));
return;
}
diff --git a/src/main/java/com/volmit/iris/util/matter/slices/BlockMatter.java b/src/main/java/com/volmit/iris/util/matter/slices/BlockMatter.java
index eb25aa8de..51612897e 100644
--- a/src/main/java/com/volmit/iris/util/matter/slices/BlockMatter.java
+++ b/src/main/java/com/volmit/iris/util/matter/slices/BlockMatter.java
@@ -21,6 +21,7 @@ package com.volmit.iris.util.matter.slices;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.palette.Palette;
import com.volmit.iris.util.matter.Sliced;
+import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
@@ -58,6 +59,6 @@ public class BlockMatter extends RawMatter {
@Override
public BlockData readNode(DataInputStream din) throws IOException {
- return B.get(din.readUTF());
+ return Bukkit.createBlockData(din.readUTF());
}
}