Smart Bore & Islands

This commit is contained in:
Daniel Mills 2020-09-04 01:15:38 -04:00
parent b201cf1990
commit d144b9ba0b
11 changed files with 253 additions and 57 deletions

View File

@ -376,6 +376,12 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
return s; return s;
} }
@Override
public boolean isDebugSmartBore()
{
return getDimension().isDebugSmartBore();
}
@Override @Override
public boolean isPreventingDecay() public boolean isPreventingDecay()
{ {

View File

@ -588,6 +588,24 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
current = glBiome.generateData(InferredType.SHORE, wx, wz, x, z, region); current = glBiome.generateData(InferredType.SHORE, wx, wz, x, z, region);
} }
// Impure Remove rivers, lakes & sea from land
if(current.isAquatic() && land)
{
current = glBiome.generatePureData(InferredType.LAND, wx, wz, x, z, region);
}
// Impure Remove land from underwater
if(current.isLand() && sea)
{
current = glBiome.generatePureData(aquaticType, wx, wz, x, z, region);
}
// Impure Add shores to land
if(shore)
{
current = glBiome.generatePureData(InferredType.SHORE, wx, wz, x, z, region);
}
return current; return current;
} }

View File

@ -25,11 +25,11 @@ public class BiomeDataProvider
public IrisBiome generatePureData(ContextualChunkGenerator g, double bx, double bz, int rawX, int rawZ, IrisRegion regionData) public IrisBiome generatePureData(ContextualChunkGenerator g, double bx, double bz, int rawX, int rawZ, IrisRegion regionData)
{ {
return layer.generateBiomeData(bx, bz, regionData, getGenerator(), regionData.getBiomes(g, getType()), getType(), rawX, rawZ); return layer.generateBiomeData(bx, bz, regionData, getGenerator(), regionData.getBiomes(g, getType()), getType(), rawX, rawZ, true);
} }
public IrisBiome generateData(ContextualChunkGenerator g, double bx, double bz, int rawX, int rawZ, IrisRegion regionData) public IrisBiome generateData(ContextualChunkGenerator g, double bx, double bz, int rawX, int rawZ, IrisRegion regionData)
{ {
return layer.generateImpureData(rawX, rawZ, getType(), regionData, generatePureData(g, bx, bz, rawX, rawZ, regionData)); return layer.generateBiomeData(bx, bz, regionData, getGenerator(), regionData.getBiomes(g, getType()), getType(), rawX, rawZ, false);
} }
} }

View File

