mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-06-18 06:41:08 +00:00
+1
-1
@@ -273,7 +273,7 @@ allprojects {
|
|||||||
compileOnly 'it.unimi.dsi:fastutil:8.5.8'
|
compileOnly 'it.unimi.dsi:fastutil:8.5.8'
|
||||||
compileOnly 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
compileOnly 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
|
||||||
compileOnly 'org.zeroturnaround:zt-zip:1.14'
|
compileOnly 'org.zeroturnaround:zt-zip:1.14'
|
||||||
compileOnly 'com.google.code.gson:gson:2.9.0'
|
compileOnly 'com.google.code.gson:gson:2.10.1'
|
||||||
compileOnly 'org.ow2.asm:asm:9.2'
|
compileOnly 'org.ow2.asm:asm:9.2'
|
||||||
compileOnly 'com.google.guava:guava:33.0.0-jre'
|
compileOnly 'com.google.guava:guava:33.0.0-jre'
|
||||||
compileOnly 'bsf:bsf:2.4.0'
|
compileOnly 'bsf:bsf:2.4.0'
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package com.volmit.iris.core.commands;
|
|||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.edit.JigsawEditor;
|
import com.volmit.iris.core.edit.JigsawEditor;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.engine.framework.placer.WorldObjectPlacer;
|
||||||
import com.volmit.iris.engine.jigsaw.PlannedStructure;
|
import com.volmit.iris.engine.jigsaw.PlannedStructure;
|
||||||
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
import com.volmit.iris.engine.object.IrisJigsawPiece;
|
||||||
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||||
@@ -34,6 +35,7 @@ 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.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -55,9 +57,16 @@ public class CommandJigsaw implements DecreeExecutor {
|
|||||||
IrisJigsawStructure structure
|
IrisJigsawStructure structure
|
||||||
) {
|
) {
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation()), new RNG());
|
try {
|
||||||
sender().sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
|
var world = world();
|
||||||
ps.place(world());
|
WorldObjectPlacer placer = new WorldObjectPlacer(world);
|
||||||
|
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation().add(0, world.getMinHeight(), 0)), new RNG());
|
||||||
|
VolmitSender sender = sender();
|
||||||
|
sender.sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
|
||||||
|
ps.place(placer, failed -> sender.sendMessage(failed ? C.GREEN + "Placed the structure!" : C.RED + "Failed to place the structure!"));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
sender().sendMessage(C.RED + "Failed to place the structure: " + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Decree(description = "Create a jigsaw piece")
|
@Decree(description = "Create a jigsaw piece")
|
||||||
|
|||||||
@@ -198,6 +198,20 @@ public class CommandObject implements DecreeExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Shrink an object to its minimum size")
|
||||||
|
public void shrink(@Param(description = "The object to shrink", customHandler = ObjectHandler.class) String object) {
|
||||||
|
IrisObject o = IrisData.loadAnyObject(object);
|
||||||
|
sender().sendMessage("Current Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
|
||||||
|
o.shrinkwrap();
|
||||||
|
sender().sendMessage("New Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
|
||||||
|
try {
|
||||||
|
o.write(o.getLoadFile());
|
||||||
|
} catch (IOException e) {
|
||||||
|
sender().sendMessage("Failed to save object " + o.getLoadFile() + ": " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Decree(description = "Get a powder that reveals objects", studio = true, aliases = "d")
|
@Decree(description = "Get a powder that reveals objects", studio = true, aliases = "d")
|
||||||
public void dust() {
|
public void dust() {
|
||||||
player().getInventory().addItem(WandSVC.createDust());
|
player().getInventory().addItem(WandSVC.createDust());
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.attribute.FileTime;
|
import java.nio.file.attribute.FileTime;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
@@ -332,6 +333,63 @@ public class CommandStudio implements DecreeExecutor {
|
|||||||
player().openInventory(inv);
|
player().openInventory(inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Decree(description = "Get all structures in a radius of chunks", aliases = "dist", origin = DecreeOrigin.PLAYER)
|
||||||
|
public void distances(@Param(description = "The radius") int radius) {
|
||||||
|
var engine = engine();
|
||||||
|
if (engine == null) {
|
||||||
|
sender().sendMessage(C.RED + "Only works in an Iris world!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var sender = sender();
|
||||||
|
int d = radius*2;
|
||||||
|
KMap<String, KList<Position2>> data = new KMap<>();
|
||||||
|
var multiBurst = new MultiBurst("Distance Sampler", Thread.MIN_PRIORITY);
|
||||||
|
var executor = multiBurst.burst(radius * radius);
|
||||||
|
|
||||||
|
sender.sendMessage(C.GRAY + "Generating data...");
|
||||||
|
var loc = player().getLocation();
|
||||||
|
new Spiraler(d, d, (x, z) -> executor.queue(() -> {
|
||||||
|
var struct = engine.getStructureAt(x, z);
|
||||||
|
if (struct != null) {
|
||||||
|
data.computeIfAbsent(struct.getLoadKey(), (k) -> new KList<>()).add(new Position2(x, z));
|
||||||
|
}
|
||||||
|
})).setOffset(loc.getBlockX(), loc.getBlockZ()).drain();
|
||||||
|
|
||||||
|
executor.complete();
|
||||||
|
multiBurst.close();
|
||||||
|
for (var key : data.keySet()) {
|
||||||
|
var list = data.get(key);
|
||||||
|
KList<Long> distances = new KList<>(list.size() - 1);
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
var pos = list.get(i);
|
||||||
|
double dist = Integer.MAX_VALUE;
|
||||||
|
for (var p : list) {
|
||||||
|
if (p.equals(pos)) continue;
|
||||||
|
dist = Math.min(dist, Math.sqrt(Math.pow(pos.getX() - p.getX(), 2) + Math.pow(pos.getZ() - p.getZ(), 2)));
|
||||||
|
}
|
||||||
|
if (dist == Integer.MAX_VALUE) continue;
|
||||||
|
distances.add(Math.round(dist * 16));
|
||||||
|
}
|
||||||
|
long[] array = new long[distances.size()];
|
||||||
|
for (int i = 0; i < distances.size(); i++) {
|
||||||
|
array[i] = distances.get(i);
|
||||||
|
}
|
||||||
|
Arrays.sort(array);
|
||||||
|
long min = array.length > 0 ? array[0] : 0;
|
||||||
|
long max = array.length > 0 ? array[array.length - 1] : 0;
|
||||||
|
long sum = Arrays.stream(array).sum();
|
||||||
|
long avg = array.length > 0 ? Math.round(sum / (double) array.length) : 0;
|
||||||
|
String msg = "%s: %s => min: %s/max: %s -> avg: %s".formatted(key, list.size(), min, max, avg);
|
||||||
|
sender.sendMessage(msg);
|
||||||
|
}
|
||||||
|
if (data.isEmpty()) {
|
||||||
|
sender.sendMessage(C.RED + "No data found!");
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(C.GREEN + "Done!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Decree(description = "Render a world map (External GUI)", aliases = "render")
|
@Decree(description = "Render a world map (External GUI)", aliases = "render")
|
||||||
public void map(
|
public void map(
|
||||||
@Param(name = "world", description = "The world to open the generator for", contextual = true)
|
@Param(name = "world", description = "The world to open the generator for", contextual = true)
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
package com.volmit.iris.engine.framework.placer;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.engine.framework.IrisLootEvent;
|
||||||
|
import com.volmit.iris.engine.mantle.EngineMantle;
|
||||||
|
import com.volmit.iris.engine.object.IObjectPlacer;
|
||||||
|
import com.volmit.iris.engine.object.InventorySlotType;
|
||||||
|
import com.volmit.iris.engine.object.IrisLootTable;
|
||||||
|
import com.volmit.iris.engine.object.TileData;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.data.B;
|
||||||
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.block.TileState;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@EqualsAndHashCode(exclude = {"engine", "mantle"})
|
||||||
|
public class WorldObjectPlacer implements IObjectPlacer {
|
||||||
|
private final World world;
|
||||||
|
private final Engine engine;
|
||||||
|
private final EngineMantle mantle;
|
||||||
|
|
||||||
|
public WorldObjectPlacer(World world) {
|
||||||
|
var a = IrisToolbelt.access(world);
|
||||||
|
if (a == null || a.getEngine() == null) throw new IllegalStateException(world.getName() + " is not an Iris World!");
|
||||||
|
this.world = world;
|
||||||
|
this.engine = a.getEngine();
|
||||||
|
this.mantle = engine.getMantle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHighest(int x, int z, IrisData data) {
|
||||||
|
return mantle.getHighest(x, z, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
|
||||||
|
return mantle.getHighest(x, z, data, ignoreFluid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(int x, int y, int z, BlockData d) {
|
||||||
|
Block block = world.getBlockAt(x, y + world.getMinHeight(), z);
|
||||||
|
|
||||||
|
if (y <= world.getMinHeight() || block.getType() == Material.BEDROCK) return;
|
||||||
|
InventorySlotType slot = null;
|
||||||
|
if (B.isStorageChest(d)) {
|
||||||
|
slot = InventorySlotType.STORAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot != null) {
|
||||||
|
RNG rx = new RNG(Cache.key(x, z));
|
||||||
|
KList<IrisLootTable> tables = engine.getLootTables(rx, block);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Bukkit.getPluginManager().callEvent(new IrisLootEvent(engine, block, slot, tables));
|
||||||
|
|
||||||
|
if (!tables.isEmpty()){
|
||||||
|
Iris.debug("IrisLootEvent has been accessed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tables.isEmpty())
|
||||||
|
return;
|
||||||
|
InventoryHolder m = (InventoryHolder) block.getState();
|
||||||
|
engine.addItems(false, m.getInventory(), rx, tables, slot, x, y, z, 15);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
block.setBlockData(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData get(int x, int y, int z) {
|
||||||
|
return world.getBlockAt(x, y + world.getMinHeight(), z).getBlockData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPreventingDecay() {
|
||||||
|
return mantle.isPreventingDecay();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCarved(int x, int y, int z) {
|
||||||
|
return mantle.isCarved(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSolid(int x, int y, int z) {
|
||||||
|
return world.getBlockAt(x, y + world.getMinHeight(), z).getType().isSolid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUnderwater(int x, int z) {
|
||||||
|
return mantle.isUnderwater(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFluidHeight() {
|
||||||
|
return mantle.getFluidHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDebugSmartBore() {
|
||||||
|
return mantle.isDebugSmartBore();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
|
||||||
|
BlockState state = world.getBlockAt(xx, yy + world.getMinHeight(), zz).getState();
|
||||||
|
tile.toBukkitTry(state);
|
||||||
|
state.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,29 +20,19 @@ package com.volmit.iris.engine.jigsaw;
|
|||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
|
||||||
import com.volmit.iris.engine.object.*;
|
import com.volmit.iris.engine.object.*;
|
||||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.context.IrisContext;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.math.AxisAlignedBB;
|
import com.volmit.iris.util.math.AxisAlignedBB;
|
||||||
import com.volmit.iris.util.math.BlockPosition;
|
import lombok.AccessLevel;
|
||||||
import com.volmit.iris.util.math.RNG;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.bukkit.Material;
|
import lombok.EqualsAndHashCode;
|
||||||
import org.bukkit.World;
|
import lombok.Setter;
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.block.BlockState;
|
|
||||||
import org.bukkit.block.TileState;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
import org.bukkit.inventory.InventoryHolder;
|
|
||||||
import org.bukkit.util.BlockVector;
|
import org.bukkit.util.BlockVector;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@SuppressWarnings("ALL")
|
|
||||||
@Data
|
@Data
|
||||||
public class PlannedPiece {
|
public class PlannedPiece {
|
||||||
private IrisPosition position;
|
private IrisPosition position;
|
||||||
@@ -50,11 +40,19 @@ public class PlannedPiece {
|
|||||||
private IrisObject ogObject;
|
private IrisObject ogObject;
|
||||||
private IrisJigsawPiece piece;
|
private IrisJigsawPiece piece;
|
||||||
private IrisObjectRotation rotation;
|
private IrisObjectRotation rotation;
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
private IrisData data;
|
private IrisData data;
|
||||||
private KList<IrisJigsawPieceConnector> connected;
|
private KList<IrisJigsawPieceConnector> connected;
|
||||||
private boolean dead = false;
|
private boolean dead = false;
|
||||||
private AxisAlignedBB box;
|
private AxisAlignedBB box;
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
private PlannedStructure structure;
|
private PlannedStructure structure;
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
|
@Setter(AccessLevel.NONE)
|
||||||
|
private ParentConnection parent = null;
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
|
@Setter(AccessLevel.NONE)
|
||||||
|
private KMap<IrisJigsawPieceConnector, IrisPosition> realPositions;
|
||||||
|
|
||||||
public PlannedPiece(PlannedStructure structure, IrisPosition position, IrisJigsawPiece piece) {
|
public PlannedPiece(PlannedStructure structure, IrisPosition position, IrisJigsawPiece piece) {
|
||||||
this(structure, position, piece, 0, 0, 0);
|
this(structure, position, piece, 0, 0, 0);
|
||||||
@@ -76,6 +74,7 @@ public class PlannedPiece {
|
|||||||
this.object.setLoadKey(piece.getObject());
|
this.object.setLoadKey(piece.getObject());
|
||||||
this.ogObject.setLoadKey(piece.getObject());
|
this.ogObject.setLoadKey(piece.getObject());
|
||||||
this.connected = new KList<>();
|
this.connected = new KList<>();
|
||||||
|
this.realPositions = new KMap<>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +93,15 @@ public class PlannedPiece {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BlockVector v = getObject().getCenter();
|
BlockVector v = getObject().getCenter();
|
||||||
box = object.getAABB().shifted(position.add(new IrisPosition(object.getCenter())));
|
IrisPosition pos = new IrisPosition();
|
||||||
|
IrisObjectPlacement options = piece.getPlacementOptions();
|
||||||
|
if (options != null && options.getTranslate() != null) {
|
||||||
|
IrisObjectTranslate translate = options.getTranslate();
|
||||||
|
pos.setX(translate.getX());
|
||||||
|
pos.setY(translate.getY());
|
||||||
|
pos.setZ(translate.getZ());
|
||||||
|
}
|
||||||
|
box = object.getAABB().shifted(position.add(new IrisPosition(object.getCenter())).add(pos));
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,11 +133,21 @@ public class PlannedPiece {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean connect(IrisJigsawPieceConnector c) {
|
public KList<IrisJigsawPieceConnector> getChildConnectors() {
|
||||||
if (piece.getConnectors().contains(c)) {
|
ParentConnection pc = getParent();
|
||||||
return connected.addIfMissing(c);
|
KList<IrisJigsawPieceConnector> c = getConnected().copy();
|
||||||
|
if (pc != null) c.removeIf(i -> i.equals(pc.connector));
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean connect(IrisJigsawPieceConnector c, PlannedPiece p, IrisJigsawPieceConnector pc) {
|
||||||
|
if (piece.getConnectors().contains(c) && p.getPiece().getConnectors().contains(pc)) {
|
||||||
|
if (connected.contains(c) || p.connected.contains(pc)) return false;
|
||||||
|
connected.add(c);
|
||||||
|
p.connected.add(pc);
|
||||||
|
p.parent = new ParentConnection(this, c, p, pc);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,108 +179,29 @@ public class PlannedPiece {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFull() {
|
public boolean isFull() {
|
||||||
return connected.size() >= piece.getConnectors().size() || isDead();
|
return connected.size() >= piece.getConnectors().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void place(World world) {
|
public void setRealPositions(int x, int y, int z, IObjectPlacer placer) {
|
||||||
PlatformChunkGenerator a = IrisToolbelt.access(world);
|
boolean isUnderwater = piece.getPlacementOptions().isUnderwater();
|
||||||
|
for (IrisJigsawPieceConnector c : piece.getConnectors()) {
|
||||||
int minY = 0;
|
var pos = c.getPosition().add(new IrisPosition(x, 0, z));
|
||||||
if (a != null) {
|
if (y < 0) {
|
||||||
minY = a.getEngine().getMinHeight();
|
pos.setY(pos.getY() + placer.getHighest(pos.getX(), pos.getZ(), getData(), isUnderwater) + (object.getH() / 2));
|
||||||
|
} else {
|
||||||
if (!a.getEngine().getDimension().isBedrock())
|
pos.setY(pos.getY() + y);
|
||||||
minY--; //If the dimension has no bedrock, allow it to go a block lower
|
|
||||||
}
|
}
|
||||||
|
realPositions.put(c, pos);
|
||||||
getPiece().getPlacementOptions().setTranslate(new IrisObjectTranslate());
|
|
||||||
getPiece().getPlacementOptions().setRotation(rotation);
|
|
||||||
int finalMinY = minY;
|
|
||||||
RNG rng = getStructure().getRng().nextParallelRNG(37555);
|
|
||||||
|
|
||||||
// TODO: REAL CLASSES!!!!!!!
|
|
||||||
getOgObject().place(position.getX() + getObject().getCenter().getBlockX(), position.getY() + getObject().getCenter().getBlockY(), position.getZ() + getObject().getCenter().getBlockZ(), new IObjectPlacer() {
|
|
||||||
@Override
|
|
||||||
public int getHighest(int x, int z, IrisData data) {
|
|
||||||
return position.getY();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
|
|
||||||
return position.getY();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void set(int x, int y, int z, BlockData d) {
|
|
||||||
Block block = world.getBlockAt(x, y, z);
|
|
||||||
|
|
||||||
//Prevent blocks being set in or bellow bedrock
|
|
||||||
if (y <= finalMinY || block.getType() == Material.BEDROCK) return;
|
|
||||||
|
|
||||||
block.setBlockData(d);
|
|
||||||
|
|
||||||
if (a != null && getPiece().getPlacementOptions().getLoot().isNotEmpty() &&
|
|
||||||
block.getState() instanceof InventoryHolder) {
|
|
||||||
|
|
||||||
IrisLootTable table = getPiece().getPlacementOptions().getTable(block.getBlockData(), getData());
|
|
||||||
if (table == null) return;
|
|
||||||
Engine engine = a.getEngine();
|
|
||||||
engine.addItems(false, ((InventoryHolder) block.getState()).getInventory(),
|
|
||||||
rng.nextParallelRNG(BlockPosition.toLong(x, y, z)),
|
|
||||||
new KList<>(table), InventorySlotType.STORAGE, x, y, z, 15);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public record ParentConnection(PlannedPiece parent, IrisJigsawPieceConnector parentConnector, PlannedPiece self, IrisJigsawPieceConnector connector) {
|
||||||
public BlockData get(int x, int y, int z) {
|
public IrisPosition getTargetPosition() {
|
||||||
return world.getBlockAt(x, y, z).getBlockData();
|
var pos = parent.realPositions.get(parentConnector);
|
||||||
}
|
if (pos == null) return null;
|
||||||
|
return pos.add(new IrisPosition(parentConnector.getDirection().toVector()))
|
||||||
@Override
|
.sub(connector.getPosition())
|
||||||
public boolean isPreventingDecay() {
|
.sub(new IrisPosition(self.object.getCenter()));
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCarved(int x, int y, int z) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSolid(int x, int y, int z) {
|
|
||||||
return world.getBlockAt(x, y, z).getType().isSolid();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isUnderwater(int x, int z) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getFluidHeight() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDebugSmartBore() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
|
|
||||||
BlockState state = world.getBlockAt(xx, yy, zz).getState();
|
|
||||||
tile.toBukkitTry(state);
|
|
||||||
state.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Engine getEngine() {
|
|
||||||
if (IrisToolbelt.isIrisWorld(world)) {
|
|
||||||
return IrisToolbelt.access(world).getEngine();
|
|
||||||
}
|
|
||||||
|
|
||||||
return IrisContext.get().getEngine();
|
|
||||||
}
|
|
||||||
}, piece.getPlacementOptions(), rng, getData());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,19 +21,20 @@ package com.volmit.iris.engine.jigsaw;
|
|||||||
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.engine.data.cache.Cache;
|
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.mantle.MantleWriter;
|
import com.volmit.iris.engine.framework.placer.WorldObjectPlacer;
|
||||||
import com.volmit.iris.engine.object.*;
|
import com.volmit.iris.engine.object.*;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.mantle.Mantle;
|
import com.volmit.iris.util.mantle.Mantle;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
|
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
|
||||||
|
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.bukkit.Axis;
|
import org.bukkit.Axis;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.block.TileState;
|
import java.util.function.Consumer;
|
||||||
import org.bukkit.block.data.BlockData;
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class PlannedStructure {
|
public class PlannedStructure {
|
||||||
@@ -74,33 +75,44 @@ public class PlannedStructure {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void place(IObjectPlacer placer, Mantle e, Engine eng) {
|
public boolean place(IObjectPlacer placer, Mantle e, Engine eng) {
|
||||||
IrisObjectPlacement options = new IrisObjectPlacement();
|
IrisObjectPlacement options = new IrisObjectPlacement();
|
||||||
options.getRotation().setEnabled(false);
|
options.setRotation(IrisObjectRotation.of(0,0,0));
|
||||||
int startHeight = pieces.get(0).getPosition().getY();
|
int startHeight = pieces.get(0).getPosition().getY();
|
||||||
|
|
||||||
|
boolean placed = false;
|
||||||
for (PlannedPiece i : pieces) {
|
for (PlannedPiece i : pieces) {
|
||||||
place(i, startHeight, options, placer, e, eng);
|
if (place(i, startHeight, options, placer, e, eng))
|
||||||
|
placed = true;
|
||||||
}
|
}
|
||||||
|
if (placed) {
|
||||||
|
Position2 chunkPos = new Position2(position.getX() >> 4, position.getZ() >> 4);
|
||||||
|
Position2 regionPos = new Position2(chunkPos.getX() >> 5, chunkPos.getZ() >> 5);
|
||||||
|
JigsawStructuresContainer slice = e.get(regionPos.getX(), 0, regionPos.getZ(), JigsawStructuresContainer.class);
|
||||||
|
if (slice == null) slice = new JigsawStructuresContainer();
|
||||||
|
slice.add(structure, chunkPos);
|
||||||
|
e.set(regionPos.getX(), 0, regionPos.getZ(), slice);
|
||||||
|
}
|
||||||
|
return placed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void place(PlannedPiece i, int startHeight, IrisObjectPlacement o, IObjectPlacer placer, Mantle e, Engine eng) {
|
public boolean place(PlannedPiece i, int startHeight, IrisObjectPlacement o, IObjectPlacer placer, Mantle e, Engine eng) {
|
||||||
IrisObjectPlacement options = o;
|
IrisObjectPlacement options = o;
|
||||||
|
|
||||||
if (i.getPiece().getPlacementOptions() != null) {
|
if (i.getPiece().getPlacementOptions() != null) {
|
||||||
options = i.getPiece().getPlacementOptions();
|
options = i.getPiece().getPlacementOptions();
|
||||||
options.getRotation().setEnabled(false);
|
options.getRotation().setEnabled(false);
|
||||||
|
options.setRotateTowardsSlope(false);
|
||||||
|
options.setWarp(new IrisGeneratorStyle(NoiseStyle.FLAT));
|
||||||
} else {
|
} else {
|
||||||
options.setMode(i.getPiece().getPlaceMode());
|
options.setMode(i.getPiece().getPlaceMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
IrisObject vo = i.getOgObject();
|
|
||||||
IrisObject v = i.getObject();
|
IrisObject v = i.getObject();
|
||||||
int sx = (v.getW() / 2);
|
int sx = (v.getW() / 2);
|
||||||
int sz = (v.getD() / 2);
|
int sz = (v.getD() / 2);
|
||||||
int xx = i.getPosition().getX() + sx;
|
int xx = i.getPosition().getX() + sx;
|
||||||
int zz = i.getPosition().getZ() + sz;
|
int zz = i.getPosition().getZ() + sz;
|
||||||
RNG rngf = new RNG(Cache.key(xx, zz));
|
|
||||||
int offset = i.getPosition().getY() - startHeight;
|
int offset = i.getPosition().getY() - startHeight;
|
||||||
int height;
|
int height;
|
||||||
|
|
||||||
@@ -108,12 +120,23 @@ public class PlannedStructure {
|
|||||||
if (i.getStructure().getStructure().getOverrideYRange() != null) {
|
if (i.getStructure().getStructure().getOverrideYRange() != null) {
|
||||||
height = (int) i.getStructure().getStructure().getOverrideYRange().get(rng, xx, zz, getData());
|
height = (int) i.getStructure().getStructure().getOverrideYRange().get(rng, xx, zz, getData());
|
||||||
} else {
|
} else {
|
||||||
height = placer.getHighest(xx, zz, getData());
|
height = placer.getHighest(xx, zz, getData(), options.isUnderwater());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
height = i.getStructure().getStructure().getLockY();
|
height = i.getStructure().getStructure().getLockY();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlannedPiece.ParentConnection connection = i.getParent();
|
||||||
|
if (connection != null && connection.connector().isLockY()) {
|
||||||
|
var pos = connection.getTargetPosition();
|
||||||
|
if (pos != null) {
|
||||||
|
height = pos.getY();
|
||||||
|
offset = 0;
|
||||||
|
} else {
|
||||||
|
Iris.warn("Failed to get target position for " + v.getLoadKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
height += offset + (v.getH() / 2);
|
height += offset + (v.getH() / 2);
|
||||||
|
|
||||||
if (options.getMode().equals(ObjectPlaceMode.PAINT)) {
|
if (options.getMode().equals(ObjectPlaceMode.PAINT)) {
|
||||||
@@ -122,16 +145,15 @@ public class PlannedStructure {
|
|||||||
|
|
||||||
int id = rng.i(0, Integer.MAX_VALUE);
|
int id = rng.i(0, Integer.MAX_VALUE);
|
||||||
JigsawPieceContainer container = JigsawPieceContainer.toContainer(i.getPiece());
|
JigsawPieceContainer container = JigsawPieceContainer.toContainer(i.getPiece());
|
||||||
vo.place(xx, height, zz, placer, options, rng, (b, data) -> {
|
i.setRealPositions(xx, height, zz, placer);
|
||||||
|
return v.place(xx, height, zz, placer, options, rng, (b, data) -> {
|
||||||
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
|
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
|
||||||
e.set(b.getX(), b.getY(), b.getZ(), container);
|
e.set(b.getX(), b.getY(), b.getZ(), container);
|
||||||
}, null, getData());
|
}, null, getData().getEngine() != null ? getData() : eng.getData()) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void place(World world) {
|
public void place(WorldObjectPlacer placer, Consumer<Boolean> consumer) {
|
||||||
for (PlannedPiece i : pieces) {
|
J.s(() -> consumer.accept(place(placer, placer.getMantle().getMantle(), placer.getEngine())));
|
||||||
Iris.sq(() -> i.place(world));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateOutwards() {
|
private void generateOutwards() {
|
||||||
@@ -167,9 +189,7 @@ public class PlannedStructure {
|
|||||||
|
|
||||||
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea) {
|
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea) {
|
||||||
if (!piece.getPiece().getPlacementOptions().getRotation().isEnabled()) {
|
if (!piece.getPiece().getPlacementOptions().getRotation().isEnabled()) {
|
||||||
if (generateRotatedPiece(piece, pieceConnector, idea, 0, 0, 0)) {
|
return generateRotatedPiece(piece, pieceConnector, idea, 0, 0, 0);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KList<Integer> forder1 = new KList<Integer>().qadd(0).qadd(1).qadd(2).qadd(3).shuffle(rng);
|
KList<Integer> forder1 = new KList<Integer>().qadd(0).qadd(1).qadd(2).qadd(3).shuffle(rng);
|
||||||
@@ -216,7 +236,7 @@ public class PlannedStructure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea, int x, int y, int z) {
|
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea, int x, int y, int z) {
|
||||||
return generateRotatedPiece(piece, pieceConnector, idea, IrisObjectRotation.of(x, y, z));
|
return generateRotatedPiece(piece, pieceConnector, idea, IrisObjectRotation.of(x * 90D, y * 90D, z * 90D));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean generatePositionedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, PlannedPiece test, IrisJigsawPieceConnector testConnector) {
|
private boolean generatePositionedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, PlannedPiece test, IrisJigsawPieceConnector testConnector) {
|
||||||
@@ -240,8 +260,7 @@ public class PlannedStructure {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
piece.connect(pieceConnector);
|
piece.connect(pieceConnector, test, testConnector);
|
||||||
test.connect(testConnector);
|
|
||||||
pieces.add(test);
|
pieces.add(test);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -250,7 +269,8 @@ public class PlannedStructure {
|
|||||||
private KList<IrisJigsawPiece> getShuffledPiecesFor(IrisJigsawPieceConnector c) {
|
private KList<IrisJigsawPiece> getShuffledPiecesFor(IrisJigsawPieceConnector c) {
|
||||||
KList<IrisJigsawPiece> p = new KList<>();
|
KList<IrisJigsawPiece> p = new KList<>();
|
||||||
|
|
||||||
for (String i : c.getPools().shuffleCopy(rng)) {
|
KList<String> pools = terminating && getStructure().getTerminatePool() != null ? new KList<>(getStructure().getTerminatePool()) : c.getPools().shuffleCopy(rng);
|
||||||
|
for (String i : pools) {
|
||||||
for (String j : getData().getJigsawPoolLoader().load(i).getPieces().shuffleCopy(rng)) {
|
for (String j : getData().getJigsawPoolLoader().load(i).getPieces().shuffleCopy(rng)) {
|
||||||
IrisJigsawPiece pi = getData().getJigsawPieceLoader().load(j);
|
IrisJigsawPiece pi = getData().getJigsawPieceLoader().load(j);
|
||||||
|
|
||||||
@@ -276,7 +296,9 @@ public class PlannedStructure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public KList<PlannedPiece> getPiecesWithAvailableConnectors() {
|
public KList<PlannedPiece> getPiecesWithAvailableConnectors() {
|
||||||
return pieces.copy().removeWhere(PlannedPiece::isFull);
|
KList<PlannedPiece> available = pieces.copy().removeWhere(PlannedPiece::isFull);
|
||||||
|
if (!terminating) available.removeIf(PlannedPiece::isDead);
|
||||||
|
return available;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVolume() {
|
public int getVolume() {
|
||||||
@@ -301,6 +323,10 @@ public class PlannedStructure {
|
|||||||
|
|
||||||
public boolean collidesWith(PlannedPiece piece, PlannedPiece ignore) {
|
public boolean collidesWith(PlannedPiece piece, PlannedPiece ignore) {
|
||||||
for (PlannedPiece i : pieces) {
|
for (PlannedPiece i : pieces) {
|
||||||
|
if (i.equals(ignore)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (i.collidesWith(piece)) {
|
if (i.collidesWith(piece)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+69
-34
@@ -24,13 +24,17 @@ import com.volmit.iris.engine.mantle.IrisMantleComponent;
|
|||||||
import com.volmit.iris.engine.mantle.MantleWriter;
|
import com.volmit.iris.engine.mantle.MantleWriter;
|
||||||
import com.volmit.iris.engine.object.*;
|
import com.volmit.iris.engine.object.*;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.collection.KSet;
|
||||||
import com.volmit.iris.util.context.ChunkContext;
|
import com.volmit.iris.util.context.ChunkContext;
|
||||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
import com.volmit.iris.util.mantle.MantleFlag;
|
import com.volmit.iris.util.mantle.MantleFlag;
|
||||||
import com.volmit.iris.util.math.Position2;
|
import com.volmit.iris.util.math.Position2;
|
||||||
import com.volmit.iris.util.math.RNG;
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
|
||||||
import com.volmit.iris.util.noise.CNG;
|
import com.volmit.iris.util.noise.CNG;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -39,21 +43,22 @@ public class MantleJigsawComponent extends IrisMantleComponent {
|
|||||||
|
|
||||||
public MantleJigsawComponent(EngineMantle engineMantle) {
|
public MantleJigsawComponent(EngineMantle engineMantle) {
|
||||||
super(engineMantle, MantleFlag.JIGSAW);
|
super(engineMantle, MantleFlag.JIGSAW);
|
||||||
cng = NoiseStyle.STATIC.create(new RNG(engineMantle.getEngine().getSeedManager().getJigsaw()));
|
cng = NoiseStyle.STATIC.create(new RNG(jigsaw()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateLayer(MantleWriter writer, int x, int z, ChunkContext context) {
|
public void generateLayer(MantleWriter writer, int x, int z, ChunkContext context) {
|
||||||
RNG rng = new RNG(cng.fit(-Integer.MAX_VALUE, Integer.MAX_VALUE, x, z));
|
|
||||||
int xxx = 8 + (x << 4);
|
int xxx = 8 + (x << 4);
|
||||||
int zzz = 8 + (z << 4);
|
int zzz = 8 + (z << 4);
|
||||||
IrisRegion region = getComplex().getRegionStream().get(xxx, zzz);
|
IrisRegion region = getComplex().getRegionStream().get(xxx, zzz);
|
||||||
IrisBiome biome = getComplex().getTrueBiomeStream().get(xxx, zzz);
|
IrisBiome biome = getComplex().getTrueBiomeStream().get(xxx, zzz);
|
||||||
generateJigsaw(writer, rng, x, z, biome, region);
|
generateJigsaw(writer, x, z, biome, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
private void generateJigsaw(MantleWriter writer, RNG rng, int x, int z, IrisBiome biome, IrisRegion region) {
|
private void generateJigsaw(MantleWriter writer, int x, int z, IrisBiome biome, IrisRegion region) {
|
||||||
|
long seed = cng.fit(Integer.MIN_VALUE, Integer.MIN_VALUE, x, z);
|
||||||
|
|
||||||
if (getDimension().getStronghold() != null) {
|
if (getDimension().getStronghold() != null) {
|
||||||
List<Position2> poss = getDimension().getStrongholds(seed());
|
List<Position2> poss = getDimension().getStrongholds(seed());
|
||||||
|
|
||||||
@@ -61,28 +66,61 @@ public class MantleJigsawComponent extends IrisMantleComponent {
|
|||||||
for (Position2 pos : poss) {
|
for (Position2 pos : poss) {
|
||||||
if (x == pos.getX() >> 4 && z == pos.getZ() >> 4) {
|
if (x == pos.getX() >> 4 && z == pos.getZ() >> 4) {
|
||||||
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(getDimension().getStronghold());
|
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(getDimension().getStronghold());
|
||||||
place(writer, pos.toIris(), structure, rng);
|
place(writer, pos.toIris(), structure, new RNG(seed));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean placed = placeStructures(writer, rng, x, z, biome.getJigsawStructures());
|
KSet<Position2> cachedRegions = new KSet<>();
|
||||||
|
KMap<String, KSet<Position2>> cache = new KMap<>();
|
||||||
|
KMap<Position2, Double> distanceCache = new KMap<>();
|
||||||
|
boolean placed = placeStructures(writer, seed, x, z, biome.getJigsawStructures(), cachedRegions, cache, distanceCache);
|
||||||
if (!placed)
|
if (!placed)
|
||||||
placed = placeStructures(writer, rng, x, z, region.getJigsawStructures());
|
placed = placeStructures(writer, seed, x, z, region.getJigsawStructures(), cachedRegions, cache, distanceCache);
|
||||||
if (!placed)
|
if (!placed)
|
||||||
placeStructures(writer, rng, x, z, getDimension().getJigsawStructures());
|
placeStructures(writer, seed, x, z, getDimension().getJigsawStructures(), cachedRegions, cache, distanceCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
private boolean placeStructures(MantleWriter writer, RNG rng, int x, int z, KList<IrisJigsawStructurePlacement> structures) {
|
private boolean placeStructures(MantleWriter writer, long seed, int x, int z, KList<IrisJigsawStructurePlacement> structures,
|
||||||
for (IrisJigsawStructurePlacement i : structures) {
|
KSet<Position2> cachedRegions, KMap<String, KSet<Position2>> cache, KMap<Position2, Double> distanceCache) {
|
||||||
if (rng.nextInt(i.getRarity()) == 0) {
|
IrisJigsawStructurePlacement i = pick(structures, seed, x, z);
|
||||||
|
if (i == null || checkMinDistances(i.collectMinDistances(), x, z, cachedRegions, cache, distanceCache))
|
||||||
|
return false;
|
||||||
|
RNG rng = new RNG(seed);
|
||||||
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
|
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
|
||||||
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
|
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
|
||||||
place(writer, position, structure, rng);
|
return place(writer, position, structure, rng);
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
@ChunkCoordinates
|
||||||
|
private boolean checkMinDistances(KMap<String, Integer> minDistances, int x, int z, KSet<Position2> cachedRegions, KMap<String, KSet<Position2>> cache, KMap<Position2, Double> distanceCache) {
|
||||||
|
int range = 0;
|
||||||
|
for (int d : minDistances.values())
|
||||||
|
range = Math.max(range, d);
|
||||||
|
|
||||||
|
for (int xx = -range; xx <= range; xx++) {
|
||||||
|
for (int zz = -range; zz <= range; zz++) {
|
||||||
|
Position2 pos = new Position2((xx + x) >> 5, (zz + z) >> 5);
|
||||||
|
if (cachedRegions.contains(pos)) continue;
|
||||||
|
cachedRegions.add(pos);
|
||||||
|
JigsawStructuresContainer container = getMantle().get(pos.getX(), 0, pos.getZ(), JigsawStructuresContainer.class);
|
||||||
|
if (container == null) continue;
|
||||||
|
for (String key : container.getStructures()) {
|
||||||
|
cache.computeIfAbsent(key, k -> new KSet<>()).addAll(container.getPositions(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Position2 pos = new Position2(x, z);
|
||||||
|
for (String structure : minDistances.keySet()) {
|
||||||
|
if (!cache.containsKey(structure)) continue;
|
||||||
|
double minDist = minDistances.get(structure);
|
||||||
|
minDist = minDist * minDist;
|
||||||
|
for (Position2 sPos : cache.get(structure)) {
|
||||||
|
double dist = distanceCache.computeIfAbsent(sPos, position2 -> position2.distance(pos));
|
||||||
|
if (minDist > dist) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -91,8 +129,8 @@ public class MantleJigsawComponent extends IrisMantleComponent {
|
|||||||
@ChunkCoordinates
|
@ChunkCoordinates
|
||||||
public IrisJigsawStructure guess(int x, int z) {
|
public IrisJigsawStructure guess(int x, int z) {
|
||||||
// todo The guess doesnt bring into account that the placer may return -1
|
// todo The guess doesnt bring into account that the placer may return -1
|
||||||
boolean t = false;
|
// todo doesnt bring skipped placements into account
|
||||||
RNG rng = new RNG(cng.fit(-Integer.MAX_VALUE, Integer.MAX_VALUE, x, z));
|
long seed = cng.fit(Integer.MIN_VALUE, Integer.MIN_VALUE, x, z);
|
||||||
IrisBiome biome = getEngineMantle().getEngine().getSurfaceBiome((x << 4) + 8, (z << 4) + 8);
|
IrisBiome biome = getEngineMantle().getEngine().getSurfaceBiome((x << 4) + 8, (z << 4) + 8);
|
||||||
IrisRegion region = getEngineMantle().getEngine().getRegion((x << 4) + 8, (z << 4) + 8);
|
IrisRegion region = getEngineMantle().getEngine().getRegion((x << 4) + 8, (z << 4) + 8);
|
||||||
|
|
||||||
@@ -108,29 +146,26 @@ public class MantleJigsawComponent extends IrisMantleComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IrisJigsawStructurePlacement i : biome.getJigsawStructures()) {
|
IrisJigsawStructurePlacement i = pick(biome.getJigsawStructures(), seed, x, z);
|
||||||
if (rng.nextInt(i.getRarity()) == 0) {
|
if (i == null) i = pick(region.getJigsawStructures(), seed, x, z);
|
||||||
return getData().getJigsawStructureLoader().load(i.getStructure());
|
if (i == null) i = pick(getDimension().getJigsawStructures(), seed, x, z);
|
||||||
}
|
return i != null ? getData().getJigsawStructureLoader().load(i.getStructure()) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IrisJigsawStructurePlacement i : region.getJigsawStructures()) {
|
@Nullable
|
||||||
if (rng.nextInt(i.getRarity()) == 0) {
|
@ChunkCoordinates
|
||||||
return getData().getJigsawStructureLoader().load(i.getStructure());
|
private IrisJigsawStructurePlacement pick(List<IrisJigsawStructurePlacement> structures, long seed, int x, int z) {
|
||||||
}
|
return IRare.pick(structures.stream()
|
||||||
}
|
.filter(p -> p.shouldPlace(jigsaw(), x, z))
|
||||||
|
.toList(), new RNG(seed).nextDouble());
|
||||||
for (IrisJigsawStructurePlacement i : getDimension().getJigsawStructures()) {
|
|
||||||
if (rng.nextInt(i.getRarity()) == 0) {
|
|
||||||
return getData().getJigsawStructureLoader().load(i.getStructure());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@BlockCoordinates
|
@BlockCoordinates
|
||||||
private void place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng) {
|
private boolean place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng) {
|
||||||
new PlannedStructure(structure, position, rng).place(writer, getMantle(), writer.getEngine());
|
return new PlannedStructure(structure, position, rng).place(writer, getMantle(), writer.getEngine());
|
||||||
|
}
|
||||||
|
|
||||||
|
private long jigsaw() {
|
||||||
|
return getEngineMantle().getEngine().getSeedManager().getJigsaw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.volmit.iris.engine.object;
|
||||||
|
|
||||||
|
import com.volmit.iris.engine.object.annotations.Desc;
|
||||||
|
import com.volmit.iris.engine.object.annotations.MinNumber;
|
||||||
|
import com.volmit.iris.engine.object.annotations.RegistryListResource;
|
||||||
|
import com.volmit.iris.engine.object.annotations.Required;
|
||||||
|
import com.volmit.iris.engine.object.annotations.Snippet;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Snippet("jigsaw-structure-min-distance")
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Desc("Represents the min distance between jigsaw structure placements")
|
||||||
|
@Data
|
||||||
|
public class IrisJigsawMinDistance {
|
||||||
|
@Required
|
||||||
|
@RegistryListResource(IrisJigsawStructure.class)
|
||||||
|
@Desc("The structure to check against")
|
||||||
|
private String structure;
|
||||||
|
|
||||||
|
@Required
|
||||||
|
@MinNumber(0)
|
||||||
|
@Desc("The min distance in blocks to a placed structure\nWARNING: The performance impact scales exponentially!")
|
||||||
|
private int distance;
|
||||||
|
}
|
||||||
@@ -101,19 +101,12 @@ public class IrisJigsawPiece extends IrisRegistrant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IrisJigsawPiece copy() {
|
public IrisJigsawPiece copy() {
|
||||||
IrisJigsawPiece p = new IrisJigsawPiece();
|
var gson = getLoader().getGson();
|
||||||
p.setObject(getObject());
|
IrisJigsawPiece copy = gson.fromJson(gson.toJson(this), IrisJigsawPiece.class);
|
||||||
p.setLoader(getLoader());
|
copy.setLoader(getLoader());
|
||||||
p.setLoadKey(getLoadKey());
|
copy.setLoadKey(getLoadKey());
|
||||||
p.setLoadFile(getLoadFile());
|
copy.setLoadFile(getLoadFile());
|
||||||
p.setConnectors(new KList<>());
|
return copy;
|
||||||
p.setPlacementOptions(getPlacementOptions());
|
|
||||||
|
|
||||||
for (IrisJigsawPieceConnector i : getConnectors()) {
|
|
||||||
p.getConnectors().add(i.copy());
|
|
||||||
}
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTerminal() {
|
public boolean isTerminal() {
|
||||||
|
|||||||
@@ -79,6 +79,9 @@ public class IrisJigsawPieceConnector {
|
|||||||
@Required
|
@Required
|
||||||
private IrisDirection direction = IrisDirection.UP_POSITIVE_Y;
|
private IrisDirection direction = IrisDirection.UP_POSITIVE_Y;
|
||||||
|
|
||||||
|
@Desc("Lock the Y position of this connector")
|
||||||
|
private boolean lockY = false;
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return direction.getFace().name() + "@(" + position.getX() + "," + position.getY() + "," + position.getZ() + ")";
|
return direction.getFace().name() + "@(" + position.getX() + "," + position.getY() + "," + position.getZ() + ")";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ public class IrisJigsawStructure extends IrisRegistrant {
|
|||||||
@Desc("If set to true, iris will look for any pieces with only one connector in valid pools for edge connectors and attach them to 'terminate' the paths/piece connectors. Essentially it caps off ends. For example in a village, Iris would add houses to the ends of roads where possible. For terminators to be selected, they can only have one connector or they wont be chosen.")
|
@Desc("If set to true, iris will look for any pieces with only one connector in valid pools for edge connectors and attach them to 'terminate' the paths/piece connectors. Essentially it caps off ends. For example in a village, Iris would add houses to the ends of roads where possible. For terminators to be selected, they can only have one connector or they wont be chosen.")
|
||||||
private boolean terminate = true;
|
private boolean terminate = true;
|
||||||
|
|
||||||
|
@RegistryListResource(IrisJigsawPool.class)
|
||||||
|
@Desc("The pool to use when terminating pieces")
|
||||||
|
private String terminatePool = null;
|
||||||
|
|
||||||
@Desc("Override the y range instead of placing on the height map")
|
@Desc("Override the y range instead of placing on the height map")
|
||||||
private IrisStyledRange overrideYRange = null;
|
private IrisStyledRange overrideYRange = null;
|
||||||
|
|
||||||
|
|||||||
@@ -18,17 +18,23 @@
|
|||||||
|
|
||||||
package com.volmit.iris.engine.object;
|
package com.volmit.iris.engine.object;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.engine.object.annotations.ArrayType;
|
||||||
import com.volmit.iris.engine.object.annotations.Desc;
|
import com.volmit.iris.engine.object.annotations.Desc;
|
||||||
|
import com.volmit.iris.engine.object.annotations.MinNumber;
|
||||||
import com.volmit.iris.engine.object.annotations.RegistryListResource;
|
import com.volmit.iris.engine.object.annotations.RegistryListResource;
|
||||||
import com.volmit.iris.engine.object.annotations.Required;
|
import com.volmit.iris.engine.object.annotations.Required;
|
||||||
import com.volmit.iris.engine.object.annotations.Snippet;
|
import com.volmit.iris.engine.object.annotations.Snippet;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
|
import com.volmit.iris.util.math.RNG;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
|
||||||
@Snippet("jigsaw-structure-placement")
|
@Snippet("jigsaw-structure-placement")
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@@ -36,13 +42,84 @@ import lombok.experimental.Accessors;
|
|||||||
@Desc("Represents a jigsaw structure placer")
|
@Desc("Represents a jigsaw structure placer")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
public class IrisJigsawStructurePlacement {
|
public class IrisJigsawStructurePlacement implements IRare {
|
||||||
@RegistryListResource(IrisJigsawStructure.class)
|
@RegistryListResource(IrisJigsawStructure.class)
|
||||||
@Required
|
@Required
|
||||||
@Desc("The structure to place")
|
@Desc("The structure to place")
|
||||||
private String structure;
|
private String structure;
|
||||||
|
|
||||||
@Required
|
@Required
|
||||||
@Desc("The 1 in X chance rarity")
|
@Desc("The 1 in X chance rarity applies when generating multiple structures at once")
|
||||||
private int rarity = 100;
|
private int rarity = 100;
|
||||||
|
|
||||||
|
@Required
|
||||||
|
@Desc("The salt to use when generating the structure (to differentiate structures)")
|
||||||
|
private int salt = 76134;
|
||||||
|
|
||||||
|
@Required
|
||||||
|
@MinNumber(0)
|
||||||
|
@Desc("Average distance in chunks between two neighboring generation attempts")
|
||||||
|
private int spacing = 32;
|
||||||
|
|
||||||
|
@Required
|
||||||
|
@MinNumber(0)
|
||||||
|
@Desc("Minimum distance in chunks between two neighboring generation attempts\nThe maximum distance of two neighboring generation attempts is 2*spacing - separation")
|
||||||
|
private int separation = 16;
|
||||||
|
|
||||||
|
@Desc("The method used to spread the structure")
|
||||||
|
private SpreadType spreadType = SpreadType.TRIANGULAR;
|
||||||
|
|
||||||
|
@ArrayType(type = IrisJigsawMinDistance.class)
|
||||||
|
@Desc("List of minimum distances to check for")
|
||||||
|
private KList<IrisJigsawMinDistance> minDistances = new KList<>();
|
||||||
|
|
||||||
|
public KMap<String, Integer> collectMinDistances() {
|
||||||
|
KMap<String, Integer> map = new KMap<>();
|
||||||
|
for (IrisJigsawMinDistance d : minDistances) {
|
||||||
|
map.compute(d.getStructure(), (k, v) -> v != null ? Math.min(toChunks(d.getDistance()), v) : toChunks(d.getDistance()));
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int toChunks(int blocks) {
|
||||||
|
return (int) Math.ceil(blocks / 16d);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ChunkCoordinates
|
||||||
|
public boolean shouldPlace(long seed, int x, int z) {
|
||||||
|
if (separation > spacing) {
|
||||||
|
separation = spacing;
|
||||||
|
Iris.warn("JigsawStructurePlacement: separation must be less than or equal to spacing");
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = Math.floorDiv(x, spacing);
|
||||||
|
int j = Math.floorDiv(z, spacing);
|
||||||
|
RNG rng = new RNG(i * 341873128712L + j * 132897987541L + seed + salt);
|
||||||
|
|
||||||
|
int k = spacing - separation;
|
||||||
|
int l = spreadType.apply(rng, k);
|
||||||
|
int m = spreadType.apply(rng, k);
|
||||||
|
return i * spacing + l == x && j * spacing + m == z;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Desc("Spread type")
|
||||||
|
public enum SpreadType {
|
||||||
|
@Desc("Linear spread")
|
||||||
|
LINEAR(RNG::i),
|
||||||
|
@Desc("Triangular spread")
|
||||||
|
TRIANGULAR((rng, bound) -> (rng.i(bound) + rng.i(bound)) / 2);
|
||||||
|
private final SpreadMethod method;
|
||||||
|
|
||||||
|
SpreadType(SpreadMethod method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int apply(RNG rng, int bound) {
|
||||||
|
return method.apply(rng, bound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private interface SpreadMethod {
|
||||||
|
int apply(RNG rng, int bound);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,6 +279,8 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
public synchronized IrisObject copy() {
|
public synchronized IrisObject copy() {
|
||||||
IrisObject o = new IrisObject(w, h, d);
|
IrisObject o = new IrisObject(w, h, d);
|
||||||
o.setLoadKey(o.getLoadKey());
|
o.setLoadKey(o.getLoadKey());
|
||||||
|
o.setLoader(getLoader());
|
||||||
|
o.setLoadFile(getLoadFile());
|
||||||
o.setCenter(getCenter().clone());
|
o.setCenter(getCenter().clone());
|
||||||
|
|
||||||
for (BlockVector i : getBlocks().keySet()) {
|
for (BlockVector i : getBlocks().keySet()) {
|
||||||
@@ -419,9 +421,10 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
max.setZ(Math.max(max.getZ(), i.getZ()));
|
max.setZ(Math.max(max.getZ(), i.getZ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
w = max.getBlockX() - min.getBlockX();
|
w = max.getBlockX() - min.getBlockX() + (min.getBlockX() <= 0 && max.getBlockX() >= 0 && min.getBlockX() != max.getBlockX() ? 1 : 0);
|
||||||
h = max.getBlockY() - min.getBlockY();
|
h = max.getBlockY() - min.getBlockY() + (min.getBlockY() <= 0 && max.getBlockY() >= 0 && min.getBlockY() != max.getBlockY() ? 1 : 0);
|
||||||
d = max.getBlockZ() - min.getBlockZ();
|
d = max.getBlockZ() - min.getBlockZ() + (min.getBlockZ() <= 0 && max.getBlockZ() >= 0 && min.getBlockZ() != max.getBlockZ() ? 1 : 0);
|
||||||
|
center = new BlockVector(w / 2, h / 2, d / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clean() {
|
public void clean() {
|
||||||
@@ -503,7 +506,7 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
if (rdata != null) {
|
if (rdata != null) {
|
||||||
// Slope condition
|
// Slope condition
|
||||||
if (!config.getSlopeCondition().isDefault() &&
|
if (!config.getSlopeCondition().isDefault() &&
|
||||||
!config.getSlopeCondition().isValid(rdata.getEngine().getComplex().getSlopeStream().get(x, z))) {
|
!config.getSlopeCondition().isValid(rdata.getEngine().getComplex().getSlopeStream().get(x, z)) && !config.isForcePlace()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,11 +536,17 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
} else if (min == hWest) {
|
} else if (min == hWest) {
|
||||||
slopeRotationY = 270;
|
slopeRotationY = 270;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
double newRotation = config.getRotation().getYAxis().getMin() + slopeRotationY;
|
double newRotation = config.getRotation().getYAxis().getMin() + slopeRotationY;
|
||||||
|
if (newRotation == 0) {
|
||||||
|
config.getRotation().setYAxis(new IrisAxisRotationClamp(false, false, 0, 0, 90));
|
||||||
|
config.getRotation().setEnabled(config.getRotation().canRotateX() || config.getRotation().canRotateZ());
|
||||||
|
} else {
|
||||||
config.getRotation().setYAxis(new IrisAxisRotationClamp(true, false, newRotation, newRotation, 90));
|
config.getRotation().setYAxis(new IrisAxisRotationClamp(true, false, newRotation, newRotation, 90));
|
||||||
config.getRotation().setEnabled(true);
|
config.getRotation().setEnabled(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (config.isSmartBore()) {
|
if (config.isSmartBore()) {
|
||||||
ensureSmartBored(placer.isDebugSmartBore());
|
ensureSmartBored(placer.isDebugSmartBore());
|
||||||
@@ -562,9 +571,11 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
if (yv < 0) {
|
if (yv < 0) {
|
||||||
if (config.getMode().equals(ObjectPlaceMode.CENTER_HEIGHT) || config.getMode() == ObjectPlaceMode.CENTER_STILT) {
|
if (config.getMode().equals(ObjectPlaceMode.CENTER_HEIGHT) || config.getMode() == ObjectPlaceMode.CENTER_STILT) {
|
||||||
y = (c != null ? c.getSurface() : placer.getHighest(x, z, getLoader(), config.isUnderwater())) + rty;
|
y = (c != null ? c.getSurface() : placer.getHighest(x, z, getLoader(), config.isUnderwater())) + rty;
|
||||||
|
if (!config.isForcePlace()) {
|
||||||
if (placer.isCarved(x, y, z) || placer.isCarved(x, y - 1, z) || placer.isCarved(x, y - 2, z) || placer.isCarved(x, y - 3, z)) {
|
if (placer.isCarved(x, y, z) || placer.isCarved(x, y - 1, z) || placer.isCarved(x, y - 2, z) || placer.isCarved(x, y - 3, z)) {
|
||||||
bail = true;
|
bail = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (config.getMode().equals(ObjectPlaceMode.MAX_HEIGHT) || config.getMode().equals(ObjectPlaceMode.STILT)) {
|
} else if (config.getMode().equals(ObjectPlaceMode.MAX_HEIGHT) || config.getMode().equals(ObjectPlaceMode.STILT)) {
|
||||||
BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ());
|
BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ());
|
||||||
BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone();
|
BlockVector rotatedDimensions = config.getRotation().rotate(new BlockVector(getW(), getH(), getD()), spinx, spiny, spinz).clone();
|
||||||
@@ -577,10 +588,12 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
for (int i = minX; i <= maxX; i++) {
|
for (int i = minX; i <= maxX; i++) {
|
||||||
for (int ii = minZ; ii <= maxZ; ii++) {
|
for (int ii = minZ; ii <= maxZ; ii++) {
|
||||||
int h = placer.getHighest(i, ii, getLoader(), config.isUnderwater()) + rty;
|
int h = placer.getHighest(i, ii, getLoader(), config.isUnderwater()) + rty;
|
||||||
|
if (!config.isForcePlace()) {
|
||||||
if (placer.isCarved(i, h, ii) || placer.isCarved(i, h - 1, ii) || placer.isCarved(i, h - 2, ii) || placer.isCarved(i, h - 3, ii)) {
|
if (placer.isCarved(i, h, ii) || placer.isCarved(i, h - 1, ii) || placer.isCarved(i, h - 2, ii) || placer.isCarved(i, h - 3, ii)) {
|
||||||
bail = true;
|
bail = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (h > y)
|
if (h > y)
|
||||||
y = h;
|
y = h;
|
||||||
}
|
}
|
||||||
@@ -601,10 +614,12 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
for (int i = minX; i <= maxX; i += Math.abs(xRadius) + 1) {
|
for (int i = minX; i <= maxX; i += Math.abs(xRadius) + 1) {
|
||||||
for (int ii = minZ; ii <= maxZ; ii += Math.abs(zRadius) + 1) {
|
for (int ii = minZ; ii <= maxZ; ii += Math.abs(zRadius) + 1) {
|
||||||
int h = placer.getHighest(i, ii, getLoader(), config.isUnderwater()) + rty;
|
int h = placer.getHighest(i, ii, getLoader(), config.isUnderwater()) + rty;
|
||||||
|
if (!config.isForcePlace()) {
|
||||||
if (placer.isCarved(i, h, ii) || placer.isCarved(i, h - 1, ii) || placer.isCarved(i, h - 2, ii) || placer.isCarved(i, h - 3, ii)) {
|
if (placer.isCarved(i, h, ii) || placer.isCarved(i, h - 1, ii) || placer.isCarved(i, h - 2, ii) || placer.isCarved(i, h - 3, ii)) {
|
||||||
bail = true;
|
bail = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (h > y)
|
if (h > y)
|
||||||
y = h;
|
y = h;
|
||||||
}
|
}
|
||||||
@@ -623,10 +638,12 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
for (int i = minX; i <= maxX; i++) {
|
for (int i = minX; i <= maxX; i++) {
|
||||||
for (int ii = minZ; ii <= maxZ; ii++) {
|
for (int ii = minZ; ii <= maxZ; ii++) {
|
||||||
int h = placer.getHighest(i, ii, getLoader(), config.isUnderwater()) + rty;
|
int h = placer.getHighest(i, ii, getLoader(), config.isUnderwater()) + rty;
|
||||||
|
if (!config.isForcePlace()) {
|
||||||
if (placer.isCarved(i, h, ii) || placer.isCarved(i, h - 1, ii) || placer.isCarved(i, h - 2, ii) || placer.isCarved(i, h - 3, ii)) {
|
if (placer.isCarved(i, h, ii) || placer.isCarved(i, h - 1, ii) || placer.isCarved(i, h - 2, ii) || placer.isCarved(i, h - 3, ii)) {
|
||||||
bail = true;
|
bail = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (h < y) {
|
if (h < y) {
|
||||||
y = h;
|
y = h;
|
||||||
}
|
}
|
||||||
@@ -649,10 +666,12 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
for (int i = minX; i <= maxX; i += Math.abs(xRadius) + 1) {
|
for (int i = minX; i <= maxX; i += Math.abs(xRadius) + 1) {
|
||||||
for (int ii = minZ; ii <= maxZ; ii += Math.abs(zRadius) + 1) {
|
for (int ii = minZ; ii <= maxZ; ii += Math.abs(zRadius) + 1) {
|
||||||
int h = placer.getHighest(i, ii, getLoader(), config.isUnderwater()) + rty;
|
int h = placer.getHighest(i, ii, getLoader(), config.isUnderwater()) + rty;
|
||||||
|
if (!config.isForcePlace()) {
|
||||||
if (placer.isCarved(i, h, ii) || placer.isCarved(i, h - 1, ii) || placer.isCarved(i, h - 2, ii) || placer.isCarved(i, h - 3, ii)) {
|
if (placer.isCarved(i, h, ii) || placer.isCarved(i, h - 1, ii) || placer.isCarved(i, h - 2, ii) || placer.isCarved(i, h - 3, ii)) {
|
||||||
bail = true;
|
bail = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (h < y) {
|
if (h < y) {
|
||||||
y = h;
|
y = h;
|
||||||
}
|
}
|
||||||
@@ -660,45 +679,51 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
}
|
}
|
||||||
} else if (config.getMode().equals(ObjectPlaceMode.PAINT)) {
|
} else if (config.getMode().equals(ObjectPlaceMode.PAINT)) {
|
||||||
y = placer.getHighest(x, z, getLoader(), config.isUnderwater()) + rty;
|
y = placer.getHighest(x, z, getLoader(), config.isUnderwater()) + rty;
|
||||||
|
if (!config.isForcePlace()) {
|
||||||
if (placer.isCarved(x, y, z) || placer.isCarved(x, y - 1, z) || placer.isCarved(x, y - 2, z) || placer.isCarved(x, y - 3, z)) {
|
if (placer.isCarved(x, y, z) || placer.isCarved(x, y - 1, z) || placer.isCarved(x, y - 2, z) || placer.isCarved(x, y - 3, z)) {
|
||||||
bail = true;
|
bail = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
y = yv;
|
y = yv;
|
||||||
|
if (!config.isForcePlace()) {
|
||||||
if (placer.isCarved(x, y, z) || placer.isCarved(x, y - 1, z) || placer.isCarved(x, y - 2, z) || placer.isCarved(x, y - 3, z)) {
|
if (placer.isCarved(x, y, z) || placer.isCarved(x, y - 1, z) || placer.isCarved(x, y - 2, z) || placer.isCarved(x, y - 3, z)) {
|
||||||
bail = true;
|
bail = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (yv >= 0 && config.isBottom()) {
|
if (yv >= 0 && config.isBottom()) {
|
||||||
y += Math.floorDiv(h, 2);
|
y += Math.floorDiv(h, 2);
|
||||||
|
if (!config.isForcePlace()) {
|
||||||
bail = placer.isCarved(x, y, z) || placer.isCarved(x, y - 1, z) || placer.isCarved(x, y - 2, z) || placer.isCarved(x, y - 3, z);
|
bail = placer.isCarved(x, y, z) || placer.isCarved(x, y - 1, z) || placer.isCarved(x, y - 2, z) || placer.isCarved(x, y - 3, z);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bail) {
|
if (bail && !config.isForcePlace()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yv < 0) {
|
if (yv < 0) {
|
||||||
if (!config.isUnderwater() && !config.isOnwater() && placer.isUnderwater(x, z)) {
|
if (!config.isForcePlace() && !config.isUnderwater() && !config.isOnwater() && placer.isUnderwater(x, z)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c != null && Math.max(0, h + yrand + ty) + 1 >= c.getHeight()) {
|
if (!config.isForcePlace() && c != null && Math.max(0, h + yrand + ty) + 1 >= c.getHeight()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.isUnderwater() && y + rty + ty >= placer.getFluidHeight()) {
|
if (!config.isForcePlace() && config.isUnderwater() && y + rty + ty >= placer.getFluidHeight()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.getClamp().canPlace(y + rty + ty, y - rty + ty)) {
|
if (!config.isForcePlace() && !config.getClamp().canPlace(y + rty + ty, y - rty + ty)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.getAllowedCollisions().isEmpty() || !config.getForbiddenCollisions().isEmpty()) {
|
if (!config.isForcePlace() && (!config.getAllowedCollisions().isEmpty() || !config.getForbiddenCollisions().isEmpty())) {
|
||||||
Engine engine = rdata.getEngine();
|
Engine engine = rdata.getEngine();
|
||||||
BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ());
|
BlockVector offset = new BlockVector(config.getTranslate().getX(), config.getTranslate().getY(), config.getTranslate().getZ());
|
||||||
for (int i = x - Math.floorDiv(w, 2) + (int) offset.getX(); i <= x + Math.floorDiv(w, 2) - (w % 2 == 0 ? 1 : 0) + (int) offset.getX(); i++) {
|
for (int i = x - Math.floorDiv(w, 2) + (int) offset.getX(); i <= x + Math.floorDiv(w, 2) - (w % 2 == 0 ? 1 : 0) + (int) offset.getX(); i++) {
|
||||||
@@ -892,6 +917,7 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
}
|
}
|
||||||
readLock.unlock();
|
readLock.unlock();
|
||||||
@@ -1026,6 +1052,7 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
|
|
||||||
blocks = d;
|
blocks = d;
|
||||||
states = dx;
|
states = dx;
|
||||||
|
shrinkwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void place(Location at) {
|
public void place(Location at) {
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ public class IrisObjectPlacement {
|
|||||||
@ArrayType(type = String.class)
|
@ArrayType(type = String.class)
|
||||||
@Desc("List of objects to this object is forbidden to collied with")
|
@Desc("List of objects to this object is forbidden to collied with")
|
||||||
private KList<String> forbiddenCollisions = new KList<>();
|
private KList<String> forbiddenCollisions = new KList<>();
|
||||||
|
@Desc("Ignore any placement restrictions for this object")
|
||||||
|
private boolean forcePlace = false;
|
||||||
private transient AtomicCache<TableCache> cache = new AtomicCache<>();
|
private transient AtomicCache<TableCache> cache = new AtomicCache<>();
|
||||||
|
|
||||||
public IrisObjectPlacement toPlacement(String... place) {
|
public IrisObjectPlacement toPlacement(String... place) {
|
||||||
|
|||||||
@@ -101,6 +101,11 @@ public class IrisObjectRotation {
|
|||||||
i.setPosition(rotate(i.getPosition()));
|
i.setPosition(rotate(i.getPosition()));
|
||||||
i.setDirection(rotate(i.getDirection()));
|
i.setDirection(rotate(i.getDirection()));
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
var translate = piece.getPlacementOptions().getTranslate();
|
||||||
|
var pos = rotate(new IrisPosition(translate.getX(), translate.getY(), translate.getZ()));
|
||||||
|
translate.setX(pos.getX()).setY(pos.getY()).setZ(pos.getZ());
|
||||||
|
} catch (NullPointerException ignored) {}
|
||||||
|
|
||||||
return piece;
|
return piece;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.volmit.iris.util.matter.slices;
|
||||||
|
|
||||||
|
import com.volmit.iris.util.data.palette.Palette;
|
||||||
|
import com.volmit.iris.util.matter.Sliced;
|
||||||
|
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Sliced
|
||||||
|
public class JigsawStructuresMatter extends RawMatter<JigsawStructuresContainer> {
|
||||||
|
public JigsawStructuresMatter() {
|
||||||
|
this(1, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JigsawStructuresMatter(int width, int height, int depth) {
|
||||||
|
super(width, height, depth, JigsawStructuresContainer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Palette<JigsawStructuresContainer> getGlobalPalette() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeNode(JigsawStructuresContainer b, DataOutputStream dos) throws IOException {
|
||||||
|
b.write(dos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JigsawStructuresContainer readNode(DataInputStream din) throws IOException {
|
||||||
|
return new JigsawStructuresContainer(din);
|
||||||
|
}
|
||||||
|
}
|
||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
package com.volmit.iris.util.matter.slices.container;
|
||||||
|
|
||||||
|
import com.volmit.iris.engine.object.IrisJigsawStructure;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class JigsawStructuresContainer {
|
||||||
|
private final Map<String, List<Position2>> map = new KMap<>();
|
||||||
|
|
||||||
|
public JigsawStructuresContainer() {}
|
||||||
|
|
||||||
|
public JigsawStructuresContainer(DataInputStream din) throws IOException {
|
||||||
|
int s0 = din.readInt();
|
||||||
|
for (int i = 0; i < s0; i++) {
|
||||||
|
int s1 = din.readInt();
|
||||||
|
KList<Position2> list = new KList<>(s1);
|
||||||
|
for (int j = 0; j < s1; j++) {
|
||||||
|
list.add(new Position2(din.readInt(), din.readInt()));
|
||||||
|
}
|
||||||
|
map.put(din.readUTF(), list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(DataOutputStream dos) throws IOException {
|
||||||
|
dos.writeInt(map.size());
|
||||||
|
for (String key : map.keySet()) {
|
||||||
|
List<Position2> list = map.get(key);
|
||||||
|
dos.writeInt(list.size());
|
||||||
|
for (Position2 pos : list) {
|
||||||
|
dos.writeInt(pos.getX());
|
||||||
|
dos.writeInt(pos.getZ());
|
||||||
|
}
|
||||||
|
dos.writeUTF(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
public Set<String> getStructures() {
|
||||||
|
return Collections.unmodifiableSet(map.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmodifiable
|
||||||
|
public List<Position2> getPositions(String structure) {
|
||||||
|
return Collections.unmodifiableList(map.get(structure));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ChunkCoordinates
|
||||||
|
public void add(IrisJigsawStructure structure, Position2 pos) {
|
||||||
|
map.computeIfAbsent(structure.getLoadKey(), k -> new KList<>()).add(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ libraries:
|
|||||||
- commons-io:commons-io:2.13.0
|
- commons-io:commons-io:2.13.0
|
||||||
- io.timeandspace:smoothie-map:2.0.2
|
- io.timeandspace:smoothie-map:2.0.2
|
||||||
- com.google.guava:guava:31.0.1-jre
|
- com.google.guava:guava:31.0.1-jre
|
||||||
- com.google.code.gson:gson:2.8.9
|
- com.google.code.gson:gson:2.10.1
|
||||||
- org.zeroturnaround:zt-zip:1.14
|
- org.zeroturnaround:zt-zip:1.14
|
||||||
- it.unimi.dsi:fastutil:8.5.6
|
- it.unimi.dsi:fastutil:8.5.6
|
||||||
- org.ow2.asm:asm:9.2
|
- org.ow2.asm:asm:9.2
|
||||||
|
|||||||
Reference in New Issue
Block a user