Faster Schematic Placement

This commit is contained in:
Daniel Mills 2020-01-08 13:50:43 -05:00
parent 4094034aaf
commit ad7a4503e0
7 changed files with 201 additions and 50 deletions

View File

@ -38,6 +38,7 @@ import ninja.bytecode.shuriken.collections.GMap;
import ninja.bytecode.shuriken.collections.GSet; import ninja.bytecode.shuriken.collections.GSet;
import ninja.bytecode.shuriken.execution.J; import ninja.bytecode.shuriken.execution.J;
import ninja.bytecode.shuriken.execution.TaskExecutor; import ninja.bytecode.shuriken.execution.TaskExecutor;
import ninja.bytecode.shuriken.execution.TaskExecutor.TaskGroup;
import ninja.bytecode.shuriken.format.F; import ninja.bytecode.shuriken.format.F;
import ninja.bytecode.shuriken.io.IO; import ninja.bytecode.shuriken.io.IO;
import ninja.bytecode.shuriken.json.JSONException; import ninja.bytecode.shuriken.json.JSONException;
@ -49,7 +50,6 @@ public class Iris extends JavaPlugin implements Listener
public static GSet<Chunk> refresh = new GSet<>(); public static GSet<Chunk> refresh = new GSet<>();
public static Profiler profiler; public static Profiler profiler;
public static TaskExecutor genPool; public static TaskExecutor genPool;
public static TaskExecutor buildPool;
public static IrisGenerator gen; public static IrisGenerator gen;
public static Settings settings; public static Settings settings;
public static Iris instance; public static Iris instance;
@ -60,7 +60,6 @@ public class Iris extends JavaPlugin implements Listener
public void onEnable() public void onEnable()
{ {
PrecisionStopwatch stopwatch = PrecisionStopwatch.start();
Direction.calculatePermutations(); Direction.calculatePermutations();
dimensions = new GMap<>(); dimensions = new GMap<>();
biomes = new GMap<>(); biomes = new GMap<>();
@ -69,19 +68,19 @@ public class Iris extends JavaPlugin implements Listener
values = new GMap<>(); values = new GMap<>();
instance = this; instance = this;
settings = new Settings(); settings = new Settings();
buildPool = new TaskExecutor(getTC(), settings.performance.threadPriority, "Iris Compiler");
J.attempt(() -> createTempCache()); J.attempt(() -> createTempCache());
loadContent(); loadContent();
processContent();
gen = new IrisGenerator(); gen = new IrisGenerator();
genPool = new TaskExecutor(getTC(), settings.performance.threadPriority, "Iris Generator"); genPool = new TaskExecutor(getTC(), settings.performance.threadPriority, "Iris Generator");
getServer().getPluginManager().registerEvents((Listener) this, this); getServer().getPluginManager().registerEvents((Listener) this, this);
getCommand("iris").setExecutor(new CommandIris()); getCommand("iris").setExecutor(new CommandIris());
getCommand("ish").setExecutor(new CommandIsh()); getCommand("ish").setExecutor(new CommandIsh());
new WandManager(); new WandManager();
loadComplete();
}
// Debug world regens private void loadComplete()
{
if(settings.performance.loadonstart) if(settings.performance.loadonstart)
{ {
GSet<String> ws = new GSet<>(); GSet<String> ws = new GSet<>();
@ -101,24 +100,6 @@ public class Iris extends JavaPlugin implements Listener
Bukkit.unloadWorld(i, false); Bukkit.unloadWorld(i, false);
} }
} }
double ms = stopwatch.getMilliseconds();
J.a(() ->
{
J.sleep(5000);
L.i("Iris Startup Took " + F.duration(ms, 2));
});
}
private void processContent()
{
L.v("Processing Content");
for(SchematicGroup i : schematics.v())
{
i.processVariants();
}
} }
private static File internalResource(String resource) private static File internalResource(String resource)
@ -158,6 +139,7 @@ public class Iris extends JavaPlugin implements Listener
private void loadContent() private void loadContent()
{ {
PrecisionStopwatch p = PrecisionStopwatch.start();
L.i("Loading Content"); L.i("Loading Content");
try try
@ -177,11 +159,23 @@ public class Iris extends JavaPlugin implements Listener
{ {
m += i.size(); m += i.size();
} }
L.v("Processing Content");
TaskExecutor exf = new TaskExecutor(settings.performance.compilerThreads, settings.performance.compilerPriority, "Iris Compiler");
TaskGroup gg = exf.startWork();
for(SchematicGroup i : schematics.v())
{
gg.queue(i::processVariants);
}
gg.execute();
exf.close();
L.i("Dimensions: " + dimensions.size()); L.i("Dimensions: " + dimensions.size());
L.i("Biomes: " + biomes.size()); L.i("Biomes: " + biomes.size());
L.i("Object Groups: " + schematics.size()); L.i("Object Groups: " + schematics.size());
L.i("Objects: " + F.f(m)); L.i("Objects: " + F.f(m));
L.i("Compilation Time: " + F.duration(p.getMilliseconds(), 2));
L.flush(); L.flush();
} }
@ -195,6 +189,8 @@ public class Iris extends JavaPlugin implements Listener
return Runtime.getRuntime().availableProcessors(); return Runtime.getRuntime().availableProcessors();
case SINGLE_THREADED: case SINGLE_THREADED:
return 1; return 1;
case DOUBLE_CPU:
return Runtime.getRuntime().availableProcessors() * 2;
case UNLIMITED: case UNLIMITED:
return -1; return -1;
case EXPLICIT: case EXPLICIT:

