diff --git a/build.gradle b/build.gradle index 34d77080..06bed5f3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ import org.apache.tools.ant.filters.ReplaceTokens plugins { - id 'com.github.johnrengelman.shadow' version '8.1.1' + id 'io.github.goooler.shadow' version "8.1.7" id 'org.cadixdev.licenser' version '0.6.1' apply false id 'org.ajoberstar.grgit' version '5.2.2' id 'maven-publish' @@ -55,7 +55,7 @@ publishing { } allprojects { - apply plugin: 'com.github.johnrengelman.shadow' + apply plugin: 'io.github.goooler.shadow' apply plugin: 'org.cadixdev.licenser' apply plugin: 'java' diff --git a/bukkit/src/main/java/net/william278/husktowns/BukkitHuskTowns.java b/bukkit/src/main/java/net/william278/husktowns/BukkitHuskTowns.java index c1d364a2..3e28b078 100644 --- a/bukkit/src/main/java/net/william278/husktowns/BukkitHuskTowns.java +++ b/bukkit/src/main/java/net/william278/husktowns/BukkitHuskTowns.java @@ -42,7 +42,9 @@ import net.william278.husktowns.database.Database; import net.william278.husktowns.events.BukkitEventDispatcher; import net.william278.husktowns.hook.*; -import net.william278.husktowns.hook.WorldGuardHook; +import net.william278.husktowns.hook.map.BlueMapHook; +import net.william278.husktowns.hook.map.DynmapHook; +import net.william278.husktowns.hook.map.Pl3xMapHook; import net.william278.husktowns.listener.BukkitListener; import net.william278.husktowns.manager.Manager; import net.william278.husktowns.network.Broker; @@ -125,8 +127,8 @@ public class BukkitHuskTowns extends JavaPlugin implements HuskTowns, BukkitTask @Nullable @Getter(AccessLevel.NONE) private Advancement advancements; - - WorldGuardHook worldGuardHook; + @Setter + private HookManager hookManager; @TestOnly @SuppressWarnings("unused") @@ -136,62 +138,69 @@ private BukkitHuskTowns(@NotNull JavaPluginLoader loader, @NotNull PluginDescrip } @Override - public void onEnable() { - // Initialize PaperLib and Adventure - this.paperLib = new MorePaperLib(this); - this.audiences = BukkitAudiences.create(this); - + public void onLoad() { // Load configuration and subsystems this.loadConfig(); if (this.settings.getGeneral().isDoAdvancements()) { loadAdvancements(); } - // Prepare the database and networking system - this.database = this.loadDatabase(); - if (!database.hasLoaded()) { - log(Level.SEVERE, "Failed to load database! Please check your credentials! Disabling plugin..."); - Bukkit.getPluginManager().disablePlugin(this); - return; - } - - // Load manager and broker - this.manager = new Manager(this); - this.broker = this.loadBroker(); - // Register hooks + this.hookManager = new BukkitHookManager(this); final PluginManager plugins = Bukkit.getPluginManager(); if (settings.getGeneral().isEconomyHook()) { if (plugins.getPlugin("Vault") != null) { - this.registerHook(new VaultEconomyHook(this)); + hookManager.registerHook(new VaultEconomyHook(this)); } } if (settings.getGeneral().getWebMapHook().isEnabled()) { if (plugins.getPlugin("BlueMap") != null) { - this.registerHook(new BlueMapHook(this)); + hookManager.registerHook(new BlueMapHook(this)); } else if (plugins.getPlugin("dynmap") != null) { - this.registerHook(new DynmapHook(this)); + hookManager.registerHook(new DynmapHook(this)); } else if (plugins.getPlugin("Pl3xMap") != null) { - this.registerHook(new Pl3xMapHook(this)); + hookManager.registerHook(new Pl3xMapHook(this)); } } if (settings.getGeneral().isLuckpermsContextsHook() && plugins.getPlugin("LuckPerms") != null) { - this.registerHook(new LuckPermsHook(this)); + hookManager.registerHook(new LuckPermsHook(this)); } if (settings.getGeneral().isPlaceholderapiHook() && plugins.getPlugin("PlaceholderAPI") != null) { - this.registerHook(new PlaceholderAPIHook(this)); + hookManager.registerHook(new PlaceholderAPIHook(this)); } if (settings.getGeneral().isHuskhomesHook() && plugins.getPlugin("HuskHomes") != null) { - this.registerHook(new HuskHomesHook(this)); + hookManager.registerHook(new HuskHomesHook(this)); } if (settings.getGeneral().isPlanHook() && plugins.getPlugin("Plan") != null) { - this.registerHook(new PlanHook(this)); + hookManager.registerHook(new PlanHook(this)); } if (settings.getGeneral().isWorldGuardHook() && plugins.getPlugin("WorldGuard") != null) { - worldGuardHook = new BukkitWorldGuardHook(this); - this.registerHook(worldGuardHook); + hookManager.registerHook(new BukkitWorldGuardHook(this)); } + hookManager.registerOnLoad(); + } + + @Override + public void onEnable() { + // Initialize PaperLib and Adventure + this.paperLib = new MorePaperLib(this); + this.audiences = BukkitAudiences.create(this); + + // Prepare the database and networking system + this.database = this.loadDatabase(); + if (!database.hasLoaded()) { + log(Level.SEVERE, "Failed to load database! Please check your credentials! Disabling plugin..."); + Bukkit.getPluginManager().disablePlugin(this); + return; + } + + // Load manager and broker + this.manager = new Manager(this); + this.broker = this.loadBroker(); + + hookManager.registerOnEnable(); + // Load towns and claim worlds this.loadData(); @@ -208,6 +217,8 @@ public void onEnable() { initializeMetrics(); log(Level.INFO, "Enabled HuskTowns v" + getVersion()); checkForUpdates(); + + runAsyncDelayed(hookManager::registerDelayed, 20L); } @Override @@ -243,8 +254,8 @@ public Optional getMessageBroker() { } @Override - public WorldGuardHook getWorldGuardHook() { - return worldGuardHook; + public @NotNull HookManager getHookManager() { + return hookManager; } @Override @@ -364,7 +375,7 @@ private void initializeMetrics() { metrics.addCustomChart(new SimplePie("using_map", () -> getMapHook().isPresent() ? "true" : "false")); getMapHook().ifPresent(hook -> metrics.addCustomChart(new SimplePie("map_type", - () -> hook.getName().toLowerCase()))); + () -> hook.getHookInfo().id().toLowerCase()))); getMessageBroker().ifPresent(broker -> metrics.addCustomChart(new SimplePie("messenger_type", () -> settings.getCrossServer().getBrokerType().name().toLowerCase()))); } catch (Exception e) { diff --git a/bukkit/src/main/java/net/william278/husktowns/hook/BukkitHookManager.java b/bukkit/src/main/java/net/william278/husktowns/hook/BukkitHookManager.java new file mode 100644 index 00000000..0b7a7f94 --- /dev/null +++ b/bukkit/src/main/java/net/william278/husktowns/hook/BukkitHookManager.java @@ -0,0 +1,71 @@ +/* + * This file is part of HuskTowns, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.william278.husktowns.hook; + +import net.william278.husktowns.HuskTowns; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; + +public class BukkitHookManager extends HookManager { + public BukkitHookManager(@NotNull HuskTowns plugin) { + super(plugin); + } + + @Override + public void registerOnLoad() { + plugin.log(Level.INFO, "Loading early hooks..."); + AtomicInteger loaded = new AtomicInteger(); + registeredHooks.stream().filter(Hook::isDisabled) + .filter((hook) -> hook.getHookInfo().register() == PluginHook.Register.ON_LOAD) + .forEach((hook) -> { + hook.enable(); + loaded.getAndIncrement(); + }); + plugin.log(Level.INFO, "Successfully loaded %s hooks".formatted(loaded.get())); + } + + @Override + public void registerOnEnable() { + plugin.log(Level.INFO, "Loading hooks..."); + AtomicInteger loaded = new AtomicInteger(); + registeredHooks.stream().filter(Hook::isDisabled) + .filter((hook) -> hook.getHookInfo().register() == PluginHook.Register.ON_ENABLE) + .forEach((hook) -> { + hook.enable(); + loaded.getAndIncrement(); + }); + plugin.log(Level.INFO, "Successfully loaded %s hooks".formatted(loaded.get())); + } + + @Override + public void registerDelayed() { + plugin.log(Level.INFO, "Loading late hooks..."); + AtomicInteger loaded = new AtomicInteger(); + registeredHooks.stream().filter(Hook::isDisabled) + .filter((hook) -> hook.getHookInfo().register() == PluginHook.Register.DELAYED) + .forEach((hook) -> { + hook.enable(); + loaded.getAndIncrement(); + }); + plugin.log(Level.INFO, "Successfully loaded %s hooks".formatted(loaded.get())); + } +} diff --git a/bukkit/src/main/java/net/william278/husktowns/hook/BukkitWorldGuardHook.java b/bukkit/src/main/java/net/william278/husktowns/hook/BukkitWorldGuardHook.java index 07a0c09c..c1fbccb6 100644 --- a/bukkit/src/main/java/net/william278/husktowns/hook/BukkitWorldGuardHook.java +++ b/bukkit/src/main/java/net/william278/husktowns/hook/BukkitWorldGuardHook.java @@ -34,6 +34,7 @@ import org.jetbrains.annotations.NotNull; public class BukkitWorldGuardHook extends WorldGuardHook { + @PluginHook(id = "WorldGuard", register = PluginHook.Register.ON_LOAD, platform = "bukkit") public BukkitWorldGuardHook(@NotNull HuskTowns plugin) { super(plugin); } diff --git a/bukkit/src/main/java/net/william278/husktowns/hook/HuskHomesHook.java b/bukkit/src/main/java/net/william278/husktowns/hook/HuskHomesHook.java index ad69d48f..3828e29a 100644 --- a/bukkit/src/main/java/net/william278/husktowns/hook/HuskHomesHook.java +++ b/bukkit/src/main/java/net/william278/husktowns/hook/HuskHomesHook.java @@ -44,9 +44,9 @@ public class HuskHomesHook extends TeleportationHook implements Listener { @Nullable private HuskHomesAPI api; - + @PluginHook(id = "HuskHomes", register = PluginHook.Register.ON_ENABLE, platform = "bukkit") public HuskHomesHook(@NotNull HuskTowns plugin) { - super(plugin, "HuskHomes"); + super(plugin); } @Override diff --git a/bukkit/src/main/java/net/william278/husktowns/hook/LuckPermsHook.java b/bukkit/src/main/java/net/william278/husktowns/hook/LuckPermsHook.java index 67c68eb2..c844fb0c 100644 --- a/bukkit/src/main/java/net/william278/husktowns/hook/LuckPermsHook.java +++ b/bukkit/src/main/java/net/william278/husktowns/hook/LuckPermsHook.java @@ -46,12 +46,12 @@ import java.util.logging.Level; public class LuckPermsHook extends Hook { - private ContextManager contexts; private final List> calculators = new ArrayList<>(); + @PluginHook(id = "LuckPerms", register = PluginHook.Register.ON_ENABLE, platform = "bukkit") public LuckPermsHook(@NotNull HuskTowns plugin) { - super(plugin, "LuckPerms"); + super(plugin); } @Override diff --git a/bukkit/src/main/java/net/william278/husktowns/hook/PlaceholderAPIHook.java b/bukkit/src/main/java/net/william278/husktowns/hook/PlaceholderAPIHook.java index d59f2c1e..1b3d0b9e 100644 --- a/bukkit/src/main/java/net/william278/husktowns/hook/PlaceholderAPIHook.java +++ b/bukkit/src/main/java/net/william278/husktowns/hook/PlaceholderAPIHook.java @@ -44,8 +44,9 @@ import java.util.stream.Collectors; public class PlaceholderAPIHook extends Hook { + @PluginHook(id = "PlaceholderAPI", register = PluginHook.Register.ON_ENABLE, platform = "bukkit") public PlaceholderAPIHook(@NotNull HuskTowns plugin) { - super(plugin, "PlaceholderAPI"); + super(plugin); } @Override diff --git a/bukkit/src/main/java/net/william278/husktowns/hook/VaultEconomyHook.java b/bukkit/src/main/java/net/william278/husktowns/hook/VaultEconomyHook.java index bccd175c..1a5c6ada 100644 --- a/bukkit/src/main/java/net/william278/husktowns/hook/VaultEconomyHook.java +++ b/bukkit/src/main/java/net/william278/husktowns/hook/VaultEconomyHook.java @@ -32,11 +32,11 @@ import java.util.logging.Level; public class VaultEconomyHook extends EconomyHook { - protected Economy economy; + @PluginHook(id = "Vault", register = PluginHook.Register.ON_ENABLE, platform = "bukkit") public VaultEconomyHook(@NotNull HuskTowns plugin) { - super(plugin, "Vault"); + super(plugin); } @Override diff --git a/bukkit/src/main/java/net/william278/husktowns/util/BukkitTask.java b/bukkit/src/main/java/net/william278/husktowns/util/BukkitTask.java index a99ca2e4..d8cfadc3 100644 --- a/bukkit/src/main/java/net/william278/husktowns/util/BukkitTask.java +++ b/bukkit/src/main/java/net/william278/husktowns/util/BukkitTask.java @@ -65,8 +65,8 @@ class Async extends Task.Async implements BukkitTask { private ScheduledTask task; - protected Async(@NotNull HuskTowns plugin, @NotNull Runnable runnable) { - super(plugin, runnable); + protected Async(@NotNull HuskTowns plugin, @NotNull Runnable runnable, long delayTicks) { + super(plugin, runnable, delayTicks); } @Override @@ -84,8 +84,18 @@ public void run() { return; } + if (delayTicks > 0) { + this.task = getScheduler().globalRegionalScheduler().runDelayed(runnable, delayTicks); + } else { + this.task = getScheduler().globalRegionalScheduler().run(runnable); + } + if (!cancelled) { - this.task = getScheduler().asyncScheduler().run(runnable); + if (delayTicks > 0) { + this.task = getScheduler().asyncScheduler().runDelayed(runnable, Duration.of(delayTicks / 20 * 1000, ChronoUnit.MILLIS)); + } else { + this.task = getScheduler().asyncScheduler().run(runnable); + } } } } @@ -135,8 +145,8 @@ default Task.Sync getSyncTask(@NotNull Runnable runnable, long delayTicks) { @NotNull @Override - default Task.Async getAsyncTask(@NotNull Runnable runnable) { - return new BukkitTask.Async(getPlugin(), runnable); + default Task.Async getAsyncTask(@NotNull Runnable runnable, long delayTicks) { + return new BukkitTask.Async(getPlugin(), runnable, delayTicks); } @NotNull diff --git a/bukkit/src/test/java/net/william278/husktowns/BukkitPluginTests.java b/bukkit/src/test/java/net/william278/husktowns/BukkitPluginTests.java index 05d05b3f..4a2cb082 100644 --- a/bukkit/src/test/java/net/william278/husktowns/BukkitPluginTests.java +++ b/bukkit/src/test/java/net/william278/husktowns/BukkitPluginTests.java @@ -25,14 +25,12 @@ import net.william278.husktowns.audit.Action; import net.william278.husktowns.audit.Log; import net.william278.husktowns.claim.*; -import net.william278.husktowns.hook.BukkitWorldGuardHook; import net.william278.husktowns.map.MapSquare; import net.william278.husktowns.town.Town; import net.william278.husktowns.user.BukkitUser; import net.william278.husktowns.user.OnlineUser; import net.william278.husktowns.user.Preferences; import org.bukkit.Location; -import org.bukkit.entity.Husk; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.*; @@ -61,12 +59,6 @@ public static void setUpPlugin() { plugin = MockBukkit.load(BukkitHuskTowns.class); } - @AfterAll - @DisplayName("Tear down Plugin") - public static void tearDownPlugin() { - MockBukkit.unmock(); - } - @Order(1) @Nested @DisplayName("Data Validation Tests") diff --git a/common/src/main/java/net/william278/husktowns/HuskTowns.java b/common/src/main/java/net/william278/husktowns/HuskTowns.java index b3549e4d..8fcf7089 100644 --- a/common/src/main/java/net/william278/husktowns/HuskTowns.java +++ b/common/src/main/java/net/william278/husktowns/HuskTowns.java @@ -35,7 +35,10 @@ import net.william278.husktowns.database.MySqlDatabase; import net.william278.husktowns.database.SqLiteDatabase; import net.william278.husktowns.events.EventDispatcher; -import net.william278.husktowns.hook.*; +import net.william278.husktowns.hook.EconomyHook; +import net.william278.husktowns.hook.HookManager; +import net.william278.husktowns.hook.MapHook; +import net.william278.husktowns.hook.TeleportationHook; import net.william278.husktowns.listener.OperationHandler; import net.william278.husktowns.listener.UserListener; import net.william278.husktowns.manager.Manager; @@ -86,7 +89,8 @@ public interface HuskTowns extends Task.Supplier, ConfigProvider, EventDispatche @NotNull Map> getInvites(); - WorldGuardHook getWorldGuardHook(); + @NotNull + HookManager getHookManager(); default void addInvite(@NotNull UUID recipient, @NotNull Invite invite) { if (!getInvites().containsKey(recipient)) { @@ -192,7 +196,6 @@ default void loadData() { log(Level.INFO, String.format("Loaded data in %s seconds.", (ChronoUnit.MILLIS.between(startTime, LocalTime.now()) / 1000d))); setLoaded(true); - loadHooks(); } catch (IllegalStateException e) { setLoaded(false); log(Level.SEVERE, String.format("Failed to load data (after %s seconds). Interaction will be disabled!", @@ -424,27 +427,8 @@ default void teleportUser(@NotNull OnlineUser user, @NotNull Position position, double getHighestYAt(double x, double z, @NotNull World world); - @NotNull - Set getHooks(); - - default void registerHook(@NotNull Hook hook) { - getHooks().add(hook); - } - - default void loadHooks() { - getHooks().stream().filter(Hook::isDisabled).forEach(Hook::enable); - log(Level.INFO, "Successfully loaded " + getHooks().size() + " hooks"); - } - - default Optional getHook(@NotNull Class hookClass) { - return getHooks().stream() - .filter(hook -> hookClass.isAssignableFrom(hook.getClass())) - .map(hookClass::cast) - .findFirst(); - } - default Optional getEconomyHook() { - return getHook(EconomyHook.class); + return getHookManager(). getHook(EconomyHook.class); } @NotNull @@ -457,11 +441,11 @@ default String formatMoney(@NotNull BigDecimal amount) { } default Optional getMapHook() { - return getHook(MapHook.class); + return getHookManager().getHook(MapHook.class); } default Optional getTeleportationHook() { - return getHook(TeleportationHook.class); + return getHookManager().getHook(TeleportationHook.class); } void dispatchCommand(@NotNull String command); diff --git a/common/src/main/java/net/william278/husktowns/hook/EconomyHook.java b/common/src/main/java/net/william278/husktowns/hook/EconomyHook.java index aed517aa..8e4f4211 100644 --- a/common/src/main/java/net/william278/husktowns/hook/EconomyHook.java +++ b/common/src/main/java/net/william278/husktowns/hook/EconomyHook.java @@ -28,8 +28,8 @@ public abstract class EconomyHook extends Hook { - protected EconomyHook(@NotNull HuskTowns plugin, @NotNull String name) { - super(plugin, name); + protected EconomyHook(@NotNull HuskTowns plugin) { + super(plugin); } /** diff --git a/common/src/main/java/net/william278/husktowns/hook/Hook.java b/common/src/main/java/net/william278/husktowns/hook/Hook.java index 4068bc08..77360371 100644 --- a/common/src/main/java/net/william278/husktowns/hook/Hook.java +++ b/common/src/main/java/net/william278/husktowns/hook/Hook.java @@ -22,15 +22,19 @@ import net.william278.husktowns.HuskTowns; import org.jetbrains.annotations.NotNull; +import java.util.Arrays; + public abstract class Hook { protected final HuskTowns plugin; - private final String name; + private final PluginHook hookInfo; private boolean enabled = false; - protected Hook(@NotNull HuskTowns plugin, @NotNull String name) { + protected Hook(@NotNull HuskTowns plugin) { this.plugin = plugin; - this.name = name; + this.hookInfo = Arrays.stream(this.getClass().getMethods()).filter(method -> + method.getAnnotation(PluginHook.class) != null).map(method -> + method.getAnnotation(PluginHook.class)).findFirst().orElse(null); } /** @@ -42,6 +46,9 @@ protected Hook(@NotNull HuskTowns plugin, @NotNull String name) { * Enable the hook */ public final void enable() { + if (hookInfo == null) { + throw new RuntimeException("Failed to register hook %s! (No @PluginHook annotation found on constructor)".formatted(this.getClass().getSimpleName())); + } this.onEnable(); this.enabled = true; } @@ -56,13 +63,13 @@ public boolean isDisabled() { } /** - * Get the name of the hook + * Get static info about the hook * - * @return the name of the hook + * @return the @interface PluginHook */ @NotNull - public String getName() { - return name; + public PluginHook getHookInfo() { + return hookInfo; } } diff --git a/common/src/main/java/net/william278/husktowns/hook/HookManager.java b/common/src/main/java/net/william278/husktowns/hook/HookManager.java new file mode 100644 index 00000000..b11ac513 --- /dev/null +++ b/common/src/main/java/net/william278/husktowns/hook/HookManager.java @@ -0,0 +1,55 @@ +/* + * This file is part of HuskTowns, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.william278.husktowns.hook; + +import lombok.AllArgsConstructor; +import net.william278.husktowns.HuskTowns; +import org.jetbrains.annotations.NotNull; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Optional; + +@AllArgsConstructor +public abstract class HookManager { + protected final HuskTowns plugin; + protected final static HashSet registeredHooks = new HashSet<>(); + + public abstract void registerOnLoad(); + + public abstract void registerOnEnable(); + + public abstract void registerDelayed(); + + public Optional getHook(@NotNull Class hookClass) { + return registeredHooks.stream() + .filter(hook -> hookClass.isAssignableFrom(hook.getClass())) + .map(hookClass::cast) + .findFirst(); + } + + public void registerHook(@NotNull Hook hook) { + if (getHook(hook.getClass()).isPresent() || registeredHooks.stream().anyMatch(var1 -> + Objects.equals(var1.getHookInfo().id(), hook.getHookInfo().id()))) { + throw new RuntimeException("Hook with matching Class or ID already registered! ID: %s".formatted(hook.getHookInfo().id())); + } + registeredHooks.add(hook); + } +} diff --git a/common/src/main/java/net/william278/husktowns/hook/MapHook.java b/common/src/main/java/net/william278/husktowns/hook/MapHook.java index 66df453f..1af8ff7e 100644 --- a/common/src/main/java/net/william278/husktowns/hook/MapHook.java +++ b/common/src/main/java/net/william278/husktowns/hook/MapHook.java @@ -29,8 +29,8 @@ public abstract class MapHook extends Hook { - protected MapHook(@NotNull HuskTowns plugin, @NotNull String name) { - super(plugin, name); + protected MapHook(@NotNull HuskTowns plugin) { + super(plugin); } public abstract void setClaimMarker(@NotNull TownClaim claim, @NotNull World world); @@ -62,7 +62,7 @@ public final void reloadClaimMarkers(@NotNull Town town) { @NotNull protected final String getMarkerSetKey() { - return plugin.getKey(getName().toLowerCase(), "markers").toString(); + return plugin.getKey(getHookInfo().id().toLowerCase(), "markers").toString(); } } diff --git a/common/src/main/java/net/william278/husktowns/hook/PlanHook.java b/common/src/main/java/net/william278/husktowns/hook/PlanHook.java index 648bbb5f..9615dfc3 100644 --- a/common/src/main/java/net/william278/husktowns/hook/PlanHook.java +++ b/common/src/main/java/net/william278/husktowns/hook/PlanHook.java @@ -39,8 +39,9 @@ import java.util.logging.Level; public class PlanHook extends Hook { + @PluginHook(id = "Plan", register = PluginHook.Register.ON_ENABLE, platform = "common") public PlanHook(@NotNull HuskTowns plugin) { - super(plugin, "Plan"); + super(plugin); } @Override diff --git a/common/src/main/java/net/william278/husktowns/hook/PluginHook.java b/common/src/main/java/net/william278/husktowns/hook/PluginHook.java new file mode 100644 index 00000000..4e62f914 --- /dev/null +++ b/common/src/main/java/net/william278/husktowns/hook/PluginHook.java @@ -0,0 +1,37 @@ +/* + * This file is part of HuskTowns, licensed under the Apache License 2.0. + * + * Copyright (c) William278 + * Copyright (c) contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.william278.husktowns.hook; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(value = ElementType.CONSTRUCTOR) +@Retention(value = RetentionPolicy.RUNTIME) +public @interface PluginHook { + String id(); + Register register(); + String platform(); + + enum Register { + ON_LOAD, ON_ENABLE, DELAYED + } +} diff --git a/common/src/main/java/net/william278/husktowns/hook/TeleportationHook.java b/common/src/main/java/net/william278/husktowns/hook/TeleportationHook.java index bded484c..7b8d04a2 100644 --- a/common/src/main/java/net/william278/husktowns/hook/TeleportationHook.java +++ b/common/src/main/java/net/william278/husktowns/hook/TeleportationHook.java @@ -28,8 +28,8 @@ * A hook for handling player teleportation */ public abstract class TeleportationHook extends Hook { - protected TeleportationHook(@NotNull HuskTowns plugin, @NotNull String name) { - super(plugin, name); + protected TeleportationHook(@NotNull HuskTowns plugin) { + super(plugin); } /** diff --git a/common/src/main/java/net/william278/husktowns/hook/WorldGuardHook.java b/common/src/main/java/net/william278/husktowns/hook/WorldGuardHook.java index c1712a39..b13606db 100644 --- a/common/src/main/java/net/william278/husktowns/hook/WorldGuardHook.java +++ b/common/src/main/java/net/william278/husktowns/hook/WorldGuardHook.java @@ -26,12 +26,10 @@ import net.william278.husktowns.claim.Chunk; import org.jetbrains.annotations.NotNull; - public abstract class WorldGuardHook extends Hook { public final static StateFlag CLAIMING = new StateFlag("husktowns-claim", false); public WorldGuardHook(@NotNull HuskTowns plugin) { - super(plugin, "WorldGuard"); - enable(); + super(plugin); } @Override diff --git a/common/src/main/java/net/william278/husktowns/hook/BlueMapHook.java b/common/src/main/java/net/william278/husktowns/hook/map/BlueMapHook.java similarity index 95% rename from common/src/main/java/net/william278/husktowns/hook/BlueMapHook.java rename to common/src/main/java/net/william278/husktowns/hook/map/BlueMapHook.java index a3052041..a7596ea1 100644 --- a/common/src/main/java/net/william278/husktowns/hook/BlueMapHook.java +++ b/common/src/main/java/net/william278/husktowns/hook/map/BlueMapHook.java @@ -17,7 +17,7 @@ * limitations under the License. */ -package net.william278.husktowns.hook; +package net.william278.husktowns.hook.map; import de.bluecolored.bluemap.api.BlueMapAPI; import de.bluecolored.bluemap.api.BlueMapMap; @@ -29,6 +29,8 @@ import net.william278.husktowns.HuskTowns; import net.william278.husktowns.claim.TownClaim; import net.william278.husktowns.claim.World; +import net.william278.husktowns.hook.MapHook; +import net.william278.husktowns.hook.PluginHook; import org.jetbrains.annotations.NotNull; import java.util.HashMap; @@ -40,9 +42,9 @@ public final class BlueMapHook extends MapHook { private Map markerSets; - + @PluginHook(id = "BlueMap", register = PluginHook.Register.ON_ENABLE, platform = "common") public BlueMapHook(@NotNull HuskTowns plugin) { - super(plugin, "BlueMap"); + super(plugin); } @Override diff --git a/common/src/main/java/net/william278/husktowns/hook/DynmapHook.java b/common/src/main/java/net/william278/husktowns/hook/map/DynmapHook.java similarity index 96% rename from common/src/main/java/net/william278/husktowns/hook/DynmapHook.java rename to common/src/main/java/net/william278/husktowns/hook/map/DynmapHook.java index c57f6e5c..5091cbef 100644 --- a/common/src/main/java/net/william278/husktowns/hook/DynmapHook.java +++ b/common/src/main/java/net/william278/husktowns/hook/map/DynmapHook.java @@ -17,12 +17,14 @@ * limitations under the License. */ -package net.william278.husktowns.hook; +package net.william278.husktowns.hook.map; import net.william278.husktowns.HuskTowns; import net.william278.husktowns.claim.Chunk; import net.william278.husktowns.claim.TownClaim; import net.william278.husktowns.claim.World; +import net.william278.husktowns.hook.MapHook; +import net.william278.husktowns.hook.PluginHook; import org.dynmap.DynmapCommonAPI; import org.dynmap.DynmapCommonAPIListener; import org.dynmap.markers.AreaMarker; @@ -40,9 +42,9 @@ public class DynmapHook extends MapHook { private DynmapCommonAPI dynmapApi; @Nullable private MarkerSet markerSet; - + @PluginHook(id = "Dynmap", register = PluginHook.Register.ON_ENABLE, platform = "common") public DynmapHook(@NotNull HuskTowns plugin) { - super(plugin, "Dynmap"); + super(plugin); DynmapCommonAPIListener.register(new DynmapCommonAPIListener() { @Override public void apiEnabled(@NotNull DynmapCommonAPI dynmapCommonAPI) { diff --git a/common/src/main/java/net/william278/husktowns/hook/Pl3xMapHook.java b/common/src/main/java/net/william278/husktowns/hook/map/Pl3xMapHook.java similarity index 96% rename from common/src/main/java/net/william278/husktowns/hook/Pl3xMapHook.java rename to common/src/main/java/net/william278/husktowns/hook/map/Pl3xMapHook.java index 8a583dd6..8374e9a3 100644 --- a/common/src/main/java/net/william278/husktowns/hook/Pl3xMapHook.java +++ b/common/src/main/java/net/william278/husktowns/hook/map/Pl3xMapHook.java @@ -17,7 +17,7 @@ * limitations under the License. */ -package net.william278.husktowns.hook; +package net.william278.husktowns.hook.map; import net.kyori.adventure.text.format.TextColor; import net.pl3x.map.core.Pl3xMap; @@ -36,6 +36,8 @@ import net.william278.husktowns.claim.ClaimWorld; import net.william278.husktowns.claim.TownClaim; import net.william278.husktowns.claim.World; +import net.william278.husktowns.hook.MapHook; +import net.william278.husktowns.hook.PluginHook; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -51,8 +53,9 @@ public class Pl3xMapHook extends MapHook { private static final String CLAIMS_LAYER = "claim_markers"; private final ConcurrentHashMap> claims = new ConcurrentHashMap<>(); + @PluginHook(id = "Pl3xMap", register = PluginHook.Register.ON_ENABLE, platform = "common") public Pl3xMapHook(@NotNull HuskTowns plugin) { - super(plugin, "Pl3xMap"); + super(plugin); } @Override diff --git a/common/src/main/java/net/william278/husktowns/manager/ClaimsManager.java b/common/src/main/java/net/william278/husktowns/manager/ClaimsManager.java index dc0c2ece..0e1b8d27 100644 --- a/common/src/main/java/net/william278/husktowns/manager/ClaimsManager.java +++ b/common/src/main/java/net/william278/husktowns/manager/ClaimsManager.java @@ -25,6 +25,7 @@ import net.william278.husktowns.audit.Action; import net.william278.husktowns.claim.*; import net.william278.husktowns.config.Settings; +import net.william278.husktowns.hook.WorldGuardHook; import net.william278.husktowns.map.ClaimMap; import net.william278.husktowns.network.Message; import net.william278.husktowns.network.Payload; @@ -54,7 +55,8 @@ public void createClaim(@NotNull OnlineUser user, @NotNull World world, @NotNull .ifPresent(user::sendMessage); return; } - if (plugin.getWorldGuardHook() != null && plugin.getWorldGuardHook().isChunkInRestrictedRegion(chunk, world.getName())) { + final Optional worldGuardHook = plugin.getHookManager().getHook(WorldGuardHook.class); + if (worldGuardHook.isPresent() && worldGuardHook.get().isChunkInRestrictedRegion(chunk, world.getName())) { plugin.getLocales().getLocale("error_chunk_not_claimable").ifPresent(user::sendMessage); return; } diff --git a/common/src/main/java/net/william278/husktowns/map/MapSquare.java b/common/src/main/java/net/william278/husktowns/map/MapSquare.java index 35b2580c..fb5a2904 100644 --- a/common/src/main/java/net/william278/husktowns/map/MapSquare.java +++ b/common/src/main/java/net/william278/husktowns/map/MapSquare.java @@ -28,6 +28,7 @@ import net.william278.husktowns.claim.Claim; import net.william278.husktowns.claim.TownClaim; import net.william278.husktowns.claim.World; +import net.william278.husktowns.hook.WorldGuardHook; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -151,7 +152,8 @@ private boolean isWilderness() { } private boolean isProtected() { - return plugin.getWorldGuardHook() != null && plugin.getWorldGuardHook().isChunkInRestrictedRegion(chunk, world.getName()); + Optional hook = plugin.getHookManager().getHook(WorldGuardHook.class); + return hook.isPresent() && hook.get().isChunkInRestrictedRegion(chunk, world.getName()); } public void markAsCurrentPosition(boolean isCurrentPosition) { this.isCurrentPosition = isCurrentPosition; diff --git a/common/src/main/java/net/william278/husktowns/util/Task.java b/common/src/main/java/net/william278/husktowns/util/Task.java index dff3b060..7b103427 100644 --- a/common/src/main/java/net/william278/husktowns/util/Task.java +++ b/common/src/main/java/net/william278/husktowns/util/Task.java @@ -51,8 +51,11 @@ public HuskTowns getPlugin() { abstract class Async extends Base { - protected Async(@NotNull HuskTowns plugin, @NotNull Runnable runnable) { + protected long delayTicks; + + protected Async(@NotNull HuskTowns plugin, @NotNull Runnable runnable, long delayTicks) { super(plugin, runnable); + this.delayTicks = delayTicks; } } @@ -86,7 +89,7 @@ interface Supplier { Task.Sync getSyncTask(@NotNull Runnable runnable, long delayTicks); @NotNull - Task.Async getAsyncTask(@NotNull Runnable runnable); + Task.Async getAsyncTask(@NotNull Runnable runnable, long delayTicks); @NotNull Task.Repeating getRepeatingTask(@NotNull Runnable runnable, long repeatingTicks); @@ -104,12 +107,17 @@ default Task.Sync runSync(@NotNull Runnable runnable) { } @NotNull - default Task.Async runAsync(@NotNull Runnable runnable) { - final Task.Async task = getAsyncTask(runnable); + default Task.Async runAsyncDelayed(@NotNull Runnable runnable, long delayTicks) { + final Task.Async task = getAsyncTask(runnable, delayTicks); task.run(); return task; } + @NotNull + default Task.Async runAsync(@NotNull Runnable runnable) { + return runAsyncDelayed(runnable, 0); + } + default CompletableFuture supplyAsync(@NotNull java.util.function.Supplier supplier) { final CompletableFuture future = new CompletableFuture<>(); runAsync(() -> {