9
0
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:
Julian Krings
2025-10-26 13:48:11 +01:00
parent 317848692e
commit 0bf5da2ca1
5 changed files with 293 additions and 79 deletions

View File

@@ -38,7 +38,6 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.Direction; import com.volmit.iris.util.math.Direction;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.scheduling.Queue;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData; 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("Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD() + "");
sender().sendMessage("Blocks Used: " + NumberFormat.getIntegerInstance().format(o.getBlocks().size())); 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<Material, Set<BlockData>> unsorted = new HashMap<>();
Map<BlockData, Integer> amounts = new HashMap<>(); Map<BlockData, Integer> amounts = new HashMap<>();
Map<Material, Integer> materials = new HashMap<>(); Map<Material, Integer> materials = new HashMap<>();

View File

@@ -119,7 +119,7 @@ public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
if (y > k.getMaxHeight() || y < k.getMinHeight() || y > height - 2) if (y > k.getMaxHeight() || y < k.getMinHeight() || y > height - 2)
continue; continue;
for (BlockVector j : clump.getBlocks().keySet()) { for (BlockVector j : clump.getBlocks().keys()) {
int nx = j.getBlockX() + x; int nx = j.getBlockX() + x;
int ny = j.getBlockY() + y; int ny = j.getBlockY() + y;
int nz = j.getBlockZ() + z; int nz = j.getBlockZ() + z;

View File

@@ -30,6 +30,7 @@ import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.context.IrisContext; import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.data.B; import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.IrisCustomData; 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.format.Form;
import com.volmit.iris.util.interpolation.IrisInterpolation; import com.volmit.iris.util.interpolation.IrisInterpolation;
import com.volmit.iris.util.json.JSONObject; 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.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.stream.StreamSupport;
@Accessors(chain = true) @Accessors(chain = true)
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@@ -81,8 +83,8 @@ public class IrisObject extends IrisRegistrant {
protected transient IrisLock lock = new IrisLock("Preloadcache"); protected transient IrisLock lock = new IrisLock("Preloadcache");
@Setter @Setter
protected transient AtomicCache<AxisAlignedBB> aabb = new AtomicCache<>(); protected transient AtomicCache<AxisAlignedBB> aabb = new AtomicCache<>();
private KMap<Vector3i, BlockData> blocks; private VectorMap<BlockData> blocks;
private KMap<Vector3i, TileData> states; private VectorMap<TileData> states;
@Getter @Getter
@Setter @Setter
private int w; private int w;
@@ -97,8 +99,8 @@ public class IrisObject extends IrisRegistrant {
private transient Vector3i center; private transient Vector3i center;
public IrisObject(int w, int h, int d) { public IrisObject(int w, int h, int d) {
blocks = new KMap<>(); blocks = new VectorMap<>();
states = new KMap<>(); states = new VectorMap<>();
this.w = w; this.w = w;
this.h = h; this.h = h;
this.d = d; 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 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); 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())); max.setX(Math.max(i.getX(), max.getX()));
min.setX(Math.min(i.getX(), min.getX())); min.setX(Math.min(i.getX(), min.getX()));
max.setY(Math.max(i.getY(), max.getY())); max.setY(Math.max(i.getY(), max.getY()));
@@ -281,13 +283,8 @@ public class IrisObject extends IrisRegistrant {
o.setLoadFile(getLoadFile()); o.setLoadFile(getLoadFile());
o.setCenter(getCenter().clone()); o.setCenter(getCenter().clone());
for (Vector3i i : getBlocks().keySet()) { getBlocks().forEach((i, v) -> o.getBlocks().put(i.clone(), v.clone()));
o.getBlocks().put(i.clone(), Objects.requireNonNull(getBlocks().get(i)).clone()); getStates().forEach((i, v) -> o.getStates().put(i.clone(), v.clone()));
}
for (Vector3i i : getStates().keySet()) {
o.getStates().put(i.clone(), Objects.requireNonNull(getStates().get(i)).clone());
}
return o; return o;
} }
@@ -366,19 +363,21 @@ public class IrisObject extends IrisRegistrant {
dos.writeInt(getBlocks().size()); dos.writeInt(getBlocks().size());
for (Vector3i i : getBlocks().keySet()) { for (var entry : getBlocks()) {
var i = entry.getKey();
dos.writeShort(i.getBlockX()); dos.writeShort(i.getBlockX());
dos.writeShort(i.getBlockY()); dos.writeShort(i.getBlockY());
dos.writeShort(i.getBlockZ()); dos.writeShort(i.getBlockZ());
dos.writeShort(palette.indexOf(getBlocks().get(i).getAsString())); dos.writeShort(palette.indexOf(entry.getValue().getAsString()));
} }
dos.writeInt(getStates().size()); dos.writeInt(getStates().size());
for (Vector3i i : getStates().keySet()) { for (var entry : getStates()) {
var i = entry.getKey();
dos.writeShort(i.getBlockX()); dos.writeShort(i.getBlockX());
dos.writeShort(i.getBlockY()); dos.writeShort(i.getBlockY());
dos.writeShort(i.getBlockZ()); 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()); dos.writeInt(getBlocks().size());
for (Vector3i i : getBlocks().keySet()) { for (var entry : getBlocks()) {
var i = entry.getKey();
dos.writeShort(i.getBlockX()); dos.writeShort(i.getBlockX());
dos.writeShort(i.getBlockY()); dos.writeShort(i.getBlockY());
dos.writeShort(i.getBlockZ()); dos.writeShort(i.getBlockZ());
dos.writeShort(palette.indexOf(getBlocks().get(i).getAsString())); dos.writeShort(palette.indexOf(entry.getValue().getAsString()));
++c; ++c;
} }
dos.writeInt(getStates().size()); dos.writeInt(getStates().size());
for (Vector3i i : getStates().keySet()) { for (var entry : getStates()) {
var i = entry.getKey();
dos.writeShort(i.getBlockX()); dos.writeShort(i.getBlockX());
dos.writeShort(i.getBlockY()); dos.writeShort(i.getBlockY());
dos.writeShort(i.getBlockZ()); dos.writeShort(i.getBlockZ());
getStates().get(i).toBinary(dos); entry.getValue().toBinary(dos);
++c; ++c;
} }
} catch (IOException e) { } catch (IOException e) {
@@ -502,7 +503,7 @@ public class IrisObject extends IrisRegistrant {
BlockVector min = new BlockVector(); BlockVector min = new BlockVector();
BlockVector max = 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.setX(Math.min(min.getX(), i.getX()));
min.setY(Math.min(min.getY(), i.getY())); min.setY(Math.min(min.getY(), i.getY()));
min.setZ(Math.min(min.getZ(), i.getZ())); min.setZ(Math.min(min.getZ(), i.getZ()));
@@ -518,21 +519,11 @@ public class IrisObject extends IrisRegistrant {
} }
public void clean() { public void clean() {
KMap<Vector3i, BlockData> d = new KMap<>(); VectorMap<BlockData> d = new VectorMap<>();
d.putAll(getBlocks());
for (Vector3i i : getBlocks().keySet()) { VectorMap<TileData> dx = new VectorMap<>();
d.put(new Vector3i(i.getBlockX(), i.getBlockY(), i.getBlockZ()), Objects.requireNonNull(getBlocks().get(i))); dx.putAll(getStates());
}
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)));
}
blocks = d; blocks = d;
states = dx; states = dx;
@@ -866,6 +857,9 @@ public class IrisObject extends IrisRegistrant {
try { try {
if (config.getMarkers().isNotEmpty() && placer.getEngine() != null) { if (config.getMarkers().isNotEmpty() && placer.getEngine() != null) {
markers = new KMap<>(); markers = new KMap<>();
var list = StreamSupport.stream(getBlocks().keys().spliterator(), false)
.collect(KList.collector());
for (IrisObjectMarker j : config.getMarkers()) { for (IrisObjectMarker j : config.getMarkers()) {
IrisMarker marker = getLoader().getMarkerLoader().load(j.getMarker()); IrisMarker marker = getLoader().getMarkerLoader().load(j.getMarker());
@@ -874,8 +868,7 @@ public class IrisObject extends IrisRegistrant {
} }
int max = j.getMaximumMarkers(); int max = j.getMaximumMarkers();
for (BlockVector i : list.shuffle()) {
for (Vector3i i : getBlocks().k().shuffle()) {
if (max <= 0) { if (max <= 0) {
break; break;
} }
@@ -888,8 +881,8 @@ public class IrisObject extends IrisRegistrant {
} }
if (j.isExact() ? k.matches(data) : k.getMaterial().equals(data.getMaterial())) { 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 a = !blocks.containsKey((BlockVector) i.clone().add(new BlockVector(0, 1, 0)));
boolean fff = !blocks.containsKey((Vector3i) i.clone().add(new BlockVector(0, 2, 0))); boolean fff = !blocks.containsKey((BlockVector) i.clone().add(new BlockVector(0, 2, 0)));
if (!marker.isEmptyAbove() || (a && fff)) { if (!marker.isEmptyAbove() || (a && fff)) {
markers.put(i, j.getMarker()); 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(); var g = entry.getKey();
BlockData d; BlockData d;
TileData tile = null; TileData tile = null;
@@ -1026,7 +1019,7 @@ public class IrisObject extends IrisRegistrant {
if (stilting) { if (stilting) {
readLock.lock(); readLock.lock();
IrisStiltSettings settings = config.getStiltSettings(); IrisStiltSettings settings = config.getStiltSettings();
for (Vector3i g : getBlocks().keySet()) { for (BlockVector g : getBlocks().keys()) {
BlockData d; BlockData d;
if (settings == null || settings.getPalette() == null) { 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) { 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()) { for (var entry : getBlocks()) {
d.put(new Vector3i(r.rotate(i, spinx, spiny, spinz)), r.rotate(getBlocks().get(i).clone(), spinx, spiny, spinz)); 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()) { for (var entry : getStates()) {
dx.put(new Vector3i(r.rotate(i, spinx, spiny, spinz)), getStates().get(i)); dx.put(r.rotate(entry.getKey(), spinx, spiny, spinz), entry.getValue());
} }
blocks = d; blocks = d;
@@ -1156,9 +1149,10 @@ public class IrisObject extends IrisRegistrant {
} }
public void place(Location at) { 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(); 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)) { if (getStates().containsKey(i)) {
Iris.info(Objects.requireNonNull(states.get(i)).toString()); Iris.info(Objects.requireNonNull(states.get(i)).toString());
@@ -1168,9 +1162,10 @@ public class IrisObject extends IrisRegistrant {
} }
public void placeCenterY(Location at) { 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(); 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)) { if (getStates().containsKey(i)) {
Objects.requireNonNull(getStates().get(i)).toBukkitTry(b); 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; return blocks;
} }
public synchronized KMap<Vector3i, TileData> getStates() { public synchronized VectorMap<TileData> getStates() {
return states; return states;
} }
public void unplaceCenterY(Location at) { 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); 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 l1 = getAABB().max();
IrisPosition l2 = getAABB().min(); IrisPosition l2 = getAABB().min();
@SuppressWarnings({"unchecked", "rawtypes"}) HashMap<BlockVector, BlockData> placeBlock = new HashMap(); VectorMap<BlockData> placeBlock = new VectorMap<>();
Vector center = getCenter(); Vector center = getCenter();
if (getH() == 2) { 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))); 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(); BlockData bd = entry.getValue();
placeBlock.put(entry.getKey().clone().add(HALF).subtract(center) placeBlock.put(entry.getKey().clone().add(HALF).subtract(center)
.multiply(scale).add(sm1).toBlockVector(), bd); .multiply(scale).add(sm1).toBlockVector(), bd);
} }
for (Map.Entry<BlockVector, BlockData> entry : placeBlock.entrySet()) { for (var entry : placeBlock) {
BlockVector v = entry.getKey(); BlockVector v = entry.getKey();
if (scale > 1) { if (scale > 1) {
for (BlockVector vec : blocksBetweenTwoPoints(v.clone().add(center), v.clone().add(center).add(sm1))) { 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 { } else {
oo.setUnsigned(v.getBlockX(), v.getBlockY(), v.getBlockZ(), entry.getValue()); oo.setUnsigned(v.getBlockX(), v.getBlockY(), v.getBlockZ(), entry.getValue());
@@ -1245,8 +1240,8 @@ public class IrisObject extends IrisRegistrant {
} }
public void trilinear(int rad) { public void trilinear(int rad) {
KMap<Vector3i, BlockData> v = getBlocks().copy(); VectorMap<BlockData> v = getBlocks();
KMap<Vector3i, BlockData> b = new KMap<>(); VectorMap<BlockData> b = new VectorMap<>();
BlockVector min = getAABB().minbv(); BlockVector min = getAABB().minbv();
BlockVector max = getAABB().maxbv(); BlockVector max = getAABB().maxbv();
@@ -1254,7 +1249,7 @@ public class IrisObject extends IrisRegistrant {
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
if (IrisInterpolation.getTrilinear(x, y, z, rad, (xx, yy, zz) -> { 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()) { if (data == null || data.getMaterial().isAir()) {
return 0; return 0;
@@ -1262,9 +1257,9 @@ public class IrisObject extends IrisRegistrant {
return 1; return 1;
}) >= 0.5) { }) >= 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 { } 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) { public void tricubic(int rad) {
KMap<Vector3i, BlockData> v = getBlocks().copy(); VectorMap<BlockData> v = getBlocks();
KMap<Vector3i, BlockData> b = new KMap<>(); VectorMap<BlockData> b = new VectorMap<>();
BlockVector min = getAABB().minbv(); BlockVector min = getAABB().minbv();
BlockVector max = getAABB().maxbv(); BlockVector max = getAABB().maxbv();
@@ -1283,7 +1278,7 @@ public class IrisObject extends IrisRegistrant {
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
if (IrisInterpolation.getTricubic(x, y, z, rad, (xx, yy, zz) -> { 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()) { if (data == null || data.getMaterial().isAir()) {
return 0; return 0;
@@ -1291,9 +1286,9 @@ public class IrisObject extends IrisRegistrant {
return 1; return 1;
}) >= 0.5) { }) >= 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 { } 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) { public void trihermite(int rad, double tension, double bias) {
KMap<Vector3i, BlockData> v = getBlocks().copy(); VectorMap<BlockData> v = getBlocks();
KMap<Vector3i, BlockData> b = new KMap<>(); VectorMap<BlockData> b = new VectorMap<>();
BlockVector min = getAABB().minbv(); BlockVector min = getAABB().minbv();
BlockVector max = getAABB().maxbv(); BlockVector max = getAABB().maxbv();
@@ -1316,7 +1311,7 @@ public class IrisObject extends IrisRegistrant {
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
if (IrisInterpolation.getTrihermite(x, y, z, rad, (xx, yy, zz) -> { 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()) { if (data == null || data.getMaterial().isAir()) {
return 0; return 0;
@@ -1324,9 +1319,9 @@ public class IrisObject extends IrisRegistrant {
return 1; return 1;
}, tension, bias) >= 0.5) { }, 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 { } 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; double d = Double.MAX_VALUE;
for (Map.Entry<Vector3i, BlockData> entry : blocks.entrySet()) { for (var entry : blocks) {
BlockData dat = entry.getValue(); BlockData dat = entry.getValue();
if (dat.getMaterial().isAir()) { if (dat.getMaterial().isAir()) {

View 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;
}
}
}

View File

@@ -85,13 +85,13 @@ public interface Matter {
BlockVector min = new BlockVector(); 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); 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.setX(Math.min(min.getX(), i.getX()));
min.setY(Math.min(min.getY(), i.getY())); min.setY(Math.min(min.getY(), i.getY()));
min.setZ(Math.min(min.getZ(), i.getZ())); 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)); m.slice(BlockData.class).set(i.getBlockX() - min.getBlockX(), i.getBlockY() - min.getBlockY(), i.getBlockZ() - min.getBlockZ(), object.getBlocks().get(i));
} }