diff --git a/src/main/java/com/volmit/iris/Iris.java b/src/main/java/com/volmit/iris/Iris.java index 3c158e99f..4dd11a222 100644 --- a/src/main/java/com/volmit/iris/Iris.java +++ b/src/main/java/com/volmit/iris/Iris.java @@ -26,7 +26,7 @@ import com.volmit.iris.core.link.BKLink; import com.volmit.iris.core.link.MultiverseCoreLink; import com.volmit.iris.core.link.MythicMobsLink; import com.volmit.iris.core.nms.INMS; -import com.volmit.iris.engine.IrisWorlds; +import com.volmit.iris.core.tools.IrisWorlds; import com.volmit.iris.engine.framework.EngineCompositeGenerator; import com.volmit.iris.engine.object.IrisBiome; import com.volmit.iris.engine.object.IrisBiomeCustom; diff --git a/src/main/java/com/volmit/iris/core/tools/IrisCreator.java b/src/main/java/com/volmit/iris/core/tools/IrisCreator.java new file mode 100644 index 000000000..1417e3fa7 --- /dev/null +++ b/src/main/java/com/volmit/iris/core/tools/IrisCreator.java @@ -0,0 +1,237 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 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.tools; + +import com.volmit.iris.core.IrisSettings; +import com.volmit.iris.core.pregenerator.PregenTask; +import com.volmit.iris.engine.framework.IrisAccess; +import com.volmit.iris.engine.headless.HeadlessWorld; +import com.volmit.iris.engine.object.IrisDimension; +import com.volmit.iris.util.exceptions.IrisException; +import com.volmit.iris.util.exceptions.MissingDimensionException; +import com.volmit.iris.util.format.C; +import com.volmit.iris.util.format.Form; +import com.volmit.iris.util.math.RNG; +import com.volmit.iris.util.plugin.VolmitSender; +import com.volmit.iris.util.scheduling.J; +import com.volmit.iris.util.scheduling.O; +import lombok.Data; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.WorldCreator; + +import java.util.function.Consumer; + +/** + * Makes it a lot easier to setup an engine, world, studio or whatever + */ +@Data +@Accessors(fluent = true, chain = true) +public class IrisCreator { + /** + * Specify an area to pregenerate during creation + */ + private PregenTask pregen; + + /** + * Specify a sender to get updates & progress info + tp when world is created. + */ + private VolmitSender sender; + + /** + * The seed to use for this generator + */ + private long seed = RNG.r.nextLong(); + + /** + * The dimension to use. This can be any online dimension, or a dimension in the + * packs folder + */ + private String dimension = IrisSettings.get().getGenerator().getDefaultWorldType(); + + /** + * The name of this world. + */ + private String name = "irisworld"; + + /** + * Headless mode allows Iris to generate / query engine information + * without needing an actual world loaded. This is normally only used + * for pregeneration purposes but it could be used for mapping. + */ + private boolean headless = false; + + /** + * Studio mode makes the engine hotloadable and uses the dimension in + * your Iris/packs folder instead of copying the dimension files into + * the world itself. Studio worlds are deleted when they are unloaded. + */ + private boolean studio = false; + + /** + * Create the IrisAccess (contains the world) + * @return the IrisAccess + * @throws IrisException shit happens + */ + public IrisAccess create() throws IrisException { + IrisDimension d = IrisToolbelt.getDimension(dimension()); + IrisAccess access = null; + Consumer prog = (pxx) -> { + double px = (headless && pregen!=null) ? pxx/2 : pxx; + + if(pregen != null && !headless) + { + px = (px / 2) + 0.5; + } + + if(sender != null) + { + if(sender.isPlayer()) + { + sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generating " + Form.pc(px))); + } + + else + { + sender.sendMessage("Generating " + Form.f(px, 0)); + } + } + }; + + if(d == null) + { + throw new MissingDimensionException("Cannot find dimension '" + dimension() + "'"); + } + + if (headless) + { + HeadlessWorld w = new HeadlessWorld(name, d, seed, studio); + access = w.generate().getGenerator(); + } + + else + { + O done = new O<>(); + done.set(false); + WorldCreator wc = new IrisWorldCreator() + .dimension(dimension) + .name(name) + .seed(seed) + .studio(studio) + .create(); + access = (IrisAccess) wc.generator(); + IrisAccess finalAccess1 = access; + + J.a(() -> + { + int req = 400; + + while (finalAccess1.getGenerated() < req && !done.get()) { + double v = (double) finalAccess1.getGenerated() / (double) req; + + if(pregen != null) + { + v /=2; + } + + if (sender.isPlayer()) { + sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess1.getGenerated()) + " Left)")))); + J.sleep(50); + } else { + sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess1.getGenerated()) + " Left)"))); + J.sleep(1000); + } + + if (finalAccess1.isFailing()) { + + sender.sendMessage("Generation Failed!"); + break; + } + } + + sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generation Complete")); + }); + + wc.createWorld(); + done.set(true); + } + + if(access == null) + { + throw new IrisException("Access is null. Something bad happened."); + } + + IrisAccess finalAccess = access; + Runnable loadup = () -> { + try { + J.sfut(() -> { + if(headless) + { + O done = new O<>(); + done.set(false); + + J.a(() -> + { + int req = 400; + + while (finalAccess.getGenerated() < req && !done.get()) { + double v = (double) finalAccess.getGenerated() / (double) req; + v = (v/2) + 0.5; + + if (sender.isPlayer()) { + sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess.getGenerated()) + " Left)")))); + J.sleep(50); + } else { + sender.sendMessage(C.WHITE + "Generating " + Form.pc(v) + ((C.GRAY + " (" + (req - finalAccess.getGenerated()) + " Left)"))); + J.sleep(1000); + } + + if (finalAccess.isFailing()) { + + sender.sendMessage("Generation Failed!"); + break; + } + } + + sender.player().spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(C.WHITE + "Generation Complete")); + }); + + finalAccess.getHeadlessGenerator().getWorld().load(); + done.set(true); + } + }).get(); + } catch (Throwable e) { + e.printStackTrace(); + } + }; + + if(pregen != null) + { + IrisToolbelt.pregenerate(pregen, access).onProgress(prog).whenDone(loadup); + } + + else + { + loadup.run(); + } + + return access; + } +} diff --git a/src/main/java/com/volmit/iris/core/tools/IrisToolbelt.java b/src/main/java/com/volmit/iris/core/tools/IrisToolbelt.java new file mode 100644 index 000000000..0ed4da091 --- /dev/null +++ b/src/main/java/com/volmit/iris/core/tools/IrisToolbelt.java @@ -0,0 +1,166 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 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.tools; + +import com.volmit.iris.Iris; +import com.volmit.iris.core.IrisDataManager; +import com.volmit.iris.core.gui.PregeneratorJob; +import com.volmit.iris.core.pregenerator.PregenTask; +import com.volmit.iris.core.pregenerator.PregeneratorMethod; +import com.volmit.iris.core.pregenerator.methods.HeadlessPregenMethod; +import com.volmit.iris.core.pregenerator.methods.HybridPregenMethod; +import com.volmit.iris.engine.framework.IrisAccess; +import com.volmit.iris.engine.object.IrisDimension; +import com.volmit.iris.util.math.Position2; +import com.volmit.iris.util.plugin.VolmitSender; +import org.bukkit.Bukkit; +import org.bukkit.World; + +import java.io.File; + +/** + * Something you really want to wear if working on Iris. Shit gets pretty hectic down there. + * Hope you packed snacks & road sodas. + */ +public class IrisToolbelt { + /** + * Will find / download / search for the dimension or return null + * + * - You can provide a dimenson in the packs folder by the folder name + * - You can provide a github repo by using (assumes branch is master unless specified) + * - GithubUsername/repository + * - GithubUsername/repository/branch + * + * @param dimension the dimension id such as overworld or flat + * @return the IrisDimension or null + */ + public static IrisDimension getDimension(String dimension) + { + File pack = Iris.instance.getDataFolder("packs", dimension); + + if(!pack.exists()) + { + Iris.proj.downloadSearch(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag()), dimension, false, false); + } + + if(!pack.exists()) + { + return null; + } + + return new IrisDataManager(pack).getDimensionLoader().load(dimension); + } + + /** + * Create a world with plenty of options + * @return the creator builder + */ + public static IrisCreator createWorld() + { + return new IrisCreator(); + } + + /** + * Checks if the given world is an Iris World (same as access(world) != null) + * @param world the world + * @return true if it is an Iris Access world + */ + public static boolean isIrisWorld(World world) + { + return access(world) != null; + } + + /** + * Get the Iris generator for the given world + * @param world the given world + * @return the IrisAccess or null if it's not an Iris World + */ + public static IrisAccess access(World world) + { + return IrisWorlds.access(world); + } + + /** + * Start a pregenerator task + * @param task the scheduled task + * @param method the method to execute the task + * @return the pregenerator job (already started) + */ + public static PregeneratorJob pregenerate(PregenTask task, PregeneratorMethod method) + { + return new PregeneratorJob(task, method); + } + + /** + * Start a pregenerator task. If the supplied generator is headless, headless mode is used, + * otherwise Hybrid mode is used. + * @param task the scheduled task + * @param access the Iris Generator + * @return the pregenerator job (already started) + */ + public static PregeneratorJob pregenerate(PregenTask task, IrisAccess access) + { + if(access.isHeadless()) + { + return pregenerate(task, new HeadlessPregenMethod(access.getHeadlessGenerator().getWorld(), access.getHeadlessGenerator())); + } + + return pregenerate(task, new HybridPregenMethod(access.getCompound().getWorld().realWorld(), Runtime.getRuntime().availableProcessors())); + } + + /** + * Evacuate all players from the world into literally any other world. + * If there are no other worlds, kick them! Not the best but what's mine is mine sometimes... + * @param world the world to evac + */ + public static void evacuate(World world) + { + IrisWorlds.evacuate(world); + } + + public static void test() + { + // Get IrisDataManager from a world + IrisToolbelt.access(anyWorld).getCompound().getData(); + + // Get Default Engine from world + IrisToolbelt.access(anyWorld).getCompound().getDefaultEngine(); + + // Get the engine at the given height + IrisToolbelt.access(anyWorld).getCompound().getEngineForHeight(68); + + // IS THIS THING ON? + boolean yes = IrisToolbelt.isIrisWorld(world); + + // GTFO for worlds (moves players to any other world, just not this one) + IrisToolbelt.evacuate(world); + + IrisAccess access = IrisToolbelt.createWorld() // If you like builders... + .name("myWorld") // The world name + .dimension("terrifyinghands") + .seed(69133742) // The world seed + .headless(true) // Headless make gen go fast + .pregen(PregenTask // Define a pregen job to run + .builder() + .center(new Position2(0,0)) // REGION coords (1 region = 32x32 chunks) + .radius(4) // Radius in REGIONS. Rad of 4 means a 9x9 Region map. + .build()) + .create(); + } +} diff --git a/src/main/java/com/volmit/iris/engine/object/common/IrisWorld.java b/src/main/java/com/volmit/iris/engine/object/common/IrisWorld.java index 3d1f5b2c9..6c091baac 100644 --- a/src/main/java/com/volmit/iris/engine/object/common/IrisWorld.java +++ b/src/main/java/com/volmit/iris/engine/object/common/IrisWorld.java @@ -19,7 +19,7 @@ package com.volmit.iris.engine.object.common; import com.volmit.iris.Iris; -import com.volmit.iris.engine.IrisWorlds; +import com.volmit.iris.core.tools.IrisWorlds; import com.volmit.iris.util.collection.KList; import lombok.Builder; import lombok.Data; @@ -27,7 +27,6 @@ import lombok.experimental.Accessors; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import java.io.File; diff --git a/src/main/java/com/volmit/iris/util/exceptions/IrisException.java b/src/main/java/com/volmit/iris/util/exceptions/IrisException.java new file mode 100644 index 000000000..5062f3469 --- /dev/null +++ b/src/main/java/com/volmit/iris/util/exceptions/IrisException.java @@ -0,0 +1,30 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 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.util.exceptions; + +public class IrisException extends Exception +{ + public IrisException() { + super(); + } + + public IrisException(String message) { + super(message); + } +} diff --git a/src/main/java/com/volmit/iris/util/exceptions/MissingDimensionException.java b/src/main/java/com/volmit/iris/util/exceptions/MissingDimensionException.java new file mode 100644 index 000000000..f8be9797c --- /dev/null +++ b/src/main/java/com/volmit/iris/util/exceptions/MissingDimensionException.java @@ -0,0 +1,30 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 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.util.exceptions; + +public class MissingDimensionException extends IrisException +{ + public MissingDimensionException() { + super(); + } + + public MissingDimensionException(String message) { + super(message); + } +}