Merge pull request #19 from VolmitDev/mca

Sync
This commit is contained in:
RePixelatedMC
2024-05-20 14:04:32 +02:00
committed by GitHub
57 changed files with 1559 additions and 767 deletions

View File

@@ -31,7 +31,7 @@ Consider supporting our development by buying Iris on spigot! We work hard to ma
4. Use `CTRL + X`, then Press `Y`, Then `ENTER`
5. Quit & Reopen Terminal and verify with `echo $JAVA_HOME`. It should print a directory
3. If this is your first time building Iris for MC 1.18+ run `gradlew setup` inside the root Iris project folder.
Otherwise, skip this step. Grab a coffee, this may take up to 5 minutes depending on your cpu & internet connection.
Otherwise, skip this step. Grab a coffee, this may take up to 45 minutes depending on your cpu & internet connection.
4. Once the project has setup, run `gradlew iris`
5. The Iris jar will be placed in `Iris/build/Iris-XXX-XXX.jar` Enjoy! Consider supporting us by buying it on spigot!

View File

@@ -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();
}
}
}

View File

@@ -19,7 +19,7 @@
plugins {
id 'java'
id 'java-library'
id "io.freefair.lombok" version "6.3.0"
id "io.freefair.lombok" version "8.6"
}
def apiVersion = '1.19'
@@ -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')
}

View File

@@ -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) {

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -35,6 +35,7 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.Direction;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.scheduling.Queue;
import org.bukkit.*;
import org.bukkit.block.Block;
@@ -52,7 +53,7 @@ import java.util.*;
@Decree(name = "object", aliases = "o", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris object manipulation")
public class CommandObject implements DecreeExecutor {
private static final Set<Material> skipBlocks = Set.of(Material.GRASS, Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
private static final Set<Material> skipBlocks = Set.of(E.getOrDefault(Material.class, "GRASS", "SHORT_GRASS"), Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
Material.POPPY, Material.DANDELION);
public static IObjectPlacer createPlacer(World world, Map<Block, BlockData> futureBlockChanges) {

View File

@@ -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)

View File

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

View File

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

View File

@@ -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

View File

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

View File

@@ -18,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) {

View File

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

View File

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

View File

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

View File

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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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();
}
}
}
}

View File

@@ -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);

View File

@@ -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++;

View File

@@ -37,7 +37,7 @@ public class UtilsSFG {
}
if (ServerBootSFG.unsuportedversion) {
Iris.safeguard(C.RED + "Server Version");
Iris.safeguard(C.RED + "- Iris only supports 1.19.2 > 1.20.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());
}
}
}

View File

@@ -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()) {

View File

@@ -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) {

View File

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

View File

@@ -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;

View File

@@ -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)

View File

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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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";

View File

@@ -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);
}

View File

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

View File

@@ -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;

View File

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

View File

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

View File

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

View File

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

View File

@@ -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());
}
}
}

View File

@@ -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) {

View File

@@ -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());
}
}
}

View File

@@ -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) {

View File

@@ -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());

View File

@@ -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) {

View File

@@ -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());

View File

@@ -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) {

View File

@@ -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());

View File

@@ -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) {

View File

@@ -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());

View File

@@ -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);
}
}

View File

@@ -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) {

View File

@@ -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));
}

View File

@@ -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);
}
}
}

View File

@@ -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!");
}
}
}
}

View File

@@ -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',