Hunks Galore

This commit is contained in:
Daniel Mills 2020-10-26 03:50:36 -04:00
parent 4a11ac917b
commit 0dd45cdfa2
14 changed files with 1203 additions and 172 deletions

View File

@ -1,171 +0,0 @@
package com.volmit.iris.gen.v2.scaffold;
public class HunkView<T> implements Hunk<T>
{
private final int ox;
private final int oy;
private final int oz;
private final int w;
private final int h;
private final int d;
private final Hunk<T> src;
public HunkView(Hunk<T> src)
{
this(src, src.getWidth(), src.getHeight(), src.getDepth());
}
public HunkView(Hunk<T> src, int w, int h, int d)
{
this(src, w, h, d, 0, 0, 0);
}
public HunkView(Hunk<T> src, int w, int h, int d, int ox, int oy, int oz)
{
this.src = src;
this.w = w;
this.h = h;
this.d = d;
this.ox = ox;
this.oy = oy;
this.oz = oz;
}
@Override
public Hunk<T> croppedView(int x1, int y1, int z1, int x2, int y2, int z2)
{
return new HunkView<T>(this, x2 - x1, y2 - y1, z2 - z1, x1 + ox, y1 + oy, z1 + oz);
}
@Override
public ArrayHunk<T> crop(int x1, int y1, int z1, int x2, int y2, int z2)
{
ArrayHunk<T> h = new ArrayHunk<T>(x2 - x1, y2 - y1, z2 - z1);
for(int i = x1; i < x2; i++)
{
for(int j = y1; j < y2; j++)
{
for(int k = z1; k < z2; k++)
{
h.set(i - x1, j - y1, k - z1, get(i, j, k));
}
}
}
return h;
}
@Override
public void insert(int offX, int offY, int offZ, Hunk<T> hunk, boolean invertY)
{
if(offX + (hunk.getWidth() - 1) >= w || offY + (hunk.getHeight() - 1) >= h || offZ + (hunk.getDepth() - 1) >= d || offX < 0 || offY < 0 || offZ < 0)
{
throw new RuntimeException("Cannot insert hunk " + hunk.getWidth() + "," + hunk.getHeight() + "," + hunk.getDepth() + " into Hunk " + w + "," + h + "," + d + " with offset " + offZ + "," + offY + "," + offZ);
}
for(int i = offX; i < offX + hunk.getWidth(); i++)
{
for(int j = offY; j < offY + hunk.getHeight(); j++)
{
for(int k = offZ; k < offZ + hunk.getDepth(); k++)
{
set(i, j, k, hunk.get(i - offX, j - offY, k - offZ));
}
}
}
}
@Override
public void set(int x1, int y1, int z1, int x2, int y2, int z2, T t)
{
if(x1 >= w || y1 >= h || z1 >= d || x2 >= w || y2 >= h || z2 >= d)
{
throw new RuntimeException(x1 + "-" + x2 + " " + y1 + "-" + y2 + " " + z1 + "-" + z2 + " is out of the bounds 0,0,0 - " + (w - 1) + "," + (h - 1) + "," + (d - 1));
}
src.set(x1, y1, z1, x2, y2, z2, t);
}
@Override
public void set(int x, int y, int z, T t)
{
if(x >= w || y >= h || z >= d)
{
throw new RuntimeException(x + " " + y + " " + z + " is out of the bounds 0,0,0 - " + (w - 1) + "," + (h - 1) + "," + (d - 1));
}
src.set(x + ox, y + oy, z + oz, t);
}
@Override
public T get(int x, int y, int z)
{
if(x >= w || y >= h || z >= d)
{
throw new RuntimeException(x + " " + y + " " + z + " is out of the bounds 0,0,0 - " + (w - 1) + "," + (h - 1) + "," + (d - 1));
}
return src.get(x + ox, y + oy, z + oz);
}
@Override
public T getClosest(int x, int y, int z)
{
return src.get(x >= w ? w + ox - 1 : x + ox, y >= h ? h + oy - 1 : y + oy, z >= d ? d + oz - 1 : z + oz);
}
@Override
public void fill(T t)
{
set(0 + ox, 0 + oy, 0 + oz, w - 1 + ox, h - 1 + oy, d - 1 + oz, t);
}
@Override
public int getWidth()
{
return w;
}
@Override
public int getDepth()
{
return d;
}
@Override
public int getHeight()
{
return h;
}
@Override
public Hunk<T> getFace(HunkFace f)
{
switch(f)
{
case BOTTOM:
return croppedView(0, 0, 0, getWidth() - 1, 0, getDepth() - 1);
case EAST:
return croppedView(getWidth() - 1, 0, 0, getWidth() - 1, getHeight() - 1, getDepth() - 1);
case NORTH:
return croppedView(0, 0, 0, getWidth() - 1, getHeight() - 1, 0);
case SOUTH:
return croppedView(0, 0, 0, 0, getHeight() - 1, getDepth() - 1);
case TOP:
return croppedView(0, getHeight() - 1, 0, getWidth() - 1, getHeight() - 1, getDepth() - 1);
case WEST:
return croppedView(0, 0, getDepth() - 1, getWidth() - 1, getHeight() - 1, getDepth() - 1);
default:
break;
}
return null;
}
@Override
public Hunk<T> getSource()
{
return src;
}
}

