mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-06-20 15:51:01 +00:00
Schematics
This commit is contained in:
@@ -4,29 +4,25 @@ import java.util.UUID;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.WorldCreator;
|
import org.bukkit.WorldCreator;
|
||||||
import org.bukkit.block.Biome;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
import ninja.bytecode.iris.generator.IrisGenerator;
|
import ninja.bytecode.iris.generator.IrisGenerator;
|
||||||
import ninja.bytecode.iris.util.RealBiome;
|
|
||||||
import ninja.bytecode.shuriken.bench.Profiler;
|
import ninja.bytecode.shuriken.bench.Profiler;
|
||||||
import ninja.bytecode.shuriken.collections.GMap;
|
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.TaskExecutor;
|
import ninja.bytecode.shuriken.execution.TaskExecutor;
|
||||||
import ninja.bytecode.shuriken.format.F;
|
|
||||||
import ninja.bytecode.shuriken.math.M;
|
|
||||||
|
|
||||||
public class Iris extends JavaPlugin implements Listener
|
public class Iris extends JavaPlugin implements Listener
|
||||||
{
|
{
|
||||||
@@ -46,6 +42,7 @@ public class Iris extends JavaPlugin implements Listener
|
|||||||
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);
|
||||||
|
new WandManager();
|
||||||
|
|
||||||
// Debug world regens
|
// Debug world regens
|
||||||
GSet<String> ws = new GSet<>();
|
GSet<String> ws = new GSet<>();
|
||||||
@@ -90,6 +87,7 @@ public class Iris extends JavaPlugin implements Listener
|
|||||||
public void onDisable()
|
public void onDisable()
|
||||||
{
|
{
|
||||||
genPool.close();
|
genPool.close();
|
||||||
|
HandlerList.unregisterAll((Plugin) this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -101,63 +99,17 @@ public class Iris extends JavaPlugin implements Listener
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
public void on(PlayerCommandPreprocessEvent e)
|
public void on(PlayerCommandPreprocessEvent e)
|
||||||
{
|
{
|
||||||
if(e.getMessage().toLowerCase().equals("/iris"))
|
if(e.getMessage().toLowerCase().equals("/iris gen"))
|
||||||
{
|
{
|
||||||
|
e.setCancelled(true);
|
||||||
World wold = e.getPlayer().getWorld();
|
World wold = e.getPlayer().getWorld();
|
||||||
World w = createIrisWorld();
|
World w = createIrisWorld();
|
||||||
e.getPlayer().teleport(new Location(w, 0, 256, 0));
|
e.getPlayer().teleport(new Location(w, 0, 256, 0));
|
||||||
e.getPlayer().setFlying(true);
|
e.getPlayer().setFlying(true);
|
||||||
e.getPlayer().setGameMode(GameMode.CREATIVE);
|
e.getPlayer().setGameMode(GameMode.CREATIVE);
|
||||||
e.setCancelled(true);
|
|
||||||
wold.setAutoSave(false);
|
wold.setAutoSave(false);
|
||||||
Bukkit.unloadWorld(wold, false);
|
Bukkit.unloadWorld(wold, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e.getMessage().toLowerCase().equals("/iris info"))
|
|
||||||
{
|
|
||||||
e.setCancelled(true);
|
|
||||||
sendInfo(e.getPlayer());
|
|
||||||
|
|
||||||
for(Biome i : Biome.values())
|
|
||||||
{
|
|
||||||
J.attempt(() -> System.out.print(new RealBiome(i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendInfo(Player player)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 18; i++)
|
|
||||||
{
|
|
||||||
player.sendMessage("");
|
|
||||||
}
|
|
||||||
|
|
||||||
GMap<String, Function<Vector, Double>> w = values.get(player.getWorld().getName());
|
|
||||||
for(String i : w.k())
|
|
||||||
{
|
|
||||||
double value = w.get(i).apply(player.getLocation().toVector());
|
|
||||||
String p = i.substring(0, 2);
|
|
||||||
String v = value + "";
|
|
||||||
|
|
||||||
if(p.startsWith("%"))
|
|
||||||
{
|
|
||||||
v = F.pc(value, Integer.valueOf(p.substring(1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(p.startsWith("D"))
|
|
||||||
{
|
|
||||||
v = F.f(value, Integer.valueOf(p.substring(1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(p.startsWith("^"))
|
|
||||||
{
|
|
||||||
double c = M.lerpInverse(-11, 37, value);
|
|
||||||
double f = 32 + (c * (1.8));
|
|
||||||
v = F.f(c, Integer.valueOf(p.substring(1))) + " \u00B0C / " + F.f(f, Integer.valueOf(p.substring(1))) + " \u00B0F";
|
|
||||||
}
|
|
||||||
|
|
||||||
player.sendMessage(ChatColor.GREEN + i.substring(2) + ": " + ChatColor.RESET + ChatColor.WHITE + ChatColor.BOLD + v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private World createIrisWorld()
|
private World createIrisWorld()
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ public class Settings
|
|||||||
|
|
||||||
public static class PerformanceSettings
|
public static class PerformanceSettings
|
||||||
{
|
{
|
||||||
public PerformanceMode performanceMode = PerformanceMode.HALF_CPU;
|
public PerformanceMode performanceMode = PerformanceMode.MATCH_CPU;
|
||||||
public int threadCount = 4;
|
public int threadCount = 12;
|
||||||
public int threadPriority = Thread.MAX_PRIORITY;
|
public int threadPriority = Thread.MAX_PRIORITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
package ninja.bytecode.iris;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
|
|
||||||
|
import ninja.bytecode.iris.schematic.Schematic;
|
||||||
|
import ninja.bytecode.iris.util.WandUtil;
|
||||||
|
|
||||||
|
public class WandManager implements Listener
|
||||||
|
{
|
||||||
|
public WandManager()
|
||||||
|
{
|
||||||
|
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void on(PlayerCommandPreprocessEvent e)
|
||||||
|
{
|
||||||
|
if(e.getMessage().startsWith("/isave "))
|
||||||
|
{
|
||||||
|
e.setCancelled(true);
|
||||||
|
Schematic s = WandUtil.createSchematic(e.getPlayer().getInventory().getItemInMainHand(), e.getPlayer().getLocation());
|
||||||
|
File f = new File(Iris.instance.getDataFolder(), "schematics/" + e.getMessage().split("\\Q \\E")[1] + ".ish");
|
||||||
|
f.getParentFile().mkdirs();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileOutputStream fos = new FileOutputStream(f);
|
||||||
|
s.write(fos);
|
||||||
|
e.getPlayer().sendMessage("Done!");
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(Throwable e1)
|
||||||
|
{
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e.getMessage().startsWith("/iload "))
|
||||||
|
{
|
||||||
|
e.setCancelled(true);
|
||||||
|
Schematic s = new Schematic(1, 1, 1, 1, 1, 1);
|
||||||
|
File f = new File(Iris.instance.getDataFolder(), "schematics/" + e.getMessage().split("\\Q \\E")[1] + ".ish");
|
||||||
|
if(!f.exists())
|
||||||
|
{
|
||||||
|
e.getPlayer().sendMessage("Not Found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileInputStream fin = new FileInputStream(f);
|
||||||
|
s.read(fin);
|
||||||
|
WandUtil.pasteSchematic(s, e.getPlayer().getLocation());
|
||||||
|
e.getPlayer().sendMessage("Done!");
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(Throwable e1)
|
||||||
|
{
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e.getMessage().equals("/iris wand"))
|
||||||
|
{
|
||||||
|
e.setCancelled(true);
|
||||||
|
e.getPlayer().getInventory().addItem(WandUtil.createWand());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void on(PlayerInteractEvent e)
|
||||||
|
{
|
||||||
|
if(e.getHand().equals(EquipmentSlot.HAND) && WandUtil.isWand(e.getPlayer().getInventory().getItemInMainHand()))
|
||||||
|
{
|
||||||
|
if(e.getAction().equals(Action.LEFT_CLICK_BLOCK))
|
||||||
|
{
|
||||||
|
e.setCancelled(true);
|
||||||
|
e.getPlayer().getInventory().setItemInMainHand(WandUtil.update(true, e.getPlayer().getLocation(), e.getPlayer().getInventory().getItemInMainHand()));
|
||||||
|
|
||||||
|
e.getPlayer().updateInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(e.getAction().equals(Action.RIGHT_CLICK_BLOCK))
|
||||||
|
{
|
||||||
|
e.setCancelled(true);
|
||||||
|
e.getPlayer().getInventory().setItemInMainHand(WandUtil.update(false, e.getPlayer().getLocation(), e.getPlayer().getInventory().getItemInMainHand()));
|
||||||
|
|
||||||
|
e.getPlayer().updateInventory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package ninja.bytecode.iris.generator;
|
package ninja.bytecode.iris.generator;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@@ -12,15 +13,19 @@ import ninja.bytecode.iris.Iris;
|
|||||||
import ninja.bytecode.iris.generator.biome.IrisBiome;
|
import ninja.bytecode.iris.generator.biome.IrisBiome;
|
||||||
import ninja.bytecode.iris.generator.layer.GenLayerBase;
|
import ninja.bytecode.iris.generator.layer.GenLayerBase;
|
||||||
import ninja.bytecode.iris.generator.layer.GenLayerBiome;
|
import ninja.bytecode.iris.generator.layer.GenLayerBiome;
|
||||||
|
import ninja.bytecode.iris.generator.layer.GenLayerCaves;
|
||||||
import ninja.bytecode.iris.generator.layer.GenLayerLayeredNoise;
|
import ninja.bytecode.iris.generator.layer.GenLayerLayeredNoise;
|
||||||
import ninja.bytecode.iris.generator.layer.GenLayerRidge;
|
import ninja.bytecode.iris.generator.layer.GenLayerRidge;
|
||||||
import ninja.bytecode.iris.generator.populator.PopulatorTrees;
|
import ninja.bytecode.iris.generator.populator.BiomeBiasSchematicPopulator;
|
||||||
|
import ninja.bytecode.iris.schematic.Schematic;
|
||||||
import ninja.bytecode.iris.util.AtomicChunkData;
|
import ninja.bytecode.iris.util.AtomicChunkData;
|
||||||
import ninja.bytecode.iris.util.ChunkPlan;
|
import ninja.bytecode.iris.util.ChunkPlan;
|
||||||
import ninja.bytecode.iris.util.IrisInterpolation;
|
import ninja.bytecode.iris.util.IrisInterpolation;
|
||||||
import ninja.bytecode.iris.util.MB;
|
import ninja.bytecode.iris.util.MB;
|
||||||
import ninja.bytecode.iris.util.ParallelChunkGenerator;
|
import ninja.bytecode.iris.util.ParallelChunkGenerator;
|
||||||
import ninja.bytecode.shuriken.collections.GList;
|
import ninja.bytecode.shuriken.collections.GList;
|
||||||
|
import ninja.bytecode.shuriken.execution.J;
|
||||||
|
import ninja.bytecode.shuriken.logging.L;
|
||||||
import ninja.bytecode.shuriken.math.M;
|
import ninja.bytecode.shuriken.math.M;
|
||||||
import ninja.bytecode.shuriken.math.RNG;
|
import ninja.bytecode.shuriken.math.RNG;
|
||||||
|
|
||||||
@@ -32,8 +37,8 @@ public class IrisGenerator extends ParallelChunkGenerator
|
|||||||
private GenLayerLayeredNoise glLNoise;
|
private GenLayerLayeredNoise glLNoise;
|
||||||
private GenLayerRidge glRidge;
|
private GenLayerRidge glRidge;
|
||||||
private GenLayerBiome glBiome;
|
private GenLayerBiome glBiome;
|
||||||
|
private GenLayerCaves glCaves;
|
||||||
private RNG rTerrain;
|
private RNG rTerrain;
|
||||||
private RNG rScatter;
|
|
||||||
private World world;
|
private World world;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -45,11 +50,7 @@ public class IrisGenerator extends ParallelChunkGenerator
|
|||||||
glLNoise = new GenLayerLayeredNoise(this, world, random, rTerrain.nextParallelRNG(2));
|
glLNoise = new GenLayerLayeredNoise(this, world, random, rTerrain.nextParallelRNG(2));
|
||||||
glRidge = new GenLayerRidge(this, world, random, rTerrain.nextParallelRNG(3));
|
glRidge = new GenLayerRidge(this, world, random, rTerrain.nextParallelRNG(3));
|
||||||
glBiome = new GenLayerBiome(this, world, random, rTerrain.nextParallelRNG(4));
|
glBiome = new GenLayerBiome(this, world, random, rTerrain.nextParallelRNG(4));
|
||||||
}
|
glCaves = new GenLayerCaves(this, world, random, rTerrain.nextParallelRNG(-1));
|
||||||
|
|
||||||
public World getWorld()
|
|
||||||
{
|
|
||||||
return world;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -69,8 +70,10 @@ public class IrisGenerator extends ParallelChunkGenerator
|
|||||||
hv += glLNoise.generateLayer(hv, wxx, wzx);
|
hv += glLNoise.generateLayer(hv, wxx, wzx);
|
||||||
hv -= glRidge.generateLayer(hv, wxx, wzx);
|
hv -= glRidge.generateLayer(hv, wxx, wzx);
|
||||||
int height = (int) Math.round(M.clip(hv, 0D, 1D) * 253);
|
int height = (int) Math.round(M.clip(hv, 0D, 1D) * 253);
|
||||||
|
int max = Math.max(height, seaLevel);
|
||||||
|
IrisBiome override = null;
|
||||||
|
|
||||||
for(int i = 0; i < Math.max(height, seaLevel); i++)
|
for(int i = 0; i < max; i++)
|
||||||
{
|
{
|
||||||
MB mb = new MB(Material.STONE);
|
MB mb = new MB(Material.STONE);
|
||||||
boolean underwater = i >= height && i < seaLevel;
|
boolean underwater = i >= height && i < seaLevel;
|
||||||
@@ -88,10 +91,43 @@ public class IrisGenerator extends ParallelChunkGenerator
|
|||||||
|
|
||||||
if(i == height - 1)
|
if(i == height - 1)
|
||||||
{
|
{
|
||||||
|
if(height > 61 && height < glBase.scatterInt(x, i, z, 4) + 65)
|
||||||
|
{
|
||||||
|
override = IrisBiome.BEACH;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(height < 63)
|
||||||
|
{
|
||||||
|
if(i < 36)
|
||||||
|
{
|
||||||
|
override = IrisBiome.DEEP_OCEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(i < 50)
|
||||||
|
{
|
||||||
|
override = IrisBiome.OCEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
override = IrisBiome.LAKE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(override != null)
|
||||||
|
{
|
||||||
|
biome = override;
|
||||||
|
}
|
||||||
|
|
||||||
mb = biome.getSurface(wx, wz, rTerrain);
|
mb = biome.getSurface(wx, wz, rTerrain);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Iris.settings.gen.flatBedrock ? i == 0 : i < glBase.scatterInt(x, i, z, 3))
|
if(i == 0)
|
||||||
|
{
|
||||||
|
mb = BEDROCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Iris.settings.gen.flatBedrock ? i == 1 : i < glBase.scatterInt(x, i, z, 3))
|
||||||
{
|
{
|
||||||
mb = BEDROCK;
|
mb = BEDROCK;
|
||||||
}
|
}
|
||||||
@@ -99,6 +135,13 @@ public class IrisGenerator extends ParallelChunkGenerator
|
|||||||
setBlock(x, i, z, mb.material, mb.data);
|
setBlock(x, i, z, mb.material, mb.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glCaves.genCaves(wxx, wzx, x, z, height, this);
|
||||||
|
|
||||||
|
if(override != null)
|
||||||
|
{
|
||||||
|
return override.getRealBiome();
|
||||||
|
}
|
||||||
|
|
||||||
return biome.getRealBiome();
|
return biome.getRealBiome();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,9 +157,61 @@ public class IrisGenerator extends ParallelChunkGenerator
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BlockPopulator> getDefaultPopulators(World world)
|
||||||
|
{
|
||||||
|
GList<BlockPopulator> p = new GList<>();
|
||||||
|
int b = 0;
|
||||||
|
for(IrisBiome i : IrisBiome.getBiomes())
|
||||||
|
{
|
||||||
|
b++;
|
||||||
|
L.i("Processing Populators for Biome " + i.getName());
|
||||||
|
|
||||||
|
for(String j : i.getSchematicGroups().keySet())
|
||||||
|
{
|
||||||
|
p.add(new BiomeBiasSchematicPopulator(i.getSchematicGroups().get(j), i, loadSchematics(j)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
J.attempt(() -> p.add(new BiomeBiasSchematicPopulator(5, IrisBiome.JUNGLE, loadSchematics(""))));
|
||||||
|
|
||||||
|
L.i("Initialized " + b + " Biomes and " + p.size() + " Populators");
|
||||||
|
L.flush();
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Schematic[] loadSchematics(String folder)
|
||||||
|
{
|
||||||
|
File f = new File(Iris.instance.getDataFolder(), "objects/" + folder);
|
||||||
|
GList<Schematic> s = new GList<>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(f.exists() && f.isDirectory())
|
||||||
|
{
|
||||||
|
for(File i : f.listFiles())
|
||||||
|
{
|
||||||
|
if(i.isFile() && i.getName().endsWith(".ish"))
|
||||||
|
{
|
||||||
|
s.add(Schematic.load(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(Throwable e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.toArray(new Schematic[s.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
private double getBiomedHeight(int x, int z, ChunkPlan plan)
|
private double getBiomedHeight(int x, int z, ChunkPlan plan)
|
||||||
{
|
{
|
||||||
return plan.getHeight(x, z, () -> {
|
return plan.getHeight(x, z, () ->
|
||||||
|
{
|
||||||
int wx = (int) Math.round((double) x * Iris.settings.gen.horizontalZoom);
|
int wx = (int) Math.round((double) x * Iris.settings.gen.horizontalZoom);
|
||||||
int wz = (int) Math.round((double) z * Iris.settings.gen.horizontalZoom);
|
int wz = (int) Math.round((double) z * Iris.settings.gen.horizontalZoom);
|
||||||
IrisBiome biome = glBiome.getBiome(wx * Iris.settings.gen.biomeScale, wz * Iris.settings.gen.biomeScale);
|
IrisBiome biome = glBiome.getBiome(wx * Iris.settings.gen.biomeScale, wz * Iris.settings.gen.biomeScale);
|
||||||
@@ -127,11 +222,8 @@ public class IrisGenerator extends ParallelChunkGenerator
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public World getWorld()
|
||||||
public List<BlockPopulator> getDefaultPopulators(World world)
|
|
||||||
{
|
{
|
||||||
GList<BlockPopulator> p = new GList<BlockPopulator>();
|
return world;
|
||||||
p.add(new PopulatorTrees());
|
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,6 +32,10 @@ public class IrisBiome
|
|||||||
.surface(MB.of(Material.SAND), MB.of(Material.SAND), MB.of(Material.SAND), MB.of(Material.CLAY), MB.of(Material.GRAVEL))
|
.surface(MB.of(Material.SAND), MB.of(Material.SAND), MB.of(Material.SAND), MB.of(Material.CLAY), MB.of(Material.GRAVEL))
|
||||||
.simplexSurface()
|
.simplexSurface()
|
||||||
.height(-0.03);
|
.height(-0.03);
|
||||||
|
public static final IrisBiome LAKE = new IrisBiome("Lake", Biome.OCEAN)
|
||||||
|
.surface(MB.of(Material.SAND), MB.of(Material.SAND), MB.of(Material.SAND), MB.of(Material.GRAVEL), MB.of(Material.CLAY), MB.of(Material.GRAVEL))
|
||||||
|
.simplexSurface()
|
||||||
|
.height(-0.03);
|
||||||
public static final IrisBiome DEEP_OCEAN = new IrisBiome("Deep Ocean", Biome.DEEP_OCEAN)
|
public static final IrisBiome DEEP_OCEAN = new IrisBiome("Deep Ocean", Biome.DEEP_OCEAN)
|
||||||
.surface(MB.of(Material.SAND), MB.of(Material.CLAY), MB.of(Material.GRAVEL))
|
.surface(MB.of(Material.SAND), MB.of(Material.CLAY), MB.of(Material.GRAVEL))
|
||||||
.simplexSurface()
|
.simplexSurface()
|
||||||
@@ -312,7 +316,7 @@ public class IrisBiome
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return poly.getChoice(wx * 0.2D, wz * 0.2D);
|
return poly.getChoice(wx * 0.2D, wz * 0.2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(scatterSurface)
|
if(scatterSurface)
|
||||||
@@ -325,7 +329,7 @@ public class IrisBiome
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return poly.getChoice(wx * 0.2D, wz * 0.2D);
|
return poly.getChoice(wx * 0.2D, wz * 0.2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
return getSurface().getRandom();
|
return getSurface().getRandom();
|
||||||
@@ -385,7 +389,12 @@ public class IrisBiome
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IrisBiome find(Biome biome)
|
public static GList<IrisBiome> getBiomes()
|
||||||
|
{
|
||||||
|
return map.v().remove(IrisBiome.ROAD_GRASSY, IrisBiome.ROAD_GRAVEL, IrisBiome.BEACH, IrisBiome.LAKE, IrisBiome.RIVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IrisBiome findByBiome(Biome biome)
|
||||||
{
|
{
|
||||||
if(map.containsKey(biome))
|
if(map.containsKey(biome))
|
||||||
{
|
{
|
||||||
@@ -394,4 +403,9 @@ public class IrisBiome
|
|||||||
|
|
||||||
return IrisBiome.PLAINS;
|
return IrisBiome.PLAINS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GMap<String, Double> getSchematicGroups()
|
||||||
|
{
|
||||||
|
return schematicGroups;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,38 +33,7 @@ public class GenLayerBiome extends GenLayer
|
|||||||
riverCheck = new CNG(rng.nextParallelRNG(30), 1D, 2).scale(0.00096);
|
riverCheck = new CNG(rng.nextParallelRNG(30), 1D, 2).scale(0.00096);
|
||||||
pathCheck = new CNG(rng.nextParallelRNG(31), 1D, 1).scale(0.00096);
|
pathCheck = new CNG(rng.nextParallelRNG(31), 1D, 1).scale(0.00096);
|
||||||
roads = new MaxingGenerator(rng.nextParallelRNG(32), 5, 0.00055, 8, factory);
|
roads = new MaxingGenerator(rng.nextParallelRNG(32), 5, 0.00055, 8, factory);
|
||||||
biomeGenerator = new EnumMaxingGenerator<IrisBiome>(rng.nextParallelRNG(33), 0.00755 * Iris.settings.gen.biomeScale, 1,
|
biomeGenerator = new EnumMaxingGenerator<IrisBiome>(rng.nextParallelRNG(33), 0.00755 * Iris.settings.gen.biomeScale, 1, IrisBiome.getBiomes().toArray(new IrisBiome[IrisBiome.getBiomes().size()]), factory);
|
||||||
new IrisBiome[] {
|
|
||||||
IrisBiome.HAUNTED_FOREST,
|
|
||||||
IrisBiome.FOREST_MOUNTAINS,
|
|
||||||
IrisBiome.DESERT,
|
|
||||||
IrisBiome.DESERT_HILLS,
|
|
||||||
IrisBiome.MESA,
|
|
||||||
IrisBiome.DESERT_COMBINED,
|
|
||||||
IrisBiome.SAVANNA,
|
|
||||||
IrisBiome.SAVANNA_HILLS,
|
|
||||||
IrisBiome.DESERT_RED,
|
|
||||||
IrisBiome.JUNGLE,
|
|
||||||
IrisBiome.JUNGLE_HILLS,
|
|
||||||
IrisBiome.SWAMP,
|
|
||||||
IrisBiome.OCEAN,
|
|
||||||
IrisBiome.PLAINS,
|
|
||||||
IrisBiome.DECAYING_PLAINS,
|
|
||||||
IrisBiome.FOREST,
|
|
||||||
IrisBiome.FOREST_HILLS,
|
|
||||||
IrisBiome.BIRCH_FOREST,
|
|
||||||
IrisBiome.BIRCH_FOREST_HILLS,
|
|
||||||
IrisBiome.ROOFED_FOREST,
|
|
||||||
IrisBiome.TAIGA,
|
|
||||||
IrisBiome.EXTREME_HILLS,
|
|
||||||
IrisBiome.EXTREME_HILLS_TREES,
|
|
||||||
IrisBiome.TAIGA_COLD,
|
|
||||||
IrisBiome.TAIGA_COLD_HILLS,
|
|
||||||
IrisBiome.ICE_FLATS,
|
|
||||||
IrisBiome.ICE_MOUNTAINS,
|
|
||||||
IrisBiome.REDWOOD_TAIGA,
|
|
||||||
IrisBiome.REDWOOD_TAIGA_HILLS,
|
|
||||||
}, factory);
|
|
||||||
//@done
|
//@done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package ninja.bytecode.iris.generator.layer;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
|
||||||
|
import ninja.bytecode.iris.generator.IrisGenerator;
|
||||||
|
import ninja.bytecode.iris.util.GenLayer;
|
||||||
|
import ninja.bytecode.iris.util.MaxingGenerator;
|
||||||
|
import ninja.bytecode.shuriken.math.CNG;
|
||||||
|
import ninja.bytecode.shuriken.math.RNG;
|
||||||
|
|
||||||
|
public class GenLayerCaves extends GenLayer
|
||||||
|
{
|
||||||
|
private CNG caveHeight;
|
||||||
|
private CNG caveGirth;
|
||||||
|
private CNG caveClamp;
|
||||||
|
private MaxingGenerator caveVeins;
|
||||||
|
|
||||||
|
public GenLayerCaves(IrisGenerator iris, World world, Random random, RNG rng)
|
||||||
|
{
|
||||||
|
super(iris, world, random, rng);
|
||||||
|
caveHeight = new CNG(rng.nextParallelRNG(-100001), 1D, 7).scale(0.00222);
|
||||||
|
caveGirth = new CNG(rng.nextParallelRNG(-100002), 1D, 12).scale(0.03);
|
||||||
|
caveClamp = new CNG(rng.nextParallelRNG(-10000), 1D, 3).scale(0.1422);
|
||||||
|
caveVeins = new MaxingGenerator(rng.nextParallelRNG(-99999), 22, 0.002, 1, (g) -> g.fractureWith(new CNG(rng.nextParallelRNG(-5555), 1D, 4).scale(0.02), 70));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void genCaves(double wxx, double wzx, int x, int z, int s, IrisGenerator g)
|
||||||
|
{
|
||||||
|
for(double itr = 0; itr < 0.2; itr += 0.1)
|
||||||
|
{
|
||||||
|
double thickness = 0.25 + itr + (0.5 * caveClamp.noise(wxx, wzx));
|
||||||
|
double size = 3.88D * thickness;
|
||||||
|
double variance = 8.34D * thickness;
|
||||||
|
double w = size + (variance * caveGirth.noise(wxx, wzx));
|
||||||
|
double h = size + (variance * caveGirth.noise(wzx, wxx));
|
||||||
|
double width = 0;
|
||||||
|
double height = h;
|
||||||
|
double elevation = (caveHeight.noise(wxx + (19949D * itr), wzx - (19949D * itr)) * (350)) - 80;
|
||||||
|
while(width <= w && height > 1D)
|
||||||
|
{
|
||||||
|
width+=2;
|
||||||
|
height-=2;
|
||||||
|
|
||||||
|
if(caveVeins.hasBorder(3, width, wxx - (19949D * itr), wzx + (19949D * itr)))
|
||||||
|
{
|
||||||
|
double r = (((caveGirth.noise(wxx, wzx, width)) * variance) + height) / 2D;
|
||||||
|
|
||||||
|
for(int i = (int) -r; i < r; i++)
|
||||||
|
{
|
||||||
|
if(i + height > s)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Material t = g.getType(x, (int) (elevation + i) - 55, z);
|
||||||
|
if(t.equals(Material.BEDROCK) || t.equals(Material.WATER) || t.equals(Material.STATIONARY_WATER))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
g.setBlock(x, (int) (elevation + i) - 55, z, Material.AIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double generateLayer(double gnoise, double dx, double dz)
|
||||||
|
{
|
||||||
|
return gnoise;
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
package ninja.bytecode.iris.generator.populator;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.World;
|
||||||
|
|
||||||
|
import ninja.bytecode.iris.generator.biome.IrisBiome;
|
||||||
|
import ninja.bytecode.iris.schematic.Schematic;
|
||||||
|
import ninja.bytecode.iris.util.MB;
|
||||||
|
|
||||||
|
public class BiomeBiasSchematicPopulator extends SurfaceBiasSchematicPopulator
|
||||||
|
{
|
||||||
|
protected IrisBiome biome;
|
||||||
|
public BiomeBiasSchematicPopulator(double chance, IrisBiome biome, Schematic... schematics)
|
||||||
|
{
|
||||||
|
super(chance, schematics);
|
||||||
|
this.biome = biome;
|
||||||
|
|
||||||
|
for(MB i : biome.getSurface())
|
||||||
|
{
|
||||||
|
surface(i.material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPopulate(World world, Random random, Chunk source, int wx, int wz)
|
||||||
|
{
|
||||||
|
if(world.getBiome(wx, wz).equals(biome.getRealBiome()))
|
||||||
|
{
|
||||||
|
super.doPopulate(world, random, source, wx, wz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
package ninja.bytecode.iris.generator.populator;
|
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import org.bukkit.Chunk;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.TreeType;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.generator.BlockPopulator;
|
|
||||||
|
|
||||||
import ninja.bytecode.iris.Iris;
|
|
||||||
import ninja.bytecode.iris.generator.biome.IrisBiome;
|
|
||||||
import ninja.bytecode.shuriken.bench.PrecisionStopwatch;
|
|
||||||
import ninja.bytecode.shuriken.math.RollingSequence;
|
|
||||||
|
|
||||||
public class PopulatorTrees extends BlockPopulator
|
|
||||||
{
|
|
||||||
public static RollingSequence timings = new RollingSequence(512);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void populate(World world, Random random, Chunk source)
|
|
||||||
{
|
|
||||||
if(!Iris.settings.gen.doTrees)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PrecisionStopwatch f = PrecisionStopwatch.start();
|
|
||||||
int debuff = 0;
|
|
||||||
|
|
||||||
for(int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
if(debuff > 0)
|
|
||||||
{
|
|
||||||
debuff--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int x = random.nextInt(15) + (source.getX() * 16);
|
|
||||||
int z = random.nextInt(15) + (source.getZ() * 16);
|
|
||||||
int y = world.getHighestBlockYAt(x, z);
|
|
||||||
Location l = new Location(world, x, y, z);
|
|
||||||
|
|
||||||
if(!l.getBlock().getType().isSolid())
|
|
||||||
{
|
|
||||||
l.getBlock().setType(Material.AIR, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
IrisBiome biome = IrisBiome.find(world.getBiome(x, z));
|
|
||||||
TreeType tt = biome.getTreeChanceSingle();
|
|
||||||
|
|
||||||
if(tt != null)
|
|
||||||
{
|
|
||||||
world.generateTree(l, tt);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
debuff += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f.end();
|
|
||||||
timings.put(f.getMilliseconds());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package ninja.bytecode.iris.generator.populator;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
|
||||||
|
import ninja.bytecode.iris.schematic.Schematic;
|
||||||
|
import ninja.bytecode.iris.util.ChancedPopulator;
|
||||||
|
|
||||||
|
public class SchematicPopulator extends ChancedPopulator
|
||||||
|
{
|
||||||
|
protected final Schematic[] schematics;
|
||||||
|
|
||||||
|
public SchematicPopulator(double chance, Schematic... schematics)
|
||||||
|
{
|
||||||
|
super(chance);
|
||||||
|
this.schematics = schematics;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doPopulate(World world, Random random, Chunk source, int wx, int wz)
|
||||||
|
{
|
||||||
|
Block b = world.getHighestBlockAt(wx, wz);
|
||||||
|
|
||||||
|
if(!b.getRelative(BlockFace.DOWN).getType().isSolid())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
schematics[random.nextInt(schematics.length)].place(world, wx, b.getY() - 1, wz);
|
||||||
|
}
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
package ninja.bytecode.iris.generator.populator;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
|
||||||
|
import ninja.bytecode.iris.schematic.Schematic;
|
||||||
|
import ninja.bytecode.shuriken.collections.GList;
|
||||||
|
|
||||||
|
public class SurfaceBiasSchematicPopulator extends SchematicPopulator
|
||||||
|
{
|
||||||
|
private GList<Material> bias;
|
||||||
|
|
||||||
|
public SurfaceBiasSchematicPopulator(double chance, Schematic... schematics)
|
||||||
|
{
|
||||||
|
super(chance, schematics);
|
||||||
|
this.bias = new GList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SurfaceBiasSchematicPopulator surface(Material mb)
|
||||||
|
{
|
||||||
|
bias.add(mb);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doPopulate(World world, Random random, Chunk source, int wx, int wz)
|
||||||
|
{
|
||||||
|
Block b = world.getHighestBlockAt(wx, wz);
|
||||||
|
|
||||||
|
for(Material i : bias)
|
||||||
|
{
|
||||||
|
if(b.getRelative(BlockFace.DOWN).getType().equals(i))
|
||||||
|
{
|
||||||
|
schematics[random.nextInt(schematics.length)].place(world, wx, b.getY() - 1, wz);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,210 @@
|
|||||||
|
package ninja.bytecode.iris.schematic;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.util.BlockVector;
|
||||||
|
|
||||||
|
import ninja.bytecode.iris.util.MB;
|
||||||
|
import ninja.bytecode.shuriken.collections.GMap;
|
||||||
|
import ninja.bytecode.shuriken.io.CustomOutputStream;
|
||||||
|
import ninja.bytecode.shuriken.logging.L;
|
||||||
|
|
||||||
|
public class Schematic
|
||||||
|
{
|
||||||
|
private int w;
|
||||||
|
private int h;
|
||||||
|
private int d;
|
||||||
|
private int x;
|
||||||
|
private int y;
|
||||||
|
private int z;
|
||||||
|
private final GMap<BlockVector, MB> s;
|
||||||
|
|
||||||
|
public Schematic(int w, int h, int d, int x, int y, int z)
|
||||||
|
{
|
||||||
|
this.w = w;
|
||||||
|
this.h = h;
|
||||||
|
this.d = d;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
s = new GMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public int getW()
|
||||||
|
{
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public int getH()
|
||||||
|
{
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public int getD()
|
||||||
|
{
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public int getX()
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public int getY()
|
||||||
|
{
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public int getZ()
|
||||||
|
{
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public GMap<BlockVector, MB> getSchematic()
|
||||||
|
{
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public void read(InputStream in) throws IOException
|
||||||
|
{
|
||||||
|
GZIPInputStream gzi = new GZIPInputStream(in);
|
||||||
|
DataInputStream din = new DataInputStream(gzi);
|
||||||
|
w = din.readInt();
|
||||||
|
h = din.readInt();
|
||||||
|
d = din.readInt();
|
||||||
|
x = din.readInt();
|
||||||
|
y = din.readInt();
|
||||||
|
z = din.readInt();
|
||||||
|
int l = din.readInt();
|
||||||
|
clear();
|
||||||
|
|
||||||
|
for(int i = 0; i < l; i++)
|
||||||
|
{
|
||||||
|
s.put(new BlockVector(din.readInt(), din.readInt(), din.readInt()), new MB(Material.getMaterial((int)din.readByte()), din.readByte()));
|
||||||
|
}
|
||||||
|
|
||||||
|
din.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public void write(OutputStream out) throws IOException
|
||||||
|
{
|
||||||
|
CustomOutputStream cos = new CustomOutputStream(out, 9);
|
||||||
|
DataOutputStream dos = new DataOutputStream(cos);
|
||||||
|
dos.writeInt(w);
|
||||||
|
dos.writeInt(h);
|
||||||
|
dos.writeInt(d);
|
||||||
|
dos.writeInt(x);
|
||||||
|
dos.writeInt(y);
|
||||||
|
dos.writeInt(z);
|
||||||
|
dos.writeInt(s.size());
|
||||||
|
|
||||||
|
for(BlockVector i : s.keySet())
|
||||||
|
{
|
||||||
|
dos.writeInt(i.getBlockX());
|
||||||
|
dos.writeInt(i.getBlockY());
|
||||||
|
dos.writeInt(i.getBlockZ());
|
||||||
|
dos.writeByte(s.get(i).material.getId());
|
||||||
|
dos.writeByte(s.get(i).data);
|
||||||
|
}
|
||||||
|
|
||||||
|
dos.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockVector getOffset()
|
||||||
|
{
|
||||||
|
return new BlockVector(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MB get(int x, int y, int z)
|
||||||
|
{
|
||||||
|
return s.get(new BlockVector(x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean has(int x, int y, int z)
|
||||||
|
{
|
||||||
|
return s.contains(new BlockVector(x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(int x, int y, int z, MB mb)
|
||||||
|
{
|
||||||
|
s.put(new BlockVector(x, y, z), mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Schematic copy()
|
||||||
|
{
|
||||||
|
Schematic s = new Schematic(w, h, d, x, y, z);
|
||||||
|
s.fill(this.s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
s.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fill(GMap<BlockVector, MB> b)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
s.put(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public void place(World source, int wx, int wy, int wz)
|
||||||
|
{
|
||||||
|
Location start = new Location(source, wx, wy, wz).clone().subtract(getOffset());
|
||||||
|
|
||||||
|
for(BlockVector i : getSchematic().keySet())
|
||||||
|
{
|
||||||
|
MB b = getSchematic().get(i);
|
||||||
|
Block blk = start.clone().add(i).getBlock();
|
||||||
|
|
||||||
|
if(!blk.isEmpty() && !b.material.isOccluding())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
blk.setTypeIdAndData(b.material.getId(), b.data, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static Schematic load(File f) throws IOException
|
||||||
|
{
|
||||||
|
L.i("Loading Schematic: " + f.getPath());
|
||||||
|
Schematic s = new Schematic(1, 1, 1, 1, 1, 1);
|
||||||
|
FileInputStream fin = new FileInputStream(f);
|
||||||
|
s.read(fin);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package ninja.bytecode.iris.util;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.generator.BlockPopulator;
|
||||||
|
|
||||||
|
import ninja.bytecode.shuriken.math.M;
|
||||||
|
|
||||||
|
public abstract class ChancedPopulator extends BlockPopulator
|
||||||
|
{
|
||||||
|
private final double chance;
|
||||||
|
|
||||||
|
public ChancedPopulator(double chance)
|
||||||
|
{
|
||||||
|
this.chance = chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void populate(World world, Random random, Chunk source)
|
||||||
|
{
|
||||||
|
if(chance == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chance > 0 && chance < 1 && M.r(chance))
|
||||||
|
{
|
||||||
|
doPopulate(world, random, source, (source.getX() << 4) + random.nextInt(16), (source.getZ() << 4) + random.nextInt(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chance > 1)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < (int) chance; i++)
|
||||||
|
{
|
||||||
|
doPopulate(world, random, source, (source.getX() << 4) + random.nextInt(16), (source.getZ() << 4) + random.nextInt(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(M.r(chance - ((int) chance)))
|
||||||
|
{
|
||||||
|
doPopulate(world, random, source, (source.getX() << 4) + random.nextInt(16), (source.getZ() << 4) + random.nextInt(16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void doPopulate(World world, Random random, Chunk source, int x, int z);
|
||||||
|
}
|
||||||
@@ -2,18 +2,28 @@ package ninja.bytecode.iris.util;
|
|||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.bukkit.util.BlockVector;
|
||||||
|
|
||||||
import ninja.bytecode.iris.generator.biome.IrisBiome;
|
import ninja.bytecode.iris.generator.biome.IrisBiome;
|
||||||
|
import ninja.bytecode.iris.schematic.Schematic;
|
||||||
import ninja.bytecode.shuriken.collections.GMap;
|
import ninja.bytecode.shuriken.collections.GMap;
|
||||||
|
|
||||||
public class ChunkPlan
|
public class ChunkPlan
|
||||||
{
|
{
|
||||||
private final GMap<ChunkedVector, Double> heightCache;
|
private final GMap<ChunkedVector, Double> heightCache;
|
||||||
private final GMap<ChunkedVector, IrisBiome> biomeCache;
|
private final GMap<ChunkedVector, IrisBiome> biomeCache;
|
||||||
|
private final GMap<BlockVector, Schematic> schematics;
|
||||||
|
|
||||||
public ChunkPlan()
|
public ChunkPlan()
|
||||||
{
|
{
|
||||||
this.heightCache = new GMap<ChunkedVector, Double>();
|
this.schematics = new GMap<>();
|
||||||
this.biomeCache = new GMap<ChunkedVector, IrisBiome>();
|
this.heightCache = new GMap<>();
|
||||||
|
this.biomeCache = new GMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void planSchematic(BlockVector b, Schematic s)
|
||||||
|
{
|
||||||
|
schematics.put(b, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IrisBiome getBiome(int x, int z)
|
public IrisBiome getBiome(int x, int z)
|
||||||
|
|||||||
@@ -0,0 +1,910 @@
|
|||||||
|
package ninja.bytecode.iris.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.material.MaterialData;
|
||||||
|
|
||||||
|
import ninja.bytecode.shuriken.collections.GList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cuboids
|
||||||
|
*
|
||||||
|
* @author cyberpwn
|
||||||
|
*/
|
||||||
|
public class Cuboid implements Iterable<Block>, Cloneable, ConfigurationSerializable
|
||||||
|
{
|
||||||
|
protected final String worldName;
|
||||||
|
protected int x1, y1, z1;
|
||||||
|
protected int x2, y2, z2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a Cuboid given two Location objects which represent any two corners
|
||||||
|
* of the Cuboid.
|
||||||
|
*
|
||||||
|
* @param l1
|
||||||
|
* one of the corners
|
||||||
|
* @param l2
|
||||||
|
* the other corner
|
||||||
|
*/
|
||||||
|
public Cuboid(Location l1, Location l2)
|
||||||
|
{
|
||||||
|
if(!l1.getWorld().equals(l2.getWorld()))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("locations must be on the same world");
|
||||||
|
}
|
||||||
|
|
||||||
|
worldName = l1.getWorld().getName();
|
||||||
|
x1 = Math.min(l1.getBlockX(), l2.getBlockX());
|
||||||
|
y1 = Math.min(l1.getBlockY(), l2.getBlockY());
|
||||||
|
z1 = Math.min(l1.getBlockZ(), l2.getBlockZ());
|
||||||
|
x2 = Math.max(l1.getBlockX(), l2.getBlockX());
|
||||||
|
y2 = Math.max(l1.getBlockY(), l2.getBlockY());
|
||||||
|
z2 = Math.max(l1.getBlockZ(), l2.getBlockZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
public GList<LivingEntity> getLivingEntities()
|
||||||
|
{
|
||||||
|
return new GList<LivingEntity>(new GListAdapter<Entity, LivingEntity>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public LivingEntity onAdapt(Entity from)
|
||||||
|
{
|
||||||
|
if(from instanceof LivingEntity)
|
||||||
|
{
|
||||||
|
return (LivingEntity) from;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}.adapt(getEntities()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GList<Entity> getEntities()
|
||||||
|
{
|
||||||
|
GList<Entity> en = new GList<Entity>();
|
||||||
|
|
||||||
|
for(Chunk i : getChunks())
|
||||||
|
{
|
||||||
|
for(Entity j : i.getEntities())
|
||||||
|
{
|
||||||
|
if(contains(j.getLocation()))
|
||||||
|
{
|
||||||
|
en.add(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return en;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the locations
|
||||||
|
*
|
||||||
|
* @param l1
|
||||||
|
* a
|
||||||
|
* @param l2
|
||||||
|
* b
|
||||||
|
*/
|
||||||
|
public void set(Location l1, Location l2)
|
||||||
|
{
|
||||||
|
x1 = Math.min(l1.getBlockX(), l2.getBlockX());
|
||||||
|
y1 = Math.min(l1.getBlockY(), l2.getBlockY());
|
||||||
|
z1 = Math.min(l1.getBlockZ(), l2.getBlockZ());
|
||||||
|
x2 = Math.max(l1.getBlockX(), l2.getBlockX());
|
||||||
|
y2 = Math.max(l1.getBlockY(), l2.getBlockY());
|
||||||
|
z2 = Math.max(l1.getBlockZ(), l2.getBlockZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a one-block Cuboid at the given Location of the Cuboid.
|
||||||
|
*
|
||||||
|
* @param l1
|
||||||
|
* location of the Cuboid
|
||||||
|
*/
|
||||||
|
public Cuboid(Location l1)
|
||||||
|
{
|
||||||
|
this(l1, l1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy constructor.
|
||||||
|
*
|
||||||
|
* @param other
|
||||||
|
* the Cuboid to copy
|
||||||
|
*/
|
||||||
|
public Cuboid(Cuboid other)
|
||||||
|
{
|
||||||
|
this(other.getWorld().getName(), other.x1, other.y1, other.z1, other.x2, other.y2, other.z2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a Cuboid in the given World and xyz co-ordinates
|
||||||
|
*
|
||||||
|
* @param world
|
||||||
|
* the Cuboid's world
|
||||||
|
* @param x1
|
||||||
|
* X co-ordinate of corner 1
|
||||||
|
* @param y1
|
||||||
|
* Y co-ordinate of corner 1
|
||||||
|
* @param z1
|
||||||
|
* Z co-ordinate of corner 1
|
||||||
|
* @param x2
|
||||||
|
* X co-ordinate of corner 2
|
||||||
|
* @param y2
|
||||||
|
* Y co-ordinate of corner 2
|
||||||
|
* @param z2
|
||||||
|
* Z co-ordinate of corner 2
|
||||||
|
*/
|
||||||
|
public Cuboid(World world, int x1, int y1, int z1, int x2, int y2, int z2)
|
||||||
|
{
|
||||||
|
this.worldName = world.getName();
|
||||||
|
this.x1 = Math.min(x1, x2);
|
||||||
|
this.x2 = Math.max(x1, x2);
|
||||||
|
this.y1 = Math.min(y1, y2);
|
||||||
|
this.y2 = Math.max(y1, y2);
|
||||||
|
this.z1 = Math.min(z1, z2);
|
||||||
|
this.z2 = Math.max(z1, z2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a Cuboid in the given world name and xyz co-ordinates.
|
||||||
|
*
|
||||||
|
* @param worldName
|
||||||
|
* the Cuboid's world name
|
||||||
|
* @param x1
|
||||||
|
* X co-ordinate of corner 1
|
||||||
|
* @param y1
|
||||||
|
* Y co-ordinate of corner 1
|
||||||
|
* @param z1
|
||||||
|
* Z co-ordinate of corner 1
|
||||||
|
* @param x2
|
||||||
|
* X co-ordinate of corner 2
|
||||||
|
* @param y2
|
||||||
|
* Y co-ordinate of corner 2
|
||||||
|
* @param z2
|
||||||
|
* Z co-ordinate of corner 2
|
||||||
|
*/
|
||||||
|
private Cuboid(String worldName, int x1, int y1, int z1, int x2, int y2, int z2)
|
||||||
|
{
|
||||||
|
this.worldName = worldName;
|
||||||
|
this.x1 = Math.min(x1, x2);
|
||||||
|
this.x2 = Math.max(x1, x2);
|
||||||
|
this.y1 = Math.min(y1, y2);
|
||||||
|
this.y2 = Math.max(y1, y2);
|
||||||
|
this.z1 = Math.min(z1, z2);
|
||||||
|
this.z2 = Math.max(z1, z2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cuboid(Map<String, Object> map)
|
||||||
|
{
|
||||||
|
worldName = (String) map.get("worldName");
|
||||||
|
x1 = (Integer) map.get("x1");
|
||||||
|
x2 = (Integer) map.get("x2");
|
||||||
|
y1 = (Integer) map.get("y1");
|
||||||
|
y2 = (Integer) map.get("y2");
|
||||||
|
z1 = (Integer) map.get("z1");
|
||||||
|
z2 = (Integer) map.get("z2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> serialize()
|
||||||
|
{
|
||||||
|
Map<String, Object> map = new HashMap<String, Object>();
|
||||||
|
map.put("worldName", worldName);
|
||||||
|
map.put("x1", x1);
|
||||||
|
map.put("y1", y1);
|
||||||
|
map.put("z1", z1);
|
||||||
|
map.put("x2", x2);
|
||||||
|
map.put("y2", y2);
|
||||||
|
map.put("z2", z2);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cuboid flatten(int level)
|
||||||
|
{
|
||||||
|
return new Cuboid(getWorld(), x1, level, z1, x2, level, z2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Location of the lower northeast corner of the Cuboid (minimum XYZ
|
||||||
|
* co-ordinates).
|
||||||
|
*
|
||||||
|
* @return Location of the lower northeast corner
|
||||||
|
*/
|
||||||
|
public Location getLowerNE()
|
||||||
|
{
|
||||||
|
return new Location(getWorld(), x1, y1, z1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Location of the upper southwest corner of the Cuboid (maximum XYZ
|
||||||
|
* co-ordinates).
|
||||||
|
*
|
||||||
|
* @return Location of the upper southwest corner
|
||||||
|
*/
|
||||||
|
public Location getUpperSW()
|
||||||
|
{
|
||||||
|
return new Location(getWorld(), x2, y2, z2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the the centre of the Cuboid
|
||||||
|
*
|
||||||
|
* @return Location at the centre of the Cuboid
|
||||||
|
*/
|
||||||
|
public Location getCenter()
|
||||||
|
{
|
||||||
|
int x1 = getUpperX() + 1;
|
||||||
|
int y1 = getUpperY() + 1;
|
||||||
|
int z1 = getUpperZ() + 1;
|
||||||
|
return new Location(getWorld(), getLowerX() + (x1 - getLowerX()) / 2.0, getLowerY() + (y1 - getLowerY()) / 2.0, getLowerZ() + (z1 - getLowerZ()) / 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Cuboid's world.
|
||||||
|
*
|
||||||
|
* @return the World object representing this Cuboid's world
|
||||||
|
* @throws IllegalStateException
|
||||||
|
* if the world is not loaded
|
||||||
|
*/
|
||||||
|
public World getWorld()
|
||||||
|
{
|
||||||
|
World world = Bukkit.getWorld(worldName);
|
||||||
|
if(world == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("world '" + worldName + "' is not loaded");
|
||||||
|
}
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the size of this Cuboid along the X axis
|
||||||
|
*
|
||||||
|
* @return Size of Cuboid along the X axis
|
||||||
|
*/
|
||||||
|
public int getSizeX()
|
||||||
|
{
|
||||||
|
return (x2 - x1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the size of this Cuboid along the Y axis
|
||||||
|
*
|
||||||
|
* @return Size of Cuboid along the Y axis
|
||||||
|
*/
|
||||||
|
public int getSizeY()
|
||||||
|
{
|
||||||
|
return (y2 - y1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the size of this Cuboid along the Z axis
|
||||||
|
*
|
||||||
|
* @return Size of Cuboid along the Z axis
|
||||||
|
*/
|
||||||
|
public int getSizeZ()
|
||||||
|
{
|
||||||
|
return (z2 - z1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cuboid dimensions
|
||||||
|
*
|
||||||
|
* @return the dimensions
|
||||||
|
*/
|
||||||
|
public Dimension getDimension()
|
||||||
|
{
|
||||||
|
return new Dimension(getSizeX(), getSizeY(), getSizeZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the minimum X co-ordinate of this Cuboid
|
||||||
|
*
|
||||||
|
* @return the minimum X co-ordinate
|
||||||
|
*/
|
||||||
|
public int getLowerX()
|
||||||
|
{
|
||||||
|
return x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the minimum Y co-ordinate of this Cuboid
|
||||||
|
*
|
||||||
|
* @return the minimum Y co-ordinate
|
||||||
|
*/
|
||||||
|
public int getLowerY()
|
||||||
|
{
|
||||||
|
return y1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the minimum Z co-ordinate of this Cuboid
|
||||||
|
*
|
||||||
|
* @return the minimum Z co-ordinate
|
||||||
|
*/
|
||||||
|
public int getLowerZ()
|
||||||
|
{
|
||||||
|
return z1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum X co-ordinate of this Cuboid
|
||||||
|
*
|
||||||
|
* @return the maximum X co-ordinate
|
||||||
|
*/
|
||||||
|
public int getUpperX()
|
||||||
|
{
|
||||||
|
return x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum Y co-ordinate of this Cuboid
|
||||||
|
*
|
||||||
|
* @return the maximum Y co-ordinate
|
||||||
|
*/
|
||||||
|
public int getUpperY()
|
||||||
|
{
|
||||||
|
return y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum Z co-ordinate of this Cuboid
|
||||||
|
*
|
||||||
|
* @return the maximum Z co-ordinate
|
||||||
|
*/
|
||||||
|
public int getUpperZ()
|
||||||
|
{
|
||||||
|
return z2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Blocks at the eight corners of the Cuboid.
|
||||||
|
*
|
||||||
|
* @return array of Block objects representing the Cuboid corners
|
||||||
|
*/
|
||||||
|
public Block[] corners()
|
||||||
|
{
|
||||||
|
Block[] res = new Block[8];
|
||||||
|
World w = getWorld();
|
||||||
|
res[0] = w.getBlockAt(x1, y1, z1);
|
||||||
|
res[1] = w.getBlockAt(x1, y1, z2);
|
||||||
|
res[2] = w.getBlockAt(x1, y2, z1);
|
||||||
|
res[3] = w.getBlockAt(x1, y2, z2);
|
||||||
|
res[4] = w.getBlockAt(x2, y1, z1);
|
||||||
|
res[5] = w.getBlockAt(x2, y1, z2);
|
||||||
|
res[6] = w.getBlockAt(x2, y2, z1);
|
||||||
|
res[7] = w.getBlockAt(x2, y2, z2);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand the Cuboid in the given direction by the given amount. Negative
|
||||||
|
* amounts will shrink the Cuboid in the given direction. Shrinking a cuboid's
|
||||||
|
* face past the opposite face is not an error and will return a valid Cuboid.
|
||||||
|
*
|
||||||
|
* @param dir
|
||||||
|
* the direction in which to expand
|
||||||
|
* @param amount
|
||||||
|
* the number of blocks by which to expand
|
||||||
|
* @return a new Cuboid expanded by the given direction and amount
|
||||||
|
*/
|
||||||
|
public Cuboid expand(CuboidDirection dir, int amount)
|
||||||
|
{
|
||||||
|
switch(dir)
|
||||||
|
{
|
||||||
|
case North:
|
||||||
|
return new Cuboid(worldName, x1 - amount, y1, z1, x2, y2, z2);
|
||||||
|
case South:
|
||||||
|
return new Cuboid(worldName, x1, y1, z1, x2 + amount, y2, z2);
|
||||||
|
case East:
|
||||||
|
return new Cuboid(worldName, x1, y1, z1 - amount, x2, y2, z2);
|
||||||
|
case West:
|
||||||
|
return new Cuboid(worldName, x1, y1, z1, x2, y2, z2 + amount);
|
||||||
|
case Down:
|
||||||
|
return new Cuboid(worldName, x1, y1 - amount, z1, x2, y2, z2);
|
||||||
|
case Up:
|
||||||
|
return new Cuboid(worldName, x1, y1, z1, x2, y2 + amount, z2);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("invalid direction " + dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shift the Cuboid in the given direction by the given amount.
|
||||||
|
*
|
||||||
|
* @param dir
|
||||||
|
* the direction in which to shift
|
||||||
|
* @param amount
|
||||||
|
* the number of blocks by which to shift
|
||||||
|
* @return a new Cuboid shifted by the given direction and amount
|
||||||
|
*/
|
||||||
|
public Cuboid shift(CuboidDirection dir, int amount)
|
||||||
|
{
|
||||||
|
return expand(dir, amount).expand(dir.opposite(), -amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outset (grow) the Cuboid in the given direction by the given amount.
|
||||||
|
*
|
||||||
|
* @param dir
|
||||||
|
* the direction in which to outset (must be Horizontal, Vertical, or
|
||||||
|
* Both)
|
||||||
|
* @param amount
|
||||||
|
* the number of blocks by which to outset
|
||||||
|
* @return a new Cuboid outset by the given direction and amount
|
||||||
|
*/
|
||||||
|
public Cuboid outset(CuboidDirection dir, int amount)
|
||||||
|
{
|
||||||
|
Cuboid c;
|
||||||
|
switch(dir)
|
||||||
|
{
|
||||||
|
case Horizontal:
|
||||||
|
c = expand(CuboidDirection.North, amount).expand(CuboidDirection.South, amount).expand(CuboidDirection.East, amount).expand(CuboidDirection.West, amount);
|
||||||
|
break;
|
||||||
|
case Vertical:
|
||||||
|
c = expand(CuboidDirection.Down, amount).expand(CuboidDirection.Up, amount);
|
||||||
|
break;
|
||||||
|
case Both:
|
||||||
|
c = outset(CuboidDirection.Horizontal, amount).outset(CuboidDirection.Vertical, amount);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("invalid direction " + dir);
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inset (shrink) the Cuboid in the given direction by the given amount.
|
||||||
|
* Equivalent to calling outset() with a negative amount.
|
||||||
|
*
|
||||||
|
* @param dir
|
||||||
|
* the direction in which to inset (must be Horizontal, Vertical, or
|
||||||
|
* Both)
|
||||||
|
* @param amount
|
||||||
|
* the number of blocks by which to inset
|
||||||
|
* @return a new Cuboid inset by the given direction and amount
|
||||||
|
*/
|
||||||
|
public Cuboid inset(CuboidDirection dir, int amount)
|
||||||
|
{
|
||||||
|
return outset(dir, -amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the point at (x,y,z) is contained within this Cuboid.
|
||||||
|
*
|
||||||
|
* @param x
|
||||||
|
* the X co-ordinate
|
||||||
|
* @param y
|
||||||
|
* the Y co-ordinate
|
||||||
|
* @param z
|
||||||
|
* the Z co-ordinate
|
||||||
|
* @return true if the given point is within this Cuboid, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean contains(int x, int y, int z)
|
||||||
|
{
|
||||||
|
return x >= x1 && x <= x2 && y >= y1 && y <= y2 && z >= z1 && z <= z2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given Block is contained within this Cuboid.
|
||||||
|
*
|
||||||
|
* @param b
|
||||||
|
* the Block to check for
|
||||||
|
* @return true if the Block is within this Cuboid, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean contains(Block b)
|
||||||
|
{
|
||||||
|
return contains(b.getLocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given Location is contained within this Cuboid.
|
||||||
|
*
|
||||||
|
* @param l
|
||||||
|
* the Location to check for
|
||||||
|
* @return true if the Location is within this Cuboid, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean contains(Location l)
|
||||||
|
{
|
||||||
|
return worldName.equals(l.getWorld().getName()) && contains(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the volume of this Cuboid.
|
||||||
|
*
|
||||||
|
* @return the Cuboid volume, in blocks
|
||||||
|
*/
|
||||||
|
public int volume()
|
||||||
|
{
|
||||||
|
return getSizeX() * getSizeY() * getSizeZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the average light level of all empty (air) blocks in the Cuboid. Returns
|
||||||
|
* 0 if there are no empty blocks.
|
||||||
|
*
|
||||||
|
* @return the average light level of this Cuboid
|
||||||
|
*/
|
||||||
|
public byte averageLightLevel()
|
||||||
|
{
|
||||||
|
long total = 0;
|
||||||
|
int n = 0;
|
||||||
|
for(Block b : this)
|
||||||
|
{
|
||||||
|
if(b.isEmpty())
|
||||||
|
{
|
||||||
|
total += b.getLightLevel();
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n > 0 ? (byte) (total / n) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contract the Cuboid, returning a Cuboid with any air around the edges
|
||||||
|
* removed, just large enough to include all non-air blocks.
|
||||||
|
*
|
||||||
|
* @return a new Cuboid with no external air blocks
|
||||||
|
*/
|
||||||
|
public Cuboid contract()
|
||||||
|
{
|
||||||
|
return this.contract(CuboidDirection.Down).contract(CuboidDirection.South).contract(CuboidDirection.East).contract(CuboidDirection.Up).contract(CuboidDirection.North).contract(CuboidDirection.West);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contract the Cuboid in the given direction, returning a new Cuboid which has
|
||||||
|
* no exterior empty space. E.g. a direction of Down will push the top face
|
||||||
|
* downwards as much as possible.
|
||||||
|
*
|
||||||
|
* @param dir
|
||||||
|
* the direction in which to contract
|
||||||
|
* @return a new Cuboid contracted in the given direction
|
||||||
|
*/
|
||||||
|
public Cuboid contract(CuboidDirection dir)
|
||||||
|
{
|
||||||
|
Cuboid face = getFace(dir.opposite());
|
||||||
|
switch(dir)
|
||||||
|
{
|
||||||
|
case Down:
|
||||||
|
while(face.containsOnly(Material.AIR) && face.getLowerY() > this.getLowerY())
|
||||||
|
{
|
||||||
|
face = face.shift(CuboidDirection.Down, 1);
|
||||||
|
}
|
||||||
|
return new Cuboid(worldName, x1, y1, z1, x2, face.getUpperY(), z2);
|
||||||
|
case Up:
|
||||||
|
while(face.containsOnly(Material.AIR) && face.getUpperY() < this.getUpperY())
|
||||||
|
{
|
||||||
|
face = face.shift(CuboidDirection.Up, 1);
|
||||||
|
}
|
||||||
|
return new Cuboid(worldName, x1, face.getLowerY(), z1, x2, y2, z2);
|
||||||
|
case North:
|
||||||
|
while(face.containsOnly(Material.AIR) && face.getLowerX() > this.getLowerX())
|
||||||
|
{
|
||||||
|
face = face.shift(CuboidDirection.North, 1);
|
||||||
|
}
|
||||||
|
return new Cuboid(worldName, x1, y1, z1, face.getUpperX(), y2, z2);
|
||||||
|
case South:
|
||||||
|
while(face.containsOnly(Material.AIR) && face.getUpperX() < this.getUpperX())
|
||||||
|
{
|
||||||
|
face = face.shift(CuboidDirection.South, 1);
|
||||||
|
}
|
||||||
|
return new Cuboid(worldName, face.getLowerX(), y1, z1, x2, y2, z2);
|
||||||
|
case East:
|
||||||
|
while(face.containsOnly(Material.AIR) && face.getLowerZ() > this.getLowerZ())
|
||||||
|
{
|
||||||
|
face = face.shift(CuboidDirection.East, 1);
|
||||||
|
}
|
||||||
|
return new Cuboid(worldName, x1, y1, z1, x2, y2, face.getUpperZ());
|
||||||
|
case West:
|
||||||
|
while(face.containsOnly(Material.AIR) && face.getUpperZ() < this.getUpperZ())
|
||||||
|
{
|
||||||
|
face = face.shift(CuboidDirection.West, 1);
|
||||||
|
}
|
||||||
|
return new Cuboid(worldName, x1, y1, face.getLowerZ(), x2, y2, z2);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Invalid direction " + dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Cuboid representing the face of this Cuboid. The resulting Cuboid
|
||||||
|
* will be one block thick in the axis perpendicular to the requested face.
|
||||||
|
*
|
||||||
|
* @param dir
|
||||||
|
* which face of the Cuboid to get
|
||||||
|
* @return the Cuboid representing this Cuboid's requested face
|
||||||
|
*/
|
||||||
|
public Cuboid getFace(CuboidDirection dir)
|
||||||
|
{
|
||||||
|
switch(dir)
|
||||||
|
{
|
||||||
|
case Down:
|
||||||
|
return new Cuboid(worldName, x1, y1, z1, x2, y1, z2);
|
||||||
|
case Up:
|
||||||
|
return new Cuboid(worldName, x1, y2, z1, x2, y2, z2);
|
||||||
|
case North:
|
||||||
|
return new Cuboid(worldName, x1, y1, z1, x1, y2, z2);
|
||||||
|
case South:
|
||||||
|
return new Cuboid(worldName, x2, y1, z1, x2, y2, z2);
|
||||||
|
case East:
|
||||||
|
return new Cuboid(worldName, x1, y1, z1, x2, y2, z1);
|
||||||
|
case West:
|
||||||
|
return new Cuboid(worldName, x1, y1, z2, x2, y2, z2);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Invalid direction " + dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the Cuboid contains only blocks of the given type
|
||||||
|
*
|
||||||
|
* @param material
|
||||||
|
* the material to check for
|
||||||
|
* @return true if this Cuboid contains only blocks of the given type
|
||||||
|
*/
|
||||||
|
public boolean containsOnly(Material material)
|
||||||
|
{
|
||||||
|
for(Block b : this)
|
||||||
|
{
|
||||||
|
if(b.getType() != material)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Cuboid big enough to hold both this Cuboid and the given one.
|
||||||
|
*
|
||||||
|
* @param other
|
||||||
|
* the other Cuboid to include
|
||||||
|
* @return a new Cuboid large enough to hold this Cuboid and the given Cuboid
|
||||||
|
*/
|
||||||
|
public Cuboid getBoundingCuboid(Cuboid other)
|
||||||
|
{
|
||||||
|
if(other == null)
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xMin = Math.min(getLowerX(), other.getLowerX());
|
||||||
|
int yMin = Math.min(getLowerY(), other.getLowerY());
|
||||||
|
int zMin = Math.min(getLowerZ(), other.getLowerZ());
|
||||||
|
int xMax = Math.max(getUpperX(), other.getUpperX());
|
||||||
|
int yMax = Math.max(getUpperY(), other.getUpperY());
|
||||||
|
int zMax = Math.max(getUpperZ(), other.getUpperZ());
|
||||||
|
|
||||||
|
return new Cuboid(worldName, xMin, yMin, zMin, xMax, yMax, zMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a block relative to the lower NE point of the Cuboid.
|
||||||
|
*
|
||||||
|
* @param x
|
||||||
|
* the X co-ordinate
|
||||||
|
* @param y
|
||||||
|
* the Y co-ordinate
|
||||||
|
* @param z
|
||||||
|
* the Z co-ordinate
|
||||||
|
* @return the block at the given position
|
||||||
|
*/
|
||||||
|
public Block getRelativeBlock(int x, int y, int z)
|
||||||
|
{
|
||||||
|
return getWorld().getBlockAt(x1 + x, y1 + y, z1 + z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a block relative to the lower NE point of the Cuboid in the given World.
|
||||||
|
* This version of getRelativeBlock() should be used if being called many times,
|
||||||
|
* to avoid excessive calls to getWorld().
|
||||||
|
*
|
||||||
|
* @param w
|
||||||
|
* the World
|
||||||
|
* @param x
|
||||||
|
* the X co-ordinate
|
||||||
|
* @param y
|
||||||
|
* the Y co-ordinate
|
||||||
|
* @param z
|
||||||
|
* the Z co-ordinate
|
||||||
|
* @return the block at the given position
|
||||||
|
*/
|
||||||
|
public Block getRelativeBlock(World w, int x, int y, int z)
|
||||||
|
{
|
||||||
|
return w.getBlockAt(x1 + x, y1 + y, z1 + z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of the chunks which are fully or partially contained in this
|
||||||
|
* cuboid.
|
||||||
|
*
|
||||||
|
* @return a list of Chunk objects
|
||||||
|
*/
|
||||||
|
public List<Chunk> getChunks()
|
||||||
|
{
|
||||||
|
List<Chunk> res = new ArrayList<Chunk>();
|
||||||
|
|
||||||
|
World w = getWorld();
|
||||||
|
int x1 = getLowerX() & ~0xf;
|
||||||
|
int x2 = getUpperX() & ~0xf;
|
||||||
|
int z1 = getLowerZ() & ~0xf;
|
||||||
|
int z2 = getUpperZ() & ~0xf;
|
||||||
|
for(int x = x1; x <= x2; x += 16)
|
||||||
|
{
|
||||||
|
for(int z = z1; z <= z2; z += 16)
|
||||||
|
{
|
||||||
|
res.add(w.getChunkAt(x >> 4, z >> 4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all the blocks within the Cuboid to the given block ID and data byte.
|
||||||
|
*
|
||||||
|
* @param blockId
|
||||||
|
* the block ID
|
||||||
|
* @param data
|
||||||
|
* the block data
|
||||||
|
* @deprecated use {@link #fill(MaterialData, MassBlockUpdate)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void fill(int blockId, byte data)
|
||||||
|
{
|
||||||
|
for(Block b : this)
|
||||||
|
{
|
||||||
|
b.setTypeIdAndData(blockId, data, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all the blocks within the Cuboid to the given MaterialData, using a
|
||||||
|
* MassBlockUpdate object for fast updates.
|
||||||
|
*
|
||||||
|
* @param mat
|
||||||
|
* the MaterialData to set
|
||||||
|
* @param mbu
|
||||||
|
* the MassBlockUpdate object
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the light level of all blocks within this Cuboid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see java.lang.Iterable#iterator()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Iterator<Block> iterator()
|
||||||
|
{
|
||||||
|
return new CuboidIterator(getWorld(), x1, y1, z1, x2, y2, z2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see java.lang.Object#clone()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Cuboid clone() throws CloneNotSupportedException
|
||||||
|
{
|
||||||
|
return new Cuboid(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "Cuboid: " + worldName + "," + x1 + "," + y1 + "," + z1 + "=>" + x2 + "," + y2 + "," + z2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CuboidIterator implements Iterator<Block>
|
||||||
|
{
|
||||||
|
private World w;
|
||||||
|
private int baseX, baseY, baseZ;
|
||||||
|
private int x, y, z;
|
||||||
|
private int sizeX, sizeY, sizeZ;
|
||||||
|
|
||||||
|
public CuboidIterator(World w, int x1, int y1, int z1, int x2, int y2, int z2)
|
||||||
|
{
|
||||||
|
this.w = w;
|
||||||
|
baseX = x1;
|
||||||
|
baseY = y1;
|
||||||
|
baseZ = z1;
|
||||||
|
sizeX = Math.abs(x2 - x1) + 1;
|
||||||
|
sizeY = Math.abs(y2 - y1) + 1;
|
||||||
|
sizeZ = Math.abs(z2 - z1) + 1;
|
||||||
|
x = y = z = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext()
|
||||||
|
{
|
||||||
|
return x < sizeX && y < sizeY && z < sizeZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block next()
|
||||||
|
{
|
||||||
|
Block b = w.getBlockAt(baseX + x, baseY + y, baseZ + z);
|
||||||
|
if(++x >= sizeX)
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
if(++y >= sizeY)
|
||||||
|
{
|
||||||
|
y = 0;
|
||||||
|
++z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove()
|
||||||
|
{
|
||||||
|
// nop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CuboidDirection
|
||||||
|
{
|
||||||
|
|
||||||
|
North,
|
||||||
|
East,
|
||||||
|
South,
|
||||||
|
West,
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
Horizontal,
|
||||||
|
Vertical,
|
||||||
|
Both,
|
||||||
|
Unknown;
|
||||||
|
|
||||||
|
public CuboidDirection opposite()
|
||||||
|
{
|
||||||
|
switch(this)
|
||||||
|
{
|
||||||
|
case North:
|
||||||
|
return South;
|
||||||
|
case East:
|
||||||
|
return West;
|
||||||
|
case South:
|
||||||
|
return North;
|
||||||
|
case West:
|
||||||
|
return East;
|
||||||
|
case Horizontal:
|
||||||
|
return Vertical;
|
||||||
|
case Vertical:
|
||||||
|
return Horizontal;
|
||||||
|
case Up:
|
||||||
|
return Down;
|
||||||
|
case Down:
|
||||||
|
return Up;
|
||||||
|
case Both:
|
||||||
|
return Both;
|
||||||
|
default:
|
||||||
|
return Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package ninja.bytecode.iris.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a cuboid exception
|
||||||
|
*
|
||||||
|
* @author cyberpwn
|
||||||
|
*/
|
||||||
|
public class CuboidException extends Exception
|
||||||
|
{
|
||||||
|
public CuboidException(String string)
|
||||||
|
{
|
||||||
|
super(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package ninja.bytecode.iris.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dimensions
|
||||||
|
*
|
||||||
|
* @author cyberpwn
|
||||||
|
*/
|
||||||
|
public class Dimension
|
||||||
|
{
|
||||||
|
private final int width;
|
||||||
|
private final int height;
|
||||||
|
private final int depth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a dimension
|
||||||
|
*
|
||||||
|
* @param width
|
||||||
|
* width of this (X)
|
||||||
|
* @param height
|
||||||
|
* the height (Y)
|
||||||
|
* @param depth
|
||||||
|
* the depth (Z)
|
||||||
|
*/
|
||||||
|
public Dimension(int width, int height, int depth)
|
||||||
|
{
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.depth = depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a dimension
|
||||||
|
*
|
||||||
|
* @param width
|
||||||
|
* width of this (X)
|
||||||
|
* @param height
|
||||||
|
* the height (Y)
|
||||||
|
*/
|
||||||
|
public Dimension(int width, int height)
|
||||||
|
{
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.depth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the direction of the flat part of this dimension (null if no thin
|
||||||
|
* face)
|
||||||
|
*
|
||||||
|
* @return the direction of the flat pane or null
|
||||||
|
*/
|
||||||
|
public DimensionFace getPane()
|
||||||
|
{
|
||||||
|
if(width == 1)
|
||||||
|
{
|
||||||
|
return DimensionFace.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(height == 1)
|
||||||
|
{
|
||||||
|
return DimensionFace.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(depth == 1)
|
||||||
|
{
|
||||||
|
return DimensionFace.Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth()
|
||||||
|
{
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight()
|
||||||
|
{
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDepth()
|
||||||
|
{
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package ninja.bytecode.iris.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a dimension (coordinates not worlds)
|
||||||
|
*
|
||||||
|
* @author cyberpwn
|
||||||
|
*/
|
||||||
|
public enum DimensionFace
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The X dimension (width)
|
||||||
|
*/
|
||||||
|
X,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Y dimension (height)
|
||||||
|
*/
|
||||||
|
Y,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Z dimension (depth)
|
||||||
|
*/
|
||||||
|
Z
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
package ninja.bytecode.iris.util;
|
||||||
|
|
||||||
|
import ninja.bytecode.iris.util.Cuboid.CuboidDirection;
|
||||||
|
import ninja.bytecode.shuriken.collections.GList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directions
|
||||||
|
*
|
||||||
|
* @author cyberpwn
|
||||||
|
*/
|
||||||
|
public enum Direction
|
||||||
|
{
|
||||||
|
U(0, 1, 0, CuboidDirection.Up),
|
||||||
|
D(0, -1, 0, CuboidDirection.Down),
|
||||||
|
N(0, 0, -1, CuboidDirection.North),
|
||||||
|
S(0, 0, 1, CuboidDirection.South),
|
||||||
|
E(1, 0, 0, CuboidDirection.East),
|
||||||
|
W(-1, 0, 0, CuboidDirection.West);
|
||||||
|
|
||||||
|
private int x;
|
||||||
|
private int y;
|
||||||
|
private int z;
|
||||||
|
private CuboidDirection f;
|
||||||
|
|
||||||
|
private Direction(int x, int y, int z, CuboidDirection f)
|
||||||
|
{
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
this.f = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int x()
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int y()
|
||||||
|
{
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int z()
|
||||||
|
{
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CuboidDirection f()
|
||||||
|
{
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GList<Direction> news()
|
||||||
|
{
|
||||||
|
return new GList<Direction>().add(N, E, W, S);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GList<Direction> udnews()
|
||||||
|
{
|
||||||
|
return new GList<Direction>().add(U, D, N, E, W, S);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the directional value from the given byte from common directional blocks
|
||||||
|
* (MUST BE BETWEEN 0 and 5 INCLUSIVE)
|
||||||
|
*
|
||||||
|
* @param b
|
||||||
|
* the byte
|
||||||
|
* @return the direction or null if the byte is outside of the inclusive range
|
||||||
|
* 0-5
|
||||||
|
*/
|
||||||
|
public static Direction fromByte(byte b)
|
||||||
|
{
|
||||||
|
if(b > 5 || b < 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(b == 0)
|
||||||
|
{
|
||||||
|
return D;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(b == 1)
|
||||||
|
{
|
||||||
|
return U;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(b == 2)
|
||||||
|
{
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(b == 3)
|
||||||
|
{
|
||||||
|
return S;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(b == 4)
|
||||||
|
{
|
||||||
|
return W;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the byte value represented in some directional blocks
|
||||||
|
*
|
||||||
|
* @return the byte value
|
||||||
|
*/
|
||||||
|
public byte byteValue()
|
||||||
|
{
|
||||||
|
switch(this)
|
||||||
|
{
|
||||||
|
case D:
|
||||||
|
return 0;
|
||||||
|
case E:
|
||||||
|
return 5;
|
||||||
|
case N:
|
||||||
|
return 2;
|
||||||
|
case S:
|
||||||
|
return 3;
|
||||||
|
case U:
|
||||||
|
return 1;
|
||||||
|
case W:
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package ninja.bytecode.iris.util;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ninja.bytecode.shuriken.collections.GList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts a list of objects into a list of other objects
|
||||||
|
*
|
||||||
|
* @author cyberpwn
|
||||||
|
* @param <FROM>
|
||||||
|
* the from object in lists (the item INSIDE the list)
|
||||||
|
* @param <TO>
|
||||||
|
* the to object in lists (the item INSIDE the list)
|
||||||
|
*/
|
||||||
|
public abstract class GListAdapter<FROM, TO>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Adapts a list of FROM to a list of TO
|
||||||
|
*
|
||||||
|
* @param from
|
||||||
|
* the from list
|
||||||
|
* @return the to list
|
||||||
|
*/
|
||||||
|
public List<TO> adapt(List<FROM> from)
|
||||||
|
{
|
||||||
|
List<TO> adapted = new GList<TO>();
|
||||||
|
|
||||||
|
for(FROM i : from)
|
||||||
|
{
|
||||||
|
TO t = onAdapt(i);
|
||||||
|
|
||||||
|
if(t != null)
|
||||||
|
{
|
||||||
|
adapted.add(onAdapt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return adapted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts a list object FROM to TO for use with the adapt method
|
||||||
|
*
|
||||||
|
* @param from
|
||||||
|
* the from object
|
||||||
|
* @return the to object
|
||||||
|
*/
|
||||||
|
public abstract TO onAdapt(FROM from);
|
||||||
|
}
|
||||||
@@ -2,21 +2,16 @@ package ninja.bytecode.iris.util;
|
|||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
|
||||||
import ninja.bytecode.iris.Iris;
|
import ninja.bytecode.iris.Iris;
|
||||||
import ninja.bytecode.iris.generator.populator.PopulatorTrees;
|
|
||||||
import ninja.bytecode.shuriken.Shuriken;
|
import ninja.bytecode.shuriken.Shuriken;
|
||||||
import ninja.bytecode.shuriken.execution.ChronoLatch;
|
import ninja.bytecode.shuriken.execution.ChronoLatch;
|
||||||
import ninja.bytecode.shuriken.execution.J;
|
|
||||||
import ninja.bytecode.shuriken.execution.TaskExecutor.TaskGroup;
|
import ninja.bytecode.shuriken.execution.TaskExecutor.TaskGroup;
|
||||||
import ninja.bytecode.shuriken.execution.TaskExecutor.TaskResult;
|
import ninja.bytecode.shuriken.execution.TaskExecutor.TaskResult;
|
||||||
import ninja.bytecode.shuriken.format.F;
|
|
||||||
import ninja.bytecode.shuriken.logging.L;
|
|
||||||
import ninja.bytecode.shuriken.math.RollingSequence;
|
import ninja.bytecode.shuriken.math.RollingSequence;
|
||||||
import ninja.bytecode.shuriken.reaction.O;
|
import ninja.bytecode.shuriken.reaction.O;
|
||||||
|
|
||||||
@@ -31,42 +26,12 @@ public abstract class ParallelChunkGenerator extends ChunkGenerator
|
|||||||
private boolean ready = false;
|
private boolean ready = false;
|
||||||
int cg = 0;
|
int cg = 0;
|
||||||
private ChronoLatch cl = new ChronoLatch(1000);
|
private ChronoLatch cl = new ChronoLatch(1000);
|
||||||
private ChronoLatch cs = new ChronoLatch(1000);
|
|
||||||
private RollingSequence rs = new RollingSequence(512);
|
private RollingSequence rs = new RollingSequence(512);
|
||||||
private RollingSequence cps = new RollingSequence(3);
|
|
||||||
private World world;
|
private World world;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
public World getWorld()
|
||||||
public ParallelChunkGenerator()
|
|
||||||
{
|
{
|
||||||
Bukkit.getScheduler().scheduleAsyncRepeatingTask(Iris.instance, () ->
|
return world;
|
||||||
{
|
|
||||||
J.attempt(() ->
|
|
||||||
{
|
|
||||||
if(world.getPlayers().isEmpty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(cs.flip())
|
|
||||||
{
|
|
||||||
cps.put(cg);
|
|
||||||
cg = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double total = rs.getAverage() + PopulatorTrees.timings.getAverage();
|
|
||||||
double rcs = (1000D / total);
|
|
||||||
double work = cps.getAverage() / (rcs + 1);
|
|
||||||
L.i("Terrain Gen for " + world.getName());
|
|
||||||
L.i("- Terrain (MLTC): " + F.duration(rs.getAverage(), 2));
|
|
||||||
L.i("- Trees (SGLC): " + F.duration(PopulatorTrees.timings.getAverage(), 2));
|
|
||||||
L.i("Total: " + F.duration(total, 3) + " Work: " + F.f(cps.getAverage(), 0) + "/s of " + F.f(rcs, 0) + "/s (" + F.pc(work, 0) + " utilization)");
|
|
||||||
L.flush();
|
|
||||||
|
|
||||||
System.out.println("");
|
|
||||||
});
|
|
||||||
|
|
||||||
}, 20, 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateFullColumn(int a, int b, int c, int d, BiomeGrid g, ChunkPlan p)
|
public void generateFullColumn(int a, int b, int c, int d, BiomeGrid g, ChunkPlan p)
|
||||||
@@ -144,33 +109,33 @@ public abstract class ParallelChunkGenerator extends ChunkGenerator
|
|||||||
public abstract void decorateColumn(int wx, int wz, int x, int z, ChunkPlan plan);
|
public abstract void decorateColumn(int wx, int wz, int x, int z, ChunkPlan plan);
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
protected void setBlock(int x, int y, int z, Material b)
|
public void setBlock(int x, int y, int z, Material b)
|
||||||
{
|
{
|
||||||
setBlock(x, y, z, b.getId(), (byte) 0);
|
setBlock(x, y, z, b.getId(), (byte) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
protected void setBlock(int x, int y, int z, Material b, byte d)
|
public void setBlock(int x, int y, int z, Material b, byte d)
|
||||||
{
|
{
|
||||||
setBlock(x, y, z, b.getId(), d);
|
setBlock(x, y, z, b.getId(), d);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setBlock(int x, int y, int z, int b)
|
public void setBlock(int x, int y, int z, int b)
|
||||||
{
|
{
|
||||||
setBlock(x, y, z, b, (byte) 0);
|
setBlock(x, y, z, b, (byte) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setBlock(int x, int y, int z, int b, byte d)
|
public void setBlock(int x, int y, int z, int b, byte d)
|
||||||
{
|
{
|
||||||
data.setBlock(x, y, z, b, d);
|
data.setBlock(x, y, z, b, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Material getType(int x, int y, int z)
|
public Material getType(int x, int y, int z)
|
||||||
{
|
{
|
||||||
return data.getType(x, y, z);
|
return data.getType(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte getData(int x, int y, int z)
|
public byte getData(int x, int y, int z)
|
||||||
{
|
{
|
||||||
return data.getData(x, y, z);
|
return data.getData(x, y, z);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
package ninja.bytecode.iris.util;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.enchantments.Enchantment;
|
||||||
|
import org.bukkit.inventory.ItemFlag;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.util.BlockVector;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import ninja.bytecode.iris.schematic.Schematic;
|
||||||
|
import ninja.bytecode.shuriken.collections.GList;
|
||||||
|
|
||||||
|
public class WandUtil
|
||||||
|
{
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static void pasteSchematic(Schematic s, Location at)
|
||||||
|
{
|
||||||
|
Location start = at.clone().add(s.getOffset());
|
||||||
|
|
||||||
|
for(BlockVector i : s.getSchematic().keySet())
|
||||||
|
{
|
||||||
|
MB b = s.getSchematic().get(i);
|
||||||
|
System.out.println("Pasted " + b.material + " @ " + start.clone().add(i));
|
||||||
|
start.clone().add(i).getBlock().setTypeIdAndData(b.material.getId(), b.data, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static Schematic createSchematic(ItemStack wand, Location at)
|
||||||
|
{
|
||||||
|
if(!isWand(wand))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Location[] f = getCuboid(wand);
|
||||||
|
Cuboid c = new Cuboid(f[0], f[1]);
|
||||||
|
Vector v = at.clone().subtract(c.getLowerNE()).toVector();
|
||||||
|
Schematic s = new Schematic(c.getSizeX(), c.getSizeY(), c.getSizeZ(), v.getBlockX(), v.getBlockY(), v.getBlockZ());
|
||||||
|
Iterator<Block> bb = c.iterator();
|
||||||
|
while(bb.hasNext())
|
||||||
|
{
|
||||||
|
Block b = bb.next();
|
||||||
|
|
||||||
|
if(b.getType().equals(Material.AIR))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockVector bv = b.getLocation().toVector().toBlockVector().subtract(c.getLowerNE().toVector().toBlockVector()).toBlockVector();
|
||||||
|
System.out.println("Load " + bv + " " + b.getType());
|
||||||
|
s.put(bv.getBlockX(), bv.getBlockY(), bv.getBlockZ(), new MB(b.getType(), b.getData()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(Throwable e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Location stringToLocation(String s)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String[] f = s.split("\\Q in \\E");
|
||||||
|
String[] g = f[0].split("\\Q,\\E");
|
||||||
|
return new Location(Bukkit.getWorld(f[1]), Integer.valueOf(g[0]), Integer.valueOf(g[1]), Integer.valueOf(g[2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(Throwable e)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String locationToString(Location s)
|
||||||
|
{
|
||||||
|
if(s == null)
|
||||||
|
{
|
||||||
|
return "<#>";
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.getBlockX() + "," + s.getBlockY() + "," + s.getBlockZ() + " in " + s.getWorld().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemStack createWand()
|
||||||
|
{
|
||||||
|
return createWand(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemStack update(boolean left, Location a, ItemStack item)
|
||||||
|
{
|
||||||
|
if(!isWand(item))
|
||||||
|
{
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location[] f = getCuboid(item);
|
||||||
|
Location other = left ? f[1] : f[0];
|
||||||
|
|
||||||
|
return createWand(left ? a : other, left ? other : a);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemStack createWand(Location a, Location b)
|
||||||
|
{
|
||||||
|
ItemStack is = new ItemStack(Material.BLAZE_ROD);
|
||||||
|
is.addUnsafeEnchantment(Enchantment.ARROW_INFINITE, 1);
|
||||||
|
ItemMeta im = is.getItemMeta();
|
||||||
|
im.setDisplayName(ChatColor.BOLD + "" + ChatColor.GOLD + "Wand of Iris");
|
||||||
|
im.setUnbreakable(true);
|
||||||
|
im.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_PLACED_ON, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_DESTROYS, ItemFlag.HIDE_ENCHANTS);
|
||||||
|
im.setLore(new GList<String>().add(locationToString(a), locationToString(b)));
|
||||||
|
is.setItemMeta(im);
|
||||||
|
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Location[] getCuboid(ItemStack is)
|
||||||
|
{
|
||||||
|
ItemMeta im = is.getItemMeta();
|
||||||
|
return new Location[] {stringToLocation(im.getLore().get(0)), stringToLocation(im.getLore().get(1))};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isWand(ItemStack item)
|
||||||
|
{
|
||||||
|
if(!item.getType().equals(createWand().getType()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!item.getItemMeta().getEnchants().equals(createWand().getItemMeta().getEnchants()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!item.getItemMeta().getDisplayName().equals(createWand().getItemMeta().getDisplayName()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user