Fix tiles & decor

This commit is contained in:
Daniel Mills 2020-08-21 23:50:07 -04:00
parent 83772bed42
commit ccc7a947cd
13 changed files with 266 additions and 228 deletions

View File

@ -87,7 +87,15 @@ public abstract class ParallelChunkGenerator extends DimensionChunkGenerator
accelerant.queue(key, () ->
{
onGenerateColumn(x, z, wx, wz, i, j, sliver, biomeMap);
try
{
onGenerateColumn(x, z, wx, wz, i, j, sliver, biomeMap);
}
catch(Throwable e)
{
fail(e);
}
});
}
}

View File

@ -86,184 +86,175 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
throw new RuntimeException("Invalid OnGenerate call: x:" + x + " z:" + z);
}
try
BlockData block;
int fluidHeight = getDimension().getFluidHeight();
double ox = getModifiedX(rx, rz);
double oz = getModifiedZ(rx, rz);
double wx = getZoomed(ox);
double wz = getZoomed(oz);
int depth = 0;
double noise = getTerrainHeight(rx, rz);
int height = (int) Math.round(noise);
boolean carvable = getDimension().isCarving() && height > getDimension().getCarvingMin();
IrisRegion region = sampleRegion(rx, rz);
BiomeResult biomeResult = sampleTrueBiome(rx, rz, noise);
IrisBiome biome = biomeResult.getBiome();
if(biome == null)
{
throw new RuntimeException("Null Biome!");
}
BlockData block;
int fluidHeight = getDimension().getFluidHeight();
double ox = getModifiedX(rx, rz);
double oz = getModifiedZ(rx, rz);
double wx = getZoomed(ox);
double wz = getZoomed(oz);
int depth = 0;
double noise = getTerrainHeight(rx, rz);
int height = (int) Math.round(noise);
boolean carvable = getDimension().isCarving() && height > getDimension().getCarvingMin();
IrisRegion region = sampleRegion(rx, rz);
BiomeResult biomeResult = sampleTrueBiome(rx, rz, noise);
IrisBiome biome = biomeResult.getBiome();
KList<BlockData> layers = biome.generateLayers(rx, rz, masterRandom, height, height - getFluidHeight());
KList<BlockData> seaLayers = biome.isSea() || biome.isShore() ? biome.generateSeaLayers(rx, rz, masterRandom, fluidHeight - height) : new KList<>();
boolean caverning = false;
KList<Integer> cavernHeights = new KList<>();
int lastCavernHeight = -1;
boolean biomeAssigned = false;
int max = Math.max(height, fluidHeight);
int biomeMax = Math.min(max + 16, 255);
if(biome == null)
// From Height to Bedrock
for(int k = max; k >= 0; k--)
{
boolean cavernSurface = false;
boolean bedrock = k == 0;
boolean underwater = k > height && k <= fluidHeight;
// Bedrock
if(bedrock)
{
throw new RuntimeException("Null Biome!");
if(biomeMap != null)
{
sliver.set(k, biome.getDerivative());
}
sliver.set(k, BEDROCK);
continue;
}
KList<BlockData> layers = biome.generateLayers(rx, rz, masterRandom, height, height - getFluidHeight());
KList<BlockData> seaLayers = biome.isSea() || biome.isShore() ? biome.generateSeaLayers(rx, rz, masterRandom, fluidHeight - height) : new KList<>();
boolean caverning = false;
KList<Integer> cavernHeights = new KList<>();
int lastCavernHeight = -1;
boolean biomeAssigned = false;
int max = Math.max(height, fluidHeight);
int biomeMax = Math.min(max + 16, 255);
// From Height to Bedrock
for(int k = max; k >= 0; k--)
// Carving
if(carvable && glCarve.isCarved(rx, k, rz))
{
boolean cavernSurface = false;
boolean bedrock = k == 0;
boolean underwater = k > height && k <= fluidHeight;
// Bedrock
if(bedrock)
if(biomeMap != null)
{
if(biomeMap != null)
{
sliver.set(k, biome.getDerivative());
}
sliver.set(k, BEDROCK);
continue;
sliver.set(k, biome.getDerivative());
}
// Carving
if(carvable && glCarve.isCarved(rx, k, rz))
sliver.set(k, CAVE_AIR);
caverning = true;
continue;
}
// Carved Surface
else if(carvable && caverning)
{
lastCavernHeight = k;
cavernSurface = true;
cavernHeights.add(k);
caverning = false;
}
// Set Biome
if(!biomeAssigned && biomeMap != null)
{
biomeAssigned = true;
sliver.set(k, biome.getGroundBiome(masterRandom, rz, k, rx));
biomeMap.setBiome(x, z, biome);
for(int kv = max; kv < biomeMax; kv++)
{
if(biomeMap != null)
{
sliver.set(k, biome.getDerivative());
}
sliver.set(k, CAVE_AIR);
caverning = true;
continue;
}
// Carved Surface
else if(carvable && caverning)
{
lastCavernHeight = k;
cavernSurface = true;
cavernHeights.add(k);
caverning = false;
}
// Set Biome
if(!biomeAssigned && biomeMap != null)
{
biomeAssigned = true;
sliver.set(k, biome.getGroundBiome(masterRandom, rz, k, rx));
biomeMap.setBiome(x, z, biome);
for(int kv = max; kv < biomeMax; kv++)
{
Biome skyBiome = biome.getSkyBiome(masterRandom, rz, kv, rx);
sliver.set(kv, skyBiome);
}
}
if(k <= Math.max(height, fluidHeight))
{
sliver.set(k, biome.getGroundBiome(masterRandom, rz, k, rx));
}
// Set Sea Material (water/lava)
if(underwater)
{
block = seaLayers.hasIndex(fluidHeight - k) ? seaLayers.get(depth) : getDimension().getFluid(rockRandom, wx, k, wz);
}
// Set Surface Material for cavern layer surfaces
else if(layers.hasIndex(lastCavernHeight - k))
{
block = layers.get(lastCavernHeight - k);
}
// Set Surface Material for true surface
else
{
block = layers.hasIndex(depth) ? layers.get(depth) : getDimension().getRock(rockRandom, wx, k, wz);
depth++;
}
// Set block and update heightmaps
sliver.set(k, block);
// Decorate underwater surface
if(!cavernSurface && (k == height && B.isSolid(block.getMaterial()) && k < fluidHeight))
{
decorateUnderwater(biome, sliver, wx, k, wz, rx, rz, block);
}
// Decorate Cavern surfaces, but not the true surface
if((carvable && cavernSurface) && !(k == Math.max(height, fluidHeight) && block.getMaterial().isSolid() && k < 255 && k >= fluidHeight))
{
decorateLand(biome, sliver, wx, k, wz, rx, rz, block);
Biome skyBiome = biome.getSkyBiome(masterRandom, rz, kv, rx);
sliver.set(kv, skyBiome);
}
}
// Carve out biomes
KList<CaveResult> caveResults = glCave.genCaves(rx, rz, x, z, sliver);
IrisBiome caveBiome = glBiome.generateData(InferredType.CAVE, wx, wz, rx, rz, region).getBiome();
// Decorate Cave Biome Height Sections
if(caveBiome != null)
if(k <= Math.max(height, fluidHeight))
{
for(CaveResult i : caveResults)
{
for(int j = i.getFloor(); j <= i.getCeiling(); j++)
{
sliver.set(j, caveBiome);
sliver.set(j, caveBiome.getGroundBiome(masterRandom, rz, j, rx));
}
KList<BlockData> floor = caveBiome.generateLayers(wx, wz, rockRandom, i.getFloor() - 2, i.getFloor() - 2);
KList<BlockData> ceiling = caveBiome.generateLayers(wx + 256, wz + 256, rockRandom, height - i.getCeiling() - 2, height - i.getCeiling() - 2);
BlockData blockc = null;
for(int j = 0; j < floor.size(); j++)
{
if(j == 0)
{
blockc = floor.get(j);
}
sliver.set(i.getFloor() - j, floor.get(j));
}
for(int j = ceiling.size() - 1; j > 0; j--)
{
sliver.set(i.getCeiling() + j, ceiling.get(j));
}
if(blockc != null && !sliver.isSolid(i.getFloor() + 1))
{
decorateCave(caveBiome, sliver, wx, i.getFloor(), wz, rx, rz, blockc);
}
}
sliver.set(k, biome.getGroundBiome(masterRandom, rz, k, rx));
}
block = sliver.get(Math.max(height, fluidHeight));
// Decorate True Surface
if(block.getMaterial().isSolid())
// Set Sea Material (water/lava)
if(underwater)
{
decorateLand(biome, sliver, wx, Math.max(height, fluidHeight), wz, rx, rz, block);
block = seaLayers.hasIndex(fluidHeight - k) ? seaLayers.get(depth) : getDimension().getFluid(rockRandom, wx, k, wz);
}
// Set Surface Material for cavern layer surfaces
else if(layers.hasIndex(lastCavernHeight - k))
{
block = layers.get(lastCavernHeight - k);
}
// Set Surface Material for true surface
else
{
block = layers.hasIndex(depth) ? layers.get(depth) : getDimension().getRock(rockRandom, wx, k, wz);
depth++;
}
// Set block and update heightmaps
sliver.set(k, block);
// Decorate underwater surface
if(!cavernSurface && (k == height && B.isSolid(block.getMaterial()) && k < fluidHeight))
{
decorateUnderwater(biome, sliver, wx, k, wz, rx, rz, block);
}
// Decorate Cavern surfaces, but not the true surface
if((carvable && cavernSurface) && !(k == Math.max(height, fluidHeight) && block.getMaterial().isSolid() && k < 255 && k >= fluidHeight))
{
decorateLand(biome, sliver, wx, k, wz, rx, rz, block);
}
}
catch(Throwable e)
// Carve out biomes
KList<CaveResult> caveResults = glCave.genCaves(rx, rz, x, z, sliver);
IrisBiome caveBiome = glBiome.generateData(InferredType.CAVE, wx, wz, rx, rz, region).getBiome();
// Decorate Cave Biome Height Sections
if(caveBiome != null)
{
fail(e);
for(CaveResult i : caveResults)
{
for(int j = i.getFloor(); j <= i.getCeiling(); j++)
{
sliver.set(j, caveBiome);
sliver.set(j, caveBiome.getGroundBiome(masterRandom, rz, j, rx));
}
KList<BlockData> floor = caveBiome.generateLayers(wx, wz, rockRandom, i.getFloor() - 2, i.getFloor() - 2);
KList<BlockData> ceiling = caveBiome.generateLayers(wx + 256, wz + 256, rockRandom, height - i.getCeiling() - 2, height - i.getCeiling() - 2);
BlockData blockc = null;
for(int j = 0; j < floor.size(); j++)
{
if(j == 0)
{
blockc = floor.get(j);
}
sliver.set(i.getFloor() - j, floor.get(j));
}
for(int j = ceiling.size() - 1; j > 0; j--)
{
sliver.set(i.getCeiling() + j, ceiling.get(j));
}
if(blockc != null && !sliver.isSolid(i.getFloor() + 1))
{
decorateCave(caveBiome, sliver, wx, i.getFloor(), wz, rx, rz, blockc);
}
}
}
block = sliver.get(Math.max(height, fluidHeight));
// Decorate True Surface
if(block.getMaterial().isSolid())
{
decorateLand(biome, sliver, wx, Math.max(height, fluidHeight), wz, rx, rz, block);
}
}
@ -313,7 +304,7 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
continue;
}
BlockData d = i.getBlockData(getMasterRandom().nextParallelRNG((int) (38888 + biome.getRarity() + biome.getName().length() + j++)), rx, rz);
BlockData d = i.getBlockData(biome, getMasterRandom().nextParallelRNG((int) (38888 + biome.getRarity() + biome.getName().length() + j++)), rx, rz);
if(d != null)
{
@ -382,7 +373,7 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
for(IrisBiomeDecorator i : biome.getDecorators())
{
BlockData d = i.getBlockData(getMasterRandom().nextParallelRNG(2333877 + biome.getRarity() + biome.getName().length() + +j++), rx, rz);
BlockData d = i.getBlockData(biome, getMasterRandom().nextParallelRNG(2333877 + biome.getRarity() + biome.getName().length() + +j++), rx, rz);
if(d != null)
{
@ -453,7 +444,7 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
continue;
}
BlockData d = i.getBlockData(getMasterRandom().nextParallelRNG(2555 + biome.getRarity() + biome.getName().length() + j++), rx, rz);
BlockData d = i.getBlockData(biome, getMasterRandom().nextParallelRNG(2555 + biome.getRarity() + biome.getName().length() + j++), rx, rz);
if(d != null)
{

View File

@ -118,14 +118,22 @@ public class GenLayerUpdate extends BlockPopulator
{
KList<ItemStack> items = new KList<>();
for(IrisLootTable i : tables)
for(int t = 0; t < gen.getDimension().getLootTries(); t++)
{
items.addAll(i.getLoot(debug, rng, slot, x, y, z));
}
for(IrisLootTable i : tables)
{
items.addAll(i.getLoot(debug, rng.nextParallelRNG(345911 * -t), slot, x, y, z));
}
for(ItemStack i : items)
{
inv.addItem(i);
for(ItemStack i : items)
{
inv.addItem(i);
}
if(items.isNotEmpty())
{
break;
}
}
}

View File

@ -2,6 +2,7 @@ package com.volmit.iris.object;
import org.bukkit.block.data.BlockData;
import com.volmit.iris.Iris;
import com.volmit.iris.gen.atomics.AtomicCache;
import com.volmit.iris.noise.CNG;
import com.volmit.iris.util.ArrayType;
@ -10,7 +11,6 @@ import com.volmit.iris.util.DependsOn;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.KMap;
import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.RNG;
@ -82,8 +82,8 @@ public class IrisBiomeDecorator
@Desc("The palette of blocks to pick from when this decorator needs to place.")
private KList<String> palette = new KList<String>().qadd("GRASS");
private transient KMap<Long, CNG> layerGenerators;
private transient KMap<Long, CNG> layerVarianceGenerators;
private transient AtomicCache<CNG> layerGenerator = new AtomicCache<>();
private transient AtomicCache<CNG> varianceGenerator = new AtomicCache<>();
private transient AtomicCache<CNG> heightGenerator = new AtomicCache<>();
private transient AtomicCache<KList<BlockData>> blockData = new AtomicCache<>();
@ -107,36 +107,12 @@ public class IrisBiomeDecorator
public CNG getGenerator(RNG rng)
{
long key = rng.nextParallelRNG(1).nextLong();
if(layerGenerators == null)
{
layerGenerators = new KMap<>();
}
if(!layerGenerators.containsKey(key))
{
layerGenerators.put(key, style.create(rng.nextParallelRNG((int) (getBlockData().size() + key))));
}
return layerGenerators.get(key);
return layerGenerator.aquire(() -> style.create(rng.nextParallelRNG((int) (getBlockData().size()))));
}
public CNG getVarianceGenerator(RNG rng)
{
long key = rng.nextParallelRNG(4).nextLong();
if(layerVarianceGenerators == null)
{
layerVarianceGenerators = new KMap<>();
}
if(!layerVarianceGenerators.containsKey(key))
{
layerVarianceGenerators.put(key, variance.create(rng.nextParallelRNG((int) (getBlockData().size() + key))).scale(1D / varianceZoom));
}
return layerVarianceGenerators.get(key);
return varianceGenerator.aquire(() -> variance.create(rng.nextParallelRNG((int) (getBlockData().size()))).scale(1D / varianceZoom));
}
public KList<String> add(String b)
@ -145,27 +121,16 @@ public class IrisBiomeDecorator
return palette;
}
public BlockData getBlockData(RNG rng, double x, double z)
public BlockData getBlockData(IrisBiome b, RNG rng, double x, double z)
{
if(getGenerator(rng) == null)
{
return null;
}
if(getBlockData() == null)
{
return null;
}
if(getBlockData().isEmpty())
{
Iris.warn("Empty Block Data for " + b.getName());
return null;
}
double xx = x;
double zz = z;
xx /= getZoom();
zz /= getZoom();
double xx = x / getZoom();
double zz = z / getZoom();
if(getGenerator(rng).fitDouble(0D, 1D, xx, zz) <= chance)
{
@ -174,14 +139,7 @@ public class IrisBiomeDecorator
return getBlockData().get(0);
}
CNG v = getVarianceGenerator(rng.nextParallelRNG(44));
if(v == null)
{
getBlockData().get(0);
}
v.fit(getBlockData(), xx, zz);
return getVarianceGenerator(rng).fit(getBlockData(), xx, zz);
}
return null;

View File

@ -46,6 +46,11 @@ public class IrisDimension extends IrisRegistrant
@Desc("Reference loot tables in this area")
private IrisLootReference loot = new IrisLootReference();
@DontObfuscate
@MinNumber(0)
@Desc("Try to fill a container with loot up to this many times to avoid too many empty chests.")
private int lootTries = 5;
@Required
@MinNumber(0)
@DontObfuscate

View File

@ -309,7 +309,7 @@ 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) && paintmap != null)
if(config.getMode().equals(ObjectPlaceMode.PAINT))
{
yy = (int) Math.round(i.getY()) + Math.floorDiv(h, 2) + paintmap.compute(new ChunkPosition(xx, zz), (k, v) ->
{

View File

@ -0,0 +1,29 @@
package com.volmit.iris.object;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.RegistryListObject;
import com.volmit.iris.util.Required;
import lombok.Data;
import lombok.EqualsAndHashCode;
@DontObfuscate
@Desc("Represents a structure tile")
@Data
@EqualsAndHashCode(callSuper = false)
public class IrisRareObject
{
@Required
@MinNumber(1)
@Desc("The rarity is 1 in X")
@DontObfuscate
private int rarity = 1;
@RegistryListObject
@Required
@Desc("The object to place if rarity check passed")
@DontObfuscate
private String object = "";
}

View File

@ -31,6 +31,18 @@ public class IrisStructure extends IrisRegistrant
@Desc("Wall style noise")
private IrisGeneratorStyle wallStyle = NoiseStyle.STATIC.style();
@Desc("Setting underwater to true will waterlog blocks")
@DontObfuscate
private boolean underwater = false;
@Desc("The max & min height any part of this structure can place at")
@DontObfuscate
private IrisObjectLimit clamp = new IrisObjectLimit();
@Desc("Setting bore to true will dig out blocks before placing tiles")
@DontObfuscate
private boolean bore = false;
@Required
@MinNumber(3)
@MaxNumber(64)
@ -110,7 +122,7 @@ public class IrisStructure extends IrisRegistrant
{
if(i.likeAGlove(floor, ceiling, walls, faces, openings))
{
return new TileResult(i, rt);
return new TileResult(this, i, rt);
}
}

View File

@ -135,7 +135,18 @@ public class IrisStructurePlacement
t.getPlacement().setBore(true);
}
IrisObject o = load(g, t.getTile().getObjects().get(rnp.nextInt(t.getTile().getObjects().size())));
IrisObject o = null;
for(IrisRareObject l : t.getTile().getRareObjects())
{
if(rnp.i(1, l.getRarity()) == 1)
{
o = load(g, l.getObject());
break;
}
}
o = o != null ? o : load(g, t.getTile().getObjects().get(rnp.nextInt(t.getTile().getObjects().size())));
o.place(Math.floorDiv(i, s) * s, height == -1 ? -1 : h, Math.floorDiv(j, s) * s, g, t.getPlacement(), rng);
}
}

