mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-01-06 15:51:30 +00:00
Compare commits
18 Commits
3.6.2-1.20
...
3.6.5-1.20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdb7cc61e5 | ||
|
|
e8f9e841c4 | ||
|
|
1b1b9d97b7 | ||
|
|
24355064ff | ||
|
|
06a45056d9 | ||
|
|
dfe4894be7 | ||
|
|
8eb2287ec0 | ||
|
|
c4f0722614 | ||
|
|
7fa1484b21 | ||
|
|
1c5eb8b910 | ||
|
|
94bf530d93 | ||
|
|
686ae57b5b | ||
|
|
a911685aaf | ||
|
|
6899761ca9 | ||
|
|
a58958fd62 | ||
|
|
307f3c9158 | ||
|
|
4f275c2e06 | ||
|
|
7e4e3f3cd8 |
@@ -33,7 +33,7 @@ plugins {
|
||||
}
|
||||
|
||||
|
||||
version '3.6.2-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 =============================
|
||||
|
||||
@@ -62,7 +62,7 @@ dependencies {
|
||||
|
||||
// Third Party Integrations
|
||||
compileOnly 'com.ticxo.playeranimator:PlayerAnimator:R1.2.7'
|
||||
compileOnly 'com.nexomc:nexo:0.6.0-dev.0'
|
||||
compileOnly 'com.nexomc:nexo:1.0.0-dev.38'
|
||||
compileOnly 'com.github.LoneDev6:api-itemsadder:3.4.1-r4'
|
||||
compileOnly 'com.github.PlaceholderAPI:placeholderapi:2.11.3'
|
||||
compileOnly 'com.github.Ssomar-Developement:SCore:4.23.10.8'
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
import com.volmit.iris.core.tools.IrisWorldCreator;
|
||||
import com.volmit.iris.engine.EnginePanic;
|
||||
import com.volmit.iris.engine.object.IrisCompat;
|
||||
import com.volmit.iris.engine.object.IrisContextInjector;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisWorld;
|
||||
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
|
||||
@@ -102,8 +103,6 @@ import static com.volmit.iris.core.safeguard.ServerBootSFG.passedserversoftware;
|
||||
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
public class Iris extends VolmitPlugin implements Listener {
|
||||
public static final String OVERWORLD_TAG = "31010";
|
||||
|
||||
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
||||
|
||||
public static Iris instance;
|
||||
@@ -460,9 +459,12 @@ 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"));
|
||||
@@ -517,11 +519,10 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
Iris.info("Loading World: %s | Generator: %s", s, generator);
|
||||
|
||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
||||
new WorldCreator(s)
|
||||
.type(IrisWorldCreator.IRIS)
|
||||
WorldCreator c = new WorldCreator(s)
|
||||
.generator(getDefaultWorldGenerator(s, generator))
|
||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment())
|
||||
.createWorld();
|
||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment());
|
||||
INMS.get().createWorld(c);
|
||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
|
||||
@@ -181,6 +181,7 @@ public class IrisSettings {
|
||||
public boolean splashLogoStartup = true;
|
||||
public boolean useConsoleCustomColors = true;
|
||||
public boolean useCustomColorsIngame = true;
|
||||
public boolean adjustVanillaHeight = false;
|
||||
public String forceMainWorld = "";
|
||||
public int spinh = -20;
|
||||
public int spins = 7;
|
||||
|
||||
@@ -28,21 +28,24 @@ import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
import com.volmit.iris.engine.object.IrisRange;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.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;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -89,12 +92,13 @@ public class ServerConfigurator {
|
||||
}
|
||||
}
|
||||
|
||||
private static List<File> getDatapacksFolder() {
|
||||
private static KList<File> getDatapacksFolder() {
|
||||
if (!IrisSettings.get().getGeneral().forceMainWorld.isEmpty()) {
|
||||
return new KList<File>().qadd(new File(Bukkit.getWorldContainer(), IrisSettings.get().getGeneral().forceMainWorld + "/datapacks"));
|
||||
}
|
||||
KList<File> worlds = new KList<>();
|
||||
Bukkit.getServer().getWorlds().forEach(w -> worlds.add(new File(w.getWorldFolder(), "datapacks")));
|
||||
if (worlds.isEmpty()) worlds.add(new File(Bukkit.getWorldContainer(), ServerProperties.LEVEL_NAME + "/datapacks"));
|
||||
return worlds;
|
||||
}
|
||||
|
||||
@@ -105,14 +109,16 @@ public class ServerConfigurator {
|
||||
public static void installDataPacks(IDataFixer fixer, boolean fullInstall) {
|
||||
Iris.info("Checking Data Packs...");
|
||||
DimensionHeight height = new DimensionHeight(fixer);
|
||||
KList<File> folders = getDatapacksFolder();
|
||||
KMap<String, KSet<String>> biomes = new KMap<>();
|
||||
|
||||
allPacks().flatMap(height::merge)
|
||||
.parallel()
|
||||
.forEach(dim -> {
|
||||
for (File dpack : getDatapacksFolder()) {
|
||||
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
|
||||
dim.installDataPack(fixer, dim::getLoader, dpack, height);
|
||||
}
|
||||
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
|
||||
dim.installBiomes(fixer, dim::getLoader, folders, biomes.computeIfAbsent(dim.getLoadKey(), k -> new KSet<>()));
|
||||
});
|
||||
IrisDimension.writeShared(folders, height);
|
||||
|
||||
Iris.info("Data Packs Setup!");
|
||||
|
||||
@@ -164,7 +170,7 @@ public class ServerConfigurator {
|
||||
Iris.warn("This will only happen when your pack changes (updates/first time setup)");
|
||||
Iris.warn("(You can disable this auto restart in iris settings)");
|
||||
J.s(() -> {
|
||||
Iris.warn("Looks like the restart command diddn't work. Stopping the server instead!");
|
||||
Iris.warn("Looks like the restart command didn't work. Stopping the server instead!");
|
||||
Bukkit.shutdown();
|
||||
}, 100);
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "restart");
|
||||
@@ -172,22 +178,24 @@ public class ServerConfigurator {
|
||||
}
|
||||
|
||||
public static boolean verifyDataPackInstalled(IrisDimension dimension) {
|
||||
IrisData idm = IrisData.get(Iris.instance.getDataFolder("packs", dimension.getLoadKey()));
|
||||
KSet<String> keys = new KSet<>();
|
||||
boolean warn = false;
|
||||
|
||||
for (IrisBiome i : dimension.getAllBiomes(() -> idm)) {
|
||||
for (IrisBiome i : dimension.getAllBiomes(dimension::getLoader)) {
|
||||
if (i.isCustom()) {
|
||||
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
|
||||
keys.add(dimension.getLoadKey() + ":" + j.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
String key = getWorld(dimension.getLoader());
|
||||
if (key == null) key = dimension.getLoadKey();
|
||||
else key += "/" + dimension.getLoadKey();
|
||||
|
||||
if (!INMS.get().supportsDataPacks()) {
|
||||
if (!keys.isEmpty()) {
|
||||
Iris.warn("===================================================================================");
|
||||
Iris.warn("Pack " + dimension.getLoadKey() + " has " + keys.size() + " custom biome(s). ");
|
||||
Iris.warn("Pack " + key + " has " + keys.size() + " custom biome(s). ");
|
||||
Iris.warn("Your server version does not yet support datapacks for iris.");
|
||||
Iris.warn("The world will generate these biomes as backup biomes.");
|
||||
Iris.warn("====================================================================================");
|
||||
@@ -206,7 +214,7 @@ public class ServerConfigurator {
|
||||
}
|
||||
|
||||
if (warn) {
|
||||
Iris.error("The Pack " + dimension.getLoadKey() + " is INCAPABLE of generating custom biomes");
|
||||
Iris.error("The Pack " + key + " is INCAPABLE of generating custom biomes");
|
||||
Iris.error("If not done automatically, restart your server before generating with this pack!");
|
||||
}
|
||||
|
||||
@@ -220,6 +228,17 @@ public class ServerConfigurator {
|
||||
.map(IrisData::get);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getWorld(@NonNull IrisData data) {
|
||||
String worldContainer = Bukkit.getWorldContainer().getAbsolutePath();
|
||||
if (!worldContainer.endsWith(File.separator)) worldContainer += File.separator;
|
||||
|
||||
String path = data.getDataFolder().getAbsolutePath();
|
||||
if (!path.startsWith(worldContainer)) return null;
|
||||
int l = path.endsWith(File.separator) ? 11 : 10;
|
||||
return path.substring(worldContainer.length(), path.length() - l);
|
||||
}
|
||||
|
||||
private static Stream<File> listFiles(File parent) {
|
||||
var files = parent.listFiles();
|
||||
return files == null ? Stream.empty() : Arrays.stream(files);
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.volmit.iris.core.commands;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.pregenerator.ChunkUpdater;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.core.tools.IrisBenchmarking;
|
||||
@@ -412,7 +413,7 @@ public class CommandIris implements DecreeExecutor {
|
||||
) {
|
||||
sender().sendMessage(C.GREEN + "Downloading pack: " + pack + "/" + branch + (trim ? " trimmed" : "") + (overwrite ? " overwriting" : ""));
|
||||
if (pack.equals("overworld")) {
|
||||
String url = "https://github.com/IrisDimensions/overworld/releases/download/" + Iris.OVERWORLD_TAG + "/overworld.zip";
|
||||
String url = "https://github.com/IrisDimensions/overworld/releases/download/" + INMS.OVERWORLD_TAG + "/overworld.zip";
|
||||
Iris.service(StudioSVC.class).downloadRelease(sender(), url, trim, overwrite);
|
||||
} else {
|
||||
Iris.service(StudioSVC.class).downloadSearch(sender(), "IrisDimensions/" + pack + "/" + branch, trim, overwrite);
|
||||
@@ -598,10 +599,10 @@ public class CommandIris implements DecreeExecutor {
|
||||
continue;
|
||||
}
|
||||
Iris.info(C.LIGHT_PURPLE + "Preparing Spawn for " + s + "' using Iris:" + generator + "...");
|
||||
new WorldCreator(s)
|
||||
WorldCreator c = new WorldCreator(s)
|
||||
.generator(getDefaultWorldGenerator(s, generator))
|
||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment())
|
||||
.createWorld();
|
||||
.environment(IrisData.loadAnyDimension(generator).getEnvironment());
|
||||
INMS.get().createWorld(c);
|
||||
Iris.info(C.LIGHT_PURPLE + "Loaded " + s + "!");
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
|
||||
@@ -125,7 +125,7 @@ public class NexoDataProvider extends ExternalDataProvider {
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getBlockTypes() {
|
||||
return Arrays.stream(NexoItems.itemNames())
|
||||
return NexoItems.itemNames().stream()
|
||||
.map(i -> new Identifier("nexo", i))
|
||||
.filter(i -> {
|
||||
try {
|
||||
@@ -140,7 +140,7 @@ public class NexoDataProvider extends ExternalDataProvider {
|
||||
@NotNull
|
||||
@Override
|
||||
public Identifier[] getItemTypes() {
|
||||
return Arrays.stream(NexoItems.itemNames())
|
||||
return NexoItems.itemNames().stream()
|
||||
.map(i -> new Identifier("nexo", i))
|
||||
.filter(i -> {
|
||||
try {
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class INMS {
|
||||
@@ -35,8 +36,15 @@ public class INMS {
|
||||
"1.21.3", "v1_21_R2",
|
||||
"1.21.4", "v1_21_R3"
|
||||
);
|
||||
private static final List<Version> PACKS = List.of(
|
||||
new Version(21, 4, "31020"),
|
||||
new Version(21, 2, "31000"),
|
||||
new Version(20, 1, "3910")
|
||||
);
|
||||
|
||||
//@done
|
||||
private static final INMSBinding binding = bind();
|
||||
public static final String OVERWORLD_TAG = getOverworldTag();
|
||||
|
||||
public static INMSBinding get() {
|
||||
return binding;
|
||||
@@ -87,4 +95,26 @@ public class INMS {
|
||||
|
||||
return new NMSBinding1X();
|
||||
}
|
||||
|
||||
private static String getOverworldTag() {
|
||||
var version = Bukkit.getServer().getBukkitVersion().split("-")[0].split("\\.", 3);
|
||||
int major = 0;
|
||||
int minor = 0;
|
||||
|
||||
if (version.length > 2) {
|
||||
major = Integer.parseInt(version[1]);
|
||||
minor = Integer.parseInt(version[2]);
|
||||
} else if (version.length == 2) {
|
||||
major = Integer.parseInt(version[1]);
|
||||
}
|
||||
|
||||
for (var p : PACKS) {
|
||||
if (p.major > major || p.minor > minor)
|
||||
continue;
|
||||
return p.tag;
|
||||
}
|
||||
return "3910";
|
||||
}
|
||||
|
||||
private record Version(int major, int minor, String tag) {}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
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;
|
||||
@@ -30,15 +32,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 {
|
||||
@@ -91,7 +90,12 @@ public interface INMSBinding {
|
||||
MCABiomeContainer newBiomeContainer(int min, int max);
|
||||
|
||||
default World createWorld(WorldCreator c) {
|
||||
return c.createWorld();
|
||||
if (missingDimensionTypes(true, true, true))
|
||||
throw new IllegalStateException("Missing dimenstion types to create world");
|
||||
|
||||
try (var ignored = injectLevelStems()) {
|
||||
return c.createWorld();
|
||||
}
|
||||
}
|
||||
|
||||
int countCustomBiomes();
|
||||
@@ -125,4 +129,10 @@ public interface INMSBinding {
|
||||
}
|
||||
|
||||
KList<String> getStructureKeys();
|
||||
|
||||
AutoClosing injectLevelStems();
|
||||
|
||||
Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end);
|
||||
|
||||
boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.volmit.iris.core.nms.container;
|
||||
|
||||
import com.volmit.iris.util.function.NastyRunnable;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class AutoClosing implements AutoCloseable {
|
||||
private final AtomicBoolean closed = new AtomicBoolean();
|
||||
private final NastyRunnable action;
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (closed.getAndSet(true)) return;
|
||||
try {
|
||||
action.run();
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,46 +20,6 @@ public interface IDataFixer {
|
||||
return obj;
|
||||
}
|
||||
|
||||
default JSONObject createPreset() {
|
||||
return new JSONObject("""
|
||||
{
|
||||
"dimensions": {
|
||||
"minecraft:overworld": {
|
||||
"type": "iris:overworld",
|
||||
"generator": {
|
||||
"type": "minecraft:noise",
|
||||
"biome_source": {
|
||||
"type": "minecraft:multi_noise",
|
||||
"preset": "minecraft:overworld"
|
||||
},
|
||||
"settings": "minecraft:overworld"
|
||||
}
|
||||
},
|
||||
"minecraft:the_end": {
|
||||
"type": "iris:the_end",
|
||||
"generator": {
|
||||
"type": "minecraft:noise",
|
||||
"biome_source": {
|
||||
"type": "minecraft:the_end"
|
||||
},
|
||||
"settings": "minecraft:end"
|
||||
}
|
||||
},
|
||||
"minecraft:the_nether": {
|
||||
"type": "iris:the_nether",
|
||||
"generator": {
|
||||
"type": "minecraft:noise",
|
||||
"biome_source": {
|
||||
"type": "minecraft:multi_noise",
|
||||
"preset": "minecraft:nether"
|
||||
},
|
||||
"settings": "minecraft:nether"
|
||||
}
|
||||
}
|
||||
}
|
||||
}""");
|
||||
}
|
||||
|
||||
enum Dimension {
|
||||
OVERRWORLD,
|
||||
NETHER,
|
||||
|
||||
@@ -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,21 @@ public class NMSBinding1X implements INMSBinding {
|
||||
return new KList<>(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AutoClosing injectLevelStems() {
|
||||
return new AutoClosing(() -> {});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Integer, AutoClosing> injectUncached(boolean overworld, boolean nether, boolean end) {
|
||||
return new Pair<>(0, new AutoClosing(() -> {}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean missingDimensionTypes(boolean overworld, boolean nether, boolean end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeEntity(Entity location) {
|
||||
return null;
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.ServerConfigurator;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.pack.IrisPack;
|
||||
import com.volmit.iris.core.project.IrisProject;
|
||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||
@@ -64,7 +65,7 @@ public class StudioSVC implements IrisService {
|
||||
if (!f.exists()) {
|
||||
Iris.info("Downloading Default Pack " + pack);
|
||||
if (pack.equals("overworld")) {
|
||||
String url = "https://github.com/IrisDimensions/overworld/releases/download/" + Iris.OVERWORLD_TAG + "/overworld.zip";
|
||||
String url = "https://github.com/IrisDimensions/overworld/releases/download/" + INMS.OVERWORLD_TAG + "/overworld.zip";
|
||||
Iris.service(StudioSVC.class).downloadRelease(Iris.getSender(), url, false, false);
|
||||
} else {
|
||||
downloadSearch(Iris.getSender(), pack, false);
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.google.common.util.concurrent.AtomicDouble;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.ServerConfigurator;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.engine.object.IrisDimension;
|
||||
@@ -170,7 +171,7 @@ public class IrisCreator {
|
||||
|
||||
try {
|
||||
J.sfut(() -> {
|
||||
world.set(wc.createWorld());
|
||||
world.set(INMS.get().createWorld(wc));
|
||||
}).get();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
|
||||
@@ -32,8 +32,6 @@ import sun.misc.Unsafe;
|
||||
import java.io.File;
|
||||
|
||||
public class IrisWorldCreator {
|
||||
public static final WorldType IRIS;
|
||||
|
||||
private String name;
|
||||
private boolean studio = false;
|
||||
private String dimensionName = null;
|
||||
@@ -85,7 +83,6 @@ public class IrisWorldCreator {
|
||||
|
||||
|
||||
return new WorldCreator(name)
|
||||
.type(IRIS)
|
||||
.environment(findEnvironment())
|
||||
.generateStructures(true)
|
||||
.generator(g).seed(seed);
|
||||
@@ -104,17 +101,4 @@ public class IrisWorldCreator {
|
||||
this.studio = studio;
|
||||
return this;
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
var unsafe = new WrappedField<Unsafe, Unsafe>(Unsafe.class, "theUnsafe").get();
|
||||
var iris = (WorldType) unsafe.allocateInstance(WorldType.class);
|
||||
unsafe.putIntVolatile(iris, unsafe.objectFieldOffset(Enum.class.getDeclaredField("ordinal")), 0);
|
||||
unsafe.putObjectVolatile(iris, unsafe.objectFieldOffset(Enum.class.getDeclaredField("name")), "IRIS");
|
||||
|
||||
IRIS = iris;
|
||||
} catch (Throwable e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
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.misc.ServerProperties;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
String levelName = ServerProperties.LEVEL_NAME;
|
||||
List<String> irisWorlds = irisWorlds();
|
||||
boolean overworld = irisWorlds.contains(levelName);
|
||||
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) {
|
||||
var pair = INMS.get().injectUncached(overworld, nether, end);
|
||||
i += pair.getA() - 3;
|
||||
autoClosing = pair.getB();
|
||||
}
|
||||
|
||||
totalWorlds = i;
|
||||
instance.registerListener(this);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(WorldInitEvent event) {
|
||||
if (++worldCounter < totalWorlds) return;
|
||||
if (autoClosing != null) {
|
||||
autoClosing.close();
|
||||
autoClosing = null;
|
||||
}
|
||||
instance.unregisterListener(this);
|
||||
}
|
||||
|
||||
private List<String> irisWorlds() {
|
||||
var config = YamlConfiguration.loadConfiguration(ServerProperties.BUKKIT_YML);
|
||||
ConfigurationSection section = config.getConfigurationSection("worlds");
|
||||
if (section == null) return List.of();
|
||||
|
||||
return section.getKeys(false)
|
||||
.stream()
|
||||
.filter(k -> section.getString(k + ".generator", "").startsWith("Iris"))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.ServerConfigurator.DimensionHeight;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.loader.IrisRegistrant;
|
||||
@@ -27,6 +28,7 @@ import com.volmit.iris.core.nms.datapack.IDataFixer;
|
||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.object.annotations.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KSet;
|
||||
import com.volmit.iris.util.data.DataProvider;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.json.JSONObject;
|
||||
@@ -377,60 +379,35 @@ public class IrisDimension extends IrisRegistrant {
|
||||
return landBiomeStyle;
|
||||
}
|
||||
|
||||
public boolean installDataPack(IDataFixer fixer, DataProvider data, File datapacks, DimensionHeight height) {
|
||||
boolean write = false;
|
||||
boolean changed = false;
|
||||
|
||||
IO.delete(new File(datapacks, "iris/data/" + getLoadKey().toLowerCase()));
|
||||
|
||||
for (IrisBiome i : getAllBiomes(data)) {
|
||||
if (i.isCustom()) {
|
||||
write = true;
|
||||
|
||||
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
|
||||
File output = new File(datapacks, "iris/data/" + getLoadKey().toLowerCase() + "/worldgen/biome/" + j.getId() + ".json");
|
||||
|
||||
if (!output.exists()) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
Iris.verbose(" Installing Data Pack Biome: " + output.getPath());
|
||||
output.getParentFile().mkdirs();
|
||||
try {
|
||||
IO.writeAll(output, j.generateJson(fixer));
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Iris.verbose(" Installing Data Pack Dimension Types: \"iris:overworld\", \"iris:the_nether\", \"iris:the_end\"");
|
||||
changed = writeDimensionType(changed, datapacks, height);
|
||||
|
||||
Iris.verbose(" Installing Data Pack World Preset: \"minecraft:iris\"");
|
||||
changed = writeWorldPreset(changed, datapacks, fixer);
|
||||
|
||||
if (write) {
|
||||
File mcm = new File(datapacks, "iris/pack.mcmeta");
|
||||
try {
|
||||
IO.writeAll(mcm, """
|
||||
{
|
||||
"pack": {
|
||||
"description": "Iris Data Pack. This pack contains all installed Iris Packs' resources.",
|
||||
"pack_format": {}
|
||||
}
|
||||
public void installBiomes(IDataFixer fixer, DataProvider data, KList<File> folders, KSet<String> biomes) {
|
||||
getAllBiomes(data)
|
||||
.stream()
|
||||
.filter(IrisBiome::isCustom)
|
||||
.map(IrisBiome::getCustomDerivitives)
|
||||
.flatMap(KList::stream)
|
||||
.parallel()
|
||||
.forEach(j -> {
|
||||
String json = j.generateJson(fixer);
|
||||
synchronized (biomes) {
|
||||
if (!biomes.add(j.getId())) {
|
||||
Iris.verbose("Duplicate Data Pack Biome: " + getLoadKey() + "/" + j.getId());
|
||||
return;
|
||||
}
|
||||
""".replace("{}", INMS.get().getDataVersion().getPackFormat() + ""));
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
Iris.verbose(" Installing Data Pack MCMeta: " + mcm.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
for (File datapacks : folders) {
|
||||
File output = new File(datapacks, "iris/data/" + getLoadKey().toLowerCase() + "/worldgen/biome/" + j.getId() + ".json");
|
||||
|
||||
Iris.verbose(" Installing Data Pack Biome: " + output.getPath());
|
||||
output.getParentFile().mkdirs();
|
||||
try {
|
||||
IO.writeAll(output, json);
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -448,56 +425,55 @@ public class IrisDimension extends IrisRegistrant {
|
||||
|
||||
}
|
||||
|
||||
public boolean writeDimensionType(boolean changed, File datapacks, DimensionHeight height) {
|
||||
File dimTypeOverworld = new File(datapacks, "iris/data/iris/dimension_type/overworld.json");
|
||||
if (!dimTypeOverworld.exists())
|
||||
changed = true;
|
||||
dimTypeOverworld.getParentFile().mkdirs();
|
||||
try {
|
||||
IO.writeAll(dimTypeOverworld, height.overworldType());
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
public static void writeShared(KList<File> folders, DimensionHeight height) {
|
||||
Iris.verbose(" Installing Data Pack Dimension Types: \"iris:overworld\", \"iris:the_nether\", \"iris:the_end\"");
|
||||
for (File datapacks : folders) {
|
||||
write(datapacks, "overworld", height.overworldType());
|
||||
write(datapacks, "the_nether", height.netherType());
|
||||
write(datapacks, "the_end", height.endType());
|
||||
}
|
||||
|
||||
String raw = """
|
||||
{
|
||||
"pack": {
|
||||
"description": "Iris Data Pack. This pack contains all installed Iris Packs' resources.",
|
||||
"pack_format": {}
|
||||
}
|
||||
}
|
||||
""".replace("{}", INMS.get().getDataVersion().getPackFormat() + "");
|
||||
|
||||
File dimTypeNether = new File(datapacks, "iris/data/iris/dimension_type/the_nether.json");
|
||||
if (!dimTypeNether.exists())
|
||||
changed = true;
|
||||
dimTypeNether.getParentFile().mkdirs();
|
||||
try {
|
||||
IO.writeAll(dimTypeNether, height.netherType());
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
for (File datapacks : folders) {
|
||||
File mcm = new File(datapacks, "iris/pack.mcmeta");
|
||||
try {
|
||||
IO.writeAll(mcm, raw);
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
Iris.verbose(" Installing Data Pack MCMeta: " + mcm.getPath());
|
||||
}
|
||||
|
||||
|
||||
File dimTypeEnd = new File(datapacks, "iris/data/iris/dimension_type/the_end.json");
|
||||
if (!dimTypeEnd.exists())
|
||||
changed = true;
|
||||
dimTypeEnd.getParentFile().mkdirs();
|
||||
try {
|
||||
IO.writeAll(dimTypeEnd, height.endType());
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
public boolean writeWorldPreset(boolean changed, File datapacks, IDataFixer fixer) {
|
||||
File worldPreset = new File(datapacks, "iris/data/minecraft/worldgen/world_preset/iris.json");
|
||||
if (!worldPreset.exists())
|
||||
changed = true;
|
||||
private static void write(File datapacks, String type, String json) {
|
||||
File dimType = new File(datapacks, "iris/data/iris/dimension_type/" + type + ".json");
|
||||
File dimTypeVanilla = new File(datapacks, "iris/data/minecraft/dimension_type/" + type + ".json");
|
||||
|
||||
dimType.getParentFile().mkdirs();
|
||||
try {
|
||||
IO.writeAll(worldPreset, fixer.createPreset());
|
||||
IO.writeAll(dimType, json);
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return changed;
|
||||
if (IrisSettings.get().getGeneral().adjustVanillaHeight || dimTypeVanilla.exists()) {
|
||||
dimTypeVanilla.getParentFile().mkdirs();
|
||||
try {
|
||||
IO.writeAll(dimTypeVanilla, json);
|
||||
} catch (IOException e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.volmit.iris.util.misc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
public class ServerProperties {
|
||||
public static final Properties DATA = new Properties();
|
||||
public static final File SERVER_PROPERTIES;
|
||||
public static final File BUKKIT_YML;
|
||||
|
||||
public static final String LEVEL_NAME;
|
||||
|
||||
static {
|
||||
String[] args = ProcessHandle.current()
|
||||
.info()
|
||||
.arguments()
|
||||
.orElse(new String[0]);
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
SERVER_PROPERTIES = new File(propertiesPath);
|
||||
BUKKIT_YML = new File(bukkitYml);
|
||||
try (FileInputStream in = new FileInputStream(SERVER_PROPERTIES)){
|
||||
DATA.load(in);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if (levelName != null) LEVEL_NAME = levelName;
|
||||
else LEVEL_NAME = DATA.getProperty("level-name", "world");
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,10 @@ package com.volmit.iris.core.nms.v1_20_R1;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
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.engine.data.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
@@ -20,27 +22,36 @@ import com.volmit.iris.util.nbt.mca.palette.*;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import lombok.SneakyThrows;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.WorldLoader;
|
||||
import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
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;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
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;
|
||||
@@ -73,11 +84,10 @@ import java.io.DataOutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class NMSBinding implements INMSBinding {
|
||||
|
||||
@@ -85,9 +95,11 @@ public class NMSBinding implements INMSBinding {
|
||||
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
|
||||
private final BlockData AIR = Material.AIR.createBlockData();
|
||||
private final AtomicCache<MCAIdMap<net.minecraft.world.level.biome.Biome>> biomeMapCache = new AtomicCache<>();
|
||||
private final AtomicCache<WorldLoader.DataLoadContext> dataLoadContext = new AtomicCache<>();
|
||||
private final AtomicCache<MCAIdMapper<BlockState>> registryCache = new AtomicCache<>();
|
||||
private final AtomicCache<MCAPalette<BlockState>> globalCache = new AtomicCache<>();
|
||||
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
|
||||
private final ReentrantLock dataContextLock = new ReentrantLock(true);
|
||||
private final AtomicCache<Method> byIdRef = new AtomicCache<>();
|
||||
private Field biomeStorageCache = null;
|
||||
|
||||
@@ -568,6 +580,9 @@ public class NMSBinding implements INMSBinding {
|
||||
|
||||
public void inject(long seed, Engine engine, World world) {
|
||||
var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap;
|
||||
var dimensionType = chunkMap.level.dimensionTypeRegistration().unwrapKey().orElse(null);
|
||||
if (dimensionType != null && !dimensionType.location().getNamespace().equals("iris"))
|
||||
Iris.error("Loaded world %s with invalid dimension type! (%s)", world.getName(), dimensionType.location().toString());
|
||||
chunkMap.generator = new IrisChunkGenerator(chunkMap.generator, seed, engine, world);
|
||||
}
|
||||
|
||||
@@ -628,4 +643,120 @@ public class NMSBinding implements INMSBinding {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}));
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
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) {
|
||||
var access = registry();
|
||||
var dimensions = access.registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
|
||||
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, 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, access.registryOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
}
|
||||
|
||||
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(ResourceKey.create(Registries.DIMENSION_TYPE, loc)).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), Lifecycle.stable());
|
||||
}
|
||||
|
||||
private void copy(MappedRegistry<LevelStem> target, Registry<LevelStem> source) {
|
||||
if (source == null) return;
|
||||
source.registryKeySet().forEach(key -> {
|
||||
var value = source.get(key);
|
||||
var info = source.lifecycle(value);
|
||||
if (value != null && info != null && !target.containsKey(key))
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return new ResourceLocation("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,21 +8,34 @@ import java.io.DataOutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.volmit.iris.core.nms.container.AutoClosing;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.SneakyThrows;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
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;
|
||||
@@ -61,10 +74,6 @@ import com.volmit.iris.util.nbt.mca.palette.*;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -83,9 +92,11 @@ public class NMSBinding implements INMSBinding {
|
||||
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
|
||||
private final BlockData AIR = Material.AIR.createBlockData();
|
||||
private final AtomicCache<MCAIdMap<net.minecraft.world.level.biome.Biome>> biomeMapCache = new AtomicCache<>();
|
||||
private final AtomicCache<WorldLoader.DataLoadContext> dataLoadContext = new AtomicCache<>();
|
||||
private final AtomicCache<MCAIdMapper<BlockState>> registryCache = new AtomicCache<>();
|
||||
private final AtomicCache<MCAPalette<BlockState>> globalCache = new AtomicCache<>();
|
||||
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
|
||||
private final ReentrantLock dataContextLock = new ReentrantLock(true);
|
||||
private final AtomicCache<Method> byIdRef = new AtomicCache<>();
|
||||
private Field biomeStorageCache = null;
|
||||
|
||||
@@ -538,6 +549,9 @@ public class NMSBinding implements INMSBinding {
|
||||
|
||||
public void inject(long seed, Engine engine, World world) {
|
||||
var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap;
|
||||
var dimensionType = chunkMap.level.dimensionTypeRegistration().unwrapKey().orElse(null);
|
||||
if (dimensionType != null && !dimensionType.location().getNamespace().equals("iris"))
|
||||
Iris.error("Loaded world %s with invalid dimension type! (%s)", world.getName(), dimensionType.location().toString());
|
||||
chunkMap.generator = new IrisChunkGenerator(chunkMap.generator, seed, engine, world);
|
||||
}
|
||||
|
||||
@@ -630,4 +644,120 @@ public class NMSBinding implements INMSBinding {
|
||||
public static Holder<net.minecraft.world.level.biome.Biome> biomeToBiomeBase(Registry<net.minecraft.world.level.biome.Biome> registry, Biome biome) {
|
||||
return registry.getHolderOrThrow(ResourceKey.create(Registries.BIOME, CraftNamespacedKey.toMinecraft(biome.getKey())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public 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);
|
||||
}));
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
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) {
|
||||
var access = registry();
|
||||
var dimensions = access.registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
|
||||
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, 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, access.registryOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
}
|
||||
|
||||
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(ResourceKey.create(Registries.DIMENSION_TYPE, loc)).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), Lifecycle.stable());
|
||||
}
|
||||
|
||||
private void copy(MappedRegistry<LevelStem> target, Registry<LevelStem> source) {
|
||||
if (source == null) return;
|
||||
source.registryKeySet().forEach(key -> {
|
||||
var value = source.get(key);
|
||||
var info = source.lifecycle(value);
|
||||
if (value != null && info != null && !target.containsKey(key))
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return new ResourceLocation("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,21 +8,34 @@ import java.io.DataOutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.volmit.iris.core.nms.container.AutoClosing;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.SneakyThrows;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
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;
|
||||
@@ -61,10 +74,6 @@ import com.volmit.iris.util.nbt.mca.palette.*;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -83,9 +92,11 @@ public class NMSBinding implements INMSBinding {
|
||||
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
|
||||
private final BlockData AIR = Material.AIR.createBlockData();
|
||||
private final AtomicCache<MCAIdMap<net.minecraft.world.level.biome.Biome>> biomeMapCache = new AtomicCache<>();
|
||||
private final AtomicCache<WorldLoader.DataLoadContext> dataLoadContext = new AtomicCache<>();
|
||||
private final AtomicCache<MCAIdMapper<BlockState>> registryCache = new AtomicCache<>();
|
||||
private final AtomicCache<MCAPalette<BlockState>> globalCache = new AtomicCache<>();
|
||||
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
|
||||
private final ReentrantLock dataContextLock = new ReentrantLock(true);
|
||||
private final AtomicCache<Method> byIdRef = new AtomicCache<>();
|
||||
private Field biomeStorageCache = null;
|
||||
|
||||
@@ -538,6 +549,9 @@ public class NMSBinding implements INMSBinding {
|
||||
|
||||
public void inject(long seed, Engine engine, World world) {
|
||||
var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap;
|
||||
var dimensionType = chunkMap.level.dimensionTypeRegistration().unwrapKey().orElse(null);
|
||||
if (dimensionType != null && !dimensionType.location().getNamespace().equals("iris"))
|
||||
Iris.error("Loaded world %s with invalid dimension type! (%s)", world.getName(), dimensionType.location().toString());
|
||||
chunkMap.generator = new IrisChunkGenerator(chunkMap.generator, seed, engine, world);
|
||||
}
|
||||
|
||||
@@ -631,4 +645,120 @@ public class NMSBinding implements INMSBinding {
|
||||
public static Holder<net.minecraft.world.level.biome.Biome> biomeToBiomeBase(Registry<net.minecraft.world.level.biome.Biome> registry, Biome biome) {
|
||||
return registry.getHolderOrThrow(ResourceKey.create(Registries.BIOME, CraftNamespacedKey.toMinecraft(biome.getKey())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public 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);
|
||||
}));
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
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) {
|
||||
var access = registry();
|
||||
var dimensions = access.registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
|
||||
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, 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, access.registryOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
}
|
||||
|
||||
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(ResourceKey.create(Registries.DIMENSION_TYPE, loc)).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), Lifecycle.stable());
|
||||
}
|
||||
|
||||
private void copy(MappedRegistry<LevelStem> target, Registry<LevelStem> source) {
|
||||
if (source == null) return;
|
||||
source.registryKeySet().forEach(key -> {
|
||||
var value = source.get(key);
|
||||
var info = source.lifecycle(value);
|
||||
if (value != null && info != null && !target.containsKey(key))
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return new ResourceLocation("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,17 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.volmit.iris.core.nms.container.AutoClosing;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.SneakyThrows;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
@@ -25,15 +30,24 @@ import net.minecraft.nbt.LongTag;
|
||||
import net.minecraft.nbt.ShortTag;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.WorldLoader;
|
||||
import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
import net.minecraft.server.commands.data.DataCommands;
|
||||
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;
|
||||
@@ -86,9 +100,11 @@ public class NMSBinding implements INMSBinding {
|
||||
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
|
||||
private final BlockData AIR = Material.AIR.createBlockData();
|
||||
private final AtomicCache<MCAIdMap<net.minecraft.world.level.biome.Biome>> biomeMapCache = new AtomicCache<>();
|
||||
private final AtomicCache<WorldLoader.DataLoadContext> dataLoadContext = new AtomicCache<>();
|
||||
private final AtomicCache<MCAIdMapper<BlockState>> registryCache = new AtomicCache<>();
|
||||
private final AtomicCache<MCAPalette<BlockState>> globalCache = new AtomicCache<>();
|
||||
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
|
||||
private final ReentrantLock dataContextLock = new ReentrantLock(true);
|
||||
private final AtomicCache<Method> byIdRef = new AtomicCache<>();
|
||||
private Field biomeStorageCache = null;
|
||||
|
||||
@@ -544,6 +560,10 @@ public class NMSBinding implements INMSBinding {
|
||||
|
||||
public void inject(long seed, Engine engine, World world) {
|
||||
var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap;
|
||||
var dimensionType = chunkMap.level.dimensionTypeRegistration().unwrapKey().orElse(null);
|
||||
if (dimensionType != null && !dimensionType.location().getNamespace().equals("iris"))
|
||||
Iris.error("Loaded world %s with invalid dimension type! (%s)", world.getName(), dimensionType.location().toString());
|
||||
|
||||
chunkMap.generator = new IrisChunkGenerator(chunkMap.generator, seed, engine, world);
|
||||
}
|
||||
|
||||
@@ -650,4 +670,120 @@ public class NMSBinding implements INMSBinding {
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}));
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
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) {
|
||||
var access = registry();
|
||||
var dimensions = access.registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
|
||||
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, 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, access.registryOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
}
|
||||
|
||||
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(ResourceKey.create(Registries.DIMENSION_TYPE, loc)).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), RegistrationInfo.BUILT_IN);
|
||||
}
|
||||
|
||||
private void copy(MappedRegistry<LevelStem> target, Registry<LevelStem> source) {
|
||||
if (source == null) return;
|
||||
source.registryKeySet().forEach(key -> {
|
||||
var value = source.get(key);
|
||||
var info = source.registrationInfo(key).orElse(null);
|
||||
if (value != null && info != null && !target.containsKey(key))
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return new ResourceLocation("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,22 +10,38 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import com.volmit.iris.core.nms.container.AutoClosing;
|
||||
import com.volmit.iris.core.nms.container.BiomeColor;
|
||||
import com.volmit.iris.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.SneakyThrows;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.WorldLoader;
|
||||
import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
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;
|
||||
@@ -64,10 +80,6 @@ import com.volmit.iris.util.nbt.mca.palette.*;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -85,9 +97,11 @@ public class NMSBinding implements INMSBinding {
|
||||
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
|
||||
private final BlockData AIR = Material.AIR.createBlockData();
|
||||
private final AtomicCache<MCAIdMap<net.minecraft.world.level.biome.Biome>> biomeMapCache = new AtomicCache<>();
|
||||
private final AtomicCache<WorldLoader.DataLoadContext> dataLoadContext = new AtomicCache<>();
|
||||
private final AtomicCache<MCAIdMapper<BlockState>> registryCache = new AtomicCache<>();
|
||||
private final AtomicCache<MCAPalette<BlockState>> globalCache = new AtomicCache<>();
|
||||
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
|
||||
private final ReentrantLock dataContextLock = new ReentrantLock(true);
|
||||
private final AtomicCache<Method> byIdRef = new AtomicCache<>();
|
||||
private Field biomeStorageCache = null;
|
||||
|
||||
@@ -546,6 +560,9 @@ public class NMSBinding implements INMSBinding {
|
||||
var worldGenContextField = getField(chunkMap.getClass(), WorldGenContext.class);
|
||||
worldGenContextField.setAccessible(true);
|
||||
var worldGenContext = (WorldGenContext) worldGenContextField.get(chunkMap);
|
||||
var dimensionType = chunkMap.level.dimensionTypeRegistration().unwrapKey().orElse(null);
|
||||
if (dimensionType != null && !dimensionType.location().getNamespace().equals("iris"))
|
||||
Iris.error("Loaded world %s with invalid dimension type! (%s)", world.getName(), dimensionType.location().toString());
|
||||
|
||||
var newContext = new WorldGenContext(
|
||||
worldGenContext.level(), new IrisChunkGenerator(worldGenContext.generator(), seed, engine, world),
|
||||
@@ -657,4 +674,120 @@ public class NMSBinding implements INMSBinding {
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}));
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
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) {
|
||||
var access = registry();
|
||||
var dimensions = access.registryOrThrow(Registries.DIMENSION_TYPE);
|
||||
|
||||
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, 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, access.registryOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
}
|
||||
|
||||
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(ResourceKey.create(Registries.DIMENSION_TYPE, loc)).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), RegistrationInfo.BUILT_IN);
|
||||
}
|
||||
|
||||
private void copy(MappedRegistry<LevelStem> target, Registry<LevelStem> source) {
|
||||
if (source == null) return;
|
||||
source.registryKeySet().forEach(key -> {
|
||||
var value = source.get(key);
|
||||
var info = source.registrationInfo(key).orElse(null);
|
||||
if (value != null && info != null && !target.containsKey(key))
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return ResourceLocation.fromNamespaceAndPath("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,22 +6,37 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
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.util.scheduling.J;
|
||||
import lombok.SneakyThrows;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.WorldLoader;
|
||||
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;
|
||||
@@ -72,9 +87,11 @@ public class NMSBinding implements INMSBinding {
|
||||
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
|
||||
private final BlockData AIR = Material.AIR.createBlockData();
|
||||
private final AtomicCache<MCAIdMap<net.minecraft.world.level.biome.Biome>> biomeMapCache = new AtomicCache<>();
|
||||
private final AtomicCache<WorldLoader.DataLoadContext> dataLoadContext = new AtomicCache<>();
|
||||
private final AtomicCache<MCAIdMapper<BlockState>> registryCache = new AtomicCache<>();
|
||||
private final AtomicCache<MCAPalette<BlockState>> globalCache = new AtomicCache<>();
|
||||
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
|
||||
private final ReentrantLock dataContextLock = new ReentrantLock(true);
|
||||
private final AtomicCache<Method> byIdRef = new AtomicCache<>();
|
||||
private Field biomeStorageCache = null;
|
||||
|
||||
@@ -533,6 +550,9 @@ public class NMSBinding implements INMSBinding {
|
||||
var worldGenContextField = getField(chunkMap.getClass(), WorldGenContext.class);
|
||||
worldGenContextField.setAccessible(true);
|
||||
var worldGenContext = (WorldGenContext) worldGenContextField.get(chunkMap);
|
||||
var dimensionType = chunkMap.level.dimensionTypeRegistration().unwrapKey().orElse(null);
|
||||
if (dimensionType != null && !dimensionType.location().getNamespace().equals("iris"))
|
||||
Iris.error("Loaded world %s with invalid dimension type! (%s)", world.getName(), dimensionType.location().toString());
|
||||
|
||||
var newContext = new WorldGenContext(
|
||||
worldGenContext.level(), new IrisChunkGenerator(worldGenContext.generator(), seed, engine, world),
|
||||
@@ -644,4 +664,120 @@ public class NMSBinding implements INMSBinding {
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}));
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
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) {
|
||||
var access = registry();
|
||||
var dimensions = access.lookupOrThrow(Registries.DIMENSION_TYPE);
|
||||
|
||||
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, 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, access.lookupOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
}
|
||||
|
||||
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(loc).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), RegistrationInfo.BUILT_IN);
|
||||
}
|
||||
|
||||
private void copy(MappedRegistry<LevelStem> target, Registry<LevelStem> source) {
|
||||
if (source == null) return;
|
||||
source.listElementIds().forEach(key -> {
|
||||
var value = source.getValue(key);
|
||||
var info = source.registrationInfo(key).orElse(null);
|
||||
if (value != null && info != null && !target.containsKey(key))
|
||||
target.register(key, value, info);
|
||||
});
|
||||
}
|
||||
|
||||
private ResourceLocation createIrisKey(ResourceKey<LevelStem> key) {
|
||||
return ResourceLocation.fromNamespaceAndPath("iris", key.location().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.volmit.iris.core.nms.v1_21_R3;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
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.core.nms.datapack.DataVersion;
|
||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
@@ -19,6 +22,7 @@ import com.volmit.iris.util.nbt.mca.palette.*;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import lombok.SneakyThrows;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
@@ -27,13 +31,17 @@ import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.nbt.*;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.WorldLoader;
|
||||
import net.minecraft.server.commands.data.BlockDataAccessor;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
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;
|
||||
@@ -41,6 +49,11 @@ import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
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;
|
||||
@@ -66,14 +79,18 @@ import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class NMSBinding implements INMSBinding {
|
||||
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
|
||||
private final BlockData AIR = Material.AIR.createBlockData();
|
||||
private final AtomicCache<MCAIdMap<net.minecraft.world.level.biome.Biome>> biomeMapCache = new AtomicCache<>();
|
||||
private final AtomicCache<WorldLoader.DataLoadContext> dataLoadContext = new AtomicCache<>();
|
||||
private final AtomicCache<MCAIdMapper<BlockState>> registryCache = new AtomicCache<>();
|
||||
private final AtomicCache<MCAPalette<BlockState>> globalCache = new AtomicCache<>();
|
||||
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
|
||||
private final ReentrantLock dataContextLock = new ReentrantLock(true);
|
||||
private final AtomicCache<Method> byIdRef = new AtomicCache<>();
|
||||
private Field biomeStorageCache = null;
|
||||
|
||||
@@ -532,6 +549,9 @@ public class NMSBinding implements INMSBinding {
|
||||
var worldGenContextField = getField(chunkMap.getClass(), WorldGenContext.class);
|
||||
worldGenContextField.setAccessible(true);
|
||||
var worldGenContext = (WorldGenContext) worldGenContextField.get(chunkMap);
|
||||
var dimensionType = chunkMap.level.dimensionTypeRegistration().unwrapKey().orElse(null);
|
||||
if (dimensionType != null && !dimensionType.location().getNamespace().equals("iris"))
|
||||
Iris.error("Loaded world %s with invalid dimension type! (%s)", world.getName(), dimensionType.location().toString());
|
||||
|
||||
var newContext = new WorldGenContext(
|
||||
worldGenContext.level(), new IrisChunkGenerator(worldGenContext.generator(), seed, engine, world),
|
||||
@@ -643,4 +663,120 @@ public class NMSBinding implements INMSBinding {
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}));
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
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) {
|
||||
var access = registry();
|
||||
var dimensions = access.lookupOrThrow(Registries.DIMENSION_TYPE);
|
||||
|
||||
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, 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, access.lookupOrThrow(Registries.LEVEL_STEM));
|
||||
|
||||
return new RegistryAccess.Frozen.ImmutableRegistryAccess(List.of(fake.freeze())).freeze();
|
||||
}
|
||||
|
||||
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(loc).orElseThrow(() -> new IllegalStateException("Missing dimension type " + loc + " in " + dimensions.keySet())),
|
||||
source
|
||||
), RegistrationInfo.BUILT_IN);
|
||||
}
|
||||
|
||||
private void copy(MappedRegistry<LevelStem> target, Registry<LevelStem> source) {
|
||||
if (source == null) return;
|
||||
source.listElementIds().forEach(key -> {
|
||||
var value = source.getValue(key);
|
||||
var info = source.registrationInfo(key).orElse(null);
|
||||
if (value != null && info != null && !target.containsKey(key))
|
||||
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