Forcefully shove stuff into other stuff

This commit is contained in:
Daniel Mills
2020-11-10 00:49:28 -05:00
parent 50ffcceaf4
commit 4fc8a5ad0c
364 changed files with 2975 additions and 5303 deletions

View File

@@ -0,0 +1,312 @@
package com.volmit.iris.generator;
import com.volmit.iris.object.*;
import com.volmit.iris.util.*;
import com.volmit.iris.scaffold.data.DataProvider;
import com.volmit.iris.scaffold.engine.Engine;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import com.volmit.iris.Iris;
import com.volmit.iris.scaffold.stream.ProceduralStream;
import com.volmit.iris.scaffold.stream.interpolation.Interpolated;
import com.volmit.iris.manager.IrisDataManager;
import com.volmit.iris.generator.noise.CNG;
import lombok.Data;
@Data
public class IrisComplex implements DataProvider
{
private RNG rng;
private double fluidHeight;
private IrisDataManager data;
private KList<IrisGenerator> generators;
private static final BlockData AIR = Material.AIR.createBlockData();
private ProceduralStream<IrisRegion> regionStream;
private ProceduralStream<InferredType> bridgeStream;
private ProceduralStream<IrisBiome> landBiomeStream;
private ProceduralStream<IrisBiome> caveBiomeStream;
private ProceduralStream<IrisBiome> seaBiomeStream;
private ProceduralStream<IrisBiome> shoreBiomeStream;
private ProceduralStream<IrisBiome> baseBiomeStream;
private ProceduralStream<IrisBiome> trueBiomeStream;
private ProceduralStream<Biome> trueBiomeDerivativeStream;
private ProceduralStream<Double> heightStream;
private ProceduralStream<Double> maxHeightStream;
private ProceduralStream<Double> overlayStream;
private ProceduralStream<Double> heightFluidStream;
private ProceduralStream<Double> slopeStream;
private ProceduralStream<RNG> rngStream;
private ProceduralStream<RNG> chunkRngStream;
private ProceduralStream<IrisDecorator> terrainSurfaceDecoration;
private ProceduralStream<IrisDecorator> terrainCeilingDecoration;
private ProceduralStream<IrisDecorator> terrainCaveSurfaceDecoration;
private ProceduralStream<IrisDecorator> terrainCaveCeilingDecoration;
private ProceduralStream<IrisDecorator> seaSurfaceDecoration;
private ProceduralStream<IrisDecorator> shoreSurfaceDecoration;
private ProceduralStream<BlockData> rockStream;
private ProceduralStream<BlockData> fluidStream;
private ProceduralStream<BlockData> glassStream;
public ProceduralStream<IrisBiome> getBiomeStream(InferredType type)
{
switch(type)
{
case CAVE:
return caveBiomeStream;
case DEFER:
break;
case LAKE:
break;
case LAND:
return landBiomeStream;
case RIVER:
break;
case SEA:
return seaBiomeStream;
case SHORE:
return shoreBiomeStream;
default:
break;
}
return null;
}
public IrisComplex(Engine engine)
{
int cacheSize = 1024;
BlockData glass = B.getBlockData("GLASS");
this.rng = new RNG(engine.getWorld().getSeed());
this.data = engine.getData();
double height = engine.getHeight();
fluidHeight = engine.getDimension().getFluidHeight();
generators = new KList<>();
RNG rng = new RNG(engine.getWorld().getSeed());
glassStream = ProceduralStream.of((x,y,z) -> glass, Interpolated.BLOCK_DATA);
//@builder
engine.getDimension().getRegions().forEach((i) -> data.getRegionLoader().load(i)
.getAllBiomes(this).forEach((b) -> b
.getGenerators()
.forEach((c) -> registerGenerator(c.getCachedGenerator(this)))));
overlayStream = ProceduralStream.ofDouble((x, z) -> 0D);
engine.getDimension().getOverlayNoise().forEach((i) -> overlayStream.add((x, z) -> i.get(rng, x, z)));
rngStream = ProceduralStream.of((x, z) -> new RNG(((x.longValue()) << 32) | (z.longValue() & 0xffffffffL))
.nextParallelRNG(engine.getWorld().getSeed()), Interpolated.RNG);
chunkRngStream = rngStream.blockToChunkCoords();
rockStream = engine.getDimension().getRockPalette().getLayerGenerator(rng.nextRNG(), data).stream()
.select(engine.getDimension().getRockPalette().getBlockData(data));
fluidStream = engine.getDimension().getFluidPalette().getLayerGenerator(rng.nextRNG(), data).stream()
.select(engine.getDimension().getFluidPalette().getBlockData(data));
regionStream = engine.getDimension().getRegionStyle().create(rng.nextRNG()).stream()
.zoom(engine.getDimension().getRegionZoom())
.selectRarity(engine.getDimension().getRegions())
.convertCached((s) -> data.getRegionLoader().load(s)).cache2D(cacheSize);
caveBiomeStream = regionStream.convert((r)
-> engine.getDimension().getCaveBiomeStyle().create(rng.nextRNG()).stream()
.zoom(r.getCaveBiomeZoom())
.selectRarity(r.getCaveBiomes())
.onNull("")
.convertCached((s) -> {
if(s.isEmpty())
{
return new IrisBiome();
}
return data.getBiomeLoader().load(s)
.setInferredType(InferredType.CAVE);
})
).convertAware2D(ProceduralStream::get).cache2D(cacheSize);
landBiomeStream = regionStream.convert((r)
-> engine.getDimension().getLandBiomeStyle().create(rng.nextRNG()).stream()
.zoom(r.getLandBiomeZoom())
.selectRarity(r.getLandBiomes())
.convertCached((s) -> data.getBiomeLoader().load(s)
.setInferredType(InferredType.LAND))
).convertAware2D(ProceduralStream::get)
.cache2D(cacheSize);
seaBiomeStream = regionStream.convert((r)
-> engine.getDimension().getSeaBiomeStyle().create(rng.nextRNG()).stream()
.zoom(r.getSeaBiomeZoom())
.selectRarity(r.getSeaBiomes())
.convertCached((s) -> data.getBiomeLoader().load(s)
.setInferredType(InferredType.SEA))
).convertAware2D(ProceduralStream::get)
.cache2D(cacheSize);
shoreBiomeStream = regionStream.convert((r)
-> engine.getDimension().getShoreBiomeStyle().create(rng.nextRNG()).stream()
.zoom(r.getShoreBiomeZoom())
.selectRarity(r.getShoreBiomes())
.convertCached((s) -> data.getBiomeLoader().load(s)
.setInferredType(InferredType.SHORE))
).convertAware2D(ProceduralStream::get).cache2D(cacheSize);
bridgeStream = engine.getDimension().getContinentalStyle().create(rng.nextRNG()).stream()
.convert((v) -> v >= engine.getDimension().getLandChance() ? InferredType.SEA : InferredType.LAND);
baseBiomeStream = bridgeStream.convertAware2D((t, x, z) -> t.equals(InferredType.SEA)
? seaBiomeStream.get(x, z) : landBiomeStream.get(x, z))
.convertAware2D(this::implode).cache2D(cacheSize);
heightStream = baseBiomeStream.convertAware2D((b, x, z) -> getHeight(b, x, z, engine.getWorld().getSeed()))
.roundDouble().cache2D(cacheSize);
slopeStream = heightStream.slope().cache2D(cacheSize);
trueBiomeStream = heightStream
.convertAware2D((h, x, z) ->
fixBiomeType(h, baseBiomeStream.get(x, z),
regionStream.get(x, z), x, z, fluidHeight)).cache2D(cacheSize);
trueBiomeDerivativeStream = trueBiomeStream.convert(IrisBiome::getDerivative).cache2D(cacheSize);
heightFluidStream = heightStream.max(fluidHeight).cache2D(cacheSize);
maxHeightStream = ProceduralStream.ofDouble((x, z) -> height);
terrainSurfaceDecoration = trueBiomeStream
.convertAware2D((b, xx,zz) -> decorateFor(b, xx, zz, DecorationPart.NONE));
terrainCeilingDecoration = trueBiomeStream
.convertAware2D((b, xx,zz) -> decorateFor(b, xx, zz, DecorationPart.CEILING));
terrainCaveSurfaceDecoration = caveBiomeStream
.convertAware2D((b, xx,zz) -> decorateFor(b, xx, zz, DecorationPart.NONE));
terrainCaveCeilingDecoration = caveBiomeStream
.convertAware2D((b, xx,zz) -> decorateFor(b, xx, zz, DecorationPart.CEILING));
shoreSurfaceDecoration = trueBiomeStream
.convertAware2D((b, xx,zz) -> decorateFor(b, xx, zz, DecorationPart.SHORE_LINE));
seaSurfaceDecoration = trueBiomeStream
.convertAware2D((b, xx,zz) -> decorateFor(b, xx, zz, DecorationPart.SEA_SURFACE));
//@done
}
private IrisDecorator decorateFor(IrisBiome b, double x, double z, DecorationPart part)
{
RNG rngc = chunkRngStream.get(x, z);
for(IrisDecorator i : b.getDecorators())
{
if(!i.getPartOf().equals(part))
{
continue;
}
BlockData block = i.getBlockData(b, rngc, x, z, data);
if(block != null)
{
return i;
}
}
return null;
}
private IrisBiome implode(IrisBiome b, Double x, Double z)
{
if(b.getChildren().isEmpty())
{
return b;
}
return implode(b, x, z, 3);
}
private IrisBiome implode(IrisBiome b, Double x, Double z, int max)
{
if(max < 0)
{
return b;
}
if(b.getChildren().isEmpty())
{
return b;
}
CNG childCell = b.getChildrenGenerator(rng, 123, b.getChildShrinkFactor());
KList<IrisBiome> chx = b.getRealChildren(this).copy();
chx.add(b);
IrisBiome biome = childCell.fitRarity(chx, x, z);
biome.setInferredType(b.getInferredType());
return implode(biome, x, z, max - 1);
}
private IrisBiome fixBiomeType(Double height, IrisBiome biome, IrisRegion region, Double x, Double z, double fluidHeight)
{
double sh = region.getShoreHeight(x, z);
if(height >= fluidHeight-1 && height <= fluidHeight + sh && !biome.isShore())
{
return shoreBiomeStream.get(x, z);
}
if(height > fluidHeight + sh && !biome.isLand())
{
return landBiomeStream.get(x, z);
}
if(height < fluidHeight && !biome.isAquatic())
{
return seaBiomeStream.get(x, z);
}
if(height == fluidHeight && !biome.isShore())
{
return shoreBiomeStream.get(x, z);
}
return biome;
}
private double getHeight(IrisBiome b, double x, double z, long seed)
{
double h = 0;
for(IrisGenerator gen : generators)
{
double hi = gen.getInterpolator().interpolate(x, z, (xx, zz) ->
{
try
{
IrisBiome bx = baseBiomeStream.get(xx, zz);
return bx.getGenLinkMax(gen.getLoadKey());
}
catch(Throwable e)
{
Iris.warn("Failed to sample hi biome at " + xx + " " + zz + " using the generator " + gen.getLoadKey());
}
return 0;
});
double lo = gen.getInterpolator().interpolate(x, z, (xx, zz) ->
{
try
{
IrisBiome bx = baseBiomeStream.get(xx, zz);
return bx.getGenLinkMin(gen.getLoadKey());
}
catch(Throwable e)
{
Iris.warn("Failed to sample lo biome at " + xx + " " + zz + " using the generator " + gen.getLoadKey());
}
return 0;
});
h += M.lerp(lo, hi, gen.getHeight(x, z, seed + 239945));
}
return h + fluidHeight + overlayStream.get(x,z);
}
private void registerGenerator(IrisGenerator cachedGenerator)
{
for(IrisGenerator i : generators)
{
if(i.getLoadKey().equals(cachedGenerator.getLoadKey()))
{
return;
}
}
generators.add(cachedGenerator);
}
}

View File

@@ -0,0 +1,119 @@
package com.volmit.iris.generator;
import com.volmit.iris.Iris;
import com.volmit.iris.scaffold.engine.*;
import com.volmit.iris.scaffold.hunk.Hunk;
import com.volmit.iris.scaffold.parallel.MultiBurst;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.generator.BlockPopulator;
import org.jetbrains.annotations.NotNull;
import java.util.Random;
public class IrisEngine extends BlockPopulator implements Engine
{
@Getter
private final EngineCompound compound;
@Getter
private final EngineTarget target;
@Getter
private final EngineFramework framework;
@Getter
private final EngineWorldManager worldManager;
@Setter
@Getter
private volatile int parallelism;
@Setter
@Getter
private volatile int minHeight;
private boolean failing;
private boolean closed;
public IrisEngine(EngineTarget target, EngineCompound compound)
{
Iris.info("Initializing Engine: " + target.getWorld().getName() + "/" + target.getDimension().getLoadKey() + " (" + target.getHeight() + " height)");
this.target = target;
this.framework = new IrisEngineFramework(this);
worldManager = new IrisWorldManager(this);
this.compound = compound;
minHeight = 0;
failing = false;
closed = false;
}
@Override
public void close()
{
closed = true;
getWorldManager().close();
getFramework().close();
}
@Override
public boolean isClosed() {
return closed;
}
@Override
public double modifyX(double x) {
return x / getDimension().getTerrainZoom();
}
@Override
public double modifyZ(double z) {
return z / getDimension().getTerrainZoom();
}
@Override
public void generate(int x, int z, Hunk<BlockData> vblocks, Hunk<Biome> vbiomes) {
Hunk<Biome> biomes = vbiomes.synchronize();
Hunk<BlockData> blocks = vblocks.synchronize().listen((xx,y,zz,t) -> catchBlockUpdates(x+xx,y+getMinHeight(),z+zz, t));
MultiBurst.burst.burst(
() -> getFramework().getEngineParallax().generateParallaxArea(x, z),
() -> getFramework().getBiomeActuator().actuate(x, z, biomes),
() -> getFramework().getTerrainActuator().actuate(x, z, blocks)
);
MultiBurst.burst.burst(
() -> getFramework().getCaveModifier().modify(x, z, blocks),
() -> getFramework().getRavineModifier().modify(x, z, blocks)
);
MultiBurst.burst.burst(
() -> getFramework().getDecorantActuator().actuate(x, z, blocks),
() -> getFramework().getDepositModifier().modify(x, z, blocks),
() -> getFramework().getPostModifier().modify(x, z, blocks),
() -> getFramework().getEngineParallax().insertParallax(x, z, blocks)
);
getFramework().recycle();
}
@Override
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk c)
{
getWorldManager().spawnInitialEntities(c);
updateChunk(c);
}
@Override
public void fail(String error, Throwable e) {
failing = true;
Iris.error(error);
e.printStackTrace();
}
@Override
public boolean hasFailed() {
return failing;
}
}

View File

@@ -0,0 +1,181 @@
package com.volmit.iris.generator;
import com.volmit.iris.Iris;
import com.volmit.iris.manager.IrisDataManager;
import com.volmit.iris.object.IrisDimension;
import com.volmit.iris.object.IrisDimensionIndex;
import com.volmit.iris.util.KList;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineCompound;
import com.volmit.iris.scaffold.engine.EngineData;
import com.volmit.iris.scaffold.engine.EngineTarget;
import com.volmit.iris.scaffold.hunk.Hunk;
import com.volmit.iris.scaffold.parallel.BurstExecutor;
import com.volmit.iris.scaffold.parallel.MultiBurst;
import lombok.Getter;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.event.EventHandler;
import org.bukkit.event.world.WorldSaveEvent;
import org.bukkit.generator.BlockPopulator;
import java.io.File;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class IrisEngineCompound implements EngineCompound {
@Getter
private final World world;
@Getter
private final EngineData engineMetadata;
private final Engine[] engines;
@Getter
private final MultiBurst burster;
@Getter
private final KList<BlockPopulator> populators;
@Getter
private final IrisDimension rootDimension;
public IrisEngineCompound(World world, IrisDimension rootDimension, IrisDataManager data, int maximumThreads)
{
this.rootDimension = rootDimension;
Iris.info("Initializing Engine Composite for " + world.getName());
this.world = world;
engineMetadata = EngineData.load(getEngineMetadataFile());
saveEngineMetadata();
populators = new KList<>();
if(rootDimension.getDimensionalComposite().isEmpty())
{
burster = null;
engines = new Engine[]{new IrisEngine(new EngineTarget(world, rootDimension, data, 256, maximumThreads), this)};
}
else
{
double totalWeight = 0D;
engines = new Engine[rootDimension.getDimensionalComposite().size()];
burster = engines.length > 1 ? new MultiBurst(engines.length) : null;
int threadDist = (Math.max(2, maximumThreads - engines.length)) / engines.length;
if((threadDist * engines.length) + engines.length > maximumThreads)
{
Iris.warn("Using " + ((threadDist * engines.length) + engines.length) + " threads instead of the configured " + maximumThreads + " maximum thread count due to the requirements of this dimension!");
}
for(IrisDimensionIndex i : rootDimension.getDimensionalComposite())
{
totalWeight += i.getWeight();
}
int buf = 0;
for(int i = 0; i < engines.length; i++)
{
IrisDimensionIndex index = rootDimension.getDimensionalComposite().get(i);
IrisDimension dimension = data.getDimensionLoader().load(index.getDimension());
engines[i] = new IrisEngine(new EngineTarget(world, dimension, data.copy().preferFolder(rootDimension.getLoadKey()), (int)Math.floor(256D * (index.getWeight() / totalWeight)), index.isInverted(), threadDist), this);
engines[i].setMinHeight(buf);
buf += engines[i].getHeight();
}
}
for(Engine i : engines)
{
if(i instanceof BlockPopulator)
{
populators.add((BlockPopulator) i);
}
}
Iris.instance.registerListener(this);
}
@EventHandler
public void on(WorldSaveEvent e)
{
if(world != null &&e.getWorld().equals(world))
{
save();
}
}
private File getEngineMetadataFile() {
return new File(world.getWorldFolder(), "iris/engine-metadata.json");
}
@Override
public void generate(int x, int z, Hunk<BlockData> blocks, Hunk<Biome> biomes)
{
if(engines.length == 1 && !getEngine(0).getTarget().isInverted())
{
engines[0].generate(x, z, blocks, biomes);
}
else
{
int i;
int offset = 0;
BurstExecutor e = burster.burst();
Runnable[] insert = new Runnable[engines.length];
for(i = 0; i < engines.length; i++)
{
AtomicInteger index = new AtomicInteger(i);
Engine engine = engines[i];
int doffset = offset;
int height = engine.getTarget().getHeight();
AtomicReference<Hunk<BlockData>> cblock = new AtomicReference<>(Hunk.newArrayHunk(16, height, 16));
AtomicReference<Hunk<Biome>> cbiome = new AtomicReference<>(Hunk.newArrayHunk(16, height, 16));
cblock.set(engine.getTarget().isInverted() ? cblock.get().invertY() : cblock.get());
cbiome.set(engine.getTarget().isInverted() ? cbiome.get().invertY() : cbiome.get());
e.queue(() -> {
engine.generate(x, z, cblock.get(), cbiome.get());
synchronized (insert)
{
insert[index.get()] = () -> {
blocks.insert(0, doffset, 0, cblock.get());
biomes.insert(0, doffset, 0, cbiome.get());
};
}
});
offset += height;
}
e.complete();
for(i = 0; i < insert.length; i++)
{
insert[i].run();
}
}
}
@Override
public int getSize() {
return engines.length;
}
@Override
public Engine getEngine(int index) {
return engines[index];
}
@Override
public void saveEngineMetadata() {
engineMetadata.save(getEngineMetadataFile());
}
@Override
public IrisDataManager getData(int height) {
return getEngineForHeight(height).getData();
}
}

View File

@@ -0,0 +1,72 @@
package com.volmit.iris.generator;
import com.volmit.iris.generator.actuator.*;
import com.volmit.iris.generator.modifier.IrisCaveModifier;
import com.volmit.iris.generator.modifier.IrisDepositModifier;
import com.volmit.iris.generator.modifier.IrisPostModifier;
import com.volmit.iris.generator.modifier.IrisRavineModifier;
import com.volmit.iris.scaffold.engine.*;
import lombok.Getter;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
public class IrisEngineFramework implements EngineFramework {
@Getter
private final Engine engine;
@Getter
private final IrisComplex complex;
@Getter
final EngineParallaxManager engineParallax;
@Getter
private final EngineActuator<BlockData> terrainActuator;
@Getter
private final EngineActuator<BlockData> decorantActuator;
@Getter
private final EngineActuator<Biome> biomeActuator;
@Getter
private final EngineModifier<BlockData> depositModifier;
@Getter
private final EngineModifier<BlockData> caveModifier;
@Getter
private final EngineModifier<BlockData> ravineModifier;
@Getter
private final EngineModifier<BlockData> postModifier;
public IrisEngineFramework(Engine engine)
{
this.engine = engine;
this.complex = new IrisComplex(getEngine());
this.engineParallax = new IrisEngineParallax(getEngine());
this.terrainActuator = new IrisTerrainActuator(getEngine());
this.decorantActuator = new IrisDecorantActuator(getEngine());
this.biomeActuator = new IrisBiomeActuator(getEngine());
this.depositModifier = new IrisDepositModifier(getEngine());
this.ravineModifier = new IrisRavineModifier(getEngine());
this.caveModifier = new IrisCaveModifier(engine);
this.postModifier = new IrisPostModifier(engine);
}
@Override
public void close()
{
getEngineParallax().close();
getTerrainActuator().close();
getDecorantActuator().close();
getBiomeActuator().close();
getDepositModifier().close();
getRavineModifier().close();
getCaveModifier().close();
getPostModifier().close();
}
}

View File

@@ -0,0 +1,24 @@
package com.volmit.iris.generator;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineParallaxManager;
import com.volmit.iris.scaffold.engine.EngineStructureManager;
import lombok.Getter;
public class IrisEngineParallax implements EngineParallaxManager {
@Getter
private final Engine engine;
@Getter
private final EngineStructureManager structureManager;
@Getter
private final int parallaxSize;
public IrisEngineParallax(Engine engine)
{
this.engine = engine;
parallaxSize = computeParallaxSize();
structureManager = new IrisEngineStructure(getEngine());
}
}

View File

@@ -0,0 +1,10 @@
package com.volmit.iris.generator;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedStructureManager;
public class IrisEngineStructure extends EngineAssignedStructureManager {
public IrisEngineStructure(Engine engine) {
super(engine);
}
}

View File

@@ -0,0 +1,44 @@
package com.volmit.iris.generator;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedWorldManager;
import org.bukkit.Chunk;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
public class IrisWorldManager extends EngineAssignedWorldManager {
public IrisWorldManager(Engine engine) {
super(engine);
}
@Override
public void onEntitySpawn(EntitySpawnEvent e) {
}
@Override
public void onTick() {
}
@Override
public void onSave() {
getEngine().getParallax().saveAll();
}
@Override
public void spawnInitialEntities(Chunk chunk) {
}
@Override
public void onBlockBreak(BlockBreakEvent e) {
}
@Override
public void onBlockPlace(BlockPlaceEvent e) {
}
}

View File

@@ -0,0 +1,32 @@
package com.volmit.iris.generator.actuator;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedActuator;
import com.volmit.iris.scaffold.hunk.Hunk;
import org.bukkit.block.Biome;
public class IrisBiomeActuator extends EngineAssignedActuator<Biome>
{
public IrisBiomeActuator(Engine engine) {
super(engine, "Biome");
}
@Override
public void onActuate(int x, int z, Hunk<Biome> h) {
int i,zf;
Biome v;
for(int xf = 0; xf < h.getWidth(); xf++)
{
for(zf = 0; zf < h.getDepth(); zf++)
{
v = getComplex().getTrueBiomeDerivativeStream().get(modX(xf+x), modZ(zf+z));
for(i = 0; i < h.getHeight(); i++)
{
h.set(xf, i, zf, v);
}
}
}
}
}

View File

@@ -0,0 +1,117 @@
package com.volmit.iris.generator.actuator;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.util.RNG;
import com.volmit.iris.generator.decorator.IrisCeilingDecorator;
import com.volmit.iris.generator.decorator.IrisSeaSurfaceDecorator;
import com.volmit.iris.generator.decorator.IrisShoreLineDecorator;
import com.volmit.iris.generator.decorator.IrisSurfaceDecorator;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedActuator;
import com.volmit.iris.scaffold.engine.EngineDecorator;
import com.volmit.iris.scaffold.hunk.Hunk;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import java.util.function.Predicate;
public class IrisDecorantActuator extends EngineAssignedActuator<BlockData>
{
private static final Predicate<BlockData> PREDICATE_SOLID = (b) -> b != null && !b.getMaterial().isAir() && !b.getMaterial().equals(Material.WATER) && !b.getMaterial().equals(Material.LAVA);
private final RNG rng;
@Getter
private final EngineDecorator surfaceDecorator;
@Getter
private final EngineDecorator ceilingDecorator;
@Getter
private final EngineDecorator seaSurfaceDecorator;
@Getter
private final EngineDecorator shoreLineDecorator;
private final boolean shouldRay;
public IrisDecorantActuator(Engine engine) {
super(engine, "Decorant");
shouldRay = shouldRayDecorate();
this.rng = new RNG(engine.getTarget().getWorld().getSeed());
surfaceDecorator = new IrisSurfaceDecorator(getEngine());
ceilingDecorator = new IrisCeilingDecorator(getEngine());
seaSurfaceDecorator = new IrisSeaSurfaceDecorator(getEngine());
shoreLineDecorator = new IrisShoreLineDecorator(getEngine());
}
@Override
public void onActuate(int x, int z, Hunk<BlockData> output) {
if(!getEngine().getDimension().isDecorate())
{
return;
}
boolean solid;
int emptyFor = 0;
int lastSolid = 0;
int j, realX, realZ, height;
IrisBiome biome, cave;
for(int i = 0; i < output.getWidth(); i++)
{
for(j = 0; j < output.getDepth(); j++)
{
realX = (int) Math.round(modX(x + i));
realZ = (int) Math.round(modZ(z + j));
height = (int) Math.round(getComplex().getHeightStream().get(realX, realZ));
biome = getComplex().getTrueBiomeStream().get(realX, realZ);
cave = shouldRay ? getComplex().getCaveBiomeStream().get(realX, realZ) : null;
if(biome.getDecorators().isEmpty() && (cave == null || cave.getDecorators().isEmpty()))
{
continue;
}
if(height == getDimension().getFluidHeight())
{
getShoreLineDecorator().decorate(i, j,
realX, (int) Math.round(modX(x + i+1)), (int) Math.round(modX(x + i-1)),
realZ, (int) Math.round(modZ(z + j+1)), (int) Math.round(modZ(z + j-1)),
output, biome, height, getEngine().getHeight() - height);
}
else if(height < getDimension().getFluidHeight())
{
getSeaSurfaceDecorator().decorate(i, j, realX, realZ, output, biome, getDimension().getFluidHeight(), getEngine().getHeight() - getDimension().getFluidHeight());
}
getSurfaceDecorator().decorate(i, j, realX, realZ, output, biome, height, getEngine().getHeight() - height);
if(cave != null && cave.getDecorators().isNotEmpty())
{
for(int k = height; k > 0; k--)
{
solid = PREDICATE_SOLID.test(output.get(i, k, j));
if(solid)
{
lastSolid = k;
}
else {
emptyFor++;
}
if(solid && emptyFor > 0)
{
getCeilingDecorator().decorate(i, j, realX, realZ, output, cave, lastSolid, emptyFor);
getSurfaceDecorator().decorate(i, j, realX, realZ, output, cave, k, emptyFor);
emptyFor = 0;
}
}
}
}
}
}
private boolean shouldRayDecorate()
{
return getEngine().getDimension().isCarving() || getEngine().getDimension().isCaves() || getEngine().getDimension().isVanillaCaves() || getEngine().getDimension().isRavines();
}
}

View File

@@ -0,0 +1,90 @@
package com.volmit.iris.generator.actuator;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.RNG;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedActuator;
import com.volmit.iris.scaffold.hunk.Hunk;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
public class IrisTerrainActuator extends EngineAssignedActuator<BlockData>
{
private static final BlockData AIR = Material.AIR.createBlockData();
private static final BlockData BEDROCK = Material.BEDROCK.createBlockData();
private static final BlockData CAVE_AIR = Material.CAVE_AIR.createBlockData();
@Getter
private final RNG rng;
private final boolean hasUnder;
public IrisTerrainActuator(Engine engine) {
super(engine, "Terrain");
rng = new RNG(engine.getWorld().getSeed());
hasUnder = getDimension().getUndercarriage() != null && !getDimension().getUndercarriage().getGenerator().isFlat();
}
@Override
public void onActuate(int x, int z, Hunk<BlockData> h) {
int i, zf, depth, realX, realZ, hf, he, b;
IrisBiome biome;
KList<BlockData> blocks;
for(int xf = 0; xf < h.getWidth(); xf++)
{
for(zf = 0; zf < h.getDepth(); zf++)
{
realX = (int) modX(xf + x);
realZ = (int) modZ(zf + z);
b = hasUnder ? (int) Math.round(getDimension().getUndercarriage().get(rng, realX, realZ)) : 0;
he = (int) Math.round(Math.min(h.getHeight(), getComplex().getHeightStream().get(realX, realZ)));
hf = (int) Math.round(Math.max(Math.min(h.getHeight(), getDimension().getFluidHeight()), he));
biome = getComplex().getTrueBiomeStream().get(realX, realZ);
blocks = null;
if(hf < b)
{
continue;
}
for(i = hf; i >= b; i--)
{
if(i == b && getDimension().isBedrock())
{
h.set(xf, i, zf, BEDROCK);
continue;
}
if(getDimension().isCarved(realX, i, realZ, rng, he))
{
continue;
}
if(i > he && i <= hf)
{
h.set(xf, i, zf, getComplex().getFluidStream().get(realX, +realZ));
continue;
}
if(i <= he)
{
depth = he - i;
if(blocks == null)
{
blocks = biome.generateLayers(realX, realZ, rng, (int)he, (int)he, getData());
}
if(blocks.hasIndex(depth))
{
h.set(xf, i, zf, blocks.get(depth));
continue;
}
h.set(xf, i, zf, getComplex().getRockStream().get(realX, realZ));
}
}
}
}
}
}

View File

@@ -0,0 +1,39 @@
package com.volmit.iris.generator.decorator;
import com.volmit.iris.object.DecorationPart;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDecorator;
import com.volmit.iris.scaffold.cache.Cache;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.hunk.Hunk;
import org.bukkit.block.data.BlockData;
public class IrisCeilingDecorator extends IrisEngineDecorator
{
public IrisCeilingDecorator(Engine engine) {
super(engine, "Ceiling", DecorationPart.CEILING);
}
@Override
public void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
IrisDecorator decorator = getDecorator(biome, realX, realZ);
if(decorator != null)
{
if(!decorator.isStacking())
{
data.set(x, height-1, z, decorator.getBlockData100(biome, getRng(), realX, realZ, getData()));
}
else
{
int stack = Math.min(getRng().nextParallelRNG(Cache.key(realX, realZ)).i(decorator.getStackMin(), decorator.getStackMax()), max);
for(int i = 0; i < stack; i++)
{
data.set(x, height-1-i, z, i == stack-1 ? decorator.getBlockDataForTop(biome, getRng(), realX+i, realZ-i, getData()) : decorator.getBlockData100(biome, getRng(), realX+i, realZ-i, getData()));
}
}
}
}
}

View File

@@ -0,0 +1,41 @@
package com.volmit.iris.generator.decorator;
import com.volmit.iris.object.DecorationPart;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDecorator;
import com.volmit.iris.util.RNG;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedComponent;
import com.volmit.iris.scaffold.engine.EngineDecorator;
import lombok.Getter;
public abstract class IrisEngineDecorator extends EngineAssignedComponent implements EngineDecorator {
@Getter
private final RNG rng;
@Getter
private final DecorationPart part;
public IrisEngineDecorator(Engine engine, String name, DecorationPart part) {
super(engine, name + " Decorator");
this.part = part;
this.rng = new RNG(getSeed() + 29356788 - (part.ordinal() * 10439677));
}
protected IrisDecorator getDecorator(IrisBiome biome, double realX, double realZ)
{
for(IrisDecorator i : biome.getDecorators())
{
if(i.getPartOf().equals(part))
{
if(i.getBlockData(biome, rng, realX, realZ, getData()) != null)
{
return i;
}
}
}
return null;
}
}

View File

@@ -0,0 +1,43 @@
package com.volmit.iris.generator.decorator;
import com.volmit.iris.object.DecorationPart;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDecorator;
import com.volmit.iris.scaffold.cache.Cache;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.hunk.Hunk;
import org.bukkit.block.data.BlockData;
public class IrisSeaSurfaceDecorator extends IrisEngineDecorator
{
public IrisSeaSurfaceDecorator(Engine engine) {
super(engine, "Sea Surface", DecorationPart.SEA_SURFACE);
}
@Override
public void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
if(height < getDimension().getFluidHeight()) {
{
IrisDecorator decorator = getDecorator(biome, realX, realZ);
if(decorator != null)
{
if(!decorator.isStacking())
{
data.set(x, getDimension().getFluidHeight()+1, z, decorator.getBlockData100(biome, getRng(), realX, realZ, getData()));
}
else
{
int stack = Math.min(getRng().nextParallelRNG(Cache.key(realX, realZ)).i(decorator.getStackMin(), decorator.getStackMax()), max);
for(int i = 0; i < stack; i++)
{
data.set(x, getDimension().getFluidHeight()+1+i, z, i == stack-1 ? decorator.getBlockDataForTop(biome, getRng(), realX+i, realZ-i, getData()) : decorator.getBlockData100(biome, getRng(), realX+i, realZ-i, getData()));
}
}
}
}
}
}
}

View File

@@ -0,0 +1,49 @@
package com.volmit.iris.generator.decorator;
import com.volmit.iris.object.DecorationPart;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDecorator;
import com.volmit.iris.scaffold.cache.Cache;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.hunk.Hunk;
import org.bukkit.block.data.BlockData;
public class IrisShoreLineDecorator extends IrisEngineDecorator
{
public IrisShoreLineDecorator(Engine engine) {
super(engine, "Shore Line", DecorationPart.SHORE_LINE);
}
@Override
public void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
if(height == getDimension().getFluidHeight()) {
if (Math.round(getComplex().getHeightStream().get(realX1, realZ)) < getComplex().getFluidHeight() ||
Math.round(getComplex().getHeightStream().get(realX_1, realZ)) < getComplex().getFluidHeight() ||
Math.round(getComplex().getHeightStream().get(realX, realZ1)) < getComplex().getFluidHeight() ||
Math.round(getComplex().getHeightStream().get(realX, realZ_1)) < getComplex().getFluidHeight()
)
{
IrisDecorator decorator = getDecorator(biome, realX, realZ);
if(decorator != null)
{
if(!decorator.isStacking())
{
data.set(x, height+1, z, decorator.getBlockData100(biome, getRng(), realX, realZ, getData()));
}
else
{
int stack = Math.min(getRng().nextParallelRNG(Cache.key(realX, realZ)).i(decorator.getStackMin(), decorator.getStackMax()), max);
for(int i = 0; i < stack; i++)
{
data.set(x, height+1+i, z, i == stack-1 ? decorator.getBlockDataForTop(biome, getRng(), realX+i, realZ-i, getData()) : decorator.getBlockData100(biome, getRng(), realX+i, realZ-i, getData()));
}
}
}
}
}
}
}

View File

@@ -0,0 +1,74 @@
package com.volmit.iris.generator.decorator;
import com.volmit.iris.object.DecorationPart;
import com.volmit.iris.object.InferredType;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDecorator;
import com.volmit.iris.scaffold.cache.Cache;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.hunk.Hunk;
import org.bukkit.block.data.BlockData;
public class IrisSurfaceDecorator extends IrisEngineDecorator
{
public IrisSurfaceDecorator(Engine engine) {
super(engine, "Surface", DecorationPart.NONE);
}
@Override
public void decorate(int x, int z, int realX, int realX1, int realX_1, int realZ, int realZ1, int realZ_1, Hunk<BlockData> data, IrisBiome biome, int height, int max) {
if(biome.getInferredType().equals(InferredType.SHORE) && height < getDimension().getFluidHeight())
{
return;
}
BlockData bd;
IrisDecorator decorator = getDecorator(biome, realX, realZ);
if(decorator != null)
{
if(!decorator.isStacking())
{
bd = decorator.getBlockData100(biome, getRng(), realX, realZ, getData());
if(!canGoOn(bd, data.get(x, height, z)))
{
return;
}
data.set(x, height+1, z, bd);
}
else {
if (height < getDimension().getFluidHeight())
{
max = getDimension().getFluidHeight() - height;
}
int stack = Math.min(getRng().nextParallelRNG(Cache.key(realX, realZ)).i(decorator.getStackMin(), decorator.getStackMax()), max);
for(int i = 0; i < stack; i++)
{
bd = i == stack-1 ? decorator.getBlockDataForTop(biome, getRng(), realX+i, realZ-i, getData()) : decorator.getBlockData100(biome, getRng(), realX+i, realZ-i, getData());
if(bd == null && i == stack-1)
{
bd = decorator.getBlockData100(biome, getRng(), realX+i, realZ-i, getData());
}
if(bd == null)
{
return;
}
if(i == 0 && !canGoOn(bd, data.get(x, height, z)))
{
return;
}
data.set(x, height+1+i, z, bd);
}
}
}
}
}

View File

@@ -0,0 +1,490 @@
package com.volmit.iris.generator.legacy;
import java.util.Random;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.ChunkUnloadEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import com.volmit.iris.Iris;
import com.volmit.iris.generator.legacy.atomics.AtomicCache;
import com.volmit.iris.generator.legacy.atomics.AtomicMulticache;
import com.volmit.iris.generator.legacy.scaffold.GeneratedChunk;
import com.volmit.iris.generator.legacy.scaffold.IrisContext;
import com.volmit.iris.generator.legacy.scaffold.IrisMetrics;
import com.volmit.iris.generator.legacy.scaffold.Provisioned;
import com.volmit.iris.generator.legacy.scaffold.TerrainChunk;
import com.volmit.iris.generator.legacy.scaffold.TerrainProvider;
import com.volmit.iris.generator.legacy.scaffold.TerrainTarget;
import com.volmit.iris.scaffold.data.DataProvider;
import com.volmit.iris.manager.IrisDataManager;
import com.volmit.iris.generator.noise.CNG;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDimension;
import com.volmit.iris.object.IrisGenerator;
import com.volmit.iris.object.IrisObject;
import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.object.IrisStructure;
import com.volmit.iris.util.B;
import com.volmit.iris.util.BlockPosition;
import com.volmit.iris.util.C;
import com.volmit.iris.util.ChronoLatch;
import com.volmit.iris.util.J;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.KSet;
import com.volmit.iris.util.M;
import com.volmit.iris.util.RNG;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public abstract class ContextualTerrainProvider implements TerrainProvider, Listener, DataProvider
{
private Provisioned provisioner;
private KList<BlockPosition> noLoot;
private BlockPosition allowLoot;
private AtomicMulticache cache;
private IrisDataManager data;
private boolean failing;
private int task;
private boolean dev;
private volatile boolean initialized;
private RNG masterRandom;
private ChronoLatch perSecond;
private ChronoLatch tickLatch;
private ChronoLatch pushLatch;
private AtomicCache<IrisDimension> dimCache;
private IrisMetrics metrics;
private int generated;
private int ticks;
private long hlast;
private boolean fastPregen = false;
private boolean pregenDone;
private volatile boolean hotloadable = false;
private final TerrainTarget target;
private KSet<String> warnings;
public ContextualTerrainProvider()
{
this(null);
}
public ContextualTerrainProvider(TerrainTarget target)
{
metrics = new IrisMetrics(256);
warnings = new KSet<>();
this.target = target;
pushLatch = new ChronoLatch(3000);
tickLatch = new ChronoLatch(650);
perSecond = new ChronoLatch(1000);
hlast = M.ms();
cache = new AtomicMulticache((IrisTerrainProvider) this);
CNG.creates = 0;
generated = 0;
ticks = 0;
task = -1;
initialized = false;
allowLoot = new BlockPosition(0, 0, 0);
failing = false;
pregenDone = false;
dimCache = new AtomicCache<>();
dev = false;
noLoot = new KList<>(1285);
}
public void warn(String warning)
{
if(!isDev())
{
return;
}
warnings.add(warning);
}
protected abstract GeneratedChunk onGenerate(RNG masterRandom, int x, int z, TerrainChunk chunk);
protected abstract void onInit(RNG masterRandom);
protected abstract void onTick(int ticks);
protected abstract void onClose();
protected abstract void onFailure(Throwable e);
protected abstract void onChunkLoaded(Chunk c);
protected abstract void onChunkUnloaded(Chunk c);
protected abstract void onPlayerJoin(Player p);
protected abstract void onPlayerLeft(Player p);
public IrisRegion loadRegion(String i)
{
return getData().getRegionLoader().load(i);
}
public IrisBiome loadBiome(String i)
{
if(getData() == null)
{
return Iris.globaldata.getBiomeLoader().load(i);
}
return getData().getBiomeLoader().load(i);
}
public IrisStructure loadStructure(String i)
{
return getData().getStructureLoader().load(i);
}
public IrisObject loadObject(String i)
{
return getData().getObjectLoader().load(i);
}
public IrisDimension loadDimension(String i)
{
return getDimCache().aquire(() -> (getData() == null ? Iris.globaldata : getData()).getDimensionLoader().load(i));
}
public IrisGenerator loadGenerator(String i)
{
return getData().getGeneratorLoader().load(i);
}
public IrisDataManager getData()
{
return isDev() ? Iris.globaldata : data;
}
private void init(RNG rng)
{
if(initialized)
{
return;
}
setInitialized(true);
setData(new IrisDataManager(getTarget().getFolder()));
setMasterRandom(new RNG(getTarget().getSeed()));
setMetrics(new IrisMetrics(128));
setTask(Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, this::tick, 0, 0));
Bukkit.getServer().getPluginManager().registerEvents(this, Iris.instance);
onInit(masterRandom);
setHotloadable(true);
}
private void tick()
{
if(isDev())
{
if(getPerSecond().flip())
{
if(getGenerated() > (isFastPregen() ? 1950 : 770))
{
setPregenDone(true);
}
if(isPregenDone())
{
getMetrics().getPerSecond().put(generated);
setGenerated(0);
}
doCheckHotload();
if(getNoLoot().size() > 1024)
{
// noinspection ListRemoveInLoop
for(int i = 0; i < 64; i++)
{
getNoLoot().remove(0);
}
}
}
}
else
{
setPregenDone(true);
setFastPregen(false);
}
onTick(ticks++);
}
@EventHandler(priority = EventPriority.MONITOR)
public void on(EntitySpawnEvent e)
{
J.a(() -> onSpawn(e));
}
protected abstract void onSpawn(EntitySpawnEvent e);
@EventHandler(priority = EventPriority.MONITOR)
public void on(BlockBreakEvent e)
{
if(!getTarget().isWorld(e.getBlock().getWorld()))
{
return;
}
BlockPosition bp = new BlockPosition(e.getBlock().getX(), e.getBlock().getY(), e.getBlock().getZ());
if(!noLoot.contains(bp))
{
noLoot.add(bp);
if(e.isDropItems() && e.getPlayer().getGameMode().equals(GameMode.SURVIVAL))
{
allowLoot = new BlockPosition(e.getBlock().getX(), e.getBlock().getY(), e.getBlock().getZ());
}
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void on(BlockPlaceEvent e)
{
if(!getTarget().isWorld(e.getBlock().getWorld()))
{
return;
}
getNoLoot().addIfMissing(new BlockPosition(e.getBlock().getX(), e.getBlock().getY(), e.getBlock().getZ()));
}
@EventHandler(priority = EventPriority.MONITOR)
public void on(BlockDropItemEvent e)
{
if(!getTarget().isWorld(e.getBlock().getWorld()))
{
return;
}
BlockPosition bp = new BlockPosition(e.getBlock().getX(), e.getBlock().getY(), e.getBlock().getZ());
if(noLoot.contains(bp) && !allowLoot.equals(bp))
{
return;
}
handleDrops(e);
}
protected abstract void handleDrops(BlockDropItemEvent e);
@EventHandler(priority = EventPriority.MONITOR)
public void on(PlayerTeleportEvent e)
{
if(getTarget().isWorld(e.getFrom().getWorld()) && !getTarget().isWorld(e.getTo().getWorld()))
{
J.a(() -> onPlayerLeft(e.getPlayer()));
}
if(!getTarget().isWorld(e.getFrom().getWorld()) && getTarget().isWorld(e.getTo().getWorld()))
{
J.a(() -> onPlayerJoin(e.getPlayer()));
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void on(PlayerQuitEvent e)
{
if(getTarget().isWorld(e.getPlayer().getWorld()))
{
J.a(() -> onPlayerLeft(e.getPlayer()));
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void on(PlayerJoinEvent e)
{
if(getTarget().isWorld(e.getPlayer().getWorld()))
{
J.a(() -> onPlayerJoin(e.getPlayer()));
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void on(ChunkLoadEvent e)
{
if(getTarget().isWorld(e.getWorld()))
{
onChunkLoaded(e.getChunk());
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void on(ChunkUnloadEvent e)
{
if(getTarget().isWorld(e.getWorld()))
{
onChunkUnloaded(e.getChunk());
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void on(WorldUnloadEvent e)
{
if(getTarget().isWorld(e.getWorld()))
{
close();
}
}
public void close()
{
if(!isDev())
{
return;
}
getNoLoot().clear();
getNoLoot().trimToSize();
HandlerList.unregisterAll(this);
Bukkit.getScheduler().cancelTask(getTask());
onClose();
}
protected void generateFailure(TerrainChunk chunk)
{
for(int i = 0; i < 16; i++)
{
for(int j = 0; j < 16; j++)
{
int h = 0;
if(j == i || j + i == 16)
{
chunk.setBlock(i, h, j, B.getBlockData("RED_TERRACOTTA").getMaterial());
}
else
{
chunk.setBlock(i, h, j, B.getBlockData("BLACK_TERRACOTTA").getMaterial());
}
}
}
}
@Override
public GeneratedChunk generate(Random no, int x, int z, TerrainChunk terrain)
{
setHotloadable(false);
if(!isDev())
{
setPregenDone(true);
setFastPregen(false);
}
if(failing)
{
generateFailure(terrain);
return GeneratedChunk.builder().build();
}
try
{
RNG random = new RNG(getTarget().getSeed());
init(random.nextParallelRNG(0));
GeneratedChunk c = onGenerate(random, x, z, terrain);
generated++;
long hits = CNG.hits;
CNG.hits = 0;
Iris.instance.hit(hits);
setHotloadable(true);
return c;
}
catch(Throwable e)
{
fail(e);
}
setHotloadable(true);
generateFailure(terrain);
return GeneratedChunk.builder().build();
}
private void doCheckHotload()
{
if(!isHotloadable())
{
return;
}
if(M.ms() - getHlast() < 1000)
{
return;
}
if(getPushLatch().flip())
{
Iris.hotloader.check((IrisContext) this);
IrisContext.pushContext((IrisContext) this);
}
}
public void onHotload()
{
setHlast(M.ms());
getDimCache().reset();
}
protected void fail(Throwable e)
{
if(isFailing())
{
return;
}
setFailing(true);
e.printStackTrace();
J.a(() ->
{
J.sleep(1000);
Iris.error("---------------------------------------------------------------------------------------------------------");
e.printStackTrace();
Iris.error("---------------------------------------------------------------------------------------------------------");
Iris.error("ERROR! Failed to generate chunk! Iris has entered a failed state!");
Iris.error("---------------------------------------------------------------------------------------------------------");
for(Player i : getTarget().getPlayers())
{
Iris.instance.imsg(i, C.DARK_RED + "Iris Generator has crashed!");
Iris.instance.imsg(i, C.RED + "- Check the console for the error.");
Iris.instance.imsg(i, C.RED + "- To Regen, use /iris std open <dim>");
}
});
onFailure(e);
}
@Override
public boolean isParallelCapable()
{
return true;
}
}

View File

@@ -0,0 +1,193 @@
package com.volmit.iris.generator.legacy;
import java.io.File;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
import com.volmit.iris.Iris;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.generator.legacy.scaffold.TerrainTarget;
import com.volmit.iris.object.InferredType;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDimension;
import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.util.B;
import com.volmit.iris.util.MortarSender;
import com.volmit.iris.util.RNG;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public abstract class DimensionalTerrainProvider extends ContextualTerrainProvider
{
private String dimensionName;
private IrisDimension forceDimension;
protected static final BlockData AIR = Material.AIR.createBlockData();
protected static final BlockData CAVE_AIR = B.get("CAVE_AIR");
protected static final BlockData BEDROCK = Material.BEDROCK.createBlockData();
protected static final BlockData WATER = Material.WATER.createBlockData();
public DimensionalTerrainProvider(TerrainTarget t, String dimensionName)
{
super(t);
setDimensionName(dimensionName);
setForceDimension(null);
if(getDimensionName().isEmpty())
{
File folder = new File(getTarget().getFolder(), "iris/dimensions");
if(!folder.exists())
{
Iris.error("Missing World iris/dimensions folder! (" + folder.getAbsolutePath() + ")");
setDimensionName(IrisSettings.get().getDefaultWorldType());
Iris.proj.installIntoWorld(new MortarSender(Bukkit.getConsoleSender()), getDimensionName(), getTarget().getFolder());
return;
}
if(!folder.exists())
{
Iris.error("Missing World iris/dimensions folder! (" + folder.getAbsolutePath() + ")");
try
{
throw new RuntimeException("Cant find dimension data!");
}
catch(Throwable e)
{
fail(e);
}
return;
}
for(File i : folder.listFiles())
{
if(i.isFile() && i.getName().endsWith(".json"))
{
setDimensionName(i.getName().replaceAll("\\Q.json\\E", ""));
return;
}
}
if(!folder.exists())
{
Iris.error("Missing World iris/dimensions folder! (" + folder.getAbsolutePath() + ")");
try
{
throw new RuntimeException("Cant find dimension data!");
}
catch(Throwable e)
{
fail(e);
}
return;
}
}
try
{
getData().preferFolder(getDimension().getLoadFile().getParentFile().getParentFile().getName());
}
catch(Throwable ignored)
{
}
}
protected void forceDimension(IrisDimension sky)
{
setForceDimension(sky);
}
protected void useDefaultDimensionSetupNOW()
{
}
public void onPlayerLeft(Player p)
{
}
public void onTick(int m)
{
getData().preferFolder(getDimension().getLoadFile().getParentFile().getParentFile().getName());
}
public void onInit(RNG masterRandom)
{
if(getDimension().hasSky())
{
getDimension().getSky().setSkyDimension(true);
}
}
public IrisDimension getDimension()
{
if(forceDimension != null)
{
return forceDimension;
}
IrisDimension d = loadDimension(getDimensionName());
return d;
}
protected IrisBiome focus()
{
IrisBiome biome = loadBiome(getDimension().getFocus());
for(String i : getDimension().getRegions())
{
IrisRegion reg = loadRegion(i);
if(reg.getLandBiomes().contains(biome.getLoadKey()))
{
biome.setInferredType(InferredType.LAND);
break;
}
if(reg.getSeaBiomes().contains(biome.getLoadKey()))
{
biome.setInferredType(InferredType.SEA);
break;
}
if(reg.getShoreBiomes().contains(biome.getLoadKey()))
{
biome.setInferredType(InferredType.SHORE);
break;
}
}
return biome;
}
public double getModifiedX(int rx, int rz)
{
return (getDimension().cosRotate() * rx) + (-getDimension().sinRotate() * rz) + getDimension().getCoordFracture(getMasterRandom(), 39392).fitDouble(-getDimension().getCoordFractureDistance() / 2, getDimension().getCoordFractureDistance() / 2, rx, rz);
}
public double getModifiedZ(int rx, int rz)
{
return (getDimension().sinRotate() * rx) + (getDimension().cosRotate() * rz) + getDimension().getCoordFracture(getMasterRandom(), 39392).fitDouble(-getDimension().getCoordFractureDistance() / 2, getDimension().getCoordFractureDistance() / 2, rx, rz);
}
public double getZoomed(double modified)
{
return modified / getDimension().getTerrainZoom();
}
public double getUnzoomed(double modified)
{
return modified * getDimension().getTerrainZoom();
}
}

View File

@@ -0,0 +1,740 @@
package com.volmit.iris.generator.legacy;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.BlockVector;
import com.volmit.iris.Iris;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.generator.legacy.atomics.AtomicRegionData;
import com.volmit.iris.generator.legacy.scaffold.GeneratedChunk;
import com.volmit.iris.generator.legacy.scaffold.IrisContext;
import com.volmit.iris.generator.legacy.scaffold.IrisGenConfiguration;
import com.volmit.iris.generator.legacy.scaffold.TerrainChunk;
import com.volmit.iris.generator.legacy.scaffold.TerrainTarget;
import com.volmit.iris.manager.gui.Renderer;
import com.volmit.iris.generator.noise.CNG;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisBlockDrops;
import com.volmit.iris.object.IrisDimension;
import com.volmit.iris.object.IrisEffect;
import com.volmit.iris.object.IrisEntityInitialSpawn;
import com.volmit.iris.object.IrisEntitySpawnOverride;
import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.util.Form;
import com.volmit.iris.util.IrisStructureResult;
import com.volmit.iris.util.J;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.M;
import com.volmit.iris.util.O;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RNG;
import com.volmit.iris.util.Spiraler;
import io.papermc.lib.PaperLib;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class IrisTerrainProvider extends PostBlockTerrainProvider implements IrisContext
{
private IrisBiome hb = null;
private IrisRegion hr = null;
private boolean spawnable = false;
public IrisTerrainProvider(IrisGenConfiguration config)
{
super(config.getTarget(), config.getDimension(), config.getThreads());
}
public IrisTerrainProvider(TerrainTarget t, String dimensionName, int threads)
{
super(t, dimensionName, threads);
}
public IrisTerrainProvider(TerrainTarget t, String dimensionName)
{
super(t, dimensionName, 16);
}
public IrisTerrainProvider(TerrainTarget t, int tc)
{
super(t, "", tc);
}
public void hotload()
{
onHotload();
}
public void retry()
{
if(isFailing())
{
setFailing(false);
hotload();
}
}
@Override
public GeneratedChunk generate(Random no, int x, int z, TerrainChunk terrain)
{
PrecisionStopwatch s = PrecisionStopwatch.start();
GeneratedChunk c = super.generate(no, x, z, terrain);
s.end();
getMetrics().getTotal().put(s.getMilliseconds());
return c;
}
@Override
protected GeneratedChunk onGenerate(RNG random, int x, int z, TerrainChunk terrain)
{
return super.onGenerate(random, x, z, terrain);
}
public void onInit(RNG rng)
{
try
{
super.onInit(rng);
}
catch(Throwable e)
{
fail(e);
}
}
@Override
public IrisBiome getBiome(int x, int z)
{
return sampleBiome(x, z);
}
@Override
public IrisRegion getRegion(int x, int z)
{
return sampleRegion(x, z);
}
@Override
public int getHeight(int x, int z)
{
return sampleHeight(x, z);
}
@Override
public void onTick(int ticks)
{
spawnable = true;
super.onTick(ticks);
try
{
tickEffects();
}
catch(Throwable e)
{
}
}
protected void tickEffects()
{
if(!IrisSettings.get().isSystemEffects())
{
return;
}
for(Player i : getTarget().getPlayers())
{
Location l = i.getLocation();
IrisRegion r = sampleRegion(l.getBlockX(), l.getBlockZ());
IrisBiome b = sampleTrueBiome(l.getBlockX(), l.getBlockY(), l.getBlockZ());
for(IrisEffect j : r.getEffects())
{
j.apply(i, this);
}
for(IrisEffect j : b.getEffects())
{
j.apply(i, this);
}
}
}
@Override
protected void onClose()
{
super.onClose();
try
{
getParallaxMap().saveAll();
getParallaxMap().getLoadedChunks().clear();
getParallaxMap().getLoadedRegions().clear();
}
catch(IOException e)
{
e.printStackTrace();
}
setSliverCache(null);
Iris.info("Closing Iris Dimension " + getTarget().getName());
}
@Override
protected void onFailure(Throwable e)
{
}
@Override
protected void onChunkLoaded(Chunk c)
{
}
@Override
protected void onChunkUnloaded(Chunk c)
{
}
@Override
protected void onPlayerJoin(Player p)
{
if(getDimension().getResourcePack().trim().isEmpty())
{
return;
}
p.setResourcePack(getDimension().getResourcePack());
}
@Override
public void onPlayerLeft(Player p)
{
super.onPlayerLeft(p);
}
@Override
public void onHotloaded()
{
if(!IrisSettings.get().isStudio())
{
return;
}
if(!isHotloadable())
{
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, this::onHotloaded);
return;
}
CNG.creates = 0;
getData().dump();
getCache().drop();
onHotload();
Iris.proj.updateWorkspace();
}
public long guessMemoryUsage()
{
long bytes = 1024 * 1024 * (8 + (getThreads() / 3));
for(AtomicRegionData i : getParallaxMap().getLoadedRegions().values())
{
bytes += i.guessMemoryUsage();
}
bytes += getCache().getSize() * 65;
bytes += getParallaxMap().getLoadedChunks().size() * 256 * 4 * 460;
bytes += getSliverBuffer() * 220;
bytes += 823 * getData().getObjectLoader().getTotalStorage();
return bytes / 2;
}
public Renderer createRenderer()
{
return this::render;
}
public Color render(double x, double z)
{
if(!IrisSettings.get().pregenRenderTerrain)
{
return Color.blue;
}
int ix = (int) x;
int iz = (int) z;
double height = getTerrainHeight(ix, iz);
IrisRegion region = sampleRegion(ix, iz);
IrisBiome biome = sampleTrueBiome(ix, iz);
if(biome.getCachedColor() != null)
{
return biome.getCachedColor();
}
float shift = (biome.hashCode() % 32) / 32f / 14f;
float shift2 = (region.hashCode() % 9) / 9f / 14f;
shift -= shift2;
float sat = 0;
float h = (biome.isLand() ? 0.233f : 0.644f) - shift;
float s = 0.25f + shift + sat;
float b = (float) (Math.max(0, Math.min(height + getFluidHeight(), 255)) / 255);
return Color.getHSBColor(h, s, b);
}
public String textFor(double x, double z)
{
int ix = (int) x;
int iz = (int) z;
double height = getTerrainHeight(ix, iz);
IrisRegion region = sampleRegion(ix, iz);
IrisBiome biome = sampleTrueBiome(ix, iz);
hb = biome;
hr = region;
return biome.getName() + " (" + Form.capitalizeWords(biome.getInferredType().name().toLowerCase().replaceAll("\\Q_\\E", " ") + ") in " + region.getName() + "\nY: " + (int) height);
}
public void saveAllParallax()
{
try
{
getParallaxMap().saveAll();
}
catch(IOException e)
{
e.printStackTrace();
}
}
@Override
protected void handleDrops(BlockDropItemEvent e)
{
int x = e.getBlock().getX();
int y = e.getBlock().getY();
int z = e.getBlock().getZ();
IrisDimension dim = getDimension();
IrisRegion reg = sampleRegion(x, z);
IrisBiome bio = sampleTrueBiome(x, z);
IrisBiome cbio = y < getFluidHeight() ? sampleTrueBiome(x, y, z) : null;
if(bio.equals(cbio))
{
cbio = null;
}
if(dim.getBlockDrops().isEmpty() && reg.getBlockDrops().isEmpty() && bio.getBlockDrops().isEmpty())
{
return;
}
BlockData data = e.getBlockState().getBlockData();
KList<ItemStack> drops = new KList<>();
boolean skipParents = false;
if(cbio != null)
{
for(IrisBlockDrops i : cbio.getBlockDrops())
{
if(i.shouldDropFor(data, getData()))
{
if(!skipParents && i.isSkipParents())
{
skipParents = true;
}
if(i.isReplaceVanillaDrops())
{
e.getItems().clear();
}
i.fillDrops(isDev(), drops);
}
}
}
if(!skipParents)
{
for(IrisBlockDrops i : bio.getBlockDrops())
{
if(i.shouldDropFor(data, getData()))
{
if(!skipParents && i.isSkipParents())
{
skipParents = true;
}
if(i.isReplaceVanillaDrops())
{
e.getItems().clear();
}
i.fillDrops(isDev(), drops);
}
}
}
if(!skipParents)
{
for(IrisBlockDrops i : reg.getBlockDrops())
{
if(i.shouldDropFor(data, getData()))
{
if(!skipParents && i.isSkipParents())
{
skipParents = true;
}
if(i.isReplaceVanillaDrops())
{
e.getItems().clear();
}
i.fillDrops(isDev(), drops);
}
}
}
if(!skipParents)
{
for(IrisBlockDrops i : dim.getBlockDrops())
{
if(i.shouldDropFor(data, getData()))
{
if(i.isReplaceVanillaDrops())
{
e.getItems().clear();
}
i.fillDrops(isDev(), drops);
}
}
}
if(drops.isNotEmpty())
{
Location l = e.getBlock().getLocation();
for(ItemStack i : drops)
{
e.getBlock().getWorld().dropItemNaturally(l, i);
}
}
}
public void spawnInitials(Chunk c, RNG rng)
{
int x = (c.getX() * 16) + rng.nextInt(15);
int z = (c.getZ() * 16) + rng.nextInt(15);
int y = getCarvedHeight(x, z) + 1;
IrisDimension dim = getDimension();
IrisRegion region = sampleRegion(x, z);
IrisBiome above = sampleTrueBiome(x, z);
IrisStructureResult res = getStructure(x, y, z);
if(res != null && res.getTile() != null)
{
trySpawn(res.getTile().getEntityInitialSpawns(), c, rng);
}
if(res != null && res.getStructure() != null)
{
trySpawn(res.getStructure().getEntityInitialSpawns(), c, rng);
}
trySpawn(above.getEntityInitialSpawns(), c, rng);
trySpawn(region.getEntityInitialSpawns(), c, rng);
trySpawn(dim.getEntityInitialSpawns(), c, rng);
}
@Override
public BlockVector computeSpawn(Function<BlockVector, Boolean> allowed)
{
RNG r = new RNG(489886222).nextParallelRNG(-293667771);
int x = 0;
int y = 0;
int z = 0;
for(int i = 0; i < 64; i++)
{
x = r.i(-64 - (i * 2), 64 + (i * 2));
z = r.i(-64 - (i * 2), 64 + (i * 2));
y = (int) Math.round(getTerrainHeight(x, z));
BlockVector b = new BlockVector(x, y, z);
if(y <= getFluidHeight() || !allowed.apply(b))
{
continue;
}
return b;
}
return new BlockVector(x, y, z);
}
@Override
protected void onSpawn(EntitySpawnEvent e)
{
if(getTarget().getRealWorld() == null || !getTarget().getRealWorld().equals(e.getEntity().getWorld()))
{
return;
}
try
{
if(!IrisSettings.get().isSystemEntitySpawnOverrides())
{
return;
}
int x = e.getEntity().getLocation().getBlockX();
int y = e.getEntity().getLocation().getBlockY();
int z = e.getEntity().getLocation().getBlockZ();
J.a(() ->
{
if(isSpawnable())
{
IrisDimension dim = getDimension();
IrisRegion region = sampleRegion(x, z);
IrisBiome above = sampleTrueBiome(x, z);
IrisBiome bbelow = sampleTrueBiome(x, y, z);
IrisStructureResult res = getStructure(x, y, z);
if(above.getLoadKey().equals(bbelow.getLoadKey()))
{
bbelow = null;
}
IrisBiome below = bbelow;
J.s(() ->
{
if(res != null && res.getTile() != null)
{
if(trySpawn(res.getTile().getEntitySpawnOverrides(), e))
{
return;
}
}
if(res != null && res.getStructure() != null)
{
if(trySpawn(res.getStructure().getEntitySpawnOverrides(), e))
{
return;
}
}
if(below != null)
{
if(trySpawn(below.getEntitySpawnOverrides(), e))
{
return;
}
}
if(trySpawn(above.getEntitySpawnOverrides(), e))
{
return;
}
if(trySpawn(region.getEntitySpawnOverrides(), e))
{
return;
}
if(trySpawn(dim.getEntitySpawnOverrides(), e))
{
return;
}
});
}
});
}
catch(Throwable xe)
{
}
}
private boolean trySpawn(KList<IrisEntitySpawnOverride> s, EntitySpawnEvent e)
{
for(IrisEntitySpawnOverride i : s)
{
setSpawnable(false);
if(i.on(this, e.getLocation(), e.getEntityType(), e) != null)
{
e.setCancelled(true);
e.getEntity().remove();
return true;
}
else
{
setSpawnable(true);
}
}
return false;
}
private void trySpawn(KList<IrisEntityInitialSpawn> s, Chunk c, RNG rng)
{
for(IrisEntityInitialSpawn i : s)
{
i.spawn(this, c, rng);
}
}
@Override
public boolean canSpawn(int x, int z)
{
return true;
}
@Override
public boolean shouldGenerateCaves()
{
if(getDimension() == null)
{
return false;
}
return getDimension().isVanillaCaves();
}
@Override
public boolean shouldGenerateVanillaStructures()
{
if(getDimension() == null)
{
return true;
}
return getDimension().isVanillaStructures();
}
@Override
public boolean shouldGenerateMobs()
{
return false;
}
@Override
public boolean shouldGenerateDecorations()
{
return true;
}
public File[] scrapeRegion(int x, int z, Consumer<Double> progress)
{
int minX = x << 5;
int minZ = z << 5;
int maxX = x + 31;
int maxZ = z + 31;
AtomicInteger outputs = new AtomicInteger(0);
new Spiraler(36, 36, (vx, vz) ->
{
int ax = vx + 16 + minX;
int az = vz + 16 + minZ;
if(ax > maxX || ax < minX || az > maxZ || az < minZ)
{
return;
}
PaperLib.getChunkAtAsyncUrgently(getTarget().getRealWorld(), ax, az, true).thenAccept((c) ->
{
outputs.addAndGet(1);
});
}).drain();
long ms = M.ms();
int lastChange = outputs.get();
while(outputs.get() != 1024)
{
J.sleep(1000);
if(outputs.get() != lastChange)
{
lastChange = outputs.get();
ms = M.ms();
progress.accept((double) lastChange / 1024D);
}
if(outputs.get() == lastChange && M.ms() - ms > 60000)
{
Iris.error("Cant get this chunk region waited 60 seconds!");
break;
}
}
progress.accept(1D);
O<Boolean> b = new O<Boolean>();
b.set(false);
J.s(() ->
{
getTarget().getRealWorld().save();
Iris.instance.getServer().dispatchCommand(Bukkit.getConsoleSender(), "save-all");
b.set(true);
});
try
{
getParallaxMap().saveAll();
}
catch(IOException e)
{
e.printStackTrace();
}
while(!b.get())
{
J.sleep(10);
}
File r = new File(getTarget().getRealWorld().getWorldFolder(), "region/r." + x + "." + z + ".mca");
File p = new File(getTarget().getRealWorld().getWorldFolder(), "parallax/sr." + x + "." + z + ".smca");
if(r.exists() && p.exists())
{
return new File[] {r, p};
}
return null;
}
}

View File

@@ -0,0 +1,531 @@
package com.volmit.iris.generator.legacy;
import com.volmit.iris.Iris;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.generator.legacy.atomics.AtomicSliver;
import com.volmit.iris.generator.legacy.atomics.AtomicSliverMap;
import com.volmit.iris.generator.legacy.atomics.AtomicWorldData;
import com.volmit.iris.generator.legacy.atomics.MasterLock;
import com.volmit.iris.generator.legacy.layer.GenLayerText;
import com.volmit.iris.generator.legacy.layer.GenLayerUpdate;
import com.volmit.iris.generator.legacy.scaffold.TerrainChunk;
import com.volmit.iris.generator.legacy.scaffold.TerrainTarget;
import com.volmit.iris.object.*;
import com.volmit.iris.util.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
import org.bukkit.generator.BlockPopulator;
import java.io.IOException;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = false)
public abstract class ParallaxTerrainProvider extends TopographicTerrainProvider implements IObjectPlacer
{
private short cacheID = 0;
private KMap<ChunkPosition, AtomicSliver> sliverCache;
private AtomicWorldData parallaxMap;
private MasterLock masterLock;
private IrisLock flock = new IrisLock("ParallaxLock");
private IrisLock lock = new IrisLock("ParallaxLock");
private GenLayerUpdate glUpdate;
private GenLayerText glText;
private int sliverBuffer;
public ParallaxTerrainProvider(TerrainTarget t, String dimensionName, int threads)
{
super(t, dimensionName, threads);
setSliverCache(new KMap<>());
setSliverBuffer(sliverBuffer);
setMasterLock(new MasterLock());
getMasterLock().disable();
}
public void onInit(RNG rng)
{
super.onInit(rng);
setParallaxMap(new AtomicWorldData(getTarget()));
setGlText(new GenLayerText(this, rng.nextParallelRNG(32485)));
setGlUpdate(null);
J.a(() -> getDimension().getParallaxSize(this));
}
protected void onClose()
{
super.onClose();
try
{
getParallaxMap().unloadAll(true);
}
catch(IOException e)
{
e.printStackTrace();
}
}
@Override
public int getHighest(int x, int z)
{
return getHighest(x, z, false);
}
@Override
public void onHotload()
{
getData().preferFolder(getDimension().getLoadFile().getParentFile().getParentFile().getName());
super.onHotload();
setCacheID(RNG.r.simax());
if(IrisSettings.get().isRegenerateLoadedChunksOnHotload())
{
World w = getTarget().getRealWorld();
if(w != null)
{
for(Player i : w.getPlayers())
{
new Spiraler(10, 10, (a, b) -> getProvisioner().regenerate(i.getLocation().getChunk().getX() + a, i.getLocation().getChunk().getZ() + b)).drain();
}
for(Chunk i : w.getLoadedChunks())
{
getProvisioner().regenerate(i.getX(), i.getZ());
}
}
}
}
@Override
public int getHighest(int x, int z, boolean ignoreFluid)
{
return getCarvedHeight(x, z, ignoreFluid);
}
@Override
public void set(int x, int y, int z, BlockData d)
{
getParallaxSliver(x, z).set(y, d);
}
@Override
public BlockData get(int x, int y, int z)
{
BlockData b = sampleSliver(x, z).getBlock()[y];
return b == null ? AIR : b;
}
@Override
public boolean isSolid(int x, int y, int z)
{
return get(x, y, z).getMaterial().isSolid();
}
public AtomicSliver getParallaxSliver(int wx, int wz)
{
getMasterLock().lock("gpc");
getMasterLock().lock((wx >> 4) + "." + (wz >> 4));
AtomicSliverMap map = getParallaxChunk(wx >> 4, wz >> 4);
getMasterLock().unlock("gpc");
AtomicSliver sliver = map.getSliver(wx & 15, wz & 15);
getMasterLock().unlock((wx >> 4) + "." + (wz >> 4));
return sliver;
}
public boolean isParallaxGenerated(int x, int z)
{
return getParallaxChunk(x, z).isParallaxGenerated();
}
public boolean isWorldGenerated(int x, int z)
{
return getParallaxChunk(x, z).isWorldGenerated();
}
public AtomicSliverMap getParallaxChunk(int x, int z)
{
try
{
if(getParallaxMap() == null)
{
if(getTarget() == null)
{
Iris.warn("Parallax map was accessed before init! Serving a dummy chunk!");
return new AtomicSliverMap();
}
else
{
setParallaxMap(new AtomicWorldData(getTarget()));
}
}
return getParallaxMap().loadChunk(x, z);
}
catch(IOException e)
{
fail(e);
}
return new AtomicSliverMap();
}
public void initGLUpdate()
{
if(getGlUpdate() == null)
{
setGlUpdate(new GenLayerUpdate(this));
}
}
@Override
public List<BlockPopulator> getPopulators()
{
List<BlockPopulator> g = new KList<>();
initGLUpdate();
g.add(getGlUpdate());
return g;
}
public void forgetThisParallaxChunk(int x, int z)
{
getParallaxChunk(x, z).reset();
getSliverCache().clear();
getCache().drop();
}
public void forgetParallaxChunksNear(int x, int z)
{
getSliverCache().clear();
getCache().drop();
ChunkPosition rad = getDimension().getParallaxSize(this);
for(int ii = x - (rad.getX() / 2); ii <= x + (rad.getX() / 2); ii++)
{
for(int jj = z - (rad.getZ() / 2); jj <= z + (rad.getZ() / 2); jj++)
{
getParallaxChunk(ii, jj).reset();
}
}
}
@Override
protected void onPostGenerate(RNG random, int x, int z, TerrainChunk terrain, HeightMap height, BiomeMap biomeMap, AtomicSliverMap map)
{
if(getSliverCache().size() > 20000)
{
getSliverCache().clear();
}
super.onPostGenerate(random, x, z, terrain, height, biomeMap, map);
PrecisionStopwatch p = PrecisionStopwatch.start();
if(getDimension().isPlaceObjects())
{
onGenerateParallax(random, x, z);
getParallaxChunk(x, z).inject(terrain);
getParallaxChunk(x, z).injectUpdates(map);
getParallaxChunk(x, z).setWorldGenerated(true);
}
setSliverBuffer(getSliverCache().size());
getMasterLock().clear();
p.end();
getMetrics().getParallax().put(p.getMilliseconds());
super.onPostParallaxPostGenerate(random, x, z, terrain, height, biomeMap, map);
getParallaxMap().clean();
getData().getObjectLoader().clean();
}
public IrisStructureResult getStructure(int x, int y, int z)
{
return getParallaxChunk(x >> 4, z >> 4).getStructure(this, y);
}
protected void onGenerateParallax(RNG randomx, int x, int z)
{
String key = "par." + x + "." + z;
ChunkPosition rad = getDimension().getParallaxSize(this);
for(int ii = x - (rad.getX() / 2); ii <= x + (rad.getX() / 2); ii++)
{
int i = ii;
for(int jj = z - (rad.getZ() / 2); jj <= z + (rad.getZ() / 2); jj++)
{
int j = jj;
RNG salt = new RNG(2922 + i + j).nextParallelRNG(i - 293938).nextParallelRNG(j + 294416);
RNG random = getMasterRandom().nextParallelRNG(i + salt.imax()).nextParallelRNG(j + salt.imax());
if(isParallaxGenerated(ii, jj))
{
continue;
}
if(isWorldGenerated(ii, jj))
{
continue;
}
getAccelerant().queue(key, () ->
{
IrisBiome b = sampleTrueBiome((i * 16) + 7, (j * 16) + 7);
IrisRegion r = sampleRegion((i * 16) + 7, (j * 16) + 7);
RNG ro = getMasterRandom().nextParallelRNG(196888 + i + j + 2225).nextParallelRNG(salt.i(-i, i)).nextParallelRNG(salt.i(-j, j));
int g = 1;
g = placeMutations(ro, random, i, j, g);
g = placeText(random, r, b, i, j, g);
g = placeObjects(random, r, b, i, j, g);
g = placeCarveObjects(random, r, b, i, j, g);
g = placeCaveObjects(ro, random, i, j, g);
g = placeStructures(randomx, r, b, i, j, g);
});
getParallaxChunk(ii, jj).setParallaxGenerated(true);
}
}
getAccelerant().waitFor(key);
}
private int placeMutations(RNG ro, RNG random, int i, int j, int g)
{
searching: for(IrisBiomeMutation k : getDimension().getMutations())
{
for(int l = 0; l < k.getChecks(); l++)
{
IrisBiome sa = sampleTrueBiome(((i * 16) + ro.nextInt(16)) + ro.i(-k.getRadius(), k.getRadius()), ((j * 16) + ro.nextInt(16)) + ro.i(-k.getRadius(), k.getRadius()));
IrisBiome sb = sampleTrueBiome(((i * 16) + ro.nextInt(16)) + ro.i(-k.getRadius(), k.getRadius()), ((j * 16) + ro.nextInt(16)) + ro.i(-k.getRadius(), k.getRadius()));
if(sa.getLoadKey().equals(sb.getLoadKey()))
{
continue;
}
if(k.getRealSideA(this).contains(sa.getLoadKey()) && k.getRealSideB(this).contains(sb.getLoadKey()))
{
for(IrisObjectPlacement m : k.getObjects())
{
placeObject(m, i, j, random.nextParallelRNG((34 * ((i * 30) + (j * 30) + g++) * i * j) + i - j + 1569962));
}
continue searching;
}
}
}
return g;
}
private int placeText(RNG random, IrisRegion r, IrisBiome b, int i, int j, int g)
{
for(IrisTextPlacement k : getDimension().getText())
{
k.place(this, random.nextParallelRNG(g++ + -7228 + (34 * ((i * 30) + (j * 30)) * i * j) + i - j + 1569962), i, j);
}
for(IrisTextPlacement k : r.getText())
{
k.place(this, random.nextParallelRNG(g++ + -4228 + -7228 + (34 * ((i * 30) + (j * 30)) * i * j) + i - j + 1569962), i, j);
}
for(IrisTextPlacement k : b.getText())
{
k.place(this, random.nextParallelRNG(g++ + -22228 + -4228 + -7228 + (34 * ((i * 30) + (j * 30)) * i * j) + i - j + 1569962), i, j);
}
return g;
}
private int placeObjects(RNG random, IrisRegion r, IrisBiome b, int i, int j, int g)
{
for(IrisObjectPlacement k : b.getSurfaceObjects())
{
placeObject(k, i, j, random.nextParallelRNG((34 * ((i * 30) + (j * 30) + g++) * i * j) + i - j + 3566522));
}
if(r == null)
{
Iris.error("R Null");
}
if(r.getSurfaceObjects() == null)
{
Iris.error("Surface objects null");
}
if(r != null)
{
for(IrisObjectPlacement k : r.getSurfaceObjects())
{
placeObject(k, i, j, random.nextParallelRNG((34 * ((i * 30) + (j * 30) + g++) * i * j) + i - j + 3569222));
}
}
return g;
}
private int placeCarveObjects(RNG random, IrisRegion r, IrisBiome b, int i, int j, int g)
{
if(!getGlCarve().isCouldCarve())
{
return g;
}
KList<CarveResult> layers = getGlCarve().getCarveLayers((i * 16) + random.nextInt(16), (j * 16) + random.nextInt(16));
if(layers.isEmpty())
{
return g + 2;
}
for(CarveResult c : layers)
{
g = placeCarveObjects(random, r, b, i, j, g, c);
}
return g;
}
private int placeCarveObjects(RNG random, IrisRegion r, IrisBiome b, int i, int j, int g, CarveResult c)
{
for(IrisObjectPlacement k : b.getCarvingObjects())
{
placeCarveObject(k, i, j, random.nextParallelRNG((34 * ((i * 30) + (j * 30) + g++) * i * j) + i - j + 3569221 + g), c);
}
for(IrisObjectPlacement k : r.getCarvingObjects())
{
placeCarveObject(k, i, j, random.nextParallelRNG((34 * ((i * 30) + (j * 30) + g++) * i * j) + i - j + 3561222 + g), c);
}
return g;
}
private int placeCaveObjects(RNG ro, RNG random, int i, int j, int g)
{
if(!getDimension().isCaves())
{
return g;
}
int bx = (i * 16) + ro.nextInt(16);
int bz = (j * 16) + ro.nextInt(16);
IrisBiome biome = sampleCaveBiome(bx, bz);
if(biome == null)
{
return g;
}
if(biome.getObjects().isEmpty())
{
return g;
}
for(IrisObjectPlacement k : biome.getObjects())
{
int gg = g++;
placeCaveObject(k, i, j, random.nextParallelRNG((34 * ((i * 30) + (j * 30) + gg) * i * j) + i - j + 1869322));
}
return g;
}
private int placeStructures(RNG random, IrisRegion r, IrisBiome b, int i, int j, int g)
{
for(IrisStructurePlacement k : r.getStructures())
{
if(k == null)
{
continue;
}
k.place(this, random.nextParallelRNG(2228 * 2 * g++), i, j);
}
for(IrisStructurePlacement k : b.getStructures())
{
if(k == null)
{
continue;
}
k.place(this, random.nextParallelRNG(-22228 * 4 * g++), i, j);
}
return g;
}
public void placeObject(IrisObjectPlacement o, int x, int z, RNG rng)
{
for(int i = 0; i < o.getTriesForChunk(rng); i++)
{
rng = rng.nextParallelRNG((i * 3 + 8) - 23040);
o.getSchematic(this, rng).place((x * 16) + rng.nextInt(16), (z * 16) + rng.nextInt(16), this, o, rng, getData());
}
}
public void placeCarveObject(IrisObjectPlacement o, int x, int z, RNG rng, CarveResult c)
{
for(int i = 0; i < o.getTriesForChunk(rng); i++)
{
rng = rng.nextParallelRNG((i * 3 + 8) - 23040);
o.getSchematic(this, rng).place((x * 16) + rng.nextInt(16), (z * 16) + rng.nextInt(16), this, o, rng, c, getData());
}
}
public void placeCaveObject(IrisObjectPlacement o, int x, int z, RNG rng)
{
for(int i = 0; i < o.getTriesForChunk(rng); i++)
{
rng = rng.nextParallelRNG((i * 3 + 8) - 23040);
int xx = (x * 16) + rng.nextInt(16);
int zz = (z * 16) + rng.nextInt(16);
KList<CaveResult> res = getCaves(xx, zz);
if(res.isEmpty())
{
continue;
}
o.getSchematic(this, rng).place(xx, res.get(rng.nextParallelRNG(29345 * (i + 234)).nextInt(res.size())).getFloor() + 2, zz, this, o, rng, getData());
}
}
public AtomicSliver sampleSliver(int x, int z)
{
ChunkPosition key = new ChunkPosition(x, z);
if(getSliverCache().containsKey(key))
{
return getSliverCache().get(key);
}
AtomicSliver s = new AtomicSliver(x & 15, z & 15);
onGenerateColumn(x >> 4, z >> 4, x, z, x & 15, z & 15, s, null, true);
getSliverCache().put(key, s);
return s;
}
@Override
public boolean isDebugSmartBore()
{
return getDimension().isDebugSmartBore();
}
@Override
public boolean isPreventingDecay()
{
return getDimension().isPreventLeafDecay();
}
}

View File

@@ -0,0 +1,131 @@
package com.volmit.iris.generator.legacy;
import com.volmit.iris.Iris;
import com.volmit.iris.generator.legacy.atomics.AtomicSliver;
import com.volmit.iris.generator.legacy.atomics.AtomicSliverMap;
import com.volmit.iris.generator.legacy.scaffold.GeneratedChunk;
import com.volmit.iris.generator.legacy.scaffold.TerrainChunk;
import com.volmit.iris.generator.legacy.scaffold.TerrainTarget;
import com.volmit.iris.util.BiomeMap;
import com.volmit.iris.util.GroupedExecutor;
import com.volmit.iris.util.HeightMap;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RNG;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public abstract class ParallelTerrainProvider extends DimensionalTerrainProvider
{
private GroupedExecutor accelerant;
private int threads;
private boolean cachingAllowed;
public ParallelTerrainProvider(TerrainTarget t, String dimensionName, int threads)
{
super(t, dimensionName);
setThreads(threads);
setCachingAllowed(false);
}
public void changeThreadCount(int tc)
{
setThreads(tc);
GroupedExecutor e = getAccelerant();
setAccelerant(new GroupedExecutor(threads, Thread.MAX_PRIORITY, "Iris Generator - " + getTarget().getName()));
Iris.executors.add(getAccelerant());
if(e != null)
{
e.close();
}
Iris.info("Thread Count changed to " + getThreads());
}
public int getThreadCount(){
return getThreads();
}
protected abstract int onGenerateColumn(int cx, int cz, int wx, int wz, int x, int z, AtomicSliver sliver, BiomeMap biomeMap, boolean sampled);
protected void onGenerateColumn(int cx, int cz, int wx, int wz, int x, int z, AtomicSliver sliver, BiomeMap biomeMap)
{
onGenerateColumn(cx, cz, wx, wz, x, z, sliver, biomeMap, false);
}
protected abstract int onSampleColumnHeight(int cx, int cz, int wx, int wz, int x, int z);
protected abstract void onPostGenerate(RNG random, int x, int z, TerrainChunk terrain, HeightMap height, BiomeMap biomeMap, AtomicSliverMap map);
protected abstract void onPreGenerate(RNG random, int x, int z, TerrainChunk terrain, HeightMap height, BiomeMap biomeMap, AtomicSliverMap map);
protected int sampleHeight(int x, int z)
{
return onSampleColumnHeight(x >> 4, z >> 4, x, z, x & 15, z & 15);
}
protected GeneratedChunk onGenerate(RNG random, int x, int z, TerrainChunk terrain)
{
PrecisionStopwatch p = PrecisionStopwatch.start();
AtomicSliverMap map = new AtomicSliverMap();
HeightMap height = new HeightMap();
String key = "c" + x + "," + z;
BiomeMap biomeMap = new BiomeMap();
int ii;
onPreGenerate(random, x, z, terrain, height, biomeMap, map);
for(ii = 0; ii < 16; ii++)
{
int i = ii;
int wx = (x * 16) + i;
getAccelerant().queue(key, () ->
{
for(int jj = 0; jj < 16; jj++)
{
int j = jj;
int wz = (z * 16) + j;
AtomicSliver sliver = map.getSliver(i, j);
try
{
onGenerateColumn(x, z, wx, wz, i, j, sliver, biomeMap);
}
catch(Throwable e)
{
fail(e);
}
}
});
}
accelerant.waitFor(key);
map.write(terrain, terrain, height, true);
getMetrics().getTerrain().put(p.getMilliseconds());
p = PrecisionStopwatch.start();
onPostGenerate(random, x, z, terrain, height, biomeMap, map);
return GeneratedChunk.builder().biomeMap(biomeMap).sliverMap(map).height(height).terrain(terrain).x(x).z(z).build();
}
protected void onClose()
{
getAccelerant().close();
Iris.executors.remove(accelerant);
}
public void onInit(RNG rng)
{
super.onInit(rng);
changeThreadCount(getThreads());
}
@Override
public boolean isParallelCapable()
{
return false;
}
}

View File

@@ -0,0 +1,139 @@
package com.volmit.iris.generator.legacy;
import org.bukkit.block.data.BlockData;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import com.volmit.iris.Iris;
import com.volmit.iris.generator.legacy.post.PostMasterPatcher;
import com.volmit.iris.generator.legacy.scaffold.GeneratedChunk;
import com.volmit.iris.generator.legacy.scaffold.TerrainChunk;
import com.volmit.iris.generator.legacy.scaffold.TerrainTarget;
import com.volmit.iris.util.CaveResult;
import com.volmit.iris.util.IPostBlockAccess;
import com.volmit.iris.util.IrisLock;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RNG;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public abstract class PostBlockTerrainProvider extends ParallaxTerrainProvider implements IPostBlockAccess
{
private String postKey;
private IrisLock postLock;
private PostMasterPatcher patcher;
public PostBlockTerrainProvider(TerrainTarget t, String dimensionName, int threads)
{
super(t, dimensionName, threads);
setPostKey("post-" + dimensionName);
setPostLock(new IrisLock("PostChunkGenerator"));
}
public void onInit(RNG rng)
{
super.onInit(rng);
patcher = new PostMasterPatcher(this);
}
@Override
protected GeneratedChunk onGenerate(RNG random, int x, int z, TerrainChunk terrain)
{
GeneratedChunk map = super.onGenerate(random, x, z, terrain);
if(!getDimension().isPostProcessing())
{
return map;
}
int rx, i;
PrecisionStopwatch p = PrecisionStopwatch.start();
KList<Runnable> q = new KList<>();
for(i = 0; i < 16; i++)
{
rx = (x << 4) + i;
int rxx = rx;
getAccelerant().queue("post", () ->
{
for(int j = 0; j < 16; j++)
{
patcher.onPost(rxx, (z << 4) + j, x, z, terrain, q);
}
});
}
getAccelerant().waitFor("post");
for(Runnable v : q)
{
v.run();
}
p.end();
getMetrics().getPost().put(p.getMilliseconds());
return map;
}
@Override
public void updateHeight(int x, int z, int h)
{
getCache().updateHeight(x, z, h);
}
@Override
public BlockData getPostBlock(int x, int y, int z, int currentPostX, int currentPostZ, ChunkData currentData)
{
if(y > 255 || y < 0)
{
return null;
}
if(x >> 4 == currentPostX && z >> 4 == currentPostZ)
{
getPostLock().lock();
BlockData d = currentData.getBlockData(x & 15, y, z & 15);
getPostLock().unlock();
return d;
}
return sampleSliver(x, z).get(y);
}
@Override
public void setPostBlock(int x, int y, int z, BlockData d, int currentPostX, int currentPostZ, ChunkData currentData)
{
if(x >> 4 == currentPostX && z >> 4 == currentPostZ)
{
getPostLock().lock();
currentData.setBlock(x & 15, y, z & 15, d);
getPostLock().unlock();
}
else
{
Iris.warn("Post Block Overdraw: " + currentPostX + "," + currentPostZ + " into " + (x >> 4) + ", " + (z >> 4));
}
}
@Override
public int highestTerrainOrFluidBlock(int x, int z)
{
return (int) Math.round(getTerrainWaterHeight(x, z));
}
@Override
public int highestTerrainBlock(int x, int z)
{
return (int) Math.round(getTerrainHeight(x, z));
}
@Override
public KList<CaveResult> caveFloors(int x, int z)
{
return getCaves(x, z);
}
}

View File

@@ -0,0 +1,947 @@
package com.volmit.iris.generator.legacy;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.Bisected.Half;
import com.volmit.iris.Iris;
import com.volmit.iris.generator.legacy.atomics.AtomicSliver;
import com.volmit.iris.generator.legacy.atomics.AtomicSliverMap;
import com.volmit.iris.generator.legacy.layer.GenLayerBiome;
import com.volmit.iris.generator.legacy.layer.GenLayerCarve;
import com.volmit.iris.generator.legacy.layer.GenLayerCave;
import com.volmit.iris.generator.legacy.layer.GenLayerRavine;
import com.volmit.iris.generator.legacy.scaffold.GeneratedChunk;
import com.volmit.iris.generator.legacy.scaffold.TerrainChunk;
import com.volmit.iris.generator.legacy.scaffold.TerrainTarget;
import com.volmit.iris.generator.noise.CNG;
import com.volmit.iris.object.DecorationPart;
import com.volmit.iris.object.InferredType;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDecorator;
import com.volmit.iris.object.IrisCaveFluid;
import com.volmit.iris.object.IrisDepositGenerator;
import com.volmit.iris.object.IrisDimension;
import com.volmit.iris.object.IrisGenerator;
import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.object.IrisShapedGeneratorStyle;
import com.volmit.iris.util.B;
import com.volmit.iris.util.BiomeMap;
import com.volmit.iris.util.CaveResult;
import com.volmit.iris.util.ChronoLatch;
import com.volmit.iris.util.HeightMap;
import com.volmit.iris.util.IrisLock;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.KMap;
import com.volmit.iris.util.M;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RNG;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.bukkit.block.data.BlockData;
@Data
@EqualsAndHashCode(callSuper = false)
public abstract class TopographicTerrainProvider extends ParallelTerrainProvider
{
private long lastUpdateRequest = M.ms();
private long lastChunkLoad = M.ms();
private GenLayerCave glCave;
private GenLayerCarve glCarve;
private GenLayerBiome glBiome;
private GenLayerRavine glRavine;
private RNG rockRandom;
private IrisLock regionLock;
private KMap<String, IrisGenerator> generators;
private KList<IrisGenerator> generatorList;
private CNG masterFracture;
private int generatorSize;
private ChronoLatch cwarn = new ChronoLatch(1000);
public TopographicTerrainProvider(TerrainTarget t, String dimensionName, int threads)
{
super(t, dimensionName, threads);
setGeneratorSize(0);
setGenerators(new KMap<>());
setGeneratorList(new KList<>());
setRegionLock(new IrisLock("BiomeChunkGenerator"));
}
@Override
public void onInit(RNG rng)
{
generatorSize = 0;
super.onInit(rng);
getData().preferFolder(getDimension().getLoadFile().getParentFile().getParentFile().getName());
buildGenLayers(getMasterRandom());
loadGenerators();
}
private void buildGenLayers(RNG rng)
{
setGlBiome(new GenLayerBiome(this, rng.nextParallelRNG(24671)));
setMasterFracture(CNG.signature(rng.nextParallelRNG(13)).scale(0.12));
setRockRandom(getMasterRandom().nextParallelRNG(2858678));
setGlCave(new GenLayerCave(this, rng.nextParallelRNG(238948)));
setGlCarve(new GenLayerCarve(this, rng.nextParallelRNG(968346576)));
setGlRavine(new GenLayerRavine(this, rng.nextParallelRNG(-229354923)));
}
public int getCarvedHeight(int x, int z, boolean ignoreFluid)
{
if(ignoreFluid)
{
return getCache().getCarvedHeightIgnoreWater(x, z);
}
return getCache().getCarvedHeight(x, z);
}
public int getCarvedHeight(int x, int z)
{
return getCarvedHeight(x, z, false);
}
public int getCarvedWaterHeight(int x, int z)
{
return getCarvedHeight(x, z, true);
}
public KList<CaveResult> getCaves(int x, int z)
{
return glCave.genCaves(x, z, x & 15, z & 15, null);
}
@Override
protected void onPreGenerate(RNG random, int x, int z, TerrainChunk terrain, HeightMap height, BiomeMap biomeMap, AtomicSliverMap map)
{
}
@Override
protected int onGenerateColumn(int cx, int cz, int rx, int rz, int x, int z, AtomicSliver sliver, BiomeMap biomeMap, boolean sampled)
{
if(x > 15 || x < 0 || z > 15 || z < 0)
{
throw new RuntimeException("Invalid OnGenerate call: x:" + x + " z:" + z);
}
RNG crand = getMasterRandom().nextParallelRNG(rx).nextParallelRNG(rz);
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 = getGlCarve().couldCarveBelow(height);
IrisRegion region = sampleRegion(rx, rz);
IrisBiome biome = sampleTrueBiome(rx, rz);
IrisBiome carveBiome = null;
Biome onlyBiome = Iris.biome3d ? null : biome.getGroundBiome(getMasterRandom(), rz, getDimension().getFluidHeight(), rx);
IrisCaveFluid forceFluid = getDimension().getForceFluid().hasFluid(getData()) ? getDimension().getForceFluid() : null;
if(biome == null)
{
throw new RuntimeException("Null Biome!");
}
KList<BlockData> layers = biome.generateLayers(rx, rz, getMasterRandom(), height, height - getFluidHeight(), getData());
KList<BlockData> cavernLayers = null;
KList<BlockData> seaLayers = biome.isAquatic() || biome.isShore() ? biome.generateSeaLayers(rx, rz, getMasterRandom(), fluidHeight - height, getData()) : new KList<>();
BlockData biomeFluid = biome.getFluidType().isEmpty() ? null : B.get(biome.getFluidType());
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 + 32, 255);
// 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 && getDimension().isBedrock())
{
if(biomeMap != null)
{
sliver.set(k, biome.getDerivative());
}
sliver.set(k, BEDROCK);
continue;
}
// Carving
if(carvable && getGlCarve().isCarved(rx, k, rz))
{
if(biomeMap != null)
{
if(carveBiome == null)
{
carveBiome = biome.getRealCarvingBiome(getData());
}
sliver.set(k, carveBiome.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 && k < max)
{
biomeAssigned = true;
if(Iris.biome3d)
{
sliver.set(k, biome.getGroundBiome(getMasterRandom(), rz, k, rx));
for(int kv = max; kv <= biomeMax; kv++)
{
sliver.set(kv, biome.getSkyBiome(getMasterRandom(), rz, kv, rx));
}
}
else
{
sliver.set(getFluidHeight(), onlyBiome);
}
biomeMap.setBiome(x, z, biome);
}
if(Iris.biome3d && k <= Math.max(height, fluidHeight))
{
sliver.set(k, biome.getGroundBiome(getMasterRandom(), rz, k, rx));
}
// Set Sea Material (water/lava)
if(underwater)
{
block = seaLayers.hasIndex(fluidHeight - k) ? seaLayers.get(depth) : biomeFluid != null ? biomeFluid : getDimension().getFluidPalette().get(rockRandom, wx, k, wz, getData());
}
// Set Surface Material for cavern layer surfaces
else if(carvable && cavernHeights.isNotEmpty() && lastCavernHeight - k >= 0 && lastCavernHeight - k < 5)
{
if(carveBiome == null)
{
carveBiome = biome.getRealCarvingBiome(getData());
}
if(cavernLayers == null)
{
cavernLayers = carveBiome.generateLayers(rx, rz, getMasterRandom(), 5, height - getFluidHeight(), getData());
}
block = cavernLayers.hasIndex(lastCavernHeight - k) ? cavernLayers.get(lastCavernHeight - k) : cavernLayers.get(0);
}
// Set Surface Material for true surface
else
{
block = layers.hasIndex(depth) ? layers.get(depth) : getDimension().getRockPalette().get(rockRandom, wx, k, wz, getData());
depth++;
}
// Set block and update heightmaps
sliver.set(k, block);
// Decorate underwater surface
if(!cavernSurface && (k == height && B.isSolid(block.getMaterial()) && k < fluidHeight))
{
decorateUnderwater(crand, biome, sliver, k, rx, rz);
}
// Decorate Cavern surfaces, but not the true surface
if((carvable && cavernSurface) && !(k == Math.max(height, fluidHeight) && block.getMaterial().isSolid() && k < 255 && k >= fluidHeight))
{
if(carveBiome == null)
{
carveBiome = biome.getRealCarvingBiome(getData());
}
decorateLand(crand, carveBiome, sliver, k, rx, rz, block);
}
if(forceFluid != null && B.isAir(block) && (forceFluid.isInverseHeight() ? k >= forceFluid.getFluidHeight() : k <= forceFluid.getFluidHeight()))
{
sliver.set(k, forceFluid.getFluid(getData()));
}
}
// Carve out biomes
KList<CaveResult> caveResults = glCave.genCaves(rx, rz, x, z, sliver);
IrisBiome caveBiome = glBiome.generateData(InferredType.CAVE, wx, wz, rx, rz, region);
// Decorate Cave Biome Height Sections
if(caveBiome != null)
{
for(CaveResult i : caveResults)
{
if(i.getFloor() < 0 || i.getFloor() > 255 || i.getCeiling() > 255 || i.getCeiling() < 0)
{
continue;
}
if(Iris.biome3d)
{
for(int j = i.getFloor(); j <= i.getCeiling(); j++)
{
sliver.set(j, caveBiome.getGroundBiome(getMasterRandom(), rz, j, rx));
}
}
KList<BlockData> floor = caveBiome.generateLayers(wx, wz, rockRandom, i.getFloor() - 2, i.getFloor() - 2, getData());
KList<BlockData> ceiling = caveBiome.generateLayers(wx + 256, wz + 256, rockRandom, (carvable ? getCarvedWaterHeight(rx, rz) : height) - i.getCeiling() - 2, (carvable ? getCarvedWaterHeight(rx, rz) : height) - i.getCeiling() - 2, getData());
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(crand, caveBiome, sliver, i.getFloor(), rx, rz, blockc);
}
}
}
if(Math.max(height, fluidHeight) > 255)
{
return height;
}
block = sliver.get(Math.max(height, fluidHeight));
// Decorate True Surface
if(block.getMaterial().isSolid())
{
decorateLand(crand, biome, sliver, Math.max(height, fluidHeight), rx, rz, block);
}
return height;
}
@Override
protected GeneratedChunk onGenerate(RNG random, int x, int z, TerrainChunk terrain)
{
GeneratedChunk map = super.onGenerate(random, x, z, terrain);
if(!getDimension().isVanillaCaves())
{
generateDeposits(random.nextParallelRNG(x * ((z * 39) + 10000)).nextParallelRNG(z + z - x), terrain, x, z);
}
return map;
}
private void decorateLand(RNG rng, IrisBiome biome, AtomicSliver sliver, int k, int rx, int rz, BlockData block)
{
if(!getDimension().isDecorate())
{
return;
}
int j = 0;
for(IrisDecorator i : biome.getDecorators())
{
if(i.getPartOf().equals(DecorationPart.SHORE_LINE) && (!touchesSea(rx, rz) || k != getFluidHeight()))
{
continue;
}
BlockData d = i.getBlockData(biome, rng.nextParallelRNG(38888 + biome.getRarity() + biome.getName().length() + j++), rx, rz, getData());
if(d != null)
{
if(!B.canPlaceOnto(d.getMaterial(), block.getMaterial()))
{
continue;
}
if(d.getMaterial().equals(Material.CACTUS))
{
if(!block.getMaterial().equals(Material.SAND) && !block.getMaterial().equals(Material.RED_SAND))
{
sliver.set(k, B.getBlockData("RED_SAND"));
}
}
if(d.getMaterial().equals(Material.WHEAT) || d.getMaterial().equals(Material.CARROTS) || d.getMaterial().equals(Material.POTATOES) || d.getMaterial().equals(Material.MELON_STEM) || d.getMaterial().equals(Material.PUMPKIN_STEM))
{
if(!block.getMaterial().equals(Material.FARMLAND))
{
sliver.set(k, B.getBlockData("FARMLAND"));
}
}
if(d instanceof Bisected && k < 254)
{
BlockData bb = d.clone();
Bisected t = ((Bisected) d);
t.setHalf(Half.TOP);
Bisected b = ((Bisected) bb);
b.setHalf(Half.BOTTOM);
sliver.set(k + 1, bb);
sliver.set(k + 2, d);
}
else
{
int stack = i.getHeight(rng.nextParallelRNG((int) (39456 + (10000 * i.getChance()) + i.getStackMax() + i.getStackMin() + i.getZoom())), rx, rz, getData());
BlockData top = null;
if(stack > 1 && i.getTopPalette().hasElements())
{
top = i.getBlockDataForTop(biome, rng.nextParallelRNG(38887 + biome.getRarity() + biome.getName().length() + j++), rx, rz, getData());
}
if(stack == 1)
{
sliver.set(k + 1, d);
}
else if(k < 255 - stack)
{
for(int l = 0; l < stack; l++)
{
BlockData dd = i.getBlockData100(biome, rng.nextParallelRNG(38888 + l + biome.getRarity() + biome.getName().length() + j++), rx + l, rz - l, getData());
d = dd != null ? dd : d;
sliver.set(k + l + 1, l == stack - 1 && top != null ? top : d);
}
}
}
break;
}
}
}
private void decorateCave(RNG rng, IrisBiome biome, AtomicSliver sliver, int k, int rx, int rz, BlockData block)
{
if(!getDimension().isDecorate())
{
return;
}
int j = 0;
for(IrisDecorator i : biome.getDecorators())
{
BlockData d = i.getBlockData(biome, rng.nextParallelRNG(2333877 + biome.getRarity() + biome.getName().length() + +j++), rx, rz, getData());
if(d != null)
{
if(!B.canPlaceOnto(d.getMaterial(), block.getMaterial()))
{
continue;
}
if(d.getMaterial().equals(Material.CACTUS))
{
if(!block.getMaterial().equals(Material.SAND) && !block.getMaterial().equals(Material.RED_SAND))
{
sliver.set(k, B.getBlockData("SAND"));
}
}
if(d instanceof Bisected && k < 254)
{
BlockData bb = d.clone();
Bisected t = ((Bisected) d);
t.setHalf(Half.TOP);
Bisected b = ((Bisected) bb);
b.setHalf(Half.BOTTOM);
sliver.set(k + 1, bb);
sliver.set(k + 2, d);
}
else
{
int stack = i.getHeight(rng.nextParallelRNG((int) (39456 + (1000 * i.getChance()) + i.getZoom() * 10)), rx, rz, getData());
if(stack == 1)
{
sliver.set(k + 1, d);
}
else if(k < 255 - stack)
{
for(int l = 0; l < stack; l++)
{
if(sliver.isSolid(k + l + 1))
{
break;
}
sliver.set(k + l + 1, d);
}
}
}
break;
}
}
}
private void decorateUnderwater(RNG random, IrisBiome biome, AtomicSliver sliver, int y, int rx, int rz)
{
if(!getDimension().isDecorate())
{
return;
}
int j = 0;
for(IrisDecorator i : biome.getDecorators())
{
if(biome.getInferredType().equals(InferredType.SHORE))
{
continue;
}
BlockData d = i.getBlockData(biome, getMasterRandom().nextParallelRNG(2555 + biome.getRarity() + biome.getName().length() + j++), rx, rz, getData());
if(d != null)
{
int stack = i.getHeight(random.nextParallelRNG((int) (239456 + i.getStackMax() + i.getStackMin() + i.getVerticalZoom() + i.getZoom() + i.getBlockData(getData()).size() + j)), rx, rz, getData());
if(stack == 1)
{
sliver.set(i.getPartOf().equals(DecorationPart.SEA_SURFACE) ? (getFluidHeight() + 1) : (y + 1), d);
}
else if(y < getFluidHeight() - stack)
{
for(int l = 0; l < stack; l++)
{
sliver.set(i.getPartOf().equals(DecorationPart.SEA_SURFACE) ? (getFluidHeight() + 1 + l) : (y + l + 1), d);
}
}
break;
}
}
}
@Override
protected void onPostGenerate(RNG random, int x, int z, TerrainChunk terrain, HeightMap height, BiomeMap biomeMap, AtomicSliverMap map)
{
onPreParallaxPostGenerate(random, x, z, terrain, height, biomeMap, map);
}
protected void onPreParallaxPostGenerate(RNG random, int x, int z, TerrainChunk terrain, HeightMap height, BiomeMap biomeMap, AtomicSliverMap map)
{
if(getDimension().isRavines())
{
getGlRavine().generateRavines(random.nextParallelRNG(x - 283845).nextParallelRNG(z + 23845868), x, z, terrain, height, biomeMap, map);
}
}
public void generateDeposits(RNG rx, TerrainChunk terrain, int x, int z)
{
PrecisionStopwatch p = PrecisionStopwatch.start();
RNG ro = rx.nextParallelRNG(x * x).nextParallelRNG(z * z);
IrisRegion region = sampleRegion((x * 16) + 7, (z * 16) + 7);
IrisBiome biome = sampleTrueBiome((x * 16) + 7, (z * 16) + 7);
for(IrisDepositGenerator k : getDimension().getDeposits())
{
k.generate(terrain, ro, this, x, z, false);
}
for(IrisDepositGenerator k : region.getDeposits())
{
for(int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++)
{
k.generate(terrain, ro, this, x, z, false);
}
}
for(IrisDepositGenerator k : biome.getDeposits())
{
for(int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++)
{
k.generate(terrain, ro, this, x, z, false);
}
}
p.end();
getMetrics().getDeposits().put(p.getMilliseconds());
}
protected void onPostParallaxPostGenerate(RNG random, int x, int z, TerrainChunk terrain, HeightMap height, BiomeMap biomeMap, AtomicSliverMap map)
{
}
public double getNoiseHeight(int rx, int rz)
{
return getBiomeHeight(rx, rz);
}
public IrisBiome sampleTrueBiomeBase(int x, int z)
{
if(!getDimension().getFocus().equals(""))
{
return focus();
}
int height = (int) Math.round(getTerrainHeight(x, z));
double wx = getModifiedX(x, z);
double wz = getModifiedZ(x, z);
IrisRegion region = sampleRegion(x, z);
double sh = region.getShoreHeight(wx, wz);
double shMax = getFluidHeight() + (sh / 2);
double shMin = getFluidHeight() - (sh / 2);
IrisBiome current = sampleBiome(x, z);
InferredType aquaticType = current.isAquatic() ? (current.isSea() ? InferredType.SEA : current.isRiver() ? InferredType.RIVER : InferredType.LAKE) : InferredType.SEA;
boolean sea = height <= getFluidHeight();
boolean shore = height >= shMin && height <= shMax;
boolean land = height > getFluidHeight();
// Remove rivers, lakes & sea from land
if(current.isAquatic() && land)
{
current = glBiome.generateData(InferredType.LAND, wx, wz, x, z, region);
}
// Remove land from underwater
if(current.isLand() && sea)
{
current = glBiome.generateData(aquaticType, wx, wz, x, z, region);
}
// Add shores to land
if(shore)
{
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;
}
public IrisBiome sampleCaveBiome(int x, int z)
{
double wx = getModifiedX(x, z);
double wz = getModifiedZ(x, z);
return glBiome.generateData(InferredType.CAVE, wx, wz, x, z, sampleRegion(x, z));
}
public IrisBiome sampleTrueBiome(int x, int y, int z)
{
if(y < getTerrainHeight(x, z))
{
double wx = getModifiedX(x, z);
double wz = getModifiedZ(x, z);
IrisBiome r = glBiome.generateData(InferredType.CAVE, wx, wz, x, z, sampleRegion(x, z));
if(r != null)
{
return r;
}
}
return sampleTrueBiome(x, z);
}
public IrisRegion sampleRegion(int x, int z)
{
return getCache().getRegion(x, z);
}
public IrisBiome sampleTrueBiome(int x, int z)
{
if(!getDimension().getFocus().equals(""))
{
return focus();
}
return getCache().getBiome(x, z);
}
@Override
protected int onSampleColumnHeight(int cx, int cz, int rx, int rz, int x, int z)
{
return (int) Math.round(getTerrainHeight(rx, rz));
}
private boolean touchesSea(int rx, int rz)
{
return isFluidAtHeight(rx + 1, rz) || isFluidAtHeight(rx - 1, rz) || isFluidAtHeight(rx, rz - 1) || isFluidAtHeight(rx, rz + 1);
}
public boolean isUnderwater(int x, int z)
{
return isFluidAtHeight(x, z);
}
public boolean isFluidAtHeight(int x, int z)
{
return Math.round(getTerrainHeight(x, z)) < getFluidHeight();
}
public int getFluidHeight()
{
if(getDimension() == null)
{
return 63;
}
return getDimension().getFluidHeight();
}
public double getTerrainHeight(int x, int z)
{
return getCache().getHeight(x, z);
}
public double getTerrainWaterHeight(int x, int z)
{
return Math.max(getTerrainHeight(x, z), getFluidHeight());
}
@Override
public void onHotload()
{
generatorSize = 0;
super.onHotload();
getData().preferFolder(getDimension().getLoadFile().getParentFile().getParentFile().getName());
loadGenerators();
buildGenLayers(getMasterRandom());
}
public void registerGenerator(IrisGenerator g)
{
KMap<String, IrisGenerator> generators = this.generators;
getRegionLock().lock();
if(g.getLoadKey() == null || generators.containsKey(g.getLoadKey()))
{
getRegionLock().unlock();
return;
}
generatorList.add(g);
getRegionLock().unlock();
generators.put(g.getLoadKey(), g);
}
protected KMap<String, IrisGenerator> getGenerators()
{
return generators;
}
protected double getRawBiomeHeight(double rrx, double rrz)
{
double h = 0;
for(int j = 0; j < generatorSize; j++)
{
try
{
h += interpolateGenerator(rrx, rrz, generatorList.get(j));
}
catch(Throwable e)
{
}
}
return h;
}
protected double getBiomeHeight(double rrx, double rrz)
{
double h = getRawBiomeHeight(rrx, rrz);
for(IrisShapedGeneratorStyle i : getDimension().getOverlayNoise())
{
h += i.get(getMasterRandom(), rrx, rrz);
}
return h;
}
protected double interpolateGenerator(double rx, double rz, IrisGenerator gen)
{
double hi = gen.getInterpolator().interpolate(rx, rz, (xx, zz) ->
{
try
{
return sampleBiome((int) xx, (int) zz).getGenLinkMax(gen.getLoadKey());
}
catch(Throwable e)
{
Iris.warn("Failed to sample hi biome at " + rx + " " + rz + " using the generator " + gen.getLoadKey());
fail(e);
}
return 0;
});
double lo = gen.getInterpolator().interpolate(rx, rz, (xx, zz) ->
{
try
{
return sampleBiome((int) xx, (int) zz).getGenLinkMin(gen.getLoadKey());
}
catch(Throwable e)
{
Iris.warn("Failed to sample lo biome at " + rx + " " + rz + " using the generator " + gen.getLoadKey());
fail(e);
}
return 0;
});
return M.lerp(lo, hi, gen.getHeight(rx, rz, getTarget().getSeed() + 239945));
}
protected void loadGenerators()
{
generatorList.clear();
generators.clear();
loadGenerators(getDimension());
generatorSize = generatorList.size();
}
protected void loadGenerators(IrisDimension dim)
{
if(dim == null)
{
Iris.warn("Cannot load generators, Dimension is null!");
return;
}
KList<String> touch = new KList<>();
KList<String> loadQueue = new KList<>();
for(String i : dim.getRegions())
{
IrisRegion r = loadRegion(i);
if(r != null)
{
loadQueue.addAll(r.getLandBiomes());
loadQueue.addAll(r.getSeaBiomes());
loadQueue.addAll(r.getShoreBiomes());
loadQueue.addAll(r.getRidgeBiomeKeys());
loadQueue.addAll(r.getSpotBiomeKeys());
}
}
while(!loadQueue.isEmpty())
{
String next = loadQueue.pop();
if(!touch.contains(next))
{
touch.add(next);
IrisBiome biome = loadBiome(next);
biome.getGenerators().forEach((i) -> registerGenerator(i.getCachedGenerator(this)));
loadQueue.addAll(biome.getChildren());
}
}
Iris.info("Loaded " + generators.size() + " Generators");
}
public IrisBiome computeRawBiome(int x, int z)
{
if(!getDimension().getFocus().equals(""))
{
IrisBiome biome = loadBiome(getDimension().getFocus());
for(String i : getDimension().getRegions())
{
IrisRegion reg = loadRegion(i);
if(reg.getLandBiomes().contains(biome.getLoadKey()))
{
biome.setInferredType(InferredType.LAND);
break;
}
if(reg.getSeaBiomes().contains(biome.getLoadKey()))
{
biome.setInferredType(InferredType.SEA);
break;
}
if(reg.getShoreBiomes().contains(biome.getLoadKey()))
{
biome.setInferredType(InferredType.SHORE);
break;
}
}
return biome;
}
double wx = getModifiedX(x, z);
double wz = getModifiedZ(x, z);
IrisRegion region = glBiome.getRegion(wx, wz);
return glBiome.generateRegionData(wx, wz, x, z, region);
}
public IrisBiome sampleBiome(int x, int z)
{
return getCache().getRawBiome(x, z);
}
}

View File

@@ -0,0 +1,7 @@
package com.volmit.iris.generator.legacy.atomics;
import com.volmit.iris.object.IrisBiome;
public class AtomicBiomeMap extends AtomicObjectMap<IrisBiome> {
}

View File

@@ -0,0 +1,119 @@
package com.volmit.iris.generator.legacy.atomics;
import java.util.function.Supplier;
import com.volmit.iris.util.IrisLock;
import com.volmit.iris.util.M;
public class AtomicCache<T>
{
private transient volatile T t;
private transient volatile long a;
private transient volatile int validations;
private final IrisLock check;
private final IrisLock time;
private final IrisLock write;
private final boolean nullSupport;
public AtomicCache()
{
this(false);
}
public AtomicCache(boolean nullSupport)
{
this.nullSupport = nullSupport;
check = new IrisLock("Check");
write = new IrisLock("Write");
time = new IrisLock("Time");
validations = 0;
a = -1;
t = null;
}
public void reset()
{
check.lock();
write.lock();
time.lock();
a = -1;
t = null;
time.unlock();
write.unlock();
check.unlock();
}
public T aquire(Supplier<T> t)
{
if(nullSupport)
{
return aquireNull(t);
}
if(this.t != null && validations > 1000)
{
return this.t;
}
if(this.t != null && M.ms() - a > 1000)
{
if(this.t != null)
{
validations++;
}
return this.t;
}
check.lock();
if(this.t == null)
{
write.lock();
this.t = t.get();
time.lock();
if(a == -1)
{
a = M.ms();
}
time.unlock();
write.unlock();
}
check.unlock();
return this.t;
}
public T aquireNull(Supplier<T> t)
{
if(validations > 1000)
{
return this.t;
}
if(M.ms() - a > 1000)
{
validations++;
return this.t;
}
check.lock();
write.lock();
this.t = t.get();
time.lock();
if(a == -1)
{
a = M.ms();
}
time.unlock();
write.unlock();
check.unlock();
return this.t;
}
}

View File

@@ -0,0 +1,23 @@
package com.volmit.iris.generator.legacy.atomics;
import com.google.common.util.concurrent.AtomicDoubleArray;
public class AtomicDoubleMap {
private final AtomicDoubleArray data;
public AtomicDoubleMap() {
data = new AtomicDoubleArray(256);
}
public double get(int x, int z) {
return data.get((z << 4) | x);
}
public int getInt(int x, int z) {
return (int) Math.round(get(x, z));
}
public void set(int x, int z, double v) {
data.set((z << 4) | x, v);
}
}

View File

@@ -0,0 +1,19 @@
package com.volmit.iris.generator.legacy.atomics;
import java.util.concurrent.atomic.AtomicIntegerArray;
public class AtomicIntMap {
private final AtomicIntegerArray data;
public AtomicIntMap() {
data = new AtomicIntegerArray(256);
}
public int get(int x, int z) {
return data.get((z << 4) | x);
}
public void set(int x, int z, int v) {
data.set((z << 4) | x, v);
}
}

View File

@@ -0,0 +1,109 @@
package com.volmit.iris.generator.legacy.atomics;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.generator.legacy.IrisTerrainProvider;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.util.ChunkPosition;
public class AtomicMulticache
{
public static boolean broken = false;
private final LoadingCache<ChunkPosition, Double> height;
private final LoadingCache<ChunkPosition, Integer> carvedHeight;
private final LoadingCache<ChunkPosition, Integer> carvedHeightIgnoreWater;
private final LoadingCache<ChunkPosition, IrisBiome> biome;
private final LoadingCache<ChunkPosition, IrisBiome> rawBiome;
private final LoadingCache<ChunkPosition, IrisRegion> region;
public AtomicMulticache(IrisTerrainProvider gen)
{
height = Caffeine.newBuilder().maximumSize(getLimit()).build((c) -> gen.getNoiseHeight(c.getX(), c.getZ()) + gen.getFluidHeight());
carvedHeight = Caffeine.newBuilder().maximumSize(getLimit()).build((c) ->
{
int h = (int) Math.round(gen.getTerrainWaterHeight(c.getX(), c.getZ()));
h = gen.getGlCarve().getSurfaceCarve(c.getX(), h, c.getZ());
return h;
});
carvedHeightIgnoreWater = Caffeine.newBuilder().maximumSize(getLimit()).build((c) ->
{
int h = (int) Math.round(gen.getTerrainHeight(c.getX(), c.getZ()));
h = gen.getGlCarve().getSurfaceCarve(c.getX(), h, c.getZ());
return h;
});
biome = Caffeine.newBuilder().maximumSize(getLimit()).build((c) -> gen.sampleTrueBiomeBase(c.getX(), c.getZ()));
rawBiome = Caffeine.newBuilder().maximumSize(getLimit()).build((c) -> gen.computeRawBiome(c.getX(), c.getZ()));
region = Caffeine.newBuilder().maximumSize(getLimit()).build((c) ->
{
double wx = gen.getModifiedX(c.getX(), c.getZ());
double wz = gen.getModifiedZ(c.getX(), c.getZ());
return gen.getGlBiome().getRegion(wx, wz);
});
}
private int getLimit()
{
return IrisSettings.get().getAtomicCacheSize();
}
public double getHeight(int x, int z)
{
return height.get(new ChunkPosition(x, z));
}
public int getCarvedHeight(int x, int z)
{
return carvedHeight.get(new ChunkPosition(x, z));
}
public int getCarvedHeightIgnoreWater(int x, int z)
{
return carvedHeightIgnoreWater.get(new ChunkPosition(x, z));
}
public IrisRegion getRegion(int x, int z)
{
return region.get(new ChunkPosition(x, z));
}
public IrisBiome getBiome(int x, int z)
{
return biome.get(new ChunkPosition(x, z));
}
public IrisBiome getRawBiome(int x, int z)
{
return rawBiome.get(new ChunkPosition(x, z));
}
public void updateHeight(int x, int z, int h)
{
if(broken)
{
return;
}
height.put(new ChunkPosition(x, z), (double) h);
}
public double getSize()
{
return height.estimatedSize() + region.estimatedSize() + biome.estimatedSize() + rawBiome.estimatedSize() + carvedHeight.estimatedSize() + carvedHeightIgnoreWater.estimatedSize();
}
public void drop()
{
if(broken)
{
return;
}
height.invalidateAll();
region.invalidateAll();
biome.invalidateAll();
rawBiome.invalidateAll();
carvedHeight.invalidateAll();
carvedHeightIgnoreWater.invalidateAll();
}
}

View File

@@ -0,0 +1,19 @@
package com.volmit.iris.generator.legacy.atomics;
import java.util.concurrent.atomic.AtomicReferenceArray;
public class AtomicObjectMap<T> {
private final AtomicReferenceArray<T> data;
public AtomicObjectMap() {
data = new AtomicReferenceArray<T>(256);
}
public T get(int x, int z) {
return data.get((z << 4) | x);
}
public void set(int x, int z, T v) {
data.set((z << 4) | x, v);
}
}

View File

@@ -0,0 +1,169 @@
package com.volmit.iris.generator.legacy.atomics;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPInputStream;
import com.volmit.iris.Iris;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.generator.legacy.scaffold.TerrainTarget;
import com.volmit.iris.util.ByteArrayTag;
import com.volmit.iris.util.CompoundTag;
import com.volmit.iris.util.CustomOutputStream;
import com.volmit.iris.util.KMap;
import com.volmit.iris.util.NBTInputStream;
import com.volmit.iris.util.NBTOutputStream;
import com.volmit.iris.util.Tag;
public class AtomicRegionData
{
private final TerrainTarget world;
private Tag[] tag;
public AtomicRegionData(TerrainTarget world)
{
this.world = world;
tag = new Tag[1024];
}
public int size()
{
return tag.length;
}
public void read(InputStream in) throws IOException
{
NBTInputStream nin = new NBTInputStream(in);
KMap<String, Tag> tags = new KMap<>();
tags.putAll(((CompoundTag) nin.readTag()).getValue());
for(String i : tags.keySet())
{
int x = Integer.parseInt(i.split("\\Q.\\E")[0]);
int z = Integer.parseInt(i.split("\\Q.\\E")[1]);
tag[(z << 5) | x] = tags.get(i);
}
nin.close();
}
public void write(OutputStream out) throws IOException
{
NBTOutputStream nos = new NBTOutputStream(out);
KMap<String, Tag> tags = new KMap<>();
for(int i = 0; i < 32; i++)
{
for(int j = 0; j < 32; j++)
{
if(tag[(j << 5) | i] != null)
{
tags.put(i + "." + j, tag[(j << 5) | i]);
}
}
}
nos.writeTag(new CompoundTag("imca", tags));
nos.close();
}
public boolean contains(int rx, int rz)
{
return tag[(rz << 5) | rx] != null;
}
public void delete(int rx, int rz)
{
tag[(rz << 5) | rx] = null;
}
public void set(int rx, int rz, AtomicSliverMap data) throws IOException
{
if(data == null)
{
return;
}
OutputStream out;
ByteArrayOutputStream boas = new ByteArrayOutputStream();
out = boas;
if(IrisSettings.get().parallaxCompression)
{
out = new CustomOutputStream(boas, IrisSettings.get().parallaxCompressionLevel);
}
data.write(out);
out.flush();
out.close();
byte[] b = boas.toByteArray();
tag[(rz << 5) | rx] = new ByteArrayTag(rx + "." + rz, b);
}
public AtomicSliverMap get(int rx, int rz) {
AtomicSliverMap data = new AtomicSliverMap();
if(!contains(rx, rz))
{
return data;
}
ByteArrayTag btag = (ByteArrayTag) tag[(rz << 5) | rx];
try
{
if(btag.getValue().length == 0)
{
Iris.warn("EMPTY BYTE TAG " + rx + " " + rz);
return data;
}
InputStream in;
if(IrisSettings.get().parallaxCompression)
{
in = new GZIPInputStream(new ByteArrayInputStream(btag.getValue()));
}
else
{
in = new ByteArrayInputStream(btag.getValue());
}
data.read(in);
in.close();
}
catch(Throwable e)
{
Iris.warn("Failed to load " + rx + "." + rz + " with " + btag.getValue().length);
}
return data;
}
public TerrainTarget getWorld()
{
return world;
}
public long guessMemoryUsage()
{
long bytes = 0;
for(int i = 0; i < 1024; i++)
{
if(tag[i] != null && tag[i] instanceof ByteArrayTag)
{
bytes += 122;
bytes += ((ByteArrayTag) tag[i]).getValue().length;
}
}
return bytes;
}
}

View File

@@ -0,0 +1,7 @@
package com.volmit.iris.generator.legacy.atomics;
import com.volmit.iris.object.IrisRegion;
public class AtomicRegionMap extends AtomicObjectMap<IrisRegion> {
}

View File

@@ -0,0 +1,422 @@
package com.volmit.iris.generator.legacy.atomics;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import com.volmit.iris.Iris;
import com.volmit.iris.util.B;
import com.volmit.iris.util.HeightMap;
import com.volmit.iris.util.IrisLock;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.M;
import lombok.Data;
@Data
public class AtomicSliver
{
public static final BlockData AIR = B.getBlockData("AIR");
public static boolean forgetful = false;
private transient Biome[] biome;
private transient Biome onlyBiome;
private transient IrisLock lock = new IrisLock("Sliver");
private transient short highestBiome = 0;
private transient long last = M.ms();
private transient final byte x;
private transient final byte z;
private transient boolean modified = false;
private BlockData[] block;
private KList<Byte> blockUpdates;
private int highestBlock = 0;
public AtomicSliver(int x, int z)
{
onlyBiome = null;
this.x = (byte) x;
this.z = (byte) z;
blockUpdates = new KList<>(4);
this.block = new BlockData[256];
this.biome = new Biome[256];
}
public Material getType(int h)
{
return getTypeSafe(h);
}
public Material getTypeSafe(int h)
{
return get(h > 255 ? 255 : Math.max(h, 0)).getMaterial();
}
public KList<Byte> getUpdatables()
{
return blockUpdates;
}
public void update(byte y)
{
if(forgetful)
{
return;
}
blockUpdates.addIfMissing((byte) (y + Byte.MIN_VALUE));
}
public void dontUpdate(byte y)
{
if(forgetful)
{
return;
}
blockUpdates.remove(Byte.valueOf((byte) (y + Byte.MIN_VALUE)));
}
public BlockData get(int h)
{
if(forgetful)
{
return null;
}
if(h > 255)
{
h = 255;
}
if(h < 0)
{
h = 0;
}
BlockData b = block[h];
last = M.ms();
if(b == null)
{
return AIR;
}
return b;
}
public BlockData getOrNull(int h)
{
if(forgetful || oob(h))
{
return null;
}
BlockData b = block[h];
last = M.ms();
if(b.getMaterial().equals(Material.AIR))
{
return null;
}
return b;
}
public void set(int h, BlockData d)
{
if(forgetful || oob(h))
{
return;
}
setSilently(h, d);
modified = true;
lock.lock();
highestBlock = Math.max(h, highestBlock);
lock.unlock();
}
public void setSilently(int h, BlockData d)
{
if(forgetful)
{
return;
}
if(d == null)
{
return;
}
if(oob(h))
{
return;
}
lock.lock();
modified = true;
block[h] = d;
if(B.isUpdatable(d))
{
update((byte) h);
}
else
{
dontUpdate((byte) h);
}
lock.unlock();
}
private boolean oob(int h)
{
return h > 255 || h < 0;
}
public boolean isSolid(int h)
{
if(oob(h))
{
return false;
}
return getType(h).isSolid();
}
public void set(int h, Biome d)
{
if(oob(h))
{
return;
}
lock.lock();
if(Iris.biome3d)
{
biome[h] = d;
}
else
{
onlyBiome = d;
}
modified = true;
highestBiome = (short) (h > highestBiome ? h : highestBiome);
lock.unlock();
}
public void write(ChunkData d, boolean skipNull)
{
if(forgetful)
{
return;
}
lock.lock();
for(int i = 0; i <= highestBlock; i++)
{
if(block[i] == null)
{
if(!skipNull)
{
d.setBlock(x, i, z, AIR.getMaterial());
}
}
else
{
d.setBlock(x, i, z, block[i]);
}
}
lock.unlock();
}
@SuppressWarnings("deprecation")
public void write(BiomeGrid d)
{
lock.lock();
if(!Iris.biome3d)
{
d.setBiome(x, z, onlyBiome);
lock.unlock();
return;
}
for(int i = 0; i <= highestBiome; i++)
{
if(biome[i] != null)
{
d.setBiome(x, i, z, biome[i]);
}
}
lock.unlock();
}
public void write(HeightMap height)
{
lock.lock();
height.setHeight(x, z, highestBlock);
lock.unlock();
}
public void read(DataInputStream din) throws IOException
{
lock.lock();
this.block = new BlockData[256];
getUpdatables().clear();
// Block Palette
int p = din.readByte() - Byte.MIN_VALUE;
int h = din.readByte() - Byte.MIN_VALUE;
int u = din.readByte() - Byte.MIN_VALUE;
KList<BlockData> palette = new KList<BlockData>();
highestBlock = h;
for(int i = 0; i < p; i++)
{
palette.add(B.getBlockData(din.readUTF()));
}
// Blocks
for(int i = 0; i <= h; i++)
{
block[i] = palette.get(din.readByte() - Byte.MIN_VALUE).clone();
}
// Updates
for(int i = 0; i < u; i++)
{
update(din.readByte());
}
modified = false;
lock.unlock();
}
public void write(DataOutputStream dos) throws IOException
{
if(forgetful)
{
return;
}
lock.lock();
// Block Palette
KList<String> palette = new KList<>();
for(int i = 0; i <= highestBlock; i++)
{
BlockData dat = block[i];
String d = (dat == null ? AIR : dat).getAsString(true);
if(!palette.contains(d))
{
palette.add(d);
}
}
dos.writeByte(palette.size() + Byte.MIN_VALUE);
dos.writeByte(highestBlock + Byte.MIN_VALUE);
dos.writeByte(blockUpdates.size() + Byte.MIN_VALUE);
for(String i : palette)
{
dos.writeUTF(i);
}
// Blocks
for(int i = 0; i <= highestBlock; i++)
{
BlockData dat = block[i];
String d = (dat == null ? AIR : dat).getAsString(true);
dos.writeByte(palette.indexOf(d) + Byte.MIN_VALUE);
}
// Updates
for(Byte i : getUpdatables())
{
dos.writeByte(i);
}
lock.unlock();
}
public void insert(AtomicSliver atomicSliver)
{
if(forgetful)
{
return;
}
lock.lock();
for(int i = 0; i < 256; i++)
{
if(block[i] == null || block[i].equals(AIR))
{
BlockData b = atomicSliver.block[i];
if(b == null || b.equals(AIR))
{
continue;
}
block[i] = b;
}
}
lock.unlock();
}
public void inject(ChunkData currentData)
{
if(forgetful)
{
return;
}
lock.lock();
for(int i = 0; i < block.length; i++)
{
BlockData b = block[i];
if(b != null)
{
if(b.getMaterial().equals(Material.AIR))
{
continue;
}
currentData.setBlock(x, i, z, b);
}
}
lock.unlock();
}
public boolean isOlderThan(long m)
{
if(forgetful)
{
return false;
}
return M.ms() - last > m;
}
public void inject(KList<Byte> updatables)
{
if(forgetful)
{
return;
}
blockUpdates.addAll(updatables);
}
}

View File

@@ -0,0 +1,228 @@
package com.volmit.iris.generator.legacy.atomics;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import com.volmit.iris.generator.legacy.DimensionalTerrainProvider;
import com.volmit.iris.object.IrisStructure;
import com.volmit.iris.object.IrisStructureTile;
import com.volmit.iris.util.HeightMap;
import com.volmit.iris.util.IrisStructureResult;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.KMap;
import lombok.Data;
@Data
public class AtomicSliverMap
{
private final AtomicSliver[] slivers;
private KMap<Integer, String> structures;
private boolean parallaxGenerated;
private boolean worldGenerated;
public AtomicSliverMap()
{
structures = new KMap<>();
parallaxGenerated = false;
worldGenerated = false;
slivers = new AtomicSliver[256];
for(int i = 0; i < 16; i++)
{
for(int j = 0; j < 16; j++)
{
slivers[i * 16 + j] = new AtomicSliver(i, j);
}
}
}
public void insert(AtomicSliverMap map)
{
for(int i = 0; i < 256; i++)
{
slivers[i].insert(map.slivers[i]);
}
}
public void setStructure(int y, IrisStructure s, IrisStructureTile t)
{
structures.put(y, s.getLoadKey() + "." + s.getTiles().indexOf(t));
}
public IrisStructureResult getStructure(DimensionalTerrainProvider g, int y)
{
String v = structures.get(y);
if(v == null)
{
return null;
}
String[] a = v.split("\\Q.\\E");
IrisStructure s = g.getData().getStructureLoader().load(a[0]);
if(s == null)
{
return null;
}
return new IrisStructureResult(s.getTiles().get(Integer.parseInt(a[1])), s);
}
public void write(OutputStream out) throws IOException
{
DataOutputStream dos = new DataOutputStream(out);
dos.writeBoolean(isParallaxGenerated());
dos.writeBoolean(isWorldGenerated());
for(int i = 0; i < 256; i++)
{
try
{
slivers[i].write(dos);
}
catch(Throwable e)
{
e.printStackTrace();
}
}
KList<String> structurePalette = new KList<>();
for(Integer i : structures.k())
{
String struct = structures.get(i);
if(!structurePalette.contains(struct))
{
structurePalette.add(struct);
}
}
dos.writeByte(structurePalette.size() + Byte.MIN_VALUE);
for(String i : structurePalette)
{
dos.writeUTF(i);
}
dos.writeByte(structures.size() + Byte.MIN_VALUE);
for(Integer i : structures.k())
{
dos.writeByte(i + Byte.MIN_VALUE);
dos.writeByte(structurePalette.indexOf(structures.get(i)) + Byte.MIN_VALUE);
}
dos.flush();
}
public void read(InputStream in) throws IOException
{
DataInputStream din = new DataInputStream(in);
parallaxGenerated = din.readBoolean();
worldGenerated = din.readBoolean();
for(int i = 0; i < 256; i++)
{
try
{
slivers[i].read(din);
}
catch(Throwable e)
{
e.printStackTrace();
}
}
int spc = din.readByte() - Byte.MIN_VALUE;
KList<String> spal = new KList<>();
for(int i = 0; i < spc; i++)
{
spal.add(din.readUTF());
}
int smc = din.readByte() - Byte.MIN_VALUE;
structures.clear();
for(int i = 0; i < smc; i++)
{
structures.put(din.readByte() - Byte.MIN_VALUE, spal.get(din.readByte() - Byte.MIN_VALUE));
}
}
public AtomicSliver getSliver(int x, int z)
{
return slivers[x * 16 + z];
}
public void write(ChunkData data, BiomeGrid grid, HeightMap height, boolean skipNull)
{
for(AtomicSliver i : slivers)
{
if(i != null)
{
i.write(data, skipNull);
i.write(grid);
i.write(height);
}
}
}
public void inject(ChunkData currentData)
{
for(AtomicSliver i : slivers)
{
i.inject(currentData);
}
}
public boolean isModified()
{
for(AtomicSliver i : slivers)
{
if(i.isModified())
{
return true;
}
}
return false;
}
public void injectUpdates(AtomicSliverMap map)
{
for(int i = 0; i < 16; i++)
{
for(int j = 0; j < 16; j++)
{
getSliver(i, j).inject(map.getSliver(i, j).getUpdatables());
}
}
}
public void reset()
{
setParallaxGenerated(false);
setWorldGenerated(false);
getStructures().clear();
for(int i = 0; i < 16; i++)
{
for(int j = 0; j < 16; j++)
{
slivers[i * 16 + j] = new AtomicSliver(i, j);
}
}
}
}

View File

@@ -0,0 +1,352 @@
package com.volmit.iris.generator.legacy.atomics;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import com.volmit.iris.Iris;
import com.volmit.iris.generator.legacy.scaffold.TerrainTarget;
import com.volmit.iris.util.ChunkPosition;
import com.volmit.iris.util.IrisLock;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.KMap;
import com.volmit.iris.util.M;
public class AtomicWorldData
{
private final TerrainTarget world;
private final KMap<ChunkPosition, AtomicSliverMap> loadedChunks;
private final KMap<ChunkPosition, AtomicRegionData> loadedSections;
private final KMap<ChunkPosition, Long> lastRegion;
private final KMap<ChunkPosition, Long> lastChunk;
private final KList<ChunkPosition> unloadRegions;
private final KList<ChunkPosition> unloadChunks;
private final IrisLock lock = new IrisLock("ULLock");
private long last = M.ms();
public AtomicWorldData(TerrainTarget world)
{
this.world = world;
loadedSections = new KMap<>();
loadedChunks = new KMap<>();
lastRegion = new KMap<>();
lastChunk = new KMap<>();
unloadRegions = new KList<>();
unloadChunks = new KList<>();
//noinspection ResultOfMethodCallIgnored
getSubregionFolder().mkdirs();
}
public KMap<ChunkPosition, AtomicRegionData> getLoadedRegions()
{
return loadedSections;
}
public AtomicRegionData getSubregion(int x, int z) throws IOException
{
lastRegion.put(new ChunkPosition(x, z), M.ms());
if(!isSectionLoaded(x, z))
{
loadedSections.put(new ChunkPosition(x, z), loadSection(x, z));
}
AtomicRegionData f = loadedSections.get(new ChunkPosition(x, z));
return f;
}
public void saveAll() throws IOException
{
saveChunks();
for(ChunkPosition i : loadedSections.keySet())
{
saveSection(i);
}
}
public void unloadAll(boolean save) throws IOException
{
saveChunks();
for(ChunkPosition i : loadedSections.keySet())
{
unloadSection(i, save);
}
loadedSections.clear();
loadedChunks.clear();
lastRegion.clear();
}
public void deleteSection(int x, int z) throws IOException
{
unloadSection(x, z, false);
//noinspection ResultOfMethodCallIgnored
getSubregionFile(x, z).delete();
}
public boolean isSectionLoaded(int x, int z)
{
return isSectionLoaded(new ChunkPosition(x, z));
}
public boolean isSectionLoaded(ChunkPosition s)
{
return loadedSections.containsKey(s);
}
public boolean unloadSection(int x, int z, boolean save) throws IOException
{
return unloadSection(new ChunkPosition(x, z), save);
}
public boolean unloadSection(ChunkPosition s, boolean save) throws IOException
{
if(!isSectionLoaded(s))
{
Iris.warn("Cant unload because section isnt loaded?");
return false;
}
if(save)
{
saveSection(s);
}
loadedSections.remove(s);
lastRegion.remove(s);
return true;
}
public boolean saveSection(int x, int z) throws IOException
{
return saveSection(new ChunkPosition(x, z));
}
public boolean saveSection(ChunkPosition s) throws IOException
{
if(!isSectionLoaded(s.getX(), s.getZ()))
{
Iris.warn("Cant save section " + s.getX() + " " + s.getZ() + " because section isnt loaded?");
return false;
}
saveChunks(s);
AtomicRegionData data = loadedSections.get(s);
FileOutputStream fos = new FileOutputStream(getSubregionFile(s.getX(), s.getZ()));
data.write(fos);
fos.close();
return true;
}
public void saveChunks() throws IOException
{
for(ChunkPosition i : loadedChunks.k())
{
saveChunk(i);
}
}
public void saveChunks(ChunkPosition reg) throws IOException
{
for(ChunkPosition i : loadedChunks.k())
{
int x = i.getX();
int z = i.getZ();
if(x >> 5 == reg.getX() && z >> 5 == reg.getZ())
{
saveChunk(i);
}
}
}
public void saveChunk(ChunkPosition i) throws IOException
{
AtomicSliverMap m = loadedChunks.get(i);
if(m.isModified())
{
int x = i.getX();
int z = i.getZ();
AtomicRegionData dat = loadSection(x >> 5, z >> 5, true);
dat.set(x & 31, z & 31, m);
}
loadedChunks.remove(i);
lastChunk.remove(i);
}
public AtomicSliverMap loadChunk(int x, int z) throws IOException
{
ChunkPosition pos = new ChunkPosition(x, z);
lastChunk.put(pos, M.ms());
if(loadedChunks.containsKey(pos))
{
return loadedChunks.get(pos);
}
AtomicRegionData dat = loadSection(x >> 5, z >> 5);
AtomicSliverMap m = dat.get(x & 31, z & 31);
loadedChunks.put(pos, m);
return m;
}
public boolean hasChunk(int x, int z) throws IOException
{
return loadSection(x >> 5, z >> 5).contains(x & 31, z & 31);
}
public AtomicRegionData loadSection(int x, int z, boolean anonymous) throws IOException
{
ChunkPosition pos = new ChunkPosition(x, z);
if(!anonymous)
{
lastRegion.put(pos, M.ms());
}
if(isSectionLoaded(x, z))
{
return loadedSections.get(pos);
}
File file = getSubregionFile(x, z);
if(!file.exists())
{
AtomicRegionData dat = createSection(x, z);
loadedSections.put(pos, dat);
return dat;
}
FileInputStream fin = new FileInputStream(file);
AtomicRegionData data = new AtomicRegionData(world);
data.read(fin);
fin.close();
loadedSections.put(pos, data);
return data;
}
public AtomicRegionData loadSection(int x, int z) throws IOException
{
return loadSection(x, z, false);
}
public AtomicRegionData createSection(int x, int z)
{
if(isSectionLoaded(x, z))
{
return loadedSections.get(new ChunkPosition(x, z));
}
AtomicRegionData data = new AtomicRegionData(world);
loadedSections.put(new ChunkPosition(x, z), data);
return data;
}
public File getSubregionFile(int x, int z)
{
return new File(getSubregionFolder(), "sr." + x + "." + z + ".smca");
}
public File getSubregionFolder()
{
return new File(world.getFolder(), "parallax");
}
public KMap<ChunkPosition, AtomicSliverMap> getLoadedChunks()
{
return loadedChunks;
}
public void clean()
{
lock.lock();
if(M.ms() - last < getUnloadBatchSpeed())
{
lock.unlock();
return;
}
int m = 0;
for(ChunkPosition i : lastRegion.keySet())
{
if(m > 1)
{
break;
}
if(M.ms() - lastRegion.get(i) > (Iris.lowMemoryMode ? 15000 : 30000))
{
unloadRegions.add(i);
m++;
}
}
m = 0;
for(ChunkPosition i : unloadRegions)
{
lastRegion.remove(i);
try
{
unloadSection(i, true);
}
catch(IOException e)
{
e.printStackTrace();
}
}
unloadRegions.clear();
for(ChunkPosition i : lastChunk.keySet())
{
if(m > getUnloadBatchSize())
{
break;
}
if(M.ms() - lastChunk.get(i) > (Iris.lowMemoryMode ? 8000 : 30000))
{
m++;
unloadChunks.add(i);
}
}
for(ChunkPosition i : unloadChunks)
{
try
{
saveChunk(i);
}
catch(IOException e)
{
Iris.warn("Failed to save chunk");
}
}
unloadChunks.clear();
lock.unlock();
}
private int getUnloadBatchSize()
{
return Math.max(3, getLoadedRegions().size() / 85);
}
private int getUnloadBatchSpeed()
{
return Math.max(250, 2000 - getLoadedRegions().size());
}
}

View File

@@ -0,0 +1,64 @@
package com.volmit.iris.generator.legacy.atomics;
import com.volmit.iris.util.IrisLock;
import com.volmit.iris.util.KMap;
public class MasterLock
{
private final KMap<String, IrisLock> locks;
private final IrisLock lock;
private boolean enabled;
public MasterLock()
{
enabled = true;
locks = new KMap<>();
lock = new IrisLock("MasterLock");
}
public void clear()
{
locks.clear();
}
public void disable()
{
enabled = false;
}
public void lock(String key)
{
if(!enabled)
{
return;
}
lock.lock();
if(!locks.containsKey(key))
{
locks.put(key, new IrisLock("Locker"));
}
IrisLock l = locks.get(key);
lock.unlock();
l.lock();
}
public void unlock(String key)
{
if(!enabled)
{
return;
}
lock.lock();
if(!locks.containsKey(key))
{
locks.put(key, new IrisLock("Unlocker"));
}
IrisLock l = locks.get(key);
lock.unlock();
l.unlock();
}
}

View File

@@ -0,0 +1,54 @@
package com.volmit.iris.generator.legacy.layer;
import com.volmit.iris.Iris;
import com.volmit.iris.generator.legacy.ContextualTerrainProvider;
import com.volmit.iris.generator.noise.CNG;
import com.volmit.iris.object.InferredType;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisGeneratorStyle;
import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.util.RNG;
import lombok.Data;
import lombok.NonNull;
@Data
public class BiomeDataProvider
{
private InferredType type;
private CNG generator;
private GenLayerBiome layer;
private double offx = 0;
private double offz = 0;
public BiomeDataProvider(@NonNull GenLayerBiome layer, @NonNull InferredType type, @NonNull RNG rng)
{
this.type = type;
this.layer = layer;
IrisGeneratorStyle b = layer.getIris().getDimension().getBiomeStyle(type);
if(b == null)
{
Iris.error("BIOME STYLE IS NULL FOR " + type);
}
generator = b.create(rng.nextParallelRNG((layer.getIris().getDimension().isAggressiveBiomeReshuffle() ? (177 + type.ordinal() + rng.nextParallelRNG(229 - type.ordinal()).nextInt()) : 4645079) + (type.ordinal() * 23845)));
if(layer.getIris().getDimension().isAggressiveBiomeReshuffle())
{
offx += generator.fitDouble(-1000, 1000, 10000, -10000);
offz += generator.fitDouble(-1000, 1000, -10000, 10000);
}
}
public IrisBiome generatePureData(ContextualTerrainProvider g, double bx, double bz, int rawX, int rawZ, IrisRegion regionData)
{
return layer.generateBiomeData(bx + offx, bz + offz, regionData, getGenerator(), regionData.getBiomes(g, getType()), getType(), (int) (rawX + offx), (int) (rawZ + offz), true);
}
public IrisBiome generateData(ContextualTerrainProvider g, double bx, double bz, int rawX, int rawZ, IrisRegion regionData)
{
return layer.generateBiomeData(bx + offx, bz + offz, regionData, getGenerator(), regionData.getBiomes(g, getType()), getType(), (int) (rawX + offx), (int) (rawZ + offz), false);
}
}

View File

@@ -0,0 +1,238 @@
package com.volmit.iris.generator.legacy.layer;
import com.volmit.iris.Iris;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.generator.legacy.DimensionalTerrainProvider;
import com.volmit.iris.generator.legacy.TopographicTerrainProvider;
import com.volmit.iris.generator.noise.CNG;
import com.volmit.iris.object.InferredType;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.object.IrisRegionRidge;
import com.volmit.iris.object.IrisRegionSpot;
import com.volmit.iris.util.GenLayer;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.RNG;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
@Data
@EqualsAndHashCode(callSuper = false)
public class GenLayerBiome extends GenLayer
{
private CNG regionGenerator;
private CNG bridgeGenerator;
private RNG lakeRandom;
private RNG riverRandom;
private BiomeDataProvider seaProvider;
private BiomeDataProvider landProvider;
private BiomeDataProvider shoreProvider;
private BiomeDataProvider caveProvider;
private BiomeDataProvider carveProvider;
private BiomeDataProvider riverProvider;
private BiomeDataProvider lakeProvider;
private DimensionalTerrainProvider iris;
public GenLayerBiome(@NonNull TopographicTerrainProvider iris, @NonNull RNG rng)
{
super(iris, rng);
this.iris = iris;
riverRandom = iris.getMasterRandom().nextParallelRNG(-324778);
lakeRandom = iris.getMasterRandom().nextParallelRNG(-868778);
seaProvider = new BiomeDataProvider(this, InferredType.SEA, !iris.getDimension().isAggressiveBiomeReshuffle() ? rng : rng.nextParallelRNG((int) (29866777 * iris.getDimension().getCoordFractureZoom())));
landProvider = new BiomeDataProvider(this, InferredType.LAND, !iris.getDimension().isAggressiveBiomeReshuffle() ? rng : rng.nextParallelRNG(-38356777 * iris.getMasterRandom().nextParallelRNG(2344).nextInt()));
shoreProvider = new BiomeDataProvider(this, InferredType.SHORE, !iris.getDimension().isAggressiveBiomeReshuffle() ? rng : rng.nextParallelRNG(29899571 + iris.getMasterRandom().nextParallelRNG(-222344).nextInt()));
caveProvider = new BiomeDataProvider(this, InferredType.CAVE, !iris.getDimension().isAggressiveBiomeReshuffle() ? rng : rng.nextParallelRNG(983564346 * -iris.getMasterRandom().nextParallelRNG(-44).nextInt()));
riverProvider = new BiomeDataProvider(this, InferredType.RIVER, !iris.getDimension().isAggressiveBiomeReshuffle() ? rng : rng.nextParallelRNG(-266717 - iris.getMasterRandom().nextParallelRNG(8100044).nextInt()));
lakeProvider = new BiomeDataProvider(this, InferredType.LAKE, !iris.getDimension().isAggressiveBiomeReshuffle() ? rng : rng.nextParallelRNG((int) (-298356111 * iris.getTarget().getSeed())));
regionGenerator = iris.getDimension().getRegionStyle().create(rng.nextParallelRNG(1188519 + (iris.getDimension().isAggressiveBiomeReshuffle() ? 329395 + (iris.getDimension().getName().hashCode()) : 0))).bake().scale(1D / iris.getDimension().getRegionZoom());
bridgeGenerator = iris.getDimension().getContinentalStyle().create(rng.nextParallelRNG(1541462 + (iris.getDimension().isAggressiveBiomeReshuffle() ? 29355 * (iris.getDimension().getRegions().size()) : 0))).bake().scale(1D / iris.getDimension().getContinentZoom());
}
public IrisRegion getRegion(double bx, double bz)
{
if(iris.getDimension().getRegions().isEmpty())
{
Iris.error("NO REGIONS!");
return null;
}
if(!iris.getDimension().getFocusRegion().trim().isEmpty())
{
return iris.loadRegion(iris.getDimension().getFocusRegion());
}
return regionGenerator.fitRarity(iris.getDimension().getAllRegions(iris), bx, bz);
}
public IrisBiome generateData(double bx, double bz, int rawX, int rawZ)
{
return generateRegionData(bx, bz, rawX, rawZ, getRegion(bx, bz));
}
public IrisBiome generateData(InferredType type, double bx, double bz, int rawX, int rawZ, IrisRegion 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)
{
if(type.equals(InferredType.SEA))
{
return seaProvider;
}
else if(type.equals(InferredType.LAND))
{
return landProvider;
}
else if(type.equals(InferredType.SHORE))
{
return shoreProvider;
}
else if(type.equals(InferredType.CAVE))
{
return caveProvider;
}
else if(type.equals(InferredType.RIVER))
{
return riverProvider;
}
else if(type.equals(InferredType.LAKE))
{
return lakeProvider;
}
else
{
Iris.error("Cannot find a BiomeDataProvider for type " + type.name());
}
return null;
}
public IrisBiome generateRegionData(double bx, double bz, int rawX, int rawZ, IrisRegion regionData)
{
return generateData(getType(bx, bz, regionData), bx, bz, rawX, rawZ, regionData);
}
public InferredType getType(double bx, double bz, IrisRegion region)
{
double c = iris.getDimension().getLandChance();
InferredType bridge;
if(c >= 1)
{
bridge = InferredType.LAND;
}
if(c <= 0)
{
bridge = InferredType.SEA;
}
bridge = bridgeGenerator.fitDouble(0, 1, bx, bz) < c ? InferredType.LAND : InferredType.SEA;
if(bridge.equals(InferredType.LAND) && region.isLake(lakeRandom, bx, bz))
{
bridge = InferredType.LAKE;
}
if(bridge.equals(InferredType.LAND) && region.isRiver(riverRandom, bx, bz))
{
bridge = InferredType.RIVER;
}
return bridge;
}
public IrisBiome generateBiomeData(double bx, double bz, IrisRegion regionData, CNG cell, KList<IrisBiome> biomes, InferredType inferredType, int rx, int rz)
{
return generateBiomeData(bx, bz, regionData, cell, biomes, inferredType, rx, rz, false);
}
public IrisBiome generateBiomeData(double bx, double bz, IrisRegion regionData, CNG cell, KList<IrisBiome> biomes, InferredType inferredType, int rx, int rz, boolean pure)
{
if(!pure)
{
for(IrisRegionRidge i : regionData.getRidgeBiomes())
{
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);
}
}
}
if(biomes.isEmpty())
{
return null;
}
double x = bx / (iris.getDimension().getBiomeZoom() * regionData.getBiomeZoom(inferredType));
double z = bz / (iris.getDimension().getBiomeZoom() * regionData.getBiomeZoom(inferredType));
IrisBiome biome = cell.fitRarity(biomes, x, z);
biome.setInferredType(inferredType);
return implode(bx, bz, regionData, cell, biome);
}
public IrisBiome generateImpureData(int rawX, int rawZ, InferredType type, IrisRegion regionData, IrisBiome pureResult)
{
return pureResult;
}
public IrisBiome implode(double bx, double bz, IrisRegion regionData, CNG parentCell, IrisBiome parent)
{
return implode(bx, bz, regionData, parentCell, parent, 1);
}
public IrisBiome implode(double bx, double bz, IrisRegion regionData, CNG parentCell, IrisBiome parent, int hits)
{
if(hits > IrisSettings.get().maxBiomeChildDepth)
{
return parent;
}
double x = bx / iris.getDimension().getBiomeZoom();
double z = bz / iris.getDimension().getBiomeZoom();
if(parent.getRealChildren(iris).isNotEmpty())
{
CNG childCell = parent.getChildrenGenerator(rng, 123, parent.getChildShrinkFactor());
KList<IrisBiome> chx = parent.getRealChildren(iris).copy();
chx.add(parent);
IrisBiome biome = childCell.fitRarity(chx, x, z);
biome.setInferredType(parent.getInferredType());
return implode(bx, bz, regionData, childCell, biome, hits + 1);
}
return parent;
}
@Override
public double generate(double x, double z)
{
return 0;
}
}

View File

@@ -0,0 +1,135 @@
package com.volmit.iris.generator.legacy.layer;
import com.volmit.iris.generator.legacy.TopographicTerrainProvider;
import com.volmit.iris.object.IrisCarveLayer;
import com.volmit.iris.util.CarveResult;
import com.volmit.iris.util.GenLayer;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.RNG;
import lombok.Getter;
public class GenLayerCarve extends GenLayer
{
private static final KList<CarveResult> EMPTY_LIST = new KList<>();
@Getter
private final boolean couldCarve;
@Getter
private int minimum;
@Getter
private int maximum;
public GenLayerCarve(TopographicTerrainProvider iris, RNG rng)
{
super(iris, rng);
couldCarve = iris.getDimension().isCarving() && iris.getDimension().getCarveLayers().isNotEmpty();
minimum = 512;
maximum = -256;
for(IrisCarveLayer i : iris.getDimension().getCarveLayers())
{
minimum = i.getMinHeight() < minimum ? i.getMinHeight() : minimum;
maximum = i.getMaxHeight() > maximum ? i.getMaxHeight() : maximum;
}
}
public boolean couldCarve(int y)
{
return couldCarve && y >= minimum && y <= maximum;
}
public boolean couldCarveBelow(int y)
{
return couldCarve && y <= maximum;
}
public KList<CarveResult> getCarveLayers(int x, int z)
{
if(!couldCarve)
{
return EMPTY_LIST;
}
KList<CarveResult> surfaces = new KList<>();
int terrainHeight = (int) Math.round(iris.getTerrainHeight(x, z));
boolean carving = false;
int lastCarve = terrainHeight + 1;
for(int i = Math.min(maximum, terrainHeight); i >= Math.max(minimum, 0); i--)
{
if(i <= 0 || i > 255)
{
continue;
}
boolean nowCarving = isCarved(x, i, z);
if(carving && !nowCarving)
{
if(lastCarve - i > 2 && !(i < terrainHeight && lastCarve - i > terrainHeight))
{
surfaces.add(new CarveResult(i, lastCarve));
}
}
if(nowCarving && !carving)
{
lastCarve = i;
}
carving = nowCarving;
}
return surfaces;
}
public int getSurfaceCarve(int x, int y, int z)
{
if(couldCarveBelow(y))
{
int h = y;
while(isCarved(x, h, z))
{
if(h <= 0)
{
break;
}
h--;
}
return h;
}
return y;
}
public boolean isCarved(int xc, int y, int zc)
{
if(!couldCarve(y))
{
return false;
}
for(IrisCarveLayer i : iris.getDimension().getCarveLayers())
{
if(i.isCarved(rng, xc, y, zc))
{
return true;
}
}
return false;
}
@Override
public double generate(double x, double z)
{
return 0;
}
}

View File

@@ -0,0 +1,200 @@
package com.volmit.iris.generator.legacy.layer;
import java.util.function.Function;
import com.volmit.iris.util.*;
import org.bukkit.Material;
import com.volmit.iris.generator.legacy.TopographicTerrainProvider;
import com.volmit.iris.generator.legacy.atomics.AtomicSliver;
import com.volmit.iris.generator.noise.FastNoiseDouble;
import com.volmit.iris.generator.noise.FastNoiseDouble.CellularDistanceFunction;
import com.volmit.iris.generator.noise.FastNoiseDouble.CellularReturnType;
import com.volmit.iris.generator.noise.FastNoiseDouble.NoiseType;
import com.volmit.iris.object.IrisCaveLayer;
import org.bukkit.block.data.BlockData;
public class GenLayerCave extends GenLayer
{
public static boolean bad = false;
public static final BlockData CAVE_AIR = B.getBlockData("CAVE_AIR");
public static final BlockData AIR = B.getBlockData("AIR");
private static final KList<CaveResult> EMPTY = new KList<>();
private final FastNoiseDouble gg;
public GenLayerCave(TopographicTerrainProvider iris, RNG rng)
{
super(iris, rng);
gg = new FastNoiseDouble(324895 * rng.nextParallelRNG(49678).imax());
}
public KList<CaveResult> genCaves(double wxx, double wzz, int x, int z, AtomicSliver data)
{
if(!iris.getDimension().isCaves())
{
return EMPTY;
}
KList<CaveResult> result = new KList<>();
gg.setNoiseType(NoiseType.Cellular);
gg.setCellularReturnType(CellularReturnType.Distance2Sub);
gg.setCellularDistanceFunction(CellularDistanceFunction.Natural);
for(int i = 0; i < iris.getDimension().getCaveLayers().size(); i++)
{
IrisCaveLayer layer = iris.getDimension().getCaveLayers().get(i);
generateCave(result, wxx, wzz, x, z, data, layer, i);
}
return result;
}
public void generateCave(KList<CaveResult> result, double wxx, double wzz, int x, int z, AtomicSliver data, IrisCaveLayer layer, int seed)
{
double scale = layer.getCaveZoom();
Function<Integer, BlockData> fluid = (height) ->
{
if(!layer.getFluid().hasFluid(iris.getData()))
{
return CAVE_AIR;
}
if(layer.getFluid().isInverseHeight() && height >= layer.getFluid().getFluidHeight())
{
return layer.getFluid().getFluid(iris.getData());
}
else if(!layer.getFluid().isInverseHeight() && height <= layer.getFluid().getFluidHeight())
{
return layer.getFluid().getFluid(iris.getData());
}
return CAVE_AIR;
};
int surface = (int) Math.round(iris.getTerrainHeight((int) wxx, (int) wzz));
double wx = wxx + layer.getHorizontalSlope().get(rng, wxx, wzz);
double wz = wzz + layer.getHorizontalSlope().get(rng, -wzz, -wxx);
double baseWidth = (14 * scale);
double distanceCheck = 0.0132 * baseWidth;
double distanceTake = 0.0022 * baseWidth;
double caveHeightNoise = layer.getVerticalSlope().get(rng, wxx, wzz);
if(caveHeightNoise > 259 || caveHeightNoise < -1)
{
return;
}
int ceiling = -256;
int floor = 512;
for(double tunnelHeight = 1; tunnelHeight <= baseWidth; tunnelHeight++)
{
double distance = (gg.GetCellular(((wx + (10000 * seed)) / layer.getCaveZoom()), ((wz - (10000 * seed)) / layer.getCaveZoom())) + 1D) / 2D;
if(distance < distanceCheck - (tunnelHeight * distanceTake))
{
int caveHeight = (int) Math.round(caveHeightNoise);
int pu = (int) (caveHeight + tunnelHeight);
int pd = (int) (caveHeight - tunnelHeight);
if(pd > surface + 1)
{
continue;
}
if(!layer.isCanBreakSurface() && pu > surface - 3)
{
continue;
}
if((pu > 255 && pd > 255) || (pu < 0 && pd < 0))
{
continue;
}
if(data == null)
{
ceiling = Math.max(pu, ceiling);
floor = Math.min(pu, floor);
ceiling = Math.max(pd, ceiling);
floor = Math.min(pd, floor);
if(tunnelHeight == 1)
{
ceiling = Math.max(caveHeight, ceiling);
floor = Math.min(caveHeight, floor);
}
}
else
{
if(dig(x, pu, z, data, fluid))
{
ceiling = Math.max(pu, ceiling);
floor = Math.min(pu, floor);
}
if(dig(x, pd, z, data, fluid))
{
ceiling = Math.max(pd, ceiling);
floor = Math.min(pd, floor);
}
if(tunnelHeight == 1)
{
if(dig(x, caveHeight, z, data, fluid))
{
ceiling = Math.max(caveHeight, ceiling);
floor = Math.min(caveHeight, floor);
}
}
}
}
}
if(floor >= 0 && ceiling <= 255)
{
result.add(new CaveResult(floor, ceiling));
}
}
public boolean dig(int x, int y, int z, AtomicSliver data, Function<Integer, BlockData> caveFluid)
{
Material a = data.getTypeSafe(y);
Material c = data.getTypeSafe(y + 1);
Material d = data.getTypeSafe(y + 2);
Material e = data.getTypeSafe(y + 3);
Material f = data.getTypeSafe(y - 1);
BlockData b = caveFluid.apply(y);
BlockData b2 = caveFluid.apply(y + 1);
if(can(a) && canAir(c, b) && canAir(f, b) && canWater(d) && canWater(e))
{
data.set(y, b);
data.set(y + 1, b2);
return true;
}
return false;
}
public boolean canAir(Material m, BlockData caveFluid)
{
return (B.isSolid(m) || (B.isDecorant(m.createBlockData())) || m.equals(Material.AIR) || m.equals(caveFluid.getMaterial()) || m.equals(B.mat("CAVE_AIR").getMaterial())) && !m.equals(Material.BEDROCK);
}
public boolean canWater(Material m)
{
return !m.equals(Material.WATER);
}
public boolean can(Material m)
{
return B.isSolid(m) && !m.equals(Material.BEDROCK);
}
@Override
public double generate(double x, double z)
{
return 0;
}
}

View File

@@ -0,0 +1,310 @@
package com.volmit.iris.generator.legacy.layer;
import org.bukkit.Material;
import com.volmit.iris.generator.legacy.TopographicTerrainProvider;
import com.volmit.iris.generator.legacy.atomics.AtomicSliverMap;
import com.volmit.iris.generator.legacy.scaffold.TerrainChunk;
import com.volmit.iris.generator.noise.CNG;
import com.volmit.iris.object.NoiseStyle;
import com.volmit.iris.util.B;
import com.volmit.iris.util.BiomeMap;
import com.volmit.iris.util.BlockPosition;
import com.volmit.iris.util.ChunkPosition;
import com.volmit.iris.util.GenLayer;
import com.volmit.iris.util.HeightMap;
import com.volmit.iris.util.MathHelper;
import com.volmit.iris.util.RNG;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.bukkit.block.data.BlockData;
@Data
@EqualsAndHashCode(callSuper = false)
public class GenLayerRavine extends GenLayer
{
private static final BlockData CAVE_AIR = B.get("CAVE_AIR");
private static final BlockData LAVA = B.get("LAVA");
private CNG cng;
public GenLayerRavine(TopographicTerrainProvider iris, RNG rng)
{
super(iris, rng);
cng = NoiseStyle.IRIS_THICK.create(rng.nextParallelRNG(29596878));
}
@Override
public double generate(double x, double z)
{
return 0;
}
private void set(TerrainChunk pos, int x, int y, int z, BlockData b, HeightMap h, AtomicSliverMap map)
{
pos.setBlock(x, y, z, b);
map.getSliver(x, z).set(y, b);
if(h.getHeight(x, z) > y)
{
h.setHeight(x, z, y);
}
}
private BlockData get(TerrainChunk pos, int x, int y, int z)
{
return pos.getBlockData(x, y, z);
}
private BlockData getSurfaceBlock(BiomeMap map, int n6, int i, RNG rmg)
{
return map.getBiome(n6, i).getSurfaceBlock(n6, i, rmg, iris.getData());
}
private float[] ravineCache = new float[1024];
private void doRavine(long seed, int tx, int tz, ChunkPosition pos, double sx, double sy, double sz, float f, float f2, float f3, int n3, int n4, double d4, RNG bbx, TerrainChunk terrain, HeightMap height, BiomeMap biomeMap, AtomicSliverMap map)
{
int n5;
RNG random = new RNG(seed);
double x = tx * 16 + 8;
double z = tz * 16 + 8;
float f4 = 0.0f;
float f5 = 0.0f;
if(n4 <= 0)
{
n5 = 8 * 16 - 16;
n4 = n5 - random.nextInt(n5 / 4);
}
n5 = 0;
if(n3 == -1)
{
n3 = n4 / 2;
n5 = 1;
}
float f6 = 1.0f;
for(int i = 0; i < 256; ++i)
{
if(i == 0 || random.nextInt(iris.getDimension().getRavineRibRarity()) == 0)
{
f6 = 1.0f + random.nextFloat() * random.nextFloat() * 1.0f;
}
this.ravineCache[i] = f6 * f6;
}
while(n3 < n4)
{
double d7 = 1.5 + (double) (MathHelper.sin((float) n3 * 3.1415927f / (float) n4) * f * 1.0f);
double d8 = d7 * d4;
d7 *= (double) random.nextFloat() * 0.25 + 0.75;
d8 *= (double) random.nextFloat() * 0.25 + 0.75;
float f7 = MathHelper.cos(f3);
float f8 = MathHelper.sin(f3);
sx = sx + (double) (MathHelper.cos(f2) * f7);
sy += f8;
sz += MathHelper.sin(f2) * f7;
f3 *= 0.7f;
f3 += f5 * 0.05f;
f2 += f4 * 0.05f;
f5 *= 0.8f;
f4 *= 0.5f;
f5 += (random.nextFloat() - random.nextFloat()) * random.nextFloat() * 2.0f;
f4 += (random.nextFloat() - random.nextFloat()) * random.nextFloat() * 4.0f;
if(n5 != 0 || random.nextInt(4) != 0)
{
double d9 = sx - x;
double d10 = sz - z;
double d11 = n4 - n3;
double d12 = f + 2.0f + 16.0f;
if(d9 * d9 + d10 * d10 - d11 * d11 > d12 * d12)
{
return;
}
if(sx >= x - 16.0 - d7 * 2.0 && sz >= z - 16.0 - d7 * 2.0 && sx <= x + 16.0 + d7 * 2.0 && sz <= z + 16.0 + d7 * 2.0)
{
int n6;
int n7 = MathHelper.floor(sx - d7) - tx * 16 - 1;
int n8 = MathHelper.floor(sx + d7) - tx * 16 + 1;
int n9 = MathHelper.floor(sy - d8) - 1;
int n10 = MathHelper.floor(sy + d8) + 1;
int n11 = MathHelper.floor(sz - d7) - tz * 16 - 1;
int n12 = MathHelper.floor(sz + d7) - tz * 16 + 1;
if(n7 < 0)
{
n7 = 0;
}
if(n8 > 16)
{
n8 = 16;
}
if(n9 < 1)
{
n9 = 1;
}
if(n10 > 248)
{
n10 = 248;
}
if(n11 < 0)
{
n11 = 0;
}
if(n12 > 16)
{
n12 = 16;
}
boolean bl = false;
for(int i = n7; !bl && i < n8; ++i)
{
for(n6 = n11; !bl && n6 < n12; ++n6)
{
for(int j = n10 + 1; !bl && j >= n9 - 1; --j)
{
if(j < 0 || j >= 256)
{
continue;
}
BlockData bb = get(terrain, i, j, n6);
if(B.isWater(bb))
{
bl = true;
}
if(j == n9 - 1 || i == n7 || i == n8 - 1 || n6 == n11 || n6 == n12 - 1)
{
continue;
}
j = n9;
}
}
}
if(!bl)
{
BlockPosition bps = new BlockPosition(0, 0, 0);
for(n6 = n7; n6 < n8; ++n6)
{
double d13 = ((double) (n6 + tx * 16) + 0.5 - sx) / d7;
for(int i = n11; i < n12; ++i)
{
double d14 = ((double) (i + tz * 16) + 0.5 - sz) / d7;
boolean bl2 = false;
if(d13 * d13 + d14 * d14 >= 1.0)
{
continue;
}
for(int j = n10; j > n9; --j)
{
double d15 = ((double) (j - 1) + 0.5 - sy) / d8;
if((d13 * d13 + d14 * d14) * (double) this.ravineCache[j - 1] + d15 * d15 / 6.0 >= 1.0)
{
continue;
}
BlockData blockData = get(terrain, n6, j, i);
if(isSurface(blockData))
{
bl2 = true;
}
if(j - 1 < 10)
{
set(terrain, n6, j, i, LAVA, height, map);
continue;
}
set(terrain, n6, j, i, CAVE_AIR, height, map);
if(!bl2 || !isDirt(get(terrain, n6, j - 1, i)))
{
continue;
}
cSet(bps, n6 + tx * 16, 0, i + tz * 16);
set(terrain, n6, j - 1, i, getSurfaceBlock(biomeMap, n6, i, rng), height, map);
}
}
}
if(n5 != 0)
break;
}
}
}
++n3;
}
}
private BlockPosition cSet(BlockPosition bb, double var0, double var2, double var4)
{
bb.setX(MathHelper.floor((double) var0));
bb.setY(MathHelper.floor((double) var2));
bb.setZ(MathHelper.floor((double) var4));
return bb;
}
private boolean isDirt(BlockData d)
{
//@builder
Material m = d.getMaterial();
return m.equals(Material.DIRT) ||
m.equals(Material.COARSE_DIRT) ||
m.equals(Material.SAND);
//@done
}
private boolean isSurface(BlockData d)
{
//@builder
Material m = d.getMaterial();
return m.equals(Material.GRASS_BLOCK) ||
m.equals(Material.DIRT) ||
m.equals(Material.COARSE_DIRT) ||
m.equals(Material.PODZOL) ||
m.equals(Material.SAND);
//@done
}
public void genRavines(int n, int n2, ChunkPosition chunkSnapshot, RNG bbb, TerrainChunk terrain, HeightMap height, BiomeMap biomeMap, AtomicSliverMap map)
{
RNG b = this.rng.nextParallelRNG(21949666);
RNG bx = this.rng.nextParallelRNG(6676121);
long l = b.nextLong();
long l2 = b.nextLong();
for(int i = n - 8; i <= n + 8; ++i)
{
for(int j = n2 - 8; j <= n2 + 8; ++j)
{
long l3 = (long) i * l;
long l4 = (long) j * l2;
bx = this.rng.nextParallelRNG((int) (l3 ^ l4 ^ 6676121));
doRavines(i, j, n, n2, chunkSnapshot, bx, terrain, height, biomeMap, map);
}
}
}
private void doRavines(int tx, int tz, int sx, int sz, ChunkPosition chunkSnapshot, RNG b, TerrainChunk terrain, HeightMap height, BiomeMap biomeMap, AtomicSliverMap map)
{
if(b.nextInt(iris.getDimension().getRavineRarity()) != 0)
{
return;
}
double x = tx * 16 + b.nextInt(16);
double d2 = b.nextInt(b.nextInt(40) + 8) + 20;
double z = tz * 16 + b.nextInt(16);
int n5 = 1;
for(int i = 0; i < n5; ++i)
{
float f = b.nextFloat() * 3.1415927f * 2.0f;
float f2 = (b.nextFloat() - 0.5f) * 2.0f / 8.0f;
float f3 = (b.nextFloat() * 2.0f + b.nextFloat()) * 2.0f;
this.doRavine(b.nextLong(), sx, sz, chunkSnapshot, x, d2, z, f3, f, f2, 0, 0, 3.0, b, terrain, height, biomeMap, map);
}
}
public void generateRavines(RNG nextParallelRNG, int x, int z, TerrainChunk terrain, HeightMap height, BiomeMap biomeMap, AtomicSliverMap map)
{
genRavines(x, z, new ChunkPosition(x, z), nextParallelRNG.nextParallelRNG(x).nextParallelRNG(z), terrain, height, biomeMap, map);
}
}

View File

@@ -0,0 +1,88 @@
package com.volmit.iris.generator.legacy.layer;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import com.volmit.iris.Iris;
import com.volmit.iris.generator.legacy.TopographicTerrainProvider;
import com.volmit.iris.generator.legacy.atomics.AtomicCache;
import com.volmit.iris.object.IrisMaterialPalette;
import com.volmit.iris.object.IrisObject;
import com.volmit.iris.util.B;
import com.volmit.iris.util.GenLayer;
import com.volmit.iris.util.RNG;
import org.bukkit.block.data.BlockData;
public class GenLayerText extends GenLayer
{
public static final BlockData AIR = B.getBlockData("AIR");
private final AtomicCache<IrisObject> debug = new AtomicCache<>();
public GenLayerText(TopographicTerrainProvider iris, RNG rng)
{
super(iris, rng);
}
public IrisObject getDebug()
{
return debug.aquire(() -> createTextObject("Test", "Impact", 24, B.get("STONE")));
}
public IrisObject createTextObject(String text, String font, int size, BlockData b)
{
Font f = new Font(font, Font.PLAIN, size);
int w = ((Graphics2D) new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).getGraphics()).getFontMetrics(f).stringWidth(text);
int h = size;
Iris.info("WH is " + w + " " + h);
BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics gs = bufferedImage.getGraphics();
Graphics2D g = (Graphics2D) gs;
g.setFont(f);
g.drawString(text, 0, h);
IrisObject o = new IrisObject(w, 1, h);
for(int y = 0; y < h; y++)
{
for(int x = 0; x < w; x++)
{
if(bufferedImage.getRGB(x, y) != -16777216)
{
o.setUnsigned(x, 0, y, b);
}
}
}
return o;
}
public IrisObject createTextObject(RNG rng, String text, int w, Font f, IrisMaterialPalette palette)
{
int h = f.getSize();
BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics gs = bufferedImage.getGraphics();
Graphics2D g = (Graphics2D) gs;
g.setFont(f);
g.drawString(text, 0, h);
IrisObject o = new IrisObject(w, 1, h);
for(int y = 0; y < h; y++)
{
for(int x = 0; x < w; x++)
{
if(bufferedImage.getRGB(x, y) != -16777216)
{
o.setUnsigned(x, 0, y, palette.get(rng, x, w, y, iris.getData()));
}
}
}
return o;
}
@Override
public double generate(double x, double z)
{
return 0;
}
}

View File

@@ -0,0 +1,318 @@
package com.volmit.iris.generator.legacy.layer;
import java.util.Arrays;
import java.util.Random;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.generator.legacy.IrisTerrainProvider;
import com.volmit.iris.generator.legacy.ParallaxTerrainProvider;
import com.volmit.iris.generator.legacy.atomics.AtomicSliverMap;
import com.volmit.iris.generator.legacy.scaffold.ChunkWrapper;
import com.volmit.iris.object.InventorySlotType;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDepositGenerator;
import com.volmit.iris.object.IrisLootReference;
import com.volmit.iris.object.IrisLootTable;
import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.object.LootMode;
import com.volmit.iris.util.B;
import com.volmit.iris.util.IrisStructureResult;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RNG;
public class GenLayerUpdate extends BlockPopulator
{
private final ParallaxTerrainProvider gen;
private final RNG rng;
public GenLayerUpdate(ParallaxTerrainProvider gen)
{
this.gen = gen;
this.rng = new RNG(gen.getTarget().getSeed() + 4996788).nextParallelRNG(-98618289);
}
@Override
public void populate(World w, Random r, Chunk c)
{
if(gen == null)
{
return;
}
AtomicSliverMap map = null;
try
{
map = gen.getParallaxChunk(c.getX(), c.getZ());
}
catch(Throwable e)
{
map = new AtomicSliverMap();
}
try
{
RNG rx = rng.nextParallelRNG(c.getX() + r.nextInt()).nextParallelRNG(c.getZ() + r.nextInt());
if(gen.getDimension().isVanillaCaves())
{
generateDepositsWithVanillaSaftey(w, rx, c);
}
updateBlocks(rx, c, map);
spawnInitials(c, rx);
}
catch(Throwable e)
{
}
}
public void spawnInitials(Chunk c, RNG rx)
{
if(!IrisSettings.get().isSystemEntityInitialSpawns())
{
return;
}
PrecisionStopwatch p = PrecisionStopwatch.start();
((IrisTerrainProvider) gen).spawnInitials(c, rx);
p.end();
gen.getMetrics().getSpawns().put(p.getMilliseconds());
}
public void generateDepositsWithVanillaSaftey(World w, RNG rx, Chunk c)
{
PrecisionStopwatch p = PrecisionStopwatch.start();
int x = c.getX();
int z = c.getZ();
RNG ro = rx.nextParallelRNG((x * x * x) - z);
IrisRegion region = gen.sampleRegion((x * 16) + 7, (z * 16) + 7);
IrisBiome biome = gen.sampleTrueBiome((x * 16) + 7, (z * 16) + 7);
ChunkWrapper terrain = new ChunkWrapper(c);
for(IrisDepositGenerator k : gen.getDimension().getDeposits())
{
k.generate(terrain, ro, gen, x, z, true);
}
for(IrisDepositGenerator k : region.getDeposits())
{
for(int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++)
{
k.generate(terrain, ro, gen, x, z, true);
}
}
for(IrisDepositGenerator k : biome.getDeposits())
{
for(int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++)
{
k.generate(terrain, ro, gen, x, z, true);
}
}
p.end();
gen.getMetrics().getDeposits().put(p.getMilliseconds());
}
private void updateBlocks(RNG rx, Chunk c, AtomicSliverMap map)
{
PrecisionStopwatch p = PrecisionStopwatch.start();
for(int i = 0; i < 16; i++)
{
for(int j = 0; j < 16; j++)
{
for(byte kv : map.getSliver(i, j).getUpdatables())
{
byte k = (byte) (kv - Byte.MIN_VALUE);
if(k > 255 || k < 0)
{
continue;
}
update(c, i, k, j, i + (c.getX() << 4), i + (c.getZ() << 4), rx);
}
}
}
p.end();
gen.getMetrics().getUpdate().put(p.getMilliseconds());
}
public void update(Chunk c, int x, int y, int z, int rx, int rz, RNG rng)
{
Block b = c.getBlock(x, y, z);
BlockData d = b.getBlockData();
if(B.isLit(d))
{
updateLight(b, d);
}
else if(B.isStorage(d))
{
updateStorage(b, d, rx, rz, rng);
}
}
public void injectTables(KList<IrisLootTable> list, IrisLootReference r)
{
if(r.getMode().equals(LootMode.CLEAR) || r.getMode().equals(LootMode.REPLACE))
{
list.clear();
}
list.addAll(r.getLootTables(gen));
}
public KList<IrisLootTable> getLootTables(RNG rng, Block b)
{
int rx = b.getX();
int rz = b.getZ();
IrisRegion region = gen.sampleRegion(rx, rz);
IrisBiome biomeSurface = gen.sampleTrueBiome(rx, rz);
IrisBiome biomeUnder = gen.sampleTrueBiome(rx, b.getY(), rz);
KList<IrisLootTable> tables = new KList<>();
IrisStructureResult structure = gen.getStructure(rx, b.getY(), rz);
double multiplier = 1D * gen.getDimension().getLoot().getMultiplier() * region.getLoot().getMultiplier() * biomeSurface.getLoot().getMultiplier() * biomeUnder.getLoot().getMultiplier();
injectTables(tables, gen.getDimension().getLoot());
injectTables(tables, region.getLoot());
injectTables(tables, biomeSurface.getLoot());
injectTables(tables, biomeUnder.getLoot());
if(structure != null && structure.getTile() != null)
{
injectTables(tables, structure.getStructure().getLoot());
injectTables(tables, structure.getTile().getLoot());
multiplier *= structure.getStructure().getLoot().getMultiplier() * structure.getTile().getLoot().getMultiplier();
}
if(tables.isNotEmpty())
{
int target = (int) Math.round(tables.size() * multiplier);
while(tables.size() < target && tables.isNotEmpty())
{
tables.add(tables.get(rng.i(tables.size() - 1)));
}
while(tables.size() > target && tables.isNotEmpty())
{
tables.remove(rng.i(tables.size() - 1));
}
}
return tables;
}
public void addItems(boolean debug, Inventory inv, RNG rng, KList<IrisLootTable> tables, InventorySlotType slot, int x, int y, int z, int mgf)
{
KList<ItemStack> items = new KList<>();
int b = 4;
for(IrisLootTable i : tables)
{
b++;
items.addAll(i.getLoot(debug, items.isEmpty(), rng.nextParallelRNG(345911), slot, x, y, z, b + b, mgf + b));
}
for(ItemStack i : items)
{
inv.addItem(i);
}
scramble(inv, rng);
}
public void updateStorage(Block b, BlockData data, int rx, int rz, RNG rng)
{
InventorySlotType slot = null;
if(B.isStorageChest(data))
{
slot = InventorySlotType.STORAGE;
}
if(slot != null)
{
KList<IrisLootTable> tables = getLootTables(rng.nextParallelRNG(4568111), b);
InventorySlotType slott = slot;
try
{
InventoryHolder m = (InventoryHolder) b.getState();
addItems(false, m.getInventory(), rng, tables, slott, rx, b.getY(), rz, 15);
}
catch(Throwable ignored)
{
}
}
}
public void scramble(Inventory inventory, RNG rng)
{
ItemStack[] items = inventory.getContents();
ItemStack[] nitems = new ItemStack[inventory.getSize()];
System.arraycopy(items, 0, nitems, 0, items.length);
boolean packedFull = false;
splitting: for(int i = 0; i < nitems.length; i++)
{
ItemStack is = nitems[i];
if(is != null && is.getAmount() > 1 && !packedFull)
{
for(int j = 0; j < nitems.length; j++)
{
if(nitems[j] == null)
{
int take = rng.nextInt(is.getAmount());
take = take == 0 ? 1 : take;
is.setAmount(is.getAmount() - take);
nitems[j] = is.clone();
nitems[j].setAmount(take);
continue splitting;
}
}
packedFull = true;
}
}
for(int i = 0; i < 4; i++)
{
try
{
Arrays.parallelSort(nitems, (a, b) -> rng.nextInt());
break;
}
catch(Throwable e)
{
}
}
inventory.setContents(nitems);
}
public void updateLight(Block b, BlockData data)
{
b.setType(Material.AIR, false);
b.setBlockData(data, false);
}
}

View File

@@ -0,0 +1,71 @@
package com.volmit.iris.generator.legacy.nms;
import com.volmit.iris.Iris;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.generator.legacy.nms.v16_2.NMSBinding16_2;
import com.volmit.iris.generator.legacy.nms.v1X.NMSBinding1X;
import com.volmit.iris.util.KMap;
import org.bukkit.Bukkit;
public class INMS
{
//@builder
private static final KMap<String, Class<? extends INMSBinding>> bindings = new KMap<String, Class<? extends INMSBinding>>()
.qput("v1_16_R2", NMSBinding16_2.class);
//@done
private static final INMSBinding binding = bind();
public static INMSBinding get()
{
return binding;
}
private static final String getNMSTag()
{
if(IrisSettings.get().disableNMS)
{
return "BUKKIT";
}
try
{
return Bukkit.getServer().getClass().getCanonicalName().split("\\Q.\\E")[3];
}
catch(Throwable e)
{
Iris.error("Failed to determine server nms version!");
e.printStackTrace();
}
return "BUKKIT";
}
private static final INMSBinding bind()
{
String code = getNMSTag();
Iris.info("Locating NMS Binding for " + code);
if(bindings.containsKey(code))
{
try
{
INMSBinding b = bindings.get(code).getConstructor().newInstance();
Iris.info("Craftbukkit " + code + " <-> " + b.getClass().getSimpleName() + " Successfully Bound");
return b;
}
catch(Throwable e)
{
e.printStackTrace();
}
}
Iris.info("Craftbukkit " + code + " <-> " + NMSBinding1X.class.getSimpleName() + " Successfully Bound");
Iris.warn("Note: Some features of Iris may not work the same since you are on an unsupported version of Minecraft.");
Iris.warn("Note: If this is a new version, expect an update soon.");
return new NMSBinding1X();
}
}

View File

@@ -0,0 +1,19 @@
package com.volmit.iris.generator.legacy.nms;
import org.bukkit.World;
import org.bukkit.WorldCreator;
public interface INMSBinding
{
public INMSCreator getCreator();
default World createWorld(WorldCreator creator)
{
return getCreator().createWorld(creator);
}
default World createWorld(WorldCreator creator, boolean loadSpawn)
{
return getCreator().createWorld(creator, loadSpawn);
}
}

View File

@@ -0,0 +1,14 @@
package com.volmit.iris.generator.legacy.nms;
import org.bukkit.World;
import org.bukkit.WorldCreator;
public interface INMSCreator
{
default World createWorld(WorldCreator creator)
{
return createWorld(creator, false);
}
public World createWorld(WorldCreator creator, boolean loadSpawn);
}

View File

@@ -0,0 +1,16 @@
package com.volmit.iris.generator.legacy.nms.v16_2;
import com.volmit.iris.generator.legacy.atomics.AtomicCache;
import com.volmit.iris.generator.legacy.nms.INMSBinding;
import com.volmit.iris.generator.legacy.nms.INMSCreator;
public class NMSBinding16_2 implements INMSBinding
{
private final AtomicCache<INMSCreator> creator = new AtomicCache<>();
@Override
public INMSCreator getCreator()
{
return creator.aquire(NMSCreator16_2::new);
}
}

View File

@@ -0,0 +1,793 @@
package com.volmit.iris.generator.legacy.nms.v16_2;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.IntStream;
import javax.annotation.Nullable;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectList;
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
import net.minecraft.server.v1_16_R2.BiomeBase;
import net.minecraft.server.v1_16_R2.BiomeSettingsMobs;
import net.minecraft.server.v1_16_R2.BlockColumn;
import net.minecraft.server.v1_16_R2.BlockPosition;
import net.minecraft.server.v1_16_R2.Blocks;
import net.minecraft.server.v1_16_R2.ChunkCoordIntPair;
import net.minecraft.server.v1_16_R2.ChunkGenerator;
import net.minecraft.server.v1_16_R2.ChunkGeneratorAbstract;
import net.minecraft.server.v1_16_R2.ChunkSection;
import net.minecraft.server.v1_16_R2.EnumCreatureType;
import net.minecraft.server.v1_16_R2.GeneratorAccess;
import net.minecraft.server.v1_16_R2.GeneratorSettingBase;
import net.minecraft.server.v1_16_R2.HeightMap;
import net.minecraft.server.v1_16_R2.IBlockAccess;
import net.minecraft.server.v1_16_R2.IBlockData;
import net.minecraft.server.v1_16_R2.IChunkAccess;
import net.minecraft.server.v1_16_R2.MathHelper;
import net.minecraft.server.v1_16_R2.NoiseGenerator;
import net.minecraft.server.v1_16_R2.NoiseGenerator3;
import net.minecraft.server.v1_16_R2.NoiseGenerator3Handler;
import net.minecraft.server.v1_16_R2.NoiseGeneratorOctaves;
import net.minecraft.server.v1_16_R2.NoiseGeneratorPerlin;
import net.minecraft.server.v1_16_R2.NoiseSettings;
import net.minecraft.server.v1_16_R2.ProtoChunk;
import net.minecraft.server.v1_16_R2.RegionLimitedWorldAccess;
import net.minecraft.server.v1_16_R2.ResourceKey;
import net.minecraft.server.v1_16_R2.SectionPosition;
import net.minecraft.server.v1_16_R2.SeededRandom;
import net.minecraft.server.v1_16_R2.SpawnerCreature;
import net.minecraft.server.v1_16_R2.StructureBoundingBox;
import net.minecraft.server.v1_16_R2.StructureGenerator;
import net.minecraft.server.v1_16_R2.StructureManager;
import net.minecraft.server.v1_16_R2.StructurePiece;
import net.minecraft.server.v1_16_R2.SystemUtils;
import net.minecraft.server.v1_16_R2.WorldChunkManager;
import net.minecraft.server.v1_16_R2.WorldChunkManagerTheEnd;
import net.minecraft.server.v1_16_R2.WorldGenFeatureDefinedStructureJigsawJunction;
import net.minecraft.server.v1_16_R2.WorldGenFeatureDefinedStructurePoolTemplate;
import net.minecraft.server.v1_16_R2.WorldGenFeaturePillagerOutpostPoolPiece;
public class NMSChunkGenerator16_2_BACKUP extends ChunkGenerator
{
//@builder
public static final Codec<NMSChunkGenerator16_2_BACKUP> d = RecordCodecBuilder.create((instance) -> {
return instance.group(WorldChunkManager.a.fieldOf("biome_source").forGetter((chunkgeneratorabstract) -> {
return chunkgeneratorabstract.b;
}), Codec.LONG.fieldOf("seed").stable().forGetter((chunkgeneratorabstract) -> {
return chunkgeneratorabstract.w;
}), GeneratorSettingBase.b.fieldOf("settings").forGetter((chunkgeneratorabstract) -> {
return chunkgeneratorabstract.h;
})).apply(instance, instance.stable(NMSChunkGenerator16_2_BACKUP::new));
});
//@done
private static final float[] i = SystemUtils.a((new float[13824]), (afloat) ->
{ // CraftBukkit - decompile error
for(int i = 0; i < 24; ++i)
{
for(int j = 0; j < 24; ++j)
{
for(int k = 0; k < 24; ++k)
{
afloat[i * 24 * 24 + j * 24 + k] = (float) b(j - 12, k - 12, i - 12);
}
}
}
});
private static final float[] j = SystemUtils.a((new float[25]), (afloat) ->
{ // CraftBukkit - decompile error
for(int i = -2; i <= 2; ++i)
{
for(int j = -2; j <= 2; ++j)
{
float f = 10.0F / MathHelper.c((float) (i * i + j * j) + 0.2F);
afloat[i + 2 + (j + 2) * 5] = f;
}
}
});
private static final IBlockData k = Blocks.AIR.getBlockData();
private final int l;
private final int m;
private final int n;
private final int o;
private final int p;
protected final SeededRandom e;
private final NoiseGeneratorOctaves q;
private final NoiseGeneratorOctaves r;
private final NoiseGeneratorOctaves s;
private final NoiseGenerator t;
private final NoiseGeneratorOctaves u;
private final NoiseGenerator3Handler v;
protected final IBlockData f;
protected final IBlockData g;
private final long w;
protected final Supplier<GeneratorSettingBase> h;
private final int x;
public NMSChunkGenerator16_2_BACKUP(WorldChunkManager worldchunkmanager, long i, Supplier<GeneratorSettingBase> supplier)
{
this(worldchunkmanager, worldchunkmanager, i, supplier);
}
private NMSChunkGenerator16_2_BACKUP(WorldChunkManager worldchunkmanager, WorldChunkManager worldchunkmanager1, long i, Supplier<GeneratorSettingBase> supplier)
{
super(worldchunkmanager, worldchunkmanager1, supplier.get().a(), i);
this.w = i;
GeneratorSettingBase generatorsettingbase = supplier.get();
this.h = supplier;
NoiseSettings noisesettings = generatorsettingbase.b();
this.x = noisesettings.a();
this.l = noisesettings.f() * 4;
this.m = noisesettings.e() * 4;
this.f = generatorsettingbase.c();
this.g = generatorsettingbase.d();
this.n = 16 / this.m;
this.o = noisesettings.a() / this.l;
this.p = 16 / this.m;
this.e = new SeededRandom(i);
this.q = new NoiseGeneratorOctaves(this.e, IntStream.rangeClosed(-15, 0));
this.r = new NoiseGeneratorOctaves(this.e, IntStream.rangeClosed(-15, 0));
this.s = new NoiseGeneratorOctaves(this.e, IntStream.rangeClosed(-7, 0));
this.t = (NoiseGenerator) (noisesettings.i() ? new NoiseGenerator3(this.e, IntStream.rangeClosed(-3, 0)) : new NoiseGeneratorOctaves(this.e, IntStream.rangeClosed(-3, 0)));
this.e.a(2620);
this.u = new NoiseGeneratorOctaves(this.e, IntStream.rangeClosed(-15, 0));
if(noisesettings.k())
{
SeededRandom seededrandom = new SeededRandom(i);
seededrandom.a(17292);
this.v = new NoiseGenerator3Handler(seededrandom);
}
else
{
this.v = null;
}
}
@Override
protected Codec<? extends ChunkGenerator> a()
{
return ChunkGeneratorAbstract.d;
}
public boolean a(long i, ResourceKey<GeneratorSettingBase> resourcekey)
{
return this.w == i && this.h.get().a(resourcekey);
}
private double a(int i, int j, int k, double d0, double d1, double d2, double d3)
{
double d4 = 0.0D;
double d5 = 0.0D;
double d6 = 0.0D;
double d7 = 1.0D;
for(int l = 0; l < 16; ++l)
{
double d8 = NoiseGeneratorOctaves.a((double) i * d0 * d7);
double d9 = NoiseGeneratorOctaves.a((double) j * d1 * d7);
double d10 = NoiseGeneratorOctaves.a((double) k * d0 * d7);
double d11 = d1 * d7;
NoiseGeneratorPerlin noisegeneratorperlin = this.q.a(l);
if(noisegeneratorperlin != null)
{
d4 += noisegeneratorperlin.a(d8, d9, d10, d11, (double) j * d11) / d7;
}
NoiseGeneratorPerlin noisegeneratorperlin1 = this.r.a(l);
if(noisegeneratorperlin1 != null)
{
d5 += noisegeneratorperlin1.a(d8, d9, d10, d11, (double) j * d11) / d7;
}
if(l < 8)
{
NoiseGeneratorPerlin noisegeneratorperlin2 = this.s.a(l);
if(noisegeneratorperlin2 != null)
{
d6 += noisegeneratorperlin2.a(NoiseGeneratorOctaves.a((double) i * d2 * d7), NoiseGeneratorOctaves.a((double) j * d3 * d7), NoiseGeneratorOctaves.a((double) k * d2 * d7), d3 * d7, (double) j * d3 * d7) / d7;
}
}
d7 /= 2.0D;
}
return MathHelper.b(d4 / 512.0D, d5 / 512.0D, (d6 / 10.0D + 1.0D) / 2.0D);
}
private double[] b(int i, int j)
{
double[] adouble = new double[this.o + 1];
this.a(adouble, i, j);
return adouble;
}
private void a(double[] adouble, int i, int j)
{
NoiseSettings noisesettings = this.h.get().b();
double d0;
double d1;
double d2;
double d3;
if(this.v != null)
{
d0 = (double) (WorldChunkManagerTheEnd.a(this.v, i, j) - 8.0F);
if(d0 > 0.0D)
{
d1 = 0.25D;
}
else
{
d1 = 1.0D;
}
}
else
{
float f = 0.0F;
float f1 = 0.0F;
float f2 = 0.0F;
int k = this.getSeaLevel();
float f3 = this.b.getBiome(i, k, j).h();
for(int l = -2; l <= 2; ++l)
{
for(int i1 = -2; i1 <= 2; ++i1)
{
BiomeBase biomebase = this.b.getBiome(i + l, k, j + i1);
float f4 = biomebase.h();
float f5 = biomebase.j();
float f6;
float f7;
if(noisesettings.l() && f4 > 0.0F)
{
f6 = 1.0F + f4 * 2.0F;
f7 = 1.0F + f5 * 4.0F;
}
else
{
f6 = f4;
f7 = f5;
}
// CraftBukkit start - fix MC-54738
if(f6 < -1.8F)
{
f6 = -1.8F;
}
// CraftBukkit end
float f8 = f4 > f3 ? 0.5F : 1.0F;
float f9 = f8 * NMSChunkGenerator16_2_BACKUP.j[l + 2 + (i1 + 2) * 5] / (f6 + 2.0F);
f += f7 * f9;
f1 += f6 * f9;
f2 += f9;
}
}
float f10 = f1 / f2;
float f11 = f / f2;
d2 = (double) (f10 * 0.5F - 0.125F);
d3 = (double) (f11 * 0.9F + 0.1F);
d0 = d2 * 0.265625D;
d1 = 96.0D / d3;
}
double d4 = 684.412D * noisesettings.b().a();
double d5 = 684.412D * noisesettings.b().b();
double d6 = d4 / noisesettings.b().c();
double d7 = d5 / noisesettings.b().d();
d2 = (double) noisesettings.c().a();
d3 = (double) noisesettings.c().b();
double d8 = (double) noisesettings.c().c();
double d9 = (double) noisesettings.d().a();
double d10 = (double) noisesettings.d().b();
double d11 = (double) noisesettings.d().c();
double d12 = noisesettings.j() ? this.c(i, j) : 0.0D;
double d13 = noisesettings.g();
double d14 = noisesettings.h();
for(int j1 = 0; j1 <= this.o; ++j1)
{
double d15 = this.a(i, j1, j, d4, d5, d6, d7);
double d16 = 1.0D - (double) j1 * 2.0D / (double) this.o + d12;
double d17 = d16 * d13 + d14;
double d18 = (d17 + d0) * d1;
if(d18 > 0.0D)
{
d15 += d18 * 4.0D;
}
else
{
d15 += d18;
}
double d19;
if(d3 > 0.0D)
{
d19 = ((double) (this.o - j1) - d8) / d3;
d15 = MathHelper.b(d2, d15, d19);
}
if(d10 > 0.0D)
{
d19 = ((double) j1 - d11) / d10;
d15 = MathHelper.b(d9, d15, d19);
}
adouble[j1] = d15;
}
}
private double c(int i, int j)
{
double d0 = this.u.a((double) (i * 200), 10.0D, (double) (j * 200), 1.0D, 0.0D, true);
double d1;
if(d0 < 0.0D)
{
d1 = -d0 * 0.3D;
}
else
{
d1 = d0;
}
double d2 = d1 * 24.575625D - 2.0D;
return d2 < 0.0D ? d2 * 0.009486607142857142D : Math.min(d2, 1.0D) * 0.006640625D;
}
@Override
public int getBaseHeight(int i, int j, HeightMap.Type heightmap_type)
{
return this.a(i, j, (IBlockData[]) null, heightmap_type.e());
}
@Override
public IBlockAccess a(int i, int j)
{
IBlockData[] aiblockdata = new IBlockData[this.o * this.l];
this.a(i, j, aiblockdata, (Predicate<IBlockData>) null);
return new BlockColumn(aiblockdata);
}
private int a(int i, int j, @Nullable IBlockData[] aiblockdata, @Nullable Predicate<IBlockData> predicate)
{
int k = Math.floorDiv(i, this.m);
int l = Math.floorDiv(j, this.m);
int i1 = Math.floorMod(i, this.m);
int j1 = Math.floorMod(j, this.m);
double d0 = (double) i1 / (double) this.m;
double d1 = (double) j1 / (double) this.m;
double[][] adouble = new double[][] {this.b(k, l), this.b(k, l + 1), this.b(k + 1, l), this.b(k + 1, l + 1)};
for(int k1 = this.o - 1; k1 >= 0; --k1)
{
double d2 = adouble[0][k1];
double d3 = adouble[1][k1];
double d4 = adouble[2][k1];
double d5 = adouble[3][k1];
double d6 = adouble[0][k1 + 1];
double d7 = adouble[1][k1 + 1];
double d8 = adouble[2][k1 + 1];
double d9 = adouble[3][k1 + 1];
for(int l1 = this.l - 1; l1 >= 0; --l1)
{
double d10 = (double) l1 / (double) this.l;
double d11 = MathHelper.a(d10, d0, d1, d2, d6, d4, d8, d3, d7, d5, d9);
int i2 = k1 * this.l + l1;
IBlockData iblockdata = this.a(d11, i2);
if(aiblockdata != null)
{
aiblockdata[i2] = iblockdata;
}
if(predicate != null && predicate.test(iblockdata))
{
return i2 + 1;
}
}
}
return 0;
}
protected IBlockData a(double d0, int i)
{
IBlockData iblockdata;
if(d0 > 0.0D)
{
iblockdata = this.f;
}
else if(i < this.getSeaLevel())
{
iblockdata = this.g;
}
else
{
iblockdata = NMSChunkGenerator16_2_BACKUP.k;
}
return iblockdata;
}
@Override
public void buildBase(RegionLimitedWorldAccess regionlimitedworldaccess, IChunkAccess ichunkaccess)
{
ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos();
int i = chunkcoordintpair.x;
int j = chunkcoordintpair.z;
SeededRandom seededrandom = new SeededRandom();
seededrandom.a(i, j);
ChunkCoordIntPair chunkcoordintpair1 = ichunkaccess.getPos();
int k = chunkcoordintpair1.d();
int l = chunkcoordintpair1.e();
// double d0 = 0.0625D;
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
for(int i1 = 0; i1 < 16; ++i1)
{
for(int j1 = 0; j1 < 16; ++j1)
{
int k1 = k + i1;
int l1 = l + j1;
int i2 = ichunkaccess.getHighestBlock(HeightMap.Type.WORLD_SURFACE_WG, i1, j1) + 1;
double d1 = this.t.a((double) k1 * 0.0625D, (double) l1 * 0.0625D, 0.0625D, (double) i1 * 0.0625D) * 15.0D;
regionlimitedworldaccess.getBiome(blockposition_mutableblockposition.d(k + i1, i2, l + j1)).a(seededrandom, ichunkaccess, k1, l1, i2, d1, this.f, this.g, this.getSeaLevel(), regionlimitedworldaccess.getSeed());
}
}
this.a(ichunkaccess, seededrandom);
}
private void a(IChunkAccess ichunkaccess, Random random)
{
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
int i = ichunkaccess.getPos().d();
int j = ichunkaccess.getPos().e();
GeneratorSettingBase generatorsettingbase = this.h.get();
int k = generatorsettingbase.f();
int l = this.x - 1 - generatorsettingbase.e();
boolean flag1 = l + 4 >= 0 && l < this.x;
boolean flag2 = k + 4 >= 0 && k < this.x;
if(flag1 || flag2)
{
Iterator<BlockPosition> iterator = BlockPosition.b(i, 0, j, i + 15, 0, j + 15).iterator();
while(iterator.hasNext())
{
BlockPosition blockposition = iterator.next();
int i1;
if(flag1)
{
for(i1 = 0; i1 < 5; ++i1)
{
if(i1 <= random.nextInt(5))
{
ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), l - i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false);
}
}
}
if(flag2)
{
for(i1 = 4; i1 >= 0; --i1)
{
if(i1 <= random.nextInt(5))
{
ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), k + i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false);
}
}
}
}
}
}
@Override
public void buildNoise(GeneratorAccess generatoraccess, StructureManager structuremanager, IChunkAccess ichunkaccess)
{
ObjectList<StructurePiece> objectlist = new ObjectArrayList<StructurePiece>(10);
ObjectList<WorldGenFeatureDefinedStructureJigsawJunction> objectlist1 = new ObjectArrayList<WorldGenFeatureDefinedStructureJigsawJunction>(32);
ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos();
int i = chunkcoordintpair.x;
int j = chunkcoordintpair.z;
int k = i << 4;
int l = j << 4;
Iterator<?> iterator = StructureGenerator.t.iterator();
while(iterator.hasNext())
{
StructureGenerator<?> structuregenerator = (StructureGenerator<?>) iterator.next();
structuremanager.a(SectionPosition.a(chunkcoordintpair, 0), structuregenerator).forEach((structurestart) ->
{
Iterator<?> iterator1 = structurestart.d().iterator();
while(iterator1.hasNext())
{
StructurePiece structurepiece = (StructurePiece) iterator1.next();
if(structurepiece.a(chunkcoordintpair, 12))
{
if(structurepiece instanceof WorldGenFeaturePillagerOutpostPoolPiece)
{
WorldGenFeaturePillagerOutpostPoolPiece worldgenfeaturepillageroutpostpoolpiece = (WorldGenFeaturePillagerOutpostPoolPiece) structurepiece;
WorldGenFeatureDefinedStructurePoolTemplate.Matching worldgenfeaturedefinedstructurepooltemplate_matching = worldgenfeaturepillageroutpostpoolpiece.b().e();
if(worldgenfeaturedefinedstructurepooltemplate_matching == WorldGenFeatureDefinedStructurePoolTemplate.Matching.RIGID)
{
objectlist.add(worldgenfeaturepillageroutpostpoolpiece);
}
Iterator<?> iterator2 = worldgenfeaturepillageroutpostpoolpiece.e().iterator();
while(iterator2.hasNext())
{
WorldGenFeatureDefinedStructureJigsawJunction worldgenfeaturedefinedstructurejigsawjunction = (WorldGenFeatureDefinedStructureJigsawJunction) iterator2.next();
int i1 = worldgenfeaturedefinedstructurejigsawjunction.a();
int j1 = worldgenfeaturedefinedstructurejigsawjunction.c();
if(i1 > k - 12 && j1 > l - 12 && i1 < k + 15 + 12 && j1 < l + 15 + 12)
{
objectlist1.add(worldgenfeaturedefinedstructurejigsawjunction);
}
}
}
else
{
objectlist.add(structurepiece);
}
}
}
});
}
double[][][] adouble = new double[2][this.p + 1][this.o + 1];
for(int i1 = 0; i1 < this.p + 1; ++i1)
{
adouble[0][i1] = new double[this.o + 1];
this.a(adouble[0][i1], i * this.n, j * this.p + i1);
adouble[1][i1] = new double[this.o + 1];
}
ProtoChunk protochunk = (ProtoChunk) ichunkaccess;
HeightMap heightmap = protochunk.a(HeightMap.Type.OCEAN_FLOOR_WG);
HeightMap heightmap1 = protochunk.a(HeightMap.Type.WORLD_SURFACE_WG);
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
ObjectListIterator<StructurePiece> objectlistiterator = objectlist.iterator();
ObjectListIterator<WorldGenFeatureDefinedStructureJigsawJunction> objectlistiterator1 = objectlist1.iterator();
for(int j1 = 0; j1 < this.n; ++j1)
{
int k1;
for(k1 = 0; k1 < this.p + 1; ++k1)
{
this.a(adouble[1][k1], i * this.n + j1 + 1, j * this.p + k1);
}
for(k1 = 0; k1 < this.p; ++k1)
{
ChunkSection chunksection = protochunk.a(15);
chunksection.a();
for(int l1 = this.o - 1; l1 >= 0; --l1)
{
double d0 = adouble[0][k1][l1];
double d1 = adouble[0][k1 + 1][l1];
double d2 = adouble[1][k1][l1];
double d3 = adouble[1][k1 + 1][l1];
double d4 = adouble[0][k1][l1 + 1];
double d5 = adouble[0][k1 + 1][l1 + 1];
double d6 = adouble[1][k1][l1 + 1];
double d7 = adouble[1][k1 + 1][l1 + 1];
for(int i2 = this.l - 1; i2 >= 0; --i2)
{
int j2 = l1 * this.l + i2;
int k2 = j2 & 15;
int l2 = j2 >> 4;
if(chunksection.getYPosition() >> 4 != l2)
{
chunksection.b();
chunksection = protochunk.a(l2);
chunksection.a();
}
double d8 = (double) i2 / (double) this.l;
double d9 = MathHelper.d(d8, d0, d4);
double d10 = MathHelper.d(d8, d2, d6);
double d11 = MathHelper.d(d8, d1, d5);
double d12 = MathHelper.d(d8, d3, d7);
for(int i3 = 0; i3 < this.m; ++i3)
{
int j3 = k + j1 * this.m + i3;
int k3 = j3 & 15;
double d13 = (double) i3 / (double) this.m;
double d14 = MathHelper.d(d13, d9, d10);
double d15 = MathHelper.d(d13, d11, d12);
for(int l3 = 0; l3 < this.m; ++l3)
{
int i4 = l + k1 * this.m + l3;
int j4 = i4 & 15;
double d16 = (double) l3 / (double) this.m;
double d17 = MathHelper.d(d16, d14, d15);
double d18 = MathHelper.a(d17 / 200.0D, -1.0D, 1.0D);
int k4;
int l4;
int i5;
for(d18 = d18 / 2.0D - d18 * d18 * d18 / 24.0D; objectlistiterator.hasNext(); d18 += a(k4, l4, i5) * 0.8D)
{
StructurePiece structurepiece = objectlistiterator.next();
StructureBoundingBox structureboundingbox = structurepiece.g();
k4 = Math.max(0, Math.max(structureboundingbox.a - j3, j3 - structureboundingbox.d));
l4 = j2 - (structureboundingbox.b + (structurepiece instanceof WorldGenFeaturePillagerOutpostPoolPiece ? ((WorldGenFeaturePillagerOutpostPoolPiece) structurepiece).d() : 0));
i5 = Math.max(0, Math.max(structureboundingbox.c - i4, i4 - structureboundingbox.f));
}
objectlistiterator.back(objectlist.size());
while(objectlistiterator1.hasNext())
{
WorldGenFeatureDefinedStructureJigsawJunction worldgenfeaturedefinedstructurejigsawjunction = objectlistiterator1.next();
int j5 = j3 - worldgenfeaturedefinedstructurejigsawjunction.a();
k4 = j2 - worldgenfeaturedefinedstructurejigsawjunction.b();
l4 = i4 - worldgenfeaturedefinedstructurejigsawjunction.c();
d18 += a(j5, k4, l4) * 0.4D;
}
objectlistiterator1.back(objectlist1.size());
IBlockData iblockdata = this.a(d18, j2);
if(iblockdata != NMSChunkGenerator16_2_BACKUP.k)
{
if(iblockdata.f() != 0)
{
blockposition_mutableblockposition.d(j3, j2, i4);
protochunk.k(blockposition_mutableblockposition);
}
chunksection.setType(k3, k2, j4, iblockdata, false);
heightmap.a(k3, j2, j4, iblockdata);
heightmap1.a(k3, j2, j4, iblockdata);
}
}
}
}
}
chunksection.b();
}
double[][] adouble1 = adouble[0];
adouble[0] = adouble[1];
adouble[1] = adouble1;
}
}
private static double a(int i, int j, int k)
{
int l = i + 12;
int i1 = j + 12;
int j1 = k + 12;
return l >= 0 && l < 24 ? (i1 >= 0 && i1 < 24 ? (j1 >= 0 && j1 < 24 ? (double) NMSChunkGenerator16_2_BACKUP.i[j1 * 24 * 24 + l * 24 + i1] : 0.0D) : 0.0D) : 0.0D;
}
private static double b(int i, int j, int k)
{
double d0 = (double) (i * i + k * k);
double d1 = (double) j + 0.5D;
double d2 = d1 * d1;
double d3 = Math.pow(2.718281828459045D, -(d2 / 16.0D + d0 / 16.0D));
double d4 = -d1 * MathHelper.i(d2 / 2.0D + d0 / 2.0D) / 2.0D;
return d4 * d3;
}
@Override
public int getGenerationDepth()
{
return this.x;
}
@Override
public int getSeaLevel()
{
return this.h.get().g();
}
@Override
public List<BiomeSettingsMobs.c> getMobsFor(BiomeBase biomebase, StructureManager structuremanager, EnumCreatureType enumcreaturetype, BlockPosition blockposition)
{
if(structuremanager.a(blockposition, true, StructureGenerator.SWAMP_HUT).e())
{
if(enumcreaturetype == EnumCreatureType.MONSTER)
{
return StructureGenerator.SWAMP_HUT.c();
}
if(enumcreaturetype == EnumCreatureType.CREATURE)
{
return StructureGenerator.SWAMP_HUT.j();
}
}
if(enumcreaturetype == EnumCreatureType.MONSTER)
{
if(structuremanager.a(blockposition, false, StructureGenerator.PILLAGER_OUTPOST).e())
{
return StructureGenerator.PILLAGER_OUTPOST.c();
}
if(structuremanager.a(blockposition, false, StructureGenerator.MONUMENT).e())
{
return StructureGenerator.MONUMENT.c();
}
if(structuremanager.a(blockposition, true, StructureGenerator.FORTRESS).e())
{
return StructureGenerator.FORTRESS.c();
}
}
return super.getMobsFor(biomebase, structuremanager, enumcreaturetype, blockposition);
}
@Override
public void addMobs(RegionLimitedWorldAccess regionlimitedworldaccess)
{
int i = regionlimitedworldaccess.a();
int j = regionlimitedworldaccess.b();
BiomeBase biomebase = regionlimitedworldaccess.getBiome((new ChunkCoordIntPair(i, j)).l());
SeededRandom seededrandom = new SeededRandom();
seededrandom.a(regionlimitedworldaccess.getSeed(), i << 4, j << 4);
SpawnerCreature.a(regionlimitedworldaccess, biomebase, i, j, seededrandom);
}
}

View File

@@ -0,0 +1,661 @@
package com.volmit.iris.generator.legacy.nms.v16_2;
import com.mojang.serialization.Codec;
import com.volmit.iris.generator.legacy.provisions.ProvisionBukkit;
import com.volmit.iris.generator.legacy.scaffold.GeneratedChunk;
import com.volmit.iris.scaffold.engine.IrisAccess;
import com.volmit.iris.util.O;
import com.volmit.iris.util.V;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectList;
import net.minecraft.server.v1_16_R2.*;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_16_R2.block.CraftBlock;
import org.bukkit.craftbukkit.v1_16_R2.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_16_R2.util.CraftMagicNumbers;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import org.bukkit.material.MaterialData;
import java.util.*;
import java.util.function.Supplier;
@SuppressWarnings("deprecation")
public class NMSChunkGenerator16_2_PAPER extends ChunkGenerator
{
private static final IBlockData k = Blocks.AIR.getBlockData();
private final IrisAccess provisioned;
private final int maxHeight;
private final int xzSize;
protected final IBlockData f;
protected final IBlockData g;
private final long w;
protected final Supplier<GeneratorSettingBase> h;
private final O<WorldServer> ws;
private BlockColumn BC;
public NMSChunkGenerator16_2_PAPER(IrisAccess p, O<WorldServer> ws, WorldChunkManager worldchunkmanager, long i, Supplier<GeneratorSettingBase> supplier)
{
this(p, ws, worldchunkmanager, worldchunkmanager, i, supplier);
}
private NMSChunkGenerator16_2_PAPER(IrisAccess p, O<WorldServer> ws, WorldChunkManager worldchunkmanager, WorldChunkManager worldchunkmanager1, long i, Supplier<GeneratorSettingBase> supplier)
{
super(worldchunkmanager, worldchunkmanager1, supplier.get().a(), i);
this.provisioned = p;
this.ws = ws;
this.w = i;
GeneratorSettingBase generatorsettingbase = supplier.get();
this.h = supplier;
NoiseSettings noisesettings = generatorsettingbase.b();
this.maxHeight = noisesettings.f() * 4;
this.f = generatorsettingbase.c();
this.g = generatorsettingbase.d();
this.xzSize = noisesettings.a() / this.maxHeight;
BC = new BlockColumn(new IBlockData[this.xzSize * this.maxHeight]);
}
public int getSpawnHeight()
{
return getSeaLevel() + 8;
}
public WorldChunkManager getWorldChunkManager()
{
return this.c;
}
public int getGenerationDepth()
{
return 256;
}
public void doCarving(long i, BiomeManager biomemanager, IChunkAccess ichunkaccess, WorldGenStage.Features worldgenstage_features)
{
if(provisioned.getCompound().getRootDimension().isVanillaCaves())
{
super.doCarving(i, biomemanager, ichunkaccess, worldgenstage_features);
}
}
@Override
protected Codec<? extends ChunkGenerator> a()
{
return ChunkGeneratorAbstract.d;
}
public boolean a(long i, ResourceKey<GeneratorSettingBase> resourcekey)
{
return this.w == i && this.h.get().a(resourcekey);
}
@Override
public int getBaseHeight(int i, int j, HeightMap.Type heightmap_type)
{
return 63;
}
@Override
public IBlockAccess a(int x, int z)
{
return BC;
}
protected IBlockData a(double d0, int i)
{
IBlockData iblockdata;
if(d0 > 0.0D)
{
iblockdata = this.f;
}
else if(i < this.getSeaLevel())
{
iblockdata = this.g;
}
else
{
iblockdata = NMSChunkGenerator16_2_PAPER.k;
}
return iblockdata;
}
@Override
public void buildBase(RegionLimitedWorldAccess regionlimitedworldaccess, IChunkAccess ichunkaccess)
{
}
@Override
public void buildNoise(GeneratorAccess generatoraccess, StructureManager structuremanager, IChunkAccess ichunkaccess)
{
ObjectList<StructurePiece> objectlist = new ObjectArrayList<StructurePiece>(10);
ObjectList<WorldGenFeatureDefinedStructureJigsawJunction> objectlist1 = new ObjectArrayList<WorldGenFeatureDefinedStructureJigsawJunction>(32);
ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos();
int i = chunkcoordintpair.x;
int j = chunkcoordintpair.z;
if(provisioned.getCompound().getRootDimension().isVanillaStructures())
{
int k = i << 4;
int l = j << 4;
Iterator<?> iterator = StructureGenerator.t.iterator();
while(iterator.hasNext())
{
StructureGenerator<?> structuregenerator = (StructureGenerator<?>) iterator.next();
structuremanager.a(SectionPosition.a(chunkcoordintpair, 0), structuregenerator).forEach((structurestart) ->
{
Iterator<?> iterator1 = structurestart.d().iterator();
while(iterator1.hasNext())
{
StructurePiece structurepiece = (StructurePiece) iterator1.next();
if(structurepiece.a(chunkcoordintpair, 12))
{
if(structurepiece instanceof WorldGenFeaturePillagerOutpostPoolPiece)
{
WorldGenFeaturePillagerOutpostPoolPiece worldgenfeaturepillageroutpostpoolpiece = (WorldGenFeaturePillagerOutpostPoolPiece) structurepiece;
WorldGenFeatureDefinedStructurePoolTemplate.Matching worldgenfeaturedefinedstructurepooltemplate_matching = worldgenfeaturepillageroutpostpoolpiece.b().e();
if(worldgenfeaturedefinedstructurepooltemplate_matching == WorldGenFeatureDefinedStructurePoolTemplate.Matching.RIGID)
{
objectlist.add(worldgenfeaturepillageroutpostpoolpiece);
}
Iterator<?> iterator2 = worldgenfeaturepillageroutpostpoolpiece.e().iterator();
while(iterator2.hasNext())
{
WorldGenFeatureDefinedStructureJigsawJunction worldgenfeaturedefinedstructurejigsawjunction = (WorldGenFeatureDefinedStructureJigsawJunction) iterator2.next();
int i1 = worldgenfeaturedefinedstructurejigsawjunction.a();
int j1 = worldgenfeaturedefinedstructurejigsawjunction.c();
if(i1 > k - 12 && j1 > l - 12 && i1 < k + 15 + 12 && j1 < l + 15 + 12)
{
objectlist1.add(worldgenfeaturedefinedstructurejigsawjunction);
}
}
}
else
{
objectlist.add(structurepiece);
}
}
}
});
}
}
ProtoChunk protochunk = (ProtoChunk) ichunkaccess;
HeightMap heightmap = protochunk.a(HeightMap.Type.OCEAN_FLOOR_WG);
HeightMap heightmap1 = protochunk.a(HeightMap.Type.WORLD_SURFACE_WG);
GeneratedChunk gc = ((ProvisionBukkit) provisioned).generateNMSChunkData(ws.get().getWorld(), new Random(i + j), i, j, new ChunkData()
{
public int getMaxHeight()
{
return 256;
}
public void setBlock(int x, int y, int z, Material material)
{
this.setBlock(x, y, z, material.createBlockData());
}
public void setBlock(int x, int y, int z, MaterialData material)
{
this.setBlock(x, y, z, CraftMagicNumbers.getBlock((MaterialData) material));
}
public void setBlock(int x, int y, int z, BlockData blockData)
{
this.setBlock(x, y, z, ((CraftBlockData) blockData).getState());
}
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, Material material)
{
this.setRegion(xMin, yMin, zMin, xMax, yMax, zMax, material.createBlockData());
}
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, MaterialData material)
{
this.setRegion(xMin, yMin, zMin, xMax, yMax, zMax, CraftMagicNumbers.getBlock((MaterialData) material));
}
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, BlockData blockData)
{
this.setRegion(xMin, yMin, zMin, xMax, yMax, zMax, ((CraftBlockData) blockData).getState());
}
public Material getType(int x, int y, int z)
{
return CraftMagicNumbers.getMaterial((Block) this.getTypeId(x, y, z).getBlock());
}
public MaterialData getTypeAndData(int x, int y, int z)
{
return CraftMagicNumbers.getMaterial((IBlockData) this.getTypeId(x, y, z));
}
public BlockData getBlockData(int x, int y, int z)
{
return CraftBlockData.fromData((IBlockData) this.getTypeId(x, y, z));
}
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, IBlockData type)
{
if(xMin > 15 || yMin >= getMaxHeight() || zMin > 15)
{
return;
}
if(xMin < 0)
{
xMin = 0;
}
if(yMin < 0)
{
yMin = 0;
}
if(zMin < 0)
{
zMin = 0;
}
if(xMax > 16)
{
xMax = 16;
}
if(yMax > getMaxHeight())
{
yMax = getMaxHeight();
}
if(zMax > 16)
{
zMax = 16;
}
if(xMin >= xMax || yMin >= yMax || zMin >= zMax)
{
return;
}
int y = yMin;
while(y < yMax)
{
int x = xMin;
while(x < xMax)
{
int z = zMin;
while(z < zMax)
{
protochunk.setType(new BlockPosition(x, y, z), type, false);
++z;
}
++x;
}
++y;
}
}
public IBlockData getTypeId(int x, int y, int z)
{
if(x != (x & 15) || y < 0 || y >= getMaxHeight() || z != (z & 15))
{
return Blocks.AIR.getBlockData();
}
return protochunk.getType(new BlockPosition(x, y, z));
}
public byte getData(int x, int y, int z)
{
return CraftMagicNumbers.toLegacyData((IBlockData) this.getTypeId(x, y, z));
}
private void setBlock(int x, int y, int z, IBlockData type)
{
if(x != (x & 15) || y < 0 || y >= getMaxHeight() || z != (z & 15))
{
return;
}
protochunk.setType(new BlockPosition(x, y, z), type, false);
if(type.getBlock().isTileEntity())
{
// if (this.tiles == null) {
// this.tiles = new HashSet<BlockPosition>();
// }
// this.tiles.add(new BlockPosition(x, y, z));
}
}
}, new BiomeGrid()
{
@Override
public void setBiome(int x, int y, int z, Biome bio)
{
protochunk.getBiomeIndex().setBiome(x, y, z, CraftBlock.biomeToBiomeBase(ws.get().r().b(IRegistry.ay), bio));
}
@Override
public void setBiome(int x, int z, Biome bio)
{
protochunk.getBiomeIndex().setBiome(x, 0, z, CraftBlock.biomeToBiomeBase(ws.get().r().b(IRegistry.ay), bio));
}
@Override
public Biome getBiome(int x, int y, int z)
{
return CraftBlock.biomeBaseToBiome(ws.get().r().b(IRegistry.ay), protochunk.getBiomeIndex().getBiome(x, y, z));
}
@Override
public Biome getBiome(int x, int z)
{
return CraftBlock.biomeBaseToBiome(ws.get().r().b(IRegistry.ay), protochunk.getBiomeIndex().getBiome(x, 0, z));
}
});
for(int xx = 0; xx < 16; xx++)
{
for(int zz = 0; zz < 16; zz++)
{
try
{
int y = gc.getHeight().getHeight(xx, zz);
if(y < getSeaLevel())
{
heightmap.a(xx, y, zz, Blocks.STONE.getBlockData());
}
heightmap1.a(xx, Math.max(y, getSeaLevel()), zz, Blocks.STONE.getBlockData());
}
catch(Throwable e)
{
}
}
}
}
public void addDecorations(RegionLimitedWorldAccess regionlimitedworldaccess, StructureManager structuremanager)
{
if(provisioned.getCompound().getRootDimension().isVanillaStructures())
{
int i = regionlimitedworldaccess.a();
int j = regionlimitedworldaccess.b();
int k = i * 16;
int l = j * 16;
BlockPosition blockposition = new BlockPosition(k, 0, l);
BiomeBase biomebase = this.b.getBiome((i << 2) + 2, 2, (j << 2) + 2);
SeededRandom seededrandom = new SeededRandom();
long i1 = seededrandom.a(regionlimitedworldaccess.getSeed(), k, l);
try
{
a(biomebase, structuremanager, this, regionlimitedworldaccess, i1, seededrandom, blockposition);
}
catch(Exception exception)
{
}
}
}
public void a(BiomeBase bbase, StructureManager var0, ChunkGenerator var1, RegionLimitedWorldAccess var2, long var3, SeededRandom var5, BlockPosition var6)
{
if(!provisioned.getCompound().getRootDimension().isVanillaStructures())
{
return;
}
int stages = WorldGenStage.Decoration.values().length;
for(int stage = 0; stage < stages; ++stage)
{
WorldGenStage.Decoration st = WorldGenStage.Decoration.values()[stage];
if(st.equals(WorldGenStage.Decoration.LAKES))
{
continue;
}
if(st.equals(WorldGenStage.Decoration.LOCAL_MODIFICATIONS))
{
continue;
}
if(st.equals(WorldGenStage.Decoration.RAW_GENERATION))
{
continue;
}
if(st.equals(WorldGenStage.Decoration.TOP_LAYER_MODIFICATION))
{
continue;
}
if(st.equals(WorldGenStage.Decoration.UNDERGROUND_DECORATION))
{
continue;
}
if(st.equals(WorldGenStage.Decoration.UNDERGROUND_ORES))
{
continue;
}
if(st.equals(WorldGenStage.Decoration.VEGETAL_DECORATION))
{
continue;
}
StructureGenerator<?> var13;
int var10 = 0;
if(var0.a())
{
@SuppressWarnings("unchecked")
List<StructureGenerator<?>> structureGenerators = ((Map<Integer, List<StructureGenerator<?>>>) new V(bbase).get("g")).getOrDefault(stage, Collections.emptyList());
Iterator<StructureGenerator<?>> iterator = structureGenerators.iterator();
while(iterator.hasNext())
{
var13 = (StructureGenerator<?>) iterator.next();
if(var13.equals(StructureGenerator.VILLAGE))
{
continue;
}
if(var13.equals(StructureGenerator.JUNGLE_PYRAMID))
{
continue;
}
if(var13.equals(StructureGenerator.IGLOO))
{
continue;
}
if(var13.equals(StructureGenerator.MINESHAFT))
{
continue;
}
if(var13.equals(StructureGenerator.NETHER_FOSSIL))
{
continue;
}
if(var13.equals(StructureGenerator.SHIPWRECK))
{
continue;
}
if(var13.equals(StructureGenerator.SHIPWRECK))
{
continue;
}
if(var13.equals(StructureGenerator.MONUMENT))
{
continue;
}
if(var13.equals(StructureGenerator.OCEAN_RUIN))
{
continue;
}
if(var13.equals(StructureGenerator.BASTION_REMNANT))
{
continue;
}
var5.b(var3, var10, stage);
int var14 = var6.getX() >> 4;
int var15 = var6.getZ() >> 4;
int var16 = var14 << 4;
int var17 = var15 << 4;
try
{
var0.a(SectionPosition.a((BlockPosition) var6), var13).forEach(var8 -> var8.a((GeneratorAccessSeed) var2, var0, var1, (Random) var5, new StructureBoundingBox(var16, var17, var16 + 15, var17 + 15), new ChunkCoordIntPair(var14, var15)));
}
catch(Exception var18)
{
}
++var10;
}
}
}
}
@Override
public int getSeaLevel()
{
return provisioned.getCompound().getRootDimension().getFluidHeight();
}
@Override
public List<BiomeSettingsMobs.c> getMobsFor(BiomeBase biomebase, StructureManager structuremanager, EnumCreatureType enumcreaturetype, BlockPosition blockposition)
{
if(structuremanager.a(blockposition, true, StructureGenerator.SWAMP_HUT).e())
{
if(enumcreaturetype == EnumCreatureType.MONSTER)
{
return StructureGenerator.SWAMP_HUT.c();
}
if(enumcreaturetype == EnumCreatureType.CREATURE)
{
return StructureGenerator.SWAMP_HUT.j();
}
}
if(enumcreaturetype == EnumCreatureType.MONSTER)
{
if(structuremanager.a(blockposition, false, StructureGenerator.PILLAGER_OUTPOST).e())
{
return StructureGenerator.PILLAGER_OUTPOST.c();
}
if(structuremanager.a(blockposition, false, StructureGenerator.MONUMENT).e())
{
return StructureGenerator.MONUMENT.c();
}
if(structuremanager.a(blockposition, true, StructureGenerator.FORTRESS).e())
{
return StructureGenerator.FORTRESS.c();
}
}
return super.getMobsFor(biomebase, structuremanager, enumcreaturetype, blockposition);
}
@Override
public void addMobs(RegionLimitedWorldAccess regionlimitedworldaccess)
{
int i = regionlimitedworldaccess.a();
int j = regionlimitedworldaccess.b();
BiomeBase biomebase = regionlimitedworldaccess.getBiome((new ChunkCoordIntPair(i, j)).l());
SeededRandom seededrandom = new SeededRandom();
seededrandom.a(regionlimitedworldaccess.getSeed(), i << 4, j << 4);
SpawnerCreature.a(regionlimitedworldaccess, biomebase, i, j, seededrandom);
}
public void createStructures(IRegistryCustom iregistrycustom, StructureManager structuremanager, IChunkAccess ichunkaccess, DefinedStructureManager definedstructuremanager, long i)
{
ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos();
BiomeBase biomebase = this.b.getBiome((chunkcoordintpair.x << 2) + 2, 0, (chunkcoordintpair.z << 2) + 2);
this.a(StructureFeatures.k, iregistrycustom, structuremanager, ichunkaccess, definedstructuremanager, i, chunkcoordintpair, biomebase);
for(Supplier<StructureFeature<?, ?>> supplier : biomebase.e().a())
{
StructureFeature<?, ?> structurefeature = (StructureFeature<?, ?>) supplier.get();
if(StructureFeature.c == StructureGenerator.STRONGHOLD)
{
StructureFeature<?, ?> structureFeature = structurefeature;
synchronized(structureFeature)
{
this.a(structurefeature, iregistrycustom, structuremanager, ichunkaccess, definedstructuremanager, i, chunkcoordintpair, biomebase);
continue;
}
}
this.a(structurefeature, iregistrycustom, structuremanager, ichunkaccess, definedstructuremanager, i, chunkcoordintpair, biomebase);
}
}
private void a(StructureFeature<?, ?> structurefeature, IRegistryCustom iregistrycustom, StructureManager structuremanager, IChunkAccess ichunkaccess, DefinedStructureManager definedstructuremanager, long i, ChunkCoordIntPair chunkcoordintpair, BiomeBase biomebase)
{
StructureStart<?> structurestart = structuremanager.a(SectionPosition.a((ChunkCoordIntPair) ichunkaccess.getPos(), (int) 0), structurefeature.d, (IStructureAccess) ichunkaccess);
int j = structurestart != null ? structurestart.j() : 0;
StructureSettingsFeature structuresettingsfeature = getSettings().a(structurefeature.d);
if(structuresettingsfeature != null)
{
StructureStart<?> structurestart1 = structurefeature.a(iregistrycustom, this, this.b, definedstructuremanager, i, chunkcoordintpair, biomebase, j, structuresettingsfeature);
structuremanager.a(SectionPosition.a((ChunkCoordIntPair) ichunkaccess.getPos(), (int) 0), structurefeature.d, structurestart1, (IStructureAccess) ichunkaccess);
}
}
public void storeStructures(GeneratorAccessSeed generatoraccessseed, StructureManager structuremanager, IChunkAccess ichunkaccess)
{
int i = ichunkaccess.getPos().x;
int j = ichunkaccess.getPos().z;
int k = i << 4;
int l = j << 4;
SectionPosition sectionposition = SectionPosition.a((ChunkCoordIntPair) ichunkaccess.getPos(), (int) 0);
int i1 = i - 8;
while(i1 <= i + 8)
{
int j1 = j - 8;
while(j1 <= j + 8)
{
long k1 = ChunkCoordIntPair.pair((int) i1, (int) j1);
for(StructureStart<?> structurestart : generatoraccessseed.getChunkAt(i1, j1).h().values())
{
try
{
if(structurestart == StructureStart.a || !structurestart.c().a(k, l, k + 15, l + 15))
continue;
structuremanager.a(sectionposition, structurestart.l(), k1, (IStructureAccess) ichunkaccess);
PacketDebug.a((GeneratorAccessSeed) generatoraccessseed, (StructureStart<?>) structurestart);
}
catch(Exception exception)
{
CrashReport crashreport = CrashReport.a((Throwable) exception, (String) "Generating structure reference");
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Structure");
crashreportsystemdetails.a("Name", () -> structurestart.l().i());
crashreportsystemdetails.a("Class", () -> structurestart.l().getClass().getCanonicalName());
throw new ReportedException(crashreport);
}
}
++j1;
}
++i1;
}
}
}

View File

@@ -0,0 +1,264 @@
package com.volmit.iris.generator.legacy.nms.v16_2;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.Lifecycle;
import com.volmit.iris.generator.legacy.nms.INMSCreator;
import com.volmit.iris.scaffold.IrisWorlds;
import com.volmit.iris.scaffold.engine.IrisAccess;
import com.volmit.iris.util.O;
import com.volmit.iris.util.V;
import net.minecraft.server.v1_16_R2.*;
import net.minecraft.server.v1_16_R2.IRegistryCustom.Dimension;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.WorldCreator;
import org.bukkit.craftbukkit.v1_16_R2.CraftServer;
import org.bukkit.event.Event;
import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.event.world.WorldLoadEvent;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
class NMSCreator16_2 implements INMSCreator
{
@SuppressWarnings({"unchecked", "rawtypes", "resource"})
public World createWorld(WorldCreator creator, boolean loadSpawn)
{
if(!creator.environment().equals(Environment.NORMAL))
{
return creator.createWorld();
}
IrisAccess pro = (IrisAccess) creator.generator();
CraftServer server = ((CraftServer) Bukkit.getServer());
Map<String, World> worlds = new V(server).get("worlds");
DedicatedServer console = new V(server).get("console");
Preconditions.checkState(!console.worldServer.isEmpty(), (Object) "Cannot create additional worlds on STARTUP");
Validate.notNull((Object) creator, "Creator may not be null");
final String name = creator.name();
org.bukkit.generator.ChunkGenerator generator = creator.generator();
final File folder = new File(server.getWorldContainer(), name);
final World world = server.getWorld(name);
if(world != null)
{
return world;
}
if(folder.exists() && !folder.isDirectory())
{
throw new IllegalArgumentException("File exists with the name '" + name + "' and isn't a folder");
}
if(generator == null)
{
generator = server.getGenerator(name);
}
ResourceKey<WorldDimension> actualDimension = null;
switch(creator.environment())
{
case NORMAL:
{
actualDimension = (ResourceKey<WorldDimension>) WorldDimension.OVERWORLD;
break;
}
case NETHER:
{
actualDimension = (ResourceKey<WorldDimension>) WorldDimension.THE_NETHER;
break;
}
case THE_END:
{
actualDimension = (ResourceKey<WorldDimension>) WorldDimension.THE_END;
break;
}
default:
{
throw new IllegalArgumentException("Illegal dimension");
}
}
Convertable.ConversionSession worldSession;
try
{
worldSession = Convertable.a(server.getWorldContainer().toPath()).c(name, (ResourceKey) actualDimension);
}
catch(IOException ex)
{
throw new RuntimeException(ex);
}
MinecraftServer.convertWorld(worldSession);
final boolean hardcore = creator.hardcore();
final RegistryReadOps<NBTBase> registryreadops = (RegistryReadOps<NBTBase>) RegistryReadOps.a((DynamicOps) DynamicOpsNBT.a, console.dataPackResources.h(), getConsoleDimension(console));
WorldDataServer worlddata = (WorldDataServer) worldSession.a((DynamicOps) registryreadops, console.datapackconfiguration);
if(worlddata == null)
{
final Properties properties = new Properties();
properties.put("generator-settings", Objects.toString(creator.generatorSettings()));
properties.put("level-seed", Objects.toString(creator.seed()));
properties.put("generate-structures", Objects.toString(creator.generateStructures()));
properties.put("level-type", Objects.toString(creator.type().getName()));
final GeneratorSettings generatorsettings = GeneratorSettings.a(getConsoleDimension(console), properties);
@SuppressWarnings("deprecation")
final WorldSettings worldSettings = new WorldSettings(name, EnumGamemode.getById(server.getDefaultGameMode().getValue()), hardcore, EnumDifficulty.EASY, false, new GameRules(), console.datapackconfiguration);
worlddata = new WorldDataServer(worldSettings, generatorsettings, Lifecycle.stable());
}
worlddata.checkName(name);
worlddata.a(console.getServerModName(), console.getModded().isPresent());
if(console.options.has("forceUpgrade"))
{
net.minecraft.server.v1_16_R2.Main.convertWorld(worldSession, DataConverterRegistry.a(), console.options.has("eraseCache"), () -> true, (ImmutableSet) worlddata.getGeneratorSettings().d().d().stream().map(entry -> ResourceKey.a(IRegistry.K, entry.getKey().a())).collect(ImmutableSet.toImmutableSet()));
}
final long j = BiomeManager.a(creator.seed());
final List<MobSpawner> list = (List<MobSpawner>) ImmutableList.of((MobSpawner) new MobSpawnerPhantom(), (MobSpawner) new MobSpawnerPatrol(), (MobSpawner) new MobSpawnerCat(), (MobSpawner) new VillageSiege(), (MobSpawner) new MobSpawnerTrader((IWorldDataServer) worlddata));
DimensionManager dimensionmanager;
net.minecraft.server.v1_16_R2.ChunkGenerator chunkgenerator;
long ll = creator.seed();
dimensionmanager = (DimensionManager) getConsoleDimension(console).a().d(DimensionManager.OVERWORLD);
O<WorldServer> ws = new O<WorldServer>();
chunkgenerator = new NMSChunkGenerator16_2_PAPER(pro, ws, (WorldChunkManager) new WorldChunkManagerOverworld(ll, false, false, (IRegistry<BiomeBase>) getConsoleDimension(console).b(IRegistry.ay)), ll, () -> (GeneratorSettingBase) getConsoleDimension(console).b(IRegistry.ar).d(GeneratorSettingBase.c));
final ResourceKey<net.minecraft.server.v1_16_R2.World> worldKey = (ResourceKey<net.minecraft.server.v1_16_R2.World>) ResourceKey.a(IRegistry.L, new MinecraftKey(name.toLowerCase(Locale.ENGLISH)));
//@builder
final WorldServer internal = new WorldServer((MinecraftServer) console,
console.executorService, worldSession,
(IWorldDataServer) worlddata,
(ResourceKey) worldKey,
dimensionmanager,
server.getServer().worldLoadListenerFactory.create(11),
chunkgenerator,
worlddata.getGeneratorSettings().isDebugWorld(),
j,
(List) ((creator.environment() == World.Environment.NORMAL) ? list : ImmutableList.of()),
true,
creator.environment(),
server.getGenerator(name));
//@done
IrisWorlds.register(internal.getWorld(), pro);
ws.set(internal);
if(!worlds.containsKey(name.toLowerCase(Locale.ENGLISH)))
{
try
{
internal.close();
}
catch(IOException e)
{
e.printStackTrace();
}
return null;
}
console.initWorld(internal, (IWorldDataServer) worlddata, (SaveData) worlddata, worlddata.getGeneratorSettings());
internal.setSpawnFlags(true, true);
console.worldServer.put(internal.getDimensionKey(), internal);
server.getPluginManager().callEvent((Event) new WorldInitEvent((World) internal.getWorld()));
if(loadSpawn)
{
server.getServer().loadSpawn(internal.getChunkProvider().playerChunkMap.worldLoadListener, internal);
}
else
{
MinecraftServer.LOGGER.info("Preparing start region for dimens... Oh wait, We don't do that here anymore.");
}
server.getPluginManager().callEvent((Event) new WorldLoadEvent((World) internal.getWorld()));
return (World) internal.getWorld();
}
private Dimension getConsoleDimension(DedicatedServer console)
{
Dimension dim = null;
try
{
dim = new V((MinecraftServer) console, true).get("customRegistry");
if(dim != null)
{
return dim;
}
}
catch(Throwable e)
{
}
try
{
dim = new V((MinecraftServer) console, true).get("f");
if(dim != null)
{
return dim;
}
}
catch(Throwable e)
{
}
for(Field i : MinecraftServer.class.getDeclaredFields())
{
if(i.getType().equals(dim.getClass()))
{
i.setAccessible(true);
if(Modifier.isStatic(i.getModifiers()))
{
try
{
return (Dimension) i.get(null);
}
catch(Throwable e)
{
e.printStackTrace();
}
}
else
{
try
{
return (Dimension) i.get((MinecraftServer) console);
}
catch(Throwable e)
{
e.printStackTrace();
}
}
}
}
if(dim == null)
{
try
{
throw new RuntimeException("Cannot find dimension field!");
}
catch(Throwable e)
{
e.printStackTrace();
}
}
return dim;
}
}

View File

@@ -0,0 +1,16 @@
package com.volmit.iris.generator.legacy.nms.v1X;
import com.volmit.iris.generator.legacy.atomics.AtomicCache;
import com.volmit.iris.generator.legacy.nms.INMSBinding;
import com.volmit.iris.generator.legacy.nms.INMSCreator;
public class NMSBinding1X implements INMSBinding
{
private final AtomicCache<INMSCreator> creator = new AtomicCache<>();
@Override
public INMSCreator getCreator()
{
return creator.aquire(NMSCreator1X::new);
}
}

View File

@@ -0,0 +1,14 @@
package com.volmit.iris.generator.legacy.nms.v1X;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import com.volmit.iris.generator.legacy.nms.INMSCreator;
class NMSCreator1X implements INMSCreator
{
public World createWorld(WorldCreator creator, boolean loadSpawn)
{
return creator.createWorld();
}
}

View File

@@ -0,0 +1,471 @@
package com.volmit.iris.generator.legacy.post;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.Slab;
import org.bukkit.block.data.type.Slab.Type;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import com.volmit.iris.generator.legacy.PostBlockTerrainProvider;
import com.volmit.iris.object.InferredType;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.util.B;
import com.volmit.iris.util.CaveResult;
import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.IrisPostBlockFilter;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.RNG;
public class PostMasterPatcher extends IrisPostBlockFilter
{
private static final BlockData WATER = B.getBlockData("WATER");
private static final BlockData AIR = B.getBlockData("AIR");
private final RNG rng;
@DontObfuscate
public PostMasterPatcher(PostBlockTerrainProvider gen, int phase)
{
super(gen, phase);
rng = gen.getMasterRandom().nextParallelRNG(1239456);
}
@DontObfuscate
public PostMasterPatcher(PostBlockTerrainProvider gen)
{
this(gen, 0);
}
@Override
public void onPost(int x, int z, int currentPostX, int currentPostZ, ChunkData currentData, KList<Runnable> q)
{
int h = highestTerrainOrCarvingBlock(x, z);
int ha = highestTerrainOrCarvingBlock(x + 1, z);
int hb = highestTerrainOrCarvingBlock(x, z + 1);
int hc = highestTerrainOrCarvingBlock(x - 1, z);
int hd = highestTerrainOrCarvingBlock(x, z - 1);
// Floating Nibs
int g = 0;
if(h < 1)
{
return;
}
g += ha < h - 1 ? 1 : 0;
g += hb < h - 1 ? 1 : 0;
g += hc < h - 1 ? 1 : 0;
g += hd < h - 1 ? 1 : 0;
if(g == 4 && isAir(x, h - 1, z, currentPostX, currentPostZ, currentData))
{
setPostBlock(x, h, z, AIR, currentPostX, currentPostZ, currentData);
for(int i = h - 1; i > 0; i--)
{
if(!isAir(x, i, z, currentPostX, currentPostZ, currentData))
{
updateHeight(x, z, i);
h = i;
break;
}
}
}
// Nibs
g = 0;
g += ha == h - 1 ? 1 : 0;
g += hb == h - 1 ? 1 : 0;
g += hc == h - 1 ? 1 : 0;
g += hd == h - 1 ? 1 : 0;
if(g >= 4)
{
BlockData bc = getPostBlock(x, h, z, currentPostX, currentPostZ, currentData);
BlockData b = getPostBlock(x, h + 1, z, currentPostX, currentPostZ, currentData);
Material m = bc.getMaterial();
if((b.getMaterial().isOccluding() && b.getMaterial().isSolid()))
{
if(m.isSolid())
{
setPostBlock(x, h, z, b, currentPostX, currentPostZ, currentData);
updateHeight(x, z, h - 1);
h--;
}
}
}
else
{
// Potholes
g = 0;
g += ha == h + 1 ? 1 : 0;
g += hb == h + 1 ? 1 : 0;
g += hc == h + 1 ? 1 : 0;
g += hd == h + 1 ? 1 : 0;
if(g >= 4)
{
BlockData ba = getPostBlock(x, ha, z, currentPostX, currentPostZ, currentData);
BlockData bb = getPostBlock(x, hb, z, currentPostX, currentPostZ, currentData);
BlockData bc = getPostBlock(x, hc, z, currentPostX, currentPostZ, currentData);
BlockData bd = getPostBlock(x, hd, z, currentPostX, currentPostZ, currentData);
g = 0;
g = B.isSolid(ba) ? g + 1 : g;
g = B.isSolid(bb) ? g + 1 : g;
g = B.isSolid(bc) ? g + 1 : g;
g = B.isSolid(bd) ? g + 1 : g;
if(g >= 3)
{
setPostBlock(x, h + 1, z, getPostBlock(x, h, z, currentPostX, currentPostZ, currentData), currentPostX, currentPostZ, currentData);
updateHeight(x, z, h + 1);
h++;
}
}
}
// Wall Patcher
IrisBiome biome = gen.sampleTrueBiome(x, z);
if(gen.getDimension().isPostProcessingWalls())
{
if(!biome.getWall().getPalette().isEmpty())
{
if(ha < h - 2 || hb < h - 2 || hc < h - 2 || hd < h - 2)
{
boolean brokeGround = false;
int max = Math.abs(Math.max(h - ha, Math.max(h - hb, Math.max(h - hc, h - hd))));
for(int i = h; i > h - max; i--)
{
BlockData d = biome.getWall().get(rng, x + i, i + h, z + i, gen.getData());
if(d != null)
{
if(isAirOrWater(x, i, z, currentPostX, currentPostZ, currentData))
{
if(brokeGround)
{
break;
}
continue;
}
setPostBlock(x, i, z, d, currentPostX, currentPostZ, currentData);
brokeGround = true;
}
}
}
}
}
// Slab
if(gen.getDimension().isPostProcessingSlabs())
{
//@builder
if((ha == h + 1 && isSolidNonSlab(x + 1, ha, z, currentPostX, currentPostZ, currentData))
|| (hb == h + 1 && isSolidNonSlab(x, hb, z + 1, currentPostX, currentPostZ, currentData))
|| (hc == h + 1 && isSolidNonSlab(x - 1, hc, z, currentPostX, currentPostZ, currentData))
|| (hd == h + 1 && isSolidNonSlab(x, hd, z - 1, currentPostX, currentPostZ, currentData)))
//@done
{
BlockData d = biome.getSlab().get(rng, x, h, z, gen.getData());
if(d != null)
{
boolean cancel = false;
if(B.isAir(d))
{
cancel = true;
}
if(d.getMaterial().equals(Material.SNOW) && h + 1 <= gen.getFluidHeight())
{
cancel = true;
}
if(isSnowLayer(x, h, z, currentPostX, currentPostZ, currentData))
{
cancel = true;
}
if(!cancel && isAirOrWater(x, h + 1, z, currentPostX, currentPostZ, currentData))
{
setPostBlock(x, h + 1, z, d, currentPostX, currentPostZ, currentData);
updateHeight(x, z, h + 1);
h++;
}
}
}
}
// Waterlogging
BlockData b = getPostBlock(x, h, z, currentPostX, currentPostZ, currentData);
if(b instanceof Waterlogged)
{
Waterlogged ww = (Waterlogged) b;
boolean w = false;
if(isWaterOrWaterlogged(x, h + 1, z, currentPostX, currentPostZ, currentData))
{
w = true;
}
else if((isWaterOrWaterlogged(x + 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x - 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z + 1, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z - 1, currentPostX, currentPostZ, currentData)))
{
w = true;
}
if(w != ww.isWaterlogged())
{
ww.setWaterlogged(w);
setPostBlock(x, h, z, b, currentPostX, currentPostZ, currentData);
}
}
else if(b.getMaterial().equals(Material.AIR) && h <= gen.getFluidHeight())
{
if((isWaterOrWaterlogged(x + 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x - 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z + 1, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z - 1, currentPostX, currentPostZ, currentData)))
{
setPostBlock(x, h, z, WATER, currentPostX, currentPostZ, currentData);
}
}
// Foliage
b = getPostBlock(x, h + 1, z, currentPostX, currentPostZ, currentData);
if(B.isFoliage(b) || b.getMaterial().equals(Material.DEAD_BUSH))
{
Material onto = getPostBlock(x, h, z, currentPostX, currentPostZ, currentData).getMaterial();
if(!B.canPlaceOnto(b.getMaterial(), onto))
{
setPostBlock(x, h + 1, z, AIR, currentPostX, currentPostZ, currentData);
}
}
if(gen.getDimension().isPostProcessCaves())
{
IrisBiome cave = gen.sampleTrueBiome(x, 1, z);
if(cave != null && cave.getInferredType().equals(InferredType.CAVE))
{
for(CaveResult i : gen.getCaves(x, z))
{
if(i.getCeiling() > 256 || i.getFloor() < 0)
{
continue;
}
int f = i.getFloor();
int fa = nearestCaveFloor(f, x + 1, z, currentPostX, currentPostZ, currentData);
int fb = nearestCaveFloor(f, x, z + 1, currentPostX, currentPostZ, currentData);
int fc = nearestCaveFloor(f, x - 1, z, currentPostX, currentPostZ, currentData);
int fd = nearestCaveFloor(f, x, z - 1, currentPostX, currentPostZ, currentData);
int c = i.getCeiling();
int ca = nearestCaveCeiling(c, x + 1, z, currentPostX, currentPostZ, currentData);
int cb = nearestCaveCeiling(c, x, z + 1, currentPostX, currentPostZ, currentData);
int cc = nearestCaveCeiling(c, x - 1, z, currentPostX, currentPostZ, currentData);
int cd = nearestCaveCeiling(c, x, z - 1, currentPostX, currentPostZ, currentData);
// Cave Nibs
g = 0;
g += fa == f - 1 ? 1 : 0;
g += fb == f - 1 ? 1 : 0;
g += fc == f - 1 ? 1 : 0;
g += fd == f - 1 ? 1 : 0;
if(g >= 4)
{
BlockData bc = getPostBlock(x, f, z, currentPostX, currentPostZ, currentData);
b = getPostBlock(x, f + 1, z, currentPostX, currentPostZ, currentData);
Material m = bc.getMaterial();
if(m.isSolid())
{
setPostBlock(x, f, z, b, currentPostX, currentPostZ, currentData);
updateHeight(x, z, f - 1);
h--;
}
}
else
{
// Cave Potholes
g = 0;
g += fa == f + 1 ? 1 : 0;
g += fb == f + 1 ? 1 : 0;
g += fc == f + 1 ? 1 : 0;
g += fd == f + 1 ? 1 : 0;
if(g >= 4)
{
BlockData ba = getPostBlock(x, fa, z, currentPostX, currentPostZ, currentData);
BlockData bb = getPostBlock(x, fb, z, currentPostX, currentPostZ, currentData);
BlockData bc = getPostBlock(x, fc, z, currentPostX, currentPostZ, currentData);
BlockData bd = getPostBlock(x, fd, z, currentPostX, currentPostZ, currentData);
g = 0;
g = B.isSolid(ba) ? g + 1 : g;
g = B.isSolid(bb) ? g + 1 : g;
g = B.isSolid(bc) ? g + 1 : g;
g = B.isSolid(bd) ? g + 1 : g;
if(g >= 4)
{
setPostBlock(x, f + 1, z, getPostBlock(x, f, z, currentPostX, currentPostZ, currentData), currentPostX, currentPostZ, currentData);
updateHeight(x, z, f + 1);
h++;
}
}
}
if(gen.getDimension().isPostProcessingSlabs())
{
//@builder
if((fa == f + 1 && isSolidNonSlab(x + 1, fa, z, currentPostX, currentPostZ, currentData))
|| (fb == f + 1 && isSolidNonSlab(x, fb, z + 1, currentPostX, currentPostZ, currentData))
|| (fc == f + 1 && isSolidNonSlab(x - 1, fc, z, currentPostX, currentPostZ, currentData))
|| (fd == f + 1 && isSolidNonSlab(x, fd, z - 1, currentPostX, currentPostZ, currentData)))
//@done
{
BlockData d = cave.getSlab().get(rng, x, f, z, gen.getData());
if(d != null)
{
boolean cancel = false;
if(B.isAir(d))
{
cancel = true;
}
if(d.getMaterial().equals(Material.SNOW) && f + 1 <= gen.getFluidHeight())
{
cancel = true;
}
if(isSnowLayer(x, f, z, currentPostX, currentPostZ, currentData))
{
cancel = true;
}
if(!cancel && isAirOrWater(x, f + 1, z, currentPostX, currentPostZ, currentData))
{
setPostBlock(x, f + 1, z, d, currentPostX, currentPostZ, currentData);
}
}
}
//@builder
if((ca == c - 1 && isSolidNonSlab(x + 1, ca, z, currentPostX, currentPostZ, currentData))
|| (cb == c - 1 && isSolidNonSlab(x, cb, z + 1, currentPostX, currentPostZ, currentData))
|| (cc == c - 1 && isSolidNonSlab(x - 1, cc, z, currentPostX, currentPostZ, currentData))
|| (cd == c - 1 && isSolidNonSlab(x, cd, z - 1, currentPostX, currentPostZ, currentData)))
//@done
{
BlockData d = cave.getSlab().get(rng, x, c, z, gen.getData());
if(d != null)
{
boolean cancel = false;
if(B.isAir(d))
{
cancel = true;
}
if(!(d instanceof Slab))
{
cancel = true;
}
if(isSnowLayer(x, c, z, currentPostX, currentPostZ, currentData))
{
cancel = true;
}
if(!cancel && isAirOrWater(x, c, z, currentPostX, currentPostZ, currentData))
{
Slab slab = (Slab) d.clone();
slab.setType(Type.TOP);
setPostBlock(x, c, z, slab, currentPostX, currentPostZ, currentData);
}
}
}
}
}
}
}
}
private int nearestCaveFloor(int floor, int x, int z, int currentPostX, int currentPostZ, ChunkData currentData)
{
if(floor > 255)
{
return 255;
}
if(B.isAir(getPostBlock(x, floor, z, currentPostX, currentPostZ, currentData)))
{
if(B.isAir(getPostBlock(x, floor - 1, z, currentPostX, currentPostZ, currentData)))
{
return floor - 2;
}
return floor - 1;
}
else
{
if(!B.isAir(getPostBlock(x, floor + 1, z, currentPostX, currentPostZ, currentData)))
{
if(!B.isAir(getPostBlock(x, floor + 2, z, currentPostX, currentPostZ, currentData)))
{
return floor + 2;
}
return floor + 1;
}
return floor;
}
}
private int nearestCaveCeiling(int ceiling, int x, int z, int currentPostX, int currentPostZ, ChunkData currentData)
{
if(ceiling > 255)
{
return 255;
}
if(B.isAir(getPostBlock(x, ceiling, z, currentPostX, currentPostZ, currentData)))
{
if(B.isAir(getPostBlock(x, ceiling + 1, z, currentPostX, currentPostZ, currentData)))
{
return ceiling + 2;
}
return ceiling + 1;
}
else
{
if(!B.isAir(getPostBlock(x, ceiling - 1, z, currentPostX, currentPostZ, currentData)))
{
if(!B.isAir(getPostBlock(x, ceiling - 2, z, currentPostX, currentPostZ, currentData)))
{
return ceiling - 2;
}
return ceiling - 1;
}
return ceiling;
}
}
}

View File

@@ -0,0 +1,297 @@
package com.volmit.iris.generator.legacy.provisions;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import com.volmit.iris.Iris;
import com.volmit.iris.generator.legacy.IrisTerrainProvider;
import com.volmit.iris.generator.legacy.scaffold.GeneratedChunk;
import com.volmit.iris.generator.legacy.scaffold.HeightedFakeWorld;
import com.volmit.iris.generator.legacy.scaffold.Provisioned;
import com.volmit.iris.generator.legacy.scaffold.TerrainChunk;
import com.volmit.iris.generator.legacy.scaffold.TerrainProvider;
import com.volmit.iris.util.ChunkPosition;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.KMap;
import com.volmit.iris.util.RNG;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class ProvisionBukkit extends ChunkGenerator implements Provisioned
{
private HeightedFakeWorld fakeworld = null;
private boolean worldSet = false;
private final TerrainProvider provider;
private final KMap<ChunkPosition, TerrainChunk> precache;
private KList<ChunkPosition> regenerated = new KList<ChunkPosition>();
private Executor e = Executors.newFixedThreadPool(Iris.getThreadCount());
private World cachedWorld;
public ProvisionBukkit(TerrainProvider provider)
{
this.provider = provider;
provider.setProvisioner(this);
precache = new KMap<>();
}
public void clearRegeneratedLists()
{
regenerated.clear();
Iris.clearQueues();
}
@SuppressWarnings("deprecation")
@Override
public void regenerate(int x, int z)
{
boolean exists = cachedWorld.loadChunk(x, z, false);
if(!exists)
{
return;
}
ChunkPosition ccp = new ChunkPosition(x, z);
if(regenerated.contains(ccp))
{
return;
}
regenerated.add(ccp);
e.execute(() ->
{
((IrisTerrainProvider) getProvider()).forgetParallaxChunksNear(x, z);
TerrainChunk snapshot = TerrainChunk.create(cachedWorld);
snapshot.setRaw(generateChunkData(cachedWorld, getRNG(cachedWorld, x, z), x, z, snapshot));
int cx = x * 16;
int cz = z * 16;
Iris.sq(() ->
{
for(int hh = 0; hh < 16; hh++)
{
int h = hh;
for(int i = 0; i < 16; i++)
{
for(int j = 0; j < 16; j++)
{
for(int k = 0; k < 16; k++)
{
BlockData b = snapshot.getBlockData(i, (h * 16) + j, k);
if(!Iris.edit.get(cachedWorld, i + cx, (h * 16) + j, k + cz).equals(b))
{
Iris.edit.set(cachedWorld, i + cx, (h * 16) + j, k + cz, b);
}
if(Iris.biome3d)
{
Biome bo = snapshot.getBiome(i, (h * 16) + j, k);
if(!Iris.edit.getBiome(cachedWorld, i, (h * 16) + j, k).equals(bo))
{
Iris.edit.setBiome(cachedWorld, i + cx, (h * 16) + j, k + cz, bo);
}
}
else if(j == 0 && h == 0)
{
Biome bo = snapshot.getBiome(i, k);
if(!Iris.edit.getBiome(cachedWorld, i, k).equals(bo))
{
Iris.edit.setBiome(cachedWorld, i + cx, k + cz, bo);
}
}
}
}
}
}
});
});
}
public void generate(World world, int x, int z)
{
cachedWorld = world;
world.loadChunk(x, z, true);
world.unloadChunkRequest(x, z);
}
public void generateAsync(World world, int x, int z, Consumer<Boolean> onDone)
{
cachedWorld = world;
ChunkPosition c = new ChunkPosition(x, z);
if(!precache.containsKey(c))
{
TerrainChunk snapshot = TerrainChunk.create(world);
snapshot.setRaw(generateChunkData(world, getRNG(world, x, z), x, z, snapshot));
precache.put(c, snapshot);
onDone.accept(true);
}
else
{
onDone.accept(false);
}
}
public void fixSpawn(World w)
{
cachedWorld = w;
if(w.getSpawnLocation().getY() == 0 && w.getSpawnLocation().getZ() == 0 && w.getSpawnLocation().getX() == 0)
{
w.setSpawnLocation(provider.computeSpawn((b) ->
{
Location at = b.toLocation(w);
Location ab = at.clone().add(0, 1, 0);
Location bl = at.clone().add(0, -1, 0);
if(!bl.getBlock().getType().isSolid())
{
return false;
}
if(ab.getBlock().getType().isSolid())
{
return false;
}
if(at.getBlock().getType().isSolid())
{
return false;
}
if(!ab.getBlock().getType().isAir())
{
return false;
}
if(!at.getBlock().getType().isAir())
{
return false;
}
return true;
}).toLocation(w));
Iris.info("Fixed " + w.getName() + " Spawn to " + w.getSpawnLocation().getBlockX() + ", " + w.getSpawnLocation().getBlockY() + ", " + w.getSpawnLocation().getBlockZ());
}
}
@Override
public ChunkData generateChunkData(World world, Random random, int x, int z, BiomeGrid biome)
{
cacheWorld(world);
if(precache.size() > 0)
{
ChunkPosition c = new ChunkPosition(x, z);
if(precache.containsKey(c))
{
TerrainChunk snapshot = precache.remove(c);
snapshot.inject(biome);
return snapshot.getRaw();
}
}
TerrainChunk terrain = TerrainChunk.create(world, biome);
getProvider().generate(getRNG(world, x, z), x, z, terrain);
return terrain.getRaw();
}
public GeneratedChunk generateNMSChunkData(World world, Random random, int x, int z, ChunkData nmsData, BiomeGrid biome)
{
cacheWorld(world);
TerrainChunk terrain = TerrainChunk.create(nmsData, biome);
return getProvider().generate(getRNG(world, x, z), x, z, terrain);
}
private void cacheWorld(World world)
{
cachedWorld = world;
if(!worldSet)
{
worldSet = true;
provider.getTarget().setRealWorld(world);
if(world.getSpawnLocation().getY() == 0 && world.getSpawnLocation().getZ() == 0 && world.getSpawnLocation().getX() == 0)
{
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, () -> fixSpawn(world));
}
}
}
private Random getRNG(World world, int x, int z)
{
cachedWorld = world;
return new RNG(world.getSeed()).nextParallelRNG(x).nextParallelRNG(z);
}
@Override
public boolean canSpawn(World world, int x, int z)
{
cachedWorld = world;
return provider.canSpawn(x, z);
}
@Override
public List<BlockPopulator> getDefaultPopulators(World world)
{
cachedWorld = world;
return provider.getPopulators();
}
@Override
public Location getFixedSpawnLocation(World world, Random random)
{
return null;
}
@Override
public boolean isParallelCapable()
{
return provider.isParallelCapable();
}
@Override
public boolean shouldGenerateCaves()
{
return provider.shouldGenerateCaves();
}
@Override
public boolean shouldGenerateDecorations()
{
return super.shouldGenerateDecorations();
}
@Override
public boolean shouldGenerateMobs()
{
return provider.shouldGenerateMobs();
}
@Override
public boolean shouldGenerateStructures()
{
return provider.shouldGenerateVanillaStructures();
}
}

View File

@@ -0,0 +1,84 @@
package com.volmit.iris.generator.legacy.scaffold;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import org.bukkit.material.MaterialData;
@SuppressWarnings("deprecation")
public class ChunkWrapper implements ChunkData
{
private final Chunk chunk;
public ChunkWrapper(Chunk chunk)
{
this.chunk = chunk;
}
@Override
public int getMaxHeight()
{
return chunk.getWorld().getMaxHeight();
}
@Override
public void setBlock(int x, int y, int z, Material material)
{
chunk.getBlock(x, y, z).setType(material, false);
}
@Override
public void setBlock(int x, int y, int z, MaterialData material)
{
throw new UnsupportedOperationException();
}
@Override
public void setBlock(int x, int y, int z, BlockData blockData)
{
chunk.getBlock(x, y, z).setBlockData(blockData, false);
}
@Override
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, Material material)
{
throw new UnsupportedOperationException();
}
@Override
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, MaterialData material)
{
throw new UnsupportedOperationException();
}
@Override
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, BlockData blockData)
{
throw new UnsupportedOperationException();
}
@Override
public Material getType(int x, int y, int z)
{
return chunk.getBlock(x, y, z).getType();
}
@Override
public MaterialData getTypeAndData(int x, int y, int z)
{
throw new UnsupportedOperationException();
}
@Override
public BlockData getBlockData(int x, int y, int z)
{
return chunk.getBlock(x, y, z).getBlockData();
}
@Override
public byte getData(int x, int y, int z)
{
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,20 @@
package com.volmit.iris.generator.legacy.scaffold;
import com.volmit.iris.generator.legacy.atomics.AtomicSliverMap;
import com.volmit.iris.util.BiomeMap;
import com.volmit.iris.util.HeightMap;
import lombok.Builder;
import lombok.Data;
@Builder
@Data
public class GeneratedChunk
{
private int x;
private int z;
private TerrainChunk terrain;
private HeightMap height;
private AtomicSliverMap sliverMap;
private BiomeMap biomeMap;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,77 @@
package com.volmit.iris.generator.legacy.scaffold;
import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import com.volmit.iris.util.IrisMathHelper;
public class IrisBiomeStorage
{
private static final int e;
private static final int f;
public static final int a;
public static final int b;
public static final int c;
private final Biome[] g;
static
{
e = (int) Math.round(Math.log(16.0) / Math.log(2.0)) - 2;
f = (int) Math.round(Math.log(256.0) / Math.log(2.0)) - 2;
a = 1 << IrisBiomeStorage.e + IrisBiomeStorage.e + IrisBiomeStorage.f;
b = (1 << IrisBiomeStorage.e) - 1;
c = (1 << IrisBiomeStorage.f) - 1;
}
public IrisBiomeStorage(final Biome[] aBiome)
{
this.g = aBiome;
}
public IrisBiomeStorage()
{
this(new Biome[IrisBiomeStorage.a]);
}
public IrisBiomeStorage b()
{
return new IrisBiomeStorage(this.g.clone());
}
public void inject(BiomeGrid grid)
{
for(int i = 0; i < 256; i++)
{
for(int j = 0; j < 16; j++)
{
for(int k = 0; k < 16; k++)
{
Biome b = getBiome(j, i, k);
if(b == null || b.equals(Biome.THE_VOID))
{
continue;
}
grid.setBiome(j, i, k, b);
}
}
}
}
public Biome getBiome(final int x, final int y, final int z)
{
final int l = x & IrisBiomeStorage.b;
final int i2 = IrisMathHelper.clamp(y, 0, IrisBiomeStorage.c);
final int j2 = z & IrisBiomeStorage.b;
return this.g[i2 << IrisBiomeStorage.e + IrisBiomeStorage.e | j2 << IrisBiomeStorage.e | l];
}
public void setBiome(final int x, final int y, final int z, final Biome biome)
{
final int l = x & IrisBiomeStorage.b;
final int i2 = IrisMathHelper.clamp(y, 0, IrisBiomeStorage.c);
final int j2 = z & IrisBiomeStorage.b;
this.g[i2 << IrisBiomeStorage.e + IrisBiomeStorage.e | j2 << IrisBiomeStorage.e | l] = biome;
}
}

View File

@@ -0,0 +1,35 @@
package com.volmit.iris.generator.legacy.scaffold;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDimension;
import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.util.KMap;
public interface IrisContext
{
static KMap<TerrainTarget, IrisContext> contexts = new KMap<>();
public static void pushContext(IrisContext context)
{
contexts.put(context.getTarget(), context);
}
public static IrisContext of(TerrainTarget world)
{
return contexts.get(world);
}
public TerrainTarget getTarget();
public IrisBiome getBiome(int x, int z);
public IrisDimension getDimension();
public IrisRegion getRegion(int x, int z);
public IrisMetrics getMetrics();
public int getHeight(int x, int z);
public void onHotloaded();
}

View File

@@ -0,0 +1,24 @@
package com.volmit.iris.generator.legacy.scaffold;
import com.volmit.iris.generator.legacy.IrisTerrainProvider;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class IrisGenConfiguration
{
private TerrainTarget target;
@Builder.Default
private int threads = 16;
@Builder.Default
private String dimension = "";
public IrisTerrainProvider buildGenerator()
{
return new IrisTerrainProvider(this);
}
}

View File

@@ -0,0 +1,38 @@
package com.volmit.iris.generator.legacy.scaffold;
import com.volmit.iris.Iris;
import com.volmit.iris.util.RollingSequence;
import lombok.Data;
@Data
public class IrisMetrics
{
private final RollingSequence parallax;
private final RollingSequence terrain;
private final RollingSequence post;
private final RollingSequence update;
private final RollingSequence deposits;
private final RollingSequence spawns;
private final RollingSequence total;
private final RollingSequence perSecond;
public int generators = 0;
public int noiseHits = 0;
public IrisMetrics(int memory)
{
parallax = new RollingSequence(memory);
spawns = new RollingSequence(memory);
terrain = new RollingSequence(memory);
post = new RollingSequence(memory);
update = new RollingSequence(memory);
deposits = new RollingSequence(memory);
total = new RollingSequence(memory);
perSecond = new RollingSequence(5);
}
public double getSpeed()
{
return (double) Iris.board.hits.getAverage() / (double) total.getAverage();
}
}

View File

@@ -0,0 +1,229 @@
package com.volmit.iris.generator.legacy.scaffold;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import org.bukkit.material.MaterialData;
import com.volmit.iris.Iris;
@SuppressWarnings("deprecation")
public class LinkedTerrainChunk implements TerrainChunk
{
private final Biome[] biome2D;
private final IrisBiomeStorage biome3D;
private ChunkData rawChunkData;
private final BiomeGrid storage;
public LinkedTerrainChunk(int maxHeight)
{
this(null, maxHeight);
}
public LinkedTerrainChunk(BiomeGrid storage, ChunkData data)
{
this.storage = storage;
rawChunkData = data;
biome2D = storage != null ? null : Iris.biome3d ? null : new Biome[256];
biome3D = storage != null ? null : Iris.biome3d ? new IrisBiomeStorage() : null;
}
public LinkedTerrainChunk(BiomeGrid storage, int maxHeight)
{
this.storage = storage;
rawChunkData = createChunkData(maxHeight);
biome2D = storage != null ? null : Iris.biome3d ? null : new Biome[256];
biome3D = storage != null ? null : Iris.biome3d ? new IrisBiomeStorage() : null;
}
private ChunkData createChunkData(int maxHeight)
{
try
{
return Bukkit.createChunkData(new HeightedFakeWorld(maxHeight));
}
catch(Throwable e)
{
e.printStackTrace();
}
return null;
}
@Override
public Biome getBiome(int x, int z)
{
if(storage != null)
{
return storage.getBiome(x, z);
}
if(biome2D != null)
{
return biome2D[(z << 4) | x];
}
return biome3D.getBiome(x, 0, z);
}
@Override
public Biome getBiome(int x, int y, int z)
{
if(storage != null)
{
return storage.getBiome(x, y, z);
}
if(biome2D != null)
{
return biome2D[(z << 4) | x];
}
return biome3D.getBiome(x, y, z);
}
@Override
public void setBiome(int x, int z, Biome bio)
{
if(storage != null)
{
storage.setBiome(x, z, bio);
return;
}
if(biome2D != null)
{
biome2D[(z << 4) | x] = bio;
return;
}
biome3D.setBiome(x, 0, z, bio);
}
@Override
public void setBiome(int x, int y, int z, Biome bio)
{
if(storage != null)
{
storage.setBiome(x, y, z, bio);
return;
}
if(biome2D != null)
{
biome2D[(z << 4) | x] = bio;
return;
}
biome3D.setBiome(x, y, z, bio);
}
@Override
public int getMaxHeight()
{
return rawChunkData.getMaxHeight();
}
@Override
public void setBlock(int x, int y, int z, BlockData blockData)
{
rawChunkData.setBlock(x, y, z, blockData);
}
@Override
public BlockData getBlockData(int x, int y, int z)
{
return rawChunkData.getBlockData(x, y, z);
}
@Deprecated
@Override
public void setBlock(int x, int y, int z, Material material)
{
rawChunkData.setBlock(x, y, z, material);
}
@Deprecated
@Override
public void setBlock(int x, int y, int z, MaterialData material)
{
rawChunkData.setBlock(x, y, z, material);
}
@Deprecated
@Override
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, Material material)
{
rawChunkData.setRegion(xMin, yMin, zMin, xMax, yMax, zMax, material);
}
@Deprecated
@Override
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, MaterialData material)
{
rawChunkData.setRegion(xMin, yMin, zMin, xMax, yMax, zMax, material);
}
@Override
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, BlockData blockData)
{
rawChunkData.setRegion(xMin, yMin, zMin, xMax, yMax, zMax, blockData);
}
@Deprecated
@Override
public Material getType(int x, int y, int z)
{
return rawChunkData.getType(x, y, z);
}
@Deprecated
@Override
public MaterialData getTypeAndData(int x, int y, int z)
{
return rawChunkData.getTypeAndData(x, y, z);
}
@Deprecated
@Override
public byte getData(int x, int y, int z)
{
return rawChunkData.getData(x, y, z);
}
@Override
public ChunkData getRaw()
{
return rawChunkData;
}
@Override
public void setRaw(ChunkData data)
{
rawChunkData = data;
}
@Override
public void inject(BiomeGrid biome)
{
if(biome2D != null)
{
for(int i = 0; i < 16; i++)
{
for(int j = 0; j < 16; j++)
{
biome.setBiome(i, j, getBiome(i, j));
}
}
}
else if(biome3D != null)
{
biome3D.inject(biome);
}
}
}

View File

@@ -0,0 +1,10 @@
package com.volmit.iris.generator.legacy.scaffold;
public interface Provisioned
{
public void clearRegeneratedLists();
public TerrainProvider getProvider();
public void regenerate(int x, int z);
}

View File

@@ -0,0 +1,6 @@
package com.volmit.iris.generator.legacy.scaffold;
public interface ProvisionedHolder extends Provisioned
{
public Provisioned getProvisioned();
}

View File

@@ -0,0 +1,138 @@
package com.volmit.iris.generator.legacy.scaffold;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;
public interface TerrainChunk extends BiomeGrid, ChunkData
{
public static TerrainChunk create(World world)
{
return create(world.getMaxHeight());
}
public static TerrainChunk create(int maxHeight)
{
return new LinkedTerrainChunk(maxHeight);
}
public static TerrainChunk create(World world, BiomeGrid grid)
{
return create(world.getMaxHeight(), grid);
}
public static TerrainChunk create(ChunkData raw, BiomeGrid grid)
{
return new LinkedTerrainChunk(grid, raw);
}
public static TerrainChunk create(int maxHeight, BiomeGrid grid)
{
return new LinkedTerrainChunk(grid, maxHeight);
}
public void setRaw(ChunkData data);
/**
* Get biome at x, z within chunk being generated
*
* @param x
* - 0-15
* @param z
* - 0-15
* @return Biome value
* @deprecated biomes are now 3-dimensional
*/
@Deprecated
Biome getBiome(int x, int z);
/**
* Get biome at x, z within chunk being generated
*
* @param x
* - 0-15
* @param y
* - 0-255
* @param z
* - 0-15
* @return Biome value
*/
Biome getBiome(int x, int y, int z);
/**
* Set biome at x, z within chunk being generated
*
* @param x
* - 0-15
* @param z
* - 0-15
* @param bio
* - Biome value
* @deprecated biomes are now 3-dimensional
*/
@Deprecated
void setBiome(int x, int z, Biome bio);
/**
* Set biome at x, z within chunk being generated
*
* @param x
* - 0-15
* @param y
* - 0-255
* @param z
* - 0-15
* @param bio
* - Biome value
*/
void setBiome(int x, int y, int z, Biome bio);
/**
* Get the maximum height for the chunk.
*
* Setting blocks at or above this height will do nothing.
*
* @return the maximum height
*/
public int getMaxHeight();
/**
* Set the block at x,y,z in the chunk data to material.
*
* Setting blocks outside the chunk's bounds does nothing.
*
* @param x
* the x location in the chunk from 0-15 inclusive
* @param y
* the y location in the chunk from 0 (inclusive) - maxHeight
* (exclusive)
* @param z
* the z location in the chunk from 0-15 inclusive
* @param blockData
* the type to set the block to
*/
public void setBlock(int x, int y, int z, BlockData blockData);
/**
* Get the type and data of the block at x, y, z.
*
* Getting blocks outside the chunk's bounds returns air.
*
* @param x
* the x location in the chunk from 0-15 inclusive
* @param y
* the y location in the chunk from 0 (inclusive) - maxHeight
* (exclusive)
* @param z
* the z location in the chunk from 0-15 inclusive
* @return the data of the block or the BlockData for air if x, y or z are
* outside the chunk's bounds
*/
public BlockData getBlockData(int x, int y, int z);
public ChunkData getRaw();
public void inject(BiomeGrid biome);
}

View File

@@ -0,0 +1,35 @@
package com.volmit.iris.generator.legacy.scaffold;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.util.BlockVector;
public interface TerrainProvider
{
public TerrainTarget getTarget();
public Provisioned getProvisioner();
public void setProvisioner(Provisioned p);
public BlockVector computeSpawn(Function<BlockVector, Boolean> allowed);
public GeneratedChunk generate(Random random, int x, int z, TerrainChunk chunk);
public boolean canSpawn(int x, int z);
public List<BlockPopulator> getPopulators();
public boolean isParallelCapable();
public boolean shouldGenerateMobs();
public boolean shouldGenerateCaves();
public boolean shouldGenerateDecorations();
public boolean shouldGenerateVanillaStructures();
}

View File

@@ -0,0 +1,97 @@
package com.volmit.iris.generator.legacy.scaffold;
import java.io.File;
import java.util.List;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.entity.Player;
import com.volmit.iris.util.KList;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class TerrainTarget
{
private long seed;
private Environment environment;
private String name;
private File folder;
private static final KList<Player> emptyPlayers = new KList<>();
private World realWorld;
public void setRealWorld(World realWorld)
{
if(this.realWorld == null || realWorld != this.realWorld)
{
this.realWorld = realWorld;
this.seed = realWorld.getSeed();
this.folder = realWorld.getWorldFolder();
this.environment = realWorld.getEnvironment();
this.name = realWorld.getName();
}
}
public static TerrainTarget from(World world)
{
// @NoArgsConstructor
return new TerrainTargetBuilder().environment(world.getEnvironment()).seed(world.getSeed()).folder(world.getWorldFolder()).name(world.getName()).realWorld(world).build();
//@done
}
public List<Player> getPlayers()
{
return realWorld != null ? realWorld.getPlayers() : emptyPlayers;
}
public boolean isWorld(World world)
{
return world.getName().equals(getName()) && world.getSeed() == getSeed() && getEnvironment().equals(world.getEnvironment()) && world.getWorldFolder().equals(getFolder());
}
@Override
public boolean equals(Object obj)
{
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
TerrainTarget other = (TerrainTarget) obj;
if(environment != other.environment)
return false;
if(folder == null)
{
if(other.folder != null)
return false;
}
else if(!folder.equals(other.folder))
return false;
if(name == null)
{
if(other.name != null)
return false;
}
else if(!name.equals(other.name))
return false;
if(seed != other.seed)
return false;
return true;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((environment == null) ? 0 : environment.hashCode());
result = prime * result + ((folder == null) ? 0 : folder.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + (int) (seed ^ (seed >>> 32));
return result;
}
}

View File

@@ -0,0 +1,252 @@
package com.volmit.iris.generator.modifier;
import com.volmit.iris.generator.noise.FastNoiseDouble;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisCaveLayer;
import com.volmit.iris.util.B;
import com.volmit.iris.util.CaveResult;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.RNG;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedModifier;
import com.volmit.iris.scaffold.hunk.Hunk;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import java.util.function.Function;
public class IrisCaveModifier extends EngineAssignedModifier<BlockData>
{
public static final BlockData CAVE_AIR = B.getBlockData("CAVE_AIR");
public static final BlockData AIR = B.getBlockData("AIR");
private static final KList<CaveResult> EMPTY = new KList<>();
private final FastNoiseDouble gg;
private final RNG rng;
public IrisCaveModifier(Engine engine) {
super(engine, "Cave");
rng = new RNG(engine.getWorld().getSeed() + 28934555);
gg = new FastNoiseDouble(324895 * rng.nextParallelRNG(49678).imax());
}
@Override
public void onModify(int x, int z, Hunk<BlockData> a) {
for(int i = 0; i < a.getWidth(); i++)
{
for(int j = 0; j < a.getDepth(); j++)
{
KList<CaveResult> caves = genCaves(x + i, z + j, i, j, a);
int he = (int) Math.round(getComplex().getHeightStream().get(x+i, z+j));
if(caves != null && caves.isNotEmpty())
{
IrisBiome cave = getComplex().getCaveBiomeStream().get(x + i, z + j);
if(cave == null)
{
continue;
}
for(CaveResult cl : caves)
{
if(cl.getFloor() < 0 || cl.getFloor() > getEngine().getHeight() || cl.getCeiling() > getEngine().getHeight() || cl.getCeiling() < 0)
{
continue;
}
KList<BlockData> floor = cave.generateLayers(x + i, z + j, rng, cl.getFloor(), cl.getFloor(), getData());
KList<BlockData> ceiling = cave.generateLayers(x + i + 656, z + j - 656, rng,
he - cl.getCeiling(),
he - cl.getCeiling(), getData());
for(int g = 0; g < floor.size(); g++)
{
a.set(i, cl.getFloor() - g, j, floor.get(g));
}
for(int g = ceiling.size() - 1; g > 0; g--)
{
a.set(i, cl.getCeiling() + g, j, ceiling.get(g));
}
}
}
}
};
}
public KList<CaveResult> genCaves(double wxx, double wzz, int x, int z, Hunk<BlockData> data)
{
if(!getDimension().isCaves())
{
return EMPTY;
}
KList<CaveResult> result = new KList<>();
gg.setNoiseType(FastNoiseDouble.NoiseType.Cellular);
gg.setCellularReturnType(FastNoiseDouble.CellularReturnType.Distance2Sub);
gg.setCellularDistanceFunction(FastNoiseDouble.CellularDistanceFunction.Natural);
for(int i = 0; i < getDimension().getCaveLayers().size(); i++)
{
IrisCaveLayer layer = getDimension().getCaveLayers().get(i);
generateCave(result, wxx, wzz, x, z, data, layer, i);
}
return result;
}
public void generateCave(KList<CaveResult> result, double wxx, double wzz, int x, int z, Hunk<BlockData> data, IrisCaveLayer layer, int seed)
{
double scale = layer.getCaveZoom();
Function<Integer, BlockData> fluid = (height) ->
{
if(!layer.getFluid().hasFluid(getData()))
{
return CAVE_AIR;
}
if(layer.getFluid().isInverseHeight() && height >= layer.getFluid().getFluidHeight())
{
return layer.getFluid().getFluid(getData());
}
else if(!layer.getFluid().isInverseHeight() && height <= layer.getFluid().getFluidHeight())
{
return layer.getFluid().getFluid(getData());
}
return CAVE_AIR;
};
int surface = (int) Math.round(getComplex().getHeightStream().get(wxx, wzz));
double wx = wxx + layer.getHorizontalSlope().get(rng, wxx, wzz);
double wz = wzz + layer.getHorizontalSlope().get(rng, -wzz, -wxx);
double baseWidth = (14 * scale);
double distanceCheck = 0.0132 * baseWidth;
double distanceTake = 0.0022 * baseWidth;
double caveHeightNoise = layer.getVerticalSlope().get(rng, wxx, wzz);
if(caveHeightNoise > 259 || caveHeightNoise < -1)
{
return;
}
int ceiling = -256;
int floor = 512;
for(double tunnelHeight = 1; tunnelHeight <= baseWidth; tunnelHeight++)
{
double distance = (gg.GetCellular(((wx + (10000 * seed)) / layer.getCaveZoom()), ((wz - (10000 * seed)) / layer.getCaveZoom())) + 1D) / 2D;
if(distance < distanceCheck - (tunnelHeight * distanceTake))
{
int caveHeight = (int) Math.round(caveHeightNoise);
int pu = (int) (caveHeight + tunnelHeight);
int pd = (int) (caveHeight - tunnelHeight);
if(pd > surface + 1)
{
continue;
}
if(!layer.isCanBreakSurface() && pu > surface - 3)
{
continue;
}
if((pu > 255 && pd > 255) || (pu < 0 && pd < 0))
{
continue;
}
if(data == null)
{
ceiling = Math.max(pu, ceiling);
floor = Math.min(pu, floor);
ceiling = Math.max(pd, ceiling);
floor = Math.min(pd, floor);
if(tunnelHeight == 1)
{
ceiling = Math.max(caveHeight, ceiling);
floor = Math.min(caveHeight, floor);
}
}
else
{
if(dig(x, pu, z, data, fluid))
{
ceiling = Math.max(pu, ceiling);
floor = Math.min(pu, floor);
}
if(dig(x, pd, z, data, fluid))
{
ceiling = Math.max(pd, ceiling);
floor = Math.min(pd, floor);
}
if(tunnelHeight == 1)
{
if(dig(x, caveHeight, z, data, fluid))
{
ceiling = Math.max(caveHeight, ceiling);
floor = Math.min(caveHeight, floor);
}
}
}
}
}
if(floor >= 0 && ceiling <= 255)
{
result.add(new CaveResult(floor, ceiling));
}
}
private Material mat(int x, int y, int z, Hunk<BlockData> data)
{
BlockData d = data.get(x,y,z);
if(d != null)
{
return d.getMaterial();
}
return Material.CAVE_AIR;
}
public boolean dig(int x, int y, int z, Hunk<BlockData> data, Function<Integer, BlockData> caveFluid)
{
Material a = mat(x,y,z, data);
Material c = mat(x, y + 1, z, data);
Material d = mat(x, y + 2, z, data);
Material e = mat(x, y + 3, z, data);
Material f = mat(x, y - 1, z, data);
BlockData b = caveFluid.apply(y);
BlockData b2 = caveFluid.apply(y + 1);
if(can(a) && canAir(c, b) && canAir(f, b) && canWater(d) && canWater(e))
{
data.set(x, y, z, b);
data.set(x, y + 1, z, b2);
return true;
}
return false;
}
public boolean canAir(Material m, BlockData caveFluid)
{
return (B.isSolid(m) || (B.isDecorant(m.createBlockData())) || m.equals(Material.AIR) || m.equals(caveFluid.getMaterial()) || m.equals(B.mat("CAVE_AIR").getMaterial())) && !m.equals(Material.BEDROCK);
}
public boolean canWater(Material m)
{
return !m.equals(Material.WATER);
}
public boolean can(Material m)
{
return B.isSolid(m) && !m.equals(Material.BEDROCK);
}
}

View File

@@ -0,0 +1,131 @@
package com.volmit.iris.generator.modifier;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDepositGenerator;
import com.volmit.iris.object.IrisObject;
import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.util.HeightMap;
import com.volmit.iris.util.RNG;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedModifier;
import com.volmit.iris.scaffold.hunk.Hunk;
import org.bukkit.block.data.BlockData;
import org.bukkit.util.BlockVector;
public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
private final RNG rng;
public IrisDepositModifier(Engine engine) {
super(engine, "Deposit");
rng = new RNG(getEngine().getWorld().getSeed()+12938).nextParallelRNG(28348777);
}
@Override
public void onModify(int x, int z, Hunk<BlockData> output) {
generateDeposits(rng, output, Math.floorDiv(x, 16), Math.floorDiv(z, 16));
}
public void generateDeposits(RNG rx, Hunk<BlockData> terrain, int x, int z)
{
RNG ro = rx.nextParallelRNG(x * x).nextParallelRNG(z * z);
IrisRegion region = getComplex().getRegionStream().get((x * 16) + 7, (z * 16) + 7);
IrisBiome biome = getComplex().getTrueBiomeStream().get((x * 16) + 7, (z * 16) + 7);
for(IrisDepositGenerator k : getDimension().getDeposits())
{
generate(k, terrain, ro, x, z, false);
}
for(IrisDepositGenerator k : region.getDeposits())
{
for(int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++)
{
generate(k, terrain, ro, x, z, false);
}
}
for(IrisDepositGenerator k : biome.getDeposits())
{
for(int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++)
{
generate(k, terrain, ro, x, z, false);
}
}
}
public void generate(IrisDepositGenerator k, Hunk<BlockData> data, RNG rng, int cx, int cz, boolean safe)
{
generate(k, data, rng, cx, cz, safe, null);
}
public void generate(IrisDepositGenerator k, Hunk<BlockData> data, RNG rng, int cx, int cz, boolean safe, HeightMap he)
{
for(int l = 0; l < rng.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++)
{
IrisObject clump = k.getClump(rng, getData());
int af = (int) Math.ceil(clump.getW() / 2D);
int bf = (int) Math.floor(16D - (clump.getW() / 2D));
if(af > bf || af < 0 || bf > 15 || af > 15 || bf < 0)
{
af = 6;
bf = 9;
}
int x = rng.i(af, bf);
int z = rng.i(af, bf);
int height = (he != null ? he.getHeight((cx << 4) + x, (cz << 4) + z) : (int) (Math.round(
getComplex().getHeightStream().get((cx << 4) + x, (cz << 4) + z)
))) - 7;
if(height <= 0)
{
return;
}
int i = Math.max(0, k.getMinHeight());
int a = Math.min(height, Math.min(256, k.getMaxHeight()));
if(i >= a)
{
return;
}
int h = rng.i(i, a);
if(h > k.getMaxHeight() || h < k.getMinHeight() || h > height - 2)
{
return;
}
for(BlockVector j : clump.getBlocks().keySet())
{
int nx = j.getBlockX() + x;
int ny = j.getBlockY() + h;
int nz = j.getBlockZ() + z;
if(ny > height || nx > 15 || nx < 0 || ny > 255 || ny < 0 || nz < 0 || nz > 15)
{
continue;
}
boolean allow = false;
BlockData b = data.get(nx, ny, nz);
if(b != null) {
for (BlockData f : getDimension().getRockPalette().getBlockData(getData())) {
if (f.getMaterial().equals(b.getMaterial())) {
allow = true;
break;
}
}
}
if(allow)
{
data.set(nx, ny, nz, clump.getBlocks().get(j));
}
}
}
}
}

View File

@@ -0,0 +1,538 @@
package com.volmit.iris.generator.modifier;
import com.volmit.iris.object.*;
import com.volmit.iris.util.B;
import com.volmit.iris.util.CaveResult;
import com.volmit.iris.util.RNG;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedModifier;
import com.volmit.iris.scaffold.hunk.Hunk;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Levelled;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.Slab;
public class IrisPostModifier extends EngineAssignedModifier<BlockData> {
private static final BlockData AIR = B.getBlockData("CAVE_AIR");
private static final BlockData WATER = B.getBlockData("WATER");
private final RNG rng;
public IrisPostModifier(Engine engine) {
super(engine, "Post");
rng = new RNG(getEngine().getWorld().getSeed()+12938).nextParallelRNG(28348777);
}
@Override
public void onModify(int x, int z, Hunk<BlockData> output) {
for(int i = 0; i < output.getWidth(); i++)
{
for(int j = 0; j < output.getDepth(); j++)
{
post(i, j, output, i+x, j+z);
}
}
}
private void post(int currentPostX, int currentPostZ, Hunk<BlockData> currentData, int x, int z) {
int h = getFramework().getEngineParallax().trueHeight(x, z);
int ha = getFramework().getEngineParallax().trueHeight(x + 1, z);
int hb = getFramework().getEngineParallax().trueHeight(x, z + 1);
int hc = getFramework().getEngineParallax().trueHeight(x - 1, z);
int hd = getFramework().getEngineParallax().trueHeight(x, z - 1);
// Floating Nibs
int g = 0;
if(h < 1)
{
return;
}
g += ha < h - 1 ? 1 : 0;
g += hb < h - 1 ? 1 : 0;
g += hc < h - 1 ? 1 : 0;
g += hd < h - 1 ? 1 : 0;
if(g == 4 && isAir(x, h - 1, z, currentPostX, currentPostZ, currentData))
{
setPostBlock(x, h, z, AIR, currentPostX, currentPostZ, currentData);
for(int i = h - 1; i > 0; i--)
{
if(!isAir(x, i, z, currentPostX, currentPostZ, currentData))
{
h = i;
break;
}
}
}
// Nibs
g = 0;
g += ha == h - 1 ? 1 : 0;
g += hb == h - 1 ? 1 : 0;
g += hc == h - 1 ? 1 : 0;
g += hd == h - 1 ? 1 : 0;
if(g >= 4)
{
BlockData bc = getPostBlock(x, h, z, currentPostX, currentPostZ, currentData);
BlockData b = getPostBlock(x, h + 1, z, currentPostX, currentPostZ, currentData);
Material m = bc.getMaterial();
if((b.getMaterial().isOccluding() && b.getMaterial().isSolid()))
{
if(m.isSolid())
{
setPostBlock(x, h, z, b, currentPostX, currentPostZ, currentData);
h--;
}
}
}
else
{
// Potholes
g = 0;
g += ha == h + 1 ? 1 : 0;
g += hb == h + 1 ? 1 : 0;
g += hc == h + 1 ? 1 : 0;
g += hd == h + 1 ? 1 : 0;
if(g >= 4)
{
BlockData ba = getPostBlock(x, ha, z, currentPostX, currentPostZ, currentData);
BlockData bb = getPostBlock(x, hb, z, currentPostX, currentPostZ, currentData);
BlockData bc = getPostBlock(x, hc, z, currentPostX, currentPostZ, currentData);
BlockData bd = getPostBlock(x, hd, z, currentPostX, currentPostZ, currentData);
g = 0;
g = B.isSolid(ba) ? g + 1 : g;
g = B.isSolid(bb) ? g + 1 : g;
g = B.isSolid(bc) ? g + 1 : g;
g = B.isSolid(bd) ? g + 1 : g;
if(g >= 3)
{
setPostBlock(x, h + 1, z, getPostBlock(x, h, z, currentPostX, currentPostZ, currentData), currentPostX, currentPostZ, currentData);
h++;
}
}
}
// Wall Patcher
IrisBiome biome = getComplex().getTrueBiomeStream().get(x,z);
if(getDimension().isPostProcessingWalls())
{
if(!biome.getWall().getPalette().isEmpty())
{
if(ha < h - 2 || hb < h - 2 || hc < h - 2 || hd < h - 2)
{
boolean brokeGround = false;
int max = Math.abs(Math.max(h - ha, Math.max(h - hb, Math.max(h - hc, h - hd))));
for(int i = h; i > h - max; i--)
{
BlockData d = biome.getWall().get(rng, x + i, i + h, z + i, getData());
if(d != null)
{
if(isAirOrWater(x, i, z, currentPostX, currentPostZ, currentData))
{
if(brokeGround)
{
break;
}
continue;
}
setPostBlock(x, i, z, d, currentPostX, currentPostZ, currentData);
brokeGround = true;
}
}
}
}
}
// Slab
if(getDimension().isPostProcessingSlabs())
{
//@builder
if((ha == h + 1 && isSolidNonSlab(x + 1, ha, z, currentPostX, currentPostZ, currentData))
|| (hb == h + 1 && isSolidNonSlab(x, hb, z + 1, currentPostX, currentPostZ, currentData))
|| (hc == h + 1 && isSolidNonSlab(x - 1, hc, z, currentPostX, currentPostZ, currentData))
|| (hd == h + 1 && isSolidNonSlab(x, hd, z - 1, currentPostX, currentPostZ, currentData)))
//@done
{
BlockData d = biome.getSlab().get(rng, x, h, z, getData());
if(d != null)
{
boolean cancel = false;
if(B.isAir(d))
{
cancel = true;
}
if(d.getMaterial().equals(Material.SNOW) && h + 1 <= getDimension().getFluidHeight())
{
cancel = true;
}
if(isSnowLayer(x, h, z, currentPostX, currentPostZ, currentData))
{
cancel = true;
}
if(!cancel && isAirOrWater(x, h + 1, z, currentPostX, currentPostZ, currentData))
{
setPostBlock(x, h + 1, z, d, currentPostX, currentPostZ, currentData);
h++;
}
}
}
}
// Waterlogging
BlockData b = getPostBlock(x, h, z, currentPostX, currentPostZ, currentData);
if(b instanceof Waterlogged)
{
Waterlogged ww = (Waterlogged) b;
boolean w = false;
if(isWaterOrWaterlogged(x, h + 1, z, currentPostX, currentPostZ, currentData))
{
w = true;
}
else if((isWaterOrWaterlogged(x + 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x - 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z + 1, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z - 1, currentPostX, currentPostZ, currentData)))
{
w = true;
}
if(w != ww.isWaterlogged())
{
ww.setWaterlogged(w);
setPostBlock(x, h, z, b, currentPostX, currentPostZ, currentData);
}
}
else if(b.getMaterial().equals(Material.AIR) && h <= getDimension().getFluidHeight())
{
if((isWaterOrWaterlogged(x + 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x - 1, h, z, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z + 1, currentPostX, currentPostZ, currentData) || isWaterOrWaterlogged(x, h, z - 1, currentPostX, currentPostZ, currentData)))
{
setPostBlock(x, h, z, WATER, currentPostX, currentPostZ, currentData);
}
}
// Foliage
b = getPostBlock(x, h + 1, z, currentPostX, currentPostZ, currentData);
if(B.isFoliage(b) || b.getMaterial().equals(Material.DEAD_BUSH))
{
Material onto = getPostBlock(x, h, z, currentPostX, currentPostZ, currentData).getMaterial();
if(!B.canPlaceOnto(b.getMaterial(), onto))
{
setPostBlock(x, h + 1, z, AIR, currentPostX, currentPostZ, currentData);
}
}
if(getDimension().isPostProcessCaves())
{
IrisBiome cave = getComplex().getCaveBiomeStream().get(x, z);
if(cave != null)
{
for(CaveResult i : ((IrisCaveModifier)getFramework().getCaveModifier()).genCaves(x, z, 0, 0, null))
{
if(i.getCeiling() >= currentData.getMax2DParallelism() || i.getFloor() < 0)
{
continue;
}
int f = i.getFloor();
int fa = nearestCaveFloor(f, x + 1, z, currentPostX, currentPostZ, currentData);
int fb = nearestCaveFloor(f, x, z + 1, currentPostX, currentPostZ, currentData);
int fc = nearestCaveFloor(f, x - 1, z, currentPostX, currentPostZ, currentData);
int fd = nearestCaveFloor(f, x, z - 1, currentPostX, currentPostZ, currentData);
int c = i.getCeiling();
int ca = nearestCaveCeiling(c, x + 1, z, currentPostX, currentPostZ, currentData);
int cb = nearestCaveCeiling(c, x, z + 1, currentPostX, currentPostZ, currentData);
int cc = nearestCaveCeiling(c, x - 1, z, currentPostX, currentPostZ, currentData);
int cd = nearestCaveCeiling(c, x, z - 1, currentPostX, currentPostZ, currentData);
// Cave Nibs
g = 0;
g += fa == f - 1 ? 1 : 0;
g += fb == f - 1 ? 1 : 0;
g += fc == f - 1 ? 1 : 0;
g += fd == f - 1 ? 1 : 0;
if(g >= 4)
{
BlockData bc = getPostBlock(x, f, z, currentPostX, currentPostZ, currentData);
b = getPostBlock(x, f + 1, z, currentPostX, currentPostZ, currentData);
Material m = bc.getMaterial();
if(m.isSolid())
{
setPostBlock(x, f, z, b, currentPostX, currentPostZ, currentData);
h--;
}
}
else
{
// Cave Potholes
g = 0;
g += fa == f + 1 ? 1 : 0;
g += fb == f + 1 ? 1 : 0;
g += fc == f + 1 ? 1 : 0;
g += fd == f + 1 ? 1 : 0;
if(g >= 4)
{
BlockData ba = getPostBlock(x, fa, z, currentPostX, currentPostZ, currentData);
BlockData bb = getPostBlock(x, fb, z, currentPostX, currentPostZ, currentData);
BlockData bc = getPostBlock(x, fc, z, currentPostX, currentPostZ, currentData);
BlockData bd = getPostBlock(x, fd, z, currentPostX, currentPostZ, currentData);
g = 0;
g = B.isSolid(ba) ? g + 1 : g;
g = B.isSolid(bb) ? g + 1 : g;
g = B.isSolid(bc) ? g + 1 : g;
g = B.isSolid(bd) ? g + 1 : g;
if(g >= 4)
{
setPostBlock(x, f + 1, z, getPostBlock(x, f, z, currentPostX, currentPostZ, currentData), currentPostX, currentPostZ, currentData);
h++;
}
}
}
if(getDimension().isPostProcessingSlabs())
{
//@builder
if((fa == f + 1 && isSolidNonSlab(x + 1, fa, z, currentPostX, currentPostZ, currentData))
|| (fb == f + 1 && isSolidNonSlab(x, fb, z + 1, currentPostX, currentPostZ, currentData))
|| (fc == f + 1 && isSolidNonSlab(x - 1, fc, z, currentPostX, currentPostZ, currentData))
|| (fd == f + 1 && isSolidNonSlab(x, fd, z - 1, currentPostX, currentPostZ, currentData)))
//@done
{
BlockData d = cave.getSlab().get(rng, x, f, z, getData());
if(d != null)
{
boolean cancel = false;
if(B.isAir(d))
{
cancel = true;
}
if(d.getMaterial().equals(Material.SNOW) && f + 1 <= getDimension().getFluidHeight())
{
cancel = true;
}
if(isSnowLayer(x, f, z, currentPostX, currentPostZ, currentData))
{
cancel = true;
}
if(!cancel && isAirOrWater(x, f + 1, z, currentPostX, currentPostZ, currentData))
{
setPostBlock(x, f + 1, z, d, currentPostX, currentPostZ, currentData);
}
}
}
//@builder
if((ca == c - 1 && isSolidNonSlab(x + 1, ca, z, currentPostX, currentPostZ, currentData))
|| (cb == c - 1 && isSolidNonSlab(x, cb, z + 1, currentPostX, currentPostZ, currentData))
|| (cc == c - 1 && isSolidNonSlab(x - 1, cc, z, currentPostX, currentPostZ, currentData))
|| (cd == c - 1 && isSolidNonSlab(x, cd, z - 1, currentPostX, currentPostZ, currentData)))
//@done
{
BlockData d = cave.getSlab().get(rng, x, c, z, getData());
if(d != null)
{
boolean cancel = false;
if(B.isAir(d))
{
cancel = true;
}
if(!(d instanceof Slab))
{
cancel = true;
}
if(isSnowLayer(x, c, z, currentPostX, currentPostZ, currentData))
{
cancel = true;
}
if(!cancel && isAirOrWater(x, c, z, currentPostX, currentPostZ, currentData))
{
Slab slab = (Slab) d.clone();
slab.setType(Slab.Type.TOP);
setPostBlock(x, c, z, slab, currentPostX, currentPostZ, currentData);
}
}
}
}
}
}
}
}
private int nearestCaveFloor(int floor, int x, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
if(floor >= currentData.getHeight())
{
return currentData.getHeight()-1;
}
if(B.isAir(getPostBlock(x, floor, z, currentPostX, currentPostZ, currentData)))
{
if(B.isAir(getPostBlock(x, floor - 1, z, currentPostX, currentPostZ, currentData)))
{
return floor - 2;
}
return floor - 1;
}
else
{
if(!B.isAir(getPostBlock(x, floor + 1, z, currentPostX, currentPostZ, currentData)))
{
if(!B.isAir(getPostBlock(x, floor + 2, z, currentPostX, currentPostZ, currentData)))
{
return floor + 2;
}
return floor + 1;
}
return floor;
}
}
private int nearestCaveCeiling(int ceiling, int x, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
if(ceiling >= currentData.getHeight())
{
return currentData.getHeight()-1;
}
if(B.isAir(getPostBlock(x, ceiling, z, currentPostX, currentPostZ, currentData)))
{
if(B.isAir(getPostBlock(x, ceiling + 1, z, currentPostX, currentPostZ, currentData)))
{
return ceiling + 2;
}
return ceiling + 1;
}
else
{
if(!B.isAir(getPostBlock(x, ceiling - 1, z, currentPostX, currentPostZ, currentData)))
{
if(!B.isAir(getPostBlock(x, ceiling - 2, z, currentPostX, currentPostZ, currentData)))
{
return ceiling - 2;
}
return ceiling - 1;
}
return ceiling;
}
}
public boolean isAir(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().equals(Material.AIR) || d.getMaterial().equals(Material.CAVE_AIR);
}
public boolean hasGravity(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().equals(Material.SAND) || d.getMaterial().equals(Material.RED_SAND) || d.getMaterial().equals(Material.BLACK_CONCRETE_POWDER) || d.getMaterial().equals(Material.BLUE_CONCRETE_POWDER) || d.getMaterial().equals(Material.BROWN_CONCRETE_POWDER) || d.getMaterial().equals(Material.CYAN_CONCRETE_POWDER) || d.getMaterial().equals(Material.GRAY_CONCRETE_POWDER) || d.getMaterial().equals(Material.GREEN_CONCRETE_POWDER) || d.getMaterial().equals(Material.LIGHT_BLUE_CONCRETE_POWDER) || d.getMaterial().equals(Material.LIGHT_GRAY_CONCRETE_POWDER) || d.getMaterial().equals(Material.LIME_CONCRETE_POWDER) || d.getMaterial().equals(Material.MAGENTA_CONCRETE_POWDER) || d.getMaterial().equals(Material.ORANGE_CONCRETE_POWDER) || d.getMaterial().equals(Material.PINK_CONCRETE_POWDER) || d.getMaterial().equals(Material.PURPLE_CONCRETE_POWDER) || d.getMaterial().equals(Material.RED_CONCRETE_POWDER) || d.getMaterial().equals(Material.WHITE_CONCRETE_POWDER) || d.getMaterial().equals(Material.YELLOW_CONCRETE_POWDER);
}
public boolean isSolid(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().isSolid();
}
public boolean isSolidNonSlab(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().isSolid() && !(d instanceof Slab);
}
public boolean isAirOrWater(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().equals(Material.WATER) || d.getMaterial().equals(Material.AIR) || d.getMaterial().equals(Material.CAVE_AIR);
}
public boolean isSlab(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d instanceof Slab;
}
public boolean isSnowLayer(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().equals(Material.SNOW);
}
public boolean isWater(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().equals(Material.WATER);
}
public boolean isWaterOrWaterlogged(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d.getMaterial().equals(Material.WATER) || (d instanceof Waterlogged && ((Waterlogged) d).isWaterlogged());
}
public boolean isLiquid(int x, int y, int z, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
BlockData d = getPostBlock(x, y, z, currentPostX, currentPostZ, currentData);
return d instanceof Levelled;
}
public void setPostBlock(int x, int y, int z, BlockData d, int currentPostX, int currentPostZ, Hunk<BlockData> currentData)
{
if(y < currentData.getHeight())
{
currentData.set(x & 15, y, z & 15, d);
}
}
public BlockData getPostBlock(int x, int y, int z, int cpx, int cpz, Hunk<BlockData> h)
{
BlockData b = h.getClosest(x & 15, y, z & 15);
return b == null ? AIR : b;
}
}

View File

@@ -0,0 +1,290 @@
package com.volmit.iris.generator.modifier;
import com.volmit.iris.generator.noise.CNG;
import com.volmit.iris.object.NoiseStyle;
import com.volmit.iris.util.*;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedModifier;
import com.volmit.iris.scaffold.hunk.Hunk;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
public class IrisRavineModifier extends EngineAssignedModifier<BlockData> {
private static final BlockData CAVE_AIR = B.get("CAVE_AIR");
private static final BlockData LAVA = B.get("LAVA");
private CNG cng;
private RNG rng;
public IrisRavineModifier(Engine engine) {
super(engine, "Ravine");
rng = new RNG(getEngine().getWorld().getSeed()).nextParallelRNG(29596878);
cng = NoiseStyle.IRIS_THICK.create(rng);
}
@Override
public void onModify(int x, int z, Hunk<BlockData> output) {
generateRavines(rng, Math.floorDiv(x, 16), Math.floorDiv(z, 16), output);
}
private void set(Hunk<BlockData> pos, int x, int y, int z, BlockData b)
{
pos.set(x, y, z, b);
}
private BlockData get(Hunk<BlockData> pos, int x, int y, int z)
{
BlockData bb = pos.get(x, y, z);
if(bb == null)
{
bb = CAVE_AIR;
}
return bb;
}
private BlockData getSurfaceBlock(int n6, int i, RNG rmg)
{
return getComplex().getTrueBiomeStream().get(n6,i).getSurfaceBlock(n6, i, rmg, getData());
}
private float[] ravineCache = new float[1024];
private void doRavine(long seed, int tx, int tz, ChunkPosition pos, double sx, double sy, double sz, float f, float f2, float f3, int n3, int n4, double d4, RNG bbx, Hunk<BlockData> terrain)
{
int n5;
RNG random = new RNG(seed);
double x = tx * 16 + 8;
double z = tz * 16 + 8;
float f4 = 0.0f;
float f5 = 0.0f;
if(n4 <= 0)
{
n5 = 8 * 16 - 16;
n4 = n5 - random.nextInt(n5 / 4);
}
n5 = 0;
if(n3 == -1)
{
n3 = n4 / 2;
n5 = 1;
}
float f6 = 1.0f;
for(int i = 0; i < 256; ++i)
{
if(i == 0 || random.nextInt(getDimension().getRavineRibRarity()) == 0)
{
f6 = 1.0f + random.nextFloat() * random.nextFloat() * 1.0f;
}
this.ravineCache[i] = f6 * f6;
}
while(n3 < n4)
{
double d7 = 1.5 + (double) (MathHelper.sin((float) n3 * 3.1415927f / (float) n4) * f * 1.0f);
double d8 = d7 * d4;
d7 *= (double) random.nextFloat() * 0.25 + 0.75;
d8 *= (double) random.nextFloat() * 0.25 + 0.75;
float f7 = MathHelper.cos(f3);
float f8 = MathHelper.sin(f3);
sx = sx + (double) (MathHelper.cos(f2) * f7);
sy += f8;
sz += MathHelper.sin(f2) * f7;
f3 *= 0.7f;
f3 += f5 * 0.05f;
f2 += f4 * 0.05f;
f5 *= 0.8f;
f4 *= 0.5f;
f5 += (random.nextFloat() - random.nextFloat()) * random.nextFloat() * 2.0f;
f4 += (random.nextFloat() - random.nextFloat()) * random.nextFloat() * 4.0f;
if(n5 != 0 || random.nextInt(4) != 0)
{
double d9 = sx - x;
double d10 = sz - z;
double d11 = n4 - n3;
double d12 = f + 2.0f + 16.0f;
if(d9 * d9 + d10 * d10 - d11 * d11 > d12 * d12)
{
return;
}
if(sx >= x - 16.0 - d7 * 2.0 && sz >= z - 16.0 - d7 * 2.0 && sx <= x + 16.0 + d7 * 2.0 && sz <= z + 16.0 + d7 * 2.0)
{
int n6;
int n7 = MathHelper.floor(sx - d7) - tx * 16 - 1;
int n8 = MathHelper.floor(sx + d7) - tx * 16 + 1;
int n9 = MathHelper.floor(sy - d8) - 1;
int n10 = MathHelper.floor(sy + d8) + 1;
int n11 = MathHelper.floor(sz - d7) - tz * 16 - 1;
int n12 = MathHelper.floor(sz + d7) - tz * 16 + 1;
if(n7 < 0)
{
n7 = 0;
}
if(n8 > 16)
{
n8 = 16;
}
if(n9 < 1)
{
n9 = 1;
}
if(n10 > 248)
{
n10 = 248;
}
if(n11 < 0)
{
n11 = 0;
}
if(n12 > 16)
{
n12 = 16;
}
boolean bl = false;
for(int i = n7; !bl && i < n8; ++i)
{
for(n6 = n11; !bl && n6 < n12; ++n6)
{
for(int j = n10 + 1; !bl && j >= n9 - 1; --j)
{
if(j < 0 || j >= 256)
{
continue;
}
BlockData bb = get(terrain, i, j, n6);
if(B.isWater(bb))
{
bl = true;
}
if(j == n9 - 1 || i == n7 || i == n8 - 1 || n6 == n11 || n6 == n12 - 1)
{
continue;
}
j = n9;
}
}
}
if(!bl) {
BlockPosition bps = new BlockPosition(0, 0, 0);
for (n6 = n7; n6 < n8; ++n6) {
double d13 = ((double) (n6 + tx * 16) + 0.5 - sx) / d7;
for (int i = n11; i < n12; ++i) {
double d14 = ((double) (i + tz * 16) + 0.5 - sz) / d7;
boolean bl2 = false;
if (d13 * d13 + d14 * d14 >= 1.0) {
continue;
}
for (int j = n10; j > n9; --j) {
double d15 = ((double) (j - 1) + 0.5 - sy) / d8;
if ((d13 * d13 + d14 * d14) * (double) this.ravineCache[j - 1] + d15 * d15 / 6.0 >= 1.0) {
continue;
}
BlockData blockData = get(terrain, n6, j, i);
if (isSurface(blockData)) {
bl2 = true;
}
if (j - 1 < 10) {
set(terrain, n6, j, i, LAVA);
continue;
}
set(terrain, n6, j, i, CAVE_AIR);
if (!bl2 || !isDirt(get(terrain, n6, j - 1, i))) {
continue;
}
cSet(bps, n6 + tx * 16, 0, i + tz * 16);
set(terrain, n6, j - 1, i, getSurfaceBlock(n6, i, rng));
}
}
}
if (n5 != 0)
{
break;
}
}
}
}
++n3;
}
}
private BlockPosition cSet(BlockPosition bb, double var0, double var2, double var4)
{
bb.setX(MathHelper.floor((double) var0));
bb.setY(MathHelper.floor((double) var2));
bb.setZ(MathHelper.floor((double) var4));
return bb;
}
private boolean isDirt(BlockData d)
{
//@builder
Material m = d.getMaterial();
return m.equals(Material.DIRT) ||
m.equals(Material.COARSE_DIRT) ||
m.equals(Material.SAND);
//@done
}
private boolean isSurface(BlockData d)
{
//@builder
Material m = d.getMaterial();
return m.equals(Material.GRASS_BLOCK) ||
m.equals(Material.DIRT) ||
m.equals(Material.COARSE_DIRT) ||
m.equals(Material.PODZOL) ||
m.equals(Material.SAND);
//@done
}
public void genRavines(int n, int n2, ChunkPosition chunkSnapshot, RNG bbb, Hunk<BlockData> terrain)
{
RNG b = this.rng.nextParallelRNG(21949666);
RNG bx = this.rng.nextParallelRNG(6676121);
long l = b.nextLong();
long l2 = b.nextLong();
for(int i = n - 8; i <= n + 8; ++i)
{
for(int j = n2 - 8; j <= n2 + 8; ++j)
{
long l3 = (long) i * l;
long l4 = (long) j * l2;
bx = this.rng.nextParallelRNG((int) (l3 ^ l4 ^ 6676121));
doRavines(i, j, n, n2, chunkSnapshot, bx, terrain);
}
}
}
private void doRavines(int tx, int tz, int sx, int sz, ChunkPosition chunkSnapshot, RNG b, Hunk<BlockData> terrain)
{
if(b.nextInt(getDimension().getRavineRarity()) != 0)
{
return;
}
double x = tx * 16 + b.nextInt(16);
double d2 = b.nextInt(b.nextInt(40) + 8) + 20;
double z = tz * 16 + b.nextInt(16);
int n5 = 1;
for(int i = 0; i < n5; ++i)
{
float f = b.nextFloat() * 3.1415927f * 2.0f;
float f2 = (b.nextFloat() - 0.5f) * 2.0f / 8.0f;
float f3 = (b.nextFloat() * 2.0f + b.nextFloat()) * 2.0f;
this.doRavine(b.nextLong(), sx, sz, chunkSnapshot, x, d2, z, f3, f, f2, 0, 0, 3.0, b, terrain);
}
}
public void generateRavines(RNG nextParallelRNG, int x, int z, Hunk<BlockData> terrain)
{
genRavines(x, z, new ChunkPosition(x, z), nextParallelRNG.nextParallelRNG(x).nextParallelRNG(z), terrain);
}
}

View File

@@ -0,0 +1,419 @@
package com.volmit.iris.generator.noise;
import java.util.List;
import com.volmit.iris.Iris;
import com.volmit.iris.scaffold.stream.ProceduralStream;
import com.volmit.iris.scaffold.stream.sources.CNGStream;
import com.volmit.iris.scaffold.stream.arithmetic.FittedStream;
import com.volmit.iris.util.IRare;
import com.volmit.iris.util.IrisInterpolation;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.NoiseInjector;
import com.volmit.iris.util.RNG;
import lombok.Data;
@Data
public class CNG
{
public static long hits = 0;
public static long creates = 0;
public static final NoiseInjector ADD = (s, v) -> new double[] {s + v, 1};
public static final NoiseInjector SRC_SUBTRACT = (s, v) -> new double[] {s - v < 0 ? 0 : s - v, -1};
public static final NoiseInjector DST_SUBTRACT = (s, v) -> new double[] {v - s < 0 ? 0 : s - v, -1};
public static final NoiseInjector MULTIPLY = (s, v) -> new double[] {s * v, 0};
public static final NoiseInjector MAX = (s, v) -> new double[] {Math.max(s, v), 0};
public static final NoiseInjector MIN = (s, v) -> new double[] {Math.min(s, v), 0};
public static final NoiseInjector SRC_MOD = (s, v) -> new double[] {s % v, 0};
public static final NoiseInjector SRC_POW = (s, v) -> new double[] {Math.pow(s, v), 0};
public static final NoiseInjector DST_MOD = (s, v) -> new double[] {v % s, 0};
public static final NoiseInjector DST_POW = (s, v) -> new double[] {Math.pow(v, s), 0};
private double scale;
private double bakedScale;
private double fscale;
private boolean trueFracturing = false;
private KList<CNG> children;
private CNG fracture;
private NoiseGenerator generator;
private final double opacity;
private NoiseInjector injector;
private RNG rng;
private boolean noscale;
private int oct;
private double patch;
private double up;
private double down;
private double power;
public NoiseGenerator getGen()
{
return generator;
}
public ProceduralStream<Double> stream()
{
return new CNGStream(this);
}
public ProceduralStream<Double> stream(double min, double max)
{
return new FittedStream<Double>(stream(), min, max);
}
public static CNG signature(RNG rng)
{
return signature(rng, NoiseType.SIMPLEX);
}
public static CNG signatureHalf(RNG rng)
{
return signatureHalf(rng, NoiseType.SIMPLEX);
}
public static CNG signatureThick(RNG rng)
{
return signatureThick(rng, NoiseType.SIMPLEX);
}
public static CNG signatureDouble(RNG rng)
{
return signatureDouble(rng, NoiseType.SIMPLEX);
}
public static CNG signatureDouble(RNG rng, NoiseType t)
{
return signatureThick(rng, t).fractureWith(signature(rng.nextParallelRNG(4956)), 93);
}
public static CNG signature(RNG rng, NoiseType t)
{
// @NoArgsConstructor
return new CNG(rng.nextParallelRNG(17), t, 1D, 1).fractureWith(new CNG(rng.nextParallelRNG(18), 1, 1).scale(0.9).fractureWith(new CNG(rng.nextParallelRNG(20), 1, 1).scale(0.21).fractureWith(new CNG(rng.nextParallelRNG(20), 1, 1).scale(0.9), 620), 145), 44).bake();
// @done
}
public static CNG signatureThick(RNG rng, NoiseType t)
{
// @NoArgsConstructor
return new CNG(rng.nextParallelRNG(133), t, 1D, 1).fractureWith(new CNG(rng.nextParallelRNG(18), 1, 1).scale(0.5).fractureWith(new CNG(rng.nextParallelRNG(20), 1, 1).scale(0.11).fractureWith(new CNG(rng.nextParallelRNG(20), 1, 1).scale(0.4), 620), 145), 44).bake();
// @done
}
public static CNG signatureHalf(RNG rng, NoiseType t)
{
// @NoArgsConstructor
return new CNG(rng.nextParallelRNG(127), t, 1D, 1).fractureWith(new CNG(rng.nextParallelRNG(18), 1, 1).scale(0.9).fractureWith(new CNG(rng.nextParallelRNG(20), 1, 1).scale(0.21).fractureWith(new CNG(rng.nextParallelRNG(20), 1, 1).scale(0.9), 420), 99), 22).bake();
// @done
}
public CNG(RNG random)
{
this(random, 1);
}
public CNG(RNG random, int octaves)
{
this(random, 1D, octaves);
}
public CNG(RNG random, double opacity, int octaves)
{
this(random, NoiseType.SIMPLEX, opacity, octaves);
}
public CNG(RNG random, NoiseType t, double opacity, int octaves)
{
creates++;
noscale = t.equals(NoiseType.WHITE);
this.oct = octaves;
this.rng = random;
power = 1;
scale = 1;
patch = 1;
bakedScale = 1;
fscale = 1;
down = 0;
up = 0;
fracture = null;
generator = t.create(random.nextParallelRNG(33).lmax());
this.opacity = opacity;
this.injector = ADD;
if(generator instanceof OctaveNoise)
{
((OctaveNoise) generator).setOctaves(octaves);
}
}
public CNG bake()
{
bakedScale *= scale;
scale = 1;
return this;
}
public CNG child(CNG c)
{
if(children == null)
{
children = new KList<>();
}
children.add(c);
return this;
}
@Deprecated
public RNG nextRNG()
{
return getRNG().nextRNG();
}
public RNG getRNG()
{
return rng;
}
public CNG fractureWith(CNG c, double scale)
{
fracture = c;
fscale = scale;
return this;
}
public CNG scale(double c)
{
scale = c;
return this;
}
public CNG patch(double c)
{
patch = c;
return this;
}
public CNG up(double c)
{
up = c;
return this;
}
public CNG down(double c)
{
down = c;
return this;
}
public CNG injectWith(NoiseInjector i)
{
injector = i;
return this;
}
public <T extends IRare> T fitRarity(KList<T> b, double... dim)
{
if(b.size() == 0)
{
return null;
}
if(b.size() == 1)
{
return b.get(0);
}
KList<T> rarityMapped = new KList<>();
boolean o = false;
int max = 1;
for(T i : b)
{
if(i.getRarity() > max)
{
max = i.getRarity();
}
}
max++;
for(T i : b)
{
for(int j = 0; j < max - i.getRarity(); j++)
{
if(o = !o)
{
rarityMapped.add(i);
}
else
{
rarityMapped.add(0, i);
}
}
}
if(rarityMapped.size() == 1)
{
return rarityMapped.get(0);
}
if(rarityMapped.isEmpty())
{
throw new RuntimeException("BAD RARITY MAP! RELATED TO: " + b.toString(", or possibly "));
}
return fit(rarityMapped, dim);
}
public <T> T fit(T[] v, double... dim)
{
if(v.length == 0)
{
return null;
}
if(v.length == 1)
{
return v[0];
}
return v[fit(0, v.length - 1, dim)];
}
public <T> T fit(List<T> v, double... dim)
{
if(v.size() == 0)
{
return null;
}
if(v.size() == 1)
{
return v.get(0);
}
try
{
return v.get(fit(0, v.size() - 1, dim));
}
catch(Throwable e)
{
Iris.error("Failed to sample noise into array " + v.size() + " nodes");
Iris.error("Noise Source: " + generator.getClass().getSimpleName());
}
return v.get(0);
}
public int fit(int min, int max, double... dim)
{
if(min == max)
{
return min;
}
double noise = noise(dim);
return (int) Math.round(IrisInterpolation.lerp(min, max, noise));
}
public int fit(double min, double max, double... dim)
{
if(min == max)
{
return (int) Math.round(min);
}
double noise = noise(dim);
return (int) Math.round(IrisInterpolation.lerp(min, max, noise));
}
public double fitDouble(double min, double max, double... dim)
{
if(min == max)
{
return min;
}
double noise = noise(dim);
return IrisInterpolation.lerp(min, max, noise);
}
private double getNoise(double... dim)
{
if(isTrueFracturing())
{
if(dim.length == 2)
{
double scale = noscale ? 1 : this.bakedScale * this.scale;
double f1 = noscale ? 0 : (fracture != null ? (fracture.noise(dim[0], dim[1]) - 0.5) * fscale : 0D);
double f2 = noscale ? 0 : (fracture != null ? (fracture.noise(dim[1], dim[0]) - 0.5) * fscale : 0D);
double x = dim[0] + f1;
double y = dim[1] + -f1;
double z = 0D;
return generator.noise(x * scale, y * scale, z * scale) * opacity;
}
else if(dim.length == 3)
{
double scale = noscale ? 1 : this.bakedScale * this.scale;
double f1 = noscale ? 0 : (fracture != null ? (fracture.noise(dim[0], dim[2], dim[1]) - 0.5) * fscale : 0D);
double f2 = noscale ? 0 : (fracture != null ? (fracture.noise(dim[1], dim[0], dim[2]) - 0.5) * fscale : 0D);
double f3 = noscale ? 0 : (fracture != null ? (fracture.noise(dim[2], dim[1], dim[0]) - 0.5) * fscale : 0D);
double x = dim[0] + f1;
double y = dim[1] + f3;
double z = dim[2] + f2;
return generator.noise(x * scale, y * scale, z * scale) * opacity;
}
}
double scale = noscale ? 1 : this.bakedScale * this.scale;
double f = noscale ? 0 : (fracture != null ? (fracture.noise(dim) - 0.5) * fscale : 0D);
double x = dim.length > 0 ? dim[0] + f : 0D;
double y = dim.length > 1 ? dim[1] + -f : 0D;
double z = dim.length > 2 ? dim[2] + -f : 0D;
return generator.noise(x * scale, y * scale, z * scale) * opacity;
}
public double noise(double... dim)
{
double n = getNoise(dim);
n = power != 1D ? (n < 0 ? -Math.pow(Math.abs(n), power) : Math.pow(n, power)) : n;
double m = 1;
hits += oct;
if(children == null)
{
return (n - down + up) * patch;
}
for(CNG i : children)
{
double[] r = injector.combine(n, i.noise(dim));
n = r[0];
m += r[1];
}
return ((n / m) - down + up) * patch;
}
public CNG pow(double power)
{
this.power = power;
return this;
}
public CNG oct(int octaves)
{
oct = octaves;
return this;
}
public double getScale()
{
return scale;
}
}

View File

@@ -0,0 +1,9 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.util.RNG;
@FunctionalInterface
public interface CNGFactory
{
CNG create(RNG seed);
}

View File

@@ -0,0 +1,88 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.util.RNG;
import lombok.Getter;
import lombok.Setter;
public class CellGenerator
{
private FastNoiseDouble fn;
private FastNoiseDouble fd;
private CNG cng;
@Getter
@Setter
private double cellScale;
@Getter
@Setter
private double shuffle;
public CellGenerator(RNG rng)
{
shuffle = 128;
cellScale = 0.73;
cng = CNG.signature(rng.nextParallelRNG(3204));
RNG rx = rng.nextParallelRNG(8735652);
long s = rx.lmax();
fn = new FastNoiseDouble(s);
fn.setNoiseType(FastNoiseDouble.NoiseType.Cellular);
fn.setCellularReturnType(FastNoiseDouble.CellularReturnType.CellValue);
fn.setCellularDistanceFunction(FastNoiseDouble.CellularDistanceFunction.Natural);
fd = new FastNoiseDouble(s);
fd.setNoiseType(FastNoiseDouble.NoiseType.Cellular);
fd.setCellularReturnType(FastNoiseDouble.CellularReturnType.Distance2Sub);
fd.setCellularDistanceFunction(FastNoiseDouble.CellularDistanceFunction.Natural);
}
public double getDistance(double x, double z)
{
return ((fd.GetCellular(((x * cellScale) + (cng.noise(x, z) * shuffle)), ((z * cellScale) + (cng.noise(z, x) * shuffle)))) + 1f) / 2f;
}
public double getDistance(double x, double y, double z)
{
return ((fd.GetCellular(((x * cellScale) + (cng.noise(x, y, z) * shuffle)), ((y * cellScale) + (cng.noise(x, y, z) * shuffle)), ((z * cellScale) + (cng.noise(z, y, x) * shuffle)))) + 1f) / 2f;
}
public double getValue(double x, double z, int possibilities)
{
if(possibilities == 1)
{
return 0;
}
return ((fn.GetCellular(((x * cellScale) + (cng.noise(x, z) * shuffle)), ((z * cellScale) + (cng.noise(z, x) * shuffle))) + 1f) / 2f) * (possibilities - 1);
}
public double getValue(double x, double y, double z, int possibilities)
{
if(possibilities == 1)
{
return 0;
}
return ((fn.GetCellular(((x * cellScale) + (cng.noise(x, z) * shuffle)), ((y * 8 * cellScale) + (cng.noise(x, y * 8) * shuffle)), ((z * cellScale) + (cng.noise(z, x) * shuffle))) + 1f) / 2f) * (possibilities - 1);
}
public int getIndex(double x, double z, int possibilities)
{
if(possibilities == 1)
{
return 0;
}
return (int) Math.round(getValue(x, z, possibilities));
}
public int getIndex(double x, double y, double z, int possibilities)
{
if(possibilities == 1)
{
return 0;
}
return (int) Math.round(getValue(x, y, z, possibilities));
}
}

View File

@@ -0,0 +1,40 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.util.M;
import com.volmit.iris.util.RNG;
public class CellHeightNoise implements NoiseGenerator
{
private final FastNoiseDouble n;
public CellHeightNoise(long seed)
{
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setNoiseType(FastNoiseDouble.NoiseType.Cellular);
n.setCellularReturnType(FastNoiseDouble.CellularReturnType.Distance2Sub);
n.setCellularDistanceFunction(FastNoiseDouble.CellularDistanceFunction.Natural);
}
private double filter(double noise)
{
return M.clip(1D - ((noise / 2D) + 0.5D), 0D, 1D);
}
@Override
public double noise(double x)
{
return filter(n.GetCellular(x, 0));
}
@Override
public double noise(double x, double z)
{
return filter(n.GetCellular(x, z));
}
@Override
public double noise(double x, double y, double z)
{
return filter(n.GetCellular(x, y, z));
}
}

View File

@@ -0,0 +1,34 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.util.RNG;
public class CellularNoise implements NoiseGenerator
{
private final FastNoiseDouble n;
public CellularNoise(long seed)
{
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setNoiseType(FastNoiseDouble.NoiseType.Cellular);
n.setCellularReturnType(FastNoiseDouble.CellularReturnType.CellValue);
n.setCellularDistanceFunction(FastNoiseDouble.CellularDistanceFunction.Natural);
}
@Override
public double noise(double x)
{
return (n.GetCellular(x, 0) / 2D) + 0.5D;
}
@Override
public double noise(double x, double z)
{
return (n.GetCellular(x, z) / 2D) + 0.5D;
}
@Override
public double noise(double x, double y, double z)
{
return (n.GetCellular(x, y, z) / 2D) + 0.5D;
}
}

View File

@@ -0,0 +1,36 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.util.RNG;
public class CubicNoise implements NoiseGenerator
{
private final FastNoiseDouble n;
public CubicNoise(long seed)
{
this.n = new FastNoiseDouble(new RNG(seed).lmax());
}
private double f(double n)
{
return (n / 2D) + 0.5D;
}
@Override
public double noise(double x)
{
return f(n.GetCubic(x, 0));
}
@Override
public double noise(double x, double z)
{
return f(n.GetCubic(x, z));
}
@Override
public double noise(double x, double y, double z)
{
return f(n.GetCubic(x, y, z));
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,27 @@
package com.volmit.iris.generator.noise;
public class FlatNoise implements NoiseGenerator
{
public FlatNoise(long seed)
{
}
@Override
public double noise(double x)
{
return 1D;
}
@Override
public double noise(double x, double z)
{
return 1D;
}
@Override
public double noise(double x, double y, double z)
{
return 1D;
}
}

View File

@@ -0,0 +1,45 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.generator.noise.FastNoiseDouble.FractalType;
import com.volmit.iris.util.RNG;
public class FractalBillowPerlinNoise implements NoiseGenerator, OctaveNoise
{
private final FastNoiseDouble n;
public FractalBillowPerlinNoise(long seed)
{
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setFractalOctaves(1);
n.setFractalType(FractalType.Billow);
}
public double f(double v)
{
return (v / 2D) + 0.5D;
}
@Override
public double noise(double x)
{
return f(n.GetPerlinFractal(x, 0f));
}
@Override
public double noise(double x, double z)
{
return f(n.GetPerlinFractal(x, z));
}
@Override
public double noise(double x, double y, double z)
{
return f(n.GetPerlinFractal(x, y, z));
}
@Override
public void setOctaves(int o)
{
n.setFractalOctaves(o);
}
}

View File

@@ -0,0 +1,45 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.generator.noise.FastNoiseDouble.FractalType;
import com.volmit.iris.util.RNG;
public class FractalBillowSimplexNoise implements NoiseGenerator, OctaveNoise
{
private final FastNoiseDouble n;
public FractalBillowSimplexNoise(long seed)
{
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setFractalOctaves(1);
n.setFractalType(FractalType.Billow);
}
public double f(double v)
{
return (v / 2D) + 0.5D;
}
@Override
public double noise(double x)
{
return f(n.GetSimplexFractal(x, 0d));
}
@Override
public double noise(double x, double z)
{
return f(n.GetSimplexFractal(x, z));
}
@Override
public double noise(double x, double y, double z)
{
return f(n.GetSimplexFractal(x, y, z));
}
@Override
public void setOctaves(int o)
{
n.setFractalOctaves(o);
}
}

View File

@@ -0,0 +1,38 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.generator.noise.FastNoiseDouble.FractalType;
import com.volmit.iris.util.RNG;
public class FractalCubicNoise implements NoiseGenerator
{
private final FastNoiseDouble n;
public FractalCubicNoise(long seed)
{
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setFractalType(FractalType.Billow);
}
private double f(double n)
{
return (n / 2D) + 0.5D;
}
@Override
public double noise(double x)
{
return f(n.GetCubicFractal(x, 0));
}
@Override
public double noise(double x, double z)
{
return f(n.GetCubicFractal(x, z));
}
@Override
public double noise(double x, double y, double z)
{
return f(n.GetCubicFractal(x, y, z));
}
}

View File

@@ -0,0 +1,45 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.generator.noise.FastNoiseDouble.FractalType;
import com.volmit.iris.util.RNG;
public class FractalFBMSimplexNoise implements NoiseGenerator, OctaveNoise
{
private final FastNoiseDouble n;
public FractalFBMSimplexNoise(long seed)
{
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setFractalOctaves(1);
n.setFractalType(FractalType.FBM);
}
public double f(double v)
{
return (v / 2D) + 0.5D;
}
@Override
public double noise(double x)
{
return f(n.GetSimplexFractal(x, 0d));
}
@Override
public double noise(double x, double z)
{
return f(n.GetSimplexFractal(x, z));
}
@Override
public double noise(double x, double y, double z)
{
return f(n.GetSimplexFractal(x, y, z));
}
@Override
public void setOctaves(int o)
{
n.setFractalOctaves(o);
}
}

View File

@@ -0,0 +1,45 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.generator.noise.FastNoiseDouble.FractalType;
import com.volmit.iris.util.RNG;
public class FractalRigidMultiSimplexNoise implements NoiseGenerator, OctaveNoise
{
private final FastNoiseDouble n;
public FractalRigidMultiSimplexNoise(long seed)
{
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setFractalOctaves(1);
n.setFractalType(FractalType.RigidMulti);
}
public double f(double v)
{
return (v / 2D) + 0.5D;
}
@Override
public double noise(double x)
{
return f(n.GetSimplexFractal(x, 0d));
}
@Override
public double noise(double x, double z)
{
return f(n.GetSimplexFractal(x, z));
}
@Override
public double noise(double x, double y, double z)
{
return f(n.GetSimplexFractal(x, y, z));
}
@Override
public void setOctaves(int o)
{
n.setFractalOctaves(o);
}
}

View File

@@ -0,0 +1,39 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.util.RNG;
public class GlobNoise implements NoiseGenerator
{
private final FastNoiseDouble n;
public GlobNoise(long seed)
{
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setNoiseType(FastNoiseDouble.NoiseType.Cellular);
n.setCellularReturnType(FastNoiseDouble.CellularReturnType.Distance2Div);
n.setCellularDistanceFunction(FastNoiseDouble.CellularDistanceFunction.Natural);
}
private double f(double n)
{
return n + 1D;
}
@Override
public double noise(double x)
{
return f(n.GetCellular(x, 0));
}
@Override
public double noise(double x, double z)
{
return f(n.GetCellular(x, z));
}
@Override
public double noise(double x, double y, double z)
{
return f(n.GetCellular(x, y, z));
}
}

View File

@@ -0,0 +1,7 @@
package com.volmit.iris.generator.noise;
@FunctionalInterface
public interface NoiseFactory
{
NoiseGenerator create(long seed);
}

View File

@@ -0,0 +1,10 @@
package com.volmit.iris.generator.noise;
public interface NoiseGenerator
{
public double noise(double x);
public double noise(double x, double z);
public double noise(double x, double y, double z);
}

View File

@@ -0,0 +1,28 @@
package com.volmit.iris.generator.noise;
public enum NoiseType {
WHITE(seed -> new WhiteNoise(seed)),
SIMPLEX(seed -> new SimplexNoise(seed)),
PERLIN(seed -> new PerlinNoise(seed)),
FRACTAL_BILLOW_SIMPLEX(seed -> new FractalBillowSimplexNoise(seed)),
FRACTAL_BILLOW_PERLIN(seed -> new FractalBillowPerlinNoise(seed)),
FRACTAL_FBM_SIMPLEX(seed -> new FractalFBMSimplexNoise(seed)),
FRACTAL_RIGID_MULTI_SIMPLEX(seed -> new FractalRigidMultiSimplexNoise(seed)),
FLAT(seed -> new FlatNoise(seed)),
CELLULAR(seed -> new CellularNoise(seed)),
GLOB(seed -> new GlobNoise(seed)),
CUBIC(seed -> new CubicNoise(seed)),
FRACTAL_CUBIC(seed -> new FractalCubicNoise(seed)),
CELLULAR_HEIGHT(seed -> new CellHeightNoise(seed)),
VASCULAR(seed -> new VascularNoise(seed));
private NoiseFactory f;
private NoiseType(NoiseFactory f) {
this.f = f;
}
public NoiseGenerator create(long seed) {
return f.create(seed);
}
}

View File

@@ -0,0 +1,6 @@
package com.volmit.iris.generator.noise;
public interface OctaveNoise
{
public void setOctaves(int o);
}

View File

@@ -0,0 +1,89 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.util.RNG;
public class PerlinNoise implements NoiseGenerator, OctaveNoise
{
private final FastNoiseDouble n;
private int octaves;
public PerlinNoise(long seed)
{
this.n = new FastNoiseDouble(new RNG(seed).lmax());
octaves = 1;
}
public double f(double v)
{
return (v / 2D) + 0.5D;
}
@Override
public double noise(double x)
{
if(octaves <= 1)
{
return f(n.GetPerlin(x, 0));
}
double f = 1;
double m = 0;
double v = 0;
for(int i = 0; i < octaves; i++)
{
v += n.GetPerlin((x * (f == 1 ? f++ : (f *= 2))), 0) * f;
m += f;
}
return f(v / m);
}
@Override
public double noise(double x, double z)
{
if(octaves <= 1)
{
return f(n.GetPerlin(x, z));
}
double f = 1;
double m = 0;
double v = 0;
for(int i = 0; i < octaves; i++)
{
f = f == 1 ? f + 1 : f * 2;
v += n.GetPerlin((x * f), (z * f)) * f;
m += f;
}
return f(v / m);
}
@Override
public double noise(double x, double y, double z)
{
if(octaves <= 1)
{
return f(n.GetPerlin(x, y, z));
}
double f = 1;
double m = 0;
double v = 0;
for(int i = 0; i < octaves; i++)
{
f = f == 1 ? f + 1 : f * 2;
v += n.GetPerlin((x * f), (y * f), (z * f)) * f;
m += f;
}
return f(v / m);
}
@Override
public void setOctaves(int o)
{
octaves = o;
}
}

View File

@@ -0,0 +1,67 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.util.IRare;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.RNG;
public class RarityCellGenerator<T extends IRare> extends CellGenerator
{
public RarityCellGenerator(RNG rng)
{
super(rng);
}
public T get(double x, double z, KList<T> b)
{
if(b.size() == 0)
{
return null;
}
if(b.size() == 1)
{
return b.get(0);
}
KList<T> rarityMapped = new KList<>();
boolean o = false;
int max = 1;
for(T i : b)
{
if(i.getRarity() > max)
{
max = i.getRarity();
}
}
max++;
for(T i : b)
{
for(int j = 0; j < max - i.getRarity(); j++)
{
if(o = !o)
{
rarityMapped.add(i);
}
else
{
rarityMapped.add(0, i);
}
}
}
if(rarityMapped.size() == 1)
{
return rarityMapped.get(0);
}
if(rarityMapped.isEmpty())
{
throw new RuntimeException("BAD RARITY MAP! RELATED TO: " + b.toString(", or possibly "));
}
return rarityMapped.get(getIndex(x, z, rarityMapped.size()));
}
}

View File

@@ -0,0 +1,89 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.util.RNG;
public class SimplexNoise implements NoiseGenerator, OctaveNoise
{
private final FastNoiseDouble n;
private int octaves;
public SimplexNoise(long seed)
{
this.n = new FastNoiseDouble(new RNG(seed).lmax());
octaves = 1;
}
public double f(double v)
{
return (v / 2D) + 0.5D;
}
@Override
public double noise(double x)
{
if(octaves <= 1)
{
return f(n.GetSimplex(x, 0d));
}
double f = 1;
double m = 0;
double v = 0;
for(int i = 0; i < octaves; i++)
{
v += n.GetSimplex((x * (f == 1 ? f++ : (f *= 2))), 0d) * f;
m += f;
}
return f(v / m);
}
@Override
public double noise(double x, double z)
{
if(octaves <= 1)
{
return f(n.GetSimplex(x, z));
}
double f = 1;
double m = 0;
double v = 0;
for(int i = 0; i < octaves; i++)
{
f = f == 1 ? f + 1 : f * 2;
v += n.GetSimplex((x * f), (z * f)) * f;
m += f;
}
return f(v / m);
}
@Override
public double noise(double x, double y, double z)
{
if(octaves <= 1)
{
return f(n.GetSimplex(x, y, z));
}
double f = 1;
double m = 0;
double v = 0;
for(int i = 0; i < octaves; i++)
{
f = f == 1 ? f + 1 : f * 2;
v += n.GetSimplex((x * f), (y * f), (z * f)) * f;
m += f;
}
return f(v / m);
}
@Override
public void setOctaves(int o)
{
octaves = o;
}
}

View File

@@ -0,0 +1,40 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.util.M;
import com.volmit.iris.util.RNG;
public class VascularNoise implements NoiseGenerator
{
private final FastNoiseDouble n;
public VascularNoise(long seed)
{
this.n = new FastNoiseDouble(new RNG(seed).lmax());
n.setNoiseType(FastNoiseDouble.NoiseType.Cellular);
n.setCellularReturnType(FastNoiseDouble.CellularReturnType.Distance2Sub);
n.setCellularDistanceFunction(FastNoiseDouble.CellularDistanceFunction.Natural);
}
private double filter(double noise)
{
return M.clip((noise / 2D) + 0.5D, 0D, 1D);
}
@Override
public double noise(double x)
{
return filter(n.GetCellular(x, 0));
}
@Override
public double noise(double x, double z)
{
return filter(n.GetCellular(x, z));
}
@Override
public double noise(double x, double y, double z)
{
return filter(n.GetCellular(x, y, z));
}
}

View File

@@ -0,0 +1,36 @@
package com.volmit.iris.generator.noise;
import com.volmit.iris.util.RNG;
public class WhiteNoise implements NoiseGenerator
{
private final FastNoise n;
public WhiteNoise(long seed)
{
n = new FastNoise(new RNG(seed).imax());
}
private double f(double m)
{
return (m % 8192) * 1024;
}
@Override
public double noise(double x)
{
return (n.GetWhiteNoise(f(x), 0d) / 2D) + 0.5D;
}
@Override
public double noise(double x, double z)
{
return (n.GetWhiteNoise(f(x), f(z)) / 2D) + 0.5D;
}
@Override
public double noise(double x, double y, double z)
{
return (n.GetWhiteNoise(f(x), f(y), f(z)) / 2D) + 0.5D;
}
}