9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-28 03:29:06 +00:00

replace datapack system with a dynamic one

This commit is contained in:
CrazyDev22
2024-05-20 06:41:38 +02:00
parent eb19d9a846
commit a967b6af85
27 changed files with 370 additions and 682 deletions

View File

@@ -227,9 +227,6 @@ shadowJar {
dependencies {
implementation project(':core')
NMS_BINDINGS.each {
implementation project(":nms:${it.key}")
}
}
configurations.configureEach {

View File

@@ -458,7 +458,6 @@ public class Iris extends VolmitPlugin implements Listener {
instance = this;
InitializeSafeguard();
ByteBuddyAgent.install();
boolean configured;
services = new KMap<>();
setupAudience();
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
@@ -474,7 +473,6 @@ public class Iris extends VolmitPlugin implements Listener {
configWatcher = new FileWatcher(getDataFile("settings.json"));
services.values().forEach(IrisService::onEnable);
services.values().forEach(this::registerListener);
configured = ServerConfigurator.postConfigure();
installMainDimension();
if (!IrisSafeguard.instance.acceptUnstable && IrisSafeguard.instance.unstablemode) {
Iris.info(C.RED + "World loading has been disabled until the incompatibility is resolved.");
@@ -488,7 +486,7 @@ public class Iris extends VolmitPlugin implements Listener {
J.ar(this::checkConfigHotload, 60);
J.sr(this::tickQueue, 0);
J.s(this::setupPapi);
if (!configured) J.a(ServerConfigurator::configure, 20);
J.a(ServerConfigurator::configure, 20);
splash();
UtilsSFG.splash();
autoStartStudio();

View File

@@ -19,35 +19,15 @@
package com.volmit.iris.core;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.engine.object.IrisRange;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import static org.bukkit.Bukkit.getServer;
public class ServerConfigurator {
public static void configure() {
IrisSettings.IrisSettingsAutoconfiguration s = IrisSettings.get().getAutoConfiguration();
@@ -58,16 +38,6 @@ public class ServerConfigurator {
if (s.isConfigurePaperWatchdogDelay()) {
J.attempt(ServerConfigurator::increasePaperWatchdog);
}
installDataPacks(true);
}
public static boolean postConfigure() {
if(postVerifyDataPacks(true)) {
configure();
return true;
}
return false;
}
private static void increaseKeepAliveSpigot() throws IOException, InvalidConfigurationException {
@@ -83,6 +53,7 @@ public class ServerConfigurator {
f.save(spigotConfig);
}
}
private static void increasePaperWatchdog() throws IOException, InvalidConfigurationException {
File spigotConfig = new File("config/paper-global.yml");
FileConfiguration f = new YamlConfiguration();
@@ -96,219 +67,4 @@ public class ServerConfigurator {
f.save(spigotConfig);
}
}
private static List<File> getDatapacksFolder() {
if (!IrisSettings.get().getGeneral().forceMainWorld.isEmpty()) {
return new KList<File>().qadd(new File(Bukkit.getWorldContainer(), IrisSettings.get().getGeneral().forceMainWorld + "/datapacks"));
}
KList<File> worlds = new KList<>();
Bukkit.getServer().getWorlds().forEach(w -> worlds.add(new File(w.getWorldFolder(), "datapacks")));
if (worlds.isEmpty()) {
worlds.add(new File(getMainWorldFolder(), "datapacks"));
}
return worlds;
}
private static File getMainWorldFolder() {
try {
Properties prop = new Properties();
prop.load(new FileInputStream("server.properties"));
String world = prop.getProperty("level-name", "world");
return new File(Bukkit.getWorldContainer(), world);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static boolean postVerifyDataPacks(boolean fast) {
try {
File datapacksFolder = new File(getMainWorldFolder(), "datapacks");
File IrisDatapacks = new File(datapacksFolder, "iris");
if (!datapacksFolder.exists() || !IrisDatapacks.exists()) {
return (true);
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static void installDataPacks(boolean fullInstall) {
installDataPacks(DataVersion.getDefault(), fullInstall);
}
public static void installDataPacks(IDataFixer fixer, boolean fullInstall) {
Iris.info("Checking Data Packs...");
File packs = new File("plugins/Iris/packs");
double ultimateMaxHeight = 0;
double ultimateMinHeight = 0;
if (packs.exists() && packs.isDirectory()) {
for (File pack : packs.listFiles()) {
IrisData data = IrisData.get(pack);
if (pack.isDirectory()) {
File dimensionsFolder = new File(pack, "dimensions");
if (dimensionsFolder.exists() && dimensionsFolder.isDirectory()) {
for (File file : dimensionsFolder.listFiles()) {
if (file.isFile() && file.getName().endsWith(".json")) {
IrisDimension dim = data.getDimensionLoader().load(file.getName().split("\\Q.\\E")[0]);
if (ultimateMaxHeight < dim.getDimensionHeight().getMax()) {
ultimateMaxHeight = dim.getDimensionHeight().getMax();
}
if (ultimateMinHeight > dim.getDimensionHeight().getMin()) {
ultimateMinHeight = dim.getDimensionHeight().getMin();
}
}
}
}
}
}
}
if (packs.exists()) {
for (File i : packs.listFiles()) {
if (i.isDirectory()) {
Iris.verbose("Checking Pack: " + i.getPath());
IrisData data = IrisData.get(i);
File dims = new File(i, "dimensions");
if (dims.exists()) {
for (File j : dims.listFiles()) {
if (j.getName().endsWith(".json")) {
IrisDimension dim = data.getDimensionLoader().load(j.getName().split("\\Q.\\E")[0]);
if (dim == null) {
continue;
}
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
for (File dpack : getDatapacksFolder()) {
dim.installDataPack(fixer, () -> data, dpack);
}
}
}
}
}
}
}
Iris.info("Data Packs Setup!");
if (fullInstall)
verifyDataPacksPost(IrisSettings.get().getAutoConfiguration().isAutoRestartOnCustomBiomeInstall());
}
private static void verifyDataPacksPost(boolean allowRestarting) {
File packs = new File("plugins/Iris/packs");
boolean bad = false;
if (packs.exists()) {
for (File i : packs.listFiles()) {
if (i.isDirectory()) {
Iris.verbose("Checking Pack: " + i.getPath());
IrisData data = IrisData.get(i);
File dims = new File(i, "dimensions");
if (dims.exists()) {
for (File j : dims.listFiles()) {
if (j.getName().endsWith(".json")) {
IrisDimension dim = data.getDimensionLoader().load(j.getName().split("\\Q.\\E")[0]);
if (dim == null) {
Iris.error("Failed to load " + j.getPath() + " ");
continue;
}
if (!verifyDataPackInstalled(dim)) {
bad = true;
}
}
}
}
}
}
}
if (bad) {
// Iris.info("");
Iris.info( "Hotloading all Datapacks!");
if (INMS.get().supportsDataPacks()) {
for (File folder : getDatapacksFolder()) {
INMS.get().loadDatapack(folder, false);
}
Iris.info("Datapacks Hotloaded!");
Iris.info(C.YELLOW + "============================================================================");
Iris.info(C.ITALIC + "" + C.YELLOW + "To ensure the stability of custom biome generation, a server restart is necessary.");
Iris.info(C.ITALIC + "" + C.YELLOW + "While datapacks have been hotloaded, a complete restart is advised.");
Iris.info(C.YELLOW + "----------------------------------------------------------------------------");
Iris.info(C.UNDERLINE + "" + C.YELLOW + "IT IS HIGHLY RECOMMENDED YOU RESTART THE SERVER BEFORE GENERATING!");
Iris.info(C.YELLOW + "============================================================================");
for (Player i : Bukkit.getOnlinePlayers()) {
if (i.isOp() || i.hasPermission("iris.all")) {
VolmitSender sender = new VolmitSender(i, Iris.instance.getTag("WARNING"));
sender.sendMessage("There are some Iris Packs that have custom biomes in them");
sender.sendMessage("You need to restart your server to use these packs.");
}
}
J.sleep(3000);
}
}
}
public static void restart() {
J.s(() -> {
Iris.warn("New data pack entries have been installed in Iris! Restarting server!");
Iris.warn("This will only happen when your pack changes (updates/first time setup)");
Iris.warn("(You can disable this auto restart in iris settings)");
J.s(() -> {
Iris.warn("Looks like the restart command didn't work. Stopping the server instead!");
Bukkit.shutdown();
}, 100);
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "restart");
});
}
public static boolean verifyDataPackInstalled(IrisDimension dimension) {
IrisData idm = IrisData.get(Iris.instance.getDataFolder("packs", dimension.getLoadKey()));
KSet<String> keys = new KSet<>();
boolean warn = false;
for (IrisBiome i : dimension.getAllBiomes(() -> idm)) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
keys.add(dimension.getLoadKey() + ":" + j.getId());
}
}
}
if (!INMS.get().supportsDataPacks()) {
if (!keys.isEmpty()) {
Iris.warn("===================================================================================");
Iris.warn("Pack " + dimension.getLoadKey() + " has " + keys.size() + " custom biome(s). ");
Iris.warn("Your server version does not yet support datapacks for iris.");
Iris.warn("The world will generate these biomes as backup biomes.");
Iris.warn("====================================================================================");
}
return true;
}
for (String i : keys) {
Object o = INMS.get().getCustomBiomeBaseFor(i);
if (o == null) {
Iris.warn("The Biome " + i + " is not registered on the server.");
warn = true;
}
}
if (warn) {
Iris.error("The Pack " + dimension.getLoadKey() + " is INCAPABLE of generating custom biomes");
Iris.error("Queued for Datapack Hotload.");
}
return !warn;
}
}

View File

@@ -163,14 +163,6 @@ public class CommandDeveloper implements DecreeExecutor {
}
@Decree(description = "Upgrade to another Minecraft version")
public void upgrade(
@Param(description = "The version to upgrade to", defaultValue = "latest") DataVersion version) {
sender().sendMessage(C.GREEN + "Upgrading to " + version.getVersion() + "...");
ServerConfigurator.installDataPacks(version.get(), false);
sender().sendMessage(C.GREEN + "Done upgrading! You can now update your server version to " + version.getVersion());
}
@Decree(description = "Test")
public void updater(
@Param(description = "Updater for chunks")

View File

@@ -20,21 +20,16 @@ package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.gui.NoiseExplorerGUI;
import com.volmit.iris.core.gui.VisionGUI;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.project.IrisProject;
import com.volmit.iris.core.service.ConversionSVC;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.core.tools.IrisConverter;
import com.volmit.iris.core.tools.IrisNoiseBenchmark;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.engine.platform.studio.StudioGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
@@ -43,30 +38,23 @@ import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.DecreeOrigin;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.decree.specialhandlers.NullablePlayerHandler;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.function.Function2;
import com.volmit.iris.util.function.NoiseProvider;
import com.volmit.iris.util.interpolation.InterpolationMethod;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.json.JSONArray;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.noise.CNG;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.O;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import com.volmit.iris.util.scheduling.jobs.QueueJob;
import io.papermc.lib.PaperLib;
import org.bukkit.*;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.util.BlockVector;
@@ -85,7 +73,6 @@ import java.util.Date;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
@Decree(name = "studio", aliases = {"std", "s"}, description = "Studio Commands", studio = true)
@@ -286,7 +273,7 @@ public class CommandStudio implements DecreeExecutor {
}
@Decree(description = "Hotload a studio", aliases = {"reload", "h"})
public void hotload(@Param(defaultValue = "false") boolean reloadDataPack) {
public void hotload() {
if (!Iris.service(StudioSVC.class).isProjectOpen()) {
sender().sendMessage(C.RED + "No studio world open!");
return;
@@ -294,15 +281,6 @@ public class CommandStudio implements DecreeExecutor {
var provider = Iris.service(StudioSVC.class).getActiveProject().getActiveProvider();
provider.getEngine().hotload();
sender().sendMessage(C.GREEN + "Hotloaded");
if (reloadDataPack) {
var world = provider.getTarget().getWorld().realWorld();
if (world == null) {
sender().sendMessage(C.RED + "Failed to reload datapacks.");
return;
}
boolean success = INMS.get().loadDatapack(new File(world.getWorldFolder(), "datapacks"), true);
sender().sendMessage(success ? C.GREEN + "Reloaded datapacks." : C.RED + "Failed to reload datapacks.");
}
}
@Decree(description = "Show loot if a chest were right here", origin = DecreeOrigin.PLAYER, sync = true)

View File

@@ -20,10 +20,10 @@ package com.volmit.iris.core.nms;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.documentation.RegionCoordinates;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
@@ -38,12 +38,9 @@ import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import java.io.File;
public interface INMSBinding {
boolean hasTile(Location l);
@@ -121,10 +118,10 @@ public interface INMSBinding {
return DataVersion.V1192;
}
boolean loadDatapack(File datapackFolder, boolean replace);
boolean registerDimension(String name, IrisDimension dimension);
boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace);
void injectBukkit();
default IHeadless createHeadless(Engine engine) {

View File

@@ -23,6 +23,7 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
import com.volmit.iris.core.nms.container.BlockPos;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
@@ -108,12 +109,12 @@ public class NMSBinding1X implements INMSBinding {
}
@Override
public boolean loadDatapack(File datapackFolder, boolean replace) {
public boolean registerDimension(String name, IrisDimension dimension) {
return false;
}
@Override
public boolean registerDimension(String name, IrisDimension dimension) {
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
return false;
}

View File

@@ -22,7 +22,6 @@ import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.pack.IrisPack;
import com.volmit.iris.core.project.IrisProject;
@@ -296,7 +295,6 @@ public class StudioSVC implements IrisService {
}
sender.sendMessage("Successfully Aquired " + d.getName());
ServerConfigurator.installDataPacks(true);
}
public KMap<String, String> getListing(boolean cached) {

View File

@@ -21,13 +21,10 @@ package com.volmit.iris.core.tools;
import com.google.common.util.concurrent.AtomicDouble;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.core.safeguard.UtilsSFG;
import com.volmit.iris.util.exceptions.IrisException;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
@@ -144,7 +141,6 @@ public class IrisCreator {
.studio(studio)
.smartVanillaHeight(smartVanillaHeight)
.create();
ServerConfigurator.installDataPacks(false);
access = (PlatformChunkGenerator) wc.generator();
PlatformChunkGenerator finalAccess1 = access;

View File

@@ -21,8 +21,6 @@ package com.volmit.iris.engine;
import com.google.common.util.concurrent.AtomicDouble;
import com.google.gson.Gson;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.events.IrisEngineHotloadEvent;
import com.volmit.iris.core.gui.PregeneratorJob;
import com.volmit.iris.core.nms.container.BlockPos;
@@ -53,7 +51,6 @@ import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
@@ -66,8 +63,6 @@ import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Data
@EqualsAndHashCode(exclude = "context")
@@ -242,11 +237,6 @@ public class IrisEngine implements Engine {
getTarget().setDimension(getData().getDimensionLoader().load(getDimension().getLoadKey()));
prehotload();
setupEngine();
J.a(() -> {
synchronized (ServerConfigurator.class) {
ServerConfigurator.installDataPacks(false);
}
});
}
@Override

View File

@@ -19,7 +19,7 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
@@ -92,7 +92,7 @@ public class IrisBiomeCustom {
@Desc("The color of foliage (hex format). Leave blank / don't define to not change")
private String foliageColor = "";
public String generateJson(IDataFixer fixer) {
public String generateJson() {
JSONObject effects = new JSONObject();
effects.put("sky_color", parseColor(getSkyColor()));
effects.put("fog_color", parseColor(getFogColor()));
@@ -158,7 +158,7 @@ public class IrisBiomeCustom {
j.put("spawners", spawners);
}
return fixer.fixCustomBiome(this, j).toString(4);
return DataVersion.getDefault().fixCustomBiome(this, j).toString(4);
}
private int parseColor(String c) {

View File

@@ -18,15 +18,12 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.loader.IrisRegistrant;
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.data.DataProvider;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RNG;
@@ -41,9 +38,6 @@ import org.bukkit.Material;
import org.bukkit.World.Environment;
import org.bukkit.block.data.BlockData;
import java.io.File;
import java.io.IOException;
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@@ -377,56 +371,6 @@ public class IrisDimension extends IrisRegistrant {
return landBiomeStyle;
}
public boolean installDataPack(IDataFixer fixer, DataProvider data, File datapacks) {
boolean write = false;
boolean changed = false;
IO.delete(new File(datapacks, "iris/data/" + getLoadKey().toLowerCase()));
for (IrisBiome i : getAllBiomes(data)) {
if (i.isCustom()) {
write = true;
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
File output = new File(datapacks, "iris/data/" + getLoadKey().toLowerCase() + "/worldgen/biome/" + j.getId() + ".json");
if (!output.exists()) {
changed = true;
}
Iris.verbose(" Installing Data Pack Biome: " + output.getPath());
output.getParentFile().mkdirs();
try {
IO.writeAll(output, j.generateJson(fixer));
} catch (IOException e) {
Iris.reportError(e);
e.printStackTrace();
}
}
}
}
if (write) {
File mcm = new File(datapacks, "iris/pack.mcmeta");
try {
IO.writeAll(mcm, """
{
"pack": {
"description": "Iris Data Pack. This pack contains all installed Iris Packs' resources.",
"pack_format": 10
}
}
""");
} catch (IOException e) {
Iris.reportError(e);
e.printStackTrace();
}
Iris.verbose(" Installing Data Pack MCMeta: " + mcm.getPath());
}
return changed;
}
@Override
public String getFolderName() {
return "dimensions";

View File

@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_19_R1;
import com.mojang.serialization.Codec;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
@@ -11,6 +12,7 @@ import com.volmit.iris.util.math.RNG;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
@@ -25,6 +27,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class CustomBiomeSource extends BiomeSource {
private final long seed;
@@ -118,8 +121,28 @@ public class CustomBiomeSource extends BiomeSource {
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
m.put(j.getId(), customRegistry.getHolder(customRegistry.getResourceKey(customRegistry
.get(new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()))).get()).get());
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(location);
if (biome == null) {
INMS.get().registerBiome(location.getNamespace(), j, false);
biome = customRegistry.get(location);
if (biome == null) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
continue;
}
}
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
if (optionalBiomeKey.isEmpty()) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
continue;
}
ResourceKey<Biome> biomeKey = optionalBiomeKey.get();
Optional<Holder<Biome>> optionalReferenceHolder = customRegistry.getHolder(biomeKey);
if (optionalReferenceHolder.isEmpty()) {
Iris.error("Cannot find reference to biome " + biomeKey + " for engine " + engine.getName());
continue;
}
m.put(j.getId(), optionalReferenceHolder.get());
}
}
}

View File

@@ -5,12 +5,9 @@ import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -26,9 +23,9 @@ import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.Lifecycle;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.io.IO;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.asm.Advice;
@@ -587,51 +584,10 @@ public class NMSBinding implements INMSBinding {
}
@Override
public boolean loadDatapack(File folder, boolean replace) {
var data = new File(folder, "iris/data");
if (!data.exists() || !data.isDirectory()) return false;
FilenameFilter jsonFilter = (dir, name) -> new File(dir, name).isFile() && name.toLowerCase().endsWith(".json");
var files = data.listFiles((dir, name) -> new File(dir, name).isDirectory());
if (files == null) return false;
for (File file : files) {
var biome = new File(file, "worldgen/biome");
if (!biome.exists()) continue;
var biomeFiles = biome.listFiles(jsonFilter);
if (biomeFiles == null) continue;
for (File biomeFile : biomeFiles) {
String json = null;
int tries = 10;
while (json == null && tries-- > 0) {
try {
json = IO.readAll(biomeFile);
} catch (IOException e) {
Iris.error("Failed to read biome " + file.getName() + ":" + biomeFile.getName() + " tries left: " + tries);
if (tries == 0) {
e.printStackTrace();
}
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {}
}
}
if (json == null) continue;
try {
var value = decode(net.minecraft.world.level.biome.Biome.CODEC, json).map(Holder::value).orElse(null);
register(Registry.BIOME_REGISTRY, from(file.getName(), biomeFile), value, replace);
} catch (Throwable e) {
Iris.error("Failed to register biome " + file.getName() + ":" + biomeFile.getName());
e.printStackTrace();
}
}
}
return true;
}
private ResourceLocation from(String namespace, File file) {
var name = file.getName();
return new ResourceLocation(namespace, name.substring(0, name.lastIndexOf('.')));
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
if (biomeBase == null) return false;
return register(Registry.BIOME_REGISTRY, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
}
private <T> Optional<T> decode(Codec<T> codec, String json) {

View File

@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_19_R2;
import com.mojang.serialization.Codec;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
@@ -12,6 +13,7 @@ import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
@@ -26,6 +28,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class CustomBiomeSource extends BiomeSource {
@@ -120,8 +123,28 @@ public class CustomBiomeSource extends BiomeSource {
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
m.put(j.getId(), customRegistry.getHolder(customRegistry.getResourceKey(customRegistry
.get(new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()))).get()).get());
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(location);
if (biome == null) {
INMS.get().registerBiome(location.getNamespace(), j, false);
biome = customRegistry.get(location);
if (biome == null) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
continue;
}
}
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
if (optionalBiomeKey.isEmpty()) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
continue;
}
ResourceKey<Biome> biomeKey = optionalBiomeKey.get();
Optional<Holder.Reference<Biome>> optionalReferenceHolder = customRegistry.getHolder(biomeKey);
if (optionalReferenceHolder.isEmpty()) {
Iris.error("Cannot find reference to biome " + biomeKey + " for engine " + engine.getName());
continue;
}
m.put(j.getId(), optionalReferenceHolder.get());
}
}
}

View File

@@ -5,12 +5,9 @@ import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -26,9 +23,9 @@ import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.Lifecycle;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.io.IO;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.asm.Advice;
@@ -589,51 +586,10 @@ public class NMSBinding implements INMSBinding {
}
@Override
public boolean loadDatapack(File folder, boolean replace) {
var data = new File(folder, "iris/data");
if (!data.exists() || !data.isDirectory()) return false;
FilenameFilter jsonFilter = (dir, name) -> new File(dir, name).isFile() && name.toLowerCase().endsWith(".json");
var files = data.listFiles((dir, name) -> new File(dir, name).isDirectory());
if (files == null) return false;
for (File file : files) {
var biome = new File(file, "worldgen/biome");
if (!biome.exists()) continue;
var biomeFiles = biome.listFiles(jsonFilter);
if (biomeFiles == null) continue;
for (File biomeFile : biomeFiles) {
String json = null;
int tries = 10;
while (json == null && tries-- > 0) {
try {
json = IO.readAll(biomeFile);
} catch (IOException e) {
Iris.error("Failed to read biome " + file.getName() + ":" + biomeFile.getName() + " tries left: " + tries);
if (tries == 0) {
e.printStackTrace();
}
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {}
}
}
if (json == null) continue;
try {
var value = decode(net.minecraft.world.level.biome.Biome.CODEC, json).map(Holder::value).orElse(null);
register(Registries.BIOME, from(file.getName(), biomeFile), value, replace);
} catch (Throwable e) {
Iris.error("Failed to register biome " + file.getName() + ":" + biomeFile.getName());
e.printStackTrace();
}
}
}
return true;
}
private ResourceLocation from(String namespace, File file) {
var name = file.getName();
return new ResourceLocation(namespace, name.substring(0, name.lastIndexOf('.')));
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
if (biomeBase == null) return false;
return register(Registries.BIOME, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
}
private <T> Optional<T> decode(Codec<T> codec, String json) {

View File

@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_19_R3;
import com.mojang.serialization.Codec;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
@@ -125,8 +126,16 @@ public class CustomBiomeSource extends BiomeSource {
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
ResourceLocation resourceLocation = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(resourceLocation);
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(location);
if (biome == null) {
INMS.get().registerBiome(location.getNamespace(), j, false);
biome = customRegistry.get(location);
if (biome == null) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
continue;
}
}
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
if (optionalBiomeKey.isEmpty()) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());

View File

@@ -5,12 +5,9 @@ import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -26,9 +23,9 @@ import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.Lifecycle;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.io.IO;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.asm.Advice;
@@ -593,51 +590,10 @@ public class NMSBinding implements INMSBinding {
}
@Override
public boolean loadDatapack(File folder, boolean replace) {
var data = new File(folder, "iris/data");
if (!data.exists() || !data.isDirectory()) return false;
FilenameFilter jsonFilter = (dir, name) -> new File(dir, name).isFile() && name.toLowerCase().endsWith(".json");
var files = data.listFiles((dir, name) -> new File(dir, name).isDirectory());
if (files == null) return false;
for (File file : files) {
var biome = new File(file, "worldgen/biome");
if (!biome.exists()) continue;
var biomeFiles = biome.listFiles(jsonFilter);
if (biomeFiles == null) continue;
for (File biomeFile : biomeFiles) {
String json = null;
int tries = 10;
while (json == null && tries-- > 0) {
try {
json = IO.readAll(biomeFile);
} catch (IOException e) {
Iris.error("Failed to read biome " + file.getName() + ":" + biomeFile.getName() + " tries left: " + tries);
if (tries == 0) {
e.printStackTrace();
}
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {}
}
}
if (json == null) continue;
try {
var value = decode(net.minecraft.world.level.biome.Biome.CODEC, json).map(Holder::value).orElse(null);
register(Registries.BIOME, from(file.getName(), biomeFile), value, replace);
} catch (Throwable e) {
Iris.error("Failed to register biome " + file.getName() + ":" + biomeFile.getName());
e.printStackTrace();
}
}
}
return true;
}
private ResourceLocation from(String namespace, File file) {
var name = file.getName();
return new ResourceLocation(namespace, name.substring(0, name.lastIndexOf('.')));
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
if (biomeBase == null) return false;
return register(Registries.BIOME, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
}
private <T> Optional<T> decode(Codec<T> codec, String json) {

View File

@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_20_R1;
import com.mojang.serialization.Codec;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
@@ -125,8 +126,16 @@ public class CustomBiomeSource extends BiomeSource {
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
ResourceLocation resourceLocation = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(resourceLocation);
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(location);
if (biome == null) {
INMS.get().registerBiome(location.getNamespace(), j, false);
biome = customRegistry.get(location);
if (biome == null) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
continue;
}
}
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
if (optionalBiomeKey.isEmpty()) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());

View File

@@ -12,12 +12,12 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
@@ -47,7 +47,6 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.RandomSequences;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
@@ -73,9 +72,7 @@ import org.bukkit.craftbukkit.v1_20_R1.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.entity.EntityType;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
@@ -87,12 +84,9 @@ import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -580,51 +574,10 @@ public class NMSBinding implements INMSBinding {
}
@Override
public boolean loadDatapack(File folder, boolean replace) {
var data = new File(folder, "iris/data");
if (!data.exists() || !data.isDirectory()) return false;
FilenameFilter jsonFilter = (dir, name) -> new File(dir, name).isFile() && name.toLowerCase().endsWith(".json");
var files = data.listFiles((dir, name) -> new File(dir, name).isDirectory());
if (files == null) return false;
for (File file : files) {
var biome = new File(file, "worldgen/biome");
if (!biome.exists()) continue;
var biomeFiles = biome.listFiles(jsonFilter);
if (biomeFiles == null) continue;
for (File biomeFile : biomeFiles) {
String json = null;
int tries = 10;
while (json == null && tries-- > 0) {
try {
json = IO.readAll(biomeFile);
} catch (IOException e) {
Iris.error("Failed to read biome " + file.getName() + ":" + biomeFile.getName() + " tries left: " + tries);
if (tries == 0) {
e.printStackTrace();
}
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {}
}
}
if (json == null) continue;
try {
var value = decode(net.minecraft.world.level.biome.Biome.CODEC, json).map(Holder::value).orElse(null);
register(Registries.BIOME, from(file.getName(), biomeFile), value, replace);
} catch (Throwable e) {
Iris.error("Failed to register biome " + file.getName() + ":" + biomeFile.getName());
e.printStackTrace();
}
}
}
return true;
}
private ResourceLocation from(String namespace, File file) {
var name = file.getName();
return new ResourceLocation(namespace, name.substring(0, name.lastIndexOf('.')));
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
if (biomeBase == null) return false;
return register(Registries.BIOME, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
}
private <T> Optional<T> decode(Codec<T> codec, String json) {

View File

@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_20_R2;
import com.mojang.serialization.Codec;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
@@ -124,8 +125,16 @@ public class CustomBiomeSource extends BiomeSource {
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
ResourceLocation resourceLocation = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(resourceLocation);
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(location);
if (biome == null) {
INMS.get().registerBiome(location.getNamespace(), j, false);
biome = customRegistry.get(location);
if (biome == null) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
continue;
}
}
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
if (optionalBiomeKey.isEmpty()) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());

View File

@@ -5,12 +5,9 @@ import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -26,9 +23,9 @@ import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.Lifecycle;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.io.IO;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.asm.Advice;
@@ -590,51 +587,10 @@ public class NMSBinding implements INMSBinding {
}
@Override
public boolean loadDatapack(File folder, boolean replace) {
var data = new File(folder, "iris/data");
if (!data.exists() || !data.isDirectory()) return false;
FilenameFilter jsonFilter = (dir, name) -> new File(dir, name).isFile() && name.toLowerCase().endsWith(".json");
var files = data.listFiles((dir, name) -> new File(dir, name).isDirectory());
if (files == null) return false;
for (File file : files) {
var biome = new File(file, "worldgen/biome");
if (!biome.exists()) continue;
var biomeFiles = biome.listFiles(jsonFilter);
if (biomeFiles == null) continue;
for (File biomeFile : biomeFiles) {
String json = null;
int tries = 10;
while (json == null && tries-- > 0) {
try {
json = IO.readAll(biomeFile);
} catch (IOException e) {
Iris.error("Failed to read biome " + file.getName() + ":" + biomeFile.getName() + " tries left: " + tries);
if (tries == 0) {
e.printStackTrace();
}
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {}
}
}
if (json == null) continue;
try {
var value = decode(net.minecraft.world.level.biome.Biome.CODEC, json).map(Holder::value).orElse(null);
register(Registries.BIOME, from(file.getName(), biomeFile), value, replace);
} catch (Throwable e) {
Iris.error("Failed to register biome " + file.getName() + ":" + biomeFile.getName());
e.printStackTrace();
}
}
}
return true;
}
private ResourceLocation from(String namespace, File file) {
var name = file.getName();
return new ResourceLocation(namespace, name.substring(0, name.lastIndexOf('.')));
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
if (biomeBase == null) return false;
return register(Registries.BIOME, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
}
private <T> Optional<T> decode(Codec<T> codec, String json) {

View File

@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_20_R3;
import com.mojang.serialization.Codec;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
@@ -124,8 +125,16 @@ public class CustomBiomeSource extends BiomeSource {
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
ResourceLocation resourceLocation = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(resourceLocation);
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(location);
if (biome == null) {
INMS.get().registerBiome(location.getNamespace(), j, false);
biome = customRegistry.get(location);
if (biome == null) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
continue;
}
}
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
if (optionalBiomeKey.isEmpty()) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());

View File

@@ -66,6 +66,14 @@ public class Headless implements IHeadless, LevelHeightAccessor {
};
queueLooper.setName("Region Save Looper");
queueLooper.start();
var dimKey = engine.getDimension().getLoadKey();
for (var biome : engine.getAllBiomes()) {
if (!biome.isCustom()) continue;
for (var custom : biome.getCustomDerivitives()) {
binding.registerBiome(dimKey, custom, false);
}
}
}
@Override

View File

@@ -5,8 +5,6 @@ import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -23,16 +21,9 @@ import com.mojang.serialization.JsonOps;
import com.mojang.serialization.Lifecycle;
import com.volmit.iris.core.nms.IHeadless;
import com.volmit.iris.core.nms.v1_20_R3.mca.ChunkSerializer;
import com.volmit.iris.core.nms.v1_20_R3.mca.MCATerrainChunk;
import com.volmit.iris.core.nms.v1_20_R3.mca.RegionFileStorage;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.documentation.RegionCoordinates;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder;
import com.volmit.iris.util.hunk.view.ChunkDataHunkHolder;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.asm.Advice;
@@ -601,51 +592,10 @@ public class NMSBinding implements INMSBinding {
}
@Override
public boolean loadDatapack(File folder, boolean replace) {
var data = new File(folder, "iris/data");
if (!data.exists() || !data.isDirectory()) return false;
FilenameFilter jsonFilter = (dir, name) -> new File(dir, name).isFile() && name.toLowerCase().endsWith(".json");
var files = data.listFiles((dir, name) -> new File(dir, name).isDirectory());
if (files == null) return false;
for (File file : files) {
var biome = new File(file, "worldgen/biome");
if (!biome.exists()) continue;
var biomeFiles = biome.listFiles(jsonFilter);
if (biomeFiles == null) continue;
for (File biomeFile : biomeFiles) {
String json = null;
int tries = 10;
while (json == null && tries-- > 0) {
try {
json = IO.readAll(biomeFile);
} catch (IOException e) {
Iris.error("Failed to read biome " + file.getName() + ":" + biomeFile.getName() + " tries left: " + tries);
if (tries == 0) {
e.printStackTrace();
}
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {}
}
}
if (json == null) continue;
try {
var value = decode(net.minecraft.world.level.biome.Biome.CODEC, json).map(Holder::value).orElse(null);
register(Registries.BIOME, from(file.getName(), biomeFile), value, replace);
} catch (Throwable e) {
Iris.error("Failed to register biome " + file.getName() + ":" + biomeFile.getName());
e.printStackTrace();
}
}
}
return true;
}
private ResourceLocation from(String namespace, File file) {
var name = file.getName();
return new ResourceLocation(namespace, name.substring(0, name.lastIndexOf('.')));
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
if (biomeBase == null) return false;
return register(Registries.BIOME, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
}
private <T> Optional<T> decode(Codec<T> codec, String json) {

View File

@@ -2,6 +2,7 @@ package com.volmit.iris.core.nms.v1_20_R4;
import com.mojang.serialization.MapCodec;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
@@ -124,8 +125,16 @@ public class CustomBiomeSource extends BiomeSource {
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
ResourceLocation resourceLocation = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(resourceLocation);
ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(location);
if (biome == null) {
INMS.get().registerBiome(location.getNamespace(), j, false);
biome = customRegistry.get(location);
if (biome == null) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
continue;
}
}
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
if (optionalBiomeKey.isEmpty()) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());

View File

@@ -4,18 +4,47 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Vector;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.base.Preconditions;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.format.C;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
import net.bytebuddy.matcher.ElementMatchers;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.RegistrationInfo;
import net.minecraft.core.component.DataComponents;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.RandomSequences;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.PrimaryLevelData;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
@@ -29,6 +58,7 @@ import org.bukkit.craftbukkit.v1_20_R4.util.CraftNamespacedKey;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
@@ -549,4 +579,189 @@ public class NMSBinding implements INMSBinding {
public DataVersion getDataVersion() {
return DataVersion.V1205;
}
@Override
public boolean registerDimension(String name, IrisDimension dimension) {
var registry = registry(Registries.DIMENSION_TYPE);
var baseLocation = switch (dimension.getEnvironment()) {
case NORMAL -> new ResourceLocation("minecraft", "overworld");
case NETHER -> new ResourceLocation("minecraft", "the_nether");
case THE_END -> new ResourceLocation("minecraft", "the_end");
case CUSTOM -> throw new IllegalArgumentException("Cannot register custom dimension");
};
var base = registry.getHolder(ResourceKey.create(Registries.DIMENSION_TYPE, baseLocation)).orElse(null);
if (base == null) return false;
var json = encode(DimensionType.CODEC, base).orElse(null);
if (json == null) return false;
var object = json.getAsJsonObject();
var height = dimension.getDimensionHeight();
object.addProperty("min_y", height.getMin());
object.addProperty("height", height.getMax() - height.getMin());
object.addProperty("logical_height", dimension.getLogicalHeight());
var value = decode(DimensionType.CODEC, object.toString()).map(Holder::value).orElse(null);
if (value == null) return false;
return register(Registries.DIMENSION_TYPE, new ResourceLocation("iris", name), value, true);
}
@Override
public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) {
var biomeBase = decode(net.minecraft.world.level.biome.Biome.CODEC, biome.generateJson()).map(Holder::value).orElse(null);
if (biomeBase == null) return false;
return register(Registries.BIOME, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace);
}
private <T> Optional<T> decode(Codec<T> codec, String json) {
return codec.decode(JsonOps.INSTANCE, GsonHelper.parse(json)).result().map(Pair::getFirst);
}
private <T> Optional<JsonElement> encode(Codec<T> codec, T value) {
return codec.encode(value, JsonOps.INSTANCE, new JsonObject()).result();
}
private <T> boolean register(ResourceKey<Registry<T>> registryKey, ResourceLocation location, T value, boolean replace) {
Preconditions.checkArgument(registryKey != null, "The registry cannot be null!");
Preconditions.checkArgument(location != null, "The location cannot be null!");
Preconditions.checkArgument(value != null, "The value cannot be null!");
var registry = registry(registryKey);
var key = ResourceKey.create(registryKey, location);
try {
if (registry.containsKey(key)) {
if (!replace) return false;
return replace(registryKey, location, value);
}
Field field = getField(MappedRegistry.class, boolean.class);
field.setAccessible(true);
boolean frozen = field.getBoolean(registry);
field.setBoolean(registry, false);
Field valueField = getField(Holder.Reference.class, "T");
valueField.setAccessible(true);
try {
var holder = registry.register(key, value, RegistrationInfo.BUILT_IN);
if (frozen) valueField.set(holder, value);
return true;
} finally {
field.setBoolean(registry, frozen);
}
} catch (Throwable e) {
throw new IllegalStateException(e);
}
}
@SuppressWarnings("unchecked")
private <T> boolean replace(ResourceKey<Registry<T>> registryKey, ResourceLocation location, T value) {
Preconditions.checkArgument(registryKey != null, "The registryKey cannot be null!");
Preconditions.checkArgument(location != null, "The location cannot be null!");
Preconditions.checkArgument(value != null, "The value cannot be null!");
var registry = registry(registryKey);
var key = ResourceKey.create(registryKey, location);
try {
var holder = registry.getHolder(key).orElse(null);
if (holder == null) return false;
var oldValue = holder.value();
Field valueField = getField(Holder.Reference.class, "T");
valueField.setAccessible(true);
Field toIdField = getField(MappedRegistry.class, buildType(Reference2IntMap.class, "T"));
toIdField.setAccessible(true);
Field byValueField = getField(MappedRegistry.class, buildType(Map.class, "T", buildType(Holder.Reference.class, "T")));
byValueField.setAccessible(true);
var toId = (Reference2IntMap<T>) toIdField.get(registry);
var byValue = (Map<T, Holder.Reference<T>>) byValueField.get(registry);
valueField.set(holder, value);
toId.put(value, toId.removeInt(oldValue));
byValue.put(value, byValue.remove(oldValue));
return true;
} catch (Throwable e) {
throw new IllegalStateException(e);
}
}
private <T> MappedRegistry<T> registry(ResourceKey<Registry<T>> registryKey) {
var rawRegistry = registry().registry(registryKey).orElse(null);
if (!(rawRegistry instanceof MappedRegistry<T> registry))
throw new IllegalStateException("The Registry is not a mapped Registry!");
return registry;
}
private static String buildType(Class<?> clazz, String... parameterTypes) {
if (parameterTypes.length == 0) return clazz.getName();
var builder = new StringBuilder(clazz.getName())
.append("<");
for (int i = 0; i < parameterTypes.length; i++) {
builder.append(parameterTypes[i]).append(parameterTypes.length - 1 == i ? ">" : ", ");
}
return builder.toString();
}
private static Field getField(Class<?> clazz, String type) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {
if (f.getGenericType().getTypeName().equals(type))
return f;
}
throw new NoSuchFieldException(type);
} catch (NoSuchFieldException e) {
Class<?> superClass = clazz.getSuperclass();
if (superClass == null) throw e;
return getField(superClass, type);
}
}
public void injectBukkit() {
try {
Iris.info("Injecting Bukkit");
new ByteBuddy()
.redefine(WorldCreator.class)
.visit(Advice.to(WorldCreatorAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(String.class))))
.make()
.load(WorldCreator.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
new ByteBuddy()
.redefine(ServerLevel.class)
.visit(Advice.to(ServerLevelAdvice.class).on(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(MinecraftServer.class, Executor.class, LevelStorageSource.LevelStorageAccess.class,
PrimaryLevelData.class, ResourceKey.class, LevelStem.class, ChunkProgressListener.class, boolean.class, long.class,
List.class, boolean.class, RandomSequences.class, World.Environment.class, ChunkGenerator.class, BiomeProvider.class))))
.make()
.load(ServerLevel.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
Iris.info("Injected Bukkit Successfully!");
} catch (Exception e) {
Iris.info(C.RED + "Failed to Inject Bukkit!");
e.printStackTrace();
Iris.reportError(e);
}
}
private static class ServerLevelAdvice {
@Advice.OnMethodEnter
static void enter(@Advice.Argument(0) MinecraftServer server, @Advice.Argument(2) LevelStorageSource.LevelStorageAccess access, @Advice.Argument(4) ResourceKey<Level> key, @Advice.Argument(value = 5, readOnly = false) LevelStem levelStem) {
File iris = new File(access.levelDirectory.path().toFile(), "iris");
if (!iris.exists() && !key.location().getPath().startsWith("iris/")) return;
ResourceKey<DimensionType> typeKey = ResourceKey.create(Registries.DIMENSION_TYPE, new ResourceLocation("iris", key.location().getPath()));
RegistryAccess registryAccess = server.registryAccess();
Registry<DimensionType> registry = registryAccess.registry(Registries.DIMENSION_TYPE).orElse(null);
if (registry == null) throw new IllegalStateException("Unable to find registry for dimension type " + typeKey);
Holder<DimensionType> holder = registry.getHolder(typeKey).orElse(null);
if (holder == null) throw new IllegalStateException("Unable to find dimension type " + typeKey);
levelStem = new LevelStem(holder, levelStem.generator());
}
}
private static class WorldCreatorAdvice {
@Advice.OnMethodEnter
static void enter(@Advice.Argument(0) String name) {
File isIrisWorld = new File(name, "iris");
boolean isFromIris = false;
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
for (StackTraceElement stack : stackTrace) {
if (stack.getClassName().contains("Iris")) {
isFromIris = true;
break;
}
}
if (!isFromIris) {
Preconditions.checkArgument(!isIrisWorld.exists(), "Only Iris can load Iris Worlds!");
}
}
}
}