View File

@ -21,6 +21,10 @@ public class IrisStructureTile
@Desc("Reference loot tables in this area")
private IrisLootReference loot = new IrisLootReference();
@DontObfuscate
@Desc("The place mode for this tile")
private ObjectPlaceMode placeMode = ObjectPlaceMode.PAINT;
@Required
@DontObfuscate
@Desc("Is this structure allowed to place if there is supposed to be a ceiling?")
@ -58,6 +62,13 @@ public class IrisStructureTile
@Desc("List of objects to place centered in this tile")
private KList<String> objects = new KList<>();
@RegistryListObject
@Required
@ArrayType(min = 1, type = IrisRareObject.class)
@DontObfuscate
@Desc("List of objects to place centered in this tile but with rarity. These items only place some of the time so specify objects for common stuff too.")
private KList<IrisRareObject> rareObjects = new KList<>();
private AtomicCache<Integer> minFaces = new AtomicCache<>();
private AtomicCache<Integer> maxFaces = new AtomicCache<>();

View File

@ -5,18 +5,23 @@ import lombok.Data;
@Data
public class TileResult
{
private IrisStructure structure;
private IrisStructureTile tile;
private IrisObjectPlacement placement;
public TileResult(IrisStructureTile tile, int rot)
public TileResult(IrisStructure structure, IrisStructureTile tile, int rot)
{
this.structure = structure;
this.tile = tile;
IrisObjectPlacement p = new IrisObjectPlacement();
IrisObjectRotation rt = new IrisObjectRotation();
rt.setYAxis(new IrisAxisRotationClamp(rot != 0, rot, rot, 0));
p.setRotation(rt);
p.setBottom(true);
p.setMode(ObjectPlaceMode.PAINT);
p.setBore(structure.isBore());
p.setClamp(structure.getClamp());
p.setWaterloggable(structure.isUnderwater());
p.setMode(tile.getPlaceMode());
placement = p;
}
}

