Merge pull request #515 from VolmitSoftware/decomposed

The Decomposition of Iris
This commit is contained in:
Dan 2021-08-09 04:40:21 -04:00 committed by GitHub
commit 722190305b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
67 changed files with 1385 additions and 2229 deletions

View File

@ -30,9 +30,11 @@ import com.volmit.iris.core.link.OraxenLink;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.EngineCompositeGenerator;
import com.volmit.iris.engine.object.noise.NoiseStyle;
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
import com.volmit.iris.engine.object.biome.IrisBiome;
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.dimensional.IrisDimension;
import com.volmit.iris.util.collection.KList;
@ -42,9 +44,11 @@ import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.function.NastyRunnable;
import com.volmit.iris.util.io.FileWatcher;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.io.InstanceState;
import com.volmit.iris.util.io.JarScanner;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.noise.CNG;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.plugin.Metrics;
import com.volmit.iris.util.plugin.Permission;
@ -66,6 +70,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.Plugin;
@ -73,6 +78,7 @@ import java.io.*;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.Date;
import java.util.UUID;
@SuppressWarnings("CanBeFinal")
public class Iris extends VolmitPlugin implements Listener {
@ -136,8 +142,46 @@ public class Iris extends VolmitPlugin implements Listener {
splash();
}
public void onDisable() {
if (IrisSettings.get().isStudio()) {
Iris.debug("Studio Mode Active: Closing Projects");
proj.close();
for (World i : Bukkit.getWorlds()) {
if (IrisToolbelt.isIrisWorld(i)) {
Iris.debug("Closing Platform Generator " + i.getName());
IrisToolbelt.access(i).close();
}
}
for (GroupedExecutor i : executors) {
Iris.debug("Closing Executor " + i.toString());
i.closeNow();
}
}
executors.clear();
board.disable();
Iris.debug("Cancelled all tasks");
Bukkit.getScheduler().cancelTasks(this);
Iris.debug("Unregistered all events");
HandlerList.unregisterAll((Plugin) this);
Iris.debug("Multiburst Shutting down");
MultiBurst.burst.shutdown();
Iris.debug("Iris Shutdown");
super.onDisable();
}
public static void callEvent(Event e) {
J.s(() -> Bukkit.getPluginManager().callEvent(e));
if(!e.isAsynchronous())
{
J.s(() -> Bukkit.getPluginManager().callEvent(e));
}
else
{
Bukkit.getPluginManager().callEvent(e);
}
}
public static KList<Object> initialize(String s, Class<? extends Annotation> slicedClass) {
@ -261,29 +305,6 @@ public class Iris extends VolmitPlugin implements Listener {
}
}
public void onDisable() {
if (IrisSettings.get().isStudio()) {
proj.close();
for (World i : Bukkit.getWorlds()) {
if (IrisToolbelt.isIrisWorld(i)) {
IrisToolbelt.access(i).close();
}
}
for (GroupedExecutor i : executors) {
i.close();
}
}
executors.clear();
board.disable();
Bukkit.getScheduler().cancelTasks(this);
HandlerList.unregisterAll((Plugin) this);
MultiBurst.burst.shutdown();
super.onDisable();
}
public static void sq(Runnable r) {
synchronized (syncJobs) {
syncJobs.queue(r);
@ -435,7 +456,23 @@ public class Iris extends VolmitPlugin implements Listener {
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) {
@ -678,4 +715,16 @@ public class Iris extends VolmitPlugin implements Listener {
Iris.debug("Exception Logged: " + e.getClass().getSimpleName() + ": " + C.RESET + "" + C.LIGHT_PURPLE + e.getMessage());
}
}
static {
try
{
InstanceState.updateInstanceId();
}
catch(Throwable e)
{
}
}
}

View File

@ -19,9 +19,8 @@
package com.volmit.iris.core;
import com.volmit.iris.Iris;
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.IrisAccess;
import com.volmit.iris.engine.object.feature.IrisFeaturePositional;
import com.volmit.iris.util.board.BoardManager;
import com.volmit.iris.util.board.BoardProvider;
@ -73,7 +72,7 @@ public class IrisBoardManager implements BoardProvider, Listener {
private boolean isIrisWorld(World w) {
return IrisWorlds.isIrisWorld(w) && IrisWorlds.access(w).isStudio();
return IrisToolbelt.isIrisWorld(w) && IrisToolbelt.access(w).isStudio();
}
public void updatePlayer(Player p) {
@ -102,7 +101,7 @@ public class IrisBoardManager implements BoardProvider, Listener {
return v;
}
IrisAccess g = IrisWorlds.access(player.getWorld());
Engine engine = IrisToolbelt.access(player.getWorld()).getEngine();
if (cl.flip()) {
// TODO MEMORY
@ -113,12 +112,6 @@ public class IrisBoardManager implements BoardProvider, Listener {
int y = player.getLocation().getBlockY();
int z = player.getLocation().getBlockZ();
if (g.getCompound() == null) {
v.add("Loading...");
return v;
}
Engine engine = g.getCompound().getEngineForHeight(y);
if (ecl.flip()) {
energyBar.setProgress(Math.min(1000D, engine.getWorldManager().getEnergy()) / 1000D);
energyBar.setTitle("Spawner Energy: " + Form.f((int) Math.min(1000D, engine.getWorldManager().getEnergy())));
@ -129,27 +122,24 @@ public class IrisBoardManager implements BoardProvider, Listener {
long memoryGuess = 0;
int loadedObjects = 0;
for (int i = 0; i < g.getCompound().getSize(); i++) {
parallaxRegions += g.getCompound().getEngine(i).getParallax().getRegionCount();
parallaxChunks += g.getCompound().getEngine(i).getParallax().getChunkCount();
loadedObjects += g.getCompound().getData().getObjectLoader().getSize();
memoryGuess += g.getCompound().getData().getObjectLoader().getTotalStorage() * 225L;
memoryGuess += parallaxChunks * 3500L;
memoryGuess += parallaxRegions * 1700000L;
}
parallaxRegions +=engine.getParallax().getRegionCount();
parallaxChunks += engine.getParallax().getChunkCount();
loadedObjects += engine.getData().getObjectLoader().getSize();
memoryGuess += engine.getData().getObjectLoader().getTotalStorage() * 225L;
memoryGuess += parallaxChunks * 3500L;
memoryGuess += parallaxRegions * 1700000L;
tp.put(0); // TODO: CHUNK SPEED
v.add("&7&m------------------");
v.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(g.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / g.getGeneratedPerSecond(), 0));
v.add(C.GREEN + "Speed" + C.GRAY + ": " + Form.f(engine.getGeneratedPerSecond(), 0) + "/s " + Form.duration(1000D / engine.getGeneratedPerSecond(), 0));
v.add(C.GREEN + "Memory Use" + C.GRAY + ": ~" + Form.memSize(memoryGuess, 0));
if (engine != null) {
v.add("&7&m------------------");
KList<IrisFeaturePositional> f = new KList<>();
f.add(engine.getEngineParallax().forEachFeature(x, z));
v.add(C.AQUA + "Engine" + C.GRAY + ": " + engine.getName() + " " + engine.getMinHeight() + "-" + engine.getMaxHeight());
v.add(C.AQUA + "Region" + C.GRAY + ": " + engine.getRegion(x, z).getName());
v.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiome(x, y, z).getName());
v.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z)));

View File

@ -356,6 +356,7 @@ public class ProjectManager {
public void close() {
if (isProjectOpen()) {
Iris.debug("Closing Active Project");
activeProject.close();
activeProject = null;
}

View File

@ -22,7 +22,6 @@ 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.framework.Engine;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.common.IObjectPlacer;
import com.volmit.iris.engine.object.objects.IrisObject;
@ -31,6 +30,7 @@ import com.volmit.iris.engine.object.regional.IrisRegion;
import com.volmit.iris.engine.object.tile.TileData;
import com.volmit.iris.engine.object.trees.IrisTreeModes;
import com.volmit.iris.engine.object.trees.IrisTreeSize;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.data.Cuboid;
@ -82,26 +82,14 @@ public class TreeManager implements Listener {
return;
}
IrisAccess worldAccess = IrisToolbelt.access(event.getWorld());
PlatformChunkGenerator worldAccess = IrisToolbelt.access(event.getWorld());
if (worldAccess == null) {
Iris.debug(this.getClass().getName() + " passed it off to vanilla because could not get IrisAccess for this world");
Iris.reportError(new NullPointerException(event.getWorld().getName() + " could not be accessed despite being an Iris world"));
return;
}
if (worldAccess.getCompound() == null) {
Iris.debug(this.getClass().getName() + " passed off to vanilla because dimension compound is null");
Iris.reportError(new NullPointerException(event.getWorld().getName() + " is accessible but does not have compound"));
return;
}
if (worldAccess.getCompound().getRootDimension() == null) {
Iris.debug(this.getClass().getName() + " passed off to vanilla because compound's root dimension is null");
Iris.reportError(new NullPointerException(event.getWorld().getName() + " is accessible & has compound but has no root dimension"));
return;
}
if (!worldAccess.getCompound().getRootDimension().getTreeSettings().isEnabled()) {
if (!worldAccess.getEngine().getDimension().getTreeSettings().isEnabled()) {
Iris.debug(this.getClass().getName() + " cancelled because tree overrides are disabled");
return;
}
@ -166,13 +154,7 @@ public class TreeManager implements Listener {
@Override
public int getFluidHeight() {
Engine engine;
if (worldAccess.getCompound().getSize() > 1) {
engine = worldAccess.getCompound().getEngine(0);
} else {
engine = (Engine) worldAccess.getCompound().getRootDimension();
}
return engine.getDimension().getFluidHeight();
return worldAccess.getEngine().getDimension().getFluidHeight();
}
@Override
@ -226,18 +208,18 @@ public class TreeManager implements Listener {
* @param size The size of the sapling area
* @return An object placement which contains the matched tree, or null if none were found / it's disabled.
*/
private IrisObjectPlacement getObjectPlacement(IrisAccess worldAccess, Location location, TreeType type, IrisTreeSize size) {
private IrisObjectPlacement getObjectPlacement(PlatformChunkGenerator worldAccess, Location location, TreeType type, IrisTreeSize size) {
KList<IrisObjectPlacement> placements = new KList<>();
boolean isUseAll = ((Engine) worldAccess.getEngineAccess(location.getBlockY())).getDimension().getTreeSettings().getMode().equals(IrisTreeModes.ALL);
boolean isUseAll = worldAccess.getEngine().getDimension().getTreeSettings().getMode().equals(IrisTreeModes.ALL);
// Retrieve objectPlacements of type `species` from biome
IrisBiome biome = worldAccess.getBiome(location.getBlockX(), location.getBlockY(), location.getBlockZ());
IrisBiome biome = worldAccess.getEngine().getBiome(location.getBlockX(), location.getBlockY(), location.getBlockZ());
placements.addAll(matchObjectPlacements(biome.getObjects(), size, type));
// Add more or find any in the region
if (isUseAll || placements.isEmpty()) {
IrisRegion region = worldAccess.getCompound().getEngineForHeight(location.getBlockY()).getRegion(location.getBlockX(), location.getBlockZ());
IrisRegion region = worldAccess.getEngine().getRegion(location.getBlockX(), location.getBlockZ());
placements.addAll(matchObjectPlacements(region.getObjects(), size, type));
}

View File

@ -24,7 +24,8 @@ public class VillagerManager implements Listener {
return;
}
IrisVillagerOverride override = IrisToolbelt.access(event.getEntity().getWorld()).getCompound().getRootDimension().getPatchCartographers();
IrisVillagerOverride override = IrisToolbelt.access(event.getEntity().getWorld()).getEngine()
.getDimension().getPatchCartographers();
if (override.isDisableTrade()) {
event.setCancelled(true);

View File

@ -41,8 +41,8 @@ public class CommandIrisDebugSpawnerBoost extends MortarCommand {
@Override
public boolean handle(VolmitSender sender, String[] args) {
((IrisEngine)
IrisToolbelt.access(sender.player().getWorld()).getEngineAccess(sender.player().getLocation().getBlockY())).getWorldManager().chargeEnergy();
IrisToolbelt.access(sender.player().getWorld()).getEngine().getWorldManager().chargeEnergy();
return true;
}

View File

@ -19,8 +19,9 @@
package com.volmit.iris.core.command;
import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisWorlds;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.IrisEngine;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.plugin.MortarCommand;
import com.volmit.iris.util.plugin.VolmitSender;
@ -46,12 +47,12 @@ public class CommandIrisMetrics extends MortarCommand {
if (sender.isPlayer()) {
Player p = sender.player();
World world = p.getWorld();
if (!IrisWorlds.isIrisWorld(world)) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender.sendMessage("You must be in an iris world.");
return true;
}
IrisAccess g = IrisWorlds.access(world);
Engine g = IrisToolbelt.access(world).getEngine();
try {
g.printMetrics(sender);

View File

@ -21,7 +21,7 @@ package com.volmit.iris.core.command.jigsaw;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
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.jigsaw.PlannedStructure;
import com.volmit.iris.engine.object.basic.IrisPosition;
import com.volmit.iris.engine.object.jigsaw.IrisJigsawStructure;
@ -42,8 +42,8 @@ public class CommandIrisJigsawPlace extends MortarCommand {
@Override
public void addTabOptions(VolmitSender sender, String[] args, KList<String> list) {
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisWorlds.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisWorlds.access(sender.player().getWorld()).getData();
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisToolbelt.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisToolbelt.access(sender.player().getWorld()).getEngine().getData();
if (data == null) {
sender.sendMessage("Tab complete options only work for jigsaw structures while in an Iris world.");
} else if (args.length == 0) {

View File

@ -4,7 +4,7 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ProjectManager;
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.object.objects.IrisObject;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.plugin.MortarCommand;
@ -31,8 +31,8 @@ public class CommandIrisObjectAnalyze extends MortarCommand {
@Override
public void addTabOptions(VolmitSender sender, String[] args, KList<String> list) {
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisWorlds.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisWorlds.access(sender.player().getWorld()).getData();
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisToolbelt.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisToolbelt.access(sender.player().getWorld()).getEngine().getData();
if (data == null) {
sender.sendMessage("Tab complete options only work for objects while in an Iris world.");
} else if (args.length == 0) {

View File

@ -23,7 +23,7 @@ import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ProjectManager;
import com.volmit.iris.core.WandManager;
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.object.common.IObjectPlacer;
import com.volmit.iris.engine.object.objects.IrisObject;
import com.volmit.iris.engine.object.objects.IrisObjectPlacement;
@ -57,8 +57,8 @@ public class CommandIrisObjectPaste extends MortarCommand {
@Override
public void addTabOptions(VolmitSender sender, String[] args, KList<String> list) {
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisWorlds.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisWorlds.access(sender.player().getWorld()).getData();
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisToolbelt.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisToolbelt.access(sender.player().getWorld()).getEngine().getData();
if (data == null) {
sender.sendMessage("Tab complete options only work for objects while in an Iris world.");
} else if (args.length == 0) {

View File

@ -21,7 +21,7 @@ package com.volmit.iris.core.command.object;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
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.object.common.IObjectPlacer;
import com.volmit.iris.engine.object.tile.TileData;
import com.volmit.iris.util.collection.KList;
@ -52,8 +52,8 @@ public class CommandIrisObjectPasteMatter extends MortarCommand {
@Override
public void addTabOptions(VolmitSender sender, String[] args, KList<String> list) {
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisWorlds.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisWorlds.access(sender.player().getWorld()).getData();
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisToolbelt.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisToolbelt.access(sender.player().getWorld()).getEngine().getData();
if (data == null) {
sender.sendMessage("Tab complete options only work for objects while in an Iris world.");
} else if (args.length == 0) {

View File

@ -57,7 +57,7 @@ public class CommandIrisStudioEditBiome extends MortarCommand {
Player p = sender.player();
try {
File f = Iris.proj.getActiveProject().getActiveProvider().getBiome(p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ()).getLoadFile();
File f = Iris.proj.getActiveProject().getActiveProvider().getEngine().getBiome(p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ()).getLoadFile();
Desktop.getDesktop().open(f);
} catch (Throwable e) {
Iris.reportError(e);

View File

@ -22,9 +22,8 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.core.tools.IrisWorlds;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.plugin.MortarCommand;
import com.volmit.iris.util.plugin.VolmitSender;
@ -39,8 +38,8 @@ public class CommandIrisStudioExecute extends MortarCommand {
@Override
public void addTabOptions(VolmitSender sender, String[] args, KList<String> list) {
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisWorlds.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisWorlds.access(sender.player().getWorld()).getData();
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisToolbelt.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisToolbelt.access(sender.player().getWorld()).getEngine().getData();
if (data == null) {
sender.sendMessage("Tab complete options only work for summons while in an Iris world.");
} else if (args.length == 0) {
@ -58,10 +57,10 @@ public class CommandIrisStudioExecute extends MortarCommand {
return true;
}
IrisAccess a = IrisToolbelt.access(sender.player().getWorld());
PlatformChunkGenerator a = IrisToolbelt.access(sender.player().getWorld());
if (a != null) {
((Engine) a.getEngineAccess(0)).getExecution().execute(args[0]);
a.getEngine().getExecution().execute(args[0]);
Iris.info("Executed. See script output in console.");
}

View File

@ -22,7 +22,7 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.gui.NoiseExplorerGUI;
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.object.noise.IrisGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.function.Function2;
@ -42,8 +42,8 @@ public class CommandIrisStudioExplorerGenerator extends MortarCommand {
@Override
public void addTabOptions(VolmitSender sender, String[] args, KList<String> list) {
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisWorlds.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisWorlds.access(sender.player().getWorld()).getData();
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisToolbelt.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisToolbelt.access(sender.player().getWorld()).getData();
if (data == null) {
sender.sendMessage("Issue when loading tab completions. No data found (?)");
} else if (args.length == 0) {

View File

@ -20,8 +20,9 @@ package com.volmit.iris.core.command.studio;
import com.volmit.iris.Iris;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.tools.IrisWorlds;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.basic.IrisPosition;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.jigsaw.IrisJigsawStructure;
import com.volmit.iris.engine.object.regional.IrisRegion;
@ -49,8 +50,8 @@ public class CommandIrisStudioGoto extends MortarCommand {
@Override
public void addTabOptions(VolmitSender sender, String[] args, KList<String> list) {
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisWorlds.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisWorlds.access(sender.player().getWorld()).getData();
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisToolbelt.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisToolbelt.access(sender.player().getWorld()).getEngine().getData();
if (data == null) {
sender.sendMessage("Issue when loading tab completions. No data found (?)");
} else if (args.length == 0) {
@ -75,47 +76,47 @@ public class CommandIrisStudioGoto extends MortarCommand {
Player p = sender.player();
World world = p.getWorld();
if (!IrisWorlds.isIrisWorld(world)) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender.sendMessage("You must be in an iris world.");
return true;
}
IrisAccess g = IrisWorlds.access(world);
Engine g = IrisToolbelt.access(world).getEngine();
IrisBiome b = IrisData.loadAnyBiome(args[0]);
IrisRegion r = IrisData.loadAnyRegion(args[0]);
IrisJigsawStructure s = IrisData.loadAnyJigsawStructure(args[0]);
if (b != null) {
J.a(() -> {
Location l = g.lookForBiome(b, 10000, (v) -> sender.sendMessage("Looking for " + C.BOLD + C.WHITE + b.getName() + C.RESET + C.GRAY + ": Checked " + Form.f(v) + " Places"));
IrisPosition l = g.lookForBiome(b, 10000, (v) -> sender.sendMessage("Looking for " + C.BOLD + C.WHITE + b.getName() + C.RESET + C.GRAY + ": Checked " + Form.f(v) + " Places"));
if (l == null) {
sender.sendMessage("Couldn't find " + b.getName() + ".");
} else {
sender.sendMessage("Found " + b.getName() + "!");
J.s(() -> sender.player().teleport(l));
J.s(() -> sender.player().teleport(l.toLocation(world)));
}
});
} else if (r != null) {
J.a(() -> {
Location l = g.lookForRegion(r, 60000, (v) -> sender.sendMessage(C.BOLD + "" + C.WHITE + r.getName() + C.RESET + C.GRAY + ": Checked " + Form.f(v) + " Places"));
IrisPosition l = g.lookForRegion(r, 60000, (v) -> sender.sendMessage(C.BOLD + "" + C.WHITE + r.getName() + C.RESET + C.GRAY + ": Checked " + Form.f(v) + " Places"));
if (l == null) {
sender.sendMessage("Couldn't find " + r.getName() + ".");
} else {
sender.sendMessage("Found " + r.getName() + "!");
J.s(() -> sender.player().teleport(l));
J.s(() -> sender.player().teleport(l.toLocation(world)));
}
});
} else if (s != null) {
J.a(() -> {
Location l = g.lookForRegion(r, 60000, (v) -> sender.sendMessage(C.BOLD + "" + C.WHITE + r.getName() + C.RESET + C.GRAY + ": Checked " + Form.f(v) + " Places"));
IrisPosition l = g.lookForRegion(r, 60000, (v) -> sender.sendMessage(C.BOLD + "" + C.WHITE + r.getName() + C.RESET + C.GRAY + ": Checked " + Form.f(v) + " Places"));
if (l == null) {
sender.sendMessage("Couldn't find " + r.getName() + ".");
} else {
sender.sendMessage("Found " + r.getName() + "!");
J.s(() -> sender.player().teleport(l));
J.s(() -> sender.player().teleport(l.toLocation(world)));
}
});
} else {

View File

@ -20,11 +20,14 @@ package com.volmit.iris.core.command.studio;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.tools.IrisWorlds;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.plugin.MortarCommand;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
import org.bukkit.World;
import org.bukkit.entity.Player;
@ -57,12 +60,12 @@ public class CommandIrisStudioHotload extends MortarCommand {
Player p = sender.player();
World world = p.getWorld();
if (!IrisWorlds.isIrisWorld(world)) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender.sendMessage("You must be in an iris world.");
return true;
}
IrisAccess worldAccess = IrisWorlds.access(world);
PlatformChunkGenerator worldAccess = IrisToolbelt.access(world);
if (worldAccess == null) {
sender.sendMessage("Could not gain access to the world you are in");
} else {

View File

@ -20,8 +20,8 @@ package com.volmit.iris.core.command.studio;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.tools.IrisWorlds;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.loot.IrisLootTable;
import com.volmit.iris.engine.object.meta.InventorySlotType;
import com.volmit.iris.util.collection.KList;
@ -56,18 +56,18 @@ public class CommandIrisStudioLoot extends MortarCommand {
if (sender.isPlayer()) {
Player p = sender.player();
IrisAccess prov = IrisWorlds.access(sender.player().getWorld());
Engine prov = IrisToolbelt.access(sender.player().getWorld()).getEngine();
if (!Iris.proj.isProjectOpen()) {
sender.sendMessage("You can only use /iris studio loot in a studio world of iris.");
return true;
}
KList<IrisLootTable> tables = prov.getCompound().getEngine(p.getLocation().getBlockY()).getLootTables(RNG.r, p.getLocation().getBlock());
KList<IrisLootTable> tables = prov.getLootTables(RNG.r, p.getLocation().getBlock());
Inventory inv = Bukkit.createInventory(null, 27 * 2);
try {
Iris.proj.getActiveProject().getActiveProvider().getCompound().getEngine(p.getLocation().getBlockY()).addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ(), 1);
Iris.proj.getActiveProject().getActiveProvider().getEngine().addItems(true, inv, RNG.r, tables, InventorySlotType.STORAGE, p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ(), 1);
} catch (Throwable e) {
Iris.reportError(e);
sender.sendMessage("You can only use /iris loot in a studio world of iris.");
@ -109,7 +109,7 @@ public class CommandIrisStudioLoot extends MortarCommand {
inv.clear();
}
Iris.proj.getActiveProject().getActiveProvider().getCompound().getEngine(p.getLocation().getBlockY()).addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ(), 1);
Iris.proj.getActiveProject().getActiveProvider().getEngine().addItems(true, inv, new RNG(RNG.r.imax()), tables, InventorySlotType.STORAGE, p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ(), 1);
}, 0, fast ? 5 : 35));
return true;

View File

@ -21,9 +21,8 @@ package com.volmit.iris.core.command.studio;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.gui.VisionGUI;
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.IrisAccess;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.plugin.MortarCommand;
import com.volmit.iris.util.plugin.VolmitSender;
@ -56,12 +55,12 @@ public class CommandIrisStudioMap extends MortarCommand {
Engine fe;
try {
IrisAccess g = Iris.proj.getActiveProject().getActiveProvider();
Engine g = Iris.proj.getActiveProject().getActiveProvider().getEngine();
VisionGUI.launch(g, 0);
sender.sendMessage("Opening Map!");
} catch (Throwable e) {
Iris.reportError(e);
IrisAccess g = IrisWorlds.access(sender.player().getWorld());
Engine g = IrisToolbelt.access(sender.player().getWorld()).getEngine();
VisionGUI.launch(g, 0);
sender.sendMessage("Opening Map!");
}

View File

@ -21,9 +21,8 @@ package com.volmit.iris.core.command.studio;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
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.IrisAccess;
import com.volmit.iris.engine.object.entity.IrisEntity;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.plugin.MortarCommand;
@ -42,8 +41,8 @@ public class CommandIrisStudioSummon extends MortarCommand {
@Override
public void addTabOptions(VolmitSender sender, String[] args, KList<String> list) {
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisWorlds.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisWorlds.access(sender.player().getWorld()).getData();
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisToolbelt.isIrisWorld(sender.player().getWorld())) {
IrisData data = IrisToolbelt.access(sender.player().getWorld()).getEngine().getData();
if (data == null) {
sender.sendMessage("Tab complete options only work for summons while in an Iris world.");
} else if (args.length == 0) {
@ -64,12 +63,12 @@ public class CommandIrisStudioSummon extends MortarCommand {
if (sender.isPlayer()) {
Player p = sender.player();
World world = p.getWorld();
if (!IrisWorlds.isIrisWorld(world)) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender.sendMessage("You must be in an iris world.");
return true;
}
IrisAccess g = IrisWorlds.access(world);
Engine g = IrisToolbelt.access(world).getEngine();
if (args.length == 0) {
for (String i : g.getData().getEntityLoader().getPossibleKeys()) {
sender.sendMessage("- " + i);
@ -83,7 +82,7 @@ public class CommandIrisStudioSummon extends MortarCommand {
}
Location vl = sender.player().getLocation().clone().add(0, 3, 0);
e.spawn((Engine) g.getEngineAccess(vl.getBlockY()), vl);
e.spawn(g, vl);
}
} else {
sender.sendMessage("Players only.");

View File

@ -20,8 +20,8 @@ package com.volmit.iris.core.command.what;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.tools.IrisWorlds;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.plugin.MortarCommand;
@ -51,7 +51,7 @@ public class CommandIrisWhatBiome extends MortarCommand {
try {
IrisAccess g = IrisWorlds.access(w);
Engine g = IrisToolbelt.access(w).getEngine();
assert g != null;
IrisBiome b = g.getBiome(p.getLocation().getBlockX(), p.getLocation().getBlockY(), p.getLocation().getBlockZ());
sender.sendMessage("IBiome: " + b.getLoadKey() + " (" + b.getDerivative().name() + ")");

View File

@ -20,7 +20,7 @@ package com.volmit.iris.core.command.what;
import com.google.gson.Gson;
import com.volmit.iris.Iris;
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.object.feature.IrisFeaturePositional;
import com.volmit.iris.util.collection.KList;
@ -51,9 +51,9 @@ public class CommandIrisWhatFeatures extends MortarCommand {
Player p = sender.player();
Chunk c = p.getLocation().getChunk();
if (IrisWorlds.isIrisWorld(c.getWorld())) {
if (IrisToolbelt.isIrisWorld(c.getWorld())) {
int m = 1;
for (IrisFeaturePositional i : ((Engine) IrisWorlds.access(c.getWorld()).getEngineAccess(p.getLocation().getBlockY())).getEngineParallax().getFeaturesInChunk(c)) {
for (IrisFeaturePositional i : ((Engine) IrisToolbelt.access(c.getWorld()).getEngine()).getEngineParallax().getFeaturesInChunk(c)) {
sender.sendMessage("#" + m++ + " " + new JSONObject(new Gson().toJson(i)).toString(4));
}
} else {

View File

@ -19,8 +19,8 @@
package com.volmit.iris.core.command.what;
import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisWorlds;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.objects.IrisObject;
import com.volmit.iris.engine.object.objects.IrisObjectPlacement;
@ -68,12 +68,12 @@ public class CommandIrisWhatObjects extends MortarCommand {
Player p = sender.player();
World world = p.getWorld();
if (!IrisWorlds.isIrisWorld(world)) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender.sendMessage("You must be in an iris world.");
return true;
}
IrisAccess g = IrisWorlds.access(world);
Engine g = IrisToolbelt.access(world).getEngine();
KList<Chunk> chunks = new KList<>();
int bx = p.getLocation().getChunk().getX();
int bz = p.getLocation().getChunk().getZ();
@ -139,7 +139,7 @@ public class CommandIrisWhatObjects extends MortarCommand {
for (int k = 0; k < 16; k += 3) {
assert g != null;
IrisBiome bb = g.getBiome((i.getX() * 16) + j, (i.getZ() * 16) + k);
IrisBiome bb = g.getSurfaceBiome((i.getX() * 16) + j, (i.getZ() * 16) + k);
IrisBiome bxf = g.getCaveBiome((i.getX() * 16) + j, (i.getZ() * 16) + k);
biomes.addIfMissing(bb.getName() + " [" + Form.capitalize(bb.getInferredType().name().toLowerCase()) + "] " + " (" + bb.getLoadFile().getName() + ")");
caveBiomes.addIfMissing(bxf.getName() + " (" + bxf.getLoadFile().getName() + ")");
@ -199,7 +199,7 @@ public class CommandIrisWhatObjects extends MortarCommand {
return true;
}
private void exportObjects(IrisBiome bb, PrintWriter pw, IrisAccess g, KMap<String, KMap<String, KList<String>>> objects) {
private void exportObjects(IrisBiome bb, PrintWriter pw, Engine g, KMap<String, KMap<String, KList<String>>> objects) {
String n1 = bb.getName() + " [" + Form.capitalize(bb.getInferredType().name().toLowerCase()) + "] " + " (" + bb.getLoadFile().getName() + ")";
int m = 0;
KSet<String> stop = new KSet<>();

View File

@ -24,8 +24,8 @@ import com.volmit.iris.core.link.MultiverseCoreLink;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.tools.IrisWorldCreator;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.plugin.MortarCommand;
@ -220,9 +220,7 @@ public class CommandIrisCreate extends MortarCommand {
File iris = new File(folder, "iris");
iris.mkdirs();
dim = Iris.proj.installIntoWorld(sender, type, folder);
WorldCreator wc = new IrisWorldCreator().dimension(dim.getLoadKey()).name(worldName)
.productionMode().seed(seed).create();
@ -236,7 +234,7 @@ public class CommandIrisCreate extends MortarCommand {
int req = 800;
while (!done.get()) {
boolean derp = false;
double v = (double) ((IrisAccess) wc.generator()).getGenerated() / (double) req;
double v = (double) ((PlatformChunkGenerator) wc.generator()).getEngine().getGenerated() / (double) req;
if (last > v || v > 1) {
derp = true;

View File

@ -19,8 +19,8 @@
package com.volmit.iris.core.command.world;
import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisWorlds;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.Spiraler;
@ -46,22 +46,18 @@ public class CommandIrisFix extends MortarCommand {
@Override
public boolean handle(VolmitSender sender, String[] args) {
try {
IrisAccess a = IrisWorlds.access(sender.player().getWorld());
if (a.getCompound().getSize() > 1) {
sender.sendMessage("Cant fix engine composite worlds!");
return true;
}
Engine a = IrisToolbelt.access(sender.player().getWorld()).getEngine();
int viewDistance = args.length > 0 ? Integer.parseInt(args[0]) : -1;
if (viewDistance <= 1) {
J.a(() -> {
int fixed = a.getCompound().getDefaultEngine().getEngineParallax().repairChunk(sender.player().getLocation().getChunk());
int fixed = a.getEngineParallax().repairChunk(sender.player().getLocation().getChunk());
sender.sendMessage("Fixed " + Form.f(fixed) + " blocks!");
});
} else {
AtomicInteger v = new AtomicInteger();
J.a(() -> {
new Spiraler(viewDistance, viewDistance, (x, z) -> v.set(v.get() + a.getCompound().getDefaultEngine().getEngineParallax().repairChunk(sender.player().getWorld().getChunkAt(x, z)))).drain();
new Spiraler(viewDistance, viewDistance, (x, z) -> v.set(v.get() + a.getEngineParallax().repairChunk(sender.player().getWorld().getChunkAt(x, z)))).drain();
sender.sendMessage("Fixed " + Form.f(v.get()) + " blocks in " + (viewDistance * viewDistance) + " chunks!");
});
}

View File

@ -19,8 +19,9 @@
package com.volmit.iris.core.command.world;
import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisWorlds;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.nbt.mca.Chunk;
import com.volmit.iris.util.nbt.mca.MCAFile;
@ -50,7 +51,7 @@ public class CommandIrisVerify extends MortarCommand {
@Override
public boolean handle(VolmitSender sender, String[] args) {
try {
IrisAccess a = IrisWorlds.access(sender.player().getWorld());
Engine a = IrisToolbelt.access(sender.player().getWorld()).getEngine();
File folder = a.getTarget().getWorld().worldFolder();
File r = new File(folder, "region");
BurstExecutor e = MultiBurst.burst.burst(r.listFiles().length);

View File

@ -19,7 +19,7 @@
package com.volmit.iris.core.command.world;
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.plugin.MortarCommand;
import com.volmit.iris.util.plugin.VolmitSender;
@ -35,7 +35,7 @@ public class CommandLocate extends MortarCommand implements Listener {
@EventHandler
public void onPlayerCommandPreprocess(final PlayerCommandPreprocessEvent event) {
if (IrisWorlds.isIrisWorld(event.getPlayer().getWorld())) {
if (IrisToolbelt.isIrisWorld(event.getPlayer().getWorld())) {
// Make sure the command starts with /locate and does not locate stronghold
if (event.getMessage().contains("/locate") && event.getMessage().contains("stronghold")) {

View File

@ -19,8 +19,8 @@
package com.volmit.iris.core.edit;
import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisWorlds;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.parallax.ParallaxAccess;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.math.BlockPosition;
@ -42,10 +42,10 @@ public class DustRevealer {
public static void spawn(Block block, VolmitSender sender) {
World world = block.getWorld();
IrisAccess access = IrisWorlds.access(world);
Engine access = IrisToolbelt.access(world).getEngine();
if (access != null) {
ParallaxAccess a = access.getEngineAccess(block.getY()).getParallaxAccess();
ParallaxAccess a = access.getParallaxAccess();
if (a.getObject(block.getX(), block.getY(), block.getZ()) != null) {
sender.sendMessage("Found object " + a.getObject(block.getX(), block.getY(), block.getZ()));

View File

@ -32,6 +32,10 @@ public class IrisEngineEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private Engine engine;
public IrisEngineEvent() {
super(true);
}
@Override
public HandlerList getHandlers() {
return handlers;

View File

@ -21,10 +21,9 @@ package com.volmit.iris.core.gui;
import com.volmit.iris.Iris;
import com.volmit.iris.core.gui.components.IrisRenderer;
import com.volmit.iris.core.gui.components.RenderType;
import com.volmit.iris.core.tools.IrisWorlds;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.IrisComplex;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.common.IrisWorld;
import com.volmit.iris.engine.object.regional.IrisRegion;
@ -156,11 +155,9 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
public boolean updateEngine() {
if (engine.isClosed()) {
int index = engine.getIndex();
if (world.hasRealWorld()) {
try {
engine = IrisWorlds.access(world.realWorld()).getCompound().getEngine(index);
engine = IrisToolbelt.access(world.realWorld()).getEngine();
return !engine.isClosed();
} catch (Throwable e) {
@ -779,9 +776,9 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
}
}
public static void launch(IrisAccess g, int i) {
public static void launch(Engine g, int i) {
J.a(() ->
createAndShowGUI(g.getCompound().getEngine(i), i, g.getCompound().getWorld()));
createAndShowGUI(g, i, g.getWorld()));
}
public void mouseWheelMoved(MouseWheelEvent e) {

View File

@ -19,9 +19,9 @@
package com.volmit.iris.core.link;
import com.volmit.iris.Iris;
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.IrisAccess;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
@ -51,46 +51,46 @@ public class IrisPapiExpansion extends PlaceholderExpansion {
@Override
public String onRequest(OfflinePlayer player, String p) {
Location l = null;
IrisAccess a = null;
PlatformChunkGenerator a = null;
if (player.isOnline()) {
l = player.getPlayer().getLocation();
a = IrisWorlds.access(l.getWorld());
a = IrisToolbelt.access(l.getWorld());
}
if (p.equalsIgnoreCase("biome_name")) {
if (a != null) {
return a.getBiome(l).getName();
return a.getEngine().getBiome(l).getName();
}
} else if (p.equalsIgnoreCase("biome_id")) {
if (a != null) {
return a.getBiome(l).getLoadKey();
return a.getEngine().getBiome(l).getLoadKey();
}
} else if (p.equalsIgnoreCase("biome_file")) {
if (a != null) {
return a.getBiome(l).getLoadFile().getPath();
return a.getEngine().getBiome(l).getLoadFile().getPath();
}
} else if (p.equalsIgnoreCase("region_name")) {
if (a != null) {
return a.getRegion(l).getName();
return a.getEngine().getRegion(l).getName();
}
} else if (p.equalsIgnoreCase("region_id")) {
if (a != null) {
return a.getRegion(l).getLoadKey();
return a.getEngine().getRegion(l).getLoadKey();
}
} else if (p.equalsIgnoreCase("region_file")) {
if (a != null) {
return a.getRegion(l).getLoadFile().getPath();
return a.getEngine().getRegion(l).getLoadFile().getPath();
}
} else if (p.equalsIgnoreCase("terrain_slope")) {
if (a != null) {
return ((Engine) a.getEngineAccess(l.getBlockY()))
return (a.getEngine())
.getComplex().getSlopeStream()
.get(l.getX(), l.getZ()) + "";
}
} else if (p.equalsIgnoreCase("terrain_height")) {
if (a != null) {
return (int) Math.round(a.getHeight(l)) + "";
return (int) Math.round(a.getEngine().getHeight(l.getBlockX(), l.getBlockZ())) + "";
}
} else if (p.equalsIgnoreCase("world_mode")) {
if (a != null) {
@ -102,7 +102,7 @@ public class IrisPapiExpansion extends PlaceholderExpansion {
}
} else if (p.equalsIgnoreCase("world_speed")) {
if (a != null) {
return a.getGeneratedPerSecond() + "/s";
return a.getEngine().getGeneratedPerSecond() + "/s";
}
}

View File

@ -20,8 +20,8 @@ package com.volmit.iris.core.pregenerator.methods;
import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
import com.volmit.iris.engine.framework.headless.HeadlessGenerator;
import com.volmit.iris.engine.framework.headless.HeadlessWorld;
import com.volmit.iris.engine.platform.HeadlessGenerator;
import com.volmit.iris.engine.object.common.HeadlessWorld;
import lombok.Getter;
public class HeadlessPregenMethod implements PregeneratorMethod {

View File

@ -22,8 +22,8 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
import com.volmit.iris.core.tools.IrisWorlds;
import com.volmit.iris.engine.framework.headless.HeadlessWorld;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.object.common.HeadlessWorld;
import com.volmit.iris.util.math.Position2;
import org.bukkit.World;
@ -42,7 +42,7 @@ public class HybridPregenMethod implements PregeneratorMethod {
}
private boolean supportsHeadless(World world) {
return IrisWorlds.access(world) != null && !IrisSettings.get().getGenerator().isDisableMCA();
return IrisToolbelt.access(world) != null && !IrisSettings.get().getGenerator().isDisableMCA();
}
@Override

View File

@ -20,8 +20,8 @@ package com.volmit.iris.core.pregenerator.syndicate;
import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.core.pregenerator.syndicate.command.*;
import com.volmit.iris.engine.framework.headless.HeadlessGenerator;
import com.volmit.iris.engine.framework.headless.HeadlessWorld;
import com.volmit.iris.engine.platform.HeadlessGenerator;
import com.volmit.iris.engine.object.common.HeadlessWorld;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.scheduling.J;
import org.zeroturnaround.zip.ZipUtil;

View File

@ -26,9 +26,9 @@ import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.core.project.loader.ResourceLoader;
import com.volmit.iris.core.report.Report;
import com.volmit.iris.core.report.ReportType;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.core.tools.IrisWorldCreator;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.biome.IrisBiomeMutation;
import com.volmit.iris.engine.object.biome.IrisBiomePaletteLayer;
@ -40,6 +40,7 @@ import com.volmit.iris.engine.object.noise.IrisGenerator;
import com.volmit.iris.engine.object.objects.IrisObjectPlacement;
import com.volmit.iris.engine.object.regional.IrisRegion;
import com.volmit.iris.engine.object.spawners.IrisSpawner;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
@ -73,124 +74,13 @@ import java.util.UUID;
public class IrisProject {
private File path;
private String name;
private IrisAccess activeProvider;
private PlatformChunkGenerator activeProvider;
public IrisProject(File path) {
this.path = path;
this.name = path.getName();
}
public KList<Report> scanForErrors() {
KList<Report> reports = new KList<>();
IrisData data = new IrisData(path);
Gson g = new Gson();
MultiBurst.burst.burst(collectFiles("json").convert((i) -> () -> {
try {
new JSONObject(IO.readAll(i));
} catch (Throwable e) {
synchronized (reports) {
reports.add(Report.builder()
.title("Invalid Json: " + i.getName())
.message(i.getAbsolutePath() + e.getMessage())
.suggestion("Correct the json")
.type(ReportType.ERROR)
.build());
}
}
}));
try {
if (activeProvider != null && activeProvider.getCompound() != null) {
for (int i = 0; i < getActiveProvider().getCompound().getSize(); i++) {
Engine e = getActiveProvider().getCompound().getEngine(i);
IrisDimension dim = e.getDimension();
reports.add(scanForErrors(dim));
}
}
} catch (Throwable e) {
reports.add(Report.builder()
.title("Failed to check all errors")
.message("There may be some json errors, correct those first")
.suggestion("Correct the json, or see exception below")
.type(ReportType.SEVERE_WARNING)
.build());
e.printStackTrace();
}
return reports;
}
private KList<Report> scanForErrors(IrisDimension dim) {
KList<Report> reports = new KList<>();
if (dim.getFocus() != null && !dim.getFocus().isEmpty()) {
reports.add(Report.builder()
.type(ReportType.NOTICE)
.title("Focus Mode is Enabled")
.message("Make sure to disable this before pushing")
.suggestion("Turn off focus mode")
.build());
}
for (IrisRegion i : dim.getAllRegions(getActiveProvider())) {
scanForErrors(i);
}
return reports;
}
private KList<Report> scanForErrors(IrisRegion region) {
KList<Report> reports = new KList<>();
if (region.getRarity() > 60) {
reports.add(Report.builder()
.type(ReportType.WARNING)
.title("Region " + region.getName() + " has a rarity of " + region.getRarity())
.message("The region rarity higher than 60 can cause performance issues")
.suggestion("Scale all rarities down by 50% all at once, then repeat until all rarities are below 60")
.build());
}
for (IrisBiome i : region.getAllBiomes(getActiveProvider())) {
reports.add(scanForErrors(i));
}
return reports;
}
private KList<Report> scanForErrors(IrisBiome biome) {
KList<Report> reports = new KList<>();
for (IrisObjectPlacement i : biome.getObjects()) {
reports.add(scanForErrors(biome, i));
}
for (IrisBiomePaletteLayer i : biome.getLayers()) {
reports.add(scanForErrors(biome, i));
}
for (IrisBiomePaletteLayer i : biome.getSeaLayers()) {
reports.add(scanForErrorsSeaLayers(biome, i));
}
return reports;
}
private KList<Report> scanForErrors(IrisBiome biome, IrisObjectPlacement i) {
return new KList<>();
}
private KList<Report> scanForErrors(IrisBiome biome, IrisBiomePaletteLayer i) {
return new KList<>();
}
private KList<Report> scanForErrorsSeaLayers(IrisBiome biome, IrisBiomePaletteLayer i) {
return new KList<>();
}
public boolean isOpen() {
return activeProvider != null;
}
@ -226,31 +116,6 @@ public class IrisProject {
boolean hasError = false;
try {
KList<Report> reports = scanForErrors();
if (reports.isNotEmpty()) {
sender.sendMessage("There are " + reports.size() + " problems detected with this project. See console!");
Iris.error("===========================================================");
for (Report i : reports) {
if (i.getType().equals(ReportType.ERROR)) {
hasError = true;
}
switch (i.getType()) {
case ERROR -> Iris.error(i.toString());
case SEVERE_WARNING -> Iris.warn(i.toString());
case WARNING -> Iris.warn(i.toString());
case NOTICE -> Iris.warn(i.toString());
}
}
Iris.error("===========================================================");
}
} catch (Throwable e) {
hasError = true;
e.printStackTrace();
}
if (hasError) {
return;
}
@ -318,7 +183,7 @@ public class IrisProject {
.studioMode()
.create();
IrisAccess gx = ((IrisAccess) c.generator());
PlatformChunkGenerator gx = ((PlatformChunkGenerator) c.generator());
O<Boolean> done = new O<>();
done.set(false);
activeProvider = gx;
@ -328,22 +193,16 @@ public class IrisProject {
double last = 0;
int req = 400;
while (gx.getGenerated() < req) {
while (gx.getEngine().getGenerated() < req) {
assert gx != null;
double v = (double) gx.getGenerated() / (double) req;
double v = (double) gx.getEngine().getGenerated() / (double) req;
if (sender.isPlayer()) {
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - gx.getGenerated()) + " Left)"))));
J.sleep(50);
sender.sendProgress(v, "Generating");
J.sleep(16);
} else {
sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - gx.getGenerated()) + " Left)")));
J.sleep(1000);
}
if (gx.isFailing()) {
sender.sendMessage("Generation Failed!");
break;
sender.sendProgress(v, "Generating");
J.sleep(16);
}
}
if (sender.isPlayer()) {
@ -366,7 +225,7 @@ public class IrisProject {
assert world != null;
sender.player().teleport(world.getSpawnLocation());
} else {
sender.sendMessage(C.WHITE + "Generating Complete!");
sender.sendAction(C.IRIS + "Generation Complete");
}
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, () ->
@ -380,11 +239,14 @@ public class IrisProject {
}
public void close() {
Iris.debug("Closing Active Provider");
IrisToolbelt.evacuate(activeProvider.getTarget().getWorld().realWorld());
activeProvider.close();
File folder = activeProvider.getTarget().getWorld().worldFolder();
Iris.linkMultiverseCore.removeFromConfig(activeProvider.getTarget().getWorld().name());
Bukkit.unloadWorld(activeProvider.getTarget().getWorld().name(), false);
J.attemptAsync(() -> IO.delete(folder));
Iris.debug("Closed Active Provider " + activeProvider.getTarget().getWorld().name());
activeProvider = null;
}

View File

@ -20,9 +20,10 @@ package com.volmit.iris.core.tools;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.engine.framework.headless.HeadlessWorld;
import com.volmit.iris.engine.object.common.HeadlessWorld;
import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.engine.platform.HeadlessGenerator;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.exceptions.IrisException;
import com.volmit.iris.util.exceptions.MissingDimensionException;
import com.volmit.iris.util.format.C;
@ -92,9 +93,9 @@ public class IrisCreator {
* @return the IrisAccess
* @throws IrisException shit happens
*/
public IrisAccess create() throws IrisException {
public PlatformChunkGenerator create() throws IrisException {
IrisDimension d = IrisToolbelt.getDimension(dimension());
IrisAccess access = null;
PlatformChunkGenerator access = null;
Consumer<Double> prog = (pxx) -> {
double px = pxx;
@ -117,7 +118,7 @@ public class IrisCreator {
if (headless) {
HeadlessWorld w = new HeadlessWorld(name, d, seed, studio);
access = w.generate().getGenerator();
access = w.generate();
} else {
O<Boolean> done = new O<>();
done.set(false);
@ -127,33 +128,27 @@ public class IrisCreator {
.seed(seed)
.studio(studio)
.create();
access = (IrisAccess) wc.generator();
IrisAccess finalAccess1 = access;
access = (PlatformChunkGenerator) wc.generator();
PlatformChunkGenerator finalAccess1 = access;
J.a(() ->
{
int req = 400;
while (finalAccess1.getGenerated() < req && !done.get()) {
double v = (double) finalAccess1.getGenerated() / (double) req;
while (finalAccess1.getEngine().getGenerated() < req && !done.get()) {
double v = (double) finalAccess1.getEngine().getGenerated() / (double) req;
if (pregen != null) {
v /= 2;
}
if (sender.isPlayer()) {
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess1.getGenerated()) + " Left)"))));
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess1.getEngine().getGenerated()) + " Left)"))));
J.sleep(50);
} else {
sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess1.getGenerated()) + " Left)")));
sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess1.getEngine().getGenerated()) + " Left)")));
J.sleep(1000);
}
if (finalAccess1.isFailing()) {
sender.sendMessage("Generation Failed!");
break;
}
}
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generation Complete"));
@ -186,7 +181,7 @@ public class IrisCreator {
try {
IrisAccess finalAccess = access;
PlatformChunkGenerator finalAccess = access;
J.sfut(() -> {
if (headless) {
O<Boolean> done = new O<>();
@ -196,29 +191,23 @@ public class IrisCreator {
{
int req = 400;
while (finalAccess.getGenerated() < req && !done.get()) {
double v = (double) finalAccess.getGenerated() / (double) req;
while (finalAccess.getEngine().getGenerated() < req && !done.get()) {
double v = (double) finalAccess.getEngine().getGenerated() / (double) req;
v = (v / 2) + 0.5;
if (sender.isPlayer()) {
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess.getGenerated()) + " Left)"))));
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess.getEngine().getGenerated()) + " Left)"))));
J.sleep(50);
} else {
sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess.getGenerated()) + " Left)")));
sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess.getEngine().getGenerated()) + " Left)")));
J.sleep(1000);
}
if (finalAccess.isFailing()) {
sender.sendMessage("Generation Failed!");
break;
}
}
sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generation Complete"));
});
finalAccess.getHeadlessGenerator().getWorld().load();
((HeadlessGenerator)finalAccess).getWorld().load();
done.set(true);
}
}).get();

View File

@ -26,11 +26,13 @@ import com.volmit.iris.core.pregenerator.PregeneratorMethod;
import com.volmit.iris.core.pregenerator.methods.HeadlessPregenMethod;
import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.engine.platform.HeadlessGenerator;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.plugin.VolmitSender;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.io.File;
@ -80,7 +82,11 @@ public class IrisToolbelt {
* @return true if it is an Iris Access world
*/
public static boolean isIrisWorld(World world) {
return access(world) != null;
if (world == null) {
return false;
}
return world.getGenerator() instanceof PlatformChunkGenerator;
}
/**
@ -89,8 +95,12 @@ public class IrisToolbelt {
* @param world the given world
* @return the IrisAccess or null if it's not an Iris World
*/
public static IrisAccess access(World world) {
return IrisWorlds.access(world);
public static PlatformChunkGenerator access(World world) {
if (isIrisWorld(world)) {
return ((PlatformChunkGenerator) world.getGenerator());
}
return null;
}
/**
@ -109,15 +119,15 @@ public class IrisToolbelt {
* otherwise Hybrid mode is used.
*
* @param task the scheduled task
* @param access the Iris Generator
* @param gen the Iris Generator
* @return the pregenerator job (already started)
*/
public static PregeneratorJob pregenerate(PregenTask task, IrisAccess access) {
if (access.isHeadless()) {
return pregenerate(task, new HeadlessPregenMethod(access.getHeadlessGenerator().getWorld(), access.getHeadlessGenerator()));
public static PregeneratorJob pregenerate(PregenTask task, PlatformChunkGenerator gen) {
if (gen.isHeadless()) {
return pregenerate(task, new HeadlessPregenMethod(((HeadlessGenerator)gen).getWorld(), (HeadlessGenerator) gen));
}
return pregenerate(task, new HybridPregenMethod(access.getCompound().getWorld().realWorld(), IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getPregenThreadCount())));
return pregenerate(task, new HybridPregenMethod(gen.getEngine().getWorld().realWorld(), IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getPregenThreadCount())));
}
/**
@ -142,7 +152,33 @@ public class IrisToolbelt {
*
* @param world the world to evac
*/
public static void evacuate(World world) {
IrisWorlds.evacuate(world);
public static boolean evacuate(World world) {
for (World i : Bukkit.getWorlds()) {
if (!i.getName().equals(world.getName())) {
for (Player j : world.getPlayers()) {
new VolmitSender(j, Iris.instance.getTag()).sendMessage("You have been evacuated from this world.");
j.teleport(i.getSpawnLocation());
}
return true;
}
}
return false;
}
public static boolean evacuate(World world, String m) {
for (World i : Bukkit.getWorlds()) {
if (!i.getName().equals(world.getName())) {
for (Player j : world.getPlayers()) {
new VolmitSender(j, Iris.instance.getTag()).sendMessage("You have been evacuated from this world. " + m);
j.teleport(i.getSpawnLocation());
}
return true;
}
}
return false;
}
}

View File

@ -18,12 +18,15 @@
package com.volmit.iris.core.tools;
import com.sun.jna.Platform;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.engine.framework.EngineCompositeGenerator;
import com.volmit.iris.engine.object.common.IrisWorld;
import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.generator.ChunkGenerator;
import java.io.File;
@ -77,15 +80,18 @@ public class IrisWorldCreator {
}
public WorldCreator create() {
EngineCompositeGenerator g = new EngineCompositeGenerator(dimensionName, !studio);
g.initialize(IrisWorld.builder()
IrisWorld w = IrisWorld.builder()
.name(name)
.minHeight(minHeight)
.maxHeight(maxHeight)
.seed(seed)
.worldFolder(new File(name))
.environment(findEnvironment())
.build());
.build();
ChunkGenerator g = new BukkitChunkGenerator(w, studio, studio
? IrisData.loadAnyDimension(dimensionName).getLoader().getDataFolder():
new File(w.worldFolder(), "iris/pack"), dimensionName);
return new WorldCreator(name)
.environment(findEnvironment())
.generateStructures(true)

View File

@ -1,91 +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.core.tools;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.IrisAccess;
import com.volmit.iris.engine.framework.IrisAccessProvider;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.plugin.VolmitSender;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
@SuppressWarnings("ALL")
public class IrisWorlds {
private static final KMap<String, IrisAccess> provisioned = new KMap<>();
public static void register(World w, IrisAccess p) {
provisioned.put(w.getUID().toString(), p);
}
public static boolean isIrisWorld(World world) {
if (world == null) {
return false;
}
if (provisioned.containsKey(world.getUID().toString())) {
return true;
}
return world.getGenerator() instanceof IrisAccess || world.getGenerator() instanceof IrisAccessProvider;
}
public static IrisAccess access(World world) {
if (isIrisWorld(world)) {
if (provisioned.containsKey(world.getUID().toString())) {
return provisioned.get(world.getUID().toString());
}
return world.getGenerator() instanceof IrisAccessProvider ? (((IrisAccessProvider) world.getGenerator()).getAccess()) : ((IrisAccess) world.getGenerator());
}
return null;
}
public static boolean evacuate(World world) {
for (World i : Bukkit.getWorlds()) {
if (!i.getName().equals(world.getName())) {
for (Player j : world.getPlayers()) {
new VolmitSender(j, Iris.instance.getTag()).sendMessage("You have been evacuated from this world.");
j.teleport(i.getSpawnLocation());
}
return true;
}
}
return false;
}
public static boolean evacuate(World world, String m) {
for (World i : Bukkit.getWorlds()) {
if (!i.getName().equals(world.getName())) {
for (Player j : world.getPlayers()) {
new VolmitSender(j, Iris.instance.getTag()).sendMessage("You have been evacuated from this world. " + m);
j.teleport(i.getSpawnLocation());
}
return true;
}
}
return false;
}
}

View File

@ -18,6 +18,7 @@
package com.volmit.iris.engine;
import com.google.common.util.concurrent.AtomicDouble;
import com.google.gson.Gson;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
@ -38,42 +39,61 @@ import com.volmit.iris.engine.object.decoration.IrisDecorator;
import com.volmit.iris.engine.object.engine.IrisEngineData;
import com.volmit.iris.engine.object.objects.IrisObjectPlacement;
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.documentation.BlockCoordinates;
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.storage.AtomicDoubleHunk;
import com.volmit.iris.util.hunk.storage.AtomicLongHunk;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.generator.BlockPopulator;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
@EqualsAndHashCode(callSuper = true)
@Data
public class IrisEngine extends BlockPopulator implements Engine {
private final EngineCompound compound;
// TODO: Remove block population, stop using bukkit
private final AtomicInteger generated;
private final AtomicInteger generatedLast;
private final AtomicDouble perSecond;
private final AtomicLong lastGPS;
private final EngineTarget target;
private final IrisContext context;
private final EngineEffects effects;
private final ChronoLatch perSecondLatch;
private final EngineExecutionEnvironment execution;
private final EngineWorldManager worldManager;
private volatile int parallelism;
private final int index;
private final EngineMetrics metrics;
private volatile int minHeight;
private final boolean studio;
private boolean failing;
private boolean closed;
private int cacheId;
private final AtomicRollingSequence wallClock;
private final int art;
private double maxBiomeObjectDensity;
private double maxBiomeLayerDensity;
@ -92,24 +112,29 @@ public class IrisEngine extends BlockPopulator implements Engine {
private final AtomicBoolean cleaning;
private final ChronoLatch cleanLatch;
public IrisEngine(EngineTarget target, EngineCompound compound, int index) {
public IrisEngine(EngineTarget target, boolean studio) {
this.studio = studio;
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);
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);
this.target = target;
getData().setEngine(this);
getEngineData();
worldManager = new IrisWorldManager(this);
this.compound = compound;
minHeight = 0;
failing = false;
closed = false;
this.index = index;
cacheId = RNG.r.nextInt();
effects = new IrisEngineEffects(this);
art = J.ar(effects::tickRandomPlayer, 0);
J.a(this::computeBiomeMaxes);
Iris.callEvent(new IrisEngineHotloadEvent(this));
context = new IrisContext(this);
context.touch();
this.complex = new IrisComplex(this);
@ -133,7 +158,8 @@ public class IrisEngine extends BlockPopulator implements Engine {
World w = null;
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()) {
try {
@ -154,6 +180,36 @@ public class IrisEngine extends BlockPopulator implements Engine {
});
}
@Override
public int getGenerated() {
return generated.get();
}
@Override
public double getGeneratedPerSecond() {
if(perSecondLatch.flip())
{
double g = generated.get() - generatedLast.get();
generatedLast.set(generated.get());
if(g == 0)
{
return 0;
}
long dur = M.ms() - lastGPS.get();
lastGPS.set(M.ms());
perSecond.set(1000D / ((double)dur / g));
}
return perSecond.get();
}
@Override
public boolean isStudio() {
return studio;
}
private void computeBiomeMaxes() {
for (IrisBiome i : getDimension().getAllBiomes(this)) {
double density = 0;
@ -180,6 +236,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
public void close() {
J.car(art);
@ -247,7 +360,7 @@ public class IrisEngine extends BlockPopulator implements Engine {
return z / getDimension().getTerrainZoom();
}
@ChunkCoordinates
@BlockCoordinates
@Override
public void generate(int x, int z, Hunk<BlockData> vblocks, Hunk<Biome> vbiomes, boolean multicore) {
context.touch();
@ -274,6 +387,7 @@ public class IrisEngine extends BlockPopulator implements Engine {
}
getMetrics().getTotal().put(p.getMilliseconds());
generated.incrementAndGet();
} catch (Throwable e) {
Iris.reportError(e);
fail("Failed to generate " + x + ", " + z, e);
@ -282,7 +396,8 @@ public class IrisEngine extends BlockPopulator implements Engine {
@Override
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();
try {
IO.writeAll(f, new Gson().toJson(getEngineData()));
@ -302,6 +417,7 @@ public class IrisEngine extends BlockPopulator implements Engine {
return getData().getBiomeLoader().load(getDimension().getFocus());
}
// TODO: Remove block population
@ChunkCoordinates
@Override
public void populate(World world, Random random, Chunk c) {
@ -325,11 +441,4 @@ public class IrisEngine extends BlockPopulator implements Engine {
public int getCacheID() {
return cacheId;
}
@Override
public void hotload() {
Iris.callEvent(new IrisEngineHotloadEvent(this));
getEngineData().getStatistics().hotloaded();
cacheId = RNG.r.nextInt();
}
}

View File

@ -1,288 +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;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineCompound;
import com.volmit.iris.engine.framework.EngineData;
import com.volmit.iris.engine.framework.EngineTarget;
import com.volmit.iris.engine.object.basic.IrisPosition;
import com.volmit.iris.engine.object.common.IrisWorld;
import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.engine.object.dimensional.IrisDimensionIndex;
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.documentation.BlockCoordinates;
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.parallel.MultiBurst;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.event.EventHandler;
import org.bukkit.event.world.WorldSaveEvent;
import org.bukkit.generator.BlockPopulator;
import java.io.File;
import java.util.List;
public class IrisEngineCompound implements EngineCompound {
@Getter
private final IrisWorld world;
private final AtomicRollingSequence wallClock;
private Engine defaultEngine;
@Getter
private final EngineData engineMetadata;
private final Engine[] engines;
@Getter
private final MultiBurst burster;
@Getter
private final KList<BlockPopulator> populators;
@Getter
private final IrisDimension rootDimension;
@Getter
private final int threadCount = -1;
@Getter
@Setter
private boolean studio;
public IrisEngineCompound(IrisWorld world, IrisDimension rootDimension, IrisData data, int maximumThreads) {
wallClock = new AtomicRollingSequence(32);
this.rootDimension = rootDimension;
Iris.info("Initializing Engine Composite for " + world.name());
this.world = world;
engineMetadata = EngineData.load(getEngineMetadataFile());
engineMetadata.setDimension(rootDimension.getLoadKey());
engineMetadata.setLastVersion(Iris.instance.getDescription().getVersion());
saveEngineMetadata();
populators = new KList<>();
if (rootDimension.getDimensionalComposite().isEmpty()) {
burster = null;
// TODO: WARNING HEIGHT
engines = new Engine[]{new IrisEngine(new EngineTarget(world, rootDimension, data, 256, maximumThreads), this, 0)};
defaultEngine = engines[0];
} else {
double totalWeight = 0D;
engines = new Engine[rootDimension.getDimensionalComposite().size()];
burster = engines.length > 1 ? new MultiBurst("Iris Compound " + rootDimension.getName(), IrisSettings.get().getConcurrency().getEngineThreadPriority(), engines.length) : null;
int threadDist = (Math.max(2, maximumThreads - engines.length)) / engines.length;
if ((threadDist * engines.length) + engines.length > maximumThreads) {
Iris.warn("Using " + ((threadDist * engines.length) + engines.length) + " threads instead of the configured " + maximumThreads + " maximum thread count due to the requirements of this dimension!");
}
for (IrisDimensionIndex i : rootDimension.getDimensionalComposite()) {
totalWeight += i.getWeight();
}
int buf = 0;
for (int i = 0; i < engines.length; i++) {
IrisDimensionIndex index = rootDimension.getDimensionalComposite().get(i);
IrisDimension dimension = data.getDimensionLoader().load(index.getDimension());
// TODO: WARNING HEIGHT
engines[i] = new IrisEngine(new EngineTarget(world, dimension, data.copy(), (int) Math.floor(256D * (index.getWeight() / totalWeight)), index.isInverted(), threadDist), this, i);
engines[i].setMinHeight(buf);
buf += engines[i].getHeight();
if (index.isPrimary()) {
defaultEngine = engines[i];
}
}
if (defaultEngine == null) {
defaultEngine = engines[0];
}
}
for (Engine i : engines) {
if (i instanceof BlockPopulator) {
populators.add((BlockPopulator) i);
}
}
Iris.instance.registerListener(this);
}
public List<IrisPosition> getStrongholdPositions() {
return engineMetadata.getStrongholdPositions();
}
@EventHandler
public void on(WorldSaveEvent e) {
if (world != null && e.getWorld().equals(world)) {
save();
}
}
public void printMetrics(CommandSender sender) {
KMap<String, Double> totals = new KMap<>();
KMap<String, Double> weights = new KMap<>();
double masterWallClock = wallClock.getAverage();
for (int i = 0; i < getSize(); i++) {
Engine e = getEngine(i);
KMap<String, Double> timings = e.getMetrics().pull();
double totalWeight = 0;
double wallClock = e.getMetrics().getTotal().getAverage();
for (double j : timings.values()) {
totalWeight += j;
}
for (String j : timings.k()) {
weights.put(e.getName() + "[" + e.getIndex() + "]." + j, (wallClock / totalWeight) * timings.get(j));
}
totals.put(e.getName() + "[" + e.getIndex() + "]", 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));
}
}
private File getEngineMetadataFile() {
return new File(world.worldFolder(), "iris/engine-metadata.json");
}
@ChunkCoordinates
@Override
public void generate(int x, int z, Hunk<BlockData> blocks, Hunk<BlockData> postblocks, Hunk<Biome> biomes, boolean multicore) {
recycle();
PrecisionStopwatch p = PrecisionStopwatch.start();
if (engines.length == 1 && !getEngine(0).getTarget().isInverted()) {
engines[0].generate(x, z, blocks, biomes, multicore);
} else {
int i;
int offset = 0;
for (i = 0; i < engines.length; i++) {
Engine engine = engines[i];
int doffset = offset;
int height = engine.getTarget().getHeight();
Hunk<BlockData> cblock = Hunk.newArrayHunk(16, height, 16);
Hunk<Biome> cbiome = Hunk.newArrayHunk(16, height, 16);
if (engine.getTarget().isInverted()) {
cblock = cblock.invertY();
cbiome = cbiome.invertY();
}
engine.generate(x, z, cblock, cbiome, multicore);
blocks.insert(0, doffset, 0, cblock);
biomes.insert(0, doffset, 0, cbiome);
offset += height;
}
}
wallClock.put(p.getMilliseconds());
}
@Override
public int getSize() {
return engines.length;
}
@Override
public Engine getEngine(int index) {
return engines[index];
}
@Override
public void saveEngineMetadata() {
engineMetadata.save(getEngineMetadataFile());
}
@BlockCoordinates
@Override
public IrisData getData(int height) {
return getEngineForHeight(height).getData();
}
//TODO: FAIL
@Override
public boolean isFailing() {
return false;
}
@Override
public Engine getDefaultEngine() {
return defaultEngine;
}
@Override
public void hotload() {
for (int i = 0; i < getSize(); i++) {
getEngine(i).hotload();
}
}
}

View File

@ -51,12 +51,8 @@ public class IrisEngineEffects extends EngineAssignedComponent implements Engine
for (Player i : pr) {
Location l = i.getLocation();
boolean pcc = players.containsKey(i.getUniqueId());
if (getEngine().contains(l)) {
if (!pcc) {
players.put(i.getUniqueId(), new EnginePlayer(getEngine(), i));
}
} else if (pcc) {
players.remove(i.getUniqueId());
if (!pcc) {
players.put(i.getUniqueId(), new EnginePlayer(getEngine(), i));
}
}

View File

@ -32,6 +32,6 @@ public class IrisEngineMantle implements EngineMantle {
public IrisEngineMantle(Engine engine) {
this.engine = engine;
this.mantle = new Mantle(new File(engine.getWorld().worldFolder(), "mantle/" + engine.getIndex()), engine.getTarget().getHeight());
this.mantle = new Mantle(new File(engine.getWorld().worldFolder(), "mantle"), engine.getTarget().getHeight());
}
}

View File

@ -354,7 +354,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
@Override
public void onBlockBreak(BlockBreakEvent e) {
if (e.getBlock().getWorld().equals(getTarget().getWorld().realWorld()) && getEngine().contains(e.getBlock().getLocation())) {
if (e.getBlock().getWorld().equals(getTarget().getWorld().realWorld())) {
KList<ItemStack> d = new KList<>();
Runnable drop = () -> J.s(() -> d.forEach((i) -> e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation().clone().add(0.5, 0.5, 0.5), i)));
IrisBiome b = getEngine().getBiome(e.getBlock().getLocation());

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.data.cache.Cache;
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.common.IrisWorld;
import com.volmit.iris.engine.object.dimensional.IrisDimension;
@ -37,23 +38,30 @@ import com.volmit.iris.engine.object.regional.IrisRegion;
import com.volmit.iris.engine.parallax.ParallaxAccess;
import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
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.data.B;
import com.volmit.iris.util.data.DataProvider;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.function.Function2;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.BlockPosition;
import com.volmit.iris.util.math.M;
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.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import com.volmit.iris.util.stream.ProceduralStream;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
@ -61,10 +69,17 @@ import org.bukkit.inventory.ItemStack;
import java.awt.*;
import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
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();
void printMetrics(CommandSender sender);
void recycle();
EngineParallaxManager getEngineParallax();
@ -111,9 +126,10 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
void setMinHeight(int min);
int getIndex();
int getMinHeight();
default int getMinHeight()
{
return getTarget().getWorld().minHeight();
}
@BlockCoordinates
double modifyX(double x);
@ -121,7 +137,7 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
@BlockCoordinates
double modifyZ(double z);
@ChunkCoordinates
@BlockCoordinates
void generate(int x, int z, Hunk<BlockData> blocks, Hunk<Biome> biomes, boolean multicore);
EngineMetrics getMetrics();
@ -143,10 +159,6 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
return getDimension().getName();
}
default int getHeight() {
return getTarget().getHeight();
}
default IrisData getData() {
return getTarget().getData();
}
@ -168,7 +180,7 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
IrisRegion region = getRegion((int) x, (int) z);
IrisBiome biome = getSurfaceBiome((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 ibc = biome.getColor(this, RenderType.BIOME);
Color rc = irc != null ? irc : Color.GREEN.darker();
@ -404,18 +416,8 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
scramble(inv, rng);
}
default int getMaxHeight() {
return getHeight() + getMinHeight();
}
EngineEffects getEffects();
EngineCompound getCompound();
default boolean isStudio() {
return getCompound().isStudio();
}
default MultiBurst burst() {
return getTarget().getBurster();
}
@ -434,11 +436,6 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
return getRegion(l.getBlockX(), l.getBlockZ());
}
@BlockCoordinates
default boolean contains(Location l) {
return l.getBlockY() >= getMinHeight() && l.getBlockY() <= getMaxHeight();
}
IrisBiome getFocus();
IrisEngineData getEngineData();
@ -450,4 +447,199 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
default IrisRegion getRegion(Chunk c) {
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 <T> IrisPosition lookForStreamResult(T find, ProceduralStream<T> stream, Function2<T, T, Boolean> matcher, long timeout)
{
AtomicInteger checked = new AtomicInteger();
AtomicLong time = new AtomicLong(M.ms());
AtomicReference<IrisPosition> r = new AtomicReference<>();
BurstExecutor b = burst().burst();
while(M.ms() - time.get() < timeout && r.get() == null)
{
b.queue(() -> {
for(int i = 0; i < 1000; i++)
{
if(M.ms() - time.get() > timeout)
{
return;
}
int x = RNG.r.i(-29999970, 29999970);
int z = RNG.r.i(-29999970, 29999970);
checked.incrementAndGet();
if(matcher.apply(stream.get(x, z), find))
{
r.set(new IrisPosition(x, 120, z));
time.set(0);
}
}
});
}
return r.get();
}
default IrisPosition lookForBiome(IrisBiome biome, long timeout, Consumer<Integer> triesc) {
if (!getWorld().hasRealWorld()) {
Iris.error("Cannot GOTO without a bound world (headless mode)");
return null;
}
ChronoLatch cl = new ChronoLatch(250, false);
long s = M.ms();
int cpus = (Runtime.getRuntime().availableProcessors());
if (!getDimension().getAllBiomes(this).contains(biome)) {
return null;
}
AtomicInteger tries = new AtomicInteger(0);
AtomicBoolean found = new AtomicBoolean(false);
AtomicBoolean running = new AtomicBoolean(true);
AtomicReference<IrisPosition> location = new AtomicReference<>();
for (int i = 0; i < cpus; i++) {
J.a(() -> {
try {
Engine e;
IrisBiome b;
int x, z;
while (!found.get() && running.get()) {
try {
x = RNG.r.i(-29999970, 29999970);
z = RNG.r.i(-29999970, 29999970);
b = getSurfaceBiome(x, z);
if (b != null && b.getLoadKey() == null) {
continue;
}
if (b != null && b.getLoadKey().equals(biome.getLoadKey())) {
found.lazySet(true);
location.lazySet(new IrisPosition(x, getHeight(x, z), z));
}
tries.getAndIncrement();
} catch (Throwable ex) {
Iris.reportError(ex);
ex.printStackTrace();
return;
}
}
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
}
});
}
while (!found.get() || location.get() == null) {
J.sleep(50);
if (cl.flip()) {
triesc.accept(tries.get());
}
if (M.ms() - s > timeout) {
running.set(false);
return null;
}
}
running.set(false);
return location.get();
}
default IrisPosition lookForRegion(IrisRegion reg, long timeout, Consumer<Integer> triesc) {
if (getWorld().hasRealWorld()) {
Iris.error("Cannot GOTO without a bound world (headless mode)");
return null;
}
ChronoLatch cl = new ChronoLatch(3000, false);
long s = M.ms();
int cpus = (Runtime.getRuntime().availableProcessors());
if (!getDimension().getRegions().contains(reg.getLoadKey())) {
return null;
}
AtomicInteger tries = new AtomicInteger(0);
AtomicBoolean found = new AtomicBoolean(false);
AtomicBoolean running = new AtomicBoolean(true);
AtomicReference<IrisPosition> location = new AtomicReference<>();
for (int i = 0; i < cpus; i++) {
J.a(() -> {
Engine e;
IrisRegion b;
int x, z;
while (!found.get() && running.get()) {
try {
x = RNG.r.i(-29999970, 29999970);
z = RNG.r.i(-29999970, 29999970);
b = getRegion(x, z);
if (b != null && b.getLoadKey() != null && b.getLoadKey().equals(reg.getLoadKey())) {
found.lazySet(true);
location.lazySet(new IrisPosition(x, getHeight(x, z), z));
}
tries.getAndIncrement();
} catch (Throwable xe) {
Iris.reportError(xe);
xe.printStackTrace();
return;
}
}
});
}
while (!found.get() || location.get() != null) {
J.sleep(50);
if (cl.flip()) {
triesc.accept(tries.get());
}
if (M.ms() - s > timeout) {
triesc.accept(tries.get());
running.set(false);
return null;
}
}
triesc.accept(tries.get());
running.set(false);
return location.get();
}
double getGeneratedPerSecond();
default int getHeight()
{
return getWorld().getHeight();
}
boolean isStudio();
}

View File

@ -19,13 +19,17 @@
package com.volmit.iris.engine.framework;
import com.volmit.iris.Iris;
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.plugin.VolmitSender;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.entity.EnderSignal;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
@ -49,6 +53,16 @@ public abstract class EngineAssignedWorldManager extends EngineAssignedComponent
taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, this::onTick, 0, 0);
}
@EventHandler
public void on(IrisEngineHotloadEvent e) {
for(Player i : e.getEngine().getWorld().getPlayers())
{
i.playSound(i.getLocation(), Sound.ITEM_TRIDENT_RETURN, 1f, 1.6f);
VolmitSender s = new VolmitSender(i);
s.sendTitle(C.IRIS + "Engine " + C.AQUA + "<font:minecraft:uniform>Hotloaded", 70, 60, 410);
}
}
@EventHandler
public void on(WorldSaveEvent e) {
if (e.getWorld().equals(getTarget().getWorld().realWorld())) {

View File

@ -1,810 +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.framework;
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.core.project.loader.IrisData;
import com.volmit.iris.engine.IrisEngineCompound;
import com.volmit.iris.engine.data.chunk.MCATerrainChunk;
import com.volmit.iris.engine.data.chunk.TerrainChunk;
import com.volmit.iris.engine.framework.headless.HeadlessGenerator;
import com.volmit.iris.engine.object.basic.IrisPosition;
import com.volmit.iris.engine.object.biome.IrisBiome;
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.collection.KMap;
import com.volmit.iris.util.data.B;
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.io.ReactiveFolder;
import com.volmit.iris.util.math.M;
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 com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.reflect.V;
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 io.netty.util.internal.ConcurrentSet;
import lombok.Getter;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
public class EngineCompositeGenerator extends ChunkGenerator implements IrisAccess {
private static final BlockData ERROR_BLOCK = Material.RED_GLAZED_TERRACOTTA.createBlockData();
private final AtomicReference<EngineCompound> compound = new AtomicReference<>();
private final AtomicBoolean initialized;
private final String dimensionQuery;
private final boolean production;
private final KList<BlockPopulator> populators;
private long mst = 0;
private HeadlessGenerator headlessGenerator;
private NBTWorld nbtWorld;
private int generated = 0;
private int lgenerated = 0;
private final ChronoLatch hotloadcd;
@Getter
private double generatedPerSecond = 0;
private ReactiveFolder hotloader = null;
private IrisWorld cworld = null;
private final Looper ticker;
private final Looper cleaner;
private int hotloaderMisses = 0;
private long lastHotloadTime = 100;
public EngineCompositeGenerator() {
this(null, true);
}
public EngineCompositeGenerator(String query, boolean production) {
super();
ticker = new Looper() {
@Override
protected long loop() {
PrecisionStopwatch p = PrecisionStopwatch.start();
if (!tickHotloader()) {
hotloaderMisses++;
} else {
hotloaderMisses = 0;
}
lastHotloadTime += p.getMilliseconds();
lastHotloadTime /= 2;
return 120 + (lastHotloadTime / 2) + Math.min(hotloaderMisses * 125, 1375);
}
};
ticker.setPriority(Thread.MIN_PRIORITY);
ticker.setName("Iris Project Manager");
cleaner = new Looper() {
@Override
protected long loop() {
if (getComposite() != null) {
getComposite().clean();
}
return 10000;
}
};
cleaner.setPriority(Thread.MIN_PRIORITY);
cleaner.setName("Iris Parallax Manager");
cleaner.start();
if (isStudio()) {
ticker.start();
}
hotloadcd = new ChronoLatch(3500);
mst = M.ms();
this.production = production;
this.dimensionQuery = query;
initialized = new AtomicBoolean(false);
populators = new KList<BlockPopulator>().qadd(new BlockPopulator() {
@Override
public void populate(World world, Random random, Chunk chunk) {
if (compound.get() != null) {
for (BlockPopulator i : compound.get().getPopulators()) {
i.populate(world, random, chunk);
}
}
}
});
}
@Override
public void hotload() {
if (isStudio()) {
Iris.proj.updateWorkspace();
getData().dump();
J.s(() -> {
try {
for (Player i : getTarget().getWorld().getPlayers()) {
new VolmitSender(i, Iris.instance.getTag()).sendMessage("Dimension Hotloaded");
i.playSound(i.getLocation(), Sound.BLOCK_COPPER_PLACE, 1f, 1.25f);
}
} catch (Throwable e) {
Iris.reportError(e);
}
});
getComposite().close();
initialized.lazySet(false);
if (cworld != null) {
initialize(cworld);
}
}
}
public boolean tickHotloader() {
if (getComposite() == null || isClosed()) {
return false;
}
if (!initialized.get()) {
return false;
}
try {
if (hotloader != null) {
return hotloader.check();
}
} catch (Throwable e) {
Iris.reportError(e);
}
return false;
}
private synchronized IrisDimension getDimension(IrisWorld world) {
String query = dimensionQuery;
query = Iris.linkMultiverseCore.getWorldNameType(world.name(), query);
IrisDimension dim = null;
if (query == null) {
File iris = new File(world.worldFolder(), "iris");
if (iris.exists() && iris.isDirectory()) {
for (File i : iris.listFiles()) {
// Look for v1 location
if (i.isDirectory() && i.getName().equals("dimensions")) {
for (File j : i.listFiles()) {
if (j.isFile() && j.getName().endsWith(".json")) {
query = j.getName().replaceAll("\\Q.json\\E", "");
Iris.error("Found v1 install. Please create a new world, this will cause chunks to change in your existing iris worlds!");
throw new RuntimeException();
}
}
}
// Look for v2 location
else if (i.isFile() && i.getName().equals("engine-metadata.json")) {
EngineData metadata = EngineData.load(i);
query = metadata.getDimension();
break;
}
}
}
}
if (query == null) {
Iris.error("Cannot find iris dimension data for world: " + world.name() + "! Assuming " + IrisSettings.get().getGenerator().getDefaultWorldType() + "!");
query = IrisSettings.get().getGenerator().getDefaultWorldType();
}
dim = IrisData.loadAnyDimension(query);
if (dim == null) {
Iris.proj.downloadSearch(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag()), query, false);
dim = IrisData.loadAnyDimension(query);
if (dim == null) {
throw new RuntimeException("Cannot find dimension: " + query);
} else {
Iris.info("Download pack: " + query);
}
}
if (production) {
IrisDimension od = dim;
dim = new IrisData(getDataFolder(world)).getDimensionLoader().load(od.getLoadKey());
if (dim == null) {
Iris.info("Installing Iris pack " + od.getName() + " into world " + world.name() + "...");
Iris.proj.installIntoWorld(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag()), od.getLoadKey(), world.worldFolder());
dim = new IrisData(getDataFolder(world)).getDimensionLoader().load(od.getLoadKey());
if (dim == null) {
throw new RuntimeException("Cannot find dimension: " + query);
}
}
}
return dim;
}
private synchronized IrisDimension getDimension(String world) {
String query = dimensionQuery;
IrisDimension dim = null;
if (query == null) {
File iris = new File(world + "/iris");
if (iris.exists() && iris.isDirectory()) {
for (File i : Objects.requireNonNull(iris.listFiles())) {
// Look for v1 location
if (i.isDirectory() && i.getName().equals("dimensions")) {
for (File j : Objects.requireNonNull(i.listFiles())) {
if (j.isFile() && j.getName().endsWith(".json")) {
query = j.getName().replaceAll("\\Q.json\\E", "");
Iris.error("Found v1 install. Please create a new world, this will cause chunks to change in your existing iris worlds!");
throw new RuntimeException();
}
}
}
// Look for v2 location
else if (i.isFile() && i.getName().equals("engine-metadata.json")) {
EngineData metadata = EngineData.load(i);
query = metadata.getDimension();
break;
}
}
}
}
if (query == null) {
Iris.error("Cannot find iris dimension data for world: " + world + "! Assuming " + IrisSettings.get().getGenerator().getDefaultWorldType() + "!");
query = IrisSettings.get().getGenerator().getDefaultWorldType();
}
dim = IrisData.loadAnyDimension(query);
if (dim == null) {
Iris.proj.downloadSearch(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag()), query, false);
dim = IrisData.loadAnyDimension(query);
if (dim == null) {
throw new RuntimeException("Cannot find dimension: " + query);
} else {
Iris.info("Download pack: " + query);
}
}
if (production) {
IrisDimension od = dim;
dim = new IrisData(getDataFolder(world)).getDimensionLoader().load(od.getLoadKey());
if (dim == null) {
Iris.info("Installing Iris pack " + od.getName() + " into world " + world + "...");
Iris.proj.installIntoWorld(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag()), od.getLoadKey(), new File(world));
dim = new IrisData(getDataFolder(world)).getDimensionLoader().load(od.getLoadKey());
if (dim == null) {
throw new RuntimeException("Cannot find dimension: " + query);
}
}
}
Iris.info(world + " is configured to generate " + dim.getName() + "!");
return dim;
}
public synchronized void initialize(IrisWorld world) {
if (initialized.get()) {
return;
}
try {
initialized.set(true);
IrisDimension dim = getDimension(world);
IrisData data = production ? new IrisData(getDataFolder(world)) : dim.getLoader().copy();
compound.set(new IrisEngineCompound(world, dim, data, IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getEngineThreadCount())));
compound.get().setStudio(!production);
populators.clear();
populators.addAll(compound.get().getPopulators());
hotloader = new ReactiveFolder(data.getDataFolder(), (a, c, d) -> hotload());
cworld = world;
if (isStudio()) {
dim.installDataPack(() -> data, Iris.instance.getDatapacksFolder());
}
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
Iris.error("FAILED TO INITIALIZE DIMENSION FROM " + world.toString());
}
}
/**
* Place strongholds in the world
*/
public void placeStrongholds(World world) {
EngineData metadata = getComposite().getEngineMetadata();
// TODO: In nms class, not here. Also it doesnt work
if (metadata.getStrongholdPositions() == null || metadata.getStrongholdPositions().size() == 0) {
List<IrisPosition> strongholds = new ArrayList<>();
Object nmsWorld = new V(world).invoke("getHandle");
Object chunkProvider = new V(nmsWorld).invoke("getChunkProvider");
Object chunkGenerator = new V(chunkProvider).invoke("getChunkGenerator");
try {
Class<?> clazz = Class.forName("net.minecraft.world.level.chunk.ChunkGenerator");
Class<?> clazzSG = Class.forName("net.minecraft.world.level.levelgen.feature.StructureGenerator");
Class<?> clazzBP = Class.forName("net.minecraft.core.BlockPosition");
@SuppressWarnings("rawtypes") Constructor bpCon = clazzBP.getConstructor(int.class, int.class, int.class);
//By default, we place 9 strongholds. One near 0,0 and 8 all around it at about 10_000 blocks out
int[][] coords = {{0, 0}, {7000, -7000}, {10000, 0}, {7000, 7000}, {0, 10000}, {-7000, 7000}, {-10000, 0}, {-7000, -7000}, {0, -10000}};
//Set of stronghold locations so we don't place 2 strongholds at the same location
Set<Long> existing = new ConcurrentSet<>();
Set<CompletableFuture<Object>> futures = new HashSet<>();
for (int[] currCoords : coords) {
//Create a NMS BlockPosition
Object blockPosToTest = bpCon.newInstance(currCoords[0], 0, currCoords[1]);
//Create a CompletableFuture so we can track once the sync code is complete
CompletableFuture<Object> future = new CompletableFuture<>();
futures.add(future);
//We have to run this code synchronously because it uses NMS
J.s(() -> {
try {
Object o = getBP(clazz, clazzSG, clazzBP, nmsWorld, blockPosToTest, chunkGenerator);
future.complete(o);
} catch (Exception e) {
Iris.reportError(e);
e.printStackTrace();
future.complete(e);
}
});
}
CompletableFuture<Void> all = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
all.thenAccept((_void) -> { //Once all futures for all 9 strongholds have completed
for (CompletableFuture<Object> future : futures) {
try {
Object pos = future.getNow(null);
if (pos != null) {
IrisPosition ipos = new IrisPosition((int) new V(pos, false).invoke("getX"), (int) new V(pos,
false).invoke("getY"), (int) new V(pos, false).invoke("getZ"));
long xz = (((long) ipos.getX()) << 32) | (ipos.getZ() & 0xffffffffL);
if (existing.contains(xz)) return; //Make sure we don't double up on stronghold locs
existing.add(xz);
strongholds.add(ipos);
}
} catch (Exception e) {
Iris.reportError(e);
e.printStackTrace();
}
}
StringBuilder positions = new StringBuilder();
for (IrisPosition pos : strongholds) {
positions.append("(").append(pos.getX()).append(",").append(pos.getY()).append(",").append(pos.getZ()).append(") ");
}
Iris.info("Strongholds (" + strongholds.size() + ") found at [" + positions + "]");
metadata.setStrongholdPositions(strongholds);
getComposite().saveEngineMetadata();
});
} catch (Exception e) {
Iris.reportError(e);
strongholds.add(new IrisPosition(1337, 32, -1337));
metadata.setStrongholdPositions(strongholds);
Iris.warn("Couldn't properly find the stronghold position for this world. Is this headless mode? Are you not using 1.16 or higher?");
Iris.warn(" -> Setting default stronghold position");
e.printStackTrace();
StringBuilder positions = new StringBuilder();
for (IrisPosition pos : strongholds) {
positions.append("(").append(pos.getX()).append(",").append(pos.getY()).append(",").append(pos.getZ()).append(") ");
}
Iris.info("Strongholds (" + metadata.getStrongholdPositions().size() + ") found at [" + positions + "]");
}
}
}
/**
* Get BlockPosition for nearest stronghold from the provided position
*/
private Object getBP(Class<?> clazz, Class<?> clazzSG, Class<?> clazzBP, Object nmsWorld, Object pos, Object chunkGenerator) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
final String stronghold = "k"; //1.17_01 mapping
Object structureGeneratorStronghold = clazzSG.getDeclaredField(stronghold).get(null);
Method getNearestGeneratedFeature = clazz.getDeclaredMethod("findNearestMapFeature",
nmsWorld.getClass(),
clazzSG,
clazzBP,
int.class,
boolean.class
);
return getNearestGeneratedFeature.invoke(chunkGenerator,
nmsWorld,
structureGeneratorStronghold,
pos,
100,
false
);
}
private File getDataFolder(IrisWorld world) {
return new File(world.worldFolder(), "iris/pack");
}
private File getDataFolder(String world) {
return new File(world + "/iris/pack");
}
@Override
public ChunkData generateChunkData(World world, Random ignored, int x, int z, BiomeGrid biome) {
try {
PrecisionStopwatch ps = PrecisionStopwatch.start();
TerrainChunk tc = TerrainChunk.create(world, biome);
IrisWorld ww = (getComposite() == null || getComposite().getWorld() == null) ? IrisWorld.fromWorld(world) : getComposite().getWorld();
generateChunkRawData(ww, x, z, tc, true).run();
if (!getComposite().getWorld().hasRealWorld()) {
getComposite().getWorld().bind(world);
}
generated++;
ps.end();
if (IrisSettings.get().getGeneral().isDebug()) {
Iris.debug("Chunk " + C.GREEN + x + "," + z + C.LIGHT_PURPLE + " in " + C.YELLOW + Form.duration(ps.getMillis(), 2) + C.LIGHT_PURPLE + " Rate: " + C.BLUE + Form.f(getGeneratedPerSecond(), 0) + "/s");
}
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;
}
}
public void assignHeadlessGenerator(HeadlessGenerator headlessGenerator) {
this.headlessGenerator = headlessGenerator;
}
@Override
public HeadlessGenerator getHeadlessGenerator() {
return headlessGenerator;
}
public void assignHeadlessNBTWriter(NBTWorld writer) {
this.nbtWorld = writer;
}
@Override
public NBTWorld getHeadlessNBTWriter() {
return nbtWorld;
}
@Override
public void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst) {
directWriteMCA(w, x, z, writer, burst, null);
}
@Override
public void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst, PregenListener l) {
BurstExecutor e = burst.burst(1024);
PregenTask.iterateRegion(x, z, (ii, jj) -> e.queue(() -> {
if (l != null) {
l.onChunkGenerating(ii, jj);
}
directWriteChunk(w, ii, jj, writer);
if (l != null) {
l.onChunkGenerated(ii, jj);
}
}));
e.complete();
}
@Override
public void directWriteChunk(IrisWorld w, int x, int z, NBTWorld writer) {
try {
int ox = x << 4;
int oz = z << 4;
com.volmit.iris.util.nbt.mca.Chunk chunk = writer.getChunk(x, z);
generateChunkRawData(w, x, z, MCATerrainChunk.builder()
.writer(writer).ox(ox).oz(oz).mcaChunk(chunk)
.minHeight(w.minHeight()).maxHeight(w.maxHeight())
.injector((xx, yy, zz, biomeBase) -> chunk.setBiomeAt(ox + xx, yy, oz + zz,
INMS.get().getTrueBiomeBaseId(biomeBase)))
.build(), false).run();
} 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);
}
}
}
}
public Runnable generateChunkRawData(IrisWorld world, int x, int z, TerrainChunk tc, boolean multicore) {
initialize(world);
tickMetrics();
Hunk<BlockData> blocks = Hunk.view((ChunkData) tc);
Hunk<Biome> biomes = Hunk.view((BiomeGrid) tc);
Hunk<BlockData> post = Hunk.newAtomicHunk(biomes.getWidth(), biomes.getHeight(), biomes.getDepth());
compound.get().generate(x * 16, z * 16, blocks, post, biomes, multicore);
return () -> blocks.insertSoftly(0, 0, 0, post, (b) -> b == null || B.isAirOrFluid(b));
}
private void tickMetrics() {
if (M.ms() - mst > 1000) {
generatedPerSecond = (double) (generated - lgenerated) / ((double) (M.ms() - mst) / 1000D);
mst = M.ms();
lgenerated = generated;
}
}
@Override
public boolean canSpawn(World world, int x, int z) {
return super.canSpawn(world, x, z);
}
@Override
public List<BlockPopulator> getDefaultPopulators(World world) {
return populators;
}
@Override
public Location getFixedSpawnLocation(World world, Random random) {
return super.getFixedSpawnLocation(world, random);
}
@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;
}
public static EngineCompositeGenerator newStudioWorld(String dimension) {
return new EngineCompositeGenerator(dimension, false);
}
public static EngineCompositeGenerator newProductionWorld(String dimension) {
return new EngineCompositeGenerator(dimension, true);
}
public static EngineCompositeGenerator newProductionWorld() {
return new EngineCompositeGenerator(null, true);
}
public EngineCompound getComposite() {
return compound.get();
}
@Override
public IrisBiome getBiome(int x, int z) {
return getBiome(x, 0, z);
}
@Override
public IrisBiome getCaveBiome(int x, int z) {
return getCaveBiome(x, 0, z);
}
@Override
public int getGenerated() {
return generated;
}
@Override
public void printMetrics(CommandSender sender) {
getComposite().printMetrics(sender);
}
@Override
public IrisBiome getBiome(int x, int y, int z) {
// TODO: REMOVE GET ABS BIOME OR THIS ONE
return getEngineAccess(y).getBiome(x, y - getComposite().getEngineForHeight(y).getMinHeight(), z);
}
@Override
public IrisBiome getCaveBiome(int x, int y, int z) {
return getEngineAccess(y).getCaveBiome(x, z);
}
@Override
public GeneratorAccess getEngineAccess(int y) {
return getComposite().getEngineForHeight(y);
}
@Override
public IrisData getData() {
if (getCompound() == null) {
return null;
}
return getComposite().getData();
}
@Override
public int getHeight(int x, int y, int z) {
return getEngineAccess(y).getHeight(x, z);
}
@Override
public int getThreadCount() {
return getComposite().getThreadCount();
}
@Override
public void changeThreadCount(int m) {
// TODO: DO IT
}
@Override
public void close() {
if (isStudio()) {
ticker.interrupt();
}
cleaner.interrupt();
if (getComposite() != null) {
getComposite().close();
if (isStudio() && getComposite().getWorld().hasRealWorld()) {
getComposite().getWorld().evacuate();
Bukkit.unloadWorld(getComposite().getWorld().realWorld(), !isStudio());
}
}
}
@Override
public boolean isClosed() {
try {
return getComposite().getEngine(0).isClosed();
} catch (Throwable e) {
Iris.reportError(e);
return false;
}
}
@Override
public EngineTarget getTarget() {
try {
return getComposite().getEngine(0).getTarget();
} catch (NullPointerException e) {
Iris.reportError(e);
Iris.info("Failed to get composite engine. Please re-create the world in case you notice issues");
return null;
}
}
@Override
public EngineCompound getCompound() {
return getComposite();
}
@Override
public boolean isFailing() {
if (getComposite() == null) {
return false;
}
return getComposite().isFailing();
}
@Override
public boolean isStudio() {
return !production;
}
public boolean isVanillaCaves() {
return false;
}
public KList<IrisBiome> getAllBiomes(String worldName) {
if (getComposite() != null) {
return getComposite().getAllBiomes();
} else {
KMap<String, IrisBiome> v = new KMap<>();
IrisDimension dim = getDimension(worldName);
dim.getAllAnyBiomes().forEach((i) -> v.put(i.getLoadKey(), i));
try {
dim.getDimensionalComposite().forEach((m) -> IrisData.loadAnyDimension(m.getDimension()).getAllAnyBiomes().forEach((i) -> v.put(i.getLoadKey(), i)));
} catch (Throwable ignored) {
Iris.reportError(ignored);
}
Iris.info("Injecting " + v.size() + " biomes into the NMS World Chunk Provider (Iris)");
return v.v();
}
}
}

View File

@ -1,169 +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.framework;
import com.volmit.iris.Iris;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.engine.actuator.IrisTerrainNormalActuator;
import com.volmit.iris.engine.object.basic.IrisPosition;
import com.volmit.iris.engine.object.biome.IrisBiome;
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.collection.KMap;
import com.volmit.iris.util.data.DataProvider;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.parallel.MultiBurst;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.event.Listener;
import org.bukkit.generator.BlockPopulator;
import java.util.List;
public interface EngineCompound extends Listener, Hotloadable, DataProvider {
IrisDimension getRootDimension();
void generate(int x, int z, Hunk<BlockData> blocks, Hunk<BlockData> postblocks, Hunk<Biome> biomes, boolean multicore);
IrisWorld getWorld();
List<IrisPosition> getStrongholdPositions();
void printMetrics(CommandSender sender);
int getSize();
default int getHeight() {
// TODO: WARNING HEIGHT
return 256;
}
Engine getEngine(int index);
MultiBurst getBurster();
EngineData getEngineMetadata();
void saveEngineMetadata();
KList<BlockPopulator> getPopulators();
default Engine getEngineForHeight(int height) {
if (getSize() == 1) {
return getEngine(0);
}
int buf = 0;
for (int i = 0; i < getSize(); i++) {
Engine e = getEngine(i);
buf += e.getHeight();
if (buf >= height) {
return e;
}
}
return getEngine(getSize() - 1);
}
default void recycle() {
for (int i = 0; i < getSize(); i++) {
getEngine(i).recycle();
}
}
default void save() {
saveEngineMetadata();
for (int i = 0; i < getSize(); i++) {
getEngine(i).save();
}
}
default void saveNOW() {
saveEngineMetadata();
for (int i = 0; i < getSize(); i++) {
getEngine(i).saveNow();
}
}
IrisData getData(int height);
default IrisData getData() {
return getData(0);
}
default void close() {
for (int i = 0; i < getSize(); i++) {
getEngine(i).close();
}
}
boolean isFailing();
int getThreadCount();
boolean isStudio();
void setStudio(boolean std);
default void clean() {
for (int i = 0; i < getSize(); i++) {
getEngine(i).clean();
}
}
Engine getDefaultEngine();
default KList<IrisBiome> getAllBiomes() {
KMap<String, IrisBiome> v = new KMap<>();
IrisDimension dim = getRootDimension();
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();
}
default int getLowestBedrock() {
int f = Integer.MAX_VALUE;
for (int i = 0; i < getSize(); i++) {
Engine e = getEngine(i);
if (e.getDimension().isBedrock()) {
int m = ((IrisTerrainNormalActuator) e.getTerrainActuator()).getLastBedrock();
if (f > m) {
f = m;
}
}
}
return f;
}
}

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.parallax.ParallaxWorld;
import com.volmit.iris.util.parallel.MultiBurst;
import lombok.Builder;
import lombok.Data;
import java.io.File;
@ -34,24 +35,24 @@ public class EngineTarget {
private final MultiBurst burster;
private final IrisDimension dimension;
private IrisWorld world;
private final int height;
private final IrisData data;
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.height = height;
this.dimension = dimension;
this.data = data;
this.inverted = inverted;
this.burster = new MultiBurst("Iris Engine " + dimension.getName(), IrisSettings.get().getConcurrency().getEngineThreadPriority(), threads);
this.burster = new MultiBurst("Iris Engine " + dimension.getName(),
IrisSettings.get().getConcurrency().getEngineThreadPriority(),
IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getEngineThreadCount()));
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) {
this(world, dimension, data, height, false, threads);
public int getHeight()
{
return world.maxHeight() - world.minHeight();
}
public void close() {

View File

@ -1,287 +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.framework;
import com.volmit.iris.Iris;
import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.engine.framework.headless.HeadlessGenerator;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.common.IrisWorld;
import com.volmit.iris.engine.object.regional.IrisRegion;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.DataProvider;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import org.bukkit.Location;
import org.bukkit.command.CommandSender;
import org.bukkit.util.Vector;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
@SuppressWarnings("EmptyMethod")
public interface IrisAccess extends Hotloadable, DataProvider {
HeadlessGenerator getHeadlessGenerator();
default boolean isHeadless() {
return getHeadlessGenerator() != null;
}
NBTWorld getHeadlessNBTWriter();
void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst);
void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst, PregenListener listener);
void directWriteChunk(IrisWorld w, int x, int z, NBTWorld writer);
int getGenerated();
double getGeneratedPerSecond();
void printMetrics(CommandSender sender);
/**
* Ignores the world, just uses the position
*
* @param l the location
* @return the biome
*/
default IrisBiome getBiome(Location l) {
return getBiome(l.toVector());
}
default IrisRegion getRegion(int x, int y, int z) {
return getEngineAccess(y).getRegion(x, z);
}
default IrisRegion getRegion(Location l) {
return getRegion(l.getBlockX(), l.getBlockY(), l.getBlockZ());
}
default IrisBiome getBiome(Vector l) {
return getBiome(l.getBlockX(), l.getBlockY(), l.getBlockZ());
}
IrisBiome getBiome(int x, int y, int z);
IrisBiome getCaveBiome(int x, int y, int z);
IrisBiome getBiome(int x, int z);
IrisBiome getCaveBiome(int x, int z);
GeneratorAccess getEngineAccess(int y);
IrisData getData();
int getHeight(int x, int y, int z);
int getThreadCount();
void changeThreadCount(int m);
void close();
boolean isClosed();
EngineTarget getTarget();
EngineCompound getCompound();
boolean isFailing();
boolean isStudio();
default Location lookForBiome(IrisBiome biome, long timeout, Consumer<Integer> triesc) {
if (!getCompound().getWorld().hasRealWorld()) {
Iris.error("Cannot GOTO without a bound world (headless mode)");
return null;
}
ChronoLatch cl = new ChronoLatch(250, false);
long s = M.ms();
int cpus = (Runtime.getRuntime().availableProcessors());
KList<Engine> engines = new KList<>();
for (int i = 0; i < getCompound().getSize(); i++) {
Engine e = getCompound().getEngine(i);
if (e.getDimension().getAllBiomes(e).contains(biome)) {
engines.add(e);
}
}
if (engines.isEmpty()) {
return null;
}
AtomicInteger tries = new AtomicInteger(0);
AtomicBoolean found = new AtomicBoolean(false);
AtomicBoolean running = new AtomicBoolean(true);
AtomicReference<Location> location = new AtomicReference<>();
for (int i = 0; i < cpus; i++) {
J.a(() -> {
try {
Engine e;
IrisBiome b;
int x, z;
while (!found.get() && running.get()) {
try {
synchronized (engines) {
e = engines.getRandom();
x = RNG.r.i(-29999970, 29999970);
z = RNG.r.i(-29999970, 29999970);
b = e.getSurfaceBiome(x, z);
}
if (b != null && b.getLoadKey() == null) {
continue;
}
if (b != null && b.getLoadKey().equals(biome.getLoadKey())) {
found.lazySet(true);
location.lazySet(new Location(e.getWorld().realWorld(), x, e.getHeight(x, z), z));
}
tries.getAndIncrement();
} catch (Throwable ex) {
Iris.reportError(ex);
ex.printStackTrace();
return;
}
}
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
}
});
}
while (!found.get() || location.get() == null) {
J.sleep(50);
if (cl.flip()) {
triesc.accept(tries.get());
}
if (M.ms() - s > timeout) {
running.set(false);
return null;
}
}
running.set(false);
return location.get();
}
default Location lookForRegion(IrisRegion reg, long timeout, Consumer<Integer> triesc) {
if (!getCompound().getWorld().hasRealWorld()) {
Iris.error("Cannot GOTO without a bound world (headless mode)");
return null;
}
ChronoLatch cl = new ChronoLatch(3000, false);
long s = M.ms();
int cpus = (Runtime.getRuntime().availableProcessors());
KList<Engine> engines = new KList<>();
for (int i = 0; i < getCompound().getSize(); i++) {
Engine e = getCompound().getEngine(i);
if (e.getDimension().getRegions().contains(reg.getLoadKey())) {
engines.add(e);
}
}
if (engines.isEmpty()) {
return null;
}
AtomicInteger tries = new AtomicInteger(0);
AtomicBoolean found = new AtomicBoolean(false);
AtomicBoolean running = new AtomicBoolean(true);
AtomicReference<Location> location = new AtomicReference<>();
for (int i = 0; i < cpus; i++) {
J.a(() -> {
Engine e;
IrisRegion b;
int x, z;
while (!found.get() && running.get()) {
try {
e = engines.getRandom();
x = RNG.r.i(-29999970, 29999970);
z = RNG.r.i(-29999970, 29999970);
b = e.getRegion(x, z);
if (b != null && b.getLoadKey() != null && b.getLoadKey().equals(reg.getLoadKey())) {
found.lazySet(true);
location.lazySet(new Location(e.getWorld().realWorld(), x, e.getHeight(x, z) + e.getMinHeight(), z));
}
tries.getAndIncrement();
} catch (Throwable xe) {
Iris.reportError(xe);
xe.printStackTrace();
return;
}
}
});
}
while (!found.get() || location.get() != null) {
J.sleep(50);
if (cl.flip()) {
triesc.accept(tries.get());
}
if (M.ms() - s > timeout) {
triesc.accept(tries.get());
running.set(false);
return null;
}
}
triesc.accept(tries.get());
running.set(false);
return location.get();
}
default int getParallaxChunkCount() {
int v = 0;
for (int i = 0; i < getCompound().getSize(); i++) {
v += getCompound().getEngine(i).getParallax().getChunkCount();
}
return v;
}
default double getHeight(Location l) {
return getHeight(l.getBlockX(), l.getBlockY(), l.getBlockZ());
}
}

View File

@ -1,93 +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.framework.headless;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.engine.framework.EngineCompositeGenerator;
import com.volmit.iris.util.collection.KList;
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.parallel.MultiBurst;
import lombok.Data;
import java.io.File;
import java.io.IOException;
@Data
public class HeadlessGenerator {
private static KList<Position2> EMPTYPOINTS = new KList<>();
private final HeadlessWorld world;
private final EngineCompositeGenerator generator;
private final NBTWorld writer;
private final MultiBurst burst;
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());
generator = new EngineCompositeGenerator(world.getDimension().getLoadKey(), !world.isStudio());
generator.assignHeadlessGenerator(this);
generator.assignHeadlessNBTWriter(writer);
generator.initialize(world.getWorld());
}
public void generateChunk(int x, int z) {
generator.directWriteChunk(world.getWorld(), x, z, writer);
}
public void generateRegion(int x, int z) {
generator.directWriteMCA(world.getWorld(), x, z, writer, burst);
}
public void generateRegion(int x, int z, PregenListener listener) {
generator.directWriteMCA(world.getWorld(), x, z, writer, burst, listener);
}
public File generateRegionToFile(int x, int z, PregenListener listener) {
generateRegionToFile(x, z, listener);
flush();
return writer.getRegionFile(x, z);
}
public void flush() {
writer.flushNow();
}
public void save() {
writer.save();
}
public void close() {
burst.shutdownAndAwait();
generator.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;
}
}

View File

@ -19,9 +19,8 @@
package com.volmit.iris.engine.jigsaw;
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.IrisAccess;
import com.volmit.iris.engine.object.basic.IrisPosition;
import com.volmit.iris.engine.object.common.IObjectPlacer;
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.IrisObjectTranslate;
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.math.AxisAlignedBB;
import com.volmit.iris.util.math.BlockPosition;
@ -150,13 +150,13 @@ public class PlannedPiece {
}
public void place(World world) {
IrisAccess a = IrisWorlds.access(world);
PlatformChunkGenerator a = IrisToolbelt.access(world);
int minY = 0;
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
}
@ -191,7 +191,7 @@ public class PlannedPiece {
IrisLootTable table = getPiece().getPlacementOptions().getTable(block.getBlockData(), getData());
if (table == null) return;
Engine engine = a.getCompound().getEngineForHeight(y);
Engine engine = a.getEngine();
engine.addItems(false, ((InventoryHolder) block.getState()).getInventory(),
rng.nextParallelRNG(BlockPosition.toLong(x, y, z)),
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.volmit.iris.Iris;
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.IrisAccess;
import com.volmit.iris.engine.object.basic.IrisPosition;
import com.volmit.iris.engine.object.common.IObjectPlacer;
import com.volmit.iris.engine.object.entity.IrisEntity;
@ -174,7 +174,7 @@ public class PlannedStructure {
Iris.sq(() -> {
for (IrisJigsawPieceConnector j : i.getAvailableConnectors()) {
if (j.getSpawnEntity() != null) {
IrisAccess a = IrisWorlds.access(world);
Engine a = IrisToolbelt.access(world).getEngine();
if (a == null) {
Iris.warn("Cannot spawn entities from jigsaw in non Iris world!");
break;
@ -183,7 +183,7 @@ public class PlannedStructure {
IrisEntity e = getData().getEntityLoader().load(j.getSpawnEntity());
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()) {
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.project.loader.IrisData;
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.data.cache.AtomicCache;
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.block.IrisBlockDrops;
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;
for (IrisBiomeGeneratorLink i : generators) {

View File

@ -16,13 +16,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.engine.framework.headless;
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.IrisWorlds;
import com.volmit.iris.engine.framework.EngineCompositeGenerator;
import com.volmit.iris.engine.object.common.IrisWorld;
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;
@ -38,7 +38,7 @@ public class HeadlessWorld {
private final IrisDimension dimension;
private final String worldName;
private final IrisWorld world;
private boolean studio = false;
private boolean studio;
public HeadlessWorld(String worldName, IrisDimension dimension, long seed) {
this(worldName, dimension, seed, false);
@ -59,7 +59,7 @@ public class HeadlessWorld {
world.worldFolder().mkdirs();
new File(world.worldFolder(), "region").mkdirs();
if (!studio && !new File(world.worldFolder(), "iris").exists()) {
if (!studio && !new File(world.worldFolder(), "iris/pack").exists()) {
Iris.proj.installIntoWorld(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag("Headless")), dimension.getLoadKey(), world.worldFolder());
}
}
@ -72,14 +72,15 @@ public class HeadlessWorld {
World w = new WorldCreator(worldName)
.environment(dimension.getEnvironment())
.seed(world.seed())
.generator(new EngineCompositeGenerator(dimension.getLoadKey(), !studio))
.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(), IrisWorlds.access(world).getTarget().getDimension(), world.getSeed());
return new HeadlessWorld(world.getName(), IrisToolbelt.access(world).getEngine().getTarget().getDimension(), world.getSeed());
}
public static HeadlessWorld from(String name, String dimension, long seed) {

View File

@ -19,7 +19,7 @@
package com.volmit.iris.engine.object.common;
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 lombok.Builder;
import lombok.Data;
@ -76,11 +76,16 @@ public class IrisWorld {
public void evacuate() {
if (hasRealWorld()) {
IrisWorlds.evacuate(realWorld());
IrisToolbelt.evacuate(realWorld());
}
}
public void bind(World world) {
if(hasRealWorld())
{
return;
}
bindWorld(this, world);
}
@ -100,4 +105,8 @@ public class IrisWorld {
return (KList<? extends T>) NO_ENTITIES;
}
public int getHeight() {
return maxHeight - minHeight;
}
}

View File

@ -238,7 +238,7 @@ public class IrisEntity extends IrisRegistrant {
inventory.addItem(i);
}
gen.getCompound().getEngine(at.getBlockY()).scramble(inventory, rng);
gen.scramble(inventory, rng);
}
});
}

View File

@ -32,10 +32,7 @@ public enum IrisEngineValueType {
ENGINE_MIN_HEIGHT((f) -> Double.valueOf(f.getMinHeight())),
@Desc("Represents virtual top of the engine in the compound. If this engine is below another engine, it's max height would be at the minHeight of the next engine - 1")
ENGINE_MAX_HEIGHT((f) -> Double.valueOf(f.getMaxHeight())),
@Desc("Represents the position of the engine in the dimensional compound. The bottom (first) dimension stasts at 0. Each new dimension added stacks on top with n+1 for the id.")
ENGINE_INDEX((f) -> Double.valueOf(f.getIndex())),
ENGINE_MAX_HEIGHT((f) -> Double.valueOf(f.getWorld().maxHeight())),
@Desc("The fluid height defined in the dimension file")
FLUID_HEIGHT((f) -> Double.valueOf(f.getComplex().getFluidHeight())),

View File

@ -0,0 +1,191 @@
/*
* 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.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.IO;
import com.volmit.iris.util.io.ReactiveFolder;
import com.volmit.iris.util.parallel.MultiBurst;
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 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.atomic.AtomicBoolean;
public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChunkGenerator {
private static final BlockData ERROR_BLOCK = Material.RED_GLAZED_TERRACOTTA.createBlockData();
private final EngineProvider provider;
private final IrisWorld world;
private final File dataLocation;
private final String dimensionKey;
private final ReactiveFolder folder;
private final KList<BlockPopulator> populators;
private final ChronoLatch hotloadChecker;
private final Looper hotloader;
private final boolean studio;
public BukkitChunkGenerator(IrisWorld world, boolean studio, File dataLocation, String dimensionKey)
{
populators = new KList<>();
this.world = world;
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();
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");
}
public Engine getEngine()
{
return provider.getEngine();
}
@Override
public boolean isHeadless() {
return false;
}
@Override
public void close() {
hotloader.interrupt();
provider.close();
}
@Override
public boolean isStudio() {
return studio;
}
@Override
public void hotload() {
initialize();
}
private void initialize()
{
provider.provideEngine(world, dimensionKey, dataLocation, isStudio(), (e) -> {
populators.clear();
populators.add((BlockPopulator) e);
folder.checkIgnore();
});
}
@Override
public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random ignored, int x, int z, @NotNull BiomeGrid biome) {
try
{
Iris.debug("Generated " + x + " " + z);
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);
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,78 @@
/*
* 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 org.bukkit.generator.BlockPopulator;
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 = new IrisData(dataLocation);
IrisDimension realDimension = data.getDimensionLoader().load(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 {
return engine.get().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
public void close() {
if(engine.get() != null && engine.get().isDone())
{
Engine e = getEngine();
if(e != null)
{
e.close();
}
}
}
}

View File

@ -0,0 +1,169 @@
/*
* 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 EngineProvider provider;
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) -> {});
}
@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();
getEngine().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();
provider.close();
writer.close();
}
@Override
public boolean isStudio() {
return false;
}
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 Engine getEngine() {
return provider.getEngine();
}
@Override
public boolean isHeadless() {
return true;
}
@Override
public void hotload() {
}
}

View File

@ -16,8 +16,33 @@
* 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 {
IrisAccess getAccess();
import com.volmit.iris.core.project.loader.IrisData;
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;
import java.io.File;
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

@ -19,6 +19,7 @@
package com.volmit.iris.util.format;
import com.volmit.iris.Iris;
import com.volmit.iris.util.plugin.VolmitSender;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import org.apache.commons.lang.Validate;
@ -368,6 +369,10 @@ public enum C {
}
public static String aura(String s, int hrad, int srad, int vrad) {
return aura(s, hrad, srad, vrad, 0.3D);
}
public static String aura(String s, int hrad, int srad, int vrad, double pulse) {
String msg = compress(s);
StringBuilder b = new StringBuilder();
boolean c = false;
@ -379,11 +384,19 @@ public enum C {
C o = C.getByChar(i);
if (hrad != 0 || srad != 0 || vrad != 0) {
b.append("<gradient:")
.append(spinToHex(o, hrad, srad, vrad))
.append(":")
.append(spinToHex(o, -hrad, -srad, -vrad))
.append(">");
if(pulse > 0)
{
b.append(VolmitSender.pulse(spinToHex(o, hrad, srad, vrad), spinToHex(o, -hrad, -srad, -vrad), pulse));
}
else
{
b.append("<gradient:")
.append(spinToHex(o, hrad, srad, vrad))
.append(":")
.append(spinToHex(o, -hrad, -srad, -vrad))
.append(">");
}
} else {
b.append(C.getByChar(i).token);
}

View File

@ -0,0 +1,53 @@
/*
* 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.util.io;
import com.volmit.iris.util.math.RNG;
import java.io.File;
import java.io.IOException;
public class InstanceState {
public static int getInstanceId()
{
try {
return Integer.parseInt(IO.readAll(instanceFile()).trim());
} catch (Throwable e) {
e.printStackTrace();
}
return -1;
}
public static void updateInstanceId()
{
try {
IO.writeAll(instanceFile(), RNG.r.imax() + "");
} catch (IOException e) {
e.printStackTrace();
}
}
private static File instanceFile()
{
File f = new File("plugins/Iris/cache/instance");
f.getParentFile().mkdirs();
return f;
}
}

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.util.collection.KList;
import com.volmit.iris.util.io.InstanceState;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.Looper;
@ -38,6 +39,7 @@ public class MultiBurst {
private final String name;
private final int tc;
private final int priority;
private final int instance;
public MultiBurst(int tc) {
this("Iris", 6, tc);
@ -47,17 +49,24 @@ public class MultiBurst {
this.name = name;
this.priority = priority;
this.tc = tc;
instance = InstanceState.getInstanceId();
last = new AtomicLong(M.ms());
heartbeat = new Looper() {
@Override
protected long loop() {
if(instance != InstanceState.getInstanceId())
{
shutdownNow();
return -1;
}
if (M.ms() - last.get() > TimeUnit.MINUTES.toMillis(1) && service != null) {
service.shutdown();
service = null;
Iris.debug("Shutting down MultiBurst Pool " + getName() + " to conserve resources.");
}
return 60000;
return 30000;
}
};
heartbeat.setName(name + " Monitor");

View File

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

View File

@ -21,10 +21,16 @@ package com.volmit.iris.util.plugin;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.scheduling.J;
import lombok.Getter;
import lombok.Setter;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.transformation.inbuild.GradientTransformation;
import net.kyori.adventure.text.minimessage.transformation.inbuild.RainbowTransformation;
import net.kyori.adventure.title.Title;
import org.bukkit.Server;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -33,8 +39,14 @@ import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.Plugin;
import java.time.Duration;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
/**
* Represents a volume sender. A command sender with extra crap in it
@ -181,6 +193,114 @@ public class VolmitSender implements CommandSender {
s.sendMessage("========================================================");
}
public void sendTitle(String title, String subtitle, int i, int s, int o)
{
Iris.audiences.player(player()).showTitle(Title.title(
createComponent(title),
createComponent(subtitle),
Title.Times.of(Duration.ofMillis(i), Duration.ofMillis(s), Duration.ofMillis(o))));
}
public static long getTick()
{
return M.ms() / 16;
}
public void sendProgress(double percent, String thing)
{
if(percent < 0)
{
int l = 44;
int g = (int) (1D * l);
sendTitle(C.IRIS + thing + " ", 0, 500, 250);
sendActionNoProcessing("" + "" + pulse("#00ff80","#00373d",1D)+"<underlined> " + Form.repeat(" ", g) + "<reset>" + Form.repeat(" ", l - g));
}
else
{
int l = 44;
int g = (int) (percent * l);
sendTitle(C.IRIS + thing + " " + C.BLUE + "<font:minecraft:uniform>" + Form.pc(percent, 0), 0, 500, 250);
sendActionNoProcessing("" + "" + pulse("#00ff80","#00373d",1D)+"<underlined> " + Form.repeat(" ", g) + "<reset>" + Form.repeat(" ", l - g));
}
}
public static String pulse(String colorA, String colorB, double speed)
{
return "<gradient:" + colorA + ":" + colorB + ":" + pulse(speed) + ">";
}
public static String pulse(double speed) {
return Form.f(invertSpread((((getTick()*15D * speed)%1000D)/1000D)), 3);
}
public static double invertSpread(double v) {
return ((1D - v) * 2D) - 1D;
}
public void sendAction(String action)
{
Iris.audiences.player(player()).sendActionBar(createNoPrefixComponent(action));
}
public void sendActionNoProcessing(String action)
{
Iris.audiences.player(player()).sendActionBar(createNoPrefixComponentNoProcessing(action));
}
public void sendTitle(String subtitle, int i, int s, int o)
{
Iris.audiences.player(player()).showTitle(Title.title(
createNoPrefixComponent(" "),
createNoPrefixComponent(subtitle),
Title.Times.of(Duration.ofMillis(i), Duration.ofMillis(s), Duration.ofMillis(o))));
}
private Component createNoPrefixComponent(String message)
{
String t = C.translateAlternateColorCodes('&', message);
String a = C.aura(t, IrisSettings.get().getGeneral().getSpinh(), IrisSettings.get().getGeneral().getSpins(), IrisSettings.get().getGeneral().getSpinb(), 0.36);
return MiniMessage.get().parse(a);
}
private Component createNoPrefixComponentNoProcessing(String message)
{
return MiniMessage.get().parse(message);
}
private Component createComponent(String message)
{
String t = C.translateAlternateColorCodes('&', getTag() + message);
String a = C.aura(t, IrisSettings.get().getGeneral().getSpinh(), IrisSettings.get().getGeneral().getSpins(), IrisSettings.get().getGeneral().getSpinb());
return MiniMessage.get().parse(a);
}
public <T> void showWaiting(String passive, CompletableFuture<T> f)
{
AtomicInteger v = new AtomicInteger();
AtomicReference<T> g = new AtomicReference<>();
v.set(J.ar(() -> {
if(f.isDone() && g.get() != null)
{
J.car(v.get());
sendAction(" ");
return;
}
sendProgress(-1, passive);
}, 0));
J.a(() -> {
try {
g.set(f.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
}
@Override
public void sendMessage(String message) {
if (message.contains("<NOMINI>")) {
@ -189,10 +309,7 @@ public class VolmitSender implements CommandSender {
}
try {
String t = C.translateAlternateColorCodes('&', getTag() + message);
String a = C.aura(t, IrisSettings.get().getGeneral().getSpinh(), IrisSettings.get().getGeneral().getSpins(), IrisSettings.get().getGeneral().getSpinb());
Component c = MiniMessage.get().parse(a);
Iris.audiences.sender(s).sendMessage(c);
Iris.audiences.sender(s).sendMessage(createComponent(message));
} catch (Throwable e) {
String t = C.translateAlternateColorCodes('&', getTag() + message);
String a = C.aura(t, IrisSettings.get().getGeneral().getSpinh(), IrisSettings.get().getGeneral().getSpins(), IrisSettings.get().getGeneral().getSpinb());

View File

@ -42,7 +42,7 @@ public abstract class Looper extends Thread {
}
}
Iris.info("Thread " + getName() + " Shutdown. Pregen stopped / finished.");
Iris.debug("Iris Thread " + getName() + " Shutdown.");
}
protected abstract long loop();