9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-27 02:59:06 +00:00
This commit is contained in:
RePixelatedMC
2024-05-29 10:18:04 +02:00
101 changed files with 6771 additions and 2793 deletions

View File

@@ -31,7 +31,7 @@ Consider supporting our development by buying Iris on spigot! We work hard to ma
4. Use `CTRL + X`, then Press `Y`, Then `ENTER`
5. Quit & Reopen Terminal and verify with `echo $JAVA_HOME`. It should print a directory
3. If this is your first time building Iris for MC 1.18+ run `gradlew setup` inside the root Iris project folder.
Otherwise, skip this step. Grab a coffee, this may take up to 5 minutes depending on your cpu & internet connection.
Otherwise, skip this step. Grab a coffee, this may take up to 45 minutes depending on your cpu & internet connection.
4. Once the project has setup, run `gradlew iris`
5. The Iris jar will be placed in `Iris/build/Iris-XXX-XXX.jar` Enjoy! Consider supporting us by buying it on spigot!
@@ -69,7 +69,6 @@ IrisAccess access=IrisToolbelt.createWorld() // If you like builders...
.name("myWorld") // The world name
.dimension("terrifyinghands")
.seed(69133742) // The world seed
.headless(true) // Headless make gen go fast
.pregen(PregenTask // Define a pregen job to run
.builder()
.center(new Position2(0,0)) // REGION coords (1 region = 32x32 chunks)

View File

@@ -1,5 +1,3 @@
import java.util.function.Consumer
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
@@ -21,12 +19,12 @@ import java.util.function.Consumer
plugins {
id 'java'
id 'java-library'
id "com.github.johnrengelman.shadow" version "7.1.2"
id "io.github.goooler.shadow" version "8.1.7"
id "de.undercouch.download" version "5.0.1"
}
version '3.0.0-1.19.2-1.20.4'
def specialSourceVersion = '1.11.0' //[NMS]
version '3.2.6-1.19.2-1.20.4'
def specialSourceVersion = '1.11.4' //[NMS]
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
// ======================== WINDOWS =============================
@@ -37,13 +35,14 @@ registerCustomOutputTask('Coco', 'D://mcsm/plugins')
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins')
registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins')
registerCustomOutputTask('Pixel', 'C://Users/repix/Iris Dimension Engine/1.20.1 - Iris Coding/plugins')
registerCustomOutputTask('Pixel', 'C://Users/repix/Iris Dimension Engine/1.20.4 - Development/plugins')
// ========================== UNIX ==============================
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
registerCustomOutputTaskUnix('PsychoLT', '/Volumes/PRO-G40/Minecraft/MinecraftDevelopment/Server/plugins')
// ==============================================================
def NMS_BINDINGS = Map.of(
"v1_20_R4", "1.20.6-R0.1-SNAPSHOT",
"v1_20_R3", "1.20.4-R0.1-SNAPSHOT",
"v1_20_R2", "1.20.2-R0.1-SNAPSHOT",
"v1_20_R1", "1.20.1-R0.1-SNAPSHOT",
@@ -51,11 +50,15 @@ def NMS_BINDINGS = Map.of(
"v1_19_R2", "1.19.3-R0.1-SNAPSHOT",
"v1_19_R1", "1.19.2-R0.1-SNAPSHOT"
)
def JVM_VERSION = Map.of(
"v1_20_R4", 21,
)
NMS_BINDINGS.each {
def key = it.key
def value = it.value
def nms = value.split("-")[0];
project(":nms:${key}") {
apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'de.undercouch.download'
@@ -64,9 +67,10 @@ NMS_BINDINGS.each {
compileOnly "org.spigotmc:spigot-api:${value}"
compileOnly "org.bukkit:craftbukkit:${value}:remapped-mojang" //[NMS]
}
def buildToolsJar = new File(rootProject.buildDir, "tools/BuildTools.jar")
def specialSourceJar = new File(rootProject.buildDir, "tools/SpecialSource.jar")
def buildToolsJar = new File(rootProject.layout.buildDirectory.asFile.get(), "tools/BuildTools.jar")
def specialSourceJar = new File(rootProject.layout.buildDirectory.asFile.get(), "tools/SpecialSource.jar")
def buildDir = layout.buildDirectory.asFile.get();
def buildToolsFolder = new File(buildDir, "buildtools")
def specialSourceFolder = new File(buildDir, "specialsource")
def buildToolsHint = new File(buildDir, "buildtools/craftbukkit-" + nms + ".jar")
@@ -81,6 +85,22 @@ NMS_BINDINGS.each {
def m2s = m2.getAbsolutePath();
// ======================== Building Mapped Jars =============================
def targetJavaVersion = JVM_VERSION.getOrDefault(key, 17)
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
def javaLanguageVersion = JavaLanguageVersion.of(targetJavaVersion)
project.java.sourceCompatibility = javaVersion
project.java.targetCompatibility = javaVersion
project.java.toolchain.languageVersion = javaLanguageVersion
def launcher = javaToolchains.launcherFor(java.toolchain).get()
def javaHome = launcher.executablePath.getAsFile().parentFile.parentFile.getAbsolutePath()
tasks.withType(JavaCompile).configureEach {
options.release.set(targetJavaVersion)
}
tasks.withType(JavaExec).configureEach {
javaLauncher.set(launcher)
}
ext {
executeBuildTools = new Runnable() {
@@ -98,6 +118,7 @@ NMS_BINDINGS.each {
if (!buildToolsHint.exists()) {
buildToolsFolder.mkdirs()
project.javaexec {
executable = launcher.executablePath
classpath = files(buildToolsJar)
workingDir = buildToolsFolder
args = [
@@ -107,16 +128,14 @@ NMS_BINDINGS.each {
"craftbukkit",
"--remap"
]
def env = new HashMap(environment)
env.put("JAVA_HOME", javaHome)
environment = env
}
}
}
}
}
tasks.register("executeBuildTools") {
doLast {
property("executeBuildTools").run();
}
}
tasks.build.doLast {
//Download
@@ -136,6 +155,7 @@ NMS_BINDINGS.each {
//obfuscate
javaexec {
executable = launcher.executablePath
workingDir = specialSourceFolder
classpath = files(specialSourceJar,
new File(m2s + "/org/spigotmc/spigot/" + value + "/spigot-" + value + "-remapped-mojang.jar"))
@@ -150,10 +170,14 @@ NMS_BINDINGS.each {
m2s + "/org/spigotmc/minecraft-server/" + value + "/minecraft-server-" + value + "-maps-mojang.txt",
"--reverse",
]
def env = new HashMap(environment)
env.put("JAVA_HOME", javaHome)
environment = env
}
//remap
javaexec {
executable = launcher.executablePath
workingDir = specialSourceFolder
classpath = files(specialSourceJar,
new File(m2s + "/org/spigotmc/spigot/" + value + "/spigot-" + value + "-remapped-obf.jar"))
@@ -167,6 +191,9 @@ NMS_BINDINGS.each {
"-m",
m2s + "/org/spigotmc/minecraft-server/" + value + "/minecraft-server-" + value + "-maps-spigot.csrg"
]
def env = new HashMap(environment)
env.put("JAVA_HOME", javaHome)
environment = env
}
//copy
copy {
@@ -181,7 +208,10 @@ NMS_BINDINGS.each {
}
shadowJar {
NMS_BINDINGS.each {dependsOn(":nms:${it.key}:build")}
NMS_BINDINGS.each {
dependsOn(":nms:${it.key}:build")
from("${project(":nms:${it.key}").layout.buildDirectory.asFile.get()}/libs/${it.key}.jar")
}
//minimize()
append("plugin.yml")
@@ -193,9 +223,6 @@ shadowJar {
dependencies {
implementation project(':core')
NMS_BINDINGS.each {
implementation project(":nms:${it.key}")
}
}
configurations.configureEach {
@@ -235,8 +262,10 @@ allprojects {
implementation 'com.dfsek:Paralithic:0.4.0'
implementation 'io.papermc:paperlib:1.0.5'
implementation "net.kyori:adventure-text-minimessage:4.13.1"
implementation 'net.kyori:adventure-platform-bukkit:4.3.0'
implementation 'net.kyori:adventure-platform-bukkit:4.3.2'
implementation 'net.kyori:adventure-api:4.13.1'
//implementation 'org.bytedeco:javacpp:1.5.10'
//implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10'
compileOnly 'io.lumine:Mythic-Dist:5.2.1'
// Dynamically Loaded
@@ -244,9 +273,9 @@ allprojects {
compileOnly 'it.unimi.dsi:fastutil:8.5.8'
compileOnly 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
compileOnly 'org.zeroturnaround:zt-zip:1.14'
compileOnly 'com.google.code.gson:gson:2.9.0'
compileOnly 'com.google.code.gson:gson:2.10.1'
compileOnly 'org.ow2.asm:asm:9.2'
compileOnly 'com.google.guava:guava:31.1-jre'
compileOnly 'com.google.guava:guava:33.0.0-jre'
compileOnly 'bsf:bsf:2.4.0'
compileOnly 'rhino:js:1.7R2'
compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6'
@@ -282,8 +311,8 @@ if (JavaVersion.current().toString() != "17") {
task iris(type: Copy) {
group "iris"
from new File(buildDir, "libs/Iris-${version}.jar")
into buildDir
from new File(layout.buildDirectory.asFile.get(), "libs/Iris-${version}.jar")
into layout.buildDirectory.asFile.get()
dependsOn(build)
}
@@ -306,7 +335,9 @@ NMS_BINDINGS.keySet().forEach {
tasks.register("setup-${nms}") {
group "iris"
dependsOn(":nms:${nms}:clean")
dependsOn(":nms:${nms}:executeBuildTools")
doLast {
project(":nms:${nms}").property("executeBuildTools").run();
}
}
}

View File

@@ -19,7 +19,7 @@
plugins {
id 'java'
id 'java-library'
id "io.freefair.lombok" version "6.3.0"
id "io.freefair.lombok" version "8.6"
}
def apiVersion = '1.19'
@@ -33,6 +33,11 @@ compileJava {
options.encoding = "UTF-8"
}
repositories {
maven { url 'https://nexus.phoenixdevt.fr/repository/maven-public/'}
maven { url 'https://repo.auxilor.io/repository/maven-public/' }
}
/**
* Dependencies.
*
@@ -61,6 +66,8 @@ dependencies {
compileOnly 'com.github.LoneDev6:api-itemsadder:3.4.1-r4'
compileOnly 'com.github.PlaceholderAPI:placeholderapi:2.11.3'
compileOnly 'com.github.Ssomar-Developement:SCore:4.23.10.8'
compileOnly 'net.Indyuce:MMOItems-API:6.9.5-SNAPSHOT'
compileOnly 'com.willfp:EcoItems:5.44.0'
//implementation files('libs/CustomItems.jar')
}

View File

@@ -128,6 +128,10 @@ public class Iris extends VolmitPlugin implements Listener {
private KMap<Class<? extends IrisService>, IrisService> services;
public static VolmitSender getSender() {
if (sender == null) {
sender = new VolmitSender(Bukkit.getConsoleSender());
sender.setTag(instance.getTag());
}
return sender;
}
@@ -194,10 +198,10 @@ public class Iris extends VolmitPlugin implements Listener {
public static void msg(String string) {
try {
sender.sendMessage(string);
getSender().sendMessage(string);
} catch (Throwable e) {
try {
System.out.println(instance.getTag() + string.replaceAll("(<([^>]+)>)", ""));
instance.getLogger().info(instance.getTag() + string.replaceAll("(<([^>]+)>)", ""));
} catch (Throwable ignored1) {
}
@@ -364,6 +368,13 @@ public class Iris extends VolmitPlugin implements Listener {
return Integer.parseInt(version);
}
public static String getJava() {
String javaRuntimeName = System.getProperty("java.vm.name");
String javaRuntimeVendor = System.getProperty("java.vendor");
String javaRuntimeVersion = System.getProperty("java.vm.version");
return String.format("%s %s (build %s)", javaRuntimeName, javaRuntimeVendor, javaRuntimeVersion);
}
public static void reportErrorChunk(int x, int z, Throwable e, String extra) {
if (IrisSettings.get().getGeneral().isDebug()) {
File f = instance.getDataFile("debug", "chunk-errors", "chunk." + x + "." + z + ".txt");
@@ -426,7 +437,7 @@ public class Iris extends VolmitPlugin implements Listener {
}
pw.close();
System.out.println("DUMPED! See " + fi.getAbsolutePath());
Iris.info("DUMPED! See " + fi.getAbsolutePath());
} catch (Throwable e) {
e.printStackTrace();
}
@@ -446,14 +457,12 @@ public class Iris extends VolmitPlugin implements Listener {
private void enable() {
instance = this;
services = new KMap<>();
setupAudience();
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
INMS.get();
IO.delete(new File("iris"));
setupAudience();
IrisSafeguard.IrisSafeguardSystem();
sender = new VolmitSender(Bukkit.getConsoleSender());
sender.setTag(getTag());
instance = this;
getSender().setTag(getTag());
compat = IrisCompat.configured(getDataFile("compat.json"));
linkMultiverseCore = new MultiverseCoreLink();
linkMythicMobs = new MythicMobsLink();
@@ -526,7 +535,7 @@ public class Iris extends VolmitPlugin implements Listener {
Iris.info("Starting up auto Studio!");
try {
Player r = new KList<>(getServer().getOnlinePlayers()).getRandom();
Iris.service(StudioSVC.class).open(r != null ? new VolmitSender(r) : sender, 1337, IrisSettings.get().getGenerator().getDefaultWorldType(), (w) -> {
Iris.service(StudioSVC.class).open(r != null ? new VolmitSender(r) : getSender(), 1337, IrisSettings.get().getGenerator().getDefaultWorldType(), (w) -> {
J.s(() -> {
for (Player i : getServer().getOnlinePlayers()) {
i.setGameMode(GameMode.SPECTATOR);
@@ -727,10 +736,10 @@ public class Iris extends VolmitPlugin implements Listener {
File ff = new File(w.worldFolder(), "iris/pack");
if (!ff.exists() || ff.listFiles().length == 0) {
ff.mkdirs();
service(StudioSVC.class).installIntoWorld(sender, dim.getLoadKey(), w.worldFolder());
service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w.worldFolder());
}
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey(), false);
}
public void splash() {
@@ -797,13 +806,11 @@ public class Iris extends VolmitPlugin implements Listener {
} else {
splash = splashstable;
}
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
String osArch = osBean.getArch();
String osName = osBean.getName();
if (!passedserversoftware) {
Iris.info("Server type & version: " + C.RED + Bukkit.getVersion());
} else { Iris.info("Server type & version: " + Bukkit.getVersion()); }
Iris.info("Java: " + getJava());
if (!instance.getServer().getVersion().contains("Purpur")) {
if (instance.getServer().getVersion().contains("Spigot") && instance.getServer().getVersion().contains("Bukkit")) {
Iris.info(C.RED + " Iris requires paper or above to function properly..");
@@ -811,38 +818,11 @@ public class Iris extends VolmitPlugin implements Listener {
Iris.info(C.YELLOW + "Purpur is recommended to use with iris.");
}
}
Iris.info("Server OS: " + osName + " (" + osArch + ")");
try {
if (warningmode){
Iris.info("Server Cpu: " + C.GOLD + getCPUModel());
} else {
if(unstablemode){
Iris.info("Server Cpu: " + C.DARK_RED + getCPUModel());
} else {
if (getCPUModel().contains("Intel")) {
Iris.info("Server Cpu: " + C.BLUE + getCPUModel());
}
if (getCPUModel().contains("Ryzen")) {
Iris.info("Server Cpu: " + C.RED + getCPUModel());
}
if (!getCPUModel().contains("Ryzen") && !getCPUModel().contains("Intel")) {
Iris.info("Server Cpu: " + C.GRAY + getCPUModel());
}
}
}
} catch (Exception e){
Iris.info("Server Cpu: " + C.DARK_RED + "Failed");
}
Iris.info("Process Threads: " + Runtime.getRuntime().availableProcessors());
Iris.info("Process Memory: " + getHardware.getProcessMemory() + " MB");
Iris.info("Free DiskSpace: " + Form.ofSize(freeSpace.getFreeSpace(), 1024));
if (getHardware.getProcessMemory() < 5999) {
Iris.warn("6GB+ Ram is recommended");
Iris.warn("Process Memory: " + getHardware.getProcessMemory() + " MB");
}
Iris.info("Bukkit version: " + Bukkit.getBukkitVersion());
Iris.info("Java version: " + getJavaVersion());
Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes());
setupChecks();
printPacks();

View File

@@ -24,6 +24,7 @@ import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.json.JSONException;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.ChronoLatch;
import lombok.Data;
import java.io.File;
@@ -135,7 +136,7 @@ public class IrisSettings {
@Data
public static class IrisSettingsPerformance {
public boolean trimMantleInStudio = false;
public boolean trimMantleInStudio = false;
public int mantleKeepAlive = 30;
public int cacheSize = 4_096;
public int resourceLoaderCacheSize = 1_024;

View File

@@ -21,9 +21,12 @@ package com.volmit.iris.core;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.engine.object.IrisRange;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.format.C;
@@ -90,10 +93,36 @@ public class ServerConfigurator {
return worlds;
}
public static void installDataPacks(boolean fullInstall) {
installDataPacks(DataVersion.getDefault(), fullInstall);
}
public static void installDataPacks(IDataFixer fixer, boolean fullInstall) {
Iris.info("Checking Data Packs...");
File packs = new File("plugins/Iris/packs");
double ultimateMaxHeight = 0;
double ultimateMinHeight = 0;
if (packs.exists() && packs.isDirectory()) {
for (File pack : packs.listFiles()) {
IrisData data = IrisData.get(pack);
if (pack.isDirectory()) {
File dimensionsFolder = new File(pack, "dimensions");
if (dimensionsFolder.exists() && dimensionsFolder.isDirectory()) {
for (File file : dimensionsFolder.listFiles()) {
if (file.isFile() && file.getName().endsWith(".json")) {
IrisDimension dim = data.getDimensionLoader().load(file.getName().split("\\Q.\\E")[0]);
if (ultimateMaxHeight < dim.getDimensionHeight().getMax()) {
ultimateMaxHeight = dim.getDimensionHeight().getMax();
}
if (ultimateMinHeight > dim.getDimensionHeight().getMin()) {
ultimateMinHeight = dim.getDimensionHeight().getMin();
}
}
}
}
}
}
}
if (packs.exists()) {
for (File i : packs.listFiles()) {
@@ -113,7 +142,7 @@ public class ServerConfigurator {
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
for (File dpack : getDatapacksFolder()) {
dim.installDataPack(() -> data, dpack);
dim.installDataPack(fixer, () -> data, dpack, ultimateMaxHeight, ultimateMinHeight);
}
}
}

View File

@@ -74,7 +74,7 @@ public class CommandDeepSearch implements DecreeExecutor {
}
DeepSearchPregenerator.DeepSearchJob DeepSearchJob = DeepSearchPregenerator.DeepSearchJob.builder()
.world(worldName)
.world(world)
.radiusBlocks(radius)
.position(0)
.build();

View File

@@ -19,10 +19,22 @@
package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.service.IrisEngineSVC;
import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.mantle.components.MantleObjectComponent;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisCave;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.engine.object.IrisEntity;
import com.volmit.iris.util.data.Dimension;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.DecreeOrigin;
import com.volmit.iris.util.decree.annotations.Decree;
@@ -31,18 +43,31 @@ import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.mantle.TectonicPlate;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.nbt.mca.MCAFile;
import com.volmit.iris.util.nbt.mca.MCAUtil;
import com.volmit.iris.util.plugin.VolmitSender;
import io.lumine.mythic.bukkit.adapters.BukkitEntity;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import net.jpountz.lz4.LZ4FrameInputStream;
import net.jpountz.lz4.LZ4FrameOutputStream;
import org.apache.commons.lang.RandomStringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Creeper;
import org.bukkit.entity.EntityType;
import java.io.*;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@@ -51,36 +76,161 @@ public class CommandDeveloper implements DecreeExecutor {
private CommandTurboPregen turboPregen;
@Decree(description = "Get Loaded TectonicPlates Count", origin = DecreeOrigin.BOTH, sync = true)
public void EngineStatus(
@Param(description = "World")
public void EngineStatus() {
List<World> IrisWorlds = new ArrayList<>();
int TotalLoadedChunks = 0;
int TotalQueuedTectonicPlates = 0;
int TotalNotQueuedTectonicPlates = 0;
int TotalTectonicPlates = 0;
long lowestUnloadDuration = 0;
long highestUnloadDuration = 0;
for (World world : Bukkit.getWorlds()) {
try {
if (IrisToolbelt.access(world).getEngine() != null) {
IrisWorlds.add(world);
}
} catch (Exception e) {
// no
}
}
for (World world : IrisWorlds) {
Engine engine = IrisToolbelt.access(world).getEngine();
TotalQueuedTectonicPlates += (int) engine.getMantle().getToUnload();
TotalNotQueuedTectonicPlates += (int) engine.getMantle().getNotQueuedLoadedRegions();
TotalTectonicPlates += engine.getMantle().getLoadedRegionCount();
if (highestUnloadDuration <= (long) engine.getMantle().getTectonicDuration()) {
highestUnloadDuration = (long) engine.getMantle().getTectonicDuration();
}
if (lowestUnloadDuration >= (long) engine.getMantle().getTectonicDuration()) {
lowestUnloadDuration = (long) engine.getMantle().getTectonicDuration();
}
for (Chunk chunk : world.getLoadedChunks()) {
if (chunk.isLoaded()) {
TotalLoadedChunks++;
}
}
}
Iris.info("-------------------------");
Iris.info(C.DARK_PURPLE + "Engine Status");
Iris.info(C.DARK_PURPLE + "Total Loaded Chunks: " + C.LIGHT_PURPLE + TotalLoadedChunks);
Iris.info(C.DARK_PURPLE + "Tectonic Limit: " + C.LIGHT_PURPLE + IrisEngineSVC.getTectonicLimit());
Iris.info(C.DARK_PURPLE + "Tectonic Total Plates: " + C.LIGHT_PURPLE + TotalTectonicPlates);
Iris.info(C.DARK_PURPLE + "Tectonic Active Plates: " + C.LIGHT_PURPLE + TotalNotQueuedTectonicPlates);
Iris.info(C.DARK_PURPLE + "Tectonic ToUnload: " + C.LIGHT_PURPLE + TotalQueuedTectonicPlates);
Iris.info(C.DARK_PURPLE + "Lowest Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration(lowestUnloadDuration));
Iris.info(C.DARK_PURPLE + "Highest Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration(highestUnloadDuration));
Iris.info(C.DARK_PURPLE + "Cache Size: " + C.LIGHT_PURPLE + Form.f(IrisData.cacheSize()));
Iris.info("-------------------------");
}
@Decree(description = "Test")
public void benchmarkMantle(
@Param(description = "The world to bench", aliases = {"world"})
World world
) throws IOException, ClassNotFoundException {
Engine engine = IrisToolbelt.access(world).getEngine();
int maxHeight = engine.getTarget().getHeight();
File folder = new File(Bukkit.getWorldContainer(), world.getName());
int c = 0;
//MCAUtil.read()
File tectonicplates = new File(folder, "mantle");
for (File i : Objects.requireNonNull(tectonicplates.listFiles())) {
TectonicPlate.read(maxHeight, i);
c++;
Iris.info("Loaded count: " + c );
}
}
@Decree(description = "Test")
public void packBenchmark(
@Param(description = "The pack to bench", aliases = {"pack"})
IrisDimension dimension
) {
Iris.info("test");
IrisPackBenchmarking benchmark = new IrisPackBenchmarking(dimension, 1);
}
@Decree(description = "Upgrade to another Minecraft version")
public void upgrade(
@Param(description = "The version to upgrade to", defaultValue = "latest") DataVersion version) {
sender().sendMessage(C.GREEN + "Upgrading to " + version.getVersion() + "...");
ServerConfigurator.installDataPacks(version.get(), false);
sender().sendMessage(C.GREEN + "Done upgrading! You can now update your server version to " + version.getVersion());
}
@Decree(description = "Test")
public void updater(
@Param(description = "Updater for chunks")
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", Bukkit.getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
return;
}
Iris.info("test");
ChunkUpdater updater = new ChunkUpdater(world);
updater.start();
Engine engine = IrisToolbelt.access(world).getEngine();
if(engine != null) {
long lastUseSize = engine.getMantle().getLastUseMapMemoryUsage();
Iris.info("-------------------------");
Iris.info(C.DARK_PURPLE + "Engine Status");
Iris.info(C.DARK_PURPLE + "Tectonic Limit: " + C.LIGHT_PURPLE + IrisEngineSVC.getTectonicLimit());
Iris.info(C.DARK_PURPLE + "Tectonic Loaded Plates: " + C.LIGHT_PURPLE + engine.getMantle().getLoadedRegionCount());
Iris.info(C.DARK_PURPLE + "Tectonic Plates: " + C.LIGHT_PURPLE + engine.getMantle().getNotClearedLoadedRegions());
Iris.info(C.DARK_PURPLE + "Tectonic ToUnload: " + C.LIGHT_PURPLE + engine.getMantle().getToUnload());
Iris.info(C.DARK_PURPLE + "Tectonic Unload Duration: " + C.LIGHT_PURPLE + Form.duration((long) engine.getMantle().getTectonicDuration()));
Iris.info(C.DARK_PURPLE + "Cache Size: " + C.LIGHT_PURPLE + Form.f(IrisData.cacheSize()));
Iris.info(C.DARK_PURPLE + "LastUse Size: " + C.LIGHT_PURPLE + Form.mem(lastUseSize));
Iris.info("-------------------------");
} else {
Iris.info(C.RED + "Engine is null!");
}
}
@Decree(description = "Test", origin = DecreeOrigin.BOTH)
public void test() {
Iris.info("Test Developer CMD Executed");
@Decree(description = "test")
public void mca (
@Param(description = "String") String world) {
try {
File[] McaFiles = new File(world, "region").listFiles((dir, name) -> name.endsWith(".mca"));
for (File mca : McaFiles) {
MCAFile MCARegion = MCAUtil.read(mca);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Decree(description = "UnloadChunks for good reasons.")
public void unloadchunks() {
List<World> IrisWorlds = new ArrayList<>();
int chunksUnloaded = 0;
for (World world : Bukkit.getWorlds()) {
try {
if (IrisToolbelt.access(world).getEngine() != null) {
IrisWorlds.add(world);
}
} catch (Exception e) {
// no
}
}
for (World world : IrisWorlds) {
for (Chunk chunk : world.getLoadedChunks()) {
if (chunk.isLoaded()) {
chunk.unload();
chunksUnloaded++;
}
}
}
Iris.info(C.IRIS + "Chunks Unloaded: " + chunksUnloaded);
}
@Decree(description = "Test", aliases = {"ip"})
public void network() {
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface ni : Collections.list(networkInterfaces)) {
Iris.info("Display Name: %s", ni.getDisplayName());
Enumeration<InetAddress> inetAddresses = ni.getInetAddresses();
for (InetAddress ia : Collections.list(inetAddresses)) {
Iris.info("IP: %s", ia.getHostAddress());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Decree(description = "Test the compression algorithms")

View File

@@ -20,21 +20,27 @@ package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.core.tools.IrisBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.core.safeguard.UtilsSFG;
import com.volmit.iris.engine.object.IrisWorld;
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
import com.volmit.iris.engine.platform.DummyChunkGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.DecreeOrigin;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.decree.specialhandlers.NullablePlayerHandler;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
import lombok.Getter;
@@ -49,8 +55,10 @@ import org.bukkit.entity.Player;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.scheduler.BukkitRunnable;
import java.io.Console;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -59,6 +67,7 @@ import static com.volmit.iris.core.service.EditSVC.deletingWorld;
import static com.volmit.iris.core.tools.IrisBenchmarking.inProgress;
import static com.volmit.iris.core.safeguard.IrisSafeguard.unstablemode;
import static com.volmit.iris.core.safeguard.ServerBootSFG.incompatibilities;
import static org.bukkit.Bukkit.getServer;
@Decree(name = "iris", aliases = {"ir", "irs"}, description = "Basic Command")
public class CommandIris implements DecreeExecutor {
@@ -71,11 +80,9 @@ public class CommandIris implements DecreeExecutor {
private CommandWhat what;
private CommandEdit edit;
private CommandFind find;
private CommandSupport support;
private CommandDeveloper developer;
public static @Getter String BenchDimension;
public static boolean worldCreation = false;
String WorldToLoad;
String WorldEngine;
String worldNameToCheck = "YourWorldName";
VolmitSender sender = Iris.getSender();
@@ -87,7 +94,9 @@ public class CommandIris implements DecreeExecutor {
@Param(aliases = "dimension", description = "The dimension type to create the world with", defaultValue = "default")
IrisDimension type,
@Param(description = "The seed to generate the world with", defaultValue = "1337")
long seed
long seed,
@Param(description = "If it should convert the dimension to match the vanilla height system.", defaultValue = "false")
boolean vanillaheight
) {
if(sender() instanceof Player) {
if (incompatibilities.get("Multiverse-Core")) {
@@ -131,6 +140,7 @@ public class CommandIris implements DecreeExecutor {
.seed(seed)
.sender(sender())
.studio(false)
.smartVanillaHeight(vanillaheight)
.create();
} catch (Throwable e) {
sender().sendMessage(C.RED + "Exception raised during creation. See the console for more details.");
@@ -184,7 +194,7 @@ public class CommandIris implements DecreeExecutor {
}
/*
/todo Fix PREGEN
/todo
@Decree(description = "Benchmark a pack", origin = DecreeOrigin.CONSOLE)
public void packbenchmark(
@Param(description = "Dimension to benchmark")
@@ -196,28 +206,16 @@ public class CommandIris implements DecreeExecutor {
IrisPackBenchmarking.runBenchmark();
} */
/* /todo Different approach this feels useless atm
@Decree(description = "Check for instabilities", origin = DecreeOrigin.CONSOLE)
public void fixunstable() throws InterruptedException {
if (unstablemode){
sender().sendMessage(C.RED + "Incompatibilities are posted in console..");
Iris.info(C.RED + "Your server is experiencing an incompatibility with the Iris plugin.");
Iris.info(C.RED + "Please rectify this problem to avoid further complications.");
Iris.info(C.RED + "----------------------------------------------------------------");
Iris.info(C.RED + "Command ran: /iris fixunstable");
UtilsSFG.printIncompatibleWarnings();
Iris.info(C.RED + "----------------------------------------------------------------");
} else {
Iris.info(C.BLUE + "Iris is running stable..");
sender().sendMessage("Iris is running stable..");
}
} */
@Decree(description = "Print world height information", origin = DecreeOrigin.PLAYER)
public void height() {
sender().sendMessage(C.GREEN + "" + sender().player().getWorld().getMinHeight() + " to " + sender().player().getWorld().getMaxHeight());
sender().sendMessage(C.GREEN + "Total Height: " + (sender().player().getWorld().getMaxHeight() - sender().player().getWorld().getMinHeight()));
if (sender().isPlayer()) {
sender().sendMessage(C.GREEN + "" + sender().player().getWorld().getMinHeight() + " to " + sender().player().getWorld().getMaxHeight());
sender().sendMessage(C.GREEN + "Total Height: " + (sender().player().getWorld().getMaxHeight() - sender().player().getWorld().getMinHeight()));
} else {
World mainWorld = getServer().getWorlds().get(0);
Iris.info(C.GREEN + "" + mainWorld.getMinHeight() + " to " + mainWorld.getMaxHeight());
Iris.info(C.GREEN + "Total Height: " + (mainWorld.getMaxHeight() - mainWorld.getMinHeight()));
}
}
@Decree(description = "QOL command to open a overworld studio world.", sync = true)
@@ -226,6 +224,44 @@ public class CommandIris implements DecreeExecutor {
Iris.service(StudioSVC.class).open(sender(), 1337, "overworld");
}
@Decree(description = "Check access of all worlds.", aliases = {"accesslist"})
public void worlds() {
KList<World> IrisWorlds = new KList<>();
KList<World> BukkitWorlds = new KList<>();
for (World w : Bukkit.getServer().getWorlds()) {
try {
Engine engine = IrisToolbelt.access(w).getEngine();
if (engine != null) {
IrisWorlds.add(w);
}
} catch (Exception e) {
BukkitWorlds.add(w);
}
}
if (sender().isPlayer()) {
sender().sendMessage(C.BLUE + "Iris Worlds: ");
for (World IrisWorld : IrisWorlds.copy()) {
sender().sendMessage(C.IRIS + "- " +IrisWorld.getName());
}
sender().sendMessage(C.GOLD + "Bukkit Worlds: ");
for (World BukkitWorld : BukkitWorlds.copy()) {
sender().sendMessage(C.GRAY + "- " +BukkitWorld.getName());
}
} else {
Iris.info(C.BLUE + "Iris Worlds: ");
for (World IrisWorld : IrisWorlds.copy()) {
Iris.info(C.IRIS + "- " +IrisWorld.getName());
}
Iris.info(C.GOLD + "Bukkit Worlds: ");
for (World BukkitWorld : BukkitWorlds.copy()) {
Iris.info(C.GRAY + "- " +BukkitWorld.getName());
}
}
}
@Decree(description = "Remove an Iris world", aliases = {"del", "rm", "delete"}, sync = true)
public void remove(
@Param(description = "The world to remove")
@@ -234,7 +270,7 @@ public class CommandIris implements DecreeExecutor {
boolean delete
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", Bukkit.getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
return;
}
sender().sendMessage(C.GREEN + "Removing world: " + world.getName());
@@ -286,6 +322,24 @@ public class CommandIris implements DecreeExecutor {
return dir.delete();
}
@Decree(description = "Updates all chunk in the specified world")
public void updater(
@Param(description = "World to update chunks at")
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.GOLD + "This is not an Iris world");
return;
}
ChunkUpdater updater = new ChunkUpdater(world);
if (sender().isPlayer()) {
sender().sendMessage(C.GREEN + "Updating " + world.getName() + " Total chunks: " + Form.f(updater.getChunks()));
} else {
Iris.info(C.GREEN + "Updating " + world.getName() + " Total chunks: " + Form.f(updater.getChunks()));
}
updater.start();
}
@Decree(description = "Set aura spins")
public void aura(
@Param(description = "The h color value", defaultValue = "-20")
@@ -417,7 +471,7 @@ public class CommandIris implements DecreeExecutor {
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", Bukkit.getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
return;
}
sender().sendMessage(C.GREEN + "Unloading world: " + world.getName());
@@ -445,9 +499,9 @@ public class CommandIris implements DecreeExecutor {
sender().sendMessage(C.YELLOW + world + " Doesnt exist on the server.");
return;
}
WorldToLoad = world;
File BUKKIT_YML = new File("bukkit.yml");
String pathtodim = world + "\\iris\\pack\\dimensions\\";
String pathtodim = world + File.separator +"iris"+File.separator +"pack"+File.separator +"dimensions"+File.separator;
File directory = new File(Bukkit.getWorldContainer(), pathtodim);
String dimension = null;
@@ -481,9 +535,10 @@ public class CommandIris implements DecreeExecutor {
} catch (IOException e) {
Iris.error("Failed to update bukkit.yml!");
e.printStackTrace();
return;
}
}
checkForBukkitWorlds();
checkForBukkitWorlds(world);
sender().sendMessage(C.GREEN + world + " loaded successfully.");
}
@Decree(description = "Evacuate an iris world", origin = DecreeOrigin.PLAYER, sync = true)
@@ -492,7 +547,7 @@ public class CommandIris implements DecreeExecutor {
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", Bukkit.getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
return;
}
sender().sendMessage(C.GREEN + "Evacuating world" + world.getName());
@@ -504,7 +559,7 @@ public class CommandIris implements DecreeExecutor {
File worldDirectory = new File(worldContainer, worldName);
return worldDirectory.exists() && worldDirectory.isDirectory();
}
private void checkForBukkitWorlds() {
private void checkForBukkitWorlds(String world) {
FileConfiguration fc = new YamlConfiguration();
try {
fc.load(new File("bukkit.yml"));
@@ -513,9 +568,9 @@ public class CommandIris implements DecreeExecutor {
return;
}
List<String> worldsToLoad = Collections.singletonList(WorldToLoad);
List<String> worldsToLoad = Collections.singletonList(world);
for (String s : section.getKeys(false)) {
for (String s : section.getKeys(false)) {
if (!worldsToLoad.contains(s)) {
continue;
}
@@ -594,6 +649,6 @@ public class CommandIris implements DecreeExecutor {
ff.mkdirs();
service(StudioSVC.class).installIntoWorld(sender, dim.getLoadKey(), ff.getParentFile());
}
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey(), false);
}
}

View File

@@ -21,6 +21,7 @@ package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.edit.JigsawEditor;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.framework.placer.WorldObjectPlacer;
import com.volmit.iris.engine.jigsaw.PlannedStructure;
import com.volmit.iris.engine.object.IrisJigsawPiece;
import com.volmit.iris.engine.object.IrisJigsawStructure;
@@ -34,6 +35,7 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import java.io.File;
@@ -55,9 +57,16 @@ public class CommandJigsaw implements DecreeExecutor {
IrisJigsawStructure structure
) {
PrecisionStopwatch p = PrecisionStopwatch.start();
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation()), new RNG());
sender().sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
ps.place(world());
try {
var world = world();
WorldObjectPlacer placer = new WorldObjectPlacer(world);
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation().add(0, world.getMinHeight(), 0)), new RNG());
VolmitSender sender = sender();
sender.sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
ps.place(placer, failed -> sender.sendMessage(failed ? C.GREEN + "Placed the structure!" : C.RED + "Failed to place the structure!"));
} catch (IllegalArgumentException e) {
sender().sendMessage(C.RED + "Failed to place the structure: " + e.getMessage());
}
}
@Decree(description = "Create a jigsaw piece")

View File

@@ -35,6 +35,7 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.Direction;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.scheduling.Queue;
import org.bukkit.*;
import org.bukkit.block.Block;
@@ -52,7 +53,7 @@ import java.util.*;
@Decree(name = "object", aliases = "o", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris object manipulation")
public class CommandObject implements DecreeExecutor {
private static final Set<Material> skipBlocks = Set.of(Material.GRASS, Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
private static final Set<Material> skipBlocks = Set.of(E.getOrDefault(Material.class, "GRASS", "SHORT_GRASS"), Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
Material.POPPY, Material.DANDELION);
public static IObjectPlacer createPlacer(World world, Map<Block, BlockData> futureBlockChanges) {
@@ -197,6 +198,20 @@ public class CommandObject implements DecreeExecutor {
}
}
@Decree(description = "Shrink an object to its minimum size")
public void shrink(@Param(description = "The object to shrink", customHandler = ObjectHandler.class) String object) {
IrisObject o = IrisData.loadAnyObject(object);
sender().sendMessage("Current Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
o.shrinkwrap();
sender().sendMessage("New Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
try {
o.write(o.getLoadFile());
} catch (IOException e) {
sender().sendMessage("Failed to save object " + o.getLoadFile() + ": " + e.getMessage());
e.printStackTrace();
}
}
@Decree(description = "Get a powder that reveals objects", studio = true, aliases = "d")
public void dust() {
player().getInventory().addItem(WandSVC.createDust());

View File

@@ -56,6 +56,7 @@ public class CommandPregen implements DecreeExecutor {
IrisToolbelt.pregenerate(PregenTask
.builder()
.center(new Position2(center.getBlockX() >> 9, center.getBlockZ() >> 9))
.gui(true)
.width(w)
.height(w)
.build(), world);

View File

@@ -26,6 +26,7 @@ import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.project.IrisProject;
import com.volmit.iris.core.service.ConversionSVC;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.core.tools.IrisConverter;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.*;
@@ -73,6 +74,7 @@ import java.nio.file.Files;
import java.nio.file.attribute.FileTime;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
@@ -84,7 +86,7 @@ import java.util.function.Supplier;
public class CommandStudio implements DecreeExecutor {
private CommandFind find;
private CommandEdit edit;
private CommandDeepSearch deepSearch;
//private CommandDeepSearch deepSearch;
public static String hrf(Duration duration) {
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
@@ -229,9 +231,9 @@ public class CommandStudio implements DecreeExecutor {
@Decree(description = "Convert objects in the \"convert\" folder")
public void convert() {
Iris.service(ConversionSVC.class).check(sender());
//IrisConverter.convertSchematics(sender());
}
@Decree(description = "Execute a script", aliases = "run", origin = DecreeOrigin.PLAYER)
public void execute(
@Param(description = "The script to run")
@@ -331,6 +333,63 @@ public class CommandStudio implements DecreeExecutor {
player().openInventory(inv);
}
@Decree(description = "Get all structures in a radius of chunks", aliases = "dist", origin = DecreeOrigin.PLAYER)
public void distances(@Param(description = "The radius") int radius) {
var engine = engine();
if (engine == null) {
sender().sendMessage(C.RED + "Only works in an Iris world!");
return;
}
var sender = sender();
int d = radius*2;
KMap<String, KList<Position2>> data = new KMap<>();
var multiBurst = new MultiBurst("Distance Sampler", Thread.MIN_PRIORITY);
var executor = multiBurst.burst(radius * radius);
sender.sendMessage(C.GRAY + "Generating data...");
var loc = player().getLocation();
new Spiraler(d, d, (x, z) -> executor.queue(() -> {
var struct = engine.getStructureAt(x, z);
if (struct != null) {
data.computeIfAbsent(struct.getLoadKey(), (k) -> new KList<>()).add(new Position2(x, z));
}
})).setOffset(loc.getBlockX(), loc.getBlockZ()).drain();
executor.complete();
multiBurst.close();
for (var key : data.keySet()) {
var list = data.get(key);
KList<Long> distances = new KList<>(list.size() - 1);
for (int i = 0; i < list.size(); i++) {
var pos = list.get(i);
double dist = Integer.MAX_VALUE;
for (var p : list) {
if (p.equals(pos)) continue;
dist = Math.min(dist, Math.sqrt(Math.pow(pos.getX() - p.getX(), 2) + Math.pow(pos.getZ() - p.getZ(), 2)));
}
if (dist == Integer.MAX_VALUE) continue;
distances.add(Math.round(dist * 16));
}
long[] array = new long[distances.size()];
for (int i = 0; i < distances.size(); i++) {
array[i] = distances.get(i);
}
Arrays.sort(array);
long min = array.length > 0 ? array[0] : 0;
long max = array.length > 0 ? array[array.length - 1] : 0;
long sum = Arrays.stream(array).sum();
long avg = array.length > 0 ? Math.round(sum / (double) array.length) : 0;
String msg = "%s: %s => min: %s/max: %s -> avg: %s".formatted(key, list.size(), min, max, avg);
sender.sendMessage(msg);
}
if (data.isEmpty()) {
sender.sendMessage(C.RED + "No data found!");
} else {
sender.sendMessage(C.GREEN + "Done!");
}
}
@Decree(description = "Render a world map (External GUI)", aliases = "render")
public void map(
@Param(name = "world", description = "The world to open the generator for", contextual = true)

View File

@@ -0,0 +1,82 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.service.IrisEngineSVC;
import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.DecreeOrigin;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.mantle.TectonicPlate;
import com.volmit.iris.util.misc.Hastebin;
import com.volmit.iris.util.misc.Platform;
import com.volmit.iris.util.misc.getHardware;
import com.volmit.iris.util.nbt.mca.MCAFile;
import com.volmit.iris.util.nbt.mca.MCAUtil;
import com.volmit.iris.util.plugin.VolmitSender;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import net.jpountz.lz4.LZ4FrameInputStream;
import net.jpountz.lz4.LZ4FrameOutputStream;
import org.apache.commons.lang.RandomStringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import oshi.SystemInfo;
import java.io.*;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@Decree(name = "Support", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"support"})
public class CommandSupport implements DecreeExecutor {
@Decree(description = "report")
public void report() {
try {
if (sender().isPlayer()) sender().sendMessage(C.GOLD + "Creating report..");
if (!sender().isPlayer()) Iris.info(C.GOLD + "Creating report..");
Hastebin.enviornment(sender());
} catch (Exception e) {
Iris.info(C.RED + "Something went wrong: ");
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,107 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.core.commands;
import org.bukkit.World;
import com.volmit.iris.Iris;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.DecreeOrigin;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
@Decree(name = "Updater", origin = DecreeOrigin.BOTH, description = "Iris World Updater")
public class CommandUpdater implements DecreeExecutor {
private ChunkUpdater chunkUpdater;
@Decree(description = "Updates all chunk in the specified world")
public void start(
@Param(description = "World to update chunks at")
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.GOLD + "This is not an Iris world");
return;
}
chunkUpdater = new ChunkUpdater(world);
if (sender().isPlayer()) {
sender().sendMessage(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
} else {
Iris.info(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
}
chunkUpdater.start();
}
@Decree(description = "Pause the updater")
public void pause(
@Param(description = "World to pause the Updater at")
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.GOLD + "This is not an Iris world");
return;
}
if (chunkUpdater == null) {
sender().sendMessage(C.GOLD + "You cant pause something that doesnt exist?");
return;
}
boolean status = chunkUpdater.pause();
if (sender().isPlayer()) {
if (status) {
sender().sendMessage(C.IRIS + "Paused task for: " + C.GRAY + world.getName());
} else {
sender().sendMessage(C.IRIS + "Unpause task for: " + C.GRAY + world.getName());
}
} else {
if (status) {
Iris.info(C.IRIS + "Paused task for: " + C.GRAY + world.getName());
} else {
Iris.info(C.IRIS + "Unpause task for: " + C.GRAY + world.getName());
}
}
}
@Decree(description = "Stops the updater")
public void stop(
@Param(description = "World to stop the Updater at")
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.GOLD + "This is not an Iris world");
return;
}
if (chunkUpdater == null) {
sender().sendMessage(C.GOLD + "You cant stop something that doesnt exist?");
return;
}
if (sender().isPlayer()) {
sender().sendMessage("Stopping Updater for: " + C.GRAY + world.getName());
} else {
Iris.info("Stopping Updater for: " + C.GRAY + world.getName());
}
chunkUpdater.stop();
}
}

View File

@@ -22,7 +22,9 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.edit.BlockSignal;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisRegion;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.DecreeOrigin;
@@ -37,6 +39,7 @@ import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
@Decree(name = "what", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris What?")
@@ -82,6 +85,19 @@ public class CommandWhat implements DecreeExecutor {
}
}
@Decree(description = "What region am i in?", origin = DecreeOrigin.PLAYER)
public void region() {
try {
Chunk chunk = world().getChunkAt(player().getLocation().getBlockZ() / 16, player().getLocation().getBlockZ() / 16);
IrisRegion r = engine().getRegion(chunk);
sender().sendMessage("IRegion: " + r.getLoadKey() + " (" + r.getName() + ")");
} catch (Throwable e) {
Iris.reportError(e);
sender().sendMessage(C.IRIS + "Iris worlds only.");
}
}
@Decree(description = "What block am i looking at?", origin = DecreeOrigin.PLAYER)
public void block() {
BlockData bd;
@@ -147,7 +163,7 @@ public class CommandWhat implements DecreeExecutor {
sender().sendMessage("Found " + v.get() + " Nearby Markers (" + marker + ")");
} else {
sender().sendMessage("Iris worlds only.");
sender().sendMessage(C.IRIS + "Iris worlds only.");
}
}
}

View File

@@ -24,6 +24,7 @@ import com.volmit.iris.core.pregenerator.IrisPregenerator;
import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.Form;
@@ -44,6 +45,8 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmarkInProgress;
public class PregeneratorJob implements PregenListener {
private static final Color COLOR_EXISTS = parseColor("#4d7d5b");
private static final Color COLOR_BLACK = parseColor("#4d7d5b");
@@ -86,7 +89,7 @@ public class PregeneratorJob implements PregenListener {
max.setZ(Math.max((zz << 5) + 31, max.getZ()));
});
if (IrisSettings.get().getGui().isUseServerLaunchedGuis()) {
if (IrisSettings.get().getGui().isUseServerLaunchedGuis() && task.isGui()) {
open();
}

View File

@@ -55,10 +55,10 @@ public class IrisRenderer {
IrisBiome b = renderer.getBiome((int) Math.round(x), renderer.getMaxHeight() - 1, (int) Math.round(z));
IrisBiomeGeneratorLink g = b.getGenerators().get(0);
Color c;
if (g.getMax() <= 0) {
if (g.getMax(renderer) <= 0) {
// Max is below water level, so it is most likely an ocean biome
c = Color.BLUE;
} else if (g.getMin() < 0) {
} else if (g.getMin(renderer) < 0) {
// Min is below water level, but max is not, so it is most likely a shore biome
c = Color.YELLOW;
} else {

View File

@@ -0,0 +1,71 @@
package com.volmit.iris.core.link;
import com.volmit.iris.Iris;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.reflect.WrappedField;
import com.willfp.ecoitems.items.EcoItem;
import com.willfp.ecoitems.items.EcoItems;
import org.bukkit.NamespacedKey;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import java.util.MissingResourceException;
public class EcoItemsDataProvider extends ExternalDataProvider {
private WrappedField<EcoItem, ItemStack> itemStack;
private WrappedField<EcoItem, NamespacedKey> id;
public EcoItemsDataProvider() {
super("EcoItems");
}
@Override
public void init() {
Iris.info("Setting up EcoItems Link...");
itemStack = new WrappedField<>(EcoItem.class, "_itemStack");
if (this.itemStack.hasFailed()) {
Iris.error("Failed to set up EcoItems Link: Unable to fetch ItemStack field!");
}
id = new WrappedField<>(EcoItem.class, "id");
if (this.id.hasFailed()) {
Iris.error("Failed to set up EcoItems Link: Unable to fetch id field!");
}
}
@Override
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
}
@Override
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
EcoItem item = EcoItems.INSTANCE.getByID(itemId.key());
if (item == null) throw new MissingResourceException("Failed to find Item!", itemId.namespace(), itemId.key());
return itemStack.get(item).clone();
}
@Override
public Identifier[] getBlockTypes() {
return new Identifier[0];
}
@Override
public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>();
for (EcoItem item : EcoItems.INSTANCE.values()) {
try {
Identifier key = Identifier.fromNamespacedKey(id.get(item));
if (getItemStack(key) != null)
names.add(key);
} catch (MissingResourceException ignored) {
}
}
return names.toArray(new Identifier[0]);
}
@Override
public boolean isValidProvider(Identifier id, boolean isItem) {
return id.namespace().equalsIgnoreCase("ecoitems") && isItem;
}
}

View File

@@ -1,8 +1,10 @@
package com.volmit.iris.core.link;
import com.volmit.iris.engine.framework.Engine;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
@@ -28,6 +30,7 @@ public abstract class ExternalDataProvider {
public abstract BlockData getBlockData(Identifier blockId) throws MissingResourceException;
public abstract ItemStack getItemStack(Identifier itemId) throws MissingResourceException;
public void processUpdate(Engine engine, Block block, Identifier blockId) {};
public abstract Identifier[] getBlockTypes();

View File

@@ -0,0 +1,135 @@
package com.volmit.iris.core.link;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.reflect.WrappedField;
import com.volmit.iris.util.reflect.WrappedReturningMethod;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Leaves;
import org.bukkit.inventory.ItemStack;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.function.Supplier;
public class HMCLeavesDataProvider extends ExternalDataProvider {
private Object apiInstance;
private WrappedReturningMethod<Object, Material> worldBlockType;
private WrappedReturningMethod<Object, Boolean> setCustomBlock;
private Map<String, Object> blockDataMap = Map.of();
private Map<String, Supplier<ItemStack>> itemDataField = Map.of();
public HMCLeavesDataProvider() {
super("HMCLeaves");
}
@Override
public String getPluginId() {
return "HMCLeaves";
}
@Override
public void init() {
try {
worldBlockType = new WrappedReturningMethod<>((Class<Object>) Class.forName("io.github.fisher2911.hmcleaves.data.BlockData"), "worldBlockType");
apiInstance = getApiInstance(Class.forName("io.github.fisher2911.hmcleaves.api.HMCLeavesAPI"));
setCustomBlock = new WrappedReturningMethod<>((Class<Object>) apiInstance.getClass(), "setCustomBlock", Location.class, String.class, boolean.class);
Object config = getLeavesConfig(apiInstance.getClass());
blockDataMap = getMap(config, "blockDataMap");
itemDataField = getMap(config, "itemSupplierMap");
} catch (Throwable e) {
Iris.error("Failed to initialize HMCLeavesDataProvider: " + e.getMessage());
}
}
@Override
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
Object o = blockDataMap.get(blockId.key());
if (o == null)
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
Material material = worldBlockType.invoke(o, new Object[0]);
if (material == null)
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
BlockData blockData = Bukkit.createBlockData(material);
if (IrisSettings.get().getGenerator().preventLeafDecay && blockData instanceof Leaves leaves)
leaves.setPersistent(true);
return new IrisBlockData(blockData, blockId);
}
@Override
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
if (!itemDataField.containsKey(itemId.key()))
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
return itemDataField.get(itemId.key()).get();
}
@Override
public void processUpdate(Engine engine, Block block, Identifier blockId) {
Boolean result = setCustomBlock.invoke(apiInstance, new Object[]{block.getLocation(), blockId.key(), false});
if (result == null || !result)
Iris.warn("Failed to set custom block! " + blockId.key() + " " + block.getX() + " " + block.getY() + " " + block.getZ());
else if (IrisSettings.get().getGenerator().preventLeafDecay) {
BlockData blockData = block.getBlockData();
if (blockData instanceof Leaves leaves)
leaves.setPersistent(true);
}
}
@Override
public Identifier[] getBlockTypes() {
KList<Identifier> names = new KList<>();
for (String name : blockDataMap.keySet()) {
try {
Identifier key = new Identifier("hmcleaves", name);
if (getBlockData(key) != null)
names.add(key);
} catch (MissingResourceException ignored) {
}
}
return names.toArray(new Identifier[0]);
}
@Override
public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>();
for (String name : itemDataField.keySet()) {
try {
Identifier key = new Identifier("hmcleaves", name);
if (getItemStack(key) != null)
names.add(key);
} catch (MissingResourceException ignored) {
}
}
return names.toArray(new Identifier[0]);
}
@Override
public boolean isValidProvider(Identifier id, boolean isItem) {
return (isItem ? itemDataField.keySet() : blockDataMap.keySet()).contains(id.key());
}
private <C, T> Map<String, T> getMap(C config, String name) {
WrappedField<C, Map<String, T>> field = new WrappedField<>((Class<C>) config.getClass(), name);
return field.get(config);
}
private <A> A getApiInstance(Class<A> apiClass) {
WrappedReturningMethod<A, A> instance = new WrappedReturningMethod<>(apiClass, "getInstance");
return instance.invoke();
}
private <A, C> C getLeavesConfig(Class<A> apiClass) {
WrappedReturningMethod<A, A> instance = new WrappedReturningMethod<>(apiClass, "getInstance");
WrappedField<A, C> config = new WrappedField<>(apiClass, "config");
return config.get(instance.invoke());
}
}

View File

@@ -6,6 +6,10 @@ public record Identifier(String namespace, String key) {
private static final String DEFAULT_NAMESPACE = "minecraft";
public static Identifier fromNamespacedKey(NamespacedKey key) {
return new Identifier(key.getNamespace(), key.getKey());
}
public static Identifier fromString(String id) {
String[] strings = id.split(":", 2);
if (strings.length == 1) {

View File

@@ -0,0 +1,106 @@
package com.volmit.iris.core.link;
import com.volmit.iris.Iris;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.scheduling.J;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.block.CustomBlock;
import org.bukkit.Bukkit;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import java.util.MissingResourceException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class MMOItemsDataProvider extends ExternalDataProvider {
public MMOItemsDataProvider() {
super("MMOItems");
}
@Override
public void init() {
Iris.info("Setting up MMOItems Link...");
}
@Override
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
int id = -1;
try {
id = Integer.parseInt(blockId.key());
} catch (NumberFormatException ignored) {}
CustomBlock block = api().getCustomBlocks().getBlock(id);
if (block == null) throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
return block.getState().getBlockData();
}
@Override
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
String[] parts = itemId.namespace().split("_", 2);
if (parts.length != 2)
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
CompletableFuture<ItemStack> future = new CompletableFuture<>();
Runnable run = () -> future.complete(api().getItem(parts[1], itemId.key()));
if (Bukkit.isPrimaryThread()) run.run();
else J.s(run);
ItemStack item = null;
try {
item = future.get();
} catch (InterruptedException | ExecutionException ignored) {}
if (item == null)
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
return item;
}
@Override
public Identifier[] getBlockTypes() {
KList<Identifier> names = new KList<>();
for (Integer id : api().getCustomBlocks().getBlockIds()) {
try {
Identifier key = new Identifier("mmoitems", String.valueOf(id));
if (getBlockData(key) != null)
names.add(key);
} catch (MissingResourceException ignored) {
}
}
return names.toArray(new Identifier[0]);
}
@Override
public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>();
Runnable run = () -> {
for (Type type : api().getTypes().getAll()) {
for (String name : api().getTemplates().getTemplateNames(type)) {
try {
Identifier key = new Identifier("mmoitems_" + type.getId(), name);
if (getItemStack(key) != null)
names.add(key);
} catch (MissingResourceException ignored) {
}
}
}
};
if (Bukkit.isPrimaryThread()) run.run();
else {
try {
J.sfut(run).get();
} catch (InterruptedException | ExecutionException e) {
Iris.error("Failed getting MMOItems item types!");
Iris.reportError(e);
}
}
return names.toArray(new Identifier[0]);
}
@Override
public boolean isValidProvider(Identifier id, boolean isItem) {
return isItem ? id.namespace().split("_", 2).length == 2 : id.namespace().equals("mmoitems");
}
private MMOItems api() {
return MMOItems.plugin;
}
}

View File

@@ -19,18 +19,25 @@
package com.volmit.iris.core.link;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.reflect.WrappedField;
import io.th0rgal.oraxen.api.OraxenItems;
import io.th0rgal.oraxen.items.ItemBuilder;
import io.th0rgal.oraxen.mechanics.Mechanic;
import io.th0rgal.oraxen.mechanics.MechanicFactory;
import io.th0rgal.oraxen.mechanics.MechanicsManager;
import io.th0rgal.oraxen.mechanics.provided.gameplay.block.BlockMechanic;
import io.th0rgal.oraxen.mechanics.provided.gameplay.block.BlockMechanicFactory;
import io.th0rgal.oraxen.mechanics.provided.gameplay.furniture.FurnitureFactory;
import io.th0rgal.oraxen.mechanics.provided.gameplay.furniture.FurnitureMechanic;
import io.th0rgal.oraxen.mechanics.provided.gameplay.noteblock.NoteBlockMechanicFactory;
import io.th0rgal.oraxen.mechanics.provided.gameplay.stringblock.StringBlockMechanicFactory;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.MultipleFacing;
import org.bukkit.inventory.ItemStack;
@@ -69,6 +76,8 @@ public class OraxenDataProvider extends ExternalDataProvider {
return newBlockData;
} else if (factory instanceof StringBlockMechanicFactory f) {
return f.createTripwireData(blockId.key());
} else if (factory instanceof FurnitureFactory) {
return new IrisBlockData(B.getAir(), blockId);
} else
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
}
@@ -79,6 +88,14 @@ public class OraxenDataProvider extends ExternalDataProvider {
return opt.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key())).build();
}
@Override
public void processUpdate(Engine engine, Block block, Identifier blockId) {
Mechanic mechanic = getFactory(blockId).getMechanic(blockId.key());
if (mechanic instanceof FurnitureMechanic f) {
f.place(block.getLocation());
}
}
@Override
public Identifier[] getBlockTypes() {
KList<Identifier> names = new KList<>();

View File

@@ -23,7 +23,13 @@ import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
import org.bukkit.Bukkit;
import java.util.Map;
public class INMS {
private static final Map<String, String> REVISION = Map.of(
"1.20.5", "v1_20_R4",
"1.20.6", "v1_20_R4"
);
//@done
private static final INMSBinding binding = bind();
@@ -37,7 +43,12 @@ public class INMS {
}
try {
return Bukkit.getServer().getClass().getCanonicalName().split("\\Q.\\E")[3];
String name = Bukkit.getServer().getClass().getCanonicalName();
if (name.equals("org.bukkit.craftbukkit.CraftServer")) {
return REVISION.getOrDefault(Bukkit.getServer().getBukkitVersion().split("-")[0], "BUKKIT");
} else {
return name.split("\\Q.\\E")[3];
}
} catch (Throwable e) {
Iris.reportError(e);
Iris.error("Failed to determine server nms version!");

View File

@@ -18,10 +18,12 @@
package com.volmit.iris.core.nms;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
import com.volmit.iris.util.nbt.tag.CompoundTag;
@@ -32,6 +34,8 @@ import org.bukkit.WorldCreator;
import org.bukkit.block.Biome;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
@@ -103,4 +107,12 @@ public interface INMSBinding {
void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos);
void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException;
Vector3d getBoundingbox(org.bukkit.entity.EntityType entity);
Entity spawnEntity(Location location, EntityType type, CreatureSpawnEvent.SpawnReason reason);
default DataVersion getDataVersion() {
return DataVersion.V1192;
}
}

View File

@@ -0,0 +1,40 @@
package com.volmit.iris.core.nms.datapack;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.datapack.v1192.DataFixerV1192;
import com.volmit.iris.core.nms.datapack.v1206.DataFixerV1206;
import com.volmit.iris.util.collection.KMap;
import lombok.AccessLevel;
import lombok.Getter;
import java.util.function.Supplier;
//https://minecraft.wiki/w/Pack_format
@Getter
public enum DataVersion {
V1192("1.19.2", 10, DataFixerV1192::new),
V1205("1.20.6", 41, DataFixerV1206::new);
private static final KMap<DataVersion, IDataFixer> cache = new KMap<>();
@Getter(AccessLevel.NONE)
private final Supplier<IDataFixer> constructor;
private final String version;
private final int packFormat;
DataVersion(String version, int packFormat, Supplier<IDataFixer> constructor) {
this.constructor = constructor;
this.packFormat = packFormat;
this.version = version;
}
public IDataFixer get() {
return cache.computeIfAbsent(this, k -> constructor.get());
}
public static IDataFixer getDefault() {
return INMS.get().getDataVersion().get();
}
public static DataVersion getLatest() {
return values()[values().length - 1];
}
}

View File

@@ -0,0 +1,11 @@
package com.volmit.iris.core.nms.datapack;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.util.json.JSONObject;
public interface IDataFixer {
JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json);
JSONObject fixDimension(JSONObject json);
}

View File

@@ -0,0 +1,18 @@
package com.volmit.iris.core.nms.datapack.v1192;
import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.util.json.JSONObject;
public class DataFixerV1192 implements IDataFixer {
@Override
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
return json;
}
@Override
public JSONObject fixDimension(JSONObject json) {
return json;
}
}

View File

@@ -0,0 +1,54 @@
package com.volmit.iris.core.nms.datapack.v1206;
import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisBiomeCustomSpawn;
import com.volmit.iris.engine.object.IrisBiomeCustomSpawnType;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.json.JSONArray;
import com.volmit.iris.util.json.JSONObject;
import java.util.Locale;
public class DataFixerV1206 implements IDataFixer {
@Override
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
int spawnRarity = biome.getSpawnRarity();
if (spawnRarity > 0) {
json.put("creature_spawn_probability", Math.min(spawnRarity/20d, 0.9999999));
}
var spawns = biome.getSpawns();
if (spawns != null && spawns.isNotEmpty()) {
JSONObject spawners = new JSONObject();
KMap<IrisBiomeCustomSpawnType, JSONArray> groups = new KMap<>();
for (IrisBiomeCustomSpawn i : spawns) {
JSONArray g = groups.computeIfAbsent(i.getGroup(), (k) -> new JSONArray());
JSONObject o = new JSONObject();
o.put("type", "minecraft:" + i.getType().name().toLowerCase());
o.put("weight", i.getWeight());
o.put("minCount", Math.min(i.getMinCount()/20d, 0));
o.put("maxCount", Math.min(i.getMaxCount()/20d, 0.9999999));
g.put(o);
}
for (IrisBiomeCustomSpawnType i : groups.k()) {
spawners.put(i.name().toLowerCase(Locale.ROOT), groups.get(i));
}
json.put("spawners", spawners);
}
return json;
}
@Override
public JSONObject fixDimension(JSONObject json) {
if (!(json.get("monster_spawn_light_level") instanceof JSONObject lightLevel))
return json;
var value = (JSONObject) lightLevel.remove("value");
lightLevel.put("max_inclusive", value.get("max_inclusive"));
lightLevel.put("min_inclusive", value.get("min_inclusive"));
return json;
}
}

View File

@@ -25,6 +25,7 @@ import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
import com.volmit.iris.util.nbt.tag.CompoundTag;
@@ -34,6 +35,8 @@ import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
@@ -85,6 +88,15 @@ public class NMSBinding1X implements INMSBinding {
}
public Vector3d getBoundingbox() {
return null;
}
@Override
public Entity spawnEntity(Location location, EntityType type, CreatureSpawnEvent.SpawnReason reason) {
return location.getWorld().spawnEntity(location, type);
}
@Override
public void deserializeTile(CompoundTag s, Location newPosition) {
@@ -203,6 +215,11 @@ public class NMSBinding1X implements INMSBinding {
}
@Override
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
return null;
}
@Override
public MCAPaletteAccess createPalette() {
Iris.error("Cannot use the global data palette! Iris is incapable of using MCA generation on this version of minecraft!");

View File

@@ -0,0 +1,318 @@
package com.volmit.iris.core.pregenerator;
import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.scheduling.J;
import io.papermc.lib.PaperLib;
import org.bukkit.Chunk;
import org.bukkit.World;
import java.io.File;
import java.util.ArrayList;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
public class ChunkUpdater {
private AtomicBoolean paused;
private AtomicBoolean cancelled;
private KMap<Chunk, Long> lastUse;
private final RollingSequence chunksPerSecond;
private final AtomicInteger worldheightsize;
private final AtomicInteger worldwidthsize;
private final AtomicInteger totalChunks;
private final AtomicInteger totalMaxChunks;
private final AtomicInteger totalMcaregions;
private final AtomicInteger position;
private AtomicInteger chunksProcessed;
private AtomicInteger chunksUpdated;
private AtomicLong startTime;
private ExecutorService executor;
private ExecutorService chunkExecutor;
private ScheduledExecutorService scheduler;
private CompletableFuture future;
private CountDownLatch latch;
private final Object pauseLock;
private final Engine engine;
private final World world;
public ChunkUpdater(World world) {
this.engine = IrisToolbelt.access(world).getEngine();
this.chunksPerSecond = new RollingSequence(5);
this.world = world;
this.lastUse = new KMap();
this.worldheightsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 1));
this.worldwidthsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 0));
int m = Math.max(worldheightsize.get(), worldwidthsize.get());
this.executor = Executors.newFixedThreadPool(Math.max(Runtime.getRuntime().availableProcessors() / 3, 1));
this.chunkExecutor = Executors.newFixedThreadPool(Math.max(Runtime.getRuntime().availableProcessors() / 3, 1));
this.scheduler = Executors.newScheduledThreadPool(1);
this.future = new CompletableFuture<>();
this.startTime = new AtomicLong();
this.worldheightsize.set(m);
this.worldwidthsize.set(m);
this.totalMaxChunks = new AtomicInteger((worldheightsize.get() / 16) * (worldwidthsize.get() / 16));
this.chunksProcessed = new AtomicInteger();
this.chunksUpdated = new AtomicInteger();
this.position = new AtomicInteger(0);
this.latch = new CountDownLatch(totalMaxChunks.get());
this.paused = new AtomicBoolean(false);
this.pauseLock = new Object();
this.cancelled = new AtomicBoolean(false);
this.totalChunks = new AtomicInteger(0);
this.totalMcaregions = new AtomicInteger(0);
}
public int getChunks() {
return totalMaxChunks.get();
}
public void start() {
unloadAndSaveAllChunks();
update();
}
public boolean pause() {
unloadAndSaveAllChunks();
if (paused.get()) {
paused.set(false);
return false;
} else {
paused.set(true);
return true;
}
}
public void stop() {
unloadAndSaveAllChunks();
cancelled.set(true);
}
private void update() {
Iris.info("Updating..");
try {
startTime.set(System.currentTimeMillis());
scheduler.scheduleAtFixedRate(() -> {
try {
if (!paused.get()) {
long eta = computeETA();
long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 1000;
int processed = chunksProcessed.get();
double cps = elapsedSeconds > 0 ? processed / (double) elapsedSeconds : 0;
chunksPerSecond.put(cps);
double percentage = ((double) chunksProcessed.get() / (double) totalMaxChunks.get()) * 100;
if (!cancelled.get()) {
Iris.info("Updated: " + Form.f(processed) + " of " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta,
2), percentage);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}, 0, 3, TimeUnit.SECONDS);
CompletableFuture.runAsync(() -> {
for (int i = 0; i < totalMaxChunks.get(); i++) {
if (paused.get()) {
synchronized (pauseLock) {
try {
pauseLock.wait();
} catch (InterruptedException e) {
Iris.error("Interrupted while waiting for executor: ");
e.printStackTrace();
break;
}
}
}
executor.submit(() -> {
if (!cancelled.get()) {
processNextChunk();
}
latch.countDown();
});
}
}).thenRun(() -> {
try {
latch.await();
close();
} catch (Exception e) {
Thread.currentThread().interrupt();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public void close() {
try {
unloadAndSaveAllChunks();
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
chunkExecutor.shutdown();
chunkExecutor.awaitTermination(5, TimeUnit.SECONDS);
scheduler.shutdownNow();
} catch (Exception ignored) {
}
if (cancelled.get()) {
Iris.info("Updated: " + Form.f(chunksUpdated.get()) + " Chunks");
Iris.info("Irritated: " + Form.f(chunksProcessed.get()) + " of " + Form.f(totalMaxChunks.get()));
Iris.info("Stopped updater.");
} else {
Iris.info("Processed: " + Form.f(chunksProcessed.get()) + " Chunks");
Iris.info("Finished Updating: " + Form.f(chunksUpdated.get()) + " Chunks");
}
}
private void processNextChunk() {
int pos = position.getAndIncrement();
int[] coords = getChunk(pos);
if (loadChunksIfGenerated(coords[0], coords[1])) {
Chunk c = world.getChunkAt(coords[0], coords[1]);
engine.updateChunk(c);
chunksUpdated.incrementAndGet();
}
chunksProcessed.getAndIncrement();
}
private boolean loadChunksIfGenerated(int x, int z) {
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
if (!PaperLib.isChunkGenerated(world, x + dx, z + dz)) {
return false;
}
}
}
AtomicBoolean generated = new AtomicBoolean(true);
KList<Future<?>> futures = new KList<>(9);
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
int xx = x + dx;
int zz = z + dz;
futures.add(chunkExecutor.submit(() -> {
Chunk c;
try {
c = PaperLib.getChunkAtAsync(world, xx, zz, false).get();
} catch (InterruptedException | ExecutionException e) {
generated.set(false);
return;
}
if (!c.isLoaded()) {
CountDownLatch latch = new CountDownLatch(1);
J.s(() -> {
c.load(false);
latch.countDown();
});
try {
latch.await();
} catch (InterruptedException ignored) {}
}
if (!c.isGenerated()) {
generated.set(false);
}
lastUse.put(c, M.ms());
}));
}
}
while (!futures.isEmpty()) {
futures.removeIf(Future::isDone);
try {
Thread.sleep(50);
} catch (InterruptedException ignored) {}
}
return generated.get();
}
private void unloadAndSaveAllChunks() {
try {
J.sfut(() -> {
if (world == null) {
Iris.warn("World was null somehow...");
return;
}
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
Long lastUseTime = lastUse.get(i);
if (lastUseTime != null && M.ms() - lastUseTime >= 5000) {
i.unload();
lastUse.remove(i);
}
}
world.save();
}).get();
} catch (Throwable e) {
e.printStackTrace();
}
}
private long computeETA() {
return (long) (totalMaxChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total?
// If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers)
((totalMaxChunks.get() - chunksProcessed.get()) * ((double) (M.ms() - startTime.get()) / (double) chunksProcessed.get())) :
// If no, use quick function (which is less accurate over time but responds better to the initial delay)
((totalMaxChunks.get() - chunksProcessed.get()) / chunksPerSecond.getAverage()) * 1000
);
}
public int calculateWorldDimensions(File regionDir, Integer o) {
File[] files = regionDir.listFiles((dir, name) -> name.endsWith(".mca"));
int minX = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int minZ = Integer.MAX_VALUE;
int maxZ = Integer.MIN_VALUE;
for (File file : files) {
String[] parts = file.getName().split("\\.");
int x = Integer.parseInt(parts[1]);
int z = Integer.parseInt(parts[2]);
if (x < minX) minX = x;
if (x > maxX) maxX = x;
if (z < minZ) minZ = z;
if (z > maxZ) maxZ = z;
}
int height = (maxX - minX + 1) * 32 * 16;
int width = (maxZ - minZ + 1) * 32 * 16;
if (o == 1) {
return height;
}
if (o == 0) {
return width;
}
return 0;
}
public int[] getChunk(int position) {
int p = -1;
AtomicInteger xx = new AtomicInteger();
AtomicInteger zz = new AtomicInteger();
Spiraler s = new Spiraler(worldheightsize.get() * 2, worldwidthsize.get() * 2, (x, z) -> {
xx.set(x);
zz.set(z);
});
while (s.hasNext() && p++ < position) {
s.next();
}
int[] coords = new int[2];
coords[0] = xx.get();
coords[1] = zz.get();
return coords;
}
}

View File

@@ -5,18 +5,16 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import io.papermc.lib.PaperLib;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
@@ -33,7 +31,6 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
@@ -56,10 +53,12 @@ public class DeepSearchPregenerator extends Thread implements Listener {
private final RollingSequence chunksPerMinute;
private final AtomicInteger chunkCachePos;
private final AtomicInteger chunkCacheSize;
private int pos;
private final AtomicInteger foundCacheLast;
private final AtomicInteger foundCache;
private LinkedHashMap<Integer, Position2> chunkCache;
private final ReentrantLock cacheLock = new ReentrantLock();
private KList<Position2> chunkQueue;
private final ReentrantLock cacheLock;
private static final Map<String, DeepSearchJob> jobs = new HashMap<>();
@@ -69,11 +68,13 @@ public class DeepSearchPregenerator extends Thread implements Listener {
this.chunkCachePos = new AtomicInteger(1000);
this.foundCacheLast = new AtomicInteger();
this.foundCache = new AtomicInteger();
this.cacheLock = new ReentrantLock();
this.destination = destination;
this.chunkCache = new LinkedHashMap();
this.chunkCache = new LinkedHashMap<>();
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
}).count();
this.world = Bukkit.getWorld(job.getWorld());
this.world = Bukkit.getWorld(job.getWorld().getUID());
this.chunkQueue = new KList<>();
this.latch = new ChronoLatch(3000);
this.startTime = new AtomicLong(M.ms());
this.chunksPerSecond = new RollingSequence(10);
@@ -81,7 +82,9 @@ public class DeepSearchPregenerator extends Thread implements Listener {
foundChunks = new AtomicInteger(0);
this.foundLast = new AtomicInteger(0);
this.foundTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2)));
jobs.put(job.getWorld(), job);
this.pos = 0;
jobs.put(job.getWorld().getName(), job);
DeepSearchPregenerator.instance = this;
}
@@ -108,29 +111,22 @@ public class DeepSearchPregenerator extends Thread implements Listener {
// chunkCache(); //todo finish this
if (latch.flip() && !job.paused) {
if (cacheLock.isLocked()) {
Iris.info("DeepFinder: Caching: " + chunkCachePos.get() + " Of " + chunkCacheSize.get());
} else {
long eta = computeETA();
save();
int secondGenerated = foundChunks.get() - foundLast.get();
foundLast.set(foundChunks.get());
secondGenerated = secondGenerated / 3;
chunksPerSecond.put(secondGenerated);
chunksPerMinute.put(secondGenerated * 60);
Iris.info("DeepFinder: " + C.IRIS + world.getName() + C.RESET + " Searching: " + Form.f(foundChunks.get()) + " of " + Form.f(foundTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
}
long eta = computeETA();
save();
int secondGenerated = foundChunks.get() - foundLast.get();
foundLast.set(foundChunks.get());
secondGenerated = secondGenerated / 3;
chunksPerSecond.put(secondGenerated);
chunksPerMinute.put(secondGenerated * 60);
Iris.info("deepFinder: " + C.IRIS + world.getName() + C.RESET + " RTT: " + Form.f(foundChunks.get()) + " of " + Form.f(foundTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2));
}
if (foundChunks.get() >= foundTotalChunks.get()) {
Iris.info("Completed DeepSearch!");
interrupt();
} else {
int pos = job.getPosition() + 1;
job.setPosition(pos);
if (!job.paused) {
tickSearch(getChunk(pos));
}
}
}
@@ -141,22 +137,18 @@ public class DeepSearchPregenerator extends Thread implements Listener {
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
private void tickSearch(Position2 chunk) {
executorService.submit(() -> {
CountDownLatch latch = new CountDownLatch(1);
try {
findInChunk(world, chunk.getX(), chunk.getZ());
} catch (IOException e) {
throw new RuntimeException(e);
private void queueSystem(Position2 chunk) {
if (chunkQueue.isEmpty()) {
for (int limit = 512; limit != 0; limit--) {
pos = job.getPosition() + 1;
chunkQueue.add(getChunk(pos));
}
Iris.verbose("Generated Async " + chunk);
latch.countDown();
} else {
//MCAUtil.read();
}
try {
latch.await();
} catch (InterruptedException ignored) {}
foundChunks.addAndGet(1);
});
}
private void findInChunk(World world, int x, int z) throws IOException {
@@ -271,7 +263,7 @@ public class DeepSearchPregenerator extends Thread implements Listener {
@Data
@Builder
public static class DeepSearchJob {
private String world;
private World world;
@Builder.Default
private int radiusBlocks = 5000;
@Builder.Default

View File

@@ -19,7 +19,9 @@
package com.volmit.iris.core.pregenerator;
import com.volmit.iris.Iris;
import com.volmit.iris.core.pack.IrisPack;
import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
@@ -30,15 +32,12 @@ import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.Looper;
import lombok.Getter;
import lombok.Setter;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmark;
public class IrisPregenerator {
private final PregenTask task;
@@ -50,6 +49,7 @@ public class IrisPregenerator {
private final RollingSequence chunksPerSecond;
private final RollingSequence chunksPerMinute;
private final RollingSequence regionsPerMinute;
private final KList<Integer> chunksPerSecondHistory;
private static AtomicInteger generated;
private final AtomicInteger generatedLast;
private final AtomicInteger generatedLastMinute;
@@ -62,8 +62,6 @@ public class IrisPregenerator {
private final KSet<Position2> net;
private final ChronoLatch cl;
private final ChronoLatch saveLatch = new ChronoLatch(30000);
static long long_generatedChunks = 0;
static long long_totalChunks = 0;
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
this.listener = listenify(listener);
@@ -80,6 +78,7 @@ public class IrisPregenerator {
chunksPerSecond = new RollingSequence(10);
chunksPerMinute = new RollingSequence(10);
regionsPerMinute = new RollingSequence(10);
chunksPerSecondHistory = new KList<>();
generated = new AtomicInteger(0);
generatedLast = new AtomicInteger(0);
generatedLastMinute = new AtomicInteger(0);
@@ -93,6 +92,7 @@ public class IrisPregenerator {
int secondGenerated = generated.get() - generatedLast.get();
generatedLast.set(generated.get());
chunksPerSecond.put(secondGenerated);
chunksPerSecondHistory.add(secondGenerated);
if (minuteLatch.flip()) {
int minuteGenerated = generated.get() - generatedLastMinute.get();
@@ -100,8 +100,6 @@ public class IrisPregenerator {
chunksPerMinute.put(minuteGenerated);
regionsPerMinute.put((double) minuteGenerated / 1024D);
}
long_generatedChunks = generated.get();
long_totalChunks = totalChunks.get();
listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(),
regionsPerMinute.getAverage(),
@@ -112,10 +110,10 @@ public class IrisPregenerator {
if (cl.flip()) {
double percentage = ((double) generated.get() / (double) totalChunks.get()) * 100;
if(benchmark) {
Iris.info(C.GREEN +"Benchmark: " + C.WHITE + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (%.0f%%) " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2), percentage);
if (!IrisPackBenchmarking.benchmarkInProgress) {
Iris.info("Pregen: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (%.0f%%) " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration(eta, 2), percentage);
} else {
Iris.info("Pregen: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (%.0f%%) " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2), percentage);
Iris.info("Benchmarking: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (%.0f%%) " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration(eta, 2), percentage);
}
}
return 1000;
@@ -128,17 +126,10 @@ public class IrisPregenerator {
// If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers)
((totalChunks.get() - generated.get()) * ((double) (M.ms() - startTime.get()) / (double) generated.get())) :
// If no, use quick function (which is less accurate over time but responds better to the initial delay)
((totalChunks.get() - generated.get()) / chunksPerSecond.getAverage()) * 1000 //
((totalChunks.get() - generated.get()) / chunksPerSecond.getAverage()) * 1000
);
}
public static long getLongGeneratedChunks() {
return long_generatedChunks;
}
public static long getLongTotalChunks() {
return long_totalChunks;
}
public void close() {
shutdown.set(true);
@@ -151,6 +142,11 @@ public class IrisPregenerator {
task.iterateRegions((x, z) -> visitRegion(x, z, true));
task.iterateRegions((x, z) -> visitRegion(x, z, false));
shutdown();
if (!IrisPackBenchmarking.benchmarkInProgress) {
Iris.info(C.IRIS + "Pregen stopped.");
} else {
IrisPackBenchmarking.instance.finishedBenchmark(chunksPerSecondHistory);
}
}
private void checkRegions() {
@@ -167,7 +163,10 @@ public class IrisPregenerator {
generator.close();
ticker.interrupt();
listener.onClose();
getMantle().trim(0, 0);
Mantle mantle = getMantle();
if (mantle != null) {
mantle.trim(0, 0);
}
}
private void visitRegion(int x, int z, boolean regions) {

View File

@@ -35,6 +35,8 @@ public class PregenTask {
private static final KList<Position2> ORDER_CENTER = computeChunkOrder();
private static final KMap<Position2, KList<Position2>> ORDERS = new KMap<>();
@Builder.Default
private boolean gui = false;
@Builder.Default
private Position2 center = new Position2(0, 0);
@Builder.Default

View File

@@ -3,11 +3,11 @@ package com.volmit.iris.core.safeguard;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
import org.apache.logging.log4j.core.util.ExecutorServices;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import javax.print.attribute.standard.Severity;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
@@ -15,11 +15,9 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static com.volmit.iris.Iris.getJavaVersion;
import static com.volmit.iris.Iris.instance;
@@ -84,7 +82,7 @@ public class ServerBootSFG {
severityHigh++;
}
if (getJavaVersion() != 17) {
if (!List.of(17, 21).contains(getJavaVersion())) {
isJDK17 = false;
joiner.add("Unsupported Java version");
severityMedium++;
@@ -96,11 +94,11 @@ public class ServerBootSFG {
severityMedium++;
}
if (!hasPrivileges()){
hasPrivileges = false;
joiner.add("Insufficient Privileges");
severityMedium++;
}
// if (!hasPrivileges()){
// hasPrivileges = false;
// joiner.add("Insufficient Privileges");
// severityMedium++;
// } Some servers dont like this
if (!enoughDiskSpace()){
hasEnoughDiskSpace = false;
@@ -128,36 +126,25 @@ public class ServerBootSFG {
}
}
public static boolean isJDK() {
String path = System.getProperty("sun.boot.library.path");
if (path != null) {
String javacPath = "";
if (path.endsWith(File.separator + "bin")) {
javacPath = path;
} else {
int libIndex = path.lastIndexOf(File.separator + "lib");
if (libIndex > 0) {
javacPath = path.substring(0, libIndex) + File.separator + "bin";
}
}
if (checkJavac(javacPath))
return true;
}
path = System.getProperty("java.home");
return path != null && checkJavac(path + File.separator + "bin");
}
public static boolean isJDK() {
try {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
// If the compiler is null, it means this is a JRE environment, not a JDK.
return compiler != null;
} catch (Exception ignored) {}
return false;
}
public static boolean hasPrivileges() {
return true ;
// Path pv = Paths.get(Bukkit.getWorldContainer() + "iristest.json");
// try (FileChannel fc = FileChannel.open(pv, StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
// if (Files.isReadable(pv) && Files.isWritable(pv)) {
// return true;
// }
// } catch (Exception e) {
// return false;
// }
// return false;
Path pv = Paths.get(Bukkit.getWorldContainer() + "iristest.json");
try (FileChannel fc = FileChannel.open(pv, StandardOpenOption.CREATE, StandardOpenOption.DELETE_ON_CLOSE, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
if (Files.isReadable(pv) && Files.isWritable(pv)) {
return true;
}
} catch (Exception e) {
return false;
}
return false;
}
public static boolean enoughDiskSpace() {

View File

@@ -37,7 +37,7 @@ public class UtilsSFG {
}
if (ServerBootSFG.unsuportedversion) {
Iris.safeguard(C.RED + "Server Version");
Iris.safeguard(C.RED + "- Iris only supports 1.19.2 > 1.20.2");
Iris.safeguard(C.RED + "- Iris only supports 1.19.2 > 1.20.6");
}
if (!ServerBootSFG.passedserversoftware) {
Iris.safeguard(C.YELLOW + "Unsupported Server Software");
@@ -53,11 +53,11 @@ public class UtilsSFG {
}
if (!ServerBootSFG.isJDK17) {
Iris.safeguard(C.YELLOW + "Unsupported java version");
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 Instead of JDK " + Iris.getJavaVersion());
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 (or 21 for 1.20.6) Instead of JDK " + Iris.getJavaVersion());
}
if (ServerBootSFG.isJRE) {
Iris.safeguard(C.YELLOW + "Unsupported Server JDK");
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 Instead of JRE " + Iris.getJavaVersion());
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 (or 21 for 1.20.6) Instead of JRE " + Iris.getJavaVersion());
}
}
}

View File

@@ -1,119 +1,142 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.core.service;
import com.volmit.iris.Iris;
import com.volmit.iris.core.link.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.plugin.IrisService;
import lombok.Data;
import org.bukkit.Bukkit;
import org.bukkit.block.data.BlockData;
import org.bukkit.event.EventHandler;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.inventory.ItemStack;
import java.util.MissingResourceException;
import java.util.Optional;
@Data
public class ExternalDataSVC implements IrisService {
private KList<ExternalDataProvider> providers = new KList<>(), activeProviders = new KList<>();
@Override
public void onEnable() {
Iris.info("Loading ExternalDataProvider...");
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
providers.add(new OraxenDataProvider());
if (Bukkit.getPluginManager().getPlugin("Oraxen") != null) {
Iris.info("Oraxen found, loading OraxenDataProvider...");
}
providers.add(new ItemAdderDataProvider());
if (Bukkit.getPluginManager().getPlugin("ItemAdder") != null) {
Iris.info("ItemAdder found, loading ItemAdderDataProvider...");
}
providers.add(new ExecutableItemsDataProvider());
if (Bukkit.getPluginManager().getPlugin("ExecutableItems") != null) {
Iris.info("ExecutableItems found, loading ExecutableItemsDataProvider...");
}
for (ExternalDataProvider p : providers) {
if (p.isReady()) {
activeProviders.add(p);
p.init();
Iris.info("Enabled ExternalDataProvider for %s.", p.getPluginId());
}
}
}
@Override
public void onDisable() {
}
@EventHandler
public void onPluginEnable(PluginEnableEvent e) {
if (activeProviders.stream().noneMatch(p -> p.getPlugin().equals(e.getPlugin()))) {
providers.stream().filter(p -> p.isReady() && p.getPlugin().equals(e.getPlugin())).findFirst().ifPresent(edp -> {
activeProviders.add(edp);
edp.init();
Iris.info("Enabled ExternalDataProvider for %s.", edp.getPluginId());
});
}
}
public Optional<BlockData> getBlockData(Identifier key) {
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, false)).findFirst();
if (provider.isEmpty())
return Optional.empty();
try {
return Optional.of(provider.get().getBlockData(key));
} catch (MissingResourceException e) {
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
return Optional.empty();
}
}
public Optional<ItemStack> getItemStack(Identifier key) {
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, true)).findFirst();
if (provider.isEmpty()) {
Iris.warn("No matching Provider found for modded material \"%s\"!", key);
return Optional.empty();
}
try {
return Optional.of(provider.get().getItemStack(key));
} catch (MissingResourceException e) {
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
return Optional.empty();
}
}
public Identifier[] getAllBlockIdentifiers() {
KList<Identifier> names = new KList<>();
activeProviders.forEach(p -> names.add(p.getBlockTypes()));
return names.toArray(new Identifier[0]);
}
public Identifier[] getAllItemIdentifiers() {
KList<Identifier> names = new KList<>();
activeProviders.forEach(p -> names.add(p.getItemTypes()));
return names.toArray(new Identifier[0]);
}
}
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.core.service;
import com.volmit.iris.Iris;
import com.volmit.iris.core.link.*;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.plugin.IrisService;
import lombok.Data;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.event.EventHandler;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.inventory.ItemStack;
import java.util.MissingResourceException;
import java.util.Optional;
@Data
public class ExternalDataSVC implements IrisService {
private KList<ExternalDataProvider> providers = new KList<>(), activeProviders = new KList<>();
@Override
public void onEnable() {
Iris.info("Loading ExternalDataProvider...");
Bukkit.getPluginManager().registerEvents(this, Iris.instance);
providers.add(new OraxenDataProvider());
if (Bukkit.getPluginManager().getPlugin("Oraxen") != null) {
Iris.info("Oraxen found, loading OraxenDataProvider...");
}
providers.add(new ItemAdderDataProvider());
if (Bukkit.getPluginManager().getPlugin("ItemAdder") != null) {
Iris.info("ItemAdder found, loading ItemAdderDataProvider...");
}
providers.add(new ExecutableItemsDataProvider());
if (Bukkit.getPluginManager().getPlugin("ExecutableItems") != null) {
Iris.info("ExecutableItems found, loading ExecutableItemsDataProvider...");
}
providers.add(new HMCLeavesDataProvider());
if (Bukkit.getPluginManager().getPlugin("HMCLeaves") != null) {
Iris.info("BlockAdder found, loading HMCLeavesDataProvider...");
}
providers.add(new MMOItemsDataProvider());
if (Bukkit.getPluginManager().getPlugin("MMOItems") != null) {
Iris.info("MMOItems found, loading MMOItemsDataProvider...");
}
providers.add(new EcoItemsDataProvider());
if (Bukkit.getPluginManager().getPlugin("EcoItems") != null) {
Iris.info("EcoItems found, loading EcoItemsDataProvider...");
}
for (ExternalDataProvider p : providers) {
if (p.isReady()) {
activeProviders.add(p);
p.init();
Iris.info("Enabled ExternalDataProvider for %s.", p.getPluginId());
}
}
}
@Override
public void onDisable() {
}
@EventHandler
public void onPluginEnable(PluginEnableEvent e) {
if (activeProviders.stream().noneMatch(p -> p.getPlugin().equals(e.getPlugin()))) {
providers.stream().filter(p -> p.isReady() && p.getPlugin().equals(e.getPlugin())).findFirst().ifPresent(edp -> {
activeProviders.add(edp);
edp.init();
Iris.info("Enabled ExternalDataProvider for %s.", edp.getPluginId());
});
}
}
public Optional<BlockData> getBlockData(Identifier key) {
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, false)).findFirst();
if (provider.isEmpty())
return Optional.empty();
try {
return Optional.of(provider.get().getBlockData(key));
} catch (MissingResourceException e) {
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
return Optional.empty();
}
}
public Optional<ItemStack> getItemStack(Identifier key) {
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, true)).findFirst();
if (provider.isEmpty()) {
Iris.warn("No matching Provider found for modded material \"%s\"!", key);
return Optional.empty();
}
try {
return Optional.of(provider.get().getItemStack(key));
} catch (MissingResourceException e) {
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
return Optional.empty();
}
}
public void processUpdate(Engine engine, Block block, Identifier blockId) {
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(blockId, false)).findFirst();
if (provider.isEmpty()) {
Iris.warn("No matching Provider found for modded material \"%s\"!", blockId);
return;
}
provider.get().processUpdate(engine, block, blockId);
}
public Identifier[] getAllBlockIdentifiers() {
KList<Identifier> names = new KList<>();
activeProviders.forEach(p -> names.add(p.getBlockTypes()));
return names.toArray(new Identifier[0]);
}
public Identifier[] getAllItemIdentifiers() {
KList<Identifier> names = new KList<>();
activeProviders.forEach(p -> names.add(p.getItemTypes()));
return names.toArray(new Identifier[0]);
}
}

View File

@@ -1,35 +1,76 @@
package com.volmit.iris.core.service;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.mantle.TectonicPlate;
import com.volmit.iris.util.misc.getHardware;
import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.Looper;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.ServerLoadEvent;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.event.world.WorldUnloadEvent;
import org.checkerframework.checker.units.qual.A;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;
public class IrisEngineSVC implements IrisService {
public static IrisEngineSVC instance;
public boolean isServerShuttingDown = false;
public boolean isServerLoaded = false;
private static final AtomicInteger tectonicLimit = new AtomicInteger(30);
private final ReentrantLock lastUseLock = new ReentrantLock();
private final KMap<World, Long> lastUse = new KMap<>();
private ReentrantLock lastUseLock;
private KMap<World, Long> lastUse;
private List<World> IrisWorlds;
private Looper cacheTicker;
private Looper trimTicker;
private Looper unloadTicker;
private Looper updateTicker;
private PrecisionStopwatch trimAlive;
private PrecisionStopwatch unloadAlive;
public PrecisionStopwatch trimActiveAlive;
public PrecisionStopwatch unloadActiveAlive;
private AtomicInteger TotalTectonicPlates;
private AtomicInteger TotalQueuedTectonicPlates;
private AtomicInteger TotalNotQueuedTectonicPlates;
private AtomicBoolean IsUnloadAlive;
private AtomicBoolean IsTrimAlive;
ChronoLatch cl;
public List<World> corruptedIrisWorlds = new ArrayList<>();
@Override
public void onEnable() {
this.cl = new ChronoLatch(5000);
lastUse = new KMap<>();
lastUseLock = new ReentrantLock();
IrisWorlds = new ArrayList<>();
IsUnloadAlive = new AtomicBoolean(true);
IsTrimAlive = new AtomicBoolean(true);
trimActiveAlive = new PrecisionStopwatch();
unloadActiveAlive = new PrecisionStopwatch();
trimAlive = new PrecisionStopwatch();
unloadAlive = new PrecisionStopwatch();
TotalTectonicPlates = new AtomicInteger();
TotalQueuedTectonicPlates = new AtomicInteger();
TotalNotQueuedTectonicPlates = new AtomicInteger();
tectonicLimit.set(2);
long t = getHardware.getProcessMemory();
while (t > 200) {
@@ -37,15 +78,69 @@ public class IrisEngineSVC implements IrisService {
t = t - 200;
}
this.setup();
this.TrimLogic();
this.UnloadLogic();
trimAlive.begin();
unloadAlive.begin();
trimActiveAlive.begin();
unloadActiveAlive.begin();
updateTicker.start();
cacheTicker.start();
trimTicker.start();
unloadTicker.start();
//trimTicker.start();
//unloadTicker.start();
instance = this;
}
public void engineStatus() {
boolean trimAlive = trimTicker.isAlive();
boolean unloadAlive = unloadTicker.isAlive();
Iris.info("Status:");
Iris.info("- Trim: " + trimAlive);
Iris.info("- Unload: " + unloadAlive);
}
public static int getTectonicLimit() {
return tectonicLimit.get();
}
@EventHandler
public void onWorldUnload(WorldUnloadEvent event) {
updateWorlds();
}
@EventHandler
public void onWorldLoad(WorldLoadEvent event) {
updateWorlds();
}
@EventHandler
public void onServerBoot(ServerLoadEvent event) {
isServerLoaded = true;
}
@EventHandler
public void onPluginDisable(PluginDisableEvent event) {
if (event.getPlugin().equals(Iris.instance)) {
isServerShuttingDown = true;
}
}
public void updateWorlds() {
for (World world : Bukkit.getWorlds()) {
try {
if (IrisToolbelt.access(world).getEngine() != null) {
IrisWorlds.add(world);
}
} catch (Exception e) {
// no
}
}
}
private void setup() {
cacheTicker = new Looper() {
@Override
@@ -57,7 +152,7 @@ public class IrisEngineSVC implements IrisService {
Long last = lastUse.get(key);
if (last == null)
continue;
if (now - last > 60000) { // 1 minute
if (now - last > 60000) {
lastUse.remove(key);
}
}
@@ -67,57 +162,115 @@ public class IrisEngineSVC implements IrisService {
return 1000;
}
};
trimTicker = new Looper() {
private final Supplier<Engine> supplier = createSupplier();
updateTicker = new Looper() {
@Override
protected long loop() {
long start = System.currentTimeMillis();
try {
Engine engine = supplier.get();
if (engine != null) {
engine.getMantle().trim(tectonicLimit.get() / lastUse.size());
TotalQueuedTectonicPlates.set(0);
TotalNotQueuedTectonicPlates.set(0);
TotalTectonicPlates.set(0);
for (World world : IrisWorlds) {
Engine engine = Objects.requireNonNull(IrisToolbelt.access(world)).getEngine();
TotalQueuedTectonicPlates.addAndGet((int) engine.getMantle().getToUnload());
TotalNotQueuedTectonicPlates.addAndGet((int) engine.getMantle().getNotQueuedLoadedRegions());
TotalTectonicPlates.addAndGet(engine.getMantle().getLoadedRegionCount());
}
} catch (Throwable e) {
Iris.reportError(e);
// return -1;
}
if (!isServerShuttingDown && isServerLoaded) {
if (!trimTicker.isAlive()) {
Iris.info(C.RED + "TrimTicker found dead! Booting it up!");
try {
TrimLogic();
} catch (Exception e) {
Iris.error("What happened?");
e.printStackTrace();
}
}
int size = lastUse.size();
long time = (size > 0 ? 1000/size : 1000) - (System.currentTimeMillis() - start);
if (time <= 0)
return 0;
return time;
}
};
unloadTicker = new Looper() {
private final Supplier<Engine> supplier = createSupplier();
@Override
protected long loop() {
long start = System.currentTimeMillis();
try {
Engine engine = supplier.get();
if (engine != null) {
long unloadStart = System.currentTimeMillis();
int count = engine.getMantle().unloadTectonicPlate(tectonicLimit.get() / lastUse.size());
if (count > 0) {
Iris.debug(C.GOLD + "Unloaded " + C.YELLOW + count + " TectonicPlates in " + C.RED + Form.duration(System.currentTimeMillis() - unloadStart, 2));
if (!unloadTicker.isAlive()) {
Iris.info(C.RED + "UnloadTicker found dead! Booting it up!");
try {
UnloadLogic();
} catch (Exception e) {
Iris.error("What happened?");
e.printStackTrace();
}
}
}
} catch (Throwable e) {
Iris.reportError(e);
} catch (Exception e) {
return -1;
}
int size = lastUse.size();
long time = (size > 0 ? 1000/size : 1000) - (System.currentTimeMillis() - start);
if (time <= 0)
return 0;
return time;
return 1000;
}
};
}
public void TrimLogic() {
if (trimTicker == null || !trimTicker.isAlive()) {
trimTicker = new Looper() {
private final Supplier<Engine> supplier = createSupplier();
@Override
protected long loop() {
long start = System.currentTimeMillis();
trimAlive.reset();
try {
Engine engine = supplier.get();
if (engine != null) {
engine.getMantle().trim(tectonicLimit.get() / lastUse.size());
}
} catch (Throwable e) {
Iris.reportError(e);
Iris.info(C.RED + "EngineSVC: Failed to trim.");
e.printStackTrace();
return -1;
}
int size = lastUse.size();
long time = (size > 0 ? 1000 / size : 1000) - (System.currentTimeMillis() - start);
if (time <= 0)
return 0;
return time;
}
};
trimTicker.start();
}
}
public void UnloadLogic() {
if (unloadTicker == null || !unloadTicker.isAlive()) {
unloadTicker = new Looper() {
private final Supplier<Engine> supplier = createSupplier();
@Override
protected long loop() {
long start = System.currentTimeMillis();
unloadAlive.reset();
try {
Engine engine = supplier.get();
if (engine != null) {
long unloadStart = System.currentTimeMillis();
int count = engine.getMantle().unloadTectonicPlate(tectonicLimit.get() / lastUse.size());
if (count > 0) {
Iris.debug(C.GOLD + "Unloaded " + C.YELLOW + count + " TectonicPlates in " + C.RED + Form.duration(System.currentTimeMillis() - unloadStart, 2));
}
}
} catch (Throwable e) {
Iris.reportError(e);
Iris.info(C.RED + "EngineSVC: Failed to unload.");
e.printStackTrace();
return -1;
}
int size = lastUse.size();
long time = (size > 0 ? 1000 / size : 1000) - (System.currentTimeMillis() - start);
if (time <= 0)
return 0;
return time;
}
};
unloadTicker.start();
}
}
private Supplier<Engine> createSupplier() {
AtomicInteger i = new AtomicInteger();
@@ -136,7 +289,8 @@ public class IrisEngineSVC implements IrisService {
if (generator != null) {
Engine engine = generator.getEngine();
if (engine != null) {
boolean closed = engine.getMantle().getData().isClosed();
if (engine != null && !engine.isStudio() && !closed) {
lastUseLock.lock();
lastUse.put(world, System.currentTimeMillis());
lastUseLock.unlock();
@@ -145,6 +299,8 @@ public class IrisEngineSVC implements IrisService {
}
}
} catch (Throwable e) {
Iris.info(C.RED + "EngineSVC: Failed to create supplier.");
e.printStackTrace();
Iris.reportError(e);
}
return null;

View File

@@ -30,9 +30,11 @@ import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.matter.Matter;
import com.volmit.iris.util.matter.WorldMatter;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.S;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
@@ -53,6 +55,9 @@ import java.util.ArrayList;
import java.util.Objects;
public class WandSVC implements IrisService {
private static final Particle CRIT_MAGIC = E.getOrDefault(Particle.class, "CRIT_MAGIC", "CRIT");
private static final Particle REDSTONE = E.getOrDefault(Particle.class, "REDSTONE", "DUST");
private static ItemStack dust;
private static ItemStack wand;
@@ -162,11 +167,11 @@ public class WandSVC implements IrisService {
*/
public static ItemStack createDust() {
ItemStack is = new ItemStack(Material.GLOWSTONE_DUST);
is.addUnsafeEnchantment(Enchantment.ARROW_INFINITE, 1);
is.addUnsafeEnchantment(Enchantment.FIRE_ASPECT, 1);
ItemMeta im = is.getItemMeta();
im.setDisplayName(C.BOLD + "" + C.YELLOW + "Dust of Revealing");
im.setUnbreakable(true);
im.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_PLACED_ON, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_DESTROYS, ItemFlag.HIDE_ENCHANTS);
im.addItemFlags(ItemFlag.values());
im.setLore(new KList<String>().qadd("Right click on a block to reveal it's placement structure!"));
is.setItemMeta(im);
@@ -206,11 +211,11 @@ public class WandSVC implements IrisService {
*/
public static ItemStack createWand(Location a, Location b) {
ItemStack is = new ItemStack(Material.BLAZE_ROD);
is.addUnsafeEnchantment(Enchantment.ARROW_INFINITE, 1);
is.addUnsafeEnchantment(Enchantment.FIRE_ASPECT, 1);
ItemMeta im = is.getItemMeta();
im.setDisplayName(C.BOLD + "" + C.GOLD + "Wand of Iris");
im.setUnbreakable(true);
im.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_PLACED_ON, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_DESTROYS, ItemFlag.HIDE_ENCHANTS);
im.addItemFlags(ItemFlag.values());
im.setLore(new KList<String>().add(locationToString(a), locationToString(b)));
is.setItemMeta(im);
@@ -311,7 +316,7 @@ public class WandSVC implements IrisService {
*/
public void draw(Location[] d, Player p) {
Vector gx = Vector.getRandom().subtract(Vector.getRandom()).normalize().clone().multiply(0.65);
d[0].getWorld().spawnParticle(Particle.CRIT_MAGIC, d[0], 1, 0.5 + gx.getX(), 0.5 + gx.getY(), 0.5 + gx.getZ(), 0, null, false);
d[0].getWorld().spawnParticle(CRIT_MAGIC, d[0], 1, 0.5 + gx.getX(), 0.5 + gx.getY(), 0.5 + gx.getZ(), 0, null, false);
Vector gxx = Vector.getRandom().subtract(Vector.getRandom()).normalize().clone().multiply(0.65);
d[1].getWorld().spawnParticle(Particle.CRIT, d[1], 1, 0.5 + gxx.getX(), 0.5 + gxx.getY(), 0.5 + gxx.getZ(), 0, null, false);
@@ -370,7 +375,7 @@ public class WandSVC implements IrisService {
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
p.spawnParticle(Particle.REDSTONE, lv.getX(), lv.getY(), lv.getZ(), 1, 0, 0, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(r, g, b), 0.75f));
p.spawnParticle(REDSTONE, lv.getX(), lv.getY(), lv.getZ(), 1, 0, 0, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(r, g, b), 0.75f));
}
}
}

View File

@@ -1,31 +0,0 @@
package com.volmit.iris.core.service;
import com.volmit.iris.Iris;
import com.volmit.iris.util.plugin.IrisService;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldLoadEvent;
import org.bukkit.plugin.java.JavaPlugin;
import static java.lang.System.getLogger;
public class WorldLoadSFG implements IrisService {
private JavaPlugin plugin;
@EventHandler
public void onWorldLoad(WorldLoadEvent event) {
World world = event.getWorld();
}
@Override
public void onEnable() {
this.plugin = Iris.instance;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@Override
public void onDisable() {
}
}

View File

@@ -28,7 +28,6 @@ import java.io.InputStreamReader;
import static com.google.common.math.LongMath.isPrime;
import static com.volmit.iris.util.misc.getHardware.getCPUModel;
import static com.volmit.iris.util.misc.getHardware.getDiskModel;
public class IrisBenchmarking {
static String ServerOS;
static String filePath = "benchmark.dat";
@@ -180,12 +179,12 @@ public class IrisBenchmarking {
Iris.info("- Data Compression: " + formatDouble(calculateDataCompression) + " MBytes/Sec");
if (WindowsDiskSpeed) {
Iris.info("Disk Model: " + getDiskModel());
//Iris.info("Disk Model: " + getDiskModel());
Iris.info(C.BLUE + "- Running with Windows System Assessment Tool");
Iris.info("- Sequential 64.0 Write: " + C.BLUE + formatDouble(avgWriteSpeedMBps) + " Mbps");
Iris.info("- Sequential 64.0 Read: " + C.BLUE + formatDouble(avgReadSpeedMBps) + " Mbps");
} else {
Iris.info("Disk Model: " + getDiskModel());
// Iris.info("Disk Model: " + getDiskModel());
Iris.info(C.GREEN + "- Running in Native Mode");
Iris.info("- Average Write Speed: " + C.GREEN + formatDouble(avgWriteSpeedMBps) + " Mbps");
Iris.info("- Average Read Speed: " + C.GREEN + formatDouble(avgReadSpeedMBps) + " Mbps");

View File

@@ -0,0 +1,395 @@
package com.volmit.iris.core.tools;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.io.NamedTag;
import com.volmit.iris.util.nbt.tag.*;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.reflect.V;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.util.Vector;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class IrisConverter {
public static void convertSchematics(VolmitSender sender) {
File folder = Iris.instance.getDataFolder("convert");
FilenameFilter filter = (dir, name) -> name.endsWith(".schem");
File[] fileList = folder.listFiles(filter);
ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.submit(() -> {
for (File schem : fileList) {
try {
PrecisionStopwatch p = new PrecisionStopwatch();
boolean largeObject = false;
NamedTag tag = null;
try {
tag = NBTUtil.read(schem);
} catch (IOException e) {
Iris.info(C.RED + "Failed to read: " + schem.getName());
throw new RuntimeException(e);
}
CompoundTag compound = (CompoundTag) tag.getTag();
if (compound.containsKey("Palette") && compound.containsKey("Width") && compound.containsKey("Height") && compound.containsKey("Length")) {
int objW = ((ShortTag) compound.get("Width")).getValue();
int objH = ((ShortTag) compound.get("Height")).getValue();
int objD = ((ShortTag) compound.get("Length")).getValue();
int mv = objW * objH * objD;
AtomicInteger v = new AtomicInteger(0);
AtomicInteger fv = new AtomicInteger(0);
if (mv > 500_000) {
largeObject = true;
Iris.info(C.GRAY + "Converting.. "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
Iris.info(C.GRAY + "- It may take a while");
if (sender.isPlayer()) {
J.a(() -> {
// while (v.get() != mv) {
// double pr = ((double) v.get() / (double ) mv);
// sender.sendProgress(pr, "Converting");
// J.sleep(16);
// }
});
}
}
CompoundTag paletteTag = (CompoundTag) compound.get("Palette");
Map<Integer, BlockData> blockmap = new HashMap<>(paletteTag.size(), 0.9f);
for (Map.Entry<String, Tag<?>> entry : paletteTag.getValue().entrySet()) {
String blockName = entry.getKey();
BlockData bd = Bukkit.createBlockData(blockName);
Tag<?> blockTag = entry.getValue();
int blockId = ((IntTag) blockTag).getValue();
blockmap.put(blockId, bd);
}
ByteArrayTag byteArray = (ByteArrayTag) compound.get("BlockData");
byte[] originalBlockArray = byteArray.getValue();
int b = 0;
int a = 0;
Map<Integer, Byte> y = new HashMap<>();
Map<Integer, Byte> x = new HashMap<>();
Map<Integer, Byte> z = new HashMap<>();
// Height adjustments
for (int h = 0; h < objH; h++) {
if (b == 0) {
y.put(h, (byte) 0);
}
if (b > 0) {
y.put(h, (byte) 1);
}
a = 0;
b = 0;
for (int d = 0; d < objD; d++) {
for (int w = 0; w < objW; w++) {
BlockData db = blockmap.get((int) originalBlockArray[fv.get()]);
if(db.getAsString().contains("minecraft:air")) {
a++;
} else {
b++;
}
fv.getAndAdd(1);
}
}
}
fv.set(0);
// Width adjustments
for (int w = 0; w < objW; w++) {
if (b == 0) {
x.put(w, (byte) 0);
}
if (b > 0) {
x.put(w, (byte) 1);
}
a = 0;
b = 0;
for (int h = 0; h < objH; h++) {
for (int d = 0; d < objD; d++) {
BlockData db = blockmap.get((int) originalBlockArray[fv.get()]);
if(db.getAsString().contains("minecraft:air")) {
a++;
} else {
b++;
}
fv.getAndAdd(1);
}
}
}
fv.set(0);
// Depth adjustments
for (int d = 0; d < objD; d++) {
if (b == 0) {
z.put(d, (byte) 0);
}
if (b > 0) {
z.put(d, (byte) 1);
}
a = 0;
b = 0;
for (int h = 0; h < objH; h++) {
for (int w = 0; w < objW; w++) {
BlockData db = blockmap.get((int) originalBlockArray[fv.get()]);
if(db.getAsString().contains("minecraft:air")) {
a++;
} else {
b++;
}
fv.getAndAdd(1);
}
}
}
fv.set(0);
int CorrectObjH = getCorrectY(y, objH);
int CorrectObjW = getCorrectX(x, objW);
int CorrectObjD = getCorrectZ(z, objD);
//IrisObject object = new IrisObject(CorrectObjW, CorrectObjH, CorrectObjH);
IrisObject object = new IrisObject(objW, objH, objD);
Vector originalVector = new Vector(objW,objH,objD);
int[] yc = null;
int[] xc = null;
int[] zc = null;
int fo = 0;
int so = 0;
int o = 0;
int c = 0;
for (Integer i : y.keySet()) {
if (y.get(i) == 0) {
o++;
}
if (y.get(i) == 1) {
c++;
if (c == 1) {
fo = o;
}
o = 0;
}
}
so = o;
yc = new int[]{fo, so};
fo = 0;
so = 0;
o = 0;
c = 0;
for (Integer i : x.keySet()) {
if (x.get(i) == 0) {
o++;
}
if (x.get(i) == 1) {
c++;
if (c == 1) {
fo = o;
}
o = 0;
}
}
so = o;
xc = new int[]{fo, so};
fo = 0;
so = 0;
o = 0;
c = 0;
for (Integer i : z.keySet()) {
if (z.get(i) == 0) {
o++;
}
if (z.get(i) == 1) {
c++;
if (c == 1) {
fo = o;
}
o = 0;
}
}
so = o;
zc = new int[]{fo, so};
int h1, h2, w1, w2, v1 = 0, volume = objW * objH * objD;
Map<Integer, Integer> blockLocationMap = new LinkedHashMap<>();
boolean hasAir = false;
int pos = 0;
for (int i : originalBlockArray) {
blockLocationMap.put(pos, i);
pos++;
}
for (int h = 0; h < objH; h++) {
for (int d = 0; d < objD; d++) {
for (int w = 0; w < objW; w++) {
BlockData bd = blockmap.get((int) originalBlockArray[v.get()]);
if (!bd.getMaterial().isAir()) {
object.setUnsigned(w, h, d, bd);
}
v.getAndAdd(1);
}
}
}
try {
object.write(new File(folder, schem.getName().replace(".schem", ".iob")));
} catch (IOException e) {
Iris.info(C.RED + "Failed to save: " + schem.getName());
throw new RuntimeException(e);
}
if (sender.isPlayer()) {
if (largeObject) {
sender.sendMessage(C.IRIS + "Converted "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
} else {
sender.sendMessage(C.IRIS + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
}
}
if (largeObject) {
Iris.info(C.GRAY + "Converted "+ schem.getName() + " -> " + schem.getName().replace(".schem", ".iob") + " in " + Form.duration(p.getMillis()));
} else {
Iris.info(C.GRAY + "Converted " + schem.getName() + " -> " + schem.getName().replace(".schem", ".iob"));
}
// schem.delete();
}
} catch (Exception e) {
Iris.info(C.RED + "Failed to convert: " + schem.getName());
if (sender.isPlayer()) {
sender.sendMessage(C.RED + "Failed to convert: " + schem.getName());
}
e.printStackTrace();
Iris.reportError(e);
}
}
});
}
public static boolean isNewPointFurther(int[] originalPoint, int[] oldPoint, int[] newPoint) {
int oX = oldPoint[1];
int oY = oldPoint[2];
int oZ = oldPoint[3];
int nX = newPoint[1];
int nY = newPoint[2];
int nZ = newPoint[3];
int orX = originalPoint[1];
int orY = originalPoint[2];
int orZ = originalPoint[3];
double oldDistance = Math.sqrt(Math.pow(oX - orX, 2) + Math.pow(oY - orY, 2) + Math.pow(oZ - orZ, 2));
double newDistance = Math.sqrt(Math.pow(nX - orX, 2) + Math.pow(nY - orY, 2) + Math.pow(nZ - orZ, 2));
if (newDistance > oldDistance) {
return true;
}
return false;
}
public static int[] getCoordinates(int pos, int obX, int obY, int obZ) {
int z = 0;
int[] coords = new int[4];
for (int h = 0; h < obY; h++) {
for (int d = 0; d < obZ; d++) {
for (int w = 0; w < obX; w++) {
if (z == pos) {
coords[1] = w;
coords[2] = h;
coords[3] = d;
return coords;
}
z++;
}
}
}
return null;
}
public static int getCorrectY(Map<Integer, Byte> y, int H) {
int fo = 0;
int so = 0;
int o = 0;
int c = 0;
for (Integer i : y.keySet()) {
if (y.get(i) == 0) {
o++;
}
if (y.get(i) == 1) {
c++;
if(c == 1){
fo = o;
}
o = 0;
}
}
so = o;
return H = H - (fo + so);
}
public static int getCorrectX(Map<Integer, Byte> x, int W) {
int fo = 0;
int so = 0;
int o = 0;
int c = 0;
for (Integer i : x.keySet()) {
if (x.get(i) == 0) {
o++;
}
if (x.get(i) == 1) {
c++;
if(c == 1){
fo = o;
}
o = 0;
}
}
so = o;
return W = W - (fo + so);
}
public static int getCorrectZ(Map<Integer, Byte> z, int D) {
int fo = 0;
int so = 0;
int o = 0;
int c = 0;
for (Integer i : z.keySet()) {
if (z.get(i) == 0) {
o++;
}
if (z.get(i) == 1) {
c++;
if(c == 1){
fo = o;
}
o = 0;
}
}
so = o;
return D = D - (fo + so);
}
}

View File

@@ -46,10 +46,6 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmark;
import static com.volmit.iris.core.safeguard.IrisSafeguard.unstablemode;
/**
@@ -86,6 +82,11 @@ public class IrisCreator {
* the world itself. Studio worlds are deleted when they are unloaded.
*/
private boolean studio = false;
/**
* Benchmark mode
*/
private boolean benchmark = false;
private boolean smartVanillaHeight = false;
public static boolean removeFromBukkitYml(String name) throws IOException {
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
@@ -110,15 +111,8 @@ public class IrisCreator {
* @return the IrisAccess
* @throws IrisException shit happens
*/
IrisPackBenchmarking PackBench = new IrisPackBenchmarking();
public World create() throws IrisException {
if (unstablemode){
Iris.info(C.RED + "Your server is experiencing an incompatibility with the Iris plugin. Please rectify this problem to avoid further complications.");
Iris.info(C.RED + "----------------------------------------------------------------");
Iris.info(C.RED + "Operation ran: Loading Iris World..");
UtilsSFG.printIncompatibleWarnings();
Iris.info(C.RED + "----------------------------------------------------------------");
}
if (Bukkit.isPrimaryThread()) {
throw new IrisException("You cannot invoke create() on the main thread.");
}
@@ -149,6 +143,7 @@ public class IrisCreator {
.name(name)
.seed(seed)
.studio(studio)
.smartVanillaHeight(smartVanillaHeight)
.create();
ServerConfigurator.installDataPacks(false);
@@ -193,7 +188,7 @@ public class IrisCreator {
done.set(true);
if (sender.isPlayer()) {
if (sender.isPlayer() && !benchmark) {
J.s(() -> {
sender.player().teleport(new Location(world.get(), 0, world.get().getHighestBlockYAt(0, 0), 0));
});

View File

@@ -2,169 +2,200 @@ package com.volmit.iris.core.tools;
import com.volmit.iris.Iris;
import com.volmit.iris.core.pregenerator.IrisPregenerator;
import com.volmit.iris.core.pregenerator.LazyPregenerator;
import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.exceptions.IrisException;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.scheduling.J;
import org.apache.commons.io.FileUtils;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Getter;
import org.bukkit.Bukkit;
import java.io.File;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import static com.volmit.iris.core.commands.CommandIris.BenchDimension;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.Clock;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.concurrent.*;
public class IrisPackBenchmarking {
public static boolean loaded = false;
public static boolean benchmark = false;
static boolean cancelled = false;
static boolean pregenInProgress = false;
static long startTime;
static long totalChunks;
static long generatedChunks;
static double elapsedTimeNs;
@Getter
public static IrisPackBenchmarking instance;
public static boolean benchmarkInProgress = false;
private IrisDimension IrisDimension;
private int radius;
private boolean finished = false;
PrecisionStopwatch stopwatch;
public static void runBenchmark() {
// IrisPackBenchmarking IrisPackBenchmarking = new IrisPackBenchmarking();
benchmark = true;
Iris.info(C.BLUE + "Benchmarking Dimension: " + C.AQUA + BenchDimension);
//progress();
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
Iris.info(C.GOLD + "Setting everything up..");
try {
String BenchmarkFolder = "\\Benchmark";
File folder = new File(BenchmarkFolder);
if (folder.exists() && folder.isDirectory()) {
FileUtils.deleteDirectory(folder);
Iris.debug("Deleted old Benchmark");
} else {
Iris.info(C.GOLD + "Old Benchmark not found!");
if(folder.exists()){
Iris.info(C.RED + "FAILED To remove old Benchmark!");
//cancelled = true;
public IrisPackBenchmarking(IrisDimension dimension, int r) {
instance = this;
this.IrisDimension = dimension;
this.radius = r;
runBenchmark();
}
}
private void runBenchmark() {
this.stopwatch = new PrecisionStopwatch();
ExecutorService service = Executors.newSingleThreadExecutor();
service.submit(() -> {
Iris.info("Setting up benchmark environment ");
benchmarkInProgress = true;
File file = new File("benchmark");
if (file.exists()) {
deleteDirectory(file.toPath());
}
createBenchmark();
while (!IrisToolbelt.isIrisWorld(Bukkit.getWorld("benchmark"))) {
J.sleep(1000);
Iris.debug("Iris PackBenchmark: Waiting...");
}
Iris.info("Starting Benchmark!");
stopwatch.begin();
startBenchmark();
});
}
public boolean getBenchmarkInProgress() {
return benchmarkInProgress;
}
public void finishedBenchmark(KList<Integer> cps) {
try {
String time = Form.duration(stopwatch.getMillis());
Engine engine = IrisToolbelt.access(Bukkit.getWorld("benchmark")).getEngine();
Iris.info("-----------------");
Iris.info("Results:");
Iris.info("- Total time: " + time);
Iris.info("- Average CPS: " + calculateAverage(cps));
Iris.info(" - Median CPS: " + calculateMedian(cps));
Iris.info(" - Highest CPS: " + findHighest(cps));
Iris.info(" - Lowest CPS: " + findLowest(cps));
Iris.info("-----------------");
Iris.info("Creating a report..");
File profilers = new File("plugins" + File.separator + "Iris" + File.separator + "packbenchmarks");
profilers.mkdir();
File results = new File("plugins " + File.separator + "Iris", IrisDimension.getName() + LocalDateTime.now(Clock.systemDefaultZone()) + ".txt");
results.createNewFile();
KMap<String, Double> metrics = engine.getMetrics().pull();
try (FileWriter writer = new FileWriter(results)) {
writer.write("-----------------\n");
writer.write("Results:\n");
writer.write("Dimension: " + IrisDimension.getName() + "\n");
writer.write("- Date of Benchmark: " + LocalDateTime.now(Clock.systemDefaultZone()) + "\n");
writer.write("\n");
writer.write("Metrics");
for (String m : metrics.k()) {
double i = metrics.get(m);
writer.write("- " + m + ": " + i);
}
} catch (Exception e) {
throw new RuntimeException();
writer.write("- " + metrics);
writer.write("Benchmark: " + LocalDateTime.now(Clock.systemDefaultZone()) + "\n");
writer.write("- Total time: " + time + "\n");
writer.write("- Average CPS: " + calculateAverage(cps) + "\n");
writer.write(" - Median CPS: " + calculateMedian(cps) + "\n");
writer.write(" - Highest CPS: " + findHighest(cps) + "\n");
writer.write(" - Lowest CPS: " + findLowest(cps) + "\n");
writer.write("-----------------\n");
Iris.info("Finished generating a report!");
} catch (IOException e) {
Iris.error("An error occurred writing to the file.");
e.printStackTrace();
}
}).thenRun(() -> {
Iris.info(C.GOLD + "Creating Benchmark Environment");
createBenchmark();
}).thenRun(() -> {
Iris.info( C.BLUE + "Benchmark Started!");
boolean done = false;
startBenchmarkTimer();
startBenchmark();
basicScheduler();
}).thenRun(() -> {
});
// cancelled = future.cancel(true);
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
Bukkit.getServer().unloadWorld("benchmark", true);
stopwatch.end();
} catch (Exception e) {
Iris.error("Something has gone wrong!");
e.printStackTrace();
}
}
private static void results(){
double averageCps = calculateAverageCPS();
Iris.info("Benchmark Dimension: " + BenchDimension);
Iris.info("Speeds");
Iris.info("- Average CPS: " + roundToTwoDecimalPlaces(averageCps));
Iris.info("Duration: " + roundToTwoDecimalPlaces(elapsedTimeNs));
}
private static void basicScheduler() {
while (true) {
totalChunks = IrisPregenerator.getLongTotalChunks();
generatedChunks = IrisPregenerator.getLongGeneratedChunks();
if(totalChunks > 0) {
if (generatedChunks >= totalChunks) {
Iris.info("Benchmark Completed!");
elapsedTimeNs = stopBenchmarkTimer();
results();
break;
}
}
//J.sleep(100); test
}
}
static void createBenchmark(){
private void createBenchmark(){
try {
IrisToolbelt.createWorld()
.dimension(BenchDimension)
.name("Benchmark")
.dimension(IrisDimension.getName())
.name("benchmark")
.seed(1337)
.studio(false)
.benchmark(true)
.create();
} catch (IrisException e) {
throw new RuntimeException(e);
}
}
static void startBenchmark(){
private void startBenchmark(){
int x = 0;
int z = 0;
IrisToolbelt.pregenerate(PregenTask
.builder()
.gui(false)
.center(new Position2(x, z))
.width(5)
.height(5)
.build(), Bukkit.getWorld("Benchmark")
.build(), Bukkit.getWorld("benchmark")
);
}
static void startLazyBenchmark(){
int x = 0;
int z = 0;
LazyPregenerator.LazyPregenJob pregenJob = LazyPregenerator.LazyPregenJob.builder()
//.world("Benchmark")
.healingPosition(0)
.healing(false)
.chunksPerMinute(3200)
.radiusBlocks(5000)
.position(0)
.build();
LazyPregenerator pregenerator = new LazyPregenerator(pregenJob, new File("plugins/Iris/lazygen.json"));
pregenerator.start();
}
public static double calculateAverageCPS() {
double elapsedTimeSec = elapsedTimeNs / 1_000_000_000.0; // Convert to seconds
return generatedChunks / elapsedTimeSec;
}
private static void startBenchmarkTimer() {
startTime = System.nanoTime();
}
private static double stopBenchmarkTimer() {
long endTime = System.nanoTime();
return (endTime - startTime) / 1_000_000_000.0;
}
public static void deleteDirectory(File dir) {
File[] files = dir.listFiles();
if(files != null) {
for(File file: files) {
if(file.isDirectory()) {
deleteDirectory(file);
} else {
file.delete();
}
}
private double calculateAverage(KList<Integer> list) {
double sum = 0;
for (int num : list) {
sum += num;
}
dir.delete();
return sum / list.size();
}
private static double roundToTwoDecimalPlaces(double value) {
return Double.parseDouble(String.format("%.2f", value));
private double calculateMedian(KList<Integer> list) {
Collections.sort(list);
int middle = list.size() / 2;
if (list.size() % 2 == 1) {
return list.get(middle);
} else {
return (list.get(middle - 1) + list.get(middle)) / 2.0;
}
}
private int findLowest(KList<Integer> list) {
return Collections.min(list);
}
private int findHighest(KList<Integer> list) {
return Collections.max(list);
}
private boolean deleteDirectory(Path dir) {
try {
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}

View File

@@ -32,6 +32,7 @@ public class IrisWorldCreator {
private String name;
private boolean studio = false;
private String dimensionName = null;
private boolean smartVanillaHeight = false;
private long seed = 1337;
public IrisWorldCreator() {
@@ -63,6 +64,11 @@ public class IrisWorldCreator {
return this;
}
public IrisWorldCreator smartVanillaHeight(boolean smartVanillaHeight) {
this.smartVanillaHeight = smartVanillaHeight;
return this;
}
public WorldCreator create() {
IrisDimension dim = IrisData.loadAnyDimension(dimensionName);
@@ -76,7 +82,7 @@ public class IrisWorldCreator {
.build();
ChunkGenerator g = new BukkitChunkGenerator(w, studio, studio
? dim.getLoader().getDataFolder() :
new File(w.worldFolder(), "iris/pack"), dimensionName);
new File(w.worldFolder(), "iris/pack"), dimensionName, smartVanillaHeight);
return new WorldCreator(name)

View File

@@ -21,6 +21,7 @@ package com.volmit.iris.core.wand;
import com.volmit.iris.util.data.Cuboid;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.misc.E;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Player;
@@ -29,6 +30,7 @@ import org.bukkit.util.Vector;
import java.awt.*;
public class WandSelection {
private static final Particle REDSTONE = E.getOrDefault(Particle.class, "REDSTONE", "DUST");
private final Cuboid c;
private final Player p;
@@ -101,7 +103,7 @@ public class WandSelection {
int g = color.getGreen();
int b = color.getBlue();
p.spawnParticle(Particle.REDSTONE, a.getX(), a.getY(), a.getZ(),
p.spawnParticle(REDSTONE, a.getX(), a.getY(), a.getZ(),
1, 0, 0, 0, 0,
new Particle.DustOptions(org.bukkit.Color.fromRGB(r, g, b),
(float) dist * 3f));

View File

@@ -292,7 +292,7 @@ public class IrisComplex implements DataProvider {
double b = 0;
for (IrisGenerator gen : generators) {
b += bx.getGenLinkMax(gen.getLoadKey());
b += bx.getGenLinkMax(gen.getLoadKey(), engine);
}
return b;
@@ -311,7 +311,7 @@ public class IrisComplex implements DataProvider {
double b = 0;
for (IrisGenerator gen : generators) {
b += bx.getGenLinkMin(gen.getLoadKey());
b += bx.getGenLinkMin(gen.getLoadKey(), engine);
}
return b;

View File

@@ -19,8 +19,6 @@
package com.volmit.iris.engine;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.mantle.EngineMantle;
@@ -47,9 +45,6 @@ import java.io.IOException;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmark;
import static com.volmit.iris.core.safeguard.PerformanceSFG.*;
@Data
@EqualsAndHashCode(exclude = "engine")
@ToString(exclude = "engine")
@@ -290,17 +285,10 @@ public class IrisEngineMantle implements EngineMantle {
x = Math.max(x, c);
x = (Math.max(x, 16) + 16) >> 4;
x = x % 2 == 0 ? x + 1 : x;
if (benchmark){
x = 4;
Iris.info("Mantle Size: " + x + " Chunks " + C.BLUE + "BENCHMARK MODE");
} else {
Iris.info("Mantle Size: " + x + " Chunks");
Iris.info(" Object Mantle Size: " + u + " (" + ((Math.max(u, 16) + 16) >> 4) + ")");
Iris.info(" Jigsaw Mantle Size: " + jig + " (" + ((Math.max(jig, 16) + 16) >> 4) + ")");
Iris.info(" Carving Mantle Size: " + c + " (" + ((Math.max(c, 16) + 16) >> 4) + ")");
}
Iris.info("Mantle Size: " + x + " Chunks");
Iris.info(" Object Mantle Size: " + u + " (" + ((Math.max(u, 16) + 16) >> 4) + ")");
Iris.info(" Jigsaw Mantle Size: " + jig + " (" + ((Math.max(jig, 16) + 16) >> 4) + ")");
Iris.info(" Carving Mantle Size: " + c + " (" + ((Math.max(c, 16) + 16) >> 4) + ")");
return x;
}

View File

@@ -21,6 +21,7 @@ package com.volmit.iris.engine.data.chunk;
import com.volmit.iris.core.nms.BiomeBaseInjector;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.util.data.IrisBiomeStorage;
import com.volmit.iris.util.data.IrisBlockData;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@@ -120,6 +121,8 @@ public class LinkedTerrainChunk implements TerrainChunk {
@Override
public synchronized void setBlock(int x, int y, int z, BlockData blockData) {
if (blockData instanceof IrisBlockData d)
blockData = d.getBase();
rawChunkData.setBlock(x, y, z, blockData);
}

View File

@@ -20,6 +20,7 @@ package com.volmit.iris.engine.data.chunk;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.BiomeBaseInjector;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.nbt.mca.Chunk;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import lombok.AllArgsConstructor;
@@ -88,6 +89,8 @@ public class MCATerrainChunk implements TerrainChunk {
if (blockData == null) {
Iris.error("NULL BD");
}
if (blockData instanceof IrisBlockData data)
blockData = data.getBase();
mcaChunk.setBlockStateAt(xx, y, zz, NBTWorld.getCompound(blockData), false);
}

View File

@@ -22,10 +22,12 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.gui.components.RenderType;
import com.volmit.iris.core.gui.components.Renderer;
import com.volmit.iris.core.link.Identifier;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.core.nms.container.BlockPos;
import com.volmit.iris.core.nms.container.Pair;
import com.volmit.iris.core.service.ExternalDataSVC;
import com.volmit.iris.engine.IrisComplex;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.data.chunk.TerrainChunk;
@@ -38,6 +40,7 @@ import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.DataProvider;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.format.C;
@@ -254,6 +257,11 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
if (B.isUpdatable(data)) {
getMantle().updateBlock(x, y, z);
}
if (data instanceof IrisBlockData d) {
getMantle().getMantle().set(x, y, z, d.getCustom());
} else {
getMantle().getMantle().remove(x, y, z, Identifier.class);
}
}
void blockUpdatedMetric();
@@ -277,6 +285,11 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
Iris.warn("Failed to set tile entity data at [%d %d %d | %s] for tile %s!", x, betterY, z, c.getBlock(x, betterY, z).getBlockData().getMaterial().getKey(), tile.getData().getTileId());
});
}));
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.CUSTOM, () -> J.s(() -> {
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), Identifier.class, (x, y, z, v) -> {
Iris.service(ExternalDataSVC.class).processUpdate(this, c.getBlock(x & 15, y + getWorld().minHeight(), z & 15), v);
});
}));
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.UPDATE, () -> J.s(() -> {
PrecisionStopwatch p = PrecisionStopwatch.start();

View File

@@ -0,0 +1,127 @@
package com.volmit.iris.engine.framework.placer;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.IrisLootEvent;
import com.volmit.iris.engine.mantle.EngineMantle;
import com.volmit.iris.engine.object.IObjectPlacer;
import com.volmit.iris.engine.object.InventorySlotType;
import com.volmit.iris.engine.object.IrisLootTable;
import com.volmit.iris.engine.object.TileData;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.math.RNG;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.InventoryHolder;
@Getter
@EqualsAndHashCode(exclude = {"engine", "mantle"})
public class WorldObjectPlacer implements IObjectPlacer {
private final World world;
private final Engine engine;
private final EngineMantle mantle;
public WorldObjectPlacer(World world) {
var a = IrisToolbelt.access(world);
if (a == null || a.getEngine() == null) throw new IllegalStateException(world.getName() + " is not an Iris World!");
this.world = world;
this.engine = a.getEngine();
this.mantle = engine.getMantle();
}
@Override
public int getHighest(int x, int z, IrisData data) {
return mantle.getHighest(x, z, data);
}
@Override
public int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
return mantle.getHighest(x, z, data, ignoreFluid);
}
@Override
public void set(int x, int y, int z, BlockData d) {
Block block = world.getBlockAt(x, y + world.getMinHeight(), z);
if (y <= world.getMinHeight() || block.getType() == Material.BEDROCK) return;
InventorySlotType slot = null;
if (B.isStorageChest(d)) {
slot = InventorySlotType.STORAGE;
}
if (slot != null) {
RNG rx = new RNG(Cache.key(x, z));
KList<IrisLootTable> tables = engine.getLootTables(rx, block);
try {
Bukkit.getPluginManager().callEvent(new IrisLootEvent(engine, block, slot, tables));
if (!tables.isEmpty()){
Iris.debug("IrisLootEvent has been accessed");
}
if (tables.isEmpty())
return;
InventoryHolder m = (InventoryHolder) block.getState();
engine.addItems(false, m.getInventory(), rx, tables, slot, x, y, z, 15);
} catch (Throwable e) {
Iris.reportError(e);
}
}
block.setBlockData(d);
}
@Override
public BlockData get(int x, int y, int z) {
return world.getBlockAt(x, y + world.getMinHeight(), z).getBlockData();
}
@Override
public boolean isPreventingDecay() {
return mantle.isPreventingDecay();
}
@Override
public boolean isCarved(int x, int y, int z) {
return mantle.isCarved(x, y, z);
}
@Override
public boolean isSolid(int x, int y, int z) {
return world.getBlockAt(x, y + world.getMinHeight(), z).getType().isSolid();
}
@Override
public boolean isUnderwater(int x, int z) {
return mantle.isUnderwater(x, z);
}
@Override
public int getFluidHeight() {
return mantle.getFluidHeight();
}
@Override
public boolean isDebugSmartBore() {
return mantle.isDebugSmartBore();
}
@Override
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
BlockState state = world.getBlockAt(xx, yy + world.getMinHeight(), zz).getState();
tile.toBukkitTry(state);
state.update();
}
}

View File

@@ -20,29 +20,19 @@ package com.volmit.iris.engine.jigsaw;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.math.AxisAlignedBB;
import com.volmit.iris.util.math.BlockPosition;
import com.volmit.iris.util.math.RNG;
import lombok.AccessLevel;
import lombok.Data;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.InventoryHolder;
import lombok.EqualsAndHashCode;
import lombok.Setter;
import org.bukkit.util.BlockVector;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("ALL")
@Data
public class PlannedPiece {
private IrisPosition position;
@@ -50,11 +40,19 @@ public class PlannedPiece {
private IrisObject ogObject;
private IrisJigsawPiece piece;
private IrisObjectRotation rotation;
@EqualsAndHashCode.Exclude
private IrisData data;
private KList<IrisJigsawPieceConnector> connected;
private boolean dead = false;
private AxisAlignedBB box;
@EqualsAndHashCode.Exclude
private PlannedStructure structure;
@EqualsAndHashCode.Exclude
@Setter(AccessLevel.NONE)
private ParentConnection parent = null;
@EqualsAndHashCode.Exclude
@Setter(AccessLevel.NONE)
private KMap<IrisJigsawPieceConnector, IrisPosition> realPositions;
public PlannedPiece(PlannedStructure structure, IrisPosition position, IrisJigsawPiece piece) {
this(structure, position, piece, 0, 0, 0);
@@ -76,6 +74,7 @@ public class PlannedPiece {
this.object.setLoadKey(piece.getObject());
this.ogObject.setLoadKey(piece.getObject());
this.connected = new KList<>();
this.realPositions = new KMap<>();
}
@@ -94,7 +93,15 @@ public class PlannedPiece {
}
BlockVector v = getObject().getCenter();
box = object.getAABB().shifted(position.add(new IrisPosition(object.getCenter())));
IrisPosition pos = new IrisPosition();
IrisObjectPlacement options = piece.getPlacementOptions();
if (options != null && options.getTranslate() != null) {
IrisObjectTranslate translate = options.getTranslate();
pos.setX(translate.getX());
pos.setY(translate.getY());
pos.setZ(translate.getZ());
}
box = object.getAABB().shifted(position.add(new IrisPosition(object.getCenter())).add(pos));
return box;
}
@@ -126,11 +133,21 @@ public class PlannedPiece {
return c;
}
public boolean connect(IrisJigsawPieceConnector c) {
if (piece.getConnectors().contains(c)) {
return connected.addIfMissing(c);
}
public KList<IrisJigsawPieceConnector> getChildConnectors() {
ParentConnection pc = getParent();
KList<IrisJigsawPieceConnector> c = getConnected().copy();
if (pc != null) c.removeIf(i -> i.equals(pc.connector));
return c;
}
public boolean connect(IrisJigsawPieceConnector c, PlannedPiece p, IrisJigsawPieceConnector pc) {
if (piece.getConnectors().contains(c) && p.getPiece().getConnectors().contains(pc)) {
if (connected.contains(c) || p.connected.contains(pc)) return false;
connected.add(c);
p.connected.add(pc);
p.parent = new ParentConnection(this, c, p, pc);
return true;
}
return false;
}
@@ -162,108 +179,29 @@ public class PlannedPiece {
}
public boolean isFull() {
return connected.size() >= piece.getConnectors().size() || isDead();
return connected.size() >= piece.getConnectors().size();
}
public void place(World world) {
PlatformChunkGenerator a = IrisToolbelt.access(world);
int minY = 0;
if (a != null) {
minY = a.getEngine().getMinHeight();
if (!a.getEngine().getDimension().isBedrock())
minY--; //If the dimension has no bedrock, allow it to go a block lower
public void setRealPositions(int x, int y, int z, IObjectPlacer placer) {
boolean isUnderwater = piece.getPlacementOptions().isUnderwater();
for (IrisJigsawPieceConnector c : piece.getConnectors()) {
var pos = c.getPosition().add(new IrisPosition(x, 0, z));
if (y < 0) {
pos.setY(pos.getY() + placer.getHighest(pos.getX(), pos.getZ(), getData(), isUnderwater) + (object.getH() / 2));
} else {
pos.setY(pos.getY() + y);
}
realPositions.put(c, pos);
}
}
getPiece().getPlacementOptions().setTranslate(new IrisObjectTranslate());
getPiece().getPlacementOptions().setRotation(rotation);
int finalMinY = minY;
RNG rng = getStructure().getRng().nextParallelRNG(37555);
// TODO: REAL CLASSES!!!!!!!
getOgObject().place(position.getX() + getObject().getCenter().getBlockX(), position.getY() + getObject().getCenter().getBlockY(), position.getZ() + getObject().getCenter().getBlockZ(), new IObjectPlacer() {
@Override
public int getHighest(int x, int z, IrisData data) {
return position.getY();
}
@Override
public int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
return position.getY();
}
@Override
public void set(int x, int y, int z, BlockData d) {
Block block = world.getBlockAt(x, y, z);
//Prevent blocks being set in or bellow bedrock
if (y <= finalMinY || block.getType() == Material.BEDROCK) return;
block.setBlockData(d);
if (a != null && getPiece().getPlacementOptions().getLoot().isNotEmpty() &&
block.getState() instanceof InventoryHolder) {
IrisLootTable table = getPiece().getPlacementOptions().getTable(block.getBlockData(), getData());
if (table == null) return;
Engine engine = a.getEngine();
engine.addItems(false, ((InventoryHolder) block.getState()).getInventory(),
rng.nextParallelRNG(BlockPosition.toLong(x, y, z)),
new KList<>(table), InventorySlotType.STORAGE, x, y, z, 15);
}
}
@Override
public BlockData get(int x, int y, int z) {
return world.getBlockAt(x, y, z).getBlockData();
}
@Override
public boolean isPreventingDecay() {
return false;
}
@Override
public boolean isCarved(int x, int y, int z) {
return false;
}
@Override
public boolean isSolid(int x, int y, int z) {
return world.getBlockAt(x, y, z).getType().isSolid();
}
@Override
public boolean isUnderwater(int x, int z) {
return false;
}
@Override
public int getFluidHeight() {
return 0;
}
@Override
public boolean isDebugSmartBore() {
return false;
}
@Override
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
BlockState state = world.getBlockAt(xx, yy, zz).getState();
tile.toBukkitTry(state);
state.update();
}
@Override
public Engine getEngine() {
if (IrisToolbelt.isIrisWorld(world)) {
return IrisToolbelt.access(world).getEngine();
}
return IrisContext.get().getEngine();
}
}, piece.getPlacementOptions(), rng, getData());
public record ParentConnection(PlannedPiece parent, IrisJigsawPieceConnector parentConnector, PlannedPiece self, IrisJigsawPieceConnector connector) {
public IrisPosition getTargetPosition() {
var pos = parent.realPositions.get(parentConnector);
if (pos == null) return null;
return pos.add(new IrisPosition(parentConnector.getDirection().toVector()))
.sub(connector.getPosition())
.sub(new IrisPosition(self.object.getCenter()));
}
}
}

View File

@@ -21,20 +21,20 @@ package com.volmit.iris.engine.jigsaw;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.mantle.MantleWriter;
import com.volmit.iris.engine.framework.placer.WorldObjectPlacer;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.slices.JigsawPieceMatter;
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
import com.volmit.iris.util.scheduling.J;
import lombok.Data;
import org.bukkit.Axis;
import org.bukkit.World;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import java.util.function.Consumer;
@Data
public class PlannedStructure {
@@ -75,33 +75,44 @@ public class PlannedStructure {
}
}
public void place(MantleWriter placer, Mantle e, Engine eng) {
public boolean place(IObjectPlacer placer, Mantle e, Engine eng) {
IrisObjectPlacement options = new IrisObjectPlacement();
options.getRotation().setEnabled(false);
options.setRotation(IrisObjectRotation.of(0,0,0));
int startHeight = pieces.get(0).getPosition().getY();
boolean placed = false;
for (PlannedPiece i : pieces) {
place(i, startHeight, options, placer, e, eng);
if (place(i, startHeight, options, placer, e, eng))
placed = true;
}
if (placed) {
Position2 chunkPos = new Position2(position.getX() >> 4, position.getZ() >> 4);
Position2 regionPos = new Position2(chunkPos.getX() >> 5, chunkPos.getZ() >> 5);
JigsawStructuresContainer slice = e.get(regionPos.getX(), 0, regionPos.getZ(), JigsawStructuresContainer.class);
if (slice == null) slice = new JigsawStructuresContainer();
slice.add(structure, chunkPos);
e.set(regionPos.getX(), 0, regionPos.getZ(), slice);
}
return placed;
}
public void place(PlannedPiece i, int startHeight, IrisObjectPlacement o, MantleWriter placer, Mantle e, Engine eng) {
public boolean place(PlannedPiece i, int startHeight, IrisObjectPlacement o, IObjectPlacer placer, Mantle e, Engine eng) {
IrisObjectPlacement options = o;
if (i.getPiece().getPlacementOptions() != null) {
options = i.getPiece().getPlacementOptions();
options.getRotation().setEnabled(false);
options.setRotateTowardsSlope(false);
options.setWarp(new IrisGeneratorStyle(NoiseStyle.FLAT));
} else {
options.setMode(i.getPiece().getPlaceMode());
}
IrisObject vo = i.getOgObject();
IrisObject v = i.getObject();
int sx = (v.getW() / 2);
int sz = (v.getD() / 2);
int xx = i.getPosition().getX() + sx;
int zz = i.getPosition().getZ() + sz;
RNG rngf = new RNG(Cache.key(xx, zz));
int offset = i.getPosition().getY() - startHeight;
int height;
@@ -109,12 +120,23 @@ public class PlannedStructure {
if (i.getStructure().getStructure().getOverrideYRange() != null) {
height = (int) i.getStructure().getStructure().getOverrideYRange().get(rng, xx, zz, getData());
} else {
height = placer.getHighest(xx, zz, getData());
height = placer.getHighest(xx, zz, getData(), options.isUnderwater());
}
} else {
height = i.getStructure().getStructure().getLockY();
}
PlannedPiece.ParentConnection connection = i.getParent();
if (connection != null && connection.connector().isLockY()) {
var pos = connection.getTargetPosition();
if (pos != null) {
height = pos.getY();
offset = 0;
} else {
Iris.warn("Failed to get target position for " + v.getLoadKey());
}
}
height += offset + (v.getH() / 2);
if (options.getMode().equals(ObjectPlaceMode.PAINT)) {
@@ -123,75 +145,15 @@ public class PlannedStructure {
int id = rng.i(0, Integer.MAX_VALUE);
JigsawPieceContainer container = JigsawPieceContainer.toContainer(i.getPiece());
vo.place(xx, height, zz, new IObjectPlacer() {
@Override
public int getHighest(int x, int z, IrisData data) {
return placer.getHighest(x, z, data);
}
@Override
public int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
return placer.getHighest(x, z, data, ignoreFluid);
}
@Override
public void set(int x, int y, int z, BlockData d) {
placer.setData(x, y, z, container);
placer.set(x, y, z, d);
}
@Override
public BlockData get(int x, int y, int z) {
placer.setData(x, y, z, container);
return placer.get(x, y, z);
}
@Override
public boolean isPreventingDecay() {
return placer.isPreventingDecay();
}
@Override
public boolean isCarved(int x, int y, int z) {
return placer.isCarved(x, y, z);
}
@Override
public boolean isSolid(int x, int y, int z) {
return placer.isSolid(x, y, z);
}
@Override
public boolean isUnderwater(int x, int z) {
return placer.isUnderwater(x, z);
}
@Override
public int getFluidHeight() {
return placer.getFluidHeight();
}
@Override
public boolean isDebugSmartBore() {
return placer.isDebugSmartBore();
}
@Override
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
placer.setTile(xx, yy, zz, tile);
}
@Override
public Engine getEngine() {
return placer.getEngine();
}
}, options, rng, (b, data) -> e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id), null, getData());
i.setRealPositions(xx, height, zz, placer);
return v.place(xx, height, zz, placer, options, rng, (b, data) -> {
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
e.set(b.getX(), b.getY(), b.getZ(), container);
}, null, getData().getEngine() != null ? getData() : eng.getData()) != -1;
}
public void place(World world) {
for (PlannedPiece i : pieces) {
Iris.sq(() -> i.place(world));
}
public void place(WorldObjectPlacer placer, Consumer<Boolean> consumer) {
J.s(() -> consumer.accept(place(placer, placer.getMantle().getMantle(), placer.getEngine())));
}
private void generateOutwards() {
@@ -227,9 +189,7 @@ public class PlannedStructure {
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea) {
if (!piece.getPiece().getPlacementOptions().getRotation().isEnabled()) {
if (generateRotatedPiece(piece, pieceConnector, idea, 0, 0, 0)) {
return true;
}
return generateRotatedPiece(piece, pieceConnector, idea, 0, 0, 0);
}
KList<Integer> forder1 = new KList<Integer>().qadd(0).qadd(1).qadd(2).qadd(3).shuffle(rng);
@@ -276,7 +236,7 @@ public class PlannedStructure {
}
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea, int x, int y, int z) {
return generateRotatedPiece(piece, pieceConnector, idea, IrisObjectRotation.of(x, y, z));
return generateRotatedPiece(piece, pieceConnector, idea, IrisObjectRotation.of(x * 90D, y * 90D, z * 90D));
}
private boolean generatePositionedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, PlannedPiece test, IrisJigsawPieceConnector testConnector) {
@@ -300,8 +260,7 @@ public class PlannedStructure {
return false;
}
piece.connect(pieceConnector);
test.connect(testConnector);
piece.connect(pieceConnector, test, testConnector);
pieces.add(test);
return true;
@@ -310,7 +269,8 @@ public class PlannedStructure {
private KList<IrisJigsawPiece> getShuffledPiecesFor(IrisJigsawPieceConnector c) {
KList<IrisJigsawPiece> p = new KList<>();
for (String i : c.getPools().shuffleCopy(rng)) {
KList<String> pools = terminating && getStructure().getTerminatePool() != null ? new KList<>(getStructure().getTerminatePool()) : c.getPools().shuffleCopy(rng);
for (String i : pools) {
for (String j : getData().getJigsawPoolLoader().load(i).getPieces().shuffleCopy(rng)) {
IrisJigsawPiece pi = getData().getJigsawPieceLoader().load(j);
@@ -336,7 +296,9 @@ public class PlannedStructure {
}
public KList<PlannedPiece> getPiecesWithAvailableConnectors() {
return pieces.copy().removeWhere(PlannedPiece::isFull);
KList<PlannedPiece> available = pieces.copy().removeWhere(PlannedPiece::isFull);
if (!terminating) available.removeIf(PlannedPiece::isDead);
return available;
}
public int getVolume() {

View File

@@ -23,6 +23,7 @@ import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.IrisComplex;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineTarget;
import com.volmit.iris.engine.framework.SeedManager;
import com.volmit.iris.engine.mantle.components.MantleJigsawComponent;
import com.volmit.iris.engine.mantle.components.MantleObjectComponent;
import com.volmit.iris.engine.object.IObjectPlacer;
@@ -298,7 +299,7 @@ public interface EngineMantle extends IObjectPlacer {
default long getToUnload(){
return getMantle().getToUnload().size();
}
default long getNotClearedLoadedRegions(){
default long getNotQueuedLoadedRegions(){
return getMantle().getLoadedRegions().size() - getMantle().getToUnload().size();
}
default double getTectonicDuration(){

View File

@@ -23,13 +23,18 @@ import com.volmit.iris.engine.mantle.EngineMantle;
import com.volmit.iris.engine.mantle.IrisMantleComponent;
import com.volmit.iris.engine.mantle.MantleWriter;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
import com.volmit.iris.util.noise.CNG;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -38,22 +43,21 @@ public class MantleJigsawComponent extends IrisMantleComponent {
public MantleJigsawComponent(EngineMantle engineMantle) {
super(engineMantle, MantleFlag.JIGSAW);
cng = NoiseStyle.STATIC.create(new RNG(engineMantle.getEngine().getSeedManager().getJigsaw()));
cng = NoiseStyle.STATIC.create(new RNG(jigsaw()));
}
@Override
public void generateLayer(MantleWriter writer, int x, int z, ChunkContext context) {
RNG rng = new RNG(cng.fit(-Integer.MAX_VALUE, Integer.MAX_VALUE, x, z));
int xxx = 8 + (x << 4);
int zzz = 8 + (z << 4);
IrisRegion region = getComplex().getRegionStream().get(xxx, zzz);
IrisBiome biome = getComplex().getTrueBiomeStream().get(xxx, zzz);
generateJigsaw(writer, rng, x, z, biome, region);
generateJigsaw(writer, x, z, biome, region);
}
@ChunkCoordinates
private void generateJigsaw(MantleWriter writer, RNG rng, int x, int z, IrisBiome biome, IrisRegion region) {
boolean placed = false;
private void generateJigsaw(MantleWriter writer, int x, int z, IrisBiome biome, IrisRegion region) {
long seed = cng.fit(Integer.MIN_VALUE, Integer.MIN_VALUE, x, z);
if (getDimension().getStronghold() != null) {
List<Position2> poss = getDimension().getStrongholds(seed());
@@ -62,51 +66,71 @@ public class MantleJigsawComponent extends IrisMantleComponent {
for (Position2 pos : poss) {
if (x == pos.getX() >> 4 && z == pos.getZ() >> 4) {
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(getDimension().getStronghold());
place(writer, pos.toIris(), structure, rng);
placed = true;
place(writer, pos.toIris(), structure, new RNG(seed));
return;
}
}
}
}
if (!placed) {
for (IrisJigsawStructurePlacement i : biome.getJigsawStructures()) {
if (rng.nextInt(i.getRarity()) == 0) {
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
place(writer, position, structure, rng);
placed = true;
}
}
}
KSet<Position2> cachedRegions = new KSet<>();
KMap<String, KSet<Position2>> cache = new KMap<>();
KMap<Position2, Double> distanceCache = new KMap<>();
boolean placed = placeStructures(writer, seed, x, z, biome.getJigsawStructures(), cachedRegions, cache, distanceCache);
if (!placed)
placed = placeStructures(writer, seed, x, z, region.getJigsawStructures(), cachedRegions, cache, distanceCache);
if (!placed)
placeStructures(writer, seed, x, z, getDimension().getJigsawStructures(), cachedRegions, cache, distanceCache);
}
if (!placed) {
for (IrisJigsawStructurePlacement i : region.getJigsawStructures()) {
if (rng.nextInt(i.getRarity()) == 0) {
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
place(writer, position, structure, rng);
placed = true;
}
}
}
@ChunkCoordinates
private boolean placeStructures(MantleWriter writer, long seed, int x, int z, KList<IrisJigsawStructurePlacement> structures,
KSet<Position2> cachedRegions, KMap<String, KSet<Position2>> cache, KMap<Position2, Double> distanceCache) {
IrisJigsawStructurePlacement i = pick(structures, seed, x, z);
if (i == null || checkMinDistances(i.collectMinDistances(), x, z, cachedRegions, cache, distanceCache))
return false;
RNG rng = new RNG(seed);
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
return place(writer, position, structure, rng);
}
if (!placed) {
for (IrisJigsawStructurePlacement i : getDimension().getJigsawStructures()) {
if (rng.nextInt(i.getRarity()) == 0) {
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
place(writer, position, structure, rng);
@ChunkCoordinates
private boolean checkMinDistances(KMap<String, Integer> minDistances, int x, int z, KSet<Position2> cachedRegions, KMap<String, KSet<Position2>> cache, KMap<Position2, Double> distanceCache) {
int range = 0;
for (int d : minDistances.values())
range = Math.max(range, d);
for (int xx = -range; xx <= range; xx++) {
for (int zz = -range; zz <= range; zz++) {
Position2 pos = new Position2((xx + x) >> 5, (zz + z) >> 5);
if (cachedRegions.contains(pos)) continue;
cachedRegions.add(pos);
JigsawStructuresContainer container = getMantle().get(pos.getX(), 0, pos.getZ(), JigsawStructuresContainer.class);
if (container == null) continue;
for (String key : container.getStructures()) {
cache.computeIfAbsent(key, k -> new KSet<>()).addAll(container.getPositions(key));
}
}
}
Position2 pos = new Position2(x, z);
for (String structure : minDistances.keySet()) {
if (!cache.containsKey(structure)) continue;
double minDist = minDistances.get(structure);
minDist = minDist * minDist;
for (Position2 sPos : cache.get(structure)) {
double dist = distanceCache.computeIfAbsent(sPos, position2 -> position2.distance(pos));
if (minDist > dist) return true;
}
}
return false;
}
@ChunkCoordinates
public IrisJigsawStructure guess(int x, int z) {
// todo The guess doesnt bring into account that the placer may return -1
boolean t = false;
RNG rng = new RNG(cng.fit(-Integer.MAX_VALUE, Integer.MAX_VALUE, x, z));
// todo doesnt bring skipped placements into account
long seed = cng.fit(Integer.MIN_VALUE, Integer.MIN_VALUE, x, z);
IrisBiome biome = getEngineMantle().getEngine().getSurfaceBiome((x << 4) + 8, (z << 4) + 8);
IrisRegion region = getEngineMantle().getEngine().getRegion((x << 4) + 8, (z << 4) + 8);
@@ -122,29 +146,26 @@ public class MantleJigsawComponent extends IrisMantleComponent {
}
}
for (IrisJigsawStructurePlacement i : biome.getJigsawStructures()) {
if (rng.nextInt(i.getRarity()) == 0) {
return getData().getJigsawStructureLoader().load(i.getStructure());
}
}
IrisJigsawStructurePlacement i = pick(biome.getJigsawStructures(), seed, x, z);
if (i == null) i = pick(region.getJigsawStructures(), seed, x, z);
if (i == null) i = pick(getDimension().getJigsawStructures(), seed, x, z);
return i != null ? getData().getJigsawStructureLoader().load(i.getStructure()) : null;
}
for (IrisJigsawStructurePlacement i : region.getJigsawStructures()) {
if (rng.nextInt(i.getRarity()) == 0) {
return getData().getJigsawStructureLoader().load(i.getStructure());
}
}
for (IrisJigsawStructurePlacement i : getDimension().getJigsawStructures()) {
if (rng.nextInt(i.getRarity()) == 0) {
return getData().getJigsawStructureLoader().load(i.getStructure());
}
}
return null;
@Nullable
@ChunkCoordinates
private IrisJigsawStructurePlacement pick(List<IrisJigsawStructurePlacement> structures, long seed, int x, int z) {
return IRare.pick(structures.stream()
.filter(p -> p.shouldPlace(jigsaw(), x, z))
.toList(), new RNG(seed).nextDouble());
}
@BlockCoordinates
private void place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng) {
new PlannedStructure(structure, position, rng).place(writer, getMantle(), writer.getEngine());
private boolean place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng) {
return new PlannedStructure(structure, position, rng).place(writer, getMantle(), writer.getEngine());
}
private long jigsaw() {
return getEngineMantle().getEngine().getSeedManager().getJigsaw();
}
}

View File

@@ -194,13 +194,14 @@ public class IrisBiome extends IrisRegistrant implements IRare {
return getCustomDerivitives() != null && getCustomDerivitives().isNotEmpty();
}
public double getGenLinkMax(String loadKey) {
public double getGenLinkMax(String loadKey, Engine engine) {
Integer v = genCacheMax.aquire(() ->
{
KMap<String, Integer> l = new KMap<>();
for (IrisBiomeGeneratorLink i : getGenerators()) {
l.put(i.getGenerator(), i.getMax());
l.put(i.getGenerator(), i.getMax(engine));
}
return l;
@@ -209,13 +210,13 @@ public class IrisBiome extends IrisRegistrant implements IRare {
return v == null ? 0 : v;
}
public double getGenLinkMin(String loadKey) {
public double getGenLinkMin(String loadKey, Engine engine) {
Integer v = genCacheMin.aquire(() ->
{
KMap<String, Integer> l = new KMap<>();
for (IrisBiomeGeneratorLink i : getGenerators()) {
l.put(i.getGenerator(), i.getMin());
l.put(i.getGenerator(), i.getMin(engine));
}
return l;
@@ -450,26 +451,26 @@ public class IrisBiome extends IrisRegistrant implements IRare {
return real;
}
public int getMaxHeight() {
public int getMaxHeight(Engine engine) {
return maxHeight.aquire(() ->
{
int maxHeight = 0;
for (IrisBiomeGeneratorLink i : getGenerators()) {
maxHeight += i.getMax();
maxHeight += i.getMax(engine);
}
return maxHeight;
});
}
public int getMaxWithObjectHeight(IrisData data) {
public int getMaxWithObjectHeight(IrisData data, Engine engine) {
return maxWithObjectHeight.aquire(() ->
{
int maxHeight = 0;
for (IrisBiomeGeneratorLink i : getGenerators()) {
maxHeight += i.getMax();
maxHeight += i.getMax(engine);
}
int gg = 0;

View File

@@ -19,6 +19,7 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
@@ -68,8 +69,10 @@ public class IrisBiomeCustom {
@Desc("The biome's category type")
private IrisBiomeCustomCategory category = IrisBiomeCustomCategory.plains;
@MinNumber(0)
@MaxNumber(20)
@Desc("The spawn rarity of any defined spawners")
private int spawnRarity = -1;
private int spawnRarity = 0;
@Desc("The color of the sky, top half of sky. (hex format)")
private String skyColor = "#79a8e1";
@@ -89,7 +92,7 @@ public class IrisBiomeCustom {
@Desc("The color of foliage (hex format). Leave blank / don't define to not change")
private String foliageColor = "";
public String generateJson() {
public String generateJson(IDataFixer fixer) {
JSONObject effects = new JSONObject();
effects.put("sky_color", parseColor(getSkyColor()));
effects.put("fog_color", parseColor(getFogColor()));
@@ -155,7 +158,7 @@ public class IrisBiomeCustom {
j.put("spawners", spawners);
}
return j.toString(4);
return fixer.fixCustomBiome(this, j).toString(4);
}
private int parseColor(String c) {

View File

@@ -18,13 +18,13 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.data.DataProvider;
import com.volmit.iris.util.interpolation.IrisInterpolation;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.*;
import lombok.experimental.Accessors;
@Snippet("generator-layer")
@@ -39,22 +39,23 @@ public class IrisBiomeGeneratorLink {
@RegistryListResource(IrisGenerator.class)
@Desc("The generator id")
private String generator = "default";
@DependsOn({"min", "max"})
@DependsOn({ "min", "max" })
@Required
@MinNumber(-2032) // TODO: WARNING HEIGHT
@MaxNumber(2032) // TODO: WARNING HEIGHT
@Desc("The min block value (value + fluidHeight)")
@Getter(AccessLevel.NONE)
private int min = 0;
@DependsOn({"min", "max"})
@DependsOn({ "min", "max" })
@Required
@MinNumber(-2032) // TODO: WARNING HEIGHT
@MaxNumber(2032) // TODO: WARNING HEIGHT
@Getter(AccessLevel.NONE)
@Desc("The max block value (value + fluidHeight)")
private int max = 0;
public IrisGenerator getCachedGenerator(DataProvider g) {
return gen.aquire(() ->
{
return gen.aquire(() -> {
IrisGenerator gen = g.getData().getGeneratorLoader().load(getGenerator());
if (gen == null) {
@@ -65,6 +66,70 @@ public class IrisBiomeGeneratorLink {
});
}
private int[] getBiomeGeneratorsRaw(Engine engine) {
int max = engine.getDimension().getMinHeight();
int min = engine.getDimension().getMaxHeight();
for (IrisBiome biome : engine.getAllBiomes()) {
for (IrisBiomeGeneratorLink i : biome.getGenerators()) {
int biomeRawMax = i.getMaxRaw();
int biomeRawMin = i.getMinRaw();
if (max < biomeRawMax)
max = biomeRawMax;
if (min > biomeRawMin)
min = biomeRawMin;
}
}
return new int[] { min, max };
}
private int calculateHeight(Engine engine, int option) {
int dmx = engine.getDimension().getMaxHeight();
int dmn = engine.getDimension().getMinHeight();
int[] heights = getBiomeGeneratorsRaw(engine);
int gmx = heights[1];
int gmn = heights[0];
int mx = getMaxRaw();
int mn = getMinRaw();
if (engine.getDimension().isSmartVanillaHeight()) {
if (mx > 0)
mx = Math.min((int) (((float) mx / (float) gmx) * 300.0f), 300);
if (mx < 0)
mx = Math.min((int) (((float) mx / (float) gmn) * 300.0f), 56);
if (mn > 0)
mn = Math.min((int) (((float) mn / (float) gmx) * 300.0f), 300);
if (mn < 0)
mn = Math.min((int) (((float) mn / (float) gmn) * 300.0f), 56);
}
if (option == 1) {
return mx;
}
if (option == 0) {
return mn;
}
Iris.error("Fatal Generator error!");
return 0;
}
public int getMax(Engine engine) {
return calculateHeight(engine, 1);
}
public int getMin(Engine engine) {
return calculateHeight(engine, 0);
}
private int getMaxRaw() {
return max;
}
private int getMinRaw() {
return min;
}
public double getHeight(DataProvider xg, double x, double z, long seed) {
double g = getCachedGenerator(xg).getHeight(x, z, seed);
g = g < 0 ? 0 : g;

View File

@@ -82,13 +82,17 @@ public class IrisCavePlacer implements IRare {
}
if (y == -1) {
int h = (int) caveStartHeight.get(rng, x, z, data);
int ma = breakSurface ? h : (int) (engine.getComplex().getHeightStream().get(x, z) - 9);
y = Math.min(h, ma);
if(!breakSurface) {
int eH = engine.getHeight(x, z);
if (caveStartHeight.getMax() > eH) {
caveStartHeight.setMax(eH);
}
}
y = (int) caveStartHeight.get(rng, x, z, data);
}
try {
cave.generate(mantle, rng, engine, x + rng.nextInt(15), y, z + rng.nextInt(15), waterHint);
cave.generate(mantle, rng, engine, x + rng.nextInt(15), y, z + rng.nextInt(15), waterHint);
} catch (Throwable e) {
e.printStackTrace();
fail.set(true);

View File

@@ -21,6 +21,7 @@ package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.collection.KList;
@@ -207,6 +208,8 @@ public class IrisDimension extends IrisRegistrant {
private IrisCarving carving = new IrisCarving();
@Desc("Configuration of fluid bodies such as rivers & lakes")
private IrisFluidBodies fluidBodies = new IrisFluidBodies();
@Desc("forceConvertTo320Height")
private Boolean forceConvertTo320Height = false;
@Desc("The world environment")
private Environment environment = Environment.NORMAL;
@RegistryListResource(IrisRegion.class)
@@ -228,6 +231,8 @@ public class IrisDimension extends IrisRegistrant {
private IrisRange dimensionHeightEnd = new IrisRange(-64, 320);
@Desc("Define the min and max Y bounds of this dimension. Please keep in mind that Iris internally generates from 0 to (max - min). \n\nFor example at -64 to 320, Iris is internally generating to 0 to 384, then on outputting chunks, it shifts it down by the min height (64 blocks). The default is -64 to 320. \n\nThe fluid height is placed at (fluid height + min height). So a fluid height of 63 would actually show up in the world at 1.")
private IrisRange dimensionHeightNether = new IrisRange(-64, 320);
@Desc("Enable smart vanilla height")
private boolean smartVanillaHeight = false;
@RegistryListResource(IrisBiome.class)
@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 = "";
@@ -439,7 +444,7 @@ public class IrisDimension extends IrisRegistrant {
return landBiomeStyle;
}
public boolean installDataPack(DataProvider data, File datapacks) {
public boolean installDataPack(IDataFixer fixer, DataProvider data, File datapacks, double ultimateMaxHeight, double ultimateMinHeight) {
boolean write = false;
boolean changed = false;
@@ -459,7 +464,7 @@ public class IrisDimension extends IrisRegistrant {
Iris.verbose(" Installing Data Pack Biome: " + output.getPath());
output.getParentFile().mkdirs();
try {
IO.writeAll(output, j.generateJson());
IO.writeAll(output, j.generateJson(fixer));
} catch (IOException e) {
Iris.reportError(e);
e.printStackTrace();
@@ -470,7 +475,9 @@ public class IrisDimension extends IrisRegistrant {
if (!dimensionHeight.equals(new IrisRange(-64, 320)) && this.name.equalsIgnoreCase("overworld")) {
Iris.verbose(" Installing Data Pack Dimension Types: \"minecraft:overworld\", \"minecraft:the_nether\", \"minecraft:the_end\"");
changed = writeDimensionType(changed, datapacks);
dimensionHeight.setMax(ultimateMaxHeight);
dimensionHeight.setMin(ultimateMinHeight);
changed = writeDimensionType(fixer, changed, datapacks);
}
if (write) {
@@ -509,13 +516,13 @@ public class IrisDimension extends IrisRegistrant {
}
public boolean writeDimensionType(boolean changed, File datapacks) {
public boolean writeDimensionType(IDataFixer fixer, boolean changed, File datapacks) {
File dimTypeOverworld = new File(datapacks, "iris/data/minecraft/dimension_type/overworld.json");
if (!dimTypeOverworld.exists())
changed = true;
dimTypeOverworld.getParentFile().mkdirs();
try {
IO.writeAll(dimTypeOverworld, generateDatapackJsonOverworld());
IO.writeAll(dimTypeOverworld, generateDatapackJsonOverworld(fixer));
} catch (IOException e) {
Iris.reportError(e);
e.printStackTrace();
@@ -527,7 +534,7 @@ public class IrisDimension extends IrisRegistrant {
changed = true;
dimTypeNether.getParentFile().mkdirs();
try {
IO.writeAll(dimTypeNether, generateDatapackJsonNether());
IO.writeAll(dimTypeNether, generateDatapackJsonNether(fixer));
} catch (IOException e) {
Iris.reportError(e);
e.printStackTrace();
@@ -539,7 +546,7 @@ public class IrisDimension extends IrisRegistrant {
changed = true;
dimTypeEnd.getParentFile().mkdirs();
try {
IO.writeAll(dimTypeEnd, generateDatapackJsonEnd());
IO.writeAll(dimTypeEnd, generateDatapackJsonEnd(fixer));
} catch (IOException e) {
Iris.reportError(e);
e.printStackTrace();
@@ -548,27 +555,27 @@ public class IrisDimension extends IrisRegistrant {
return changed;
}
private String generateDatapackJsonOverworld() {
private String generateDatapackJsonOverworld(IDataFixer fixer) {
JSONObject obj = new JSONObject(DP_OVERWORLD_DEFAULT);
obj.put("min_y", dimensionHeight.getMin());
obj.put("height", dimensionHeight.getMax() - dimensionHeight.getMin());
obj.put("logical_height", logicalHeight);
return obj.toString(4);
return fixer.fixDimension(obj).toString(4);
}
private String generateDatapackJsonNether() {
private String generateDatapackJsonNether(IDataFixer fixer) {
JSONObject obj = new JSONObject(DP_NETHER_DEFAULT);
obj.put("min_y", dimensionHeightNether.getMin());
obj.put("height", dimensionHeightNether.getMax() - dimensionHeightNether.getMin());
obj.put("logical_height", logicalHeightNether);
return obj.toString(4);
return fixer.fixDimension(obj).toString(4);
}
private String generateDatapackJsonEnd() {
private String generateDatapackJsonEnd(IDataFixer fixer) {
JSONObject obj = new JSONObject(DP_END_DEFAULT);
obj.put("min_y", dimensionHeightEnd.getMin());
obj.put("height", dimensionHeightEnd.getMax() - dimensionHeightEnd.getMin());
obj.put("logical_height", logicalHeightEnd);
return obj.toString(4);
return fixer.fixDimension(obj).toString(4);
}
}

View File

@@ -21,6 +21,7 @@ package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.collection.KList;
@@ -28,6 +29,7 @@ import com.volmit.iris.util.format.C;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.plugin.Chunks;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
@@ -41,6 +43,7 @@ import org.bukkit.*;
import org.bukkit.attribute.Attributable;
import org.bukkit.entity.*;
import org.bukkit.entity.Panda.Gene;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.loot.LootContext;
@@ -63,10 +66,14 @@ import java.util.concurrent.atomic.AtomicReference;
@Data
@EqualsAndHashCode(callSuper = false)
public class IrisEntity extends IrisRegistrant {
private static final Particle ITEM = E.getOrDefault(Particle.class, "ITEM_CRACK", "ITEM");
@Required
@Desc("The type of entity to spawn. To spawn a mythic mob, set this type to unknown and define mythic type.")
private EntityType type = EntityType.UNKNOWN;
@Desc("The SpawnReason to spawn the entity with.")
private CreatureSpawnEvent.SpawnReason reason = CreatureSpawnEvent.SpawnReason.NATURAL;
@Desc("The custom name of this entity")
private String customName = "";
@@ -381,7 +388,7 @@ public class IrisEntity extends IrisRegistrant {
if (e.getLocation().getBlock().getType().isSolid() || ((LivingEntity) e).getEyeLocation().getBlock().getType().isSolid()) {
e.teleport(start.add(new Vector(0, 0.1, 0)));
ItemStack itemCrackData = new ItemStack(((LivingEntity) e).getEyeLocation().clone().subtract(0, 2, 0).getBlock().getBlockData().getMaterial());
e.getWorld().spawnParticle(Particle.ITEM_CRACK, ((LivingEntity) e).getEyeLocation(), 6, 0.2, 0.4, 0.2, 0.06f, itemCrackData);
e.getWorld().spawnParticle(ITEM, ((LivingEntity) e).getEyeLocation(), 6, 0.2, 0.4, 0.2, 0.06f, itemCrackData);
if (M.r(0.2)) {
e.getWorld().playSound(e.getLocation(), Sound.BLOCK_CHORUS_FLOWER_GROW, 0.8f, 0.1f);
}
@@ -457,7 +464,7 @@ public class IrisEntity extends IrisRegistrant {
}
return at.getWorld().spawnEntity(at, getType());
return INMS.get().spawnEntity(at, getType(), getReason());
}
public boolean isCitizens() {

View File

@@ -19,21 +19,28 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.matter.MatterMarker;
import com.volmit.iris.util.matter.slices.MarkerMatter;
import io.lumine.mythic.bukkit.adapters.BukkitEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.util.BoundingBox;
@Snippet("entity-spawn")
@Accessors(chain = true)
@@ -165,12 +172,19 @@ public class IrisEntitySpawn implements IRare {
return null;
}
Entity e = irisEntity.spawn(g, at.add(0.5, 0, 0.5), rng.aquire(() -> new RNG(g.getSeedManager().getEntity())));
Vector3d boundingBox = INMS.get().getBoundingbox(irisEntity.getType());
if (!ignoreSurfaces && boundingBox != null) {
boolean isClearForSpawn = isAreaClearForSpawn(at, boundingBox);
if (!isClearForSpawn) {
return null;
}
}
Entity e = irisEntity.spawn(g, at.add(0.5, 0.5, 0.5), rng.aquire(() -> new RNG(g.getSeedManager().getEntity())));
if (e != null) {
Iris.debug("Spawned " + C.DARK_AQUA + "Entity<" + getEntity() + "> " + C.GREEN + e.getType() + C.LIGHT_PURPLE + " @ " + C.GRAY + e.getLocation().getX() + ", " + e.getLocation().getY() + ", " + e.getLocation().getZ());
}
return e;
} catch (Throwable e) {
Iris.reportError(e);
@@ -179,4 +193,25 @@ public class IrisEntitySpawn implements IRare {
return null;
}
}
private boolean isAreaClearForSpawn(Location center, Vector3d boundingBox) {
World world = center.getWorld();
int startX = center.getBlockX() - (int) (boundingBox.x / 2);
int endX = center.getBlockX() + (int) (boundingBox.x / 2);
int startY = center.getBlockY();
int endY = center.getBlockY() + (int) boundingBox.y;
int startZ = center.getBlockZ() - (int) (boundingBox.z / 2);
int endZ = center.getBlockZ() + (int) (boundingBox.z / 2);
for (int x = startX; x <= endX; x++) {
for (int y = startY; y <= endY; y++) {
for (int z = startZ; z <= endZ; z++) {
if (world.getBlockAt(x, y, z).getType() != Material.AIR) {
return false;
}
}
}
}
return true;
}
}

View File

@@ -0,0 +1,29 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.MinNumber;
import com.volmit.iris.engine.object.annotations.RegistryListResource;
import com.volmit.iris.engine.object.annotations.Required;
import com.volmit.iris.engine.object.annotations.Snippet;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Snippet("jigsaw-structure-min-distance")
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Desc("Represents the min distance between jigsaw structure placements")
@Data
public class IrisJigsawMinDistance {
@Required
@RegistryListResource(IrisJigsawStructure.class)
@Desc("The structure to check against")
private String structure;
@Required
@MinNumber(0)
@Desc("The min distance in blocks to a placed structure\nWARNING: The performance impact scales exponentially!")
private int distance;
}

View File

@@ -101,19 +101,12 @@ public class IrisJigsawPiece extends IrisRegistrant {
}
public IrisJigsawPiece copy() {
IrisJigsawPiece p = new IrisJigsawPiece();
p.setObject(getObject());
p.setLoader(getLoader());
p.setLoadKey(getLoadKey());
p.setLoadFile(getLoadFile());
p.setConnectors(new KList<>());
p.setPlacementOptions(getPlacementOptions());
for (IrisJigsawPieceConnector i : getConnectors()) {
p.getConnectors().add(i.copy());
}
return p;
var gson = getLoader().getGson();
IrisJigsawPiece copy = gson.fromJson(gson.toJson(this), IrisJigsawPiece.class);
copy.setLoader(getLoader());
copy.setLoadKey(getLoadKey());
copy.setLoadFile(getLoadFile());
return copy;
}
public boolean isTerminal() {

View File

@@ -79,6 +79,9 @@ public class IrisJigsawPieceConnector {
@Required
private IrisDirection direction = IrisDirection.UP_POSITIVE_Y;
@Desc("Lock the Y position of this connector")
private boolean lockY = false;
public String toString() {
return direction.getFace().name() + "@(" + position.getX() + "," + position.getY() + "," + position.getZ() + ")";
}

View File

@@ -56,6 +56,10 @@ public class IrisJigsawStructure extends IrisRegistrant {
@Desc("If set to true, iris will look for any pieces with only one connector in valid pools for edge connectors and attach them to 'terminate' the paths/piece connectors. Essentially it caps off ends. For example in a village, Iris would add houses to the ends of roads where possible. For terminators to be selected, they can only have one connector or they wont be chosen.")
private boolean terminate = true;
@RegistryListResource(IrisJigsawPool.class)
@Desc("The pool to use when terminating pieces")
private String terminatePool = null;
@Desc("Override the y range instead of placing on the height map")
private IrisStyledRange overrideYRange = null;

View File

@@ -18,17 +18,24 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.object.annotations.ArrayType;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.MaxNumber;
import com.volmit.iris.engine.object.annotations.MinNumber;
import com.volmit.iris.engine.object.annotations.RegistryListResource;
import com.volmit.iris.engine.object.annotations.Required;
import com.volmit.iris.engine.object.annotations.Snippet;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.math.RNG;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Snippet("jigsaw-structure-placement")
@Accessors(chain = true)
@NoArgsConstructor
@@ -36,13 +43,99 @@ import lombok.experimental.Accessors;
@Desc("Represents a jigsaw structure placer")
@Data
@EqualsAndHashCode(callSuper = false)
public class IrisJigsawStructurePlacement {
public class IrisJigsawStructurePlacement implements IRare {
@RegistryListResource(IrisJigsawStructure.class)
@Required
@Desc("The structure to place")
private String structure;
@Required
@Desc("The 1 in X chance rarity")
@Desc("The 1 in X chance rarity applies when generating multiple structures at once")
private int rarity = 100;
@Required
@Desc("The salt to use when generating the structure (to differentiate structures)")
@MinNumber(Long.MIN_VALUE)
@MaxNumber(Long.MAX_VALUE)
private long salt = 0;
@Required
@MinNumber(0)
@Desc("Average distance in chunks between two neighboring generation attempts")
private int spacing = -1;
@Required
@MinNumber(0)
@Desc("Minimum distance in chunks between two neighboring generation attempts\nThe maximum distance of two neighboring generation attempts is 2*spacing - separation")
private int separation = -1;
@Desc("The method used to spread the structure")
private SpreadType spreadType = SpreadType.TRIANGULAR;
@ArrayType(type = IrisJigsawMinDistance.class)
@Desc("List of minimum distances to check for")
private KList<IrisJigsawMinDistance> minDistances = new KList<>();
public KMap<String, Integer> collectMinDistances() {
KMap<String, Integer> map = new KMap<>();
for (IrisJigsawMinDistance d : minDistances) {
map.compute(d.getStructure(), (k, v) -> v != null ? Math.min(toChunks(d.getDistance()), v) : toChunks(d.getDistance()));
}
return map;
}
private int toChunks(int blocks) {
return (int) Math.ceil(blocks / 16d);
}
private void calculateMissing(long seed) {
seed = seed + hashCode();
if (salt == 0) {
salt = new RNG(seed).nextLong(Integer.MIN_VALUE, Integer.MAX_VALUE);
}
if (separation == -1 || spacing == -1) {
separation = (int) Math.round(rarity / 20d);
spacing = new RNG(seed).nextInt(separation, separation * 2);
}
}
@ChunkCoordinates
public boolean shouldPlace(long seed, int x, int z) {
calculateMissing(seed);
if (separation > spacing) {
separation = spacing;
Iris.warn("JigsawStructurePlacement: separation must be less than or equal to spacing");
}
int i = Math.floorDiv(x, spacing);
int j = Math.floorDiv(z, spacing);
RNG rng = new RNG(i * 341873128712L + j * 132897987541L + seed + salt);
int k = spacing - separation;
int l = spreadType.apply(rng, k);
int m = spreadType.apply(rng, k);
return i * spacing + l == x && j * spacing + m == z;
}
@Desc("Spread type")
public enum SpreadType {
@Desc("Linear spread")
LINEAR(RNG::i),
@Desc("Triangular spread")
TRIANGULAR((rng, bound) -> (rng.i(bound) + rng.i(bound)) / 2);
private final SpreadMethod method;
SpreadType(SpreadMethod method) {
this.method = method;
}
public int apply(RNG rng, int bound) {
return method.apply(rng, bound);
}
}
private interface SpreadMethod {
int apply(RNG rng, int bound);
}
}

View File

@@ -136,6 +136,8 @@ public class IrisObjectPlacement {
@ArrayType(type = String.class)
@Desc("List of objects to this object is forbidden to collied with")
private KList<String> forbiddenCollisions = new KList<>();
@Desc("Ignore any placement restrictions for this object")
private boolean forcePlace = false;
private transient AtomicCache<TableCache> cache = new AtomicCache<>();
public IrisObjectPlacement toPlacement(String... place) {

View File

@@ -101,6 +101,11 @@ public class IrisObjectRotation {
i.setPosition(rotate(i.getPosition()));
i.setDirection(rotate(i.getDirection()));
}
try {
var translate = piece.getPlacementOptions().getTranslate();
var pos = rotate(new IrisPosition(translate.getX(), translate.getY(), translate.getZ()));
translate.setX(pos.getX()).setY(pos.getY()).setZ(pos.getZ());
} catch (NullPointerException ignored) {}
return piece;
}

View File

@@ -1,413 +1,444 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.engine.platform;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.engine.IrisEngine;
import com.volmit.iris.engine.data.chunk.TerrainChunk;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineTarget;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.engine.object.IrisWorld;
import com.volmit.iris.engine.object.StudioMode;
import com.volmit.iris.engine.platform.studio.StudioGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.IrisBiomeStorage;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder;
import com.volmit.iris.util.hunk.view.ChunkDataHunkHolder;
import com.volmit.iris.util.io.ReactiveFolder;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.Looper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Setter;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.WorldInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
@EqualsAndHashCode(callSuper = true)
@Data
public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChunkGenerator, Listener {
private static final int LOAD_LOCKS = Runtime.getRuntime().availableProcessors() * 4;
private final Semaphore loadLock;
private final IrisWorld world;
private final File dataLocation;
private final String dimensionKey;
private final ReactiveFolder folder;
private final ReentrantLock lock = new ReentrantLock();
private final KList<BlockPopulator> populators;
private final ChronoLatch hotloadChecker;
private final AtomicBoolean setup;
private final boolean studio;
private final AtomicInteger a = new AtomicInteger(0);
private Engine engine;
private Looper hotloader;
private StudioMode lastMode;
private DummyBiomeProvider dummyBiomeProvider;
@Setter
private StudioGenerator studioGenerator;
private boolean initialized = false;
public BukkitChunkGenerator(IrisWorld world, boolean studio, File dataLocation, String dimensionKey) {
setup = new AtomicBoolean(false);
studioGenerator = null;
dummyBiomeProvider = new DummyBiomeProvider();
populators = new KList<>();
loadLock = new Semaphore(LOAD_LOCKS);
this.world = world;
this.hotloadChecker = new ChronoLatch(1000, false);
this.studio = studio;
this.dataLocation = dataLocation;
this.dimensionKey = dimensionKey;
this.folder = new ReactiveFolder(dataLocation, (_a, _b, _c) -> hotload());
Bukkit.getServer().getPluginManager().registerEvents(this, Iris.instance);
}
private static Field getField(Class clazz, String fieldName)
throws NoSuchFieldException {
try {
return clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
Class superClass = clazz.getSuperclass();
if (superClass == null) {
throw e;
} else {
return getField(superClass, fieldName);
}
}
}
@EventHandler
public void onWorldInit(WorldInitEvent event) {
try {
if (!initialized) {
world.setRawWorldSeed(event.getWorld().getSeed());
if (world.name().equals(event.getWorld().getName())) {
INMS.get().inject(event.getWorld().getSeed(), getEngine(event.getWorld()), event.getWorld());
Iris.info("Injected Iris Biome Source into " + event.getWorld().getName());
initialized = true;
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
private void setupEngine() {
IrisData data = IrisData.get(dataLocation);
IrisDimension dimension = data.getDimensionLoader().load(dimensionKey);
if (dimension == null) {
Iris.error("Oh No! There's no pack in " + data.getDataFolder().getPath() + " or... there's no dimension for the key " + dimensionKey);
IrisDimension test = IrisData.loadAnyDimension(dimensionKey);
if (test != null) {
Iris.warn("Looks like " + dimensionKey + " exists in " + test.getLoadFile().getPath() + " ");
Iris.service(StudioSVC.class).installIntoWorld(Iris.getSender(), dimensionKey, dataLocation.getParentFile().getParentFile());
Iris.warn("Attempted to install into " + data.getDataFolder().getPath());
data.dump();
data.clearLists();
test = data.getDimensionLoader().load(dimensionKey);
if (test != null) {
Iris.success("Woo! Patched the Engine!");
dimension = test;
} else {
Iris.error("Failed to patch dimension!");
throw new RuntimeException("Missing Dimension: " + dimensionKey);
}
} else {
Iris.error("Nope, you don't have an installation containing " + dimensionKey + " try downloading it?");
throw new RuntimeException("Missing Dimension: " + dimensionKey);
}
}
lastMode = StudioMode.NORMAL;
engine = new IrisEngine(new EngineTarget(world, dimension, data), studio);
populators.clear();
}
@Override
public void injectChunkReplacement(World world, int x, int z, Consumer<Runnable> jobs) {
try {
loadLock.acquire();
IrisBiomeStorage st = new IrisBiomeStorage();
TerrainChunk tc = TerrainChunk.createUnsafe(world, st);
Hunk<BlockData> blocks = Hunk.view(tc);
Hunk<Biome> biomes = Hunk.view(tc, tc.getMinHeight(), tc.getMaxHeight());
this.world.bind(world);
getEngine().generate(x << 4, z << 4, blocks, biomes, true);
Iris.debug("Regenerated " + x + " " + z);
int t = 0;
for (int i = getEngine().getHeight() >> 4; i >= 0; i--) {
if (!world.isChunkLoaded(x, z)) {
continue;
}
Chunk c = world.getChunkAt(x, z);
for (Entity ee : c.getEntities()) {
if (ee instanceof Player) {
continue;
}
J.s(ee::remove);
}
J.s(() -> engine.getWorldManager().onChunkLoad(c, false));
int finalI = i;
jobs.accept(() -> {
for (int xx = 0; xx < 16; xx++) {
for (int yy = 0; yy < 16; yy++) {
for (int zz = 0; zz < 16; zz++) {
if (yy + (finalI << 4) >= engine.getHeight() || yy + (finalI << 4) < 0) {
continue;
}
c.getBlock(xx, yy + (finalI << 4) + world.getMinHeight(), zz)
.setBlockData(tc.getBlockData(xx, yy + (finalI << 4) + world.getMinHeight(), zz), false);
}
}
}
});
}
loadLock.release();
} catch (Throwable e) {
loadLock.release();
Iris.error("======================================");
e.printStackTrace();
Iris.reportErrorChunk(x, z, e, "CHUNK");
Iris.error("======================================");
ChunkData d = Bukkit.createChunkData(world);
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
d.setBlock(i, 0, j, Material.RED_GLAZED_TERRACOTTA.createBlockData());
}
}
}
}
private Engine getEngine(WorldInfo world) {
if (setup.get()) {
return getEngine();
}
lock.lock();
if (setup.get()) {
return getEngine();
}
setup.set(true);
getWorld().setRawWorldSeed(world.getSeed());
setupEngine();
this.hotloader = studio ? new Looper() {
@Override
protected long loop() {
if (hotloadChecker.flip()) {
folder.check();
}
return 250;
}
} : null;
if (studio) {
hotloader.setPriority(Thread.MIN_PRIORITY);
hotloader.start();
hotloader.setName(getTarget().getWorld().name() + " Hotloader");
}
lock.unlock();
return engine;
}
@Override
public void close() {
withExclusiveControl(() -> {
if (isStudio()) {
hotloader.interrupt();
}
getEngine().close();
folder.clear();
populators.clear();
});
}
@Override
public boolean isStudio() {
return studio;
}
@Override
public void hotload() {
if (!isStudio()) {
return;
}
withExclusiveControl(() -> getEngine().hotload());
}
public void withExclusiveControl(Runnable r) {
J.a(() -> {
try {
loadLock.acquire(LOAD_LOCKS);
r.run();
loadLock.release(LOAD_LOCKS);
} catch (Throwable e) {
Iris.reportError(e);
}
});
}
@Override
public void touch(World world) {
getEngine(world);
}
@Override
public void generateNoise(@NotNull WorldInfo world, @NotNull Random random, int x, int z, @NotNull ChunkGenerator.ChunkData d) {
try {
getEngine(world);
computeStudioGenerator();
TerrainChunk tc = TerrainChunk.create(d, new IrisBiomeStorage());
this.world.bind(world);
if (studioGenerator != null) {
studioGenerator.generateChunk(getEngine(), tc, x, z);
} else {
ChunkDataHunkHolder blocks = new ChunkDataHunkHolder(tc);
BiomeGridHunkHolder biomes = new BiomeGridHunkHolder(tc, tc.getMinHeight(), tc.getMaxHeight());
getEngine().generate(x << 4, z << 4, blocks, biomes, false);
blocks.apply();
biomes.apply();
}
Iris.debug("Generated " + x + " " + z);
} catch (Throwable e) {
Iris.error("======================================");
e.printStackTrace();
Iris.reportErrorChunk(x, z, e, "CHUNK");
Iris.error("======================================");
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
d.setBlock(i, 0, j, Material.RED_GLAZED_TERRACOTTA.createBlockData());
}
}
}
}
@Override
public int getBaseHeight(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull HeightMap heightMap) {
return 4;
}
private void computeStudioGenerator() {
if (!getEngine().getDimension().getStudioMode().equals(lastMode)) {
lastMode = getEngine().getDimension().getStudioMode();
getEngine().getDimension().getStudioMode().inject(this);
}
}
@NotNull
@Override
public List<BlockPopulator> getDefaultPopulators(@NotNull World world) {
return populators;
}
@Override
public boolean isParallelCapable() {
return true;
}
@Override
public boolean shouldGenerateCaves() {
return false;
}
@Override
public boolean shouldGenerateDecorations() {
return false;
}
@Override
public boolean shouldGenerateMobs() {
return false;
}
@Override
public boolean shouldGenerateStructures() {
return false;
}
@Override
public boolean shouldGenerateNoise() {
return false;
}
@Override
public boolean shouldGenerateSurface() {
return false;
}
@Override
public boolean shouldGenerateBedrock() {
return false;
}
@Nullable
@Override
public BiomeProvider getDefaultBiomeProvider(@NotNull WorldInfo worldInfo) {
return dummyBiomeProvider;
}
}
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.engine.platform;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.engine.IrisEngine;
import com.volmit.iris.engine.data.chunk.TerrainChunk;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineTarget;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.engine.object.IrisWorld;
import com.volmit.iris.engine.object.StudioMode;
import com.volmit.iris.engine.platform.studio.StudioGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.IrisBiomeStorage;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder;
import com.volmit.iris.util.hunk.view.ChunkDataHunkHolder;
import com.volmit.iris.util.io.ReactiveFolder;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.Looper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Setter;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.WorldInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
@EqualsAndHashCode(callSuper = true)
@Data
public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChunkGenerator, Listener {
private static final int LOAD_LOCKS = Runtime.getRuntime().availableProcessors() * 4;
private final Semaphore loadLock;
private final IrisWorld world;
private final File dataLocation;
private final String dimensionKey;
private final ReactiveFolder folder;
private final ReentrantLock lock = new ReentrantLock();
private final KList<BlockPopulator> populators;
private final ChronoLatch hotloadChecker;
private final AtomicBoolean setup;
private final boolean studio;
private final AtomicInteger a = new AtomicInteger(0);
private final boolean smartVanillaHeight;
private Engine engine;
private Looper hotloader;
private StudioMode lastMode;
private DummyBiomeProvider dummyBiomeProvider;
@Setter
private StudioGenerator studioGenerator;
private boolean initialized = false;
public BukkitChunkGenerator(IrisWorld world, boolean studio, File dataLocation, String dimensionKey, boolean smartVanillaHeight) {
setup = new AtomicBoolean(false);
studioGenerator = null;
dummyBiomeProvider = new DummyBiomeProvider();
populators = new KList<>();
loadLock = new Semaphore(LOAD_LOCKS);
this.world = world;
this.hotloadChecker = new ChronoLatch(1000, false);
this.studio = studio;
this.dataLocation = dataLocation;
this.dimensionKey = dimensionKey;
this.folder = new ReactiveFolder(dataLocation, (_a, _b, _c) -> hotload());
this.smartVanillaHeight = smartVanillaHeight;
Bukkit.getServer().getPluginManager().registerEvents(this, Iris.instance);
}
private static Field getField(Class clazz, String fieldName)
throws NoSuchFieldException {
try {
return clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
Class superClass = clazz.getSuperclass();
if (superClass == null) {
throw e;
} else {
return getField(superClass, fieldName);
}
}
}
@EventHandler
public void onWorldInit(WorldInitEvent event) {
try {
if (!initialized) {
world.setRawWorldSeed(event.getWorld().getSeed());
if (world.name().equals(event.getWorld().getName())) {
Engine engine = getEngine(event.getWorld());
if (engine == null) {
Iris.warn("Failed to get Engine!");
J.s(() -> {
Engine engine1 = getEngine(event.getWorld());
if (engine1 != null) {
try {
INMS.get().inject(event.getWorld().getSeed(), engine1, event.getWorld());
Iris.info("Injected Iris Biome Source into " + event.getWorld().getName());
initialized = true;
} catch (Throwable e) {
e.printStackTrace();
}
}
}, 10);
} else {
INMS.get().inject(event.getWorld().getSeed(), engine, event.getWorld());
Iris.info("Injected Iris Biome Source into " + event.getWorld().getName());
initialized = true;
}
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
private void setupEngine() {
IrisData data = IrisData.get(dataLocation);
IrisDimension dimension = data.getDimensionLoader().load(dimensionKey);
if (dimension == null) {
Iris.error("Oh No! There's no pack in " + data.getDataFolder().getPath() + " or... there's no dimension for the key " + dimensionKey);
IrisDimension test = IrisData.loadAnyDimension(dimensionKey);
if (test != null) {
Iris.warn("Looks like " + dimensionKey + " exists in " + test.getLoadFile().getPath() + " ");
Iris.service(StudioSVC.class).installIntoWorld(Iris.getSender(), dimensionKey, dataLocation.getParentFile().getParentFile());
Iris.warn("Attempted to install into " + data.getDataFolder().getPath());
data.dump();
data.clearLists();
test = data.getDimensionLoader().load(dimensionKey);
if (test != null) {
Iris.success("Woo! Patched the Engine!");
dimension = test;
} else {
Iris.error("Failed to patch dimension!");
throw new RuntimeException("Missing Dimension: " + dimensionKey);
}
} else {
Iris.error("Nope, you don't have an installation containing " + dimensionKey + " try downloading it?");
throw new RuntimeException("Missing Dimension: " + dimensionKey);
}
}
if (smartVanillaHeight) {
dimension.setSmartVanillaHeight(true);
try (FileWriter writer = new FileWriter(data.getDimensionLoader().fileFor(dimension))) {
writer.write(data.getGson().toJson(dimension));
} catch (IOException e) {
e.printStackTrace();
}
}
lastMode = StudioMode.NORMAL;
engine = new IrisEngine(new EngineTarget(world, dimension, data), studio);
populators.clear();
}
@Override
public void injectChunkReplacement(World world, int x, int z, Consumer<Runnable> jobs) {
try {
loadLock.acquire();
IrisBiomeStorage st = new IrisBiomeStorage();
TerrainChunk tc = TerrainChunk.createUnsafe(world, st);
Hunk<BlockData> blocks = Hunk.view(tc);
Hunk<Biome> biomes = Hunk.view(tc, tc.getMinHeight(), tc.getMaxHeight());
this.world.bind(world);
getEngine().generate(x << 4, z << 4, blocks, biomes, true);
Iris.debug("Regenerated " + x + " " + z);
int t = 0;
for (int i = getEngine().getHeight() >> 4; i >= 0; i--) {
if (!world.isChunkLoaded(x, z)) {
continue;
}
Chunk c = world.getChunkAt(x, z);
for (Entity ee : c.getEntities()) {
if (ee instanceof Player) {
continue;
}
J.s(ee::remove);
}
J.s(() -> engine.getWorldManager().onChunkLoad(c, false));
int finalI = i;
jobs.accept(() -> {
for (int xx = 0; xx < 16; xx++) {
for (int yy = 0; yy < 16; yy++) {
for (int zz = 0; zz < 16; zz++) {
if (yy + (finalI << 4) >= engine.getHeight() || yy + (finalI << 4) < 0) {
continue;
}
c.getBlock(xx, yy + (finalI << 4) + world.getMinHeight(), zz)
.setBlockData(tc.getBlockData(xx, yy + (finalI << 4) + world.getMinHeight(), zz), false);
}
}
}
});
}
loadLock.release();
} catch (Throwable e) {
loadLock.release();
Iris.error("======================================");
e.printStackTrace();
Iris.reportErrorChunk(x, z, e, "CHUNK");
Iris.error("======================================");
ChunkData d = Bukkit.createChunkData(world);
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
d.setBlock(i, 0, j, Material.RED_GLAZED_TERRACOTTA.createBlockData());
}
}
}
}
private Engine getEngine(WorldInfo world) {
if (setup.get()) {
return getEngine();
}
lock.lock();
try {
if (setup.get()) {
return getEngine();
}
getWorld().setRawWorldSeed(world.getSeed());
setupEngine();
setup.set(true);
this.hotloader = studio ? new Looper() {
@Override
protected long loop() {
if (hotloadChecker.flip()) {
folder.check();
}
return 250;
}
} : null;
if (studio) {
hotloader.setPriority(Thread.MIN_PRIORITY);
hotloader.start();
hotloader.setName(getTarget().getWorld().name() + " Hotloader");
}
return engine;
} finally {
lock.unlock();
}
}
@Override
public void close() {
withExclusiveControl(() -> {
if (isStudio()) {
hotloader.interrupt();
}
getEngine().close();
folder.clear();
populators.clear();
});
}
@Override
public boolean isStudio() {
return studio;
}
@Override
public void hotload() {
if (!isStudio()) {
return;
}
withExclusiveControl(() -> getEngine().hotload());
}
public void withExclusiveControl(Runnable r) {
J.a(() -> {
try {
loadLock.acquire(LOAD_LOCKS);
r.run();
loadLock.release(LOAD_LOCKS);
} catch (Throwable e) {
Iris.reportError(e);
}
});
}
@Override
public void touch(World world) {
getEngine(world);
}
@Override
public void generateNoise(@NotNull WorldInfo world, @NotNull Random random, int x, int z, @NotNull ChunkGenerator.ChunkData d) {
try {
getEngine(world);
computeStudioGenerator();
TerrainChunk tc = TerrainChunk.create(d, new IrisBiomeStorage());
this.world.bind(world);
if (studioGenerator != null) {
studioGenerator.generateChunk(getEngine(), tc, x, z);
} else {
ChunkDataHunkHolder blocks = new ChunkDataHunkHolder(tc);
BiomeGridHunkHolder biomes = new BiomeGridHunkHolder(tc, tc.getMinHeight(), tc.getMaxHeight());
getEngine().generate(x << 4, z << 4, blocks, biomes, false);
blocks.apply();
biomes.apply();
}
Iris.debug("Generated " + x + " " + z);
} catch (Throwable e) {
Iris.error("======================================");
e.printStackTrace();
Iris.reportErrorChunk(x, z, e, "CHUNK");
Iris.error("======================================");
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
d.setBlock(i, 0, j, Material.RED_GLAZED_TERRACOTTA.createBlockData());
}
}
}
}
@Override
public int getBaseHeight(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull HeightMap heightMap) {
return 4;
}
private void computeStudioGenerator() {
if (!getEngine().getDimension().getStudioMode().equals(lastMode)) {
lastMode = getEngine().getDimension().getStudioMode();
getEngine().getDimension().getStudioMode().inject(this);
}
}
@NotNull
@Override
public List<BlockPopulator> getDefaultPopulators(@NotNull World world) {
return populators;
}
@Override
public boolean isParallelCapable() {
return true;
}
@Override
public boolean shouldGenerateCaves() {
return false;
}
@Override
public boolean shouldGenerateDecorations() {
return false;
}
@Override
public boolean shouldGenerateMobs() {
return false;
}
@Override
public boolean shouldGenerateStructures() {
return false;
}
@Override
public boolean shouldGenerateNoise() {
return false;
}
@Override
public boolean shouldGenerateSurface() {
return false;
}
@Override
public boolean shouldGenerateBedrock() {
return false;
}
@Nullable
@Override
public BiomeProvider getDefaultBiomeProvider(@NotNull WorldInfo worldInfo) {
return dummyBiomeProvider;
}
}

View File

@@ -25,6 +25,7 @@ import com.volmit.iris.core.service.ExternalDataSVC;
import com.volmit.iris.engine.object.IrisCompat;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.scheduling.ChronoLatch;
import it.unimi.dsi.fastutil.ints.*;
import org.bukkit.Bukkit;
@@ -46,6 +47,7 @@ public class B {
private static final KMap<String, BlockData> custom = new KMap<>();
private static final Material AIR_MATERIAL = Material.AIR;
private static final Material SHORT_GRASS = E.getOrDefault(Material.class, "GRASS", "SHORT_GRASS");
private static final BlockData AIR = AIR_MATERIAL.createBlockData();
private static final IntSet foliageCache = buildFoliageCache();
private static final IntSet deepslateCache = buildDeepslateCache();
@@ -85,7 +87,7 @@ public class B {
WHITE_TULIP,
FERN,
LARGE_FERN,
GRASS,
SHORT_GRASS,
TALL_GRASS
}).forEach((i) -> b.add(i.ordinal()));
@@ -143,7 +145,7 @@ public class B {
private static IntSet buildDecorantCache() {
IntSet b = new IntOpenHashSet();
Arrays.stream(new Material[]{
GRASS,
SHORT_GRASS,
TALL_GRASS,
TALL_SEAGRASS,
FERN,

View File

@@ -0,0 +1,127 @@
package com.volmit.iris.util.data;
import com.volmit.iris.core.link.Identifier;
import lombok.Data;
import lombok.NonNull;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.SoundGroup;
import org.bukkit.block.*;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.structure.Mirror;
import org.bukkit.block.structure.StructureRotation;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@Data
public class IrisBlockData implements BlockData {
private final @NonNull BlockData base;
private final @NotNull Identifier custom;
@NotNull
@Override
public Material getMaterial() {
return base.getMaterial();
}
@NotNull
@Override
public String getAsString() {
return base.getAsString();
}
@NotNull
@Override
public String getAsString(boolean b) {
return base.getAsString(b);
}
@NotNull
@Override
public BlockData merge(@NotNull BlockData blockData) {
return new IrisBlockData(base.merge(blockData), custom);
}
@Override
public boolean matches(@Nullable BlockData blockData) {
if (blockData instanceof IrisBlockData b)
return custom.equals(b.custom) && base.matches(b.base);
return base.matches(blockData);
}
@NotNull
@Override
public BlockData clone() {
return new IrisBlockData(base.clone(), custom);
}
@NotNull
@Override
public SoundGroup getSoundGroup() {
return base.getSoundGroup();
}
@Override
public int getLightEmission() {
return base.getLightEmission();
}
@Override
public boolean isOccluding() {
return base.isOccluding();
}
@Override
public boolean requiresCorrectToolForDrops() {
return base.requiresCorrectToolForDrops();
}
@Override
public boolean isPreferredTool(@NotNull ItemStack itemStack) {
return base.isPreferredTool(itemStack);
}
@NotNull
@Override
public PistonMoveReaction getPistonMoveReaction() {
return base.getPistonMoveReaction();
}
@Override
public boolean isSupported(@NotNull Block block) {
return base.isSupported(block);
}
@Override
public boolean isSupported(@NotNull Location location) {
return base.isSupported(location);
}
@Override
public boolean isFaceSturdy(@NotNull BlockFace blockFace, @NotNull BlockSupport blockSupport) {
return base.isFaceSturdy(blockFace, blockSupport);
}
@NotNull
@Override
public Material getPlacementMaterial() {
return base.getPlacementMaterial();
}
@Override
public void rotate(@NotNull StructureRotation structureRotation) {
base.rotate(structureRotation);
}
@Override
public void mirror(@NotNull Mirror mirror) {
base.mirror(mirror);
}
@NotNull
@Override
public BlockState createBlockState() {
return base.createBlockState();
}
}

View File

@@ -0,0 +1,36 @@
package com.volmit.iris.util.decree.handlers;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.decree.DecreeParameterHandler;
import com.volmit.iris.util.decree.exceptions.DecreeParsingException;
public class DataVersionHandler implements DecreeParameterHandler<DataVersion> {
@Override
public KList<DataVersion> getPossibilities() {
return new KList<>(DataVersion.values());
}
@Override
public String toString(DataVersion version) {
return version.getVersion();
}
@Override
public DataVersion parse(String in, boolean force) throws DecreeParsingException {
if (in.equalsIgnoreCase("latest")) {
return DataVersion.getLatest();
}
for (DataVersion v : DataVersion.values()) {
if (v.getVersion().equalsIgnoreCase(in)) {
return v;
}
}
throw new DecreeParsingException("Unable to parse data version \"" + in + "\"");
}
@Override
public boolean supports(Class<?> type) {
return DataVersion.class.equals(type);
}
}

View File

@@ -19,6 +19,7 @@
package com.volmit.iris.util.hunk.view;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.hunk.Hunk;
import org.bukkit.block.data.BlockData;
import org.bukkit.generator.ChunkGenerator.ChunkData;
@@ -72,7 +73,8 @@ public class ChunkDataHunkView implements Hunk<BlockData> {
}
try {
if (t instanceof IrisBlockData d)
t = d.getBase();
chunk.setBlock(x, y + chunk.getMinHeight(), z, t);
} catch (Throwable ignored) {

View File

@@ -212,7 +212,7 @@ public class UIElement implements Element {
im.setLore(getLore().copy());
if (isEnchanted()) {
im.addEnchant(Enchantment.DURABILITY, 1, true);
im.addEnchant(Enchantment.FIRE_ASPECT, 1, true);
}
is.setItemMeta(im);

View File

@@ -21,6 +21,7 @@ package com.volmit.iris.util.mantle;
import com.google.common.util.concurrent.AtomicDouble;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.service.IrisEngineSVC;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
@@ -59,6 +60,7 @@ import java.util.concurrent.locks.ReentrantLock;
*/
public class Mantle {
private static final boolean disableClear = System.getProperty("disableClear", "false").equals("true");
private final File dataFolder;
@Getter
private final int worldHeight;
@@ -423,17 +425,17 @@ public class Mantle {
ioTrim.set(true);
unloadLock.lock();
try {
if (lastUse != null) {
if (lastUse != null && IrisEngineSVC.instance != null) {
if (!lastUse.isEmpty()) {
Iris.debug("Trimming Tectonic Plates older than " + Form.duration(adjustedIdleDuration.get(), 0));
for (Long i : new ArrayList<>(lastUse.keySet())) {
for (long i : new ArrayList<>(lastUse.keySet())) {
double finalAdjustedIdleDuration = adjustedIdleDuration.get();
hyperLock.withLong(i, () -> {
Long lastUseTime = lastUse.get(i);
if (lastUseTime != null && M.ms() - lastUseTime >= finalAdjustedIdleDuration) {
toUnload.add(i);
Iris.debug("Tectonic Region added to unload");
//Iris.panic();
IrisEngineSVC.instance.trimActiveAlive.reset();
}
});
}
@@ -452,37 +454,47 @@ public class Mantle {
AtomicInteger i = new AtomicInteger();
unloadLock.lock();
BurstExecutor burst = null;
try {
KList<Long> copy = toUnload.copy();
burst = MultiBurst.burst.burst(copy.size());
burst.setMulticore(copy.size() > tectonicLimit);
for (long id : copy) {
burst.queue(() ->
hyperLock.withLong(id, () -> {
TectonicPlate m = loadedRegions.get(id);
if (m != null) {
try {
m.write(fileForRegion(dataFolder, id));
loadedRegions.remove(id);
lastUse.remove(id);
toUnload.remove(id);
i.incrementAndGet();
Iris.debug("Unloaded Tectonic Plate " + C.DARK_GREEN + Cache.keyX(id) + " " + Cache.keyZ(id));
} catch (IOException e) {
Iris.reportError(e);
}
}
}));
if (IrisEngineSVC.instance != null) {
try {
KList<Long> copy = toUnload.copy();
if (!disableClear) toUnload.clear();
burst = MultiBurst.burst.burst(copy.size());
burst.setMulticore(copy.size() > tectonicLimit);
for (int j = 0; j < copy.size(); j++) {
Long id = copy.get(j);
if (id == null) {
Iris.error("Null id in unloadTectonicPlate at index " + j);
continue;
}
}
burst.complete();
} catch (Throwable e) {
e.printStackTrace();
if (burst != null)
burst.queue(() ->
hyperLock.withLong(id, () -> {
TectonicPlate m = loadedRegions.get(id);
if (m != null) {
try {
m.write(fileForRegion(dataFolder, id));
loadedRegions.remove(id);
lastUse.remove(id);
if (disableClear) toUnload.remove(id);
i.incrementAndGet();
Iris.debug("Unloaded Tectonic Plate " + C.DARK_GREEN + Cache.keyX(id) + " " + Cache.keyZ(id));
IrisEngineSVC.instance.unloadActiveAlive.reset();
} catch (IOException e) {
Iris.reportError(e);
}
}
}));
}
burst.complete();
} finally {
unloadLock.unlock();
ioTectonicUnload.set(true);
} catch (Throwable e) {
e.printStackTrace();
if (burst != null)
burst.complete();
} finally {
unloadLock.unlock();
ioTectonicUnload.set(true);
}
return i.get();
}
return i.get();
}

View File

@@ -33,7 +33,8 @@ public enum MantleFlag {
CLEANED,
PLANNED,
ETCHED,
TILE;
TILE,
CUSTOM;
static StateList getStateList() {
return new StateList(MantleFlag.values());

View File

@@ -18,6 +18,7 @@
package com.volmit.iris.util.matter.slices;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.data.palette.Palette;
import com.volmit.iris.util.matter.Sliced;
import org.bukkit.Bukkit;
@@ -39,7 +40,11 @@ public class BlockMatter extends RawMatter<BlockData> {
public BlockMatter(int width, int height, int depth) {
super(width, height, depth, BlockData.class);
registerWriter(World.class, ((w, d, x, y, z) -> w.getBlockAt(x, y, z).setBlockData(d)));
registerWriter(World.class, ((w, d, x, y, z) -> {
if (d instanceof IrisBlockData c)
w.getBlockAt(x, y, z).setBlockData(c.getBase());
else w.getBlockAt(x, y, z).setBlockData(d);
}));
registerReader(World.class, (w, x, y, z) -> {
BlockData d = w.getBlockAt(x, y, z).getBlockData();
return d.getMaterial().isAir() ? null : d;

View File

@@ -0,0 +1,36 @@
package com.volmit.iris.util.matter.slices;
import com.volmit.iris.core.link.Identifier;
import com.volmit.iris.util.data.palette.Palette;
import com.volmit.iris.util.matter.Sliced;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
@Sliced
public class IdentifierMatter extends RawMatter<Identifier> {
public IdentifierMatter() {
this(1, 1, 1);
}
public IdentifierMatter(int width, int height, int depth) {
super(width, height, depth, Identifier.class);
}
@Override
public Palette<Identifier> getGlobalPalette() {
return null;
}
@Override
public void writeNode(Identifier b, DataOutputStream dos) throws IOException {
dos.writeUTF(b.toString());
}
@Override
public Identifier readNode(DataInputStream din) throws IOException {
return Identifier.fromString(din.readUTF());
}
}

View File

@@ -0,0 +1,35 @@
package com.volmit.iris.util.matter.slices;
import com.volmit.iris.util.data.palette.Palette;
import com.volmit.iris.util.matter.Sliced;
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
@Sliced
public class JigsawStructuresMatter extends RawMatter<JigsawStructuresContainer> {
public JigsawStructuresMatter() {
this(1, 1, 1);
}
public JigsawStructuresMatter(int width, int height, int depth) {
super(width, height, depth, JigsawStructuresContainer.class);
}
@Override
public Palette<JigsawStructuresContainer> getGlobalPalette() {
return null;
}
@Override
public void writeNode(JigsawStructuresContainer b, DataOutputStream dos) throws IOException {
b.write(dos);
}
@Override
public JigsawStructuresContainer readNode(DataInputStream din) throws IOException {
return new JigsawStructuresContainer(din);
}
}

View File

@@ -0,0 +1,62 @@
package com.volmit.iris.util.matter.slices.container;
import com.volmit.iris.engine.object.IrisJigsawStructure;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.math.Position2;
import org.jetbrains.annotations.Unmodifiable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class JigsawStructuresContainer {
private final Map<String, List<Position2>> map = new KMap<>();
public JigsawStructuresContainer() {}
public JigsawStructuresContainer(DataInputStream din) throws IOException {
int s0 = din.readInt();
for (int i = 0; i < s0; i++) {
int s1 = din.readInt();
KList<Position2> list = new KList<>(s1);
for (int j = 0; j < s1; j++) {
list.add(new Position2(din.readInt(), din.readInt()));
}
map.put(din.readUTF(), list);
}
}
public void write(DataOutputStream dos) throws IOException {
dos.writeInt(map.size());
for (String key : map.keySet()) {
List<Position2> list = map.get(key);
dos.writeInt(list.size());
for (Position2 pos : list) {
dos.writeInt(pos.getX());
dos.writeInt(pos.getZ());
}
dos.writeUTF(key);
}
}
@Unmodifiable
public Set<String> getStructures() {
return Collections.unmodifiableSet(map.keySet());
}
@Unmodifiable
public List<Position2> getPositions(String structure) {
return Collections.unmodifiableList(map.get(structure));
}
@ChunkCoordinates
public void add(IrisJigsawStructure structure, Position2 pos) {
map.computeIfAbsent(structure.getLoadKey(), k -> new KList<>()).add(pos);
}
}

View File

@@ -0,0 +1,12 @@
package com.volmit.iris.util.misc;
public class E {
public static <T extends Enum<T>> T getOrDefault(Class<T> enumClass, String name, String fallback) {
try {
return Enum.valueOf(enumClass, name);
} catch (Throwable e) {
return Enum.valueOf(enumClass, fallback);
}
}
}

View File

@@ -0,0 +1,135 @@
package com.volmit.iris.util.misc;
import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import oshi.SystemInfo;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.util.List;
public class Hastebin {
public static void enviornment(CommandSender sender) {
// Construct the server information
StringBuilder sb = new StringBuilder();
SystemInfo systemInfo = new SystemInfo();
KList<String> disks = new KList<>(getHardware.getDisk());
KList<String> interfaces = new KList<>(getHardware.getInterfaces());
KList<String> displays = new KList<>(getHardware.getEDID());
KList<String> sensors = new KList<>(getHardware.getSensors());
KList<String> gpus = new KList<>(getHardware.getGraphicsCards());
KList<String> powersources = new KList<>(getHardware.getPowerSources());
KList<World> IrisWorlds = new KList<>();
KList<World> BukkitWorlds = new KList<>();
for (World w : Bukkit.getServer().getWorlds()) {
try {
Engine engine = IrisToolbelt.access(w).getEngine();
if (engine != null) {
IrisWorlds.add(w);
}
} catch (Exception e) {
BukkitWorlds.add(w);
}
}
sb.append(" -- == Iris Info == -- \n");
sb.append("Iris Version Version: ").append(Iris.instance.getDescription().getVersion()).append("\n");
sb.append("- Iris Worlds");
for (World w : IrisWorlds.copy()) {
sb.append(" - ").append(w.getName());
}
sb.append("- Bukkit Worlds");
for (World w : BukkitWorlds.copy()) {
sb.append(" - ").append(w.getName());
}
sb.append(" -- == Platform Overview == -- " + "\n");
sb.append("Server Type: ").append(Bukkit.getVersion()).append("\n");
sb.append("Server Uptime: ").append(Form.stampTime(systemInfo.getOperatingSystem().getSystemUptime())).append("\n");
sb.append("Version: ").append(Platform.getVersion()).append(" - Platform: ").append(Platform.getName()).append("\n");
sb.append("Java Vendor: ").append(Platform.ENVIRONMENT.getJavaVendor()).append(" - Java Version: ").append(Platform.ENVIRONMENT.getJavaVersion()).append("\n");
sb.append(" -- == Processor Overview == -- " + "\n");
sb.append("CPU Model: ").append(getHardware.getCPUModel());
sb.append("CPU Architecture: ").append(Platform.CPU.getArchitecture()).append(" Available Processors: ").append(Platform.CPU.getAvailableProcessors()).append("\n");
sb.append("CPU Load: ").append(Form.pc(Platform.CPU.getCPULoad())).append(" CPU Live Process Load: ").append(Form.pc(Platform.CPU.getLiveProcessCPULoad())).append("\n");
sb.append("-=" + " Graphics " + "=- " + "\n");
for (String gpu : gpus) {
sb.append(" ").append(gpu).append("\n");
}
sb.append(" -- == Memory Information == -- " + "\n");
sb.append("Physical Memory - Total: ").append(Form.memSize(Platform.MEMORY.PHYSICAL.getTotalMemory())).append(" Free: ").append(Form.memSize(Platform.MEMORY.PHYSICAL.getFreeMemory())).append(" Used: ").append(Form.memSize(Platform.MEMORY.PHYSICAL.getUsedMemory())).append("\n");
sb.append("Virtual Memory - Total: ").append(Form.memSize(Platform.MEMORY.VIRTUAL.getTotalMemory())).append(" Free: ").append(Form.memSize(Platform.MEMORY.VIRTUAL.getFreeMemory())).append(" Used: ").append(Form.memSize(Platform.MEMORY.VIRTUAL.getUsedMemory())).append("\n");
sb.append(" -- == Storage Information == -- " + "\n");
for (String disk : disks) {
sb.append(" ").append(sb.append(disk)).append("\n");
}
sb.append(" -- == Interface Information == -- "+ "\n" );
for (String inter : interfaces) {
sb.append(" ").append(inter).append("\n");
}
sb.append(" -- == Display Information == -- "+ "\n" );
for (String display : displays) {
sb.append(display).append("\n");
}
sb.append(" -- == Sensor Information == -- " + "\n");
for (String sensor : sensors) {
sb.append(" ").append(sensor).append("\n");
}
sb.append(" -- == Power Information == -- " + "\n");
for (String power : powersources) {
sb.append(" ").append(power).append("\n");
}
try {
String hastebinUrl = uploadToHastebin(sb.toString());
// Create the clickable message
TextComponent message = new TextComponent("[Link]");
TextComponent link = new TextComponent(hastebinUrl);
link.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, hastebinUrl));
message.addExtra(link);
// Send the clickable message to the player
sender.spigot().sendMessage(message);
} catch (Exception e) {
sender.sendMessage(C.DARK_RED + "Failed to upload server information to Hastebin.");
}
}
private static String uploadToHastebin(String content) throws Exception {
URL url = new URL("https://paste.bytecode.ninja/documents");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "text/plain");
conn.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(content);
wr.flush();
wr.close();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String response = br.readLine();
br.close();
return "https://paste.bytecode.ninja/" + response.split("\"")[3];
}
}

View File

@@ -0,0 +1,145 @@
package com.volmit.iris.util.misc;
import com.sun.management.OperatingSystemMXBean;
import java.io.File;
import java.lang.management.ManagementFactory;
@SuppressWarnings("restriction")
public class Platform {
public static String getVersion() {
return getSystem().getVersion();
}
public static String getName() {
return getSystem().getName();
}
private static OperatingSystemMXBean getSystem() {
return (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
}
public static class ENVIRONMENT {
public static boolean canRunBatch() {
return getSystem().getName().toLowerCase().contains("windows");
}
public static String getJavaHome() {
return System.getProperty("java.home");
}
public static String getJavaVendor() {
return System.getProperty("java.vendor");
}
public static String getJavaVersion() {
return System.getProperty("java.version");
}
}
public static class STORAGE {
public static long getAbsoluteTotalSpace() {
long t = 0;
for (File i : getRoots()) {
t += getTotalSpace(i);
}
return t;
}
public static long getTotalSpace() {
return getTotalSpace(new File("."));
}
public static long getTotalSpace(File root) {
return root.getTotalSpace();
}
public static long getAbsoluteFreeSpace() {
long t = 0;
for (File i : getRoots()) {
t += getFreeSpace(i);
}
return t;
}
public static long getFreeSpace() {
return getFreeSpace(new File("."));
}
public static long getFreeSpace(File root) {
return root.getFreeSpace();
}
public static long getUsedSpace() {
return getTotalSpace() - getFreeSpace();
}
public static long getUsedSpace(File root) {
return getTotalSpace(root) - getFreeSpace(root);
}
public static long getAbsoluteUsedSpace() {
return getAbsoluteTotalSpace() - getAbsoluteFreeSpace();
}
public static File[] getRoots() {
return File.listRoots();
}
}
public static class MEMORY {
public static class PHYSICAL {
public static long getTotalMemory() {
return getSystem().getTotalPhysicalMemorySize();
}
public static long getFreeMemory() {
return getSystem().getFreePhysicalMemorySize();
}
public static long getUsedMemory() {
return getTotalMemory() - getFreeMemory();
}
}
public static class VIRTUAL {
public static long getTotalMemory() {
return getSystem().getTotalSwapSpaceSize();
}
public static long getFreeMemory() {
return getSystem().getFreeSwapSpaceSize();
}
public static long getUsedMemory() {
return getTotalMemory() - getFreeMemory();
}
public static long getCommittedVirtualMemory() {
return getSystem().getCommittedVirtualMemorySize();
}
}
}
public static class CPU {
public static int getAvailableProcessors() {
return getSystem().getAvailableProcessors();
}
public static double getCPULoad() {
return getSystem().getSystemCpuLoad();
}
public static double getLiveProcessCPULoad() {
return getSystem().getProcessCpuLoad();
}
public static String getArchitecture() {
return getSystem().getArch();
}
}
}

View File

@@ -1,11 +1,24 @@
package com.volmit.iris.util.misc;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.HWDiskStore;
import oshi.software.os.OperatingSystem;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import org.jetbrains.annotations.Nullable;
import oshi.SystemInfo;
import oshi.hardware.*;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.EdidUtil;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.stream.Collectors;
public class getHardware {
public static String getServerOS() {
@@ -44,14 +57,127 @@ public class getHardware {
}
}
public static String getDiskModel() {
SystemInfo systemInfo = new SystemInfo();
List<HWDiskStore> diskStores = systemInfo.getHardware().getDiskStores();
if (!diskStores.isEmpty()) {
HWDiskStore firstDisk = diskStores.get(0);
return firstDisk.getModel();
} else {
return "Unknown Disk Model";
public static KList<String> getSensors() {
try {
KList<String> temps = new KList<>();
SystemInfo systemInfo = new SystemInfo();
temps.add("CPU Temperature: " + systemInfo.getHardware().getSensors().getCpuTemperature());
temps.add("CPU Voltage: " + systemInfo.getHardware().getSensors().getCpuTemperature());
temps.add("Fan Speeds: " + Arrays.toString(systemInfo.getHardware().getSensors().getFanSpeeds()));
return temps.copy();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public static KList<String> getGraphicsCards() {
try {
KList<String> gpus = new KList<>();
SystemInfo systemInfo = new SystemInfo();
for (GraphicsCard gpu : systemInfo.getHardware().getGraphicsCards()) {
gpus.add(C.BLUE + "Gpu Model: " + C.GRAY + gpu.getName());
gpus.add("- vRam Size: " + C.GRAY + Form.memSize(gpu.getVRam()));
gpus.add("- Vendor: " + C.GRAY + gpu.getVendor());
}
return gpus.copy();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static KList<String> getDisk() {
try {
KList<String> systemDisks = new KList<>();
SystemInfo systemInfo = new SystemInfo();
List<HWDiskStore> diskStores = systemInfo.getHardware().getDiskStores();
OperatingSystem operatingSystem = systemInfo.getOperatingSystem();
List<OSFileStore> fileStores = operatingSystem.getFileSystem().getFileStores();
for (HWDiskStore disk : diskStores) {
systemDisks.add(C.BLUE + "Disk: " + disk.getName());
systemDisks.add("- Model: " + disk.getModel());
systemDisks.add("Partitions: " + disk.getPartitions());
for (OSFileStore partition : fileStores) {
systemDisks.add(C.BLUE + "- Name: " + partition.getName());
systemDisks.add(" - Description: " + partition.getDescription());
systemDisks.add(" - Total Space: " + Form.memSize(partition.getTotalSpace()));
systemDisks.add(" - Free Space: " + Form.memSize(partition.getFreeSpace()));
systemDisks.add(" - Mount: " + partition.getMount());
systemDisks.add(" - Label: " + partition.getLabel());
}
systemDisks.add(C.DARK_GRAY + "-=" + C.BLUE +" Since Boot " + C.DARK_GRAY + "=- ");
systemDisks.add("- Total Reads: " + Form.memSize(disk.getReadBytes()));
systemDisks.add("- Total Writes: " + Form.memSize(disk.getWriteBytes()));
}
if (systemDisks.isEmpty()) {
systemDisks.add("Failed to get disks.");
}
return systemDisks.copy();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static KList<String> getPowerSources() {
try {
KList<String> systemPowerSources = new KList<>();
SystemInfo systemInfo = new SystemInfo();
List<PowerSource> powerSources = systemInfo.getHardware().getPowerSources();
for (PowerSource powersource : powerSources) {
systemPowerSources.add(C.BLUE + "- Name: " + powersource.getName());
systemPowerSources.add("- RemainingCapacityPercent: " + powersource.getRemainingCapacityPercent());
systemPowerSources.add("- Power Usage Rate: " + powersource.getPowerUsageRate());
systemPowerSources.add("- Power OnLine: " + powersource.isPowerOnLine());
systemPowerSources.add("- Capacity Units: " + powersource.getCapacityUnits());
systemPowerSources.add("- Cycle Count: " + powersource.getCycleCount());
}
if (systemPowerSources.isEmpty()) {
systemPowerSources.add("No PowerSources.");
}
return systemPowerSources.copy();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static KList<String> getEDID() {
try {
KList<String> systemEDID = new KList<>();
SystemInfo systemInfo = new SystemInfo();
HardwareAbstractionLayer hardware = systemInfo.getHardware();
List<Display> displays = hardware.getDisplays();
for (Display display : displays) {
systemEDID.add("Display: " + display.getEdid());
}
if (!systemEDID.isEmpty()) {
systemEDID.add("No displays");
}
return systemEDID.copy();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static KList<String> getInterfaces() {
try {
KList<String> interfaces = new KList<>();
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface ni : Collections.list(networkInterfaces)) {
interfaces.add(C.BLUE + "Display Name: %s", ni.getDisplayName());
Enumeration<InetAddress> inetAddresses = ni.getInetAddresses();
for (InetAddress ia : Collections.list(inetAddresses)) {
interfaces.add("IP: %s", ia.getHostAddress());
}
return interfaces.copy();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@@ -27,10 +27,12 @@ import com.volmit.iris.util.nbt.io.NamedTag;
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import com.volmit.iris.util.nbt.tag.ListTag;
import org.bukkit.World;
import java.io.*;
import static com.volmit.iris.util.nbt.mca.LoadFlags.*;
import static org.bukkit.Bukkit.getServer;
public class Chunk {
public static final int DEFAULT_DATA_VERSION = 2730;
@@ -39,6 +41,7 @@ public class Chunk {
private int lastMCAUpdate;
private CompoundTag data;
private int dataVersion;
private int nativeIrisVersion;
private long lastUpdate;
private long inhabitedTime;
private MCABiomeContainer biomes;
@@ -71,15 +74,21 @@ public class Chunk {
}
public static Chunk newChunk() {
World mainWorld = getServer().getWorlds().get(0);
Chunk c = new Chunk(0);
c.dataVersion = DEFAULT_DATA_VERSION;
c.data = new CompoundTag();
c.biomes = INMS.get().newBiomeContainer(0, 256);
c.biomes = INMS.get().newBiomeContainer(mainWorld.getMinHeight(), mainWorld.getMaxHeight());
c.data.put("Level", defaultLevel());
c.status = "full";
return c;
}
public static void injectIrisData(Chunk c) {
World mainWorld = getServer().getWorlds().get(0);
c.data.put("Iris", nativeIrisVersion());
}
private static CompoundTag defaultLevel() {
CompoundTag level = new CompoundTag();
level.putString("Status", "full");
@@ -87,19 +96,25 @@ public class Chunk {
return level;
}
private static CompoundTag nativeIrisVersion() {
CompoundTag level = new CompoundTag();
level.putString("Generator", "Iris " + Iris.instance.getDescription().getVersion());
return level;
}
private void initReferences(long loadFlags) {
if (data == null) {
throw new NullPointerException("data cannot be null");
}
CompoundTag level;
if ((level = data.getCompoundTag("Level")) == null) {
throw new IllegalArgumentException("data does not contain \"Level\" tag");
}
CompoundTag level = data;
World mainWorld = getServer().getWorlds().get(0);
dataVersion = data.getInt("DataVersion");
inhabitedTime = level.getLong("InhabitedTime");
lastUpdate = level.getLong("LastUpdate");
if ((loadFlags & BIOMES) != 0) {
biomes = INMS.get().newBiomeContainer(0, 256, level.getIntArray("Biomes"));
biomes = INMS.get().newBiomeContainer(mainWorld.getMinHeight(), mainWorld.getMaxHeight(), level.getIntArray("Biomes"));
}
if ((loadFlags & HEIGHTMAPS) != 0) {
heightMaps = level.getCompoundTag("Heightmaps");

View File

@@ -18,6 +18,8 @@
package com.volmit.iris.util.plugin;
import com.volmit.iris.util.format.C;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@@ -28,4 +30,5 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Target(FIELD)
public @interface Command {
String value() default "";
}

View File

@@ -12,7 +12,7 @@ libraries:
- commons-io:commons-io:2.13.0
- io.timeandspace:smoothie-map:2.0.2
- com.google.guava:guava:31.0.1-jre
- com.google.code.gson:gson:2.8.9
- com.google.code.gson:gson:2.10.1
- org.zeroturnaround:zt-zip:1.14
- it.unimi.dsi:fastutil:8.5.6
- org.ow2.asm:asm:9.2

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -1,5 +1,34 @@
package com.volmit.iris.core.nms.v1_19_R1;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_19_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
@@ -10,11 +39,13 @@ import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.matter.MatterBiomeInject;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.mca.palette.*;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
@@ -24,40 +55,15 @@ import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_19_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_19_R1.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import sun.misc.Unsafe;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class NMSBinding implements INMSBinding {
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
private final BlockData AIR = Material.AIR.createBlockData();
@@ -483,6 +489,34 @@ public class NMSBinding implements INMSBinding {
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
Field[] fields = EntityType.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) && field.getType().equals(EntityType.class)) {
try {
EntityType entityType = (EntityType) field.get(null);
if (entityType.getDescriptionId().equals("entity.minecraft." + entity.name().toLowerCase())) {
Vector<Float> v1 = new Vector<>();
v1.add(entityType.getHeight());
entityType.getDimensions();
Vector3d box = new Vector3d( entityType.getWidth(), entityType.getHeight(), entityType.getWidth());
//System.out.println("Entity Type: " + entityType.getDescriptionId() + ", " + "Height: " + height + ", Width: " + width);
return box;
}
} catch (IllegalAccessException e) {
Iris.error("Unable to get entity dimensions!");
e.printStackTrace();
}
}
}
return null;
}
@Override
public Entity spawnEntity(Location location, org.bukkit.entity.EntityType type, CreatureSpawnEvent.SpawnReason reason) {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -1,36 +1,17 @@
package com.volmit.iris.core.nms.v1_19_R2;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.matter.MatterBiomeInject;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.mca.palette.*;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
@@ -43,20 +24,46 @@ import org.bukkit.craftbukkit.v1_19_R2.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import sun.misc.Unsafe;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.matter.MatterBiomeInject;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.mca.palette.*;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import sun.misc.Unsafe;
public class NMSBinding implements INMSBinding {
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
@@ -483,6 +490,35 @@ public class NMSBinding implements INMSBinding {
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
Field[] fields = EntityType.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) && field.getType().equals(EntityType.class)) {
try {
EntityType entityType = (EntityType) field.get(null);
if (entityType.getDescriptionId().equals("entity.minecraft." + entity.name().toLowerCase())) {
Vector<Float> v1 = new Vector<>();
v1.add(entityType.getHeight());
entityType.getDimensions();
Vector3d box = new Vector3d( entityType.getWidth(), entityType.getHeight(), entityType.getWidth());
//System.out.println("Entity Type: " + entityType.getDescriptionId() + ", " + "Height: " + height + ", Width: " + width);
return box;
}
} catch (IllegalAccessException e) {
Iris.error("Unable to get entity dimensions!");
e.printStackTrace();
}
}
}
return null;
}
@Override
public Entity spawnEntity(Location location, org.bukkit.entity.EntityType type, CreatureSpawnEvent.SpawnReason reason) {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -1,5 +1,34 @@
package com.volmit.iris.core.nms.v1_19_R3;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_19_R3.CraftChunk;
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlock;
import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
@@ -10,11 +39,13 @@ import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.matter.MatterBiomeInject;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.mca.palette.*;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
@@ -25,6 +56,7 @@ import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
@@ -32,34 +64,8 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_19_R3.CraftChunk;
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlock;
import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import sun.misc.Unsafe;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class NMSBinding implements INMSBinding {
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
private final BlockData AIR = Material.AIR.createBlockData();
@@ -276,7 +282,7 @@ public class NMSBinding implements INMSBinding {
@Override
public KList<Biome> getBiomes() {
return new KList<>(Biome.values()).qadd(Biome.CHERRY_GROVE).qdel(Biome.CUSTOM);
return new KList<>(Biome.values()).qdel(Biome.CHERRY_GROVE).qdel(Biome.CUSTOM);
}
@Override
@@ -486,6 +492,37 @@ public class NMSBinding implements INMSBinding {
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
Field[] fields = EntityType.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) && field.getType().equals(EntityType.class)) {
try {
EntityType entityType = (EntityType) field.get(null);
if (entityType.getDescriptionId().equals("entity.minecraft." + entity.name().toLowerCase())) {
Vector<Float> v1 = new Vector<>();
v1.add(entityType.getHeight());
entityType.getDimensions();
Vector3d box = new Vector3d( entityType.getWidth(), entityType.getHeight(), entityType.getWidth());
//System.out.println("Entity Type: " + entityType.getDescriptionId() + ", " + "Height: " + height + ", Width: " + width);
return box;
}
} catch (IllegalAccessException e) {
Iris.error("Unable to get entity dimensions!");
e.printStackTrace();
}
}
}
return null;
}
@Override
public Entity spawnEntity(Location location, org.bukkit.entity.EntityType type, CreatureSpawnEvent.SpawnReason reason) {
if (type == org.bukkit.entity.EntityType.CAMEL) {
return null;
}
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -10,6 +10,7 @@ import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.matter.MatterBiomeInject;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
@@ -25,6 +26,7 @@ import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
@@ -45,6 +47,9 @@ import org.bukkit.craftbukkit.v1_20_R1.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.entity.EntityType;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
@@ -56,8 +61,10 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
public class NMSBinding implements INMSBinding {
@@ -474,6 +481,34 @@ public class NMSBinding implements INMSBinding {
cd.getHandle().setGotFish(true);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
Field[] fields = net.minecraft.world.entity.EntityType.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) && field.getType().equals(net.minecraft.world.entity.EntityType.class)) {
try {
net.minecraft.world.entity.EntityType entityType = (net.minecraft.world.entity.EntityType) field.get(null);
if (entityType.getDescriptionId().equals("entity.minecraft." + entity.name().toLowerCase())) {
Vector<Float> v1 = new Vector<>();
v1.add(entityType.getHeight());
entityType.getDimensions();
Vector3d box = new Vector3d( entityType.getWidth(), entityType.getHeight(), entityType.getWidth());
//System.out.println("Entity Type: " + entityType.getDescriptionId() + ", " + "Height: " + height + ", Width: " + width);
return box;
}
} catch (IllegalAccessException e) {
Iris.error("Unable to get entity dimensions!");
e.printStackTrace();
}
}
}
return null;
}
@Override
public Entity spawnEntity(Location location, org.bukkit.entity.EntityType type, CreatureSpawnEvent.SpawnReason reason) {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
ServerLevel serverLevel = ((CraftWorld)world).getHandle();
Class<?> clazz = serverLevel.getChunkSource().chunkMap.generator.getClass();

View File

@@ -1,5 +1,34 @@
package com.volmit.iris.core.nms.v1_20_R2;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_20_R2.CraftChunk;
import org.bukkit.craftbukkit.v1_20_R2.CraftServer;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
@@ -10,11 +39,13 @@ import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.matter.MatterBiomeInject;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.mca.palette.*;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
@@ -26,6 +57,7 @@ import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
@@ -33,34 +65,8 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_20_R2.CraftChunk;
import org.bukkit.craftbukkit.v1_20_R2.CraftServer;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import sun.misc.Unsafe;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class NMSBinding implements INMSBinding {
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
private final BlockData AIR = Material.AIR.createBlockData();
@@ -486,6 +492,34 @@ public class NMSBinding implements INMSBinding {
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
Field[] fields = EntityType.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) && field.getType().equals(EntityType.class)) {
try {
EntityType entityType = (EntityType) field.get(null);
if (entityType.getDescriptionId().equals("entity.minecraft." + entity.name().toLowerCase())) {
Vector<Float> v1 = new Vector<>();
v1.add(entityType.getHeight());
entityType.getDimensions();
Vector3d box = new Vector3d( entityType.getWidth(), entityType.getHeight(), entityType.getWidth());
//System.out.println("Entity Type: " + entityType.getDescriptionId() + ", " + "Height: " + height + ", Width: " + width);
return box;
}
} catch (IllegalAccessException e) {
Iris.error("Unable to get entity dimensions!");
e.printStackTrace();
}
}
}
return null;
}
@Override
public Entity spawnEntity(Location location, org.bukkit.entity.EntityType type, CreatureSpawnEvent.SpawnReason reason) {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -1,5 +1,34 @@
package com.volmit.iris.core.nms.v1_20_R3;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_20_R3.CraftChunk;
import org.bukkit.craftbukkit.v1_20_R3.CraftServer;
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
@@ -10,11 +39,13 @@ import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.matter.MatterBiomeInject;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.mca.palette.*;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
@@ -26,6 +57,7 @@ import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
@@ -33,34 +65,8 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_20_R3.CraftChunk;
import org.bukkit.craftbukkit.v1_20_R3.CraftServer;
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R3.util.CraftNamespacedKey;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import sun.misc.Unsafe;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class NMSBinding implements INMSBinding {
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
private final BlockData AIR = Material.AIR.createBlockData();
@@ -486,6 +492,35 @@ public class NMSBinding implements INMSBinding {
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
Field[] fields = EntityType.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) && field.getType().equals(EntityType.class)) {
try {
EntityType entityType = (EntityType) field.get(null);
if (entityType.getDescriptionId().equals("entity.minecraft." + entity.name().toLowerCase())) {
Vector<Float> v1 = new Vector<>();
v1.add(entityType.getHeight());
entityType.getDimensions();
Vector3d box = new Vector3d( entityType.getWidth(), entityType.getHeight(), entityType.getWidth());
//System.out.println("Entity Type: " + entityType.getDescriptionId() + ", " + "Height: " + height + ", Width: " + width);
return box;
}
} catch (IllegalAccessException e) {
Iris.error("Unable to get entity dimensions!");
e.printStackTrace();
}
}
}
return null;
}
@Override
public Entity spawnEntity(Location location, org.bukkit.entity.EntityType type, CreatureSpawnEvent.SpawnReason reason) {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -0,0 +1,168 @@
package com.volmit.iris.core.nms.v1_20_R4;
import com.mojang.serialization.MapCodec;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.math.RNG;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Climate;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R4.CraftServer;
import org.bukkit.craftbukkit.v1_20_R4.CraftWorld;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class CustomBiomeSource extends BiomeSource {
private final long seed;
private final Engine engine;
private final Registry<Biome> biomeCustomRegistry;
private final Registry<Biome> biomeRegistry;
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
private final RNG rng;
private final KMap<String, Holder<Biome>> customBiomes;
public CustomBiomeSource(long seed, Engine engine, World world) {
this.engine = engine;
this.seed = seed;
this.biomeCustomRegistry = registry().registry(Registries.BIOME).orElse(null);
this.biomeRegistry = ((RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer())).registry(Registries.BIOME).orElse(null);
this.rng = new RNG(engine.getSeedManager().getBiome());
this.customBiomes = fillCustomBiomes(biomeCustomRegistry, engine);
}
private static List<Holder<Biome>> getAllBiomes(Registry<Biome> customRegistry, Registry<Biome> registry, Engine engine) {
List<Holder<Biome>> b = new ArrayList<>();
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
b.add(customRegistry.getHolder(customRegistry.getResourceKey(customRegistry
.get(new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()))).get()).get());
}
} else {
b.add(NMSBinding.biomeToBiomeBase(registry, i.getVanillaDerivative()));
}
}
return b;
}
private static Object getFor(Class<?> type, Object source) {
Object o = fieldFor(type, source);
if (o != null) {
return o;
}
return invokeFor(type, source);
}
private static Object fieldFor(Class<?> returns, Object in) {
return fieldForClass(returns, in.getClass(), in);
}
private static Object invokeFor(Class<?> returns, Object in) {
for (Method i : in.getClass().getMethods()) {
if (i.getReturnType().equals(returns)) {
i.setAccessible(true);
try {
Iris.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()");
return i.invoke(in);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
return null;
}
@SuppressWarnings("unchecked")
private static <T> T fieldForClass(Class<T> returnType, Class<?> sourceType, Object in) {
for (Field i : sourceType.getDeclaredFields()) {
if (i.getType().equals(returnType)) {
i.setAccessible(true);
try {
Iris.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName());
return (T) i.get(in);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return null;
}
@Override
protected Stream<Holder<Biome>> collectPossibleBiomes() {
return getAllBiomes(
((RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()))
.registry(Registries.BIOME).orElse(null),
((CraftWorld) engine.getWorld().realWorld()).getHandle().registryAccess().registry(Registries.BIOME).orElse(null),
engine).stream();
}
private KMap<String, Holder<Biome>> fillCustomBiomes(Registry<Biome> customRegistry, Engine engine) {
KMap<String, Holder<Biome>> m = new KMap<>();
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
ResourceLocation resourceLocation = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(resourceLocation);
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
if (optionalBiomeKey.isEmpty()) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
continue;
}
ResourceKey<Biome> biomeKey = optionalBiomeKey.get();
Optional<Holder.Reference<Biome>> optionalReferenceHolder = customRegistry.getHolder(biomeKey);
if (optionalReferenceHolder.isEmpty()) {
Iris.error("Cannot find reference to biome " + biomeKey + " for engine " + engine.getName());
continue;
}
m.put(j.getId(), optionalReferenceHolder.get());
}
}
}
return m;
}
private RegistryAccess registry() {
return registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()));
}
@Override
protected MapCodec<? extends BiomeSource> codec() {
throw new UnsupportedOperationException("Not supported");
}
@Override
public Holder<Biome> getNoiseBiome(int x, int y, int z, Climate.Sampler sampler) {
int m = (y - engine.getMinHeight()) << 2;
IrisBiome ib = engine.getComplex().getTrueBiomeStream().get(x << 2, z << 2);
if (ib.isCustom()) {
return customBiomes.get(ib.getCustomBiome(rng, x << 2, m, z << 2).getId());
} else {
org.bukkit.block.Biome v = ib.getSkyBiome(rng, x << 2, m, z << 2);
return NMSBinding.biomeToBiomeBase(biomeRegistry, v);
}
}
}

View File

@@ -0,0 +1,552 @@
package com.volmit.iris.core.nms.v1_20_R4;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.datapack.DataVersion;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_20_R4.CraftChunk;
import org.bukkit.craftbukkit.v1_20_R4.CraftServer;
import org.bukkit.craftbukkit.v1_20_R4.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R4.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R4.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R4.util.CraftNamespacedKey;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.matter.MatterBiomeInject;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.mca.palette.*;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import sun.misc.Unsafe;
public class NMSBinding implements INMSBinding {
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
private final BlockData AIR = Material.AIR.createBlockData();
private final AtomicCache<MCAIdMap<net.minecraft.world.level.biome.Biome>> biomeMapCache = new AtomicCache<>();
private final AtomicCache<MCAIdMapper<BlockState>> registryCache = new AtomicCache<>();
private final AtomicCache<MCAPalette<BlockState>> globalCache = new AtomicCache<>();
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
private final AtomicCache<Method> byIdRef = new AtomicCache<>();
private Field biomeStorageCache = null;
private static Object getFor(Class<?> type, Object source) {
Object o = fieldFor(type, source);
if (o != null) {
return o;
}
return invokeFor(type, source);
}
private static Object invokeFor(Class<?> returns, Object in) {
for (Method i : in.getClass().getMethods()) {
if (i.getReturnType().equals(returns)) {
i.setAccessible(true);
try {
Iris.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()");
return i.invoke(in);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
return null;
}
private static Object fieldFor(Class<?> returns, Object in) {
return fieldForClass(returns, in.getClass(), in);
}
@SuppressWarnings("unchecked")
private static <T> T fieldForClass(Class<T> returnType, Class<?> sourceType, Object in) {
for (Field i : sourceType.getDeclaredFields()) {
if (i.getType().equals(returnType)) {
i.setAccessible(true);
try {
Iris.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName());
return (T) i.get(in);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return null;
}
private static Class<?> getClassType(Class<?> type, int ordinal) {
return type.getDeclaredClasses()[ordinal];
}
@Override
public boolean hasTile(Location l) {
return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()), false) != null;
}
@Override
public CompoundTag serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), true);
if (e == null) {
return null;
}
net.minecraft.nbt.CompoundTag tag = e.saveWithFullMetadata(registry());
return convert(tag);
}
private CompoundTag convert(net.minecraft.nbt.CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(boas);
tag.write(dos);
dos.close();
return (CompoundTag) NBTUtil.read(new ByteArrayInputStream(boas.toByteArray()), false).getTag();
} catch (Throwable ex) {
ex.printStackTrace();
}
return null;
}
private net.minecraft.nbt.CompoundTag convert(CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
NBTUtil.write(tag, boas, false);
DataInputStream din = new DataInputStream(new ByteArrayInputStream(boas.toByteArray()));
net.minecraft.nbt.CompoundTag c = NbtIo.read(din);
din.close();
return c;
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
@Override
public void deserializeTile(CompoundTag c, Location pos) {
((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c));
}
@Override
public CompoundTag serializeEntity(Entity location) {
return null;// TODO:
}
@Override
public Entity deserializeEntity(CompoundTag s, Location newPosition) {
return null;// TODO:
}
@Override
public boolean supportsCustomHeight() {
return true;
}
private RegistryAccess registry() {
return registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()));
}
private Registry<net.minecraft.world.level.biome.Biome> getCustomBiomeRegistry() {
return registry().registry(Registries.BIOME).orElse(null);
}
private Registry<Block> getBlockRegistry() {
return registry().registry(Registries.BLOCK).orElse(null);
}
@Override
public Object getBiomeBaseFromId(int id) {
return getCustomBiomeRegistry().getHolder(id);
}
@Override
public int getMinHeight(World world) {
return world.getMinHeight();
}
@Override
public boolean supportsCustomBiomes() {
return true;
}
@Override
public int getTrueBiomeBaseId(Object biomeBase) {
return getCustomBiomeRegistry().getId(((Holder<net.minecraft.world.level.biome.Biome>) biomeBase).value());
}
@Override
public Object getTrueBiomeBase(Location location) {
return ((CraftWorld) location.getWorld()).getHandle().getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
}
@Override
public String getTrueBiomeBaseKey(Location location) {
return getKeyForBiomeBase(getTrueBiomeBase(location));
}
@Override
public Object getCustomBiomeBaseFor(String mckey) {
return getCustomBiomeRegistry().get(new ResourceLocation(mckey));
}
@Override
public Object getCustomBiomeBaseHolderFor(String mckey) {
return getCustomBiomeRegistry().getHolder(getTrueBiomeBaseId(getCustomBiomeRegistry().get(new ResourceLocation(mckey)))).get();
}
public int getBiomeBaseIdForKey(String key) {
return getCustomBiomeRegistry().getId(getCustomBiomeRegistry().get(new ResourceLocation(key)));
}
@Override
public String getKeyForBiomeBase(Object biomeBase) {
return getCustomBiomeRegistry().getKey((net.minecraft.world.level.biome.Biome) biomeBase).getPath(); // something, not something:something
}
@Override
public Object getBiomeBase(World world, Biome biome) {
return biomeToBiomeBase(((CraftWorld) world).getHandle()
.registryAccess().registry(Registries.BIOME).orElse(null), biome);
}
@Override
public Object getBiomeBase(Object registry, Biome biome) {
Object v = baseBiomeCache.get(biome);
if (v != null) {
return v;
}
//noinspection unchecked
v = biomeToBiomeBase((Registry<net.minecraft.world.level.biome.Biome>) registry, biome);
if (v == null) {
// Ok so there is this new biome name called "CUSTOM" in Paper's new releases.
// But, this does NOT exist within CraftBukkit which makes it return an error.
// So, we will just return the ID that the plains biome returns instead.
//noinspection unchecked
return biomeToBiomeBase((Registry<net.minecraft.world.level.biome.Biome>) registry, Biome.PLAINS);
}
baseBiomeCache.put(biome, v);
return v;
}
@Override
public KList<Biome> getBiomes() {
return new KList<>(Biome.values()).qadd(Biome.CHERRY_GROVE).qdel(Biome.CUSTOM);
}
@Override
public boolean isBukkit() {
return true;
}
@Override
public int getBiomeId(Biome biome) {
for (World i : Bukkit.getWorlds()) {
if (i.getEnvironment().equals(World.Environment.NORMAL)) {
Registry<net.minecraft.world.level.biome.Biome> registry = ((CraftWorld) i).getHandle().registryAccess().registry(Registries.BIOME).orElse(null);
return registry.getId((net.minecraft.world.level.biome.Biome) getBiomeBase(registry, biome));
}
}
return biome.ordinal();
}
private MCAIdMap<net.minecraft.world.level.biome.Biome> getBiomeMapping() {
return biomeMapCache.aquire(() -> new MCAIdMap<>() {
@NotNull
@Override
public Iterator<net.minecraft.world.level.biome.Biome> iterator() {
return getCustomBiomeRegistry().iterator();
}
@Override
public int getId(net.minecraft.world.level.biome.Biome paramT) {
return getCustomBiomeRegistry().getId(paramT);
}
@Override
public net.minecraft.world.level.biome.Biome byId(int paramInt) {
return (net.minecraft.world.level.biome.Biome) getBiomeBaseFromId(paramInt);
}
});
}
@NotNull
private MCABiomeContainer getBiomeContainerInterface(MCAIdMap<net.minecraft.world.level.biome.Biome> biomeMapping, MCAChunkBiomeContainer<net.minecraft.world.level.biome.Biome> base) {
return new MCABiomeContainer() {
@Override
public int[] getData() {
return base.writeBiomes();
}
@Override
public void setBiome(int x, int y, int z, int id) {
base.setBiome(x, y, z, biomeMapping.byId(id));
}
@Override
public int getBiome(int x, int y, int z) {
return biomeMapping.getId(base.getBiome(x, y, z));
}
};
}
@Override
public MCABiomeContainer newBiomeContainer(int min, int max) {
MCAChunkBiomeContainer<net.minecraft.world.level.biome.Biome> base = new MCAChunkBiomeContainer<>(getBiomeMapping(), min, max);
return getBiomeContainerInterface(getBiomeMapping(), base);
}
@Override
public MCABiomeContainer newBiomeContainer(int min, int max, int[] data) {
MCAChunkBiomeContainer<net.minecraft.world.level.biome.Biome> base = new MCAChunkBiomeContainer<>(getBiomeMapping(), min, max, data);
return getBiomeContainerInterface(getBiomeMapping(), base);
}
@Override
public int countCustomBiomes() {
AtomicInteger a = new AtomicInteger(0);
getCustomBiomeRegistry().keySet().forEach((i) -> {
if (i.getNamespace().equals("minecraft")) {
return;
}
a.incrementAndGet();
Iris.debug("Custom Biome: " + i);
});
return a.get();
}
public boolean supportsDataPacks() {
return true;
}
public void setBiomes(int cx, int cz, World world, Hunk<Object> biomes) {
LevelChunk c = ((CraftWorld) world).getHandle().getChunk(cx, cz);
biomes.iterateSync((x, y, z, b) -> c.setBiome(x, y, z, (Holder<net.minecraft.world.level.biome.Biome>) b));
c.setUnsaved(true);
}
@Override
public void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk) {
try {
ChunkAccess s = (ChunkAccess) getFieldForBiomeStorage(chunk).get(chunk);
Holder<net.minecraft.world.level.biome.Biome> biome = (Holder<net.minecraft.world.level.biome.Biome>) somethingVeryDirty;
s.setBiome(x, y, z, biome);
} catch (IllegalAccessException e) {
Iris.reportError(e);
e.printStackTrace();
}
}
private Field getFieldForBiomeStorage(Object storage) {
Field f = biomeStorageCache;
if (f != null) {
return f;
}
try {
f = storage.getClass().getDeclaredField("biome");
f.setAccessible(true);
return f;
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
Iris.error(storage.getClass().getCanonicalName());
}
biomeStorageCache = f;
return null;
}
@Override
public MCAPaletteAccess createPalette() {
MCAIdMapper<BlockState> registry = registryCache.aquireNasty(() -> {
Field cf = net.minecraft.core.IdMapper.class.getDeclaredField("tToId");
Field df = net.minecraft.core.IdMapper.class.getDeclaredField("idToT");
Field bf = net.minecraft.core.IdMapper.class.getDeclaredField("nextId");
cf.setAccessible(true);
df.setAccessible(true);
bf.setAccessible(true);
net.minecraft.core.IdMapper<BlockState> blockData = Block.BLOCK_STATE_REGISTRY;
int b = bf.getInt(blockData);
Object2IntMap<BlockState> c = (Object2IntMap<BlockState>) cf.get(blockData);
List<BlockState> d = (List<BlockState>) df.get(blockData);
return new MCAIdMapper<BlockState>(c, d, b);
});
MCAPalette<BlockState> global = globalCache.aquireNasty(() -> new MCAGlobalPalette<>(registry, ((CraftBlockData) AIR).getState()));
MCAPalettedContainer<BlockState> container = new MCAPalettedContainer<>(global, registry,
i -> ((CraftBlockData) NBTWorld.getBlockData(i)).getState(),
i -> NBTWorld.getCompound(CraftBlockData.fromData(i)),
((CraftBlockData) AIR).getState());
return new MCAWrappedPalettedContainer<>(container,
i -> NBTWorld.getCompound(CraftBlockData.fromData(i)),
i -> ((CraftBlockData) NBTWorld.getBlockData(i)).getState());
}
@Override
public void injectBiomesFromMantle(Chunk e, Mantle mantle) {
ChunkAccess chunk = ((CraftChunk) e).getHandle(ChunkStatus.FULL);
AtomicInteger c = new AtomicInteger();
AtomicInteger r = new AtomicInteger();
mantle.iterateChunk(e.getX(), e.getZ(), MatterBiomeInject.class, (x, y, z, b) -> {
if (b != null) {
if (b.isCustom()) {
chunk.setBiome(x, y, z, getCustomBiomeRegistry().getHolder(b.getBiomeId()).get());
c.getAndIncrement();
} else {
chunk.setBiome(x, y, z, (Holder<net.minecraft.world.level.biome.Biome>) getBiomeBase(e.getWorld(), b.getBiome()));
r.getAndIncrement();
}
}
});
}
public ItemStack applyCustomNbt(ItemStack itemStack, KMap<String, Object> customNbt) throws IllegalArgumentException {
if (customNbt != null && !customNbt.isEmpty()) {
net.minecraft.world.item.ItemStack s = CraftItemStack.asNMSCopy(itemStack);
try {
net.minecraft.nbt.CompoundTag tag = TagParser.parseTag((new JSONObject(customNbt)).toString());
tag.merge(s.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).getUnsafe());
s.set(DataComponents.CUSTOM_DATA, CustomData.of(tag));
} catch (CommandSyntaxException var5) {
throw new IllegalArgumentException(var5);
}
return CraftItemStack.asBukkitCopy(s);
} else {
return itemStack;
}
}
public void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos) {
CraftDolphin cd = (CraftDolphin)dolphin;
cd.getHandle().setTreasurePos(new BlockPos(pos.getX(), pos.getY(), pos.getZ()));
cd.getHandle().setGotFish(true);
}
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
ServerLevel serverLevel = ((CraftWorld)world).getHandle();
Class<?> clazz = serverLevel.getChunkSource().chunkMap.generator.getClass();
Field biomeSource = getField(clazz, BiomeSource.class);
biomeSource.setAccessible(true);
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unsafeField.get(null);
CustomBiomeSource customBiomeSource = new CustomBiomeSource(seed, engine, world);
unsafe.putObject(biomeSource.get(serverLevel.getChunkSource().chunkMap.generator), unsafe.objectFieldOffset(biomeSource), customBiomeSource);
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
Field[] fields = EntityType.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) && field.getType().equals(EntityType.class)) {
try {
EntityType entityType = (EntityType) field.get(null);
if (entityType.getDescriptionId().equals("entity.minecraft." + entity.name().toLowerCase())) {
Vector<Float> v1 = new Vector<>();
v1.add(entityType.getHeight());
entityType.getDimensions();
Vector3d box = new Vector3d( entityType.getWidth(), entityType.getHeight(), entityType.getWidth());
//System.out.println("Entity Type: " + entityType.getDescriptionId() + ", " + "Height: " + height + ", Width: " + width);
return box;
}
} catch (IllegalAccessException e) {
Iris.error("Unable to get entity dimensions!");
e.printStackTrace();
}
}
}
return null;
}
@Override
public Entity spawnEntity(Location location, org.bukkit.entity.EntityType type, CreatureSpawnEvent.SpawnReason reason) {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(fieldType))
return f;
}
throw new NoSuchFieldException(fieldType.getName());
} catch (NoSuchFieldException var4) {
Class<?> superClass = clazz.getSuperclass();
if (superClass == null) {
throw var4;
} else {
return getField(superClass, fieldType);
}
}
}
public static Holder<net.minecraft.world.level.biome.Biome> biomeToBiomeBase(Registry<net.minecraft.world.level.biome.Biome> registry, Biome biome) {
return registry.getHolderOrThrow(ResourceKey.create(Registries.BIOME, CraftNamespacedKey.toMinecraft(biome.getKey())));
}
@Override
public DataVersion getDataVersion() {
return DataVersion.V1205;
}
}

Some files were not shown because too many files have changed in this diff Show More