diff --git a/src/main/java/com/volmit/iris/object/IrisObject.java b/src/main/java/com/volmit/iris/object/IrisObject.java index d35c4b417..8b330a3c7 100644 --- a/src/main/java/com/volmit/iris/object/IrisObject.java +++ b/src/main/java/com/volmit/iris/object/IrisObject.java @@ -134,7 +134,113 @@ public class IrisObject extends IrisRegistrant int spinz = rng.imax() / 1000; int rty = config.getRotation().rotate(new BlockVector(0, getCenter().getBlockY(), 0), spinx, spiny, spinz).getBlockY(); int ty = config.getTranslate().translate(new BlockVector(0, getCenter().getBlockY(), 0), config.getRotation(), spinx, spiny, spinz).getBlockY(); - int y = yv < 0 ? placer.getHighest(x, z, config.isUnderwater()) + rty : yv; + int y = -1; + KMap paintmap = null; + + if(yv < 0) + { + if(config.getMode().equals(ObjectPlaceMode.CENTER_HEIGHT_RIGID)) + { + if(config.isTranslateCenter()) + { + y = placer.getHighest(x, z, config.isUnderwater()) + rty; + } + + else + { + y = placer.getHighest(x, z, config.isUnderwater()) + rty; + } + } + + if(config.getMode().equals(ObjectPlaceMode.MAX_HEIGHT_RIGID_ACCURATE)) + { + 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(); + + for(int i = x - (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i <= x + (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i++) + { + for(int j = z - (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j <= z + (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j++) + { + int h = placer.getHighest(i, j, config.isUnderwater()) + rty; + + if(h > y) + { + y = h; + } + } + } + } + + else if(config.getMode().equals(ObjectPlaceMode.MAX_HEIGHT_RIGID)) + { + 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(); + + for(int i = x - (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i <= x + (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i += (rotatedDimensions.getBlockX() / 2)) + { + for(int j = z - (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j <= z + (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j += (rotatedDimensions.getBlockZ() / 2)) + { + int h = placer.getHighest(i, j, config.isUnderwater()) + rty; + + if(h > y) + { + y = h; + } + } + } + } + + else if(config.getMode().equals(ObjectPlaceMode.MIN_HEIGHT_RIGID_ACCURATE)) + { + y = 257; + 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(); + + for(int i = x - (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i <= x + (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i++) + { + for(int j = z - (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j <= z + (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j++) + { + int h = placer.getHighest(i, j, config.isUnderwater()) + rty; + + if(h < y) + { + y = h; + } + } + } + } + + else if(config.getMode().equals(ObjectPlaceMode.MIN_HEIGHT_RIGID)) + { + y = 257; + 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(); + + for(int i = x - (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i <= x + (rotatedDimensions.getBlockX() / 2) + offset.getBlockX(); i += (rotatedDimensions.getBlockX() / 2)) + { + for(int j = z - (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j <= z + (rotatedDimensions.getBlockZ() / 2) + offset.getBlockZ(); j += (rotatedDimensions.getBlockZ() / 2)) + { + int h = placer.getHighest(i, j, config.isUnderwater()) + rty; + + if(h < y) + { + y = h; + } + } + } + } + + else if(config.getMode().equals(ObjectPlaceMode.PAINT) || config.getMode().equals(ObjectPlaceMode.STILT)) + { + y = placer.getHighest(x, z, config.isUnderwater()) + rty; + paintmap = new KMap<>(); + } + } + + else + { + y = yv; + } if(yv >= 0 && config.isBottom()) { @@ -203,6 +309,19 @@ public class IrisObject extends IrisRegistrant int yy = y + (int) Math.round(i.getY()); int zz = z + (int) Math.round(i.getZ()); + if(config.getMode().equals(ObjectPlaceMode.PAINT)) + { + yy = (int) Math.round(i.getY()) + Math.floorDiv(h, 2) + paintmap.compute(new ChunkPosition(xx, zz), (k, v) -> + { + if(k == null || v == null) + { + return placer.getHighest(xx, zz, config.isUnderwater()); + } + + return v; + }); + } + if(heightmap != null) { ChunkPosition pos = new ChunkPosition(xx, zz); diff --git a/src/main/java/com/volmit/iris/object/IrisObjectPlacement.java b/src/main/java/com/volmit/iris/object/IrisObjectPlacement.java index e5948c3bc..7b20b070f 100644 --- a/src/main/java/com/volmit/iris/object/IrisObjectPlacement.java +++ b/src/main/java/com/volmit/iris/object/IrisObjectPlacement.java @@ -25,6 +25,14 @@ public class IrisObjectPlacement @Desc("List of objects to place") private KList place = new KList<>(); + @DontObfuscate + @Desc("If the place mode is set to CENTER_HEIGHT_RIGID and you have an X/Z translation, Turning on translate center will also translate the center height check.") + private boolean translateCenter = false; + + @DontObfuscate + @Desc("The placement mode") + private ObjectPlaceMode mode = ObjectPlaceMode.CENTER_HEIGHT_RIGID; + @ArrayType(min = 1, type = IrisObjectReplace.class) @DontObfuscate @Desc("Find and replace blocks") @@ -77,7 +85,7 @@ public class IrisObjectPlacement private boolean meld = false; @DontObfuscate - @Desc("If set to true, this object will place from the ground up instead of height checks when not y locked to the surface.") + @Desc("If set to true, this object will place from the ground up instead of height checks when not y locked to the surface. This is not compatable with X and Z axis rotations (it may look off)") private boolean bottom = false; @DontObfuscate diff --git a/src/main/java/com/volmit/iris/object/IrisStructure.java b/src/main/java/com/volmit/iris/object/IrisStructure.java index 8a77cd011..91e568061 100644 --- a/src/main/java/com/volmit/iris/object/IrisStructure.java +++ b/src/main/java/com/volmit/iris/object/IrisStructure.java @@ -19,13 +19,18 @@ import lombok.EqualsAndHashCode; @Desc("Represents a structure in iris.") @Data @EqualsAndHashCode(callSuper = false) -public class IrisStructure extends IrisRegistrant { +public class IrisStructure extends IrisRegistrant +{ @MinNumber(2) @Required @DontObfuscate @Desc("This is the human readable name for this structure. Such as Red Dungeon or Tropical Village.") private String name = "A Structure Type"; + @DontObfuscate + @Desc("Wall style noise") + private IrisGeneratorStyle wallStyle = NoiseStyle.STATIC.style(); + @Required @MinNumber(3) @MaxNumber(64) @@ -65,37 +70,48 @@ public class IrisStructure extends IrisRegistrant { private transient AtomicCache wallGenerator = new AtomicCache<>(); - public TileResult getTile(RNG rng, double x, double y, double z) { + public TileResult getTile(RNG rng, double x, double y, double z) + { KList walls = new KList<>(); boolean floor = isWall(rng, x, y, z, StructureTileFace.DOWN); boolean ceiling = isWall(rng, x, y, z, StructureTileFace.UP); - if (isWall(rng, x, y, z, StructureTileFace.NORTH)) { + if(isWall(rng, x, y, z, StructureTileFace.NORTH)) + { walls.add(StructureTileFace.NORTH); } - if (isWall(rng, x, y, z, StructureTileFace.SOUTH)) { + if(isWall(rng, x, y, z, StructureTileFace.SOUTH)) + { walls.add(StructureTileFace.SOUTH); } - if (isWall(rng, x, y, z, StructureTileFace.EAST)) { + if(isWall(rng, x, y, z, StructureTileFace.EAST)) + { walls.add(StructureTileFace.EAST); } - if (isWall(rng, x, y, z, StructureTileFace.WEST)) { + if(isWall(rng, x, y, z, StructureTileFace.WEST)) + { walls.add(StructureTileFace.WEST); } + int faces = walls.size() + (floor ? 1 : 0) + (ceiling ? +1 : 0); + int openings = 6 - faces; int rt = 0; - for (int cx = 0; cx < 4; cx++) { - for (IrisStructureTile i : tiles) { - if (i.likeAGlove(floor, ceiling, walls)) { + for(int cx = 0; cx < 4; cx++) + { + for(IrisStructureTile i : tiles) + { + if(i.likeAGlove(floor, ceiling, walls, faces, openings)) + { return new TileResult(i, rt); } } - if (cx < 3) { + if(cx < 3) + { rotate(walls); rt += 90; } @@ -104,14 +120,18 @@ public class IrisStructure extends IrisRegistrant { return null; } - public void rotate(KList faces) { - for (int i = 0; i < faces.size(); i++) { + public void rotate(KList faces) + { + for(int i = 0; i < faces.size(); i++) + { faces.set(i, faces.get(i).rotate90CW()); } } - public boolean isWall(RNG rng, double x, double y, double z, StructureTileFace face) { - if ((face == StructureTileFace.DOWN || face == StructureTileFace.UP) && maxLayers == 1) { + public boolean isWall(RNG rng, double x, double y, double z, StructureTileFace face) + { + if((face == StructureTileFace.DOWN || face == StructureTileFace.UP) && maxLayers == 1) + { return true; } @@ -119,25 +139,30 @@ public class IrisStructure extends IrisRegistrant { return (getWallGenerator(rng).fitDouble(0, 1, p.getX(), p.getY(), p.getZ()) < getWallChance()); } - public int getTileHorizon(double v) { + public int getTileHorizon(double v) + { return (int) Math.floor(v / gridSize); } - public BlockPosition asTileHorizon(BlockPosition b, StructureTileFace face) { - b.setX((int) (Math.floor((b.getX() * 2) / gridSize) + face.x())); - b.setY((int) (Math.floor((b.getY() * 2) / gridHeight) + face.y())); - b.setZ((int) (Math.floor((b.getZ() * 2) / gridSize) + face.z())); + public BlockPosition asTileHorizon(BlockPosition b, StructureTileFace face) + { + b.setX((int) (Math.floor((b.getX() * 2) / (gridSize)) + face.x())); + b.setY((int) (Math.floor((b.getY() * 2) / (gridHeight)) + face.y())); + b.setZ((int) (Math.floor((b.getZ() * 2) / (gridSize)) + face.z())); return b; } - public CNG getWallGenerator(RNG rng) { - return wallGenerator.aquire(() -> { + public CNG getWallGenerator(RNG rng) + { + return wallGenerator.aquire(() -> + { RNG rngx = rng.nextParallelRNG((int) (name.hashCode() + gridHeight - gridSize + maxLayers + tiles.size())); - return CNG.signature(rngx).scale(0.8); + return wallStyle.create(rngx).scale(0.8); }); } - public IrisStructure() { + public IrisStructure() + { } } diff --git a/src/main/java/com/volmit/iris/object/IrisStructurePlacement.java b/src/main/java/com/volmit/iris/object/IrisStructurePlacement.java index 79904c127..dfaa6f00d 100644 --- a/src/main/java/com/volmit/iris/object/IrisStructurePlacement.java +++ b/src/main/java/com/volmit/iris/object/IrisStructurePlacement.java @@ -5,8 +5,10 @@ import com.volmit.iris.gen.ContextualChunkGenerator; import com.volmit.iris.gen.ParallaxChunkGenerator; import com.volmit.iris.gen.atomics.AtomicCache; import com.volmit.iris.noise.CellGenerator; +import com.volmit.iris.util.ChunkPosition; import com.volmit.iris.util.Desc; import com.volmit.iris.util.DontObfuscate; +import com.volmit.iris.util.KSet; import com.volmit.iris.util.MaxNumber; import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.RNG; @@ -68,14 +70,34 @@ public class IrisStructurePlacement try { RNG rng = g.getMasterRandom().nextParallelRNG(-88738456); - RNG rnp = rng.nextParallelRNG(cx - (cz * cz)); + RNG rnp = rng.nextParallelRNG(cx - (cz * cz << 3)); int s = gridSize(g) - (getStructure(g).isMergeEdges() ? 1 : 0); int sh = gridHeight(g) - (getStructure(g).isMergeEdges() ? 1 : 0); + KSet m = new KSet<>(); - for(int i = cx << 4; i < (cx << 4) + 15; i += Math.max(s, 1)) + for(int i = cx << 4; i <= (cx << 4) + 15; i += 1) { - for(int j = cz << 4; j < (cz << 4) + 15; j += Math.max(s, 1)) + if(Math.floorDiv(i, s) * s >> 4 < cx) { + continue; + } + + for(int j = cz << 4; j <= (cz << 4) + 15; j += 1) + { + if(Math.floorDiv(j, s) * s >> 4 < cz) + { + continue; + } + + ChunkPosition p = new ChunkPosition(Math.floorDiv(i, s) * s, Math.floorDiv(j, s) * s); + + if(m.contains(p)) + { + continue; + } + + m.add(p); + if(getStructure(g).getMaxLayers() <= 1) { placeLayer(g, rng, rnp, i, 0, j, s, sh); @@ -104,7 +126,7 @@ public class IrisStructurePlacement } int h = (height == -1 ? 0 : height) + (Math.floorDiv(k, sh) * sh); - TileResult t = getStructure(g).getTile(rng, i, h, j); + TileResult t = getStructure(g).getTile(rng, Math.floorDiv(i, s) * s, h, Math.floorDiv(j, s) * s); if(t != null) { @@ -120,7 +142,8 @@ public class IrisStructurePlacement private IrisObjectPlacement getConfig() { - return config.aquire(() -> { + return config.aquire(() -> + { IrisObjectPlacement p = new IrisObjectPlacement(); p.setWaterloggable(false); return p; diff --git a/src/main/java/com/volmit/iris/object/IrisStructureTile.java b/src/main/java/com/volmit/iris/object/IrisStructureTile.java index d9afd5527..d297dc39a 100644 --- a/src/main/java/com/volmit/iris/object/IrisStructureTile.java +++ b/src/main/java/com/volmit/iris/object/IrisStructureTile.java @@ -1,5 +1,6 @@ package com.volmit.iris.object; +import com.volmit.iris.gen.atomics.AtomicCache; import com.volmit.iris.util.ArrayType; import com.volmit.iris.util.Desc; import com.volmit.iris.util.DontObfuscate; @@ -53,6 +54,9 @@ public class IrisStructureTile @Desc("List of objects to place centered in this tile") private KList objects = new KList<>(); + private AtomicCache minFaces = new AtomicCache<>(); + private AtomicCache maxFaces = new AtomicCache<>(); + public IrisStructureTile() { @@ -63,7 +67,7 @@ public class IrisStructureTile return (ceiling.required() ? "C" : "") + (floor.required() ? "F" : "") + "| " + (north.required() ? "X" : "-") + (south.required() ? "X" : "-") + (east.required() ? "X" : "-") + (west.required() ? "X" : "-") + " |"; } - public boolean likeAGlove(boolean floor, boolean ceiling, KList walls) + public boolean likeAGlove(boolean floor, boolean ceiling, KList walls, int faces, int openings) { //@builder @@ -77,17 +81,37 @@ public class IrisStructureTile return false; } - if(!fitsWalls(walls)) + if(!fitsWalls(walls, faces, openings)) { return false; } //@done - return true; + return faces >= minFaces.aquire(() -> + { + int m = 0; + m += this.ceiling.required() ? 1 : 0; + m += this.floor.required() ? 1 : 0; + m += this.north.required() ? 1 : 0; + m += this.south.required() ? 1 : 0; + m += this.east.required() ? 1 : 0; + m += this.west.required() ? 1 : 0; + return m; + }) && faces <= maxFaces.aquire(() -> + { + int m = 0; + m += this.ceiling.supported() ? 1 : 0; + m += this.floor.supported() ? 1 : 0; + m += this.north.supported() ? 1 : 0; + m += this.south.supported() ? 1 : 0; + m += this.east.supported() ? 1 : 0; + m += this.west.supported() ? 1 : 0; + return m; + }); } - private boolean fitsWalls(KList walls) + private boolean fitsWalls(KList walls, int faces, int openings) { //@builder if((getNorth().required() && !walls.contains(StructureTileFace.NORTH)) diff --git a/src/main/java/com/volmit/iris/object/ObjectPlaceMode.java b/src/main/java/com/volmit/iris/object/ObjectPlaceMode.java new file mode 100644 index 000000000..6031bb74d --- /dev/null +++ b/src/main/java/com/volmit/iris/object/ObjectPlaceMode.java @@ -0,0 +1,27 @@ +package com.volmit.iris.object; + +import com.volmit.iris.util.DontObfuscate; + +public enum ObjectPlaceMode +{ + @DontObfuscate + CENTER_HEIGHT_RIGID, + + @DontObfuscate + MAX_HEIGHT_RIGID_ACCURATE, + + @DontObfuscate + MAX_HEIGHT_RIGID, + + @DontObfuscate + MIN_HEIGHT_RIGID_ACCURATE, + + @DontObfuscate + MIN_HEIGHT_RIGID, + + @DontObfuscate + PAINT, + + @DontObfuscate + STILT; +} diff --git a/src/main/java/com/volmit/iris/object/TileResult.java b/src/main/java/com/volmit/iris/object/TileResult.java index c00b0c121..adbe1a5ad 100644 --- a/src/main/java/com/volmit/iris/object/TileResult.java +++ b/src/main/java/com/volmit/iris/object/TileResult.java @@ -16,6 +16,7 @@ public class TileResult rt.setYAxis(new IrisAxisRotationClamp(rot != 0, rot, rot, 0)); p.setRotation(rt); p.setBottom(true); + p.setMode(ObjectPlaceMode.PAINT); placement = p; } }