This commit is contained in:
Daniel Mills 2020-11-15 23:36:33 -05:00
parent 116ab72f4e
commit 6d08faa30f
33 changed files with 576 additions and 265 deletions

View File

@ -190,7 +190,6 @@ public class Iris extends VolmitPlugin
board.disable();
Bukkit.getScheduler().cancelTasks(this);
HandlerList.unregisterAll((Plugin) this);
IrisDataManager.managers.clear();
super.onDisable();
}

View File

@ -4,6 +4,8 @@ import com.volmit.iris.Iris;
import com.volmit.iris.scaffold.engine.*;
import com.volmit.iris.scaffold.hunk.Hunk;
import com.volmit.iris.scaffold.parallel.MultiBurst;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RNG;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Chunk;
@ -36,15 +38,20 @@ public class IrisEngine extends BlockPopulator implements Engine
@Getter
private final int index;
@Getter
private final EngineMetrics metrics;
@Setter
@Getter
private volatile int minHeight;
private boolean failing;
private boolean closed;
private int cacheId;
public IrisEngine(EngineTarget target, EngineCompound compound, int index)
{
Iris.info("Initializing Engine: " + target.getWorld().getName() + "/" + target.getDimension().getLoadKey() + " (" + target.getHeight() + " height)");
metrics = new EngineMetrics(32);
this.target = target;
this.framework = new IrisEngineFramework(this);
worldManager = new IrisWorldManager(this);
@ -53,6 +60,7 @@ public class IrisEngine extends BlockPopulator implements Engine
failing = false;
closed = false;
this.index = index;
cacheId = RNG.r.nextInt();
}
@Override
@ -82,6 +90,7 @@ public class IrisEngine extends BlockPopulator implements Engine
public void generate(int x, int z, Hunk<BlockData> vblocks, Hunk<Biome> vbiomes) {
try
{
PrecisionStopwatch p = PrecisionStopwatch.start();
Hunk<Biome> biomes = vbiomes;
Hunk<BlockData> blocks = vblocks.synchronize().listen((xx,y,zz,t) -> catchBlockUpdates(x+xx,y+getMinHeight(),z+zz, t));
@ -102,6 +111,7 @@ public class IrisEngine extends BlockPopulator implements Engine
getFramework().getEngineParallax().insertParallax(x, z, blocks);
getFramework().recycle();
getMetrics().getTotal().put(p.getMilliseconds());
}
catch(Throwable e)
{
@ -127,4 +137,14 @@ public class IrisEngine extends BlockPopulator implements Engine
public boolean hasFailed() {
return failing;
}
@Override
public int getCacheID() {
return cacheId;
}
@Override
public void hotload() {
cacheId = RNG.r.nextInt();
}
}

View File

@ -11,12 +11,13 @@ import com.volmit.iris.scaffold.engine.EngineTarget;
import com.volmit.iris.scaffold.hunk.Hunk;
import com.volmit.iris.scaffold.parallel.BurstExecutor;
import com.volmit.iris.scaffold.parallel.MultiBurst;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.*;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.World;
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;
@ -29,6 +30,8 @@ public class IrisEngineCompound implements EngineCompound {
@Getter
private final World world;
private final AtomicRollingSequence wallClock;
@Getter
private final EngineData engineMetadata;
@ -52,6 +55,7 @@ public class IrisEngineCompound implements EngineCompound {
public IrisEngineCompound(World world, IrisDimension rootDimension, IrisDataManager data, int maximumThreads)
{
wallClock = new AtomicRollingSequence(32);
this.rootDimension = rootDimension;
Iris.info("Initializing Engine Composite for " + world.getName());
this.world = world;
@ -116,6 +120,75 @@ public class IrisEngineCompound implements EngineCompound {
}
}
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.getWorldFolder(), "iris/engine-metadata.json");
}
@ -123,6 +196,7 @@ public class IrisEngineCompound implements EngineCompound {
@Override
public void generate(int x, int z, Hunk<BlockData> blocks, Hunk<Biome> biomes)
{
PrecisionStopwatch p = PrecisionStopwatch.start();
if(engines.length == 1 && !getEngine(0).getTarget().isInverted())
{
engines[0].generate(x, z, blocks, biomes);
@ -166,8 +240,9 @@ public class IrisEngineCompound implements EngineCompound {
insert[i].run();
}
}
}
wallClock.put(p.getMilliseconds());
}
@Override
public int getSize() {
@ -194,4 +269,12 @@ public class IrisEngineCompound implements EngineCompound {
public boolean isFailing() {
return false;
}
@Override
public void hotload() {
for(int i = 0; i < getSize(); i++)
{
getEngine(i).hotload();
}
}
}

View File

@ -3,6 +3,7 @@ package com.volmit.iris.generator.actuator;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedActuator;
import com.volmit.iris.scaffold.hunk.Hunk;
import com.volmit.iris.util.PrecisionStopwatch;
import org.bukkit.block.Biome;
public class IrisBiomeActuator extends EngineAssignedActuator<Biome>
@ -13,6 +14,7 @@ public class IrisBiomeActuator extends EngineAssignedActuator<Biome>
@Override
public void onActuate(int x, int z, Hunk<Biome> h) {
PrecisionStopwatch p = PrecisionStopwatch.start();
int i,zf;
Biome v;
@ -28,5 +30,6 @@ public class IrisBiomeActuator extends EngineAssignedActuator<Biome>
}
}
}
getEngine().getMetrics().getBiome().put(p.getMilliseconds());
}
}

