diff --git a/api-internal/pom.xml b/api-internal/pom.xml index 49cc600b..aa108e74 100644 --- a/api-internal/pom.xml +++ b/api-internal/pom.xml @@ -21,6 +21,12 @@ gson 2.11.0 + + org.jetbrains + annotations + 24.0.0 + compile + diff --git a/api-internal/src/main/java/at/pavlov/internal/Hook.java b/api-internal/src/main/java/at/pavlov/internal/Hook.java index 9d492071..b44afc95 100644 --- a/api-internal/src/main/java/at/pavlov/internal/Hook.java +++ b/api-internal/src/main/java/at/pavlov/internal/Hook.java @@ -9,7 +9,7 @@ default boolean active() { } void onEnable(); - void onDisable(); + default void onDisable() {} Class> getTypeClass(); default @NotNull String enabledMessage() { diff --git a/api-internal/src/main/java/at/pavlov/internal/HookManager.java b/api-internal/src/main/java/at/pavlov/internal/HookManager.java index fb2d17c6..d278dcb4 100644 --- a/api-internal/src/main/java/at/pavlov/internal/HookManager.java +++ b/api-internal/src/main/java/at/pavlov/internal/HookManager.java @@ -1,10 +1,12 @@ package at.pavlov.internal; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.function.Consumer; public class HookManager { private final Map>, Hook> hooks = new HashMap<>(); @@ -30,7 +32,7 @@ public boolean isRegistered(@NotNull Class> type) { return false; } - public > @NotNull T getHook(@NotNull Class type) { + public > @Nullable T getHook(@NotNull Class type) { Hook hook = this.hooks.get(type); if (hook != null) { return type.cast(hook); @@ -42,7 +44,21 @@ public boolean isRegistered(@NotNull Class> type) { } } - throw new IllegalArgumentException("No registered hook of type " + type.getName() + "!"); + return null; + } + + public > void processIfPresent(@NotNull Class type, Consumer consumer) { + T hook = getHook(type); + if (hook == null || !hook.active()) { + return; + } + + C hookContent = hook.hook(); + if (hookContent == null) { + return; + } + + consumer.accept(hookContent); } /** diff --git a/cannons-bukkit/pom.xml b/cannons-bukkit/pom.xml index 75debaa4..380c9a96 100644 --- a/cannons-bukkit/pom.xml +++ b/cannons-bukkit/pom.xml @@ -65,6 +65,10 @@ true + + glaremasters repo + https://repo.glaremasters.me/repository/towny/ + @@ -149,6 +153,12 @@ 2.11.6 provided + + com.palmergames.bukkit.towny + towny + 0.101.1.0 + provided + diff --git a/cannons-bukkit/src/main/java/at/pavlov/cannons/Aiming.java b/cannons-bukkit/src/main/java/at/pavlov/cannons/Aiming.java index 0ca1f5e0..9de780a8 100644 --- a/cannons-bukkit/src/main/java/at/pavlov/cannons/Aiming.java +++ b/cannons-bukkit/src/main/java/at/pavlov/cannons/Aiming.java @@ -18,10 +18,13 @@ import at.pavlov.cannons.event.CannonLinkAimingEvent; import at.pavlov.cannons.event.CannonTargetEvent; import at.pavlov.cannons.event.CannonUseEvent; +import at.pavlov.cannons.hooks.towny.TownyHook; import at.pavlov.cannons.projectile.Projectile; import at.pavlov.cannons.scheduler.FakeBlockHandler; import at.pavlov.cannons.utils.CannonsUtil; import at.pavlov.cannons.utils.SoundUtils; +import com.palmergames.bukkit.towny.object.Resident; +import com.palmergames.bukkit.towny.utils.CombatUtil; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -37,11 +40,11 @@ import org.bukkit.util.Vector; import java.text.DecimalFormat; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Random; import java.util.UUID; @@ -651,7 +654,7 @@ private void findSuitableTarget(Cannon cannon, Map targets) { return; } - ArrayList possibleTargets = new ArrayList<>(); + LinkedList possibleTargets = new LinkedList<>(); for (Target t : targets.values()) { TargetType type = t.targetType(); @@ -667,6 +670,26 @@ private void findSuitableTarget(Cannon cannon, Map targets) { if (cannon.isWhitelisted(t.uniqueId())) continue; //Player if (type == TargetType.PLAYER) { + + final boolean[] skip = new boolean[1]; + Cannons.getPlugin().getHookManager().processIfPresent(TownyHook.class, townyApi -> { + Resident ownerResident = townyApi.getResident(cannon.getOwner()); + if (ownerResident == null) { + return; + } + + Resident residentTarget = townyApi.getResident(t.uniqueId()); + if (residentTarget == null) { + return; + } + + if (CombatUtil.isAlly(residentTarget, ownerResident)) { + skip[0] = true; + } + }); + + if (skip[0]) continue; + // get solution handlePossibleTarget(cannon, t, possibleTargets); continue; @@ -674,6 +697,7 @@ private void findSuitableTarget(Cannon cannon, Map targets) { Cannon tCannon = CannonManager.getCannon(t.uniqueId()); if (tCannon == null) continue; + if (cannon.isWhitelisted(tCannon.getOwner())) continue; //Cannons & Other have same handling //check if the owner is whitelisted if (type == TargetType.CANNON || type == TargetType.OTHER) { @@ -697,7 +721,7 @@ private void findSuitableTarget(Cannon cannon, Map targets) { } } - private void handlePossibleTarget(Cannon cannon, Target t, ArrayList possibleTargets) { + private void handlePossibleTarget(Cannon cannon, Target t, List possibleTargets) { if (canFindTargetSolution(cannon, t)) { possibleTargets.add(t); } diff --git a/cannons-bukkit/src/main/java/at/pavlov/cannons/Cannons.java b/cannons-bukkit/src/main/java/at/pavlov/cannons/Cannons.java index c05cf266..5b41f839 100644 --- a/cannons-bukkit/src/main/java/at/pavlov/cannons/Cannons.java +++ b/cannons-bukkit/src/main/java/at/pavlov/cannons/Cannons.java @@ -18,6 +18,7 @@ import at.pavlov.cannons.hooks.VaultHook; import at.pavlov.cannons.hooks.movecraft.type.MaxCannonsProperty; import at.pavlov.cannons.hooks.movecraftcombat.MovecraftCombatHook; +import at.pavlov.cannons.hooks.towny.TownyHook; import at.pavlov.cannons.listener.*; import at.pavlov.cannons.projectile.Projectile; import at.pavlov.cannons.projectile.ProjectileManager; @@ -206,6 +207,10 @@ public void onEnable() PlaceholderAPIHook placeholderAPIHook = new PlaceholderAPIHook(this); hookManager.registerHook(placeholderAPIHook); + logDebug("Loading TownyHook"); + TownyHook townyHook = new TownyHook(this); + hookManager.registerHook(townyHook); + logDebug("Time to enable hooks: " + new DecimalFormat("0.00").format(System.currentTimeMillis() - startTime) + "ms"); startTime = System.nanoTime(); @@ -306,10 +311,7 @@ public void onEnable() " You don't need to add Movecraft-Cannons anymore as Movecraft support is now embedded," + " we suggest you stop using it as in the future it might stop work properly."); - if (hookManager.isRegistered(MovecraftCombatHook.class)) { - - } - movecraftHook.onDisable(); + movecraftHook.onDisable(); }, 1L); } diff --git a/cannons-bukkit/src/main/java/at/pavlov/cannons/config/Config.java b/cannons-bukkit/src/main/java/at/pavlov/cannons/config/Config.java index 3c7df816..35a3c449 100644 --- a/cannons-bukkit/src/main/java/at/pavlov/cannons/config/Config.java +++ b/cannons-bukkit/src/main/java/at/pavlov/cannons/config/Config.java @@ -5,6 +5,7 @@ import at.pavlov.cannons.builders.ParticleBuilder; import at.pavlov.cannons.cannon.CannonManager; import at.pavlov.cannons.container.ItemHolder; +import at.pavlov.cannons.hooks.towny.TownyAllowCannon; import at.pavlov.cannons.utils.ArmorCalculationUtil; import at.pavlov.cannons.utils.CannonsUtil; import at.pavlov.cannons.utils.FileUtils; @@ -39,6 +40,9 @@ //movecraft private boolean movecraftEnabled; private boolean movecraftCannonEnabled; + + private boolean townyEnabled; + private TownyAllowCannon townyAllowedPlayers; //endregion //build limits @@ -133,6 +137,9 @@ public void loadConfig() { setMovecraftEnabled(config.getBoolean("hooks.movecraft.enabled", true)); setMovecraftCannonEnabled(config.getBoolean("hooks.movecraftCombat.enabled", true)); + setTownyEnabled(config.getBoolean("hooks.towny.enabled", true)); + setTownyAllowedPlayers(TownyAllowCannon.fromConfig(config, "hooks.towny")); + setRelayExplosionEvent(config.getBoolean("general.relayExplosionEvent", false)); setClaimEdgeLength(config.getInt("general.claimEdgeLength", 60)); ArmorCalculationUtil.setMagicValue(config.getDouble("general.armorEffectiveness", 0.04)); diff --git a/cannons-bukkit/src/main/java/at/pavlov/cannons/event/CannonUseEvent.java b/cannons-bukkit/src/main/java/at/pavlov/cannons/event/CannonUseEvent.java index cc763eb4..35c8f507 100644 --- a/cannons-bukkit/src/main/java/at/pavlov/cannons/event/CannonUseEvent.java +++ b/cannons-bukkit/src/main/java/at/pavlov/cannons/event/CannonUseEvent.java @@ -2,43 +2,28 @@ import at.pavlov.cannons.Enum.InteractAction; import at.pavlov.cannons.cannon.Cannon; +import lombok.Getter; +import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import java.util.UUID; -public class CannonUseEvent extends Event -{ +@Getter +public class CannonUseEvent extends Event implements Cancellable { private static final HandlerList handlers = new HandlerList(); private final Cannon cannon; private final UUID player; private final InteractAction action; private boolean cancelled; - public CannonUseEvent(Cannon cannon, UUID player, InteractAction action) - { + public CannonUseEvent(Cannon cannon, UUID player, InteractAction action) { this.cannon = cannon; this.player = player; this.action = action; this.cancelled = false; } - public Cannon getCannon() { - return cannon; - } - - public UUID getPlayer() { - return player; - } - - public InteractAction getAction() { - return action; - } - - public boolean isCancelled() { - return cancelled; - } - public void setCancelled(boolean cancelled) { this.cancelled = cancelled; } diff --git a/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/VaultHook.java b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/VaultHook.java index e155698a..6d23cc6f 100644 --- a/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/VaultHook.java +++ b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/VaultHook.java @@ -34,9 +34,6 @@ public void onEnable() { plugin.logInfo(ChatColor.GREEN + enabledMessage()); } - @Override - public void onDisable() { } - @Override public Class> getTypeClass() { return VaultHook.class; diff --git a/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/movecraft/MovecraftHook.java b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/movecraft/MovecraftHook.java index 3667bcc2..00356e20 100644 --- a/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/movecraft/MovecraftHook.java +++ b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/movecraft/MovecraftHook.java @@ -43,13 +43,6 @@ public void onEnable() { plugin.logInfo(ChatColor.GREEN + enabledMessage()); } - @Override - public void onDisable() { - HandlerList.unregisterAll(new CraftDetectListener()); - HandlerList.unregisterAll(new TranslationListener()); - HandlerList.unregisterAll(new RotationListener()); - } - @Override public Class> getTypeClass() { return MovecraftHook.class; diff --git a/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/movecraftcombat/MovecraftCombatHook.java b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/movecraftcombat/MovecraftCombatHook.java index 7019053c..c8e8695c 100644 --- a/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/movecraftcombat/MovecraftCombatHook.java +++ b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/movecraftcombat/MovecraftCombatHook.java @@ -29,11 +29,6 @@ public void onEnable() { plugin.logInfo(ChatColor.GREEN + enabledMessage()); } - @Override - public void onDisable() { - HandlerList.unregisterAll(new ProjectileImpactListener()); - } - @Override public Class> getTypeClass() { return MovecraftCombatHook.class; diff --git a/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/papi/PlaceholderAPIHook.java b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/papi/PlaceholderAPIHook.java index 1a831118..9708ec28 100644 --- a/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/papi/PlaceholderAPIHook.java +++ b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/papi/PlaceholderAPIHook.java @@ -29,11 +29,6 @@ public void onEnable() { plugin.logInfo(ChatColor.GREEN + enabledMessage()); } - @Override - public void onDisable() { - - } - @Override public boolean active() { return working; diff --git a/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/towny/TownyAllowCannon.java b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/towny/TownyAllowCannon.java new file mode 100644 index 00000000..3a86b109 --- /dev/null +++ b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/towny/TownyAllowCannon.java @@ -0,0 +1,21 @@ +package at.pavlov.cannons.hooks.towny; + +import org.bukkit.configuration.file.FileConfiguration; + +import java.util.Locale; + +public enum TownyAllowCannon { + ALL, + TOWN, + ALLIES; + + public static TownyAllowCannon fromConfig(FileConfiguration config, String key) { + String result = config.getString(key, "TOWN"); + + try { + return TownyAllowCannon.valueOf(result.toUpperCase(Locale.ROOT)); + } catch (Exception ignored) { + return TOWN; + } + } +} diff --git a/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/towny/TownyHook.java b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/towny/TownyHook.java new file mode 100644 index 00000000..6448f407 --- /dev/null +++ b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/towny/TownyHook.java @@ -0,0 +1,38 @@ +package at.pavlov.cannons.hooks.towny; + +import at.pavlov.cannons.Cannons; +import at.pavlov.cannons.hooks.BukkitHook; +import at.pavlov.internal.Hook; +import com.palmergames.bukkit.towny.TownyAPI; +import lombok.SneakyThrows; +import org.bukkit.plugin.PluginManager; + +public class TownyHook extends BukkitHook { + + public TownyHook(Cannons plugin) { + super(plugin); + } + + @SneakyThrows + @Override + public void onEnable() { + + if (!plugin.getMyConfig().isTownyEnabled()) { + return; + } + + PluginManager pluginManager = plugin.getServer().getPluginManager(); + if (!pluginManager.isPluginEnabled("Towny")) { + plugin.logDebug("Towny not found or disabled"); + return; + } + + hook = TownyAPI.getInstance(); + pluginManager.registerEvents(new TownyListeners(), plugin); + } + + @Override + public Class> getTypeClass() { + return TownyHook.class; + } +} diff --git a/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/towny/TownyListeners.java b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/towny/TownyListeners.java new file mode 100644 index 00000000..4122e173 --- /dev/null +++ b/cannons-bukkit/src/main/java/at/pavlov/cannons/hooks/towny/TownyListeners.java @@ -0,0 +1,84 @@ +package at.pavlov.cannons.hooks.towny; + +import at.pavlov.cannons.config.Config; +import at.pavlov.cannons.event.CannonUseEvent; +import com.palmergames.bukkit.towny.TownyAPI; +import com.palmergames.bukkit.towny.object.Resident; +import com.palmergames.bukkit.towny.object.Town; +import com.palmergames.bukkit.towny.utils.CombatUtil; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +import java.util.UUID; + +import static at.pavlov.cannons.Enum.InteractAction.adjustPlayer; +import static at.pavlov.cannons.Enum.InteractAction.fireRightClickTigger; + +public class TownyListeners implements Listener { + private static final Config config = Config.getInstance(); + private static final TownyAPI api = TownyAPI.getInstance(); + + @EventHandler + public void onAction(CannonUseEvent event) { + Location location = event.getCannon().getLocation(); + TownyAllowCannon tac = config.getTownyAllowedPlayers(); + if (tac == TownyAllowCannon.ALL) { + return; + } + + Town town = api.getTown(location); + if (town == null) { + return; + } + + UUID playerUUID = event.getPlayer(); + if (playerUUID == null) { + return; + } + + Player player = Bukkit.getPlayer(playerUUID); + if (player == null) { + event.setCancelled(true); + return; + } + + if (player.hasPermission("cannons.admin.*")) { + return; + } + + if (town.hasResident(playerUUID)) { + return; + } + + // we already did town check, + // if it failed and tac is set to TOWN we are done here + if (tac == TownyAllowCannon.TOWN) { + event.setCancelled(true); + player.sendMessage("§4[Cannons] No permission to interact with this cannons. (TownyAllowCannon.TOWN)"); + return; + } + + Resident resident = api.getResident(playerUUID); + if (resident == null) { //this shouldn't happen tbh + return; + } + + Town otherTown = resident.getTownOrNull();; + if (otherTown == null) { + event.setCancelled(true); + player.sendMessage("§4[Cannons] No permission to interact with this cannons. (No town)"); + return; + } + + if (CombatUtil.isAlly(town, otherTown)) { + return; + } + + event.setCancelled(true); + player.sendMessage("§4[Cannons] No permission to interact with this cannons. (TownyAllowCannon.ALLY)"); + } + +} diff --git a/cannons-bukkit/src/main/resources/config.yml b/cannons-bukkit/src/main/resources/config.yml index d6657686..f2a6fac2 100644 --- a/cannons-bukkit/src/main/resources/config.yml +++ b/cannons-bukkit/src/main/resources/config.yml @@ -21,6 +21,13 @@ hooks: enabled: true movecraftCombat: enabled: true + towny: + enabled: true + # Possible values of allowedPlayers: + # ALL : all player can use cannons in a town. + # TOWN : all residents can use the cannons in a town. + # ALLIES : all residents and allies can use the cannons in a town. + allowedPlayers: TOWN cannonLimits: diff --git a/cannons-bukkit/src/main/resources/plugin.yml b/cannons-bukkit/src/main/resources/plugin.yml index 14c3a02e..d065f0ab 100644 --- a/cannons-bukkit/src/main/resources/plugin.yml +++ b/cannons-bukkit/src/main/resources/plugin.yml @@ -3,7 +3,7 @@ main: at.pavlov.cannons.Cannons api-version: 1.13 version: ${version} depend: [WorldEdit] -softdepend: [Vault, Movecraft, Movecraft-Combat, PlaceholderAPI] +softdepend: [Vault, Movecraft, Movecraft-Combat, PlaceholderAPI, Towny] authors: [DerPavlov, Vaan1310] description: Fire block build cannons and smash your enemies folia-supported: true