View File

@ -74,7 +74,7 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject>
useCache.remove(v);
loadCache.remove(v);
lock.unlock();
Iris.info("Unloaded Object: " + v);
J.a(() -> Iris.verbose("Unloaded Object: " + v));
}
public IrisObject loadFile(File j, String key, String name)
@ -86,7 +86,7 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject>
t.read(j);
loadCache.put(key, t);
Iris.hotloader.track(j);
Iris.info("Loading " + resourceTypeName + ": " + j.getPath());
J.a(() -> Iris.verbose("Loading " + resourceTypeName + ": " + j.getPath()));
t.setLoadKey(name);
lock.unlock();
return t;

View File

@ -84,7 +84,7 @@ public class ResourceLoader<T extends IrisRegistrant>
T t = new Gson().fromJson(IO.readAll(j), objectClass);
loadCache.put(key, t);
Iris.hotloader.track(j);
Iris.info("Loading " + resourceTypeName + ": " + j.getPath());
J.a(() -> Iris.verbose("Loading " + resourceTypeName + ": " + j.getPath()));
t.setLoadKey(name);
t.setLoadFile(j);
lock.unlock();
@ -94,7 +94,7 @@ public class ResourceLoader<T extends IrisRegistrant>
catch(Throwable e)
{
lock.unlock();
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
J.a(() -> Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage()));
return null;
}
}
@ -128,7 +128,7 @@ public class ResourceLoader<T extends IrisRegistrant>
}
}
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
J.a(() -> Iris.warn("Couldn't find " + resourceTypeName + ": " + name));
lock.unlock();
return null;