Compare commits

..

11 Commits

Author SHA1 Message Date
RePixelatedMC f42bf07d4e - Bit clumsy 2025-04-11 14:39:50 +02:00
RePixelatedMC 289813b044 - Fixed noStudio null pointer when not in studio lol
- Added a debugger for when creating images
2025-04-11 14:36:54 +02:00
RePixelatedMC b209f69bba Merge remote-tracking branch 'origin/feat/map' into feat/map 2025-04-11 12:45:53 +02:00
RePixelatedMC 790fde02a8 Some todos 2025-04-11 11:12:59 +02:00
RePixelatedMC eddc0c81f2 ah now it should work 2025-04-11 11:12:34 +02:00
RePixelatedMC d8c3fd8e6c ah now it should work 2025-04-10 13:17:57 +02:00
RePixelatedMC 984d294bab wait 2025-04-10 13:15:19 +02:00
RePixelatedMC 96b0db309a huh 2025-04-10 13:07:22 +02:00
RePixelatedMC b5da0dd33f Iris std map v4 sync 2025-04-04 16:55:02 +02:00
RePixelatedMC 1ac482ff49 sync 2025-04-04 16:39:39 +02:00
Julian Krings fb0bc112e3 increase worker threads on paper servers during pregen 2025-03-30 14:31:11 +02:00
24 changed files with 588 additions and 325 deletions
+7 -28
View File
@@ -1,5 +1,3 @@
import xyz.jpenilla.runpaper.task.RunServer
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
@@ -32,11 +30,10 @@ plugins {
id 'java-library'
id "io.github.goooler.shadow" version "8.1.7"
id "de.undercouch.download" version "5.0.1"
id "xyz.jpenilla.run-paper" version "2.3.1"
}
version '3.6.6-1.20.1-1.21.4'
version '3.6.5-1.20.1-1.21.4'
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
// ======================== WINDOWS =============================
@@ -48,7 +45,7 @@ registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins')
registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins')
registerCustomOutputTask('PixelFury', 'C://Users/repix/workplace/Iris/1.21.3 - Development-Public-v3/plugins')
registerCustomOutputTask('PixelFuryDev', 'C://Users/repix/workplace/Iris/1.21 - Development-v3/plugins')
registerCustomOutputTask('PixelFuryDev', 'C://Users/repix/workplace/Iris/1.21.4 - Development-v3/plugins')
// ========================== UNIX ==============================
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Developer/RemoteGit/Server/plugins')
@@ -56,11 +53,6 @@ registerCustomOutputTaskUnix('PixelMac', '/Users/test/Desktop/mcserver/plugins')
registerCustomOutputTaskUnix('CrazyDev22LT', '/home/julian/Desktop/server/plugins')
// ==============================================================
def MIN_HEAP_SIZE = "2G"
def MAX_HEAP_SIZE = "8G"
//Valid values are: none, truecolor, indexed256, indexed16, indexed8
def COLOR = "truecolor"
def NMS_BINDINGS = Map.of(
"v1_21_R3", "1.21.4-R0.1-SNAPSHOT",
"v1_21_R2", "1.21.3-R0.1-SNAPSHOT",
@@ -70,34 +62,21 @@ def NMS_BINDINGS = Map.of(
"v1_20_R2", "1.20.2-R0.1-SNAPSHOT",
"v1_20_R1", "1.20.1-R0.1-SNAPSHOT",
)
def JVM_VERSION = Map.<String, Integer>of()
NMS_BINDINGS.forEach { key, value ->
project(":nms:$key") {
def JVM_VERSION = Map.of()
NMS_BINDINGS.each { nms ->
project(":nms:${nms.key}") {
apply plugin: 'java'
apply plugin: 'com.volmit.nmstools'
nmsTools {
it.jvm = JVM_VERSION.getOrDefault(key, 21)
it.version = value
it.jvm = JVM_VERSION.getOrDefault(nms.key, 21)
it.version = nms.value
}
dependencies {
implementation project(":core")
}
}
tasks.register("runServer-$key", RunServer) {
group("servers")
minecraftVersion(value.split("-")[0])
minHeapSize(MIN_HEAP_SIZE)
maxHeapSize(MAX_HEAP_SIZE)
pluginJars(tasks.shadowJar.archiveFile)
javaLauncher = javaToolchains.launcherFor { it.languageVersion = JavaLanguageVersion.of(JVM_VERSION.getOrDefault(key, 21))}
runDirectory.convention(layout.buildDirectory.dir("run/$key"))
systemProperty("disable.watchdog", "")
systemProperty("net.kyori.ansi.colorLevel", COLOR)
systemProperty("com.mojang.eula.agree", true)
}
}
shadowJar {
@@ -24,7 +24,6 @@ import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.json.JSONException;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.ChronoLatch;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -135,6 +134,11 @@ public class IrisSettings {
@Data
public static class IrisSettingsConcurrency {
public int parallelism = -1;
public int worldGenParallelism = -1;
public int getWorldGenThreads() {
return getThreadCount(worldGenParallelism);
}
}
@Data
@@ -19,13 +19,17 @@
package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.engine.object.*;
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.NullableBiomeHandler;
import com.volmit.iris.util.decree.specialhandlers.NullableRegionHandler;
import com.volmit.iris.util.format.C;
import org.bukkit.block.Biome;
import java.awt.*;
@@ -51,12 +55,31 @@ public class CommandEdit implements DecreeExecutor {
@Decree(description = "Edit the biome you specified", aliases = {"b"}, origin = DecreeOrigin.PLAYER)
public void biome(@Param(contextual = false, description = "The biome to edit") IrisBiome biome) {
public void biome(@Param(contextual = false, description = "The biome to edit", defaultValue = "---", customHandler = NullableBiomeHandler.class) IrisBiome biome) {
if (noStudio()) {
return;
}
if (biome == null) {
try {
IrisBiome b = engine().getBiome(player().getLocation().getBlockX(), player().getLocation().getBlockY() - player().getWorld().getMinHeight(), player().getLocation().getBlockZ());
Desktop.getDesktop().open(b.getLoadFile());
sender().sendMessage(C.GREEN + "Opening " + b.getTypeName() + " " + b.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
} catch (Throwable e) {
Iris.reportError(e);
sender().sendMessage("Non-Iris Biome: " + player().getLocation().getBlock().getBiome().name());
if (player().getLocation().getBlock().getBiome().equals(Biome.CUSTOM)) {
try {
sender().sendMessage("Data Pack Biome: " + INMS.get().getTrueBiomeBaseKey(player().getLocation()) + " (ID: " + INMS.get().getTrueBiomeBaseId(INMS.get().getTrueBiomeBase(player().getLocation())) + ")");
} catch (Throwable ee) {
Iris.reportError(ee);
}
}
}
return;
}
try {
if (biome == null || biome.getLoadFile() == null) {
if (biome.getLoadFile() == null) {
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
return;
}
@@ -69,10 +92,20 @@ public class CommandEdit implements DecreeExecutor {
}
@Decree(description = "Edit the region you specified", aliases = {"r"}, origin = DecreeOrigin.PLAYER)
public void region(@Param(contextual = false, description = "The region to edit") IrisRegion region) {
public void region(@Param(contextual = false, description = "The region to edit", defaultValue = "---", customHandler = NullableRegionHandler.class) IrisRegion region) {
if (noStudio()) {
return;
}
if (region == null) {
try {
IrisRegion r = engine().getRegion(player().getLocation().getBlockX(), player().getLocation().getBlockZ());
Desktop.getDesktop().open(r.getLoadFile());
sender().sendMessage(C.GREEN + "Opening " + r.getTypeName() + " " + r.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! ");
} catch (Throwable e) {
sender().sendMessage(C.RED + "Failed to get region.");
}
return;
}
try {
if (region == null || region.getLoadFile() == null) {
sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?");
@@ -22,6 +22,7 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.gui.NoiseExplorerGUI;
import com.volmit.iris.core.gui.VisionGUI;
import com.volmit.iris.core.gui.components.IrisRenderer;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.project.IrisProject;
import com.volmit.iris.core.service.ConversionSVC;
@@ -65,6 +66,9 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;
import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -156,6 +160,37 @@ public class CommandStudio implements DecreeExecutor {
sender().sendMessage(C.GREEN + "The \"" + dimension.getName() + "\" pack has version: " + dimension.getVersion());
}
@Decree(description = "Debug image")
public void printImageChannel(
@Param(name = "image", description = "Image found in the image folder inside the project")
String image,
@Param(name = "channel", description = "Image channel")
IrisImageChannel channel
) {
if (noStudio()) return;
try {
File file = new File(access().getEngine().getComplex().getData().getDataFolder(), "images/" + image);
if (!file.exists()) {
sender().sendMessage(C.RED + "The image \"" + image + "\" does not exist.");
return;
}
BufferedImage buffer = ImageIO.read(file);
IrisImage irisImage = new IrisImage(buffer);
File at = new File(file.getParentFile(), "debug-see-" + file.getName());
BufferedImage b = new BufferedImage(buffer.getWidth(), buffer.getHeight(), BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < buffer.getWidth(); i++) {
for (int j = 0; j < buffer.getHeight(); j++) {
b.setRGB(i, j, Color.getHSBColor(0, 0, (float) irisImage.getValue(channel, i, j)).getRGB());
}
}
ImageIO.write(b, "png", at);
sender().sendMessage(C.IRIS + "Debug image written to ./images for channel " + channel.name());
} catch (Exception e) {
sender().sendMessage(C.RED + "Something went wrong.. ");
e.printStackTrace();
}
}
@Decree(name = "regen", description = "Regenerate nearby chunks.", aliases = "rg", sync = true, origin = DecreeOrigin.PLAYER)
public void regen(
@Param(name = "radius", description = "The radius of nearby cunks", defaultValue = "5")
@@ -404,9 +439,16 @@ public class CommandStudio implements DecreeExecutor {
@Param(name = "world", description = "The world to open the generator for", contextual = true)
World world
) {
if (noGUI()) return;
if (noGUI()) {
sender().sendMessage(C.GOLD + "GUI Support isn't enabled or supported on this server.");
return;
}
if (!IrisToolbelt.isIrisWorld(world)) {
if (world == null) {
if (noStudio()) return;
world = player().getWorld();
}
else if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.RED + "You need to be in or specify an Iris-generated world!");
return;
}
@@ -842,7 +884,7 @@ public class CommandStudio implements DecreeExecutor {
sender().sendMessage(C.RED + "No studio world is open!");
return true;
}
if (!engine().isStudio()) {
if (engine() == null || !engine().isStudio()) {
sender().sendMessage(C.RED + "You must be in a studio world!");
return true;
}
@@ -1,6 +1,6 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2024 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,7 +30,6 @@ import com.volmit.iris.engine.object.IrisWorld;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.data.registry.Attributes;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.BlockPosition;
import com.volmit.iris.util.math.M;
@@ -57,8 +56,9 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.BiFunction;
import static com.volmit.iris.util.data.registry.Attributes.MAX_HEALTH;
//todo
// - Misalignment
// - Weird snapping?
public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener, MouseMotionListener, MouseInputListener {
private static final long serialVersionUID = 2094606939770332040L;
private final KList<LivingEntity> lastEntities = new KList<>();
@@ -415,8 +415,8 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
}
private double getWorldX(double screenX) {
//return (mscale * screenX) + ((oxp / scale) * mscale);
return (mscale * screenX) + ((oxp / scale));
return (mscale * screenX) + ((oxp / scale) * mscale);
// return (mscale * screenX) + ((oxp / scale));
}
private double getWorldZ(double screenZ) {
@@ -639,7 +639,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener
k.add("Pos: " + h.getLocation().getBlockX() + ", " + h.getLocation().getBlockY() + ", " + h.getLocation().getBlockZ());
k.add("UUID: " + h.getUniqueId());
k.add("HP: " + h.getHealth() + " / " + h.getAttribute(MAX_HEALTH).getValue());
k.add("HP: " + h.getHealth() + " / " + h.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
drawCardTR(g, k);
}
@@ -20,6 +20,7 @@ package com.volmit.iris.core.nms;
import com.volmit.iris.core.nms.container.AutoClosing;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.nms.container.Pair;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
@@ -93,7 +94,6 @@ public interface INMSBinding {
throw new IllegalStateException("Missing dimenstion types to create world");
try (var ignored = injectLevelStems()) {
ignored.storeContext();
return c.createWorld();
}
}
@@ -132,11 +132,7 @@ public interface INMSBinding {
AutoClosing injectLevelStems();
default AutoClosing injectUncached(boolean overworld, boolean nether, boolean end) {
return null;
}
Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end);
boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end);
void removeCustomDimensions(World world);
}
@@ -1,6 +1,5 @@
package com.volmit.iris.core.nms.container;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.function.NastyRunnable;
import lombok.AllArgsConstructor;
@@ -8,7 +7,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
@AllArgsConstructor
public class AutoClosing implements AutoCloseable {
private static final KMap<Thread, AutoClosing> CONTEXTS = new KMap<>();
private final AtomicBoolean closed = new AtomicBoolean();
private final NastyRunnable action;
@@ -16,24 +14,9 @@ public class AutoClosing implements AutoCloseable {
public void close() {
if (closed.getAndSet(true)) return;
try {
removeContext();
action.run();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
public void storeContext() {
CONTEXTS.put(Thread.currentThread(), this);
}
public void removeContext() {
CONTEXTS.values().removeIf(c -> c == this);
}
public static void closeContext() {
AutoClosing closing = CONTEXTS.remove(Thread.currentThread());
if (closing == null) return;
closing.close();
}
}
@@ -126,8 +126,8 @@ public class NMSBinding1X implements INMSBinding {
}
@Override
public AutoClosing injectUncached(boolean overworld, boolean nether, boolean end) {
return injectLevelStems();
public Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end) {
return new Pair<>(0, new AutoClosing(() -> {}));
}
@Override
@@ -135,11 +135,6 @@ public class NMSBinding1X implements INMSBinding {
return false;
}
@Override
public void removeCustomDimensions(World world) {
}
@Override
public CompoundTag serializeEntity(Entity location) {
return null;
@@ -19,6 +19,7 @@
package com.volmit.iris.core.pregenerator.methods;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.pregenerator.PregenListener;
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
import com.volmit.iris.core.tools.IrisToolbelt;
@@ -34,8 +35,10 @@ import org.bukkit.World;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
public class AsyncPregenMethod implements PregeneratorMethod {
private static final AtomicInteger THREAD_COUNT = new AtomicInteger();
private final World world;
private final MultiBurst burst;
private final Semaphore semaphore;
@@ -92,6 +95,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
@Override
public void init() {
unloadAndSaveAllChunks();
increaseWorkerThreads();
}
@Override
@@ -104,6 +108,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
semaphore.acquireUninterruptibly(256);
unloadAndSaveAllChunks();
burst.close();
resetWorkerThreads();
}
@Override
@@ -140,4 +145,44 @@ public class AsyncPregenMethod implements PregeneratorMethod {
return null;
}
public static void increaseWorkerThreads() {
THREAD_COUNT.updateAndGet(i -> {
if (i > 0) return 1;
try {
var field = Class.forName("ca.spottedleaf.moonrise.common.util.MoonriseCommon").getDeclaredField("WORKER_POOL");
var pool = field.get(null);
var threads = ((Thread[]) pool.getClass().getDeclaredMethod("getCoreThreads").invoke(pool)).length;
var adjusted = IrisSettings.get().getConcurrency().getWorldGenThreads();
if (threads >= adjusted) return 0;
pool.getClass().getDeclaredMethod("adjustThreadCount", int.class).invoke(pool, adjusted);
return threads;
} catch (ClassNotFoundException ignored) {
} catch (Throwable e) {
Iris.error("Failed to increase worker threads");
e.printStackTrace();
}
return 0;
});
}
public static void resetWorkerThreads() {
THREAD_COUNT.updateAndGet(i -> {
if (i == 0) return 0;
try {
var field = Class.forName("ca.spottedleaf.moonrise.common.util.MoonriseCommon").getDeclaredField("WORKER_POOL");
var pool = field.get(null);
var method = pool.getClass().getDeclaredMethod("adjustThreadCount", int.class);
method.invoke(pool, i);
return 0;
} catch (ClassNotFoundException ignored) {
} catch (Throwable e) {
Iris.error("Failed to reset worker threads");
e.printStackTrace();
}
return i;
});
}
}
@@ -9,6 +9,7 @@ import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.exceptions.IrisException;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Getter;
@@ -17,11 +18,6 @@ import org.bukkit.Bukkit;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.Clock;
import java.time.LocalDateTime;
import java.util.Collections;
@@ -50,10 +46,7 @@ public class IrisPackBenchmarking {
.start(() -> {
Iris.info("Setting up benchmark environment ");
benchmarkInProgress = true;
File file = new File("benchmark");
if (file.exists()) {
deleteDirectory(file.toPath());
}
IO.delete(new File(Bukkit.getWorldContainer(), "benchmark"));
createBenchmark();
while (!IrisToolbelt.isIrisWorld(Bukkit.getWorld("benchmark"))) {
J.sleep(1000);
@@ -72,7 +65,7 @@ public class IrisPackBenchmarking {
public void finishedBenchmark(KList<Integer> cps) {
try {
String time = Form.duration(stopwatch.getMillis());
String time = Form.duration((long) stopwatch.getMilliseconds());
Engine engine = IrisToolbelt.access(Bukkit.getWorld("benchmark")).getEngine();
Iris.info("-----------------");
Iris.info("Results:");
@@ -83,11 +76,7 @@ public class IrisPackBenchmarking {
Iris.info(" - Lowest CPS: " + findLowest(cps));
Iris.info("-----------------");
Iris.info("Creating a report..");
File profilers = new File("plugins" + File.separator + "Iris" + File.separator + "packbenchmarks");
profilers.mkdir();
File results = new File(profilers, dimension.getName() + " " + LocalDateTime.now(Clock.systemDefaultZone()).toString().replace(':', '-') + ".txt");
results.getParentFile().mkdirs();
File results = Iris.instance.getDataFile("packbenchmarks", dimension.getName() + " " + LocalDateTime.now(Clock.systemDefaultZone()).toString().replace(':', '-') + ".txt");
KMap<String, Double> metrics = engine.getMetrics().pull();
try (FileWriter writer = new FileWriter(results)) {
writer.write("-----------------\n");
@@ -178,26 +167,4 @@ public class IrisPackBenchmarking {
private int findHighest(KList<Integer> list) {
return Collections.max(list);
}
private boolean deleteDirectory(Path dir) {
try {
Files.walkFileTree(dir, new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}
@@ -2,15 +2,12 @@ package com.volmit.iris.engine.object;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.container.AutoClosing;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.misc.ServerProperties;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldInitEvent;
@@ -22,9 +19,14 @@ public class IrisContextInjector implements Listener {
@Getter
private static boolean missingDimensionTypes = false;
private AutoClosing autoClosing = null;
private final int totalWorlds;
private int worldCounter = 0;
public IrisContextInjector() {
if (!Bukkit.getWorlds().isEmpty()) return;
if (!Bukkit.getWorlds().isEmpty()) {
totalWorlds = 0;
return;
}
String levelName = ServerProperties.LEVEL_NAME;
List<String> irisWorlds = irisWorlds();
@@ -32,20 +34,29 @@ public class IrisContextInjector implements Listener {
boolean nether = irisWorlds.contains(levelName + "_nether");
boolean end = irisWorlds.contains(levelName + "_end");
int i = 1;
if (Bukkit.getAllowNether()) i++;
if (Bukkit.getAllowEnd()) i++;
if (INMS.get().missingDimensionTypes(overworld, nether, end)) {
missingDimensionTypes = true;
totalWorlds = 0;
return;
}
if (overworld || nether || end) {
autoClosing = INMS.get().injectUncached(overworld, nether, end);
var pair = INMS.get().injectUncached(overworld, nether, end);
i += pair.getA() - 3;
autoClosing = pair.getB();
}
totalWorlds = i;
instance.registerListener(this);
}
@EventHandler(priority = EventPriority.LOWEST)
@EventHandler
public void on(WorldInitEvent event) {
if (++worldCounter < totalWorlds) return;
if (autoClosing != null) {
autoClosing.close();
autoClosing = null;
@@ -123,8 +123,6 @@ public class IrisImage extends IrisRegistrant {
}
public void writeDebug(IrisImageChannel channel) {
try {
File at = new File(getLoadFile().getParentFile(), "debug-see-" + getLoadFile().getName());
BufferedImage b = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
@@ -21,7 +21,6 @@ package com.volmit.iris.engine.platform;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.container.AutoClosing;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.engine.IrisEngine;
import com.volmit.iris.engine.data.chunk.TerrainChunk;
@@ -49,7 +48,6 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.generator.BiomeProvider;
@@ -124,13 +122,11 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
}
}
@EventHandler(priority = EventPriority.LOWEST)
@EventHandler
public void onWorldInit(WorldInitEvent event) {
try {
if (initialized || !world.name().equals(event.getWorld().getName()))
return;
AutoClosing.closeContext();
INMS.get().removeCustomDimensions(event.getWorld());
world.setRawWorldSeed(event.getWorld().getSeed());
Engine engine = getEngine(event.getWorld());
if (engine == null) {
@@ -26,8 +26,6 @@ import com.volmit.iris.util.math.RNG;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collector;
import java.util.stream.Collectors;
@SuppressWarnings("ALL")
public class KList<T> extends ArrayList<T> implements List<T> {
@@ -67,10 +65,6 @@ public class KList<T> extends ArrayList<T> implements List<T> {
return s;
}
public static <T> Collector<T, ?, KList<T>> collector() {
return Collectors.toCollection(KList::new);
}
public static KList<String> asStringList(List<?> oo) {
KList<String> s = new KList<String>();
@@ -0,0 +1,53 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.decree.handlers;
import com.volmit.iris.engine.object.IrisImageChannel;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.decree.DecreeParameterHandler;
import com.volmit.iris.util.decree.exceptions.DecreeParsingException;
import java.util.Arrays;
public class ImageChannelHandler implements DecreeParameterHandler<IrisImageChannel> {
@Override
public KList<IrisImageChannel> getPossibilities() {
return new KList<>(Arrays.stream(IrisImageChannel.values()).toList());
}
@Override
public String toString(IrisImageChannel channel) {
return channel.name();
}
@Override
public IrisImageChannel parse(String in, boolean force) throws DecreeParsingException {
return IrisImageChannel.valueOf(in);
}
@Override
public boolean supports(Class<?> type) {
return type.equals(IrisImageChannel.class);
}
@Override
public String getRandomDefault() {
return IrisImageChannel.BRIGHTNESS.toString();
}
}
@@ -0,0 +1,31 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2024 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.decree.specialhandlers;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.util.decree.exceptions.DecreeParsingException;
import com.volmit.iris.util.decree.handlers.BiomeHandler;
public class NullableBiomeHandler extends BiomeHandler {
@Override
public IrisBiome parse(String in, boolean force) throws DecreeParsingException {
return getPossibilities(in).stream().filter((i) -> toString(i).equalsIgnoreCase(in)).findFirst().orElse(null);
}
}
@@ -0,0 +1,31 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2024 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.decree.specialhandlers;
import com.volmit.iris.engine.object.IrisRegion;
import com.volmit.iris.util.decree.exceptions.DecreeParsingException;
import com.volmit.iris.util.decree.handlers.RegionHandler;
public class NullableRegionHandler extends RegionHandler {
@Override
public IrisRegion parse(String in, boolean force) throws DecreeParsingException {
return getPossibilities(in).stream().filter((i) -> toString(i).equalsIgnoreCase(in)).findFirst().orElse(null);
}
}
@@ -645,44 +645,37 @@ public class NMSBinding implements INMSBinding {
}
@Override
@SneakyThrows
public AutoClosing injectLevelStems() {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
)));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
return inject(this::supplier);
}
@Override
@SneakyThrows
public AutoClosing injectUncached(boolean overworld, boolean nether, boolean end) {
public com.volmit.iris.core.nms.container.Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end) {
var reg = registry();
var field = getField(RegistryAccess.ImmutableRegistryAccess.class, Map.class);
field.setAccessible(true);
var access = createRegistryAccess(((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions(), true, overworld, nether, end);
var injected = access.registryOrThrow(Registries.LEVEL_STEM);
AutoClosing closing = inject(old -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), true, overworld, nether, end)
)
);
var injected = ((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM);
var old = (Map<ResourceKey<? extends Registry<?>>, Registry<?>>) field.get(reg);
var fake = new HashMap<>(old);
fake.put(Registries.LEVEL_STEM, injected);
field.set(reg, fake);
return new AutoClosing(() -> field.set(reg, old));
return new com.volmit.iris.core.nms.container.Pair<>(
injected.size(),
new AutoClosing(() -> {
closing.close();
field.set(reg, old);
}));
}
@Override
@@ -694,9 +687,31 @@ public class NMSBinding implements INMSBinding {
return overworld || nether || end;
}
@Override
public void removeCustomDimensions(World world) {
((CraftWorld) world).getHandle().K.customDimensions = null;
private WorldLoader.DataLoadContext supplier(WorldLoader.DataLoadContext old) {
return dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
));
}
@SneakyThrows
private AutoClosing inject(Function<WorldLoader.DataLoadContext, WorldLoader.DataLoadContext> transformer) {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, transformer.apply(old));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
}
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
@@ -720,7 +735,7 @@ public class NMSBinding implements INMSBinding {
if (copy) copy(fake, access.registryOrThrow(Registries.LEVEL_STEM));
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
}
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
@@ -646,44 +646,37 @@ public class NMSBinding implements INMSBinding {
}
@Override
@SneakyThrows
public AutoClosing injectLevelStems() {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
)));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
return inject(this::supplier);
}
@Override
@SneakyThrows
public AutoClosing injectUncached(boolean overworld, boolean nether, boolean end) {
public com.volmit.iris.core.nms.container.Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end) {
var reg = registry();
var field = getField(RegistryAccess.ImmutableRegistryAccess.class, Map.class);
field.setAccessible(true);
var access = createRegistryAccess(((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions(), true, overworld, nether, end);
var injected = access.registryOrThrow(Registries.LEVEL_STEM);
AutoClosing closing = inject(old -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), true, overworld, nether, end)
)
);
var injected = ((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM);
var old = (Map<ResourceKey<? extends Registry<?>>, Registry<?>>) field.get(reg);
var fake = new HashMap<>(old);
fake.put(Registries.LEVEL_STEM, injected);
field.set(reg, fake);
return new AutoClosing(() -> field.set(reg, old));
return new com.volmit.iris.core.nms.container.Pair<>(
injected.size(),
new AutoClosing(() -> {
closing.close();
field.set(reg, old);
}));
}
@Override
@@ -695,9 +688,31 @@ public class NMSBinding implements INMSBinding {
return overworld || nether || end;
}
@Override
public void removeCustomDimensions(World world) {
((CraftWorld) world).getHandle().K.customDimensions = null;
private WorldLoader.DataLoadContext supplier(WorldLoader.DataLoadContext old) {
return dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
));
}
@SneakyThrows
private AutoClosing inject(Function<WorldLoader.DataLoadContext, WorldLoader.DataLoadContext> transformer) {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, transformer.apply(old));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
}
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
@@ -721,7 +736,7 @@ public class NMSBinding implements INMSBinding {
if (copy) copy(fake, access.registryOrThrow(Registries.LEVEL_STEM));
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
}
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
@@ -647,44 +647,37 @@ public class NMSBinding implements INMSBinding {
}
@Override
@SneakyThrows
public AutoClosing injectLevelStems() {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
)));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
return inject(this::supplier);
}
@Override
@SneakyThrows
public AutoClosing injectUncached(boolean overworld, boolean nether, boolean end) {
public com.volmit.iris.core.nms.container.Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end) {
var reg = registry();
var field = getField(RegistryAccess.ImmutableRegistryAccess.class, Map.class);
field.setAccessible(true);
var access = createRegistryAccess(((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions(), true, overworld, nether, end);
var injected = access.registryOrThrow(Registries.LEVEL_STEM);
AutoClosing closing = inject(old -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), true, overworld, nether, end)
)
);
var injected = ((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM);
var old = (Map<ResourceKey<? extends Registry<?>>, Registry<?>>) field.get(reg);
var fake = new HashMap<>(old);
fake.put(Registries.LEVEL_STEM, injected);
field.set(reg, fake);
return new AutoClosing(() -> field.set(reg, old));
return new com.volmit.iris.core.nms.container.Pair<>(
injected.size(),
new AutoClosing(() -> {
closing.close();
field.set(reg, old);
}));
}
@Override
@@ -696,9 +689,31 @@ public class NMSBinding implements INMSBinding {
return overworld || nether || end;
}
@Override
public void removeCustomDimensions(World world) {
((CraftWorld) world).getHandle().K.customDimensions = null;
private WorldLoader.DataLoadContext supplier(WorldLoader.DataLoadContext old) {
return dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
));
}
@SneakyThrows
private AutoClosing inject(Function<WorldLoader.DataLoadContext, WorldLoader.DataLoadContext> transformer) {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, transformer.apply(old));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
}
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
@@ -722,7 +737,7 @@ public class NMSBinding implements INMSBinding {
if (copy) copy(fake, access.registryOrThrow(Registries.LEVEL_STEM));
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
}
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
@@ -672,44 +672,37 @@ public class NMSBinding implements INMSBinding {
}
@Override
@SneakyThrows
public AutoClosing injectLevelStems() {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
)));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
return inject(this::supplier);
}
@Override
@SneakyThrows
public AutoClosing injectUncached(boolean overworld, boolean nether, boolean end) {
public com.volmit.iris.core.nms.container.Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end) {
var reg = registry();
var field = getField(RegistryAccess.ImmutableRegistryAccess.class, Map.class);
field.setAccessible(true);
var access = createRegistryAccess(((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions(), true, overworld, nether, end);
var injected = access.registryOrThrow(Registries.LEVEL_STEM);
AutoClosing closing = inject(old -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), true, overworld, nether, end)
)
);
var injected = ((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM);
var old = (Map<ResourceKey<? extends Registry<?>>, Registry<?>>) field.get(reg);
var fake = new HashMap<>(old);
fake.put(Registries.LEVEL_STEM, injected);
field.set(reg, fake);
return new AutoClosing(() -> field.set(reg, old));
return new com.volmit.iris.core.nms.container.Pair<>(
injected.size(),
new AutoClosing(() -> {
closing.close();
field.set(reg, old);
}));
}
@Override
@@ -721,9 +714,31 @@ public class NMSBinding implements INMSBinding {
return overworld || nether || end;
}
@Override
public void removeCustomDimensions(World world) {
((CraftWorld) world).getHandle().K.customDimensions = null;
private WorldLoader.DataLoadContext supplier(WorldLoader.DataLoadContext old) {
return dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
));
}
@SneakyThrows
private AutoClosing inject(Function<WorldLoader.DataLoadContext, WorldLoader.DataLoadContext> transformer) {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, transformer.apply(old));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
}
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
@@ -747,7 +762,7 @@ public class NMSBinding implements INMSBinding {
if (copy) copy(fake, access.registryOrThrow(Registries.LEVEL_STEM));
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
}
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
@@ -676,44 +676,37 @@ public class NMSBinding implements INMSBinding {
}
@Override
@SneakyThrows
public AutoClosing injectLevelStems() {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
)));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
return inject(this::supplier);
}
@Override
@SneakyThrows
public AutoClosing injectUncached(boolean overworld, boolean nether, boolean end) {
public com.volmit.iris.core.nms.container.Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end) {
var reg = registry();
var field = getField(RegistryAccess.ImmutableRegistryAccess.class, Map.class);
field.setAccessible(true);
var access = createRegistryAccess(((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions(), true, overworld, nether, end);
var injected = access.registryOrThrow(Registries.LEVEL_STEM);
AutoClosing closing = inject(old -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), true, overworld, nether, end)
)
);
var injected = ((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions().registryOrThrow(Registries.LEVEL_STEM);
var old = (Map<ResourceKey<? extends Registry<?>>, Registry<?>>) field.get(reg);
var fake = new HashMap<>(old);
fake.put(Registries.LEVEL_STEM, injected);
field.set(reg, fake);
return new AutoClosing(() -> field.set(reg, old));
return new com.volmit.iris.core.nms.container.Pair<>(
injected.size(),
new AutoClosing(() -> {
closing.close();
field.set(reg, old);
}));
}
@Override
@@ -725,9 +718,31 @@ public class NMSBinding implements INMSBinding {
return overworld || nether || end;
}
@Override
public void removeCustomDimensions(World world) {
((CraftWorld) world).getHandle().K.customDimensions = null;
private WorldLoader.DataLoadContext supplier(WorldLoader.DataLoadContext old) {
return dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
));
}
@SneakyThrows
private AutoClosing inject(Function<WorldLoader.DataLoadContext, WorldLoader.DataLoadContext> transformer) {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, transformer.apply(old));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
}
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
@@ -751,7 +766,7 @@ public class NMSBinding implements INMSBinding {
if (copy) copy(fake, access.registryOrThrow(Registries.LEVEL_STEM));
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
}
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
@@ -666,44 +666,37 @@ public class NMSBinding implements INMSBinding {
}
@Override
@SneakyThrows
public AutoClosing injectLevelStems() {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
)));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
return inject(this::supplier);
}
@Override
@SneakyThrows
public AutoClosing injectUncached(boolean overworld, boolean nether, boolean end) {
public Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end) {
var reg = registry();
var field = getField(RegistryAccess.ImmutableRegistryAccess.class, Map.class);
field.setAccessible(true);
var access = createRegistryAccess(((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions(), true, overworld, nether, end);
var injected = access.lookupOrThrow(Registries.LEVEL_STEM);
AutoClosing closing = inject(old -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), true, overworld, nether, end)
)
);
var injected = ((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions().lookupOrThrow(Registries.LEVEL_STEM);
var old = (Map<ResourceKey<? extends Registry<?>>, Registry<?>>) field.get(reg);
var fake = new HashMap<>(old);
fake.put(Registries.LEVEL_STEM, injected);
field.set(reg, fake);
return new AutoClosing(() -> field.set(reg, old));
return new Pair<>(
injected.size(),
new AutoClosing(() -> {
closing.close();
field.set(reg, old);
}));
}
@Override
@@ -715,9 +708,31 @@ public class NMSBinding implements INMSBinding {
return overworld || nether || end;
}
@Override
public void removeCustomDimensions(World world) {
((CraftWorld) world).getHandle().L.customDimensions = null;
private WorldLoader.DataLoadContext supplier(WorldLoader.DataLoadContext old) {
return dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
));
}
@SneakyThrows
private AutoClosing inject(Function<WorldLoader.DataLoadContext, WorldLoader.DataLoadContext> transformer) {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, transformer.apply(old));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
}
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
@@ -741,7 +756,7 @@ public class NMSBinding implements INMSBinding {
if (copy) copy(fake, access.lookupOrThrow(Registries.LEVEL_STEM));
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
}
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
@@ -665,44 +665,37 @@ public class NMSBinding implements INMSBinding {
}
@Override
@SneakyThrows
public AutoClosing injectLevelStems() {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
)));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
return inject(this::supplier);
}
@Override
@SneakyThrows
public AutoClosing injectUncached(boolean overworld, boolean nether, boolean end) {
public Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end) {
var reg = registry();
var field = getField(RegistryAccess.ImmutableRegistryAccess.class, Map.class);
field.setAccessible(true);
var access = createRegistryAccess(((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions(), true, overworld, nether, end);
var injected = access.lookupOrThrow(Registries.LEVEL_STEM);
AutoClosing closing = inject(old -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), true, overworld, nether, end)
)
);
var injected = ((CraftServer) Bukkit.getServer()).getServer().worldLoader.datapackDimensions().lookupOrThrow(Registries.LEVEL_STEM);
var old = (Map<ResourceKey<? extends Registry<?>>, Registry<?>>) field.get(reg);
var fake = new HashMap<>(old);
fake.put(Registries.LEVEL_STEM, injected);
field.set(reg, fake);
return new AutoClosing(() -> field.set(reg, old));
return new Pair<>(
injected.size(),
new AutoClosing(() -> {
closing.close();
field.set(reg, old);
}));
}
@Override
@@ -714,9 +707,31 @@ public class NMSBinding implements INMSBinding {
return overworld || nether || end;
}
@Override
public void removeCustomDimensions(World world) {
((CraftWorld) world).getHandle().L.customDimensions = null;
private WorldLoader.DataLoadContext supplier(WorldLoader.DataLoadContext old) {
return dataLoadContext.aquire(() -> new WorldLoader.DataLoadContext(
old.resources(),
old.dataConfiguration(),
old.datapackWorldgen(),
createRegistryAccess(old.datapackDimensions(), false, true, true, true)
));
}
@SneakyThrows
private AutoClosing inject(Function<WorldLoader.DataLoadContext, WorldLoader.DataLoadContext> transformer) {
if (!dataContextLock.tryLock()) throw new IllegalStateException("Failed to inject data context!");
var server = ((CraftServer) Bukkit.getServer());
var field = getField(MinecraftServer.class, WorldLoader.DataLoadContext.class);
var nmsServer = server.getServer();
var old = nmsServer.worldLoader;
field.setAccessible(true);
field.set(nmsServer, transformer.apply(old));
return new AutoClosing(() -> {
field.set(nmsServer, old);
dataContextLock.unlock();
});
}
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
@@ -740,7 +755,7 @@ public class NMSBinding implements INMSBinding {
if (copy) copy(fake, access.lookupOrThrow(Registries.LEVEL_STEM));
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
}
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {