mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-04-05 07:16:22 +00:00
@@ -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!
|
||||
|
||||
|
||||
66
build.gradle
66
build.gradle
@@ -21,12 +21,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.2.6-1.19.2-1.20.4'
|
||||
def specialSourceVersion = '1.11.0' //[NMS]
|
||||
def specialSourceVersion = '1.11.4' //[NMS]
|
||||
|
||||
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
||||
// ======================== WINDOWS =============================
|
||||
@@ -43,8 +43,8 @@ registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/serve
|
||||
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",
|
||||
@@ -52,11 +52,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'
|
||||
|
||||
@@ -65,9 +69,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")
|
||||
@@ -82,6 +87,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() {
|
||||
@@ -99,6 +120,7 @@ NMS_BINDINGS.each {
|
||||
if (!buildToolsHint.exists()) {
|
||||
buildToolsFolder.mkdirs()
|
||||
project.javaexec {
|
||||
executable = launcher.executablePath
|
||||
classpath = files(buildToolsJar)
|
||||
workingDir = buildToolsFolder
|
||||
args = [
|
||||
@@ -108,16 +130,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
|
||||
@@ -137,6 +157,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"))
|
||||
@@ -151,10 +172,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"))
|
||||
@@ -168,6 +193,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 {
|
||||
@@ -182,6 +210,10 @@ NMS_BINDINGS.each {
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
NMS_BINDINGS.each {
|
||||
dependsOn(":nms:${it.key}:build")
|
||||
from("${project(":nms:${it.key}").layout.buildDirectory.asFile.get()}/libs/${it.key}.jar")
|
||||
}
|
||||
NMS_BINDINGS.each {dependsOn(":nms:${it.key}:build")}
|
||||
dependsOn(':com.volmit.gui:build')
|
||||
|
||||
@@ -195,9 +227,6 @@ shadowJar {
|
||||
|
||||
dependencies {
|
||||
implementation project(':core')
|
||||
NMS_BINDINGS.each {
|
||||
implementation project(":nms:${it.key}")
|
||||
}
|
||||
}
|
||||
|
||||
configurations.configureEach {
|
||||
@@ -230,7 +259,6 @@ allprojects {
|
||||
|
||||
dependencies {
|
||||
// Provided or Classpath
|
||||
// implementation project(':com.volmit.gui')
|
||||
compileOnly 'org.projectlombok:lombok:1.18.24'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.24'
|
||||
|
||||
@@ -240,6 +268,8 @@ allprojects {
|
||||
implementation "net.kyori:adventure-text-minimessage:4.13.1"
|
||||
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
|
||||
@@ -289,8 +319,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)
|
||||
}
|
||||
|
||||
@@ -313,7 +343,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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'
|
||||
@@ -35,6 +35,7 @@ compileJava {
|
||||
|
||||
repositories {
|
||||
maven { url 'https://nexus.phoenixdevt.fr/repository/maven-public/'}
|
||||
maven { url 'https://repo.auxilor.io/repository/maven-public/' }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,6 +67,7 @@ dependencies {
|
||||
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')
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ import java.lang.management.OperatingSystemMXBean;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -457,7 +458,6 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
instance = this;
|
||||
InitializeSafeguard();
|
||||
ByteBuddyAgent.install();
|
||||
boolean configured;
|
||||
services = new KMap<>();
|
||||
setupAudience();
|
||||
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
|
||||
@@ -473,7 +473,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
configWatcher = new FileWatcher(getDataFile("settings.json"));
|
||||
services.values().forEach(IrisService::onEnable);
|
||||
services.values().forEach(this::registerListener);
|
||||
configured = ServerConfigurator.postConfigure();
|
||||
installMainDimension();
|
||||
if (!IrisSafeguard.instance.acceptUnstable && IrisSafeguard.instance.unstablemode) {
|
||||
Iris.info(C.RED + "World loading has been disabled until the incompatibility is resolved.");
|
||||
Iris.info(C.DARK_RED + "Alternatively, go to plugins/iris/settings.json and set ignoreBootMode to true.");
|
||||
@@ -486,7 +486,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
J.ar(this::checkConfigHotload, 60);
|
||||
J.sr(this::tickQueue, 0);
|
||||
J.s(this::setupPapi);
|
||||
if (!configured) J.a(ServerConfigurator::configure, 20);
|
||||
J.a(ServerConfigurator::configure, 20);
|
||||
splash();
|
||||
UtilsSFG.splash();
|
||||
autoStartStudio();
|
||||
@@ -686,6 +686,48 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
s.sendMessage(C.IRIS + "[" + C.DARK_GRAY + "Iris" + C.IRIS + "]" + C.GRAY + ": " + msg);
|
||||
}
|
||||
|
||||
private void installMainDimension() {
|
||||
try {
|
||||
Properties props = new Properties();
|
||||
props.load(new FileInputStream("server.properties"));
|
||||
String world = props.getProperty("level-name");
|
||||
if (world == null) return;
|
||||
|
||||
FileConfiguration fc = new YamlConfiguration();
|
||||
fc.load(new File("bukkit.yml"));
|
||||
String id = fc.getString("worlds." + world + ".generator");
|
||||
if (id.startsWith("Iris:")) {
|
||||
id = id.split("\\Q:\\E")[1];
|
||||
} else if (id.equalsIgnoreCase("Iris")) {
|
||||
id = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
IrisDimension dim;
|
||||
if (id == null || id.isEmpty()) {
|
||||
dim = IrisData.loadAnyDimension(IrisSettings.get().getGenerator().getDefaultWorldType());
|
||||
} else {
|
||||
dim = IrisData.loadAnyDimension(id);
|
||||
}
|
||||
|
||||
File w = new File(Bukkit.getWorldContainer(), world);
|
||||
File packFolder = new File(w, "/iris/pack");
|
||||
if (!packFolder.exists() || packFolder.listFiles().length == 0) {
|
||||
packFolder.mkdirs();
|
||||
service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w);
|
||||
}
|
||||
if (packFolder.exists()) {
|
||||
IrisDimension worldDim = IrisData.get(packFolder).getDimensionLoader().load(id);
|
||||
if (worldDim != null) dim = worldDim;
|
||||
}
|
||||
|
||||
INMS.get().registerDimension("overworld", dim);
|
||||
} catch (Throwable e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BiomeProvider getDefaultBiomeProvider(@NotNull String worldName, @Nullable String id) {
|
||||
|
||||
@@ -19,33 +19,15 @@
|
||||
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.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;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.bukkit.Bukkit.getServer;
|
||||
|
||||
public class ServerConfigurator {
|
||||
public static void configure() {
|
||||
IrisSettings.IrisSettingsAutoconfiguration s = IrisSettings.get().getAutoConfiguration();
|
||||
@@ -56,16 +38,6 @@ public class ServerConfigurator {
|
||||
if (s.isConfigurePaperWatchdogDelay()) {
|
||||
J.attempt(ServerConfigurator::increasePaperWatchdog);
|
||||
}
|
||||
|
||||
installDataPacks(true);
|
||||
}
|
||||
|
||||
public static boolean postConfigure() {
|
||||
if(postVerifyDataPacks(true)) {
|
||||
configure();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void increaseKeepAliveSpigot() throws IOException, InvalidConfigurationException {
|
||||
@@ -81,6 +53,7 @@ public class ServerConfigurator {
|
||||
f.save(spigotConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private static void increasePaperWatchdog() throws IOException, InvalidConfigurationException {
|
||||
File spigotConfig = new File("config/paper-global.yml");
|
||||
FileConfiguration f = new YamlConfiguration();
|
||||
@@ -94,191 +67,4 @@ public class ServerConfigurator {
|
||||
f.save(spigotConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<File> getDatapacksFolder() {
|
||||
if (!IrisSettings.get().getGeneral().forceMainWorld.isEmpty()) {
|
||||
return new KList<File>().qadd(new File(Bukkit.getWorldContainer(), IrisSettings.get().getGeneral().forceMainWorld + "/datapacks"));
|
||||
}
|
||||
KList<File> worlds = new KList<>();
|
||||
Bukkit.getServer().getWorlds().forEach(w -> worlds.add(new File(w.getWorldFolder(), "datapacks")));
|
||||
if (worlds.isEmpty()) {
|
||||
worlds.add(new File(getMainWorldFolder(), "datapacks"));
|
||||
}
|
||||
return worlds;
|
||||
}
|
||||
|
||||
private static File getMainWorldFolder() {
|
||||
try {
|
||||
Properties prop = new Properties();
|
||||
prop.load(new FileInputStream("server.properties"));
|
||||
String world = prop.getProperty("level-name");
|
||||
return new File(Bukkit.getWorldContainer(), world);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean postVerifyDataPacks(boolean fast) {
|
||||
try {
|
||||
File datapacksFolder = new File(getMainWorldFolder(), "datapacks");
|
||||
File IrisDatapacks = new File(datapacksFolder, "iris");
|
||||
if (!datapacksFolder.exists() || !IrisDatapacks.exists()) {
|
||||
return (true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void installDataPacks(boolean fullInstall) {
|
||||
Iris.info("Checking Data Packs...");
|
||||
File packs = new File("plugins/Iris/packs");
|
||||
if (packs.exists()) {
|
||||
for (File i : packs.listFiles()) {
|
||||
if (i.isDirectory()) {
|
||||
Iris.verbose("Checking Pack: " + i.getPath());
|
||||
IrisData data = IrisData.get(i);
|
||||
File dims = new File(i, "dimensions");
|
||||
|
||||
if (dims.exists()) {
|
||||
for (File j : dims.listFiles()) {
|
||||
if (j.getName().endsWith(".json")) {
|
||||
IrisDimension dim = data.getDimensionLoader().load(j.getName().split("\\Q.\\E")[0]);
|
||||
|
||||
if (dim == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
|
||||
for (File dpack : getDatapacksFolder()) {
|
||||
dim.installDataPack(() -> data, dpack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Iris.info("Data Packs Setup!");
|
||||
|
||||
if (fullInstall)
|
||||
verifyDataPacksPost(IrisSettings.get().getAutoConfiguration().isAutoRestartOnCustomBiomeInstall());
|
||||
}
|
||||
|
||||
private static void verifyDataPacksPost(boolean allowRestarting) {
|
||||
File packs = new File("plugins/Iris/packs");
|
||||
|
||||
boolean bad = false;
|
||||
if (packs.exists()) {
|
||||
for (File i : packs.listFiles()) {
|
||||
if (i.isDirectory()) {
|
||||
Iris.verbose("Checking Pack: " + i.getPath());
|
||||
IrisData data = IrisData.get(i);
|
||||
File dims = new File(i, "dimensions");
|
||||
|
||||
if (dims.exists()) {
|
||||
for (File j : dims.listFiles()) {
|
||||
if (j.getName().endsWith(".json")) {
|
||||
IrisDimension dim = data.getDimensionLoader().load(j.getName().split("\\Q.\\E")[0]);
|
||||
|
||||
if (dim == null) {
|
||||
Iris.error("Failed to load " + j.getPath() + " ");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!verifyDataPackInstalled(dim)) {
|
||||
bad = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bad) {
|
||||
// Iris.info("");
|
||||
Iris.info( "Hotloading all Datapacks!");
|
||||
if (INMS.get().supportsDataPacks()) {
|
||||
for (File folder : getDatapacksFolder()) {
|
||||
INMS.get().loadDatapack(folder, false);
|
||||
}
|
||||
Iris.info("Datapacks Hotloaded!");
|
||||
Iris.info(C.YELLOW + "============================================================================");
|
||||
Iris.info(C.ITALIC + "" + C.YELLOW + "To ensure the stability of custom biome generation, a server restart is necessary.");
|
||||
Iris.info(C.ITALIC + "" + C.YELLOW + "While datapacks have been hotloaded, a complete restart is advised.");
|
||||
Iris.info(C.YELLOW + "----------------------------------------------------------------------------");
|
||||
Iris.info(C.UNDERLINE + "" + C.YELLOW + "IT IS HIGHLY RECOMMENDED YOU RESTART THE SERVER BEFORE GENERATING!");
|
||||
Iris.info(C.YELLOW + "============================================================================");
|
||||
|
||||
for (Player i : Bukkit.getOnlinePlayers()) {
|
||||
if (i.isOp() || i.hasPermission("iris.all")) {
|
||||
VolmitSender sender = new VolmitSender(i, Iris.instance.getTag("WARNING"));
|
||||
sender.sendMessage("There are some Iris Packs that have custom biomes in them");
|
||||
sender.sendMessage("You need to restart your server to use these packs.");
|
||||
}
|
||||
}
|
||||
|
||||
J.sleep(3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void restart() {
|
||||
J.s(() -> {
|
||||
Iris.warn("New data pack entries have been installed in Iris! Restarting server!");
|
||||
Iris.warn("This will only happen when your pack changes (updates/first time setup)");
|
||||
Iris.warn("(You can disable this auto restart in iris settings)");
|
||||
J.s(() -> {
|
||||
Iris.warn("Looks like the restart command didn't work. Stopping the server instead!");
|
||||
Bukkit.shutdown();
|
||||
}, 100);
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "restart");
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean verifyDataPackInstalled(IrisDimension dimension) {
|
||||
IrisData idm = IrisData.get(Iris.instance.getDataFolder("packs", dimension.getLoadKey()));
|
||||
KSet<String> keys = new KSet<>();
|
||||
boolean warn = false;
|
||||
|
||||
for (IrisBiome i : dimension.getAllBiomes(() -> idm)) {
|
||||
if (i.isCustom()) {
|
||||
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
|
||||
keys.add(dimension.getLoadKey() + ":" + j.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!INMS.get().supportsDataPacks()) {
|
||||
if (!keys.isEmpty()) {
|
||||
Iris.warn("===================================================================================");
|
||||
Iris.warn("Pack " + dimension.getLoadKey() + " has " + keys.size() + " custom biome(s). ");
|
||||
Iris.warn("Your server version does not yet support datapacks for iris.");
|
||||
Iris.warn("The world will generate these biomes as backup biomes.");
|
||||
Iris.warn("====================================================================================");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
for (String i : keys) {
|
||||
Object o = INMS.get().getCustomBiomeBaseFor(i);
|
||||
|
||||
if (o == null) {
|
||||
Iris.warn("The Biome " + i + " is not registered on the server.");
|
||||
warn = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (warn) {
|
||||
Iris.error("The Pack " + dimension.getLoadKey() + " is INCAPABLE of generating custom biomes");
|
||||
Iris.error("Queued for Datapack Hotload.");
|
||||
}
|
||||
|
||||
return !warn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,10 @@
|
||||
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;
|
||||
@@ -152,10 +154,12 @@ public class CommandDeveloper implements DecreeExecutor {
|
||||
@Param(description = "The pack to bench", aliases = {"pack"})
|
||||
IrisDimension dimension,
|
||||
@Param(description = "Headless", defaultValue = "false")
|
||||
boolean headless
|
||||
boolean headless,
|
||||
@Param(description = "GUI", defaultValue = "false")
|
||||
boolean gui
|
||||
) {
|
||||
Iris.info("test");
|
||||
IrisPackBenchmarking benchmark = new IrisPackBenchmarking(dimension, 1, headless);
|
||||
IrisPackBenchmarking benchmark = new IrisPackBenchmarking(dimension, 1, headless, gui);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,9 @@ 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.safeguard.IrisSafeguard;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -20,21 +20,16 @@ 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.gui.NoiseExplorerGUI;
|
||||
import com.volmit.iris.core.gui.VisionGUI;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
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.IrisNoiseBenchmark;
|
||||
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.engine.platform.studio.StudioGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
@@ -43,30 +38,23 @@ 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.function.Function2;
|
||||
import com.volmit.iris.util.function.NoiseProvider;
|
||||
import com.volmit.iris.util.interpolation.InterpolationMethod;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONArray;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.math.Spiraler;
|
||||
import com.volmit.iris.util.noise.CNG;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.O;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.util.BlockVector;
|
||||
@@ -85,7 +73,6 @@ import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
|
||||
@@ -286,7 +273,7 @@ public class CommandStudio implements DecreeExecutor {
|
||||
}
|
||||
|
||||
@Decree(description = "Hotload a studio", aliases = {"reload", "h"})
|
||||
public void hotload(@Param(defaultValue = "false") boolean reloadDataPack) {
|
||||
public void hotload() {
|
||||
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
|
||||
sender().sendMessage(C.RED + "No studio world open!");
|
||||
return;
|
||||
@@ -294,15 +281,6 @@ public class CommandStudio implements DecreeExecutor {
|
||||
var provider = Iris.service(StudioSVC.class).getActiveProject().getActiveProvider();
|
||||
provider.getEngine().hotload();
|
||||
sender().sendMessage(C.GREEN + "Hotloaded");
|
||||
if (reloadDataPack) {
|
||||
var world = provider.getTarget().getWorld().realWorld();
|
||||
if (world == null) {
|
||||
sender().sendMessage(C.RED + "Failed to reload datapacks.");
|
||||
return;
|
||||
}
|
||||
boolean success = INMS.get().loadDatapack(new File(world.getWorldFolder(), "datapacks"), true);
|
||||
sender().sendMessage(success ? C.GREEN + "Reloaded datapacks." : C.RED + "Failed to reload datapacks.");
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Show loot if a chest were right here", origin = DecreeOrigin.PLAYER, sync = true)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -9,9 +9,9 @@ import java.io.Closeable;
|
||||
|
||||
public interface IHeadless extends Closeable {
|
||||
|
||||
void saveAll();
|
||||
void save();
|
||||
|
||||
@RegionCoordinates
|
||||
@ChunkCoordinates
|
||||
boolean exists(int x, int z);
|
||||
|
||||
@RegionCoordinates
|
||||
|
||||
@@ -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!");
|
||||
|
||||
@@ -18,11 +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.engine.object.IrisBiomeCustom;
|
||||
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.documentation.RegionCoordinates;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Vector3d;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||
@@ -40,8 +41,6 @@ import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface INMSBinding {
|
||||
boolean hasTile(Location l);
|
||||
|
||||
@@ -115,10 +114,14 @@ public interface INMSBinding {
|
||||
|
||||
Entity spawnEntity(Location location, EntityType type, CreatureSpawnEvent.SpawnReason reason);
|
||||
|
||||
boolean loadDatapack(File datapackFolder, boolean replace);
|
||||
default DataVersion getDataVersion() {
|
||||
return DataVersion.V1192;
|
||||
}
|
||||
|
||||
boolean registerDimension(String name, IrisDimension dimension);
|
||||
|
||||
boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace);
|
||||
|
||||
void injectBukkit();
|
||||
|
||||
default IHeadless createHeadless(Engine engine) {
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMSBinding;
|
||||
import com.volmit.iris.core.nms.container.BlockPos;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
@@ -108,12 +109,12 @@ public class NMSBinding1X implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadDatapack(File datapackFolder, boolean replace) {
|
||||
public boolean registerDimension(String name, IrisDimension dimension) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerDimension(String name, IrisDimension dimension) {
|
||||
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,11 +82,8 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
private void completeChunk(int x, int z, PregenListener listener) {
|
||||
try {
|
||||
future.add(PaperLib.getChunkAtAsync(world, x, z, true).thenApply((i) -> {
|
||||
if (i == null) {
|
||||
|
||||
}
|
||||
Chunk c = Bukkit.getWorld(world.getUID()).getChunkAt(x, z);
|
||||
lastUse.put(c, M.ms());
|
||||
if (i == null) return 0;
|
||||
lastUse.put(i, M.ms());
|
||||
listener.onChunkGenerated(x, z);
|
||||
listener.onChunkCleaned(x, z);
|
||||
return 0;
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
package com.volmit.iris.core.pregenerator.methods;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.IHeadless;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class HeadlessPregenMethod implements PregeneratorMethod {
|
||||
private final Engine engine;
|
||||
private final IHeadless headless;
|
||||
private final MultiBurst burst;
|
||||
private final KList<Future<?>> futures;
|
||||
private final Semaphore semaphore;
|
||||
private final int max;
|
||||
|
||||
public HeadlessPregenMethod(Engine engine) {
|
||||
this.max = IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism());
|
||||
this.engine = engine;
|
||||
this.headless = INMS.get().createHeadless(engine);
|
||||
this.burst = new MultiBurst("Iris Headless", Thread.MAX_PRIORITY);
|
||||
this.futures = new KList<>();
|
||||
this.semaphore = new Semaphore(max);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -32,9 +31,10 @@ public class HeadlessPregenMethod implements PregeneratorMethod {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
waitForChunksPartial(0);
|
||||
burst.close();
|
||||
headless.saveAll();
|
||||
try {
|
||||
semaphore.acquire(max);
|
||||
} catch (InterruptedException ignored) {}
|
||||
headless.save();
|
||||
try {
|
||||
headless.close();
|
||||
} catch (IOException e) {
|
||||
@@ -45,7 +45,7 @@ public class HeadlessPregenMethod implements PregeneratorMethod {
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
headless.saveAll();
|
||||
headless.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,34 +63,25 @@ public class HeadlessPregenMethod implements PregeneratorMethod {
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
futures.removeIf(Future::isDone);
|
||||
waitForChunksPartial(512);
|
||||
futures.add(burst.complete(() -> {
|
||||
listener.onChunkGenerating(x, z);
|
||||
headless.generateChunk(x, z);
|
||||
listener.onChunkGenerated(x, z);
|
||||
}));
|
||||
try {
|
||||
semaphore.acquire();
|
||||
} catch (InterruptedException ignored) {
|
||||
semaphore.release();
|
||||
return;
|
||||
}
|
||||
MultiBurst.burst.complete(() -> {
|
||||
try {
|
||||
listener.onChunkGenerating(x, z);
|
||||
headless.generateChunk(x, z);
|
||||
listener.onChunkGenerated(x, z);
|
||||
} finally {
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mantle getMantle() {
|
||||
return engine.getMantle().getMantle();
|
||||
}
|
||||
|
||||
private void waitForChunksPartial(int maxWaiting) {
|
||||
futures.removeWhere(Objects::isNull);
|
||||
while (futures.size() > maxWaiting) {
|
||||
try {
|
||||
Future<?> i = futures.remove(0);
|
||||
|
||||
if (i == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
i.get();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,8 +119,7 @@ public class MedievalPregenMethod implements PregeneratorMethod {
|
||||
|
||||
listener.onChunkGenerating(x, z);
|
||||
futures.add(J.sfut(() -> {
|
||||
world.getChunkAt(x, z);
|
||||
Chunk c = Bukkit.getWorld(world.getUID()).getChunkAt(x, z);
|
||||
Chunk c = world.getChunkAt(x, z);
|
||||
lastUse.put(c, M.ms());
|
||||
listener.onChunkGenerated(x, z);
|
||||
listener.onChunkCleaned(x, z);
|
||||
|
||||
@@ -15,6 +15,7 @@ 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;
|
||||
|
||||
@@ -81,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++;
|
||||
|
||||
@@ -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.4");
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,10 @@ public class ExternalDataSVC implements IrisService {
|
||||
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()) {
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
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.pack.IrisPack;
|
||||
import com.volmit.iris.core.project.IrisProject;
|
||||
@@ -296,7 +295,6 @@ public class StudioSVC implements IrisService {
|
||||
}
|
||||
|
||||
sender.sendMessage("Successfully Aquired " + d.getName());
|
||||
ServerConfigurator.installDataPacks(true);
|
||||
}
|
||||
|
||||
public KMap<String, String> getListing(boolean cached) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,10 @@ package com.volmit.iris.core.tools;
|
||||
import com.google.common.util.concurrent.AtomicDouble;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.ServerConfigurator;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
|
||||
import com.volmit.iris.core.safeguard.UtilsSFG;
|
||||
import com.volmit.iris.util.exceptions.IrisException;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
@@ -144,7 +141,6 @@ public class IrisCreator {
|
||||
.studio(studio)
|
||||
.smartVanillaHeight(smartVanillaHeight)
|
||||
.create();
|
||||
ServerConfigurator.installDataPacks(false);
|
||||
|
||||
access = (PlatformChunkGenerator) wc.generator();
|
||||
PlatformChunkGenerator finalAccess1 = access;
|
||||
|
||||
@@ -45,15 +45,17 @@ public class IrisPackBenchmarking {
|
||||
private IrisDimension IrisDimension;
|
||||
private int radius;
|
||||
private final boolean headless;
|
||||
private final boolean gui;
|
||||
private boolean finished = false;
|
||||
private Engine engine;
|
||||
PrecisionStopwatch stopwatch;
|
||||
|
||||
public IrisPackBenchmarking(IrisDimension dimension, int r, boolean headless) {
|
||||
public IrisPackBenchmarking(IrisDimension dimension, int r, boolean headless, boolean gui) {
|
||||
instance = this;
|
||||
this.IrisDimension = dimension;
|
||||
this.radius = r;
|
||||
this.headless = headless;
|
||||
this.gui = gui;
|
||||
runBenchmark();
|
||||
}
|
||||
|
||||
@@ -153,7 +155,7 @@ public class IrisPackBenchmarking {
|
||||
return new IrisEngine(new EngineTarget(world, dim, data), false);
|
||||
}
|
||||
return IrisToolbelt.access(IrisToolbelt.createWorld()
|
||||
.dimension(IrisDimension.getName())
|
||||
.dimension(IrisDimension.getLoadKey())
|
||||
.name("benchmark")
|
||||
.seed(1337)
|
||||
.studio(false)
|
||||
@@ -169,7 +171,7 @@ public class IrisPackBenchmarking {
|
||||
int z = 0;
|
||||
IrisToolbelt.pregenerate(PregenTask
|
||||
.builder()
|
||||
.gui(false)
|
||||
.gui(gui)
|
||||
.center(new Position2(x, z))
|
||||
.width(5)
|
||||
.height(5)
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -21,8 +21,6 @@ package com.volmit.iris.engine;
|
||||
import com.google.common.util.concurrent.AtomicDouble;
|
||||
import com.google.gson.Gson;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.ServerConfigurator;
|
||||
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
|
||||
import com.volmit.iris.core.gui.PregeneratorJob;
|
||||
import com.volmit.iris.core.nms.container.BlockPos;
|
||||
@@ -53,7 +51,6 @@ import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -66,8 +63,6 @@ import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(exclude = "context")
|
||||
@@ -242,11 +237,6 @@ public class IrisEngine implements Engine {
|
||||
getTarget().setDimension(getData().getDimensionLoader().load(getDimension().getLoadKey()));
|
||||
prehotload();
|
||||
setupEngine();
|
||||
J.a(() -> {
|
||||
synchronized (ServerConfigurator.class) {
|
||||
ServerConfigurator.installDataPacks(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
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";
|
||||
@@ -155,7 +158,7 @@ public class IrisBiomeCustom {
|
||||
j.put("spawners", spawners);
|
||||
}
|
||||
|
||||
return j.toString(4);
|
||||
return DataVersion.getDefault().fixCustomBiome(this, j).toString(4);
|
||||
}
|
||||
|
||||
private int parseColor(String c) {
|
||||
|
||||
@@ -18,17 +18,12 @@
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||
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.collection.KList;
|
||||
import com.volmit.iris.util.data.DataProvider;
|
||||
import com.volmit.iris.util.data.Dimension;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
@@ -43,10 +38,6 @@ import org.bukkit.Material;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@@ -380,56 +371,6 @@ public class IrisDimension extends IrisRegistrant {
|
||||
return landBiomeStyle;
|
||||
}
|
||||
|
||||
public boolean installDataPack(DataProvider data, File datapacks) {
|
||||
boolean write = false;
|
||||
boolean changed = false;
|
||||
|
||||
IO.delete(new File(datapacks, "iris/data/" + getLoadKey().toLowerCase()));
|
||||
|
||||
for (IrisBiome i : getAllBiomes(data)) {
|
||||
if (i.isCustom()) {
|
||||
write = true;
|
||||
|
||||
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
|
||||
File output = new File(datapacks, "iris/data/" + getLoadKey().toLowerCase() + "/worldgen/biome/" + j.getId() + ".json");
|
||||
|
||||
if (!output.exists()) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
Iris.verbose(" Installing Data Pack Biome: " + output.getPath());
|
||||
output.getParentFile().mkdirs();
|
||||
try {
|
||||
IO.writeAll(output, j.generateJson());
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (write) {
|
||||
File mcm = new File(datapacks, "iris/pack.mcmeta");
|
||||
try {
|
||||
IO.writeAll(mcm, """
|
||||
{
|
||||
"pack": {
|
||||
"description": "Iris Data Pack. This pack contains all installed Iris Packs' resources.",
|
||||
"pack_format": 10
|
||||
}
|
||||
}
|
||||
""");
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
Iris.verbose(" Installing Data Pack MCMeta: " + mcm.getPath());
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFolderName() {
|
||||
return "dimensions";
|
||||
|
||||
@@ -29,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;
|
||||
@@ -65,6 +66,7 @@ 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;
|
||||
@@ -386,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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Data
|
||||
public class IrisBlockData implements BlockData{
|
||||
public class IrisBlockData implements BlockData {
|
||||
private final @NonNull BlockData base;
|
||||
private final @NotNull Identifier custom;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
12
core/src/main/java/com/volmit/iris/util/misc/E.java
Normal file
12
core/src/main/java/com/volmit/iris/util/misc/E.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -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
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_19_R1;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
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.IrisBiome;
|
||||
@@ -11,6 +12,7 @@ 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.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
@@ -25,6 +27,7 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class CustomBiomeSource extends BiomeSource {
|
||||
private final long seed;
|
||||
@@ -118,8 +121,28 @@ public class CustomBiomeSource extends BiomeSource {
|
||||
for (IrisBiome i : engine.getAllBiomes()) {
|
||||
if (i.isCustom()) {
|
||||
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
|
||||
m.put(j.getId(), customRegistry.getHolder(customRegistry.getResourceKey(customRegistry
|
||||
.get(new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()))).get()).get());
|
||||
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
|
||||
Biome biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
INMS.get().registerBiome(location.getNamespace(), j, false);
|
||||
biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
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<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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,9 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -26,9 +23,9 @@ import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
@@ -587,51 +584,10 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadDatapack(File folder, boolean replace) {
|
||||
var data = new File(folder, "iris/data");
|
||||
if (!data.exists() || !data.isDirectory()) return false;
|
||||
FilenameFilter jsonFilter = (dir, name) -> new File(dir, name).isFile() && name.toLowerCase().endsWith(".json");
|
||||
|
||||
var files = data.listFiles((dir, name) -> new File(dir, name).isDirectory());
|
||||
if (files == null) return false;
|
||||
for (File file : files) {
|
||||
var biome = new File(file, "worldgen/biome");
|
||||
if (!biome.exists()) continue;
|
||||
var biomeFiles = biome.listFiles(jsonFilter);
|
||||
if (biomeFiles == null) continue;
|
||||
for (File biomeFile : biomeFiles) {
|
||||
String json = null;
|
||||
int tries = 10;
|
||||
while (json == null && tries-- > 0) {
|
||||
try {
|
||||
json = IO.readAll(biomeFile);
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to read biome " + file.getName() + ":" + biomeFile.getName() + " tries left: " + tries);
|
||||
if (tries == 0) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
if (json == null) continue;
|
||||
|
||||
try {
|
||||
var value = decode(net.minecraft.world.level.biome.Biome.CODEC, json).map(Holder::value).orElse(null);
|
||||
register(Registry.BIOME_REGISTRY, from(file.getName(), biomeFile), value, replace);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to register biome " + file.getName() + ":" + biomeFile.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private ResourceLocation from(String namespace, File file) {
|
||||
var name = file.getName();
|
||||
return new ResourceLocation(namespace, name.substring(0, name.lastIndexOf('.')));
|
||||
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
|
||||
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
|
||||
if (biomeBase == null) return false;
|
||||
return register(Registry.BIOME_REGISTRY, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
|
||||
}
|
||||
|
||||
private <T> Optional<T> decode(Codec<T> codec, String json) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_19_R2;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
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.IrisBiome;
|
||||
@@ -12,6 +13,7 @@ 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;
|
||||
@@ -26,6 +28,7 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class CustomBiomeSource extends BiomeSource {
|
||||
|
||||
@@ -120,8 +123,28 @@ public class CustomBiomeSource extends BiomeSource {
|
||||
for (IrisBiome i : engine.getAllBiomes()) {
|
||||
if (i.isCustom()) {
|
||||
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
|
||||
m.put(j.getId(), customRegistry.getHolder(customRegistry.getResourceKey(customRegistry
|
||||
.get(new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()))).get()).get());
|
||||
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
|
||||
Biome biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
INMS.get().registerBiome(location.getNamespace(), j, false);
|
||||
biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,9 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -26,9 +23,9 @@ import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
@@ -589,51 +586,10 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadDatapack(File folder, boolean replace) {
|
||||
var data = new File(folder, "iris/data");
|
||||
if (!data.exists() || !data.isDirectory()) return false;
|
||||
FilenameFilter jsonFilter = (dir, name) -> new File(dir, name).isFile() && name.toLowerCase().endsWith(".json");
|
||||
|
||||
var files = data.listFiles((dir, name) -> new File(dir, name).isDirectory());
|
||||
if (files == null) return false;
|
||||
for (File file : files) {
|
||||
var biome = new File(file, "worldgen/biome");
|
||||
if (!biome.exists()) continue;
|
||||
var biomeFiles = biome.listFiles(jsonFilter);
|
||||
if (biomeFiles == null) continue;
|
||||
for (File biomeFile : biomeFiles) {
|
||||
String json = null;
|
||||
int tries = 10;
|
||||
while (json == null && tries-- > 0) {
|
||||
try {
|
||||
json = IO.readAll(biomeFile);
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to read biome " + file.getName() + ":" + biomeFile.getName() + " tries left: " + tries);
|
||||
if (tries == 0) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
if (json == null) continue;
|
||||
|
||||
try {
|
||||
var value = decode(net.minecraft.world.level.biome.Biome.CODEC, json).map(Holder::value).orElse(null);
|
||||
register(Registries.BIOME, from(file.getName(), biomeFile), value, replace);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to register biome " + file.getName() + ":" + biomeFile.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private ResourceLocation from(String namespace, File file) {
|
||||
var name = file.getName();
|
||||
return new ResourceLocation(namespace, name.substring(0, name.lastIndexOf('.')));
|
||||
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
|
||||
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
|
||||
if (biomeBase == null) return false;
|
||||
return register(Registries.BIOME, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
|
||||
}
|
||||
|
||||
private <T> Optional<T> decode(Codec<T> codec, String json) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_19_R3;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
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.IrisBiome;
|
||||
@@ -125,8 +126,16 @@ public class CustomBiomeSource extends BiomeSource {
|
||||
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);
|
||||
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
|
||||
Biome biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
INMS.get().registerBiome(location.getNamespace(), j, false);
|
||||
biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
|
||||
if (optionalBiomeKey.isEmpty()) {
|
||||
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
|
||||
|
||||
@@ -5,12 +5,9 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -26,9 +23,9 @@ import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
@@ -593,51 +590,10 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadDatapack(File folder, boolean replace) {
|
||||
var data = new File(folder, "iris/data");
|
||||
if (!data.exists() || !data.isDirectory()) return false;
|
||||
FilenameFilter jsonFilter = (dir, name) -> new File(dir, name).isFile() && name.toLowerCase().endsWith(".json");
|
||||
|
||||
var files = data.listFiles((dir, name) -> new File(dir, name).isDirectory());
|
||||
if (files == null) return false;
|
||||
for (File file : files) {
|
||||
var biome = new File(file, "worldgen/biome");
|
||||
if (!biome.exists()) continue;
|
||||
var biomeFiles = biome.listFiles(jsonFilter);
|
||||
if (biomeFiles == null) continue;
|
||||
for (File biomeFile : biomeFiles) {
|
||||
String json = null;
|
||||
int tries = 10;
|
||||
while (json == null && tries-- > 0) {
|
||||
try {
|
||||
json = IO.readAll(biomeFile);
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to read biome " + file.getName() + ":" + biomeFile.getName() + " tries left: " + tries);
|
||||
if (tries == 0) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
if (json == null) continue;
|
||||
|
||||
try {
|
||||
var value = decode(net.minecraft.world.level.biome.Biome.CODEC, json).map(Holder::value).orElse(null);
|
||||
register(Registries.BIOME, from(file.getName(), biomeFile), value, replace);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to register biome " + file.getName() + ":" + biomeFile.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private ResourceLocation from(String namespace, File file) {
|
||||
var name = file.getName();
|
||||
return new ResourceLocation(namespace, name.substring(0, name.lastIndexOf('.')));
|
||||
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
|
||||
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
|
||||
if (biomeBase == null) return false;
|
||||
return register(Registries.BIOME, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
|
||||
}
|
||||
|
||||
private <T> Optional<T> decode(Codec<T> codec, String json) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_20_R1;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
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.IrisBiome;
|
||||
@@ -125,8 +126,16 @@ public class CustomBiomeSource extends BiomeSource {
|
||||
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);
|
||||
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
|
||||
Biome biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
INMS.get().registerBiome(location.getNamespace(), j, false);
|
||||
biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
|
||||
if (optionalBiomeKey.isEmpty()) {
|
||||
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
|
||||
|
||||
@@ -12,12 +12,12 @@ 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.engine.object.IrisBiomeCustom;
|
||||
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.format.C;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.math.Vector3d;
|
||||
@@ -47,7 +47,6 @@ import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.RandomSequences;
|
||||
import net.minecraft.world.entity.EntityDimensions;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
@@ -73,9 +72,7 @@ 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.BiomeProvider;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -87,12 +84,9 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -580,51 +574,10 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadDatapack(File folder, boolean replace) {
|
||||
var data = new File(folder, "iris/data");
|
||||
if (!data.exists() || !data.isDirectory()) return false;
|
||||
FilenameFilter jsonFilter = (dir, name) -> new File(dir, name).isFile() && name.toLowerCase().endsWith(".json");
|
||||
|
||||
var files = data.listFiles((dir, name) -> new File(dir, name).isDirectory());
|
||||
if (files == null) return false;
|
||||
for (File file : files) {
|
||||
var biome = new File(file, "worldgen/biome");
|
||||
if (!biome.exists()) continue;
|
||||
var biomeFiles = biome.listFiles(jsonFilter);
|
||||
if (biomeFiles == null) continue;
|
||||
for (File biomeFile : biomeFiles) {
|
||||
String json = null;
|
||||
int tries = 10;
|
||||
while (json == null && tries-- > 0) {
|
||||
try {
|
||||
json = IO.readAll(biomeFile);
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to read biome " + file.getName() + ":" + biomeFile.getName() + " tries left: " + tries);
|
||||
if (tries == 0) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
if (json == null) continue;
|
||||
|
||||
try {
|
||||
var value = decode(net.minecraft.world.level.biome.Biome.CODEC, json).map(Holder::value).orElse(null);
|
||||
register(Registries.BIOME, from(file.getName(), biomeFile), value, replace);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to register biome " + file.getName() + ":" + biomeFile.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private ResourceLocation from(String namespace, File file) {
|
||||
var name = file.getName();
|
||||
return new ResourceLocation(namespace, name.substring(0, name.lastIndexOf('.')));
|
||||
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
|
||||
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
|
||||
if (biomeBase == null) return false;
|
||||
return register(Registries.BIOME, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
|
||||
}
|
||||
|
||||
private <T> Optional<T> decode(Codec<T> codec, String json) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_20_R2;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
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.IrisBiome;
|
||||
@@ -124,8 +125,16 @@ public class CustomBiomeSource extends BiomeSource {
|
||||
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);
|
||||
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
|
||||
Biome biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
INMS.get().registerBiome(location.getNamespace(), j, false);
|
||||
biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
|
||||
if (optionalBiomeKey.isEmpty()) {
|
||||
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
|
||||
|
||||
@@ -5,12 +5,9 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -26,9 +23,9 @@ import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
@@ -590,51 +587,10 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadDatapack(File folder, boolean replace) {
|
||||
var data = new File(folder, "iris/data");
|
||||
if (!data.exists() || !data.isDirectory()) return false;
|
||||
FilenameFilter jsonFilter = (dir, name) -> new File(dir, name).isFile() && name.toLowerCase().endsWith(".json");
|
||||
|
||||
var files = data.listFiles((dir, name) -> new File(dir, name).isDirectory());
|
||||
if (files == null) return false;
|
||||
for (File file : files) {
|
||||
var biome = new File(file, "worldgen/biome");
|
||||
if (!biome.exists()) continue;
|
||||
var biomeFiles = biome.listFiles(jsonFilter);
|
||||
if (biomeFiles == null) continue;
|
||||
for (File biomeFile : biomeFiles) {
|
||||
String json = null;
|
||||
int tries = 10;
|
||||
while (json == null && tries-- > 0) {
|
||||
try {
|
||||
json = IO.readAll(biomeFile);
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to read biome " + file.getName() + ":" + biomeFile.getName() + " tries left: " + tries);
|
||||
if (tries == 0) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
if (json == null) continue;
|
||||
|
||||
try {
|
||||
var value = decode(net.minecraft.world.level.biome.Biome.CODEC, json).map(Holder::value).orElse(null);
|
||||
register(Registries.BIOME, from(file.getName(), biomeFile), value, replace);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to register biome " + file.getName() + ":" + biomeFile.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private ResourceLocation from(String namespace, File file) {
|
||||
var name = file.getName();
|
||||
return new ResourceLocation(namespace, name.substring(0, name.lastIndexOf('.')));
|
||||
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
|
||||
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
|
||||
if (biomeBase == null) return false;
|
||||
return register(Registries.BIOME, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
|
||||
}
|
||||
|
||||
private <T> Optional<T> decode(Codec<T> codec, String json) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_20_R3;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
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.IrisBiome;
|
||||
@@ -124,8 +125,16 @@ public class CustomBiomeSource extends BiomeSource {
|
||||
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);
|
||||
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
|
||||
Biome biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
INMS.get().registerBiome(location.getNamespace(), j, false);
|
||||
biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
|
||||
if (optionalBiomeKey.isEmpty()) {
|
||||
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
|
||||
|
||||
@@ -48,7 +48,7 @@ public class Headless implements IHeadless, LevelHeightAccessor {
|
||||
private final Engine engine;
|
||||
private final RegionFileStorage storage;
|
||||
private final Queue<ProtoChunk> chunkQueue = new ArrayDeque<>();
|
||||
private final ReentrantLock manualLock = new ReentrantLock();
|
||||
private final ReentrantLock saveLock = new ReentrantLock();
|
||||
private final KMap<String, Holder<Biome>> customBiomes = new KMap<>();
|
||||
private final KMap<NamespacedKey, Holder<Biome>> minecraftBiomes = new KMap<>();
|
||||
private boolean closed = false;
|
||||
@@ -60,49 +60,50 @@ public class Headless implements IHeadless, LevelHeightAccessor {
|
||||
var queueLooper = new Looper() {
|
||||
@Override
|
||||
protected long loop() {
|
||||
if (manualLock.isLocked()) {
|
||||
manualLock.lock();
|
||||
manualLock.unlock();
|
||||
}
|
||||
saveAll();
|
||||
save();
|
||||
return closed ? -1 : 100;
|
||||
}
|
||||
};
|
||||
queueLooper.setName("Region Save Looper");
|
||||
queueLooper.start();
|
||||
|
||||
var dimKey = engine.getDimension().getLoadKey();
|
||||
for (var biome : engine.getAllBiomes()) {
|
||||
if (!biome.isCustom()) continue;
|
||||
for (var custom : biome.getCustomDerivitives()) {
|
||||
binding.registerBiome(dimKey, custom, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(int x, int z) {
|
||||
if (closed) return false;
|
||||
try {
|
||||
return storage.getRegionFile(new ChunkPos(x << 5, z << 5), true) != null;
|
||||
CompoundTag tag = storage.read(new ChunkPos(x, z));
|
||||
return tag != null && !"empty".equals(tag.getString("Status"));
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAll() {
|
||||
manualLock.lock();
|
||||
try {
|
||||
save();
|
||||
} finally {
|
||||
manualLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void save() {
|
||||
public void save() {
|
||||
if (closed) return;
|
||||
while (!chunkQueue.isEmpty()) {
|
||||
ChunkAccess chunk = chunkQueue.poll();
|
||||
if (chunk == null) break;
|
||||
try {
|
||||
storage.write(chunk.getPos(), binding.serializeChunk(chunk, this));
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to save chunk " + chunk.getPos().x + ", " + chunk.getPos().z);
|
||||
e.printStackTrace();
|
||||
saveLock.lock();
|
||||
try {
|
||||
while (!chunkQueue.isEmpty()) {
|
||||
ChunkAccess chunk = chunkQueue.poll();
|
||||
if (chunk == null) break;
|
||||
try {
|
||||
storage.write(chunk.getPos(), binding.serializeChunk(chunk, this));
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to save chunk " + chunk.getPos().x + ", " + chunk.getPos().z);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
saveLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,16 +138,9 @@ public class Headless implements IHeadless, LevelHeightAccessor {
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z) {
|
||||
if (closed) return;
|
||||
if (closed || exists(x, z)) return;
|
||||
try {
|
||||
var pos = new ChunkPos(x, z);
|
||||
try {
|
||||
CompoundTag tag = storage.read(pos);
|
||||
if (tag != null && !"empty".equals(tag.getString("Status"))) {
|
||||
return;
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
ProtoChunk chunk = binding.createProtoChunk(pos, this);
|
||||
var tc = new MCATerrainChunk(chunk);
|
||||
|
||||
@@ -190,7 +184,7 @@ public class Headless implements IHeadless, LevelHeightAccessor {
|
||||
IrisContext.getOr(engine).setChunkContext(ctx);
|
||||
|
||||
for (EngineStage i : engine.getMode().getStages()) {
|
||||
i.generate(x, z, blocks, vbiomes, true, ctx);
|
||||
i.generate(x, z, blocks, vbiomes, false, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
@@ -23,16 +21,9 @@ import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.volmit.iris.core.nms.IHeadless;
|
||||
import com.volmit.iris.core.nms.v1_20_R3.mca.ChunkSerializer;
|
||||
import com.volmit.iris.core.nms.v1_20_R3.mca.MCATerrainChunk;
|
||||
import com.volmit.iris.core.nms.v1_20_R3.mca.RegionFileStorage;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.documentation.RegionCoordinates;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder;
|
||||
import com.volmit.iris.util.hunk.view.ChunkDataHunkHolder;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
@@ -601,51 +592,10 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadDatapack(File folder, boolean replace) {
|
||||
var data = new File(folder, "iris/data");
|
||||
if (!data.exists() || !data.isDirectory()) return false;
|
||||
FilenameFilter jsonFilter = (dir, name) -> new File(dir, name).isFile() && name.toLowerCase().endsWith(".json");
|
||||
|
||||
var files = data.listFiles((dir, name) -> new File(dir, name).isDirectory());
|
||||
if (files == null) return false;
|
||||
for (File file : files) {
|
||||
var biome = new File(file, "worldgen/biome");
|
||||
if (!biome.exists()) continue;
|
||||
var biomeFiles = biome.listFiles(jsonFilter);
|
||||
if (biomeFiles == null) continue;
|
||||
for (File biomeFile : biomeFiles) {
|
||||
String json = null;
|
||||
int tries = 10;
|
||||
while (json == null && tries-- > 0) {
|
||||
try {
|
||||
json = IO.readAll(biomeFile);
|
||||
} catch (IOException e) {
|
||||
Iris.error("Failed to read biome " + file.getName() + ":" + biomeFile.getName() + " tries left: " + tries);
|
||||
if (tries == 0) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
if (json == null) continue;
|
||||
|
||||
try {
|
||||
var value = decode(net.minecraft.world.level.biome.Biome.CODEC, json).map(Holder::value).orElse(null);
|
||||
register(Registries.BIOME, from(file.getName(), biomeFile), value, replace);
|
||||
} catch (Throwable e) {
|
||||
Iris.error("Failed to register biome " + file.getName() + ":" + biomeFile.getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private ResourceLocation from(String namespace, File file) {
|
||||
var name = file.getName();
|
||||
return new ResourceLocation(namespace, name.substring(0, name.lastIndexOf('.')));
|
||||
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
|
||||
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
|
||||
if (biomeBase == null) return false;
|
||||
return register(Registries.BIOME, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
|
||||
}
|
||||
|
||||
private <T> Optional<T> decode(Codec<T> codec, String json) {
|
||||
|
||||
@@ -42,6 +42,9 @@ public record MCATerrainChunk(ChunkAccess chunk) implements TerrainChunk {
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int y, int z, Biome bio) {
|
||||
if (y < 0) return;
|
||||
y += getMinHeight();
|
||||
if (y > getMaxHeight()) return;
|
||||
chunk.setBiome(x & 15, y, z & 15, CraftBiome.bukkitToMinecraftHolder(bio));
|
||||
}
|
||||
|
||||
@@ -61,9 +64,9 @@ public record MCATerrainChunk(ChunkAccess chunk) implements TerrainChunk {
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, BlockData blockData) {
|
||||
if (y > getMaxHeight() || y < getMinHeight()) {
|
||||
return;
|
||||
}
|
||||
if (y < 0) return;
|
||||
y += getMinHeight();
|
||||
if (y > getMaxHeight()) return;
|
||||
|
||||
if (blockData == null) {
|
||||
Iris.error("NULL BD");
|
||||
@@ -76,14 +79,14 @@ public record MCATerrainChunk(ChunkAccess chunk) implements TerrainChunk {
|
||||
}
|
||||
|
||||
private BlockState getBlockState(int x, int y, int z) {
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
}
|
||||
y += getMinHeight();
|
||||
if (y > getMaxHeight()) {
|
||||
y = getMaxHeight();
|
||||
}
|
||||
|
||||
if (y < getMinHeight()) {
|
||||
y = getMinHeight();
|
||||
}
|
||||
|
||||
return chunk.getBlockState(new BlockPos(x & 15, y, z & 15));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package com.volmit.iris.core.nms.v1_20_R4;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
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.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 location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
|
||||
Biome biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
INMS.get().registerBiome(location.getNamespace(), j, false);
|
||||
biome = customRegistry.get(location);
|
||||
if (biome == null) {
|
||||
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,767 @@
|
||||
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.io.File;
|
||||
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.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.RegistrationInfo;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.RandomSequences;
|
||||
import net.minecraft.world.item.component.CustomData;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
import net.minecraft.world.level.storage.PrimaryLevelData;
|
||||
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.BiomeProvider;
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerDimension(String name, IrisDimension dimension) {
|
||||
var registry = registry(Registries.DIMENSION_TYPE);
|
||||
var baseLocation = switch (dimension.getEnvironment()) {
|
||||
case NORMAL -> new ResourceLocation("minecraft", "overworld");
|
||||
case NETHER -> new ResourceLocation("minecraft", "the_nether");
|
||||
case THE_END -> new ResourceLocation("minecraft", "the_end");
|
||||
case CUSTOM -> throw new IllegalArgumentException("Cannot register custom dimension");
|
||||
};
|
||||
var base = registry.getHolder(ResourceKey.create(Registries.DIMENSION_TYPE, baseLocation)).orElse(null);
|
||||
if (base == null) return false;
|
||||
var json = encode(DimensionType.CODEC, base).orElse(null);
|
||||
if (json == null) return false;
|
||||
var object = json.getAsJsonObject();
|
||||
var height = dimension.getDimensionHeight();
|
||||
object.addProperty("min_y", height.getMin());
|
||||
object.addProperty("height", height.getMax() - height.getMin());
|
||||
object.addProperty("logical_height", dimension.getLogicalHeight());
|
||||
var value = decode(DimensionType.CODEC, object.toString()).map(Holder::value).orElse(null);
|
||||
if (value == null) return false;
|
||||
return register(Registries.DIMENSION_TYPE, new ResourceLocation("iris", name), value, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
|
||||
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
|
||||
if (biomeBase == null) return false;
|
||||
return register(Registries.BIOME, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
|
||||
}
|
||||
|
||||
private <T> Optional<T> decode(Codec<T> codec, String json) {
|
||||
return codec.decode(JsonOps.INSTANCE, GsonHelper.parse(json)).result().map(Pair::getFirst);
|
||||
}
|
||||
|
||||
private <T> Optional<JsonElement> encode(Codec<T> codec, T value) {
|
||||
return codec.encode(value, JsonOps.INSTANCE, new JsonObject()).result();
|
||||
}
|
||||
|
||||
private <T> boolean register(ResourceKey<Registry<T>> registryKey, ResourceLocation location, T value, boolean replace) {
|
||||
Preconditions.checkArgument(registryKey != null, "The registry cannot be null!");
|
||||
Preconditions.checkArgument(location != null, "The location cannot be null!");
|
||||
Preconditions.checkArgument(value != null, "The value cannot be null!");
|
||||
var registry = registry(registryKey);
|
||||
var key = ResourceKey.create(registryKey, location);
|
||||
try {
|
||||
if (registry.containsKey(key)) {
|
||||
if (!replace) return false;
|
||||
return replace(registryKey, location, value);
|
||||
}
|
||||
Field field = getField(MappedRegistry.class, boolean.class);
|
||||
field.setAccessible(true);
|
||||
boolean frozen = field.getBoolean(registry);
|
||||
field.setBoolean(registry, false);
|
||||
Field valueField = getField(Holder.Reference.class, "T");
|
||||
valueField.setAccessible(true);
|
||||
|
||||
try {
|
||||
var holder = registry.register(key, value, RegistrationInfo.BUILT_IN);
|
||||
if (frozen) valueField.set(holder, value);
|
||||
return true;
|
||||
} finally {
|
||||
field.setBoolean(registry, frozen);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> boolean replace(ResourceKey<Registry<T>> registryKey, ResourceLocation location, T value) {
|
||||
Preconditions.checkArgument(registryKey != null, "The registryKey cannot be null!");
|
||||
Preconditions.checkArgument(location != null, "The location cannot be null!");
|
||||
Preconditions.checkArgument(value != null, "The value cannot be null!");
|
||||
var registry = registry(registryKey);
|
||||
var key = ResourceKey.create(registryKey, location);
|
||||
try {
|
||||
var holder = registry.getHolder(key).orElse(null);
|
||||
if (holder == null) return false;
|
||||
var oldValue = holder.value();
|
||||
Field valueField = getField(Holder.Reference.class, "T");
|
||||
valueField.setAccessible(true);
|
||||
Field toIdField = getField(MappedRegistry.class, buildType(Reference2IntMap.class, "T"));
|
||||
toIdField.setAccessible(true);
|
||||
Field byValueField = getField(MappedRegistry.class, buildType(Map.class, "T", buildType(Holder.Reference.class, "T")));
|
||||
byValueField.setAccessible(true);
|
||||
var toId = (Reference2IntMap<T>) toIdField.get(registry);
|
||||
var byValue = (Map<T, Holder.Reference<T>>) byValueField.get(registry);
|
||||
|
||||
valueField.set(holder, value);
|
||||
toId.put(value, toId.removeInt(oldValue));
|
||||
byValue.put(value, byValue.remove(oldValue));
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> MappedRegistry<T> registry(ResourceKey<Registry<T>> registryKey) {
|
||||
var rawRegistry = registry().registry(registryKey).orElse(null);
|
||||
if (!(rawRegistry instanceof MappedRegistry<T> registry))
|
||||
throw new IllegalStateException("The Registry is not a mapped Registry!");
|
||||
return registry;
|
||||
}
|
||||
|
||||
private static String buildType(Class<?> clazz, String... parameterTypes) {
|
||||
if (parameterTypes.length == 0) return clazz.getName();
|
||||
var builder = new StringBuilder(clazz.getName())
|
||||
.append("<");
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
builder.append(parameterTypes[i]).append(parameterTypes.length - 1 == i ? ">" : ", ");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static Field getField(Class<?> clazz, String type) throws NoSuchFieldException {
|
||||
try {
|
||||
for (Field f : clazz.getDeclaredFields()) {
|
||||
if (f.getGenericType().getTypeName().equals(type))
|
||||
return f;
|
||||
}
|
||||
throw new NoSuchFieldException(type);
|
||||
} catch (NoSuchFieldException e) {
|
||||
Class<?> superClass = clazz.getSuperclass();
|
||||
if (superClass == null) throw e;
|
||||
return getField(superClass, type);
|
||||
}
|
||||
}
|
||||
|
||||
public void injectBukkit() {
|
||||
try {
|
||||
Iris.info("Injecting Bukkit");
|
||||
new ByteBuddy()
|
||||
.redefine(WorldCreator.class)
|
||||
.visit(Advice.to(WorldCreatorAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(String.class))))
|
||||
.make()
|
||||
.load(WorldCreator.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
|
||||
new ByteBuddy()
|
||||
.redefine(ServerLevel.class)
|
||||
.visit(Advice.to(ServerLevelAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(MinecraftServer.class, Executor.class, LevelStorageSource.LevelStorageAccess.class,
|
||||
PrimaryLevelData.class, ResourceKey.class, LevelStem.class, ChunkProgressListener.class, boolean.class, long.class,
|
||||
List.class, boolean.class, RandomSequences.class, World.Environment.class, ChunkGenerator.class, BiomeProvider.class))))
|
||||
.make()
|
||||
.load(ServerLevel.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
|
||||
Iris.info("Injected Bukkit Successfully!");
|
||||
} catch (Exception e) {
|
||||
Iris.info(C.RED + "Failed to Inject Bukkit!");
|
||||
e.printStackTrace();
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ServerLevelAdvice {
|
||||
@Advice.OnMethodEnter
|
||||
static void enter(@Advice.Argument(0) MinecraftServer server, @Advice.Argument(2) LevelStorageSource.LevelStorageAccess access, @Advice.Argument(4) ResourceKey<Level> key, @Advice.Argument(value = 5, readOnly = false) LevelStem levelStem) {
|
||||
File iris = new File(access.levelDirectory.path().toFile(), "iris");
|
||||
if (!iris.exists() && !key.location().getPath().startsWith("iris/")) return;
|
||||
ResourceKey<DimensionType> typeKey = ResourceKey.create(Registries.DIMENSION_TYPE, new ResourceLocation("iris", key.location().getPath()));
|
||||
RegistryAccess registryAccess = server.registryAccess();
|
||||
Registry<DimensionType> registry = registryAccess.registry(Registries.DIMENSION_TYPE).orElse(null);
|
||||
if (registry == null) throw new IllegalStateException("Unable to find registry for dimension type " + typeKey);
|
||||
Holder<DimensionType> holder = registry.getHolder(typeKey).orElse(null);
|
||||
if (holder == null) throw new IllegalStateException("Unable to find dimension type " + typeKey);
|
||||
levelStem = new LevelStem(holder, levelStem.generator());
|
||||
}
|
||||
}
|
||||
|
||||
private static class WorldCreatorAdvice {
|
||||
@Advice.OnMethodEnter
|
||||
static void enter(@Advice.Argument(0) String name) {
|
||||
File isIrisWorld = new File(name, "iris");
|
||||
boolean isFromIris = false;
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
for (StackTraceElement stack : stackTrace) {
|
||||
if (stack.getClassName().contains("Iris")) {
|
||||
isFromIris = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isFromIris) {
|
||||
Preconditions.checkArgument(!isIrisWorld.exists(), "Only Iris can load Iris Worlds!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ rootProject.name = 'Iris'
|
||||
include 'app', 'com.volmit.gui'
|
||||
include(':core')
|
||||
include(
|
||||
':nms:v1_20_R4',
|
||||
':nms:v1_20_R3',
|
||||
':nms:v1_20_R2',
|
||||
':nms:v1_20_R1',
|
||||
|
||||
Reference in New Issue
Block a user