This commit is contained in:
Daniel Mills 2020-08-16 13:18:02 -04:00
parent d89371a279
commit 2407c3f2f8
35 changed files with 1531 additions and 505 deletions

View File

@ -41,14 +41,14 @@ import com.volmit.iris.util.Permission;
import com.volmit.iris.util.RollingSequence; import com.volmit.iris.util.RollingSequence;
import com.volmit.iris.util.ScoreDirection; import com.volmit.iris.util.ScoreDirection;
public class Iris extends MortarPlugin implements BoardProvider { public class Iris extends MortarPlugin implements BoardProvider
{
public static KList<GroupedExecutor> executors = new KList<>(); public static KList<GroupedExecutor> executors = new KList<>();
public static Iris instance; public static Iris instance;
public static IrisDataManager globaldata; public static IrisDataManager globaldata;
public static ProjectManager proj; public static ProjectManager proj;
public static IrisHotloadManager hotloader; public static IrisHotloadManager hotloader;
public static WandController wand; public static WandController wand;
private static String last = "";
private BoardManager manager; private BoardManager manager;
private String mem = "..."; private String mem = "...";
private ChronoLatch cl = new ChronoLatch(1000); private ChronoLatch cl = new ChronoLatch(1000);
@ -65,27 +65,31 @@ public class Iris extends MortarPlugin implements BoardProvider {
@com.volmit.iris.util.Command @com.volmit.iris.util.Command
public CommandIris commandIris; public CommandIris commandIris;
public Iris() { public Iris()
{
IO.delete(new File("iris")); IO.delete(new File("iris"));
} }
@Override @Override
public void start() { public void start()
{
} }
@Override @Override
public void stop() { public void stop()
{
} }
@Override @Override
public String getTag(String subTag) { public String getTag(String subTag)
return ChatColor.BOLD + "" + ChatColor.DARK_GRAY + "[" + ChatColor.BOLD + "" + ChatColor.GREEN + "Iris" {
+ ChatColor.BOLD + ChatColor.DARK_GRAY + "]" + ChatColor.RESET + "" + ChatColor.GRAY + ": "; return ChatColor.BOLD + "" + ChatColor.DARK_GRAY + "[" + ChatColor.BOLD + "" + ChatColor.GREEN + "Iris" + ChatColor.BOLD + ChatColor.DARK_GRAY + "]" + ChatColor.RESET + "" + ChatColor.GRAY + ": ";
} }
public void onEnable() { public void onEnable()
{
lock = new IrisLock("Iris"); lock = new IrisLock("Iris");
instance = this; instance = this;
hotloader = new IrisHotloadManager(); hotloader = new IrisHotloadManager();
@ -93,22 +97,25 @@ public class Iris extends MortarPlugin implements BoardProvider {
wand = new WandController(); wand = new WandController();
postProcessors = loadPostProcessors(); postProcessors = loadPostProcessors();
proj = new ProjectManager(); proj = new ProjectManager();
manager = new BoardManager(this, manager = new BoardManager(this, BoardSettings.builder().boardProvider(this).scoreDirection(ScoreDirection.UP).build());
BoardSettings.builder().boardProvider(this).scoreDirection(ScoreDirection.UP).build());
super.onEnable(); super.onEnable();
} }
public void onDisable() { public void onDisable()
{
lock.unlock(); lock.unlock();
proj.close(); proj.close();
for (GroupedExecutor i : executors) { for(GroupedExecutor i : executors)
{
i.close(); i.close();
} }
for (World i : Bukkit.getWorlds()) { for(World i : Bukkit.getWorlds())
if (i.getGenerator() instanceof IrisChunkGenerator) { {
if(i.getGenerator() instanceof IrisChunkGenerator)
{
((IrisChunkGenerator) i).close(); ((IrisChunkGenerator) i).close();
} }
} }
@ -121,23 +128,28 @@ public class Iris extends MortarPlugin implements BoardProvider {
} }
@Override @Override
public String getTitle(Player player) { public String getTitle(Player player)
{
return ChatColor.GREEN + "Iris"; return ChatColor.GREEN + "Iris";
} }
@Override @Override
public List<String> getLines(Player player) { public List<String> getLines(Player player)
if (!clf.flip()) { {
if(!clf.flip())
{
return lines; return lines;
} }
World world = player.getWorld(); World world = player.getWorld();
lines.clear(); lines.clear();
if (world.getGenerator() instanceof IrisChunkGenerator) { if(world.getGenerator() instanceof IrisChunkGenerator)
{
IrisChunkGenerator g = (IrisChunkGenerator) world.getGenerator(); IrisChunkGenerator g = (IrisChunkGenerator) world.getGenerator();
if (cl.flip()) { if(cl.flip())
{
mem = Form.memSize(g.guessMemoryUsage(), 2); mem = Form.memSize(g.guessMemoryUsage(), 2);
} }
@ -150,23 +162,21 @@ public class Iris extends MortarPlugin implements BoardProvider {
tp.put(g.getMetrics().getSpeed()); tp.put(g.getMetrics().getSpeed());
lines.add("&7&m-----------------"); lines.add("&7&m-----------------");
lines.add(ChatColor.GREEN + "Speed" + ChatColor.GRAY + ": " + ChatColor.BOLD + "" + ChatColor.GRAY lines.add(ChatColor.GREEN + "Speed" + ChatColor.GRAY + ": " + ChatColor.BOLD + "" + ChatColor.GRAY + Form.f(g.getMetrics().getPerSecond().getAverage(), 0) + "/s " + Form.duration(g.getMetrics().getTotal().getAverage(), 1) + "");
+ Form.f(g.getMetrics().getPerSecond().getAverage(), 0) + "/s "
+ Form.duration(g.getMetrics().getTotal().getAverage(), 1) + "");
lines.add(ChatColor.GREEN + "Generators" + ChatColor.GRAY + ": " + Form.f(CNG.creates)); lines.add(ChatColor.GREEN + "Generators" + ChatColor.GRAY + ": " + Form.f(CNG.creates));
lines.add(ChatColor.GREEN + "Noise" + ChatColor.GRAY + ": " + Form.f((int) hits.getAverage())); lines.add(ChatColor.GREEN + "Noise" + ChatColor.GRAY + ": " + Form.f((int) hits.getAverage()));
lines.add(ChatColor.GREEN + "Parallax Chunks" + ChatColor.GRAY + ": " lines.add(ChatColor.GREEN + "Parallax Chunks" + ChatColor.GRAY + ": " + Form.f((int) g.getParallaxMap().getLoadedChunks().size()));
+ Form.f((int) g.getParallaxMap().getLoadedChunks().size())); lines.add(ChatColor.GREEN + "Objects" + ChatColor.GRAY + ": " + Form.f(g.getData().getObjectLoader().count()));
lines.add(ChatColor.GREEN + "Objects" + ChatColor.GRAY + ": "
+ Form.f(g.getData().getObjectLoader().count()));
lines.add(ChatColor.GREEN + "Memory" + ChatColor.GRAY + ": " + mem); lines.add(ChatColor.GREEN + "Memory" + ChatColor.GRAY + ": " + mem);
if (er != null && b != null) { if(er != null && b != null)
{
lines.add(ChatColor.GREEN + "Biome" + ChatColor.GRAY + ": " + b.getName()); lines.add(ChatColor.GREEN + "Biome" + ChatColor.GRAY + ": " + b.getName());
lines.add(ChatColor.GREEN + "File" + ChatColor.GRAY + ": " + b.getLoadKey()); lines.add(ChatColor.GREEN + "File" + ChatColor.GRAY + ": " + b.getLoadKey());
} }
if (st != null) { if(st != null)
{
lines.add(ChatColor.GREEN + "Structure" + ChatColor.GRAY + ": " + st.getStructure().getName()); lines.add(ChatColor.GREEN + "Structure" + ChatColor.GRAY + ": " + st.getStructure().getName());
lines.add(ChatColor.GREEN + "Tile" + ChatColor.GRAY + ": " + st.getTile().toString()); lines.add(ChatColor.GREEN + "Tile" + ChatColor.GRAY + ": " + st.getTile().toString());
} }
@ -174,14 +184,16 @@ public class Iris extends MortarPlugin implements BoardProvider {
lines.add("&7&m-----------------"); lines.add("&7&m-----------------");
} }
else { else
{
lines.add(ChatColor.GREEN + "Join an Iris World!"); lines.add(ChatColor.GREEN + "Join an Iris World!");
} }
return lines; return lines;
} }
private static KList<Class<? extends IrisPostBlockFilter>> loadPostProcessors() { private static KList<Class<? extends IrisPostBlockFilter>> loadPostProcessors()
{
KList<Class<? extends IrisPostBlockFilter>> g = new KList<Class<? extends IrisPostBlockFilter>>(); KList<Class<? extends IrisPostBlockFilter>> g = new KList<Class<? extends IrisPostBlockFilter>>();
g.add(PostFloatingNibDeleter.class); g.add(PostFloatingNibDeleter.class);
@ -195,55 +207,57 @@ public class Iris extends MortarPlugin implements BoardProvider {
} }
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public boolean onCommand(CommandSender sender, Command command, String label, String[] args)
{
return super.onCommand(sender, command, label, args); return super.onCommand(sender, command, label, args);
} }
public void imsg(CommandSender s, String msg) { public void imsg(CommandSender s, String msg)
s.sendMessage(ChatColor.GREEN + "[" + ChatColor.DARK_GRAY + "Iris" + ChatColor.GREEN + "]" + ChatColor.GRAY {
+ ": " + msg); s.sendMessage(ChatColor.GREEN + "[" + ChatColor.DARK_GRAY + "Iris" + ChatColor.GREEN + "]" + ChatColor.GRAY + ": " + msg);
} }
@Override @Override
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { public ChunkGenerator getDefaultWorldGenerator(String worldName, String id)
return new IrisChunkGenerator(16); {
return new IrisChunkGenerator(IrisSettings.get().threads);
} }
public static void msg(String string) { public static void msg(String string)
{
lock.lock(); lock.lock();
String msg = ChatColor.GREEN + "[Iris]: " + ChatColor.GRAY + string; String msg = ChatColor.GREEN + "[Iris]: " + ChatColor.GRAY + string;
if (last.equals(msg)) {
lock.unlock();
return;
}
last = msg;
Bukkit.getConsoleSender().sendMessage(msg); Bukkit.getConsoleSender().sendMessage(msg);
lock.unlock(); lock.unlock();
} }
public static void warn(String string) { public static void warn(String string)
{
msg(ChatColor.YELLOW + string); msg(ChatColor.YELLOW + string);
} }
public static void error(String string) { public static void error(String string)
{
msg(ChatColor.RED + string); msg(ChatColor.RED + string);
} }
public static void verbose(String string) { public static void verbose(String string)
{
msg(ChatColor.GRAY + string); msg(ChatColor.GRAY + string);
} }
public static void success(String string) { public static void success(String string)
{
msg(ChatColor.GREEN + string); msg(ChatColor.GREEN + string);
} }
public static void info(String string) { public static void info(String string)
{
msg(ChatColor.WHITE + string); msg(ChatColor.WHITE + string);
} }
public void hit(long hits2) { public void hit(long hits2)
{
hits.put(hits2); hits.put(hits2);
} }
} }

View File

@ -43,12 +43,14 @@ public class IrisDataManager
File packs = this.packs.getName().equals("packs") ? this.packs : dataFolder; File packs = this.packs.getName().equals("packs") ? this.packs : dataFolder;
packs.mkdirs(); packs.mkdirs();
this.regionLoader = new ResourceLoader<>(packs, "regions", "Region", IrisRegion.class); this.regionLoader = new ResourceLoader<>(packs, "regions", "Region", IrisRegion.class);
this.biomeLoader = new ResourceLoader<>(packs, "biomes", "Biome", IrisBiome.class); this.biomeLoader = new ResourceLoader<>(packs, "biomes", "Biome", IrisBiome.class);
this.dimensionLoader = new ResourceLoader<>(packs, "dimensions", "Dimension", IrisDimension.class); this.dimensionLoader = new ResourceLoader<>(packs, "dimensions", "Dimension", IrisDimension.class);
this.structureLoader = new ResourceLoader<>(packs, "structures", "Structure", IrisStructure.class); this.structureLoader = new ResourceLoader<>(packs, "structures", "Structure", IrisStructure.class);
this.generatorLoader = new ResourceLoader<>(packs, "generators", "Generator", IrisGenerator.class); this.generatorLoader = new ResourceLoader<>(packs, "generators", "Generator", IrisGenerator.class);
this.objectLoader = new ObjectResourceLoader(packs, "objects", "Object"); this.objectLoader = new ObjectResourceLoader(packs, "objects", "Object");
if(packs.getName().equals("packs")) if(packs.getName().equals("packs"))
{ {
writeExamples(); writeExamples();
@ -164,4 +166,13 @@ public class IrisDataManager
generatorLoader.preferFolder(name); generatorLoader.preferFolder(name);
structureLoader.preferFolder(name); structureLoader.preferFolder(name);
} }
public void clearLists()
{
biomeLoader.clearList();
regionLoader.clearList();
dimensionLoader.clearList();
generatorLoader.clearList();
structureLoader.clearList();
}
} }

View File

@ -3,19 +3,20 @@ package com.volmit.iris;
import java.io.File; import java.io.File;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import com.volmit.iris.util.ChronoLatch; import com.volmit.iris.util.ChronoLatch;
import com.volmit.iris.util.FileWatcher; import com.volmit.iris.util.FolderWatcher;
import com.volmit.iris.util.KSet;
public class IrisHotloadManager public class IrisHotloadManager
{ {
private ChronoLatch latch; private ChronoLatch latch;
private KSet<FileWatcher> watchers;
private FolderWatcher w;
public IrisHotloadManager() public IrisHotloadManager()
{ {
watchers = new KSet<>(); w = new FolderWatcher(Iris.instance.getDataFolder("packs"));
latch = new ChronoLatch(3000); latch = new ChronoLatch(3000);
} }
@ -33,13 +34,87 @@ public class IrisHotloadManager
try try
{ {
for(FileWatcher i : watchers) if(w.checkModified())
{ {
if(i.checkModified()) for(File i : w.getCreated())
{ {
c++; if(i.isDirectory())
Iris.info("File Modified: " + i.getFile().getPath()); {
continue;
}
if(i.getPath().contains(".git"))
{
continue;
}
if(i.getPath().contains("_docs"))
{
continue;
}
if(i.getName().endsWith(".code-workspace"))
{
continue;
}
modified = true; modified = true;
c++;
Iris.verbose("File Created: " + i.getPath());
}
for(File i : w.getDeleted())
{
if(i.isDirectory())
{
continue;
}
if(i.getPath().contains("_docs"))
{
continue;
}
if(i.getPath().contains(".git"))
{
continue;
}
if(i.getName().endsWith(".code-workspace"))
{
continue;
}
modified = true;
c++;
Iris.verbose("File Deleted: " + i.getPath());
}
for(File i : w.getChanged())
{
if(i.isDirectory())
{
continue;
}
if(i.getPath().contains(".git"))
{
continue;
}
if(i.getPath().contains("_docs"))
{
continue;
}
if(i.getName().endsWith(".code-workspace"))
{
continue;
}
modified = true;
c++;
Iris.verbose("File Modified: " + i.getPath());
} }
} }
} }
@ -51,8 +126,14 @@ public class IrisHotloadManager
if(modified) if(modified)
{ {
watchers.clear(); String m = "Hotloaded " + c + " File" + (c == 1 ? "" : "s");
Iris.success("Hotloading Iris (" + c + " File" + (c == 1 ? "" : "s") + " changed)");
for(Player i : Bukkit.getOnlinePlayers())
{
i.sendMessage(Iris.instance.getTag("Studio") + m);
}
Bukkit.getConsoleSender().sendMessage(Iris.instance.getTag("Studio") + m);
Iris.globaldata.hotloaded(); Iris.globaldata.hotloaded();
ch.onHotloaded(); ch.onHotloaded();
} }
@ -61,6 +142,6 @@ public class IrisHotloadManager
public void track(File file) public void track(File file)
{ {
watchers.add(new FileWatcher(file));
} }
} }

View File

@ -1,14 +1,21 @@
package com.volmit.iris; package com.volmit.iris;
import java.io.File;
import java.io.IOException;
import com.google.gson.Gson;
import com.volmit.iris.util.Desc; import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.IO;
import com.volmit.iris.util.JSONException;
import com.volmit.iris.util.JSONObject;
public class IrisSettings public class IrisSettings
{ {
public static transient IrisSettings settings; public static transient IrisSettings settings;
@DontObfuscate @DontObfuscate
@Desc("Iris generator threads (must be 2 or higher).") @Desc("Iris generator threads (must be 2 or higher). Threads in iris are not a perfect scale for performance as a lot of data has to be shared. 16 Threads is a good rule of thumb. Use 8 threads on a quad core processor.")
public int threads = 16; public int threads = 16;
@DontObfuscate @DontObfuscate
@ -17,14 +24,67 @@ public class IrisSettings
@DontObfuscate @DontObfuscate
@Desc("Compression level (0-9) lower is faster, but is not as good compression. Best results around 3-5") @Desc("Compression level (0-9) lower is faster, but is not as good compression. Best results around 3-5")
public int parallaxCompressionLevel = 3; public int parallaxCompressionLevel = 2;
@DontObfuscate
@Desc("If A is a child of B, and B is a child of A, how deep should iris follow the children in biomes. Lower is faster gen.")
public int maxBiomeChildDepth = 5;
@DontObfuscate
@Desc("When enabled, The cache is shared for all chunks and cleared periodically instead of per chunk. This uses more memory but provides a ~15% speedup.")
public boolean sharedCaching = true;
@DontObfuscate
@Desc("Allows configs to be changed and hotloaded without reloading.")
public boolean hotloading = true;
public static IrisSettings get() public static IrisSettings get()
{ {
if(settings == null) if(settings == null)
{ {
settings = new IrisSettings(); settings = new IrisSettings();
// TODO LOAD
File s = Iris.instance.getDataFile("settings.json");
if(!s.exists())
{
try
{
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
}
catch(JSONException | IOException e)
{
e.printStackTrace();
}
}
else
{
try
{
settings = new Gson().fromJson(IO.readAll(s), IrisSettings.class);
}
catch(JSONException | IOException e)
{
e.printStackTrace();
s.delete();
}
}
if(!s.exists())
{
try
{
IO.writeAll(s, new JSONObject(new Gson().toJson(settings)).toString(4));
}
catch(JSONException | IOException e)
{
e.printStackTrace();
}
}
} }
return settings; return settings;

View File

@ -6,6 +6,7 @@ import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.locks.ReentrantLock;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
@ -56,7 +57,15 @@ import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.MortarSender; import com.volmit.iris.util.MortarSender;
import com.volmit.iris.util.O; import com.volmit.iris.util.O;
import com.volmit.iris.util.RegistryListBiome;
import com.volmit.iris.util.RegistryListDimension;
import com.volmit.iris.util.RegistryListGenerator;
import com.volmit.iris.util.RegistryListObject;
import com.volmit.iris.util.RegistryListRegion;
import com.volmit.iris.util.RegistryListStructure;
import com.volmit.iris.util.Required; import com.volmit.iris.util.Required;
import com.volmit.iris.util.TaskExecutor;
import com.volmit.iris.util.TaskExecutor.TaskGroup;
import lombok.Data; import lombok.Data;
@ -64,6 +73,8 @@ import lombok.Data;
public class ProjectManager public class ProjectManager
{ {
private IrisChunkGenerator currentProject; private IrisChunkGenerator currentProject;
private TaskExecutor tx = new TaskExecutor(8, Thread.MIN_PRIORITY, "Iris Compiler");
private ReentrantLock lock = new ReentrantLock();
public ProjectManager() public ProjectManager()
{ {
@ -522,7 +533,7 @@ public class ProjectManager
IO.writeAll(Iris.instance.getDataFile("packs", dimension.getLoadKey(), "biomes", exampleShore1.getLoadKey() + ".json"), new JSONObject(new Gson().toJson(exampleShore1)).toString(4)); IO.writeAll(Iris.instance.getDataFile("packs", dimension.getLoadKey(), "biomes", exampleShore1.getLoadKey() + ".json"), new JSONObject(new Gson().toJson(exampleShore1)).toString(4));
IO.writeAll(Iris.instance.getDataFile("packs", dimension.getLoadKey(), "biomes", exampleOcean1.getLoadKey() + ".json"), new JSONObject(new Gson().toJson(exampleOcean1)).toString(4)); IO.writeAll(Iris.instance.getDataFile("packs", dimension.getLoadKey(), "biomes", exampleOcean1.getLoadKey() + ".json"), new JSONObject(new Gson().toJson(exampleOcean1)).toString(4));
IO.writeAll(Iris.instance.getDataFile("packs", dimension.getLoadKey(), "generators", gen.getLoadKey() + ".json"), new JSONObject(new Gson().toJson(gen)).toString(4)); IO.writeAll(Iris.instance.getDataFile("packs", dimension.getLoadKey(), "generators", gen.getLoadKey() + ".json"), new JSONObject(new Gson().toJson(gen)).toString(4));
IO.writeAll(Iris.instance.getDataFile("packs", dimension.getLoadKey(), dimension.getLoadKey() + ".code-workspace"), ws.toString(4)); IO.writeAll(Iris.instance.getDataFile("packs", dimension.getLoadKey(), dimension.getLoadKey() + ".code-workspace"), ws.toString(0));
Iris.proj.open(sender, dimension.getName()); Iris.proj.open(sender, dimension.getName());
} }
@ -535,6 +546,7 @@ public class ProjectManager
private JSONObject newWorkspaceConfig() private JSONObject newWorkspaceConfig()
{ {
Iris.globaldata.clearLists();
JSONObject ws = new JSONObject(); JSONObject ws = new JSONObject();
JSONArray folders = new JSONArray(); JSONArray folders = new JSONArray();
JSONObject folder = new JSONObject(); JSONObject folder = new JSONObject();
@ -549,7 +561,26 @@ public class ProjectManager
settings.put("workbench.tree.indent", 24); settings.put("workbench.tree.indent", 24);
settings.put("files.autoSave", "onFocusChange"); settings.put("files.autoSave", "onFocusChange");
JSONArray schemas = buildSchemas(); JSONObject jc = new JSONObject();
jc.put("editor.autoIndent", "brackets");
jc.put("editor.acceptSuggestionOnEnter", "smart");
jc.put("editor.cursorSmoothCaretAnimation", true);
jc.put("editor.dragAndDrop", false);
jc.put("files.trimTrailingWhitespace", true);
jc.put("diffEditor.ignoreTrimWhitespace", true);
jc.put("files.trimFinalNewlines", true);
jc.put("editor.suggest.showKeywords", false);
jc.put("editor.suggest.showSnippets", false);
jc.put("editor.suggest.showWords", false);
jc.put("json.maxItemsComputed", 50000);
JSONObject st = new JSONObject();
st.put("strings", true);
jc.put("editor.quickSuggestions", st);
jc.put("editor.suggest.insertMode", "replace");
settings.put("[json]", jc);
settings.put("json.maxItemsComputed", 50000);
JSONArray schemas = buildSchemas(Iris.globaldata);
settings.put("json.schemas", schemas); settings.put("json.schemas", schemas);
ws.put("settings", settings); ws.put("settings", settings);
@ -565,29 +596,11 @@ public class ProjectManager
{ {
try try
{ {
Iris.info("Updating Workspace: " + ws.getPath());
J.attemptAsync(() -> writeDocs(ws.getParentFile())); J.attemptAsync(() -> writeDocs(ws.getParentFile()));
JSONObject j = new JSONObject(IO.readAll(ws)); JSONObject j = newWorkspaceConfig();
JSONObject s = j.getJSONObject("settings");
JSONObject jc = new JSONObject();
jc.put("editor.autoIndent", "brackets");
jc.put("editor.acceptSuggestionOnEnter", "smart");
jc.put("editor.cursorSmoothCaretAnimation", true);
jc.put("editor.dragAndDrop", false);
jc.put("files.trimTrailingWhitespace", true);
jc.put("diffEditor.ignoreTrimWhitespace", true);
jc.put("files.trimFinalNewlines", true);
jc.put("editor.suggest.showKeywords", false);
jc.put("editor.suggest.showSnippets", false);
jc.put("editor.suggest.showWords", false);
JSONObject st = new JSONObject();
st.put("strings", true);
jc.put("editor.quickSuggestions", st);
jc.put("editor.suggest.insertMode", "replace");
s.put("[json]", jc);
s.put("json.schemas", buildSchemas());
j.put("settings", s);
IO.writeAll(ws, j.toString(4)); IO.writeAll(ws, j.toString(4));
Iris.info("Updating Project " + ws.getAbsolutePath()); Iris.info("Updated Workspace: " + ws.getPath());
} }
catch(Throwable e) catch(Throwable e)
@ -606,30 +619,43 @@ public class ProjectManager
} }
} }
private JSONArray buildSchemas() private void ex(JSONArray schemas, Class<?> c, IrisDataManager dat, String v)
{
JSONObject o = getSchemaEntry(c, dat, v);
lock.lock();
schemas.put(o);
lock.unlock();
}
private JSONArray buildSchemas(IrisDataManager dat)
{ {
JSONArray schemas = new JSONArray(); JSONArray schemas = new JSONArray();
schemas.put(getSchemaEntry(IrisDimension.class, "/dimensions/*.json")); TaskGroup g = tx.startWork();
schemas.put(getSchemaEntry(IrisBiome.class, "/biomes/*.json")); g.queue(() -> ex(schemas, IrisDimension.class, dat, "/dimensions/*.json"));
schemas.put(getSchemaEntry(IrisRegion.class, "/regions/*.json")); g.queue(() -> ex(schemas, IrisBiome.class, dat, "/biomes/*.json"));
schemas.put(getSchemaEntry(IrisGenerator.class, "/generators/*.json")); g.queue(() -> ex(schemas, IrisRegion.class, dat, "/regions/*.json"));
schemas.put(getSchemaEntry(IrisStructure.class, "/structures/*.json")); g.queue(() -> ex(schemas, IrisGenerator.class, dat, "/generators/*.json"));
g.queue(() -> ex(schemas, IrisStructure.class, dat, "/structures/*.json"));
g.execute();
return schemas; return schemas;
} }
public JSONObject getSchemaEntry(Class<?> i, String... fileMatch) public JSONObject getSchemaEntry(Class<?> i, IrisDataManager dat, String... fileMatch)
{ {
Iris.verbose("Processing Folder " + i.getSimpleName() + " " + fileMatch[0]);
JSONObject o = new JSONObject(); JSONObject o = new JSONObject();
o.put("fileMatch", new JSONArray(fileMatch)); o.put("fileMatch", new JSONArray(fileMatch));
o.put("schema", getSchemaFor(i)); o.put("schema", getSchemaFor(i, dat));
return o; return o;
} }
public JSONObject getSchemaFor(Class<?> i) public JSONObject getSchemaFor(Class<?> i, IrisDataManager dat)
{ {
Iris.verbose("Processing " + i.getSimpleName());
KMap<String, JSONObject> def = new KMap<>(); KMap<String, JSONObject> def = new KMap<>();
JSONObject s = getSchemaFor(i, 7, def); JSONObject s = getSchemaFor(i, 7, def, dat);
JSONObject defx = new JSONObject(); JSONObject defx = new JSONObject();
for(String v : def.k()) for(String v : def.k())
{ {
@ -641,7 +667,7 @@ public class ProjectManager
return s; return s;
} }
public JSONObject getSchemaFor(Class<?> i, int step, KMap<String, JSONObject> def) public JSONObject getSchemaFor(Class<?> i, int step, KMap<String, JSONObject> def, IrisDataManager dat)
{ {
if(step <= 0) if(step <= 0)
{ {
@ -670,7 +696,6 @@ public class ProjectManager
JSONObject prop = new JSONObject(); JSONObject prop = new JSONObject();
if(k.isAnnotationPresent(Desc.class)) if(k.isAnnotationPresent(Desc.class))
{ {
if(k.isAnnotationPresent(DependsOn.class)) if(k.isAnnotationPresent(DependsOn.class))
{ {
deps.put(k.getName(), new JSONArray(k.getDeclaredAnnotation(DependsOn.class).value())); deps.put(k.getName(), new JSONArray(k.getDeclaredAnnotation(DependsOn.class).value()));
@ -726,11 +751,36 @@ public class ProjectManager
{ {
prop.put("maxLength", (int) k.getDeclaredAnnotation(MaxNumber.class).value()); prop.put("maxLength", (int) k.getDeclaredAnnotation(MaxNumber.class).value());
} }
}
if(k.getType().equals(String.class)) if(k.isAnnotationPresent(RegistryListBiome.class))
{ {
tp = "string"; prop.put("enum", new JSONArray(getBiomeList(dat)));
}
if(k.isAnnotationPresent(RegistryListDimension.class))
{
prop.put("enum", new JSONArray(getDimensionList(dat)));
}
if(k.isAnnotationPresent(RegistryListGenerator.class))
{
prop.put("enum", new JSONArray(getGeneratorList(dat)));
}
if(k.isAnnotationPresent(RegistryListObject.class))
{
prop.put("enum", new JSONArray(getObjectList(dat)));
}
if(k.isAnnotationPresent(RegistryListRegion.class))
{
prop.put("enum", new JSONArray(getRegionList(dat)));
}
if(k.isAnnotationPresent(RegistryListStructure.class))
{
prop.put("enum", new JSONArray(getStructureList(dat)));
}
} }
if(k.getType().isEnum()) if(k.getType().isEnum())
@ -774,7 +824,7 @@ public class ProjectManager
if(k.getType().isAnnotationPresent(Desc.class)) if(k.getType().isAnnotationPresent(Desc.class))
{ {
prop.put("additionalProperties", false); prop.put("additionalProperties", false);
prop.put("properties", getSchemaFor(k.getType(), step - 1, def).getJSONObject("properties")); prop.put("properties", getSchemaFor(k.getType(), step - 1, def, Iris.globaldata).getJSONObject("properties"));
} }
} }
@ -782,6 +832,11 @@ public class ProjectManager
{ {
ArrayType t = k.getDeclaredAnnotation(ArrayType.class); ArrayType t = k.getDeclaredAnnotation(ArrayType.class);
if(t == null)
{
Iris.warn("Expected " + ArrayType.class.getSimpleName() + " in " + k.getName() + " in " + i.getSimpleName());
}
if(t.min() > 0) if(t.min() > 0)
{ {
prop.put("minItems", t.min()); prop.put("minItems", t.min());
@ -809,6 +864,136 @@ public class ProjectManager
if(t.type().equals(String.class)) if(t.type().equals(String.class))
{ {
tx = "string"; tx = "string";
if(k.isAnnotationPresent(MinNumber.class))
{
prop.put("minLength", (int) k.getDeclaredAnnotation(MinNumber.class).value());
}
if(k.isAnnotationPresent(MaxNumber.class))
{
prop.put("maxLength", (int) k.getDeclaredAnnotation(MaxNumber.class).value());
}
if(k.isAnnotationPresent(RegistryListBiome.class))
{
String name = "enbiom" + t.type().getSimpleName().toLowerCase();
if(!def.containsKey(name))
{
JSONObject deff = new JSONObject();
deff.put("type", tx);
deff.put("enum", new JSONArray(getBiomeList(dat)));
def.put(name, deff);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + name);
prop.put("items", items);
prop.put("description", k.getAnnotation(Desc.class).value());
prop.put("type", tp);
properties.put(k.getName(), prop);
continue;
}
if(k.isAnnotationPresent(RegistryListDimension.class))
{
String name = "endim" + t.type().getSimpleName().toLowerCase();
if(!def.containsKey(name))
{
JSONObject deff = new JSONObject();
deff.put("type", tx);
deff.put("enum", new JSONArray(getDimensionList(dat)));
def.put(name, deff);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + name);
prop.put("items", items);
prop.put("description", k.getAnnotation(Desc.class).value());
prop.put("type", tp);
properties.put(k.getName(), prop);
continue;
}
if(k.isAnnotationPresent(RegistryListGenerator.class))
{
String name = "engen" + t.type().getSimpleName().toLowerCase();
if(!def.containsKey(name))
{
JSONObject deff = new JSONObject();
deff.put("type", tx);
deff.put("enum", new JSONArray(getGeneratorList(dat)));
def.put(name, deff);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + name);
prop.put("items", items);
prop.put("description", k.getAnnotation(Desc.class).value());
prop.put("type", tp);
properties.put(k.getName(), prop);
continue;
}
if(k.isAnnotationPresent(RegistryListObject.class))
{
String name = "enobj" + t.type().getSimpleName().toLowerCase();
if(!def.containsKey(name))
{
JSONObject deff = new JSONObject();
deff.put("type", tx);
deff.put("enum", new JSONArray(getObjectList(dat)));
def.put(name, deff);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + name);
prop.put("items", items);
prop.put("description", k.getAnnotation(Desc.class).value());
prop.put("type", tp);
properties.put(k.getName(), prop);
continue;
}
if(k.isAnnotationPresent(RegistryListRegion.class))
{
String name = "enreg" + t.type().getSimpleName().toLowerCase();
if(!def.containsKey(name))
{
JSONObject deff = new JSONObject();
deff.put("type", tx);
deff.put("enum", new JSONArray(getRegionList(dat)));
def.put(name, deff);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + name);
prop.put("items", items);
prop.put("description", k.getAnnotation(Desc.class).value());
prop.put("type", tp);
properties.put(k.getName(), prop);
continue;
}
if(k.isAnnotationPresent(RegistryListStructure.class))
{
String name = "enstruct" + t.type().getSimpleName().toLowerCase();
if(!def.containsKey(name))
{
JSONObject deff = new JSONObject();
deff.put("type", tx);
deff.put("enum", new JSONArray(getStructureList(dat)));
def.put(name, deff);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + name);
prop.put("items", items);
prop.put("description", k.getAnnotation(Desc.class).value());
prop.put("type", tp);
properties.put(k.getName(), prop);
continue;
}
} }
if(t.type().isEnum()) if(t.type().isEnum())
@ -834,6 +1019,10 @@ public class ProjectManager
JSONObject items = new JSONObject(); JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + name); items.put("$ref", "#/definitions/" + name);
prop.put("items", items); prop.put("items", items);
prop.put("description", k.getAnnotation(Desc.class).value());
prop.put("type", tp);
properties.put(k.getName(), prop);
continue;
} }
if(t.type().isEnum()) if(t.type().isEnum())
@ -857,7 +1046,7 @@ public class ProjectManager
if(!def.containsKey(name)) if(!def.containsKey(name))
{ {
JSONObject deff = new JSONObject(); JSONObject deff = new JSONObject();
JSONObject scv = getSchemaFor(t.type(), step - 1, def); JSONObject scv = getSchemaFor(t.type(), step - 1, def, Iris.globaldata);
deff.put("type", tx); deff.put("type", tx);
deff.put("description", t.type().getDeclaredAnnotation(Desc.class).value()); deff.put("description", t.type().getDeclaredAnnotation(Desc.class).value());
deff.put("additionalProperties", false); deff.put("additionalProperties", false);
@ -888,7 +1077,7 @@ public class ProjectManager
if(tp.getClass().isAnnotationPresent(Desc.class)) if(tp.getClass().isAnnotationPresent(Desc.class))
{ {
prop.put("properties", getSchemaFor(tp.getClass(), step - 1, def).getJSONObject("properties")); prop.put("properties", getSchemaFor(tp.getClass(), step - 1, def, Iris.globaldata).getJSONObject("properties"));
} }
} }
@ -907,6 +1096,36 @@ public class ProjectManager
return schema; return schema;
} }
private String[] getBiomeList(IrisDataManager data)
{
return data.getBiomeLoader().getPossibleKeys();
}
private String[] getDimensionList(IrisDataManager data)
{
return data.getDimensionLoader().getPossibleKeys();
}
private String[] getRegionList(IrisDataManager data)
{
return data.getRegionLoader().getPossibleKeys();
}
private String[] getObjectList(IrisDataManager data)
{
return data.getObjectLoader().getPossibleKeys();
}
private String[] getStructureList(IrisDataManager data)
{
return data.getStructureLoader().getPossibleKeys();
}
private String[] getGeneratorList(IrisDataManager data)
{
return data.getGeneratorLoader().getPossibleKeys();
}
public KList<String> analyzeFolder(File folder, String fn, Object t) public KList<String> analyzeFolder(File folder, String fn, Object t)
{ {
KList<String> a = new KList<String>(); KList<String> a = new KList<String>();
@ -941,6 +1160,7 @@ public class ProjectManager
try try
{ {
Iris.info("Reading " + i.getPath());
j = new JSONObject(IO.readAll(i)); j = new JSONObject(IO.readAll(i));
o = new Gson().fromJson(j.toString(), t.getClass()); o = new Gson().fromJson(j.toString(), t.getClass());
a.addAll(analyze(o, i)); a.addAll(analyze(o, i));

View File

@ -1,6 +1,7 @@
package com.volmit.iris.gen; package com.volmit.iris.gen;
import java.awt.Color; import java.awt.Color;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -12,6 +13,7 @@ import org.bukkit.entity.Player;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.IrisContext; import com.volmit.iris.IrisContext;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.gen.atomics.AtomicRegionData; import com.volmit.iris.gen.atomics.AtomicRegionData;
import com.volmit.iris.noise.CNG; import com.volmit.iris.noise.CNG;
import com.volmit.iris.object.IrisBiome; import com.volmit.iris.object.IrisBiome;
@ -189,18 +191,29 @@ public class IrisChunkGenerator extends CeilingChunkGenerator implements IrisCon
@Override @Override
public void onHotloaded() public void onHotloaded()
{ {
if(!IrisSettings.get().hotloading)
{
return;
}
if(!isHotloadable()) if(!isHotloadable())
{ {
Iris.warn("Hotload skipped (During Chunk Gen). Retrying.");
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, this::onHotloaded); Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, this::onHotloaded);
return; return;
} }
CNG.creates = 0; CNG.creates = 0;
getData().dump(); getData().dump();
getCache().drop();
Iris.proj.updateWorkspace(getWorkspaceFile());
onHotload(); onHotload();
} }
private File getWorkspaceFile()
{
return new File(getDimension().getLoadFile().getParent(), getDimension().getLoadKey() + ".code-workspace");
}
public long guessMemoryUsage() public long guessMemoryUsage()
{ {
long bytes = 1024 * 1024 * (8 + (getThreads() / 3)); long bytes = 1024 * 1024 * (8 + (getThreads() / 3));
@ -215,6 +228,7 @@ public class IrisChunkGenerator extends CeilingChunkGenerator implements IrisCon
bytes += i.guessMemoryUsage(); bytes += i.guessMemoryUsage();
} }
bytes += getCache().getSize() * 65;
bytes += parallaxMap.getLoadedChunks().size() * 256 * 4 * 460; bytes += parallaxMap.getLoadedChunks().size() * 256 * 4 * 460;
bytes += ceilingParallaxMap.getLoadedChunks().size() * 256 * 4 * 460; bytes += ceilingParallaxMap.getLoadedChunks().size() * 256 * 4 * 460;
bytes += getSliverBuffer() * 220; bytes += getSliverBuffer() * 220;

View File

@ -33,7 +33,8 @@ import lombok.EqualsAndHashCode;
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator implements IObjectPlacer { public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator implements IObjectPlacer
{
protected KMap<ChunkPosition, AtomicSliver> sliverCache; protected KMap<ChunkPosition, AtomicSliver> sliverCache;
protected AtomicWorldData parallaxMap; protected AtomicWorldData parallaxMap;
protected KMap<ChunkPosition, AtomicSliver> ceilingSliverCache; protected KMap<ChunkPosition, AtomicSliver> ceilingSliverCache;
@ -43,7 +44,8 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
private IrisLock lockq = new IrisLock("ParallaxQueueLock"); private IrisLock lockq = new IrisLock("ParallaxQueueLock");
private int sliverBuffer; private int sliverBuffer;
public ParallaxChunkGenerator(String dimensionName, int threads) { public ParallaxChunkGenerator(String dimensionName, int threads)
{
super(dimensionName, threads); super(dimensionName, threads);
sliverCache = new KMap<>(); sliverCache = new KMap<>();
ceilingSliverCache = new KMap<>(); ceilingSliverCache = new KMap<>();
@ -51,41 +53,49 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
masterLock = new MasterLock(); masterLock = new MasterLock();
} }
public void onInit(World world, RNG rng) { public void onInit(World world, RNG rng)
{
super.onInit(world, rng); super.onInit(world, rng);
parallaxMap = new AtomicWorldData(world, "floor"); parallaxMap = new AtomicWorldData(world, "floor");
ceilingParallaxMap = new AtomicWorldData(world, "ceiling"); ceilingParallaxMap = new AtomicWorldData(world, "ceiling");
} }
protected KMap<ChunkPosition, AtomicSliver> getSliverCache() { protected KMap<ChunkPosition, AtomicSliver> getSliverCache()
{
return getDimension().isInverted() ? ceilingSliverCache : sliverCache; return getDimension().isInverted() ? ceilingSliverCache : sliverCache;
} }
protected void onClose() { protected void onClose()
{
super.onClose(); super.onClose();
try { try
{
parallaxMap.unloadAll(true); parallaxMap.unloadAll(true);
ceilingParallaxMap.unloadAll(true); ceilingParallaxMap.unloadAll(true);
} }
catch (IOException e) { catch(IOException e)
{
e.printStackTrace(); e.printStackTrace();
} }
} }
@Override @Override
public int getHighest(int x, int z) { public int getHighest(int x, int z)
{
return getHighest(x, z, false); return getHighest(x, z, false);
} }
@Override @Override
public int getHighest(int x, int z, boolean ignoreFluid) { public int getHighest(int x, int z, boolean ignoreFluid)
int h = (int) Math {
.round(ignoreFluid ? getTerrainHeight(x, z) : getTerrainWaterHeight(x, z)); int h = (int) Math.round(ignoreFluid ? getTerrainHeight(x, z) : getTerrainWaterHeight(x, z));
if (getDimension().isCarving() && h >= getDimension().getCarvingMin()) { if(getDimension().isCarving() && h >= getDimension().getCarvingMin())
while (getGlCarve().isCarved(x, h, z)) { {
while(getGlCarve().isCarved(x, h, z))
{
h--; h--;
} }
@ -96,24 +106,28 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
} }
@Override @Override
public void set(int x, int y, int z, BlockData d) { public void set(int x, int y, int z, BlockData d)
{
getMasterLock().lock((x >> 4) + "." + (z >> 4)); getMasterLock().lock((x >> 4) + "." + (z >> 4));
getParallaxSliver(x, z).set(y, d); getParallaxSliver(x, z).set(y, d);
getMasterLock().unlock((x >> 4) + "." + (z >> 4)); getMasterLock().unlock((x >> 4) + "." + (z >> 4));
} }
@Override @Override
public BlockData get(int x, int y, int z) { public BlockData get(int x, int y, int z)
{
BlockData b = sampleSliver(x, z).getBlock().get(y); BlockData b = sampleSliver(x, z).getBlock().get(y);
return b == null ? AIR : b; return b == null ? AIR : b;
} }
@Override @Override
public boolean isSolid(int x, int y, int z) { public boolean isSolid(int x, int y, int z)
{
return get(x, y, z).getMaterial().isSolid(); return get(x, y, z).getMaterial().isSolid();
} }
public AtomicSliver getParallaxSliver(int wx, int wz) { public AtomicSliver getParallaxSliver(int wx, int wz)
{
getMasterLock().lock("gpc"); getMasterLock().lock("gpc");
getMasterLock().lock((wx >> 4) + "." + (wz >> 4)); getMasterLock().lock((wx >> 4) + "." + (wz >> 4));
AtomicSliverMap map = getParallaxChunk(wx >> 4, wz >> 4); AtomicSliverMap map = getParallaxChunk(wx >> 4, wz >> 4);
@ -124,24 +138,30 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
return sliver; return sliver;
} }
public boolean isParallaxGenerated(int x, int z) { public boolean isParallaxGenerated(int x, int z)
{
return getParallaxChunk(x, z).isParallaxGenerated(); return getParallaxChunk(x, z).isParallaxGenerated();
} }
public boolean isWorldGenerated(int x, int z) { public boolean isWorldGenerated(int x, int z)
{
return getParallaxChunk(x, z).isWorldGenerated(); return getParallaxChunk(x, z).isWorldGenerated();
} }
public AtomicWorldData getParallaxMap() { public AtomicWorldData getParallaxMap()
{
return getDimension().isInverted() ? ceilingParallaxMap : parallaxMap; return getDimension().isInverted() ? ceilingParallaxMap : parallaxMap;
} }
public AtomicSliverMap getParallaxChunk(int x, int z) { public AtomicSliverMap getParallaxChunk(int x, int z)
try { {
try
{
return getParallaxMap().loadChunk(x, z); return getParallaxMap().loadChunk(x, z);
} }
catch (IOException e) { catch(IOException e)
{
fail(e); fail(e);
} }
@ -149,16 +169,18 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
} }
@Override @Override
protected void onPostGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid, HeightMap height, protected void onPostGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid, HeightMap height, BiomeMap biomeMap)
BiomeMap biomeMap) { {
if (getSliverCache().size() > 20000) { if(getSliverCache().size() > 20000)
{
getSliverCache().clear(); getSliverCache().clear();
} }
super.onPostGenerate(random, x, z, data, grid, height, biomeMap); super.onPostGenerate(random, x, z, data, grid, height, biomeMap);
PrecisionStopwatch p = PrecisionStopwatch.start(); PrecisionStopwatch p = PrecisionStopwatch.start();
if (getDimension().isPlaceObjects()) { if(getDimension().isPlaceObjects())
{
onGenerateParallax(random, x, z); onGenerateParallax(random, x, z);
getParallaxChunk(x, z).inject(data); getParallaxChunk(x, z).inject(data);
setSliverBuffer(getSliverCache().size()); setSliverBuffer(getSliverCache().size());
@ -173,50 +195,58 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
getData().getObjectLoader().clean(); getData().getObjectLoader().clean();
} }
public IrisStructureResult getStructure(int x, int y, int z) { public IrisStructureResult getStructure(int x, int y, int z)
{
IrisBiome b = sampleTrueBiome(x, z).getBiome(); IrisBiome b = sampleTrueBiome(x, z).getBiome();
IrisRegion r = sampleRegion(x, z); IrisRegion r = sampleRegion(x, z);
RNG ro = getMasterRandom().nextParallelRNG(496888 + (x >> 4) + (z >> 4)); RNG ro = getMasterRandom().nextParallelRNG(496888 + (x >> 4) + (z >> 4));
int h = (int) Math.round(getTerrainHeight(x, z)); int h = (int) Math.round(getTerrainHeight(x, z));
KList<IrisStructurePlacement> p = new KList<>(); KList<IrisStructurePlacement> p = new KList<>();
for (IrisStructurePlacement i : r.getStructures()) { for(IrisStructurePlacement i : r.getStructures())
if (i.getHeight() > -1) { {
if (y >= i.getHeight() && y <= i.getHeight() if(i.getHeight() > -1)
+ (i.getStructure(this).getGridHeight() * i.getStructure(this).getMaxLayers())) { {
if(y >= i.getHeight() && y <= i.getHeight() + (i.getStructure(this).getGridHeight() * i.getStructure(this).getMaxLayers()))
{
p.add(i); p.add(i);
} }
} }
else if (y >= h && y <= i.getStructure(this).getGridHeight() + h) { else if(y >= h && y <= i.getStructure(this).getGridHeight() + h)
{
p.add(i); p.add(i);
} }
} }
for (IrisStructurePlacement i : b.getStructures()) { for(IrisStructurePlacement i : b.getStructures())
if (i.getHeight() > -1) { {
if (y >= i.getHeight() && y <= i.getHeight() if(i.getHeight() > -1)
+ (i.getStructure(this).getGridHeight() * i.getStructure(this).getMaxLayers())) { {
if(y >= i.getHeight() && y <= i.getHeight() + (i.getStructure(this).getGridHeight() * i.getStructure(this).getMaxLayers()))
{
p.add(i); p.add(i);
} }
} }
else if (y >= h && y <= i.getStructure(this).getGridHeight() + h) { else if(y >= h && y <= i.getStructure(this).getGridHeight() + h)
{
p.add(i); p.add(i);
} }
} }
for (IrisStructurePlacement i : p) { for(IrisStructurePlacement i : p)
if (!i.hasStructure(ro, x, y, z)) { {
if(!i.hasStructure(ro, x, y, z))
{
continue; continue;
} }
int hv = (i.getHeight() == -1 ? 0 : i.getHeight()) int hv = (i.getHeight() == -1 ? 0 : i.getHeight()) + (Math.floorDiv(y, i.getStructure(this).getGridHeight()) * i.getStructure(this).getGridHeight());
+ (Math.floorDiv(y, i.getStructure(this).getGridHeight()) * i.getStructure(this).getGridHeight()); TileResult tile = i.getStructure(this).getTile(ro, Math.floorDiv(i.gridSize(this), x) * i.gridSize(this), hv, Math.floorDiv(i.gridSize(this), z) * i.gridSize(this));
TileResult tile = i.getStructure(this).getTile(ro, Math.floorDiv(i.gridSize(this), x) * i.gridSize(this),
hv, Math.floorDiv(i.gridSize(this), z) * i.gridSize(this));
if (tile != null && tile.getTile() != null) { if(tile != null && tile.getTile() != null)
{
return new IrisStructureResult(tile.getTile(), i.getStructure(this)); return new IrisStructureResult(tile.getTile(), i.getStructure(this));
} }
} }
@ -224,52 +254,58 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
return null; return null;
} }
protected void onGenerateParallax(RNG random, int x, int z) { protected void onGenerateParallax(RNG random, int x, int z)
{
String key = "par." + x + "." + "z"; String key = "par." + x + "." + "z";
ChunkPosition rad = getDimension().getParallaxSize(this); ChunkPosition rad = getDimension().getParallaxSize(this);
KList<NastyRunnable> q = new KList<>(); KList<NastyRunnable> q = new KList<>();
for (int ii = x - (rad.getX() / 2); ii <= x + (rad.getX() / 2); ii++) { for(int ii = x - (rad.getX() / 2); ii <= x + (rad.getX() / 2); ii++)
{
int i = ii; int i = ii;
for (int jj = z - (rad.getZ() / 2); jj <= z + (rad.getZ() / 2); jj++) { for(int jj = z - (rad.getZ() / 2); jj <= z + (rad.getZ() / 2); jj++)
{
int j = jj; int j = jj;
if (isParallaxGenerated(ii, jj)) { if(isParallaxGenerated(ii, jj))
{
continue; continue;
} }
if (isWorldGenerated(ii, jj)) { if(isWorldGenerated(ii, jj))
{
continue; continue;
} }
getAccelerant().queue(key, () -> { getAccelerant().queue(key, () ->
{
IrisBiome b = sampleTrueBiome((i * 16) + 7, (j * 16) + 7).getBiome(); IrisBiome b = sampleTrueBiome((i * 16) + 7, (j * 16) + 7).getBiome();
RNG ro = getMasterRandom().nextParallelRNG(496888 + i + j); RNG ro = getMasterRandom().nextParallelRNG(496888 + i + j);
int g = 1; int g = 1;
searching: for (IrisBiomeMutation k : getDimension().getMutations()) { searching: for(IrisBiomeMutation k : getDimension().getMutations())
for (int l = 0; l < k.getChecks(); l++) { {
IrisBiome sa = sampleTrueBiome( for(int l = 0; l < k.getChecks(); l++)
((i * 16) + ro.nextInt(16)) + ro.i(-k.getRadius(), k.getRadius()), {
((j * 16) + ro.nextInt(16)) + ro.i(-k.getRadius(), k.getRadius())).getBiome(); IrisBiome sa = sampleTrueBiome(((i * 16) + ro.nextInt(16)) + ro.i(-k.getRadius(), k.getRadius()), ((j * 16) + ro.nextInt(16)) + ro.i(-k.getRadius(), k.getRadius())).getBiome();
IrisBiome sb = sampleTrueBiome( IrisBiome sb = sampleTrueBiome(((i * 16) + ro.nextInt(16)) + ro.i(-k.getRadius(), k.getRadius()), ((j * 16) + ro.nextInt(16)) + ro.i(-k.getRadius(), k.getRadius())).getBiome();
((i * 16) + ro.nextInt(16)) + ro.i(-k.getRadius(), k.getRadius()),
((j * 16) + ro.nextInt(16)) + ro.i(-k.getRadius(), k.getRadius())).getBiome();
if (sa.getLoadKey().equals(sb.getLoadKey())) { if(sa.getLoadKey().equals(sb.getLoadKey()))
{
continue; continue;
} }
if (k.getRealSideA(this).contains(sa.getLoadKey()) if(k.getRealSideA(this).contains(sa.getLoadKey()) && k.getRealSideB(this).contains(sb.getLoadKey()))
&& k.getRealSideB(this).contains(sb.getLoadKey())) { {
for (IrisObjectPlacement m : k.getObjects()) { for(IrisObjectPlacement m : k.getObjects())
{
int gg = g++; int gg = g++;
lockq.lock(); lockq.lock();
q.add(() -> { q.add(() ->
placeObject(m, i, j, random.nextParallelRNG( {
(34 * ((i * 30) + (j * 30) + gg) * i * j) + i - j + 1569962)); placeObject(m, i, j, random.nextParallelRNG((34 * ((i * 30) + (j * 30) + gg) * i * j) + i - j + 1569962));
}); });
lockq.unlock(); lockq.unlock();
} }
@ -281,52 +317,61 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
IrisRegion r = sampleRegion((i * 16) + 7, (j * 16) + 7); IrisRegion r = sampleRegion((i * 16) + 7, (j * 16) + 7);
for (IrisStructurePlacement k : r.getStructures()) { for(IrisStructurePlacement k : r.getStructures())
{
lockq.lock(); lockq.lock();
q.add(() -> { q.add(() ->
{
k.place(this, random.nextParallelRNG(2228), i, j); k.place(this, random.nextParallelRNG(2228), i, j);
}); });
lockq.unlock(); lockq.unlock();
} }
for (IrisStructurePlacement k : b.getStructures()) { for(IrisStructurePlacement k : b.getStructures())
{
lockq.lock(); lockq.lock();
q.add(() -> { q.add(() ->
{
k.place(this, random.nextParallelRNG(-22228), i, j); k.place(this, random.nextParallelRNG(-22228), i, j);
}); });
lockq.unlock(); lockq.unlock();
} }
for (IrisObjectPlacement k : b.getObjects()) { for(IrisObjectPlacement k : b.getObjects())
{
int gg = g++; int gg = g++;
lockq.lock(); lockq.lock();
q.add(() -> { q.add(() ->
placeObject(k, i, j, random {
.nextParallelRNG((34 * ((i * 30) + (j * 30) + gg) * i * j) + i - j + 3569222)); placeObject(k, i, j, random.nextParallelRNG((34 * ((i * 30) + (j * 30) + gg) * i * j) + i - j + 3569222));
}); });
lockq.unlock(); lockq.unlock();
} }
if (getDimension().isCaves()) { if(getDimension().isCaves())
{
int bx = (i * 16) + ro.nextInt(16); int bx = (i * 16) + ro.nextInt(16);
int bz = (j * 16) + ro.nextInt(16); int bz = (j * 16) + ro.nextInt(16);
IrisBiome biome = sampleCaveBiome(bx, bz).getBiome(); IrisBiome biome = sampleCaveBiome(bx, bz).getBiome();
if (biome == null) { if(biome == null)
{
return; return;
} }
if (biome.getObjects().isEmpty()) { if(biome.getObjects().isEmpty())
{
return; return;
} }
for (IrisObjectPlacement k : biome.getObjects()) { for(IrisObjectPlacement k : biome.getObjects())
{
int gg = g++; int gg = g++;
lockq.lock(); lockq.lock();
q.add(() -> { q.add(() ->
placeCaveObject(k, i, j, random {
.nextParallelRNG((34 * ((i * 30) + (j * 30) + gg) * i * j) + i - j + 1869322)); placeCaveObject(k, i, j, random.nextParallelRNG((34 * ((i * 30) + (j * 30) + gg) * i * j) + i - j + 1869322));
}); });
lockq.unlock(); lockq.unlock();
} }
@ -340,7 +385,8 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
getAccelerant().waitFor(key); getAccelerant().waitFor(key);
lockq.lock(); lockq.lock();
for (NastyRunnable i : q) { for(NastyRunnable i : q)
{
getAccelerant().queue(key + "-obj", i); getAccelerant().queue(key + "-obj", i);
} }
lockq.unlock(); lockq.unlock();
@ -348,34 +394,39 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
getAccelerant().waitFor(key + "-obj"); getAccelerant().waitFor(key + "-obj");
} }
public void placeObject(IrisObjectPlacement o, int x, int z, RNG rng) { public void placeObject(IrisObjectPlacement o, int x, int z, RNG rng)
for (int i = 0; i < o.getTriesForChunk(rng); i++) { {
for(int i = 0; i < o.getTriesForChunk(rng); i++)
{
rng = rng.nextParallelRNG((i * 3 + 8) - 23040); rng = rng.nextParallelRNG((i * 3 + 8) - 23040);
o.getSchematic(this, rng).place((x * 16) + rng.nextInt(16), (z * 16) + rng.nextInt(16), this, o, rng); o.getSchematic(this, rng).place((x * 16) + rng.nextInt(16), (z * 16) + rng.nextInt(16), this, o, rng);
} }
} }
public void placeCaveObject(IrisObjectPlacement o, int x, int z, RNG rng) { public void placeCaveObject(IrisObjectPlacement o, int x, int z, RNG rng)
for (int i = 0; i < o.getTriesForChunk(rng); i++) { {
for(int i = 0; i < o.getTriesForChunk(rng); i++)
{
rng = rng.nextParallelRNG((i * 3 + 8) - 23040); rng = rng.nextParallelRNG((i * 3 + 8) - 23040);
int xx = (x * 16) + rng.nextInt(16); int xx = (x * 16) + rng.nextInt(16);
int zz = (z * 16) + rng.nextInt(16); int zz = (z * 16) + rng.nextInt(16);
KList<CaveResult> res = getCaves(xx, zz); KList<CaveResult> res = getCaves(xx, zz);
if (res.isEmpty()) { if(res.isEmpty())
{
continue; continue;
} }
o.getSchematic(this, rng).place(xx, o.getSchematic(this, rng).place(xx, res.get(rng.nextParallelRNG(29345 * (i + 234)).nextInt(res.size())).getFloor() + 2, zz, this, o, rng);
res.get(rng.nextParallelRNG(29345 * (i + 234)).nextInt(res.size())).getFloor() + 2, zz, this, o,
rng);
} }
} }
public AtomicSliver sampleSliver(int x, int z) { public AtomicSliver sampleSliver(int x, int z)
{
ChunkPosition key = new ChunkPosition(x, z); ChunkPosition key = new ChunkPosition(x, z);
if (getSliverCache().containsKey(key)) { if(getSliverCache().containsKey(key))
{
return getSliverCache().get(key); return getSliverCache().get(key);
} }
@ -387,7 +438,8 @@ public abstract class ParallaxChunkGenerator extends TerrainChunkGenerator imple
} }
@Override @Override
public boolean isPreventingDecay() { public boolean isPreventingDecay()
{
return getDimension().isPreventLeafDecay(); return getDimension().isPreventLeafDecay();
} }
} }

View File

@ -17,7 +17,8 @@ import lombok.EqualsAndHashCode;
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public abstract class ParallelChunkGenerator extends BiomeChunkGenerator { public abstract class ParallelChunkGenerator extends BiomeChunkGenerator
{
private GroupedExecutor accelerant; private GroupedExecutor accelerant;
private int threads; private int threads;
protected int cacheX; protected int cacheX;
@ -25,7 +26,8 @@ public abstract class ParallelChunkGenerator extends BiomeChunkGenerator {
private IrisLock genlock; private IrisLock genlock;
protected boolean cachingAllowed; protected boolean cachingAllowed;
public ParallelChunkGenerator(String dimensionName, int threads) { public ParallelChunkGenerator(String dimensionName, int threads)
{
super(dimensionName); super(dimensionName);
cacheX = 0; cacheX = 0;
cacheZ = 0; cacheZ = 0;
@ -34,35 +36,37 @@ public abstract class ParallelChunkGenerator extends BiomeChunkGenerator {
cachingAllowed = false; cachingAllowed = false;
} }
public void changeThreadCount(int tc) { public void changeThreadCount(int tc)
{
threads = tc; threads = tc;
GroupedExecutor e = accelerant; GroupedExecutor e = accelerant;
accelerant = new GroupedExecutor(threads, Thread.NORM_PRIORITY, "Iris Generator - " + world.getName()); accelerant = new GroupedExecutor(threads, Thread.NORM_PRIORITY, "Iris Generator - " + world.getName());
Iris.executors.add(accelerant); Iris.executors.add(accelerant);
if (e != null) { if(e != null)
{
e.close(); e.close();
} }
} }
protected abstract void onGenerateColumn(int cx, int cz, int wx, int wz, int x, int z, AtomicSliver sliver, protected abstract void onGenerateColumn(int cx, int cz, int wx, int wz, int x, int z, AtomicSliver sliver, BiomeMap biomeMap, boolean sampled);
BiomeMap biomeMap, boolean sampled);
protected void onGenerateColumn(int cx, int cz, int wx, int wz, int x, int z, AtomicSliver sliver, protected void onGenerateColumn(int cx, int cz, int wx, int wz, int x, int z, AtomicSliver sliver, BiomeMap biomeMap)
BiomeMap biomeMap) { {
onGenerateColumn(cx, cz, wx, wz, x, z, sliver, biomeMap, false); onGenerateColumn(cx, cz, wx, wz, x, z, sliver, biomeMap, false);
} }
protected abstract int onSampleColumnHeight(int cx, int cz, int wx, int wz, int x, int z); protected abstract int onSampleColumnHeight(int cx, int cz, int wx, int wz, int x, int z);
protected abstract void onPostGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid, HeightMap height, protected abstract void onPostGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid, HeightMap height, BiomeMap biomeMap);
BiomeMap biomeMap);
protected int sampleHeight(int x, int z) { protected int sampleHeight(int x, int z)
{
return onSampleColumnHeight(x >> 4, z >> 4, x, z, x & 15, z & 15); return onSampleColumnHeight(x >> 4, z >> 4, x, z, x & 15, z & 15);
} }
protected void onGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid) { protected void onGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid)
{
genlock.lock(); genlock.lock();
cacheX = x; cacheX = x;
cacheZ = z; cacheZ = z;
@ -74,16 +78,19 @@ public abstract class ParallelChunkGenerator extends BiomeChunkGenerator {
BiomeMap biomeMap = new BiomeMap(); BiomeMap biomeMap = new BiomeMap();
int ii, jj; int ii, jj;
for (ii = 0; ii < 16; ii++) { for(ii = 0; ii < 16; ii++)
{
int i = ii; int i = ii;
int wx = (x * 16) + i; int wx = (x * 16) + i;
for (jj = 0; jj < 16; jj++) { for(jj = 0; jj < 16; jj++)
{
int j = jj; int j = jj;
int wz = (z * 16) + j; int wz = (z * 16) + j;
AtomicSliver sliver = map.getSliver(i, j); AtomicSliver sliver = map.getSliver(i, j);
accelerant.queue(key, () -> { accelerant.queue(key, () ->
{
onGenerateColumn(x, z, wx, wz, i, j, sliver, biomeMap); onGenerateColumn(x, z, wx, wz, i, j, sliver, biomeMap);
}); });
} }
@ -97,18 +104,21 @@ public abstract class ParallelChunkGenerator extends BiomeChunkGenerator {
genlock.unlock(); genlock.unlock();
} }
protected void onClose() { protected void onClose()
{
accelerant.close(); accelerant.close();
Iris.executors.remove(accelerant); Iris.executors.remove(accelerant);
} }
public void onInit(World world, RNG rng) { public void onInit(World world, RNG rng)
{
super.onInit(world, rng); super.onInit(world, rng);
changeThreadCount(threads); changeThreadCount(threads);
} }
@Override @Override
public boolean isParallelCapable() { public boolean isParallelCapable()
{
return false; return false;
} }
} }

View File

@ -2,6 +2,7 @@ package com.volmit.iris.gen;
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.data.Bisected; import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.Bisected.Half; import org.bukkit.block.data.Bisected.Half;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -29,36 +30,42 @@ import lombok.EqualsAndHashCode;
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public abstract class TerrainChunkGenerator extends ParallelChunkGenerator { public abstract class TerrainChunkGenerator extends ParallelChunkGenerator
{
private long lastUpdateRequest = M.ms(); private long lastUpdateRequest = M.ms();
private long lastChunkLoad = M.ms(); private long lastChunkLoad = M.ms();
private GenLayerCave glCave; private GenLayerCave glCave;
private GenLayerCarve glCarve; private GenLayerCarve glCarve;
private RNG rockRandom; private RNG rockRandom;
public TerrainChunkGenerator(String dimensionName, int threads) { public TerrainChunkGenerator(String dimensionName, int threads)
{
super(dimensionName, threads); super(dimensionName, threads);
} }
public void onInit(World world, RNG rng) { public void onInit(World world, RNG rng)
{
super.onInit(world, rng); super.onInit(world, rng);
rockRandom = getMasterRandom().nextParallelRNG(2858678); rockRandom = getMasterRandom().nextParallelRNG(2858678);
glCave = new GenLayerCave(this, rng.nextParallelRNG(238948)); glCave = new GenLayerCave(this, rng.nextParallelRNG(238948));
glCarve = new GenLayerCarve(this, rng.nextParallelRNG(968346576)); glCarve = new GenLayerCarve(this, rng.nextParallelRNG(968346576));
} }
public KList<CaveResult> getCaves(int x, int z) { public KList<CaveResult> getCaves(int x, int z)
{
return glCave.genCaves(x, z, x & 15, z & 15, null); return glCave.genCaves(x, z, x & 15, z & 15, null);
} }
@Override @Override
protected void onGenerateColumn(int cx, int cz, int rx, int rz, int x, int z, AtomicSliver sliver, protected void onGenerateColumn(int cx, int cz, int rx, int rz, int x, int z, AtomicSliver sliver, BiomeMap biomeMap, boolean sampled)
BiomeMap biomeMap, boolean sampled) { {
if (x > 15 || x < 0 || z > 15 || z < 0) { if(x > 15 || x < 0 || z > 15 || z < 0)
{
throw new RuntimeException("Invalid OnGenerate call: x:" + x + " z:" + z); throw new RuntimeException("Invalid OnGenerate call: x:" + x + " z:" + z);
} }
try { try
{
int highestPlaced = 0; int highestPlaced = 0;
BlockData block; BlockData block;
@ -75,27 +82,29 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
BiomeResult biomeResult = sampleTrueBiome(rx, rz, noise); BiomeResult biomeResult = sampleTrueBiome(rx, rz, noise);
IrisBiome biome = biomeResult.getBiome(); IrisBiome biome = biomeResult.getBiome();
if (biome == null) { if(biome == null)
{
throw new RuntimeException("Null Biome!"); throw new RuntimeException("Null Biome!");
} }
KList<BlockData> layers = biome.generateLayers(rx, rz, masterRandom, height, height - getFluidHeight()); KList<BlockData> layers = biome.generateLayers(rx, rz, masterRandom, height, height - getFluidHeight());
KList<BlockData> seaLayers = biome.isSea() KList<BlockData> seaLayers = biome.isSea() ? biome.generateSeaLayers(rx, rz, masterRandom, fluidHeight - height) : new KList<>();
? biome.generateSeaLayers(rx, rz, masterRandom, fluidHeight - height)
: new KList<>();
boolean caverning = false; boolean caverning = false;
KList<Integer> cavernHeights = new KList<>(); KList<Integer> cavernHeights = new KList<>();
int lastCavernHeight = -1; int lastCavernHeight = -1;
boolean bxx = false;
// From Height to Bedrock // From Height to Bedrock
for (int k = Math.max(height, fluidHeight); k >= 0; k--) { for(int k = Math.max(height, fluidHeight); k >= 0; k--)
{
boolean cavernSurface = false; boolean cavernSurface = false;
// Bedrock // Bedrock
if (k == 0) { if(k == 0)
if (biomeMap != null) { {
if(biomeMap != null)
{
sliver.set(k, biome.getDerivative()); sliver.set(k, biome.getDerivative());
biomeMap.setBiome(x, z, biome);
} }
sliver.set(k, BEDROCK); sliver.set(k, BEDROCK);
@ -103,10 +112,11 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
} }
// Carving // Carving
if (carvable && glCarve.isCarved(rx, k, rz)) { if(carvable && glCarve.isCarved(rx, k, rz))
if (biomeMap != null) { {
if(biomeMap != null)
{
sliver.set(k, biome.getDerivative()); sliver.set(k, biome.getDerivative());
biomeMap.setBiome(x, z, biome);
} }
sliver.set(k, CAVE_AIR); sliver.set(k, CAVE_AIR);
@ -114,7 +124,8 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
continue; continue;
} }
else if (carvable && caverning) { else if(carvable && caverning)
{
lastCavernHeight = k; lastCavernHeight = k;
cavernSurface = true; cavernSurface = true;
cavernHeights.add(k); cavernHeights.add(k);
@ -124,24 +135,35 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
boolean underwater = k > height && k <= fluidHeight; boolean underwater = k > height && k <= fluidHeight;
// Set Biome // Set Biome
if (biomeMap != null) { if(!bxx && biomeMap != null)
{
bxx = true;
sliver.set(k, biome.getGroundBiome(masterRandom, rz, k, rx)); sliver.set(k, biome.getGroundBiome(masterRandom, rz, k, rx));
biomeMap.setBiome(x, z, biome); biomeMap.setBiome(x, z, biome);
for(int kv = Math.max(height, fluidHeight); kv < Math.min(Math.max(height, fluidHeight) + 16, 255); kv++)
{
Biome skyBiome = biome.getSkyBiome(masterRandom, rz, kv, rx);
sliver.set(kv, biome.getDerivative());
sliver.set(k, skyBiome);
}
} }
// Set Sea Material (water/lava) // Set Sea Material (water/lava)
if (underwater) { if(underwater)
block = seaLayers.hasIndex(fluidHeight - k) ? layers.get(depth) {
: getDimension().getFluid(rockRandom, wx, k, wz); block = seaLayers.hasIndex(fluidHeight - k) ? layers.get(depth) : getDimension().getFluid(rockRandom, wx, k, wz);
} }
// Set Surface Material for cavern layer surfaces // Set Surface Material for cavern layer surfaces
else if (layers.hasIndex(lastCavernHeight - k)) { else if(layers.hasIndex(lastCavernHeight - k))
{
block = layers.get(lastCavernHeight - k); block = layers.get(lastCavernHeight - k);
} }
// Set Surface Material for true surface // Set Surface Material for true surface
else { else
{
block = layers.hasIndex(depth) ? layers.get(depth) : getDimension().getRock(rockRandom, wx, k, wz); block = layers.hasIndex(depth) ? layers.get(depth) : getDimension().getRock(rockRandom, wx, k, wz);
depth++; depth++;
} }
@ -151,13 +173,14 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
highestPlaced = Math.max(highestPlaced, k); highestPlaced = Math.max(highestPlaced, k);
// Decorate underwater surface // Decorate underwater surface
if (!cavernSurface && (k == height && block.getMaterial().isSolid() && k < fluidHeight)) { if(!cavernSurface && (k == height && B.isSolid(block.getMaterial()) && k < fluidHeight))
{
decorateUnderwater(biome, sliver, wx, k, wz, rx, rz, block); decorateUnderwater(biome, sliver, wx, k, wz, rx, rz, block);
} }
// Decorate Cavern surfaces, but not the true surface // Decorate Cavern surfaces, but not the true surface
if ((carvable && cavernSurface) && !(k == Math.max(height, fluidHeight) && block.getMaterial().isSolid() if((carvable && cavernSurface) && !(k == Math.max(height, fluidHeight) && block.getMaterial().isSolid() && k < 255 && k >= fluidHeight))
&& k < 255 && k >= fluidHeight)) { {
decorateLand(biome, sliver, wx, k, wz, rx, rz, block); decorateLand(biome, sliver, wx, k, wz, rx, rz, block);
} }
} }
@ -167,31 +190,36 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
IrisBiome caveBiome = glBiome.generateData(InferredType.CAVE, wx, wz, rx, rz, region).getBiome(); IrisBiome caveBiome = glBiome.generateData(InferredType.CAVE, wx, wz, rx, rz, region).getBiome();
// Decorate Cave Biome Height Sections // Decorate Cave Biome Height Sections
if (caveBiome != null) { if(caveBiome != null)
for (CaveResult i : caveResults) { {
for (int j = i.getFloor(); j <= i.getCeiling(); j++) { for(CaveResult i : caveResults)
{
for(int j = i.getFloor(); j <= i.getCeiling(); j++)
{
sliver.set(j, caveBiome); sliver.set(j, caveBiome);
sliver.set(j, caveBiome.getGroundBiome(masterRandom, rz, j, rx)); sliver.set(j, caveBiome.getGroundBiome(masterRandom, rz, j, rx));
} }
KList<BlockData> floor = caveBiome.generateLayers(wx, wz, rockRandom, i.getFloor() - 2, KList<BlockData> floor = caveBiome.generateLayers(wx, wz, rockRandom, i.getFloor() - 2, i.getFloor() - 2);
i.getFloor() - 2); KList<BlockData> ceiling = caveBiome.generateLayers(wx + 256, wz + 256, rockRandom, height - i.getCeiling() - 2, height - i.getCeiling() - 2);
KList<BlockData> ceiling = caveBiome.generateLayers(wx + 256, wz + 256, rockRandom,
height - i.getCeiling() - 2, height - i.getCeiling() - 2);
BlockData blockc = null; BlockData blockc = null;
for (int j = 0; j < floor.size(); j++) { for(int j = 0; j < floor.size(); j++)
if (j == 0) { {
if(j == 0)
{
blockc = floor.get(j); blockc = floor.get(j);
} }
sliver.set(i.getFloor() - j, floor.get(j)); sliver.set(i.getFloor() - j, floor.get(j));
} }
for (int j = ceiling.size() - 1; j > 0; j--) { for(int j = ceiling.size() - 1; j > 0; j--)
{
sliver.set(i.getCeiling() + j, ceiling.get(j)); sliver.set(i.getCeiling() + j, ceiling.get(j));
} }
if (blockc != null && !sliver.isSolid(i.getFloor() + 1)) { if(blockc != null && !sliver.isSolid(i.getFloor() + 1))
{
decorateCave(caveBiome, sliver, wx, i.getFloor(), wz, rx, rz, blockc); decorateCave(caveBiome, sliver, wx, i.getFloor(), wz, rx, rz, blockc);
} }
} }
@ -200,76 +228,91 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
block = sliver.get(Math.max(height, fluidHeight)); block = sliver.get(Math.max(height, fluidHeight));
// Decorate True Surface // Decorate True Surface
if (block.getMaterial().isSolid()) { if(block.getMaterial().isSolid())
{
decorateLand(biome, sliver, wx, Math.max(height, fluidHeight), wz, rx, rz, block); decorateLand(biome, sliver, wx, Math.max(height, fluidHeight), wz, rx, rz, block);
} }
} }
catch (Throwable e) { catch(Throwable e)
{
fail(e); fail(e);
} }
} }
@Override @Override
protected void onGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid) { protected void onGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid)
{
super.onGenerate(random, x, z, data, grid); super.onGenerate(random, x, z, data, grid);
RNG ro = random.nextParallelRNG((x * x * x) - z); RNG ro = random.nextParallelRNG((x * x * x) - z);
IrisRegion region = sampleRegion((x * 16) + 7, (z * 16) + 7); IrisRegion region = sampleRegion((x * 16) + 7, (z * 16) + 7);
IrisBiome biome = sampleTrueBiome((x * 16) + 7, (z * 16) + 7).getBiome(); IrisBiome biome = sampleTrueBiome((x * 16) + 7, (z * 16) + 7).getBiome();
for (IrisDepositGenerator k : getDimension().getDeposits()) { for(IrisDepositGenerator k : getDimension().getDeposits())
{
k.generate(data, ro, this); k.generate(data, ro, this);
} }
for (IrisDepositGenerator k : region.getDeposits()) { for(IrisDepositGenerator k : region.getDeposits())
for (int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) { {
for(int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++)
{
k.generate(data, ro, this); k.generate(data, ro, this);
} }
} }
for (IrisDepositGenerator k : biome.getDeposits()) { for(IrisDepositGenerator k : biome.getDeposits())
for (int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) { {
for(int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++)
{
k.generate(data, ro, this); k.generate(data, ro, this);
} }
} }
} }
private void decorateLand(IrisBiome biome, AtomicSliver sliver, double wx, int k, double wz, int rx, int rz, private void decorateLand(IrisBiome biome, AtomicSliver sliver, double wx, int k, double wz, int rx, int rz, BlockData block)
BlockData block) { {
if (!getDimension().isDecorate()) { if(!getDimension().isDecorate())
{
return; return;
} }
int j = 0; int j = 0;
for (IrisBiomeDecorator i : biome.getDecorators()) { for(IrisBiomeDecorator i : biome.getDecorators())
if (i.getPartOf().equals(DecorationPart.SHORE_LINE) && (!touchesSea(rx, rz) || k != getFluidHeight())) { {
if(i.getPartOf().equals(DecorationPart.SHORE_LINE) && (!touchesSea(rx, rz) || k != getFluidHeight()))
{
continue; continue;
} }
BlockData d = i.getBlockData(getMasterRandom() BlockData d = i.getBlockData(getMasterRandom().nextParallelRNG((int) (38888 + biome.getRarity() + biome.getName().length() + j++)), rx, rz);
.nextParallelRNG((int) (38888 + biome.getRarity() + biome.getName().length() + j++)), rx, rz);
if (d != null) { if(d != null)
if (!B.canPlaceOnto(d.getMaterial(), block.getMaterial())) { {
if(!B.canPlaceOnto(d.getMaterial(), block.getMaterial()))
{
continue; continue;
} }
if (d.getMaterial().equals(Material.CACTUS)) { if(d.getMaterial().equals(Material.CACTUS))
if (!block.getMaterial().equals(Material.SAND) && !block.getMaterial().equals(Material.RED_SAND)) { {
if(!block.getMaterial().equals(Material.SAND) && !block.getMaterial().equals(Material.RED_SAND))
{
sliver.set(k, B.getBlockData("RED_SAND")); sliver.set(k, B.getBlockData("RED_SAND"));
} }
} }
if (d.getMaterial().equals(Material.WHEAT) || d.getMaterial().equals(Material.CARROTS) if(d.getMaterial().equals(Material.WHEAT) || d.getMaterial().equals(Material.CARROTS) || d.getMaterial().equals(Material.POTATOES) || d.getMaterial().equals(Material.MELON_STEM) || d.getMaterial().equals(Material.PUMPKIN_STEM))
|| d.getMaterial().equals(Material.POTATOES) || d.getMaterial().equals(Material.MELON_STEM) {
|| d.getMaterial().equals(Material.PUMPKIN_STEM)) { if(!block.getMaterial().equals(Material.FARMLAND))
if (!block.getMaterial().equals(Material.FARMLAND)) { {
sliver.set(k, B.getBlockData("FARMLAND")); sliver.set(k, B.getBlockData("FARMLAND"));
} }
} }
if (d instanceof Bisected && k < 254) { if(d instanceof Bisected && k < 254)
{
Bisected t = ((Bisected) d.clone()); Bisected t = ((Bisected) d.clone());
t.setHalf(Half.TOP); t.setHalf(Half.TOP);
Bisected b = ((Bisected) d.clone()); Bisected b = ((Bisected) d.clone());
@ -278,17 +321,19 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
sliver.set(k + 2, t); sliver.set(k + 2, t);
} }
else { else
int stack = i.getHeight(getMasterRandom().nextParallelRNG( {
(int) (39456 + (10000 * i.getChance()) + i.getStackMax() + i.getStackMin() + i.getZoom())), int stack = i.getHeight(getMasterRandom().nextParallelRNG((int) (39456 + (10000 * i.getChance()) + i.getStackMax() + i.getStackMin() + i.getZoom())), rx, rz);
rx, rz);
if (stack == 1) { if(stack == 1)
{
sliver.set(k + 1, d); sliver.set(k + 1, d);
} }
else if (k < 255 - stack) { else if(k < 255 - stack)
for (int l = 0; l < stack; l++) { {
for(int l = 0; l < stack; l++)
{
sliver.set(k + l + 1, d); sliver.set(k + l + 1, d);
} }
} }
@ -299,31 +344,36 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
} }
} }
private void decorateCave(IrisBiome biome, AtomicSliver sliver, double wx, int k, double wz, int rx, int rz, private void decorateCave(IrisBiome biome, AtomicSliver sliver, double wx, int k, double wz, int rx, int rz, BlockData block)
BlockData block) { {
if (!getDimension().isDecorate()) { if(!getDimension().isDecorate())
{
return; return;
} }
int j = 0; int j = 0;
for (IrisBiomeDecorator i : biome.getDecorators()) { for(IrisBiomeDecorator i : biome.getDecorators())
BlockData d = i.getBlockData( {
getMasterRandom().nextParallelRNG(2333877 + biome.getRarity() + biome.getName().length() + +j++), BlockData d = i.getBlockData(getMasterRandom().nextParallelRNG(2333877 + biome.getRarity() + biome.getName().length() + +j++), rx, rz);
rx, rz);
if (d != null) { if(d != null)
if (!B.canPlaceOnto(d.getMaterial(), block.getMaterial())) { {
if(!B.canPlaceOnto(d.getMaterial(), block.getMaterial()))
{
continue; continue;
} }
if (d.getMaterial().equals(Material.CACTUS)) { if(d.getMaterial().equals(Material.CACTUS))
if (!block.getMaterial().equals(Material.SAND) && !block.getMaterial().equals(Material.RED_SAND)) { {
if(!block.getMaterial().equals(Material.SAND) && !block.getMaterial().equals(Material.RED_SAND))
{
sliver.set(k, B.getBlockData("SAND")); sliver.set(k, B.getBlockData("SAND"));
} }
} }
if (d instanceof Bisected && k < 254) { if(d instanceof Bisected && k < 254)
{
Bisected t = ((Bisected) d.clone()); Bisected t = ((Bisected) d.clone());
t.setHalf(Half.TOP); t.setHalf(Half.TOP);
Bisected b = ((Bisected) d.clone()); Bisected b = ((Bisected) d.clone());
@ -332,17 +382,21 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
sliver.set(k + 2, t); sliver.set(k + 2, t);
} }
else { else
int stack = i.getHeight(getMasterRandom() {
.nextParallelRNG((int) (39456 + (1000 * i.getChance()) + i.getZoom() * 10)), rx, rz); int stack = i.getHeight(getMasterRandom().nextParallelRNG((int) (39456 + (1000 * i.getChance()) + i.getZoom() * 10)), rx, rz);
if (stack == 1) { if(stack == 1)
{
sliver.set(k + 1, d); sliver.set(k + 1, d);
} }
else if (k < 255 - stack) { else if(k < 255 - stack)
for (int l = 0; l < stack; l++) { {
if (sliver.isSolid(k + l + 1)) { for(int l = 0; l < stack; l++)
{
if(sliver.isSolid(k + l + 1))
{
break; break;
} }
@ -356,35 +410,38 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
} }
} }
private void decorateUnderwater(IrisBiome biome, AtomicSliver sliver, double wx, int y, double wz, int rx, int rz, private void decorateUnderwater(IrisBiome biome, AtomicSliver sliver, double wx, int y, double wz, int rx, int rz, BlockData block)
BlockData block) { {
if (!getDimension().isDecorate()) { if(!getDimension().isDecorate())
{
return; return;
} }
int j = 0; int j = 0;
for (IrisBiomeDecorator i : biome.getDecorators()) { for(IrisBiomeDecorator i : biome.getDecorators())
if (biome.getInferredType().equals(InferredType.SHORE)) { {
if(biome.getInferredType().equals(InferredType.SHORE))
{
continue; continue;
} }
BlockData d = i.getBlockData( BlockData d = i.getBlockData(getMasterRandom().nextParallelRNG(2555 + biome.getRarity() + biome.getName().length() + j++), rx, rz);
getMasterRandom().nextParallelRNG(2555 + biome.getRarity() + biome.getName().length() + j++), rx,
rz);
if (d != null) { if(d != null)
int stack = i.getHeight(getMasterRandom().nextParallelRNG((int) (239456 + i.getStackMax() {
+ i.getStackMin() + i.getVerticalZoom() + i.getZoom() + i.getBlockData().size() + j)), rx, rz); int stack = i.getHeight(getMasterRandom().nextParallelRNG((int) (239456 + i.getStackMax() + i.getStackMin() + i.getVerticalZoom() + i.getZoom() + i.getBlockData().size() + j)), rx, rz);
if (stack == 1) { if(stack == 1)
{
sliver.set(i.getPartOf().equals(DecorationPart.SEA_SURFACE) ? (getFluidHeight() + 1) : (y + 1), d); sliver.set(i.getPartOf().equals(DecorationPart.SEA_SURFACE) ? (getFluidHeight() + 1) : (y + 1), d);
} }
else if (y < getFluidHeight() - stack) { else if(y < getFluidHeight() - stack)
for (int l = 0; l < stack; l++) { {
sliver.set(i.getPartOf().equals(DecorationPart.SEA_SURFACE) ? (getFluidHeight() + 1 + l) for(int l = 0; l < stack; l++)
: (y + l + 1), d); {
sliver.set(i.getPartOf().equals(DecorationPart.SEA_SURFACE) ? (getFluidHeight() + 1 + l) : (y + l + 1), d);
} }
} }
@ -394,22 +451,23 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
} }
@Override @Override
protected void onPostGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid, HeightMap height, protected void onPostGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid, HeightMap height, BiomeMap biomeMap)
BiomeMap biomeMap) { {
onPreParallaxPostGenerate(random, x, z, data, grid, height, biomeMap); onPreParallaxPostGenerate(random, x, z, data, grid, height, biomeMap);
} }
protected void onPreParallaxPostGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid, HeightMap height, protected void onPreParallaxPostGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid, HeightMap height, BiomeMap biomeMap)
BiomeMap biomeMap) { {
} }
protected void onPostParallaxPostGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid, protected void onPostParallaxPostGenerate(RNG random, int x, int z, ChunkData data, BiomeGrid grid, HeightMap height, BiomeMap biomeMap)
HeightMap height, BiomeMap biomeMap) { {
} }
private double getNoiseHeight(int rx, int rz) { private double getNoiseHeight(int rx, int rz)
{
double wx = getZoomed(rx); double wx = getZoomed(rx);
double wz = getZoomed(rz); double wz = getZoomed(rz);
double h = getBiomeHeight(wx, wz, rx, rz); double h = getBiomeHeight(wx, wz, rx, rz);
@ -417,8 +475,10 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
return h; return h;
} }
public BiomeResult sampleTrueBiomeBase(int x, int z, int height) { public BiomeResult sampleTrueBiomeBase(int x, int z, int height)
if (!getDimension().getFocus().equals("")) { {
if(!getDimension().getFocus().equals(""))
{
return focus(); return focus();
} }
@ -428,42 +488,51 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
double sh = region.getShoreHeight(wx, wz); double sh = region.getShoreHeight(wx, wz);
IrisBiome current = sampleBiome(x, z).getBiome(); IrisBiome current = sampleBiome(x, z).getBiome();
if (current.isShore() && height > sh) { if(current.isShore() && height > sh)
{
return glBiome.generateData(InferredType.LAND, wx, wz, x, z, region); return glBiome.generateData(InferredType.LAND, wx, wz, x, z, region);
} }
if (current.isShore() || current.isLand() && height <= getDimension().getFluidHeight()) { if(current.isShore() || current.isLand() && height <= getDimension().getFluidHeight())
{
return glBiome.generateData(InferredType.SEA, wx, wz, x, z, region); return glBiome.generateData(InferredType.SEA, wx, wz, x, z, region);
} }
if (current.isSea() && height > getDimension().getFluidHeight()) { if(current.isSea() && height > getDimension().getFluidHeight())
{
return glBiome.generateData(InferredType.LAND, wx, wz, x, z, region); return glBiome.generateData(InferredType.LAND, wx, wz, x, z, region);
} }
if (height <= getDimension().getFluidHeight()) { if(height <= getDimension().getFluidHeight())
{
return glBiome.generateData(InferredType.SEA, wx, wz, x, z, region); return glBiome.generateData(InferredType.SEA, wx, wz, x, z, region);
} }
if (height <= getDimension().getFluidHeight() + sh) { if(height <= getDimension().getFluidHeight() + sh)
{
return glBiome.generateData(InferredType.SHORE, wx, wz, x, z, region); return glBiome.generateData(InferredType.SHORE, wx, wz, x, z, region);
} }
return glBiome.generateRegionData(wx, wz, x, z, region); return glBiome.generateRegionData(wx, wz, x, z, region);
} }
public BiomeResult sampleCaveBiome(int x, int z) { public BiomeResult sampleCaveBiome(int x, int z)
{
double wx = getModifiedX(x, z); double wx = getModifiedX(x, z);
double wz = getModifiedZ(x, z); double wz = getModifiedZ(x, z);
return glBiome.generateData(InferredType.CAVE, wx, wz, x, z, sampleRegion(x, z)); return glBiome.generateData(InferredType.CAVE, wx, wz, x, z, sampleRegion(x, z));
} }
public BiomeResult sampleTrueBiome(int x, int y, int z) { public BiomeResult sampleTrueBiome(int x, int y, int z)
if (y < getTerrainHeight(x, z)) { {
if(y < getTerrainHeight(x, z))
{
double wx = getModifiedX(x, z); double wx = getModifiedX(x, z);
double wz = getModifiedZ(x, z); double wz = getModifiedZ(x, z);
BiomeResult r = glBiome.generateData(InferredType.CAVE, wx, wz, x, z, sampleRegion(x, z)); BiomeResult r = glBiome.generateData(InferredType.CAVE, wx, wz, x, z, sampleRegion(x, z));
if (r.getBiome() != null) { if(r.getBiome() != null)
{
return r; return r;
} }
} }
@ -471,21 +540,26 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
return sampleTrueBiome(x, z); return sampleTrueBiome(x, z);
} }
public BiomeResult sampleTrueBiome(int x, int z) { public BiomeResult sampleTrueBiome(int x, int z)
{
return sampleTrueBiome(x, z, getTerrainHeight(x, z)); return sampleTrueBiome(x, z, getTerrainHeight(x, z));
} }
@Override @Override
public IrisRegion sampleRegion(int x, int z) { public IrisRegion sampleRegion(int x, int z)
{
return getCache().getRegion(x, z, () -> super.sampleRegion(x, z)); return getCache().getRegion(x, z, () -> super.sampleRegion(x, z));
} }
public BiomeResult sampleTrueBiome(int x, int z, double noise) { public BiomeResult sampleTrueBiome(int x, int z, double noise)
if (!getDimension().getFocus().equals("")) { {
if(!getDimension().getFocus().equals(""))
{
return focus(); return focus();
} }
return getCache().getBiome(x, z, () -> { return getCache().getBiome(x, z, () ->
{
double wx = getModifiedX(x, z); double wx = getModifiedX(x, z);
double wz = getModifiedZ(x, z); double wz = getModifiedZ(x, z);
IrisRegion region = sampleRegion(x, z); IrisRegion region = sampleRegion(x, z);
@ -494,7 +568,8 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
BiomeResult res = sampleTrueBiomeBase(x, z, height); BiomeResult res = sampleTrueBiomeBase(x, z, height);
IrisBiome current = res.getBiome(); IrisBiome current = res.getBiome();
if (current.isSea() && height > getDimension().getFluidHeight() - sh) { if(current.isSea() && height > getDimension().getFluidHeight() - sh)
{
return glBiome.generateData(InferredType.SHORE, wx, wz, x, z, region); return glBiome.generateData(InferredType.SHORE, wx, wz, x, z, region);
} }
@ -503,32 +578,38 @@ public abstract class TerrainChunkGenerator extends ParallelChunkGenerator {
} }
@Override @Override
protected int onSampleColumnHeight(int cx, int cz, int rx, int rz, int x, int z) { protected int onSampleColumnHeight(int cx, int cz, int rx, int rz, int x, int z)
{
return (int) Math.round(getTerrainHeight(rx, rz)); return (int) Math.round(getTerrainHeight(rx, rz));
} }
private boolean touchesSea(int rx, int rz) { private boolean touchesSea(int rx, int rz)
return isFluidAtHeight(rx + 1, rz) || isFluidAtHeight(rx - 1, rz) || isFluidAtHeight(rx, rz - 1) {
|| isFluidAtHeight(rx, rz + 1); return isFluidAtHeight(rx + 1, rz) || isFluidAtHeight(rx - 1, rz) || isFluidAtHeight(rx, rz - 1) || isFluidAtHeight(rx, rz + 1);
} }
public boolean isUnderwater(int x, int z) { public boolean isUnderwater(int x, int z)
{
return isFluidAtHeight(x, z); return isFluidAtHeight(x, z);
} }
public boolean isFluidAtHeight(int x, int z) { public boolean isFluidAtHeight(int x, int z)
{
return Math.round(getTerrainHeight(x, z)) < getFluidHeight(); return Math.round(getTerrainHeight(x, z)) < getFluidHeight();
} }
public int getFluidHeight() { public int getFluidHeight()
{
return getDimension().getFluidHeight(); return getDimension().getFluidHeight();
} }
public double getTerrainHeight(int x, int z) { public double getTerrainHeight(int x, int z)
{
return getCache().getHeight(x, z, () -> getNoiseHeight(x, z) + getFluidHeight()); return getCache().getHeight(x, z, () -> getNoiseHeight(x, z) + getFluidHeight());
} }
public double getTerrainWaterHeight(int x, int z) { public double getTerrainWaterHeight(int x, int z)
{
return Math.max(getTerrainHeight(x, z), getFluidHeight()); return Math.max(getTerrainHeight(x, z), getFluidHeight());
} }
} }

View File

@ -3,11 +3,13 @@ package com.volmit.iris.gen.atomics;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.object.IrisRegion; import com.volmit.iris.object.IrisRegion;
import com.volmit.iris.util.BiomeResult; import com.volmit.iris.util.BiomeResult;
import com.volmit.iris.util.KMap; import com.volmit.iris.util.KMap;
public class AtomicMulticache { public class AtomicMulticache
{
private final AtomicInteger x; private final AtomicInteger x;
private final AtomicInteger z; private final AtomicInteger z;
private final KMap<Long, Double> height; private final KMap<Long, Double> height;
@ -18,7 +20,8 @@ public class AtomicMulticache {
private int w = 0; private int w = 0;
private int m = 0; private int m = 0;
public AtomicMulticache() { public AtomicMulticache()
{
x = new AtomicInteger(0); x = new AtomicInteger(0);
z = new AtomicInteger(0); z = new AtomicInteger(0);
height = new KMap<Long, Double>(); height = new KMap<Long, Double>();
@ -27,83 +30,108 @@ public class AtomicMulticache {
region = new KMap<Long, IrisRegion>(); region = new KMap<Long, IrisRegion>();
} }
public void targetChunk(int x, int z) { public void targetChunk(int x, int z)
{
this.x.set(x); this.x.set(x);
this.z.set(z); this.z.set(z);
r = 0;
w = 0;
m = 0;
if(!IrisSettings.get().sharedCaching || getSize() > 42000)
{
drop();
}
}
public double getHeight(int x, int z, Supplier<Double> g)
{
return height.compute(pos(x, z), (k, v) ->
{
if(v == null)
{
m++;
w++;
return g.get();
}
r++;
return v;
});
}
public IrisRegion getRegion(int x, int z, Supplier<IrisRegion> g)
{
return region.compute(pos(x, z), (k, v) ->
{
if(v == null)
{
m++;
w++;
return g.get();
}
r++;
return v;
});
}
public BiomeResult getBiome(int x, int z, Supplier<BiomeResult> g)
{
return biome.compute(pos(x, z), (k, v) ->
{
if(v == null)
{
m++;
w++;
return g.get();
}
r++;
return v;
});
}
public BiomeResult getRawBiome(int x, int z, Supplier<BiomeResult> g)
{
return rawBiome.compute(pos(x, z), (k, v) ->
{
if(v == null)
{
m++;
w++;
return g.get();
}
r++;
return v;
});
}
private long pos(int x, int z)
{
return (((long) x) << 32) | (z & 0xffffffffL);
}
public void updateHeight(int x, int z, int h)
{
height.put(pos(x, z), (double) h);
}
public double getSize()
{
return height.size() + region.size() + biome.size() + rawBiome.size();
}
public void drop()
{
height.clear(); height.clear();
region.clear(); region.clear();
biome.clear(); biome.clear();
rawBiome.clear(); rawBiome.clear();
r = 0;
w = 0;
m = 0;
}
public double getHeight(int x, int z, Supplier<Double> g) {
return height.compute(pos(x, z), (k, v) -> {
if (v == null) {
m++;
w++;
return g.get();
}
r++;
return v;
});
}
public IrisRegion getRegion(int x, int z, Supplier<IrisRegion> g) {
return region.compute(pos(x, z), (k, v) -> {
if (v == null) {
m++;
w++;
return g.get();
}
r++;
return v;
});
}
public BiomeResult getBiome(int x, int z, Supplier<BiomeResult> g) {
return biome.compute(pos(x, z), (k, v) -> {
if (v == null) {
m++;
w++;
return g.get();
}
r++;
return v;
});
}
public BiomeResult getRawBiome(int x, int z, Supplier<BiomeResult> g) {
return rawBiome.compute(pos(x, z), (k, v) -> {
if (v == null) {
m++;
w++;
return g.get();
}
r++;
return v;
});
}
private long pos(int x, int z) {
return (((long) x) << 32) | (z & 0xffffffffL);
}
public void updateHeight(int x, int z, int h) {
height.put(pos(x, z), (double) h);
}
public double getSize() {
return height.size();
} }
} }

View File

@ -1,6 +1,7 @@
package com.volmit.iris.gen.layer; package com.volmit.iris.gen.layer;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.IrisSettings;
import com.volmit.iris.gen.DimensionChunkGenerator; import com.volmit.iris.gen.DimensionChunkGenerator;
import com.volmit.iris.noise.CNG; import com.volmit.iris.noise.CNG;
import com.volmit.iris.object.InferredType; import com.volmit.iris.object.InferredType;
@ -144,7 +145,7 @@ public class GenLayerBiome extends GenLayer {
public BiomeResult implode(double bx, double bz, IrisRegion regionData, CNG parentCell, BiomeResult parent, public BiomeResult implode(double bx, double bz, IrisRegion regionData, CNG parentCell, BiomeResult parent,
int hits) { int hits) {
if (hits > 9) { if (hits > IrisSettings.get().maxBiomeChildDepth) {
return parent; return parent;
} }

View File

@ -17,6 +17,7 @@ import com.volmit.iris.util.KSet;
import com.volmit.iris.util.MaxNumber; import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.RNG; import com.volmit.iris.util.RNG;
import com.volmit.iris.util.RegistryListBiome;
import com.volmit.iris.util.Required; import com.volmit.iris.util.Required;
import lombok.Data; import lombok.Data;
@ -85,6 +86,7 @@ public class IrisBiome extends IrisRegistrant implements IRare
@Desc("If this biome has children biomes, and the gen layer chooses one of this biomes children, How will it be shaped?") @Desc("If this biome has children biomes, and the gen layer chooses one of this biomes children, How will it be shaped?")
private IrisGeneratorStyle childStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); private IrisGeneratorStyle childStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style();
@RegistryListBiome
@ArrayType(min = 1, type = String.class) @ArrayType(min = 1, type = String.class)
@DontObfuscate @DontObfuscate
@Desc("List any biome names (file names without.json) here as children. Portions of this biome can sometimes morph into their children. Iris supports cyclic relationships such as A > B > A > B. Iris will stop checking 9 biomes down the tree.") @Desc("List any biome names (file names without.json) here as children. Portions of this biome can sometimes morph into their children. Iris supports cyclic relationships such as A > B > A > B. Iris will stop checking 9 biomes down the tree.")

View File

@ -9,18 +9,21 @@ import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.IrisInterpolation; import com.volmit.iris.util.IrisInterpolation;
import com.volmit.iris.util.MaxNumber; import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.RegistryListGenerator;
import com.volmit.iris.util.Required; import com.volmit.iris.util.Required;
import lombok.Data; import lombok.Data;
@Desc("This represents a link to a generator for a biome") @Desc("This represents a link to a generator for a biome")
@Data @Data
public class IrisBiomeGeneratorLink { public class IrisBiomeGeneratorLink
{
@RegistryListGenerator
@DontObfuscate @DontObfuscate
@Desc("The generator id") @Desc("The generator id")
private String generator = "default"; private String generator = "default";
@DependsOn({ "min", "max" }) @DependsOn({"min", "max"})
@Required @Required
@MinNumber(-256) @MinNumber(-256)
@MaxNumber(256) @MaxNumber(256)
@ -28,7 +31,7 @@ public class IrisBiomeGeneratorLink {
@Desc("The min block value (value + fluidHeight)") @Desc("The min block value (value + fluidHeight)")
private int min = 0; private int min = 0;
@DependsOn({ "min", "max" }) @DependsOn({"min", "max"})
@Required @Required
@MinNumber(-256) @MinNumber(-256)
@MaxNumber(256) @MaxNumber(256)
@ -38,16 +41,19 @@ public class IrisBiomeGeneratorLink {
private transient AtomicCache<IrisGenerator> gen = new AtomicCache<>(); private transient AtomicCache<IrisGenerator> gen = new AtomicCache<>();
public IrisBiomeGeneratorLink() { public IrisBiomeGeneratorLink()
{
} }
public IrisGenerator getCachedGenerator(ContextualChunkGenerator g) { public IrisGenerator getCachedGenerator(ContextualChunkGenerator g)
return gen.aquire(() -> { {
IrisGenerator gen = g != null ? g.loadGenerator(getGenerator()) return gen.aquire(() ->
: Iris.globaldata.getGeneratorLoader().load(getGenerator()); {
IrisGenerator gen = g != null ? g.loadGenerator(getGenerator()) : Iris.globaldata.getGeneratorLoader().load(getGenerator());
if (gen == null) { if(gen == null)
{
gen = new IrisGenerator(); gen = new IrisGenerator();
} }
@ -55,7 +61,8 @@ public class IrisBiomeGeneratorLink {
}); });
} }
public double getHeight(ContextualChunkGenerator xg, double x, double z, long seed) { public double getHeight(ContextualChunkGenerator xg, double x, double z, long seed)
{
double g = getCachedGenerator(xg).getHeight(x, z, seed); double g = getCachedGenerator(xg).getHeight(x, z, seed);
g = g < 0 ? 0 : g; g = g < 0 ? 0 : g;
g = g > 1 ? 1 : g; g = g > 1 ? 1 : g;

View File

@ -9,6 +9,8 @@ import com.volmit.iris.util.KList;
import com.volmit.iris.util.KSet; import com.volmit.iris.util.KSet;
import com.volmit.iris.util.MaxNumber; import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.RegistryListBiome;
import com.volmit.iris.util.RegistryListObject;
import com.volmit.iris.util.Required; import com.volmit.iris.util.Required;
import lombok.Data; import lombok.Data;
@ -17,12 +19,14 @@ import lombok.Data;
@Data @Data
public class IrisBiomeMutation public class IrisBiomeMutation
{ {
@RegistryListBiome
@Required @Required
@ArrayType(min = 1, type = String.class) @ArrayType(min = 1, type = String.class)
@DontObfuscate @DontObfuscate
@Desc("One of The following biomes or regions must show up") @Desc("One of The following biomes or regions must show up")
private KList<String> sideA = new KList<>(); private KList<String> sideA = new KList<>();
@RegistryListBiome
@Required @Required
@ArrayType(min = 1, type = String.class) @ArrayType(min = 1, type = String.class)
@DontObfuscate @DontObfuscate
@ -43,6 +47,7 @@ public class IrisBiomeMutation
@Desc("How many tries per chunk to check for this mutation") @Desc("How many tries per chunk to check for this mutation")
private int checks = 2; private int checks = 2;
@RegistryListObject
@ArrayType(min = 1, type = IrisObjectPlacement.class) @ArrayType(min = 1, type = IrisObjectPlacement.class)
@DontObfuscate @DontObfuscate
@Desc("Objects define what schematics (iob files) iris will place in this biome mutation") @Desc("Objects define what schematics (iob files) iris will place in this biome mutation")

View File

@ -21,6 +21,9 @@ import com.volmit.iris.util.KSet;
import com.volmit.iris.util.MaxNumber; import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.RNG; import com.volmit.iris.util.RNG;
import com.volmit.iris.util.RegistryListBiome;
import com.volmit.iris.util.RegistryListDimension;
import com.volmit.iris.util.RegistryListRegion;
import com.volmit.iris.util.Required; import com.volmit.iris.util.Required;
import lombok.Data; import lombok.Data;
@ -160,6 +163,7 @@ public class IrisDimension extends IrisRegistrant
@Desc("Compatability filters") @Desc("Compatability filters")
private KList<IrisCompatabilityFilter> compatability = getDefaultCompatability(); private KList<IrisCompatabilityFilter> compatability = getDefaultCompatability();
@RegistryListDimension
@DontObfuscate @DontObfuscate
@Desc("The ceiling dimension. Leave blank for normal sky.") @Desc("The ceiling dimension. Leave blank for normal sky.")
private String ceiling = ""; private String ceiling = "";
@ -173,6 +177,7 @@ public class IrisDimension extends IrisRegistrant
@Desc("The world environment") @Desc("The world environment")
private Environment environment = Environment.NORMAL; private Environment environment = Environment.NORMAL;
@RegistryListRegion
@Required @Required
@ArrayType(min = 1, type = String.class) @ArrayType(min = 1, type = String.class)
@DontObfuscate @DontObfuscate
@ -186,6 +191,7 @@ public class IrisDimension extends IrisRegistrant
@Desc("The fluid height for this dimension") @Desc("The fluid height for this dimension")
private int fluidHeight = 63; private int fluidHeight = 63;
@RegistryListBiome
@DontObfuscate @DontObfuscate
@Desc("Keep this either undefined or empty. Setting any biome name into this will force iris to only generate the specified biome. Great for testing.") @Desc("Keep this either undefined or empty. Setting any biome name into this will force iris to only generate the specified biome. Great for testing.")
private String focus = ""; private String focus = "";

View File

@ -12,6 +12,7 @@ import java.io.OutputStream;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.Leaves; import org.bukkit.block.data.type.Leaves;
import org.bukkit.util.BlockVector; import org.bukkit.util.BlockVector;
@ -26,21 +27,19 @@ import lombok.EqualsAndHashCode;
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class IrisObject extends IrisRegistrant { public class IrisObject extends IrisRegistrant
{
private static final Material SNOW = Material.SNOW; private static final Material SNOW = Material.SNOW;
private static final BlockData AIR = B.getBlockData("CAVE_AIR"); private static final BlockData AIR = B.getBlockData("CAVE_AIR");
private static final BlockData[] SNOW_LAYERS = new BlockData[] { B.getBlockData("minecraft:snow[layers=1]"), private static final BlockData[] SNOW_LAYERS = new BlockData[] {B.getBlockData("minecraft:snow[layers=1]"), B.getBlockData("minecraft:snow[layers=2]"), B.getBlockData("minecraft:snow[layers=3]"), B.getBlockData("minecraft:snow[layers=4]"), B.getBlockData("minecraft:snow[layers=5]"), B.getBlockData("minecraft:snow[layers=6]"), B.getBlockData("minecraft:snow[layers=7]"), B.getBlockData("minecraft:snow[layers=8]")};
B.getBlockData("minecraft:snow[layers=2]"), B.getBlockData("minecraft:snow[layers=3]"),
B.getBlockData("minecraft:snow[layers=4]"), B.getBlockData("minecraft:snow[layers=5]"),
B.getBlockData("minecraft:snow[layers=6]"), B.getBlockData("minecraft:snow[layers=7]"),
B.getBlockData("minecraft:snow[layers=8]") };
private KMap<BlockVector, BlockData> blocks; private KMap<BlockVector, BlockData> blocks;
private int w; private int w;
private int d; private int d;
private int h; private int h;
private transient BlockVector center; private transient BlockVector center;
public IrisObject(int w, int h, int d) { public IrisObject(int w, int h, int d)
{
blocks = new KMap<>(); blocks = new KMap<>();
this.w = w; this.w = w;
this.h = h; this.h = h;
@ -48,7 +47,8 @@ public class IrisObject extends IrisRegistrant {
center = new BlockVector(w / 2, h / 2, d / 2); center = new BlockVector(w / 2, h / 2, d / 2);
} }
public static BlockVector sampleSize(File file) throws IOException { public static BlockVector sampleSize(File file) throws IOException
{
FileInputStream in = new FileInputStream(file); FileInputStream in = new FileInputStream(file);
DataInputStream din = new DataInputStream(in); DataInputStream din = new DataInputStream(in);
BlockVector bv = new BlockVector(din.readInt(), din.readInt(), din.readInt()); BlockVector bv = new BlockVector(din.readInt(), din.readInt(), din.readInt());
@ -56,7 +56,8 @@ public class IrisObject extends IrisRegistrant {
return bv; return bv;
} }
public void read(InputStream in) throws IOException { public void read(InputStream in) throws IOException
{
DataInputStream din = new DataInputStream(in); DataInputStream din = new DataInputStream(in);
this.w = din.readInt(); this.w = din.readInt();
this.h = din.readInt(); this.h = din.readInt();
@ -64,32 +65,36 @@ public class IrisObject extends IrisRegistrant {
center = new BlockVector(w / 2, h / 2, d / 2); center = new BlockVector(w / 2, h / 2, d / 2);
int s = din.readInt(); int s = din.readInt();
for (int i = 0; i < s; i++) { for(int i = 0; i < s; i++)
blocks.put(new BlockVector(din.readShort(), din.readShort(), din.readShort()), {
B.getBlockData(din.readUTF())); blocks.put(new BlockVector(din.readShort(), din.readShort(), din.readShort()), B.getBlockData(din.readUTF()));
} }
} }
public void read(File file) throws IOException { public void read(File file) throws IOException
{
FileInputStream fin = new FileInputStream(file); FileInputStream fin = new FileInputStream(file);
read(fin); read(fin);
fin.close(); fin.close();
} }
public void write(File file) throws IOException { public void write(File file) throws IOException
{
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream(file); FileOutputStream out = new FileOutputStream(file);
write(out); write(out);
out.close(); out.close();
} }
public void write(OutputStream o) throws IOException { public void write(OutputStream o) throws IOException
{
DataOutputStream dos = new DataOutputStream(o); DataOutputStream dos = new DataOutputStream(o);
dos.writeInt(w); dos.writeInt(w);
dos.writeInt(h); dos.writeInt(h);
dos.writeInt(d); dos.writeInt(d);
dos.writeInt(blocks.size()); dos.writeInt(blocks.size());
for (BlockVector i : blocks.k()) { for(BlockVector i : blocks.k())
{
dos.writeShort(i.getBlockX()); dos.writeShort(i.getBlockX());
dos.writeShort(i.getBlockY()); dos.writeShort(i.getBlockY());
dos.writeShort(i.getBlockZ()); dos.writeShort(i.getBlockZ());
@ -97,68 +102,102 @@ public class IrisObject extends IrisRegistrant {
} }
} }
public void setUnsigned(int x, int y, int z, BlockData block) { public void setUnsigned(int x, int y, int z, BlockData block)
if (x >= w || y >= h || z >= d) { {
if(x >= w || y >= h || z >= d)
{
throw new RuntimeException(x + " " + y + " " + z + " exceeds limit of " + w + " " + h + " " + d); throw new RuntimeException(x + " " + y + " " + z + " exceeds limit of " + w + " " + h + " " + d);
} }
BlockVector v = new BlockVector(x, y, z).subtract(center).toBlockVector(); BlockVector v = new BlockVector(x, y, z).subtract(center).toBlockVector();
if (block == null) { if(block == null)
{
blocks.remove(v); blocks.remove(v);
} }
else { else
{
blocks.put(v, block); blocks.put(v, block);
} }
} }
public void place(int x, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng) { public void place(int x, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng)
{
place(x, -1, z, placer, config, rng); place(x, -1, z, placer, config, rng);
} }
public void place(int x, int yv, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng) { public void place(int x, int yv, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng)
{
int spinx = rng.imax() / 1000; int spinx = rng.imax() / 1000;
int spiny = rng.imax() / 1000; int spiny = rng.imax() / 1000;
int spinz = rng.imax() / 1000; int spinz = rng.imax() / 1000;
int y = yv < 0 ? placer.getHighest(x, z, config.isUnderwater()) + config.getRotation() int rty = config.getRotation().rotate(new BlockVector(0, getCenter().getBlockY(), 0), spinx, spiny, spinz).getBlockY();
.rotate(new BlockVector(0, getCenter().getBlockY(), 0), spinx, spiny, spinz).getBlockY() : yv; int ty = config.getTranslate().translate(new BlockVector(0, getCenter().getBlockY(), 0), config.getRotation(), spinx, spiny, spinz).getBlockY();
int y = yv < 0 ? placer.getHighest(x, z, config.isUnderwater()) + rty : yv;
if (yv >= 0 && config.isBottom()) { if(yv >= 0 && config.isBottom())
{
y += Math.floorDiv(h, 2); y += Math.floorDiv(h, 2);
} }
KMap<ChunkPosition, Integer> heightmap = config.getSnow() > 0 ? new KMap<>() : null; KMap<ChunkPosition, Integer> heightmap = config.getSnow() > 0 ? new KMap<>() : null;
if (yv < 0) { if(yv < 0)
if (!config.isUnderwater() && !config.isOnwater() && placer.isUnderwater(x, z)) { {
if(!config.isUnderwater() && !config.isOnwater() && placer.isUnderwater(x, z))
{
return; return;
} }
} }
if (config.isBore()) { if(config.isUnderwater() && y + rty + ty >= placer.getFluidHeight())
for (int i = x - Math.floorDiv(w, 2); i <= x + Math.floorDiv(w, 2) - (w % 2 == 0 ? 1 : 0); i++) { {
for (int j = y - Math.floorDiv(h, 2); j <= y + Math.floorDiv(h, 2) - (h % 2 == 0 ? 1 : 0); j++) { return;
for (int k = z - Math.floorDiv(d, 2); k <= z + Math.floorDiv(d, 2) - (d % 2 == 0 ? 1 : 0); k++) { }
if(!config.getClamp().canPlace(y + rty + ty, y - rty + ty))
{
return;
}
if(config.isBore())
{
for(int i = x - Math.floorDiv(w, 2); i <= x + Math.floorDiv(w, 2) - (w % 2 == 0 ? 1 : 0); i++)
{
for(int j = y - Math.floorDiv(h, 2); j <= y + Math.floorDiv(h, 2) - (h % 2 == 0 ? 1 : 0); j++)
{
for(int k = z - Math.floorDiv(d, 2); k <= z + Math.floorDiv(d, 2) - (d % 2 == 0 ? 1 : 0); k++)
{
placer.set(i, j, k, AIR); placer.set(i, j, k, AIR);
} }
} }
} }
} }
for (BlockVector g : blocks.keySet()) { for(BlockVector g : blocks.keySet())
{
BlockVector i = g.clone(); BlockVector i = g.clone();
i = config.getRotation().rotate(i.clone(), spinx, spiny, spinz).clone(); i = config.getRotation().rotate(i.clone(), spinx, spiny, spinz).clone();
i = config.getTranslate().translate(i.clone(), config.getRotation(), spinx, spiny, spinz).clone(); i = config.getTranslate().translate(i.clone(), config.getRotation(), spinx, spiny, spinz).clone();
BlockData data = blocks.get(g).clone(); BlockData data = blocks.get(g).clone();
if (placer.isPreventingDecay() && data instanceof Leaves && !((Leaves) data).isPersistent()) { if(placer.isPreventingDecay() && data instanceof Leaves && !((Leaves) data).isPersistent())
{
((Leaves) data).setPersistent(true); ((Leaves) data).setPersistent(true);
} }
for (IrisObjectReplace j : config.getEdit()) { for(IrisObjectReplace j : config.getEdit())
if (j.isExact() ? j.getFind().matches(data) : j.getFind().getMaterial().equals(data.getMaterial())) { {
data = j.getReplace(); if(j.isExact())
{
for(BlockData k : j.getFind())
{
if(j.isExact() ? k.matches(data) : k.getMaterial().equals(data.getMaterial()))
{
data = j.getReplace(rng, i.getX() + x, i.getY() + y, i.getZ() + z).clone();
}
}
} }
} }
@ -167,36 +206,49 @@ public class IrisObject extends IrisRegistrant {
int yy = y + (int) Math.round(i.getY()); int yy = y + (int) Math.round(i.getY());
int zz = z + (int) Math.round(i.getZ()); int zz = z + (int) Math.round(i.getZ());
if (heightmap != null) { if(heightmap != null)
{
ChunkPosition pos = new ChunkPosition(xx, zz); ChunkPosition pos = new ChunkPosition(xx, zz);
if (!heightmap.containsKey(pos)) { if(!heightmap.containsKey(pos))
{
heightmap.put(pos, yy); heightmap.put(pos, yy);
} }
if (heightmap.get(pos) < yy) { if(heightmap.get(pos) < yy)
{
heightmap.put(pos, yy); heightmap.put(pos, yy);
} }
} }
if (config.isMeld() && !placer.isSolid(xx, yy, zz)) { if(config.isMeld() && !placer.isSolid(xx, yy, zz))
{
continue; continue;
} }
if(yy <= placer.getFluidHeight() && data instanceof Waterlogged)
{
((Waterlogged) data).setWaterlogged(true);
}
placer.set(xx, yy, zz, data); placer.set(xx, yy, zz, data);
} }
if (heightmap != null) { if(heightmap != null)
{
RNG rngx = rng.nextParallelRNG(3468854); RNG rngx = rng.nextParallelRNG(3468854);
for (ChunkPosition i : heightmap.k()) { for(ChunkPosition i : heightmap.k())
{
int vx = i.getX(); int vx = i.getX();
int vy = heightmap.get(i); int vy = heightmap.get(i);
int vz = i.getZ(); int vz = i.getZ();
if (config.getSnow() > 0) { if(config.getSnow() > 0)
{
BlockData bd = placer.get(vx, vy, vz); BlockData bd = placer.get(vx, vy, vz);
if (bd != null && bd.getMaterial().equals(SNOW)) { if(bd != null && bd.getMaterial().equals(SNOW))
{
continue; continue;
} }
@ -207,8 +259,10 @@ public class IrisObject extends IrisRegistrant {
} }
} }
public void place(Location at) { public void place(Location at)
for (BlockVector i : blocks.keySet()) { {
for(BlockVector i : blocks.keySet())
{
at.clone().add(0, getCenter().getY(), 0).add(i).getBlock().setBlockData(blocks.get(i), false); at.clone().add(0, getCenter().getY(), 0).add(i).getBlock().setBlockData(blocks.get(i), false);
} }
} }

View File

@ -0,0 +1,40 @@
package com.volmit.iris.object;
import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber;
import lombok.Data;
@Desc("Translate objects")
@Data
public class IrisObjectLimit
{
@MinNumber(0)
@MaxNumber(255)
@DontObfuscate
@Desc("The minimum height for placement (bottom of object)")
private int minimumHeight = 0;
@MinNumber(0)
@MaxNumber(255)
@DontObfuscate
@Desc("The maximum height for placement (top of object)")
private int maximumHeight = 255;
public IrisObjectLimit()
{
}
public boolean canPlace(int h, int l)
{
if(h > maximumHeight || l < minimumHeight)
{
return false;
}
return true;
}
}

View File

@ -9,6 +9,7 @@ import com.volmit.iris.util.KList;
import com.volmit.iris.util.MaxNumber; import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.RNG; import com.volmit.iris.util.RNG;
import com.volmit.iris.util.RegistryListObject;
import com.volmit.iris.util.Required; import com.volmit.iris.util.Required;
import lombok.Data; import lombok.Data;
@ -17,6 +18,7 @@ import lombok.Data;
@Data @Data
public class IrisObjectPlacement public class IrisObjectPlacement
{ {
@RegistryListObject
@Required @Required
@ArrayType(min = 1, type = String.class) @ArrayType(min = 1, type = String.class)
@DontObfuscate @DontObfuscate
@ -36,6 +38,10 @@ public class IrisObjectPlacement
@Desc("Rotate this objects placement") @Desc("Rotate this objects placement")
private IrisObjectRotation rotation = new IrisObjectRotation(); private IrisObjectRotation rotation = new IrisObjectRotation();
@DontObfuscate
@Desc("Limit the max height or min height of placement.")
private IrisObjectLimit clamp = new IrisObjectLimit();
@MinNumber(0) @MinNumber(0)
@MaxNumber(1) @MaxNumber(1)
@DontObfuscate @DontObfuscate

View File

@ -3,9 +3,13 @@ package com.volmit.iris.object;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import com.volmit.iris.gen.atomics.AtomicCache; import com.volmit.iris.gen.atomics.AtomicCache;
import com.volmit.iris.noise.CNG;
import com.volmit.iris.util.ArrayType;
import com.volmit.iris.util.B; import com.volmit.iris.util.B;
import com.volmit.iris.util.Desc; import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.KList;
import com.volmit.iris.util.RNG;
import com.volmit.iris.util.Required; import com.volmit.iris.util.Required;
import lombok.Data; import lombok.Data;
@ -14,35 +18,43 @@ import lombok.Data;
@Data @Data
public class IrisObjectReplace public class IrisObjectReplace
{ {
@ArrayType(min = 1, type = String.class)
@Required @Required
@Desc("Find this block") @Desc("Find this block")
@DontObfuscate @DontObfuscate
private String find; private KList<String> find;
@ArrayType(min = 1, type = String.class)
@Required @Required
@Desc("Replace it with this block") @Desc("Replace it with this block")
@DontObfuscate @DontObfuscate
private String replace; private KList<String> replace;
@Desc("Exactly match the block data or not") @Desc("Exactly match the block data or not")
@DontObfuscate @DontObfuscate
private boolean exact = false; private boolean exact = false;
private transient AtomicCache<BlockData> findData = new AtomicCache<>(); private transient AtomicCache<CNG> replaceGen = new AtomicCache<>();
private transient AtomicCache<BlockData> replaceData = new AtomicCache<>(); private transient AtomicCache<KList<BlockData>> findData = new AtomicCache<>();
private transient AtomicCache<KList<BlockData>> replaceData = new AtomicCache<>();
public IrisObjectReplace() public IrisObjectReplace()
{ {
} }
public BlockData getFind() public KList<BlockData> getFind()
{ {
return findData.aquire(() -> B.getBlockData(find)); return findData.aquire(() -> B.getBlockData(find));
} }
public BlockData getReplace() public KList<BlockData> getReplace()
{ {
return replaceData.aquire(() -> B.getBlockData(replace)); return replaceData.aquire(() -> B.getBlockData(replace));
} }
public BlockData getReplace(RNG seed, double x, double y, double z)
{
return replaceGen.aquire(() -> NoiseStyle.STATIC.create(seed).bake()).fit(getReplace(), x, y, z);
}
} }

View File

@ -7,6 +7,7 @@ import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.MaxNumber; import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.RNG; import com.volmit.iris.util.RNG;
import com.volmit.iris.util.RegistryListBiome;
import com.volmit.iris.util.Required; import com.volmit.iris.util.Required;
import lombok.Data; import lombok.Data;
@ -15,6 +16,7 @@ import lombok.Data;
@Data @Data
public class IrisRegionRidge public class IrisRegionRidge
{ {
@RegistryListBiome
@Required @Required
@DontObfuscate @DontObfuscate
@Desc("The biome name") @Desc("The biome name")

View File

@ -6,6 +6,7 @@ import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.RNG; import com.volmit.iris.util.RNG;
import com.volmit.iris.util.RegistryListBiome;
import com.volmit.iris.util.Required; import com.volmit.iris.util.Required;
import lombok.Data; import lombok.Data;
@ -14,6 +15,7 @@ import lombok.Data;
@Data @Data
public class IrisRegionSpot public class IrisRegionSpot
{ {
@RegistryListBiome
@Required @Required
@DontObfuscate @DontObfuscate
@Desc("The biome to be placed") @Desc("The biome to be placed")

View File

@ -10,6 +10,7 @@ import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.MaxNumber; import com.volmit.iris.util.MaxNumber;
import com.volmit.iris.util.MinNumber; import com.volmit.iris.util.MinNumber;
import com.volmit.iris.util.RNG; import com.volmit.iris.util.RNG;
import com.volmit.iris.util.RegistryListStructure;
import com.volmit.iris.util.Required; import com.volmit.iris.util.Required;
import lombok.Data; import lombok.Data;
@ -18,6 +19,7 @@ import lombok.Data;
@Data @Data
public class IrisStructurePlacement public class IrisStructurePlacement
{ {
@RegistryListStructure
@Required @Required
@DontObfuscate @DontObfuscate
@Desc("The structure tileset to use") @Desc("The structure tileset to use")

View File

@ -4,6 +4,7 @@ import com.volmit.iris.util.ArrayType;
import com.volmit.iris.util.Desc; import com.volmit.iris.util.Desc;
import com.volmit.iris.util.DontObfuscate; import com.volmit.iris.util.DontObfuscate;
import com.volmit.iris.util.KList; import com.volmit.iris.util.KList;
import com.volmit.iris.util.RegistryListObject;
import com.volmit.iris.util.Required; import com.volmit.iris.util.Required;
import lombok.Data; import lombok.Data;
@ -45,6 +46,7 @@ public class IrisStructureTile
@Desc("Is this structure allowed to place if there is supposed to be a west wall?") @Desc("Is this structure allowed to place if there is supposed to be a west wall?")
private StructureTileCondition west = StructureTileCondition.AGNOSTIC; private StructureTileCondition west = StructureTileCondition.AGNOSTIC;
@RegistryListObject
@Required @Required
@ArrayType(min = 1, type = String.class) @ArrayType(min = 1, type = String.class)
@DontObfuscate @DontObfuscate

View File

@ -13,12 +13,23 @@ public class B
private static final KMap<String, BlockData> bdc = new KMap<>(); private static final KMap<String, BlockData> bdc = new KMap<>();
private static final KList<String> nulls = new KList<>(); private static final KList<String> nulls = new KList<>();
private static final IrisDimension defaultCompat = new IrisDimension(); private static final IrisDimension defaultCompat = new IrisDimension();
private static final KMap<Material, Boolean> solid = new KMap<>();
public static BlockData get(String bd) public static BlockData get(String bd)
{ {
return getBlockData(bd); return getBlockData(bd);
} }
public static boolean isSolid(Material mat)
{
if(!solid.containsKey(mat))
{
solid.put(mat, mat.isSolid());
}
return solid.get(mat);
}
public static Material mat(String bd) public static Material mat(String bd)
{ {
return getBlockData(bd).getMaterial(); return getBlockData(bd).getMaterial();
@ -214,4 +225,21 @@ public class B
|| m.equals(B.mat("SOUL_TORCH")); || m.equals(B.mat("SOUL_TORCH"));
//@done //@done
} }
public static KList<BlockData> getBlockData(KList<String> find)
{
KList<BlockData> b = new KList<>();
for(String i : find)
{
BlockData bd = getBlockData(i);
if(bd != null)
{
b.add(bd);
}
}
return b;
}
} }

View File

@ -2,14 +2,9 @@ package com.volmit.iris.util;
import java.io.File; import java.io.File;
import lombok.Data;
import lombok.Getter;
@Data
public class FileWatcher public class FileWatcher
{ {
@Getter protected final File file;
private final File file;
private boolean exists; private boolean exists;
private long lastModified; private long lastModified;
private long size; private long size;
@ -20,11 +15,11 @@ public class FileWatcher
readProperties(); readProperties();
} }
private void readProperties() protected void readProperties()
{ {
exists = file.exists(); exists = file.exists();
lastModified = exists ? file.lastModified() : -1; lastModified = exists ? file.lastModified() : -1;
size = exists ? file.length() : -1; size = exists ? file.isDirectory() ? -2 : file.length() : -1;
} }
public boolean checkModified() public boolean checkModified()

View File

@ -0,0 +1,122 @@
package com.volmit.iris.util;
import java.io.File;
public class FolderWatcher extends FileWatcher
{
private KMap<File, FolderWatcher> watchers;
private KList<File> changed;
private KList<File> created;
private KList<File> deleted;
public FolderWatcher(File file)
{
super(file);
}
protected void readProperties()
{
if(watchers == null)
{
watchers = new KMap<>();
changed = new KList<>();
created = new KList<>();
deleted = new KList<>();
}
if(file.isDirectory())
{
for(File i : file.listFiles())
{
if(!watchers.containsKey(i))
{
watchers.put(i, new FolderWatcher(i));
}
}
if(watchers == null)
{
System.out.print("wtf");
}
for(File i : watchers.k())
{
if(!i.exists())
{
watchers.remove(i);
}
}
}
else
{
super.readProperties();
}
}
public boolean checkModified()
{
changed.clear();
created.clear();
deleted.clear();
if(file.isDirectory())
{
KMap<File, FolderWatcher> w = watchers.copy();
readProperties();
for(File i : w.k())
{
if(!watchers.containsKey(i))
{
deleted.add(i);
}
}
for(File i : watchers.k())
{
if(!w.containsKey(i))
{
created.add(i);
}
else
{
FolderWatcher fw = watchers.get(i);
if(fw.checkModified())
{
changed.add(fw.file);
}
changed.addAll(fw.getChanged());
created.addAll(fw.getCreated());
deleted.addAll(fw.getDeleted());
}
}
return !changed.isEmpty() || !created.isEmpty() || !deleted.isEmpty();
}
return super.checkModified();
}
public KMap<File, FolderWatcher> getWatchers()
{
return watchers;
}
public KList<File> getChanged()
{
return changed;
}
public KList<File> getCreated()
{
return created;
}
public KList<File> getDeleted()
{
return deleted;
}
}

View File

@ -2,7 +2,8 @@ package com.volmit.iris.util;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
public interface IObjectPlacer { public interface IObjectPlacer
{
public int getHighest(int x, int z); public int getHighest(int x, int z);
public int getHighest(int x, int z, boolean ignoreFluid); public int getHighest(int x, int z, boolean ignoreFluid);
@ -16,4 +17,6 @@ public interface IObjectPlacer {
public boolean isSolid(int x, int y, int z); public boolean isSolid(int x, int y, int z);
public boolean isUnderwater(int x, int z); public boolean isUnderwater(int x, int z);
public int getFluidHeight();
} }

View File

@ -100,6 +100,43 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject>
} }
} }
public String[] getPossibleKeys()
{
if(possibleKeys != null)
{
return possibleKeys;
}
Iris.info("Building " + resourceTypeName + " Possibility Lists");
KSet<String> m = new KSet<>();
for(File i : getFolders())
{
for(File j : i.listFiles())
{
if(j.isFile() && j.getName().endsWith(".iob"))
{
m.add(j.getName().replaceAll("\\Q.json\\E", ""));
}
else if(j.isDirectory())
{
for(File k : j.listFiles())
{
if(k.isFile() && k.getName().endsWith(".iob"))
{
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.iob\\E", ""));
}
}
}
}
}
KList<String> v = new KList<>(m);
possibleKeys = v.toArray(new String[v.size()]);
return possibleKeys;
}
public File findFile(String name) public File findFile(String name)
{ {
lock.lock(); lock.lock();

View File

@ -0,0 +1,14 @@
package com.volmit.iris.util;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target({PARAMETER, TYPE, FIELD})
public @interface RegistryListBiome
{
}

View File

@ -0,0 +1,14 @@
package com.volmit.iris.util;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target({PARAMETER, TYPE, FIELD})
public @interface RegistryListDimension
{
}

View File

@ -0,0 +1,14 @@
package com.volmit.iris.util;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target({PARAMETER, TYPE, FIELD})
public @interface RegistryListGenerator
{
}

View File

@ -0,0 +1,14 @@
package com.volmit.iris.util;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target({PARAMETER, TYPE, FIELD})
public @interface RegistryListObject
{
}

View File

@ -0,0 +1,14 @@
package com.volmit.iris.util;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target({PARAMETER, TYPE, FIELD})
public @interface RegistryListRegion
{
}

View File

@ -0,0 +1,14 @@
package com.volmit.iris.util;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target({PARAMETER, TYPE, FIELD})
public @interface RegistryListStructure
{
}

View File

@ -21,6 +21,7 @@ public class ResourceLoader<T extends IrisRegistrant>
protected String cname; protected String cname;
protected IrisLock lock; protected IrisLock lock;
protected String preferredFolder = null; protected String preferredFolder = null;
protected String[] possibleKeys = null;
public ResourceLoader(File root, String folderName, String resourceTypeName, Class<? extends T> objectClass) public ResourceLoader(File root, String folderName, String resourceTypeName, Class<? extends T> objectClass)
{ {
@ -34,6 +35,43 @@ public class ResourceLoader<T extends IrisRegistrant>
loadCache = new KMap<>(); loadCache = new KMap<>();
} }
public String[] getPossibleKeys()
{
if(possibleKeys != null)
{
return possibleKeys;
}
Iris.info("Building " + resourceTypeName + " Possibility Lists");
KSet<String> m = new KSet<>();
for(File i : getFolders())
{
for(File j : i.listFiles())
{
if(j.isFile() && j.getName().endsWith(".json"))
{
m.add(j.getName().replaceAll("\\Q.json\\E", ""));
}
else if(j.isDirectory())
{
for(File k : j.listFiles())
{
if(k.isFile() && k.getName().endsWith(".json"))
{
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.json\\E", ""));
}
}
}
}
}
KList<String> v = new KList<>(m);
possibleKeys = v.toArray(new String[v.size()]);
return possibleKeys;
}
public long count() public long count()
{ {
return loadCache.size(); return loadCache.size();
@ -155,6 +193,7 @@ public class ResourceLoader<T extends IrisRegistrant>
public void clearCache() public void clearCache()
{ {
possibleKeys = null;
loadCache.clear(); loadCache.clear();
folderCache = null; folderCache = null;
} }
@ -191,4 +230,10 @@ public class ResourceLoader<T extends IrisRegistrant>
{ {
preferredFolder = name; preferredFolder = name;
} }
public void clearList()
{
folderCache = null;
possibleKeys = null;
}
} }