View File

@ -1,6 +1,7 @@
package com.volmit.iris.generator.actuator;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RNG;
import com.volmit.iris.generator.decorator.IrisCeilingDecorator;
import com.volmit.iris.generator.decorator.IrisSeaSurfaceDecorator;
@ -47,6 +48,7 @@ public class IrisDecorantActuator extends EngineAssignedActuator<BlockData>
return;
}
PrecisionStopwatch p = PrecisionStopwatch.start();
boolean solid;
int emptyFor = 0;
int lastSolid = 0;
@ -108,6 +110,8 @@ public class IrisDecorantActuator extends EngineAssignedActuator<BlockData>
}
}
}
getEngine().getMetrics().getDecoration().put(p.getMilliseconds());
}
private boolean shouldRayDecorate()

View File

@ -2,6 +2,7 @@ package com.volmit.iris.generator.actuator;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RNG;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedActuator;
@ -27,6 +28,7 @@ public class IrisTerrainActuator extends EngineAssignedActuator<BlockData>
@Override
public void onActuate(int x, int z, Hunk<BlockData> h) {
PrecisionStopwatch p = PrecisionStopwatch.start();
int i, zf, depth, realX, realZ, hf, he, b;
IrisBiome biome;
KList<BlockData> blocks;
@ -86,5 +88,7 @@ public class IrisTerrainActuator extends EngineAssignedActuator<BlockData>
}
}
}
getEngine().getMetrics().getTerrain().put(p.getMilliseconds());
}
}

View File

@ -3,10 +3,7 @@ package com.volmit.iris.generator.modifier;
import com.volmit.iris.generator.noise.FastNoiseDouble;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisCaveLayer;
import com.volmit.iris.util.B;
import com.volmit.iris.util.CaveResult;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.RNG;
import com.volmit.iris.util.*;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedModifier;
import com.volmit.iris.scaffold.hunk.Hunk;
@ -31,6 +28,12 @@ public class IrisCaveModifier extends EngineAssignedModifier<BlockData>
@Override
public void onModify(int x, int z, Hunk<BlockData> a) {
if(!getDimension().isCaves())
{
return;
}
PrecisionStopwatch p = PrecisionStopwatch.start();
for(int i = 0; i < a.getWidth(); i++)
{
for(int j = 0; j < a.getDepth(); j++)
@ -71,6 +74,8 @@ public class IrisCaveModifier extends EngineAssignedModifier<BlockData>
}
}
};
getEngine().getMetrics().getCave().put(p.getMilliseconds());
}
public KList<CaveResult> genCaves(double wxx, double wzz, int x, int z, Hunk<BlockData> data)

View File

@ -4,11 +4,12 @@ import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisDepositGenerator;
import com.volmit.iris.object.IrisObject;
import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.util.HeightMap;
import com.volmit.iris.util.RNG;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedModifier;
import com.volmit.iris.scaffold.hunk.Hunk;
import com.volmit.iris.util.HeightMap;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RNG;
import org.bukkit.block.data.BlockData;
import org.bukkit.util.BlockVector;
@ -21,7 +22,9 @@ public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
@Override
public void onModify(int x, int z, Hunk<BlockData> output) {
PrecisionStopwatch p = PrecisionStopwatch.start();
generateDeposits(rng, output, Math.floorDiv(x, 16), Math.floorDiv(z, 16));
getEngine().getMetrics().getDeposit().put(p.getMilliseconds());
}
public void generateDeposits(RNG rx, Hunk<BlockData> terrain, int x, int z)

View File

