Merge remote-tracking branch 'upstream/master' into DecreeCommands

This commit is contained in:
CocoTheOwner 2021-08-18 10:09:29 +02:00
commit 5b15ef81f5
35 changed files with 471 additions and 348 deletions

View File

@ -32,7 +32,7 @@ plugins {
}
group 'com.volmit.iris'
version '1.7.2'
version '1.7.3'
def apiVersion = '1.17'
def name = getRootProject().getName() // See settings.gradle
def main = 'com.volmit.iris.Iris'

View File

@ -27,6 +27,7 @@ import com.volmit.iris.core.link.MultiverseCoreLink;
import com.volmit.iris.core.link.MythicMobsLink;
import com.volmit.iris.core.link.OraxenLink;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.project.IrisProject;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.engine.object.biome.IrisBiome;
@ -93,6 +94,10 @@ public class Iris extends VolmitPlugin implements Listener {
@com.volmit.iris.util.plugin.Command
public CommandIrisStudio commandStudio;
public static VolmitSender getSender() {
return sender;
}
private void preEnable() {
instance = this;
services = new KMap<>();
@ -427,7 +432,6 @@ public class Iris extends VolmitPlugin implements Listener {
@Override
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
IrisDimension dim;
if (id == null || id.isEmpty()) {
dim = IrisData.loadAnyDimension(IrisSettings.get().getGenerator().getDefaultWorldType());
@ -448,6 +452,7 @@ public class Iris extends VolmitPlugin implements Listener {
Iris.info("Resolved missing dimension, proceeding with generation.");
}
}
Iris.debug("Assuming IrisDimension: " + dim.getName());
IrisWorld w = IrisWorld.builder()
@ -458,7 +463,17 @@ public class Iris extends VolmitPlugin implements Listener {
.minHeight(0)
.maxHeight(256)
.build();
return new BukkitChunkGenerator(w, false, new File(w.worldFolder(), "iris"), dim.getName());
Iris.debug("Generator Config: " + w.toString());
File ff = new File(w.worldFolder(), "iris/pack");
if(!ff.exists() || ff.listFiles().length == 0)
{
ff.mkdirs();
service(StudioSVC.class).installIntoWorld(sender, dim.getLoadKey(), ff.getParentFile());
}
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
}
public static void msg(String string) {

View File

@ -82,6 +82,20 @@ public class IrisData {
hotloaded();
}
public static void dereference()
{
dataLoaders.v().forEach(IrisData::cleanupEngine);
}
public void cleanupEngine()
{
if(engine != null && engine.isClosed())
{
engine = null;
Iris.debug("Dereferenced Data<Engine> " + getId() + " " + getDataFolder());
}
}
public static int cacheSize() {
int m = 0;
for(IrisData i : dataLoaders.values())

View File

@ -1,33 +0,0 @@
package com.volmit.iris.core.service;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.plugin.VolmitSender;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
public class LocateSVC implements IrisService {
@EventHandler
public void on(final PlayerCommandPreprocessEvent event) {
if (IrisToolbelt.isIrisWorld(event.getPlayer().getWorld())) {
VolmitSender sender = new VolmitSender(event.getPlayer());
sender.sendMessage(C.YELLOW + "You cannot locate structures in Iris worlds through vanilla commands");
sender.sendMessage("You can use:");
// TODO: Convert this to have the correct command prefix
Bukkit.dispatchCommand(event.getPlayer(), "/ird studio find");
}
}
@Override
public void onEnable() {
}
@Override
public void onDisable() {
}
}

View File

@ -19,17 +19,21 @@
package com.volmit.iris.core.service;
import com.volmit.iris.Iris;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.scheduling.Looper;
import java.util.concurrent.ExecutorService;
public class ExecutionSVC implements IrisService
public class PreservationSVC implements IrisService
{
private KList<Thread> threads = new KList<>();
private KList<MultiBurst> bursts = new KList<>();
private KList<ExecutorService> services = new KList<>();
private Looper dereferencer;
public void register(Thread t)
{
@ -46,13 +50,31 @@ public class ExecutionSVC implements IrisService
services.add(service);
}
public void dereference()
{
IrisContext.dereference();
IrisData.dereference();
}
@Override
public void onEnable() {
/*
* Dereferences copies of Engine instances that are closed to prevent memory from
* hanging around and keeping copies of complex, caches and other dead objects.
*/
dereferencer = new Looper() {
@Override
protected long loop() {
dereference();
return 60000;
}
};
}
@Override
public void onDisable() {
dereferencer.interrupt();
for(Thread i : threads)
{
if(i.isAlive())
@ -97,5 +119,7 @@ public class ExecutionSVC implements IrisService
}
}
dereference();
}
}

View File

@ -47,6 +47,7 @@ import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import java.lang.reflect.Field;
import java.util.List;
import java.util.UUID;
@ -76,11 +77,13 @@ public class IrisComplex implements DataProvider {
private ProceduralStream<Biome> trueBiomeDerivativeStream;
private ProceduralStream<Double> heightStream;
private ProceduralStream<Double> heightStreamNoFeatures;
private ProceduralStream<Double> heightDomainStreamNoFeatures;
private ProceduralStream<Double> objectChanceStream;
private ProceduralStream<Double> maxHeightStream;
private ProceduralStream<Double> overlayStream;
private ProceduralStream<Double> heightFluidStream;
private ProceduralStream<Integer> trueHeightStream;
private ProceduralStream<Integer> trueHeightDomainStream;
private ProceduralStream<Double> slopeStream;
private ProceduralStream<Integer> islandTopStream;
private ProceduralStream<Integer> islandBottomStream;
@ -226,6 +229,25 @@ public class IrisComplex implements DataProvider {
IrisBiome b = focus != null ? focus : baseBiomeStream.get(x, z);
return getHeight(engine, b, x, z, engine.getWorld().seed(), false);
}, Interpolated.DOUBLE).clamp(0, engine.getHeight()).cache2D(cacheSize);
heightDomainStreamNoFeatures = engine.getDimension().getVerticalDomain().isFlat()
? heightStreamNoFeatures
: ProceduralStream.of((x, z) -> {
double hh = 0;
double v, i;
for(i = 0; i < engine.getHeight(); i++)
{
double ox = engine.getDimension().getVerticalDomain().get(rng, getData(), i - 12345);
double oz = engine.getDimension().getVerticalDomain().get(rng, getData(), i + 54321);
v = heightStreamNoFeatures.get(x+ox, z+oz);
if(v > hh)
{
hh = v;
}
}
return hh;
}, Interpolated.DOUBLE).cache2D(cacheSize);
slopeStream = heightStream.slope(3).cache2D(cacheSize);
objectChanceStream = ProceduralStream.ofDouble((x, z) -> {
if (engine.getDimension().hasFeatures(engine)) {
@ -323,6 +345,7 @@ public class IrisComplex implements DataProvider {
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.SEA_SURFACE)).cache2D(cacheSize);
seaFloorDecoration = trueBiomeStream
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.SEA_FLOOR)).cache2D(cacheSize);
trueHeightStream = ProceduralStream.of((x, z) -> {
int rx = (int) Math.round(engine.modifyX(x));
int rz = (int) Math.round(engine.modifyZ(z));
@ -370,6 +393,26 @@ public class IrisComplex implements DataProvider {
.get(x, z) : 0);
islandBottomStream = islandStream.convertAware2D((i, x, z) ->
i ? islandHeightStream.subtract(islandDepthStream).round().get(x, z) : 0);
trueHeightDomainStream = engine.getDimension().getVerticalDomain().isFlat()
? trueHeightStream
: ProceduralStream.of((x, z) -> {
double hh = 0;
double v, i;
for(i = 0; i < engine.getHeight(); i++)
{
double ox = engine.getDimension().getVerticalDomain().get(rng, getData(), i - 12345);
double oz = engine.getDimension().getVerticalDomain().get(rng, getData(), i + 54321);
v = trueHeightStream.get(x+ox, z+oz);
if(v > hh)
{
hh = v;
}
}
return (int)Math.round(hh);
}, Interpolated.INT).cache2D(cacheSize);
//@done
}
@ -502,4 +545,8 @@ public class IrisComplex implements DataProvider {
biome.setInferredType(b.getInferredType());
return implode(biome, x, z, max - 1);
}
public void close() {
}
}

View File

@ -22,6 +22,8 @@ import com.google.common.util.concurrent.AtomicDouble;
import com.google.gson.Gson;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
import com.volmit.iris.core.service.PreservationSVC;
import com.volmit.iris.engine.actuator.IrisBiomeActuator;
import com.volmit.iris.engine.actuator.IrisDecorantActuator;
import com.volmit.iris.engine.actuator.IrisTerrainIslandActuator;
@ -65,8 +67,6 @@ import org.bukkit.generator.BlockPopulator;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
@ -81,11 +81,11 @@ public class IrisEngine extends BlockPopulator implements Engine {
private final AtomicLong lastGPS;
private final EngineTarget target;
private final IrisContext context;
private final EngineEffects effects;
private EngineEffects effects;
private final EngineMantle mantle;
private final ChronoLatch perSecondLatch;
private final EngineExecutionEnvironment execution;
private final EngineWorldManager worldManager;
private EngineExecutionEnvironment execution;
private EngineWorldManager worldManager;
private volatile int parallelism;
private final EngineMetrics metrics;
private volatile int minHeight;
@ -98,57 +98,93 @@ public class IrisEngine extends BlockPopulator implements Engine {
private double maxBiomeObjectDensity;
private double maxBiomeLayerDensity;
private double maxBiomeDecoratorDensity;
private final IrisComplex complex;
private final EngineActuator<BlockData> terrainNormalActuator;
private final EngineActuator<BlockData> terrainIslandActuator;
private final EngineActuator<BlockData> decorantActuator;
private final EngineActuator<Biome> biomeActuator;
private final EngineModifier<BlockData> depositModifier;
private final EngineModifier<BlockData> caveModifier;
private final EngineModifier<BlockData> ravineModifier;
private final EngineModifier<BlockData> postModifier;
private IrisComplex complex;
private EngineActuator<BlockData> terrainNormalActuator;
private EngineActuator<BlockData> terrainIslandActuator;
private EngineActuator<BlockData> decorantActuator;
private EngineActuator<Biome> biomeActuator;
private EngineModifier<BlockData> depositModifier;
private EngineModifier<BlockData> caveModifier;
private EngineModifier<BlockData> ravineModifier;
private EngineModifier<BlockData> postModifier;
private final AtomicCache<IrisEngineData> engineData = new AtomicCache<>();
private final AtomicBoolean cleaning;
private final ChronoLatch cleanLatch;
public IrisEngine(EngineTarget target, boolean studio) {
this.studio = studio;
this.target = target;
metrics = new EngineMetrics(32);
cleanLatch = new ChronoLatch(Math.max(10000, Math.min(IrisSettings.get().getParallax()
.getParallaxChunkEvictionMS(), IrisSettings.get().getParallax().getParallaxRegionEvictionMS())));
generatedLast = new AtomicInteger(0);
perSecond = new AtomicDouble(0);
perSecondLatch = new ChronoLatch(1000, false);
wallClock = new AtomicRollingSequence(32);
lastGPS = new AtomicLong(M.ms());
generated = new AtomicInteger(0);
execution = new IrisExecutionEnvironment(this);
// TODO: HEIGHT ------------------------------------------------------------------------------------------------------>
mantle = new IrisEngineMantle(this);
context = new IrisContext(this);
cleaning = new AtomicBoolean(false);
context.touch();
Iris.info("Initializing Engine: " + target.getWorld().name() + "/" + target.getDimension().getLoadKey() + " (" + 256 + " height)");
metrics = new EngineMetrics(32);
this.target = target;
getData().setEngine(this);
getEngineData();
worldManager = new IrisWorldManager(this);
minHeight = 0;
failing = false;
closed = false;
art = J.ar(this::tickRandomPlayer, 0);
setupEngine();
}
private void tickRandomPlayer() {
if(effects != null) {
effects.tickRandomPlayer();
}
}
private void prehotload()
{
worldManager.close();
complex.close();
execution.close();
terrainNormalActuator.close();
terrainIslandActuator.close();
decorantActuator.close();
biomeActuator.close();
depositModifier.close();
ravineModifier.close();
caveModifier.close();
postModifier.close();
effects.close();
}
private void setupEngine()
{
cacheId = RNG.r.nextInt();
worldManager = new IrisWorldManager(this);
complex = new IrisComplex(this);
execution = new IrisExecutionEnvironment(this);
terrainNormalActuator = new IrisTerrainNormalActuator(this);
terrainIslandActuator = new IrisTerrainIslandActuator(this);
decorantActuator = new IrisDecorantActuator(this);
biomeActuator = new IrisBiomeActuator(this);
depositModifier = new IrisDepositModifier(this);
ravineModifier = new IrisRavineModifier(this);
caveModifier = new IrisCaveModifier(this);
postModifier = new IrisPostModifier(this);
effects = new IrisEngineEffects(this);
art = J.ar(effects::tickRandomPlayer, 0);
J.a(this::computeBiomeMaxes);
context = new IrisContext(this);
context.touch();
this.complex = new IrisComplex(this);
this.terrainNormalActuator = new IrisTerrainNormalActuator(this);
this.terrainIslandActuator = new IrisTerrainIslandActuator(this);
this.decorantActuator = new IrisDecorantActuator(this);
this.biomeActuator = new IrisBiomeActuator(this);
this.depositModifier = new IrisDepositModifier(this);
this.ravineModifier = new IrisRavineModifier(this);
this.caveModifier = new IrisCaveModifier(this);
this.postModifier = new IrisPostModifier(this);
cleaning = new AtomicBoolean(false);
cleanLatch = new ChronoLatch(Math.max(10000, Math.min(IrisSettings.get().getParallax()
.getParallaxChunkEvictionMS(), IrisSettings.get().getParallax().getParallaxRegionEvictionMS())));
mantle = new IrisEngineMantle(this);
}
@Override
public void hotload() {
getData().dump();
getData().clearLists();
getTarget().setDimension(getData().getDimensionLoader().load(getDimension().getLoadKey()));
prehotload();
setupEngine();
Iris.callEvent(new IrisEngineHotloadEvent(this));
}
@Override
@ -302,6 +338,10 @@ public class IrisEngine extends BlockPopulator implements Engine {
getCaveModifier().close();
getPostModifier().close();
getMantle().close();
getComplex().close();
getData().dump();
getData().clearLists();
Iris.service(PreservationSVC.class).dereference();
Iris.debug("Engine Fully Shutdown!");
}

View File

@ -57,6 +57,7 @@ import java.util.stream.Stream;
@Data
public class IrisWorldManager extends EngineAssignedWorldManager {
private final Looper looper;
private final int id;
private final KMap<Long, Long> chunkCooldowns;
private double energy = 25;
private int entityCount = 0;
@ -75,6 +76,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
cln = null;
chunkCooldowns = null;
looper = null;
id = -1;
}
public IrisWorldManager(Engine engine) {
@ -83,11 +85,12 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
cl = new ChronoLatch(3000);
ecl = new ChronoLatch(250);
chunkCooldowns = new KMap<>();
id = engine.getCacheID();
energy = 25;
looper = new Looper() {
@Override
protected long loop() {
if (getEngine().isClosed()) {
if (getEngine().isClosed() || getEngine().getCacheID() != id) {
interrupt();
}
@ -186,9 +189,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
}
Chunk c = cc[RNG.r.nextInt(cc.length)];
IrisBiome biome = getEngine().getSurfaceBiome(c);
IrisRegion region = getEngine().getRegion(c);
spawnIn(c, biome, region);
spawnIn(c, false);
chunkCooldowns.put(Cache.key(c), M.ms());
}
@ -200,26 +201,29 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
energy = M.clip(energy, 1D, 1000D);
}
private void spawnIn(Chunk c, IrisBiome biome, IrisRegion region) {
private void spawnIn(Chunk c, boolean initial) {
IrisBiome biome = getEngine().getSurfaceBiome(c);
IrisRegion region = getEngine().getRegion(c);
//@builder
IrisEntitySpawn v = spawnRandomly(Stream.concat(Stream.concat(
getData().getSpawnerLoader()
.loadAll(getDimension().getEntitySpawners())
.shuffleCopy(RNG.r).stream().filter(this::canSpawn),
.shuffleCopy(RNG.r).stream()
.filter(this::canSpawn),
getData().getSpawnerLoader().streamAll(getEngine().getMantle()
.getFeaturesInChunk(c).stream()
.flatMap((o) -> o.getFeature().getEntitySpawners().stream()))
.filter(this::canSpawn))
.filter((i) -> i.isValid(biome))
.flatMap(this::stream),
.flatMap((i) -> stream(i, initial)),
Stream.concat(getData().getSpawnerLoader()
.loadAll(getEngine().getRegion(c.getX() << 4, c.getZ() << 4).getEntitySpawners())
.shuffleCopy(RNG.r).stream().filter(this::canSpawn)
.flatMap(this::stream),
.flatMap((i) -> stream(i, initial)),
getData().getSpawnerLoader()
.loadAll(getEngine().getSurfaceBiome(c.getX() << 4, c.getZ() << 4).getEntitySpawners())
.shuffleCopy(RNG.r).stream().filter(this::canSpawn)
.flatMap(this::stream)))
.flatMap((i) -> stream(i, initial))))
.collect(Collectors.toList()))
.popRandom(RNG.r);
@ -279,12 +283,12 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
}
}
private Stream<IrisEntitySpawn> stream(IrisSpawner s) {
for (IrisEntitySpawn i : s.getSpawns()) {
private Stream<IrisEntitySpawn> stream(IrisSpawner s, boolean initial) {
for (IrisEntitySpawn i : initial ? s.getInitialSpawns() : s.getSpawns()) {
i.setReferenceSpawner(s);
}
return s.getSpawns().stream();
return (initial ? s.getInitialSpawns() : s.getSpawns()).stream();
}
private KList<IrisEntitySpawn> spawnRandomly(List<IrisEntitySpawn> types) {
@ -340,6 +344,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
public void onChunkLoad(Chunk e, boolean generated) {
if (generated) {
energy += 1.2;
spawnIn(e, true);
} else {
energy += 0.3;
}

View File

@ -40,7 +40,6 @@ public class IrisTerrainIslandActuator extends EngineAssignedActuator<BlockData>
@Getter
private final RNG rng;
private final boolean carving;
private final boolean hasUnder;
@Getter
private final int lastBedrock = -1;
@ -48,7 +47,6 @@ public class IrisTerrainIslandActuator extends EngineAssignedActuator<BlockData>
super(engine, "TerrainIsland");
rng = new RNG(engine.getWorld().seed());
carving = getDimension().isCarving() && getDimension().getCarveLayers().isNotEmpty();
hasUnder = getDimension().getUndercarriage() != null && !getDimension().getUndercarriage().getGenerator().isFlat();
}
@BlockCoordinates

View File

@ -18,9 +18,11 @@
package com.volmit.iris.engine.actuator;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedActuator;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.noise.IrisShapedGeneratorStyle;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.hunk.Hunk;
@ -38,15 +40,16 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
@Getter
private final RNG rng;
private final boolean carving;
private final boolean hasUnder;
@Getter
private int lastBedrock = -1;
private IrisShapedGeneratorStyle domain;
public IrisTerrainNormalActuator(Engine engine) {
super(engine, "Terrain");
rng = new RNG(engine.getWorld().seed());
carving = getDimension().isCarving() && getDimension().getCarveLayers().isNotEmpty();
hasUnder = getDimension().getUndercarriage() != null && !getDimension().getUndercarriage().getGenerator().isFlat();
domain = getDimension().getVerticalDomain();
domain = domain.isFlat() ? null : domain;
}
@BlockCoordinates
@ -71,6 +74,75 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
getEngine().getMetrics().getTerrain().put(p.getMilliseconds());
}
public void generateGround(int realX, int realZ, int xf, int zf, Hunk<BlockData> h, int surface, int bottom, int height, int fluidOrHeight, IrisBiome biome)
{
if(surface == bottom || surface-1 == bottom)
{
return;
}
KList<BlockData> blocks = null;
KList<BlockData> fblocks = null;
int depth,fdepth;
for (int i = surface; i >= bottom; i--) {
if (i >= h.getHeight()) {
continue;
}
if (i == 0) {
if (getDimension().isBedrock()) {
h.set(xf, i, zf, BEDROCK);
lastBedrock = i;
continue;
}
}
if (carving && getDimension().isCarved(getData(), realX, i, realZ, rng, height)) {
continue;
}
if (getDimension().getCaverns() != null && getDimension().getCaverns().isCavern(rng, realX, i, realZ, height, getData())) {
continue;
}
if (i > height && i <= fluidOrHeight) {
fdepth = fluidOrHeight - i;
if (fblocks == null) {
fblocks = biome.generateSeaLayers(realX, realZ, rng, fluidOrHeight - height, getData());
}
if (fblocks.hasIndex(fdepth)) {
h.set(xf, i, zf, fblocks.get(fdepth));
continue;
}
h.set(xf, i, zf, getComplex().getFluidStream().get(realX, +realZ));
continue;
}
if (i <= height) {
depth = surface - i;
if (blocks == null) {
blocks = biome.generateLayers(realX, realZ, rng, surface - bottom, surface, getData(), getComplex());
}
if (blocks.hasIndex(depth)) {
h.set(xf, i, zf, blocks.get(depth));
continue;
}
h.set(xf, i, zf, getComplex().getRockStream().get(realX, realZ));
}
}
}
private int fluidOrHeight(int height)
{
return Math.max(getDimension().getFluidHeight(), height);
}
/**
* This is calling 1/16th of a chunk x/z slice. It is a plane from sky to bedrock 1 thick in the x direction.
*
@ -81,74 +153,63 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
*/
@BlockCoordinates
public void terrainSliver(int x, int z, int xf, Hunk<BlockData> h) {
int i, depth, realX, realZ, hf, he, b, fdepth;
int i, j, k, realX, realZ, hf, he;
IrisBiome biome;
KList<BlockData> blocks, fblocks;
for (int zf = 0; zf < h.getDepth(); zf++) {
for (i = 0; i < h.getDepth(); i++) {
realX = (int) modX(xf + x);
realZ = (int) modZ(zf + z);
b = hasUnder ? (int) Math.round(getDimension().getUndercarriage().get(rng, getData(), realX, realZ)) : 0;
he = (int) Math.round(Math.min(h.getHeight(), getComplex().getHeightStream().get(realX, realZ)));
hf = Math.round(Math.max(Math.min(h.getHeight(), getDimension().getFluidHeight()), he));
biome = getComplex().getTrueBiomeStream().get(realX, realZ);
blocks = null;
fblocks = null;
realZ = (int) modZ(i + z);
if (hf < b) {
continue;
if(domain != null)
{
int[] heights = new int[h.getHeight()];
IrisBiome[] biomes = new IrisBiome[h.getHeight()];
int maximum = 0;
for(j = 0; j < h.getHeight(); j++)
{
double ox = domain.get(rng, getData(), j - 12345);
double oz = domain.get(rng, getData(), j + 54321);
biomes[j] = getComplex().getTrueBiomeStream().get(realX+ox, realZ+oz);
heights[j] = (int) Math.round(Math.min(h.getHeight(), getComplex().getHeightStream().get(realX+ox, realZ+oz)));
maximum = Math.max(maximum, heights[j]);
}
for(j = maximum; j >= 0; j--) {
if(fluidOrHeight(heights[j]) < j)
{
continue;
}
int hi = j;
int lo = 0;
for(k = j; k >= 0; k--)
{
if(fluidOrHeight(heights[k]) < k)
{
break;
}
lo = k;
j = k-1;
}
generateGround(realX, realZ, xf, i, h, hi, lo, heights[hi], fluidOrHeight(heights[hi]), biomes[hi]);
}
}
for (i = hf; i >= b; i--) {
if (i >= h.getHeight()) {
else
{
biome = getComplex().getTrueBiomeStream().get(realX, realZ);
he = (int) Math.round(Math.min(h.getHeight(), getComplex().getHeightStream().get(realX, realZ)));
hf = Math.round(Math.max(Math.min(h.getHeight(), getDimension().getFluidHeight()), he));
if (hf < 0) {
continue;
}
if (i == b) {
if (getDimension().isBedrock()) {
h.set(xf, i, zf, BEDROCK);
lastBedrock = i;
continue;
}
}
if (carving && getDimension().isCarved(getData(), realX, i, realZ, rng, he)) {
continue;
}
if (getDimension().getCaverns() != null && getDimension().getCaverns().isCavern(rng, realX, i, realZ, he, getData())) {
continue;
}
if (i > he && i <= hf) {
fdepth = hf - i;
if (fblocks == null) {
fblocks = biome.generateSeaLayers(realX, realZ, rng, hf - he, getData());
}
if (fblocks.hasIndex(fdepth)) {
h.set(xf, i, zf, fblocks.get(fdepth));
continue;
}
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, he, he, getData(), getComplex());
}
if (blocks.hasIndex(depth)) {
h.set(xf, i, zf, blocks.get(depth));
continue;
}
h.set(xf, i, zf, getComplex().getRockStream().get(realX, realZ));
}
generateGround(realX, realZ, xf, i, h, hf, 0, he, hf, biome);
}
}
}

View File

@ -77,7 +77,7 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdater, Renderer {
public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdater, Renderer, Hotloadable {
IrisComplex getComplex();
void printMetrics(CommandSender sender);

View File

@ -28,7 +28,7 @@ import lombok.Data;
@Data
public class EngineTarget {
private final MultiBurst burster;
private final IrisDimension dimension;
private IrisDimension dimension;
private IrisWorld world;
private final IrisData data;

View File

@ -76,6 +76,8 @@ public class PlannedStructure {
generateTerminators();
Iris.debug("JPlace: ROOT @ relative " + position.toString());
for (PlannedPiece i : pieces) {
Iris.debug("Place: " + i.getObject().getLoadKey() + " at @ relative " + i.getPosition().toString());
}
@ -112,7 +114,9 @@ public class PlannedStructure {
int xx = i.getPosition().getX() + sx;
int zz = i.getPosition().getZ() + sz;
int offset = i.getPosition().getY() - startHeight;
int height = placer.getHighest(xx, zz, getData()) + offset + (v.getH() / 2);
int height = (i.getStructure().getStructure().getLockY() != -1
? i.getStructure().getStructure().getLockY()
: placer.getHighest(xx, zz, getData())) + offset + (v.getH() / 2);
if (options.getMode().equals(ObjectPlaceMode.PAINT) || options.isVacuum()) {
height = -1;
@ -122,7 +126,6 @@ public class PlannedStructure {
int h = vo.place(xx, height, zz, placer, options, rng, (b)
-> e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id), null, getData());
for (IrisJigsawPieceConnector j : i.getAvailableConnectors()) {
if (j.getSpawnEntity() != null)// && h != -1)
{
@ -155,27 +158,6 @@ public class PlannedStructure {
public void place(World world) {
for (PlannedPiece i : pieces) {
Iris.sq(() -> {
for (IrisJigsawPieceConnector j : i.getAvailableConnectors()) {
if (j.getSpawnEntity() != null) {
Engine a = IrisToolbelt.access(world).getEngine();
if (a == null) {
Iris.warn("Cannot spawn entities from jigsaw in non Iris world!");
break;
}
IrisPosition p = i.getWorldPosition(j).add(new IrisPosition(j.getDirection().toVector().multiply(2)));
IrisEntity e = getData().getEntityLoader().load(j.getSpawnEntity());
if (a != null) {
Entity entity = e.spawn(a, new Location(world, p.getX() + 0.5, p.getY(), p.getZ() + 0.5), rng);
if (j.isKeepEntity()) {
entity.setPersistent(true);
}
}
}
}
});
Iris.sq(() -> i.place(world));
}
}
@ -246,7 +228,9 @@ public class PlannedStructure {
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea, IrisObjectRotation rotation) {
if (!idea.getPlacementOptions().getRotation().isEnabled())
rotation = piece.getRotation(); //Inherit parent rotation
{
rotation = piece.getRotation();
}
PlannedPiece test = new PlannedPiece(this, piece.getPosition(), idea, rotation);

View File

@ -44,6 +44,7 @@ import org.bukkit.block.data.BlockData;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
@ -189,8 +190,13 @@ public interface EngineMantle extends IObjectPlacer {
}
PrecisionStopwatch p = PrecisionStopwatch.start();
List<Runnable> post = Collections.synchronizedList(new KList<>());
Consumer<Runnable> c = post::add;
KList<Runnable> post = new KList<>();
Consumer<Runnable> c = (i) -> {
synchronized (post)
{
post.add(i);
}
};
int s = getRealRadius();
BurstExecutor burst = burst().burst();
@ -205,7 +211,13 @@ public interface EngineMantle extends IObjectPlacer {
}
burst.complete();
burst().burst(post);
while(!post.isEmpty())
{
KList<Runnable> px = post.copy();
post.clear();
burst().burst(px);
}
}
default void generateMantleComponent(int x, int z, MantleComponent c, Consumer<Runnable> post) {

View File

@ -35,6 +35,7 @@ import com.volmit.iris.engine.object.jigsaw.IrisJigsawStructurePlacement;
import com.volmit.iris.engine.object.loot.IrisLootReference;
import com.volmit.iris.engine.object.meta.IrisEffect;
import com.volmit.iris.engine.object.noise.IrisGeneratorStyle;
import com.volmit.iris.engine.object.noise.IrisShapedGeneratorStyle;
import com.volmit.iris.engine.object.noise.IrisSlopeClip;
import com.volmit.iris.engine.object.noise.NoiseStyle;
import com.volmit.iris.engine.object.objects.IrisObject;

View File

@ -22,6 +22,7 @@ import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.engine.object.block.IrisBlockData;
import com.volmit.iris.engine.object.noise.IrisGenerator;
import com.volmit.iris.engine.object.objects.IrisObject;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.math.RNG;

View File

@ -39,6 +39,7 @@ import com.volmit.iris.engine.object.jigsaw.IrisJigsawStructure;
import com.volmit.iris.engine.object.jigsaw.IrisJigsawStructurePlacement;
import com.volmit.iris.engine.object.loot.IrisLootReference;
import com.volmit.iris.engine.object.noise.IrisGeneratorStyle;
import com.volmit.iris.engine.object.noise.IrisInterpolator;
import com.volmit.iris.engine.object.noise.IrisShapedGeneratorStyle;
import com.volmit.iris.engine.object.noise.NoiseStyle;
import com.volmit.iris.engine.object.objects.IrisObjectPlacement;
@ -106,9 +107,6 @@ public class IrisDimension extends IrisRegistrant {
@Desc("Define iris cavern zones")
private IrisCaverns caverns = new IrisCaverns();
@Desc("Instead of a flat bottom, applies a clamp (using this noise style) to the bottom instead of a flat bottom. Useful for carving out center-dimensions in a dimension composite world.")
private IrisShapedGeneratorStyle undercarriage = null;
@Desc("Upon joining this world, Iris will send a resource pack request to the client. If they have previously selected yes, it will auto-switch depending on which dimension they go to.")
private String resourcePack = "";
@ -332,6 +330,9 @@ public class IrisDimension extends IrisRegistrant {
@Desc("Cartographer map trade overrides")
private IrisVillagerOverride patchCartographers = new IrisVillagerOverride().setDisableTrade(false);
@Desc("If defined, warp the terrain vertically by this style. This will cause overhangs & carving-like shapes")
private IrisShapedGeneratorStyle verticalDomain = new IrisShapedGeneratorStyle(NoiseStyle.FLAT, 1, 1);
private final transient AtomicCache<Position2> parallaxSize = new AtomicCache<>();
private final transient AtomicCache<CNG> rockLayerGenerator = new AtomicCache<>();
private final transient AtomicCache<CNG> fluidLayerGenerator = new AtomicCache<>();

View File

@ -59,6 +59,9 @@ public class IrisJigsawStructure extends IrisRegistrant {
@Desc("If set to true, iris will look for any pieces with only one connector in valid pools for edge connectors and attach them to 'terminate' the paths/piece connectors. Essentially it caps off ends. For example in a village, Iris would add houses to the ends of roads where possible. For terminators to be selected, they can only have one connector or they wont be chosen.")
private boolean terminate = true;
@Desc("Set to lock the starting peice to a y coordinate, otherwise the surface will be used.")
private int lockY = -1;
private transient AtomicCache<Integer> maxDimension = new AtomicCache<>();
private void loadPool(String p, KList<String> pools, KList<String> pieces) {

View File

@ -24,6 +24,7 @@ import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.engine.object.common.IRare;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.interpolation.IrisInterpolation;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.noise.CellGenerator;

View File

@ -38,13 +38,13 @@ import lombok.experimental.Accessors;
public class IrisInterpolator {
@Required
@Desc("The interpolation method when two biomes use different heights but this same generator")
private InterpolationMethod function = InterpolationMethod.BICUBIC;
private InterpolationMethod function = InterpolationMethod.BILINEAR_STARCAST_6;
@Required
@MinNumber(1)
@MaxNumber(8192)
@Desc("The range checked horizontally. Smaller ranges yeild more detail but are not as smooth.")
private double horizontalScale = 3;
private double horizontalScale = 7;
public double interpolate(double x, double z, NoiseProvider provider) {
return interpolate((int) Math.round(x), (int) Math.round(z), provider);

View File

@ -64,4 +64,8 @@ public class IrisShapedGeneratorStyle {
public IrisShapedGeneratorStyle(NoiseStyle style) {
this.generator = new IrisGeneratorStyle(style);
}
public boolean isFlat() {
return min == max || getGenerator().isFlat();
}
}

View File

@ -33,6 +33,7 @@ import lombok.experimental.Accessors;
public class IrisAxisRotationClamp {
@Desc("Should this axis be rotated at all?")
private boolean enabled = false;
private transient boolean forceLock = false;
@Required
@ -72,7 +73,7 @@ public class IrisAxisRotationClamp {
public double getRadians(int rng) {
if (forceLock) {
return Math.toRadians(max);
return Math.toRadians(Math.ceil(Math.abs((max % 360D))));
}
if (isUnlimited()) {

View File

@ -34,6 +34,7 @@ import com.volmit.iris.engine.object.jigsaw.IrisJigsawStructurePlacement;
import com.volmit.iris.engine.object.loot.IrisLootReference;
import com.volmit.iris.engine.object.meta.IrisEffect;
import com.volmit.iris.engine.object.noise.IrisGeneratorStyle;
import com.volmit.iris.engine.object.noise.IrisShapedGeneratorStyle;
import com.volmit.iris.engine.object.noise.NoiseStyle;
import com.volmit.iris.engine.object.objects.IrisObjectPlacement;
import com.volmit.iris.engine.object.spawners.IrisSpawner;

View File

@ -45,6 +45,10 @@ public class IrisSpawner extends IrisRegistrant {
@Desc("The entity spawns to add")
private KList<IrisEntitySpawn> spawns = new KList<>();
@ArrayType(min = 1, type = IrisEntitySpawn.class)
@Desc("The entity spawns to add initially. EXECUTES PER CHUNK!")
private KList<IrisEntitySpawn> initialSpawns = new KList<>();
@Desc("The energy multiplier when calculating spawn energy usage")
private double energyMultiplier = 1;

View File

@ -19,10 +19,15 @@
package com.volmit.iris.engine.platform;
import com.volmit.iris.Iris;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.engine.IrisEngine;
import com.volmit.iris.engine.data.chunk.TerrainChunk;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineTarget;
import com.volmit.iris.engine.framework.WrongEngineBroException;
import com.volmit.iris.engine.object.common.IrisWorld;
import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.io.ReactiveFolder;
@ -30,6 +35,8 @@ import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.Looper;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
@ -39,14 +46,18 @@ import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import org.jetbrains.annotations.NotNull;
import javax.management.RuntimeErrorException;
import java.io.File;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Semaphore;
@EqualsAndHashCode(callSuper = true)
@Data
public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChunkGenerator {
private static final int HOTLOAD_LOCKS = 1000000;
private final EngineProvider provider;
private static final int LOAD_LOCKS = 1_000_000;
private final Semaphore loadLock;
private final Engine engine;
private final IrisWorld world;
private final File dataLocation;
private final String dimensionKey;
@ -54,21 +65,56 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
private final KList<BlockPopulator> populators;
private final ChronoLatch hotloadChecker;
private final Looper hotloader;
private final Semaphore hotloadLock;
private final boolean studio;
public BukkitChunkGenerator(IrisWorld world, boolean studio, File dataLocation, String dimensionKey) {
populators = new KList<>();
loadLock = new Semaphore(LOAD_LOCKS);
this.world = world;
this.hotloadLock = new Semaphore(HOTLOAD_LOCKS);
this.hotloadChecker = new ChronoLatch(1000, false);
this.studio = studio;
this.dataLocation = dataLocation;
this.dimensionKey = dimensionKey;
this.folder = new ReactiveFolder(dataLocation, (_a, _b, _c) -> hotload());
this.provider = new EngineProvider();
initialize();
IrisData data = IrisData.get(dataLocation);
IrisDimension dimension = data.getDimensionLoader().load(dimensionKey);
if(dimension == null)
{
Iris.error("Oh No! There's no pack in " + data.getDataFolder().getPath() + " or... there's no dimension for the key " + dimensionKey);
IrisDimension test = IrisData.loadAnyDimension(dimensionKey);
if(test != null)
{
Iris.warn("Looks like " + dimensionKey + " exists in " + test.getLoadFile().getPath());
Iris.service(StudioSVC.class).installIntoWorld(Iris.getSender(), dimensionKey, dataLocation.getParentFile().getParentFile());
Iris.warn("Attempted to install into " + data.getDataFolder().getPath());
data.dump();
data.clearLists();
test = data.getDimensionLoader().load(dimensionKey);
if(test != null)
{
Iris.success("Woo! Patched the Engine to work with MVC bugs. Have a nice day!");
dimension = test;
}
else
{
Iris.error("Failed to patch dimension!");
throw new RuntimeException("Missing Dimension: " + dimensionKey);
}
}
else
{
Iris.error("Nope, you don't have an installation containing " + dimensionKey + " try downloading it?");
throw new RuntimeException("Missing Dimension: " + dimensionKey);
}
}
this.engine = new IrisEngine(new EngineTarget(world, dimension, data), studio);
populators.add((BlockPopulator) engine);
this.hotloader = new Looper() {
@Override
protected long loop() {
@ -84,13 +130,6 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
hotloader.setName(getTarget().getWorld().name() + " Hotloader");
}
public synchronized Engine getEngine() {
synchronized (provider)
{
return provider.getEngine();
}
}
@Override
public boolean isHeadless() {
return false;
@ -98,11 +137,10 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
@Override
public void close() {
synchronized (provider)
{
withExclusiveControl(() -> {
hotloader.interrupt();
provider.close();
}
getEngine().close();
});
}
@Override
@ -112,58 +150,40 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
@Override
public void hotload() {
J.aBukkit(this::hotloadBLOCKING);
withExclusiveControl(() -> getEngine().hotload());
}
public void hotloadBLOCKING() {
try {
hotloadLock.acquire(HOTLOAD_LOCKS);
initialize();
hotloadLock.release(HOTLOAD_LOCKS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void initialize() {
synchronized (provider)
{
provider.provideEngine(world, dimensionKey, dataLocation, isStudio(), (e) -> {
populators.clear();
populators.add((BlockPopulator) e);
folder.checkIgnore();
});
}
public void withExclusiveControl(Runnable r)
{
J.a(() -> {
try {
loadLock.acquire(LOAD_LOCKS);
r.run();
loadLock.release(LOAD_LOCKS);
} catch (Throwable e) {
e.printStackTrace();
}
});
}
@Override
public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random ignored, int x, int z, @NotNull BiomeGrid biome) {
try {
hotloadLock.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Iris.debug("Generated " + x + " " + z);
loadLock.acquire();
PrecisionStopwatch ps = PrecisionStopwatch.start();
TerrainChunk tc = TerrainChunk.create(world, biome);
Hunk<BlockData> blocks = Hunk.view((ChunkData) tc);
Hunk<Biome> biomes = Hunk.view((BiomeGrid) tc);
this.world.bind(world);
getEngine().generate(x * 16, z * 16, blocks, biomes, true);
hotloadLock.release();
return tc.getRaw();
}
catch(WrongEngineBroException e)
{
hotloadLock.release();
hotloadBLOCKING();
return generateChunkData(world, ignored, x, z, biome);
ChunkData c = tc.getRaw();
Iris.debug("Generated " + x + " " + z);
loadLock.release();
return c;
}
catch (Throwable e) {
loadLock.release();
Iris.error("======================================");
e.printStackTrace();
Iris.reportErrorChunk(x, z, e, "CHUNK");
@ -177,10 +197,8 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
}
}
hotloadLock.release();
return d;
}
}
@NotNull

View File

@ -1,85 +0,0 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.engine.platform;
import com.volmit.iris.Iris;
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.engine.IrisEngine;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineTarget;
import com.volmit.iris.engine.object.common.IrisWorld;
import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.util.parallel.MultiBurst;
import java.io.File;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
public class EngineProvider {
private final AtomicReference<CompletableFuture<Engine>> engine = new AtomicReference<>();
public void provideEngine(IrisWorld world, String dimension, File dataLocation, boolean studio, Consumer<Engine> post) {
close();
engine.set(MultiBurst.burst.completeValue(() -> {
IrisData data = IrisData.get(dataLocation);
IrisDimension realDimension = data.getDimensionLoader().load(dimension);
if (realDimension == null) {
throw new RuntimeException("Cannot find dimension in " + data.getDataFolder().getAbsolutePath() + " with key " + dimension);
}
EngineTarget target = new EngineTarget(world, realDimension, data);
Engine engine = new IrisEngine(target, studio);
post.accept(engine);
return engine;
}));
engine.get().whenComplete((e, x) -> Iris.callEvent(new IrisEngineHotloadEvent(e)));
}
public Engine getEngine() {
try {
Engine e = engine.get().get();
if (e == null) {
throw new RuntimeException("NULL");
}
return e;
} catch (InterruptedException e) {
e.printStackTrace();
throw new RuntimeException("INTERRUPTED");
} catch (ExecutionException e) {
e.printStackTrace();
throw new RuntimeException("EXECUTION ERROR");
}
}
public void close() {
if (engine.get() != null && engine.get().isDone()) {
Engine e = getEngine();
if (e != null) {
e.close();
}
}
}
}

View File

@ -23,9 +23,11 @@ import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.engine.IrisEngine;
import com.volmit.iris.engine.data.chunk.MCATerrainChunk;
import com.volmit.iris.engine.data.chunk.TerrainChunk;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineTarget;
import com.volmit.iris.engine.object.common.HeadlessWorld;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.documentation.ChunkCoordinates;
@ -52,15 +54,13 @@ public class HeadlessGenerator implements PlatformChunkGenerator {
private final HeadlessWorld world;
private final NBTWorld writer;
private final MultiBurst burst;
private final EngineProvider provider;
private final Engine engine;
public HeadlessGenerator(HeadlessWorld world) {
this.world = world;
burst = new MultiBurst("Iris Headless Generator", 9, IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getPregenThreadCount()));
writer = new NBTWorld(world.getWorld().worldFolder());
provider = new EngineProvider();
provider.provideEngine(world.getWorld(), world.getDimension().getLoadKey(), world.getDimension().getLoader().getDataFolder(), isStudio(), (e) -> {
});
engine = new IrisEngine(new EngineTarget(world.getWorld(), world.getDimension(), world.getDimension().getLoader()), isStudio());
}
@ChunkCoordinates
@ -132,7 +132,7 @@ public class HeadlessGenerator implements PlatformChunkGenerator {
public void close() {
burst.shutdownAndAwait();
provider.close();
getEngine().close();
writer.close();
}
@ -151,11 +151,6 @@ public class HeadlessGenerator implements PlatformChunkGenerator {
return EMPTYPOINTS;
}
@Override
public Engine getEngine() {
return provider.getEngine();
}
@Override
public boolean isHeadless() {
return true;

View File

@ -18,6 +18,7 @@
package com.volmit.iris.util.context;
import com.volmit.iris.Iris;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.engine.IrisComplex;
import com.volmit.iris.engine.framework.Engine;
@ -30,7 +31,7 @@ import lombok.Data;
@AllArgsConstructor
public class IrisContext {
private static ChronoLatch cl = new ChronoLatch(60000);
private static KMap<Thread, IrisContext> context = new KMap<>();
private static final KMap<Thread, IrisContext> context = new KMap<>();
private final Engine engine;
public static IrisContext get() {
@ -42,10 +43,22 @@ public class IrisContext {
context.put(Thread.currentThread(), c);
if (cl.flip()) {
for (Thread i : context.k()) {
if (!i.isAlive()) {
context.remove(i);
dereference();
}
}
}
public static void dereference() {
synchronized (context)
{
for (Thread i : context.k()) {
if (!i.isAlive() || context.get(i).engine.isClosed()) {
if(context.get(i).engine.isClosed())
{
Iris.debug("Dereferenced Context<Engine> " + i.getName() + " " + i.getId());
}
context.remove(i);
}
}
}

View File

@ -19,7 +19,7 @@ public class ObjectHandler implements DecreeParameterHandler<IrisObject> {
//noinspection ConstantConditions
for (File i : Iris.instance.getDataFolder("packs").listFiles()) {
if (i.isDirectory()) {
IrisData data = new IrisData(i, true);
IrisData data = IrisData.get(i);
for (IrisObject j : data.getObjectLoader().loadAll(data.getObjectLoader().getPossibleKeys())) {
p.putIfAbsent(j.getLoadKey(), j);
}

View File

@ -192,7 +192,7 @@ public class Mantle {
public synchronized void close() {
Iris.debug("Closing The Mantle " + C.DARK_AQUA + dataFolder.getAbsolutePath());
if (closed.get()) {
throw new RuntimeException("The Mantle is closed");
return;
}
closed.set(true);

View File

@ -45,7 +45,7 @@ public class BurstExecutor {
public BurstExecutor queue(List<Runnable> r) {
synchronized (futures) {
for (Runnable i : r) {
for (Runnable i : new KList<>(r)) {
CompletableFuture<Void> c = CompletableFuture.runAsync(i, executor);
futures.add(c);
}

View File

@ -20,7 +20,7 @@ package com.volmit.iris.util.parallel;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.service.ExecutionSVC;
import com.volmit.iris.core.service.PreservationSVC;
import com.volmit.iris.util.io.InstanceState;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.scheduling.J;
@ -71,7 +71,7 @@ public class MultiBurst {
};
heartbeat.setName(name + " Monitor");
heartbeat.start();
Iris.service(ExecutionSVC.class).register(this);
Iris.service(PreservationSVC.class).register(this);
}
private synchronized ExecutorService getService() {
@ -90,7 +90,7 @@ public class MultiBurst {
return t;
});
Iris.service(ExecutionSVC.class).register(service);
Iris.service(PreservationSVC.class).register(service);
Iris.debug("Started MultiBurst Pool " + name + " with " + tc + " threads at " + priority + " priority.");
}

View File

@ -19,14 +19,12 @@
package com.volmit.iris.util.scheduling;
import com.volmit.iris.Iris;
import com.volmit.iris.core.service.ExecutionSVC;
import java.util.concurrent.ExecutorService;
import com.volmit.iris.core.service.PreservationSVC;
public abstract class Looper extends Thread {
@SuppressWarnings("BusyWait")
public void run() {
Iris.service(ExecutionSVC.class).register(this);
Iris.service(PreservationSVC.class).register(this);
while (!interrupted()) {
try {
long m = loop();

View File

@ -58,5 +58,4 @@ public class AddingStream<T> extends BasicStream<T> {
public T get(double x, double y, double z) {
return fromDouble(add.apply(x, y, z) + getTypedSource().getDouble(x, y, z));
}
}

View File

@ -32,6 +32,7 @@ public interface Interpolated<T> {
Interpolated<KList<CaveResult>> CAVE_RESULTS = of((t) -> 0D, (t) -> null);
Interpolated<RNG> RNG = of((t) -> 0D, (t) -> null);
Interpolated<Double> DOUBLE = of((t) -> t, (t) -> t);
Interpolated<Double[]> DOUBLE_ARRAY = of((t) -> 0D, (t) -> new Double[2]);
Interpolated<Boolean> BOOLEAN = of((t) -> 0D, (t) -> false);
Interpolated<Integer> INT = of(Double::valueOf, Double::intValue);
Interpolated<Long> LONG = of(Double::valueOf, Double::longValue);