View File

@ -0,0 +1,43 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
import org.bouncycastle.util.Arrays;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class ArrayHunk<T> extends StorageHunk<T> implements Hunk<T>
{
private final T[] data;
@SuppressWarnings("unchecked")
protected ArrayHunk(int w, int h, int d)
{
super(w, h, d);
data = (T[]) new Object[w * h * d];
}
@Override
public void setRaw(int x, int y, int z, T t)
{
data[index(x, y, z)] = t;
}
@Override
public T getRaw(int x, int y, int z)
{
return data[index(x, y, z)];
}
private int index(int x, int y, int z)
{
return (z * getWidth() * getHeight()) + (y * getWidth()) + x;
}
@Override
public void fill(T t)
{
Arrays.fill(data, t);
}
}

View File

@ -0,0 +1,36 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
import com.google.common.util.concurrent.AtomicDoubleArray;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class AtomicDoubleHunk extends StorageHunk<Double> implements Hunk<Double>
{
private final AtomicDoubleArray data;
protected AtomicDoubleHunk(int w, int h, int d)
{
super(w, h, d);
data = new AtomicDoubleArray(w * h * d);
}
@Override
public void setRaw(int x, int y, int z, Double t)
{
data.set(index(x, y, z), t);
}
@Override
public Double getRaw(int x, int y, int z)
{
return data.get(index(x, y, z));
}
private int index(int x, int y, int z)
{
return (z * getWidth() * getHeight()) + (y * getWidth()) + x;
}
}

View File

@ -0,0 +1,36 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
import java.util.concurrent.atomic.AtomicReferenceArray;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class AtomicHunk<T> extends StorageHunk<T> implements Hunk<T>
{
private final AtomicReferenceArray<T> data;
protected AtomicHunk(int w, int h, int d)
{
super(w, h, d);
data = new AtomicReferenceArray<T>(w * h * d);
}
@Override
public void setRaw(int x, int y, int z, T t)
{
data.set(index(x, y, z), t);
}
@Override
public T getRaw(int x, int y, int z)
{
return data.get(index(x, y, z));
}
private int index(int x, int y, int z)
{
return (z * getWidth() * getHeight()) + (y * getWidth()) + x;
}
}

View File

@ -0,0 +1,36 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
import java.util.concurrent.atomic.AtomicIntegerArray;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class AtomicIntegerHunk extends StorageHunk<Integer> implements Hunk<Integer>
{
private final AtomicIntegerArray data;
protected AtomicIntegerHunk(int w, int h, int d)
{
super(w, h, d);
data = new AtomicIntegerArray(w * h * d);
}
@Override
public void setRaw(int x, int y, int z, Integer t)
{
data.set(index(x, y, z), t);
}
@Override
public Integer getRaw(int x, int y, int z)
{
return data.get(index(x, y, z));
}
private int index(int x, int y, int z)
{
return (z * getWidth() * getHeight()) + (y * getWidth()) + x;
}
}

View File

@ -0,0 +1,36 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
import java.util.concurrent.atomic.AtomicLongArray;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class AtomicLongHunk extends StorageHunk<Long> implements Hunk<Long>
{
private final AtomicLongArray data;
protected AtomicLongHunk(int w, int h, int d)
{
super(w, h, d);
data = new AtomicLongArray(w * h * d);
}
@Override
public void setRaw(int x, int y, int z, Long t)
{
data.set(index(x, y, z), t);
}
@Override
public Long getRaw(int x, int y, int z)
{
return data.get(index(x, y, z));
}
private int index(int x, int y, int z)
{
return (z * getWidth() * getHeight()) + (y * getWidth()) + x;
}
}