@ -3,6 +3,7 @@ package com.volmit.iris.generator.modifier;
import com.volmit.iris.object.*;
import com.volmit.iris.util.B;
import com.volmit.iris.util.CaveResult;
import com.volmit.iris.util.PrecisionStopwatch;
import com.volmit.iris.util.RNG;
import com.volmit.iris.scaffold.engine.Engine;
import com.volmit.iris.scaffold.engine.EngineAssignedModifier;
@ -25,6 +26,7 @@ public class IrisPostModifier extends EngineAssignedModifier<BlockData> {
@Override
public void onModify(int x, int z, Hunk<BlockData> output) {
PrecisionStopwatch p = PrecisionStopwatch.start();
for(int i = 0; i < output.getWidth(); i++)
{
for(int j = 0; j < output.getDepth(); j++)
@ -32,6 +34,7 @@ public class IrisPostModifier extends EngineAssignedModifier<BlockData> {
post(i, j, output, i+x, j+z);
}
}
getEngine().getMetrics().getPost().put(p.getMilliseconds());
}
private void post(int currentPostX, int currentPostZ, Hunk<BlockData> currentData, int x, int z) {

View File

@ -23,7 +23,9 @@ public class IrisRavineModifier extends EngineAssignedModifier<BlockData> {
@Override
public void onModify(int x, int z, Hunk<BlockData> output) {
PrecisionStopwatch p = PrecisionStopwatch.start();
generateRavines(rng, Math.floorDiv(x, 16), Math.floorDiv(z, 16), output);
getEngine().getMetrics().getRavine().put(p.getMilliseconds());
}
private void set(Hunk<BlockData> pos, int x, int y, int z, BlockData b)

View File

@ -2,7 +2,6 @@ package com.volmit.iris.manager;
import com.volmit.iris.Iris;
import com.volmit.iris.object.*;
import com.volmit.iris.util.KMap;
import com.volmit.iris.util.ObjectResourceLoader;
import com.volmit.iris.util.RNG;
import com.volmit.iris.util.ResourceLoader;
@ -14,7 +13,6 @@ import java.util.function.Function;
@Data
public class IrisDataManager
{
public static final KMap<Integer, IrisDataManager> managers = new KMap<>();
private ResourceLoader<IrisBiome> biomeLoader;
private ResourceLoader<IrisLootTable> lootLoader;
private ResourceLoader<IrisRegion> regionLoader;
@ -39,17 +37,11 @@ public class IrisDataManager
this.id = RNG.r.imax();
closed = false;
hotloaded();
if(!oneshot)
{
managers.put(id, this);
}
}
public void close()
{
closed = true;
managers.remove(id);
dump();
this.lootLoader = null;
this.entityLoader = null;
@ -62,23 +54,6 @@ public class IrisDataManager
this.objectLoader = null;
}
public static void dumpManagers()
{
for(IrisDataManager i : managers.v())
{
Iris.warn(i.getId() + " @ " + i.getDataFolder().getAbsolutePath());
printData(i.lootLoader);
printData(i.entityLoader);
printData(i.regionLoader);
printData(i.biomeLoader);
printData(i.dimensionLoader);
printData(i.structureLoader);
printData(i.generatorLoader);
printData(i.blockLoader);
printData(i.objectLoader);
}
}
private static void printData(ResourceLoader<?> rl)
{
Iris.warn(" " + rl.getResourceTypeName() + " @ /" + rl.getFolderName() + ": Cache=" + rl.getLoadCache().size() + " Folders=" + rl.getFolders().size());

View File

@ -35,15 +35,6 @@ public class CommandIris extends MortarCommand
@Command
private CommandIrisMetrics metrics;
@Command
private CommandIrisCTC ctc;
@Command
private CommandIrisLMM lmm;
@Command
private CommandIrisIDM idm;
@Command
private CommandIrisPregen pregen;

View File

@ -1,71 +0,0 @@
package com.volmit.iris.manager.command;
import com.volmit.iris.Iris;
import com.volmit.iris.scaffold.IrisWorlds;
import com.volmit.iris.scaffold.engine.IrisAccess;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.MortarCommand;
import com.volmit.iris.util.MortarSender;
import org.bukkit.World;
import org.bukkit.entity.Player;
public class CommandIrisCTC extends MortarCommand
{
public CommandIrisCTC()
{
super("ctc", "threads", "thread");
setDescription("Change generator thread count");
requiresPermission(Iris.perm.studio);
setCategory("World");
}
@Override
public void addTabOptions(MortarSender sender, String[] args, KList<String> list) {
if(args.length == 0)
{
list.qadd("4").qadd("8").qadd("12").qadd("16").qadd("18").qadd("24").qadd("32");
}
}
@Override
public boolean handle(MortarSender sender, String[] args)
{
if(sender.isPlayer())
{
Player p = sender.player();
World world = p.getWorld();
if(!IrisWorlds.isIrisWorld(world))
{
sender.sendMessage("You must be in an iris world.");
return true;
}
IrisAccess g = IrisWorlds.access(world);
if(args.length == 0){
sender.sendMessage("Current threads: " + g.getThreadCount());
sender.sendMessage("You can change the treadcount with /iris ctc <number>");
return true;
}
int m = Math.min(Math.max(Integer.valueOf(args[0]), 2), 256);
g.changeThreadCount(m);
sender.sendMessage("Thread count changed to " + m);
return true;
}
else
{
sender.sendMessage("Players only.");
}
return true;
}
@Override
protected String getArgsUsage()
{
return "[thread-count]";
}
}

View File

@ -1,43 +0,0 @@
package com.volmit.iris.manager.command;
import com.volmit.iris.Iris;
import com.volmit.iris.manager.IrisDataManager;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.MortarCommand;
import com.volmit.iris.util.MortarSender;
public class CommandIrisIDM extends MortarCommand
{
public CommandIrisIDM()
{
super("idm");
setDescription("Diagnostics for Iris Data Managers");
requiresPermission(Iris.perm.studio);
setCategory("World");
}
@Override
public void addTabOptions(MortarSender sender, String[] args, KList<String> list) {
}
@Override
public boolean handle(MortarSender sender, String[] args)
{
if(sender.isPlayer())
{
sender.sendMessage("Use this in the console.");
return true;
}
sender.sendMessage("Total Managers: " + IrisDataManager.managers.size());
IrisDataManager.dumpManagers();
return true;
}
@Override
protected String getArgsUsage()
{
return "";
}
}

View File

@ -1,36 +0,0 @@
package com.volmit.iris.manager.command;
import com.volmit.iris.Iris;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.MortarCommand;
import com.volmit.iris.util.MortarSender;
public class CommandIrisLMM extends MortarCommand
{
public CommandIrisLMM()
{
super("lmm");
setDescription("Toggle Low Memory Mode");
requiresPermission(Iris.perm.studio);
setCategory("World");
}
@Override
public void addTabOptions(MortarSender sender, String[] args, KList<String> list) {
}
@Override
public boolean handle(MortarSender sender, String[] args)
{
Iris.lowMemoryMode = !Iris.lowMemoryMode;
sender.sendMessage("Low Memory Mode is " + (Iris.lowMemoryMode ? "On" : "Off"));
return true;
}
@Override
protected String getArgsUsage()
{
return "";
}
}

View File

@ -36,7 +36,16 @@ public class CommandIrisMetrics extends MortarCommand
}
IrisAccess g = IrisWorlds.access(world);
// TODO: METRICS
try
{
g.printMetrics(sender);
}
catch(Throwable e)
{
sender.sendMessage("You must be in an iris world.");
}
return true;
}

View File

@ -27,8 +27,8 @@ public class CommandIrisStudio extends MortarCommand
@Command
private CommandIrisStudioUpdate update;
@Command
private CommandIrisStudioMap map;
//@Command
//private CommandIrisStudioMap map;
@Command
private CommandIrisStudioGoto got0;

View File

@ -2,6 +2,7 @@ package com.volmit.iris.manager.command;
import com.volmit.iris.Iris;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.manager.gui.IrisVision;
import com.volmit.iris.scaffold.engine.IrisAccess;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.MortarCommand;
@ -38,8 +39,8 @@ public class CommandIrisStudioMap extends MortarCommand
}
IrisAccess g = Iris.proj.getActiveProject().getActiveProvider();
// IrisVision.launch(g);
sender.sendMessage("NYI: Opening Map!");
IrisVision.launch(g, 0);
sender.sendMessage("Opening Map!");
return true;
}

