From 34884efd0bfb2ba644624067df46fc3165ae840e Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Tue, 22 Sep 2026 21:48:22 +0200 Subject: [PATCH 1/5] Add per-feature enable/disable system via modules.yml Signed-off-by: Martin Sulikowski --- .../com/eternalcode/core/EternalCore.java | 19 +- .../feature/adminchat/AdminchatModule.java | 11 ++ .../core/feature/afk/AfkModule.java | 11 ++ .../automessage/AutoMessageModule.java | 11 ++ .../core/feature/back/BackModule.java | 11 ++ .../feature/broadcast/BroadcastModule.java | 11 ++ .../core/feature/burn/BurnModule.java | 11 ++ .../core/feature/butcher/ButcherModule.java | 11 ++ .../core/feature/chat/ChatModule.java | 11 ++ .../core/feature/clear/ClearModule.java | 11 ++ .../feature/container/ContainerModule.java | 11 ++ .../customcommand/CustomCommandModule.java | 11 ++ .../deathmessage/DeathMessageModule.java | 11 ++ .../deathteleport/DeathTeleportModule.java | 11 ++ .../core/feature/disposal/DisposalModule.java | 11 ++ .../core/feature/enchant/EnchantModule.java | 11 ++ .../core/feature/feed/FeedModule.java | 11 ++ .../core/feature/fireball/FireballModule.java | 11 ++ .../core/feature/fly/FlyModule.java | 11 ++ .../core/feature/freeze/FreezeModule.java | 11 ++ .../FullServerBypassModule.java | 11 ++ .../core/feature/fun/FunModule.java | 11 ++ .../core/feature/gamemode/GamemodeModule.java | 11 ++ .../core/feature/give/GiveModule.java | 11 ++ .../core/feature/godmode/GodmodeModule.java | 11 ++ .../core/feature/hat/HatModule.java | 11 ++ .../core/feature/heal/HealModule.java | 11 ++ .../core/feature/helpop/HelpOpModule.java | 11 ++ .../core/feature/home/HomeModule.java | 11 ++ .../core/feature/ignore/IgnoreModule.java | 11 ++ .../core/feature/item/ItemModule.java | 11 ++ .../core/feature/itemedit/ItemEditModule.java | 11 ++ .../core/feature/jail/JailModule.java | 11 ++ .../joinmessage/JoinMessageModule.java | 11 ++ .../core/feature/kill/KillModule.java | 11 ++ .../core/feature/lag/LagModule.java | 11 ++ .../feature/lightning/LightningModule.java | 11 ++ .../feature/mobignore/MobIgnoreModule.java | 11 ++ .../core/feature/motd/MotdModule.java | 11 ++ .../core/feature/msg/MsgModule.java | 11 ++ .../core/feature/near/NearModule.java | 11 ++ .../onlineplayers/OnlinePlayersModule.java | 11 ++ .../core/feature/ping/PingModule.java | 11 ++ .../core/feature/playtime/PlaytimeModule.java | 11 ++ .../feature/powertool/PowertoolModule.java | 11 ++ .../quitmessage/QuitMessageModule.java | 11 ++ .../randomteleport/RandomTeleportModule.java | 11 ++ .../core/feature/repair/RepairModule.java | 11 ++ .../core/feature/seen/SeenModule.java | 11 ++ .../serverlinks/ServerLinksModule.java | 11 ++ .../core/feature/setslot/SetSlotModule.java | 11 ++ .../feature/signeditor/SignEditorModule.java | 11 ++ .../core/feature/skull/SkullModule.java | 11 ++ .../core/feature/sleep/SleepModule.java | 11 ++ .../core/feature/spawn/SpawnModule.java | 11 ++ .../core/feature/speed/SpeedModule.java | 11 ++ .../core/feature/sudo/SudoModule.java | 11 ++ .../core/feature/teleport/TeleportModule.java | 11 ++ .../TeleportOfflineModule.java | 11 ++ .../TeleportRandomPlayerModule.java | 11 ++ .../TeleportRequestModule.java | 11 ++ .../core/feature/time/TimeModule.java | 11 ++ .../core/feature/vanish/VanishModule.java | 11 ++ .../core/feature/warp/WarpModule.java | 11 ++ .../core/feature/weather/WeatherModule.java | 11 ++ .../core/feature/whois/WhoisModule.java | 11 ++ .../core/modules/ModuleDependencyGraph.java | 60 ++++++ .../core/modules/ModuleDescription.java | 14 ++ .../core/modules/ModuleService.java | 183 ++++++++++++++++++ .../core/modules/ModulesConfig.java | 23 +++ .../testdependent/DependentComponent.java | 12 ++ .../feature/testrequired/RequiredService.java | 7 + 72 files changed, 1032 insertions(+), 1 deletion(-) create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/adminchat/AdminchatModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/afk/AfkModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/automessage/AutoMessageModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/back/BackModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/broadcast/BroadcastModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/burn/BurnModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/butcher/ButcherModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/chat/ChatModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/clear/ClearModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/container/ContainerModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/customcommand/CustomCommandModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/deathmessage/DeathMessageModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/deathteleport/DeathTeleportModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/disposal/DisposalModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/enchant/EnchantModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/feed/FeedModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/fireball/FireballModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/fly/FlyModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/freeze/FreezeModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/fullserverbypass/FullServerBypassModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/fun/FunModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/gamemode/GamemodeModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/give/GiveModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/godmode/GodmodeModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/hat/HatModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/heal/HealModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/helpop/HelpOpModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/home/HomeModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/ignore/IgnoreModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/item/ItemModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/itemedit/ItemEditModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/jail/JailModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/joinmessage/JoinMessageModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/kill/KillModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/lag/LagModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/lightning/LightningModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/mobignore/MobIgnoreModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/motd/MotdModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/msg/MsgModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/near/NearModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/onlineplayers/OnlinePlayersModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/ping/PingModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/playtime/PlaytimeModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/powertool/PowertoolModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/quitmessage/QuitMessageModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/randomteleport/RandomTeleportModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/repair/RepairModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/seen/SeenModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/serverlinks/ServerLinksModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/setslot/SetSlotModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/signeditor/SignEditorModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/skull/SkullModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/sleep/SleepModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/spawn/SpawnModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/speed/SpeedModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/sudo/SudoModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportoffline/TeleportOfflineModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrandomplayer/TeleportRandomPlayerModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/TeleportRequestModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/time/TimeModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/vanish/VanishModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/weather/WeatherModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/feature/whois/WhoisModule.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleDependencyGraph.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleDescription.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/modules/ModulesConfig.java create mode 100644 eternalcore-core/src/test/java/com/eternalcode/core/feature/testdependent/DependentComponent.java create mode 100644 eternalcore-core/src/test/java/com/eternalcode/core/feature/testrequired/RequiredService.java diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/EternalCore.java b/eternalcore-core/src/main/java/com/eternalcode/core/EternalCore.java index 49be17f43..ac3c08f2d 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/EternalCore.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/EternalCore.java @@ -21,17 +21,20 @@ import com.eternalcode.core.injector.bean.processor.BeanProcessor; import com.eternalcode.core.injector.bean.processor.BeanProcessorFactory; import com.eternalcode.core.injector.scan.DependencyScanner; +import com.eternalcode.core.modules.ModuleService; import com.eternalcode.core.publish.Publisher; import com.eternalcode.core.publish.event.EternalInitializeEvent; import com.eternalcode.core.publish.event.EternalShutdownEvent; import dev.rollczi.litecommands.annotations.command.Command; import dev.rollczi.litecommands.annotations.command.RootCommand; +import java.util.stream.Collectors; import org.bukkit.Server; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginManager; import java.io.File; +import java.util.List; import java.util.logging.Logger; class EternalCore { @@ -42,6 +45,7 @@ public EternalCore(Plugin plugin) { EternalCoreEnvironment environment = new EternalCoreEnvironment(plugin.getLogger()); CompatibilityService compatibilityService = new CompatibilityService(); + ModuleService moduleService = new ModuleService(plugin.getDataFolder(), plugin.getLogger()); BeanProcessor beanProcessor = BeanProcessorFactory.defaultProcessors(plugin); BeanFactory beanFactory = new BeanFactory(beanProcessor) .withCandidateSelf() @@ -75,7 +79,20 @@ public EternalCore(Plugin plugin) { beanFactory.addCandidate(DependencyInjector.class, () -> injector); - for (BeanCandidate beanCandidate : scanner.scan(EternalCore.class.getPackage())) { + List beanCandidates = scanner.scan(EternalCore.class.getPackage()); + List> scannedTypes = beanCandidates.stream().map(BeanCandidate::getType).collect(Collectors.toList()); + + moduleService.registerDiscoveredModules(scannedTypes); + moduleService.loadModuleDescriptions(EternalCore.class.getClassLoader()); + moduleService.resolveEffectiveState(scannedTypes); + moduleService.writeModulesFile(); + moduleService.logDisabledModules(); + + for (BeanCandidate beanCandidate : beanCandidates) { + if (!moduleService.isEnabled(beanCandidate.getType())) { + continue; + } + beanFactory.addCandidate(beanCandidate); } diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/adminchat/AdminchatModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/adminchat/AdminchatModule.java new file mode 100644 index 000000000..4c87af7e9 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/adminchat/AdminchatModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.adminchat; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Private staff chat channel for players with the admin chat permission (/adminchat).") +final class AdminchatModule { + + private AdminchatModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/afk/AfkModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/afk/AfkModule.java new file mode 100644 index 000000000..0f9e1de9c --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/afk/AfkModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.afk; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Marks players as AFK after inactivity (or via /afk) and can kick them while idle.") +final class AfkModule { + + private AfkModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/automessage/AutoMessageModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/automessage/AutoMessageModule.java new file mode 100644 index 000000000..5b2c1c1a0 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/automessage/AutoMessageModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.automessage; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Periodically broadcasts a rotating set of messages to the server.") +final class AutoMessageModule { + + private AutoMessageModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/back/BackModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/back/BackModule.java new file mode 100644 index 000000000..bfb8fba9e --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/back/BackModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.back; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Lets players return to their previous location with /back.") +final class BackModule { + + private BackModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/broadcast/BroadcastModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/broadcast/BroadcastModule.java new file mode 100644 index 000000000..050e4f7fc --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/broadcast/BroadcastModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.broadcast; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Sends a formatted announcement to the whole server (/broadcast).") +final class BroadcastModule { + + private BroadcastModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/burn/BurnModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/burn/BurnModule.java new file mode 100644 index 000000000..4ec1393e6 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/burn/BurnModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.burn; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Sets a player on fire for a duration (/burn).") +final class BurnModule { + + private BurnModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/butcher/ButcherModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/butcher/ButcherModule.java new file mode 100644 index 000000000..b75a6c434 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/butcher/ButcherModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.butcher; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Bulk-removes nearby entities like mobs or dropped items (/butcher).") +final class ButcherModule { + + private ButcherModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/chat/ChatModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/chat/ChatModule.java new file mode 100644 index 000000000..20e2f6dea --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/chat/ChatModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.chat; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Formats and manages the public chat channel.") +final class ChatModule { + + private ChatModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/clear/ClearModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/clear/ClearModule.java new file mode 100644 index 000000000..944aac6a7 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/clear/ClearModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.clear; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Clears a player's inventory (/clear).") +final class ClearModule { + + private ClearModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/container/ContainerModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/container/ContainerModule.java new file mode 100644 index 000000000..bd643a825 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/container/ContainerModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.container; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Opens portable virtual containers (anvil, enderchest, grindstone, loom, etc.) without needing the block.") +final class ContainerModule { + + private ContainerModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/customcommand/CustomCommandModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/customcommand/CustomCommandModule.java new file mode 100644 index 000000000..ee7a23827 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/customcommand/CustomCommandModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.customcommand; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Lets admins define custom commands that run a set of actions or send a message.") +final class CustomCommandModule { + + private CustomCommandModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/deathmessage/DeathMessageModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/deathmessage/DeathMessageModule.java new file mode 100644 index 000000000..b428a9135 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/deathmessage/DeathMessageModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.deathmessage; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Sends a customizable death message to the server when a player dies.") +final class DeathMessageModule { + + private DeathMessageModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/deathteleport/DeathTeleportModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/deathteleport/DeathTeleportModule.java new file mode 100644 index 000000000..dd4d4cea0 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/deathteleport/DeathTeleportModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.deathteleport; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Automatically teleports players back to their death location after respawning.") +final class DeathTeleportModule { + + private DeathTeleportModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/disposal/DisposalModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/disposal/DisposalModule.java new file mode 100644 index 000000000..52d2e0c3a --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/disposal/DisposalModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.disposal; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Opens a virtual trash can inventory to destroy unwanted items (/disposal).") +final class DisposalModule { + + private DisposalModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/enchant/EnchantModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/enchant/EnchantModule.java new file mode 100644 index 000000000..87b6419ff --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/enchant/EnchantModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.enchant; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Lets players enchant items directly (/enchant).") +final class EnchantModule { + + private EnchantModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/feed/FeedModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/feed/FeedModule.java new file mode 100644 index 000000000..37e7fd2c4 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/feed/FeedModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.feed; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Restores a player's hunger and saturation (/feed).") +final class FeedModule { + + private FeedModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/fireball/FireballModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/fireball/FireballModule.java new file mode 100644 index 000000000..686945571 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/fireball/FireballModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.fireball; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Lets players launch fireballs (/fireball).") +final class FireballModule { + + private FireballModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/fly/FlyModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/fly/FlyModule.java new file mode 100644 index 000000000..ef1d23655 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/fly/FlyModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.fly; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Toggles flight mode for players (/fly).") +final class FlyModule { + + private FlyModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/freeze/FreezeModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/freeze/FreezeModule.java new file mode 100644 index 000000000..41bfcf156 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/freeze/FreezeModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.freeze; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Freezes a player in place until unfrozen (/freeze, /unfreeze).") +final class FreezeModule { + + private FreezeModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/fullserverbypass/FullServerBypassModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/fullserverbypass/FullServerBypassModule.java new file mode 100644 index 000000000..857354bfe --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/fullserverbypass/FullServerBypassModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.fullserverbypass; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Lets players with permission join even when the server is full.") +final class FullServerBypassModule { + + private FullServerBypassModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/fun/FunModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/fun/FunModule.java new file mode 100644 index 000000000..867452518 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/fun/FunModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.fun; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Cosmetic screen-effect commands (catboy, demoscreen, elderguardian, endscreen).") +final class FunModule { + + private FunModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/gamemode/GamemodeModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/gamemode/GamemodeModule.java new file mode 100644 index 000000000..5969e6baf --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/gamemode/GamemodeModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.gamemode; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Changes a player's game mode (/gamemode).") +final class GamemodeModule { + + private GamemodeModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/give/GiveModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/give/GiveModule.java new file mode 100644 index 000000000..3caab07e8 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/give/GiveModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.give; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Gives items to players (/give).") +final class GiveModule { + + private GiveModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/godmode/GodmodeModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/godmode/GodmodeModule.java new file mode 100644 index 000000000..590ccf037 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/godmode/GodmodeModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.godmode; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Makes a player invulnerable to damage (/god).") +final class GodmodeModule { + + private GodmodeModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/hat/HatModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/hat/HatModule.java new file mode 100644 index 000000000..c877d4bbc --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/hat/HatModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.hat; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Lets players wear the item in their hand as a hat (/hat).") +final class HatModule { + + private HatModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/heal/HealModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/heal/HealModule.java new file mode 100644 index 000000000..5d112e64b --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/heal/HealModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.heal; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Restores a player's health (/heal).") +final class HealModule { + + private HealModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/helpop/HelpOpModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/helpop/HelpOpModule.java new file mode 100644 index 000000000..f8aa4019d --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/helpop/HelpOpModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.helpop; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Lets players request help from staff (/helpop).") +final class HelpOpModule { + + private HelpOpModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/home/HomeModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/home/HomeModule.java new file mode 100644 index 000000000..d24847b6e --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/home/HomeModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.home; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Player homes: set, teleport to and manage multiple named locations (/home, /sethome, /delhome).") +final class HomeModule { + + private HomeModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/ignore/IgnoreModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/ignore/IgnoreModule.java new file mode 100644 index 000000000..b884e694f --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/ignore/IgnoreModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.ignore; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Lets players ignore each other's private messages. Required by: msg, teleportrequest.") +final class IgnoreModule { + + private IgnoreModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/item/ItemModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/item/ItemModule.java new file mode 100644 index 000000000..c1a1bb87d --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/item/ItemModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.item; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Displays information about the item a player is holding (/item).") +final class ItemModule { + + private ItemModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/itemedit/ItemEditModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/itemedit/ItemEditModule.java new file mode 100644 index 000000000..2a9d67401 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/itemedit/ItemEditModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.itemedit; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Edits an item's name, lore and flags (/itemname, /itemlore, /itemflag).") +final class ItemEditModule { + + private ItemEditModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/jail/JailModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/jail/JailModule.java new file mode 100644 index 000000000..e2fd120ce --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/jail/JailModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.jail; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Confines players to a jail location, restricting their movement (/jail).") +final class JailModule { + + private JailModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/joinmessage/JoinMessageModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/joinmessage/JoinMessageModule.java new file mode 100644 index 000000000..1b20c6bda --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/joinmessage/JoinMessageModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.joinmessage; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Sends a customizable message to the server when a player joins.") +final class JoinMessageModule { + + private JoinMessageModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/kill/KillModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/kill/KillModule.java new file mode 100644 index 000000000..e9bb61ad0 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/kill/KillModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.kill; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Instantly kills a player (/kill).") +final class KillModule { + + private KillModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/lag/LagModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/lag/LagModule.java new file mode 100644 index 000000000..f54130063 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/lag/LagModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.lag; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Reports server performance metrics like TPS and memory usage (/lag).") +final class LagModule { + + private LagModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/lightning/LightningModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/lightning/LightningModule.java new file mode 100644 index 000000000..f33ab13d3 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/lightning/LightningModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.lightning; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Strikes lightning at a player or location (/lightning).") +final class LightningModule { + + private LightningModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/mobignore/MobIgnoreModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/mobignore/MobIgnoreModule.java new file mode 100644 index 000000000..ea36514b9 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/mobignore/MobIgnoreModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.mobignore; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Prevents mobs from targeting a player (/mobignore).") +final class MobIgnoreModule { + + private MobIgnoreModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/motd/MotdModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/motd/MotdModule.java new file mode 100644 index 000000000..a462d68b5 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/motd/MotdModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.motd; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Sends a custom message of the day to players when they join.") +final class MotdModule { + + private MotdModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/msg/MsgModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/msg/MsgModule.java new file mode 100644 index 000000000..faec93151 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/msg/MsgModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.msg; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Private messaging between players (/msg, /reply, socialspy). Requires: ignore.") +final class MsgModule { + + private MsgModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/near/NearModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/near/NearModule.java new file mode 100644 index 000000000..1843c067c --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/near/NearModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.near; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Lists players near the sender's location (/near).") +final class NearModule { + + private NearModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/onlineplayers/OnlinePlayersModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/onlineplayers/OnlinePlayersModule.java new file mode 100644 index 000000000..4ca9a3f7d --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/onlineplayers/OnlinePlayersModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.onlineplayers; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Lists players currently online (/list, /online).") +final class OnlinePlayersModule { + + private OnlinePlayersModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/ping/PingModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/ping/PingModule.java new file mode 100644 index 000000000..749bc39ba --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/ping/PingModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.ping; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Shows a player's network latency (/ping).") +final class PingModule { + + private PingModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/playtime/PlaytimeModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/playtime/PlaytimeModule.java new file mode 100644 index 000000000..d7e04a13b --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/playtime/PlaytimeModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.playtime; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Tracks and displays how long a player has played (/playtime).") +final class PlaytimeModule { + + private PlaytimeModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/powertool/PowertoolModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/powertool/PowertoolModule.java new file mode 100644 index 000000000..0ab3e9a3e --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/powertool/PowertoolModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.powertool; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Binds commands to an item, run when a player interacts with it (/powertool).") +final class PowertoolModule { + + private PowertoolModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/quitmessage/QuitMessageModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/quitmessage/QuitMessageModule.java new file mode 100644 index 000000000..ccd86f80c --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/quitmessage/QuitMessageModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.quitmessage; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Sends a customizable message to the server when a player leaves.") +final class QuitMessageModule { + + private QuitMessageModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/randomteleport/RandomTeleportModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/randomteleport/RandomTeleportModule.java new file mode 100644 index 000000000..de8d76439 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/randomteleport/RandomTeleportModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.randomteleport; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Teleports a player to a random safe location (/rtp).") +final class RandomTeleportModule { + + private RandomTeleportModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/repair/RepairModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/repair/RepairModule.java new file mode 100644 index 000000000..d662186c5 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/repair/RepairModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.repair; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Repairs the durability of an item or the player's whole inventory (/repair).") +final class RepairModule { + + private RepairModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/seen/SeenModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/seen/SeenModule.java new file mode 100644 index 000000000..79c5c03b8 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/seen/SeenModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.seen; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Shows when a player was last online (/seen).") +final class SeenModule { + + private SeenModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/serverlinks/ServerLinksModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/serverlinks/ServerLinksModule.java new file mode 100644 index 000000000..d46892101 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/serverlinks/ServerLinksModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.serverlinks; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Configures the server links shown in the client's pause menu.") +final class ServerLinksModule { + + private ServerLinksModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/setslot/SetSlotModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/setslot/SetSlotModule.java new file mode 100644 index 000000000..fd9b15d59 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/setslot/SetSlotModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.setslot; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Sets the number of player slots shown in the server list (/setslot).") +final class SetSlotModule { + + private SetSlotModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/signeditor/SignEditorModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/signeditor/SignEditorModule.java new file mode 100644 index 000000000..509860247 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/signeditor/SignEditorModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.signeditor; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Lets players edit the text of existing signs (/signedit).") +final class SignEditorModule { + + private SignEditorModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/skull/SkullModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/skull/SkullModule.java new file mode 100644 index 000000000..a508a4b43 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/skull/SkullModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.skull; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Gives a player head/skull item (/skull).") +final class SkullModule { + + private SkullModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/sleep/SleepModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/sleep/SleepModule.java new file mode 100644 index 000000000..cd90c1f3d --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/sleep/SleepModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.sleep; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Sleep-related permissions: skip the night-vote requirement or opt out of phantom spawning.") +final class SleepModule { + + private SleepModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/spawn/SpawnModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/spawn/SpawnModule.java new file mode 100644 index 000000000..f32ad5f4e --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/spawn/SpawnModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.spawn; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("The server spawn point: teleporting to it and setting it (/spawn, /setspawn).") +final class SpawnModule { + + private SpawnModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/speed/SpeedModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/speed/SpeedModule.java new file mode 100644 index 000000000..5306a9733 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/speed/SpeedModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.speed; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Changes a player's walk/fly speed (/speed).") +final class SpeedModule { + + private SpeedModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/sudo/SudoModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/sudo/SudoModule.java new file mode 100644 index 000000000..a546eb009 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/sudo/SudoModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.sudo; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Forces a player to run a command (/sudo).") +final class SudoModule { + + private SudoModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportModule.java new file mode 100644 index 000000000..33bcbc858 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.teleport; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Core teleportation commands between players and to coordinates (/teleport, /tphere, /tppos, /tpup).") +final class TeleportModule { + + private TeleportModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportoffline/TeleportOfflineModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportoffline/TeleportOfflineModule.java new file mode 100644 index 000000000..80a687d51 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportoffline/TeleportOfflineModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.teleportoffline; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Teleports a player to an offline player's last known location (/tpoffline).") +final class TeleportOfflineModule { + + private TeleportOfflineModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrandomplayer/TeleportRandomPlayerModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrandomplayer/TeleportRandomPlayerModule.java new file mode 100644 index 000000000..c270c9fb4 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrandomplayer/TeleportRandomPlayerModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.teleportrandomplayer; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Teleports a player to another random online player (/tprp).") +final class TeleportRandomPlayerModule { + + private TeleportRandomPlayerModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/TeleportRequestModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/TeleportRequestModule.java new file mode 100644 index 000000000..fa23e49c0 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/TeleportRequestModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.teleportrequest; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Teleport requests between players (/tpa, /tpahere). Requires: ignore.") +final class TeleportRequestModule { + + private TeleportRequestModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/time/TimeModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/time/TimeModule.java new file mode 100644 index 000000000..e83a0ab91 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/time/TimeModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.time; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Changes or displays the world time (/time, /day, /night).") +final class TimeModule { + + private TimeModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/vanish/VanishModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/vanish/VanishModule.java new file mode 100644 index 000000000..d2e53db59 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/vanish/VanishModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.vanish; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Hides a player from other players while keeping them online (/vanish).") +final class VanishModule { + + private VanishModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpModule.java new file mode 100644 index 000000000..699379d5a --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.warp; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Named warp points players can teleport to (/warp, /setwarp, /delwarp).") +final class WarpModule { + + private WarpModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/weather/WeatherModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/weather/WeatherModule.java new file mode 100644 index 000000000..84174295a --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/weather/WeatherModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.weather; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Changes the weather in a world (/rain, /sun, /thunder).") +final class WeatherModule { + + private WeatherModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/whois/WhoisModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/whois/WhoisModule.java new file mode 100644 index 000000000..0e3508c21 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/whois/WhoisModule.java @@ -0,0 +1,11 @@ +package com.eternalcode.core.feature.whois; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Shows detailed information about a player (/whois).") +final class WhoisModule { + + private WhoisModule() { + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleDependencyGraph.java b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleDependencyGraph.java new file mode 100644 index 000000000..d9da888b6 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleDependencyGraph.java @@ -0,0 +1,60 @@ +package com.eternalcode.core.modules; + +import com.eternalcode.core.injector.annotations.Inject; +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +class ModuleDependencyGraph { + + private final Map> dependentsByRequiredModule = new LinkedHashMap<>(); + + static ModuleDependencyGraph build(Collection> scannedTypes) { + ModuleDependencyGraph graph = new ModuleDependencyGraph(); + + for (Class type : scannedTypes) { + Constructor injectConstructor = findInjectConstructor(type); + + if (injectConstructor == null) { + continue; + } + + for (Class parameterType : injectConstructor.getParameterTypes()) { + graph.registerDependency(type, parameterType); + } + } + + return graph; + } + + Set dependentsOf(String requiredModuleId) { + return this.dependentsByRequiredModule.getOrDefault(requiredModuleId, Set.of()); + } + + private void registerDependency(Class owner, Class required) { + String ownerModule = ModuleService.resolveModuleId(owner); + String requiredModule = ModuleService.resolveModuleId(required); + + if (ownerModule == null || requiredModule == null || ownerModule.equals(requiredModule)) { + return; + } + + this.dependentsByRequiredModule + .computeIfAbsent(requiredModule, key -> new LinkedHashSet<>()) + .add(ownerModule); + } + + private static Constructor findInjectConstructor(Class type) { + for (Constructor constructor : type.getDeclaredConstructors()) { + if (constructor.isAnnotationPresent(Inject.class)) { + return constructor; + } + } + + return null; + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleDescription.java b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleDescription.java new file mode 100644 index 000000000..1ab0302fd --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleDescription.java @@ -0,0 +1,14 @@ +package com.eternalcode.core.modules; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface ModuleDescription { + + String value(); + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java new file mode 100644 index 000000000..9ddb19719 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java @@ -0,0 +1,183 @@ +package com.eternalcode.core.modules; + +import com.eternalcode.core.util.ReflectUtil; +import eu.okaeri.configs.annotation.Header; +import eu.okaeri.configs.yaml.snakeyaml.YamlSnakeYamlConfigurer; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.logging.Logger; + +public class ModuleService { + + private static final String FEATURE_PACKAGE = "com.eternalcode.core.feature"; + private static final String FEATURE_PACKAGE_PREFIX = FEATURE_PACKAGE + "."; + private static final String[] HEADER = ModulesConfig.class.getAnnotation(Header.class).value(); + + private final File file; + private final ModulesConfig config; + private final Logger logger; + private final Map descriptions = new LinkedHashMap<>(); + private Map effectiveState; + + public ModuleService(File dataFolder, Logger logger) { + this.logger = logger; + this.file = new File(dataFolder, "modules.yml"); + this.config = new ModulesConfig(); + this.config.withConfigurer(new YamlSnakeYamlConfigurer()).withBindFile(this.file); + + if (this.file.exists()) { + this.config.load(true); + } + + this.effectiveState = new LinkedHashMap<>(this.config.modules); + } + + public boolean isEnabled(Class type) { + String moduleId = resolveModuleId(type); + + return moduleId == null || this.effectiveState.getOrDefault(moduleId, true); + } + + public void registerDiscoveredModules(Collection> discoveredTypes) { + Set discoveredModules = new TreeSet<>(); + + for (Class type : discoveredTypes) { + String moduleId = resolveModuleId(type); + + if (moduleId != null) { + discoveredModules.add(moduleId); + } + } + + for (String moduleId : discoveredModules) { + this.config.modules.putIfAbsent(moduleId, true); + } + } + + public void loadModuleDescriptions(ClassLoader classLoader) { + for (Class type : ReflectUtil.scanClasses(FEATURE_PACKAGE, classLoader)) { + ModuleDescription description = type.getAnnotation(ModuleDescription.class); + + if (description == null) { + continue; + } + + String moduleId = resolveModuleId(type); + + if (moduleId != null) { + this.descriptions.put(moduleId, description.value()); + } + } + } + + public void resolveEffectiveState(Collection> discoveredTypes) { + ModuleDependencyGraph graph = ModuleDependencyGraph.build(discoveredTypes); + Map effective = new LinkedHashMap<>(this.config.modules); + + boolean changed = true; + while (changed) { + changed = false; + + for (String moduleId : this.config.modules.keySet()) { + if (effective.getOrDefault(moduleId, true)) { + continue; + } + + List blockingDependents = graph.dependentsOf(moduleId).stream() + .filter(dependent -> effective.getOrDefault(dependent, true)) + .sorted() + .toList(); + + if (blockingDependents.isEmpty()) { + continue; + } + + effective.put(moduleId, true); + changed = true; + + this.warnAboutConflict(moduleId, blockingDependents); + } + } + + this.effectiveState = effective; + } + + public void logDisabledModules() { + for (Map.Entry entry : this.effectiveState.entrySet()) { + if (Boolean.FALSE.equals(entry.getValue())) { + this.logger.info("Module '" + entry.getKey() + "' is disabled in modules.yml, its commands, listeners, tasks and config will not be loaded."); + } + } + } + + public void writeModulesFile() { + StringBuilder content = new StringBuilder(); + + for (String headerLine : HEADER) { + content.append(headerLine).append(System.lineSeparator()); + } + + content.append(System.lineSeparator()).append("modules:").append(System.lineSeparator()); + + for (Map.Entry entry : this.config.modules.entrySet()) { + String description = this.descriptions.get(entry.getKey()); + + if (description != null) { + content.append(" # ").append(description).append(System.lineSeparator()); + } + + content.append(" ").append(entry.getKey()).append(": ").append(entry.getValue()).append(System.lineSeparator()); + } + + this.writeIfChanged(content.toString()); + } + + private void writeIfChanged(String newContent) { + try { + if (this.file.exists() && newContent.equals(Files.readString(this.file.toPath(), StandardCharsets.UTF_8))) { + return; + } + + File parentFile = this.file.getParentFile(); + if (parentFile != null) { + Files.createDirectories(parentFile.toPath()); + } + + Files.writeString(this.file.toPath(), newContent, StandardCharsets.UTF_8); + } catch (IOException exception) { + this.logger.warning("Failed to write " + this.file.getName() + ": " + exception.getMessage()); + } + } + + private void warnAboutConflict(String moduleId, List blockingDependents) { + String dependents = String.join(", ", blockingDependents); + + this.logger.warning("============================================================"); + this.logger.warning("You can't disable module '" + moduleId + "' - it is required by: " + dependents); + this.logger.warning("Keeping '" + moduleId + "' ENABLED to avoid starting in a broken state."); + this.logger.warning("If you really want to disable '" + moduleId + "', disable " + dependents + " in modules.yml too."); + this.logger.warning("============================================================"); + } + + static String resolveModuleId(Class type) { + String packageName = type.getPackageName(); + + if (!packageName.startsWith(FEATURE_PACKAGE_PREFIX)) { + return null; + } + + String remainder = packageName.substring(FEATURE_PACKAGE_PREFIX.length()); + int dotIndex = remainder.indexOf('.'); + + return dotIndex == -1 ? remainder : remainder.substring(0, dotIndex); + } + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModulesConfig.java b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModulesConfig.java new file mode 100644 index 000000000..a1925b872 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModulesConfig.java @@ -0,0 +1,23 @@ +package com.eternalcode.core.modules; + +import eu.okaeri.configs.OkaeriConfig; +import eu.okaeri.configs.annotation.Header; +import java.util.LinkedHashMap; +import java.util.Map; + +@Header({ + "#", + "# This file lets you completely disable individual EternalCore features.", + "#", + "# A feature set to 'false' will not register its commands, listeners, tasks or config section at all -", + "# it behaves as if it was never installed. This only takes effect on plugin startup, not on /reload.", + "#", + "# New features are added to this file automatically (enabled by default) as soon as the plugin sees them,", + "# so you never have to fill this list in by hand - just flip the ones you want off to 'false'.", + "#", +}) +public class ModulesConfig extends OkaeriConfig { + + public Map modules = new LinkedHashMap<>(); + +} diff --git a/eternalcore-core/src/test/java/com/eternalcode/core/feature/testdependent/DependentComponent.java b/eternalcore-core/src/test/java/com/eternalcode/core/feature/testdependent/DependentComponent.java new file mode 100644 index 000000000..081cbdb4b --- /dev/null +++ b/eternalcore-core/src/test/java/com/eternalcode/core/feature/testdependent/DependentComponent.java @@ -0,0 +1,12 @@ +package com.eternalcode.core.feature.testdependent; + +import com.eternalcode.core.feature.testrequired.RequiredService; +import com.eternalcode.core.injector.annotations.Inject; + +public class DependentComponent { + + @Inject + public DependentComponent(RequiredService requiredService) { + } + +} diff --git a/eternalcore-core/src/test/java/com/eternalcode/core/feature/testrequired/RequiredService.java b/eternalcore-core/src/test/java/com/eternalcode/core/feature/testrequired/RequiredService.java new file mode 100644 index 000000000..364607570 --- /dev/null +++ b/eternalcore-core/src/test/java/com/eternalcode/core/feature/testrequired/RequiredService.java @@ -0,0 +1,7 @@ +package com.eternalcode.core.feature.testrequired; + +import com.eternalcode.core.modules.ModuleDescription; + +@ModuleDescription("Test fixture module used by ModuleServiceTest.") +public interface RequiredService { +} From e79d83d6bdaa122a62bbc03840fb64f83f74e8a4 Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Tue, 22 Sep 2026 21:54:47 +0200 Subject: [PATCH 2/5] refactor: remove unused DependentComponent and RequiredService classes --- .../feature/testdependent/DependentComponent.java | 12 ------------ .../core/feature/testrequired/RequiredService.java | 7 ------- 2 files changed, 19 deletions(-) delete mode 100644 eternalcore-core/src/test/java/com/eternalcode/core/feature/testdependent/DependentComponent.java delete mode 100644 eternalcore-core/src/test/java/com/eternalcode/core/feature/testrequired/RequiredService.java diff --git a/eternalcore-core/src/test/java/com/eternalcode/core/feature/testdependent/DependentComponent.java b/eternalcore-core/src/test/java/com/eternalcode/core/feature/testdependent/DependentComponent.java deleted file mode 100644 index 081cbdb4b..000000000 --- a/eternalcore-core/src/test/java/com/eternalcode/core/feature/testdependent/DependentComponent.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.eternalcode.core.feature.testdependent; - -import com.eternalcode.core.feature.testrequired.RequiredService; -import com.eternalcode.core.injector.annotations.Inject; - -public class DependentComponent { - - @Inject - public DependentComponent(RequiredService requiredService) { - } - -} diff --git a/eternalcore-core/src/test/java/com/eternalcode/core/feature/testrequired/RequiredService.java b/eternalcore-core/src/test/java/com/eternalcode/core/feature/testrequired/RequiredService.java deleted file mode 100644 index 364607570..000000000 --- a/eternalcore-core/src/test/java/com/eternalcode/core/feature/testrequired/RequiredService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.eternalcode.core.feature.testrequired; - -import com.eternalcode.core.modules.ModuleDescription; - -@ModuleDescription("Test fixture module used by ModuleServiceTest.") -public interface RequiredService { -} From 7eb2d6fa4c455eed7afffb6c3e287f262921a593 Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Tue, 22 Sep 2026 22:13:00 +0200 Subject: [PATCH 3/5] Simplify way to disable modules - ignore just listeners and commands. --- .../com/eternalcode/core/EternalCore.java | 1 - .../core/feature/ignore/IgnoreModule.java | 2 +- .../core/feature/msg/MsgModule.java | 2 +- .../TeleportRequestModule.java | 2 +- .../core/modules/ModuleDependencyGraph.java | 60 ------------- .../core/modules/ModuleService.java | 84 +++++++++---------- 6 files changed, 41 insertions(+), 110 deletions(-) delete mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleDependencyGraph.java diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/EternalCore.java b/eternalcore-core/src/main/java/com/eternalcode/core/EternalCore.java index ac3c08f2d..472594192 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/EternalCore.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/EternalCore.java @@ -84,7 +84,6 @@ public EternalCore(Plugin plugin) { moduleService.registerDiscoveredModules(scannedTypes); moduleService.loadModuleDescriptions(EternalCore.class.getClassLoader()); - moduleService.resolveEffectiveState(scannedTypes); moduleService.writeModulesFile(); moduleService.logDisabledModules(); diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/ignore/IgnoreModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/ignore/IgnoreModule.java index b884e694f..c91d271a0 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/ignore/IgnoreModule.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/ignore/IgnoreModule.java @@ -2,7 +2,7 @@ import com.eternalcode.core.modules.ModuleDescription; -@ModuleDescription("Lets players ignore each other's private messages. Required by: msg, teleportrequest.") +@ModuleDescription("Lets players ignore each other's private messages.") final class IgnoreModule { private IgnoreModule() { diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/msg/MsgModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/msg/MsgModule.java index faec93151..4cb440ca2 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/msg/MsgModule.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/msg/MsgModule.java @@ -2,7 +2,7 @@ import com.eternalcode.core.modules.ModuleDescription; -@ModuleDescription("Private messaging between players (/msg, /reply, socialspy). Requires: ignore.") +@ModuleDescription("Private messaging between players (/msg, /reply, socialspy).") final class MsgModule { private MsgModule() { diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/TeleportRequestModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/TeleportRequestModule.java index fa23e49c0..72a53b251 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/TeleportRequestModule.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/TeleportRequestModule.java @@ -2,7 +2,7 @@ import com.eternalcode.core.modules.ModuleDescription; -@ModuleDescription("Teleport requests between players (/tpa, /tpahere). Requires: ignore.") +@ModuleDescription("Teleport requests between players (/tpa, /tpahere).") final class TeleportRequestModule { private TeleportRequestModule() { diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleDependencyGraph.java b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleDependencyGraph.java deleted file mode 100644 index d9da888b6..000000000 --- a/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleDependencyGraph.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.eternalcode.core.modules; - -import com.eternalcode.core.injector.annotations.Inject; -import java.lang.reflect.Constructor; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -class ModuleDependencyGraph { - - private final Map> dependentsByRequiredModule = new LinkedHashMap<>(); - - static ModuleDependencyGraph build(Collection> scannedTypes) { - ModuleDependencyGraph graph = new ModuleDependencyGraph(); - - for (Class type : scannedTypes) { - Constructor injectConstructor = findInjectConstructor(type); - - if (injectConstructor == null) { - continue; - } - - for (Class parameterType : injectConstructor.getParameterTypes()) { - graph.registerDependency(type, parameterType); - } - } - - return graph; - } - - Set dependentsOf(String requiredModuleId) { - return this.dependentsByRequiredModule.getOrDefault(requiredModuleId, Set.of()); - } - - private void registerDependency(Class owner, Class required) { - String ownerModule = ModuleService.resolveModuleId(owner); - String requiredModule = ModuleService.resolveModuleId(required); - - if (ownerModule == null || requiredModule == null || ownerModule.equals(requiredModule)) { - return; - } - - this.dependentsByRequiredModule - .computeIfAbsent(requiredModule, key -> new LinkedHashSet<>()) - .add(ownerModule); - } - - private static Constructor findInjectConstructor(Class type) { - for (Constructor constructor : type.getDeclaredConstructors()) { - if (constructor.isAnnotationPresent(Inject.class)) { - return constructor; - } - } - - return null; - } - -} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java index 9ddb19719..14fd417a5 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java @@ -1,15 +1,22 @@ package com.eternalcode.core.modules; +import com.eternalcode.core.injector.annotations.component.Controller; +import com.eternalcode.core.injector.annotations.lite.LiteArgument; +import com.eternalcode.core.injector.annotations.lite.LiteCommandEditor; +import com.eternalcode.core.injector.annotations.lite.LiteContextual; +import com.eternalcode.core.injector.annotations.lite.LiteHandler; import com.eternalcode.core.util.ReflectUtil; +import dev.rollczi.litecommands.annotations.command.Command; +import dev.rollczi.litecommands.annotations.command.RootCommand; import eu.okaeri.configs.annotation.Header; import eu.okaeri.configs.yaml.snakeyaml.YamlSnakeYamlConfigurer; import java.io.File; import java.io.IOException; +import java.lang.annotation.Annotation; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.Collection; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; @@ -21,11 +28,20 @@ public class ModuleService { private static final String FEATURE_PACKAGE_PREFIX = FEATURE_PACKAGE + "."; private static final String[] HEADER = ModulesConfig.class.getAnnotation(Header.class).value(); + private static final Set> GATED_ANNOTATIONS = Set.of( + Controller.class, + Command.class, + RootCommand.class, + LiteArgument.class, + LiteHandler.class, + LiteContextual.class, + LiteCommandEditor.class + ); + private final File file; private final ModulesConfig config; private final Logger logger; private final Map descriptions = new LinkedHashMap<>(); - private Map effectiveState; public ModuleService(File dataFolder, Logger logger) { this.logger = logger; @@ -36,14 +52,22 @@ public ModuleService(File dataFolder, Logger logger) { if (this.file.exists()) { this.config.load(true); } - - this.effectiveState = new LinkedHashMap<>(this.config.modules); } + /** + * Only listeners and commands are gated by modules.yml - everything else (services, tasks, + * config, repositories) is always created, regardless of a module's enabled state. This keeps + * a disabled module's functionality fully hidden from players while other, still-enabled + * modules can keep depending on its services without breaking. + */ public boolean isEnabled(Class type) { + if (!isGated(type)) { + return true; + } + String moduleId = resolveModuleId(type); - return moduleId == null || this.effectiveState.getOrDefault(moduleId, true); + return moduleId == null || this.config.modules.getOrDefault(moduleId, true); } public void registerDiscoveredModules(Collection> discoveredTypes) { @@ -78,42 +102,10 @@ public void loadModuleDescriptions(ClassLoader classLoader) { } } - public void resolveEffectiveState(Collection> discoveredTypes) { - ModuleDependencyGraph graph = ModuleDependencyGraph.build(discoveredTypes); - Map effective = new LinkedHashMap<>(this.config.modules); - - boolean changed = true; - while (changed) { - changed = false; - - for (String moduleId : this.config.modules.keySet()) { - if (effective.getOrDefault(moduleId, true)) { - continue; - } - - List blockingDependents = graph.dependentsOf(moduleId).stream() - .filter(dependent -> effective.getOrDefault(dependent, true)) - .sorted() - .toList(); - - if (blockingDependents.isEmpty()) { - continue; - } - - effective.put(moduleId, true); - changed = true; - - this.warnAboutConflict(moduleId, blockingDependents); - } - } - - this.effectiveState = effective; - } - public void logDisabledModules() { - for (Map.Entry entry : this.effectiveState.entrySet()) { + for (Map.Entry entry : this.config.modules.entrySet()) { if (Boolean.FALSE.equals(entry.getValue())) { - this.logger.info("Module '" + entry.getKey() + "' is disabled in modules.yml, its commands, listeners, tasks and config will not be loaded."); + this.logger.info("Module '" + entry.getKey() + "' is disabled in modules.yml, its commands and listeners will not be registered."); } } } @@ -157,14 +149,14 @@ private void writeIfChanged(String newContent) { } } - private void warnAboutConflict(String moduleId, List blockingDependents) { - String dependents = String.join(", ", blockingDependents); + private static boolean isGated(Class type) { + for (Class annotationType : GATED_ANNOTATIONS) { + if (type.isAnnotationPresent(annotationType)) { + return true; + } + } - this.logger.warning("============================================================"); - this.logger.warning("You can't disable module '" + moduleId + "' - it is required by: " + dependents); - this.logger.warning("Keeping '" + moduleId + "' ENABLED to avoid starting in a broken state."); - this.logger.warning("If you really want to disable '" + moduleId + "', disable " + dependents + " in modules.yml too."); - this.logger.warning("============================================================"); + return false; } static String resolveModuleId(Class type) { From 54a006e9aad4e56784cbac53d8efb76618cfd2af Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Tue, 22 Sep 2026 22:17:24 +0200 Subject: [PATCH 4/5] Remove outdated comments from ModuleService.java --- .../java/com/eternalcode/core/modules/ModuleService.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java index 14fd417a5..b49707c57 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java @@ -54,12 +54,6 @@ public ModuleService(File dataFolder, Logger logger) { } } - /** - * Only listeners and commands are gated by modules.yml - everything else (services, tasks, - * config, repositories) is always created, regardless of a module's enabled state. This keeps - * a disabled module's functionality fully hidden from players while other, still-enabled - * modules can keep depending on its services without breaking. - */ public boolean isEnabled(Class type) { if (!isGated(type)) { return true; From 4f3684fe4c2cee3cbcd1c8ccccaba70e57fe13c9 Mon Sep 17 00:00:00 2001 From: Martin Sulikowski Date: Tue, 22 Sep 2026 22:38:55 +0200 Subject: [PATCH 5/5] Add GatedByModule annotation to various tasks and services --- .../implementation/PluginConfiguration.java | 4 ++-- .../adminchat/AdminChatReminderTask.java | 2 ++ .../eternalcode/core/feature/afk/AfkTask.java | 2 ++ .../automessage/AutoMessageService.java | 2 ++ .../core/feature/back/BackService.java | 2 +- .../customcommand/CustomCommandRegistry.java | 2 ++ .../core/feature/fun/catboy/CatboyTask.java | 2 ++ .../feature/home/HomeTeleportService.java | 4 ++-- .../core/feature/jail/JailTask.java | 2 ++ .../RandomTeleportTaskService.java | 6 +++--- .../core/feature/spawn/SpawnCommand.java | 2 +- .../core/feature/teleport/TeleportModule.java | 2 +- .../teleportrequest/TpaAcceptCommand.java | 2 +- .../self/TpaHereActionCommand.java | 2 +- .../feature/vanish/VanishReminderTask.java | 2 ++ .../feature/warp/WarpTeleportService.java | 4 ++-- .../core/modules/GatedByModule.java | 19 +++++++++++++++++++ .../core/modules/ModuleService.java | 4 ++++ .../core/{feature => }/teleport/Teleport.java | 2 +- .../teleport/TeleportController.java | 2 +- .../TeleportDeathLastLocationController.java | 3 ++- .../teleport/TeleportResult.java | 2 +- .../teleport/TeleportServiceImpl.java | 3 ++- .../{feature => }/teleport/TeleportTask.java | 5 +++-- .../teleport/TeleportTaskService.java | 2 +- .../teleport/messages/ENTeleportMessages.java | 2 +- .../teleport/messages/PLTeleportMessages.java | 2 +- .../teleport/messages/TeleportMessages.java | 2 +- .../core/teleport/package-info.java | 5 +++++ .../teleport/settings/TeleportConfig.java | 2 +- .../teleport/settings/TeleportSettings.java | 2 +- .../core/translation/Translation.java | 2 +- .../implementation/ENTranslation.java | 2 +- .../implementation/PLTranslation.java | 2 +- 34 files changed, 75 insertions(+), 30 deletions(-) create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/modules/GatedByModule.java rename eternalcore-core/src/main/java/com/eternalcode/core/{feature => }/teleport/Teleport.java (96%) rename eternalcore-core/src/main/java/com/eternalcode/core/{feature => }/teleport/TeleportController.java (97%) rename eternalcore-core/src/main/java/com/eternalcode/core/{feature => }/teleport/TeleportDeathLastLocationController.java (89%) rename eternalcore-core/src/main/java/com/eternalcode/core/{feature => }/teleport/TeleportResult.java (72%) rename eternalcore-core/src/main/java/com/eternalcode/core/{feature => }/teleport/TeleportServiceImpl.java (94%) rename eternalcore-core/src/main/java/com/eternalcode/core/{feature => }/teleport/TeleportTask.java (96%) rename eternalcore-core/src/main/java/com/eternalcode/core/{feature => }/teleport/TeleportTaskService.java (97%) rename eternalcore-core/src/main/java/com/eternalcode/core/{feature => }/teleport/messages/ENTeleportMessages.java (97%) rename eternalcore-core/src/main/java/com/eternalcode/core/{feature => }/teleport/messages/PLTeleportMessages.java (97%) rename eternalcore-core/src/main/java/com/eternalcode/core/{feature => }/teleport/messages/TeleportMessages.java (90%) create mode 100644 eternalcore-core/src/main/java/com/eternalcode/core/teleport/package-info.java rename eternalcore-core/src/main/java/com/eternalcode/core/{feature => }/teleport/settings/TeleportConfig.java (88%) rename eternalcore-core/src/main/java/com/eternalcode/core/{feature => }/teleport/settings/TeleportSettings.java (58%) diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/configuration/implementation/PluginConfiguration.java b/eternalcore-core/src/main/java/com/eternalcode/core/configuration/implementation/PluginConfiguration.java index 716d0da8b..fa75a4282 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/configuration/implementation/PluginConfiguration.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/configuration/implementation/PluginConfiguration.java @@ -3,8 +3,8 @@ import com.eternalcode.core.configuration.AbstractConfigurationFile; import com.eternalcode.core.database.DatabaseConfig; import com.eternalcode.core.database.DatabaseSettings; -import com.eternalcode.core.feature.teleport.settings.TeleportConfig; -import com.eternalcode.core.feature.teleport.settings.TeleportSettings; +import com.eternalcode.core.teleport.settings.TeleportConfig; +import com.eternalcode.core.teleport.settings.TeleportSettings; import com.eternalcode.core.util.date.DateConfig; import com.eternalcode.core.util.date.DateSettings; import com.eternalcode.core.feature.afk.AfkConfig; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/adminchat/AdminChatReminderTask.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/adminchat/AdminChatReminderTask.java index 5a06c655d..328fd30c4 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/adminchat/AdminChatReminderTask.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/adminchat/AdminChatReminderTask.java @@ -3,11 +3,13 @@ import com.eternalcode.commons.bukkit.runnable.OnlinePlayersRunnable; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Task; +import com.eternalcode.core.modules.GatedByModule; import com.eternalcode.core.notice.NoticeService; import java.util.concurrent.TimeUnit; import org.bukkit.entity.Player; @Task(period = 1, delay = 1, unit = TimeUnit.SECONDS) +@GatedByModule final class AdminChatReminderTask extends OnlinePlayersRunnable { private final AdminChatService adminChatService; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/afk/AfkTask.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/afk/AfkTask.java index f888a80f9..3f0d894bb 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/afk/AfkTask.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/afk/AfkTask.java @@ -3,12 +3,14 @@ import com.eternalcode.core.feature.vanish.VanishService; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Task; +import com.eternalcode.core.modules.GatedByModule; import java.util.UUID; import java.util.concurrent.TimeUnit; import org.bukkit.Server; import org.bukkit.entity.Player; @Task(delay = 1L, period = 1L, unit = TimeUnit.MINUTES) +@GatedByModule class AfkTask implements Runnable { private final AfkService afkService; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/automessage/AutoMessageService.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/automessage/AutoMessageService.java index 9ca4d88b4..d859df14d 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/automessage/AutoMessageService.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/automessage/AutoMessageService.java @@ -5,6 +5,7 @@ import com.eternalcode.core.feature.automessage.messages.AutoMessageMessages; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Service; +import com.eternalcode.core.modules.GatedByModule; import com.eternalcode.core.notice.NoticeService; import com.eternalcode.multification.notice.Notice; import java.util.Collection; @@ -18,6 +19,7 @@ import org.bukkit.entity.Entity; @Service +@GatedByModule class AutoMessageService { private final AutoMessageRepository repository; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/back/BackService.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/back/BackService.java index 4bde19d46..bbe8b2504 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/back/BackService.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/back/BackService.java @@ -3,7 +3,7 @@ import com.eternalcode.commons.bukkit.position.Position; import com.eternalcode.commons.bukkit.position.PositionAdapter; import com.eternalcode.core.feature.teleport.TeleportService; -import com.eternalcode.core.feature.teleport.TeleportTaskService; +import com.eternalcode.core.teleport.TeleportTaskService; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Service; import com.github.benmanes.caffeine.cache.Cache; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/customcommand/CustomCommandRegistry.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/customcommand/CustomCommandRegistry.java index bcc3b56e9..01e7ab048 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/customcommand/CustomCommandRegistry.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/customcommand/CustomCommandRegistry.java @@ -2,6 +2,7 @@ import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Service; +import com.eternalcode.core.modules.GatedByModule; import com.eternalcode.core.notice.NoticeService; import dev.rollczi.litecommands.util.StringUtil; import java.lang.reflect.Field; @@ -9,6 +10,7 @@ import org.bukkit.command.CommandMap; @Service +@GatedByModule public class CustomCommandRegistry { private static final String FALLBACK_PREFIX = "eternalcore"; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/fun/catboy/CatboyTask.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/fun/catboy/CatboyTask.java index a6c995650..1c98908f3 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/fun/catboy/CatboyTask.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/fun/catboy/CatboyTask.java @@ -5,6 +5,7 @@ import com.eternalcode.core.feature.catboy.CatboyService; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Task; +import com.eternalcode.core.modules.GatedByModule; import net.md_5.bungee.api.ChatColor; import org.bukkit.DyeColor; import org.bukkit.Particle; @@ -18,6 +19,7 @@ import java.util.concurrent.TimeUnit; @Task(delay = 400L, period = 400L, unit = TimeUnit.MILLISECONDS) +@GatedByModule class CatboyTask implements Runnable { private static final String CATBOY_NAME = "Catboy"; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/home/HomeTeleportService.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/home/HomeTeleportService.java index f052c2368..7baec883e 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/home/HomeTeleportService.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/home/HomeTeleportService.java @@ -6,8 +6,8 @@ import com.eternalcode.core.event.EventCaller; import com.eternalcode.core.feature.home.event.HomeTeleportEvent; import com.eternalcode.core.feature.home.event.PreHomeTeleportEvent; -import com.eternalcode.core.feature.teleport.Teleport; -import com.eternalcode.core.feature.teleport.TeleportTaskService; +import com.eternalcode.core.teleport.Teleport; +import com.eternalcode.core.teleport.TeleportTaskService; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Service; import java.time.Duration; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/jail/JailTask.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/jail/JailTask.java index 31cf90428..3f522af82 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/jail/JailTask.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/jail/JailTask.java @@ -2,6 +2,7 @@ import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Task; +import com.eternalcode.core.modules.GatedByModule; import com.eternalcode.core.notice.NoticeService; import com.eternalcode.core.util.DurationUtil; import java.util.concurrent.TimeUnit; @@ -9,6 +10,7 @@ import org.bukkit.entity.Player; @Task(period = 1, delay = 1, unit = TimeUnit.SECONDS) +@GatedByModule class JailTask implements Runnable { private final JailService jailService; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/randomteleport/RandomTeleportTaskService.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/randomteleport/RandomTeleportTaskService.java index 6d45902a0..e9c66999b 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/randomteleport/RandomTeleportTaskService.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/randomteleport/RandomTeleportTaskService.java @@ -5,9 +5,9 @@ import com.eternalcode.commons.bukkit.position.Position; import com.eternalcode.commons.bukkit.position.PositionAdapter; -import com.eternalcode.core.feature.teleport.Teleport; -import com.eternalcode.core.feature.teleport.TeleportResult; -import com.eternalcode.core.feature.teleport.TeleportTaskService; +import com.eternalcode.core.teleport.Teleport; +import com.eternalcode.core.teleport.TeleportResult; +import com.eternalcode.core.teleport.TeleportTaskService; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Service; import com.eternalcode.core.notice.NoticeService; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/spawn/SpawnCommand.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/spawn/SpawnCommand.java index fbb9d5a04..d09adce33 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/spawn/SpawnCommand.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/spawn/SpawnCommand.java @@ -4,7 +4,7 @@ import com.eternalcode.annotations.scan.permission.PermissionDocs; import com.eternalcode.commons.bukkit.position.PositionAdapter; import com.eternalcode.core.feature.teleport.TeleportService; -import com.eternalcode.core.feature.teleport.TeleportTaskService; +import com.eternalcode.core.teleport.TeleportTaskService; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.notice.NoticeService; import com.eternalcode.core.viewer.Viewer; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportModule.java index 33bcbc858..b5990d41b 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportModule.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportModule.java @@ -2,7 +2,7 @@ import com.eternalcode.core.modules.ModuleDescription; -@ModuleDescription("Core teleportation commands between players and to coordinates (/teleport, /tphere, /tppos, /tpup).") +@ModuleDescription("The /teleport, /tphere, /tppos and /tpup commands.") final class TeleportModule { private TeleportModule() { diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/TpaAcceptCommand.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/TpaAcceptCommand.java index e6909872c..51d172168 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/TpaAcceptCommand.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/TpaAcceptCommand.java @@ -2,7 +2,7 @@ import com.eternalcode.annotations.scan.command.DescriptionDocs; import com.eternalcode.commons.bukkit.position.PositionAdapter; -import com.eternalcode.core.feature.teleport.TeleportTaskService; +import com.eternalcode.core.teleport.TeleportTaskService; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.notice.NoticeService; import dev.rollczi.litecommands.annotations.argument.Arg; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/self/TpaHereActionCommand.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/self/TpaHereActionCommand.java index 77421d826..86056a0bb 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/self/TpaHereActionCommand.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleportrequest/self/TpaHereActionCommand.java @@ -2,7 +2,7 @@ import com.eternalcode.annotations.scan.command.DescriptionDocs; import com.eternalcode.commons.bukkit.position.PositionAdapter; -import com.eternalcode.core.feature.teleport.TeleportTaskService; +import com.eternalcode.core.teleport.TeleportTaskService; import com.eternalcode.core.feature.teleportrequest.TeleportRequestSettings; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.notice.NoticeService; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/vanish/VanishReminderTask.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/vanish/VanishReminderTask.java index ddf4eebb6..6bb78677a 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/vanish/VanishReminderTask.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/vanish/VanishReminderTask.java @@ -2,12 +2,14 @@ import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Task; +import com.eternalcode.core.modules.GatedByModule; import com.eternalcode.core.notice.NoticeService; import java.util.UUID; import java.util.concurrent.TimeUnit; @Task(period = 1, delay = 1, unit = TimeUnit.SECONDS) +@GatedByModule class VanishReminderTask implements Runnable { private final NoticeService noticeService; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpTeleportService.java b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpTeleportService.java index 51d8c6f43..70dcfd5f2 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpTeleportService.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/feature/warp/WarpTeleportService.java @@ -4,8 +4,8 @@ import com.eternalcode.commons.bukkit.position.Position; import com.eternalcode.commons.bukkit.position.PositionAdapter; import com.eternalcode.core.event.EventCaller; -import com.eternalcode.core.feature.teleport.Teleport; -import com.eternalcode.core.feature.teleport.TeleportTaskService; +import com.eternalcode.core.teleport.Teleport; +import com.eternalcode.core.teleport.TeleportTaskService; import com.eternalcode.core.feature.warp.event.PreWarpTeleportEvent; import com.eternalcode.core.feature.warp.event.WarpTeleportEvent; import com.eternalcode.core.injector.annotations.Inject; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/modules/GatedByModule.java b/eternalcore-core/src/main/java/com/eternalcode/core/modules/GatedByModule.java new file mode 100644 index 000000000..b916ee925 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/modules/GatedByModule.java @@ -0,0 +1,19 @@ +package com.eternalcode.core.modules; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * For a bean that is not a listener or command but still has a side effect on construction (e.g. + * scheduling a recurring task, registering a raw Bukkit command) - marks it as gated by its + * module's modules.yml entry, same as {@code @Controller}/{@code @Command} already are. Only use + * this on beans nothing outside their own module depends on, otherwise disabling the module would + * make that other dependency fail to resolve. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface GatedByModule { + +} diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java index b49707c57..2a003ea56 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/modules/ModuleService.java @@ -144,6 +144,10 @@ private void writeIfChanged(String newContent) { } private static boolean isGated(Class type) { + if (type.isAnnotationPresent(GatedByModule.class)) { + return true; + } + for (Class annotationType : GATED_ANNOTATIONS) { if (type.isAnnotationPresent(annotationType)) { return true; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/Teleport.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/Teleport.java similarity index 96% rename from eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/Teleport.java rename to eternalcore-core/src/main/java/com/eternalcode/core/teleport/Teleport.java index 3224ae9c9..649df1894 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/Teleport.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/Teleport.java @@ -1,4 +1,4 @@ -package com.eternalcode.core.feature.teleport; +package com.eternalcode.core.teleport; import com.eternalcode.commons.bukkit.position.Position; import java.time.Instant; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportController.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportController.java similarity index 97% rename from eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportController.java rename to eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportController.java index 58014da1e..22496cd5b 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportController.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportController.java @@ -1,4 +1,4 @@ -package com.eternalcode.core.feature.teleport; +package com.eternalcode.core.teleport; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Controller; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportDeathLastLocationController.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportDeathLastLocationController.java similarity index 89% rename from eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportDeathLastLocationController.java rename to eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportDeathLastLocationController.java index 786608d52..3f9437ef3 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportDeathLastLocationController.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportDeathLastLocationController.java @@ -1,5 +1,6 @@ -package com.eternalcode.core.feature.teleport; +package com.eternalcode.core.teleport; +import com.eternalcode.core.feature.teleport.TeleportService; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Controller; import org.bukkit.entity.Player; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportResult.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportResult.java similarity index 72% rename from eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportResult.java rename to eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportResult.java index d00366a06..053f0f4f2 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportResult.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportResult.java @@ -1,4 +1,4 @@ -package com.eternalcode.core.feature.teleport; +package com.eternalcode.core.teleport; public enum TeleportResult { diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportServiceImpl.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportServiceImpl.java similarity index 94% rename from eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportServiceImpl.java rename to eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportServiceImpl.java index 177b4e8ce..7715ed727 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportServiceImpl.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportServiceImpl.java @@ -1,8 +1,9 @@ -package com.eternalcode.core.feature.teleport; +package com.eternalcode.core.teleport; import com.eternalcode.commons.bukkit.position.Position; import com.eternalcode.commons.bukkit.position.PositionAdapter; import com.eternalcode.core.event.EventCaller; +import com.eternalcode.core.feature.teleport.TeleportService; import com.eternalcode.core.feature.teleport.event.EternalTeleportEvent; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Service; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportTask.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportTask.java similarity index 96% rename from eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportTask.java rename to eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportTask.java index 192a46100..ea29ee90a 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportTask.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportTask.java @@ -1,8 +1,9 @@ -package com.eternalcode.core.feature.teleport; +package com.eternalcode.core.teleport; import com.eternalcode.commons.bukkit.position.Position; import com.eternalcode.commons.bukkit.position.PositionAdapter; -import com.eternalcode.core.feature.teleport.settings.TeleportSettings; +import com.eternalcode.core.feature.teleport.TeleportService; +import com.eternalcode.core.teleport.settings.TeleportSettings; import com.eternalcode.core.injector.annotations.Inject; import com.eternalcode.core.injector.annotations.component.Task; import com.eternalcode.core.notice.NoticeService; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportTaskService.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportTaskService.java similarity index 97% rename from eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportTaskService.java rename to eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportTaskService.java index 784ff7c6c..85bc99513 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/TeleportTaskService.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/TeleportTaskService.java @@ -1,4 +1,4 @@ -package com.eternalcode.core.feature.teleport; +package com.eternalcode.core.teleport; import com.eternalcode.commons.bukkit.position.Position; import com.eternalcode.core.injector.annotations.component.Service; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/messages/ENTeleportMessages.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/messages/ENTeleportMessages.java similarity index 97% rename from eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/messages/ENTeleportMessages.java rename to eternalcore-core/src/main/java/com/eternalcode/core/teleport/messages/ENTeleportMessages.java index 222da9adc..c1c415572 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/messages/ENTeleportMessages.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/messages/ENTeleportMessages.java @@ -1,4 +1,4 @@ -package com.eternalcode.core.feature.teleport.messages; +package com.eternalcode.core.teleport.messages; import com.eternalcode.multification.notice.Notice; import eu.okaeri.configs.OkaeriConfig; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/messages/PLTeleportMessages.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/messages/PLTeleportMessages.java similarity index 97% rename from eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/messages/PLTeleportMessages.java rename to eternalcore-core/src/main/java/com/eternalcode/core/teleport/messages/PLTeleportMessages.java index 692001d87..0fad49968 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/messages/PLTeleportMessages.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/messages/PLTeleportMessages.java @@ -1,4 +1,4 @@ -package com.eternalcode.core.feature.teleport.messages; +package com.eternalcode.core.teleport.messages; import com.eternalcode.multification.notice.Notice; import eu.okaeri.configs.OkaeriConfig; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/messages/TeleportMessages.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/messages/TeleportMessages.java similarity index 90% rename from eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/messages/TeleportMessages.java rename to eternalcore-core/src/main/java/com/eternalcode/core/teleport/messages/TeleportMessages.java index b42c073e3..2dbac3610 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/messages/TeleportMessages.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/messages/TeleportMessages.java @@ -1,4 +1,4 @@ -package com.eternalcode.core.feature.teleport.messages; +package com.eternalcode.core.teleport.messages; import com.eternalcode.multification.notice.Notice; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/teleport/package-info.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/package-info.java new file mode 100644 index 000000000..107f0b199 --- /dev/null +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/package-info.java @@ -0,0 +1,5 @@ +/** + * Shared teleport engine used by many features (home, back, warp, spawn, rtp, teleport requests). + * It's too common to move it inside {@code feature} package + */ +package com.eternalcode.core.teleport; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/settings/TeleportConfig.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/settings/TeleportConfig.java similarity index 88% rename from eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/settings/TeleportConfig.java rename to eternalcore-core/src/main/java/com/eternalcode/core/teleport/settings/TeleportConfig.java index 3e69a7cb4..01f251832 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/settings/TeleportConfig.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/settings/TeleportConfig.java @@ -1,4 +1,4 @@ -package com.eternalcode.core.feature.teleport.settings; +package com.eternalcode.core.teleport.settings; import eu.okaeri.configs.OkaeriConfig; import eu.okaeri.configs.annotation.Comment; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/settings/TeleportSettings.java b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/settings/TeleportSettings.java similarity index 58% rename from eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/settings/TeleportSettings.java rename to eternalcore-core/src/main/java/com/eternalcode/core/teleport/settings/TeleportSettings.java index fe3f32242..43f5cee6e 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/feature/teleport/settings/TeleportSettings.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/teleport/settings/TeleportSettings.java @@ -1,4 +1,4 @@ -package com.eternalcode.core.feature.teleport.settings; +package com.eternalcode.core.teleport.settings; public interface TeleportSettings { boolean movementCancelsTeleport(); diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/translation/Translation.java b/eternalcore-core/src/main/java/com/eternalcode/core/translation/Translation.java index d81be3f53..f5357fda1 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/translation/Translation.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/translation/Translation.java @@ -51,7 +51,7 @@ import com.eternalcode.core.feature.spawn.messages.SpawnMessages; import com.eternalcode.core.feature.speed.messages.SpeedMessages; import com.eternalcode.core.feature.sudo.messages.SudoMessages; -import com.eternalcode.core.feature.teleport.messages.TeleportMessages; +import com.eternalcode.core.teleport.messages.TeleportMessages; import com.eternalcode.core.feature.teleportoffline.TeleportOfflineMessages; import com.eternalcode.core.feature.teleportrandomplayer.messages.TeleportToRandomPlayerMessages; import com.eternalcode.core.feature.teleportrequest.messages.TeleportRequestMessages; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/ENTranslation.java b/eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/ENTranslation.java index 09287f181..c433159cd 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/ENTranslation.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/ENTranslation.java @@ -50,7 +50,7 @@ import com.eternalcode.core.feature.spawn.messages.ENSpawnMessages; import com.eternalcode.core.feature.speed.messages.ENSpeedMessages; import com.eternalcode.core.feature.sudo.messages.ENSudoMessages; -import com.eternalcode.core.feature.teleport.messages.ENTeleportMessages; +import com.eternalcode.core.teleport.messages.ENTeleportMessages; import com.eternalcode.core.feature.teleportoffline.ENTeleportOfflineMessages; import com.eternalcode.core.feature.teleportrandomplayer.messages.ENTeleportToRandomPlayerMessages; import com.eternalcode.core.feature.teleportrequest.messages.ENTeleportRequestMessages; diff --git a/eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/PLTranslation.java b/eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/PLTranslation.java index 67925fbaa..17773c22d 100644 --- a/eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/PLTranslation.java +++ b/eternalcore-core/src/main/java/com/eternalcode/core/translation/implementation/PLTranslation.java @@ -51,7 +51,7 @@ import com.eternalcode.core.feature.spawn.messages.PLSpawnMessages; import com.eternalcode.core.feature.speed.messages.PLSpeedMessages; import com.eternalcode.core.feature.sudo.messages.PLSudoMessages; -import com.eternalcode.core.feature.teleport.messages.PLTeleportMessages; +import com.eternalcode.core.teleport.messages.PLTeleportMessages; import com.eternalcode.core.feature.teleportoffline.PLTeleportOfflineMessages; import com.eternalcode.core.feature.teleportrandomplayer.messages.PLTeleportToRandomPlayerMessages; import com.eternalcode.core.feature.teleportrequest.messages.PLTeleportRequestMessages;