View File

@ -9,11 +9,14 @@ public class Settings
public static class PerformanceSettings public static class PerformanceSettings
{ {
public PerformanceMode performanceMode = PerformanceMode.MATCH_CPU; public PerformanceMode performanceMode = PerformanceMode.DOUBLE_CPU;
public int threadCount = 1; public int threadCount = 1;
public int threadPriority = Thread.MIN_PRIORITY; public int threadPriority = Thread.MIN_PRIORITY;
public boolean loadonstart = false; public boolean loadonstart = true;
public boolean fastPlacement = false; public boolean fastPlacement = false;
public int compilerThreads = 4;
public int compilerPriority = Thread.MAX_PRIORITY;
public int decorationAccuracy = 3;
} }
public static class GeneratorSettings public static class GeneratorSettings

View File

@ -20,8 +20,7 @@ import ninja.bytecode.iris.generator.layer.GenLayerOreGold;
import ninja.bytecode.iris.generator.layer.GenLayerOreIron; import ninja.bytecode.iris.generator.layer.GenLayerOreIron;
import ninja.bytecode.iris.generator.layer.GenLayerOreLapis; import ninja.bytecode.iris.generator.layer.GenLayerOreLapis;
import ninja.bytecode.iris.generator.layer.GenLayerRidge; import ninja.bytecode.iris.generator.layer.GenLayerRidge;
import ninja.bytecode.iris.generator.populator.BiomeBiasSchematicPopulator; import ninja.bytecode.iris.generator.populator.ObjectPopulator;
import ninja.bytecode.iris.schematic.Schematic;
import ninja.bytecode.iris.schematic.SchematicGroup; import ninja.bytecode.iris.schematic.SchematicGroup;
import ninja.bytecode.iris.spec.IrisBiome; import ninja.bytecode.iris.spec.IrisBiome;
import ninja.bytecode.iris.spec.IrisDimension; import ninja.bytecode.iris.spec.IrisDimension;
@ -255,28 +254,13 @@ public class IrisGenerator extends ParallelChunkGenerator
if(Iris.settings.gen.doSchematics) if(Iris.settings.gen.doSchematics)
{ {
int b = 0; p.add(new ObjectPopulator(this));
int sch = 0;
for(IrisBiome i : IrisBiome.getAllBiomes().copy().add(dim.getBiomes()))
{
b++;
L.i("Processing Populators for Biome " + i.getName());
for(String j : i.getSchematicGroups().keySet())
{
SchematicGroup gs = loadSchematics(j);
sch += gs.size();
p.add(new BiomeBiasSchematicPopulator(i.getSchematicGroups().get(j), i, gs.getSchematics().toArray(new Schematic[gs.size()])));
}
}
L.i("Initialized " + b + " Biomes with " + p.size() + " Populators using " + sch + " Schematics");
} }
return p; return p;
} }
private SchematicGroup loadSchematics(String folder) public SchematicGroup loadSchematics(String folder)
{ {
return Iris.schematics.get(folder); return Iris.schematics.get(folder);
} }