View File

@ -1,7 +1,7 @@
package com.volmit.iris.manager.gui;
import com.volmit.iris.Iris;
import com.volmit.iris.scaffold.engine.GeneratorAccess;
import com.volmit.iris.scaffold.engine.IrisAccess;
import com.volmit.iris.util.*;
import javax.imageio.ImageIO;
@ -35,7 +35,6 @@ public class IrisVision extends JPanel implements MouseWheelListener
private double oz = 0;
private double oxp = 0;
private double ozp = 0;
private short lid = -1;
double tfps = 240D;
private RollingSequence rs = new RollingSequence(512);
private O<Integer> m = new O<>();
@ -131,7 +130,6 @@ public class IrisVision extends JPanel implements MouseWheelListener
working.add(key);
double mk = mscale;
double mkd = scale;
short l = lid;
e.submit(() ->
{
PrecisionStopwatch ps = PrecisionStopwatch.start();
@ -139,7 +137,7 @@ public class IrisVision extends JPanel implements MouseWheelListener
rs.put(ps.getMilliseconds());
working.remove(key);
if(mk == mscale && mkd == scale && lid == l)
if(mk == mscale && mkd == scale)
{
positions.put(key, b);
}
@ -162,7 +160,6 @@ public class IrisVision extends JPanel implements MouseWheelListener
workingfast.add(key);
double mk = mscale;
double mkd = scale;
short l = lid;
eh.submit(() ->
{
PrecisionStopwatch ps = PrecisionStopwatch.start();
@ -170,7 +167,7 @@ public class IrisVision extends JPanel implements MouseWheelListener
rs.put(ps.getMilliseconds());
workingfast.remove(key);
if(mk == mscale && mkd == scale && lid == l)
if(mk == mscale && mkd == scale)
{
fastpositions.put(key, b);
}
@ -202,17 +199,6 @@ public class IrisVision extends JPanel implements MouseWheelListener
ozp += Math.abs(ozp - oz) * 0.36;
}
// TODO: DETECT HOTLOADS
if(false)
{
working.clear();
workingfast.clear();
positions.clear();
fastpositions.clear();
//TODO: lid = Iris.proj.getActiveProject().getActiveProvider().getCacheID();
Iris.info("Hotloading Vision");
}
PrecisionStopwatch p = PrecisionStopwatch.start();
Graphics2D g = (Graphics2D) gx;
w = getWidth();
@ -293,14 +279,13 @@ public class IrisVision extends JPanel implements MouseWheelListener
});
}
private static void createAndShowGUI(Renderer r, short s)
private static void createAndShowGUI(Renderer r, int s)
{
JFrame frame = new JFrame("Vision");
IrisVision nv = new IrisVision();
nv.renderer = new IrisRenderer(r);
frame.add(nv);
frame.setSize(1440, 820);
nv.lid = s;
frame.setVisible(true);
File file = Iris.getCached("Iris Icon", "https://raw.githubusercontent.com/VolmitSoftware/Iris/master/icon.png");
@ -318,11 +303,10 @@ public class IrisVision extends JPanel implements MouseWheelListener
}
}
public static void launch(GeneratorAccess g)
{
public static void launch(IrisAccess g, int i) {
J.a(() ->
{
//createAndShowGUI(g.createRenderer(), g.getCacheID());
createAndShowGUI((x, z) -> g.getEngineAccess(i).draw(x, z), i);
});
}
@ -334,7 +318,7 @@ public class IrisVision extends JPanel implements MouseWheelListener
return;
}
Iris.info("BPP: " + (mscale) + " BW: " + (w * mscale));
Iris.info("Blocks/Pixel: " + (mscale) + ", Blocks Wide: " + (w * mscale));
positions.clear();
fastpositions.clear();
mscale = mscale + ((0.044 * mscale) * notches);

