9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-28 11:39:07 +00:00

add min distance to jigsaw structures

This commit is contained in:
CrazyDev22
2024-04-17 21:15:15 +02:00
parent 61c0ddb15b
commit 856c926cde
6 changed files with 214 additions and 14 deletions

View File

@@ -26,8 +26,10 @@ import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList;
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.matter.slices.container.JigsawPieceContainer;
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
import lombok.Data;
import org.bukkit.Axis;
import org.bukkit.World;
@@ -71,17 +73,28 @@ 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();
options.setRotation(IrisObjectRotation.of(0,0,0));
int startHeight = pieces.get(0).getPosition().getY();
boolean placed = false;
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;
if (i.getPiece().getPlacementOptions() != null) {
@@ -119,10 +132,10 @@ public class PlannedStructure {
int id = rng.i(0, Integer.MAX_VALUE);
JigsawPieceContainer container = JigsawPieceContainer.toContainer(i.getPiece());
v.place(xx, height, zz, placer, options, rng, (b, data) -> {
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(), container);
}, null, getData());
}, null, getData()) != -1;
}
public void place(World world) {

View File

@@ -24,12 +24,15 @@ import com.volmit.iris.engine.mantle.IrisMantleComponent;
import com.volmit.iris.engine.mantle.MantleWriter;
import com.volmit.iris.engine.object.*;
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.documentation.BlockCoordinates;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
import com.volmit.iris.util.noise.CNG;
import java.util.List;
@@ -68,21 +71,58 @@ public class MantleJigsawComponent extends IrisMantleComponent {
}
}
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, rng, x, z, biome.getJigsawStructures(), cachedRegions, cache, distanceCache);
if (!placed)
placed = placeStructures(writer, rng, x, z, region.getJigsawStructures());
placed = placeStructures(writer, rng, x, z, region.getJigsawStructures(), cachedRegions, cache, distanceCache);
if (!placed)
placeStructures(writer, rng, x, z, getDimension().getJigsawStructures());
placeStructures(writer, rng, x, z, getDimension().getJigsawStructures(), cachedRegions, cache, distanceCache);
}
@ChunkCoordinates
private boolean placeStructures(MantleWriter writer, RNG rng, int x, int z, KList<IrisJigsawStructurePlacement> structures) {
private boolean placeStructures(MantleWriter writer, RNG rng, int x, int z, KList<IrisJigsawStructurePlacement> structures,
KSet<Position2> cachedRegions, KMap<String, KSet<Position2>> cache, KMap<Position2, Double> distanceCache) {
for (IrisJigsawStructurePlacement i : structures) {
if (rng.nextInt(i.getRarity()) == 0) {
if (checkDistances(i.collectDistances(), x, z, cachedRegions, cache, distanceCache))
continue;
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
place(writer, position, structure, rng);
return true;
if (place(writer, position, structure, rng))
return true;
}
}
return false;
}
@ChunkCoordinates
private boolean checkDistances(KMap<String, Integer> distances, int x, int z, KSet<Position2> cachedRegions, KMap<String, KSet<Position2>> cache, KMap<Position2, Double> distanceCache) {
int range = 0;
for (int d : distances.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 : distances.keySet()) {
if (!cache.containsKey(structure)) continue;
double maxDist = distances.get(structure);
maxDist = maxDist * maxDist;
for (Position2 sPos : cache.get(structure)) {
double dist = distanceCache.computeIfAbsent(sPos, position2 -> position2.distance(pos));
if (dist > maxDist) return true;
}
}
return false;
@@ -91,7 +131,7 @@ public class MantleJigsawComponent extends IrisMantleComponent {
@ChunkCoordinates
public IrisJigsawStructure guess(int x, int z) {
// 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));
IrisBiome biome = getEngineMantle().getEngine().getSurfaceBiome((x << 4) + 8, (z << 4) + 8);
IrisRegion region = getEngineMantle().getEngine().getRegion((x << 4) + 8, (z << 4) + 8);
@@ -130,7 +170,7 @@ public class MantleJigsawComponent extends IrisMantleComponent {
}
@BlockCoordinates
private void place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng) {
new PlannedStructure(structure, position, rng).place(writer, getMantle(), writer.getEngine());
private boolean place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng) {
return new PlannedStructure(structure, position, rng).place(writer, getMantle(), writer.getEngine());
}
}

View File

@@ -0,0 +1,31 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.MaxNumber;
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-distance")
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Desc("Represents the min distance between jigsaw structure placements")
@Data
public class IrisJigsawDistance {
@Required
@RegistryListResource(IrisJigsawStructure.class)
@Desc("The structure to check against")
private String structure;
@Required
@MinNumber(0)
@MaxNumber(5000)
@Desc("The min distance in blocks to a placed structure\nWARNING: The performance impact scales exponentially!")
private int distance;
}

View File

@@ -18,10 +18,13 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.engine.object.annotations.ArrayType;
import com.volmit.iris.engine.object.annotations.Desc;
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 com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -45,4 +48,20 @@ public class IrisJigsawStructurePlacement {
@Required
@Desc("The 1 in X chance rarity")
private int rarity = 100;
@ArrayType(type = IrisJigsawDistance.class)
@Desc("List of distances to check for")
private KList<IrisJigsawDistance> distances = new KList<>();
public KMap<String, Integer> collectDistances() {
KMap<String, Integer> map = new KMap<>();
for (IrisJigsawDistance d : distances) {
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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}