View File

@ -0,0 +1,44 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
public class BiomeGridHunkView implements Hunk<Biome>
{
private final BiomeGrid chunk;
public BiomeGridHunkView(BiomeGrid chunk)
{
this.chunk = chunk;
}
@Override
public int getWidth()
{
return 16;
}
@Override
public int getDepth()
{
return 16;
}
@Override
public int getHeight()
{
return 256;
}
@Override
public void setRaw(int x, int y, int z, Biome t)
{
chunk.setBiome(x, y, z, t);
}
@Override
public Biome getRaw(int x, int y, int z)
{
return chunk.getBiome(x, y, z);
}
}

View File

@ -0,0 +1,51 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
import org.bukkit.block.data.BlockData;
import org.bukkit.generator.ChunkGenerator.ChunkData;
public class ChunkDataHunkView implements Hunk<BlockData>
{
private final ChunkData chunk;
public ChunkDataHunkView(ChunkData chunk)
{
this.chunk = chunk;
}
@Override
public int getWidth()
{
return 16;
}
@Override
public int getDepth()
{
return 16;
}
@Override
public int getHeight()
{
return chunk.getMaxHeight();
}
@Override
public void set(int x1, int y1, int z1, int x2, int y2, int z2, BlockData t)
{
enforceBounds(x1, y1, z1, x2 - x1, y2 - y1, z2 - z1);
chunk.setRegion(x1, y1, z1, x2, y2, z2, t);
}
@Override
public void setRaw(int x, int y, int z, BlockData t)
{
chunk.setBlock(x, y, z, t);
}
@Override
public BlockData getRaw(int x, int y, int z)
{
return chunk.getBlockData(x, y, z);
}
}

View File

