mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-05-20 00:20:24 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ab4770400e | |||
| 1a810d5d62 | |||
| 536d20bca7 | |||
| 9a691ac5b4 | |||
| 71078a20a9 | |||
| 74e2576ca2 | |||
| 407e51378c | |||
| c468eb1ab1 | |||
| bdb7cc61e5 | |||
| e8f9e841c4 | |||
| 1b1b9d97b7 | |||
| 24355064ff | |||
| 06a45056d9 |
+27
-6
@@ -1,3 +1,5 @@
|
||||
import xyz.jpenilla.runpaper.task.RunServer
|
||||
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||
@@ -30,10 +32,11 @@ 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.4-1.20.1-1.21.4'
|
||||
version '3.6.6-1.20.1-1.21.4'
|
||||
|
||||
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
|
||||
// ======================== WINDOWS =============================
|
||||
@@ -53,6 +56,11 @@ 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",
|
||||
@@ -62,21 +70,34 @@ 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.of()
|
||||
NMS_BINDINGS.each { nms ->
|
||||
project(":nms:${nms.key}") {
|
||||
def JVM_VERSION = Map.<String, Integer>of()
|
||||
NMS_BINDINGS.forEach { key, value ->
|
||||
project(":nms:$key") {
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'com.volmit.nmstools'
|
||||
|
||||
nmsTools {
|
||||
it.jvm = JVM_VERSION.getOrDefault(nms.key, 21)
|
||||
it.version = nms.value
|
||||
it.jvm = JVM_VERSION.getOrDefault(key, 21)
|
||||
it.version = 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 {
|
||||
|
||||
@@ -459,15 +459,17 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
|
||||
INMS.get();
|
||||
IO.delete(new File("iris"));
|
||||
compat = IrisCompat.configured(getDataFile("compat.json"));
|
||||
ServerConfigurator.configure();
|
||||
new IrisContextInjector();
|
||||
IrisSafeguard.IrisSafeguardSystem();
|
||||
getSender().setTag(getTag());
|
||||
compat = IrisCompat.configured(getDataFile("compat.json"));
|
||||
IrisSafeguard.earlySplash();
|
||||
linkMultiverseCore = new MultiverseCoreLink();
|
||||
linkMythicMobs = new MythicMobsLink();
|
||||
configWatcher = new FileWatcher(getDataFile("settings.json"));
|
||||
services.values().forEach(IrisService::onEnable);
|
||||
services.values().forEach(this::registerListener);
|
||||
registerListener(new IrisContextInjector());
|
||||
J.s(() -> {
|
||||
J.a(() -> PaperLib.suggestPaper(this));
|
||||
J.a(() -> IO.delete(getTemp()));
|
||||
|
||||
@@ -31,6 +31,7 @@ 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.format.C;
|
||||
import com.volmit.iris.util.misc.ServerProperties;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.Data;
|
||||
@@ -97,6 +98,7 @@ public class ServerConfigurator {
|
||||
}
|
||||
KList<File> worlds = new KList<>();
|
||||
Bukkit.getServer().getWorlds().forEach(w -> worlds.add(new File(w.getWorldFolder(), "datapacks")));
|
||||
if (worlds.isEmpty()) worlds.add(new File(Bukkit.getWorldContainer(), ServerProperties.LEVEL_NAME + "/datapacks"));
|
||||
return worlds;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ public class CommandDeveloper implements DecreeExecutor {
|
||||
public void packBenchmark(
|
||||
@Param(description = "The pack to bench", aliases = {"pack"}, defaultValue = "overworld")
|
||||
IrisDimension dimension,
|
||||
@Param(description = "Radius in regions", defaultValue = "5")
|
||||
@Param(description = "Radius in regions", defaultValue = "2048")
|
||||
int radius,
|
||||
@Param(description = "Open GUI while benchmarking", defaultValue = "false")
|
||||
boolean gui
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
package com.volmit.iris.core.commands;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.gui.PregeneratorJob;
|
||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.util.decree.DecreeExecutor;
|
||||
@@ -29,12 +27,9 @@ import com.volmit.iris.util.decree.annotations.Decree;
|
||||
import com.volmit.iris.util.decree.annotations.Param;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@Decree(name = "pregen", aliases = "pregenerate", description = "Pregenerate your Iris worlds!")
|
||||
public class CommandPregen implements DecreeExecutor {
|
||||
@Decree(description = "Pregenerate a world")
|
||||
@@ -52,13 +47,12 @@ public class CommandPregen implements DecreeExecutor {
|
||||
sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example.");
|
||||
}
|
||||
radius = Math.max(radius, 1024);
|
||||
int w = (radius >> 9 + 1) * 2;
|
||||
IrisToolbelt.pregenerate(PregenTask
|
||||
.builder()
|
||||
.center(new Position2(center.getBlockX() >> 9, center.getBlockZ() >> 9))
|
||||
.center(new Position2(center.getBlockX(), center.getBlockZ()))
|
||||
.gui(true)
|
||||
.width(w)
|
||||
.height(w)
|
||||
.radiusX(radius)
|
||||
.radiusZ(radius)
|
||||
.build(), world);
|
||||
String msg = C.GREEN + "Pregen started in " + C.GOLD + world.getName() + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ();
|
||||
sender().sendMessage(msg);
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.volmit.iris.core.pregenerator.IrisPregenerator;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.pregenerator.PregeneratorMethod;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
@@ -45,8 +44,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmarkInProgress;
|
||||
|
||||
public class PregeneratorJob implements PregenListener {
|
||||
private static final Color COLOR_EXISTS = parseColor("#4d7d5b");
|
||||
private static final Color COLOR_BLACK = parseColor("#4d7d5b");
|
||||
@@ -81,12 +78,12 @@ public class PregeneratorJob implements PregenListener {
|
||||
this.task = task;
|
||||
this.pregenerator = new IrisPregenerator(task, method, this);
|
||||
max = new Position2(0, 0);
|
||||
min = new Position2(0, 0);
|
||||
task.iterateRegions((xx, zz) -> {
|
||||
min.setX(Math.min(xx << 5, min.getX()));
|
||||
min.setZ(Math.min(zz << 5, min.getZ()));
|
||||
max.setX(Math.max((xx << 5) + 31, max.getX()));
|
||||
max.setZ(Math.max((zz << 5) + 31, max.getZ()));
|
||||
min = new Position2(Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
task.iterateAllChunks((xx, zz) -> {
|
||||
min.setX(Math.min(xx, min.getX()));
|
||||
min.setZ(Math.min(zz, min.getZ()));
|
||||
max.setX(Math.max(xx, max.getX()));
|
||||
max.setZ(Math.max(zz, max.getZ()));
|
||||
});
|
||||
|
||||
if (IrisSettings.get().getGui().isUseServerLaunchedGuis() && task.isGui()) {
|
||||
@@ -162,7 +159,7 @@ public class PregeneratorJob implements PregenListener {
|
||||
}
|
||||
|
||||
public void drawRegion(int x, int z, Color color) {
|
||||
J.a(() -> PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
J.a(() -> task.iterateChunks(x, z, (xx, zz) -> {
|
||||
draw(xx, zz, color);
|
||||
J.sleep(3);
|
||||
}));
|
||||
|
||||
@@ -37,7 +37,7 @@ public class INMS {
|
||||
"1.21.4", "v1_21_R3"
|
||||
);
|
||||
private static final List<Version> PACKS = List.of(
|
||||
new Version(21, 4, "31010"),
|
||||
new Version(21, 4, "31020"),
|
||||
new Version(21, 2, "31000"),
|
||||
new Version(20, 1, "3910")
|
||||
);
|
||||
|
||||
@@ -20,7 +20,6 @@ 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;
|
||||
@@ -32,15 +31,12 @@ import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.entity.Dolphin;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.structure.Structure;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
|
||||
public interface INMSBinding {
|
||||
@@ -93,7 +89,11 @@ public interface INMSBinding {
|
||||
MCABiomeContainer newBiomeContainer(int min, int max);
|
||||
|
||||
default World createWorld(WorldCreator c) {
|
||||
if (missingDimensionTypes(true, true, true))
|
||||
throw new IllegalStateException("Missing dimenstion types to create world");
|
||||
|
||||
try (var ignored = injectLevelStems()) {
|
||||
ignored.storeContext();
|
||||
return c.createWorld();
|
||||
}
|
||||
}
|
||||
@@ -130,11 +130,13 @@ public interface INMSBinding {
|
||||
|
||||
KList<String> getStructureKeys();
|
||||
|
||||
default AutoClosing injectLevelStems() {
|
||||
return new AutoClosing(() -> {});
|
||||
AutoClosing injectLevelStems();
|
||||
|
||||
default AutoClosing injectUncached(boolean overworld, boolean nether, boolean end) {
|
||||
return null;
|
||||
}
|
||||
|
||||
default Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end) {
|
||||
return new Pair<>(0, injectLevelStems());
|
||||
}
|
||||
boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end);
|
||||
|
||||
void removeCustomDimensions(World world);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.volmit.iris.core.nms.container;
|
||||
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.function.NastyRunnable;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@@ -7,6 +8,7 @@ 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;
|
||||
|
||||
@@ -14,9 +16,24 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,9 @@ package com.volmit.iris.core.nms.v1X;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMSBinding;
|
||||
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.engine.framework.Engine;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
@@ -118,6 +120,26 @@ public class NMSBinding1X implements INMSBinding {
|
||||
return new KList<>(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoClosing injectLevelStems() {
|
||||
return new AutoClosing(() -> {});
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoClosing injectUncached(boolean overworld, boolean nether, boolean end) {
|
||||
return injectLevelStems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomDimensions(World world) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeEntity(Entity location) {
|
||||
return null;
|
||||
|
||||
@@ -165,8 +165,11 @@ public class ChunkUpdater {
|
||||
if (rX < dimensions.min.getX() || rX > dimensions.max.getX() || rZ < dimensions.min.getZ() || rZ > dimensions.max.getZ()) {
|
||||
return;
|
||||
}
|
||||
if (!new File(world.getWorldFolder(), "region" + File.separator + rX + "." + rZ + ".mca").exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PregenTask.iterateRegion(rX, rZ, (x, z) -> {
|
||||
task.iterateChunks(rX, rZ, (x, z) -> {
|
||||
while (paused.get() && !cancelled.get()) {
|
||||
J.sleep(50);
|
||||
}
|
||||
@@ -348,8 +351,8 @@ public class ChunkUpdater {
|
||||
int width = maxZ - minZ + 1;
|
||||
|
||||
return new Dimensions(new Position2(minX, minZ), new Position2(maxX, maxZ), height * width, PregenTask.builder()
|
||||
.width((int) Math.ceil(width / 2d))
|
||||
.height((int) Math.ceil(height / 2d))
|
||||
.radiusZ((int) Math.ceil(width / 2d * 512))
|
||||
.radiusX((int) Math.ceil(height / 2d * 512))
|
||||
.center(new Position2(oX, oZ))
|
||||
.build());
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
package com.volmit.iris.core.pregenerator;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.pack.IrisPack;
|
||||
import com.volmit.iris.core.tools.IrisPackBenchmarking;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
@@ -83,7 +82,7 @@ public class IrisPregenerator {
|
||||
generatedLast = new AtomicInteger(0);
|
||||
generatedLastMinute = new AtomicInteger(0);
|
||||
totalChunks = new AtomicInteger(0);
|
||||
task.iterateRegions((_a, _b) -> totalChunks.addAndGet(1024));
|
||||
task.iterateAllChunks((_a, _b) -> totalChunks.incrementAndGet());
|
||||
startTime = new AtomicLong(M.ms());
|
||||
ticker = new Looper() {
|
||||
@Override
|
||||
@@ -194,7 +193,7 @@ public class IrisPregenerator {
|
||||
} else if (!regions) {
|
||||
hit = true;
|
||||
listener.onRegionGenerating(x, z);
|
||||
PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
task.iterateChunks(x, z, (xx, zz) -> {
|
||||
while (paused.get() && !shutdown.get()) {
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
@@ -32,17 +32,26 @@ import java.util.Comparator;
|
||||
@Data
|
||||
public class PregenTask {
|
||||
private static final Position2 ZERO = new Position2(0, 0);
|
||||
private static final KList<Position2> ORDER_CENTER = computeChunkOrder();
|
||||
private static final KMap<Position2, KList<Position2>> ORDERS = new KMap<>();
|
||||
|
||||
@Builder.Default
|
||||
private boolean gui = false;
|
||||
private final boolean gui = false;
|
||||
@Builder.Default
|
||||
private Position2 center = new Position2(0, 0);
|
||||
private final Position2 center = new Position2(0, 0);
|
||||
@Builder.Default
|
||||
private int width = 1;
|
||||
private final int radiusX = 1;
|
||||
@Builder.Default
|
||||
private int height = 1;
|
||||
private final int radiusZ = 1;
|
||||
|
||||
private final Bounds bounds = new Bounds();
|
||||
|
||||
protected PregenTask(boolean gui, Position2 center, int radiusX, int radiusZ) {
|
||||
this.gui = gui;
|
||||
this.center = new ProxiedPos(center);
|
||||
this.radiusX = radiusX;
|
||||
this.radiusZ = radiusZ;
|
||||
bounds.update();
|
||||
}
|
||||
|
||||
public static void iterateRegion(int xr, int zr, Spiraled s, Position2 pull) {
|
||||
for (Position2 i : ORDERS.computeIfAbsent(pull, PregenTask::computeOrder)) {
|
||||
@@ -70,29 +79,72 @@ public class PregenTask {
|
||||
return p;
|
||||
}
|
||||
|
||||
private static KList<Position2> computeChunkOrder() {
|
||||
Position2 center = new Position2(15, 15);
|
||||
KList<Position2> p = new KList<>();
|
||||
new Spiraler(33, 33, (x, z) -> {
|
||||
int xx = x + 15;
|
||||
int zz = z + 15;
|
||||
if (xx < 0 || xx > 31 || zz < 0 || zz > 31) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.add(new Position2(xx, zz));
|
||||
}).drain();
|
||||
p.sort(Comparator.comparing((i) -> i.distance(center)));
|
||||
return p;
|
||||
public void iterateRegions(Spiraled s) {
|
||||
var bound = bounds.region();
|
||||
new Spiraler(bound.sizeX, bound.sizeZ, ((x, z) -> {
|
||||
if (bound.check(x, z)) s.on(x, z);
|
||||
})).setOffset(center.getX() >> 9, center.getZ() >> 9).drain();
|
||||
}
|
||||
|
||||
public void iterateRegions(Spiraled s) {
|
||||
new Spiraler(getWidth() * 2, getHeight() * 2, s)
|
||||
.setOffset(center.getX(), center.getZ()).drain();
|
||||
public void iterateChunks(int rX, int rZ, Spiraled s) {
|
||||
var bound = bounds.chunk();
|
||||
iterateRegion(rX, rZ, ((x, z) -> {
|
||||
if (bound.check(x, z)) s.on(x, z);
|
||||
}));
|
||||
}
|
||||
|
||||
public void iterateAllChunks(Spiraled s) {
|
||||
new Spiraler(getWidth() * 2, getHeight() * 2, (x, z) -> iterateRegion(x, z, s))
|
||||
.setOffset(center.getX(), center.getZ()).drain();
|
||||
iterateRegions(((rX, rZ) -> iterateChunks(rX, rZ, s)));
|
||||
}
|
||||
|
||||
private class Bounds {
|
||||
private Bound chunk = null;
|
||||
private Bound region = null;
|
||||
|
||||
public void update() {
|
||||
int maxX = center.getX() + radiusX;
|
||||
int maxZ = center.getZ() + radiusZ;
|
||||
int minX = center.getX() - radiusX;
|
||||
int minZ = center.getZ() - radiusZ;
|
||||
|
||||
chunk = new Bound(minX >> 4, minZ >> 4, Math.ceilDiv(maxX, 16), Math.ceilDiv(maxZ, 16));
|
||||
region = new Bound(minX >> 9, minZ >> 9, Math.ceilDiv(maxX, 512), Math.ceilDiv(maxZ, 512));
|
||||
}
|
||||
|
||||
public Bound chunk() {
|
||||
if (chunk == null) update();
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public Bound region() {
|
||||
if (region == null) update();
|
||||
return region;
|
||||
}
|
||||
}
|
||||
|
||||
private record Bound(int minX, int maxX, int minZ, int maxZ, int sizeX, int sizeZ) {
|
||||
private Bound(int minX, int minZ, int maxX, int maxZ) {
|
||||
this(minX, maxX, minZ, maxZ, maxZ - minZ + 1, maxZ - minZ + 1);
|
||||
}
|
||||
|
||||
boolean check(int x, int z) {
|
||||
return x >= minX && x <= maxX && z >= minZ && z <= maxZ;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ProxiedPos extends Position2 {
|
||||
public ProxiedPos(Position2 p) {
|
||||
super(p.getX(), p.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setX(int x) {
|
||||
throw new IllegalStateException("This Position2 may not be modified");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZ(int z) {
|
||||
throw new IllegalStateException("This Position2 may not be modified");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.volmit.iris.core.safeguard;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
|
||||
public class IrisSafeguard {
|
||||
public static boolean unstablemode = false;
|
||||
@@ -11,5 +12,13 @@ public class IrisSafeguard {
|
||||
Iris.info("Enabled Iris SafeGuard");
|
||||
ServerBootSFG.BootCheck();
|
||||
}
|
||||
|
||||
public static void earlySplash() {
|
||||
if (ServerBootSFG.safeguardPassed || IrisSettings.get().getGeneral().DoomsdayAnnihilationSelfDestructMode)
|
||||
return;
|
||||
|
||||
Iris.instance.splash();
|
||||
UtilsSFG.splash();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.volmit.iris.core.safeguard;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import com.volmit.iris.engine.object.IrisContextInjector;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
@@ -29,6 +30,7 @@ public class ServerBootSFG {
|
||||
public static boolean isJRE = false;
|
||||
public static boolean hasPrivileges = true;
|
||||
public static boolean unsuportedversion = false;
|
||||
public static boolean missingDimensionTypes = false;
|
||||
protected static boolean safeguardPassed;
|
||||
public static boolean passedserversoftware = true;
|
||||
protected static int count;
|
||||
@@ -110,6 +112,12 @@ public class ServerBootSFG {
|
||||
severityMedium++;
|
||||
}
|
||||
|
||||
if (IrisContextInjector.isMissingDimensionTypes()) {
|
||||
missingDimensionTypes = true;
|
||||
joiner.add("Missing Dimension Types");
|
||||
severityHigh++;
|
||||
}
|
||||
|
||||
allIncompatibilities = joiner.toString();
|
||||
|
||||
safeguardPassed = (severityHigh == 0 && severityMedium == 0 && severityLow == 0);
|
||||
|
||||
@@ -39,6 +39,11 @@ public class UtilsSFG {
|
||||
Iris.safeguard(C.RED + "Server Version");
|
||||
Iris.safeguard(C.RED + "- Iris only supports 1.20.1 > 1.21.4");
|
||||
}
|
||||
if (ServerBootSFG.missingDimensionTypes) {
|
||||
Iris.safeguard(C.RED + "Dimension Types");
|
||||
Iris.safeguard(C.RED + "- Required Iris dimension types were not loaded.");
|
||||
Iris.safeguard(C.RED + "- If this still happens after a restart please contact support.");
|
||||
}
|
||||
if (!ServerBootSFG.passedserversoftware) {
|
||||
Iris.safeguard(C.YELLOW + "Unsupported Server Software");
|
||||
Iris.safeguard(C.YELLOW + "- Please consider using Paper or Purpur instead.");
|
||||
|
||||
@@ -146,8 +146,8 @@ public class IrisPackBenchmarking {
|
||||
IrisToolbelt.pregenerate(PregenTask
|
||||
.builder()
|
||||
.gui(gui)
|
||||
.width(radius)
|
||||
.height(radius)
|
||||
.radiusX(radius)
|
||||
.radiusZ(radius)
|
||||
.build(), Bukkit.getWorld("benchmark")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,11 +2,15 @@ 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;
|
||||
|
||||
@@ -15,15 +19,12 @@ import java.util.List;
|
||||
import static com.volmit.iris.Iris.instance;
|
||||
|
||||
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()) {
|
||||
totalWorlds = 0;
|
||||
return;
|
||||
}
|
||||
if (!Bukkit.getWorlds().isEmpty()) return;
|
||||
|
||||
String levelName = ServerProperties.LEVEL_NAME;
|
||||
List<String> irisWorlds = irisWorlds();
|
||||
@@ -31,22 +32,20 @@ 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 (overworld || nether || end) {
|
||||
var pair = INMS.get().injectUncached(overworld, nether, end);
|
||||
i += pair.getA() - 3;
|
||||
autoClosing = pair.getB();
|
||||
if (INMS.get().missingDimensionTypes(overworld, nether, end)) {
|
||||
missingDimensionTypes = true;
|
||||
return;
|
||||
}
|
||||
|
||||
totalWorlds = i;
|
||||
if (overworld || nether || end) {
|
||||
autoClosing = INMS.get().injectUncached(overworld, nether, end);
|
||||
}
|
||||
|
||||
instance.registerListener(this);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void on(WorldInitEvent event) {
|
||||
if (++worldCounter < totalWorlds) return;
|
||||
if (autoClosing != null) {
|
||||
autoClosing.close();
|
||||
autoClosing = null;
|
||||
|
||||
@@ -21,6 +21,7 @@ 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;
|
||||
@@ -48,6 +49,7 @@ 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;
|
||||
@@ -122,11 +124,13 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
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,6 +26,8 @@ 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> {
|
||||
@@ -65,6 +67,10 @@ 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>();
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ public class Spiraler {
|
||||
|
||||
public void next() {
|
||||
if ((-sizeX / 2 <= x) && (x <= sizeX / 2) && (-sizeZ / 2 <= z) && (z <= sizeZ / 2)) {
|
||||
spiraled.on(x + ox, z + ox);
|
||||
spiraled.on(x + ox, z + oz);
|
||||
}
|
||||
|
||||
if ((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z))) {
|
||||
|
||||
@@ -10,7 +10,7 @@ public class ServerProperties {
|
||||
public static final File SERVER_PROPERTIES;
|
||||
public static final File BUKKIT_YML;
|
||||
|
||||
public static final String LEVEL_NAME = DATA.getProperty("level-name", "world");
|
||||
public static final String LEVEL_NAME;
|
||||
|
||||
static {
|
||||
String[] args = ProcessHandle.current()
|
||||
@@ -20,11 +20,13 @@ public class ServerProperties {
|
||||
|
||||
String propertiesPath = "server.properties";
|
||||
String bukkitYml = "bukkit.yml";
|
||||
String levelName = null;
|
||||
|
||||
for (int i = 0; i < args.length - 1; i++) {
|
||||
switch (args[i]) {
|
||||
case "-c", "--config" -> propertiesPath = args[i + 1];
|
||||
case "-b", "--bukkit-settings" -> bukkitYml = args[i + 1];
|
||||
case "-w", "--level-name", "--world" -> levelName = args[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,5 +37,8 @@ public class ServerProperties {
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if (levelName != null) LEVEL_NAME = levelName;
|
||||
else LEVEL_NAME = DATA.getProperty("level-name", "world");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,9 @@ import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.entity.EntityDimensions;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
@@ -47,6 +49,9 @@ import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLayerInfo;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -640,50 +645,8 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public AutoClosing injectLevelStems() {
|
||||
return inject(this::supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
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);
|
||||
|
||||
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 com.volmit.iris.core.nms.container.Pair<>(
|
||||
injected.size(),
|
||||
new AutoClosing(() -> {
|
||||
closing.close();
|
||||
field.set(reg, old);
|
||||
}));
|
||||
}
|
||||
|
||||
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());
|
||||
@@ -692,7 +655,12 @@ public class NMSBinding implements INMSBinding {
|
||||
var old = nmsServer.worldLoader;
|
||||
|
||||
field.setAccessible(true);
|
||||
field.set(nmsServer, transformer.apply(old));
|
||||
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);
|
||||
@@ -700,26 +668,66 @@ public class NMSBinding implements INMSBinding {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public 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);
|
||||
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));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end) {
|
||||
var registry = registry().registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
if (overworld) overworld = !registry.containsKey(createIrisKey(LevelStem.OVERWORLD));
|
||||
if (nether) nether = !registry.containsKey(createIrisKey(LevelStem.NETHER));
|
||||
if (end) end = !registry.containsKey(createIrisKey(LevelStem.END));
|
||||
return overworld || nether || end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomDimensions(World world) {
|
||||
((CraftWorld) world).getHandle().K.customDimensions = null;
|
||||
}
|
||||
|
||||
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
|
||||
var access = registry();
|
||||
var dimensions = access.registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
var levelStems = access.registryOrThrow(Registries.LEVEL_STEM);
|
||||
|
||||
var settings = new FlatLevelGeneratorSettings(
|
||||
Optional.empty(),
|
||||
access.lookupOrThrow(Registries.BIOME).getOrThrow(Biomes.THE_VOID),
|
||||
List.of()
|
||||
);
|
||||
settings.getLayersInfo().add(new FlatLayerInfo(1, Blocks.AIR));
|
||||
settings.updateLayers();
|
||||
|
||||
var source = new FlatLevelSource(settings);
|
||||
var fake = new MappedRegistry<>(Registries.LEVEL_STEM, Lifecycle.experimental());
|
||||
if (overworld) register(fake, levelStems, dimensions, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, levelStems, dimensions, LevelStem.NETHER);
|
||||
if (end) register(fake, levelStems, dimensions, LevelStem.END);
|
||||
if (overworld) register(fake, dimensions, source, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, dimensions, source, LevelStem.NETHER);
|
||||
if (end) register(fake, dimensions, source, LevelStem.END);
|
||||
copy(fake, datapack.registry(Registries.LEVEL_STEM).orElse(null));
|
||||
|
||||
if (copy) copy(fake, levelStems);
|
||||
if (copy) copy(fake, access.registryOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
|
||||
}
|
||||
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<LevelStem> levelStems, Registry<DimensionType> dimensions, ResourceKey<LevelStem> key) {
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
|
||||
var loc = createIrisKey(key);
|
||||
target.register(key, new LevelStem(
|
||||
dimensions.getHolderOrThrow(ResourceKey.create(Registries.DIMENSION_TYPE, new ResourceLocation("iris", key.location().getPath()))),
|
||||
levelStems.getOrThrow(key).generator()
|
||||
dimensions.getHolder(ResourceKey.create(Registries.DIMENSION_TYPE, loc)).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), Lifecycle.stable());
|
||||
}
|
||||
|
||||
@@ -732,4 +740,8 @@ public class NMSBinding implements INMSBinding {
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return new ResourceLocation("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,14 @@ import net.minecraft.server.WorldLoader;
|
||||
import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLayerInfo;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -641,50 +646,8 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public AutoClosing injectLevelStems() {
|
||||
return inject(this::supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
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);
|
||||
|
||||
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 com.volmit.iris.core.nms.container.Pair<>(
|
||||
injected.size(),
|
||||
new AutoClosing(() -> {
|
||||
closing.close();
|
||||
field.set(reg, old);
|
||||
}));
|
||||
}
|
||||
|
||||
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());
|
||||
@@ -693,7 +656,12 @@ public class NMSBinding implements INMSBinding {
|
||||
var old = nmsServer.worldLoader;
|
||||
|
||||
field.setAccessible(true);
|
||||
field.set(nmsServer, transformer.apply(old));
|
||||
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);
|
||||
@@ -701,26 +669,66 @@ public class NMSBinding implements INMSBinding {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public 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);
|
||||
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));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end) {
|
||||
var registry = registry().registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
if (overworld) overworld = !registry.containsKey(createIrisKey(LevelStem.OVERWORLD));
|
||||
if (nether) nether = !registry.containsKey(createIrisKey(LevelStem.NETHER));
|
||||
if (end) end = !registry.containsKey(createIrisKey(LevelStem.END));
|
||||
return overworld || nether || end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomDimensions(World world) {
|
||||
((CraftWorld) world).getHandle().K.customDimensions = null;
|
||||
}
|
||||
|
||||
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
|
||||
var access = registry();
|
||||
var dimensions = access.registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
var levelStems = access.registryOrThrow(Registries.LEVEL_STEM);
|
||||
|
||||
var settings = new FlatLevelGeneratorSettings(
|
||||
Optional.empty(),
|
||||
access.lookupOrThrow(Registries.BIOME).getOrThrow(Biomes.THE_VOID),
|
||||
List.of()
|
||||
);
|
||||
settings.getLayersInfo().add(new FlatLayerInfo(1, Blocks.AIR));
|
||||
settings.updateLayers();
|
||||
|
||||
var source = new FlatLevelSource(settings);
|
||||
var fake = new MappedRegistry<>(Registries.LEVEL_STEM, Lifecycle.experimental());
|
||||
if (overworld) register(fake, levelStems, dimensions, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, levelStems, dimensions, LevelStem.NETHER);
|
||||
if (end) register(fake, levelStems, dimensions, LevelStem.END);
|
||||
if (overworld) register(fake, dimensions, source, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, dimensions, source, LevelStem.NETHER);
|
||||
if (end) register(fake, dimensions, source, LevelStem.END);
|
||||
copy(fake, datapack.registry(Registries.LEVEL_STEM).orElse(null));
|
||||
|
||||
if (copy) copy(fake, levelStems);
|
||||
if (copy) copy(fake, access.registryOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
|
||||
}
|
||||
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<LevelStem> levelStems, Registry<DimensionType> dimensions, ResourceKey<LevelStem> key) {
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
|
||||
var loc = createIrisKey(key);
|
||||
target.register(key, new LevelStem(
|
||||
dimensions.getHolderOrThrow(ResourceKey.create(Registries.DIMENSION_TYPE, new ResourceLocation("iris", key.location().getPath()))),
|
||||
levelStems.getOrThrow(key).generator()
|
||||
dimensions.getHolder(ResourceKey.create(Registries.DIMENSION_TYPE, loc)).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), Lifecycle.stable());
|
||||
}
|
||||
|
||||
@@ -733,4 +741,8 @@ public class NMSBinding implements INMSBinding {
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return new ResourceLocation("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,14 @@ import net.minecraft.server.WorldLoader;
|
||||
import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLayerInfo;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -642,50 +647,8 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public AutoClosing injectLevelStems() {
|
||||
return inject(this::supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
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);
|
||||
|
||||
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 com.volmit.iris.core.nms.container.Pair<>(
|
||||
injected.size(),
|
||||
new AutoClosing(() -> {
|
||||
closing.close();
|
||||
field.set(reg, old);
|
||||
}));
|
||||
}
|
||||
|
||||
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());
|
||||
@@ -694,7 +657,12 @@ public class NMSBinding implements INMSBinding {
|
||||
var old = nmsServer.worldLoader;
|
||||
|
||||
field.setAccessible(true);
|
||||
field.set(nmsServer, transformer.apply(old));
|
||||
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);
|
||||
@@ -702,26 +670,66 @@ public class NMSBinding implements INMSBinding {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public 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);
|
||||
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));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end) {
|
||||
var registry = registry().registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
if (overworld) overworld = !registry.containsKey(createIrisKey(LevelStem.OVERWORLD));
|
||||
if (nether) nether = !registry.containsKey(createIrisKey(LevelStem.NETHER));
|
||||
if (end) end = !registry.containsKey(createIrisKey(LevelStem.END));
|
||||
return overworld || nether || end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomDimensions(World world) {
|
||||
((CraftWorld) world).getHandle().K.customDimensions = null;
|
||||
}
|
||||
|
||||
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
|
||||
var access = registry();
|
||||
var dimensions = access.registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
var levelStems = access.registryOrThrow(Registries.LEVEL_STEM);
|
||||
|
||||
var settings = new FlatLevelGeneratorSettings(
|
||||
Optional.empty(),
|
||||
access.lookupOrThrow(Registries.BIOME).getOrThrow(Biomes.THE_VOID),
|
||||
List.of()
|
||||
);
|
||||
settings.getLayersInfo().add(new FlatLayerInfo(1, Blocks.AIR));
|
||||
settings.updateLayers();
|
||||
|
||||
var source = new FlatLevelSource(settings);
|
||||
var fake = new MappedRegistry<>(Registries.LEVEL_STEM, Lifecycle.experimental());
|
||||
if (overworld) register(fake, levelStems, dimensions, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, levelStems, dimensions, LevelStem.NETHER);
|
||||
if (end) register(fake, levelStems, dimensions, LevelStem.END);
|
||||
if (overworld) register(fake, dimensions, source, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, dimensions, source, LevelStem.NETHER);
|
||||
if (end) register(fake, dimensions, source, LevelStem.END);
|
||||
copy(fake, datapack.registry(Registries.LEVEL_STEM).orElse(null));
|
||||
|
||||
if (copy) copy(fake, levelStems);
|
||||
if (copy) copy(fake, access.registryOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
|
||||
}
|
||||
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<LevelStem> levelStems, Registry<DimensionType> dimensions, ResourceKey<LevelStem> key) {
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
|
||||
var loc = createIrisKey(key);
|
||||
target.register(key, new LevelStem(
|
||||
dimensions.getHolderOrThrow(ResourceKey.create(Registries.DIMENSION_TYPE, new ResourceLocation("iris", key.location().getPath()))),
|
||||
levelStems.getOrThrow(key).generator()
|
||||
dimensions.getHolder(ResourceKey.create(Registries.DIMENSION_TYPE, loc)).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), Lifecycle.stable());
|
||||
}
|
||||
|
||||
@@ -734,4 +742,8 @@ public class NMSBinding implements INMSBinding {
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return new ResourceLocation("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +38,16 @@ import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.component.CustomData;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
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.levelgen.FlatLevelSource;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLayerInfo;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -667,50 +672,8 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public AutoClosing injectLevelStems() {
|
||||
return inject(this::supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
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);
|
||||
|
||||
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 com.volmit.iris.core.nms.container.Pair<>(
|
||||
injected.size(),
|
||||
new AutoClosing(() -> {
|
||||
closing.close();
|
||||
field.set(reg, old);
|
||||
}));
|
||||
}
|
||||
|
||||
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());
|
||||
@@ -719,7 +682,12 @@ public class NMSBinding implements INMSBinding {
|
||||
var old = nmsServer.worldLoader;
|
||||
|
||||
field.setAccessible(true);
|
||||
field.set(nmsServer, transformer.apply(old));
|
||||
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);
|
||||
@@ -727,26 +695,66 @@ public class NMSBinding implements INMSBinding {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public 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);
|
||||
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));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end) {
|
||||
var registry = registry().registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
if (overworld) overworld = !registry.containsKey(createIrisKey(LevelStem.OVERWORLD));
|
||||
if (nether) nether = !registry.containsKey(createIrisKey(LevelStem.NETHER));
|
||||
if (end) end = !registry.containsKey(createIrisKey(LevelStem.END));
|
||||
return overworld || nether || end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomDimensions(World world) {
|
||||
((CraftWorld) world).getHandle().K.customDimensions = null;
|
||||
}
|
||||
|
||||
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
|
||||
var access = registry();
|
||||
var dimensions = access.registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
var levelStems = access.registryOrThrow(Registries.LEVEL_STEM);
|
||||
|
||||
var settings = new FlatLevelGeneratorSettings(
|
||||
Optional.empty(),
|
||||
access.lookupOrThrow(Registries.BIOME).getOrThrow(Biomes.THE_VOID),
|
||||
List.of()
|
||||
);
|
||||
settings.getLayersInfo().add(new FlatLayerInfo(1, Blocks.AIR));
|
||||
settings.updateLayers();
|
||||
|
||||
var source = new FlatLevelSource(settings);
|
||||
var fake = new MappedRegistry<>(Registries.LEVEL_STEM, Lifecycle.experimental());
|
||||
if (overworld) register(fake, levelStems, dimensions, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, levelStems, dimensions, LevelStem.NETHER);
|
||||
if (end) register(fake, levelStems, dimensions, LevelStem.END);
|
||||
if (overworld) register(fake, dimensions, source, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, dimensions, source, LevelStem.NETHER);
|
||||
if (end) register(fake, dimensions, source, LevelStem.END);
|
||||
copy(fake, datapack.registry(Registries.LEVEL_STEM).orElse(null));
|
||||
|
||||
if (copy) copy(fake, levelStems);
|
||||
if (copy) copy(fake, access.registryOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
|
||||
}
|
||||
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<LevelStem> levelStems, Registry<DimensionType> dimensions, ResourceKey<LevelStem> key) {
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
|
||||
var loc = createIrisKey(key);
|
||||
target.register(key, new LevelStem(
|
||||
dimensions.getHolder(new ResourceLocation("iris", key.location().getPath())).orElseThrow(),
|
||||
levelStems.getOrThrow(key).generator()
|
||||
dimensions.getHolder(ResourceKey.create(Registries.DIMENSION_TYPE, loc)).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), RegistrationInfo.BUILT_IN);
|
||||
}
|
||||
|
||||
@@ -759,4 +767,8 @@ public class NMSBinding implements INMSBinding {
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return new ResourceLocation("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,16 @@ import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.component.CustomData;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.status.WorldGenContext;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLayerInfo;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -671,50 +676,8 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public AutoClosing injectLevelStems() {
|
||||
return inject(this::supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
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);
|
||||
|
||||
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 com.volmit.iris.core.nms.container.Pair<>(
|
||||
injected.size(),
|
||||
new AutoClosing(() -> {
|
||||
closing.close();
|
||||
field.set(reg, old);
|
||||
}));
|
||||
}
|
||||
|
||||
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());
|
||||
@@ -723,7 +686,12 @@ public class NMSBinding implements INMSBinding {
|
||||
var old = nmsServer.worldLoader;
|
||||
|
||||
field.setAccessible(true);
|
||||
field.set(nmsServer, transformer.apply(old));
|
||||
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);
|
||||
@@ -731,26 +699,66 @@ public class NMSBinding implements INMSBinding {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public 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);
|
||||
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));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end) {
|
||||
var registry = registry().registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
if (overworld) overworld = !registry.containsKey(createIrisKey(LevelStem.OVERWORLD));
|
||||
if (nether) nether = !registry.containsKey(createIrisKey(LevelStem.NETHER));
|
||||
if (end) end = !registry.containsKey(createIrisKey(LevelStem.END));
|
||||
return overworld || nether || end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomDimensions(World world) {
|
||||
((CraftWorld) world).getHandle().K.customDimensions = null;
|
||||
}
|
||||
|
||||
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
|
||||
var access = registry();
|
||||
var dimensions = access.registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
var levelStems = access.registryOrThrow(Registries.LEVEL_STEM);
|
||||
|
||||
var settings = new FlatLevelGeneratorSettings(
|
||||
Optional.empty(),
|
||||
access.lookupOrThrow(Registries.BIOME).getOrThrow(Biomes.THE_VOID),
|
||||
List.of()
|
||||
);
|
||||
settings.getLayersInfo().add(new FlatLayerInfo(1, Blocks.AIR));
|
||||
settings.updateLayers();
|
||||
|
||||
var source = new FlatLevelSource(settings);
|
||||
var fake = new MappedRegistry<>(Registries.LEVEL_STEM, Lifecycle.experimental());
|
||||
if (overworld) register(fake, levelStems, dimensions, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, levelStems, dimensions, LevelStem.NETHER);
|
||||
if (end) register(fake, levelStems, dimensions, LevelStem.END);
|
||||
if (overworld) register(fake, dimensions, source, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, dimensions, source, LevelStem.NETHER);
|
||||
if (end) register(fake, dimensions, source, LevelStem.END);
|
||||
copy(fake, datapack.registry(Registries.LEVEL_STEM).orElse(null));
|
||||
|
||||
if (copy) copy(fake, levelStems);
|
||||
if (copy) copy(fake, access.registryOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
|
||||
}
|
||||
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<LevelStem> levelStems, Registry<DimensionType> dimensions, ResourceKey<LevelStem> key) {
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
|
||||
var loc = createIrisKey(key);
|
||||
target.register(key, new LevelStem(
|
||||
dimensions.getHolder(ResourceLocation.fromNamespaceAndPath("iris", key.location().getPath())).orElseThrow(),
|
||||
levelStems.getOrThrow(key).generator()
|
||||
dimensions.getHolder(ResourceKey.create(Registries.DIMENSION_TYPE, loc)).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), RegistrationInfo.BUILT_IN);
|
||||
}
|
||||
|
||||
@@ -763,4 +771,8 @@ public class NMSBinding implements INMSBinding {
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return ResourceLocation.fromNamespaceAndPath("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,11 +27,16 @@ import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.component.CustomData;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.status.WorldGenContext;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLayerInfo;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -661,50 +666,8 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public AutoClosing injectLevelStems() {
|
||||
return inject(this::supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
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);
|
||||
|
||||
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 Pair<>(
|
||||
injected.size(),
|
||||
new AutoClosing(() -> {
|
||||
closing.close();
|
||||
field.set(reg, old);
|
||||
}));
|
||||
}
|
||||
|
||||
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());
|
||||
@@ -713,7 +676,12 @@ public class NMSBinding implements INMSBinding {
|
||||
var old = nmsServer.worldLoader;
|
||||
|
||||
field.setAccessible(true);
|
||||
field.set(nmsServer, transformer.apply(old));
|
||||
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);
|
||||
@@ -721,26 +689,66 @@ public class NMSBinding implements INMSBinding {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public 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);
|
||||
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));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end) {
|
||||
var registry = registry().lookupOrThrow(Registries.DIMENSION_TYPE);
|
||||
if (overworld) overworld = !registry.containsKey(createIrisKey(LevelStem.OVERWORLD));
|
||||
if (nether) nether = !registry.containsKey(createIrisKey(LevelStem.NETHER));
|
||||
if (end) end = !registry.containsKey(createIrisKey(LevelStem.END));
|
||||
return overworld || nether || end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomDimensions(World world) {
|
||||
((CraftWorld) world).getHandle().L.customDimensions = null;
|
||||
}
|
||||
|
||||
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
|
||||
var access = registry();
|
||||
var dimensions = access.lookupOrThrow(Registries.DIMENSION_TYPE);
|
||||
var levelStems = access.lookupOrThrow(Registries.LEVEL_STEM);
|
||||
|
||||
var settings = new FlatLevelGeneratorSettings(
|
||||
Optional.empty(),
|
||||
access.lookupOrThrow(Registries.BIOME).getOrThrow(Biomes.THE_VOID),
|
||||
List.of()
|
||||
);
|
||||
settings.getLayersInfo().add(new FlatLayerInfo(1, Blocks.AIR));
|
||||
settings.updateLayers();
|
||||
|
||||
var source = new FlatLevelSource(settings);
|
||||
var fake = new MappedRegistry<>(Registries.LEVEL_STEM, Lifecycle.experimental());
|
||||
if (overworld) register(fake, levelStems, dimensions, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, levelStems, dimensions, LevelStem.NETHER);
|
||||
if (end) register(fake, levelStems, dimensions, LevelStem.END);
|
||||
if (overworld) register(fake, dimensions, source, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, dimensions, source, LevelStem.NETHER);
|
||||
if (end) register(fake, dimensions, source, LevelStem.END);
|
||||
copy(fake, datapack.lookup(Registries.LEVEL_STEM).orElse(null));
|
||||
|
||||
if (copy) copy(fake, levelStems);
|
||||
if (copy) copy(fake, access.lookupOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
|
||||
}
|
||||
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<LevelStem> levelStems, Registry<DimensionType> dimensions, ResourceKey<LevelStem> key) {
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
|
||||
var loc = createIrisKey(key);
|
||||
target.register(key, new LevelStem(
|
||||
dimensions.get(ResourceLocation.fromNamespaceAndPath("iris", key.location().getPath())).orElseThrow(),
|
||||
levelStems.getValueOrThrow(key).generator()
|
||||
dimensions.get(loc).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), RegistrationInfo.BUILT_IN);
|
||||
}
|
||||
|
||||
@@ -753,4 +761,8 @@ public class NMSBinding implements INMSBinding {
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return ResourceLocation.fromNamespaceAndPath("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,9 @@ import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.item.component.CustomData;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
@@ -49,6 +51,9 @@ import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.status.WorldGenContext;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLayerInfo;
|
||||
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -660,50 +665,8 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public AutoClosing injectLevelStems() {
|
||||
return inject(this::supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
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);
|
||||
|
||||
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 Pair<>(
|
||||
injected.size(),
|
||||
new AutoClosing(() -> {
|
||||
closing.close();
|
||||
field.set(reg, old);
|
||||
}));
|
||||
}
|
||||
|
||||
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());
|
||||
@@ -712,7 +675,12 @@ public class NMSBinding implements INMSBinding {
|
||||
var old = nmsServer.worldLoader;
|
||||
|
||||
field.setAccessible(true);
|
||||
field.set(nmsServer, transformer.apply(old));
|
||||
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);
|
||||
@@ -720,26 +688,66 @@ public class NMSBinding implements INMSBinding {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public 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);
|
||||
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));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end) {
|
||||
var registry = registry().lookupOrThrow(Registries.DIMENSION_TYPE);
|
||||
if (overworld) overworld = !registry.containsKey(createIrisKey(LevelStem.OVERWORLD));
|
||||
if (nether) nether = !registry.containsKey(createIrisKey(LevelStem.NETHER));
|
||||
if (end) end = !registry.containsKey(createIrisKey(LevelStem.END));
|
||||
return overworld || nether || end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomDimensions(World world) {
|
||||
((CraftWorld) world).getHandle().L.customDimensions = null;
|
||||
}
|
||||
|
||||
private RegistryAccess.Frozen createRegistryAccess(RegistryAccess.Frozen datapack, boolean copy, boolean overworld, boolean nether, boolean end) {
|
||||
var access = registry();
|
||||
var dimensions = access.lookupOrThrow(Registries.DIMENSION_TYPE);
|
||||
var levelStems = access.lookupOrThrow(Registries.LEVEL_STEM);
|
||||
|
||||
var settings = new FlatLevelGeneratorSettings(
|
||||
Optional.empty(),
|
||||
access.lookupOrThrow(Registries.BIOME).getOrThrow(Biomes.THE_VOID),
|
||||
List.of()
|
||||
);
|
||||
settings.getLayersInfo().add(new FlatLayerInfo(1, Blocks.AIR));
|
||||
settings.updateLayers();
|
||||
|
||||
var source = new FlatLevelSource(settings);
|
||||
var fake = new MappedRegistry<>(Registries.LEVEL_STEM, Lifecycle.experimental());
|
||||
if (overworld) register(fake, levelStems, dimensions, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, levelStems, dimensions, LevelStem.NETHER);
|
||||
if (end) register(fake, levelStems, dimensions, LevelStem.END);
|
||||
if (overworld) register(fake, dimensions, source, LevelStem.OVERWORLD);
|
||||
if (nether) register(fake, dimensions, source, LevelStem.NETHER);
|
||||
if (end) register(fake, dimensions, source, LevelStem.END);
|
||||
copy(fake, datapack.lookup(Registries.LEVEL_STEM).orElse(null));
|
||||
|
||||
if (copy) copy(fake, levelStems);
|
||||
if (copy) copy(fake, access.lookupOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake)).freeze();
|
||||
}
|
||||
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<LevelStem> levelStems, Registry<DimensionType> dimensions, ResourceKey<LevelStem> key) {
|
||||
private void register(MappedRegistry<LevelStem> target, Registry<DimensionType> dimensions, FlatLevelSource source, ResourceKey<LevelStem> key) {
|
||||
var loc = createIrisKey(key);
|
||||
target.register(key, new LevelStem(
|
||||
dimensions.get(ResourceLocation.fromNamespaceAndPath("iris", key.location().getPath())).orElseThrow(),
|
||||
levelStems.getValueOrThrow(key).generator()
|
||||
dimensions.get(loc).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), RegistrationInfo.BUILT_IN);
|
||||
}
|
||||
|
||||
@@ -752,4 +760,8 @@ public class NMSBinding implements INMSBinding {
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return ResourceLocation.fromNamespaceAndPath("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user