diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index d396dbfb4..74dc108f7 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -14,8 +14,8 @@
@@ -48,6 +48,7 @@
+
@@ -113,14 +114,14 @@
-
+
-
-
+
+
-
+
@@ -141,9 +142,9 @@
-
+
-
+
\ No newline at end of file
diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/io/HunkCompoundRegion.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/io/HunkCompoundRegion.java
deleted file mode 100644
index 9efe846cf..000000000
--- a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/io/HunkCompoundRegion.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.volmit.iris.gen.v2.scaffold.hunk.io;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.bukkit.block.data.BlockData;
-
-import com.volmit.iris.util.CompoundTag;
-
-import lombok.Getter;
-
-public class HunkCompoundRegion extends HunkRegion
-{
- @Getter
- private HunkRegionSlice blockSlice;
- @Getter
- private HunkRegionSlice objectSlice;
- @Getter
- private HunkRegionSlice updateSlice;
-
- private final int height;
-
- public HunkCompoundRegion(int height, File folder, int x, int z, CompoundTag compound)
- {
- super(folder, x, z, compound);
- this.height = height;
- setupSlices();
- }
-
- public HunkCompoundRegion(int height, File folder, int x, int z)
- {
- super(folder, x, z);
- this.height = height;
- setupSlices();
- }
-
- private void setupSlices()
- {
- blockSlice = HunkRegionSlice.BLOCKDATA.apply(height, getCompound());
- objectSlice = HunkRegionSlice.STRING.apply(height, getCompound(), "objects");
- updateSlice = HunkRegionSlice.BOOLEAN.apply(height, getCompound(), "updates");
- }
-
- public void save() throws IOException
- {
- blockSlice.save();
- objectSlice.save();
- updateSlice.save();
- super.save();
- }
-
- public void unload()
- {
- blockSlice.unloadAll();
- objectSlice.unloadAll();
- updateSlice.unloadAll();
- }
-}
diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/io/HunkRegion.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/io/HunkRegion.java
index c8b30e7b6..c0b91cbd5 100644
--- a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/io/HunkRegion.java
+++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/io/HunkRegion.java
@@ -15,7 +15,6 @@ import com.volmit.iris.util.Tag;
import lombok.Data;
-@Data
public class HunkRegion
{
private final File folder;
@@ -53,6 +52,10 @@ public class HunkRegion
}
}
+ public CompoundTag getCompound() {
+ return compound;
+ }
+
private CompoundTag fix(CompoundTag readTag)
{
Map v = readTag.getValue();
@@ -82,4 +85,12 @@ public class HunkRegion
Iris.verbose("Saved Region: " + getX() + " " + getZ());
}
}
+
+ public int getX() {
+ return x;
+ }
+ public int getZ() {
+ return z;
+ }
+
}
diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/io/HunkRegionSlice.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/io/HunkRegionSlice.java
index cb85b9ced..5e647934c 100644
--- a/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/io/HunkRegionSlice.java
+++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/hunk/io/HunkRegionSlice.java
@@ -2,17 +2,11 @@ package com.volmit.iris.gen.v2.scaffold.hunk.io;
import java.io.IOException;
+import com.volmit.iris.util.*;
import org.bukkit.block.data.BlockData;
import com.volmit.iris.Iris;
import com.volmit.iris.gen.v2.scaffold.hunk.Hunk;
-import com.volmit.iris.util.ByteArrayTag;
-import com.volmit.iris.util.CompoundTag;
-import com.volmit.iris.util.Function2;
-import com.volmit.iris.util.Function3;
-import com.volmit.iris.util.KList;
-import com.volmit.iris.util.KMap;
-import com.volmit.iris.util.Tag;
public class HunkRegionSlice
{
@@ -24,6 +18,7 @@ public class HunkRegionSlice
private final CompoundTag compound;
private final String key;
private final KMap> loadedChunks;
+ private final KMap lastUse;
private final KList save;
private final int height;
@@ -36,6 +31,23 @@ public class HunkRegionSlice
this.compound = compound;
this.save = new KList<>();
this.key = key;
+ this.lastUse = new KMap<>();
+ }
+
+ public void cleanup(long t)
+ {
+ if(loadedChunks.size() != lastUse.size())
+ {
+ Iris.warn("Incorrect chunk use counts in " + key);
+ }
+
+ for(Short i : lastUse.k())
+ {
+ if(M.ms() - lastUse.get(i) > t)
+ {
+ unload((byte) (i & 0xFF), (byte) ((i >> 8) & 0xFF));
+ }
+ }
}
public void clear()
@@ -99,6 +111,7 @@ public class HunkRegionSlice
save.clear();
loadedChunks.clear();
+ lastUse.clear();
}
public synchronized void save(Hunk region, int x, int z)
@@ -138,6 +151,7 @@ public class HunkRegionSlice
save.remove(key);
}
+ lastUse.remove(key);
loadedChunks.remove(key);
}
}
@@ -168,6 +182,7 @@ public class HunkRegionSlice
{
v = factory.apply(16, height, 16);
}
+
loadedChunks.put(ikey(x, z), v);
return v;
@@ -184,6 +199,8 @@ public class HunkRegionSlice
c = load(x, z);
}
+ lastUse.put(ikey(x,z), M.ms());
+
return c;
}
diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxAccess.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxAccess.java
index 1bd20bbc4..437821836 100644
--- a/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxAccess.java
+++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxAccess.java
@@ -40,6 +40,31 @@ public interface ParallaxAccess
getUpdatesRW(x>>4, z>>4).set(x&15, y, z&15, d);
}
+ default boolean isParallaxGenerated(int x, int z)
+ {
+ return getMetaR(x,z).isParallaxGenerated();
+ }
+
+ default boolean isChunkGenerated(int x, int z) {
+ return getMetaR(x, z).isGenerated();
+ }
+
+ default void setParallaxGenerated(int x, int z) {
+ setParallaxGenerated(x,z,true);
+ }
+
+ default void setChunkGenerated(int x, int z) {
+ setChunkGenerated(x,z,true);
+ }
+
+ default void setParallaxGenerated(int x, int z, boolean v) {
+ getMetaRW(x, z).setParallaxGenerated(v);
+ }
+
+ default void setChunkGenerated(int x, int z, boolean v) {
+ getMetaRW(x, z).setGenerated(v);
+ }
+
public Hunk getBlocksR(int x, int z);
public Hunk getBlocksRW(int x, int z);
@@ -51,4 +76,16 @@ public interface ParallaxAccess
public Hunk getUpdatesR(int x, int z);
public Hunk getUpdatesRW(int x, int z);
+
+ public ParallaxChunkMeta getMetaR(int x, int z);
+
+ public ParallaxChunkMeta getMetaRW(int x, int z);
+
+ public void cleanup(long regionIdle, long chunkIdle);
+
+ public void cleanup();
+
+ public void saveAll();
+
+ public void saveAllNOW();
}
diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxChunkMeta.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxChunkMeta.java
new file mode 100644
index 000000000..f875ad65b
--- /dev/null
+++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxChunkMeta.java
@@ -0,0 +1,37 @@
+package com.volmit.iris.gen.v2.scaffold.parallax;
+
+import com.sun.tools.javac.code.Attribute;
+import com.volmit.iris.gen.v2.scaffold.hunk.io.HunkIOAdapter;
+import com.volmit.iris.gen.v2.scaffold.hunk.io.PaletteHunkIOAdapter;
+import com.volmit.iris.util.CompoundTag;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.function.Function;
+
+@AllArgsConstructor
+@Data
+public class ParallaxChunkMeta {
+ public static final Function> adapter = (c) -> new PaletteHunkIOAdapter() {
+ @Override
+ public void write(ParallaxChunkMeta parallaxChunkMeta, DataOutputStream dos) throws IOException {
+ dos.writeBoolean(parallaxChunkMeta.isGenerated());
+ dos.writeBoolean(parallaxChunkMeta.isParallaxGenerated());
+ }
+
+ @Override
+ public ParallaxChunkMeta read(DataInputStream din) throws IOException {
+ return new ParallaxChunkMeta(din.readBoolean(), din.readBoolean());
+ }
+ };
+ private boolean generated;
+ private boolean parallaxGenerated;
+
+ public ParallaxChunkMeta()
+ {
+ this(false, false);
+ }
+}
diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxRegion.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxRegion.java
new file mode 100644
index 000000000..c9766275d
--- /dev/null
+++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxRegion.java
@@ -0,0 +1,179 @@
+package com.volmit.iris.gen.v2.scaffold.parallax;
+
+import java.io.File;
+import java.io.IOException;
+
+import com.volmit.iris.gen.v2.scaffold.hunk.Hunk;
+import com.volmit.iris.gen.v2.scaffold.hunk.io.HunkIOAdapter;
+import com.volmit.iris.gen.v2.scaffold.hunk.io.HunkRegion;
+import com.volmit.iris.gen.v2.scaffold.hunk.io.HunkRegionSlice;
+import com.volmit.iris.util.*;
+import javassist.bytecode.ByteArray;
+import org.bukkit.block.data.BlockData;
+
+import lombok.Getter;
+
+public class ParallaxRegion extends HunkRegion
+{
+ private boolean dirtyMeta;
+ private Hunk meta;
+ private HunkIOAdapter metaAdapter;
+ private HunkRegionSlice blockSlice;
+ private HunkRegionSlice objectSlice;
+ private HunkRegionSlice updateSlice;
+ private long lastUse;
+ private final int height;
+
+ public ParallaxRegion(int height, File folder, int x, int z, CompoundTag compound)
+ {
+ super(folder, x, z, compound);
+ this.height = height;
+ setupSlices();
+ }
+
+ public ParallaxRegion(int height, File folder, int x, int z)
+ {
+ super(folder, x, z);
+ this.height = height;
+ setupSlices();
+ }
+
+ private void setupSlices()
+ {
+ blockSlice = HunkRegionSlice.BLOCKDATA.apply(height, getCompound());
+ objectSlice = HunkRegionSlice.STRING.apply(height, getCompound(), "objects");
+ updateSlice = HunkRegionSlice.BOOLEAN.apply(height, getCompound(), "updates");
+ metaAdapter = ParallaxChunkMeta.adapter.apply(getCompound());
+ dirtyMeta = false;
+ meta = null;
+ lastUse = M.ms();
+ }
+
+ public boolean hasBeenIdleLongerThan(long time)
+ {
+ return M.ms() - lastUse > time;
+ }
+
+ public ParallaxChunkMeta getMetaR(int x, int z)
+ {
+ lastUse = M.ms();
+ return getMetaHunkR().getOr(x, 0, z, new ParallaxChunkMeta());
+ }
+
+ public ParallaxChunkMeta getMetaRW(int x, int z)
+ {
+ lastUse = M.ms();
+ dirtyMeta = true;
+ ParallaxChunkMeta p = getMetaHunkRW().get(x, 0, z);
+ if(p == null)
+ {
+ p = new ParallaxChunkMeta();
+ getMetaHunkRW().set(x,0,z,p);
+ }
+
+ return p;
+ }
+
+ private Hunk getMetaHunkR()
+ {
+ if(meta == null)
+ {
+ meta = loadMetaHunk();
+ }
+
+ return meta;
+ }
+
+ private Hunk getMetaHunkRW()
+ {
+ dirtyMeta = true;
+ return getMetaHunkR();
+ }
+
+ public synchronized Hunk loadMetaHunk()
+ {
+ lastUse = M.ms();
+ if(meta == null)
+ {
+ Tag t = getCompound().getValue().get("meta");
+
+ if((t instanceof ByteArrayTag))
+ {
+ try {
+ meta = metaAdapter.read((x,y,z) -> Hunk.newArrayHunk(32, 1, 32), (ByteArrayTag)t);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if(meta == null)
+ {
+ meta = Hunk.newArrayHunk(32, 1, 32);
+ }
+ }
+
+ return meta;
+ }
+
+ public synchronized void unloadMetaHunk()
+ {
+ if(dirtyMeta)
+ {
+ saveMetaHunk();
+ dirtyMeta = false;
+ }
+
+ meta = null;
+ }
+
+ public synchronized void saveMetaHunk()
+ {
+ if(meta != null && dirtyMeta)
+ {
+ try {
+ getCompound().getValue().put("meta", meta.writeByteArrayTag(metaAdapter, "meta"));
+ dirtyMeta = false;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void save() throws IOException
+ {
+ blockSlice.save();
+ objectSlice.save();
+ updateSlice.save();
+ saveMetaHunk();
+ super.save();
+ }
+
+ public void unload()
+ {
+ blockSlice.unloadAll();
+ objectSlice.unloadAll();
+ updateSlice.unloadAll();
+ unloadMetaHunk();
+ }
+
+ public HunkRegionSlice getBlockSlice() {
+ lastUse = M.ms();
+ return blockSlice;
+ }
+
+ public HunkRegionSlice getObjectSlice() {
+ lastUse = M.ms();
+ return objectSlice;
+ }
+
+ public HunkRegionSlice getUpdateSlice() {
+ lastUse = M.ms();
+ return updateSlice;
+ }
+
+ public void cleanup(long c) {
+ blockSlice.cleanup(c);
+ objectSlice.cleanup(c);
+ updateSlice.cleanup(c);
+ }
+}
diff --git a/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxWorld.java b/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxWorld.java
index 78f81e3c9..eaaaec11e 100644
--- a/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxWorld.java
+++ b/src/main/java/com/volmit/iris/gen/v2/scaffold/parallax/ParallaxWorld.java
@@ -3,19 +3,18 @@ package com.volmit.iris.gen.v2.scaffold.parallax;
import java.io.File;
import java.io.IOException;
+import com.volmit.iris.util.*;
import org.bukkit.block.data.BlockData;
import com.volmit.iris.gen.v2.scaffold.hunk.Hunk;
-import com.volmit.iris.gen.v2.scaffold.hunk.io.HunkCompoundRegion;
-import com.volmit.iris.util.KList;
-import com.volmit.iris.util.KMap;
public class ParallaxWorld implements ParallaxAccess
{
- private final KMap loadedRegions;
+ private final KMap loadedRegions;
private final KList save;
private final File folder;
private final int height;
+ private final ChronoLatch cleanup;
public ParallaxWorld(int height, File folder)
{
@@ -23,12 +22,13 @@ public class ParallaxWorld implements ParallaxAccess
this.folder = folder;
save = new KList<>();
loadedRegions = new KMap<>();
+ cleanup = new ChronoLatch(10000);
folder.mkdirs();
}
public synchronized void close()
{
- for(HunkCompoundRegion i : loadedRegions.v())
+ for(ParallaxRegion i : loadedRegions.v())
{
unload(i.getX(), i.getZ());
}
@@ -37,7 +37,7 @@ public class ParallaxWorld implements ParallaxAccess
loadedRegions.clear();
}
- public synchronized void save(HunkCompoundRegion region)
+ public synchronized void save(ParallaxRegion region)
{
try
{
@@ -79,23 +79,29 @@ public class ParallaxWorld implements ParallaxAccess
}
}
- public synchronized HunkCompoundRegion load(int x, int z)
+ public synchronized ParallaxRegion load(int x, int z)
{
if(isLoaded(x, z))
{
return loadedRegions.get(key(x, z));
}
- HunkCompoundRegion v = new HunkCompoundRegion(height, folder, x, z);
+ ParallaxRegion v = new ParallaxRegion(height, folder, x, z);
loadedRegions.put(key(x, z), v);
+
+ if(cleanup.flip())
+ {
+ cleanup();
+ }
+
return v;
}
- public HunkCompoundRegion getR(int x, int z)
+ public ParallaxRegion getR(int x, int z)
{
long key = key(x, z);
- HunkCompoundRegion region = loadedRegions.get(key);
+ ParallaxRegion region = loadedRegions.get(key);
if(region == null)
{
@@ -105,7 +111,7 @@ public class ParallaxWorld implements ParallaxAccess
return region;
}
- public HunkCompoundRegion getRW(int x, int z)
+ public ParallaxRegion getRW(int x, int z)
{
save.addIfMissing(key(x, z));
return getR(x, z);
@@ -151,4 +157,64 @@ public class ParallaxWorld implements ParallaxAccess
{
return getRW(x >> 5, z >> 5).getUpdateSlice().getRW(x & 31, z & 31);
}
+
+ @Override
+ public ParallaxChunkMeta getMetaR(int x, int z)
+ {
+ return getR(x >> 5, z >> 5).getMetaR(x & 31, z & 31);
+ }
+
+ @Override
+ public ParallaxChunkMeta getMetaRW(int x, int z)
+ {
+ return getRW(x >> 5, z >> 5).getMetaRW(x & 31, z & 31);
+ }
+
+ public void cleanup()
+ {
+ cleanup(30000, 10000);
+ }
+
+ @Override
+ public void cleanup(long r, long c) {
+ J.a(() -> {
+ synchronized (loadedRegions)
+ {
+ for(ParallaxRegion i : loadedRegions.v())
+ {
+ if(i.hasBeenIdleLongerThan(r))
+ {
+ unload(i.getX(), i.getZ());
+ }
+
+ else
+ {
+ i.cleanup(c);
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ public void saveAll() {
+ J.a(this::saveAllNOW);
+ }
+
+ @Override
+ public synchronized void saveAllNOW() {
+ synchronized (loadedRegions)
+ {
+ for(ParallaxRegion i : loadedRegions.v())
+ {
+ synchronized (save)
+ {
+ if(save.contains(key(i.getX(), i.getZ())))
+ {
+ save(i.getX(), i.getZ());
+ }
+ }
+ }
+ }
+ }
}