Parallax 2 Backend & API Complete

This commit is contained in:
Daniel Mills 2020-10-28 00:28:56 -04:00
parent aff7e49024
commit 9e062acafb
8 changed files with 374 additions and 84 deletions

15
.idea/workspace.xml generated
View File

@ -14,8 +14,8 @@
<option name="RECENT_TEMPLATES">
<list>
<option value="Enum" />
<option value="Class" />
<option value="Interface" />
<option value="Class" />
</list>
</option>
</component>
@ -48,6 +48,7 @@
</component>
<component name="RecentsManager">
<key name="MoveClassesOrPackagesDialog.RECENTS_KEY">
<recent name="com.volmit.iris.gen.v2.scaffold.parallax" />
<recent name="com.volmit.iris.gen.v2.scaffold.hunk.io" />
<recent name="com.volmit.iris.gen.v2.scaffold.hunk.view" />
<recent name="com.volmit.iris.gen.v2.scaffold.hunk.storage" />
@ -113,14 +114,14 @@
<screen x="0" y="0" width="1920" height="1050" />
</state>
<state x="410" y="171" width="1234" height="708" key="#com.intellij.execution.impl.EditConfigurationsDialog/-1920.0.1920.1050/1920.0.1920.1050/0.0.1920.1050@0.0.1920.1050" timestamp="1603832427608" />
<state x="718" y="163" key="#com.intellij.ide.util.MemberChooser" timestamp="1603846309805">
<state x="718" y="163" key="#com.intellij.ide.util.MemberChooser" timestamp="1603859002833">
<screen x="0" y="0" width="1920" height="1050" />
</state>
<state x="718" y="163" key="#com.intellij.ide.util.MemberChooser/-1920.0.1920.1050/1920.0.1920.1050/0.0.1920.1050@0.0.1920.1050" timestamp="1603846309805" />
<state x="675" y="394" key="#com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesDialog.classes" timestamp="1603843352310">
<state x="718" y="163" key="#com.intellij.ide.util.MemberChooser/-1920.0.1920.1050/1920.0.1920.1050/0.0.1920.1050@0.0.1920.1050" timestamp="1603859002833" />
<state x="675" y="394" key="#com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesDialog.classes" timestamp="1603856300756">
<screen x="0" y="0" width="1920" height="1050" />
</state>
<state x="675" y="394" key="#com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesDialog.classes/-1920.0.1920.1050/1920.0.1920.1050/0.0.1920.1050@0.0.1920.1050" timestamp="1603843352310" />
<state x="675" y="394" key="#com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesDialog.classes/-1920.0.1920.1050/1920.0.1920.1050/0.0.1920.1050@0.0.1920.1050" timestamp="1603856300756" />
<state x="624" y="211" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog" timestamp="1603833082664">
<screen x="0" y="0" width="1920" height="1050" />
</state>
@ -141,9 +142,9 @@
<screen x="0" y="0" width="1920" height="1050" />
</state>
<state width="1921" height="983" key="GridCell.Tab.0.right/-1920.0.1920.1050/1920.0.1920.1050/0.0.1920.1050@0.0.1920.1050" timestamp="1603837860350" />
<state x="598" y="193" width="723" height="664" key="find.popup" timestamp="1603846050804">
<state x="598" y="193" width="723" height="664" key="find.popup" timestamp="1603856657478">
<screen x="0" y="0" width="1920" height="1050" />
</state>
<state x="598" y="193" width="723" height="664" key="find.popup/-1920.0.1920.1050/1920.0.1920.1050/0.0.1920.1050@0.0.1920.1050" timestamp="1603846050804" />
<state x="598" y="193" width="723" height="664" key="find.popup/-1920.0.1920.1050/1920.0.1920.1050/0.0.1920.1050@0.0.1920.1050" timestamp="1603856657478" />
</component>
</project>

View File

@ -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<BlockData> blockSlice;
@Getter
private HunkRegionSlice<String> objectSlice;
@Getter
private HunkRegionSlice<Boolean> 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();
}
}

View File

@ -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<String, Tag> 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;
}
}

View File

@ -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<T>
{
@ -24,6 +18,7 @@ public class HunkRegionSlice<T>
private final CompoundTag compound;
private final String key;
private final KMap<Short, Hunk<T>> loadedChunks;
private final KMap<Short, Long> lastUse;
private final KList<Short> save;
private final int height;
@ -36,6 +31,23 @@ public class HunkRegionSlice<T>
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<T>
save.clear();
loadedChunks.clear();
lastUse.clear();
}
public synchronized void save(Hunk<T> region, int x, int z)
@ -138,6 +151,7 @@ public class HunkRegionSlice<T>
save.remove(key);
}
lastUse.remove(key);
loadedChunks.remove(key);
}
}
@ -168,6 +182,7 @@ public class HunkRegionSlice<T>
{
v = factory.apply(16, height, 16);
}
loadedChunks.put(ikey(x, z), v);
return v;
@ -184,6 +199,8 @@ public class HunkRegionSlice<T>
c = load(x, z);
}
lastUse.put(ikey(x,z), M.ms());
return c;
}

View File

@ -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<BlockData> getBlocksR(int x, int z);
public Hunk<BlockData> getBlocksRW(int x, int z);
@ -51,4 +76,16 @@ public interface ParallaxAccess
public Hunk<Boolean> getUpdatesR(int x, int z);
public Hunk<Boolean> 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();
}

View File

@ -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<CompoundTag, HunkIOAdapter<ParallaxChunkMeta>> adapter = (c) -> new PaletteHunkIOAdapter<ParallaxChunkMeta>() {
@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);
}
}

View File

@ -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<ParallaxChunkMeta> meta;
private HunkIOAdapter<ParallaxChunkMeta> metaAdapter;
private HunkRegionSlice<BlockData> blockSlice;
private HunkRegionSlice<String> objectSlice;
private HunkRegionSlice<Boolean> 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<ParallaxChunkMeta> getMetaHunkR()
{
if(meta == null)
{
meta = loadMetaHunk();
}
return meta;
}
private Hunk<ParallaxChunkMeta> getMetaHunkRW()
{
dirtyMeta = true;
return getMetaHunkR();
}
public synchronized Hunk<ParallaxChunkMeta> 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<BlockData> getBlockSlice() {
lastUse = M.ms();
return blockSlice;
}
public HunkRegionSlice<String> getObjectSlice() {
lastUse = M.ms();
return objectSlice;
}
public HunkRegionSlice<Boolean> getUpdateSlice() {
lastUse = M.ms();
return updateSlice;
}
public void cleanup(long c) {
blockSlice.cleanup(c);
objectSlice.cleanup(c);
updateSlice.cleanup(c);
}
}

View File

@ -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<Long, HunkCompoundRegion> loadedRegions;
private final KMap<Long, ParallaxRegion> loadedRegions;
private final KList<Long> 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());
}
}
}
}
}
}