View File

@ -85,8 +85,8 @@ public class IrisBiome extends IrisRegistrant implements IRare
private int rarity = 1;
@DontObfuscate
@Desc("A debug color for visualizing this biome with a color. I.e. #F13AF5")
private String debugColor = "";
@Desc("A color for visualizing this biome with a color. I.e. #F13AF5. This will show up on the map.")
private IrisColor color = null;
@Required
@DontObfuscate
@ -295,29 +295,6 @@ public class IrisBiome extends IrisRegistrant implements IRare
});
}
public Color getCachedColor()
{
return cacheColor.aquire(() ->
{
if(getDebugColor() == null || getDebugColor().isEmpty())
{
return null;
}
try
{
return Color.decode(getDebugColor());
}
catch(Throwable e)
{
}
return null;
});
}
public double getHeight(IrisAccess xg, double x, double z, long seed)
{
double height = 0;

View File

@ -0,0 +1,97 @@
package com.volmit.iris.object;
import com.volmit.iris.scaffold.cache.AtomicCache;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.awt.*;
@Accessors(chain = true)
@NoArgsConstructor
@Desc("Represents a color")
@Data
public class IrisColor
{
@DontObfuscate
@MaxNumber(7)
@MinNumber(6)
@Desc("Pass in a 6 digit hexadecimal color to fill R G and B values. You can also include the # symbol, but it's not required.")
private String hex = null;
@DontObfuscate
@MaxNumber(255)
@MinNumber(0)
@Desc("Represents the red channel. Only define this if you are not defining the hex value.")
private int red = 0;
@DontObfuscate
@MaxNumber(255)
@MinNumber(0)
@Desc("Represents the green channel. Only define this if you are not defining the hex value.")
private int green = 0;
@DontObfuscate
@MaxNumber(255)
@MinNumber(0)
@Desc("Represents the blue channel. Only define this if you are not defining the hex value.")
private int blue = 0;
private final transient AtomicCache<Color> color = new AtomicCache<>();
public Color getColor()
{
return color.aquire(() -> {
if(hex != null)
{
String v = (hex.startsWith("#") ? hex : "#" + hex).trim();
try
{
return Color.decode(v);
}
catch(Throwable e)
{
}
}
return new Color(red, green, blue);
});
}
public org.bukkit.Color getBukkitColor()
{
return org.bukkit.Color.fromRGB(getColor().getRGB());
}
public static Color blend(Color... c) {
if (c == null || c.length <= 0) {
return null;
}
float ratio = 1f / ((float) c.length);
int a = 0;
int r = 0;
int g = 0;
int b = 0;
for (int i = 0; i < c.length; i++) {
int rgb = c[i].getRGB();
int a1 = (rgb >> 24 & 0xff);
int r1 = ((rgb & 0xff0000) >> 16);
int g1 = ((rgb & 0xff00) >> 8);
int b1 = (rgb & 0xff);
a += ((int) a1 * ratio);
r += ((int) r1 * ratio);
g += ((int) g1 * ratio);
b += ((int) b1 * ratio);
}
return new Color(a << 24 | r << 16 | g << 8 | b);
}
}

View File

@ -18,7 +18,6 @@ import lombok.experimental.Accessors;
@EqualsAndHashCode(callSuper = false)
public class IrisRegion extends IrisRegistrant implements IRare
{
@MinNumber(2)
@Required
@DontObfuscate
@ -211,6 +210,10 @@ public class IrisRegion extends IrisRegistrant implements IRare
@Desc("Generate rivers in this region")
private double riverThickness = 0.1;
@DontObfuscate
@Desc("A color for visualizing this region with a color. I.e. #F13AF5. This will show up on the map.")
private IrisColor color = null;
private final transient AtomicCache<KList<IrisObjectPlacement>> surfaceObjectsCache = new AtomicCache<>();
private final transient AtomicCache<KList<IrisObjectPlacement>> carveObjectsCache = new AtomicCache<>();
private final transient AtomicCache<KList<String>> cacheRidge = new AtomicCache<>();

View File

@ -1,15 +1,14 @@
package com.volmit.iris.scaffold.engine;
import com.volmit.iris.manager.IrisDataManager;
import com.volmit.iris.manager.gui.Renderer;
import com.volmit.iris.object.*;
import com.volmit.iris.scaffold.cache.Cache;
import com.volmit.iris.scaffold.data.DataProvider;
import com.volmit.iris.scaffold.hunk.Hunk;
import com.volmit.iris.scaffold.parallax.ParallaxAccess;
import com.volmit.iris.scaffold.parallel.MultiBurst;
import com.volmit.iris.util.B;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.RNG;
import com.volmit.iris.util.*;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
@ -20,9 +19,10 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import java.awt.*;
import java.util.Arrays;
public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootProvider, BlockUpdater {
public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootProvider, BlockUpdater, Renderer, Hotloadable {
public void close();
public boolean isClosed();
@ -49,6 +49,8 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
public void generate(int x, int z, Hunk<BlockData> blocks, Hunk<Biome> biomes);
public EngineMetrics getMetrics();
default void save()
{
getParallax().saveAll();
@ -89,6 +91,21 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
return getTarget().getParallaxWorld();
}
public default Color draw(double x, double z)
{
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);
IrisColor irc = region.getColor();
IrisColor ibc = biome.getColor();
Color rc = irc != null ? irc.getColor() : Color.GREEN.darker();
Color bc = ibc != null ? ibc.getColor() : biome.isAquatic() ? Color.BLUE : Color.YELLOW;
Color f = IrisColor.blend(rc, bc, bc, Color.getHSBColor(0, 0, (float)heightFactor));
return f;
}
@Override
public default IrisRegion getRegion(int x, int z) {
return getFramework().getComplex().getRegionStream().get(x, z);
@ -136,6 +153,7 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
@Override
public default void updateChunk(Chunk c)
{
PrecisionStopwatch p = PrecisionStopwatch.start();
if(getParallax().getMetaR(c.getX(), c.getZ()).isUpdates())
{
Hunk<Boolean> b = getParallax().getUpdatesR(c.getX(), c.getZ());
@ -155,6 +173,8 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
}
});
}
getMetrics().getUpdates().put(p.getMilliseconds());
}
public default void updateLighting(int x, int y, int z, Chunk c)

View File

@ -12,6 +12,7 @@ import com.volmit.iris.util.*;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.material.MaterialData;
@ -250,6 +251,11 @@ public class EngineCompositeGenerator extends ChunkGenerator implements IrisAcce
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

View File

@ -2,17 +2,17 @@ package com.volmit.iris.scaffold.engine;
import com.volmit.iris.manager.IrisDataManager;
import com.volmit.iris.object.IrisDimension;
import com.volmit.iris.scaffold.hunk.Hunk;
import com.volmit.iris.scaffold.parallel.MultiBurst;
import com.volmit.iris.util.KList;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.event.Listener;
import com.volmit.iris.scaffold.hunk.Hunk;
import com.volmit.iris.scaffold.parallel.MultiBurst;
import org.bukkit.generator.BlockPopulator;
public interface EngineCompound extends Listener
public interface EngineCompound extends Listener, Hotloadable
{
public IrisDimension getRootDimension();
@ -20,6 +20,8 @@ public interface EngineCompound extends Listener
public World getWorld();
public void printMetrics(CommandSender sender);
public int getSize();
public Engine getEngine(int index);

View File

@ -0,0 +1,51 @@
package com.volmit.iris.scaffold.engine;
import com.volmit.iris.util.AtomicRollingSequence;
import com.volmit.iris.util.KMap;
import lombok.Data;
@Data
public class EngineMetrics {
private final AtomicRollingSequence total;
private final AtomicRollingSequence updates;
private final AtomicRollingSequence terrain;
private final AtomicRollingSequence biome;
private final AtomicRollingSequence parallax;
private final AtomicRollingSequence parallaxInsert;
private final AtomicRollingSequence post;
private final AtomicRollingSequence decoration;
private final AtomicRollingSequence cave;
private final AtomicRollingSequence ravine;
private final AtomicRollingSequence deposit;
public EngineMetrics(int mem)
{
this.total = new AtomicRollingSequence(mem);
this.terrain = new AtomicRollingSequence(mem);
this.biome = new AtomicRollingSequence(mem);
this.parallax = new AtomicRollingSequence(mem);
this.parallaxInsert = new AtomicRollingSequence(mem);
this.post = new AtomicRollingSequence(mem);
this.decoration = new AtomicRollingSequence(mem);
this.updates = new AtomicRollingSequence(mem);
this.cave = new AtomicRollingSequence(mem);
this.ravine = new AtomicRollingSequence(mem);
this.deposit = new AtomicRollingSequence(mem);
}
public KMap<String, Double> pull() {
KMap<String, Double> v = new KMap<>();
v.put("terrain", terrain.getAverage());
v.put("biome", biome.getAverage());
v.put("parallax", parallax.getAverage());
v.put("parallax.insert", parallaxInsert.getAverage());
v.put("post", post.getAverage());
v.put("decoration", decoration.getAverage());
v.put("updates", updates.getAverage());
v.put("cave", cave.getAverage());
v.put("ravine", ravine.getAverage());
v.put("deposit", deposit.getAverage());
return v;
}
}

View File

@ -73,9 +73,11 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer
default void insertParallax(int x, int z, Hunk<BlockData> data)
{
PrecisionStopwatch p = PrecisionStopwatch.start();
ParallaxChunkMeta meta = getParallaxAccess().getMetaR(x>>4, z>>4);
if(!meta.isObjects()) {
getEngine().getMetrics().getParallaxInsert().put(p.getMilliseconds());
return;
}
@ -94,10 +96,13 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer
}
}
}
getEngine().getMetrics().getParallaxInsert().put(p.getMilliseconds());
}
default void generateParallaxArea(int x, int z)
{
PrecisionStopwatch p = PrecisionStopwatch.start();
int s = (int) Math.ceil(getParallaxSize() / 2D);
int j;
BurstExecutor e = MultiBurst.burst.burst(getParallaxSize() * getParallaxSize());
@ -114,8 +119,9 @@ public interface EngineParallaxManager extends DataProvider, IObjectPlacer
}
e.complete();
getParallaxAccess().setChunkGenerated(x>>4, z>>4);
p.end();
getEngine().getMetrics().getParallax().put(p.getMilliseconds());
}
default void generateParallaxLayer(int x, int z)

