Engine fixes

This commit is contained in:
Daniel Mills 2021-08-08 07:50:55 -04:00
parent 69cbb262ba
commit b081bbb444
13 changed files with 623 additions and 62 deletions

View File

@ -30,9 +30,10 @@ import com.volmit.iris.core.link.OraxenLink;
import com.volmit.iris.core.nms.INMS; import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.project.loader.IrisData; import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.EngineCompositeGenerator; import com.volmit.iris.engine.platform.BukkitChunkGenerator;
import com.volmit.iris.engine.object.biome.IrisBiome; import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.biome.IrisBiomeCustom; import com.volmit.iris.engine.object.biome.IrisBiomeCustom;
import com.volmit.iris.engine.object.common.IrisWorld;
import com.volmit.iris.engine.object.compat.IrisCompat; import com.volmit.iris.engine.object.compat.IrisCompat;
import com.volmit.iris.engine.object.dimensional.IrisDimension; import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
@ -435,7 +436,23 @@ public class Iris extends VolmitPlugin implements Listener {
Iris.info("Generator ID: " + id + " requested by bukkit/plugin. Assuming IrisDimension: " + id); Iris.info("Generator ID: " + id + " requested by bukkit/plugin. Assuming IrisDimension: " + id);
} }
return new EngineCompositeGenerator(dimension, true); IrisDimension d = IrisData.loadAnyDimension(dimension);
if(d == null)
{
throw new RuntimeException("Can't find dimension " + dimension + "!");
}
IrisWorld w = IrisWorld.builder()
.name(worldName)
.seed(RNG.r.lmax())
.environment(d.getEnvironment())
.worldFolder(new File(worldName))
.minHeight(0)
.maxHeight(256)
.build();
return new BukkitChunkGenerator(w, false, new File(w.worldFolder(), "iris"), dimension);
} }
public static void msg(String string) { public static void msg(String string) {

View File

@ -38,9 +38,14 @@ import com.volmit.iris.engine.object.decoration.IrisDecorator;
import com.volmit.iris.engine.object.engine.IrisEngineData; import com.volmit.iris.engine.object.engine.IrisEngineData;
import com.volmit.iris.engine.object.objects.IrisObjectPlacement; import com.volmit.iris.engine.object.objects.IrisObjectPlacement;
import com.volmit.iris.engine.scripting.EngineExecutionEnvironment; import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
import com.volmit.iris.util.atomics.AtomicRollingSequence;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.context.IrisContext; import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.documentation.BlockCoordinates; import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.documentation.ChunkCoordinates; import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.hunk.Hunk; import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.io.IO; import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
@ -49,10 +54,12 @@ import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch; import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import java.io.File; import java.io.File;
@ -63,19 +70,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Data @Data
public class IrisEngine extends BlockPopulator implements Engine { public class IrisEngine extends BlockPopulator implements Engine {
private final EngineCompound compound; // TODO: Remove block population, stop using bukkit
private final EngineTarget target; private final EngineTarget target;
private final IrisContext context; private final IrisContext context;
private final EngineEffects effects; private final EngineEffects effects;
private final EngineExecutionEnvironment execution; private final EngineExecutionEnvironment execution;
private final EngineWorldManager worldManager; private final EngineWorldManager worldManager;
private volatile int parallelism; private volatile int parallelism;
private final int index;
private final EngineMetrics metrics; private final EngineMetrics metrics;
private volatile int minHeight; private volatile int minHeight;
private boolean failing; private boolean failing;
private boolean closed; private boolean closed;
private int cacheId; private int cacheId;
private final AtomicRollingSequence wallClock;
private final int art; private final int art;
private double maxBiomeObjectDensity; private double maxBiomeObjectDensity;
private double maxBiomeLayerDensity; private double maxBiomeLayerDensity;
@ -94,19 +101,19 @@ public class IrisEngine extends BlockPopulator implements Engine {
private final AtomicBoolean cleaning; private final AtomicBoolean cleaning;
private final ChronoLatch cleanLatch; private final ChronoLatch cleanLatch;
public IrisEngine(EngineTarget target, EngineCompound compound, int index) { public IrisEngine(EngineTarget target) {
wallClock = new AtomicRollingSequence(32);
execution = new IrisExecutionEnvironment(this); execution = new IrisExecutionEnvironment(this);
Iris.info("Initializing Engine: " + target.getWorld().name() + "/" + target.getDimension().getLoadKey() + " (" + target.getHeight() + " height)"); // TODO: HEIGHT ------------------------------------------------------------------------------------------------------>
Iris.info("Initializing Engine: " + target.getWorld().name() + "/" + target.getDimension().getLoadKey() + " (" + 256+ " height)");
metrics = new EngineMetrics(32); metrics = new EngineMetrics(32);
this.target = target; this.target = target;
getData().setEngine(this); getData().setEngine(this);
getEngineData(); getEngineData();
worldManager = new IrisWorldManager(this); worldManager = new IrisWorldManager(this);
this.compound = compound;
minHeight = 0; minHeight = 0;
failing = false; failing = false;
closed = false; closed = false;
this.index = index;
cacheId = RNG.r.nextInt(); cacheId = RNG.r.nextInt();
effects = new IrisEngineEffects(this); effects = new IrisEngineEffects(this);
art = J.ar(effects::tickRandomPlayer, 0); art = J.ar(effects::tickRandomPlayer, 0);
@ -135,7 +142,8 @@ public class IrisEngine extends BlockPopulator implements Engine {
World w = null; World w = null;
return engineData.aquire(() -> { return engineData.aquire(() -> {
File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + "-" + getIndex() + ".json"); //TODO: Method this file
File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + ".json");
if (!f.exists()) { if (!f.exists()) {
try { try {
@ -182,6 +190,63 @@ public class IrisEngine extends BlockPopulator implements Engine {
} }
} }
public void printMetrics(CommandSender sender) {
KMap<String, Double> totals = new KMap<>();
KMap<String, Double> weights = new KMap<>();
double masterWallClock = wallClock.getAverage();
KMap<String, Double> timings = getMetrics().pull();
double totalWeight = 0;
double wallClock = getMetrics().getTotal().getAverage();
for (double j : timings.values()) {
totalWeight += j;
}
for (String j : timings.k()) {
weights.put(getName() + "." + j, (wallClock / totalWeight) * timings.get(j));
}
totals.put(getName(), wallClock);
double mtotals = 0;
for (double i : totals.values()) {
mtotals += i;
}
for (String i : totals.k()) {
totals.put(i, (masterWallClock / mtotals) * totals.get(i));
}
double v = 0;
for (double i : weights.values()) {
v += i;
}
for (String i : weights.k()) {
weights.put(i, weights.get(i) / v);
}
sender.sendMessage("Total: " + C.BOLD + C.WHITE + Form.duration(masterWallClock, 0));
for (String i : totals.k()) {
sender.sendMessage(" Engine " + C.UNDERLINE + C.GREEN + i + C.RESET + ": " + C.BOLD + C.WHITE + Form.duration(totals.get(i), 0));
}
sender.sendMessage("Details: ");
for (String i : weights.sortKNumber().reverse()) {
String befb = C.UNDERLINE + "" + C.GREEN + "" + i.split("\\Q[\\E")[0] + C.RESET + C.GRAY + "[";
String num = C.GOLD + i.split("\\Q[\\E")[1].split("]")[0] + C.RESET + C.GRAY + "].";
String afb = C.ITALIC + "" + C.AQUA + i.split("\\Q]\\E")[1].substring(1) + C.RESET + C.GRAY;
sender.sendMessage(" " + befb + num + afb + ": " + C.BOLD + C.WHITE + Form.pc(weights.get(i), 0));
}
}
@Override @Override
public void close() { public void close() {
J.car(art); J.car(art);
@ -249,7 +314,7 @@ public class IrisEngine extends BlockPopulator implements Engine {
return z / getDimension().getTerrainZoom(); return z / getDimension().getTerrainZoom();
} }
@ChunkCoordinates @BlockCoordinates
@Override @Override
public void generate(int x, int z, Hunk<BlockData> vblocks, Hunk<Biome> vbiomes, boolean multicore) { public void generate(int x, int z, Hunk<BlockData> vblocks, Hunk<Biome> vbiomes, boolean multicore) {
context.touch(); context.touch();
@ -284,7 +349,8 @@ public class IrisEngine extends BlockPopulator implements Engine {
@Override @Override
public void saveEngineData() { public void saveEngineData() {
File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + "-" + getIndex() + ".json"); //TODO: Method this file
File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + ".json");
f.getParentFile().mkdirs(); f.getParentFile().mkdirs();
try { try {
IO.writeAll(f, new Gson().toJson(getEngineData())); IO.writeAll(f, new Gson().toJson(getEngineData()));
@ -304,6 +370,7 @@ public class IrisEngine extends BlockPopulator implements Engine {
return getData().getBiomeLoader().load(getDimension().getFocus()); return getData().getBiomeLoader().load(getDimension().getFocus());
} }
// TODO: Remove block population
@ChunkCoordinates @ChunkCoordinates
@Override @Override
public void populate(World world, Random random, Chunk c) { public void populate(World world, Random random, Chunk c) {

View File

@ -25,6 +25,7 @@ import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.engine.IrisComplex; import com.volmit.iris.engine.IrisComplex;
import com.volmit.iris.engine.data.cache.Cache; import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.object.basic.IrisColor; import com.volmit.iris.engine.object.basic.IrisColor;
import com.volmit.iris.engine.object.basic.IrisPosition;
import com.volmit.iris.engine.object.biome.IrisBiome; import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.common.IrisWorld; import com.volmit.iris.engine.object.common.IrisWorld;
import com.volmit.iris.engine.object.dimensional.IrisDimension; import com.volmit.iris.engine.object.dimensional.IrisDimension;
@ -37,6 +38,7 @@ import com.volmit.iris.engine.object.regional.IrisRegion;
import com.volmit.iris.engine.parallax.ParallaxAccess; import com.volmit.iris.engine.parallax.ParallaxAccess;
import com.volmit.iris.engine.scripting.EngineExecutionEnvironment; import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.context.IrisContext; import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.data.B; import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.DataProvider; import com.volmit.iris.util.data.DataProvider;
@ -54,6 +56,7 @@ import org.bukkit.Material;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -61,10 +64,13 @@ import org.bukkit.inventory.ItemStack;
import java.awt.*; import java.awt.*;
import java.util.Arrays; import java.util.Arrays;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer;
public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootProvider, BlockUpdater, Renderer, Hotloadable { public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootProvider, BlockUpdater, Renderer {
IrisComplex getComplex(); IrisComplex getComplex();
void printMetrics(CommandSender sender);
void recycle(); void recycle();
EngineParallaxManager getEngineParallax(); EngineParallaxManager getEngineParallax();
@ -111,9 +117,10 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
void setMinHeight(int min); void setMinHeight(int min);
int getIndex(); default int getMinHeight()
{
int getMinHeight(); return getTarget().getWorld().minHeight();
}
@BlockCoordinates @BlockCoordinates
double modifyX(double x); double modifyX(double x);
@ -121,7 +128,7 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
@BlockCoordinates @BlockCoordinates
double modifyZ(double z); double modifyZ(double z);
@ChunkCoordinates @BlockCoordinates
void generate(int x, int z, Hunk<BlockData> blocks, Hunk<Biome> biomes, boolean multicore); void generate(int x, int z, Hunk<BlockData> blocks, Hunk<Biome> biomes, boolean multicore);
EngineMetrics getMetrics(); EngineMetrics getMetrics();
@ -143,10 +150,6 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
return getDimension().getName(); return getDimension().getName();
} }
default int getHeight() {
return getTarget().getHeight();
}
default IrisData getData() { default IrisData getData() {
return getTarget().getData(); return getTarget().getData();
} }
@ -168,7 +171,7 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
IrisRegion region = getRegion((int) x, (int) z); IrisRegion region = getRegion((int) x, (int) z);
IrisBiome biome = getSurfaceBiome((int) x, (int) z); IrisBiome biome = getSurfaceBiome((int) x, (int) z);
int height = getHeight((int) x, (int) z); int height = getHeight((int) x, (int) z);
double heightFactor = M.lerpInverse(0, getHeight(), height); double heightFactor = M.lerpInverse(0, getTarget().getHeight(), height);
Color irc = region.getColor(this.getComplex(), RenderType.BIOME); Color irc = region.getColor(this.getComplex(), RenderType.BIOME);
Color ibc = biome.getColor(this, RenderType.BIOME); Color ibc = biome.getColor(this, RenderType.BIOME);
Color rc = irc != null ? irc : Color.GREEN.darker(); Color rc = irc != null ? irc : Color.GREEN.darker();
@ -404,18 +407,8 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
scramble(inv, rng); scramble(inv, rng);
} }
default int getMaxHeight() {
return getHeight() + getMinHeight();
}
EngineEffects getEffects(); EngineEffects getEffects();
EngineCompound getCompound();
default boolean isStudio() {
return getCompound().isStudio();
}
default MultiBurst burst() { default MultiBurst burst() {
return getTarget().getBurster(); return getTarget().getBurster();
} }
@ -434,11 +427,6 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
return getRegion(l.getBlockX(), l.getBlockZ()); return getRegion(l.getBlockX(), l.getBlockZ());
} }
@BlockCoordinates
default boolean contains(Location l) {
return l.getBlockY() >= getMinHeight() && l.getBlockY() <= getMaxHeight();
}
IrisBiome getFocus(); IrisBiome getFocus();
IrisEngineData getEngineData(); IrisEngineData getEngineData();
@ -450,4 +438,34 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
default IrisRegion getRegion(Chunk c) { default IrisRegion getRegion(Chunk c) {
return getRegion((c.getX() << 4) + 8, (c.getZ() << 4) + 8); return getRegion((c.getX() << 4) + 8, (c.getZ() << 4) + 8);
} }
default KList<IrisBiome> getAllBiomes() {
KMap<String, IrisBiome> v = new KMap<>();
IrisDimension dim = getDimension();
dim.getAllBiomes(this).forEach((i) -> v.put(i.getLoadKey(), i));
try {
dim.getDimensionalComposite().forEach((m) -> getData().getDimensionLoader().load(m.getDimension()).getAllBiomes(this).forEach((i) -> v.put(i.getLoadKey(), i)));
} catch (Throwable ignored) {
Iris.reportError(ignored);
}
return v.v();
}
int getGenerated();
default IrisPosition lookForBiome(IrisBiome biome, int checks, Consumer<Integer> progress)
{
return null;
}
default IrisPosition lookForRegion(IrisRegion biome, int checks, Consumer<Integer> progress)
{
return null;
}
double getGeneratedPerSecond();
} }

View File

@ -24,6 +24,7 @@ import com.volmit.iris.engine.object.common.IrisWorld;
import com.volmit.iris.engine.object.dimensional.IrisDimension; import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.engine.parallax.ParallaxWorld; import com.volmit.iris.engine.parallax.ParallaxWorld;
import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.parallel.MultiBurst;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import java.io.File; import java.io.File;
@ -34,24 +35,24 @@ public class EngineTarget {
private final MultiBurst burster; private final MultiBurst burster;
private final IrisDimension dimension; private final IrisDimension dimension;
private IrisWorld world; private IrisWorld world;
private final int height;
private final IrisData data; private final IrisData data;
private final ParallaxWorld parallaxWorld; private final ParallaxWorld parallaxWorld;
private final boolean inverted;
public EngineTarget(IrisWorld world, IrisDimension dimension, IrisData data, int height, boolean inverted, int threads) { public EngineTarget(IrisWorld world, IrisDimension dimension, IrisData data) {
this.world = world; this.world = world;
this.height = height;
this.dimension = dimension; this.dimension = dimension;
this.data = data; this.data = data;
this.inverted = inverted; this.burster = new MultiBurst("Iris Engine " + dimension.getName(),
this.burster = new MultiBurst("Iris Engine " + dimension.getName(), IrisSettings.get().getConcurrency().getEngineThreadPriority(), threads); IrisSettings.get().getConcurrency().getEngineThreadPriority(),
IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getEngineThreadCount()));
this.parallaxBurster = new MultiBurst("Iris Parallax Engine " + dimension.getName(), 3, 4); this.parallaxBurster = new MultiBurst("Iris Parallax Engine " + dimension.getName(), 3, 4);
this.parallaxWorld = new ParallaxWorld(parallaxBurster, 256, new File(world.worldFolder(), "iris/" + dimension.getLoadKey() + "/parallax")); this.parallaxWorld = new ParallaxWorld(parallaxBurster, 256, new File(world.worldFolder(),
"iris/" + dimension.getLoadKey() + "/parallax"));
} }
public EngineTarget(IrisWorld world, IrisDimension dimension, IrisData data, int height, int threads) { public int getHeight()
this(world, dimension, data, height, false, threads); {
return world.maxHeight() - world.minHeight();
} }
public void close() { public void close() {

View File

@ -19,9 +19,8 @@
package com.volmit.iris.engine.jigsaw; package com.volmit.iris.engine.jigsaw;
import com.volmit.iris.core.project.loader.IrisData; import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.tools.IrisWorlds; import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.engine.object.basic.IrisPosition; import com.volmit.iris.engine.object.basic.IrisPosition;
import com.volmit.iris.engine.object.common.IObjectPlacer; import com.volmit.iris.engine.object.common.IObjectPlacer;
import com.volmit.iris.engine.object.jigsaw.IrisJigsawPiece; import com.volmit.iris.engine.object.jigsaw.IrisJigsawPiece;
@ -32,6 +31,7 @@ import com.volmit.iris.engine.object.objects.IrisObject;
import com.volmit.iris.engine.object.objects.IrisObjectRotation; import com.volmit.iris.engine.object.objects.IrisObjectRotation;
import com.volmit.iris.engine.object.objects.IrisObjectTranslate; import com.volmit.iris.engine.object.objects.IrisObjectTranslate;
import com.volmit.iris.engine.object.tile.TileData; import com.volmit.iris.engine.object.tile.TileData;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.math.AxisAlignedBB; import com.volmit.iris.util.math.AxisAlignedBB;
import com.volmit.iris.util.math.BlockPosition; import com.volmit.iris.util.math.BlockPosition;
@ -150,13 +150,13 @@ public class PlannedPiece {
} }
public void place(World world) { public void place(World world) {
IrisAccess a = IrisWorlds.access(world); PlatformChunkGenerator a = IrisToolbelt.access(world);
int minY = 0; int minY = 0;
if (a != null) { if (a != null) {
minY = a.getCompound().getDefaultEngine().getMinHeight(); minY = a.getEngine().getMinHeight();
if (!a.getCompound().getRootDimension().isBedrock()) if (!a.getEngine().getDimension().isBedrock())
minY--; //If the dimension has no bedrock, allow it to go a block lower minY--; //If the dimension has no bedrock, allow it to go a block lower
} }
@ -191,7 +191,7 @@ public class PlannedPiece {
IrisLootTable table = getPiece().getPlacementOptions().getTable(block.getBlockData(), getData()); IrisLootTable table = getPiece().getPlacementOptions().getTable(block.getBlockData(), getData());
if (table == null) return; if (table == null) return;
Engine engine = a.getCompound().getEngineForHeight(y); Engine engine = a.getEngine();
engine.addItems(false, ((InventoryHolder) block.getState()).getInventory(), engine.addItems(false, ((InventoryHolder) block.getState()).getInventory(),
rng.nextParallelRNG(BlockPosition.toLong(x, y, z)), rng.nextParallelRNG(BlockPosition.toLong(x, y, z)),
new KList<>(table), InventorySlotType.STORAGE, x, y, z, 15); new KList<>(table), InventorySlotType.STORAGE, x, y, z, 15);

View File

@ -21,9 +21,9 @@ package com.volmit.iris.engine.jigsaw;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.project.loader.IrisData; import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.tools.IrisWorlds; import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineParallaxManager; import com.volmit.iris.engine.framework.EngineParallaxManager;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.engine.object.basic.IrisPosition; import com.volmit.iris.engine.object.basic.IrisPosition;
import com.volmit.iris.engine.object.common.IObjectPlacer; import com.volmit.iris.engine.object.common.IObjectPlacer;
import com.volmit.iris.engine.object.entity.IrisEntity; import com.volmit.iris.engine.object.entity.IrisEntity;
@ -174,7 +174,7 @@ public class PlannedStructure {
Iris.sq(() -> { Iris.sq(() -> {
for (IrisJigsawPieceConnector j : i.getAvailableConnectors()) { for (IrisJigsawPieceConnector j : i.getAvailableConnectors()) {
if (j.getSpawnEntity() != null) { if (j.getSpawnEntity() != null) {
IrisAccess a = IrisWorlds.access(world); Engine a = IrisToolbelt.access(world).getEngine();
if (a == null) { if (a == null) {
Iris.warn("Cannot spawn entities from jigsaw in non Iris world!"); Iris.warn("Cannot spawn entities from jigsaw in non Iris world!");
break; break;
@ -183,7 +183,7 @@ public class PlannedStructure {
IrisEntity e = getData().getEntityLoader().load(j.getSpawnEntity()); IrisEntity e = getData().getEntityLoader().load(j.getSpawnEntity());
if (a != null) { if (a != null) {
Entity entity = e.spawn(a.getCompound().getEngineForHeight(p.getY()), new Location(world, p.getX() + 0.5, p.getY(), p.getZ() + 0.5), rng); Entity entity = e.spawn(a, new Location(world, p.getX() + 0.5, p.getY(), p.getZ() + 0.5), rng);
if (j.isKeepEntity()) { if (j.isKeepEntity()) {
entity.setPersistent(true); entity.setPersistent(true);
} }

View File

@ -22,10 +22,10 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.gui.components.RenderType; import com.volmit.iris.core.gui.components.RenderType;
import com.volmit.iris.core.project.loader.IrisData; import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.project.loader.IrisRegistrant; import com.volmit.iris.core.project.loader.IrisRegistrant;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.IrisComplex; import com.volmit.iris.engine.IrisComplex;
import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.engine.object.annotations.*; import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.engine.object.block.IrisBlockDrops; import com.volmit.iris.engine.object.block.IrisBlockDrops;
import com.volmit.iris.engine.object.common.IRare; import com.volmit.iris.engine.object.common.IRare;
@ -306,7 +306,7 @@ public class IrisBiome extends IrisRegistrant implements IRare {
}); });
} }
public double getHeight(IrisAccess xg, double x, double z, long seed) { public double getHeight(Engine xg, double x, double z, long seed) {
double height = 0; double height = 0;
for (IrisBiomeGeneratorLink i : generators) { for (IrisBiomeGeneratorLink i : generators) {

View File

@ -0,0 +1,89 @@
/*
* 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.object.common;
import com.volmit.iris.Iris;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.platform.HeadlessGenerator;
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.util.plugin.VolmitSender;
import lombok.Data;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import java.io.File;
@Data
@SuppressWarnings("ResultOfMethodCallIgnored")
public class HeadlessWorld {
private final IrisDimension dimension;
private final String worldName;
private final IrisWorld world;
private boolean studio;
public HeadlessWorld(String worldName, IrisDimension dimension, long seed) {
this(worldName, dimension, seed, false);
}
public HeadlessWorld(String worldName, IrisDimension dimension, long seed, boolean studio) {
this.worldName = worldName;
this.dimension = dimension;
this.studio = studio;
world = IrisWorld.builder()
.environment(dimension.getEnvironment())
.worldFolder(new File(worldName))
.seed(seed)
.maxHeight(256)
.minHeight(0)
.name(worldName)
.build();
world.worldFolder().mkdirs();
new File(world.worldFolder(), "region").mkdirs();
if (!studio && !new File(world.worldFolder(), "iris").exists()) {
Iris.proj.installIntoWorld(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag("Headless")), dimension.getLoadKey(), world.worldFolder());
}
}
public HeadlessGenerator generate() {
return new HeadlessGenerator(this);
}
public World load() {
World w = new WorldCreator(worldName)
.environment(dimension.getEnvironment())
.seed(world.seed())
.generator(new BukkitChunkGenerator(world, studio, dimension.getLoader().getDataFolder(),
dimension.getLoadKey()))
.createWorld();
world.realWorld(w);
return w;
}
public static HeadlessWorld from(World world) {
return new HeadlessWorld(world.getName(), IrisToolbelt.access(world).getEngine().getTarget().getDimension(), world.getSeed());
}
public static HeadlessWorld from(String name, String dimension, long seed) {
return new HeadlessWorld(name, IrisData.loadAnyDimension(dimension), seed);
}
}

View File

@ -19,7 +19,7 @@
package com.volmit.iris.engine.object.common; package com.volmit.iris.engine.object.common;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisWorlds; import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
@ -76,11 +76,16 @@ public class IrisWorld {
public void evacuate() { public void evacuate() {
if (hasRealWorld()) { if (hasRealWorld()) {
IrisWorlds.evacuate(realWorld()); IrisToolbelt.evacuate(realWorld());
} }
} }
public void bind(World world) { public void bind(World world) {
if(hasRealWorld())
{
return;
}
bindWorld(this, world); bindWorld(this, world);
} }

View File

@ -0,0 +1,177 @@
/*
* 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.project.loader.IrisData;
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.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;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import org.bukkit.Bukkit;
import org.bukkit.Material;
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 org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChunkGenerator {
private static final BlockData ERROR_BLOCK = Material.RED_GLAZED_TERRACOTTA.createBlockData();
private final AtomicReference<CompletableFuture<Engine>> engine = new AtomicReference<>();
private final AtomicBoolean busy = new AtomicBoolean(false);
private final IrisWorld world;
private final File dataLocation;
private final String dimensionKey;
private final ReactiveFolder folder;
private final KList<BlockPopulator> populators;
private final boolean studio;
public BukkitChunkGenerator(IrisWorld world, boolean studio, File dataLocation, String dimensionKey)
{
populators = new KList<>();
this.world = world;
this.studio = studio;
this.dataLocation = dataLocation;
this.dimensionKey = dimensionKey;
this.folder = new ReactiveFolder(dataLocation, (_a, _b, _c) -> initialize());
initialize();
}
public Engine getEngine()
{
try {
return engine.get().get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return null;
}
@Override
public boolean isHeadless() {
return false;
}
@Override
public void close() {
getEngine().close();
}
@Override
public void hotload() {
initialize();
}
private void initialize()
{
engine.set(MultiBurst.burst.completeValue(() -> createEngine(world, dimensionKey, dataLocation)));
}
private Engine createEngine(IrisWorld world, String dimension, File dataLocation) {
IrisData data = new IrisData(dataLocation);
IrisDimension realDimension = data.getDimensionLoader().load(dimension);
EngineTarget target = new EngineTarget(world, realDimension, data);
Engine engine = new IrisEngine(target);
populators.clear();
populators.add((BlockPopulator) engine);
return engine;
}
@Override
public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random ignored, int x, int z, @NotNull BiomeGrid biome) {
try
{
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);
engine.get().get().generate(x * 16, z * 16, blocks, biomes, true);
return tc.getRaw();
}
catch(Throwable e)
{
Iris.error("======================================");
e.printStackTrace();
Iris.reportErrorChunk(x, z, e, "CHUNK");
Iris.error("======================================");
ChunkData d = Bukkit.createChunkData(world);
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
d.setBlock(i, 0, j, ERROR_BLOCK);
}
}
return d;
}
}
@NotNull
@Override
public List<BlockPopulator> getDefaultPopulators(@NotNull World world) {
return populators;
}
@Override
public boolean isParallelCapable() {
return true;
}
@Override
public boolean shouldGenerateCaves() {
return false;
}
@Override
public boolean shouldGenerateDecorations() {
return false;
}
@Override
public boolean shouldGenerateMobs() {
return false;
}
@Override
public boolean shouldGenerateStructures() {
return false;
}
}

View File

@ -0,0 +1,158 @@
/*
* 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.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;
import com.volmit.iris.util.documentation.RegionCoordinates;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.nbt.mca.MCAUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import lombok.Data;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.generator.ChunkGenerator;
import java.io.File;
import java.io.IOException;
@Data
public class HeadlessGenerator implements PlatformChunkGenerator {
private static final BlockData ERROR_BLOCK = Material.RED_GLAZED_TERRACOTTA.createBlockData();
private static KList<Position2> EMPTYPOINTS = new KList<>();
private final HeadlessWorld world;
private final NBTWorld writer;
private final MultiBurst burst;
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());
engine = new IrisEngine(new EngineTarget(world.getWorld(),world.getDimension(), world.getDimension().getLoader()));
}
@ChunkCoordinates
public void generateChunk(int x, int z) {
try {
int ox = x << 4;
int oz = z << 4;
com.volmit.iris.util.nbt.mca.Chunk chunk = writer.getChunk(x, z);
TerrainChunk tc = MCATerrainChunk.builder()
.writer(writer).ox(ox).oz(oz).mcaChunk(chunk)
.minHeight(world.getWorld().minHeight()).maxHeight(world.getWorld().maxHeight())
.injector((xx, yy, zz, biomeBase) -> chunk.setBiomeAt(ox + xx, yy, oz + zz,
INMS.get().getTrueBiomeBaseId(biomeBase)))
.build();
engine.generate(x * 16, z * 16,
Hunk.view((ChunkGenerator.ChunkData) tc), Hunk.view((ChunkGenerator.BiomeGrid) tc),
false);
} catch (Throwable e) {
Iris.error("======================================");
e.printStackTrace();
Iris.reportErrorChunk(x, z, e, "MCA");
Iris.error("======================================");
com.volmit.iris.util.nbt.mca.Chunk chunk = writer.getChunk(x, z);
CompoundTag c = NBTWorld.getCompound(ERROR_BLOCK);
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
chunk.setBlockStateAt(i, 0, j, c, false);
}
}
}
}
@RegionCoordinates
public void generateRegion(int x, int z) {
generateRegion(x, z, null);
}
@RegionCoordinates
public void generateRegion(int x, int z, PregenListener listener) {
BurstExecutor e = burst.burst(1024);
PregenTask.iterateRegion(x, z, (ii, jj) -> e.queue(() -> {
if (listener != null) {
listener.onChunkGenerating(ii, jj);
}
generateChunk(ii, jj);
if (listener != null) {
listener.onChunkGenerated(ii, jj);
}
}));
e.complete();
}
@RegionCoordinates
public File generateRegionToFile(int x, int z, PregenListener listener) {
generateRegion(x, z, listener);
flush();
return writer.getRegionFile(x, z);
}
public void flush() {
writer.flushNow();
}
public void save() {
writer.save();
}
public void close() {
burst.shutdownAndAwait();
engine.close();
writer.close();
}
public KList<Position2> getChunksInRegion(int x, int z) {
try {
return MCAUtil.sampleChunkPositions(writer.getRegionFile(x, z));
} catch (IOException e) {
e.printStackTrace();
}
return EMPTYPOINTS;
}
@Override
public boolean isHeadless() {
return true;
}
@Override
public void hotload() {
}
}

View File

@ -16,8 +16,31 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.volmit.iris.engine.framework; package com.volmit.iris.engine.platform;
public interface IrisAccessProvider { import com.volmit.iris.core.project.loader.IrisData;
IrisAccess getAccess(); import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineTarget;
import com.volmit.iris.engine.framework.Hotloadable;
import com.volmit.iris.util.data.DataProvider;
public interface PlatformChunkGenerator extends Hotloadable, DataProvider {
Engine getEngine();
boolean isHeadless();
@Override
default IrisData getData()
{
return getEngine().getData();
}
default EngineTarget getTarget()
{
return getEngine().getTarget();
}
void close();
boolean isStudio();
} }

View File

@ -18,6 +18,7 @@
package com.volmit.iris.util.plugin; package com.volmit.iris.util.plugin;
import com.google.common.collect.Comparators;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
@ -26,6 +27,9 @@ import org.bukkit.Sound;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
/** /**
* Represents a pawn command * Represents a pawn command
@ -197,6 +201,8 @@ public abstract class MortarCommand implements ICommand {
} }
} }
p.sort(Comparator.comparing(MortarCommand::getNode));
return p; return p;
} }