diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java index a3c2eb4dd..656ba4791 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java @@ -1,10 +1,10 @@ package net.momirealms.craftengine.bukkit.compatibility; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; -import net.momirealms.craftengine.bukkit.compatibility.item.CustomFishingProvider; -import net.momirealms.craftengine.bukkit.compatibility.item.MMOItemsProvider; -import net.momirealms.craftengine.bukkit.compatibility.item.MythicMobsProvider; -import net.momirealms.craftengine.bukkit.compatibility.item.NeigeItemsProvider; +import net.momirealms.craftengine.bukkit.compatibility.item.CustomFishingSource; +import net.momirealms.craftengine.bukkit.compatibility.item.MMOItemsSource; +import net.momirealms.craftengine.bukkit.compatibility.item.MythicMobsSource; +import net.momirealms.craftengine.bukkit.compatibility.item.NeigeItemsSource; import net.momirealms.craftengine.bukkit.compatibility.legacy.slimeworld.LegacySlimeFormatStorageAdaptor; import net.momirealms.craftengine.bukkit.compatibility.leveler.*; import net.momirealms.craftengine.bukkit.compatibility.model.bettermodel.BetterModelModel; @@ -130,7 +130,7 @@ public class BukkitCompatibilityManager implements CompatibilityManager { logHook("EcoJobs"); } if (this.isPluginEnabled("MythicMobs")) { - BukkitItemManager.instance().registerExternalItemProvider(new MythicMobsProvider()); + BukkitItemManager.instance().registerExternalItemSource(new MythicMobsSource()); new MythicMobsListener(this.plugin); logHook("MythicMobs"); } @@ -247,15 +247,15 @@ public class BukkitCompatibilityManager implements CompatibilityManager { private void initItemHooks() { BukkitItemManager itemManager = BukkitItemManager.instance(); if (this.isPluginEnabled("NeigeItems")) { - itemManager.registerExternalItemProvider(new NeigeItemsProvider()); + itemManager.registerExternalItemSource(new NeigeItemsSource()); logHook("NeigeItems"); } if (this.isPluginEnabled("MMOItems")) { - itemManager.registerExternalItemProvider(new MMOItemsProvider()); + itemManager.registerExternalItemSource(new MMOItemsSource()); logHook("MMOItems"); } if (this.isPluginEnabled("CustomFishing")) { - itemManager.registerExternalItemProvider(new CustomFishingProvider()); + itemManager.registerExternalItemSource(new CustomFishingSource()); logHook("CustomFishing"); } } diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/CustomFishingProvider.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/CustomFishingSource.java similarity index 89% rename from bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/CustomFishingProvider.java rename to bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/CustomFishingSource.java index c8e7cbb25..e4e28368d 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/CustomFishingProvider.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/CustomFishingSource.java @@ -1,6 +1,6 @@ package net.momirealms.craftengine.bukkit.compatibility.item; -import net.momirealms.craftengine.core.item.ExternalItemProvider; +import net.momirealms.craftengine.core.item.ExternalItemSource; import net.momirealms.craftengine.core.item.ItemBuildContext; import net.momirealms.customfishing.api.BukkitCustomFishingPlugin; import net.momirealms.customfishing.api.mechanic.context.Context; @@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Optional; -public class CustomFishingProvider implements ExternalItemProvider { +public class CustomFishingSource implements ExternalItemSource { @Override public String plugin() { return "customfishing"; diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsProvider.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsSource.java similarity index 88% rename from bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsProvider.java rename to bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsSource.java index 8888553e4..b22e5595a 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsProvider.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MMOItemsSource.java @@ -3,7 +3,7 @@ package net.momirealms.craftengine.bukkit.compatibility.item; import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.Type; import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem; -import net.momirealms.craftengine.core.item.ExternalItemProvider; +import net.momirealms.craftengine.core.item.ExternalItemSource; import net.momirealms.craftengine.core.item.ItemBuildContext; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; @@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable; import static java.util.Objects.requireNonNull; -public class MMOItemsProvider implements ExternalItemProvider { +public class MMOItemsSource implements ExternalItemSource { @Override public String plugin() { diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MythicMobsProvider.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MythicMobsSource.java similarity index 86% rename from bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MythicMobsProvider.java rename to bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MythicMobsSource.java index 70c111499..67d974f20 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MythicMobsProvider.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/MythicMobsSource.java @@ -1,12 +1,12 @@ package net.momirealms.craftengine.bukkit.compatibility.item; import io.lumine.mythic.bukkit.MythicBukkit; -import net.momirealms.craftengine.core.item.ExternalItemProvider; +import net.momirealms.craftengine.core.item.ExternalItemSource; import net.momirealms.craftengine.core.item.ItemBuildContext; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; -public class MythicMobsProvider implements ExternalItemProvider { +public class MythicMobsSource implements ExternalItemSource { private MythicBukkit mythicBukkit; @Override diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/NeigeItemsProvider.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/NeigeItemsSource.java similarity index 83% rename from bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/NeigeItemsProvider.java rename to bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/NeigeItemsSource.java index a6b5ca3ec..5631f1dc9 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/NeigeItemsProvider.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/item/NeigeItemsSource.java @@ -1,6 +1,6 @@ package net.momirealms.craftengine.bukkit.compatibility.item; -import net.momirealms.craftengine.core.item.ExternalItemProvider; +import net.momirealms.craftengine.core.item.ExternalItemSource; import net.momirealms.craftengine.core.item.ItemBuildContext; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -8,7 +8,7 @@ import pers.neige.neigeitems.manager.ItemManager; import java.util.Optional; -public class NeigeItemsProvider implements ExternalItemProvider { +public class NeigeItemsSource implements ExternalItemSource { @Override public String plugin() { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index ab907daee..a4c4c12e7 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -81,15 +81,15 @@ public class BukkitItemManager extends AbstractItemManager { @Override public void delayedLoad() { super.delayedLoad(); - List> sources = new ArrayList<>(); + List> sources = new ArrayList<>(); for (String externalSource : Config.recipeIngredientSources()) { String sourceId = externalSource.toLowerCase(Locale.ENGLISH); - ExternalItemProvider provider = getExternalItemProvider(sourceId); + ExternalItemSource provider = getExternalItemSource(sourceId); if (provider != null) { sources.add(provider); } } - this.factory.resetRecipeIngredientSources(sources.isEmpty() ? null : sources.toArray(new ExternalItemProvider[0])); + this.factory.resetRecipeIngredientSources(sources.isEmpty() ? null : sources.toArray(new ExternalItemSource[0])); } @Override diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java index 7ea6d8056..42447daec 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java @@ -6,14 +6,13 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries; import net.momirealms.craftengine.bukkit.util.ItemTags; import net.momirealms.craftengine.bukkit.util.KeyUtils; -import net.momirealms.craftengine.core.item.ExternalItemProvider; +import net.momirealms.craftengine.core.item.ExternalItemSource; import net.momirealms.craftengine.core.item.ItemFactory; import net.momirealms.craftengine.core.item.ItemKeys; import net.momirealms.craftengine.core.item.ItemWrapper; import net.momirealms.craftengine.core.item.data.JukeboxPlayable; import net.momirealms.craftengine.core.item.setting.EquipmentData; import net.momirealms.craftengine.core.plugin.CraftEngine; -import net.momirealms.craftengine.core.util.CharacterUtils; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.StringUtils; import net.momirealms.craftengine.core.util.UniqueKey; @@ -21,13 +20,12 @@ import net.momirealms.sparrow.nbt.Tag; import org.bukkit.Bukkit; import org.bukkit.inventory.ItemStack; -import java.util.Locale; import java.util.Objects; import java.util.Optional; public abstract class BukkitItemFactory> extends ItemFactory { private boolean hasExternalRecipeSource = false; - private ExternalItemProvider[] recipeIngredientSources = null; + private ExternalItemSource[] recipeIngredientSources = null; protected BukkitItemFactory(CraftEngine plugin) { super(plugin); @@ -58,7 +56,7 @@ public abstract class BukkitItemFactory> extend } } - public void resetRecipeIngredientSources(ExternalItemProvider[] recipeIngredientSources) { + public void resetRecipeIngredientSources(ExternalItemSource[] recipeIngredientSources) { if (recipeIngredientSources == null || recipeIngredientSources.length == 0) { this.recipeIngredientSources = null; this.hasExternalRecipeSource = false; @@ -99,7 +97,7 @@ public abstract class BukkitItemFactory> extend @Override protected UniqueKey recipeIngredientID(W item) { if (this.hasExternalRecipeSource) { - for (ExternalItemProvider source : this.recipeIngredientSources) { + for (ExternalItemSource source : this.recipeIngredientSources) { String id = source.id(item.getItem()); if (id != null) { return UniqueKey.create(Key.of(source.plugin(), StringUtils.toLowerCase(id))); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java index 34a97ec8d..02b362da3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java @@ -45,7 +45,7 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl private final ItemParser itemParser; private final EquipmentParser equipmentParser; - protected final Map> externalItemProviders = new HashMap<>(); + protected final Map> externalItemSources = new HashMap<>(); protected final Map>> dataFunctions = new HashMap<>(); protected final Map> customItems = new HashMap<>(); protected final Map> customItemTags = new HashMap<>(); @@ -99,15 +99,15 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl } @Override - public ExternalItemProvider getExternalItemProvider(String name) { - return this.externalItemProviders.get(name); + public ExternalItemSource getExternalItemSource(String name) { + return this.externalItemSources.get(name); } @Override - public boolean registerExternalItemProvider(ExternalItemProvider externalItemProvider) { - if (!ResourceLocation.isValidNamespace(externalItemProvider.plugin())) return false; - if (this.externalItemProviders.containsKey(externalItemProvider.plugin())) return false; - this.externalItemProviders.put(externalItemProvider.plugin(), externalItemProvider); + public boolean registerExternalItemSource(ExternalItemSource externalItemSource) { + if (!ResourceLocation.isValidNamespace(externalItemSource.plugin())) return false; + if (this.externalItemSources.containsKey(externalItemSource.plugin())) return false; + this.externalItemSources.put(externalItemSource.plugin(), externalItemSource); return true; } @@ -511,7 +511,7 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl Map data = MiscUtils.castToMap(obj, false); String plugin = data.get("plugin").toString(); String id = data.get("id").toString(); - ExternalItemProvider provider = AbstractItemManager.this.getExternalItemProvider(plugin.toLowerCase(Locale.ENGLISH)); + ExternalItemSource provider = AbstractItemManager.this.getExternalItemSource(plugin.toLowerCase(Locale.ENGLISH)); return new ExternalModifier<>(id, Objects.requireNonNull(provider, "Item provider " + plugin + " not found")); }, "external"); if (VersionHelper.isOrAbove1_20_5()) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ExternalItemProvider.java b/core/src/main/java/net/momirealms/craftengine/core/item/ExternalItemSource.java similarity index 82% rename from core/src/main/java/net/momirealms/craftengine/core/item/ExternalItemProvider.java rename to core/src/main/java/net/momirealms/craftengine/core/item/ExternalItemSource.java index 14dd780d8..68daa3d67 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ExternalItemProvider.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ExternalItemSource.java @@ -2,7 +2,7 @@ package net.momirealms.craftengine.core.item; import org.jetbrains.annotations.Nullable; -public interface ExternalItemProvider { +public interface ExternalItemSource { String plugin(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java index 434ae4d65..9505da8f1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java @@ -61,9 +61,9 @@ public interface ItemManager extends Manageable, ModelGenerator { Key customItemId(T itemStack); - ExternalItemProvider getExternalItemProvider(String name); + ExternalItemSource getExternalItemSource(String name); - boolean registerExternalItemProvider(ExternalItemProvider externalItemProvider); + boolean registerExternalItemSource(ExternalItemSource externalItemSource); Optional getEquipment(Key key); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ExternalModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ExternalModifier.java index 95c52bd45..3acc923b8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ExternalModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ExternalModifier.java @@ -1,15 +1,15 @@ package net.momirealms.craftengine.core.item.modifier; -import net.momirealms.craftengine.core.item.ExternalItemProvider; +import net.momirealms.craftengine.core.item.ExternalItemSource; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.ItemBuildContext; import net.momirealms.craftengine.core.plugin.CraftEngine; public class ExternalModifier implements ItemDataModifier { private final String id; - private final ExternalItemProvider provider; + private final ExternalItemSource provider; - public ExternalModifier(String id, ExternalItemProvider provider) { + public ExternalModifier(String id, ExternalItemSource provider) { this.id = id; this.provider = provider; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java index 7cc4f0f3f..a78856e6f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java @@ -16,6 +16,7 @@ import net.momirealms.craftengine.core.plugin.classpath.ClassPathAppender; import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager; import net.momirealms.craftengine.core.plugin.command.sender.SenderFactory; import net.momirealms.craftengine.core.plugin.compatibility.CompatibilityManager; +import net.momirealms.craftengine.core.plugin.compatibility.PluginTaskRegistry; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.config.template.TemplateManager; import net.momirealms.craftengine.core.plugin.config.template.TemplateManagerImpl; @@ -37,6 +38,7 @@ import net.momirealms.craftengine.core.sound.SoundManager; import net.momirealms.craftengine.core.world.WorldManager; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Logger; +import org.jetbrains.annotations.ApiStatus; import java.util.ArrayList; import java.util.List; @@ -73,6 +75,9 @@ public abstract class CraftEngine implements Plugin { protected GlobalVariableManager globalVariableManager; protected ProjectileManager projectileManager; + private final PluginTaskRegistry preLoadTaskRegistry = new PluginTaskRegistry(); + private final PluginTaskRegistry postLoadTaskRegistry = new PluginTaskRegistry(); + private final Consumer reloadEventDispatcher; private boolean isReloading; private boolean isInitializing; @@ -205,6 +210,7 @@ public abstract class CraftEngine implements Plugin { this.commandManager.registerDefaultFeatures(); // delay the reload so other plugins can register some custom parsers this.scheduler.sync().runDelayed(() -> { + this.preLoadTaskRegistry.executeTasks(); this.registerDefaultParsers(); // hook external item plugins this.itemManager.delayedInit(); @@ -231,6 +237,7 @@ public abstract class CraftEngine implements Plugin { // set up some platform extra tasks this.platformDelayedEnable(); this.isInitializing = false; + this.postLoadTaskRegistry.executeTasks(); this.scheduler.executeAsync(() -> this.packManager.initCachedAssets()); }); } @@ -462,4 +469,14 @@ public abstract class CraftEngine implements Plugin { public Platform platform() { return platform; } + + @ApiStatus.Experimental + public PluginTaskRegistry preLoadTaskRegistry() { + return preLoadTaskRegistry; + } + + @ApiStatus.Experimental + public PluginTaskRegistry postLoadTaskRegistry() { + return postLoadTaskRegistry; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/Plugin.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/Plugin.java index 3521c3914..d1308dc45 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/Plugin.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/Plugin.java @@ -12,6 +12,7 @@ import net.momirealms.craftengine.core.pack.PackManager; import net.momirealms.craftengine.core.plugin.classpath.ClassPathAppender; import net.momirealms.craftengine.core.plugin.command.sender.SenderFactory; import net.momirealms.craftengine.core.plugin.compatibility.CompatibilityManager; +import net.momirealms.craftengine.core.plugin.compatibility.PluginTaskRegistry; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.config.template.TemplateManager; import net.momirealms.craftengine.core.plugin.context.GlobalVariableManager; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/compatibility/PluginTask.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/compatibility/PluginTask.java new file mode 100644 index 000000000..f6c360f09 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/compatibility/PluginTask.java @@ -0,0 +1,74 @@ +package net.momirealms.craftengine.core.plugin.compatibility; + +public final class PluginTask { + private final Runnable task; + private final Priority priority; + private final String plugin; + + private PluginTask(Runnable task, String plugin, Priority priority) { + this.task = task; + this.priority = priority; + this.plugin = plugin; + } + + public static PluginTask create(Runnable task, String plugin, Priority priority) { + return new PluginTask(task, plugin, priority); + } + + public static PluginTask create(Runnable task, String plugin) { + return new PluginTask(task, plugin, Priority.tail()); + } + + public String plugin() { + return plugin; + } + + public Priority priority() { + return priority; + } + + public Runnable task() { + return task; + } + + public static class Priority { + public enum Position { + BEFORE_PLUGIN, + AFTER_PLUGIN, + HEAD, + TAIL + } + + private final Position position; + private final String relativePlugin; + + private Priority(Position position, String relativePlugin) { + this.position = position; + this.relativePlugin = relativePlugin; + } + + public static Priority before(String pluginName) { + return new Priority(Position.BEFORE_PLUGIN, pluginName); + } + + public static Priority after(String pluginName) { + return new Priority(Position.AFTER_PLUGIN, pluginName); + } + + public static Priority head() { + return new Priority(Position.HEAD, null); + } + + public static Priority tail() { + return new Priority(Position.TAIL, null); + } + + Position position() { + return position; + } + + String relativePlugin() { + return relativePlugin; + } + } +} \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/compatibility/PluginTaskRegistry.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/compatibility/PluginTaskRegistry.java new file mode 100644 index 000000000..6635db6fc --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/compatibility/PluginTaskRegistry.java @@ -0,0 +1,97 @@ +package net.momirealms.craftengine.core.plugin.compatibility; + +import java.util.HashMap; +import java.util.Map; + +public final class PluginTaskRegistry { + private static class Node { + final PluginTask task; + Node prev; + Node next; + + Node(PluginTask task) { + this.task = task; + } + } + + private final Node head = new Node(null); // 哨兵头节点 + private final Node tail = new Node(null); // 哨兵尾节点 + private final Map pluginNodeMap = new HashMap<>(); + + public PluginTaskRegistry() { + head.next = tail; + tail.prev = head; + } + + public void registerTask(PluginTask task) { + PluginTask.Priority priority = task.priority(); + Node newNode = new Node(task); + String pluginName = task.plugin(); + + if (this.pluginNodeMap.containsKey(pluginName)) { + throw new IllegalArgumentException("Duplicate task for plugin: " + pluginName); + } + + switch (priority.position()) { + case HEAD: + insertAfter(this.head, newNode); + break; + case TAIL: + insertBefore(this.tail, newNode); + break; + case BEFORE_PLUGIN: + Node targetBefore = this.pluginNodeMap.get(priority.relativePlugin()); + if (targetBefore == null) { + throw new IllegalArgumentException("Target plugin not found: " + priority.relativePlugin()); + } + insertBefore(targetBefore, newNode); + break; + case AFTER_PLUGIN: + Node targetAfter =this. pluginNodeMap.get(priority.relativePlugin()); + if (targetAfter == null) { + throw new IllegalArgumentException("Target plugin not found: " + priority.relativePlugin()); + } + insertAfter(targetAfter, newNode); + break; + } + + this.pluginNodeMap.put(pluginName, newNode); + } + + private void insertAfter(Node existing, Node newNode) { + newNode.next = existing.next; + newNode.prev = existing; + existing.next.prev = newNode; + existing.next = newNode; + } + + private void insertBefore(Node existing, Node newNode) { + newNode.prev = existing.prev; + newNode.next = existing; + existing.prev.next = newNode; + existing.prev = newNode; + } + + public void executeTasks() { + try { + Node current = head.next; + while (current != tail) { + current.task.task().run(); + current = current.next; + } + } catch (Throwable ignored) { + // 不要管其他插件的异常,应该他们自己处理 + } + } + + public String getExecutionOrder() { + StringBuilder sb = new StringBuilder(); + Node current = head.next; + while (current != tail) { + sb.append(current.task.plugin()); + if (current.next != tail) sb.append(" -> "); + current = current.next; + } + return sb.toString(); + } +} \ No newline at end of file