@ -0,0 +1,738 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
import java.util.function.Consumer;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import com.volmit.iris.gen.v2.scaffold.multicore.BurstExecutor;
import com.volmit.iris.gen.v2.scaffold.multicore.MultiBurst;
import com.volmit.iris.util.Consumer2;
import com.volmit.iris.util.Consumer3;
import com.volmit.iris.util.Consumer4;
import com.volmit.iris.util.Consumer5;
import com.volmit.iris.util.Function3;
import com.volmit.iris.util.KList;
public interface Hunk<T>
{
/**
* Create a hunk view from a source hunk. This view reads and writes through to
* the source hunk. Its is not a copy.
*
* @param <T>
* the type
* @param src
* the source hunk
* @return the hunk view
*/
public static <T> Hunk<T> view(Hunk<T> src)
{
return new HunkView<T>(src);
}
public static Hunk<Biome> view(BiomeGrid biome)
{
return new BiomeGridHunkView(biome);
}
public static Hunk<BlockData> view(ChunkData src)
{
return new ChunkDataHunkView(src);
}
public static <T> Hunk<T> newHunk(int w, int h, int d)
{
return newArrayHunk(w, h, d);
}
@SafeVarargs
public static <T> Hunk<T> newCombinedHunk(Hunk<T>... hunks)
{
return newCombinedArrayHunk(hunks);
}
public static <T> Hunk<T> newArrayHunk(int w, int h, int d)
{
return new ArrayHunk<>(w, h, d);
}
@SafeVarargs
public static <T> Hunk<T> newCombinedArrayHunk(Hunk<T>... hunks)
{
return combined(Hunk::newArrayHunk, hunks);
}
public static <T> Hunk<T> newSynchronizedArrayHunk(int w, int h, int d)
{
return new SynchronizedArrayHunk<>(w, h, d);
}
@SafeVarargs
public static <T> Hunk<T> newCombinedSynchronizedArrayHunk(Hunk<T>... hunks)
{
return combined(Hunk::newSynchronizedArrayHunk, hunks);
}
public static <T> Hunk<T> newMappedHunk(int w, int h, int d)
{
return new MappedHunk<>(w, h, d);
}
@SafeVarargs
public static <T> Hunk<T> newCombinedMappedHunk(Hunk<T>... hunks)
{
return combined(Hunk::newMappedHunk, hunks);
}
public static <T> Hunk<T> newAtomicHunk(int w, int h, int d)
{
return new AtomicHunk<>(w, h, d);
}
@SafeVarargs
public static <T> Hunk<T> newCombinedAtomicHunk(Hunk<T>... hunks)
{
return combined(Hunk::newAtomicHunk, hunks);
}
public static Hunk<Double> newAtomicDoubleHunk(int w, int h, int d)
{
return new AtomicDoubleHunk(w, h, d);
}
@SafeVarargs
public static Hunk<Double> newCombinedAtomicDoubleHunk(Hunk<Double>... hunks)
{
return combined(Hunk::newAtomicDoubleHunk, hunks);
}
public static Hunk<Long> newAtomicLongHunk(int w, int h, int d)
{
return new AtomicLongHunk(w, h, d);
}
@SafeVarargs
public static Hunk<Long> newCombinedAtomicLongHunk(Hunk<Long>... hunks)
{
return combined(Hunk::newAtomicLongHunk, hunks);
}
public static Hunk<Integer> newAtomicIntegerHunk(int w, int h, int d)
{
return new AtomicIntegerHunk(w, h, d);
}
@SafeVarargs
public static Hunk<Integer> newCombinedAtomicIntegerHunk(Hunk<Integer>... hunks)
{
return combined(Hunk::newAtomicIntegerHunk, hunks);
}
/**
* Creates a new bounding hunk from the given hunks
*
* @param <T>
* the type
* @param factory
* the factory that creates a hunk
* @param hunks
* the hunks
* @return the new bounding hunk
*/
@SafeVarargs
public static <T> Hunk<T> combined(Function3<Integer, Integer, Integer, Hunk<T>> factory, Hunk<T>... hunks)
{
int w = 0;
int h = 0;
int d = 0;
for(Hunk<T> i : hunks)
{
w = Math.max(w, i.getWidth());
h = Math.max(h, i.getHeight());
d = Math.max(d, i.getDepth());
}
Hunk<T> b = factory.apply(w, h, d);
for(Hunk<T> i : hunks)
{
b.insert(i);
}
return b;
}
default Hunk<T> iterate(Consumer3<Integer, Integer, Integer> c)
{
for(int i = 0; i < getWidth(); i++)
{
for(int j = 0; j < getWidth(); j++)
{
for(int k = 0; k < getWidth(); k++)
{
c.accept(i, j, k);
}
}
}
return this;
}
default Hunk<T> iterate(Consumer4<Integer, Integer, Integer, T> c)
{
for(int i = 0; i < getWidth(); i++)
{
for(int j = 0; j < getWidth(); j++)
{
for(int k = 0; k < getWidth(); k++)
{
c.accept(i, j, k, get(i, j, k));
}
}
}
return this;
}
default Hunk<T> compute3D(int parallelism, Consumer4<Integer, Integer, Integer, Hunk<T>> v)
{
BurstExecutor e = MultiBurst.burst.burst(parallelism);
KList<Runnable> rq = new KList<Runnable>(parallelism);
getSections3D(parallelism, (xx, yy, zz, h, r) -> e.queue(() ->
{
v.accept(xx, yy, zz, h);
synchronized(rq)
{
rq.add(r);
}
}), (xx, yy, zz, c) -> insert(xx, yy, zz, c));
e.complete();
rq.forEach(Runnable::run);
return this;
}
default Hunk<T> compute2D(int parallelism, Consumer4<Integer, Integer, Integer, Hunk<T>> v)
{
BurstExecutor e = MultiBurst.burst.burst(parallelism);
KList<Runnable> rq = new KList<Runnable>(parallelism);
getSections2D(parallelism, (xx, yy, zz, h, r) -> e.queue(() ->
{
v.accept(xx, yy, zz, h);
synchronized(rq)
{
rq.add(r);
}
}), (xx, yy, zz, c) -> insert(xx, yy, zz, c));
e.complete();
rq.forEach(Runnable::run);
return this;
}
default Hunk<T> compute2DAtomically(int parallelism, Consumer4<Integer, Integer, Integer, Hunk<T>> v)
{
BurstExecutor e = MultiBurst.burst.burst(parallelism);
KList<Runnable> rq = new KList<Runnable>(parallelism);
getAtomicSections2D(parallelism, (xx, yy, zz, h) -> e.queue(() -> v.accept(xx, yy, zz, h)));
e.complete();
rq.forEach(Runnable::run);
return this;
}
default Hunk<T> compute3DAtomically(int parallelism, Consumer4<Integer, Integer, Integer, Hunk<T>> v)
{
BurstExecutor e = MultiBurst.burst.burst(parallelism);
KList<Runnable> rq = new KList<Runnable>(parallelism);
getAtomicSections3D(parallelism, (xx, yy, zz, h) -> e.queue(() -> v.accept(xx, yy, zz, h)));
e.complete();
rq.forEach(Runnable::run);
return this;
}
default Hunk<T> getSections2D(int sections, Consumer5<Integer, Integer, Integer, Hunk<T>, Runnable> v)
{
return getSections2D(sections, v, (xx, yy, zz, c) -> insert(xx, yy, zz, c));
}
default Hunk<T> getSections2D(int sections, Consumer5<Integer, Integer, Integer, Hunk<T>, Runnable> v, Consumer4<Integer, Integer, Integer, Hunk<T>> inserter)
{
int dim = (int) Math.ceil(Math.sqrt(sections));
dim = dim < 2 ? 2 : dim;
dim = dim % 2 != 0 ? dim + 1 : dim;
int w = getWidth() / dim;
int d = getDepth() / dim;
int i, j;
for(i = 0; i < getWidth(); i += w)
{
int ii = i;
for(j = 0; j < getDepth(); j += d)
{
int jj = j;
getSection(i, 0, j, i + w - 1, getHeight() - 1, j + d - 1, (h, r) -> v.accept(ii, 0, jj, h, r), inserter);
}
}
return this;
}
default Hunk<T> getAtomicSections2D(int sections, Consumer4<Integer, Integer, Integer, Hunk<T>> v)
{
int dim = (int) Math.ceil(Math.sqrt(sections));
dim = dim < 2 ? 2 : dim;
dim = dim % 2 != 0 ? dim + 1 : dim;
int w = getWidth() / dim;
int d = getDepth() / dim;
int i, j;
for(i = 0; i < getWidth(); i += w)
{
int ii = i;
for(j = 0; j < getDepth(); j += d)
{
int jj = j;
getAtomicSection(i, 0, j, i + w - 1, getHeight() - 1, j + d - 1, (h) -> v.accept(ii, 0, jj, h));
}
}
return this;
}
default Hunk<T> getSections3D(int sections, Consumer5<Integer, Integer, Integer, Hunk<T>, Runnable> v)
{
return getSections3D(sections, v, (xx, yy, zz, c) -> insert(xx, yy, zz, c));
}
default Hunk<T> getSections3D(int sections, Consumer5<Integer, Integer, Integer, Hunk<T>, Runnable> v, Consumer4<Integer, Integer, Integer, Hunk<T>> inserter)
{
int dim = (int) Math.ceil(Math.cbrt(sections));
dim = dim < 2 ? 2 : dim;
dim = dim % 2 != 0 ? dim + 1 : dim;
int w = getWidth() / dim;
int h = getHeight() / dim;
int d = getDepth() / dim;
int i, j, k;
for(i = 0; i < getWidth(); i += w)
{
int ii = i;
for(j = 0; j < getHeight(); j += d)
{
int jj = j;
for(k = 0; k < getDepth(); k += d)
{
int kk = k;
getSection(i, j, k, i + w - 1, j + h - 1, k + d - 1, (hh, r) -> v.accept(ii, jj, kk, hh, r), inserter);
}
}
}
return this;
}
default Hunk<T> getAtomicSections3D(int sections, Consumer4<Integer, Integer, Integer, Hunk<T>> v)
{
int dim = (int) Math.ceil(Math.cbrt(sections));
dim = dim < 2 ? 2 : dim;
dim = dim % 2 != 0 ? dim + 1 : dim;
int w = getWidth() / dim;
int h = getHeight() / dim;
int d = getDepth() / dim;
int i, j, k;
for(i = 0; i < getWidth(); i += w)
{
int ii = i;
for(j = 0; j < getHeight(); j += d)
{
int jj = j;
for(k = 0; k < getDepth(); k += d)
{
int kk = k;
getAtomicSection(i, j, k, i + w - 1, j + h - 1, k + d - 1, (hh) -> v.accept(ii, jj, kk, hh));
}
}
}
return this;
}
default Hunk<T> getSection(int x, int y, int z, int x1, int y1, int z1, Consumer2<Hunk<T>, Runnable> v)
{
return getSection(x, y, z, x1, y1, z1, v, (xx, yy, zz, c) -> insert(xx, yy, zz, c));
}
default Hunk<T> getSection(int x, int y, int z, int x1, int y1, int z1, Consumer2<Hunk<T>, Runnable> v, Consumer4<Integer, Integer, Integer, Hunk<T>> inserter)
{
Hunk<T> copy = crop(x, y, z, x1, y1, z1);
v.accept(copy, () -> inserter.accept(x, y, z, copy));
return this;
}
default Hunk<T> getAtomicSection(int x, int y, int z, int x1, int y1, int z1, Consumer<Hunk<T>> v)
{
v.accept(croppedView(x, y, z, x1, y1, z1));
return this;
}
default void enforceBounds(int x, int y, int z)
{
if(x < 0 || x >= getWidth() || y < 0 || y >= getHeight() || z < 0 || z >= getDepth())
{
throw new IndexOutOfBoundsException(x + "," + y + "," + z + " does not fit within size " + getWidth() + "," + getHeight() + "," + getDepth() + " (0,0,0 to " + (getWidth() - 1) + "," + (getHeight() - 1) + "," + (getDepth() - 1) + ")");
}
}
default void enforceBounds(int x, int y, int z, int w, int h, int d)
{
if(x < 0 || x >= getWidth() || y < 0 || y >= getHeight() || z < 0 || z >= getDepth() || x + w < 0 || x + w >= getWidth() || y + h < 0 || y + h >= getHeight() || z + d < 0 || z + d >= getDepth())
{
throw new IndexOutOfBoundsException("The hunk " + w + "," + h + "," + d + " with an offset of " + x + "," + y + "," + z + " does not fit within the parent hunk " + getWidth() + "," + getHeight() + "," + getDepth() + " (0,0,0 to " + (getWidth() - 1) + "," + (getHeight() - 1) + "," + (getDepth() - 1) + ")");
}
}
/**
* Create a new hunk from a section of this hunk.
*
*
* @param x1
* The min x (inclusive)
* @param y1
* The min y (inclusive)
* @param z1
* The min z (inclusive)
* @param x2
* The max x (exclusive)
* @param y2
* The max y (exclusive)
* @param z2
* The max z (exclusive)
* @return the new hunk (x2-x1, y2-y1, z2-z1)
*/
default ArrayHunk<T> crop(int x1, int y1, int z1, int x2, int y2, int z2)
{
ArrayHunk<T> h = new ArrayHunk<T>(x2 - x1, y2 - y1, z2 - z1);
enforceBounds(x1, y1, z1, x2 - x1, y2 - y1, z2 - z1);
for(int i = x1; i < x2; i++)
{
for(int j = y1; j < y2; j++)
{
for(int k = z1; k < z2; k++)
{
h.setRaw(i - x1, j - y1, k - z1, getRaw(i, j, k));
}
}
}
return h;
}
/**
* Create a new view of this same hunk from a section of this hunk.
* Modifications are routed to this hunk!
*
* @param x1
* The min x (inclusive)
* @param y1
* The min y (inclusive)
* @param z1
* The min z (inclusive)
* @param x2
* The max x (exclusive)
* @param y2
* The max y (exclusive)
* @param z2
* The max z (exclusive)
* @return the cropped view of this hunk (x2-x1, y2-y1, z2-z1)
*/
default Hunk<T> croppedView(int x1, int y1, int z1, int x2, int y2, int z2)
{
enforceBounds(x1, y1, z1, x2 - x1, y2 - y1, z2 - z1);
return new HunkView<T>(this, x2 - x1, y2 - y1, z2 - z1, x1, y1, z1);
}
/**
* @return The X length
*/
public int getWidth();
/**
* @return The Z length
*/
public int getDepth();
/**
* @return The Y length
*/
public int getHeight();
/**
* Set a region
*
* @param x1
* inclusive 1st x
* @param y1
* inclusive 1st y
* @param z1
* inclusive 1st z
* @param x2
* inclusive 2nd x
* @param y2
* inclusive 2nd y
* @param z2
* inclusive 2nd z
* @param t
* the value to set
*/
default void set(int x1, int y1, int z1, int x2, int y2, int z2, T t)
{
enforceBounds(x1, y1, z1, x2 - x1, y2 - y1, z2 - z1);
for(int i = x1; i <= x2; i++)
{
for(int j = y1; j <= y2; j++)
{
for(int k = z1; k <= z2; k++)
{
setRaw(i, j, k, t);
}
}
}
}
/**
* Get the value to the closest valid position
*
* @param x
* the x
* @param y
* the y
* @param z
* the z
* @return the value closest to the border of the hunk
*/
default T getClosest(int x, int y, int z)
{
return getRaw(x >= getWidth() ? getWidth() - 1 : x, y >= getHeight() ? getHeight() - 1 : y, z >= getDepth() ? getDepth() - 1 : z);
}
default void fill(T t)
{
set(0, 0, 0, getWidth() - 1, getHeight() - 1, getDepth() - 1, t);
}
/**
* Get a 1 node thick hunk representing the face of this hunk
*
* @param f
* the face
* @return the hunk view of this hunk
*/
default Hunk<T> viewFace(HunkFace f)
{
switch(f)
{
case BOTTOM:
return croppedView(0, 0, 0, getWidth() - 1, 0, getDepth() - 1);
case EAST:
return croppedView(getWidth() - 1, 0, 0, getWidth() - 1, getHeight() - 1, getDepth() - 1);
case NORTH:
return croppedView(0, 0, 0, getWidth() - 1, getHeight() - 1, 0);
case SOUTH:
return croppedView(0, 0, 0, 0, getHeight() - 1, getDepth() - 1);
case TOP:
return croppedView(0, getHeight() - 1, 0, getWidth() - 1, getHeight() - 1, getDepth() - 1);
case WEST:
return croppedView(0, 0, getDepth() - 1, getWidth() - 1, getHeight() - 1, getDepth() - 1);
default:
break;
}
return null;
}
/**
* Crop (copy) a 1 node thick hunk representing the face of this hunk
*
* @param f
* the face
* @return the hunk copy (face) of this hunk
*/
default Hunk<T> cropFace(HunkFace f)
{
switch(f)
{
case BOTTOM:
return crop(0, 0, 0, getWidth() - 1, 0, getDepth() - 1);
case EAST:
return crop(getWidth() - 1, 0, 0, getWidth() - 1, getHeight() - 1, getDepth() - 1);
case NORTH:
return crop(0, 0, 0, getWidth() - 1, getHeight() - 1, 0);
case SOUTH:
return crop(0, 0, 0, 0, getHeight() - 1, getDepth() - 1);
case TOP:
return crop(0, getHeight() - 1, 0, getWidth() - 1, getHeight() - 1, getDepth() - 1);
case WEST:
return crop(0, 0, getDepth() - 1, getWidth() - 1, getHeight() - 1, getDepth() - 1);
default:
break;
}
return null;
}
/**
* Set a value at the given position
*
* @param x
* the x
* @param y
* the y
* @param z
* the z
* @param t
* the value
*/
default void set(int x, int y, int z, T t)
{
enforceBounds(x, y, z);
setRaw(x, y, z, t);
}
/**
* Set a value at the given position without checking coordinate bounds
*
* @param x
* the x
* @param y
* the y
* @param z
* the z
* @param t
* the value
*/
public void setRaw(int x, int y, int z, T t);
/**
* Get a value at the given position without checking coordinate bounds
*
* @param x
* the x
* @param y
* the y
* @param z
* the z
* @return the value or null
*/
public T getRaw(int x, int y, int z);
/**
* Get a value at the given position
*
* @param x
* the x
* @param y
* the y
* @param z
* the z
* @return the value or null
*/
default T get(int x, int y, int z)
{
enforceBounds(x, y, z);
return getRaw(x, y, z);
}
/**
* Insert a hunk into this one with an offset the inserted hunk
*
* @param offX
* the offset from zero for x
* @param offY
* the offset from zero for y
* @param offZ
* the offset from zero for z
* @param hunk
* the hunk to insert
*/
default void insert(int offX, int offY, int offZ, Hunk<T> hunk)
{
insert(offX, offY, offZ, hunk, false);
}
/**
* Insert a hunk into this one
*
* @param hunk
* the hunk to insert
*/
default void insert(Hunk<T> hunk)
{
insert(0, 0, 0, hunk, false);
}
/**
* Returns the source of this hunk view. This could return another hunk view,
* not an actual source, however it does return it's underlying data source. If
* this hunk is a data source and not a view, it will return null.
*
* @return the source or null if this is already the source
*/
default Hunk<T> getSource()
{
return null;
}
/**
* Insert a hunk into this one
*
* @param hunk
* the hunk to insert
* @param inverted
* invert the inserted hunk or not
*/
default void insert(Hunk<T> hunk, boolean inverted)
{
insert(0, 0, 0, hunk, inverted);
}
/**
* Insert a hunk into this one with an offset and possibly inverting the y of
* the inserted hunk
*
* @param offX
* the offset from zero for x
* @param offY
* the offset from zero for y
* @param offZ
* the offset from zero for z
* @param hunk
* the hunk to insert
* @param invertY
* should the inserted hunk be inverted
*/
default void insert(int offX, int offY, int offZ, Hunk<T> hunk, boolean invertY)
{
enforceBounds(offX, offY, offZ, hunk.getWidth(), hunk.getHeight(), hunk.getDepth());
for(int i = offX; i < offX + hunk.getWidth(); i++)
{
for(int j = offY; j < offY + hunk.getHeight(); j++)
{
for(int k = offZ; k < offZ + hunk.getDepth(); k++)
{
setRaw(i, j, k, hunk.getRaw(i - offX, j - offY, k - offZ));
}
}
}
}
}