@ -72,6 +72,11 @@ public class GenLayerBiome extends GenLayer
return getProvider(type).generateData(iris, bx, bz, rawX, rawZ, regionData); return getProvider(type).generateData(iris, bx, bz, rawX, rawZ, regionData);
} }
public IrisBiome generatePureData(InferredType type, double bx, double bz, int rawX, int rawZ, IrisRegion regionData)
{
return getProvider(type).generatePureData(iris, bx, bz, rawX, rawZ, regionData);
}
public BiomeDataProvider getProvider(InferredType type) public BiomeDataProvider getProvider(InferredType type)
{ {
if(type.equals(InferredType.SEA)) if(type.equals(InferredType.SEA))
@ -151,19 +156,27 @@ public class GenLayerBiome extends GenLayer
public IrisBiome generateBiomeData(double bx, double bz, IrisRegion regionData, CNG cell, KList<IrisBiome> biomes, InferredType inferredType, int rx, int rz) public IrisBiome generateBiomeData(double bx, double bz, IrisRegion regionData, CNG cell, KList<IrisBiome> biomes, InferredType inferredType, int rx, int rz)
{ {
for(IrisRegionRidge i : regionData.getRidgeBiomes()) return generateBiomeData(bx, bz, regionData, cell, biomes, inferredType, rx, rz, false);
{ }
if(i.getType().equals(inferredType) && i.isRidge(rng, rx, rz))
{
return iris.loadBiome(i.getBiome()).infer(i.getAs(), inferredType);
}
}
for(IrisRegionSpot i : regionData.getSpotBiomes()) public IrisBiome generateBiomeData(double bx, double bz, IrisRegion regionData, CNG cell, KList<IrisBiome> biomes, InferredType inferredType, int rx, int rz, boolean pure)
{
if(!pure)
{ {
if(i.getType().equals(inferredType) && i.isSpot(rng, rx, rz)) for(IrisRegionRidge i : regionData.getRidgeBiomes())
{ {
return iris.loadBiome(i.getBiome()).infer(i.getAs(), inferredType); if(i.getType().equals(inferredType) && i.isRidge(rng, rx, rz))
{
return iris.loadBiome(i.getBiome()).infer(i.getAs(), inferredType);
}
}
for(IrisRegionSpot i : regionData.getSpotBiomes())
{
if(i.getType().equals(inferredType) && i.isSpot(rng, rx, rz))
{
return iris.loadBiome(i.getBiome()).infer(i.getAs(), inferredType);
}
} }
} }

View File

@ -130,6 +130,10 @@ public class IrisDimension extends IrisRegistrant
@Desc("Generate caves or not.") @Desc("Generate caves or not.")
private boolean caves = true; private boolean caves = true;
@DontObfuscate
@Desc("Instead of filling objects with air, fills them with cobweb so you can see them")
private boolean debugSmartBore = false;
@DontObfuscate @DontObfuscate
@Desc("Carve terrain or not") @Desc("Carve terrain or not")
private boolean carving = true; private boolean carving = true;

View File

@ -17,10 +17,12 @@ import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.Leaves; import org.bukkit.block.data.type.Leaves;
import org.bukkit.util.BlockVector; import org.bukkit.util.BlockVector;
import com.volmit.iris.Iris;
import com.volmit.iris.util.B; import com.volmit.iris.util.B;
import com.volmit.iris.util.BlockPosition; import com.volmit.iris.util.BlockPosition;
import com.volmit.iris.util.ChunkPosition; import com.volmit.iris.util.ChunkPosition;
import com.volmit.iris.util.IObjectPlacer; import com.volmit.iris.util.IObjectPlacer;
import com.volmit.iris.util.IrisLock;
import com.volmit.iris.util.KMap; import com.volmit.iris.util.KMap;
import com.volmit.iris.util.RNG; import com.volmit.iris.util.RNG;
@ -32,6 +34,8 @@ import lombok.EqualsAndHashCode;
public class IrisObject extends IrisRegistrant public class IrisObject extends IrisRegistrant
{ {
private static final BlockData AIR = B.getBlockData("CAVE_AIR"); private static final BlockData AIR = B.getBlockData("CAVE_AIR");
private static final BlockData VAIR = B.getBlockData("VOID_AIR");
private static final BlockData VAIR_DEBUG = B.getBlockData("COBWEB");
private static final BlockData[] SNOW_LAYERS = new BlockData[] {B.getBlockData("minecraft:snow[layers=1]"), B.getBlockData("minecraft:snow[layers=2]"), B.getBlockData("minecraft:snow[layers=3]"), B.getBlockData("minecraft:snow[layers=4]"), B.getBlockData("minecraft:snow[layers=5]"), B.getBlockData("minecraft:snow[layers=6]"), B.getBlockData("minecraft:snow[layers=7]"), B.getBlockData("minecraft:snow[layers=8]")}; private static final BlockData[] SNOW_LAYERS = new BlockData[] {B.getBlockData("minecraft:snow[layers=1]"), B.getBlockData("minecraft:snow[layers=2]"), B.getBlockData("minecraft:snow[layers=3]"), B.getBlockData("minecraft:snow[layers=4]"), B.getBlockData("minecraft:snow[layers=5]"), B.getBlockData("minecraft:snow[layers=6]"), B.getBlockData("minecraft:snow[layers=7]"), B.getBlockData("minecraft:snow[layers=8]")};
public static boolean shitty = false; public static boolean shitty = false;
private KMap<BlockVector, BlockData> blocks; private KMap<BlockVector, BlockData> blocks;
@ -39,6 +43,143 @@ public class IrisObject extends IrisRegistrant
private int d; private int d;
private int h; private int h;
private transient BlockVector center; private transient BlockVector center;
private transient volatile boolean smartBored = false;
private transient IrisLock lock = new IrisLock("Preloadcache");
public void ensureSmartBored(boolean debug)
{
if(smartBored)
{
return;
}
lock.lock();
int applied = 0;
if(blocks.isEmpty())
{
lock.unlock();
Iris.warn("Cannot Smart Bore " + getLoadKey() + " because it has 0 blocks in it.");
smartBored = true;
return;
}
BlockVector max = new BlockVector(Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE);
BlockVector min = new BlockVector(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
for(BlockVector i : blocks.k())
{
max.setX(i.getX() > max.getX() ? i.getX() : max.getX());
min.setX(i.getX() < min.getX() ? i.getX() : min.getX());
max.setY(i.getY() > max.getY() ? i.getY() : max.getY());
min.setY(i.getY() < min.getY() ? i.getY() : min.getY());
max.setZ(i.getZ() > max.getZ() ? i.getZ() : max.getZ());
min.setZ(i.getZ() < min.getZ() ? i.getZ() : min.getZ());
}
// Smash X
for(int rayY = min.getBlockY(); rayY <= max.getBlockY(); rayY++)
{
for(int rayZ = min.getBlockZ(); rayZ <= max.getBlockZ(); rayZ++)
{
int start = Integer.MAX_VALUE;
int end = Integer.MIN_VALUE;
for(int ray = min.getBlockX(); ray <= max.getBlockX(); ray++)
{
if(blocks.containsKey(new BlockVector(ray, rayY, rayZ)))
{
start = ray < start ? ray : start;
end = ray > end ? ray : end;
}
}
if(start != Integer.MAX_VALUE && end != Integer.MIN_VALUE)
{
for(int i = start; i <= end; i++)
{
BlockVector v = new BlockVector(i, rayY, rayZ);
if(!blocks.containsKey(v) || B.isAir(blocks.get(v)))
{
blocks.put(v, debug ? VAIR_DEBUG : VAIR);
applied++;
}
}
}
}
}
// Smash Y
for(int rayX = min.getBlockX(); rayX <= max.getBlockX(); rayX++)
{
for(int rayZ = min.getBlockZ(); rayZ <= max.getBlockZ(); rayZ++)
{
int start = Integer.MAX_VALUE;
int end = Integer.MIN_VALUE;
for(int ray = min.getBlockY(); ray <= max.getBlockY(); ray++)
{
if(blocks.containsKey(new BlockVector(rayX, ray, rayZ)))
{
start = ray < start ? ray : start;
end = ray > end ? ray : end;
}
}
if(start != Integer.MAX_VALUE && end != Integer.MIN_VALUE)
{
for(int i = start; i <= end; i++)
{
BlockVector v = new BlockVector(rayX, i, rayZ);
if(!blocks.containsKey(v) || B.isAir(blocks.get(v)))
{
blocks.put(v, debug ? VAIR_DEBUG : VAIR);
applied++;
}
}
}
}
}
// Smash Z
for(int rayX = min.getBlockX(); rayX <= max.getBlockX(); rayX++)
{
for(int rayY = min.getBlockY(); rayY <= max.getBlockY(); rayY++)
{
int start = Integer.MAX_VALUE;
int end = Integer.MIN_VALUE;
for(int ray = min.getBlockZ(); ray <= max.getBlockZ(); ray++)
{
if(blocks.containsKey(new BlockVector(rayX, rayY, ray)))
{
start = ray < start ? ray : start;
end = ray > end ? ray : end;
}
}
if(start != Integer.MAX_VALUE && end != Integer.MIN_VALUE)
{
for(int i = start; i <= end; i++)
{
BlockVector v = new BlockVector(rayX, rayY, i);
if(!blocks.containsKey(v) || B.isAir(blocks.get(v)))
{
blocks.put(v, debug ? VAIR_DEBUG : VAIR);
applied++;
}
}
}
}
}
Iris.verbose("- Applied Smart Bore to " + getLoadKey() + " Filled with " + applied + " VOID_AIR blocks.");
smartBored = true;
lock.unlock();
}
public IrisObject copy() public IrisObject copy()
{ {
@ -190,10 +331,13 @@ public class IrisObject extends IrisRegistrant
public int place(int x, int yv, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng, Consumer<BlockPosition> listener) public int place(int x, int yv, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng, Consumer<BlockPosition> listener)
{ {
if(config.isSmartBore())
{
ensureSmartBored(placer.isDebugSmartBore());
}
boolean warped = !config.getWarp().isFlat(); boolean warped = !config.getWarp().isFlat();
boolean stilting = (config.getMode().equals(ObjectPlaceMode.STILT) || config.getMode().equals(ObjectPlaceMode.FAST_STILT)); boolean stilting = (config.getMode().equals(ObjectPlaceMode.STILT) || config.getMode().equals(ObjectPlaceMode.FAST_STILT));
KMap<ChunkPosition, Integer> lowmap = stilting ? new KMap<>() : null;
KMap<ChunkPosition, BlockData> lowmapData = stilting ? new KMap<>() : null;
KMap<ChunkPosition, Integer> heightmap = config.getSnow() > 0 ? new KMap<>() : null; KMap<ChunkPosition, Integer> heightmap = config.getSnow() > 0 ? new KMap<>() : null;
int spinx = rng.imax() / 1000; int spinx = rng.imax() / 1000;
int spiny = rng.imax() / 1000; int spiny = rng.imax() / 1000;
@ -201,6 +345,7 @@ public class IrisObject extends IrisRegistrant
int rty = config.getRotation().rotate(new BlockVector(0, getCenter().getBlockY(), 0), spinx, spiny, spinz).getBlockY(); 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 ty = config.getTranslate().translate(new BlockVector(0, getCenter().getBlockY(), 0), config.getRotation(), spinx, spiny, spinz).getBlockY();
int y = -1; int y = -1;
int xx, zz;
if(yv < 0) if(yv < 0)
{ {
@ -344,6 +489,11 @@ public class IrisObject extends IrisRegistrant
i = config.getTranslate().translate(i.clone(), config.getRotation(), spinx, spiny, spinz).clone(); i = config.getTranslate().translate(i.clone(), config.getRotation(), spinx, spiny, spinz).clone();
BlockData data = blocks.get(g).clone(); BlockData data = blocks.get(g).clone();
if(stilting && i.getBlockY() < lowest && !B.isAir(data))
{
lowest = i.getBlockY();
}
if(placer.isPreventingDecay() && data instanceof Leaves && !((Leaves) data).isPersistent()) if(placer.isPreventingDecay() && data instanceof Leaves && !((Leaves) data).isPersistent())
{ {
((Leaves) data).setPersistent(true); ((Leaves) data).setPersistent(true);
@ -361,9 +511,9 @@ public class IrisObject extends IrisRegistrant
} }
data = config.getRotation().rotate(data, spinx, spiny, spinz); data = config.getRotation().rotate(data, spinx, spiny, spinz);
int xx = x + (int) Math.round(i.getX()); xx = x + (int) Math.round(i.getX());
int yy = y + (int) Math.round(i.getY()); int yy = y + (int) Math.round(i.getY());
int zz = z + (int) Math.round(i.getZ()); zz = z + (int) Math.round(i.getZ());
if(warped) if(warped)
{ {
@ -410,59 +560,47 @@ public class IrisObject extends IrisRegistrant
{ {
placer.set(xx, yy, zz, data); placer.set(xx, yy, zz, data);
} }
if(yy < lowest)
{
lowest = yy;
}
if(stilting)
{
BlockData bdata = data;
int yyy = yy;
ChunkPosition ck = new ChunkPosition(xx, zz);
lowmap.compute(ck, (k, v) ->
{
if(v == null)
{
lowmapData.put(ck, bdata);
return yyy;
}
if(v > yyy)
{
lowmapData.put(ck, bdata);
return yyy;
}
return v;
});
}
} }
if(stilting) if(stilting)
{ {
for(ChunkPosition i : lowmap.keySet()) for(BlockVector g : blocks.keySet())
{ {
int yf = lowmap.get(i); BlockVector i = g.clone();
i = config.getRotation().rotate(i.clone(), spinx, spiny, spinz).clone();
i = config.getTranslate().translate(i.clone(), config.getRotation(), spinx, spiny, spinz).clone();
if(yf > lowest) if(i.getBlockY() != lowest)
{ {
continue; continue;
} }
int xf = i.getX(); BlockData d = blocks.get(i);
int zf = i.getZ();
int yg = Math.floorDiv(h, 2) + placer.getHighest(xf, zf, config.isUnderwater());
BlockData d = lowmapData.get(i);
if(d != null && !B.isAir(d)) if(d == null || B.isAir(d))
{ {
for(int j = yf; j > yg - config.getOverStilt(); j--) continue;
{ }
placer.set(xf, j, zf, d);
} xx = x + (int) Math.round(i.getX());
zz = z + (int) Math.round(i.getZ());
if(warped)
{
xx += config.warp(rng, i.getX() + x, i.getY() + y, i.getZ() + z);
zz += config.warp(rng, i.getZ() + z, i.getY() + y, i.getX() + x);
}
int yg = placer.getHighest(xx, zz, config.isUnderwater());
if(yv >= 0 && config.isBottom())
{
y += Math.floorDiv(h, 2);
}
for(int j = lowest + y; j > yg - config.getOverStilt() - 1; j--)
{
placer.set(xx, j, zz, d);
} }
} }
} }

View File

@ -92,6 +92,10 @@ public class IrisObjectPlacement
@Desc("If set to true, objects will place on the terrain height, ignoring the water surface.") @Desc("If set to true, objects will place on the terrain height, ignoring the water surface.")
private boolean underwater = false; private boolean underwater = false;
@DontObfuscate
@Desc("If set to true, Iris will try to fill the insides of 'rooms' and 'pockets' where air should fit based off of raytrace checks. This prevents a village house placing in an area where a tree already exists, and instead replaces the parts of the tree where the interior of the structure is. \n\nThis operation does not affect warmed-up generation speed however it does slow down loading objects.")
private boolean smartBore = false;
@DontObfuscate @DontObfuscate
@Desc("If set to true, Blocks placed underwater that could be waterlogged are waterlogged.") @Desc("If set to true, Blocks placed underwater that could be waterlogged are waterlogged.")
private boolean waterloggable = true; private boolean waterloggable = true;

View File

@ -70,6 +70,10 @@ public class IrisStructureTile
@Desc("List of objects to place centered in this tile") @Desc("List of objects to place centered in this tile")
private KList<String> objects = new KList<>(); private KList<String> objects = new KList<>();
@DontObfuscate
@Desc("If set to true, Iris will try to fill the insides of 'rooms' and 'pockets' where air should fit based off of raytrace checks. This prevents a village house placing in an area where a tree already exists, and instead replaces the parts of the tree where the interior of the structure is. \n\nThis operation does not affect warmed-up generation speed however it does slow down loading objects.")
private boolean smartBore = false;
private transient KMap<Integer, IrisObject> forceObjects = new KMap<>(); private transient KMap<Integer, IrisObject> forceObjects = new KMap<>();
@RegistryListObject @RegistryListObject

View File

@ -20,6 +20,7 @@ public class TileResult
p.setBottom(true); p.setBottom(true);
p.setBore(structure.isBore()); p.setBore(structure.isBore());
p.setClamp(structure.getClamp()); p.setClamp(structure.getClamp());
p.setSmartBore(tile.isSmartBore());
p.setWaterloggable(structure.isUnderwater()); p.setWaterloggable(structure.isUnderwater());
p.setMode(tile.getPlaceMode()); p.setMode(tile.getPlaceMode());
placement = p; placement = p;

View File

@ -19,4 +19,6 @@ public interface IObjectPlacer
public boolean isUnderwater(int x, int z); public boolean isUnderwater(int x, int z);
public int getFluidHeight(); public int getFluidHeight();
public boolean isDebugSmartBore();
} }

View File

@ -1215,4 +1215,10 @@ public class StructureTemplate implements Listener, IObjectPlacer
this.center = center; this.center = center;
updateTiles(focus, null, null); updateTiles(focus, null, null);
} }
@Override
public boolean isDebugSmartBore()
{
return false;
}
} }