diff --git a/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java b/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java index 8e28490d8..e5e1ed192 100644 --- a/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java +++ b/core/src/main/java/com/volmit/iris/engine/IrisEngineMantle.java @@ -23,15 +23,11 @@ import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.mantle.EngineMantle; import com.volmit.iris.engine.mantle.MantleComponent; -import com.volmit.iris.engine.mantle.components.MantleCarvingComponent; -import com.volmit.iris.engine.mantle.components.MantleFluidBodyComponent; -import com.volmit.iris.engine.mantle.components.MantleJigsawComponent; -import com.volmit.iris.engine.mantle.components.MantleObjectComponent; +import com.volmit.iris.engine.mantle.components.*; 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.format.C; import com.volmit.iris.util.format.Form; import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.parallel.BurstExecutor; @@ -68,6 +64,7 @@ public class IrisEngineMantle implements EngineMantle { registerComponent(jigsaw); object = new MantleObjectComponent(this); registerComponent(object); + registerComponent(new MantleStaticComponent(this)); } @Override @@ -165,6 +162,22 @@ public class IrisEngineMantle implements EngineMantle { jig = Math.max(jig, getData().getJigsawStructureLoader().load(j.getStructure()).getMaxDimension()); } + jig = Math.max(getEngine().getDimension().getStaticPlacements().getStructures().stream() + .mapToInt(p -> p.maxDimension(getData())) + .max() + .orElse(0), jig); + + getEngine().getDimension().getStaticPlacements().getObjects() + .stream() + .map(IrisStaticObjectPlacement::placement) + .forEach(j -> { + if (j.getScale().canScaleBeyond()) { + scalars.put(j.getScale(), j.getPlace()); + } else { + objects.addAll(j.getPlace()); + } + }); + if (getEngine().getDimension().getStronghold() != null) { try { jig = Math.max(jig, getData().getJigsawStructureLoader().load(getEngine().getDimension().getStronghold()).getMaxDimension()); diff --git a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java index 145fdd4e7..bf5260502 100644 --- a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java +++ b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java @@ -826,6 +826,13 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat return new PlacedObject(piece.getPlacementOptions(), getData().getObjectLoader().load(object), id, x, z); } + for (var staticPlacement : getDimension().getStaticPlacements().getObjects()) { + IrisObjectPlacement i = staticPlacement.placement(); + if (i.getPlace().contains(object)) { + return new PlacedObject(i, getData().getObjectLoader().load(object), id, x, z); + } + } + IrisRegion region = getRegion(x, z); for (IrisObjectPlacement i : region.getObjects()) { diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleStaticComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleStaticComponent.java new file mode 100644 index 000000000..cc0ba6e42 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleStaticComponent.java @@ -0,0 +1,28 @@ +package com.volmit.iris.engine.mantle.components; + +import com.volmit.iris.engine.mantle.EngineMantle; +import com.volmit.iris.engine.mantle.IrisMantleComponent; +import com.volmit.iris.engine.mantle.MantleWriter; +import com.volmit.iris.engine.object.IrisStaticPlacement; +import com.volmit.iris.engine.object.NoiseStyle; +import com.volmit.iris.util.context.ChunkContext; +import com.volmit.iris.util.mantle.MantleFlag; +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.noise.CNG; + +public class MantleStaticComponent extends IrisMantleComponent { + private final CNG cng; + + public MantleStaticComponent(EngineMantle engineMantle) { + super(engineMantle, MantleFlag.STATIC); + cng = NoiseStyle.STATIC.create(new RNG(seed())); + } + + @Override + public void generateLayer(MantleWriter writer, int x, int z, ChunkContext context) { + RNG rng = new RNG(cng.fit(Integer.MIN_VALUE, Integer.MAX_VALUE, x, z)); + for (IrisStaticPlacement placement : getDimension().getStaticPlacements().getAll(x, z)) { + placement.place(writer, rng, getData()); + } + } +} diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java b/core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java index 82ca54137..26d256c88 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java @@ -310,6 +310,8 @@ public class IrisDimension extends IrisRegistrant { @MaxNumber(318) @Desc("The Subterrain Fluid Layer Height") private int caveLavaHeight = 8; + @Desc("Static Placements for objects and structures") + private IrisStaticPlacements staticPlacements = new IrisStaticPlacements(); public int getMaxHeight() { return (int) getDimensionHeight().getMax(); diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisStaticObjectPlacement.java b/core/src/main/java/com/volmit/iris/engine/object/IrisStaticObjectPlacement.java new file mode 100644 index 000000000..8b871de56 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisStaticObjectPlacement.java @@ -0,0 +1,52 @@ +package com.volmit.iris.engine.object; + +import com.volmit.iris.core.loader.IrisData; +import com.volmit.iris.engine.mantle.MantleWriter; +import com.volmit.iris.engine.object.annotations.Desc; +import com.volmit.iris.engine.object.annotations.Required; +import com.volmit.iris.util.data.B; +import com.volmit.iris.util.data.IrisBlockData; +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.matter.MatterStructurePOI; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +@Data +@Desc("Static Object Placement") +@Accessors(chain = true, fluent = true) +@NoArgsConstructor +@AllArgsConstructor +public class IrisStaticObjectPlacement implements IrisStaticPlacement { + @Required + @Desc("The X coordinate to spawn the object at") + private int x = 0; + @Required + @Desc("The Y coordinate to spawn the object at\nuse a value <0 to allow the placement modes to function") + private int y = 0; + @Required + @Desc("The Z coordinate to spawn the object at") + private int z = 0; + @Required + @Desc("The object placement to use") + private IrisObjectPlacement placement; + + @Override + public void place(MantleWriter writer, RNG rng, IrisData irisData) { + IrisObject v = placement.getScale().get(rng, placement.getObject(() -> irisData, rng)); + if (v == null) return; + + v.place(x, y, z, writer, placement, rng, irisData); + int id = rng.i(0, Integer.MAX_VALUE); + v.place(x, y, z, writer, placement, rng, (b, data) -> { + writer.setData(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id); + if (placement.isDolphinTarget() && placement.isUnderwater() && B.isStorageChest(data)) { + writer.setData(b.getX(), b.getY(), b.getZ(), MatterStructurePOI.BURIED_TREASURE); + } + if (data instanceof IrisBlockData d) { + writer.setData(b.getX(), b.getY(), b.getZ(), d.getCustom()); + } + }, null, irisData); + } +} diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisStaticPlacement.java b/core/src/main/java/com/volmit/iris/engine/object/IrisStaticPlacement.java new file mode 100644 index 000000000..db6459453 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisStaticPlacement.java @@ -0,0 +1,19 @@ +package com.volmit.iris.engine.object; + +import com.volmit.iris.core.loader.IrisData; +import com.volmit.iris.engine.mantle.MantleWriter; +import com.volmit.iris.util.documentation.ChunkCoordinates; +import com.volmit.iris.util.math.RNG; + +public interface IrisStaticPlacement { + int x(); + int y(); + int z(); + + @ChunkCoordinates + default boolean shouldPlace(int chunkX, int chunkZ) { + return x() >> 4 == chunkX && z() >> 4 == chunkZ; + } + + void place(MantleWriter writer, RNG rng, IrisData data); +} diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisStaticPlacements.java b/core/src/main/java/com/volmit/iris/engine/object/IrisStaticPlacements.java new file mode 100644 index 000000000..42f0e8930 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisStaticPlacements.java @@ -0,0 +1,49 @@ +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.util.collection.KList; +import com.volmit.iris.util.documentation.ChunkCoordinates; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Accessors(chain = true) +@NoArgsConstructor +@AllArgsConstructor +@Desc("Static Placements") +@Data +public class IrisStaticPlacements { + @Desc("List of static jigsaw structures") + @ArrayType(type = IrisStaticStructurePlacement.class) + private KList structures = new KList<>(); + + @Desc("List of static objects") + @ArrayType(type = IrisStaticObjectPlacement.class) + private KList objects = new KList<>(); + + @ChunkCoordinates + public KList getStructures(int chunkX, int chunkZ) { + return filter(structures.stream(), chunkX, chunkZ); + } + + @ChunkCoordinates + public KList getObjects(int chunkX, int chunkZ) { + return filter(objects.stream(), chunkX, chunkZ); + } + + @ChunkCoordinates + public KList getAll(int chunkX, int chunkZ) { + return filter(Stream.concat(structures.stream(), objects.stream()), chunkX, chunkZ); + } + + private KList filter(Stream stream, int chunkX, int chunkZ) { + return stream.filter(p -> p.shouldPlace(chunkX, chunkZ)) + .collect(Collectors.toCollection(KList::new)); + } +} diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisStaticStructurePlacement.java b/core/src/main/java/com/volmit/iris/engine/object/IrisStaticStructurePlacement.java new file mode 100644 index 000000000..76234fa0e --- /dev/null +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisStaticStructurePlacement.java @@ -0,0 +1,65 @@ +package com.volmit.iris.engine.object; + +import com.volmit.iris.Iris; +import com.volmit.iris.core.loader.IrisData; +import com.volmit.iris.engine.jigsaw.PlannedStructure; +import com.volmit.iris.engine.mantle.MantleWriter; +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.util.collection.KList; +import com.volmit.iris.util.math.RNG; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +@Data +@Desc("Static Jigsaw Structure Placement") +@Accessors(chain = true, fluent = true) +@NoArgsConstructor +@AllArgsConstructor +public class IrisStaticStructurePlacement implements IrisStaticPlacement { + @Required + @Desc("The X coordinate to spawn the structure at") + private int x = 0; + @Required + @Desc("The Y coordinate to spawn the structure at") + private int y = 0; + @Required + @Desc("The Z coordinate to spawn the structure at") + private int z = 0; + @Required + @ArrayType(min = 1, type = String.class) + @RegistryListResource(IrisJigsawStructure.class) + @Desc("The structures to place") + private KList structures; + + public int maxDimension(IrisData data) { + return data.getJigsawStructureLoader().loadAll(structures) + .stream() + .mapToInt(IrisJigsawStructure::getMaxDimension) + .max() + .orElse(0); + } + + @Override + public void place(MantleWriter writer, RNG rng, IrisData data) { + IrisJigsawStructure jigsaw = null; + while (jigsaw == null && !structures.isEmpty()) { + String loadKey = structures.popRandom(rng); + jigsaw = data.getJigsawStructureLoader().load(loadKey); + + if (jigsaw == null) + Iris.error("Jigsaw structure not found " + loadKey); + } + if (jigsaw == null) { + Iris.error("No jigsaw structure found for " + structures); + return; + } + + new PlannedStructure(jigsaw, new IrisPosition(x, y, z), rng, false) + .place(writer, writer.getMantle(), writer.getEngine()); + } +} diff --git a/core/src/main/java/com/volmit/iris/util/collection/KList.java b/core/src/main/java/com/volmit/iris/util/collection/KList.java index 9e00ea20d..877ef6bab 100644 --- a/core/src/main/java/com/volmit/iris/util/collection/KList.java +++ b/core/src/main/java/com/volmit/iris/util/collection/KList.java @@ -487,7 +487,7 @@ public class KList extends ArrayList implements List { return pop(); } - return remove(rng.i(0, last())); + return remove(rng.i(0, size())); } public KList sub(int f, int t) { diff --git a/core/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java b/core/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java index fc2b9762f..53ee595c0 100644 --- a/core/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java +++ b/core/src/main/java/com/volmit/iris/util/mantle/MantleFlag.java @@ -35,7 +35,8 @@ public enum MantleFlag { ETCHED, TILE, CUSTOM, - DISCOVERED; + DISCOVERED, + STATIC; static StateList getStateList() { return new StateList(MantleFlag.values());