View File

@ -1,4 +1,4 @@
package com.volmit.iris.gen.v2.scaffold;
package com.volmit.iris.gen.v2.scaffold.hunk;
public enum HunkFace
{

View File

@ -0,0 +1,69 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
public class HunkView<T> implements Hunk<T>
{
private final int ox;
private final int oy;
private final int oz;
private final int w;
private final int h;
private final int d;
private final Hunk<T> src;
public HunkView(Hunk<T> src)
{
this(src, src.getWidth(), src.getHeight(), src.getDepth());
}
public HunkView(Hunk<T> src, int w, int h, int d)
{
this(src, w, h, d, 0, 0, 0);
}
public HunkView(Hunk<T> src, int w, int h, int d, int ox, int oy, int oz)
{
this.src = src;
this.w = w;
this.h = h;
this.d = d;
this.ox = ox;
this.oy = oy;
this.oz = oz;
}
@Override
public void setRaw(int x, int y, int z, T t)
{
src.setRaw(x + ox, y + oy, z + oz, t);
}
@Override
public T getRaw(int x, int y, int z)
{
return src.getRaw(x + ox, y + oy, z + oz);
}
@Override
public int getWidth()
{
return w;
}
@Override
public int getDepth()
{
return d;
}
@Override
public int getHeight()
{
return h;
}
@Override
public Hunk<T> getSource()
{
return src;
}
}

View File

@ -0,0 +1,32 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
import com.volmit.iris.util.BlockPosition;
import com.volmit.iris.util.KMap;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class MappedHunk<T> extends StorageHunk<T> implements Hunk<T>
{
private final KMap<BlockPosition, T> data;
protected MappedHunk(int w, int h, int d)
{
super(w, h, d);
data = new KMap<>();
}
@Override
public void setRaw(int x, int y, int z, T t)
{
data.put(new BlockPosition(x, y, z), t);
}
@Override
public T getRaw(int x, int y, int z)
{
return data.get(new BlockPosition(x, y, z));
}
}

View File

@ -0,0 +1,29 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
import lombok.Data;
@Data
public abstract class StorageHunk<T> implements Hunk<T>
{
private final int width;
private final int height;
private final int depth;
protected StorageHunk(int width, int height, int depth)
{
if(width <= 0 || height <= 0 || depth <= 0)
{
throw new RuntimeException("Unsupported size " + width + " " + height + " " + depth);
}
this.width = width;
this.height = height;
this.depth = depth;
}
@Override
public abstract void setRaw(int x, int y, int z, T t);
@Override
public abstract T getRaw(int x, int y, int z);
}

View File

@ -0,0 +1,52 @@
package com.volmit.iris.gen.v2.scaffold.hunk;
import org.bouncycastle.util.Arrays;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class SynchronizedArrayHunk<T> extends StorageHunk<T> implements Hunk<T>
{
private final T[] data;
@SuppressWarnings("unchecked")
protected SynchronizedArrayHunk(int w, int h, int d)
{
super(w, h, d);
data = (T[]) new Object[w * h * d];
}
@Override
public void setRaw(int x, int y, int z, T t)
{
synchronized(data)
{
data[index(x, y, z)] = t;
}
}
@Override
public T getRaw(int x, int y, int z)
{
synchronized(data)
{
return data[index(x, y, z)];
}
}
private int index(int x, int y, int z)
{
return (z * getWidth() * getHeight()) + (y * getWidth()) + x;
}
@Override
public void fill(T t)
{
synchronized(data)
{
Arrays.fill(data, t);
}
}
}