mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-12-19 15:09:18 +00:00
optimize object maps
This commit is contained in:
@@ -38,7 +38,6 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.Direction;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.Queue;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -140,7 +139,7 @@ public class CommandObject implements DecreeExecutor {
|
||||
sender().sendMessage("Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD() + "");
|
||||
sender().sendMessage("Blocks Used: " + NumberFormat.getIntegerInstance().format(o.getBlocks().size()));
|
||||
|
||||
Queue<BlockData> queue = o.getBlocks().enqueueValues();
|
||||
var queue = o.getBlocks().values();
|
||||
Map<Material, Set<BlockData>> unsorted = new HashMap<>();
|
||||
Map<BlockData, Integer> amounts = new HashMap<>();
|
||||
Map<Material, Integer> materials = new HashMap<>();
|
||||
|
||||
@@ -119,7 +119,7 @@ public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
|
||||
if (y > k.getMaxHeight() || y < k.getMinHeight() || y > height - 2)
|
||||
continue;
|
||||
|
||||
for (BlockVector j : clump.getBlocks().keySet()) {
|
||||
for (BlockVector j : clump.getBlocks().keys()) {
|
||||
int nx = j.getBlockX() + x;
|
||||
int ny = j.getBlockY() + y;
|
||||
int nz = j.getBlockZ() + z;
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.context.IrisContext;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.data.IrisCustomData;
|
||||
import com.volmit.iris.util.data.VectorMap;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.interpolation.IrisInterpolation;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
@@ -63,6 +64,7 @@ import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@@ -81,8 +83,8 @@ public class IrisObject extends IrisRegistrant {
|
||||
protected transient IrisLock lock = new IrisLock("Preloadcache");
|
||||
@Setter
|
||||
protected transient AtomicCache<AxisAlignedBB> aabb = new AtomicCache<>();
|
||||
private KMap<Vector3i, BlockData> blocks;
|
||||
private KMap<Vector3i, TileData> states;
|
||||
private VectorMap<BlockData> blocks;
|
||||
private VectorMap<TileData> states;
|
||||
@Getter
|
||||
@Setter
|
||||
private int w;
|
||||
@@ -97,8 +99,8 @@ public class IrisObject extends IrisRegistrant {
|
||||
private transient Vector3i center;
|
||||
|
||||
public IrisObject(int w, int h, int d) {
|
||||
blocks = new KMap<>();
|
||||
states = new KMap<>();
|
||||
blocks = new VectorMap<>();
|
||||
states = new VectorMap<>();
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
this.d = d;
|
||||
@@ -170,7 +172,7 @@ public class IrisObject extends IrisRegistrant {
|
||||
BlockVector max = new BlockVector(Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE);
|
||||
BlockVector min = new BlockVector(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
|
||||
|
||||
for (BlockVector i : getBlocks().keySet()) {
|
||||
for (BlockVector i : getBlocks().keys()) {
|
||||
max.setX(Math.max(i.getX(), max.getX()));
|
||||
min.setX(Math.min(i.getX(), min.getX()));
|
||||
max.setY(Math.max(i.getY(), max.getY()));
|
||||
@@ -281,13 +283,8 @@ public class IrisObject extends IrisRegistrant {
|
||||
o.setLoadFile(getLoadFile());
|
||||
o.setCenter(getCenter().clone());
|
||||
|
||||
for (Vector3i i : getBlocks().keySet()) {
|
||||
o.getBlocks().put(i.clone(), Objects.requireNonNull(getBlocks().get(i)).clone());
|
||||
}
|
||||
|
||||
for (Vector3i i : getStates().keySet()) {
|
||||
o.getStates().put(i.clone(), Objects.requireNonNull(getStates().get(i)).clone());
|
||||
}
|
||||
getBlocks().forEach((i, v) -> o.getBlocks().put(i.clone(), v.clone()));
|
||||
getStates().forEach((i, v) -> o.getStates().put(i.clone(), v.clone()));
|
||||
|
||||
return o;
|
||||
}
|
||||
@@ -366,19 +363,21 @@ public class IrisObject extends IrisRegistrant {
|
||||
|
||||
dos.writeInt(getBlocks().size());
|
||||
|
||||
for (Vector3i i : getBlocks().keySet()) {
|
||||
for (var entry : getBlocks()) {
|
||||
var i = entry.getKey();
|
||||
dos.writeShort(i.getBlockX());
|
||||
dos.writeShort(i.getBlockY());
|
||||
dos.writeShort(i.getBlockZ());
|
||||
dos.writeShort(palette.indexOf(getBlocks().get(i).getAsString()));
|
||||
dos.writeShort(palette.indexOf(entry.getValue().getAsString()));
|
||||
}
|
||||
|
||||
dos.writeInt(getStates().size());
|
||||
for (Vector3i i : getStates().keySet()) {
|
||||
for (var entry : getStates()) {
|
||||
var i = entry.getKey();
|
||||
dos.writeShort(i.getBlockX());
|
||||
dos.writeShort(i.getBlockY());
|
||||
dos.writeShort(i.getBlockZ());
|
||||
getStates().get(i).toBinary(dos);
|
||||
entry.getValue().toBinary(dos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,20 +419,22 @@ public class IrisObject extends IrisRegistrant {
|
||||
|
||||
dos.writeInt(getBlocks().size());
|
||||
|
||||
for (Vector3i i : getBlocks().keySet()) {
|
||||
for (var entry : getBlocks()) {
|
||||
var i = entry.getKey();
|
||||
dos.writeShort(i.getBlockX());
|
||||
dos.writeShort(i.getBlockY());
|
||||
dos.writeShort(i.getBlockZ());
|
||||
dos.writeShort(palette.indexOf(getBlocks().get(i).getAsString()));
|
||||
dos.writeShort(palette.indexOf(entry.getValue().getAsString()));
|
||||
++c;
|
||||
}
|
||||
|
||||
dos.writeInt(getStates().size());
|
||||
for (Vector3i i : getStates().keySet()) {
|
||||
for (var entry : getStates()) {
|
||||
var i = entry.getKey();
|
||||
dos.writeShort(i.getBlockX());
|
||||
dos.writeShort(i.getBlockY());
|
||||
dos.writeShort(i.getBlockZ());
|
||||
getStates().get(i).toBinary(dos);
|
||||
entry.getValue().toBinary(dos);
|
||||
++c;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@@ -502,7 +503,7 @@ public class IrisObject extends IrisRegistrant {
|
||||
BlockVector min = new BlockVector();
|
||||
BlockVector max = new BlockVector();
|
||||
|
||||
for (BlockVector i : getBlocks().keySet()) {
|
||||
for (BlockVector i : getBlocks().keys()) {
|
||||
min.setX(Math.min(min.getX(), i.getX()));
|
||||
min.setY(Math.min(min.getY(), i.getY()));
|
||||
min.setZ(Math.min(min.getZ(), i.getZ()));
|
||||
@@ -518,21 +519,11 @@ public class IrisObject extends IrisRegistrant {
|
||||
}
|
||||
|
||||
public void clean() {
|
||||
KMap<Vector3i, BlockData> d = new KMap<>();
|
||||
VectorMap<BlockData> d = new VectorMap<>();
|
||||
d.putAll(getBlocks());
|
||||
|
||||
for (Vector3i i : getBlocks().keySet()) {
|
||||
d.put(new Vector3i(i.getBlockX(), i.getBlockY(), i.getBlockZ()), Objects.requireNonNull(getBlocks().get(i)));
|
||||
}
|
||||
|
||||
KMap<Vector3i, TileData> dx = new KMap<>();
|
||||
|
||||
for (Vector3i i : getBlocks().keySet()) {
|
||||
d.put(new Vector3i(i.getBlockX(), i.getBlockY(), i.getBlockZ()), Objects.requireNonNull(getBlocks().get(i)));
|
||||
}
|
||||
|
||||
for (Vector3i i : getStates().keySet()) {
|
||||
dx.put(new Vector3i(i.getBlockX(), i.getBlockY(), i.getBlockZ()), Objects.requireNonNull(getStates().get(i)));
|
||||
}
|
||||
VectorMap<TileData> dx = new VectorMap<>();
|
||||
dx.putAll(getStates());
|
||||
|
||||
blocks = d;
|
||||
states = dx;
|
||||
@@ -866,6 +857,9 @@ public class IrisObject extends IrisRegistrant {
|
||||
try {
|
||||
if (config.getMarkers().isNotEmpty() && placer.getEngine() != null) {
|
||||
markers = new KMap<>();
|
||||
var list = StreamSupport.stream(getBlocks().keys().spliterator(), false)
|
||||
.collect(KList.collector());
|
||||
|
||||
for (IrisObjectMarker j : config.getMarkers()) {
|
||||
IrisMarker marker = getLoader().getMarkerLoader().load(j.getMarker());
|
||||
|
||||
@@ -874,8 +868,7 @@ public class IrisObject extends IrisRegistrant {
|
||||
}
|
||||
|
||||
int max = j.getMaximumMarkers();
|
||||
|
||||
for (Vector3i i : getBlocks().k().shuffle()) {
|
||||
for (BlockVector i : list.shuffle()) {
|
||||
if (max <= 0) {
|
||||
break;
|
||||
}
|
||||
@@ -888,8 +881,8 @@ public class IrisObject extends IrisRegistrant {
|
||||
}
|
||||
|
||||
if (j.isExact() ? k.matches(data) : k.getMaterial().equals(data.getMaterial())) {
|
||||
boolean a = !blocks.containsKey((Vector3i) i.clone().add(new BlockVector(0, 1, 0)));
|
||||
boolean fff = !blocks.containsKey((Vector3i) i.clone().add(new BlockVector(0, 2, 0)));
|
||||
boolean a = !blocks.containsKey((BlockVector) i.clone().add(new BlockVector(0, 1, 0)));
|
||||
boolean fff = !blocks.containsKey((BlockVector) i.clone().add(new BlockVector(0, 2, 0)));
|
||||
|
||||
if (!marker.isEmptyAbove() || (a && fff)) {
|
||||
markers.put(i, j.getMarker());
|
||||
@@ -901,7 +894,7 @@ public class IrisObject extends IrisRegistrant {
|
||||
}
|
||||
}
|
||||
|
||||
for (var entry : getBlocks().entrySet()) {
|
||||
for (var entry : getBlocks()) {
|
||||
var g = entry.getKey();
|
||||
BlockData d;
|
||||
TileData tile = null;
|
||||
@@ -1026,7 +1019,7 @@ public class IrisObject extends IrisRegistrant {
|
||||
if (stilting) {
|
||||
readLock.lock();
|
||||
IrisStiltSettings settings = config.getStiltSettings();
|
||||
for (Vector3i g : getBlocks().keySet()) {
|
||||
for (BlockVector g : getBlocks().keys()) {
|
||||
BlockData d;
|
||||
|
||||
if (settings == null || settings.getPalette() == null) {
|
||||
@@ -1138,16 +1131,16 @@ public class IrisObject extends IrisRegistrant {
|
||||
}
|
||||
|
||||
public void rotate(IrisObjectRotation r, int spinx, int spiny, int spinz) {
|
||||
KMap<Vector3i, BlockData> d = new KMap<>();
|
||||
VectorMap<BlockData> d = new VectorMap<>();
|
||||
|
||||
for (Vector3i i : getBlocks().keySet()) {
|
||||
d.put(new Vector3i(r.rotate(i, spinx, spiny, spinz)), r.rotate(getBlocks().get(i).clone(), spinx, spiny, spinz));
|
||||
for (var entry : getBlocks()) {
|
||||
d.put(r.rotate(entry.getKey(), spinx, spiny, spinz), r.rotate(entry.getValue(), spinx, spiny, spinz));
|
||||
}
|
||||
|
||||
KMap<Vector3i, TileData> dx = new KMap<>();
|
||||
VectorMap<TileData> dx = new VectorMap<>();
|
||||
|
||||
for (Vector3i i : getStates().keySet()) {
|
||||
dx.put(new Vector3i(r.rotate(i, spinx, spiny, spinz)), getStates().get(i));
|
||||
for (var entry : getStates()) {
|
||||
dx.put(r.rotate(entry.getKey(), spinx, spiny, spinz), entry.getValue());
|
||||
}
|
||||
|
||||
blocks = d;
|
||||
@@ -1156,9 +1149,10 @@ public class IrisObject extends IrisRegistrant {
|
||||
}
|
||||
|
||||
public void place(Location at) {
|
||||
for (Vector3i i : getBlocks().keySet()) {
|
||||
for (var entry : getBlocks()) {
|
||||
var i = entry.getKey();
|
||||
Block b = at.clone().add(0, getCenter().getY(), 0).add(i).getBlock();
|
||||
b.setBlockData(Objects.requireNonNull(getBlocks().get(i)), false);
|
||||
b.setBlockData(Objects.requireNonNull(entry.getValue()), false);
|
||||
|
||||
if (getStates().containsKey(i)) {
|
||||
Iris.info(Objects.requireNonNull(states.get(i)).toString());
|
||||
@@ -1168,9 +1162,10 @@ public class IrisObject extends IrisRegistrant {
|
||||
}
|
||||
|
||||
public void placeCenterY(Location at) {
|
||||
for (Vector3i i : getBlocks().keySet()) {
|
||||
for (var entry : getBlocks()) {
|
||||
var i = entry.getKey();
|
||||
Block b = at.clone().add(getCenter().getX(), getCenter().getY(), getCenter().getZ()).add(i).getBlock();
|
||||
b.setBlockData(Objects.requireNonNull(getBlocks().get(i)), false);
|
||||
b.setBlockData(Objects.requireNonNull(entry.getValue()), false);
|
||||
|
||||
if (getStates().containsKey(i)) {
|
||||
Objects.requireNonNull(getStates().get(i)).toBukkitTry(b);
|
||||
@@ -1178,16 +1173,16 @@ public class IrisObject extends IrisRegistrant {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized KMap<Vector3i, BlockData> getBlocks() {
|
||||
public synchronized VectorMap<BlockData> getBlocks() {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
public synchronized KMap<Vector3i, TileData> getStates() {
|
||||
public synchronized VectorMap<TileData> getStates() {
|
||||
return states;
|
||||
}
|
||||
|
||||
public void unplaceCenterY(Location at) {
|
||||
for (BlockVector i : getBlocks().keySet()) {
|
||||
for (BlockVector i : getBlocks().keys()) {
|
||||
at.clone().add(getCenter().getX(), getCenter().getY(), getCenter().getZ()).add(i).getBlock().setBlockData(AIR, false);
|
||||
}
|
||||
}
|
||||
@@ -1201,7 +1196,7 @@ public class IrisObject extends IrisRegistrant {
|
||||
|
||||
IrisPosition l1 = getAABB().max();
|
||||
IrisPosition l2 = getAABB().min();
|
||||
@SuppressWarnings({"unchecked", "rawtypes"}) HashMap<BlockVector, BlockData> placeBlock = new HashMap();
|
||||
VectorMap<BlockData> placeBlock = new VectorMap<>();
|
||||
|
||||
Vector center = getCenter();
|
||||
if (getH() == 2) {
|
||||
@@ -1216,17 +1211,17 @@ public class IrisObject extends IrisRegistrant {
|
||||
|
||||
IrisObject oo = new IrisObject((int) Math.ceil((w * scale) + (scale * 2)), (int) Math.ceil((h * scale) + (scale * 2)), (int) Math.ceil((d * scale) + (scale * 2)));
|
||||
|
||||
for (Map.Entry<Vector3i, BlockData> entry : blocks.entrySet()) {
|
||||
for (var entry : blocks) {
|
||||
BlockData bd = entry.getValue();
|
||||
placeBlock.put(entry.getKey().clone().add(HALF).subtract(center)
|
||||
.multiply(scale).add(sm1).toBlockVector(), bd);
|
||||
}
|
||||
|
||||
for (Map.Entry<BlockVector, BlockData> entry : placeBlock.entrySet()) {
|
||||
for (var entry : placeBlock) {
|
||||
BlockVector v = entry.getKey();
|
||||
if (scale > 1) {
|
||||
for (BlockVector vec : blocksBetweenTwoPoints(v.clone().add(center), v.clone().add(center).add(sm1))) {
|
||||
oo.getBlocks().put(new Vector3i(vec), entry.getValue());
|
||||
oo.getBlocks().put(vec, entry.getValue());
|
||||
}
|
||||
} else {
|
||||
oo.setUnsigned(v.getBlockX(), v.getBlockY(), v.getBlockZ(), entry.getValue());
|
||||
@@ -1245,8 +1240,8 @@ public class IrisObject extends IrisRegistrant {
|
||||
}
|
||||
|
||||
public void trilinear(int rad) {
|
||||
KMap<Vector3i, BlockData> v = getBlocks().copy();
|
||||
KMap<Vector3i, BlockData> b = new KMap<>();
|
||||
VectorMap<BlockData> v = getBlocks();
|
||||
VectorMap<BlockData> b = new VectorMap<>();
|
||||
BlockVector min = getAABB().minbv();
|
||||
BlockVector max = getAABB().maxbv();
|
||||
|
||||
@@ -1254,7 +1249,7 @@ public class IrisObject extends IrisRegistrant {
|
||||
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
|
||||
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
|
||||
if (IrisInterpolation.getTrilinear(x, y, z, rad, (xx, yy, zz) -> {
|
||||
BlockData data = v.get(new Vector3i((int) xx, (int) yy, (int) zz));
|
||||
BlockData data = v.get(new BlockVector((int) xx, (int) yy, (int) zz));
|
||||
|
||||
if (data == null || data.getMaterial().isAir()) {
|
||||
return 0;
|
||||
@@ -1262,9 +1257,9 @@ public class IrisObject extends IrisRegistrant {
|
||||
|
||||
return 1;
|
||||
}) >= 0.5) {
|
||||
b.put(new Vector3i(x, y, z), nearestBlockData(x, y, z));
|
||||
b.put(new BlockVector(x, y, z), nearestBlockData(x, y, z));
|
||||
} else {
|
||||
b.put(new Vector3i(x, y, z), AIR);
|
||||
b.put(new BlockVector(x, y, z), AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1274,8 +1269,8 @@ public class IrisObject extends IrisRegistrant {
|
||||
}
|
||||
|
||||
public void tricubic(int rad) {
|
||||
KMap<Vector3i, BlockData> v = getBlocks().copy();
|
||||
KMap<Vector3i, BlockData> b = new KMap<>();
|
||||
VectorMap<BlockData> v = getBlocks();
|
||||
VectorMap<BlockData> b = new VectorMap<>();
|
||||
BlockVector min = getAABB().minbv();
|
||||
BlockVector max = getAABB().maxbv();
|
||||
|
||||
@@ -1283,7 +1278,7 @@ public class IrisObject extends IrisRegistrant {
|
||||
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
|
||||
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
|
||||
if (IrisInterpolation.getTricubic(x, y, z, rad, (xx, yy, zz) -> {
|
||||
BlockData data = v.get(new Vector3i((int) xx, (int) yy, (int) zz));
|
||||
BlockData data = v.get(new BlockVector((int) xx, (int) yy, (int) zz));
|
||||
|
||||
if (data == null || data.getMaterial().isAir()) {
|
||||
return 0;
|
||||
@@ -1291,9 +1286,9 @@ public class IrisObject extends IrisRegistrant {
|
||||
|
||||
return 1;
|
||||
}) >= 0.5) {
|
||||
b.put(new Vector3i(x, y, z), nearestBlockData(x, y, z));
|
||||
b.put(new BlockVector(x, y, z), nearestBlockData(x, y, z));
|
||||
} else {
|
||||
b.put(new Vector3i(x, y, z), AIR);
|
||||
b.put(new BlockVector(x, y, z), AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1307,8 +1302,8 @@ public class IrisObject extends IrisRegistrant {
|
||||
}
|
||||
|
||||
public void trihermite(int rad, double tension, double bias) {
|
||||
KMap<Vector3i, BlockData> v = getBlocks().copy();
|
||||
KMap<Vector3i, BlockData> b = new KMap<>();
|
||||
VectorMap<BlockData> v = getBlocks();
|
||||
VectorMap<BlockData> b = new VectorMap<>();
|
||||
BlockVector min = getAABB().minbv();
|
||||
BlockVector max = getAABB().maxbv();
|
||||
|
||||
@@ -1316,7 +1311,7 @@ public class IrisObject extends IrisRegistrant {
|
||||
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
|
||||
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
|
||||
if (IrisInterpolation.getTrihermite(x, y, z, rad, (xx, yy, zz) -> {
|
||||
BlockData data = v.get(new Vector3i((int) xx, (int) yy, (int) zz));
|
||||
BlockData data = v.get(new BlockVector((int) xx, (int) yy, (int) zz));
|
||||
|
||||
if (data == null || data.getMaterial().isAir()) {
|
||||
return 0;
|
||||
@@ -1324,9 +1319,9 @@ public class IrisObject extends IrisRegistrant {
|
||||
|
||||
return 1;
|
||||
}, tension, bias) >= 0.5) {
|
||||
b.put(new Vector3i(x, y, z), nearestBlockData(x, y, z));
|
||||
b.put(new BlockVector(x, y, z), nearestBlockData(x, y, z));
|
||||
} else {
|
||||
b.put(new Vector3i(x, y, z), AIR);
|
||||
b.put(new BlockVector(x, y, z), AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1345,7 +1340,7 @@ public class IrisObject extends IrisRegistrant {
|
||||
|
||||
double d = Double.MAX_VALUE;
|
||||
|
||||
for (Map.Entry<Vector3i, BlockData> entry : blocks.entrySet()) {
|
||||
for (var entry : blocks) {
|
||||
BlockData dat = entry.getValue();
|
||||
|
||||
if (dat.getMaterial().isAir()) {
|
||||
|
||||
220
core/src/main/java/com/volmit/iris/util/data/VectorMap.java
Normal file
220
core/src/main/java/com/volmit/iris/util/data/VectorMap.java
Normal file
@@ -0,0 +1,220 @@
|
||||
package com.volmit.iris.util.data;
|
||||
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class VectorMap<T> implements Iterable<Map.Entry<BlockVector, T>> {
|
||||
private final Map<Key, Map<Key, T>> map = new KMap<>();
|
||||
|
||||
public int size() {
|
||||
return map.values().stream().mapToInt(Map::size).sum();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return map.values().stream().allMatch(Map::isEmpty);
|
||||
}
|
||||
|
||||
public boolean containsKey(@NonNull BlockVector vector) {
|
||||
var chunk = map.get(chunk(vector));
|
||||
return chunk != null && chunk.containsKey(relative(vector));
|
||||
}
|
||||
|
||||
public boolean containsValue(@NonNull T value) {
|
||||
return map.values().stream().anyMatch(m -> m.containsValue(value));
|
||||
}
|
||||
|
||||
public @Nullable T get(@NonNull BlockVector vector) {
|
||||
var chunk = map.get(chunk(vector));
|
||||
return chunk == null ? null : chunk.get(relative(vector));
|
||||
}
|
||||
|
||||
public @Nullable T put(@NonNull BlockVector vector, @NonNull T value) {
|
||||
return map.computeIfAbsent(chunk(vector), k -> new KMap<>())
|
||||
.put(relative(vector), value);
|
||||
}
|
||||
|
||||
public @Nullable T computeIfAbsent(@NonNull BlockVector vector, @NonNull Function<@NonNull BlockVector, @NonNull T> mappingFunction) {
|
||||
return map.computeIfAbsent(chunk(vector), k -> new KMap<>())
|
||||
.computeIfAbsent(relative(vector), $ -> mappingFunction.apply(vector));
|
||||
}
|
||||
|
||||
public @Nullable T remove(@NonNull BlockVector vector) {
|
||||
var chunk = map.get(chunk(vector));
|
||||
return chunk == null ? null : chunk.remove(relative(vector));
|
||||
}
|
||||
|
||||
public void putAll(@NonNull VectorMap<T> map) {
|
||||
map.forEach(this::put);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public void forEach(@NonNull BiConsumer<@NonNull BlockVector, @NonNull T> consumer) {
|
||||
map.forEach((chunk, values) -> {
|
||||
int rX = chunk.x << 10;
|
||||
int rY = chunk.y << 10;
|
||||
int rZ = chunk.z << 10;
|
||||
|
||||
values.forEach((relative, value) -> consumer.accept(
|
||||
relative.resolve(rX, rY, rZ),
|
||||
value
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
private static Key chunk(BlockVector vector) {
|
||||
return new Key(vector.getBlockX() >> 10, vector.getBlockY() >> 10, vector.getBlockZ() >> 10);
|
||||
}
|
||||
|
||||
private static Key relative(BlockVector vector) {
|
||||
return new Key(vector.getBlockX() & 0x3FF, vector.getBlockY() & 0x3FF, vector.getBlockZ() & 0x3FF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull EntryIterator iterator() {
|
||||
return new EntryIterator();
|
||||
}
|
||||
|
||||
public @NotNull KeyIterator keys() {
|
||||
return new KeyIterator();
|
||||
}
|
||||
|
||||
public @NotNull ValueIterator values() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
public class EntryIterator implements Iterator<Map.Entry<BlockVector, T>> {
|
||||
private final Iterator<Map.Entry<Key, Map<Key, T>>> chunkIterator = map.entrySet().iterator();
|
||||
private Iterator<Map.Entry<Key, T>> relativeIterator;
|
||||
private int rX, rY, rZ;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return relativeIterator != null && relativeIterator.hasNext() || chunkIterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map.Entry<BlockVector, T> next() {
|
||||
if (relativeIterator == null || !relativeIterator.hasNext()) {
|
||||
if (!chunkIterator.hasNext()) throw new IllegalStateException("No more elements");
|
||||
var chunk = chunkIterator.next();
|
||||
rX = chunk.getKey().x << 10;
|
||||
rY = chunk.getKey().y << 10;
|
||||
rZ = chunk.getKey().z << 10;
|
||||
relativeIterator = chunk.getValue().entrySet().iterator();
|
||||
}
|
||||
|
||||
var entry = relativeIterator.next();
|
||||
return Map.entry(entry.getKey().resolve(rX, rY, rZ), entry.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (relativeIterator == null) throw new IllegalStateException("No element to remove");
|
||||
relativeIterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public class KeyIterator implements Iterator<BlockVector>, Iterable<BlockVector> {
|
||||
private final Iterator<Map.Entry<Key, Map<Key, T>>> chunkIterator = map.entrySet().iterator();
|
||||
private Iterator<Key> relativeIterator;
|
||||
private int rX, rY, rZ;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return relativeIterator != null && relativeIterator.hasNext() || chunkIterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector next() {
|
||||
if (relativeIterator == null || !relativeIterator.hasNext()) {
|
||||
var chunk = chunkIterator.next();
|
||||
rX = chunk.getKey().x << 10;
|
||||
rY = chunk.getKey().y << 10;
|
||||
rZ = chunk.getKey().z << 10;
|
||||
relativeIterator = chunk.getValue().keySet().iterator();
|
||||
}
|
||||
|
||||
return relativeIterator.next().resolve(rX, rY, rZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (relativeIterator == null) throw new IllegalStateException("No element to remove");
|
||||
relativeIterator.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterator<BlockVector> iterator() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public class ValueIterator implements Iterator<T>, Iterable<T> {
|
||||
private final Iterator<Map<Key, T>> chunkIterator = map.values().iterator();
|
||||
private Iterator<T> relativeIterator;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return relativeIterator != null && relativeIterator.hasNext() || chunkIterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
if (relativeIterator == null || !relativeIterator.hasNext()) {
|
||||
relativeIterator = chunkIterator.next().values().iterator();
|
||||
}
|
||||
return relativeIterator.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (relativeIterator == null) throw new IllegalStateException("No element to remove");
|
||||
relativeIterator.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterator<T> iterator() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Key {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final int hashCode;
|
||||
|
||||
private Key(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.hashCode = (x << 20) | (y << 10) | z;
|
||||
}
|
||||
|
||||
private BlockVector resolve(int rX, int rY, int rZ) {
|
||||
return new BlockVector(rX + x, rY + y, rZ + z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Key key)) return false;
|
||||
return x == key.x && y == key.y && z == key.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,13 +85,13 @@ public interface Matter {
|
||||
BlockVector min = new BlockVector();
|
||||
Matter m = new IrisMatter(Math.max(object.getW(), 1) + 1, Math.max(object.getH(), 1) + 1, Math.max(object.getD(), 1) + 1);
|
||||
|
||||
for (BlockVector i : object.getBlocks().keySet()) {
|
||||
for (BlockVector i : object.getBlocks().keys()) {
|
||||
min.setX(Math.min(min.getX(), i.getX()));
|
||||
min.setY(Math.min(min.getY(), i.getY()));
|
||||
min.setZ(Math.min(min.getZ(), i.getZ()));
|
||||
}
|
||||
|
||||
for (BlockVector i : object.getBlocks().keySet()) {
|
||||
for (BlockVector i : object.getBlocks().keys()) {
|
||||
m.slice(BlockData.class).set(i.getBlockX() - min.getBlockX(), i.getBlockY() - min.getBlockY(), i.getBlockZ() - min.getBlockZ(), object.getBlocks().get(i));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user