View File

@ -0,0 +1,121 @@
package ninja.bytecode.iris.generator.populator;
import java.util.Random;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.generator.BlockPopulator;
import ninja.bytecode.iris.Iris;
import ninja.bytecode.iris.generator.IrisGenerator;
import ninja.bytecode.iris.schematic.SchematicGroup;
import ninja.bytecode.iris.spec.IrisBiome;
import ninja.bytecode.shuriken.collections.GMap;
import ninja.bytecode.shuriken.collections.GSet;
import ninja.bytecode.shuriken.math.M;
public class ObjectPopulator extends BlockPopulator
{
private GMap<Biome, IrisBiome> biomeMap;
private GMap<Biome, GMap<SchematicGroup, Double>> populationCache;
public ObjectPopulator(IrisGenerator generator)
{
biomeMap = new GMap<>();
populationCache = new GMap<>();
for(IrisBiome i : generator.getLoadedBiomes())
{
biomeMap.put(i.getRealBiome(), i);
GMap<SchematicGroup, Double> gk = new GMap<>();
for(String j : i.getSchematicGroups().k())
{
gk.put(Iris.schematics.get(j), i.getSchematicGroups().get(j));
}
populationCache.put(i.getRealBiome(), gk);
}
}
@Override
public void populate(World world, Random random, Chunk source)
{
GSet<Biome> hits = new GSet<>();
for(int i = 0; i < Iris.settings.performance.decorationAccuracy; i++)
{
int x = (source.getX() << 4) + random.nextInt(16);
int z = (source.getZ() << 4) + random.nextInt(16);
Biome biome = world.getBiome(x, z);
if(hits.contains(biome))
{
continue;
}
IrisBiome ibiome = biomeMap.get(biome);
if(ibiome == null)
{
continue;
}
GMap<SchematicGroup, Double> objects = populationCache.get(biome);
if(objects == null)
{
continue;
}
hits.add(biome);
populate(world, random, source, biome, objects);
}
}
private void populate(World world, Random random, Chunk source, Biome biome, GMap<SchematicGroup, Double> objects)
{
for(SchematicGroup i : objects.k())
{
for(int j = 0; j < getTries(objects.get(i)); j++)
{
int x = (source.getX() << 4) + random.nextInt(16);
int z = (source.getZ() << 4) + random.nextInt(16);
Block b = world.getHighestBlockAt(x, z);
if(!b.getRelative(BlockFace.DOWN).getType().isSolid())
{
return;
}
i.getSchematics().get(random.nextInt(i.getSchematics().size())).place(world, x, b.getY() - 1, z);
}
}
}
public int getTries(double chance)
{
if(chance <= 0)
{
return 0;
}
if(Math.floor(chance) == chance)
{
return (int) chance;
}
int floor = (int) Math.floor(chance);
if(chance - floor > 0 && M.r(chance - floor))
{
floor++;
}
return floor;
}
}

View File

