mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-04-07 16:26:14 +00:00
Forcefully shove stuff into other stuff
This commit is contained in:
312
src/main/java/com/volmit/iris/generator/IrisComplex.java
Normal file
312
src/main/java/com/volmit/iris/generator/IrisComplex.java
Normal 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);
|
||||
}
|
||||
}
|
||||
119
src/main/java/com/volmit/iris/generator/IrisEngine.java
Normal file
119
src/main/java/com/volmit/iris/generator/IrisEngine.java
Normal 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;
|
||||
}
|
||||
}
|
||||
181
src/main/java/com/volmit/iris/generator/IrisEngineCompound.java
Normal file
181
src/main/java/com/volmit/iris/generator/IrisEngineCompound.java
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.volmit.iris.generator.legacy.atomics;
|
||||
|
||||
import com.volmit.iris.object.IrisBiome;
|
||||
|
||||
public class AtomicBiomeMap extends AtomicObjectMap<IrisBiome> {
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.volmit.iris.generator.legacy.atomics;
|
||||
|
||||
import com.volmit.iris.object.IrisRegion;
|
||||
|
||||
public class AtomicRegionMap extends AtomicObjectMap<IrisRegion> {
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
71
src/main/java/com/volmit/iris/generator/legacy/nms/INMS.java
Normal file
71
src/main/java/com/volmit/iris/generator/legacy/nms/INMS.java
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.volmit.iris.generator.legacy.scaffold;
|
||||
|
||||
public interface ProvisionedHolder extends Provisioned
|
||||
{
|
||||
public Provisioned getProvisioned();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
419
src/main/java/com/volmit/iris/generator/noise/CNG.java
Normal file
419
src/main/java/com/volmit/iris/generator/noise/CNG.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.volmit.iris.generator.noise;
|
||||
|
||||
import com.volmit.iris.util.RNG;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CNGFactory
|
||||
{
|
||||
CNG create(RNG seed);
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
2369
src/main/java/com/volmit/iris/generator/noise/FastNoise.java
Normal file
2369
src/main/java/com/volmit/iris/generator/noise/FastNoise.java
Normal file
File diff suppressed because one or more lines are too long
2364
src/main/java/com/volmit/iris/generator/noise/FastNoiseDouble.java
Normal file
2364
src/main/java/com/volmit/iris/generator/noise/FastNoiseDouble.java
Normal file
File diff suppressed because one or more lines are too long
27
src/main/java/com/volmit/iris/generator/noise/FlatNoise.java
Normal file
27
src/main/java/com/volmit/iris/generator/noise/FlatNoise.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
39
src/main/java/com/volmit/iris/generator/noise/GlobNoise.java
Normal file
39
src/main/java/com/volmit/iris/generator/noise/GlobNoise.java
Normal 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));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.volmit.iris.generator.noise;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface NoiseFactory
|
||||
{
|
||||
NoiseGenerator create(long seed);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
28
src/main/java/com/volmit/iris/generator/noise/NoiseType.java
Normal file
28
src/main/java/com/volmit/iris/generator/noise/NoiseType.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.volmit.iris.generator.noise;
|
||||
|
||||
public interface OctaveNoise
|
||||
{
|
||||
public void setOctaves(int o);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user