diff --git a/build.gradle b/build.gradle index ed5e204c3..e13410ee2 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) @@ -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..335207de5 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 ignoreBootMode = 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..e9774ceff 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().ignoreBootMode) { 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) { + 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/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 c0b7dbcd3..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 @@ -18,12 +18,15 @@ 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; @@ -38,6 +41,9 @@ 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 @@ -47,6 +53,73 @@ import org.bukkit.block.data.BlockData; 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<>(); @@ -64,6 +137,10 @@ public class IrisDimension extends IrisRegistrant { @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; @@ -152,6 +229,10 @@ public class IrisDimension extends IrisRegistrant { 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) @@ -294,14 +375,6 @@ public class IrisDimension extends IrisRegistrant { 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(""); } @@ -373,6 +446,63 @@ public class IrisDimension extends IrisRegistrant { 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"; @@ -387,4 +517,67 @@ public class IrisDimension extends IrisRegistrant { 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/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 9227e91e6..f1464496d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -27,7 +27,7 @@ plugins { } rootProject.name = 'Iris' -//include 'app', 'com.volmit.gui' + include(':core') include( ':nms:v1_20_R4',