@ -7,6 +7,7 @@ import java.util.concurrent.locks.ReentrantLock;
import ninja.bytecode.iris.Iris; import ninja.bytecode.iris.Iris;
import ninja.bytecode.iris.util.Direction; import ninja.bytecode.iris.util.Direction;
import ninja.bytecode.shuriken.collections.GList; import ninja.bytecode.shuriken.collections.GList;
import ninja.bytecode.shuriken.execution.TaskExecutor;
import ninja.bytecode.shuriken.execution.TaskExecutor.TaskGroup; import ninja.bytecode.shuriken.execution.TaskExecutor.TaskGroup;
import ninja.bytecode.shuriken.io.IO; import ninja.bytecode.shuriken.io.IO;
import ninja.bytecode.shuriken.logging.L; import ninja.bytecode.shuriken.logging.L;
@ -122,9 +123,10 @@ public class SchematicGroup
GList<Schematic> inject = new GList<>(); GList<Schematic> inject = new GList<>();
L.v("Processing " + name + " Objects"); L.v("Processing " + name + " Objects");
L.v("# Creating Rotations for " + getSchematics().size() + " Objects"); L.v("# Creating Rotations for " + getSchematics().size() + " Objects");
String x = Thread.currentThread().getName();
ReentrantLock rr = new ReentrantLock(); ReentrantLock rr = new ReentrantLock();
TaskGroup gg = Iris.buildPool.startWork(); TaskExecutor ex = new TaskExecutor(Iris.settings.performance.compilerThreads, Iris.settings.performance.compilerPriority, x + "/Subroutine ");
TaskGroup gg = ex.startWork();
for(Schematic i : getSchematics()) for(Schematic i : getSchematics())
{ {
for(Direction j : new Direction[] {Direction.S, Direction.E, Direction.W}) for(Direction j : new Direction[] {Direction.S, Direction.E, Direction.W})
@ -142,7 +144,7 @@ public class SchematicGroup
} }
gg.execute(); gg.execute();
gg = Iris.buildPool.startWork(); gg = ex.startWork();
getSchematics().add(inject); getSchematics().add(inject);
L.v("# Generated " + inject.size() + " Rotated Objects to " + getName()); L.v("# Generated " + inject.size() + " Rotated Objects to " + getName());
@ -159,5 +161,46 @@ public class SchematicGroup
} }
gg.execute(); gg.execute();
ex.close();
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((flags == null) ? 0 : flags.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + priority;
return result;
}
@Override
public boolean equals(Object obj)
{
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
SchematicGroup other = (SchematicGroup) obj;
if(flags == null)
{
if(other.flags != null)
return false;
}
else if(!flags.equals(other.flags))
return false;
if(name == null)
{
if(other.name != null)
return false;
}
else if(!name.equals(other.name))
return false;
if(priority != other.priority)
return false;
return true;
} }
} }

View File

@ -8,6 +8,7 @@ import org.bukkit.World.Environment;
import ninja.bytecode.iris.Iris; import ninja.bytecode.iris.Iris;
import ninja.bytecode.shuriken.collections.GList; import ninja.bytecode.shuriken.collections.GList;
import ninja.bytecode.shuriken.execution.J; import ninja.bytecode.shuriken.execution.J;
import ninja.bytecode.shuriken.execution.TaskExecutor;
import ninja.bytecode.shuriken.execution.TaskExecutor.TaskGroup; import ninja.bytecode.shuriken.execution.TaskExecutor.TaskGroup;
import ninja.bytecode.shuriken.json.JSONArray; import ninja.bytecode.shuriken.json.JSONArray;
import ninja.bytecode.shuriken.json.JSONException; import ninja.bytecode.shuriken.json.JSONException;
@ -74,7 +75,8 @@ public class IrisDimension
private GList<IrisBiome> biomesFromArray(JSONArray a) throws JSONException, IOException private GList<IrisBiome> biomesFromArray(JSONArray a) throws JSONException, IOException
{ {
GList<IrisBiome> b = new GList<>(); GList<IrisBiome> b = new GList<>();
TaskGroup g = Iris.buildPool.startWork(); TaskExecutor ex= new TaskExecutor(Iris.settings.performance.compilerThreads, Iris.settings.performance.compilerPriority, "Iris Dim Compiler");
TaskGroup g = ex.startWork();
ReentrantLock lock = new ReentrantLock(); ReentrantLock lock = new ReentrantLock();
for(int i = 0; i < a.length(); i++) for(int i = 0; i < a.length(); i++)
@ -90,6 +92,7 @@ public class IrisDimension
} }
g.execute(); g.execute();
ex.close();
return b; return b;
} }

View File

@ -5,6 +5,7 @@ public enum PerformanceMode
SINGLE_THREADED, SINGLE_THREADED,
UNLIMITED, UNLIMITED,
MATCH_CPU, MATCH_CPU,
DOUBLE_CPU,
HALF_CPU, HALF_CPU,
EXPLICIT, EXPLICIT,
} }