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

This commit is contained in:
CocoTheOwner 2021-08-19 09:54:55 +02:00
commit baf76c51f9
29 changed files with 438 additions and 185 deletions

View File

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

View File

@ -75,7 +75,6 @@ import java.util.Map;
@SuppressWarnings("CanBeFinal")
public class Iris extends VolmitPlugin implements Listener {
private KMap<Class<? extends IrisService>, IrisService> services;
public static KList<GroupedExecutor> executors = new KList<>();
public static Iris instance;
public static BukkitAudiences audiences;
public static MultiverseCoreLink linkMultiverseCore;
@ -85,6 +84,7 @@ public class Iris extends VolmitPlugin implements Listener {
public static IrisCompat compat;
public static FileWatcher configWatcher;
private static VolmitSender sender;
private final KList<Runnable> postShutdown = new KList<>();
@Permission
public static PermissionIris perm;
@ -126,6 +126,11 @@ public class Iris extends VolmitPlugin implements Listener {
services.values().forEach(this::registerListener);
}
public void postShutdown(Runnable r)
{
postShutdown.add(r);
}
private void postEnable() {
J.a(() -> PaperLib.suggestPaper(this));
J.a(() -> IO.delete(getTemp()));
@ -155,18 +160,10 @@ public class Iris extends VolmitPlugin implements Listener {
}
public void onDisable() {
for (GroupedExecutor i : executors) {
Iris.debug("Closing Executor " + i.toString());
i.closeNow();
}
executors.clear();
services.values().forEach(IrisService::onDisable);
Bukkit.getScheduler().cancelTasks(this);
HandlerList.unregisterAll((Plugin) this);
MultiBurst.burst.shutdown();
services.values().forEach(IrisService::onDisable);
postShutdown.forEach(Runnable::run);
services.clear();
super.onDisable();
}

View File

@ -104,6 +104,7 @@ public class IrisSettings {
public boolean verbose = false;
public boolean ignoreWorldEdit = false;
public boolean disableNMS = false;
public boolean keepProductionOnReload = false;
public boolean pluginMetrics = true;
public boolean splashLogoStartup = true;
public String forceMainWorld = "";

View File

@ -37,7 +37,6 @@ public class EditSVC implements IrisService {
@Override
public void onEnable() {
this.editors = new KMap<>();
Iris.info("EDIT SVC ENABLED!");
Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, this::update, 1000, 1000);
}

View File

@ -74,52 +74,53 @@ public class PreservationSVC implements IrisService
@Override
public void onDisable() {
dereferencer.interrupt();
dereference();
for(Thread i : threads)
{
if(i.isAlive())
postShutdown(() -> {
for(Thread i : threads)
{
if(i.isAlive())
{
try
{
i.interrupt();
Iris.info("Shutdown Thread " + i.getName());
}
catch(Throwable e)
{
Iris.reportError(e);
}
}
}
for(MultiBurst i : bursts)
{
try
{
i.interrupt();
Iris.info("Shutdown Thread " + i.getName());
i.shutdownNow();
Iris.info("Shutdown Multiburst " + i);
}
catch(Throwable e)
{
Iris.reportError(e);
}
}
}
for(MultiBurst i : bursts)
{
try
for(ExecutorService i : services)
{
i.shutdownNow();
Iris.info("Shutdown Multiburst " + i);
try
{
i.shutdownNow();
Iris.info("Shutdown Executor Service " + i);
}
catch(Throwable e)
{
Iris.reportError(e);
}
}
catch(Throwable e)
{
}
}
for(ExecutorService i : services)
{
try
{
i.shutdownNow();
Iris.info("Shutdown Executor Service " + i);
}
catch(Throwable e)
{
}
}
dereference();
});
}
}

View File

@ -73,15 +73,27 @@ public class StudioSVC implements IrisService {
@Override
public void onDisable() {
if (IrisSettings.get().isStudio()) {
Iris.debug("Studio Mode Active: Closing Projects");
Iris.debug("Studio Mode Active: Closing Projects");
for (World i : Bukkit.getWorlds()) {
if (IrisToolbelt.isIrisWorld(i)) {
for (World i : Bukkit.getWorlds()) {
if (IrisToolbelt.isIrisWorld(i)) {
if(IrisToolbelt.isStudio(i))
{
IrisToolbelt.evacuate(i);
Iris.debug("Closing Platform Generator " + i.getName());
IrisToolbelt.access(i).close();
}
else
{
if(!IrisSettings.get().getGeneral().isKeepProductionOnReload())
{
IrisToolbelt.evacuate(i);
IrisToolbelt.access(i).close();
Iris.error("You cannot reload Iris while production worlds are active!");
Iris.error("To prevent corrupted chunks, Iris is shutting the server down now!");
Bukkit.shutdown();
}
}
}
}
}

View File

@ -189,4 +189,12 @@ public class IrisToolbelt {
return false;
}
public static boolean isStudio(World i) {
return isIrisWorld(i) && access(i).isStudio();
}
public static boolean isHeadless(World i) {
return isIrisWorld(i) && access(i).isHeadless();
}
}

View File

@ -412,14 +412,14 @@ public class IrisEngine extends BlockPopulator implements Engine {
switch (getDimension().getTerrainMode()) {
case NORMAL -> {
getMantle().generateMatter(x >> 4, z >> 4);
getMantle().generateMatter(x >> 4, z >> 4, multicore);
getTerrainActuator().actuate(x, z, vblocks, multicore);
getBiomeActuator().actuate(x, z, vbiomes, multicore);
getCaveModifier().modify(x, z, vblocks, multicore);
getRavineModifier().modify(x, z, vblocks, multicore);
getPostModifier().modify(x, z, vblocks, multicore);
getDecorantActuator().actuate(x, z, blocks, multicore);
getMantle().insertMatter(x >> 4, z >> 4, BlockData.class, blocks);
getMantle().insertMatter(x >> 4, z >> 4, BlockData.class, blocks, multicore);
getDepositModifier().modify(x, z, blocks, multicore);
}
case ISLANDS -> {

View File

@ -26,9 +26,12 @@ import com.volmit.iris.engine.framework.EngineAssignedActuator;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.biome.IrisBiomeCustom;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.hunk.view.BiomeGridHunkView;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator;
@ -65,41 +68,46 @@ public class IrisBiomeActuator extends EngineAssignedActuator<Biome> {
@Override
public void onActuate(int x, int z, Hunk<Biome> h, boolean multicore) {
PrecisionStopwatch p = PrecisionStopwatch.start();
int zf, maxHeight;
IrisBiome ib;
BurstExecutor burst = burst().burst();
burst.setMulticore(multicore);
for (int xf = 0; xf < h.getWidth(); xf++) {
for (zf = 0; zf < h.getDepth(); zf++) {
ib = getComplex().getTrueBiomeStream().get(modX(xf + x), modZ(zf + z));
maxHeight = (int) (getComplex().getFluidHeight() + ib.getMaxWithObjectHeight(getData()));
if (ib.isCustom()) {
try {
IrisBiomeCustom custom = ib.getCustomBiome(rng, x, 0, z);
Object biomeBase = INMS.get().getCustomBiomeBaseFor(getDimension().getLoadKey() + ":" + custom.getId());
int finalXf = xf;
burst.queue(() -> {
IrisBiome ib;
for (int zf = 0; zf < h.getDepth(); zf++) {
ib = getComplex().getTrueBiomeStream().get(modX(finalXf + x), modZ(zf + z));
int maxHeight = (int) (getComplex().getFluidHeight() + ib.getMaxWithObjectHeight(getData()));
if (ib.isCustom()) {
try {
IrisBiomeCustom custom = ib.getCustomBiome(rng, x, 0, z);
Object biomeBase = INMS.get().getCustomBiomeBaseFor(getDimension().getLoadKey() + ":" + custom.getId());
if (biomeBase == null || !injectBiome(h, x, 0, z, biomeBase)) {
throw new RuntimeException("Cant inject biome!");
}
if (biomeBase == null || !injectBiome(h, x, 0, z, biomeBase)) {
throw new RuntimeException("Cant inject biome!");
}
for (int i = 0; i < maxHeight; i++) {
injectBiome(h, xf, i, zf, biomeBase);
for (int i = 0; i < maxHeight; i++) {
injectBiome(h, finalXf, i, zf, biomeBase);
}
} catch (Throwable e) {
Iris.reportError(e);
Biome v = ib.getSkyBiome(rng, x, 0, z);
for (int i = 0; i < maxHeight; i++) {
h.set(finalXf, i, zf, v);
}
}
} catch (Throwable e) {
Iris.reportError(e);
} else {
Biome v = ib.getSkyBiome(rng, x, 0, z);
for (int i = 0; i < maxHeight; i++) {
h.set(xf, i, zf, v);
h.set(finalXf, i, zf, v);
}
}
} else {
Biome v = ib.getSkyBiome(rng, x, 0, z);
for (int i = 0; i < maxHeight; i++) {
h.set(xf, i, zf, v);
}
}
}
});
}
burst.complete();
getEngine().getMetrics().getBiome().put(p.getMilliseconds());
}
}

View File

@ -18,6 +18,7 @@
package com.volmit.iris.engine.actuator;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.decorator.*;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedActuator;
@ -25,13 +26,16 @@ import com.volmit.iris.engine.framework.EngineDecorator;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.carve.IrisCaveLayer;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
@ -86,72 +90,82 @@ public class IrisDecorantActuator extends EngineAssignedActuator<BlockData> {
}
PrecisionStopwatch p = PrecisionStopwatch.start();
int j, realX, realZ, height;
IrisBiome biome, cave;
BurstExecutor burst = burst().burst();
burst.setMulticore(multicore);
for (int i = 0; i < output.getWidth(); i++) {
for (j = 0; j < output.getDepth(); j++) {
boolean solid, liquid;
int emptyFor = 0;
int liquidFor = 0;
int lastSolid = 0;
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;
int finalI = i;
burst.queue(() -> {
int height;
int realX = (int) Math.round(modX(x + finalI));
int realZ;
IrisBiome biome, cave;
for (int j=0; j < output.getDepth(); j++) {
boolean solid, liquid;
int emptyFor = 0;
int liquidFor = 0;
int lastSolid = 0;
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 (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());
} else if (height == getDimension().getFluidHeight() + 1) {
getSeaSurfaceDecorator().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());
} else if (height < getDimension().getFluidHeight()) {
getSeaFloorDecorator().decorate(i, j, realX, realZ, output, biome, height + 1, getDimension().getFluidHeight() + 1);
}
if(height < getDimension().getFluidHeight())
{
getSeaSurfaceDecorator().decorate(finalI, j,
realX, (int) Math.round(modX(x + finalI + 1)), (int) Math.round(modX(x + finalI - 1)),
realZ, (int) Math.round(modZ(z + j + 1)), (int) Math.round(modZ(z + j - 1)),
output, biome, getDimension().getFluidHeight(), getEngine().getHeight());
getSeaFloorDecorator().decorate(finalI, j,
realX, realZ, output, biome, height + 1,
getDimension().getFluidHeight() + 1);
}
getSurfaceDecorator().decorate(i, j, realX, realZ, output, biome, height, getEngine().getHeight() - height);
if (height == getDimension().getFluidHeight()) {
getShoreLineDecorator().decorate(finalI, j,
realX, (int) Math.round(modX(x + finalI + 1)), (int) Math.round(modX(x + finalI - 1)),
realZ, (int) Math.round(modZ(z + j + 1)), (int) Math.round(modZ(z + j - 1)),
output, biome, height, getEngine().getHeight());
}
getSurfaceDecorator().decorate(finalI, 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));
liquid = PREDICATE_CAVELIQUID.test(output.get(i, k + 1, j), k + 1);
if (cave != null && cave.getDecorators().isNotEmpty()) {
for (int k = height; k > 0; k--) {
solid = PREDICATE_SOLID.test(output.get(finalI, k, j));
liquid = PREDICATE_CAVELIQUID.test(output.get(finalI, k + 1, j), k + 1);
if (solid) {
if (emptyFor > 0) {
if (liquid) {
getSeaFloorDecorator().decorate(i, j, realX, realZ, output, cave, k + 1, liquidFor + lastSolid - emptyFor + 1);
getSeaSurfaceDecorator().decorate(i, j, realX, realZ, output, cave, k + liquidFor + 1, emptyFor - liquidFor + lastSolid);
} else {
getSurfaceDecorator().decorate(i, j, realX, realZ, output, cave, k, lastSolid);
getCeilingDecorator().decorate(i, j, realX, realZ, output, cave, lastSolid - 1, emptyFor);
if (solid) {
if (emptyFor > 0) {
if (liquid) {
getSeaFloorDecorator().decorate(finalI, j, realX, realZ, output, cave, k + 1, liquidFor + lastSolid - emptyFor + 1);
getSeaSurfaceDecorator().decorate(finalI, j, realX, realZ, output, cave, k + liquidFor + 1, emptyFor - liquidFor + lastSolid);
} else {
getSurfaceDecorator().decorate(finalI, j, realX, realZ, output, cave, k, lastSolid);
getCeilingDecorator().decorate(finalI, j, realX, realZ, output, cave, lastSolid - 1, emptyFor);
}
emptyFor = 0;
liquidFor = 0;
}
emptyFor = 0;
liquidFor = 0;
lastSolid = k;
} else {
emptyFor++;
if (liquid) liquidFor++;
}
lastSolid = k;
} else {
emptyFor++;
if (liquid) liquidFor++;
}
}
}
}
});
}
burst.complete();
getEngine().getMetrics().getDecoration().put(p.getMilliseconds());
}
private boolean shouldRayDecorate() {

View File

@ -57,20 +57,15 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<BlockData>
public void onActuate(int x, int z, Hunk<BlockData> h, boolean multicore) {
PrecisionStopwatch p = PrecisionStopwatch.start();
if (multicore) {
BurstExecutor e = getEngine().burst().burst(h.getWidth());
for (int xf = 0; xf < h.getWidth(); xf++) {
int finalXf = xf;
e.queue(() -> terrainSliver(x, z, finalXf, h));
}
e.complete();
} else {
for (int xf = 0; xf < h.getWidth(); xf++) {
terrainSliver(x, z, xf, h);
}
BurstExecutor e = getEngine().burst().burst(h.getWidth());
e.setMulticore(multicore);
for (int xf = 0; xf < h.getWidth(); xf++) {
int finalXf = xf;
e.queue(() -> terrainSliver(x, z, finalXf, h));
}
e.complete();
getEngine().getMetrics().getTerrain().put(p.getMilliseconds());
}

View File

@ -18,6 +18,7 @@
package com.volmit.iris.engine.decorator;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.biome.IrisBiome;

View File

@ -77,10 +77,6 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
}
int stack = decorator.getHeight(getRng().nextParallelRNG(Cache.key(realX, realZ)), realX, realZ, getData());
if (decorator.isScaleStack()) {
int maxStack = max - height;
stack = (int) Math.ceil((double) maxStack * ((double) stack / 100));
} else stack = Math.min(height - max, stack);
if (stack == 1) {
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));

View File

@ -23,6 +23,7 @@ import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.engine.IrisComplex;
import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.parallel.MultiBurst;
import org.bukkit.event.Listener;
public interface EngineComponent {
@ -32,6 +33,11 @@ public interface EngineComponent {
String getName();
default MultiBurst burst()
{
return getEngine().burst();
}
default void close() {
try {
if (this instanceof Listener) {

View File

@ -184,7 +184,7 @@ public interface EngineMantle extends IObjectPlacer {
@ChunkCoordinates
default void generateMatter(int x, int z) {
default void generateMatter(int x, int z, boolean multicore) {
if (!getEngine().getDimension().isUseMantle()) {
return;
}
@ -199,6 +199,7 @@ public interface EngineMantle extends IObjectPlacer {
};
int s = getRealRadius();
BurstExecutor burst = burst().burst();
burst.setMulticore(multicore);
for (int i = -s; i <= s; i++) {
int xx = i + x;
@ -216,7 +217,16 @@ public interface EngineMantle extends IObjectPlacer {
{
KList<Runnable> px = post.copy();
post.clear();
burst().burst(px);
if(multicore)
{
burst().burst(px);
}
else
{
burst().sync(px);
}
}
}
@ -225,7 +235,7 @@ public interface EngineMantle extends IObjectPlacer {
}
@ChunkCoordinates
default <T> void insertMatter(int x, int z, Class<T> t, Hunk<T> blocks) {
default <T> void insertMatter(int x, int z, Class<T> t, Hunk<T> blocks, boolean multicore) {
if (!getEngine().getDimension().isUseMantle()) {
return;
}

View File

@ -18,6 +18,7 @@
package com.volmit.iris.engine.modifier;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedModifier;
import com.volmit.iris.engine.object.biome.IrisBiome;
@ -25,8 +26,11 @@ import com.volmit.iris.engine.object.deposits.IrisDepositGenerator;
import com.volmit.iris.engine.object.objects.IrisObject;
import com.volmit.iris.engine.object.regional.IrisRegion;
import com.volmit.iris.util.data.HeightMap;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import org.bukkit.block.data.BlockData;
import org.bukkit.util.BlockVector;
@ -42,30 +46,32 @@ public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
@Override
public void onModify(int x, int z, Hunk<BlockData> output, boolean multicore) {
PrecisionStopwatch p = PrecisionStopwatch.start();
generateDeposits(rng, output, Math.floorDiv(x, 16), Math.floorDiv(z, 16));
generateDeposits(rng, output, Math.floorDiv(x, 16), Math.floorDiv(z, 16), multicore);
getEngine().getMetrics().getDeposit().put(p.getMilliseconds());
}
public void generateDeposits(RNG rx, Hunk<BlockData> terrain, int x, int z) {
public void generateDeposits(RNG rx, Hunk<BlockData> terrain, int x, int z, boolean multicore) {
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);
BurstExecutor burst = burst().burst();
burst.setMulticore(multicore);
for (IrisDepositGenerator k : getDimension().getDeposits()) {
generate(k, terrain, ro, x, z, false);
burst.queue(() -> 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);
burst.queue(() -> 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);
burst.queue(() -> generate(k, terrain, ro, x, z, false));
}
}
burst.complete();
}
public void generate(IrisDepositGenerator k, Hunk<BlockData> data, RNG rng, int cx, int cz, boolean safe) {

View File

@ -19,14 +19,26 @@
package com.volmit.iris.engine.modifier;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedModifier;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.common.CaveResult;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.function.*;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.hunk.storage.ArrayHunk;
import com.volmit.iris.util.math.Average;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import com.volmit.iris.util.stream.ProceduralStream;
import com.volmit.iris.util.stream.interpolation.Interpolated;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Levelled;
@ -34,9 +46,11 @@ import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.Slab;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class IrisPostModifier extends EngineAssignedModifier<BlockData> {
private static final BlockData AIR = B.get("CAVE_AIR");
private static final BlockData AIR = B.get("AIR");
private static final BlockData WATER = B.get("WATER");
private final RNG rng;
@ -48,15 +62,22 @@ public class IrisPostModifier extends EngineAssignedModifier<BlockData> {
@Override
public void onModify(int x, int z, Hunk<BlockData> output, boolean multicore) {
PrecisionStopwatch p = PrecisionStopwatch.start();
int i;
AtomicInteger i = new AtomicInteger();
AtomicInteger j = new AtomicInteger();
for (i = 0; i < output.getWidth(); i++) {
for (j.set(0); j.get() < output.getDepth(); j.getAndIncrement()) {
post(i, j.get(), output, i + x, j.get() + z);
}
BurstExecutor burst = burst().burst();
burst.setMulticore(multicore);
Hunk<BlockData> sync = output.synchronize();
for (i.set(0); i.get() < output.getWidth(); i.getAndIncrement()) {
burst.queue(() -> {
for (j.set(0); j.get() < output.getDepth(); j.getAndIncrement()) {
int ii = i.get();
int jj = j.get();
post(ii, jj, sync, ii + x, jj + z);
}
});
}
burst.complete();
getEngine().getMetrics().getPost().put(p.getMilliseconds());
}

View File

@ -44,4 +44,8 @@ public class IrisRange {
return rng.d(min, max);
}
public boolean contains(int v) {
return v >= min && v <= max;
}
}

View File

@ -107,7 +107,10 @@ public class IrisDecorator {
return stackMin;
}
return getHeightGenerator(rng, data).fit(stackMin, stackMax, x / heightVariance.getZoom(), z / heightVariance.getZoom()) + 1;
return getHeightGenerator(rng, data)
.fit(stackMin, stackMax,
x / heightVariance.getZoom(),
z / heightVariance.getZoom()) + 1;
}
public CNG getHeightGenerator(RNG rng, IrisData data) {

View File

@ -105,8 +105,24 @@ public class IrisEntitySpawn implements IRare {
};
if (l != null) {
if (spawn100(gen, l) != null)
s++;
if(referenceSpawner.getAllowedLightLevels().getMin() > 0 || referenceSpawner.getAllowedLightLevels().getMax() < 15)
{
if(referenceSpawner.getAllowedLightLevels().contains(l.getBlock().getLightLevel()))
{
if (spawn100(gen, l) != null)
{
s++;
}
}
}
else
{
if (spawn100(gen, l) != null)
{
s++;
}
}
}
}
}

View File

@ -21,6 +21,7 @@ package com.volmit.iris.engine.object.spawners;
import com.volmit.iris.core.project.loader.IrisRegistrant;
import com.volmit.iris.engine.object.annotations.ArrayType;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.basic.IrisRange;
import com.volmit.iris.engine.object.basic.IrisRate;
import com.volmit.iris.engine.object.basic.IrisTimeBlock;
import com.volmit.iris.engine.object.basic.IrisWeather;
@ -32,6 +33,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.bukkit.Bukkit;
import org.bukkit.World;
@EqualsAndHashCode(callSuper = true)
@ -67,6 +69,9 @@ public class IrisSpawner extends IrisRegistrant {
@Desc("The maximum rate this spawner can fire on a specific chunk")
private IrisRate maximumRatePerChunk = new IrisRate();
@Desc("The light levels this spawn is allowed to run in (0-15 inclusive)")
private IrisRange allowedLightLevels = new IrisRange(0, 15);
@Desc("Where should these spawns be placed")
private IrisSpawnGroup group = IrisSpawnGroup.NORMAL;

View File

@ -29,6 +29,7 @@ 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.format.C;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.io.ReactiveFolder;
import com.volmit.iris.util.scheduling.ChronoLatch;
@ -47,6 +48,7 @@ import org.bukkit.generator.ChunkGenerator;
import org.jetbrains.annotations.NotNull;
import javax.management.RuntimeErrorException;
import javax.swing.text.TableView;
import java.io.File;
import java.util.List;
import java.util.Random;
@ -57,7 +59,7 @@ import java.util.concurrent.Semaphore;
public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChunkGenerator {
private static final int LOAD_LOCKS = 1_000_000;
private final Semaphore loadLock;
private final Engine engine;
private Engine engine;
private final IrisWorld world;
private final File dataLocation;
private final String dimensionKey;
@ -66,9 +68,11 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
private final ChronoLatch hotloadChecker;
private final Looper hotloader;
private final boolean studio;
private long lastSeed;
public BukkitChunkGenerator(IrisWorld world, boolean studio, File dataLocation, String dimensionKey) {
populators = new KList<>();
lastSeed = world.seed();
loadLock = new Semaphore(LOAD_LOCKS);
this.world = world;
this.hotloadChecker = new ChronoLatch(1000, false);
@ -76,6 +80,23 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
this.dataLocation = dataLocation;
this.dimensionKey = dimensionKey;
this.folder = new ReactiveFolder(dataLocation, (_a, _b, _c) -> hotload());
setupEngine();
this.hotloader = new Looper() {
@Override
protected long loop() {
if (hotloadChecker.flip()) {
folder.check();
}
return 250;
}
};
hotloader.setPriority(Thread.MIN_PRIORITY);
hotloader.start();
hotloader.setName(getTarget().getWorld().name() + " Hotloader");
}
private void setupEngine() {
IrisData data = IrisData.get(dataLocation);
IrisDimension dimension = data.getDimensionLoader().load(dimensionKey);
@ -113,21 +134,9 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
}
}
this.engine = new IrisEngine(new EngineTarget(world, dimension, data), studio);
engine = new IrisEngine(new EngineTarget(world, dimension, data), studio);
populators.clear();
populators.add((BlockPopulator) engine);
this.hotloader = new Looper() {
@Override
protected long loop() {
if (hotloadChecker.flip()) {
folder.check();
}
return 250;
}
};
hotloader.setPriority(Thread.MIN_PRIORITY);
hotloader.start();
hotloader.setName(getTarget().getWorld().name() + " Hotloader");
}
@Override
@ -161,7 +170,7 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
r.run();
loadLock.release(LOAD_LOCKS);
} catch (Throwable e) {
e.printStackTrace();
Iris.reportError(e);
}
});
}
@ -169,6 +178,15 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
@Override
public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random ignored, int x, int z, @NotNull BiomeGrid biome) {
try {
if(lastSeed != world.getSeed())
{
Iris.warn("Seed for engine " + lastSeed + " does not match world seed if " + world.getSeed());
lastSeed = world.getSeed();
engine.getTarget().getWorld().seed(lastSeed);
engine.hotload();
Iris.success("Updated Engine seed to " + lastSeed);
}
loadLock.acquire();
PrecisionStopwatch ps = PrecisionStopwatch.start();
TerrainChunk tc = TerrainChunk.create(world, biome);
@ -182,6 +200,26 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
return c;
}
catch (WrongEngineBroException e)
{
Iris.warn("Trying to generate with a shut-down engine! Did you reload? Attempting to resolve this...");
try
{
setupEngine();
Iris.success("Resolved! Should generate now!");
}
catch(Throwable fe)
{
Iris.error("FATAL! Iris cannot generate in this world since it was reloaded! This will cause a crash, with missing chunks, so we're crashing right now!");
Bukkit.shutdown();
throw new RuntimeException();
}
return generateChunkData(world, ignored, x, z, biome);
}
catch (Throwable e) {
loadLock.release();
Iris.error("======================================");

View File

@ -1449,4 +1449,9 @@ public interface Hunk<T> {
default boolean isEmpty() {
return false;
}
default boolean contains(int x, int y, int z)
{
return x < getWidth() && x >= 0 && y < getHeight() && y >= 0 && z < getDepth() && z >= 0;
}
}

View File

@ -111,6 +111,17 @@ public class Mantle {
get(x >> 5, z >> 5).getOrCreate(x & 31, z & 31).iterate(type, iterator);
}
@ChunkCoordinates
public <T> void iterateChunk(int x, int z, Class<T> type, Consumer4<Integer, Integer, Integer, T> iterator, BurstExecutor e, MantleFlag... requiredFlags) {
for (MantleFlag i : requiredFlags) {
if (!hasFlag(x, z, i)) {
return;
}
}
get(x >> 5, z >> 5).getOrCreate(x & 31, z & 31).iterate(type, iterator, e);
}
@ChunkCoordinates
public boolean hasFlag(int x, int z, MantleFlag flag) {
return get(x >> 5, z >> 5).getOrCreate(x & 31, z & 31).isFlagged(flag);
@ -207,7 +218,16 @@ public class Mantle {
});
}
b.complete();
try
{
b.complete();
}
catch(Throwable e)
{
Iris.reportError(e);
}
ioBurst.shutdownNow();
Iris.debug("The Mantle has Closed " + C.DARK_AQUA + dataFolder.getAbsolutePath());
}

View File

@ -23,6 +23,8 @@ import com.volmit.iris.util.function.Consumer4;
import com.volmit.iris.util.matter.IrisMatter;
import com.volmit.iris.util.matter.Matter;
import com.volmit.iris.util.matter.MatterSlice;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@ -184,6 +186,26 @@ public class MantleChunk {
}
}
public <T> void iterate(Class<T> type, Consumer4<Integer, Integer, Integer, T> iterator, BurstExecutor burst) {
for (int i = 0; i < sections.length(); i++) {
int finalI = i;
burst.queue(() -> {
int bs = (finalI << 4);
Matter matter = get(finalI);
if (matter != null) {
MatterSlice<T> t = matter.getSlice(type);
if (t != null) {
t.iterateSync((a, b, c, f) -> iterator.accept(a, b + bs, c, f));
}
}
});
}
burst.complete();
}
public <T> void iterate(Class<T> type, Consumer4<Integer, Integer, Integer, T> iterator) {
for (int i = 0; i < sections.length(); i++) {
int bs = (i << 4);

View File

@ -20,6 +20,7 @@ package com.volmit.iris.util.parallel;
import com.volmit.iris.Iris;
import com.volmit.iris.util.collection.KList;
import lombok.Setter;
import java.util.List;
import java.util.concurrent.*;
@ -28,6 +29,8 @@ import java.util.concurrent.*;
public class BurstExecutor {
private final ExecutorService executor;
private final KList<CompletableFuture<Void>> futures;
@Setter
private boolean multicore = true;
public BurstExecutor(ExecutorService executor, int burstSizeEstimate) {
this.executor = executor;
@ -36,6 +39,12 @@ public class BurstExecutor {
@SuppressWarnings("UnusedReturnValue")
public CompletableFuture<Void> queue(Runnable r) {
if(!multicore)
{
r.run();
return null;
}
synchronized (futures) {
CompletableFuture<Void> c = CompletableFuture.runAsync(r, executor);
futures.add(c);
@ -44,6 +53,16 @@ public class BurstExecutor {
}
public BurstExecutor queue(List<Runnable> r) {
if(!multicore)
{
for(Runnable i : r)
{
i.run();
}
return this;
}
synchronized (futures) {
for (Runnable i : new KList<>(r)) {
CompletableFuture<Void> c = CompletableFuture.runAsync(i, executor);
@ -55,6 +74,16 @@ public class BurstExecutor {
}
public BurstExecutor queue(Runnable[] r) {
if(!multicore)
{
for(Runnable i : r)
{
i.run();
}
return this;
}
synchronized (futures) {
for (Runnable i : r) {
CompletableFuture<Void> c = CompletableFuture.runAsync(i, executor);
@ -66,6 +95,11 @@ public class BurstExecutor {
}
public void complete() {
if(!multicore)
{
return;
}
synchronized (futures) {
if (futures.isEmpty()) {
return;
@ -75,13 +109,17 @@ public class BurstExecutor {
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).get();
futures.clear();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
Iris.reportError(e);
}
}
}
public boolean complete(long maxDur) {
if(!multicore)
{
return true;
}
synchronized (futures) {
if (futures.isEmpty()) {
return true;

View File

@ -21,6 +21,7 @@ package com.volmit.iris.util.parallel;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.service.PreservationSVC;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.io.InstanceState;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.scheduling.J;
@ -111,6 +112,12 @@ public class MultiBurst {
}
}
public void sync(KList<Runnable> r) {
for (Runnable i : r) {
i.run();
}
}
public BurstExecutor burst(int estimate) {
return new BurstExecutor(getService(), estimate);
}
@ -159,16 +166,30 @@ public class MultiBurst {
public void shutdownLater() {
if (service != null) {
service.submit(() -> {
J.sleep(3000);
try
{
service.submit(() -> {
J.sleep(3000);
Iris.debug("Shutting down MultiBurst Pool " + heartbeat.getName() + ".");
if (service != null) {
service.shutdown();
}
});
heartbeat.interrupt();
}
catch(Throwable e)
{
Iris.debug("Shutting down MultiBurst Pool " + heartbeat.getName() + ".");
if (service != null) {
service.shutdown();
}
});
heartbeat.interrupt();
heartbeat.interrupt();
}
}
}

View File

@ -18,10 +18,16 @@
package com.volmit.iris.util.plugin;
import com.volmit.iris.Iris;
import org.bukkit.event.Listener;
public interface IrisService extends Listener {
void onEnable();
void onDisable();
default void postShutdown(Runnable r)
{
Iris.instance.postShutdown(r);
}
}

View File

@ -226,7 +226,7 @@ public class VolmitSender implements CommandSender {
}
public static String pulse(double speed) {
return Form.f(invertSpread((((getTick() * 15D * speed) % 1000D) / 1000D)), 3).replaceAll("\\Q,\\E", ".");
return Form.f(invertSpread((((getTick() * 15D * speed) % 1000D) / 1000D)), 3).replaceAll("\\Q,\\E", ".").replaceAll("\\Q?\\E", "-");
}
public static double invertSpread(double v) {