diff --git a/build.gradle b/build.gradle index d1d8b7191..937842a4f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,3 @@ -import java.util.function.Consumer - /* * Iris is a World Generator for Minecraft Bukkit Servers * Copyright (c) 2021 Arcane Arts (Volmit Software) @@ -25,7 +23,7 @@ plugins { id "de.undercouch.download" version "5.0.1" } -version '3.2.6-1.19.2-1.20.4' +version '3.3.1-1.19.2-1.20.6' def specialSourceVersion = '1.11.4' //[NMS] // ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED @@ -214,8 +212,6 @@ shadowJar { dependsOn(":nms:${it.key}:build") from("${project(":nms:${it.key}").layout.buildDirectory.asFile.get()}/libs/${it.key}.jar") } - NMS_BINDINGS.each {dependsOn(":nms:${it.key}:build")} - //dependsOn(':com.volmit.gui:build') //minimize() append("plugin.yml") @@ -284,10 +280,6 @@ allprojects { compileOnly 'rhino:js:1.7R2' compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6' compileOnly 'org.apache.commons:commons-lang3:3.12.0' - compileOnly 'net.bytebuddy:byte-buddy:1.14.14' - compileOnly 'net.bytebuddy:byte-buddy-agent:1.12.8' - compileOnly 'org.bytedeco:javacpp:1.5.10' - compileOnly 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10' } /** diff --git a/core/src/main/java/com/volmit/iris/Iris.java b/core/src/main/java/com/volmit/iris/Iris.java index 240e656e7..c39154b13 100644 --- a/core/src/main/java/com/volmit/iris/Iris.java +++ b/core/src/main/java/com/volmit/iris/Iris.java @@ -64,10 +64,12 @@ import com.volmit.iris.util.scheduling.Queue; import com.volmit.iris.util.scheduling.ShurikenQueue; import io.papermc.lib.PaperLib; import lombok.Getter; -import net.bytebuddy.agent.ByteBuddyAgent; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.text.serializer.ComponentSerializer; -import org.bukkit.*; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.WorldCreator; import org.bukkit.block.data.BlockData; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -92,14 +94,12 @@ import java.lang.management.OperatingSystemMXBean; import java.net.URL; import java.util.Date; import java.util.Map; -import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.volmit.iris.core.safeguard.IrisSafeguard.*; import static com.volmit.iris.core.safeguard.ServerBootSFG.passedserversoftware; import static com.volmit.iris.util.misc.getHardware.getCPUModel; -import static org.bukkit.Bukkit.getServer; @SuppressWarnings("CanBeFinal") public class Iris extends VolmitPlugin implements Listener { @@ -456,45 +456,36 @@ public class Iris extends VolmitPlugin implements Listener { } private void enable() { instance = this; - InitializeSafeguard(); - ByteBuddyAgent.install(); services = new KMap<>(); setupAudience(); initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class) i.getClass(), (IrisService) i)); INMS.get(); IO.delete(new File("iris")); - IrisSafeguard.instance.IrisSafeguardSystem(); + IrisSafeguard.IrisSafeguardSystem(); getSender().setTag(getTag()); - INMS.get().injectBukkit(); - if (IrisSafeguard.instance.unstablemode && !IrisSafeguard.instance.acceptUnstable) IrisSafeguard.instance.earlySplash(); compat = IrisCompat.configured(getDataFile("compat.json")); linkMultiverseCore = new MultiverseCoreLink(); linkMythicMobs = new MythicMobsLink(); configWatcher = new FileWatcher(getDataFile("settings.json")); services.values().forEach(IrisService::onEnable); services.values().forEach(this::registerListener); - installMainDimension(); - if (!IrisSafeguard.instance.acceptUnstable && IrisSafeguard.instance.unstablemode) { - Iris.info(C.RED + "World loading has been disabled until the incompatibility is resolved."); - Iris.info(C.DARK_RED + "Alternatively, go to plugins/iris/settings.json and set ignoreBootMode to true."); - } else { - J.s(() -> { - J.a(() -> PaperLib.suggestPaper(this)); - J.a(() -> IO.delete(getTemp())); - J.a(LazyPregenerator::loadLazyGenerators, 100); - J.a(this::bstats); - J.ar(this::checkConfigHotload, 60); - J.sr(this::tickQueue, 0); - J.s(this::setupPapi); - J.a(ServerConfigurator::configure, 20); - splash(); - UtilsSFG.splash(); - autoStartStudio(); - checkForBukkitWorlds(); - IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName()); - IrisToolbelt.retainMantleDataForSlice(BlockData.class.getCanonicalName()); - }); - } + J.s(() -> { + J.a(() -> PaperLib.suggestPaper(this)); + J.a(() -> IO.delete(getTemp())); + J.a(LazyPregenerator::loadLazyGenerators, 100); + J.a(this::bstats); + J.ar(this::checkConfigHotload, 60); + J.sr(this::tickQueue, 0); + J.s(this::setupPapi); + J.a(ServerConfigurator::configure, 20); + splash(); + UtilsSFG.splash(); + + autoStartStudio(); + checkForBukkitWorlds(); + IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName()); + IrisToolbelt.retainMantleDataForSlice(BlockData.class.getCanonicalName()); + }); } private void checkForBukkitWorlds() { @@ -608,10 +599,10 @@ public class Iris extends VolmitPlugin implements Listener { @Override public String getTag(String subTag) { - if (IrisSafeguard.instance.unstablemode) { + if (unstablemode) { return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.RED + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": "; } - if (IrisSafeguard.instance.warningmode) { + if (warningmode) { return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.GOLD + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": "; } return C.BOLD + "" + C.DARK_GRAY + "[" + C.BOLD + "" + C.IRIS + "Iris" + C.BOLD + C.DARK_GRAY + "]" + C.RESET + "" + C.GRAY + ": "; @@ -620,7 +611,7 @@ public class Iris extends VolmitPlugin implements Listener { private boolean setupChecks() { boolean passed = true; - Iris.info("Server type & version: " + instance.getServer().getVersion() + " | " + instance.getServer().getBukkitVersion()); + Iris.info("Version Information: " + instance.getServer().getVersion() + " | " + instance.getServer().getBukkitVersion()); if (INMS.get() instanceof NMSBinding1X) { passed = false; Iris.warn("============================================"); @@ -686,48 +677,6 @@ public class Iris extends VolmitPlugin implements Listener { s.sendMessage(C.IRIS + "[" + C.DARK_GRAY + "Iris" + C.IRIS + "]" + C.GRAY + ": " + msg); } - private void installMainDimension() { - try { - Properties props = new Properties(); - props.load(new FileInputStream("server.properties")); - String world = props.getProperty("level-name"); - if (world == null) return; - - FileConfiguration fc = new YamlConfiguration(); - fc.load(new File("bukkit.yml")); - String id = fc.getString("worlds." + world + ".generator"); - if (id.startsWith("Iris:")) { - id = id.split("\\Q:\\E")[1]; - } else if (id.equalsIgnoreCase("Iris")) { - id = IrisSettings.get().getGenerator().getDefaultWorldType(); - } else { - return; - } - - IrisDimension dim; - if (id == null || id.isEmpty()) { - dim = IrisData.loadAnyDimension(IrisSettings.get().getGenerator().getDefaultWorldType()); - } else { - dim = IrisData.loadAnyDimension(id); - } - - File w = new File(Bukkit.getWorldContainer(), world); - File packFolder = new File(w, "/iris/pack"); - if (!packFolder.exists() || packFolder.listFiles().length == 0) { - packFolder.mkdirs(); - service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w); - } - if (packFolder.exists()) { - IrisDimension worldDim = IrisData.get(packFolder).getDimensionLoader().load(id); - if (worldDim != null) dim = worldDim; - } - - INMS.get().registerDimension("overworld", dim); - } catch (Throwable e) { - - } - } - @Nullable @Override public BiomeProvider getDefaultBiomeProvider(@NotNull String worldName, @Nullable String id) { @@ -770,11 +719,6 @@ public class Iris extends VolmitPlugin implements Listener { Iris.info("Resolved missing dimension, proceeding with generation."); } } - File packFolder = new File(Bukkit.getWorldContainer(), worldName + "/iris/pack"); - if (packFolder.exists()) { - IrisDimension worldDim = IrisData.get(packFolder).getDimensionLoader().load(id); - if (worldDim != null) dim = worldDim; - } Iris.debug("Assuming IrisDimension: " + dim.getName()); @@ -794,9 +738,6 @@ public class Iris extends VolmitPlugin implements Listener { ff.mkdirs(); service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w.worldFolder()); } - if (!INMS.get().registerDimension(worldName, dim)) { - throw new IllegalStateException("Unable to register dimension " + dim.getName()); - } return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey(), false); } @@ -809,10 +750,10 @@ public class Iris extends VolmitPlugin implements Listener { String padd = Form.repeat(" ", 8); String padd2 = Form.repeat(" ", 4); String[] info = {"", "", "", "", "", padd2 + C.IRIS + " Iris", padd2 + C.GRAY + " by " + "Volmit Software", padd2 + C.GRAY + " v" + C.IRIS + getDescription().getVersion()}; - if (IrisSafeguard.instance.unstablemode) { + if (unstablemode) { info = new String[]{"", "", "", "", "", padd2 + C.RED + " Iris", padd2 + C.GRAY + " by " + C.DARK_RED + "Volmit Software", padd2 + C.GRAY + " v" + C.RED + getDescription().getVersion()}; } - if (IrisSafeguard.instance.warningmode) { + if (warningmode) { info = new String[]{"", "", "", "", "", padd2 + C.GOLD + " Iris", padd2 + C.GRAY + " by " + C.GOLD + "Volmit Software", padd2 + C.GRAY + " v" + C.GOLD + getDescription().getVersion()}; } @@ -857,15 +798,18 @@ public class Iris extends VolmitPlugin implements Listener { padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@" }; String[] splash; - if (IrisSafeguard.instance.unstablemode) { + File freeSpace = new File(Bukkit.getWorldContainer() + "."); + if (unstablemode) { splash = splashunstable; - } else if (IrisSafeguard.instance.warningmode) { + } else if (warningmode) { splash = splashwarning; } else { splash = splashstable; } - setupChecks(); + if (!passedserversoftware) { + Iris.info("Server type & version: " + C.RED + Bukkit.getVersion()); + } else { Iris.info("Server type & version: " + Bukkit.getVersion()); } Iris.info("Java: " + getJava()); if (!instance.getServer().getVersion().contains("Purpur")) { if (instance.getServer().getVersion().contains("Spigot") && instance.getServer().getVersion().contains("Bukkit")) { @@ -880,6 +824,7 @@ public class Iris extends VolmitPlugin implements Listener { } Iris.info("Bukkit distro: " + Bukkit.getName()); Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes()); + setupChecks(); printPacks(); for (int i = 0; i < info.length; i++) { diff --git a/core/src/main/java/com/volmit/iris/core/IrisSettings.java b/core/src/main/java/com/volmit/iris/core/IrisSettings.java index de38220fb..9eccc80e1 100644 --- a/core/src/main/java/com/volmit/iris/core/IrisSettings.java +++ b/core/src/main/java/com/volmit/iris/core/IrisSettings.java @@ -34,7 +34,6 @@ import java.io.IOException; @Data public class IrisSettings { public static IrisSettings settings; - private IrisSafeGuard safeguard = new IrisSafeGuard(); private IrisSettingsGeneral general = new IrisSettingsGeneral(); private IrisSettingsWorld world = new IrisSettingsWorld(); private IrisSettingsGUI gui = new IrisSettingsGUI(); @@ -43,7 +42,6 @@ public class IrisSettings { private IrisSettingsConcurrency concurrency = new IrisSettingsConcurrency(); private IrisSettingsStudio studio = new IrisSettingsStudio(); private IrisSettingsPerformance performance = new IrisSettingsPerformance(); - private IrisWorldDump worldDump = new IrisWorldDump(); public static int getThreadCount(int c) { return switch (c) { @@ -104,12 +102,6 @@ public class IrisSettings { } } - @Data - public static class IrisSafeGuard { - public boolean ignoreBootMode = false; - public boolean userUnstableWarning = true; - } - @Data public static class IrisSettingsAutoconfiguration { public boolean configureSpigotTimeoutTime = true; @@ -154,6 +146,7 @@ public class IrisSettings { @Data public static class IrisSettingsGeneral { + public boolean DoomsdayAnnihilationSelfDestructMode = false; public boolean commandSounds = true; public boolean debug = false; public boolean disableNMS = false; @@ -194,8 +187,4 @@ public class IrisSettings { public boolean disableTimeAndWeather = true; public boolean autoStartDefaultStudio = false; } - @Data - public static class IrisWorldDump { - public int mcaCacheSize = 3; - } } diff --git a/core/src/main/java/com/volmit/iris/core/ServerConfigurator.java b/core/src/main/java/com/volmit/iris/core/ServerConfigurator.java index dc75b46df..1a760d9d7 100644 --- a/core/src/main/java/com/volmit/iris/core/ServerConfigurator.java +++ b/core/src/main/java/com/volmit/iris/core/ServerConfigurator.java @@ -19,13 +19,28 @@ 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.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.IOException; +import java.util.List; import java.util.concurrent.TimeUnit; public class ServerConfigurator { @@ -38,10 +53,12 @@ public class ServerConfigurator { if (s.isConfigurePaperWatchdogDelay()) { J.attempt(ServerConfigurator::increasePaperWatchdog); } + + installDataPacks(true); } private static void increaseKeepAliveSpigot() throws IOException, InvalidConfigurationException { - File spigotConfig = new File("spigot.yml"); + File spigotConfig = new File("config/spigot.yml"); FileConfiguration f = new YamlConfiguration(); f.load(spigotConfig); long tt = f.getLong("settings.timeout-time"); @@ -53,7 +70,6 @@ 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(); @@ -67,4 +83,187 @@ public class ServerConfigurator { f.save(spigotConfig); } } + + private static List getDatapacksFolder() { + if (!IrisSettings.get().getGeneral().forceMainWorld.isEmpty()) { + return new KList().qadd(new File(Bukkit.getWorldContainer(), IrisSettings.get().getGeneral().forceMainWorld + "/datapacks")); + } + KList worlds = new KList<>(); + Bukkit.getServer().getWorlds().forEach(w -> worlds.add(new File(w.getWorldFolder(), "datapacks"))); + return worlds; + } + + 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, ultimateMaxHeight, ultimateMinHeight); + } + } + } + } + } + } + } + + 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) { + if (allowRestarting) { + restart(); + } else if (INMS.get().supportsDataPacks()) { + Iris.error("============================================================================"); + Iris.error(C.ITALIC + "You need to restart your server to properly generate custom biomes."); + Iris.error(C.ITALIC + "By continuing, Iris will use backup biomes in place of the custom biomes."); + Iris.error("----------------------------------------------------------------------------"); + Iris.error(C.UNDERLINE + "IT IS HIGHLY RECOMMENDED YOU RESTART THE SERVER BEFORE GENERATING!"); + Iris.error("============================================================================"); + + 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 diddn'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 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("If not done automatically, restart your server before generating with this pack!"); + } + + return !warn; + } } diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandDeepSearch.java b/core/src/main/java/com/volmit/iris/core/commands/CommandDeepSearch.java new file mode 100644 index 000000000..d8cd6a260 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandDeepSearch.java @@ -0,0 +1,134 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.core.commands; + +import com.volmit.iris.Iris; +import com.volmit.iris.core.pregenerator.DeepSearchPregenerator; +import com.volmit.iris.core.pregenerator.PregenTask; +import com.volmit.iris.core.pregenerator.TurboPregenerator; +import com.volmit.iris.core.tools.IrisToolbelt; +import com.volmit.iris.util.data.Dimension; +import com.volmit.iris.util.decree.DecreeExecutor; +import com.volmit.iris.util.decree.annotations.Decree; +import com.volmit.iris.util.decree.annotations.Param; +import com.volmit.iris.util.format.C; +import com.volmit.iris.util.math.Position2; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.util.Vector; + +import java.io.File; +import java.io.IOException; + +@Decree(name = "DeepSearch", aliases = "search", description = "Pregenerate your Iris worlds!") +public class CommandDeepSearch implements DecreeExecutor { + public String worldName; + @Decree(description = "DeepSearch a world") + public void start( + @Param(description = "The radius of the pregen in blocks", aliases = "size") + int radius, + @Param(description = "The world to pregen", contextual = true) + World world, + @Param(aliases = "middle", description = "The center location of the pregen. Use \"me\" for your current location", defaultValue = "0,0") + Vector center + ) { + + worldName = world.getName(); + File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName()); + File TurboFile = new File(worldDirectory, "DeepSearch.json"); + if (TurboFile.exists()) { + if (DeepSearchPregenerator.getInstance() != null) { + sender().sendMessage(C.BLUE + "DeepSearch is already in progress"); + Iris.info(C.YELLOW + "DeepSearch is already in progress"); + return; + } else { + try { + TurboFile.delete(); + } catch (Exception e){ + Iris.error("Failed to delete the old instance file of DeepSearch!"); + return; + } + } + } + + try { + if (sender().isPlayer() && access() == null) { + sender().sendMessage(C.RED + "The engine access for this world is null!"); + sender().sendMessage(C.RED + "Please make sure the world is loaded & the engine is initialized. Generate a new chunk, for example."); + } + + DeepSearchPregenerator.DeepSearchJob DeepSearchJob = DeepSearchPregenerator.DeepSearchJob.builder() + .world(world) + .radiusBlocks(radius) + .position(0) + .build(); + + File SearchGenFile = new File(worldDirectory, "DeepSearch.json"); + DeepSearchPregenerator pregenerator = new DeepSearchPregenerator(DeepSearchJob, SearchGenFile); + pregenerator.start(); + + String msg = C.GREEN + "DeepSearch started in " + C.GOLD + worldName + C.GREEN + " of " + C.GOLD + (radius * 2) + C.GREEN + " by " + C.GOLD + (radius * 2) + C.GREEN + " blocks from " + C.GOLD + center.getX() + "," + center.getZ(); + sender().sendMessage(msg); + Iris.info(msg); + } catch (Throwable e) { + sender().sendMessage(C.RED + "Epic fail. See console."); + Iris.reportError(e); + e.printStackTrace(); + } + } + + @Decree(description = "Stop the active DeepSearch task", aliases = "x") + public void stop(@Param(aliases = "world", description = "The world to pause") World world) throws IOException { + DeepSearchPregenerator DeepSearchInstance = DeepSearchPregenerator.getInstance(); + File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName()); + File turboFile = new File(worldDirectory, "DeepSearch.json"); + + if (DeepSearchInstance != null) { + DeepSearchInstance.shutdownInstance(world); + sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName()); + } else if (turboFile.exists() && turboFile.delete()) { + sender().sendMessage(C.LIGHT_PURPLE + "Closed Turbogen instance for " + world.getName()); + } else if (turboFile.exists()) { + Iris.error("Failed to delete the old instance file of Turbo Pregen!"); + } else { + sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop"); + } + } + + @Decree(description = "Pause / continue the active pregeneration task", aliases = {"t", "resume", "unpause"}) + public void pause( + @Param(aliases = "world", description = "The world to pause") + World world + ) { + if (TurboPregenerator.getInstance() != null) { + TurboPregenerator.setPausedTurbo(world); + sender().sendMessage(C.GREEN + "Paused/unpaused Turbo Pregen, now: " + (TurboPregenerator.isPausedTurbo(world) ? "Paused" : "Running") + "."); + } else { + File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName()); + File TurboFile = new File(worldDirectory, "DeepSearch.json"); + if (TurboFile.exists()){ + TurboPregenerator.loadTurboGenerator(world.getName()); + sender().sendMessage(C.YELLOW + "Started DeepSearch back up!"); + } else { + sender().sendMessage(C.YELLOW + "No active DeepSearch tasks to pause/unpause."); + } + + } + } +} diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java b/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java index 7f6a0786f..9439d29d6 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandDeveloper.java @@ -28,9 +28,7 @@ import com.volmit.iris.core.pregenerator.ChunkUpdater; import com.volmit.iris.core.service.IrisEngineSVC; import com.volmit.iris.core.tools.IrisPackBenchmarking; import com.volmit.iris.core.tools.IrisToolbelt; -import com.volmit.iris.core.tools.IrisWorldDump; import com.volmit.iris.engine.framework.Engine; -import com.volmit.iris.engine.jvm.VMJavaFX; import com.volmit.iris.engine.mantle.components.MantleObjectComponent; import com.volmit.iris.engine.object.IrisBiome; import com.volmit.iris.engine.object.IrisCave; @@ -152,18 +150,21 @@ public class CommandDeveloper implements DecreeExecutor { @Decree(description = "Test") public void packBenchmark( @Param(description = "The pack to bench", aliases = {"pack"}) - IrisDimension dimension, - @Param(description = "Headless", defaultValue = "true") - boolean headless, - @Param(description = "GUI", defaultValue = "false") - boolean gui + IrisDimension dimension ) { Iris.info("test"); - IrisPackBenchmarking benchmark = new IrisPackBenchmarking(dimension, 1, headless, gui); - benchmark.runBenchmark(); + IrisPackBenchmarking benchmark = new IrisPackBenchmarking(dimension, 1); } + @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") @@ -178,22 +179,12 @@ public class CommandDeveloper implements DecreeExecutor { @Decree(description = "test") public void mca ( - @Param(description = "String") World world) { + @Param(description = "String") String world) { try { - IrisWorldDump dump = new IrisWorldDump(world, sender()); - dump.start(); - - } catch (Exception e) { - e.printStackTrace(); - } - - } - - @Decree(description = "test") - public void javafx () { - try { - VMJavaFX javaFX = new VMJavaFX(sender()); - javaFX.start(); + File[] McaFiles = new File(world, "region").listFiles((dir, name) -> name.endsWith(".mca")); + for (File mca : McaFiles) { + MCAFile MCARegion = MCAUtil.read(mca); + } } catch (Exception e) { e.printStackTrace(); } diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandEdit.java b/core/src/main/java/com/volmit/iris/core/commands/CommandEdit.java index f5e8d0b1c..345b3f214 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandEdit.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandEdit.java @@ -19,19 +19,13 @@ package com.volmit.iris.core.commands; import com.volmit.iris.Iris; -import com.volmit.iris.core.nms.INMS; import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.engine.object.*; import com.volmit.iris.util.decree.DecreeExecutor; import com.volmit.iris.util.decree.DecreeOrigin; import com.volmit.iris.util.decree.annotations.Decree; import com.volmit.iris.util.decree.annotations.Param; -import com.volmit.iris.util.decree.specialhandlers.NullableBiomeHandler; -import com.volmit.iris.util.decree.specialhandlers.NullablePlayerHandler; -import com.volmit.iris.util.decree.specialhandlers.NullableRegionHandler; import com.volmit.iris.util.format.C; -import org.bukkit.Location; -import org.bukkit.block.Biome; import java.awt.*; @@ -57,31 +51,12 @@ public class CommandEdit implements DecreeExecutor { @Decree(description = "Edit the biome you specified", aliases = {"b"}, origin = DecreeOrigin.PLAYER) - public void biome(@Param(contextual = false, description = "The biome to edit", defaultValue = "---", customHandler = NullableBiomeHandler.class) IrisBiome biome ) { + public void biome(@Param(contextual = false, description = "The biome to edit") IrisBiome biome) { if (noStudio()) { return; } - if(biome == null) { - try { - IrisBiome b = engine().getBiome(player().getLocation().getBlockX(), player().getLocation().getBlockY() - player().getWorld().getMinHeight(), player().getLocation().getBlockZ()); - Desktop.getDesktop().open(b.getLoadFile()); - sender().sendMessage(C.GREEN + "Opening " + b.getTypeName() + " " + b.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! "); - } catch (Throwable e) { - Iris.reportError(e); - sender().sendMessage("Non-Iris Biome: " + player().getLocation().getBlock().getBiome().name()); - if (player().getLocation().getBlock().getBiome().equals(Biome.CUSTOM)) { - try { - sender().sendMessage("Data Pack Biome: " + INMS.get().getTrueBiomeBaseKey(player().getLocation()) + " (ID: " + INMS.get().getTrueBiomeBaseId(INMS.get().getTrueBiomeBase(player().getLocation())) + ")"); - } catch (Throwable ee) { - Iris.reportError(ee); - } - } - } - return; - } - try { - if (biome.getLoadFile() == null) { + if (biome == null || biome.getLoadFile() == null) { sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?"); return; } @@ -94,20 +69,10 @@ public class CommandEdit implements DecreeExecutor { } @Decree(description = "Edit the region you specified", aliases = {"r"}, origin = DecreeOrigin.PLAYER) - public void region(@Param(contextual = false, description = "The region to edit", defaultValue = "---", customHandler = NullableRegionHandler.class) IrisRegion region) { + public void region(@Param(contextual = false, description = "The region to edit") IrisRegion region) { if (noStudio()) { return; } - if(region == null) { - try { - IrisRegion r = engine().getRegion(player().getLocation().getBlockX(), player().getLocation().getBlockZ()); - Desktop.getDesktop().open(r.getLoadFile()); - sender().sendMessage(C.GREEN + "Opening " + r.getTypeName() + " " + r.getLoadFile().getName().split("\\Q.\\E")[0] + " in VSCode! "); - } catch (Throwable e) { - sender().sendMessage(C.RED + "Failed to get region."); - } - return; - } try { if (region == null || region.getLoadFile() == null) { sender().sendMessage(C.GOLD + "Cannot find the file; Perhaps it was not loaded directly from a file?"); diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java b/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java index 94c21710f..5154ea4af 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandIris.java @@ -24,7 +24,6 @@ import com.volmit.iris.core.ServerConfigurator; import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.nms.datapack.DataVersion; import com.volmit.iris.core.pregenerator.ChunkUpdater; -import com.volmit.iris.core.safeguard.IrisSafeguard; import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.core.tools.IrisBenchmarking; import com.volmit.iris.core.tools.IrisToolbelt; @@ -44,7 +43,6 @@ import com.volmit.iris.util.format.C; import com.volmit.iris.util.format.Form; import com.volmit.iris.util.plugin.VolmitSender; import com.volmit.iris.util.scheduling.J; -import io.lumine.mythic.bukkit.adapters.BukkitPlayer; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.Difficulty; @@ -67,6 +65,7 @@ import java.util.List; import static com.volmit.iris.Iris.service; import static com.volmit.iris.core.service.EditSVC.deletingWorld; import static com.volmit.iris.core.tools.IrisBenchmarking.inProgress; +import static com.volmit.iris.core.safeguard.IrisSafeguard.unstablemode; import static com.volmit.iris.core.safeguard.ServerBootSFG.incompatibilities; import static org.bukkit.Bukkit.getServer; @@ -99,7 +98,24 @@ public class CommandIris implements DecreeExecutor { @Param(description = "If it should convert the dimension to match the vanilla height system.", defaultValue = "false") boolean vanillaheight ) { - + if(sender() instanceof Player) { + if (incompatibilities.get("Multiverse-Core")) { + sender().sendMessage(C.RED + "Your server has an incompatibility that may corrupt all worlds on the server if not handled properly."); + sender().sendMessage(C.RED + "it is strongly advised for you to take action. see log for full detail"); + sender().sendMessage(C.RED + "----------------------------------------------------------------"); + sender().sendMessage(C.RED + "Command ran: /iris create"); + sender().sendMessage(C.RED + UtilsSFG.MSGIncompatibleWarnings()); + sender().sendMessage(C.RED + "----------------------------------------------------------------"); + } + if (unstablemode && !incompatibilities.get("Multiverse-Core")) { + sender().sendMessage(C.RED + "Your server is experiencing an incompatibility with the Iris plugin."); + sender().sendMessage(C.RED + "Please rectify this problem to avoid further complications."); + sender().sendMessage(C.RED + "----------------------------------------------------------------"); + sender().sendMessage(C.RED + "Command ran: /iris create"); + sender().sendMessage(C.RED + UtilsSFG.MSGIncompatibleWarnings()); + sender().sendMessage(C.RED + "----------------------------------------------------------------"); + } + } if (name.equals("iris")) { sender().sendMessage(C.RED + "You cannot use the world name \"iris\" for creating worlds as Iris uses this directory for studio worlds."); sender().sendMessage(C.RED + "May we suggest the name \"IrisWorld\" instead?"); diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java b/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java index 095e28406..774e760b8 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandStudio.java @@ -22,10 +22,11 @@ import com.volmit.iris.Iris; import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.gui.NoiseExplorerGUI; import com.volmit.iris.core.gui.VisionGUI; +import com.volmit.iris.core.loader.IrisData; 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.IrisNoiseBenchmark; +import com.volmit.iris.core.tools.IrisConverter; import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.object.*; @@ -41,17 +42,22 @@ import com.volmit.iris.util.decree.annotations.Param; 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.*; @@ -73,12 +79,14 @@ 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) public class CommandStudio implements DecreeExecutor { private CommandFind find; private CommandEdit edit; + //private CommandDeepSearch deepSearch; public static String hrf(Duration duration) { return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase(); @@ -278,8 +286,7 @@ public class CommandStudio implements DecreeExecutor { sender().sendMessage(C.RED + "No studio world open!"); return; } - var provider = Iris.service(StudioSVC.class).getActiveProject().getActiveProvider(); - provider.getEngine().hotload(); + Iris.service(StudioSVC.class).getActiveProject().getActiveProvider().getEngine().hotload(); sender().sendMessage(C.GREEN + "Hotloaded"); } @@ -384,10 +391,18 @@ public class CommandStudio implements DecreeExecutor { } @Decree(description = "Render a world map (External GUI)", aliases = "render") - public void map() { + public void map( + @Param(name = "world", description = "The world to open the generator for", contextual = true) + World world + ) { if (noGUI()) return; - if (noStudio()) return; - VisionGUI.launch(IrisToolbelt.access(player().getWorld()).getEngine(), 0); + + if (!IrisToolbelt.isIrisWorld(world)) { + sender().sendMessage(C.RED + "You need to be in or specify an Iris-generated world!"); + return; + } + + VisionGUI.launch(IrisToolbelt.access(world).getEngine(), 0); sender().sendMessage(C.GREEN + "Opening map!"); } @@ -408,8 +423,188 @@ public class CommandStudio implements DecreeExecutor { @Param(description = "The dimension to profile", contextual = true, defaultValue = "default") IrisDimension dimension ) { - IrisNoiseBenchmark noiseBenchmark = new IrisNoiseBenchmark(dimension, sender()); - noiseBenchmark.runAll(); + // Todo: Make this more accurate + File pack = dimension.getLoadFile().getParentFile().getParentFile(); + File report = Iris.instance.getDataFile("profile.txt"); + IrisProject project = new IrisProject(pack); + IrisData data = IrisData.get(pack); + + KList fileText = new KList<>(); + + KMap styleTimings = new KMap<>(); + KMap interpolatorTimings = new KMap<>(); + KMap generatorTimings = new KMap<>(); + KMap biomeTimings = new KMap<>(); + KMap regionTimings = new KMap<>(); + + sender().sendMessage("Calculating Performance Metrics for Noise generators"); + + for (NoiseStyle i : NoiseStyle.values()) { + CNG c = i.create(new RNG(i.hashCode())); + + for (int j = 0; j < 3000; j++) { + c.noise(j, j + 1000, j * j); + c.noise(j, -j); + } + + PrecisionStopwatch px = PrecisionStopwatch.start(); + + for (int j = 0; j < 100000; j++) { + c.noise(j, j + 1000, j * j); + c.noise(j, -j); + } + + styleTimings.put(i, px.getMilliseconds()); + } + + fileText.add("Noise Style Performance Impacts: "); + + for (NoiseStyle i : styleTimings.sortKNumber()) { + fileText.add(i.name() + ": " + styleTimings.get(i)); + } + + fileText.add(""); + + sender().sendMessage("Calculating Interpolator Timings..."); + + for (InterpolationMethod i : InterpolationMethod.values()) { + IrisInterpolator in = new IrisInterpolator(); + in.setFunction(i); + in.setHorizontalScale(8); + + NoiseProvider np = (x, z) -> Math.random(); + + for (int j = 0; j < 3000; j++) { + in.interpolate(j, -j, np); + } + + PrecisionStopwatch px = PrecisionStopwatch.start(); + + for (int j = 0; j < 100000; j++) { + in.interpolate(j + 10000, -j - 100000, np); + } + + interpolatorTimings.put(i, px.getMilliseconds()); + } + + fileText.add("Noise Interpolator Performance Impacts: "); + + for (InterpolationMethod i : interpolatorTimings.sortKNumber()) { + fileText.add(i.name() + ": " + interpolatorTimings.get(i)); + } + + fileText.add(""); + + sender().sendMessage("Processing Generator Scores: "); + + KMap> btx = new KMap<>(); + + for (String i : data.getGeneratorLoader().getPossibleKeys()) { + KList vv = new KList<>(); + IrisGenerator g = data.getGeneratorLoader().load(i); + KList composites = g.getAllComposites(); + double score = 0; + int m = 0; + for (IrisNoiseGenerator j : composites) { + m++; + score += styleTimings.get(j.getStyle().getStyle()); + vv.add("Composite Noise Style " + m + " " + j.getStyle().getStyle().name() + ": " + styleTimings.get(j.getStyle().getStyle())); + } + + score += interpolatorTimings.get(g.getInterpolator().getFunction()); + vv.add("Interpolator " + g.getInterpolator().getFunction().name() + ": " + interpolatorTimings.get(g.getInterpolator().getFunction())); + generatorTimings.put(i, score); + btx.put(i, vv); + } + + fileText.add("Project Generator Performance Impacts: "); + + for (String i : generatorTimings.sortKNumber()) { + fileText.add(i + ": " + generatorTimings.get(i)); + + btx.get(i).forEach((ii) -> fileText.add(" " + ii)); + } + + fileText.add(""); + + KMap> bt = new KMap<>(); + + for (String i : data.getBiomeLoader().getPossibleKeys()) { + KList vv = new KList<>(); + IrisBiome b = data.getBiomeLoader().load(i); + double score = 0; + + int m = 0; + for (IrisBiomePaletteLayer j : b.getLayers()) { + m++; + score += styleTimings.get(j.getStyle().getStyle()); + vv.add("Palette Layer " + m + ": " + styleTimings.get(j.getStyle().getStyle())); + } + + score += styleTimings.get(b.getBiomeStyle().getStyle()); + vv.add("Biome Style: " + styleTimings.get(b.getBiomeStyle().getStyle())); + score += styleTimings.get(b.getChildStyle().getStyle()); + vv.add("Child Style: " + styleTimings.get(b.getChildStyle().getStyle())); + biomeTimings.put(i, score); + bt.put(i, vv); + } + + fileText.add("Project Biome Performance Impacts: "); + + for (String i : biomeTimings.sortKNumber()) { + fileText.add(i + ": " + biomeTimings.get(i)); + + bt.get(i).forEach((ff) -> fileText.add(" " + ff)); + } + + fileText.add(""); + + for (String i : data.getRegionLoader().getPossibleKeys()) { + IrisRegion b = data.getRegionLoader().load(i); + double score = 0; + + score += styleTimings.get(b.getLakeStyle().getStyle()); + score += styleTimings.get(b.getRiverStyle().getStyle()); + regionTimings.put(i, score); + } + + fileText.add("Project Region Performance Impacts: "); + + for (String i : regionTimings.sortKNumber()) { + fileText.add(i + ": " + regionTimings.get(i)); + } + + fileText.add(""); + + double m = 0; + for (double i : biomeTimings.v()) { + m += i; + } + m /= biomeTimings.size(); + double mm = 0; + for (double i : generatorTimings.v()) { + mm += i; + } + mm /= generatorTimings.size(); + m += mm; + double mmm = 0; + for (double i : regionTimings.v()) { + mmm += i; + } + mmm /= regionTimings.size(); + m += mmm; + + fileText.add("Average Score: " + m); + sender().sendMessage("Score: " + Form.duration(m, 0)); + + try { + IO.writeAll(report, fileText.toString("\n")); + } catch (IOException e) { + Iris.reportError(e); + e.printStackTrace(); + } + + sender().sendMessage(C.GREEN + "Done! " + report.getPath()); } @Decree(description = "Spawn an Iris entity", aliases = "summon", origin = DecreeOrigin.PLAYER) diff --git a/core/src/main/java/com/volmit/iris/core/commands/CommandWhat.java b/core/src/main/java/com/volmit/iris/core/commands/CommandWhat.java index 87ee13ba3..48d8c726e 100644 --- a/core/src/main/java/com/volmit/iris/core/commands/CommandWhat.java +++ b/core/src/main/java/com/volmit/iris/core/commands/CommandWhat.java @@ -88,7 +88,8 @@ public class CommandWhat implements DecreeExecutor { @Decree(description = "What region am i in?", origin = DecreeOrigin.PLAYER) public void region() { try { - IrisRegion r = engine().getRegion(player().getLocation()); + Chunk chunk = world().getChunkAt(player().getLocation().getBlockZ() / 16, player().getLocation().getBlockZ() / 16); + IrisRegion r = engine().getRegion(chunk); sender().sendMessage("IRegion: " + r.getLoadKey() + " (" + r.getName() + ")"); } catch (Throwable e) { diff --git a/core/src/main/java/com/volmit/iris/core/gui/VisionGUI.java b/core/src/main/java/com/volmit/iris/core/gui/VisionGUI.java index 0342dbc41..93c7c2009 100644 --- a/core/src/main/java/com/volmit/iris/core/gui/VisionGUI.java +++ b/core/src/main/java/com/volmit/iris/core/gui/VisionGUI.java @@ -80,7 +80,6 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener private boolean lowtile = false; private boolean follow = false; private boolean alt = false; - private boolean dragging = false; private IrisRenderer renderer; private IrisWorld world; private double velocity = 0; @@ -202,7 +201,6 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener @Override public void mouseDragged(MouseEvent e) { - dragging = true; Point cp = e.getPoint(); ox += (lx - cp.getX()) * scale; oz += (lz - cp.getY()) * scale; @@ -415,7 +413,7 @@ public class VisionGUI extends JPanel implements MouseWheelListener, KeyListener private double getWorldX(double screenX) { //return (mscale * screenX) + ((oxp / scale) * mscale); - return (mscale * screenX) + ((oxp / scale) * mscale); + return (mscale * screenX) + ((oxp / scale)); } private double getWorldZ(double screenZ) { diff --git a/core/src/main/java/com/volmit/iris/core/nms/IHeadless.java b/core/src/main/java/com/volmit/iris/core/nms/IHeadless.java deleted file mode 100644 index 2b7accdc1..000000000 --- a/core/src/main/java/com/volmit/iris/core/nms/IHeadless.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.volmit.iris.core.nms; - -import com.volmit.iris.core.pregenerator.PregenListener; -import com.volmit.iris.util.documentation.ChunkCoordinates; -import com.volmit.iris.util.documentation.RegionCoordinates; -import com.volmit.iris.util.parallel.MultiBurst; - -import java.io.Closeable; - -public interface IHeadless extends Closeable { - - void save(); - - @ChunkCoordinates - boolean exists(int x, int z); - - @RegionCoordinates - void generateRegion(MultiBurst burst, int x, int z, PregenListener listener); - - @ChunkCoordinates - void generateChunk(int x, int z); -} diff --git a/core/src/main/java/com/volmit/iris/core/nms/INMSBinding.java b/core/src/main/java/com/volmit/iris/core/nms/INMSBinding.java index 7f72c84d7..da90e6fb2 100644 --- a/core/src/main/java/com/volmit/iris/core/nms/INMSBinding.java +++ b/core/src/main/java/com/volmit/iris/core/nms/INMSBinding.java @@ -20,8 +20,6 @@ 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.mantle.Mantle; @@ -117,14 +115,4 @@ public interface INMSBinding { default DataVersion getDataVersion() { return DataVersion.V1192; } - - boolean registerDimension(String name, IrisDimension dimension); - - boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace); - - void injectBukkit(); - - default IHeadless createHeadless(Engine engine) { - throw new IllegalStateException("Headless mode not supported"); - } } diff --git a/core/src/main/java/com/volmit/iris/core/nms/v1X/NMSBinding1X.java b/core/src/main/java/com/volmit/iris/core/nms/v1X/NMSBinding1X.java index d54ee7f6a..e99478753 100644 --- a/core/src/main/java/com/volmit/iris/core/nms/v1X/NMSBinding1X.java +++ b/core/src/main/java/com/volmit/iris/core/nms/v1X/NMSBinding1X.java @@ -18,29 +18,20 @@ package com.volmit.iris.core.nms.v1X; -import com.google.common.base.Preconditions; 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; -import com.volmit.iris.util.format.C; import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.math.Vector3d; import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer; import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess; import com.volmit.iris.util.nbt.tag.CompoundTag; -import net.bytebuddy.ByteBuddy; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.dynamic.loading.ClassReloadingStrategy; -import net.bytebuddy.matcher.ElementMatchers; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.WorldCreator; import org.bukkit.block.Biome; import org.bukkit.entity.Dolphin; import org.bukkit.entity.Entity; @@ -49,8 +40,6 @@ import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.generator.ChunkGenerator; import org.bukkit.inventory.ItemStack; -import java.io.File; - public class NMSBinding1X implements INMSBinding { private static final boolean supportsCustomHeight = testCustomHeight(); @@ -108,16 +97,6 @@ public class NMSBinding1X implements INMSBinding { return location.getWorld().spawnEntity(location, type); } - @Override - public boolean registerDimension(String name, IrisDimension dimension) { - return false; - } - - @Override - public boolean registerBiome(String dimensionId, IrisBiomeCustom biome, boolean replace) { - return false; - } - @Override public void deserializeTile(CompoundTag s, Location newPosition) { @@ -246,39 +225,4 @@ public class NMSBinding1X implements INMSBinding { Iris.error("Cannot use the global data palette! Iris is incapable of using MCA generation on this version of minecraft!"); return null; } - - 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()); - Iris.info("Injected Bukkit Successfully!"); - } catch (Exception e) { - Iris.info(C.RED + "Failed to Inject Bukkit!"); - e.printStackTrace(); - Iris.reportError(e); - } - - } - - 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!"); - } - } - } } diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java b/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java index 29c590fa2..d89ad3340 100644 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/ChunkUpdater.java @@ -106,7 +106,7 @@ public class ChunkUpdater { try { if (!paused.get()) { long eta = computeETA(); - long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 3000; + long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 1000; int processed = chunksProcessed.get(); double cps = elapsedSeconds > 0 ? processed / (double) elapsedSeconds : 0; chunksPerSecond.put(cps); diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/DeepSearchPregenerator.java b/core/src/main/java/com/volmit/iris/core/pregenerator/DeepSearchPregenerator.java new file mode 100644 index 000000000..c60724d2a --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/DeepSearchPregenerator.java @@ -0,0 +1,275 @@ +package com.volmit.iris.core.pregenerator; + +import com.google.gson.Gson; +import com.volmit.iris.Iris; +import com.volmit.iris.core.tools.IrisToolbelt; +import com.volmit.iris.engine.framework.Engine; +import com.volmit.iris.engine.object.IrisBiome; +import com.volmit.iris.util.collection.KList; +import com.volmit.iris.util.format.C; +import com.volmit.iris.util.format.Form; +import com.volmit.iris.util.io.IO; +import com.volmit.iris.util.math.M; +import com.volmit.iris.util.math.Position2; +import com.volmit.iris.util.math.RollingSequence; +import com.volmit.iris.util.math.Spiraler; +import com.volmit.iris.util.scheduling.ChronoLatch; +import com.volmit.iris.util.scheduling.J; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.world.WorldUnloadEvent; +import org.bukkit.scheduler.BukkitRunnable; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.ReentrantLock; + +public class DeepSearchPregenerator extends Thread implements Listener { + @Getter + private static DeepSearchPregenerator instance; + private final DeepSearchJob job; + private final File destination; + private final int maxPosition; + private World world; + private final ChronoLatch latch; + private static AtomicInteger foundChunks; + private final AtomicInteger foundLast; + private final AtomicInteger foundTotalChunks; + private final AtomicLong startTime; + private final RollingSequence chunksPerSecond; + private final RollingSequence chunksPerMinute; + private final AtomicInteger chunkCachePos; + private final AtomicInteger chunkCacheSize; + private int pos; + private final AtomicInteger foundCacheLast; + private final AtomicInteger foundCache; + private LinkedHashMap chunkCache; + private KList chunkQueue; + private final ReentrantLock cacheLock; + + private static final Map jobs = new HashMap<>(); + + public DeepSearchPregenerator(DeepSearchJob job, File destination) { + this.job = job; + this.chunkCacheSize = new AtomicInteger(); // todo + this.chunkCachePos = new AtomicInteger(1000); + this.foundCacheLast = new AtomicInteger(); + this.foundCache = new AtomicInteger(); + this.cacheLock = new ReentrantLock(); + this.destination = destination; + this.chunkCache = new LinkedHashMap<>(); + this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> { + }).count(); + this.world = Bukkit.getWorld(job.getWorld().getUID()); + this.chunkQueue = new KList<>(); + this.latch = new ChronoLatch(3000); + this.startTime = new AtomicLong(M.ms()); + this.chunksPerSecond = new RollingSequence(10); + this.chunksPerMinute = new RollingSequence(10); + foundChunks = new AtomicInteger(0); + this.foundLast = new AtomicInteger(0); + this.foundTotalChunks = new AtomicInteger((int) Math.ceil(Math.pow((2.0 * job.getRadiusBlocks()) / 16, 2))); + + this.pos = 0; + jobs.put(job.getWorld().getName(), job); + DeepSearchPregenerator.instance = this; + } + + @EventHandler + public void on(WorldUnloadEvent e) { + if (e.getWorld().equals(world)) { + interrupt(); + } + } + + public void run() { + while (!interrupted()) { + tick(); + } + try { + saveNow(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void tick() { + DeepSearchJob job = jobs.get(world.getName()); + // chunkCache(); //todo finish this + if (latch.flip() && !job.paused) { + if (cacheLock.isLocked()) { + Iris.info("DeepFinder: Caching: " + chunkCachePos.get() + " Of " + chunkCacheSize.get()); + } else { + long eta = computeETA(); + save(); + int secondGenerated = foundChunks.get() - foundLast.get(); + foundLast.set(foundChunks.get()); + secondGenerated = secondGenerated / 3; + chunksPerSecond.put(secondGenerated); + chunksPerMinute.put(secondGenerated * 60); + Iris.info("DeepFinder: " + C.IRIS + world.getName() + C.RESET + " Searching: " + Form.f(foundChunks.get()) + " of " + Form.f(foundTotalChunks.get()) + " " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2)); + } + + } + if (foundChunks.get() >= foundTotalChunks.get()) { + Iris.info("Completed DeepSearch!"); + interrupt(); + } + } + + private long computeETA() { + return (long) ((foundTotalChunks.get() - foundChunks.get()) / chunksPerSecond.getAverage()) * 1000; + // todo broken + } + + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + + private void queueSystem(Position2 chunk) { + if (chunkQueue.isEmpty()) { + for (int limit = 512; limit != 0; limit--) { + pos = job.getPosition() + 1; + chunkQueue.add(getChunk(pos)); + } + } else { + //MCAUtil.read(); + + } + + + } + + private void findInChunk(World world, int x, int z) throws IOException { + int xx = x * 16; + int zz = z * 16; + Engine engine = IrisToolbelt.access(world).getEngine(); + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + int height = engine.getHeight(xx + i, zz + j); + if (height > 300) { + File found = new File("plugins" + "iris" + "found.txt"); + FileWriter writer = new FileWriter(found); + if (!found.exists()) { + found.createNewFile(); + } + IrisBiome biome = engine.getBiome(xx, engine.getHeight(), zz); + Iris.info("Found at! " + xx + ", " + zz + "Biome ID: " + biome.getName() + ", "); + writer.write("Biome at: X: " + xx + " Z: " + zz + "Biome ID: " + biome.getName() + ", "); + return; + } + } + } + } + + public Position2 getChunk(int position) { + int p = -1; + AtomicInteger xx = new AtomicInteger(); + AtomicInteger zz = new AtomicInteger(); + Spiraler s = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> { + xx.set(x); + zz.set(z); + }); + + while (s.hasNext() && p++ < position) { + s.next(); + } + + return new Position2(xx.get(), zz.get()); + } + + public void save() { + J.a(() -> { + try { + saveNow(); + } catch (Throwable e) { + e.printStackTrace(); + } + }); + } + + public static void setPausedDeep(World world) { + DeepSearchJob job = jobs.get(world.getName()); + if (isPausedDeep(world)){ + job.paused = false; + } else { + job.paused = true; + } + + if ( job.paused) { + Iris.info(C.BLUE + "DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Paused"); + } else { + Iris.info(C.BLUE + "DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Resumed"); + } + } + + public static boolean isPausedDeep(World world) { + DeepSearchJob job = jobs.get(world.getName()); + return job != null && job.isPaused(); + } + + public void shutdownInstance(World world) throws IOException { + Iris.info("DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " Shutting down.."); + DeepSearchJob job = jobs.get(world.getName()); + File worldDirectory = new File(Bukkit.getWorldContainer(), world.getName()); + File deepFile = new File(worldDirectory, "DeepSearch.json"); + + if (job == null) { + Iris.error("No DeepSearch job found for world: " + world.getName()); + return; + } + + try { + if (!job.isPaused()) { + job.setPaused(true); + } + save(); + jobs.remove(world.getName()); + new BukkitRunnable() { + @Override + public void run() { + while (deepFile.exists()){ + deepFile.delete(); + J.sleep(1000); + } + Iris.info("DeepSearch: " + C.IRIS + world.getName() + C.BLUE + " File deleted and instance closed."); + } + }.runTaskLater(Iris.instance, 20L); + } catch (Exception e) { + Iris.error("Failed to shutdown DeepSearch for " + world.getName()); + e.printStackTrace(); + } finally { + saveNow(); + interrupt(); + } + } + + + public void saveNow() throws IOException { + IO.writeAll(this.destination, new Gson().toJson(job)); + } + + @Data + @Builder + public static class DeepSearchJob { + private World world; + @Builder.Default + private int radiusBlocks = 5000; + @Builder.Default + private int position = 0; + @Builder.Default + boolean paused = false; + } +} + diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java b/core/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java index 495454f22..80b0a3dfd 100644 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/methods/AsyncPregenMethod.java @@ -82,8 +82,11 @@ public class AsyncPregenMethod implements PregeneratorMethod { private void completeChunk(int x, int z, PregenListener listener) { try { future.add(PaperLib.getChunkAtAsync(world, x, z, true).thenApply((i) -> { - if (i == null) return 0; - lastUse.put(i, M.ms()); + if (i == null) { + + } + Chunk c = Bukkit.getWorld(world.getUID()).getChunkAt(x, z); + lastUse.put(c, M.ms()); listener.onChunkGenerated(x, z); listener.onChunkCleaned(x, z); return 0; diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/methods/HeadlessPregenMethod.java b/core/src/main/java/com/volmit/iris/core/pregenerator/methods/HeadlessPregenMethod.java deleted file mode 100644 index 7196032fa..000000000 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/methods/HeadlessPregenMethod.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.volmit.iris.core.pregenerator.methods; - -import com.volmit.iris.Iris; -import com.volmit.iris.core.IrisSettings; -import com.volmit.iris.core.nms.IHeadless; -import com.volmit.iris.core.nms.INMS; -import com.volmit.iris.core.pregenerator.PregenListener; -import com.volmit.iris.core.pregenerator.PregeneratorMethod; -import com.volmit.iris.engine.framework.Engine; -import com.volmit.iris.util.mantle.Mantle; -import com.volmit.iris.util.parallel.MultiBurst; - -import java.io.IOException; -import java.util.concurrent.Semaphore; - -public class HeadlessPregenMethod implements PregeneratorMethod { - private final Engine engine; - private final IHeadless headless; - private final Semaphore semaphore; - private final int max; - - public HeadlessPregenMethod(Engine engine) { - this.max = IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism()); - this.engine = engine; - this.headless = INMS.get().createHeadless(engine); - this.semaphore = new Semaphore(max); - } - - @Override - public void init() {} - - @Override - public void close() { - try { - semaphore.acquire(max); - } catch (InterruptedException ignored) {} - headless.save(); - try { - headless.close(); - } catch (IOException e) { - Iris.error("Failed to close headless"); - e.printStackTrace(); - } - } - - @Override - public void save() { - headless.save(); - } - - @Override - public boolean supportsRegions(int x, int z, PregenListener listener) { - return false; - } - - @Override - public String getMethod(int x, int z) { - return "Headless"; - } - - @Override - public void generateRegion(int x, int z, PregenListener listener) {} - - @Override - public void generateChunk(int x, int z, PregenListener listener) { - try { - semaphore.acquire(); - } catch (InterruptedException ignored) { - semaphore.release(); - return; - } - MultiBurst.burst.complete(() -> { - try { - listener.onChunkGenerating(x, z); - headless.generateChunk(x, z); - listener.onChunkGenerated(x, z); - } finally { - semaphore.release(); - } - }); - } - - @Override - public Mantle getMantle() { - return engine.getMantle().getMantle(); - } -} diff --git a/core/src/main/java/com/volmit/iris/core/pregenerator/methods/MedievalPregenMethod.java b/core/src/main/java/com/volmit/iris/core/pregenerator/methods/MedievalPregenMethod.java index cdecf2bcc..2ebfb64b2 100644 --- a/core/src/main/java/com/volmit/iris/core/pregenerator/methods/MedievalPregenMethod.java +++ b/core/src/main/java/com/volmit/iris/core/pregenerator/methods/MedievalPregenMethod.java @@ -119,7 +119,8 @@ public class MedievalPregenMethod implements PregeneratorMethod { listener.onChunkGenerating(x, z); futures.add(J.sfut(() -> { - Chunk c = world.getChunkAt(x, z); + world.getChunkAt(x, z); + Chunk c = Bukkit.getWorld(world.getUID()).getChunkAt(x, z); lastUse.put(c, M.ms()); listener.onChunkGenerated(x, z); listener.onChunkCleaned(x, z); diff --git a/core/src/main/java/com/volmit/iris/core/safeguard/IrisSafeguard.java b/core/src/main/java/com/volmit/iris/core/safeguard/IrisSafeguard.java index 14a1a66bc..4fb25371a 100644 --- a/core/src/main/java/com/volmit/iris/core/safeguard/IrisSafeguard.java +++ b/core/src/main/java/com/volmit/iris/core/safeguard/IrisSafeguard.java @@ -1,71 +1,15 @@ package com.volmit.iris.core.safeguard; import com.volmit.iris.Iris; -import com.volmit.iris.core.IrisSettings; -import com.volmit.iris.core.nms.INMS; -import com.volmit.iris.core.safeguard.handler.onCommandWarning; -import com.volmit.iris.util.collection.KList; -import com.volmit.iris.util.format.C; -import com.volmit.iris.util.format.Form; -import com.volmit.iris.util.misc.getHardware; - -import static org.bukkit.Bukkit.getServer; public class IrisSafeguard { - public static IrisSafeguard instance; - public boolean acceptUnstable = false; - public boolean unstablemode = false; - public boolean warningmode = false; - public boolean stablemode = false; + public static boolean unstablemode = false; + public static boolean warningmode = false; + public static boolean stablemode = false; - public static void InitializeSafeguard() { - instance = new IrisSafeguard(); - } - - public void IrisSafeguardSystem() { - acceptUnstable = IrisSettings.get().getSafeguard().ignoreBootMode; - getServer().getPluginManager().registerEvents(new onCommandWarning(), Iris.instance); + public static void IrisSafeguardSystem() { Iris.info("Enabled Iris SafeGuard"); ServerBootSFG.BootCheck(); } - - public void earlySplash() { - String padd = Form.repeat(" ", 8); - String padd2 = Form.repeat(" ", 4); - String[] info = new String[]{"", "", "", "", "", padd2 + C.RED + " Iris", padd2 + C.GRAY + " by " + C.DARK_RED + "Volmit Software", padd2 + C.GRAY + " v" + C.RED + Iris.instance.getDescription().getVersion()}; - String[] splashunstable = { - padd + C.GRAY + " @@@@@@@@@@@@@@" + C.DARK_GRAY + "@@@", - padd + C.GRAY + " @@&&&&&&&&&" + C.DARK_GRAY + "&&&&&&" + C.RED + " .(((()))). ", - padd + C.GRAY + "@@@&&&&&&&&" + C.DARK_GRAY + "&&&&&" + C.RED + " .((((((())))))). ", - padd + C.GRAY + "@@@&&&&&" + C.DARK_GRAY + "&&&&&&&" + C.RED + " ((((((((())))))))) " + C.GRAY + " @", - padd + C.GRAY + "@@@&&&&" + C.DARK_GRAY + "@@@@@&" + C.RED + " ((((((((-))))))))) " + C.GRAY + " @@", - padd + C.GRAY + "@@@&&" + C.RED + " ((((((({ })))))))) " + C.GRAY + " &&@@@", - padd + C.GRAY + "@@" + C.RED + " ((((((((-))))))))) " + C.DARK_GRAY + "&@@@@@" + C.GRAY + "&&&&@@@", - padd + C.GRAY + "@" + C.RED + " ((((((((())))))))) " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&@@@", - padd + C.GRAY + "" + C.RED + " '((((((()))))))' " + C.DARK_GRAY + "&&&&&" + C.GRAY + "&&&&&&&&@@@", - padd + C.GRAY + "" + C.RED + " '(((())))' " + C.DARK_GRAY + "&&&&&&&&" + C.GRAY + "&&&&&&&@@", - padd + C.GRAY + " " + C.DARK_GRAY + "@@@" + C.GRAY + "@@@@@@@@@@@@@@" - }; - - for (int i = 0; i < info.length; i++) { - splashunstable[i] += info[i]; - } - Iris.info("Java: " + Iris.instance.getJava()); - if (!Iris.instance.getServer().getVersion().contains("Purpur")) { - if (Iris.instance.getServer().getVersion().contains("Spigot") && Iris.instance.getServer().getVersion().contains("Bukkit")) { - Iris.info(C.RED + " Iris requires paper or above to function properly.."); - } else { - Iris.info(C.YELLOW + "Purpur is recommended to use with iris."); - } - } - if (getHardware.getProcessMemory() < 5999) { - Iris.warn("6GB+ Ram is recommended"); - Iris.warn("Process Memory: " + getHardware.getProcessMemory() + " MB"); - } - Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes()); - Iris.info("\n\n " + new KList<>(splashunstable).toString("\n") + "\n"); - UtilsSFG.splash(); - - } } diff --git a/core/src/main/java/com/volmit/iris/core/safeguard/ModesSFG.java b/core/src/main/java/com/volmit/iris/core/safeguard/ModesSFG.java index 127d560f8..76989d8e7 100644 --- a/core/src/main/java/com/volmit/iris/core/safeguard/ModesSFG.java +++ b/core/src/main/java/com/volmit/iris/core/safeguard/ModesSFG.java @@ -3,20 +3,18 @@ package com.volmit.iris.core.safeguard; import com.volmit.iris.Iris; import com.volmit.iris.core.IrisSettings; import com.volmit.iris.util.format.C; -import org.bukkit.Bukkit; -import org.bukkit.scheduler.BukkitScheduler; public class ModesSFG { public static void selectMode() { - if (IrisSafeguard.instance.unstablemode) { + if (IrisSafeguard.unstablemode) { Iris.safeguard(C.DARK_RED + "Iris is running in Unstable Mode"); unstable(); } - if (IrisSafeguard.instance.warningmode) { + if (IrisSafeguard.warningmode) { Iris.safeguard(C.GOLD + "Iris is running in Warning Mode"); warning(); } - if (IrisSafeguard.instance.stablemode) { + if (IrisSafeguard.stablemode) { stable(); } } @@ -29,7 +27,7 @@ public class ModesSFG { UtilsSFG.printIncompatibleWarnings(); - if (IrisSafeguard.instance.unstablemode) { + if (IrisSafeguard.unstablemode) { Iris.info(""); Iris.info(C.DARK_GRAY + "--==<" + C.RED + " IMPORTANT " + C.DARK_GRAY + ">==--"); Iris.info(C.RED + "Iris is running in unstable mode which may cause the following issues:"); @@ -46,26 +44,27 @@ public class ModesSFG { Iris.info(C.DARK_RED + "ATTENTION: " + C.RED + "While running Iris in unstable mode, you won't be eligible for support."); Iris.info(C.DARK_RED + "CAUSE: " + C.RED + UtilsSFG.MSGIncompatibleWarnings()); - if (IrisSettings.get().getSafeguard().ignoreBootMode) { + if (IrisSettings.get().getGeneral().DoomsdayAnnihilationSelfDestructMode) { Iris.info(C.DARK_RED + "Boot Unstable is set to true, continuing with the startup process."); } else { - Iris.info(C.DARK_RED + "Go to plugins/iris/settings.json and set ignoreBootMode to true if you wish to proceed."); - Iris.info(C.DARK_RED + "Shutting down server in " + C.UNDERLINE + "" + C.DARK_RED + "50 Seconds"); - try { - Thread.sleep(50000); - Bukkit.shutdown(); - } catch (Exception ignored) { + Iris.info(C.DARK_RED + "Go to plugins/iris/settings.json and set DoomsdayAnnihilationSelfDestructMode to true if you wish to proceed."); + while (true) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // no + } } } + Iris.info(""); } - Iris.info(""); } public static void warning() { UtilsSFG.printIncompatibleWarnings(); - if (IrisSafeguard.instance.warningmode) { + if (IrisSafeguard.warningmode) { Iris.info(""); Iris.info(C.DARK_GRAY + "--==<" + C.GOLD + " IMPORTANT " + C.DARK_GRAY + ">==--"); Iris.info(C.GOLD + "Iris is running in warning mode which may cause the following issues:"); diff --git a/core/src/main/java/com/volmit/iris/core/safeguard/PerformanceSFG.java b/core/src/main/java/com/volmit/iris/core/safeguard/PerformanceSFG.java new file mode 100644 index 000000000..90aab8cf5 --- /dev/null +++ b/core/src/main/java/com/volmit/iris/core/safeguard/PerformanceSFG.java @@ -0,0 +1,8 @@ +package com.volmit.iris.core.safeguard; + +public class PerformanceSFG { + public static void calculatePerformance() { + + + } +} diff --git a/core/src/main/java/com/volmit/iris/core/safeguard/ServerBootSFG.java b/core/src/main/java/com/volmit/iris/core/safeguard/ServerBootSFG.java index 45526181a..6e88835be 100644 --- a/core/src/main/java/com/volmit/iris/core/safeguard/ServerBootSFG.java +++ b/core/src/main/java/com/volmit/iris/core/safeguard/ServerBootSFG.java @@ -116,16 +116,16 @@ public class ServerBootSFG { safeguardPassed = (severityHigh == 0 && severityMedium == 0 && severityLow == 0); count = severityHigh + severityMedium + severityLow; if (safeguardPassed) { - IrisSafeguard.instance.stablemode = true; + stablemode = true; Iris.safeguard("Stable mode has been activated."); } if (!safeguardPassed) { if (severityMedium >= 1 && severityHigh == 0) { - IrisSafeguard.instance.warningmode = true; + warningmode = true; Iris.safeguard("Warning mode has been activated."); } if (severityHigh >= 1) { - IrisSafeguard.instance.unstablemode = true; + unstablemode = true; Iris.safeguard("Unstable mode has been activated."); } } diff --git a/core/src/main/java/com/volmit/iris/core/safeguard/UtilsSFG.java b/core/src/main/java/com/volmit/iris/core/safeguard/UtilsSFG.java index 2b2bf5c46..659c02bdd 100644 --- a/core/src/main/java/com/volmit/iris/core/safeguard/UtilsSFG.java +++ b/core/src/main/java/com/volmit/iris/core/safeguard/UtilsSFG.java @@ -14,10 +14,10 @@ public class UtilsSFG { if (ServerBootSFG.safeguardPassed) { Iris.safeguard(C.BLUE + "0 Conflicts found"); } else { - if (IrisSafeguard.instance.unstablemode) { + if (IrisSafeguard.unstablemode) { Iris.safeguard(C.DARK_RED + "" + ServerBootSFG.count + " Conflicts found"); } - if (IrisSafeguard.instance.warningmode) { + if (IrisSafeguard.warningmode) { Iris.safeguard(C.YELLOW + "" + ServerBootSFG.count + " Conflicts found"); } diff --git a/core/src/main/java/com/volmit/iris/core/safeguard/handler/onCommandWarning.java b/core/src/main/java/com/volmit/iris/core/safeguard/handler/onCommandWarning.java deleted file mode 100644 index 95d74328a..000000000 --- a/core/src/main/java/com/volmit/iris/core/safeguard/handler/onCommandWarning.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.volmit.iris.core.safeguard.handler; - -import com.volmit.iris.core.IrisSettings; -import com.volmit.iris.core.safeguard.IrisSafeguard; -import com.volmit.iris.util.format.C; -import com.volmit.iris.util.plugin.VolmitSender; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerCommandPreprocessEvent; - -public class onCommandWarning implements Listener { - @EventHandler - public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { - if (IrisSettings.get().getSafeguard().userUnstableWarning && IrisSafeguard.instance.unstablemode) { - String command = event.getMessage(); - Player player = event.getPlayer(); - if (command.startsWith("/iris")) { - VolmitSender sender = new VolmitSender(player); - boolean perm = sender.hasPermission("iris.all") || sender.isOp(); - if (perm) { - sender.sendMessage(C.DARK_GRAY + "[" + C.RED + "!" + C.DARK_GRAY+ "]" + C.DARK_RED + "Iris is running unstably! Please resolve this."); - } - } - } - } -} diff --git a/core/src/main/java/com/volmit/iris/core/service/StudioSVC.java b/core/src/main/java/com/volmit/iris/core/service/StudioSVC.java index 519a92b5f..720da652f 100644 --- a/core/src/main/java/com/volmit/iris/core/service/StudioSVC.java +++ b/core/src/main/java/com/volmit/iris/core/service/StudioSVC.java @@ -22,6 +22,7 @@ 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; @@ -295,6 +296,7 @@ public class StudioSVC implements IrisService { } sender.sendMessage("Successfully Aquired " + d.getName()); + ServerConfigurator.installDataPacks(true); } public KMap getListing(boolean cached) { diff --git a/core/src/main/java/com/volmit/iris/core/tools/IrisCreator.java b/core/src/main/java/com/volmit/iris/core/tools/IrisCreator.java index 9f5b58e67..6096582d2 100644 --- a/core/src/main/java/com/volmit/iris/core/tools/IrisCreator.java +++ b/core/src/main/java/com/volmit/iris/core/tools/IrisCreator.java @@ -21,10 +21,13 @@ 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; @@ -43,6 +46,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; +import static com.volmit.iris.core.safeguard.IrisSafeguard.unstablemode; /** * Makes it a lot easier to setup an engine, world, studio or whatever @@ -141,6 +145,7 @@ public class IrisCreator { .studio(studio) .smartVanillaHeight(smartVanillaHeight) .create(); + ServerConfigurator.installDataPacks(false); access = (PlatformChunkGenerator) wc.generator(); PlatformChunkGenerator finalAccess1 = access; diff --git a/core/src/main/java/com/volmit/iris/core/tools/IrisNoiseBenchmark.java b/core/src/main/java/com/volmit/iris/core/tools/IrisNoiseBenchmark.java deleted file mode 100644 index 0d43b26d1..000000000 --- a/core/src/main/java/com/volmit/iris/core/tools/IrisNoiseBenchmark.java +++ /dev/null @@ -1,254 +0,0 @@ -package com.volmit.iris.core.tools; - -import com.volmit.iris.Iris; -import com.volmit.iris.core.loader.IrisData; -import com.volmit.iris.core.project.IrisProject; -import com.volmit.iris.engine.object.*; -import com.volmit.iris.util.collection.KList; -import com.volmit.iris.util.collection.KMap; -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.format.C; -import com.volmit.iris.util.format.Form; -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.math.RNG; -import com.volmit.iris.util.noise.CNG; -import com.volmit.iris.util.plugin.VolmitSender; -import com.volmit.iris.util.scheduling.PrecisionStopwatch; - -import java.io.File; -import java.io.IOException; - -public class IrisNoiseBenchmark { - private IrisDimension dimension; - private VolmitSender sender; - - public IrisNoiseBenchmark(IrisDimension dimension, VolmitSender sender) { - this.dimension = dimension; - this.sender = sender; - } - - public void runAll() { - // Todo: Make this more accurate - File pack = dimension.getLoadFile().getParentFile().getParentFile(); - File report = Iris.instance.getDataFile(pack.getName() + "-profile.txt"); - IrisProject project = new IrisProject(pack); - IrisData data = IrisData.get(pack); - - KList fileText = new KList<>(); - - KMap styleTimings = new KMap<>(); - KMap interpolatorTimings = new KMap<>(); - KMap generatorTimings = new KMap<>(); - KMap biomeTimings = new KMap<>(); - KMap regionTimings = new KMap<>(); - KMap dimensionTimings = new KMap<>(); - - sender.sendMessage("Calculating Performance Metrics for Noise generators"); - - for (NoiseStyle i : NoiseStyle.values()) { - CNG c = i.create(new RNG(i.hashCode())); - - for (int j = 0; j < 3000; j++) { - c.noise(j, j + 1000, j * j); - c.noise(j, -j); - } - - PrecisionStopwatch px = PrecisionStopwatch.start(); - - for (int j = 0; j < 100000; j++) { - c.noise(j, j + 1000, j * j); - c.noise(j, -j); - } - - styleTimings.put(i, px.getMilliseconds()); - } - - fileText.add("Noise Style Performance Impacts: "); - - for (NoiseStyle i : styleTimings.sortKNumber()) { - fileText.add(i.name() + ": " + styleTimings.get(i)); - } - - fileText.add(""); - - sender.sendMessage("Calculating Interpolator Timings..."); - - for (InterpolationMethod i : InterpolationMethod.values()) { - IrisInterpolator in = new IrisInterpolator(); - in.setFunction(i); - in.setHorizontalScale(8); - - NoiseProvider np = (x, z) -> Math.random(); - - for (int j = 0; j < 3000; j++) { - in.interpolate(j, -j, np); - } - - PrecisionStopwatch px = PrecisionStopwatch.start(); - - for (int j = 0; j < 100000; j++) { - in.interpolate(j + 10000, -j - 100000, np); - } - - interpolatorTimings.put(i, px.getMilliseconds()); - } - - fileText.add("Noise Interpolator Performance Impacts: "); - - for (InterpolationMethod i : interpolatorTimings.sortKNumber()) { - fileText.add(i.name() + ": " + interpolatorTimings.get(i)); - } - - fileText.add(""); - - sender.sendMessage("Processing Generator Scores: "); - - KMap> btx = new KMap<>(); - - for (String i : data.getGeneratorLoader().getPossibleKeys()) { - KList vv = new KList<>(); - IrisGenerator g = data.getGeneratorLoader().load(i); - KList composites = g.getAllComposites(); - double score = 0; - int m = 0; - for (IrisNoiseGenerator j : composites) { - m++; - score += styleTimings.get(j.getStyle().getStyle()); - vv.add("Composite Noise Style " + m + " " + j.getStyle().getStyle().name() + ": " + styleTimings.get(j.getStyle().getStyle())); - } - - score += interpolatorTimings.get(g.getInterpolator().getFunction()); - vv.add("Interpolator " + g.getInterpolator().getFunction().name() + ": " + interpolatorTimings.get(g.getInterpolator().getFunction())); - generatorTimings.put(i, score); - btx.put(i, vv); - } - - fileText.add("Project Generator Performance Impacts: "); - - for (String i : generatorTimings.sortKNumber()) { - fileText.add(i + ": " + generatorTimings.get(i)); - - btx.get(i).forEach((ii) -> fileText.add(" " + ii)); - } - - fileText.add(""); - - KMap> bt = new KMap<>(); - - for (String i : data.getBiomeLoader().getPossibleKeys()) { - KList vv = new KList<>(); - IrisBiome b = data.getBiomeLoader().load(i); - double score = 0; - - int m = 0; - for (IrisBiomePaletteLayer j : b.getLayers()) { - m++; - score += styleTimings.get(j.getStyle().getStyle()); - vv.add("Palette Layer " + m + ": " + styleTimings.get(j.getStyle().getStyle())); - } - - score += styleTimings.get(b.getBiomeStyle().getStyle()); - vv.add("Biome Style: " + styleTimings.get(b.getBiomeStyle().getStyle())); - score += styleTimings.get(b.getChildStyle().getStyle()); - vv.add("Child Style: " + styleTimings.get(b.getChildStyle().getStyle())); - biomeTimings.put(i, score); - bt.put(i, vv); - } - - fileText.add("Project Biome Performance Impacts: "); - - for (String i : biomeTimings.sortKNumber()) { - fileText.add(i + ": " + biomeTimings.get(i)); - - bt.get(i).forEach((ff) -> fileText.add(" " + ff)); - } - - fileText.add(""); - - for (String i : data.getRegionLoader().getPossibleKeys()) { - IrisRegion b = data.getRegionLoader().load(i); - double score = 0; - - score += styleTimings.get(b.getLakeStyle().getStyle()); - score += styleTimings.get(b.getRiverStyle().getStyle()); - regionTimings.put(i, score); - } - - fileText.add("Project Region Performance Impacts: "); - - for (String i : regionTimings.sortKNumber()) { - fileText.add(i + ": " + regionTimings.get(i)); - } - - fileText.add(""); - - double m = 0; - for (double i : biomeTimings.v()) { - m += i; - } - m /= biomeTimings.size(); - double mm = 0; - for (double i : generatorTimings.v()) { - mm += i; - } - mm /= generatorTimings.size(); - m += mm; - double mmm = 0; - for (double i : regionTimings.v()) { - mmm += i; - } - mmm /= regionTimings.size(); - m += mmm; - - KMap> dt = new KMap<>(); - - for (String i : data.getDimensionLoader().getPossibleKeys()) { - IrisDimension d = data.getDimensionLoader().load(i); - KList vv = new KList<>(); - double score = 0; - - score += styleTimings.get(d.getContinentalStyle().getStyle()); - vv.add("Continental Style: " + styleTimings.get(d.getContinentalStyle().getStyle())); - score += styleTimings.get(d.getRegionStyle().getStyle()); - vv.add("Region Style: " + styleTimings.get(d.getRegionStyle().getStyle())); - score += styleTimings.get(d.getBiomeStyle(InferredType.LAND).getStyle()); - vv.add("LandBiome Style: " + styleTimings.get(d.getBiomeStyle(InferredType.LAND).getStyle())); - score += styleTimings.get(d.getBiomeStyle(InferredType.SEA).getStyle()); - vv.add("OceanBiome Style: " + styleTimings.get(d.getBiomeStyle(InferredType.SEA).getStyle())); - score += styleTimings.get(d.getCaveBiomeStyle().getStyle()); - vv.add("CaveBiome Style: " + styleTimings.get(d.getCaveBiomeStyle().getStyle())); - score += styleTimings.get(d.getShoreBiomeStyle().getStyle()); - vv.add("ShoreBiome Style: " + styleTimings.get(d.getShoreBiomeStyle().getStyle())); - dimensionTimings.put(i, score); - dt.put(i, vv); - - } - - fileText.add("Project Dimension Performance Impacts: "); - - for (String i : dimensionTimings.sortKNumber()) { - fileText.add(i + ": " + dimensionTimings.get(i)); - - dt.get(i).forEach((ff) -> fileText.add(" " + ff)); - } - - fileText.add(""); - - fileText.add("Average Score: " + m); - sender.sendMessage("Score: " + Form.duration(m, 0)); - - try { - IO.writeAll(report, fileText.toString("\n")); - } catch (IOException e) { - Iris.reportError(e); - e.printStackTrace(); - } - - sender.sendMessage(C.GREEN + "Done! " + report.getPath()); - - } -} diff --git a/core/src/main/java/com/volmit/iris/core/tools/IrisPackBenchmarking.java b/core/src/main/java/com/volmit/iris/core/tools/IrisPackBenchmarking.java index 180109b70..7993cf6e7 100644 --- a/core/src/main/java/com/volmit/iris/core/tools/IrisPackBenchmarking.java +++ b/core/src/main/java/com/volmit/iris/core/tools/IrisPackBenchmarking.java @@ -2,17 +2,9 @@ package com.volmit.iris.core.tools; import com.volmit.iris.Iris; -import com.volmit.iris.core.IrisSettings; -import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.pregenerator.PregenTask; -import com.volmit.iris.core.pregenerator.methods.HeadlessPregenMethod; -import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod; -import com.volmit.iris.core.service.StudioSVC; -import com.volmit.iris.engine.IrisEngine; import com.volmit.iris.engine.framework.Engine; -import com.volmit.iris.engine.framework.EngineTarget; import com.volmit.iris.engine.object.IrisDimension; -import com.volmit.iris.engine.object.IrisWorld; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.exceptions.IrisException; @@ -44,32 +36,28 @@ public class IrisPackBenchmarking { public static boolean benchmarkInProgress = false; private IrisDimension IrisDimension; private int radius; - private final boolean headless; - private final boolean gui; private boolean finished = false; - private Engine engine; PrecisionStopwatch stopwatch; - public IrisPackBenchmarking(IrisDimension dimension, int r, boolean headless, boolean gui) { + public IrisPackBenchmarking(IrisDimension dimension, int r) { instance = this; this.IrisDimension = dimension; this.radius = r; - this.headless = headless; - this.gui = gui; + runBenchmark(); } - public void runBenchmark() { + private void runBenchmark() { this.stopwatch = new PrecisionStopwatch(); ExecutorService service = Executors.newSingleThreadExecutor(); service.submit(() -> { Iris.info("Setting up benchmark environment "); benchmarkInProgress = true; - File file = new File(Bukkit.getWorldContainer(), "benchmark"); + File file = new File("benchmark"); if (file.exists()) { deleteDirectory(file.toPath()); } - engine = createBenchmark(); - while (!headless && !IrisToolbelt.isIrisWorld(Bukkit.getWorld("benchmark"))) { + createBenchmark(); + while (!IrisToolbelt.isIrisWorld(Bukkit.getWorld("benchmark"))) { J.sleep(1000); Iris.debug("Iris PackBenchmark: Waiting..."); } @@ -87,6 +75,7 @@ public class IrisPackBenchmarking { public void finishedBenchmark(KList cps) { try { String time = Form.duration(stopwatch.getMillis()); + Engine engine = IrisToolbelt.access(Bukkit.getWorld("benchmark")).getEngine(); Iris.info("-----------------"); Iris.info("Results:"); Iris.info("- Total time: " + time); @@ -99,8 +88,8 @@ public class IrisPackBenchmarking { File profilers = new File("plugins" + File.separator + "Iris" + File.separator + "packbenchmarks"); profilers.mkdir(); - File results = new File("plugins" + File.separator + "Iris", IrisDimension.getName() + " " + LocalDateTime.now(Clock.systemDefaultZone()).toString().replace(':', '-') + ".txt"); - results.getParentFile().mkdirs(); + File results = new File("plugins " + File.separator + "Iris", IrisDimension.getName() + LocalDateTime.now(Clock.systemDefaultZone()) + ".txt"); + results.createNewFile(); KMap metrics = engine.getMetrics().pull(); try (FileWriter writer = new FileWriter(results)) { writer.write("-----------------\n"); @@ -134,34 +123,15 @@ public class IrisPackBenchmarking { e.printStackTrace(); } } - private Engine createBenchmark(){ + private void createBenchmark(){ try { - if (headless) { - Iris.info("Using headless benchmark!"); - IrisWorld world = IrisWorld.builder() - .name("benchmark") - .minHeight(IrisDimension.getMinHeight()) - .maxHeight(IrisDimension.getMaxHeight()) - .seed(1337) - .worldFolder(new File(Bukkit.getWorldContainer(), "benchmark")) - .environment(IrisDimension.getEnvironment()) - .build(); - Iris.service(StudioSVC.class).installIntoWorld( - Iris.getSender(), - IrisDimension.getLoadKey(), - world.worldFolder()); - var data = IrisData.get(new File(world.worldFolder(), "iris/pack")); - var dim = data.getDimensionLoader().load(IrisDimension.getLoadKey()); - return new IrisEngine(new EngineTarget(world, dim, data), false); - } - Iris.info("Using Standard benchmark!"); - return IrisToolbelt.access(IrisToolbelt.createWorld() - .dimension(IrisDimension.getLoadKey()) + IrisToolbelt.createWorld() + .dimension(IrisDimension.getName()) .name("benchmark") .seed(1337) .studio(false) .benchmark(true) - .create()).getEngine(); + .create(); } catch (IrisException e) { throw new RuntimeException(e); } @@ -172,12 +142,12 @@ public class IrisPackBenchmarking { int z = 0; IrisToolbelt.pregenerate(PregenTask .builder() - .gui(gui) + .gui(false) .center(new Position2(x, z)) .width(5) .height(5) - .build(), headless ? new HeadlessPregenMethod(engine) : new HybridPregenMethod(engine.getWorld().realWorld(), - IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())), engine); + .build(), Bukkit.getWorld("benchmark") + ); } private double calculateAverage(KList list) { diff --git a/core/src/main/java/com/volmit/iris/core/tools/IrisWorldCreator.java b/core/src/main/java/com/volmit/iris/core/tools/IrisWorldCreator.java index 36aa52789..b815d3809 100644 --- a/core/src/main/java/com/volmit/iris/core/tools/IrisWorldCreator.java +++ b/core/src/main/java/com/volmit/iris/core/tools/IrisWorldCreator.java @@ -19,7 +19,6 @@ package com.volmit.iris.core.tools; import com.volmit.iris.core.loader.IrisData; -import com.volmit.iris.core.nms.INMS; import com.volmit.iris.engine.object.*; import com.volmit.iris.engine.platform.BukkitChunkGenerator; import org.bukkit.Bukkit; @@ -85,9 +84,6 @@ public class IrisWorldCreator { ? dim.getLoader().getDataFolder() : new File(w.worldFolder(), "iris/pack"), dimensionName, smartVanillaHeight); - if (!INMS.get().registerDimension(name, dim)) { - throw new IllegalStateException("Unable to register dimension " + dim.getName()); - } return new WorldCreator(name) .environment(findEnvironment()) diff --git a/core/src/main/java/com/volmit/iris/core/tools/IrisWorldDump.java b/core/src/main/java/com/volmit/iris/core/tools/IrisWorldDump.java deleted file mode 100644 index c6b8da0bf..000000000 --- a/core/src/main/java/com/volmit/iris/core/tools/IrisWorldDump.java +++ /dev/null @@ -1,241 +0,0 @@ -package com.volmit.iris.core.tools; - -import com.volmit.iris.Iris; -import com.volmit.iris.core.IrisSettings; -import com.volmit.iris.engine.framework.Engine; -import com.volmit.iris.util.collection.KList; -import com.volmit.iris.util.collection.KMap; -import com.volmit.iris.util.format.Form; -import com.volmit.iris.util.math.M; -import com.volmit.iris.util.math.RollingSequence; -import com.volmit.iris.util.nbt.mca.Chunk; -import com.volmit.iris.util.nbt.mca.MCAFile; -import com.volmit.iris.util.nbt.mca.MCAUtil; -import com.volmit.iris.util.nbt.tag.CompoundTag; -import com.volmit.iris.util.nbt.tag.StringTag; -import com.volmit.iris.util.plugin.VolmitSender; -import lombok.Getter; -import lombok.Setter; -import org.bukkit.World; - -import java.io.File; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReferenceArray; - -public class IrisWorldDump { - private KMap storage; - private AtomicLong airStorage; - private World world; - private File MCADirectory; - private AtomicInteger threads; - private AtomicInteger regionsProcessed; - private AtomicInteger chunksProcessed; - private AtomicInteger totalToProcess; - private AtomicInteger totalMaxChunks; - private AtomicInteger totalMCAFiles; - private RollingSequence chunksPerSecond; - private Engine engine = null; - private Boolean IrisWorld; - private VolmitSender sender; - private ExecutorService executor; - private ScheduledExecutorService scheduler; - private AtomicLong startTime; - private File dumps; - private File worldDump; - private int mcaCacheSize; - private File temp; - private File blocks; - private File structures; - - public IrisWorldDump(World world, VolmitSender sender) { - sender.sendMessage("Initializing IrisWorldDump..."); - this.world = world; - this.sender = sender; - this.MCADirectory = new File(world.getWorldFolder(), "region"); - this.dumps = new File("plugins" + File.separator + "iris", "dumps"); - this.worldDump = new File(dumps, world.getName()); - this.mcaCacheSize = IrisSettings.get().getWorldDump().mcaCacheSize; - this.regionsProcessed = new AtomicInteger(0); - this.chunksProcessed = new AtomicInteger(0); - this.totalToProcess = new AtomicInteger(0); - this.chunksPerSecond = new RollingSequence(10); - this.temp = new File(worldDump, "temp"); - this.executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() - 1); - this.scheduler = Executors.newSingleThreadScheduledExecutor(); - this.startTime = new AtomicLong(); - this.storage = new KMap<>(); - this.airStorage = new AtomicLong(0); - - this.blocks = new File(worldDump, "blocks"); - this.structures = new File(worldDump, "structures"); - - try { - this.engine = IrisToolbelt.access(world).getEngine(); - this.IrisWorld = true; - } catch (Exception e) { - this.IrisWorld = false; - } - } - - - public void start() { - - if (!dumps.exists()) { - if (!dumps.mkdirs()) { - System.err.println("Failed to create dump directory."); - return; - } - } - - try { - CompletableFuture mcaCount = CompletableFuture.supplyAsync(this::totalMcaFiles); - CompletableFuture chunkCount = CompletableFuture.supplyAsync(this::totalMCAChunks); - this.totalMCAFiles = new AtomicInteger(mcaCount.get()); - this.totalMaxChunks = new AtomicInteger(chunkCount.get()); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException(e); - } - dump(); - updater(); - } - - private void updater() { - startTime.set(System.currentTimeMillis()); - scheduler.scheduleAtFixedRate(() -> { - long eta = computeETA(); - long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 3000; - int processed = chunksProcessed.get(); - double cps = elapsedSeconds > 0 ? processed / (double) elapsedSeconds : 0; - chunksPerSecond.put(cps); - double percentage = ((double) chunksProcessed.get() / (double) totalMaxChunks.get()) * 100; - Iris.info("Processed: " + Form.f(processed) + " of " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta, 2), percentage); - - }, 1, 3, TimeUnit.SECONDS); - - } - - public class blockData { - @Getter - @Setter - private String block; - private int biome; - private int height; - - public blockData(String b, int bm, int h) { - this.block = b; - this.height = h; - this.biome = bm; - } - } - - - private void dump() { - Iris.info("Starting the dump process."); - int threads = Runtime.getRuntime().availableProcessors(); - AtomicInteger f = new AtomicInteger(); - for (File mcaFile : MCADirectory.listFiles()) { - if (mcaFile.getName().endsWith(".mca")) { - executor.submit(() -> { - try { - processMCARegion( MCAUtil.read(mcaFile)); - } catch (Exception e) { - f.getAndIncrement(); - Iris.error("Failed to read mca file"); - e.printStackTrace(); - } - }); - } - } - } - - private void processMCARegion(MCAFile mca) { - AtomicReferenceArray chunks = new AtomicReferenceArray<>(1024); - for (int i = 0; i < chunks.length(); i++) { - chunks.set(i, mca.getChunks().get(i)); - } - for (int i = 0; i < chunks.length(); i++) { - Chunk chunk = chunks.get(i); - if (chunk != null) { - int CHUNK_HEIGHT = (world.getMaxHeight() - world.getMinHeight()); - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - for (int y = 0; y < CHUNK_HEIGHT; y++) { - CompoundTag tag = chunk.getBlockStateAt(x, y, z); - int biome = chunk.getBiomeAt(x, y, z); - if (tag == null) { - String blockName = "minecraft:air"; - //storage.compute(blockName, (key, count) -> (count == null) ? 1 : count + 1); - airStorage.getAndIncrement(); - int ii = 0; - } else { - StringTag nameTag = tag.getStringTag("Name"); - String blockName = nameTag.getValue(); - blockData data = new blockData(blockName, biome, y); - storage.compute(data, (key, count) -> (count == null) ? 1 : count + 1); - int ii = 0; - } - } - } - } - chunksProcessed.getAndIncrement(); - } - } - regionsProcessed.getAndIncrement(); - } - - private int totalMCAChunks() { - AtomicInteger chunks = new AtomicInteger(); - CountDownLatch latch = new CountDownLatch(totalMcaFiles() * 1024); - for (File mcafile : MCADirectory.listFiles()) { - executor.submit(() -> { - try { - if (mcafile.getName().endsWith(".mca")) { - MCAFile mca = MCAUtil.read(mcafile); - for (int width = 0; width < 32; width++) { - for (int depth = 0; depth < 32; depth++) { - Chunk chunk = mca.getChunk(width, depth); - if (chunk != null) { - chunks.getAndIncrement(); - } - latch.countDown(); - } - } - } - } catch (Exception e) { - Iris.error("Failed to read mca file"); - e.printStackTrace(); - } - }); - } - - try { - latch.await(); - } catch (Exception e) { - e.printStackTrace(); - } - - return chunks.get(); - } - - private int totalMcaFiles() { - int size = 0; - for (File mca : MCADirectory.listFiles()) { - if (mca.getName().endsWith(".mca")) { - size++; - } - } - return size; - } - - private long computeETA() { - return (long) (totalMaxChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total? - // If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers) - ((totalMaxChunks.get() - chunksProcessed.get()) * ((double) (M.ms() - startTime.get()) / (double) chunksProcessed.get())) : - // If no, use quick function (which is less accurate over time but responds better to the initial delay) - ((totalMaxChunks.get() - chunksProcessed.get()) / chunksPerSecond.getAverage()) * 1000 - ); - } - -} diff --git a/core/src/main/java/com/volmit/iris/engine/IrisEngine.java b/core/src/main/java/com/volmit/iris/engine/IrisEngine.java index 18b67d056..e1ea0a00e 100644 --- a/core/src/main/java/com/volmit/iris/engine/IrisEngine.java +++ b/core/src/main/java/com/volmit/iris/engine/IrisEngine.java @@ -21,6 +21,8 @@ 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; @@ -51,6 +53,7 @@ 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; @@ -63,6 +66,8 @@ 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") @@ -237,6 +242,11 @@ public class IrisEngine implements Engine { getTarget().setDimension(getData().getDimensionLoader().load(getDimension().getLoadKey())); prehotload(); setupEngine(); + J.a(() -> { + synchronized (ServerConfigurator.class) { + ServerConfigurator.installDataPacks(false); + } + }); } @Override @@ -276,13 +286,6 @@ public class IrisEngine implements Engine { return generated.get(); } - @Override - public void addGenerated() { - if (generated.incrementAndGet() == 661) { - J.a(() -> getData().savePrefetch(this)); - } - } - @Override public double getGeneratedPerSecond() { if (perSecondLatch.flip()) { @@ -465,7 +468,11 @@ public class IrisEngine implements Engine { getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.REAL, true); getMetrics().getTotal().put(p.getMilliseconds()); - addGenerated(); + generated.incrementAndGet(); + + if (generated.get() == 661) { + J.a(() -> getData().savePrefetch(this)); + } } catch (Throwable e) { Iris.reportError(e); fail("Failed to generate " + x + ", " + z, e); diff --git a/core/src/main/java/com/volmit/iris/engine/decorator/IrisSeaFloorDecorator.java b/core/src/main/java/com/volmit/iris/engine/decorator/IrisSeaFloorDecorator.java index b7aa7298e..dc3ac48c5 100644 --- a/core/src/main/java/com/volmit/iris/engine/decorator/IrisSeaFloorDecorator.java +++ b/core/src/main/java/com/volmit/iris/engine/decorator/IrisSeaFloorDecorator.java @@ -41,11 +41,9 @@ public class IrisSeaFloorDecorator extends IrisEngineDecorator { if (!decorator.isStacking()) { if (height >= 0 || height < getEngine().getHeight()) { if (null != decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())) { - if (height == getDimension().getFluidHeight() - 1) { - data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData())); - height++; - data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())); - } + data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData())); + height++; + data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())); } else { data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData())); } @@ -75,5 +73,6 @@ public class IrisSeaFloorDecorator extends IrisEngineDecorator { } } } + } } diff --git a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java index 0809d0932..e1f6560dc 100644 --- a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java +++ b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java @@ -577,8 +577,6 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat int getGenerated(); - void addGenerated(); - default IrisPosition lookForStreamResult(T find, ProceduralStream stream, Function2 matcher, long timeout) { AtomicInteger checked = new AtomicInteger(); AtomicLong time = new AtomicLong(M.ms()); diff --git a/core/src/main/java/com/volmit/iris/engine/jvm/VMJavaFX.java b/core/src/main/java/com/volmit/iris/engine/jvm/VMJavaFX.java deleted file mode 100644 index d187c333b..000000000 --- a/core/src/main/java/com/volmit/iris/engine/jvm/VMJavaFX.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.volmit.iris.engine.jvm; - -import com.volmit.iris.util.plugin.VolmitSender; - -public class VMJavaFX { - private VolmitSender sender; - public VMJavaFX(VolmitSender user) { - this.sender = user; - - } - - public void start() { - try { - // Start JavaFX in a new JVM - ProcessBuilder processBuilder = new ProcessBuilder( - "java", - "--module-path", "path/to/javafx-sdk/lib", // Set path to JavaFX SDK - "--add-modules", "javafx.controls,javafx.fxml", - "-jar", "path/to/javafx-application.jar" - ); - processBuilder.inheritIO(); - processBuilder.start(); - sender.sendMessage("JavaFX application is launched!"); - } catch (Exception e) { - sender.sendMessage("Failed to launch JavaFX application."); - e.printStackTrace(); - } - } - - - -} diff --git a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java index b7d8223b7..4f48245bf 100644 --- a/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java +++ b/core/src/main/java/com/volmit/iris/engine/mantle/components/MantleJigsawComponent.java @@ -156,7 +156,7 @@ public class MantleJigsawComponent extends IrisMantleComponent { @ChunkCoordinates private IrisJigsawStructurePlacement pick(List structures, long seed, int x, int z) { return IRare.pick(structures.stream() - .filter(p -> p.shouldPlace(jigsaw(), x, z)) + .filter(p -> p.shouldPlace(getDimension().getJigsawStructureDivisor(), jigsaw(), x, z)) .toList(), new RNG(seed).nextDouble()); } diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisBiome.java b/core/src/main/java/com/volmit/iris/engine/object/IrisBiome.java index 669917ab2..d75dca7ad 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisBiome.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisBiome.java @@ -170,6 +170,7 @@ public class IrisBiome extends IrisRegistrant implements IRare { @Desc("Collection of ores to be generated") @ArrayType(type = IrisOreGenerator.class, min = 1) private KList ores = new KList<>(); + public BlockData generateOres(int x, int y, int z, RNG rng, IrisData data) { if (ores.isEmpty()) { return null; diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisBiomeCustom.java b/core/src/main/java/com/volmit/iris/engine/object/IrisBiomeCustom.java index f491dff68..dd3e16af6 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisBiomeCustom.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisBiomeCustom.java @@ -19,7 +19,7 @@ package com.volmit.iris.engine.object; import com.volmit.iris.Iris; -import com.volmit.iris.core.nms.datapack.DataVersion; +import com.volmit.iris.core.nms.datapack.IDataFixer; 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() { + public String generateJson(IDataFixer fixer) { 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 DataVersion.getDefault().fixCustomBiome(this, j).toString(4); + return fixer.fixCustomBiome(this, j).toString(4); } private int parseColor(String c) { diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java b/core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java index 98049d32f..fafeb768d 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java @@ -1,388 +1,583 @@ -/* - * Iris is a World Generator for Minecraft Bukkit Servers - * Copyright (c) 2022 Arcane Arts (Volmit Software) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.volmit.iris.engine.object; - -import com.volmit.iris.core.loader.IrisData; -import com.volmit.iris.core.loader.IrisRegistrant; -import com.volmit.iris.engine.data.cache.AtomicCache; -import com.volmit.iris.engine.object.annotations.*; -import com.volmit.iris.util.collection.KList; -import com.volmit.iris.util.data.DataProvider; -import com.volmit.iris.util.json.JSONObject; -import com.volmit.iris.util.math.Position2; -import com.volmit.iris.util.math.RNG; -import com.volmit.iris.util.noise.CNG; -import com.volmit.iris.util.plugin.VolmitSender; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; -import org.bukkit.Material; -import org.bukkit.World.Environment; -import org.bukkit.block.data.BlockData; - -@Accessors(chain = true) -@AllArgsConstructor -@NoArgsConstructor -@Desc("Represents a dimension") -@Data -@EqualsAndHashCode(callSuper = false) -public class IrisDimension extends IrisRegistrant { - public static final BlockData STONE = Material.STONE.createBlockData(); - public static final BlockData WATER = Material.WATER.createBlockData(); - private final transient AtomicCache parallaxSize = new AtomicCache<>(); - private final transient AtomicCache rockLayerGenerator = new AtomicCache<>(); - private final transient AtomicCache fluidLayerGenerator = new AtomicCache<>(); - private final transient AtomicCache coordFracture = new AtomicCache<>(); - private final transient AtomicCache sinr = new AtomicCache<>(); - private final transient AtomicCache cosr = new AtomicCache<>(); - private final transient AtomicCache rad = new AtomicCache<>(); - private final transient AtomicCache featuresUsed = new AtomicCache<>(); - private final transient AtomicCache> strongholdsCache = new AtomicCache<>(); - @MinNumber(2) - @Required - @Desc("The human readable name of this dimension") - private String name = "A Dimension"; - @MinNumber(1) - @MaxNumber(2032) - @Desc("Maximum height at which players can be teleported to through gameplay.") - private int logicalHeight = 256; - @RegistryListResource(IrisJigsawStructure.class) - @Desc("If defined, Iris will place the given jigsaw structure where minecraft should place the overworld stronghold.") - private String stronghold; - @Desc("If set to true, Iris will remove chunks to allow visualizing cross sections of chunks easily") - private boolean debugChunkCrossSections = false; - @Desc("Vertically split up the biome palettes with 3 air blocks in between to visualize them") - private boolean explodeBiomePalettes = false; - @Desc("Studio Mode for testing different parts of the world") - private StudioMode studioMode = StudioMode.NORMAL; - @MinNumber(1) - @MaxNumber(16) - @Desc("Customize the palette height explosion") - private int explodeBiomePaletteSize = 3; - @MinNumber(2) - @MaxNumber(16) - @Desc("Every X/Z % debugCrossSectionsMod == 0 cuts the chunk") - private int debugCrossSectionsMod = 3; - @Desc("The average distance between strongholds") - private int strongholdJumpDistance = 1280; - @Desc("Define the maximum strongholds to place") - private int maxStrongholds = 14; - @Desc("Tree growth override settings") - private IrisTreeSettings treeSettings = new IrisTreeSettings(); - @Desc("Spawn Entities in this dimension over time. Iris will continually replenish these mobs just like vanilla does.") - @ArrayType(min = 1, type = String.class) - @RegistryListResource(IrisSpawner.class) - private KList entitySpawners = new KList<>(); - @Desc("Reference loot tables in this area") - private IrisLootReference loot = new IrisLootReference(); - @MinNumber(0) - @Desc("The version of this dimension. Changing this will stop users from accidentally upgrading (and breaking their worlds).") - private int version = 1; - @ArrayType(min = 1, type = IrisBlockDrops.class) - @Desc("Define custom block drops for this dimension") - private KList blockDrops = new KList<>(); - @Desc("Should bedrock be generated or not.") - private boolean bedrock = true; - @MinNumber(0) - @MaxNumber(1) - @Desc("The land chance. Up to 1.0 for total land or 0.0 for total sea") - private double landChance = 0.625; - @Desc("The placement style of regions") - private IrisGeneratorStyle regionStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); - @Desc("The placement style of land/sea") - private IrisGeneratorStyle continentalStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); - @Desc("The placement style of biomes") - private IrisGeneratorStyle landBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); - @Desc("The placement style of biomes") - private IrisGeneratorStyle shoreBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); - @Desc("The placement style of biomes") - private IrisGeneratorStyle seaBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); - @Desc("The placement style of biomes") - private IrisGeneratorStyle caveBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); - @Desc("Instead of filling objects with air, fills them with cobweb so you can see them") - private boolean debugSmartBore = false; - @Desc("Generate decorations or not") - private boolean decorate = true; - @Desc("Use post processing or not") - private boolean postProcessing = true; - @Desc("Add slabs in post processing") - private boolean postProcessingSlabs = true; - @Desc("Add painted walls in post processing") - private boolean postProcessingWalls = true; - @Desc("Carving configuration for the dimension") - private IrisCarving carving = new IrisCarving(); - @Desc("Configuration of fluid bodies such as rivers & lakes") - private IrisFluidBodies fluidBodies = new IrisFluidBodies(); - @Desc("forceConvertTo320Height") - private Boolean forceConvertTo320Height = false; - @Desc("The world environment") - private Environment environment = Environment.NORMAL; - @RegistryListResource(IrisRegion.class) - @Required - @ArrayType(min = 1, type = String.class) - @Desc("Define all of the regions to include in this dimension. Dimensions -> Regions -> Biomes -> Objects etc") - private KList regions = new KList<>(); - @ArrayType(min = 1, type = IrisJigsawStructurePlacement.class) - @Desc("Jigsaw structures") - private KList jigsawStructures = new KList<>(); - @Required - @MinNumber(0) - @MaxNumber(1024) - @Desc("The fluid height for this dimension") - private int fluidHeight = 63; - @Desc("Define the min and max Y bounds of this dimension. Please keep in mind that Iris internally generates from 0 to (max - min). \n\nFor example at -64 to 320, Iris is internally generating to 0 to 384, then on outputting chunks, it shifts it down by the min height (64 blocks). The default is -64 to 320. \n\nThe fluid height is placed at (fluid height + min height). So a fluid height of 63 would actually show up in the world at 1.") - private IrisRange dimensionHeight = new IrisRange(-64, 320); - @Desc("Enable smart vanilla height") - private boolean smartVanillaHeight = false; - @RegistryListResource(IrisBiome.class) - @Desc("Keep this either undefined or empty. Setting any biome name into this will force iris to only generate the specified biome. Great for testing.") - private String focus = ""; - @RegistryListResource(IrisRegion.class) - @Desc("Keep this either undefined or empty. Setting any region name into this will force iris to only generate the specified region. Great for testing.") - private String focusRegion = ""; - @MinNumber(0.0001) - @MaxNumber(512) - @Desc("Zoom in or out the biome size. Higher = bigger biomes") - private double biomeZoom = 5D; - @MinNumber(0) - @MaxNumber(360) - @Desc("You can rotate the input coordinates by an angle. This can make terrain appear more natural (less sharp corners and lines). This literally rotates the entire dimension by an angle. Hint: Try 12 degrees or something not on a 90 or 45 degree angle.") - private double dimensionAngleDeg = 0; - @Required - @Desc("Define the mode of this dimension (required!)") - private IrisDimensionMode mode = new IrisDimensionMode(); - @MinNumber(0) - @MaxNumber(8192) - @Desc("Coordinate fracturing applies noise to the input coordinates. This creates the 'iris swirls' and wavy features. The distance pushes these waves further into places they shouldnt be. This is a block value multiplier.") - private double coordFractureDistance = 20; - @MinNumber(0.0001) - @MaxNumber(512) - @Desc("Coordinate fracturing zoom. Higher = less frequent warping, Lower = more frequent and rapid warping / swirls.") - private double coordFractureZoom = 8; - @MinNumber(0.0001) - @MaxNumber(512) - @Desc("This zooms in the land space") - private double landZoom = 1; - @MinNumber(0.0001) - @MaxNumber(512) - @Desc("This zooms oceanic biomes") - private double seaZoom = 1; - @MinNumber(0.0001) - @MaxNumber(512) - @Desc("Zoom in continents") - private double continentZoom = 1; - @MinNumber(0.0001) - @MaxNumber(512) - @Desc("Change the size of regions") - private double regionZoom = 1; - @Desc("Disable this to stop placing objects, entities, features & updates") - private boolean useMantle = true; - @Desc("Prevent Leaf decay as if placed in creative mode") - private boolean preventLeafDecay = false; - @ArrayType(min = 1, type = IrisDepositGenerator.class) - @Desc("Define global deposit generators") - private KList deposits = new KList<>(); - @ArrayType(min = 1, type = IrisShapedGeneratorStyle.class) - @Desc("Overlay additional noise on top of the interoplated terrain.") - private KList overlayNoise = new KList<>(); - @Desc("If true, the spawner system has infinite energy. This is NOT recommended because it would allow for mobs to keep spawning over and over without a rate limit") - private boolean infiniteEnergy = false; - @MinNumber(0) - @MaxNumber(10000) - @Desc("This is the maximum energy you can have in a dimension") - private double maximumEnergy = 1000; - @MinNumber(0.0001) - @MaxNumber(512) - @Desc("The rock zoom mostly for zooming in on a wispy palette") - private double rockZoom = 5; - @Desc("The palette of blocks for 'stone'") - private IrisMaterialPalette rockPalette = new IrisMaterialPalette().qclear().qadd("stone"); - @Desc("The palette of blocks for 'water'") - private IrisMaterialPalette fluidPalette = new IrisMaterialPalette().qclear().qadd("water"); - @Desc("Remove cartographers so they do not crash the server (Iris worlds only)") - private boolean removeCartographersDueToCrash = true; - @Desc("Notify players of cancelled cartographer villager in this radius in blocks (set to -1 to disable, -2 for everyone)") - private int notifyPlayersOfCartographerCancelledRadius = 30; - @Desc("Collection of ores to be generated") - @ArrayType(type = IrisOreGenerator.class, min = 1) - private KList ores = new KList<>(); - @MinNumber(0) - @MaxNumber(318) - @Desc("The Subterrain Fluid Layer Height") - private int caveLavaHeight = 8; - - public int getMaxHeight() { - return (int) getDimensionHeight().getMax(); - } - - public int getMinHeight() { - return (int) getDimensionHeight().getMin(); - } - - public BlockData generateOres(int x, int y, int z, RNG rng, IrisData data) { - if (ores.isEmpty()) { - return null; - } - BlockData b = null; - for (IrisOreGenerator i : ores) { - - b = i.generate(x, y, z, rng, data); - if (b != null) { - return b; - } - } - return null; - } - - public KList getStrongholds(long seed) { - return strongholdsCache.aquire(() -> { - KList pos = new KList<>(); - int jump = strongholdJumpDistance; - RNG rng = new RNG((seed * 223) + 12945); - for (int i = 0; i < maxStrongholds + 1; i++) { - int m = i + 1; - pos.add(new Position2( - (int) ((rng.i(jump * i) + (jump * i)) * (rng.b() ? -1D : 1D)), - (int) ((rng.i(jump * i) + (jump * i)) * (rng.b() ? -1D : 1D)) - )); - } - - pos.remove(0); - - return pos; - }); - } - - public int getFluidHeight() { - return fluidHeight - (int) dimensionHeight.getMin(); - } - - public CNG getCoordFracture(RNG rng, int signature) { - return coordFracture.aquire(() -> - { - CNG coordFracture = CNG.signature(rng.nextParallelRNG(signature)); - coordFracture.scale(0.012 / coordFractureZoom); - return coordFracture; - }); - } - - public double getDimensionAngle() { - return rad.aquire(() -> Math.toRadians(dimensionAngleDeg)); - } - - public Environment getEnvironment() { - return environment; - } - - public IrisRange getDimensionHeight() { - return smartVanillaHeight ? new IrisRange(-64, 320) : dimensionHeight; - } - - public int getLogicalHeight() { - return smartVanillaHeight ? 256 : logicalHeight; - } - - public boolean hasFocusRegion() { - return !focusRegion.equals(""); - } - - public String getFocusRegion() { - return focusRegion; - } - - public double sinRotate() { - return sinr.aquire(() -> Math.sin(getDimensionAngle())); - } - - public double cosRotate() { - return cosr.aquire(() -> Math.cos(getDimensionAngle())); - } - - public KList getAllRegions(DataProvider g) { - KList r = new KList<>(); - - for (String i : getRegions()) { - r.add(g.getData().getRegionLoader().load(i)); - } - - return r; - } - - public KList getAllAnyRegions() { - KList r = new KList<>(); - - for (String i : getRegions()) { - r.add(IrisData.loadAnyRegion(i)); - } - - return r; - } - - public KList getAllBiomes(DataProvider g) { - return g.getData().getBiomeLoader().loadAll(g.getData().getBiomeLoader().getPossibleKeys()); - } - - public KList getAllAnyBiomes() { - KList r = new KList<>(); - - for (IrisRegion i : getAllAnyRegions()) { - if (i == null) { - continue; - } - - r.addAll(i.getAllAnyBiomes()); - } - - return r; - } - - public IrisGeneratorStyle getBiomeStyle(InferredType type) { - switch (type) { - case CAVE: - return caveBiomeStyle; - case LAND: - return landBiomeStyle; - case SEA: - return seaBiomeStyle; - case SHORE: - return shoreBiomeStyle; - default: - break; - } - - return landBiomeStyle; - } - - @Override - public String getFolderName() { - return "dimensions"; - } - - @Override - public String getTypeName() { - return "Dimension"; - } - - @Override - public void scanForErrors(JSONObject p, VolmitSender sender) { - - } -} +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2022 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +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; +import com.volmit.iris.util.noise.CNG; +import com.volmit.iris.util.plugin.VolmitSender; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; +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 +@Desc("Represents a dimension") +@Data +@EqualsAndHashCode(callSuper = false) +public class IrisDimension extends IrisRegistrant { + public static final BlockData STONE = Material.STONE.createBlockData(); + public static final BlockData WATER = Material.WATER.createBlockData(); + private static final String DP_OVERWORLD_DEFAULT = """ + { + "ambient_light": 0.0, + "bed_works": true, + "coordinate_scale": 1.0, + "effects": "minecraft:overworld", + "has_ceiling": false, + "has_raids": true, + "has_skylight": true, + "infiniburn": "#minecraft:infiniburn_overworld", + "monster_spawn_block_light_limit": 0, + "monster_spawn_light_level": { + "type": "minecraft:uniform", + "value": { + "max_inclusive": 7, + "min_inclusive": 0 + } + }, + "natural": true, + "piglin_safe": false, + "respawn_anchor_works": false, + "ultrawarm": false + }"""; + + private static final String DP_NETHER_DEFAULT = """ + { + "ambient_light": 0.1, + "bed_works": false, + "coordinate_scale": 8.0, + "effects": "minecraft:the_nether", + "fixed_time": 18000, + "has_ceiling": true, + "has_raids": false, + "has_skylight": false, + "infiniburn": "#minecraft:infiniburn_nether", + "monster_spawn_block_light_limit": 15, + "monster_spawn_light_level": 7, + "natural": false, + "piglin_safe": true, + "respawn_anchor_works": true, + "ultrawarm": true + }"""; + + private static final String DP_END_DEFAULT = """ + { + "ambient_light": 0.0, + "bed_works": false, + "coordinate_scale": 1.0, + "effects": "minecraft:the_end", + "fixed_time": 6000, + "has_ceiling": false, + "has_raids": true, + "has_skylight": false, + "infiniburn": "#minecraft:infiniburn_end", + "monster_spawn_block_light_limit": 0, + "monster_spawn_light_level": { + "type": "minecraft:uniform", + "value": { + "max_inclusive": 7, + "min_inclusive": 0 + } + }, + "natural": false, + "piglin_safe": false, + "respawn_anchor_works": false, + "ultrawarm": false + }"""; + private final transient AtomicCache parallaxSize = new AtomicCache<>(); + private final transient AtomicCache rockLayerGenerator = new AtomicCache<>(); + private final transient AtomicCache fluidLayerGenerator = new AtomicCache<>(); + private final transient AtomicCache coordFracture = new AtomicCache<>(); + private final transient AtomicCache sinr = new AtomicCache<>(); + private final transient AtomicCache cosr = new AtomicCache<>(); + private final transient AtomicCache rad = new AtomicCache<>(); + private final transient AtomicCache featuresUsed = new AtomicCache<>(); + private final transient AtomicCache> strongholdsCache = new AtomicCache<>(); + @MinNumber(2) + @Required + @Desc("The human readable name of this dimension") + private String name = "A Dimension"; + @MinNumber(1) + @MaxNumber(2032) + @Desc("Maximum height at which players can be teleported to through gameplay.") + private int logicalHeight = 256; + @Desc("Maximum height at which players can be teleported to through gameplay.") + private int logicalHeightEnd = 256; + @Desc("Maximum height at which players can be teleported to through gameplay.") + private int logicalHeightNether = 256; + @RegistryListResource(IrisJigsawStructure.class) + @Desc("If defined, Iris will place the given jigsaw structure where minecraft should place the overworld stronghold.") + private String stronghold; + @Desc("If set to true, Iris will remove chunks to allow visualizing cross sections of chunks easily") + private boolean debugChunkCrossSections = false; + @Desc("Vertically split up the biome palettes with 3 air blocks in between to visualize them") + private boolean explodeBiomePalettes = false; + @Desc("Studio Mode for testing different parts of the world") + private StudioMode studioMode = StudioMode.NORMAL; + @MinNumber(1) + @MaxNumber(16) + @Desc("Customize the palette height explosion") + private int explodeBiomePaletteSize = 3; + @MinNumber(2) + @MaxNumber(16) + @Desc("Every X/Z % debugCrossSectionsMod == 0 cuts the chunk") + private int debugCrossSectionsMod = 3; + @Desc("The average distance between strongholds") + private int strongholdJumpDistance = 1280; + @Desc("Define the maximum strongholds to place") + private int maxStrongholds = 14; + @Desc("Tree growth override settings") + private IrisTreeSettings treeSettings = new IrisTreeSettings(); + @Desc("Spawn Entities in this dimension over time. Iris will continually replenish these mobs just like vanilla does.") + @ArrayType(min = 1, type = String.class) + @RegistryListResource(IrisSpawner.class) + private KList entitySpawners = new KList<>(); + @Desc("Reference loot tables in this area") + private IrisLootReference loot = new IrisLootReference(); + @MinNumber(0) + @Desc("The version of this dimension. Changing this will stop users from accidentally upgrading (and breaking their worlds).") + private int version = 1; + @ArrayType(min = 1, type = IrisBlockDrops.class) + @Desc("Define custom block drops for this dimension") + private KList blockDrops = new KList<>(); + @Desc("Should bedrock be generated or not.") + private boolean bedrock = true; + @MinNumber(0) + @MaxNumber(1) + @Desc("The land chance. Up to 1.0 for total land or 0.0 for total sea") + private double landChance = 0.625; + @Desc("The placement style of regions") + private IrisGeneratorStyle regionStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); + @Desc("The placement style of land/sea") + private IrisGeneratorStyle continentalStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); + @Desc("The placement style of biomes") + private IrisGeneratorStyle landBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); + @Desc("The placement style of biomes") + private IrisGeneratorStyle shoreBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); + @Desc("The placement style of biomes") + private IrisGeneratorStyle seaBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); + @Desc("The placement style of biomes") + private IrisGeneratorStyle caveBiomeStyle = NoiseStyle.CELLULAR_IRIS_DOUBLE.style(); + @Desc("Instead of filling objects with air, fills them with cobweb so you can see them") + private boolean debugSmartBore = false; + @Desc("Generate decorations or not") + private boolean decorate = true; + @Desc("Use post processing or not") + private boolean postProcessing = true; + @Desc("Add slabs in post processing") + private boolean postProcessingSlabs = true; + @Desc("Add painted walls in post processing") + private boolean postProcessingWalls = true; + @Desc("Carving configuration for the dimension") + private IrisCarving carving = new IrisCarving(); + @Desc("Configuration of fluid bodies such as rivers & lakes") + private IrisFluidBodies fluidBodies = new IrisFluidBodies(); + @Desc("forceConvertTo320Height") + private Boolean forceConvertTo320Height = false; + @Desc("The world environment") + private Environment environment = Environment.NORMAL; + @RegistryListResource(IrisRegion.class) + @Required + @ArrayType(min = 1, type = String.class) + @Desc("Define all of the regions to include in this dimension. Dimensions -> Regions -> Biomes -> Objects etc") + private KList regions = new KList<>(); + @ArrayType(min = 1, type = IrisJigsawStructurePlacement.class) + @Desc("Jigsaw structures") + private KList jigsawStructures = new KList<>(); + @Desc("The jigsaw structure divisor to use when generating missing jigsaw placement values") + private double jigsawStructureDivisor = 18; + @Required + @MinNumber(0) + @MaxNumber(1024) + @Desc("The fluid height for this dimension") + private int fluidHeight = 63; + @Desc("Define the min and max Y bounds of this dimension. Please keep in mind that Iris internally generates from 0 to (max - min). \n\nFor example at -64 to 320, Iris is internally generating to 0 to 384, then on outputting chunks, it shifts it down by the min height (64 blocks). The default is -64 to 320. \n\nThe fluid height is placed at (fluid height + min height). So a fluid height of 63 would actually show up in the world at 1.") + private IrisRange dimensionHeight = new IrisRange(-64, 320); + @Desc("Define the min and max Y bounds of this dimension. Please keep in mind that Iris internally generates from 0 to (max - min). \n\nFor example at -64 to 320, Iris is internally generating to 0 to 384, then on outputting chunks, it shifts it down by the min height (64 blocks). The default is -64 to 320. \n\nThe fluid height is placed at (fluid height + min height). So a fluid height of 63 would actually show up in the world at 1.") + private IrisRange dimensionHeightEnd = new IrisRange(-64, 320); + @Desc("Define the min and max Y bounds of this dimension. Please keep in mind that Iris internally generates from 0 to (max - min). \n\nFor example at -64 to 320, Iris is internally generating to 0 to 384, then on outputting chunks, it shifts it down by the min height (64 blocks). The default is -64 to 320. \n\nThe fluid height is placed at (fluid height + min height). So a fluid height of 63 would actually show up in the world at 1.") + private IrisRange dimensionHeightNether = new IrisRange(-64, 320); + @Desc("Enable smart vanilla height") + private boolean smartVanillaHeight = false; + @RegistryListResource(IrisBiome.class) + @Desc("Keep this either undefined or empty. Setting any biome name into this will force iris to only generate the specified biome. Great for testing.") + private String focus = ""; + @RegistryListResource(IrisRegion.class) + @Desc("Keep this either undefined or empty. Setting any region name into this will force iris to only generate the specified region. Great for testing.") + private String focusRegion = ""; + @MinNumber(0.0001) + @MaxNumber(512) + @Desc("Zoom in or out the biome size. Higher = bigger biomes") + private double biomeZoom = 5D; + @MinNumber(0) + @MaxNumber(360) + @Desc("You can rotate the input coordinates by an angle. This can make terrain appear more natural (less sharp corners and lines). This literally rotates the entire dimension by an angle. Hint: Try 12 degrees or something not on a 90 or 45 degree angle.") + private double dimensionAngleDeg = 0; + @Required + @Desc("Define the mode of this dimension (required!)") + private IrisDimensionMode mode = new IrisDimensionMode(); + @MinNumber(0) + @MaxNumber(8192) + @Desc("Coordinate fracturing applies noise to the input coordinates. This creates the 'iris swirls' and wavy features. The distance pushes these waves further into places they shouldnt be. This is a block value multiplier.") + private double coordFractureDistance = 20; + @MinNumber(0.0001) + @MaxNumber(512) + @Desc("Coordinate fracturing zoom. Higher = less frequent warping, Lower = more frequent and rapid warping / swirls.") + private double coordFractureZoom = 8; + @MinNumber(0.0001) + @MaxNumber(512) + @Desc("This zooms in the land space") + private double landZoom = 1; + @MinNumber(0.0001) + @MaxNumber(512) + @Desc("This zooms oceanic biomes") + private double seaZoom = 1; + @MinNumber(0.0001) + @MaxNumber(512) + @Desc("Zoom in continents") + private double continentZoom = 1; + @MinNumber(0.0001) + @MaxNumber(512) + @Desc("Change the size of regions") + private double regionZoom = 1; + @Desc("Disable this to stop placing objects, entities, features & updates") + private boolean useMantle = true; + @Desc("Prevent Leaf decay as if placed in creative mode") + private boolean preventLeafDecay = false; + @ArrayType(min = 1, type = IrisDepositGenerator.class) + @Desc("Define global deposit generators") + private KList deposits = new KList<>(); + @ArrayType(min = 1, type = IrisShapedGeneratorStyle.class) + @Desc("Overlay additional noise on top of the interoplated terrain.") + private KList overlayNoise = new KList<>(); + @Desc("If true, the spawner system has infinite energy. This is NOT recommended because it would allow for mobs to keep spawning over and over without a rate limit") + private boolean infiniteEnergy = false; + @MinNumber(0) + @MaxNumber(10000) + @Desc("This is the maximum energy you can have in a dimension") + private double maximumEnergy = 1000; + @MinNumber(0.0001) + @MaxNumber(512) + @Desc("The rock zoom mostly for zooming in on a wispy palette") + private double rockZoom = 5; + @Desc("The palette of blocks for 'stone'") + private IrisMaterialPalette rockPalette = new IrisMaterialPalette().qclear().qadd("stone"); + @Desc("The palette of blocks for 'water'") + private IrisMaterialPalette fluidPalette = new IrisMaterialPalette().qclear().qadd("water"); + @Desc("Remove cartographers so they do not crash the server (Iris worlds only)") + private boolean removeCartographersDueToCrash = true; + @Desc("Notify players of cancelled cartographer villager in this radius in blocks (set to -1 to disable, -2 for everyone)") + private int notifyPlayersOfCartographerCancelledRadius = 30; + @Desc("Collection of ores to be generated") + @ArrayType(type = IrisOreGenerator.class, min = 1) + private KList ores = new KList<>(); + @MinNumber(0) + @MaxNumber(318) + @Desc("The Subterrain Fluid Layer Height") + private int caveLavaHeight = 8; + + public int getMaxHeight() { + return (int) getDimensionHeight().getMax(); + } + + public int getMinHeight() { + return (int) getDimensionHeight().getMin(); + } + + public BlockData generateOres(int x, int y, int z, RNG rng, IrisData data) { + if (ores.isEmpty()) { + return null; + } + BlockData b = null; + for (IrisOreGenerator i : ores) { + + b = i.generate(x, y, z, rng, data); + if (b != null) { + return b; + } + } + return null; + } + + public KList getStrongholds(long seed) { + return strongholdsCache.aquire(() -> { + KList pos = new KList<>(); + int jump = strongholdJumpDistance; + RNG rng = new RNG((seed * 223) + 12945); + for (int i = 0; i < maxStrongholds + 1; i++) { + int m = i + 1; + pos.add(new Position2( + (int) ((rng.i(jump * i) + (jump * i)) * (rng.b() ? -1D : 1D)), + (int) ((rng.i(jump * i) + (jump * i)) * (rng.b() ? -1D : 1D)) + )); + } + + pos.remove(0); + + return pos; + }); + } + + public int getFluidHeight() { + return fluidHeight - (int) dimensionHeight.getMin(); + } + + public CNG getCoordFracture(RNG rng, int signature) { + return coordFracture.aquire(() -> + { + CNG coordFracture = CNG.signature(rng.nextParallelRNG(signature)); + coordFracture.scale(0.012 / coordFractureZoom); + return coordFracture; + }); + } + + public double getDimensionAngle() { + return rad.aquire(() -> Math.toRadians(dimensionAngleDeg)); + } + + public Environment getEnvironment() { + return environment; + } + + public boolean hasFocusRegion() { + return !focusRegion.equals(""); + } + + public String getFocusRegion() { + return focusRegion; + } + + public double sinRotate() { + return sinr.aquire(() -> Math.sin(getDimensionAngle())); + } + + public double cosRotate() { + return cosr.aquire(() -> Math.cos(getDimensionAngle())); + } + + public KList getAllRegions(DataProvider g) { + KList r = new KList<>(); + + for (String i : getRegions()) { + r.add(g.getData().getRegionLoader().load(i)); + } + + return r; + } + + public KList getAllAnyRegions() { + KList r = new KList<>(); + + for (String i : getRegions()) { + r.add(IrisData.loadAnyRegion(i)); + } + + return r; + } + + public KList getAllBiomes(DataProvider g) { + return g.getData().getBiomeLoader().loadAll(g.getData().getBiomeLoader().getPossibleKeys()); + } + + public KList getAllAnyBiomes() { + KList r = new KList<>(); + + for (IrisRegion i : getAllAnyRegions()) { + if (i == null) { + continue; + } + + r.addAll(i.getAllAnyBiomes()); + } + + return r; + } + + public IrisGeneratorStyle getBiomeStyle(InferredType type) { + switch (type) { + case CAVE: + return caveBiomeStyle; + case LAND: + return landBiomeStyle; + case SEA: + return seaBiomeStyle; + case SHORE: + return shoreBiomeStyle; + default: + break; + } + + return landBiomeStyle; + } + + public boolean installDataPack(IDataFixer fixer, DataProvider data, File datapacks, double ultimateMaxHeight, double ultimateMinHeight) { + 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 (!dimensionHeight.equals(new IrisRange(-64, 320)) && this.name.equalsIgnoreCase("overworld")) { + Iris.verbose(" Installing Data Pack Dimension Types: \"minecraft:overworld\", \"minecraft:the_nether\", \"minecraft:the_end\""); + dimensionHeight.setMax(ultimateMaxHeight); + dimensionHeight.setMin(ultimateMinHeight); + changed = writeDimensionType(fixer, changed, datapacks); + } + + 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"; + } + + @Override + public String getTypeName() { + return "Dimension"; + } + + @Override + public void scanForErrors(JSONObject p, VolmitSender sender) { + + } + + public boolean writeDimensionType(IDataFixer fixer, boolean changed, File datapacks) { + File dimTypeOverworld = new File(datapacks, "iris/data/minecraft/dimension_type/overworld.json"); + if (!dimTypeOverworld.exists()) + changed = true; + dimTypeOverworld.getParentFile().mkdirs(); + try { + IO.writeAll(dimTypeOverworld, generateDatapackJsonOverworld(fixer)); + } catch (IOException e) { + Iris.reportError(e); + e.printStackTrace(); + } + + + File dimTypeNether = new File(datapacks, "iris/data/minecraft/dimension_type/the_nether.json"); + if (!dimTypeNether.exists()) + changed = true; + dimTypeNether.getParentFile().mkdirs(); + try { + IO.writeAll(dimTypeNether, generateDatapackJsonNether(fixer)); + } catch (IOException e) { + Iris.reportError(e); + e.printStackTrace(); + } + + + File dimTypeEnd = new File(datapacks, "iris/data/minecraft/dimension_type/the_end.json"); + if (!dimTypeEnd.exists()) + changed = true; + dimTypeEnd.getParentFile().mkdirs(); + try { + IO.writeAll(dimTypeEnd, generateDatapackJsonEnd(fixer)); + } catch (IOException e) { + Iris.reportError(e); + e.printStackTrace(); + } + + return changed; + } + + private String generateDatapackJsonOverworld(IDataFixer fixer) { + JSONObject obj = new JSONObject(DP_OVERWORLD_DEFAULT); + obj.put("min_y", dimensionHeight.getMin()); + obj.put("height", dimensionHeight.getMax() - dimensionHeight.getMin()); + obj.put("logical_height", logicalHeight); + return fixer.fixDimension(obj).toString(4); + } + + private String generateDatapackJsonNether(IDataFixer fixer) { + JSONObject obj = new JSONObject(DP_NETHER_DEFAULT); + obj.put("min_y", dimensionHeightNether.getMin()); + obj.put("height", dimensionHeightNether.getMax() - dimensionHeightNether.getMin()); + obj.put("logical_height", logicalHeightNether); + return fixer.fixDimension(obj).toString(4); + } + + private String generateDatapackJsonEnd(IDataFixer fixer) { + JSONObject obj = new JSONObject(DP_END_DEFAULT); + obj.put("min_y", dimensionHeightEnd.getMin()); + obj.put("height", dimensionHeightEnd.getMax() - dimensionHeightEnd.getMin()); + obj.put("logical_height", logicalHeightEnd); + return fixer.fixDimension(obj).toString(4); + } +} diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java b/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java index 66f6ec3ac..6f732f449 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java @@ -454,21 +454,16 @@ public class IrisEntity extends IrisRegistrant { return ae.get(); } - if (isSpecialType() && Iris.linkMythicMobs.isEnabled()) { + if (isSpecialType()) { if (specialType.toLowerCase().startsWith("mythicmobs:")) { return Iris.linkMythicMobs.spawnMob(specialType.substring(11), at); } else { Iris.warn("Invalid mob type to spawn: '" + specialType + "'!"); return null; } - } else { - if (isSpecialType()) { - Iris.warn("MythicMobs is not enabled, falling back to: " + type + "'!"); - } } - return INMS.get().spawnEntity(at, getType(), getReason()); } diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisJigsawStructurePlacement.java b/core/src/main/java/com/volmit/iris/engine/object/IrisJigsawStructurePlacement.java index b65a7d2c5..40603ce85 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisJigsawStructurePlacement.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisJigsawStructurePlacement.java @@ -88,21 +88,21 @@ public class IrisJigsawStructurePlacement implements IRare { return (int) Math.ceil(blocks / 16d); } - private void calculateMissing(long seed) { + private void calculateMissing(double divisor, long seed) { seed = seed + hashCode(); if (salt == 0) { salt = new RNG(seed).nextLong(Integer.MIN_VALUE, Integer.MAX_VALUE); } if (separation == -1 || spacing == -1) { - separation = (int) Math.round(rarity / 15d); + separation = (int) Math.round(rarity / divisor); spacing = new RNG(seed).nextInt(separation, separation * 2); } } @ChunkCoordinates - public boolean shouldPlace(long seed, int x, int z) { - calculateMissing(seed); + public boolean shouldPlace(double divisor, long seed, int x, int z) { + calculateMissing(divisor, seed); if (separation > spacing) { separation = spacing; Iris.warn("JigsawStructurePlacement: separation must be less than or equal to spacing"); diff --git a/core/src/main/java/com/volmit/iris/engine/platform/BukkitChunkGenerator.java b/core/src/main/java/com/volmit/iris/engine/platform/BukkitChunkGenerator.java index ad0f5c86a..ce0bebd74 100644 --- a/core/src/main/java/com/volmit/iris/engine/platform/BukkitChunkGenerator.java +++ b/core/src/main/java/com/volmit/iris/engine/platform/BukkitChunkGenerator.java @@ -21,7 +21,6 @@ package com.volmit.iris.engine.platform; import com.volmit.iris.Iris; import com.volmit.iris.core.loader.IrisData; import com.volmit.iris.core.nms.INMS; -import com.volmit.iris.core.safeguard.IrisSafeguard; import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.engine.IrisEngine; import com.volmit.iris.engine.data.chunk.TerrainChunk; @@ -33,7 +32,6 @@ import com.volmit.iris.engine.object.StudioMode; import com.volmit.iris.engine.platform.studio.StudioGenerator; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.data.IrisBiomeStorage; -import com.volmit.iris.util.format.C; import com.volmit.iris.util.hunk.Hunk; import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder; import com.volmit.iris.util.hunk.view.ChunkDataHunkHolder; @@ -265,15 +263,6 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun } private Engine getEngine(WorldInfo world) { -// if (!IrisSafeguard.instance.acceptUnstable && IrisSafeguard.instance.unstablemode) { -// Iris.info(C.RED + "------------------------------------------------------------"); -// Iris.info(C.DARK_RED + "Cancelled World Loading of " + world.getName() + "!"); -// Iris.info(C.RED + "World loading has been disabled until the incompatibility is resolved."); -// Iris.info(C.DARK_RED + "Alternatively, go to plugins/iris/settings.json and set ignoreBootMode to true."); -// Iris.info(C.RED + "------------------------------------------------------------"); -// return null; -// } - if (setup.get()) { return getEngine(); } diff --git a/core/src/main/java/com/volmit/iris/util/decree/specialhandlers/NullableBiomeHandler.java b/core/src/main/java/com/volmit/iris/util/decree/specialhandlers/NullableBiomeHandler.java deleted file mode 100644 index 8af2fcfc7..000000000 --- a/core/src/main/java/com/volmit/iris/util/decree/specialhandlers/NullableBiomeHandler.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.volmit.iris.util.decree.specialhandlers; - -import com.volmit.iris.engine.object.IrisBiome; -import com.volmit.iris.util.decree.exceptions.DecreeParsingException; -import com.volmit.iris.util.decree.handlers.BiomeHandler; -import com.volmit.iris.util.decree.handlers.PlayerHandler; -import org.bukkit.entity.Player; - -public class NullableBiomeHandler extends BiomeHandler { - - @Override - public IrisBiome parse(String in, boolean force) throws DecreeParsingException { - return getPossibilities(in).stream().filter((i) -> toString(i).equalsIgnoreCase(in)).findFirst().orElse(null); - } -} diff --git a/core/src/main/java/com/volmit/iris/util/decree/specialhandlers/NullableRegionHandler.java b/core/src/main/java/com/volmit/iris/util/decree/specialhandlers/NullableRegionHandler.java deleted file mode 100644 index f2c9c1665..000000000 --- a/core/src/main/java/com/volmit/iris/util/decree/specialhandlers/NullableRegionHandler.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.volmit.iris.util.decree.specialhandlers; - -import com.volmit.iris.engine.object.IrisBiome; -import com.volmit.iris.engine.object.IrisRegion; -import com.volmit.iris.util.decree.exceptions.DecreeParsingException; -import com.volmit.iris.util.decree.handlers.BiomeHandler; -import com.volmit.iris.util.decree.handlers.RegionHandler; - -import javax.swing.plaf.synth.Region; - -public class NullableRegionHandler extends RegionHandler { - - @Override - public IrisRegion parse(String in, boolean force) throws DecreeParsingException { - return getPossibilities(in).stream().filter((i) -> toString(i).equalsIgnoreCase(in)).findFirst().orElse(null); - } -} diff --git a/core/src/main/java/com/volmit/iris/util/nbt/mca/Chunk.java b/core/src/main/java/com/volmit/iris/util/nbt/mca/Chunk.java index 7fbe2e106..f74cdcf7f 100644 --- a/core/src/main/java/com/volmit/iris/util/nbt/mca/Chunk.java +++ b/core/src/main/java/com/volmit/iris/util/nbt/mca/Chunk.java @@ -20,9 +20,7 @@ package com.volmit.iris.util.nbt.mca; import com.volmit.iris.Iris; import com.volmit.iris.core.nms.INMS; -import com.volmit.iris.core.tools.IrisWorldDump; import com.volmit.iris.util.collection.KMap; -import com.volmit.iris.util.format.Form; import com.volmit.iris.util.nbt.io.NBTDeserializer; import com.volmit.iris.util.nbt.io.NBTSerializer; import com.volmit.iris.util.nbt.io.NamedTag; @@ -59,8 +57,6 @@ public class Chunk { private ListTag> postProcessing; private String status; private CompoundTag structures; - private int d; - private int f; Chunk(int lastMCAUpdate) { this.lastMCAUpdate = lastMCAUpdate; @@ -73,8 +69,6 @@ public class Chunk { */ public Chunk(CompoundTag data) { this.data = data; - d = 0; - f = 0; initReferences(ALL_DATA); setStatus("full"); } @@ -156,8 +150,8 @@ public class Chunk { if ((loadFlags & STRUCTURES) != 0) { structures = level.getCompoundTag("Structures"); } - if ((loadFlags & (BLOCK_LIGHTS | BLOCK_STATES | SKY_LIGHT)) != 0 && level.containsKey("sections")) { - for (CompoundTag section : level.getListTag("sections").asCompoundTagList()) { + if ((loadFlags & (BLOCK_LIGHTS | BLOCK_STATES | SKY_LIGHT)) != 0 && level.containsKey("Sections")) { + for (CompoundTag section : level.getListTag("Sections").asCompoundTagList()) { int sectionIndex = section.getByte("Y"); if (sectionIndex > 15 || sectionIndex < 0) { continue; diff --git a/core/src/main/java/com/volmit/iris/util/nbt/mca/Section.java b/core/src/main/java/com/volmit/iris/util/nbt/mca/Section.java index 713d7ee1f..f58f74faf 100644 --- a/core/src/main/java/com/volmit/iris/util/nbt/mca/Section.java +++ b/core/src/main/java/com/volmit/iris/util/nbt/mca/Section.java @@ -37,17 +37,12 @@ public class Section { public Section(CompoundTag sectionRoot, int dataVersion, long loadFlags) { data = sectionRoot; - //ListTag rawPalette = sectionRoot.getListTag("palette"); - ListTag rawPalette = sectionRoot.getCompoundTag("biomes").getListTag("palette"); + ListTag rawPalette = sectionRoot.getListTag("Palette"); if (rawPalette == null) { return; } palette = INMS.get().createPalette(); - try { - palette.readFromSection(sectionRoot); - } catch (Exception e) { - e.printStackTrace(); - } + palette.readFromSection(sectionRoot); ByteArrayTag blockLight = sectionRoot.getByteArrayTag("BlockLight"); ByteArrayTag skyLight = sectionRoot.getByteArrayTag("SkyLight"); this.blockLight = blockLight != null ? blockLight.getValue() : null; diff --git a/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCABitStorageLongArray.java b/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCABitStorage.java similarity index 96% rename from core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCABitStorageLongArray.java rename to core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCABitStorage.java index e2d9e157f..b3413bf5b 100644 --- a/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCABitStorageLongArray.java +++ b/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCABitStorage.java @@ -20,10 +20,9 @@ package com.volmit.iris.util.nbt.mca.palette; import org.apache.commons.lang3.Validate; -import java.util.BitSet; import java.util.function.IntConsumer; -public class MCABitStorageLongArray { +public class MCABitStorage { private static final int[] MAGIC = new int[]{ -1, -1, 0, Integer.MIN_VALUE, 0, 0, 1431655765, 1431655765, 0, Integer.MIN_VALUE, 0, 1, 858993459, 858993459, 0, 715827882, 715827882, 0, 613566756, 613566756, @@ -62,11 +61,11 @@ public class MCABitStorageLongArray { private final int divideShift; - public MCABitStorageLongArray(int bits, int length) { + public MCABitStorage(int bits, int length) { this(bits, length, null); } - public MCABitStorageLongArray(int bits, int length, long[] data) { + public MCABitStorage(int bits, int length, long[] data) { Validate.inclusiveBetween(1L, 32L, bits); this.size = length; this.bits = bits; diff --git a/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCABitStorageByteArray.java b/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCABitStorageByteArray.java deleted file mode 100644 index 22a073314..000000000 --- a/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCABitStorageByteArray.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Iris is a World Generator for Minecraft Bukkit Servers - * Copyright (c) 2022 Arcane Arts (Volmit Software) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * abyte with this program. If not, see . - */ - -package com.volmit.iris.util.nbt.mca.palette; - -import org.apache.commons.lang3.Validate; -// todo Cool idea but im way to dumb for this for now -public class MCABitStorageByteArray { - private final byte[] data; - private final int bits; - private final int mask; - private final int size; - private final int valuesPerByte; - - private final int divideMul; - private final int divideAdd; - private final int divideShift; - - public MCABitStorageByteArray(int bits, int length) { - this(bits, length, null); - } - - public MCABitStorageByteArray(int bits, int length, byte[] data) { - Validate.inclusiveBetween(1L, 8L, bits); // Ensure bits are between 1 and 8 - this.size = length; - this.bits = bits; - this.mask = (1 << bits) - 1; - this.valuesPerByte = 8 / bits; - int[] divisionParams = computeDivisionParameters(this.valuesPerByte); - this.divideMul = divisionParams[0]; - this.divideAdd = divisionParams[1]; - this.divideShift = divisionParams[2]; - int numBytes = (length + this.valuesPerByte - 1) / this.valuesPerByte; - if (data != null) { - if (data.length != numBytes) - throw new IllegalArgumentException("Data array length does not match the required size."); - this.data = data; - } else { - this.data = new byte[numBytes]; - } - } - - private int[] computeDivisionParameters(int denom) { - long two32 = 1L << 32; - long magic = two32 / denom; - int shift = 0; - while ((1L << (shift + 32)) < magic * denom) { - shift++; - } - return new int[]{(int) magic, 0, shift}; - } - - private int cellIndex(int index) { - long indexLong = Integer.toUnsignedLong(this.divideMul); - long addLong = Integer.toUnsignedLong(this.divideAdd); - return (int) ((index * indexLong + addLong) >>> 32 >>> this.divideShift); - } - - public int getAndSet(int index, int newValue) { - Validate.inclusiveBetween(0L, (this.size - 1), index); - Validate.inclusiveBetween(0L, this.mask, newValue); - int byteIndex = cellIndex(index); - int bitOffset = (index - byteIndex * this.valuesPerByte) * this.bits; - int currentValue = (this.data[byteIndex] >> bitOffset) & this.mask; - this.data[byteIndex] = (byte) ((this.data[byteIndex] & ~(this.mask << bitOffset)) | (newValue & this.mask) << bitOffset); - return currentValue; - } - - public void set(int index, int value) { - Validate.inclusiveBetween(0L, (this.size - 1), index); - Validate.inclusiveBetween(0L, this.mask, value); - int byteIndex = cellIndex(index); - int bitOffset = (index - byteIndex * this.valuesPerByte) * this.bits; - this.data[byteIndex] = (byte) ((this.data[byteIndex] & ~(this.mask << bitOffset)) | (value & this.mask) << bitOffset); - } - - public int get(int index) { - Validate.inclusiveBetween(0L, (this.size - 1), index); - int byteIndex = cellIndex(index); - int bitOffset = (index - byteIndex * this.valuesPerByte) * this.bits; - return (this.data[byteIndex] >> bitOffset) & this.mask; - } - - public byte[] getRaw() { - return this.data; - } - - public int getSize() { - return this.size; - } - - public int getBits() { - return this.bits; - } -} - - diff --git a/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCAPalettedContainer.java b/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCAPalettedContainer.java index 4af6e234e..941c37447 100644 --- a/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCAPalettedContainer.java +++ b/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCAPalettedContainer.java @@ -41,8 +41,7 @@ public class MCAPalettedContainer implements MCAPaletteResize { private final T defaultValue; - // Todo multiple storage systems cause long isnt the only one? - protected MCABitStorageLongArray storage; + protected MCABitStorage storage; private MCAPalette palette; @@ -75,11 +74,11 @@ public class MCAPalettedContainer implements MCAPaletteResize { this.bits = MCAMth.ceillog2(this.registry.size()); } this.palette.idFor(this.defaultValue); - this.storage = new MCABitStorageLongArray(this.bits, 4096); + this.storage = new MCABitStorage(this.bits, 4096); } public int onResize(int var0, T var1) { - MCABitStorageLongArray var2 = this.storage; + MCABitStorage var2 = this.storage; MCAPalette var3 = this.palette; setBits(var0); for (int var4 = 0; var4 < var2.getSize(); var4++) { @@ -122,12 +121,6 @@ public class MCAPalettedContainer implements MCAPaletteResize { T var1 = this.palette.valueFor(this.storage.get(var0)); return (var1 == null) ? this.defaultValue : var1; } - /** - /** - * Reads and processes block data from encoded byte arrays. - * @param var0 BlockID Strings - List of block types identified by strings. - * @param var1 Encoded Locations - Long array containing compactly encoded block IDs, representing sequential block positions within a chunk. - */ public void read(ListTag var0, long[] var1) { int var2 = Math.max(4, MCAMth.ceillog2(var0.size())); @@ -138,69 +131,18 @@ public class MCAPalettedContainer implements MCAPaletteResize { if (this.palette == this.globalPalette) { MCAPalette var4 = new MCAHashMapPalette<>(this.registry, var2, this.dummyPaletteResize, this.reader, this.writer); var4.read(var0); - MCABitStorageLongArray var5 = new MCABitStorageLongArray(var2, 4096, var1); + MCABitStorage var5 = new MCABitStorage(var2, 4096, var1); for (int var6 = 0; var6 < 4096; var6++) this.storage.set(var6, this.globalPalette.idFor(var4.valueFor(var5.get(var6)))); } else if (var3 == this.bits) { System.arraycopy(var1, 0, this.storage.getRaw(), 0, var1.length); } else { - MCABitStorageLongArray var4 = new MCABitStorageLongArray(var3, 4096, var1); + MCABitStorage var4 = new MCABitStorage(var3, 4096, var1); for (int var5 = 0; var5 < 4096; var5++) this.storage.set(var5, var4.get(var5)); } } - /** - * Reads and processes block data from encoded byte arrays. - * @param var0 BlockID Strings - List of block types identified by strings. - * @param var1 Encoded Locations - Byte array containing compactly encoded block IDs, representing sequential block positions within a chunk. - * Currently, Minecraft doesn't use ByteArray storage. - */ - - public void read(ListTag var0, byte[] var1) { - int requiredBits = Math.max(4, MCAMth.ceillog2(var0.size())); - if (requiredBits != this.bits) { - setBits(requiredBits); - } - this.palette.read(var0); - - int bitsPerByte = 8 * var1.length / 4096; - if (this.palette == this.globalPalette) { - MCAPalette var4 = new MCAHashMapPalette<>(this.registry, requiredBits, this.dummyPaletteResize, this.reader, this.writer); - var4.read(var0); - MCABitStorageByteArray var5 = new MCABitStorageByteArray(requiredBits, 4096, var1); - for (int var6 = 0; var6 < 4096; var6++) { - this.storage.set(var6, this.globalPalette.idFor(var4.valueFor(var5.get(var6)))); - } - } else if (bitsPerByte == this.bits) { - System.arraycopy(var1, 0, this.storage.getRaw(), 0, var1.length); - } else { - MCABitStorageByteArray var4 = new MCABitStorageByteArray(bitsPerByte, 4096, var1); - for (int var5 = 0; var5 < 4096; var5++) { - this.storage.set(var5, var4.get(var5)); - } - } - } - - /** - * Reads and processes block data from encoded byte arrays. - * @param var0 BlockID Strings - List of block types identified by strings. - * This method is primarily used to read air sections. - */ - - public void read(ListTag var0) { - int requiredBits = Math.max(4, MCAMth.ceillog2(var0.size())); - if (requiredBits != this.bits) { - setBits(requiredBits); - } - this.palette.read(var0); - int defaultValue = 0; - for (int i = 0; i < 4096; i++) { - this.storage.set(i, defaultValue); - } - } - - public void write(CompoundTag var0, String var1, String var2) { MCAHashMapPalette var3 = new MCAHashMapPalette<>(this.registry, this.bits, this.dummyPaletteResize, this.reader, this.writer); T var4 = this.defaultValue; @@ -218,7 +160,7 @@ public class MCAPalettedContainer implements MCAPaletteResize { var3.write(paletteList); var0.put(var1, paletteList); int var8 = Math.max(4, MCAMth.ceillog2(paletteList.size())); - MCABitStorageLongArray var9 = new MCABitStorageLongArray(var8, 4096); + MCABitStorage var9 = new MCABitStorage(var8, 4096); for (int var10 = 0; var10 < var6.length; var10++) { var9.set(var10, var6[var10]); } diff --git a/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCAWrappedPalettedContainer.java b/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCAWrappedPalettedContainer.java index 06ba7c439..fcd7edd5c 100644 --- a/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCAWrappedPalettedContainer.java +++ b/core/src/main/java/com/volmit/iris/util/nbt/mca/palette/MCAWrappedPalettedContainer.java @@ -18,10 +18,7 @@ package com.volmit.iris.util.nbt.mca.palette; -import com.volmit.iris.Iris; -import com.volmit.iris.util.nbt.tag.ByteArrayTag; import com.volmit.iris.util.nbt.tag.CompoundTag; -import com.volmit.iris.util.nbt.tag.LongArrayTag; import lombok.RequiredArgsConstructor; import java.util.function.Function; @@ -45,22 +42,6 @@ public class MCAWrappedPalettedContainer implements MCAPaletteAccess { } public void readFromSection(CompoundTag tag) { - // container.read(tag.getCompoundTag("block_states").getListTag("palette"), tag.getCompoundTag("block_states").getLongArrayTag("data").getValue()); - CompoundTag blockStates = tag.getCompoundTag("block_states"); - if (blockStates == null) { - throw new IllegalArgumentException("block_states tag is missing"); - } - LongArrayTag longData = blockStates.getLongArrayTag("data"); - if (longData != null && longData.getValue() != null) { - container.read(tag.getCompoundTag("block_states").getListTag("palette"), tag.getCompoundTag("block_states").getLongArrayTag("data").getValue()); - } else { - ByteArrayTag byteData = blockStates.getByteArrayTag("data"); - if (byteData == null) { - container.read(tag.getCompoundTag("block_states").getListTag("palette")); - } else { - throw new IllegalArgumentException("No palette data tag found or data value is null"); - } - } + container.read(tag.getListTag("Palette"), tag.getLongArrayTag("BlockStates").getValue()); } - } diff --git a/core/src/main/resources/plugin.yml b/core/src/main/resources/plugin.yml index 05cd9bf4b..a54d30829 100644 --- a/core/src/main/resources/plugin.yml +++ b/core/src/main/resources/plugin.yml @@ -6,10 +6,6 @@ authors: [ cyberpwn, NextdoorPsycho, Vatuu ] website: volmit.com description: More than a Dimension! libraries: - - org.bytedeco:cuda-platform:12.3-8.9-1.5.10 - - org.bytedeco:javacpp:1.5.10 - - net.bytebuddy:byte-buddy:1.14.14 - - net.bytebuddy:byte-buddy-agent:1.12.8 - com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2 - com.github.ben-manes.caffeine:caffeine:3.0.5 - org.apache.commons:commons-lang3:3.12.0 diff --git a/nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/CustomBiomeSource.java b/nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/CustomBiomeSource.java index 5a1f89970..a24e62d85 100644 --- a/nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/CustomBiomeSource.java +++ b/nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/CustomBiomeSource.java @@ -2,7 +2,6 @@ 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; @@ -12,7 +11,6 @@ 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; @@ -27,7 +25,6 @@ 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; @@ -121,28 +118,8 @@ public class CustomBiomeSource extends BiomeSource { for (IrisBiome i : engine.getAllBiomes()) { if (i.isCustom()) { for (IrisBiomeCustom j : i.getCustomDerivitives()) { - ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()); - Biome biome = customRegistry.get(location); - if (biome == null) { - INMS.get().registerBiome(location.getNamespace(), j, false); - biome = customRegistry.get(location); - if (biome == null) { - Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); - continue; - } - } - Optional> optionalBiomeKey = customRegistry.getResourceKey(biome); - if (optionalBiomeKey.isEmpty()) { - Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); - continue; - } - ResourceKey biomeKey = optionalBiomeKey.get(); - Optional> 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()); + m.put(j.getId(), customRegistry.getHolder(customRegistry.getResourceKey(customRegistry + .get(new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()))).get()).get()); } } } diff --git a/nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/NMSBinding.java b/nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/NMSBinding.java index 264d0abce..49c921288 100644 --- a/nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/NMSBinding.java +++ b/nms/v1_19_R1/src/main/java/com/volmit/iris/core/nms/v1_19_R1/NMSBinding.java @@ -4,44 +4,14 @@ 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 java.util.logging.Logger; -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.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 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.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.GsonHelper; -import net.minecraft.world.level.Level; -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; @@ -55,7 +25,6 @@ import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack; 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; @@ -201,17 +170,6 @@ public class NMSBinding implements INMSBinding { return null; } - private RegistryAccess getRegistryAccess(World world) { - try { - var field = getField(Level.class, RegistryAccess.class); - field.setAccessible(true); - return (RegistryAccess) field.get(((CraftWorld) world).getHandle()); - } catch (Throwable e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - @Override public void deserializeTile(CompoundTag c, Location pos) { ((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c)); @@ -295,7 +253,8 @@ public class NMSBinding implements INMSBinding { @Override public Object getBiomeBase(World world, Biome biome) { - return CraftBlock.biomeToBiomeBase(getRegistryAccess(world).registry(Registry.BIOME_REGISTRY).orElse(null), biome); + return CraftBlock.biomeToBiomeBase(((CraftWorld) world).getHandle() + .registryAccess().registry(Registry.BIOME_REGISTRY).orElse(null), biome); } @Override @@ -332,11 +291,8 @@ public class NMSBinding implements INMSBinding { public int getBiomeId(Biome biome) { for (World i : Bukkit.getWorlds()) { if (i.getEnvironment().equals(World.Environment.NORMAL)) { - var registry = getRegistryAccess(i).registry(Registry.BIOME_REGISTRY).orElse(null); - if (registry != null) { - var holder = (Holder) getBiomeBase(registry, biome); - return registry.getId(holder.value()); - } + Registry registry = ((CraftWorld) i).getHandle().registryAccess().registry(Registry.BIOME_REGISTRY).orElse(null); + return registry.getId((net.minecraft.world.level.biome.Biome) getBiomeBase(registry, biome)); } } @@ -561,139 +517,6 @@ public class NMSBinding implements INMSBinding { return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason); } - @Override - public boolean registerDimension(String name, IrisDimension dimension) { - var registry = registry(Registry.DIMENSION_TYPE_REGISTRY); - 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(Registry.DIMENSION_TYPE_REGISTRY, 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(Registry.DIMENSION_TYPE_REGISTRY, 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(Registry.BIOME_REGISTRY, new ResourceLocation(dimensionId, biome.getId()), biomeBase, replace); - } - - private Optional decode(Codec codec, String json) { - return codec.decode(JsonOps.INSTANCE, GsonHelper.parse(json)).get().left().map(Pair::getFirst); - } - - private Optional encode(Codec codec, T value) { - return codec.encode(value, JsonOps.INSTANCE, new JsonObject()).result(); - } - - private boolean register(ResourceKey> 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, Lifecycle.stable()); - if (frozen) valueField.set(holder, value); - return true; - } finally { - field.setBoolean(registry, frozen); - } - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - @SuppressWarnings("unchecked") - private boolean replace(ResourceKey> 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); - Field lifecyclesField = getField(MappedRegistry.class, buildType(Map.class, "T", Lifecycle.class.getName())); - lifecyclesField.setAccessible(true); - var toId = (Reference2IntMap) toIdField.get(registry); - var byValue = (Map>) byValueField.get(registry); - var lifecycles = (Map) lifecyclesField.get(registry); - - valueField.set(holder, value); - toId.put(value, toId.removeInt(oldValue)); - byValue.put(value, byValue.remove(oldValue)); - lifecycles.put(value, lifecycles.remove(oldValue)); - return true; - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - private MappedRegistry registry(ResourceKey> registryKey) { - var rawRegistry = registry().registry(registryKey).orElse(null); - if (!(rawRegistry instanceof MappedRegistry 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); - } - } - - private static Field getField(Class clazz, Class fieldType) throws NoSuchFieldException { try { for (Field f : clazz.getDeclaredFields()) { @@ -710,76 +533,4 @@ public class NMSBinding implements INMSBinding { } } } - - public void injectBukkit() { - try { - Iris.info("Injecting Bukkit"); - new ByteBuddy() - .redefine(CraftServer.class) - .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) - .make() - .load(CraftServer.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, 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 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; - var logger = MinecraftServer.LOGGER; - ResourceKey typeKey = ResourceKey.create(Registry.DIMENSION_TYPE_REGISTRY, new ResourceLocation("iris", key.location().getPath())); - RegistryAccess registryAccess = server.registryAccess(); - Registry registry = registryAccess.registry(Registry.DIMENSION_TYPE_REGISTRY).orElse(null); - if (registry == null) throw new IllegalStateException("Unable to find registry for dimension type " + typeKey); - Holder 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 CraftServerAdvice { - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { - File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); - boolean isFromIris = false; - StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - for (StackTraceElement stack : stackTrace) { - if (stack.getClassName().contains("Iris")) { - isFromIris = true; - break; - } - } - if (isIrisWorld.exists() && !isFromIris) { - var logger = Logger.getLogger("Iris"); - logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); - - if (System.getProperty("iris.debug", "false").equals("true")) { - new RuntimeException().printStackTrace(); - } - return true; - } - return false; - } - - @Advice.OnMethodExit - static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { - if (bool) { - returned = null; - } - } - } -} \ No newline at end of file +} diff --git a/nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/CustomBiomeSource.java b/nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/CustomBiomeSource.java index 340c053cd..7a82acf42 100644 --- a/nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/CustomBiomeSource.java +++ b/nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/CustomBiomeSource.java @@ -2,7 +2,6 @@ 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; @@ -13,7 +12,6 @@ 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; @@ -28,7 +26,6 @@ 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 { @@ -123,28 +120,8 @@ public class CustomBiomeSource extends BiomeSource { for (IrisBiome i : engine.getAllBiomes()) { if (i.isCustom()) { for (IrisBiomeCustom j : i.getCustomDerivitives()) { - ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()); - Biome biome = customRegistry.get(location); - if (biome == null) { - INMS.get().registerBiome(location.getNamespace(), j, false); - biome = customRegistry.get(location); - if (biome == null) { - Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); - continue; - } - } - Optional> optionalBiomeKey = customRegistry.getResourceKey(biome); - if (optionalBiomeKey.isEmpty()) { - Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); - continue; - } - ResourceKey biomeKey = optionalBiomeKey.get(); - Optional> 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()); + m.put(j.getId(), customRegistry.getHolder(customRegistry.getResourceKey(customRegistry + .get(new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()))).get()).get()); } } } diff --git a/nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/NMSBinding.java b/nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/NMSBinding.java index 6af6c20bb..8aa76bc52 100644 --- a/nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/NMSBinding.java +++ b/nms/v1_19_R2/src/main/java/com/volmit/iris/core/nms/v1_19_R2/NMSBinding.java @@ -4,44 +4,14 @@ 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 java.util.logging.Logger; -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.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 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.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.GsonHelper; -import net.minecraft.world.level.Level; -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; @@ -55,7 +25,6 @@ import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack; 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; @@ -202,17 +171,6 @@ public class NMSBinding implements INMSBinding { return null; } - private RegistryAccess getRegistryAccess(World world) { - try { - var field = getField(Level.class, RegistryAccess.class); - field.setAccessible(true); - return (RegistryAccess) field.get(((CraftWorld) world).getHandle()); - } catch (Throwable e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - @Override public void deserializeTile(CompoundTag c, Location pos) { ((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c)); @@ -296,7 +254,8 @@ public class NMSBinding implements INMSBinding { @Override public Object getBiomeBase(World world, Biome biome) { - return CraftBlock.biomeToBiomeBase(getRegistryAccess(world).registry(Registries.BIOME).orElse(null), biome); + return CraftBlock.biomeToBiomeBase(((CraftWorld) world).getHandle() + .registryAccess().registry(Registries.BIOME).orElse(null), biome); } @Override @@ -333,11 +292,8 @@ public class NMSBinding implements INMSBinding { public int getBiomeId(Biome biome) { for (World i : Bukkit.getWorlds()) { if (i.getEnvironment().equals(World.Environment.NORMAL)) { - var registry = getRegistryAccess(i).registry(Registries.BIOME).orElse(null); - if (registry != null) { - var holder = (Holder) getBiomeBase(registry, biome); - return registry.getId(holder.value()); - } + Registry registry = ((CraftWorld) i).getHandle().registryAccess().registry(Registries.BIOME).orElse(null); + return registry.getId((net.minecraft.world.level.biome.Biome) getBiomeBase(registry, biome)); } } @@ -563,138 +519,6 @@ public class NMSBinding implements INMSBinding { return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason); } - @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 Optional decode(Codec codec, String json) { - return codec.decode(JsonOps.INSTANCE, GsonHelper.parse(json)).get().left().map(Pair::getFirst); - } - - private Optional encode(Codec codec, T value) { - return codec.encode(value, JsonOps.INSTANCE, new JsonObject()).result(); - } - - private boolean register(ResourceKey> 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, Lifecycle.stable()); - if (frozen) valueField.set(holder, value); - return true; - } finally { - field.setBoolean(registry, frozen); - } - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - @SuppressWarnings("unchecked") - private boolean replace(ResourceKey> 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); - Field lifecyclesField = getField(MappedRegistry.class, buildType(Map.class, "T", Lifecycle.class.getName())); - lifecyclesField.setAccessible(true); - var toId = (Reference2IntMap) toIdField.get(registry); - var byValue = (Map>) byValueField.get(registry); - var lifecycles = (Map) lifecyclesField.get(registry); - - valueField.set(holder, value); - toId.put(value, toId.removeInt(oldValue)); - byValue.put(value, byValue.remove(oldValue)); - lifecycles.put(value, lifecycles.remove(oldValue)); - return true; - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - private MappedRegistry registry(ResourceKey> registryKey) { - var rawRegistry = registry().registry(registryKey).orElse(null); - if (!(rawRegistry instanceof MappedRegistry 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); - } - } - private static Field getField(Class clazz, Class fieldType) throws NoSuchFieldException { try { for (Field f : clazz.getDeclaredFields()) { @@ -711,75 +535,4 @@ public class NMSBinding implements INMSBinding { } } } - - public void injectBukkit() { - try { - Iris.info("Injecting Bukkit"); - new ByteBuddy() - .redefine(CraftServer.class) - .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) - .make() - .load(CraftServer.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, 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 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 typeKey = ResourceKey.create(Registries.DIMENSION_TYPE, new ResourceLocation("iris", key.location().getPath())); - RegistryAccess registryAccess = server.registryAccess(); - Registry registry = registryAccess.registry(Registries.DIMENSION_TYPE).orElse(null); - if (registry == null) throw new IllegalStateException("Unable to find registry for dimension type " + typeKey); - Holder 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 CraftServerAdvice { - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { - File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); - boolean isFromIris = false; - StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - for (StackTraceElement stack : stackTrace) { - if (stack.getClassName().contains("Iris")) { - isFromIris = true; - break; - } - } - if (isIrisWorld.exists() && !isFromIris) { - var logger = Logger.getLogger("Iris"); - logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); - - if (System.getProperty("iris.debug", "false").equals("true")) { - new RuntimeException().printStackTrace(); - } - return true; - } - return false; - } - - @Advice.OnMethodExit - static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { - if (bool) { - returned = null; - } - } - } -} \ No newline at end of file +} diff --git a/nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/CustomBiomeSource.java b/nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/CustomBiomeSource.java index 3e26f6f79..f3debbaad 100644 --- a/nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/CustomBiomeSource.java +++ b/nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/CustomBiomeSource.java @@ -2,7 +2,6 @@ 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; @@ -126,16 +125,8 @@ public class CustomBiomeSource extends BiomeSource { for (IrisBiome i : engine.getAllBiomes()) { if (i.isCustom()) { for (IrisBiomeCustom j : i.getCustomDerivitives()) { - ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()); - Biome biome = customRegistry.get(location); - if (biome == null) { - INMS.get().registerBiome(location.getNamespace(), j, false); - biome = customRegistry.get(location); - if (biome == null) { - Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); - continue; - } - } + ResourceLocation resourceLocation = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()); + Biome biome = customRegistry.get(resourceLocation); Optional> optionalBiomeKey = customRegistry.getResourceKey(biome); if (optionalBiomeKey.isEmpty()) { Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); diff --git a/nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/NMSBinding.java b/nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/NMSBinding.java index 4a33fed2d..c32354ae9 100644 --- a/nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/NMSBinding.java +++ b/nms/v1_19_R3/src/main/java/com/volmit/iris/core/nms/v1_19_R3/NMSBinding.java @@ -4,44 +4,14 @@ 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 java.util.logging.Logger; -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.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 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.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.GsonHelper; -import net.minecraft.world.level.Level; -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; @@ -55,7 +25,6 @@ import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack; 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; @@ -203,17 +172,6 @@ public class NMSBinding implements INMSBinding { return null; } - private RegistryAccess getRegistryAccess(World world) { - try { - var field = getField(Level.class, RegistryAccess.class); - field.setAccessible(true); - return (RegistryAccess) field.get(((CraftWorld) world).getHandle()); - } catch (Throwable e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - @Override public void deserializeTile(CompoundTag c, Location pos) { ((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c)); @@ -297,7 +255,8 @@ public class NMSBinding implements INMSBinding { @Override public Object getBiomeBase(World world, Biome biome) { - return CraftBlock.biomeToBiomeBase(getRegistryAccess(world).registry(Registries.BIOME).orElse(null), biome); + return CraftBlock.biomeToBiomeBase(((CraftWorld) world).getHandle() + .registryAccess().registry(Registries.BIOME).orElse(null), biome); } @Override @@ -335,11 +294,8 @@ public class NMSBinding implements INMSBinding { public int getBiomeId(Biome biome) { for (World i : Bukkit.getWorlds()) { if (i.getEnvironment().equals(World.Environment.NORMAL)) { - var registry = getRegistryAccess(i).registry(Registries.BIOME).orElse(null); - if (registry != null) { - var holder = (Holder) getBiomeBase(registry, biome); - return registry.getId(holder.value()); - } + Registry registry = ((CraftWorld) i).getHandle().registryAccess().registry(Registries.BIOME).orElse(null); + return registry.getId((net.minecraft.world.level.biome.Biome) getBiomeBase(registry, biome)); } } @@ -567,138 +523,6 @@ public class NMSBinding implements INMSBinding { return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason); } - @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 Optional decode(Codec codec, String json) { - return codec.decode(JsonOps.INSTANCE, GsonHelper.parse(json)).get().left().map(Pair::getFirst); - } - - private Optional encode(Codec codec, T value) { - return codec.encode(value, JsonOps.INSTANCE, new JsonObject()).result(); - } - - private boolean register(ResourceKey> 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, Lifecycle.stable()); - if (frozen) valueField.set(holder, value); - return true; - } finally { - field.setBoolean(registry, frozen); - } - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - @SuppressWarnings("unchecked") - private boolean replace(ResourceKey> 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); - Field lifecyclesField = getField(MappedRegistry.class, buildType(Map.class, "T", Lifecycle.class.getName())); - lifecyclesField.setAccessible(true); - var toId = (Reference2IntMap) toIdField.get(registry); - var byValue = (Map>) byValueField.get(registry); - var lifecycles = (Map) lifecyclesField.get(registry); - - valueField.set(holder, value); - toId.put(value, toId.removeInt(oldValue)); - byValue.put(value, byValue.remove(oldValue)); - lifecycles.put(value, lifecycles.remove(oldValue)); - return true; - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - private MappedRegistry registry(ResourceKey> registryKey) { - var rawRegistry = registry().registry(registryKey).orElse(null); - if (!(rawRegistry instanceof MappedRegistry 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); - } - } - private static Field getField(Class clazz, Class fieldType) throws NoSuchFieldException { try { for (Field f : clazz.getDeclaredFields()) { @@ -715,75 +539,4 @@ public class NMSBinding implements INMSBinding { } } } - - public void injectBukkit() { - try { - Iris.info("Injecting Bukkit"); - new ByteBuddy() - .redefine(CraftServer.class) - .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) - .make() - .load(CraftServer.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, 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 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 typeKey = ResourceKey.create(Registries.DIMENSION_TYPE, new ResourceLocation("iris", key.location().getPath())); - RegistryAccess registryAccess = server.registryAccess(); - Registry registry = registryAccess.registry(Registries.DIMENSION_TYPE).orElse(null); - if (registry == null) throw new IllegalStateException("Unable to find registry for dimension type " + typeKey); - Holder 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 CraftServerAdvice { - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { - File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); - boolean isFromIris = false; - StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - for (StackTraceElement stack : stackTrace) { - if (stack.getClassName().contains("Iris")) { - isFromIris = true; - break; - } - } - if (isIrisWorld.exists() && !isFromIris) { - var logger = Logger.getLogger("Iris"); - logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); - - if (System.getProperty("iris.debug", "false").equals("true")) { - new RuntimeException().printStackTrace(); - } - return true; - } - return false; - } - - @Advice.OnMethodExit - static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { - if (bool) { - returned = null; - } - } - } } diff --git a/nms/v1_20_R1/src/main/java/com/volmit/iris/core/nms/v1_20_R1/CustomBiomeSource.java b/nms/v1_20_R1/src/main/java/com/volmit/iris/core/nms/v1_20_R1/CustomBiomeSource.java index 6ebea1093..41f4170c8 100644 --- a/nms/v1_20_R1/src/main/java/com/volmit/iris/core/nms/v1_20_R1/CustomBiomeSource.java +++ b/nms/v1_20_R1/src/main/java/com/volmit/iris/core/nms/v1_20_R1/CustomBiomeSource.java @@ -2,7 +2,6 @@ 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; @@ -126,16 +125,8 @@ public class CustomBiomeSource extends BiomeSource { for (IrisBiome i : engine.getAllBiomes()) { if (i.isCustom()) { for (IrisBiomeCustom j : i.getCustomDerivitives()) { - ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()); - Biome biome = customRegistry.get(location); - if (biome == null) { - INMS.get().registerBiome(location.getNamespace(), j, false); - biome = customRegistry.get(location); - if (biome == null) { - Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); - continue; - } - } + ResourceLocation resourceLocation = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()); + Biome biome = customRegistry.get(resourceLocation); Optional> optionalBiomeKey = customRegistry.getResourceKey(biome); if (optionalBiomeKey.isEmpty()) { Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); diff --git a/nms/v1_20_R1/src/main/java/com/volmit/iris/core/nms/v1_20_R1/NMSBinding.java b/nms/v1_20_R1/src/main/java/com/volmit/iris/core/nms/v1_20_R1/NMSBinding.java index 1451edd92..165f97808 100644 --- a/nms/v1_20_R1/src/main/java/com/volmit/iris/core/nms/v1_20_R1/NMSBinding.java +++ b/nms/v1_20_R1/src/main/java/com/volmit/iris/core/nms/v1_20_R1/NMSBinding.java @@ -1,22 +1,12 @@ package com.volmit.iris.core.nms.v1_20_R1; -import com.google.common.base.Preconditions; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import com.mojang.brigadier.exceptions.CommandSyntaxException; -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.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.json.JSONObject; import com.volmit.iris.util.mantle.Mantle; @@ -27,27 +17,16 @@ import com.volmit.iris.util.nbt.mca.NBTWorld; import com.volmit.iris.util.nbt.mca.palette.*; import com.volmit.iris.util.nbt.tag.CompoundTag; import it.unimi.dsi.fastutil.objects.Object2IntMap; -import 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.BlockPos; import net.minecraft.core.Holder; -import net.minecraft.core.MappedRegistry; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.TagParser; -import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; 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.level.Level; +import net.minecraft.world.entity.EntityDimensions; import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; @@ -55,10 +34,6 @@ 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.storage.LevelStorageSource; -import net.minecraft.world.level.storage.PrimaryLevelData; import org.bukkit.*; import org.bukkit.block.Biome; import org.bukkit.block.data.BlockData; @@ -72,8 +47,9 @@ 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.generator.BiomeProvider; +import org.bukkit.entity.EntityType; import org.bukkit.generator.ChunkGenerator; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -83,18 +59,13 @@ 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 java.util.logging.Logger; public class NMSBinding implements INMSBinding { @@ -204,17 +175,6 @@ public class NMSBinding implements INMSBinding { return null; } - private RegistryAccess getRegistryAccess(World world) { - try { - var field = getField(Level.class, RegistryAccess.class); - field.setAccessible(true); - return (RegistryAccess) field.get(((CraftWorld) world).getHandle()); - } catch (Throwable e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - @Override public void deserializeTile(CompoundTag c, Location pos) { ((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c)); @@ -298,7 +258,8 @@ public class NMSBinding implements INMSBinding { @Override public Object getBiomeBase(World world, Biome biome) { - return CraftBlock.biomeToBiomeBase(getRegistryAccess(world).registry(Registries.BIOME).orElse(null), biome); + return CraftBlock.biomeToBiomeBase(((CraftWorld) world).getHandle() + .registryAccess().registry(Registries.BIOME).orElse(null), biome); } @Override @@ -335,11 +296,8 @@ public class NMSBinding implements INMSBinding { public int getBiomeId(Biome biome) { for (World i : Bukkit.getWorlds()) { if (i.getEnvironment().equals(World.Environment.NORMAL)) { - var registry = getRegistryAccess(i).registry(Registries.BIOME).orElse(null); - if (registry != null) { - var holder = (Holder) getBiomeBase(registry, biome); - return registry.getId(holder.value()); - } + Registry registry = ((CraftWorld) i).getHandle().registryAccess().registry(Registries.BIOME).orElse(null); + return registry.getId((net.minecraft.world.level.biome.Biome) getBiomeBase(registry, biome)); } } @@ -551,138 +509,6 @@ public class NMSBinding implements INMSBinding { return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason); } - @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 Optional decode(Codec codec, String json) { - return codec.decode(JsonOps.INSTANCE, GsonHelper.parse(json)).get().left().map(Pair::getFirst); - } - - private Optional encode(Codec codec, T value) { - return codec.encode(value, JsonOps.INSTANCE, new JsonObject()).result(); - } - - private boolean register(ResourceKey> 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, Lifecycle.stable()); - if (frozen) valueField.set(holder, value); - return true; - } finally { - field.setBoolean(registry, frozen); - } - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - @SuppressWarnings("unchecked") - private boolean replace(ResourceKey> 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); - Field lifecyclesField = getField(MappedRegistry.class, buildType(Map.class, "T", Lifecycle.class.getName())); - lifecyclesField.setAccessible(true); - var toId = (Reference2IntMap) toIdField.get(registry); - var byValue = (Map>) byValueField.get(registry); - var lifecycles = (Map) lifecyclesField.get(registry); - - valueField.set(holder, value); - toId.put(value, toId.removeInt(oldValue)); - byValue.put(value, byValue.remove(oldValue)); - lifecycles.put(value, lifecycles.remove(oldValue)); - return true; - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - private MappedRegistry registry(ResourceKey> registryKey) { - var rawRegistry = registry().registry(registryKey).orElse(null); - if (!(rawRegistry instanceof MappedRegistry 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 inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException { ServerLevel serverLevel = ((CraftWorld)world).getHandle(); Class clazz = serverLevel.getChunkSource().chunkMap.generator.getClass(); @@ -712,75 +538,4 @@ public class NMSBinding implements INMSBinding { } } } - - public void injectBukkit() { - try { - Iris.info("Injecting Bukkit"); - new ByteBuddy() - .redefine(CraftServer.class) - .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) - .make() - .load(CraftServer.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 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 typeKey = ResourceKey.create(Registries.DIMENSION_TYPE, new ResourceLocation("iris", key.location().getPath())); - RegistryAccess registryAccess = server.registryAccess(); - Registry registry = registryAccess.registry(Registries.DIMENSION_TYPE).orElse(null); - if (registry == null) throw new IllegalStateException("Unable to find registry for dimension type " + typeKey); - Holder 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 CraftServerAdvice { - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { - File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); - boolean isFromIris = false; - StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - for (StackTraceElement stack : stackTrace) { - if (stack.getClassName().contains("Iris")) { - isFromIris = true; - break; - } - } - if (isIrisWorld.exists() && !isFromIris) { - var logger = Logger.getLogger("Iris"); - logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); - - if (System.getProperty("iris.debug", "false").equals("true")) { - new RuntimeException().printStackTrace(); - } - return true; - } - return false; - } - - @Advice.OnMethodExit - static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { - if (bool) { - returned = null; - } - } - } } diff --git a/nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/CustomBiomeSource.java b/nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/CustomBiomeSource.java index 24ce23216..fcf462f95 100644 --- a/nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/CustomBiomeSource.java +++ b/nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/CustomBiomeSource.java @@ -2,7 +2,6 @@ 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; @@ -125,16 +124,8 @@ public class CustomBiomeSource extends BiomeSource { for (IrisBiome i : engine.getAllBiomes()) { if (i.isCustom()) { for (IrisBiomeCustom j : i.getCustomDerivitives()) { - ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()); - Biome biome = customRegistry.get(location); - if (biome == null) { - INMS.get().registerBiome(location.getNamespace(), j, false); - biome = customRegistry.get(location); - if (biome == null) { - Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); - continue; - } - } + ResourceLocation resourceLocation = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()); + Biome biome = customRegistry.get(resourceLocation); Optional> optionalBiomeKey = customRegistry.getResourceKey(biome); if (optionalBiomeKey.isEmpty()) { Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); diff --git a/nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/NMSBinding.java b/nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/NMSBinding.java index d74e7c125..73a15d89c 100644 --- a/nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/NMSBinding.java +++ b/nms/v1_20_R2/src/main/java/com/volmit/iris/core/nms/v1_20_R2/NMSBinding.java @@ -4,44 +4,14 @@ 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 java.util.logging.Logger; -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.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 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.server.MinecraftServer; -import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.GsonHelper; -import net.minecraft.world.RandomSequences; -import net.minecraft.world.level.Level; -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; @@ -55,7 +25,6 @@ import org.bukkit.craftbukkit.v1_20_R2.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; @@ -204,17 +173,6 @@ public class NMSBinding implements INMSBinding { return null; } - private RegistryAccess getRegistryAccess(World world) { - try { - var field = getField(Level.class, RegistryAccess.class); - field.setAccessible(true); - return (RegistryAccess) field.get(((CraftWorld) world).getHandle()); - } catch (Throwable e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - @Override public void deserializeTile(CompoundTag c, Location pos) { ((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c)); @@ -298,7 +256,8 @@ public class NMSBinding implements INMSBinding { @Override public Object getBiomeBase(World world, Biome biome) { - return biomeToBiomeBase(getRegistryAccess(world).registry(Registries.BIOME).orElse(null), biome); + return biomeToBiomeBase(((CraftWorld) world).getHandle() + .registryAccess().registry(Registries.BIOME).orElse(null), biome); } @Override @@ -335,11 +294,8 @@ public class NMSBinding implements INMSBinding { public int getBiomeId(Biome biome) { for (World i : Bukkit.getWorlds()) { if (i.getEnvironment().equals(World.Environment.NORMAL)) { - var registry = getRegistryAccess(i).registry(Registries.BIOME).orElse(null); - if (registry != null) { - var holder = (Holder) getBiomeBase(registry, biome); - return registry.getId(holder.value()); - } + Registry registry = ((CraftWorld) i).getHandle().registryAccess().registry(Registries.BIOME).orElse(null); + return registry.getId((net.minecraft.world.level.biome.Biome) getBiomeBase(registry, biome)); } } @@ -564,139 +520,6 @@ public class NMSBinding implements INMSBinding { return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason); } - @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 Optional decode(Codec codec, String json) { - return codec.decode(JsonOps.INSTANCE, GsonHelper.parse(json)).get().left().map(Pair::getFirst); - } - - private Optional encode(Codec codec, T value) { - return codec.encode(value, JsonOps.INSTANCE, new JsonObject()).result(); - } - - private boolean register(ResourceKey> 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, Lifecycle.stable()); - if (frozen) valueField.set(holder, value); - return true; - } finally { - field.setBoolean(registry, frozen); - } - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - @SuppressWarnings("unchecked") - private boolean replace(ResourceKey> 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); - Field lifecyclesField = getField(MappedRegistry.class, buildType(Map.class, "T", Lifecycle.class.getName())); - lifecyclesField.setAccessible(true); - var toId = (Reference2IntMap) toIdField.get(registry); - var byValue = (Map>) byValueField.get(registry); - var lifecycles = (Map) lifecyclesField.get(registry); - - valueField.set(holder, value); - toId.put(value, toId.removeInt(oldValue)); - byValue.put(value, byValue.remove(oldValue)); - lifecycles.put(value, lifecycles.remove(oldValue)); - return true; - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - private MappedRegistry registry(ResourceKey> registryKey) { - var rawRegistry = registry().registry(registryKey).orElse(null); - if (!(rawRegistry instanceof MappedRegistry 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); - } - } - - private static Field getField(Class clazz, Class fieldType) throws NoSuchFieldException { try { for (Field f : clazz.getDeclaredFields()) { @@ -717,75 +540,4 @@ public class NMSBinding implements INMSBinding { public static Holder biomeToBiomeBase(Registry registry, Biome biome) { return registry.getHolderOrThrow(ResourceKey.create(Registries.BIOME, CraftNamespacedKey.toMinecraft(biome.getKey()))); } - - public void injectBukkit() { - try { - Iris.info("Injecting Bukkit"); - new ByteBuddy() - .redefine(CraftServer.class) - .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) - .make() - .load(CraftServer.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 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 typeKey = ResourceKey.create(Registries.DIMENSION_TYPE, new ResourceLocation("iris", key.location().getPath())); - RegistryAccess registryAccess = server.registryAccess(); - Registry registry = registryAccess.registry(Registries.DIMENSION_TYPE).orElse(null); - if (registry == null) throw new IllegalStateException("Unable to find registry for dimension type " + typeKey); - Holder 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 CraftServerAdvice { - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { - File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); - boolean isFromIris = false; - StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - for (StackTraceElement stack : stackTrace) { - if (stack.getClassName().contains("Iris")) { - isFromIris = true; - break; - } - } - if (isIrisWorld.exists() && !isFromIris) { - var logger = Logger.getLogger("Iris"); - logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); - - if (System.getProperty("iris.debug", "false").equals("true")) { - new RuntimeException().printStackTrace(); - } - return true; - } - return false; - } - - @Advice.OnMethodExit - static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { - if (bool) { - returned = null; - } - } - } } diff --git a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/CustomBiomeSource.java b/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/CustomBiomeSource.java index 323fa255b..3d3582239 100644 --- a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/CustomBiomeSource.java +++ b/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/CustomBiomeSource.java @@ -2,7 +2,6 @@ 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; @@ -125,16 +124,8 @@ public class CustomBiomeSource extends BiomeSource { for (IrisBiome i : engine.getAllBiomes()) { if (i.isCustom()) { for (IrisBiomeCustom j : i.getCustomDerivitives()) { - ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()); - Biome biome = customRegistry.get(location); - if (biome == null) { - INMS.get().registerBiome(location.getNamespace(), j, false); - biome = customRegistry.get(location); - if (biome == null) { - Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); - continue; - } - } + ResourceLocation resourceLocation = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()); + Biome biome = customRegistry.get(resourceLocation); Optional> optionalBiomeKey = customRegistry.getResourceKey(biome); if (optionalBiomeKey.isEmpty()) { Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); diff --git a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/Headless.java b/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/Headless.java deleted file mode 100644 index 36b552545..000000000 --- a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/Headless.java +++ /dev/null @@ -1,256 +0,0 @@ -package com.volmit.iris.core.nms.v1_20_R3; - -import com.volmit.iris.Iris; -import com.volmit.iris.core.nms.BiomeBaseInjector; -import com.volmit.iris.core.nms.IHeadless; -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.core.pregenerator.PregenListener; -import com.volmit.iris.engine.framework.Engine; -import com.volmit.iris.engine.framework.EngineStage; -import com.volmit.iris.engine.framework.WrongEngineBroException; -import com.volmit.iris.engine.object.IrisBiome; -import com.volmit.iris.util.collection.KMap; -import com.volmit.iris.util.context.ChunkContext; -import com.volmit.iris.util.context.IrisContext; -import com.volmit.iris.util.documentation.BlockCoordinates; -import com.volmit.iris.util.documentation.RegionCoordinates; -import com.volmit.iris.util.hunk.Hunk; -import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder; -import com.volmit.iris.util.hunk.view.ChunkDataHunkHolder; -import com.volmit.iris.util.mantle.MantleFlag; -import com.volmit.iris.util.math.RNG; -import com.volmit.iris.util.parallel.MultiBurst; -import com.volmit.iris.util.scheduling.Looper; -import com.volmit.iris.util.scheduling.PrecisionStopwatch; -import net.minecraft.core.Holder; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.world.level.chunk.ProtoChunk; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.block.data.BlockData; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayDeque; -import java.util.Queue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; - -public class Headless implements IHeadless, LevelHeightAccessor { - private final NMSBinding binding; - private final Engine engine; - private final RegionFileStorage storage; - private final Queue chunkQueue = new ArrayDeque<>(); - private final ReentrantLock saveLock = new ReentrantLock(); - private final KMap> customBiomes = new KMap<>(); - private final KMap> minecraftBiomes = new KMap<>(); - private boolean closed = false; - - public Headless(NMSBinding binding, Engine engine) { - this.binding = binding; - this.engine = engine; - this.storage = new RegionFileStorage(new File(engine.getWorld().worldFolder(), "region").toPath(), false); - var queueLooper = new Looper() { - @Override - protected long loop() { - save(); - return closed ? -1 : 100; - } - }; - queueLooper.setName("Region Save Looper"); - queueLooper.start(); - - var dimKey = engine.getDimension().getLoadKey(); - for (var biome : engine.getAllBiomes()) { - if (!biome.isCustom()) continue; - for (var custom : biome.getCustomDerivitives()) { - binding.registerBiome(dimKey, custom, false); - } - } - } - - @Override - public boolean exists(int x, int z) { - if (closed) return false; - try { - CompoundTag tag = storage.read(new ChunkPos(x, z)); - return tag != null && !"empty".equals(tag.getString("Status")); - } catch (IOException e) { - return false; - } - } - - @Override - public void save() { - if (closed) return; - saveLock.lock(); - try { - while (!chunkQueue.isEmpty()) { - ChunkAccess chunk = chunkQueue.poll(); - if (chunk == null) break; - try { - storage.write(chunk.getPos(), binding.serializeChunk(chunk, this)); - } catch (Throwable e) { - Iris.error("Failed to save chunk " + chunk.getPos().x + ", " + chunk.getPos().z); - e.printStackTrace(); - } - } - } finally { - saveLock.unlock(); - } - } - - @Override - public void generateRegion(MultiBurst burst, int x, int z, PregenListener listener) { - if (closed) return; - boolean listening = listener != null; - if (listening) listener.onRegionGenerating(x, z); - CountDownLatch latch = new CountDownLatch(1024); - iterateRegion(x, z, pos -> burst.complete(() -> { - if (listening) listener.onChunkGenerating(pos.x, pos.z); - generateChunk(pos.x, pos.z); - if (listening) listener.onChunkGenerated(pos.x, pos.z); - latch.countDown(); - })); - try { - latch.await(); - } catch (InterruptedException ignored) {} - if (listening) listener.onRegionGenerated(x, z); - } - - @RegionCoordinates - private static void iterateRegion(int x, int z, Consumer chunkPos) { - int cX = x << 5; - int cZ = z << 5; - for (int xx = 0; xx < 32; xx++) { - for (int zz = 0; zz < 32; zz++) { - chunkPos.accept(new ChunkPos(cX + xx, cZ + zz)); - } - } - } - - @Override - public void generateChunk(int x, int z) { - if (closed || exists(x, z)) return; - try { - var pos = new ChunkPos(x, z); - ProtoChunk chunk = binding.createProtoChunk(pos, this); - var tc = new MCATerrainChunk(chunk); - - ChunkDataHunkHolder blocks = new ChunkDataHunkHolder(tc); - BiomeGridHunkHolder biomes = new BiomeGridHunkHolder(tc, tc.getMinHeight(), tc.getMaxHeight()); - ChunkContext ctx = generate(engine, pos.x << 4, pos.z << 4, blocks, biomes); - blocks.apply(); - biomes.apply(); - - inject(engine, tc.getBiomeBaseInjector(), chunk, ctx); //TODO improve - chunk.setStatus(ChunkStatus.FULL); - chunkQueue.add(chunk); - } catch (Throwable e) { - Iris.error("Failed to generate " + x + ", " + z); - e.printStackTrace(); - } - } - - @BlockCoordinates - private ChunkContext generate(Engine engine, int x, int z, Hunk vblocks, Hunk vbiomes) throws WrongEngineBroException { - if (engine.isClosed()) { - throw new WrongEngineBroException(); - } - - engine.getContext().touch(); - engine.getEngineData().getStatistics().generatedChunk(); - ChunkContext ctx = null; - try { - PrecisionStopwatch p = PrecisionStopwatch.start(); - Hunk blocks = vblocks.listen((xx, y, zz, t) -> engine.catchBlockUpdates(x + xx, y + engine.getMinHeight(), z + zz, t)); - - var dimension = engine.getDimension(); - if (dimension.isDebugChunkCrossSections() && ((x >> 4) % dimension.getDebugCrossSectionsMod() == 0 || (z >> 4) % dimension.getDebugCrossSectionsMod() == 0)) { - for (int i = 0; i < 16; i++) { - for (int j = 0; j < 16; j++) { - blocks.set(i, 0, j, Material.CRYING_OBSIDIAN.createBlockData()); - } - } - } else { - ctx = new ChunkContext(x, z, engine.getComplex()); - IrisContext.getOr(engine).setChunkContext(ctx); - - for (EngineStage i : engine.getMode().getStages()) { - i.generate(x, z, blocks, vbiomes, false, ctx); - } - } - - engine.getMantle().getMantle().flag(x >> 4, z >> 4, MantleFlag.REAL, true); - engine.getMetrics().getTotal().put(p.getMilliseconds()); - engine.addGenerated(); - - } catch (Throwable e) { - Iris.reportError(e); - engine.fail("Failed to generate " + x + ", " + z, e); - } - return ctx; - } - - private void inject(Engine engine, BiomeBaseInjector injector, ChunkAccess chunk, ChunkContext ctx) { - var pos = chunk.getPos(); - for (int y = engine.getMinHeight(); y < engine.getMaxHeight(); y++) { - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - int wX = pos.getBlockX(x); - int wZ = pos.getBlockZ(z); - try { - injector.setBiome(x, y, z, getNoiseBiome(engine, ctx, x, z, wX, y, wZ)); - } catch (Throwable e) { - Iris.error("Failed to inject biome for " + wX + ", " + y + ", " + wZ); - e.printStackTrace(); - } - } - } - } - } - - private Holder getNoiseBiome(Engine engine, ChunkContext ctx, int rX, int rZ, int x, int y, int z) { - RNG rng = new RNG(engine.getSeedManager().getBiome()); - int m = (y - engine.getMinHeight()) << 2; - IrisBiome ib = ctx == null ? - engine.getComplex().getTrueBiomeStream().get(x << 2, z << 2) : - ctx.getBiome().get(rX, rZ); - if (ib.isCustom()) { - return customBiomes.computeIfAbsent(ib.getCustomBiome(rng, x << 2, m, z << 2).getId(), - id -> binding.getBiomeHolder(engine.getDimension().getLoadKey(), id)); - } else { - return minecraftBiomes.computeIfAbsent(ib.getSkyBiome(rng, x << 2, m, z << 2).getKey(), - id -> binding.getBiomeHolder(id.getNamespace(), id.getKey())); - } - } - - @Override - public void close() throws IOException { - if (closed) return; - try { - storage.close(); - } finally { - closed = true; - customBiomes.clear(); - minecraftBiomes.clear(); - } - } - - @Override - public int getHeight() { - return engine.getHeight(); - } - - @Override - public int getMinBuildHeight() { - return engine.getMinHeight(); - } -} diff --git a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java b/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java index 79ec5e942..01fa75d94 100644 --- a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java +++ b/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/NMSBinding.java @@ -4,52 +4,14 @@ 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.*; -import java.util.concurrent.Executor; +import java.util.Iterator; +import java.util.List; +import java.util.Vector; import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Logger; -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.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.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.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.dynamic.loading.ClassReloadingStrategy; -import net.bytebuddy.implementation.bytecode.StackManipulation; -import net.bytebuddy.implementation.bytecode.assign.Assigner; -import net.bytebuddy.implementation.bytecode.member.MethodInvocation; -import net.bytebuddy.matcher.ElementMatchers; -import net.minecraft.core.IdMapper; -import net.minecraft.core.MappedRegistry; -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.level.ChunkPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.UpgradeData; -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; @@ -63,7 +25,6 @@ import org.bukkit.craftbukkit.v1_20_R3.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; @@ -106,8 +67,6 @@ import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.LevelChunk; import sun.misc.Unsafe; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - public class NMSBinding implements INMSBinding { private final KMap baseBiomeCache = new KMap<>(); private final BlockData AIR = Material.AIR.createBlockData(); @@ -214,17 +173,6 @@ public class NMSBinding implements INMSBinding { return null; } - private RegistryAccess getRegistryAccess(World world) { - try { - var field = getField(Level.class, RegistryAccess.class); - field.setAccessible(true); - return (RegistryAccess) field.get(((CraftWorld) world).getHandle()); - } catch (Throwable e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - @Override public void deserializeTile(CompoundTag c, Location pos) { ((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c)); @@ -308,7 +256,8 @@ public class NMSBinding implements INMSBinding { @Override public Object getBiomeBase(World world, Biome biome) { - return biomeToBiomeBase(getRegistryAccess(world).registry(Registries.BIOME).orElse(null), biome); + return biomeToBiomeBase(((CraftWorld) world).getHandle() + .registryAccess().registry(Registries.BIOME).orElse(null), biome); } @Override @@ -345,11 +294,8 @@ public class NMSBinding implements INMSBinding { public int getBiomeId(Biome biome) { for (World i : Bukkit.getWorlds()) { if (i.getEnvironment().equals(World.Environment.NORMAL)) { - var registry = getRegistryAccess(i).registry(Registries.BIOME).orElse(null); - if (registry != null) { - var holder = (Holder) getBiomeBase(registry, biome); - return registry.getId(holder.value()); - } + Registry registry = ((CraftWorld) i).getHandle().registryAccess().registry(Registries.BIOME).orElse(null); + return registry.getId((net.minecraft.world.level.biome.Biome) getBiomeBase(registry, biome)); } } @@ -469,13 +415,13 @@ public class NMSBinding implements INMSBinding { @Override public MCAPaletteAccess createPalette() { MCAIdMapper registry = registryCache.aquireNasty(() -> { - Field cf = IdMapper.class.getDeclaredField("tToId"); - Field df = IdMapper.class.getDeclaredField("idToT"); - Field bf = IdMapper.class.getDeclaredField("nextId"); + Field cf = net.minecraft.core.IdMapper.class.getDeclaredField("tToId"); + Field df = net.minecraft.core.IdMapper.class.getDeclaredField("idToT"); + Field bf = net.minecraft.core.IdMapper.class.getDeclaredField("nextId"); cf.setAccessible(true); df.setAccessible(true); bf.setAccessible(true); - IdMapper blockData = Block.BLOCK_STATE_REGISTRY; + net.minecraft.core.IdMapper blockData = Block.BLOCK_STATE_REGISTRY; int b = bf.getInt(blockData); Object2IntMap c = (Object2IntMap) cf.get(blockData); List d = (List) df.get(blockData); @@ -569,143 +515,12 @@ public class NMSBinding implements INMSBinding { return null; } + @Override public Entity spawnEntity(Location location, org.bukkit.entity.EntityType type, CreatureSpawnEvent.SpawnReason reason) { return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason); } - @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 Optional decode(Codec codec, String json) { - return codec.decode(JsonOps.INSTANCE, GsonHelper.parse(json)).get().left().map(Pair::getFirst); - } - - private Optional encode(Codec codec, T value) { - return codec.encode(value, JsonOps.INSTANCE, new JsonObject()).result(); - } - - private boolean register(ResourceKey> 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, Lifecycle.stable()); - if (frozen) valueField.set(holder, value); - return true; - } finally { - field.setBoolean(registry, frozen); - } - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - @SuppressWarnings("unchecked") - private boolean replace(ResourceKey> 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); - Field lifecyclesField = getField(MappedRegistry.class, buildType(Map.class, "T", Lifecycle.class.getName())); - lifecyclesField.setAccessible(true); - var toId = (Reference2IntMap) toIdField.get(registry); - var byValue = (Map>) byValueField.get(registry); - var lifecycles = (Map) lifecyclesField.get(registry); - - valueField.set(holder, value); - toId.put(value, toId.removeInt(oldValue)); - byValue.put(value, byValue.remove(oldValue)); - lifecycles.put(value, lifecycles.remove(oldValue)); - return true; - } catch (Throwable e) { - throw new IllegalStateException(e); - } - } - - private MappedRegistry registry(ResourceKey> registryKey) { - var rawRegistry = registry().registry(registryKey).orElse(null); - if (!(rawRegistry instanceof MappedRegistry 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); - } - } - private static Field getField(Class clazz, Class fieldType) throws NoSuchFieldException { try { for (Field f : clazz.getDeclaredFields()) { @@ -726,92 +541,4 @@ public class NMSBinding implements INMSBinding { public static Holder biomeToBiomeBase(Registry registry, Biome biome) { return registry.getHolderOrThrow(ResourceKey.create(Registries.BIOME, CraftNamespacedKey.toMinecraft(biome.getKey()))); } - - public void injectBukkit() { - try { - Iris.info("Injecting Bukkit"); - new ByteBuddy() - .redefine(CraftServer.class) - .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) - .make() - .load(CraftServer.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); - } - - } - - @Override - public IHeadless createHeadless(Engine engine) { - return new Headless(this, engine); - } - - private static class ServerLevelAdvice { - @Advice.OnMethodEnter - static void enter(@Advice.Argument(0) MinecraftServer server, @Advice.Argument(2) LevelStorageSource.LevelStorageAccess access, @Advice.Argument(4) ResourceKey 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 typeKey = ResourceKey.create(Registries.DIMENSION_TYPE, new ResourceLocation("iris", key.location().getPath())); - RegistryAccess registryAccess = server.registryAccess(); - Registry registry = registryAccess.registry(Registries.DIMENSION_TYPE).orElse(null); - if (registry == null) throw new IllegalStateException("Unable to find registry for dimension type " + typeKey); - Holder 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 CraftServerAdvice { - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { - File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); - boolean isFromIris = false; - StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - for (StackTraceElement stack : stackTrace) { - if (stack.getClassName().contains("Iris")) { - isFromIris = true; - break; - } - } - if (isIrisWorld.exists() && !isFromIris) { - var logger = Logger.getLogger("Iris"); - logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); - - if (System.getProperty("iris.debug", "false").equals("true")) { - new RuntimeException().printStackTrace(); - } - return true; - } - return false; - } - - @Advice.OnMethodExit - static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { - if (bool) { - returned = null; - } - } - } - - Holder.Reference getBiomeHolder(String namespace, String id) { - return getCustomBiomeRegistry().getHolder(ResourceKey.create(Registries.BIOME, new ResourceLocation(namespace, id))).orElse(null); - } - - ProtoChunk createProtoChunk(ChunkPos pos, LevelHeightAccessor heightAccessor) { - return new ProtoChunk(pos, UpgradeData.EMPTY, heightAccessor, getCustomBiomeRegistry(), null); - } - - net.minecraft.nbt.CompoundTag serializeChunk(ChunkAccess chunkAccess, LevelHeightAccessor heightAccessor) { - return ChunkSerializer.write(chunkAccess, heightAccessor, getCustomBiomeRegistry()); - } } diff --git a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/mca/ChunkSerializer.java b/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/mca/ChunkSerializer.java deleted file mode 100644 index a90699c53..000000000 --- a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/mca/ChunkSerializer.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.volmit.iris.core.nms.v1_20_R3.mca; - -import com.mojang.logging.LogUtils; -import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; -import it.unimi.dsi.fastutil.shorts.ShortList; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Map.Entry; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.LongArrayTag; -import net.minecraft.nbt.NbtOps; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.nbt.ShortTag; -import net.minecraft.nbt.Tag; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.chunk.CarvingMask; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.chunk.PalettedContainerRO; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.UpgradeData; -import net.minecraft.world.level.chunk.ChunkAccess.TicksToSave; -import net.minecraft.world.level.levelgen.BelowZeroRetrogen; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.levelgen.GenerationStep.Carving; -import net.minecraft.world.level.levelgen.Heightmap.Types; -import net.minecraft.world.level.levelgen.blending.BlendingData; -import org.slf4j.Logger; - -import static net.minecraft.world.level.chunk.storage.ChunkSerializer.BLOCK_STATE_CODEC; - -public class ChunkSerializer { - private static final Logger LOGGER = LogUtils.getLogger(); - private static Method CODEC = null; - - static { - for (Method method : net.minecraft.world.level.chunk.storage.ChunkSerializer.class.getDeclaredMethods()) { - if (method.getReturnType().equals(Codec.class) && method.getParameterCount() == 1) { - CODEC = method; - CODEC.setAccessible(true); - break; - } - } - } - - public static CompoundTag write(ChunkAccess chunk, LevelHeightAccessor heightAccessor, Registry biomeRegistry) { - ChunkPos pos = chunk.getPos(); - CompoundTag data = NbtUtils.addCurrentDataVersion(new CompoundTag()); - data.putInt("xPos", pos.x); - data.putInt("yPos", ((LevelHeightAccessor) chunk).getMinSection()); - data.putInt("zPos", pos.z); - data.putLong("LastUpdate", 0L); - data.putLong("InhabitedTime", chunk.getInhabitedTime()); - data.putString("Status", BuiltInRegistries.CHUNK_STATUS.getKey(chunk.getStatus()).toString()); - BlendingData blendingdata = chunk.getBlendingData(); - if (blendingdata != null) { - DataResult dataResult = BlendingData.CODEC.encodeStart(NbtOps.INSTANCE, blendingdata); - dataResult.resultOrPartial(LOGGER::error).ifPresent(base -> data.put("blending_data", base)); - } - - BelowZeroRetrogen belowzeroretrogen = chunk.getBelowZeroRetrogen(); - if (belowzeroretrogen != null) { - DataResult dataResult = BelowZeroRetrogen.CODEC.encodeStart(NbtOps.INSTANCE, belowzeroretrogen); - dataResult.resultOrPartial(LOGGER::error).ifPresent(base -> data.put("below_zero_retrogen", base)); - } - - UpgradeData upgradeData = chunk.getUpgradeData(); - if (!upgradeData.isEmpty()) { - data.put("UpgradeData", upgradeData.write()); - } - - LevelChunkSection[] chunkSections = chunk.getSections(); - ListTag sections = new ListTag(); - Codec>> codec; - try { - codec = (Codec>>) CODEC.invoke(null, biomeRegistry); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - - int minLightSection = heightAccessor.getMinSection() - 1; - int maxLightSection = minLightSection + heightAccessor.getSectionsCount() + 2; - for (int y = minLightSection; y < maxLightSection; y++) { - int i = ((LevelHeightAccessor) chunk).getSectionIndexFromSectionY(y); - if (i >= 0 && i < chunkSections.length) { - CompoundTag section = new CompoundTag(); - LevelChunkSection chunkSection = chunkSections[i]; - DataResult dataResult = BLOCK_STATE_CODEC.encodeStart(NbtOps.INSTANCE, chunkSection.getStates()); - section.put("block_states", dataResult.getOrThrow(false, LOGGER::error)); - dataResult = codec.encodeStart(NbtOps.INSTANCE, chunkSection.getBiomes()); - section.put("biomes", dataResult.getOrThrow(false, LOGGER::error)); - - if (!section.isEmpty()) { - section.putByte("Y", (byte)y); - sections.add(section); - } - } - } - - data.put("sections", sections); - if (chunk.isLightCorrect()) { - data.putBoolean("isLightOn", true); - } - - ListTag blockEntities = new ListTag(); - for (BlockPos blockPos : chunk.getBlockEntitiesPos()) { - CompoundTag blockEntityNbt = chunk.getBlockEntityNbtForSaving(blockPos); - if (blockEntityNbt != null) { - blockEntities.add(blockEntityNbt); - } - } - data.put("block_entities", blockEntities); - - if (chunk instanceof ProtoChunk protoChunk) { - ListTag entities = new ListTag(); - entities.addAll(protoChunk.getEntities()); - data.put("entities", entities); - - CompoundTag carvingMasks = new CompoundTag(); - for (Carving carving : Carving.values()) { - CarvingMask carvingMask = protoChunk.getCarvingMask(carving); - if (carvingMask != null) { - carvingMasks.putLongArray(carving.toString(), carvingMask.toArray()); - } - } - data.put("CarvingMasks", carvingMasks); - } - - saveTicks(data, chunk.getTicksForSerialization()); - data.put("PostProcessing", packOffsets(chunk.getPostProcessing())); - CompoundTag heightmaps = new CompoundTag(); - - for (Entry entry : chunk.getHeightmaps()) { - if (chunk.getStatus().heightmapsAfter().contains(entry.getKey())) { - heightmaps.put(entry.getKey().getSerializationKey(), new LongArrayTag(entry.getValue().getRawData())); - } - } - - data.put("Heightmaps", heightmaps); - - CompoundTag structures = new CompoundTag(); - structures.put("starts", new CompoundTag()); - structures.put("References", new CompoundTag()); - data.put("structures", structures); - if (!chunk.persistentDataContainer.isEmpty()) { - data.put("ChunkBukkitValues", chunk.persistentDataContainer.toTagCompound()); - } - - return data; - } - - private static void saveTicks(CompoundTag compoundTag, TicksToSave ticksToSave) { - compoundTag.put("block_ticks", ticksToSave.blocks().save(0, block -> BuiltInRegistries.BLOCK.getKey(block).toString())); - compoundTag.put("fluid_ticks", ticksToSave.fluids().save(0, fluid -> BuiltInRegistries.FLUID.getKey(fluid).toString())); - } - - public static ListTag packOffsets(ShortList[] offsets) { - ListTag tags = new ListTag(); - for (ShortList shorts : offsets) { - ListTag listTag = new ListTag(); - if (shorts != null) { - for (Short s : shorts) { - listTag.add(ShortTag.valueOf(s)); - } - } - tags.add(listTag); - } - - return tags; - } -} diff --git a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/mca/MCATerrainChunk.java b/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/mca/MCATerrainChunk.java deleted file mode 100644 index e574c892a..000000000 --- a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/mca/MCATerrainChunk.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.volmit.iris.core.nms.v1_20_R3.mca; - -import com.volmit.iris.Iris; -import com.volmit.iris.core.nms.BiomeBaseInjector; -import com.volmit.iris.engine.data.chunk.TerrainChunk; -import com.volmit.iris.util.data.IrisBlockData; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Holder; -import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkAccess; -import org.bukkit.Material; -import org.bukkit.block.Biome; -import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_20_R3.block.CraftBiome; -import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData; -import org.bukkit.generator.ChunkGenerator; -import org.bukkit.material.MaterialData; -import org.jetbrains.annotations.NotNull; - -public record MCATerrainChunk(ChunkAccess chunk) implements TerrainChunk { - - @Override - public BiomeBaseInjector getBiomeBaseInjector() { - return (x, y, z, biomeBase) -> chunk.setBiome(x, y, z, (Holder) biomeBase); - } - - @Override - public Biome getBiome(int x, int z) { - return Biome.THE_VOID; - } - - @Override - public Biome getBiome(int x, int y, int z) { - return Biome.THE_VOID; - } - - @Override - public void setBiome(int x, int z, Biome bio) { - setBiome(x, 0, z, bio); - } - - @Override - public void setBiome(int x, int y, int z, Biome bio) { - if (y < 0) return; - y += getMinHeight(); - if (y > getMaxHeight()) return; - chunk.setBiome(x & 15, y, z & 15, CraftBiome.bukkitToMinecraftHolder(bio)); - } - - private LevelHeightAccessor height() { - return chunk; - } - - @Override - public int getMinHeight() { - return height().getMinBuildHeight(); - } - - @Override - public int getMaxHeight() { - return height().getMaxBuildHeight(); - } - - @Override - public void setBlock(int x, int y, int z, BlockData blockData) { - if (y < 0) return; - y += getMinHeight(); - if (y > getMaxHeight()) return; - - if (blockData == null) { - Iris.error("NULL BD"); - } - if (blockData instanceof IrisBlockData data) - blockData = data.getBase(); - if (!(blockData instanceof CraftBlockData craftBlockData)) - throw new IllegalArgumentException("Expected CraftBlockData, got " + blockData.getClass().getSimpleName() + " instead"); - chunk.setBlockState(new BlockPos(x & 15, y, z & 15), craftBlockData.getState(), false); - } - - private BlockState getBlockState(int x, int y, int z) { - if (y < 0) { - y = 0; - } - y += getMinHeight(); - if (y > getMaxHeight()) { - y = getMaxHeight(); - } - - return chunk.getBlockState(new BlockPos(x & 15, y, z & 15)); - } - - @NotNull - @Override - public org.bukkit.block.data.BlockData getBlockData(int x, int y, int z) { - return CraftBlockData.fromData(getBlockState(x, y, z)); - } - - @Override - public ChunkGenerator.ChunkData getRaw() { - return null; - } - - @Override - public void setRaw(ChunkGenerator.ChunkData data) { - - } - - @Override - @Deprecated - public void inject(ChunkGenerator.BiomeGrid biome) { - - } - - @Override - public void setBlock(int x, int y, int z, @NotNull Material material) { - - } - - @Override - @Deprecated - public void setBlock(int x, int y, int z, @NotNull MaterialData material) { - - } - - @Override - public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, @NotNull Material material) { - - } - - @Override - @Deprecated - public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, @NotNull MaterialData material) { - - } - - @Override - public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, @NotNull BlockData blockData) { - - } - - - @NotNull - @Override - public Material getType(int x, int y, int z) { - return getBlockData(x, y, z).getMaterial(); - } - - @NotNull - @Override - public MaterialData getTypeAndData(int x, int y, int z) { - return getBlockData(x, y, z).createBlockState().getData(); - } - - @Override - public byte getData(int x, int y, int z) { - return getTypeAndData(x, y, z).getData(); - } -} diff --git a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/mca/RegionFileStorage.java b/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/mca/RegionFileStorage.java deleted file mode 100644 index d7a9d1cee..000000000 --- a/nms/v1_20_R3/src/main/java/com/volmit/iris/core/nms/v1_20_R3/mca/RegionFileStorage.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.volmit.iris.core.nms.v1_20_R3.mca; - -import com.google.common.base.Preconditions; -import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import javax.annotation.Nullable; -import net.minecraft.FileUtil; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtAccounter; -import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.StreamTagVisitor; -import net.minecraft.util.ExceptionCollector; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.storage.RegionFile; - -public final class RegionFileStorage implements AutoCloseable { - public final Long2ObjectLinkedOpenHashMap regionCache = new Long2ObjectLinkedOpenHashMap<>(); - private final Path folder; - private final boolean sync; - - public RegionFileStorage(Path folder, boolean sync) { - this.folder = folder; - this.sync = sync; - } - - public RegionFile getRegionFile(ChunkPos chunkPos, boolean existingOnly) throws IOException { - long id = ChunkPos.asLong(chunkPos.getRegionX(), chunkPos.getRegionZ()); - RegionFile regionFile = this.regionCache.getAndMoveToFirst(id); - if (regionFile != null) { - return regionFile; - } else { - if (this.regionCache.size() >= 256) { - this.regionCache.removeLast().close(); - } - - FileUtil.createDirectoriesSafe(this.folder); - Path path = folder.resolve("r." + chunkPos.getRegionX() + "." + chunkPos.getRegionZ() + ".mca"); - if (existingOnly && !Files.exists(path)) { - return null; - } else { - regionFile = new RegionFile(path, this.folder, this.sync); - this.regionCache.putAndMoveToFirst(id, regionFile); - return regionFile; - } - } - } - - @Nullable - public CompoundTag read(ChunkPos chunkPos) throws IOException { - RegionFile regionFile = this.getRegionFile(chunkPos, true); - if (regionFile != null) { - try (DataInputStream datainputstream = regionFile.getChunkDataInputStream(chunkPos)) { - if (datainputstream != null) { - return NbtIo.read(datainputstream); - } - } - - } - return null; - } - - public void scanChunk(ChunkPos chunkPos, StreamTagVisitor visitor) throws IOException { - RegionFile regionFile = this.getRegionFile(chunkPos, true); - if (regionFile != null) { - try (DataInputStream din = regionFile.getChunkDataInputStream(chunkPos)) { - if (din != null) { - NbtIo.parse(din, visitor, NbtAccounter.unlimitedHeap()); - } - } - } - } - - public void write(ChunkPos chunkPos, @Nullable CompoundTag compound) throws IOException { - RegionFile regionFile = this.getRegionFile(chunkPos, false); - Preconditions.checkArgument(regionFile != null, "Failed to find region file for chunk %s", chunkPos); - if (compound == null) { - regionFile.clear(chunkPos); - } else { - try (DataOutputStream dos = regionFile.getChunkDataOutputStream(chunkPos)) { - NbtIo.write(compound, dos); - } - } - } - - @Override - public void close() throws IOException { - ExceptionCollector collector = new ExceptionCollector<>(); - - for (RegionFile regionFile : this.regionCache.values()) { - try { - regionFile.close(); - } catch (IOException e) { - collector.add(e); - } - } - - collector.throwIfPresent(); - } - - public void flush() throws IOException { - for (RegionFile regionfile : this.regionCache.values()) { - regionfile.flush(); - } - } -} \ No newline at end of file diff --git a/nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/CustomBiomeSource.java b/nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/CustomBiomeSource.java index a27c9a306..d37284c25 100644 --- a/nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/CustomBiomeSource.java +++ b/nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/CustomBiomeSource.java @@ -2,7 +2,6 @@ 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; @@ -125,16 +124,8 @@ public class CustomBiomeSource extends BiomeSource { for (IrisBiome i : engine.getAllBiomes()) { if (i.isCustom()) { for (IrisBiomeCustom j : i.getCustomDerivitives()) { - ResourceLocation location = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()); - Biome biome = customRegistry.get(location); - if (biome == null) { - INMS.get().registerBiome(location.getNamespace(), j, false); - biome = customRegistry.get(location); - if (biome == null) { - Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); - continue; - } - } + ResourceLocation resourceLocation = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()); + Biome biome = customRegistry.get(resourceLocation); Optional> optionalBiomeKey = customRegistry.getResourceKey(biome); if (optionalBiomeKey.isEmpty()) { Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName()); diff --git a/nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/NMSBinding.java b/nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/NMSBinding.java index 1ecfd0f7e..59f90620b 100644 --- a/nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/NMSBinding.java +++ b/nms/v1_20_R4/src/main/java/com/volmit/iris/core/nms/v1_20_R4/NMSBinding.java @@ -4,48 +4,18 @@ 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 java.util.logging.Logger; -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; @@ -59,7 +29,6 @@ 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; @@ -580,203 +549,4 @@ 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 Optional decode(Codec codec, String json) { - return codec.decode(JsonOps.INSTANCE, GsonHelper.parse(json)).result().map(Pair::getFirst); - } - - private Optional encode(Codec codec, T value) { - return codec.encode(value, JsonOps.INSTANCE, new JsonObject()).result(); - } - - private boolean register(ResourceKey> 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 boolean replace(ResourceKey> 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) toIdField.get(registry); - var byValue = (Map>) 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 MappedRegistry registry(ResourceKey> registryKey) { - var rawRegistry = registry().registry(registryKey).orElse(null); - if (!(rawRegistry instanceof MappedRegistry 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(CraftServer.class) - .visit(Advice.to(CraftServerAdvice.class).on(ElementMatchers.isMethod().and(ElementMatchers.takesArguments(WorldCreator.class)))) - .make() - .load(CraftServer.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 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 typeKey = ResourceKey.create(Registries.DIMENSION_TYPE, new ResourceLocation("iris", key.location().getPath())); - RegistryAccess registryAccess = server.registryAccess(); - Registry registry = registryAccess.registry(Registries.DIMENSION_TYPE).orElse(null); - if (registry == null) throw new IllegalStateException("Unable to find registry for dimension type " + typeKey); - Holder 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 CraftServerAdvice { - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - static boolean enter(@Advice.This CraftServer self, @Advice.Argument(0) WorldCreator creator) { - File isIrisWorld = new File(self.getWorldContainer(), creator.name() + "/iris"); - boolean isFromIris = false; - StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - for (StackTraceElement stack : stackTrace) { - if (stack.getClassName().contains("Iris")) { - isFromIris = true; - break; - } - } - if (isIrisWorld.exists() && !isFromIris) { - var logger = Logger.getLogger("Iris"); - logger.warning("detected another Plugin trying to load " + creator.name() + ". This is not supported and will be ignored."); - - if (System.getProperty("iris.debug", "false").equals("true")) { - new RuntimeException().printStackTrace(); - } - return true; - } - return false; - } - - @Advice.OnMethodExit - static void exit(@Advice.Enter boolean bool, @Advice.Return(readOnly = false) World returned) { - if (bool) { - returned = null; - } - } - } } diff --git a/settings.gradle b/settings.gradle index 2052a7afe..f1464496d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -22,8 +22,12 @@ pluginManagement { gradlePluginPortal() } } +plugins { + id "org.gradle.toolchains.foojay-resolver-convention" version "0.8.0" +} + rootProject.name = 'Iris' -//include 'app', 'com.volmit.gui' + include(':core') include( ':nms:v1_20_R4',