View File

@ -1,13 +1,14 @@
package com.volmit.iris.scaffold.engine;
import com.volmit.iris.manager.IrisDataManager;
import com.volmit.iris.manager.gui.Renderer;
import com.volmit.iris.object.IrisBiome;
import com.volmit.iris.object.IrisObjectPlacement;
import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.scaffold.data.DataProvider;
import com.volmit.iris.scaffold.parallax.ParallaxAccess;
public interface GeneratorAccess extends DataProvider
public interface GeneratorAccess extends DataProvider, Renderer
{
public IrisRegion getRegion(int x, int z);
@ -64,4 +65,6 @@ public interface GeneratorAccess extends DataProvider
return new PlacedObject(null, getData().getObjectLoader().load(object), id, x, z);
}
public int getCacheID();
}

View File

@ -5,6 +5,7 @@ import com.volmit.iris.object.*;
import com.volmit.iris.scaffold.data.DataProvider;
import com.volmit.iris.util.*;
import org.bukkit.Location;
import org.bukkit.command.CommandSender;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@ -15,6 +16,8 @@ public interface IrisAccess extends Hotloadable, DataProvider {
public int getGenerated();
public void printMetrics(CommandSender sender);
public IrisBiome getBiome(int x, int y, int z);
public IrisBiome getCaveBiome(int x, int y, int z);

View File

@ -0,0 +1,87 @@
package com.volmit.iris.util;
import com.google.common.util.concurrent.AtomicDoubleArray;
/**
* Provides an incredibly fast averaging object. It swaps values from a sum
* using an array. Averages do not use any form of looping. An average of 10,000
* entries is the same speed as an average with 5 entries.
*
* @author cyberpwn
*
*/
public class AtomicAverage {
protected AtomicDoubleArray values;
private double average;
private double lastSum;
private boolean dirty;
protected int cursor;
private boolean brandNew;
/**
* Create an average holder
*
* @param size the size of entries to keep
*/
public AtomicAverage(int size) {
values = new AtomicDoubleArray(size);
DoubleArrayUtils.fill(values, 0);
brandNew = true;
average = 0;
cursor = 0;
lastSum = 0;
dirty = false;
}
/**
* Put a value into the average (rolls over if full)
*
* @param i the value
*/
public void put(double i) {
dirty = true;
if(brandNew)
{
DoubleArrayUtils.fill(values, i);
lastSum = size() * i;
brandNew = false;
return;
}
double current = values.get(cursor);
lastSum = (lastSum - current) + i;
values.set(cursor, i);
cursor = cursor + 1 < size() ? cursor + 1 : 0;
}
/**
* Get the current average
*
* @return the average
*/
public double getAverage() {
if (dirty) {
calculateAverage();
return getAverage();
}
return average;
}
private void calculateAverage() {
average = lastSum / (double) size();
dirty = false;
}
public int size()
{
return values.length();
}
public boolean isDirty()
{
return dirty;
}
}

View File

@ -0,0 +1,102 @@
package com.volmit.iris.util;
public class AtomicRollingSequence extends AtomicAverage
{
private double median;
private double max;
private double min;
private boolean dirtyMedian;
private int dirtyExtremes;
private boolean precision;
public AtomicRollingSequence(int size)
{
super(size);
median = 0;
min = 0;
max = 0;
setPrecision(false);
}
public double addLast(int amt)
{
double f = 0;
for(int i = 0; i < Math.min(values.length(), amt); i++)
{
f += values.get(i);
}
return f;
}
public void setPrecision(boolean p)
{
this.precision = p;
}
public boolean isPrecision()
{
return precision;
}
public double getMin()
{
if(dirtyExtremes > (isPrecision() ? 0 : values.length()))
{
resetExtremes();
}
return min;
}
public double getMax()
{
if(dirtyExtremes > (isPrecision() ? 0 : values.length()))
{
resetExtremes();
}
return max;
}
public double getMedian()
{
if(dirtyMedian)
{
recalculateMedian();
}
return median;
}
private void recalculateMedian()
{
median = new KList<Double>().forceAdd(values).sort().middleValue();
dirtyMedian = false;
}
public void resetExtremes()
{
max = Integer.MIN_VALUE;
min = Integer.MAX_VALUE;
for(int i = 0; i < values.length(); i++)
{
double v = values.get(i);
max = M.max(max, v);
min = M.min(min, v);
}
dirtyExtremes = 0;
}
public void put(double i)
{
super.put(i);
dirtyMedian = true;
dirtyExtremes++;
max = M.max(max, i);
min = M.min(min, i);
}
}

View File

@ -1,6 +1,10 @@
package com.volmit.iris.util;
import com.google.common.util.concurrent.AtomicDoubleArray;
import java.util.Arrays;
public class DoubleArrayUtils
{
public static void shiftRight(double[] values, double push)
@ -21,9 +25,15 @@ public class DoubleArrayUtils
public static void fill(double[] values, double value)
{
for(int i = 0; i < values.length; i++)
Arrays.fill(values, value);
}
public static void fill(AtomicDoubleArray values, double value)
{
for(int i = 0; i < values.length(); i++)
{
values[i] = value;
values.set(i, value);
}
}
}

View File

@ -1,11 +1,8 @@
package com.volmit.iris.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.List;
import com.google.common.util.concurrent.AtomicDoubleArray;
import java.util.*;
import java.util.function.Function;
public class KList<T> extends ArrayList<T> implements List<T>
@ -594,6 +591,17 @@ public class KList<T> extends ArrayList<T> implements List<T>
return this;
}
@SuppressWarnings("unchecked")
public KList<T> forceAdd(AtomicDoubleArray values)
{
for(int i = 0; i < values.length(); i++)
{
add((T) ((Object)values.get(i)));
}
return this;
}
@SuppressWarnings("unchecked")
public KList<T> forceAdd(float[] values)
{