From 1aeb245666898e84251f95ecb6504d74ec56af9a Mon Sep 17 00:00:00 2001 From: YouHaveTrouble Date: Sat, 24 Feb 2024 19:23:54 +0100 Subject: [PATCH] Refactor damage source checking and restructure player management The source of damage detection for PvP interactions has been updated to improve accuracy and flexibility. A 'Target' sub-class has been implemented in the PlayerManager class, removing the need for a separate DamageCheck class. The PlayerManager class was also moved to the 'data' package. Distribution of feedback messages has been simplified using the new DamageCheckResult class. --- .../preventstabby/PreventStabby.java | 11 +- .../preventstabby/api/PreventStabbyAPI.java | 6 + .../api/event/PlayerEnterCombatEvent.java | 2 +- .../api/event/PlayerLeaveCombatEvent.java | 2 +- .../api/event/PlayerTogglePvpEvent.java | 2 +- .../commands/PvpToggleCommand.java | 2 +- .../preventstabby/data/DamageCheckResult.java | 41 ++++++ .../{players => data}/PlayerData.java | 17 ++- .../{players => data}/PlayerListener.java | 17 ++- .../{players => data}/PlayerManager.java | 77 +++++++++- .../preventstabby/data/Target.java | 71 +++++++++ .../listeners/PlayerDamageListener.java | 33 +++++ .../preventstabby/util/DamageCheck.java | 138 ------------------ .../preventstabby/util/DatabaseSQLite.java | 2 +- .../preventstabby/util/PluginMessages.java | 10 ++ src/main/resources/plugin.yml | 2 +- 16 files changed, 266 insertions(+), 167 deletions(-) create mode 100644 src/main/java/me/youhavetrouble/preventstabby/data/DamageCheckResult.java rename src/main/java/me/youhavetrouble/preventstabby/{players => data}/PlayerData.java (89%) rename src/main/java/me/youhavetrouble/preventstabby/{players => data}/PlayerListener.java (79%) rename src/main/java/me/youhavetrouble/preventstabby/{players => data}/PlayerManager.java (63%) create mode 100644 src/main/java/me/youhavetrouble/preventstabby/data/Target.java create mode 100644 src/main/java/me/youhavetrouble/preventstabby/listeners/PlayerDamageListener.java delete mode 100644 src/main/java/me/youhavetrouble/preventstabby/util/DamageCheck.java diff --git a/src/main/java/me/youhavetrouble/preventstabby/PreventStabby.java b/src/main/java/me/youhavetrouble/preventstabby/PreventStabby.java index 2f869e8..67980f6 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/PreventStabby.java +++ b/src/main/java/me/youhavetrouble/preventstabby/PreventStabby.java @@ -4,7 +4,8 @@ import me.youhavetrouble.preventstabby.commands.MainCommand; import me.youhavetrouble.preventstabby.config.ConfigCache; import me.youhavetrouble.preventstabby.hooks.PlaceholderApiHook; import me.youhavetrouble.preventstabby.hooks.WorldGuardHook; -import me.youhavetrouble.preventstabby.players.PlayerManager; +import me.youhavetrouble.preventstabby.data.PlayerListener; +import me.youhavetrouble.preventstabby.data.PlayerManager; import me.youhavetrouble.preventstabby.util.*; import org.bstats.bukkit.Metrics; import org.bukkit.command.CommandSender; @@ -16,7 +17,6 @@ public final class PreventStabby extends JavaPlugin { private static PreventStabby plugin; private ConfigCache configCache; private PlayerManager playerManager; - private DamageCheck damageCheck; private DatabaseSQLite sqLite; private static boolean worldGuardHook; @@ -25,10 +25,9 @@ public final class PreventStabby extends JavaPlugin { plugin = this; reloadPluginConfig(); playerManager = new PlayerManager(this); - damageCheck = new DamageCheck(this); // Register listeners TODO - + getServer().getPluginManager().registerEvents(new PlayerListener(), this); // Register command PluginCommand pvpCommand = getCommand("pvp"); @@ -83,10 +82,6 @@ public final class PreventStabby extends JavaPlugin { return playerManager; } - public DamageCheck getDamageUtil() { - return damageCheck; - } - public DatabaseSQLite getSqLite() {return sqLite;} public static PreventStabby getPlugin() { diff --git a/src/main/java/me/youhavetrouble/preventstabby/api/PreventStabbyAPI.java b/src/main/java/me/youhavetrouble/preventstabby/api/PreventStabbyAPI.java index 040adb8..c3fb736 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/api/PreventStabbyAPI.java +++ b/src/main/java/me/youhavetrouble/preventstabby/api/PreventStabbyAPI.java @@ -1,7 +1,9 @@ package me.youhavetrouble.preventstabby.api; import me.youhavetrouble.preventstabby.PreventStabby; +import me.youhavetrouble.preventstabby.data.DamageCheckResult; import me.youhavetrouble.preventstabby.util.PvpState; +import org.bukkit.entity.Entity; public class PreventStabbyAPI { @@ -19,5 +21,9 @@ public class PreventStabbyAPI { PreventStabby.getPlugin().getPlayerManager().setForcedPvpState(newForcedPvpState); } + public static DamageCheckResult canDamage(Entity attacker, Entity victim) { + return PreventStabby.getPlugin().getPlayerManager().canDamage(attacker, victim); + } + } diff --git a/src/main/java/me/youhavetrouble/preventstabby/api/event/PlayerEnterCombatEvent.java b/src/main/java/me/youhavetrouble/preventstabby/api/event/PlayerEnterCombatEvent.java index cc13c96..975180a 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/api/event/PlayerEnterCombatEvent.java +++ b/src/main/java/me/youhavetrouble/preventstabby/api/event/PlayerEnterCombatEvent.java @@ -1,7 +1,7 @@ package me.youhavetrouble.preventstabby.api.event; import me.youhavetrouble.preventstabby.PreventStabby; -import me.youhavetrouble.preventstabby.players.PlayerData; +import me.youhavetrouble.preventstabby.data.PlayerData; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; diff --git a/src/main/java/me/youhavetrouble/preventstabby/api/event/PlayerLeaveCombatEvent.java b/src/main/java/me/youhavetrouble/preventstabby/api/event/PlayerLeaveCombatEvent.java index db43bb3..413660a 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/api/event/PlayerLeaveCombatEvent.java +++ b/src/main/java/me/youhavetrouble/preventstabby/api/event/PlayerLeaveCombatEvent.java @@ -1,7 +1,7 @@ package me.youhavetrouble.preventstabby.api.event; import me.youhavetrouble.preventstabby.PreventStabby; -import me.youhavetrouble.preventstabby.players.PlayerData; +import me.youhavetrouble.preventstabby.data.PlayerData; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; diff --git a/src/main/java/me/youhavetrouble/preventstabby/api/event/PlayerTogglePvpEvent.java b/src/main/java/me/youhavetrouble/preventstabby/api/event/PlayerTogglePvpEvent.java index c423485..f95f020 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/api/event/PlayerTogglePvpEvent.java +++ b/src/main/java/me/youhavetrouble/preventstabby/api/event/PlayerTogglePvpEvent.java @@ -1,7 +1,7 @@ package me.youhavetrouble.preventstabby.api.event; import me.youhavetrouble.preventstabby.PreventStabby; -import me.youhavetrouble.preventstabby.players.PlayerData; +import me.youhavetrouble.preventstabby.data.PlayerData; import org.bukkit.OfflinePlayer; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; diff --git a/src/main/java/me/youhavetrouble/preventstabby/commands/PvpToggleCommand.java b/src/main/java/me/youhavetrouble/preventstabby/commands/PvpToggleCommand.java index 9506722..948643c 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/commands/PvpToggleCommand.java +++ b/src/main/java/me/youhavetrouble/preventstabby/commands/PvpToggleCommand.java @@ -3,7 +3,7 @@ package me.youhavetrouble.preventstabby.commands; import me.youhavetrouble.preventstabby.PreventStabby; import me.youhavetrouble.preventstabby.api.event.PlayerTogglePvpEvent; import me.youhavetrouble.preventstabby.config.PreventStabbyPermission; -import me.youhavetrouble.preventstabby.players.PlayerManager; +import me.youhavetrouble.preventstabby.data.PlayerManager; import me.youhavetrouble.preventstabby.util.PluginMessages; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; diff --git a/src/main/java/me/youhavetrouble/preventstabby/data/DamageCheckResult.java b/src/main/java/me/youhavetrouble/preventstabby/data/DamageCheckResult.java new file mode 100644 index 0000000..99c91d0 --- /dev/null +++ b/src/main/java/me/youhavetrouble/preventstabby/data/DamageCheckResult.java @@ -0,0 +1,41 @@ +package me.youhavetrouble.preventstabby.data; + +import javax.annotation.Nullable; +import java.util.UUID; + +/** + * @param ableToDamage Result of the damage check + * @param feedbackForAttacker Feedback to send to the attacker + * @param feedbackForVictim Feedback to send to the victim + * @param attackerId UUID of attacker player + * @param victimId UUID of victim player + */ +public record DamageCheckResult( + boolean ableToDamage, + @Nullable UUID attackerId, + @Nullable UUID victimId, + @Nullable String feedbackForAttacker, + @Nullable String feedbackForVictim +) { + + public static DamageCheckResult positive() { + return new DamageCheckResult( + true, + null, + null, + null, + null + ); + } + + public static DamageCheckResult positive(UUID attackerId, UUID victimId) { + return new DamageCheckResult( + true, + attackerId, + victimId, + null, + null + ); + } + +} \ No newline at end of file diff --git a/src/main/java/me/youhavetrouble/preventstabby/players/PlayerData.java b/src/main/java/me/youhavetrouble/preventstabby/data/PlayerData.java similarity index 89% rename from src/main/java/me/youhavetrouble/preventstabby/players/PlayerData.java rename to src/main/java/me/youhavetrouble/preventstabby/data/PlayerData.java index 25d2c9c..255ccc4 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/players/PlayerData.java +++ b/src/main/java/me/youhavetrouble/preventstabby/data/PlayerData.java @@ -1,4 +1,4 @@ -package me.youhavetrouble.preventstabby.players; +package me.youhavetrouble.preventstabby.data; import me.youhavetrouble.preventstabby.PreventStabby; @@ -10,16 +10,17 @@ import java.util.UUID; public class PlayerData { private final UUID playerUuid; - private long lastAccessTimestamp, combatStartTimestamp, loginTimestamp, teleportTimestamp; + private long lastAccessTimestamp, loginTimestamp; + private Long combatStartTimestamp, teleportTimestamp; private boolean pvpEnabled, lastCombatCheck; public PlayerData(UUID playerUuid, boolean pvpEnabled) { this.playerUuid = playerUuid; this.pvpEnabled = pvpEnabled; this.lastCombatCheck = false; - this.combatStartTimestamp = Long.MIN_VALUE; - this.loginTimestamp = Long.MIN_VALUE; - this.teleportTimestamp = Long.MIN_VALUE; + this.combatStartTimestamp = null; + this.loginTimestamp = System.currentTimeMillis(); + this.teleportTimestamp = null; refreshCacheTime(); } @@ -89,14 +90,14 @@ public class PlayerData { protected void markNotInCombat() { refreshCacheTime(); - this.combatStartTimestamp = Long.MIN_VALUE; + this.combatStartTimestamp = null; } /** * Sets the login timestamp for the player. * @param loginTimestamp The login timestamp to set. */ - public void setLoginTimestamp(long loginTimestamp) { + protected void setLoginTimestamp(long loginTimestamp) { this.loginTimestamp = loginTimestamp; } @@ -130,6 +131,7 @@ public class PlayerData { * @return The number of seconds left until combat ends. -1 if not in combat */ public long getSecondsLeftUntilCombatEnd() { + if (combatStartTimestamp == null) return -1; long timeSinceCombatStart = System.currentTimeMillis() - combatStartTimestamp; long combatTimeConfigured = PreventStabby.getPlugin().getConfigCache().combat_time * 1000; return (timeSinceCombatStart < combatTimeConfigured) ? (combatTimeConfigured - timeSinceCombatStart) / 1000 : -1; @@ -145,6 +147,7 @@ public class PlayerData { } public boolean hasTeleportProtection() { + if (teleportTimestamp == null) return false; return System.currentTimeMillis() - (teleportTimestamp + (PreventStabby.getPlugin().getConfigCache().teleport_protection_time * 1000)) < 0; } diff --git a/src/main/java/me/youhavetrouble/preventstabby/players/PlayerListener.java b/src/main/java/me/youhavetrouble/preventstabby/data/PlayerListener.java similarity index 79% rename from src/main/java/me/youhavetrouble/preventstabby/players/PlayerListener.java rename to src/main/java/me/youhavetrouble/preventstabby/data/PlayerListener.java index 749759d..f030ad0 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/players/PlayerListener.java +++ b/src/main/java/me/youhavetrouble/preventstabby/data/PlayerListener.java @@ -1,8 +1,11 @@ -package me.youhavetrouble.preventstabby.players; +package me.youhavetrouble.preventstabby.data; +import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent; import me.youhavetrouble.preventstabby.PreventStabby; import me.youhavetrouble.preventstabby.util.PluginMessages; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.entity.Tameable; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -55,4 +58,16 @@ public class PlayerListener implements Listener { playerData.markNotInCombat(); } + /** + * Load data for owners of loaded tameables + */ + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onEntityLoad(EntityAddToWorldEvent event) { + Entity entity = event.getEntity(); + if (!(entity instanceof Tameable tameable)) return; + UUID ownerId = tameable.getOwnerUniqueId(); + if (ownerId == null) return; + PreventStabby.getPlugin().getPlayerManager().getPlayerData(ownerId); + } + } diff --git a/src/main/java/me/youhavetrouble/preventstabby/players/PlayerManager.java b/src/main/java/me/youhavetrouble/preventstabby/data/PlayerManager.java similarity index 63% rename from src/main/java/me/youhavetrouble/preventstabby/players/PlayerManager.java rename to src/main/java/me/youhavetrouble/preventstabby/data/PlayerManager.java index d655dba..da0357f 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/players/PlayerManager.java +++ b/src/main/java/me/youhavetrouble/preventstabby/data/PlayerManager.java @@ -1,14 +1,19 @@ -package me.youhavetrouble.preventstabby.players; +package me.youhavetrouble.preventstabby.data; import me.youhavetrouble.preventstabby.PreventStabby; import me.youhavetrouble.preventstabby.api.event.PlayerEnterCombatEvent; import me.youhavetrouble.preventstabby.api.event.PlayerLeaveCombatEvent; -import me.youhavetrouble.preventstabby.util.DamageCheck; import me.youhavetrouble.preventstabby.util.PluginMessages; import me.youhavetrouble.preventstabby.util.PvpState; import org.bukkit.Bukkit; import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.entity.Tameable; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; @@ -27,6 +32,17 @@ public class PlayerManager { playerList.values().removeIf(PlayerData::isCacheExpired); }, 250, 250, TimeUnit.MILLISECONDS); + Bukkit.getScheduler().runTaskTimer(plugin, (task -> { + List entities = new ArrayList<>(); + Bukkit.getWorlds().forEach((world -> entities.addAll(world.getLivingEntities()))); + Bukkit.getAsyncScheduler().runNow(plugin, (asyncTask) -> entities.forEach(livingEntity -> { + if (!(livingEntity instanceof Tameable tameable)) return; + UUID ownerId = tameable.getOwnerUniqueId(); + if (ownerId == null) return; + getPlayerData(ownerId); + })); + }), 0, 20 * 15); + Bukkit.getGlobalRegionScheduler().runAtFixedRate(plugin, (task) -> { for (PlayerData playerData : playerList.values()) { if (playerData == null) continue; @@ -83,17 +99,64 @@ public class PlayerManager { playerList.put(uuid, data); } + public void handleDamageCheck(@NotNull DamageCheckResult damageCheckResult) { + PluginMessages.sendOutMessages(damageCheckResult); + PlayerData attacker = getPlayer(damageCheckResult.attackerId()); + PlayerData victim = getPlayer(damageCheckResult.victimId()); + if (attacker == null || victim == null) return; + if (!damageCheckResult.ableToDamage()) return; + attacker.markInCombat(); + victim.markInCombat(); + } + /** * Determines whether the given attacker can damage the victim. * * @param attacker The attacking entity. - * @param victim The victim entity. - * @return A {@link DamageCheck.DamageCheckResult} object containing the result of the damage check. + * @param victim The victim entity. + * @return A {@link DamageCheckResult} object containing the result of the damage check. */ - public DamageCheck.DamageCheckResult canDamage(Entity attacker, Entity victim) { - DamageCheck damageCheck = plugin.getDamageUtil(); - return damageCheck.canDamage(attacker, victim); + public DamageCheckResult canDamage(@NotNull Entity attacker, @NotNull Entity victim) { + Target attackerData = Target.getTarget(attacker); + Target victimData = Target.getTarget(victim); + if (attackerData == null || victimData == null) return DamageCheckResult.positive(); + return canDamage(attackerData.playerUuid, victimData.playerUuid, victimData.classifier); + } + + public DamageCheckResult canDamage(UUID attackerId, UUID victimId, Target.EntityClassifier victimClassifier) { + + if (attackerId == null || victimId == null) return DamageCheckResult.positive(); + + PlayerData attackerPlayerData = getPlayer(attackerId); + PlayerData victimPlayerData = getPlayer(victimId); + + if (attackerPlayerData == null || victimPlayerData == null) { + return DamageCheckResult.positive(); + } + + if (attackerPlayerData.isProtected()) { + String message = switch (victimClassifier) { + case PLAYER -> plugin.getConfigCache().cannotAttackTeleportOrSpawnProtectionAttacker; + case PET -> plugin.getConfigCache().cannotAttackPetsTeleportOrSpawnProtectionAttacker; + case MOUNT -> plugin.getConfigCache().cannotAttackMountsTeleportOrSpawnProtectionAttacker; + default -> null; + }; + return new DamageCheckResult(false, attackerId, victimId, message, null); + } + if (victimPlayerData.isProtected()) { + String message = null; + if (victimClassifier == Target.EntityClassifier.PLAYER) { + message = plugin.getConfigCache().cannotAttackTeleportOrSpawnProtectionVictim; + } + return new DamageCheckResult(false, attackerId, victimId, message, null); + } + + return switch (getForcedPvpState()) { + case DISABLED -> new DamageCheckResult(false, attackerId, victimId, plugin.getConfigCache().cannotAttackForcedPvpOff, null); + case ENABLED -> DamageCheckResult.positive(); + default -> DamageCheckResult.positive(); + }; } /** diff --git a/src/main/java/me/youhavetrouble/preventstabby/data/Target.java b/src/main/java/me/youhavetrouble/preventstabby/data/Target.java new file mode 100644 index 0000000..3fedecd --- /dev/null +++ b/src/main/java/me/youhavetrouble/preventstabby/data/Target.java @@ -0,0 +1,71 @@ +package me.youhavetrouble.preventstabby.data; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.Tameable; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; +import java.util.UUID; + +public class Target { + + /** + * The unique identifier for a player. + */ + public final UUID playerUuid; + + /** + * Represents the entity classifier of a target. + * This indicates what type of entity player's id was assumed from + */ + public final EntityClassifier classifier; + + private Target(UUID uuid, EntityClassifier classifier) { + this.playerUuid = uuid; + this.classifier = classifier; + } + + /** + * Get the UUID of the actual player, being owner of a pet, shooter of a projectile, etc. + * + * @param entity Base entity to get the player UUID from + * @return UUID of the actual player, null if not found + */ + @Nullable + public static Target getTarget(@NotNull Entity entity) { + if (entity instanceof Player) return new Target(entity.getUniqueId(), EntityClassifier.PLAYER); + + // Get shooter of projectile + if (entity instanceof Projectile projectile) { + if (projectile.getShooter() instanceof Player shooter) { + return new Target(shooter.getUniqueId(), EntityClassifier.PLAYER); + } + } + + // Get player riding mount + if (!entity.getPassengers().isEmpty()) { + Entity passenger = entity.getPassengers().get(0); + if (passenger instanceof Player) { + return new Target(passenger.getUniqueId(), EntityClassifier.MOUNT); + } + } + + // Get owner of tamed entity + if (entity instanceof Tameable tameable) { + if (tameable.getOwner() != null) { + return new Target(tameable.getOwner().getUniqueId(), EntityClassifier.PET); + } + } + + return null; + } + + public enum EntityClassifier { + PLAYER, + PET, + MOUNT, + OTHER + } +} \ No newline at end of file diff --git a/src/main/java/me/youhavetrouble/preventstabby/listeners/PlayerDamageListener.java b/src/main/java/me/youhavetrouble/preventstabby/listeners/PlayerDamageListener.java new file mode 100644 index 0000000..725468e --- /dev/null +++ b/src/main/java/me/youhavetrouble/preventstabby/listeners/PlayerDamageListener.java @@ -0,0 +1,33 @@ +package me.youhavetrouble.preventstabby.listeners; + +import me.youhavetrouble.preventstabby.PreventStabby; +import me.youhavetrouble.preventstabby.data.DamageCheckResult; +import org.bukkit.entity.Entity; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; + +public class PlayerDamageListener implements Listener { + + private final PreventStabby plugin; + + PlayerDamageListener(PreventStabby plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onEntityDamageEvent(EntityDamageByEntityEvent event) { + Entity attacker = event.getDamager(); + Entity victim = event.getEntity(); + + DamageCheckResult result = plugin.getPlayerManager().canDamage(attacker, victim); + + if (!result.ableToDamage()) { + event.setCancelled(true); + } + plugin.getPlayerManager().handleDamageCheck(result); + + } + +} diff --git a/src/main/java/me/youhavetrouble/preventstabby/util/DamageCheck.java b/src/main/java/me/youhavetrouble/preventstabby/util/DamageCheck.java deleted file mode 100644 index 3d50a7b..0000000 --- a/src/main/java/me/youhavetrouble/preventstabby/util/DamageCheck.java +++ /dev/null @@ -1,138 +0,0 @@ -package me.youhavetrouble.preventstabby.util; - -import me.youhavetrouble.preventstabby.PreventStabby; -import me.youhavetrouble.preventstabby.config.ConfigCache; -import me.youhavetrouble.preventstabby.players.PlayerData; -import me.youhavetrouble.preventstabby.players.PlayerManager; -import org.bukkit.entity.*; -import org.jetbrains.annotations.NotNull; - -import javax.annotation.Nullable; -import java.util.UUID; - -public class DamageCheck { - - private final ConfigCache config; - private final PlayerManager playerManager; - - public DamageCheck(PreventStabby plugin) { - this.config = plugin.getConfigCache(); - this.playerManager = plugin.getPlayerManager(); - } - - public DamageCheckResult canDamage(@NotNull Entity attacker, @NotNull Entity victim) { - Target attackerData = getUuidOfActualPlayer(attacker); - Target victimData = getUuidOfActualPlayer(victim); - if (attackerData == null || victimData == null) return new DamageCheckResult(true, null, null); - return canDamage(attackerData.playerUuid, victimData.playerUuid, victimData.classifier); - } - - public DamageCheckResult canDamage(UUID attackerId, UUID victimId, EntityClassifier victimClassifier) { - - if (attackerId == null || victimId == null) return new DamageCheckResult(true, null, null); - - PlayerData attackerPlayerData = PreventStabby.getPlugin().getPlayerManager().getPlayer(attackerId); - PlayerData victimPlayerData = PreventStabby.getPlugin().getPlayerManager().getPlayer(victimId); - - if (attackerPlayerData.isProtected()) { - String message = switch (victimClassifier) { - case PLAYER -> config.cannotAttackTeleportOrSpawnProtectionAttacker; - case PET -> config.cannotAttackPetsTeleportOrSpawnProtectionAttacker; - case MOUNT -> config.cannotAttackMountsTeleportOrSpawnProtectionAttacker; - default -> null; - }; - return new DamageCheckResult(false, message, null); - } - if (victimPlayerData.isProtected()) { - String message = null; - if (victimClassifier == EntityClassifier.PLAYER) { - message = config.cannotAttackTeleportOrSpawnProtectionVictim; - } - return new DamageCheckResult(false, message, null); - } - - return switch (playerManager.getForcedPvpState()) { - case DISABLED -> new DamageCheckResult(false, config.cannotAttackForcedPvpOff, null); - case ENABLED -> new DamageCheckResult(true, null, null); - default -> new DamageCheckResult(true, null, null); - }; - } - - /** - * Get the UUID of the actual player, being owner of a pet, shooter of a projectile, etc. - * - * @param entity Base entity to get the player UUID from - * @return UUID of the actual player, null if not found - */ - @Nullable - public Target getUuidOfActualPlayer(@NotNull Entity entity) { - if (entity instanceof Player) return new Target(entity.getUniqueId(), EntityClassifier.PLAYER); - - // Get shooter of projectile - if (entity instanceof Projectile projectile) { - if (projectile.getShooter() instanceof Player shooter) { - return new Target(shooter.getUniqueId(), EntityClassifier.PLAYER); - } - } - - // Get player riding mount - if (!entity.getPassengers().isEmpty()) { - Entity passenger = entity.getPassengers().get(0); - if (passenger instanceof Player) { - return new Target(passenger.getUniqueId(), EntityClassifier.MOUNT); - } - } - - // Get owner of tamed entity - if (entity instanceof Tameable tameable) { - if (tameable.getOwner() != null) { - return new Target(tameable.getOwner().getUniqueId(), EntityClassifier.PET); - } - } - - return null; - } - - - public static class DamageCheckResult { - public final boolean ableToDamage; - public final String feedbackForAttacker, feedbackForVictim; - - private DamageCheckResult( - boolean ableToDamage, - @Nullable String feedbackForAttacker, - @Nullable String feedbackForVictim - ) { - this.ableToDamage = ableToDamage; - this.feedbackForAttacker = feedbackForAttacker; - this.feedbackForVictim = feedbackForVictim; - } - } - - public static class Target { - - /** - * The unique identifier for a player. - */ - public final UUID playerUuid; - - /** - * Represents the entity classifier of a target. - * This indicates what type of entity player's id was assumed from - */ - public final EntityClassifier classifier; - - private Target(UUID uuid, EntityClassifier classifier) { - this.playerUuid = uuid; - this.classifier = classifier; - } - } - - public enum EntityClassifier { - PLAYER, - PET, - MOUNT, - OTHER - } - -} diff --git a/src/main/java/me/youhavetrouble/preventstabby/util/DatabaseSQLite.java b/src/main/java/me/youhavetrouble/preventstabby/util/DatabaseSQLite.java index 2b03095..6f7b275 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/util/DatabaseSQLite.java +++ b/src/main/java/me/youhavetrouble/preventstabby/util/DatabaseSQLite.java @@ -1,7 +1,7 @@ package me.youhavetrouble.preventstabby.util; import me.youhavetrouble.preventstabby.PreventStabby; -import me.youhavetrouble.preventstabby.players.PlayerData; +import me.youhavetrouble.preventstabby.data.PlayerData; import java.io.File; import java.sql.*; diff --git a/src/main/java/me/youhavetrouble/preventstabby/util/PluginMessages.java b/src/main/java/me/youhavetrouble/preventstabby/util/PluginMessages.java index a00375b..47188c1 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/util/PluginMessages.java +++ b/src/main/java/me/youhavetrouble/preventstabby/util/PluginMessages.java @@ -2,6 +2,7 @@ package me.youhavetrouble.preventstabby.util; import me.clip.placeholderapi.PlaceholderAPI; import me.youhavetrouble.preventstabby.PreventStabby; +import me.youhavetrouble.preventstabby.data.DamageCheckResult; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -69,6 +70,15 @@ public class PluginMessages { Bukkit.broadcast(parseMessage(message)); } + public static void sendOutMessages(DamageCheckResult damageCheckResult) { + if (damageCheckResult.victimId() != null && damageCheckResult.feedbackForVictim() != null) { + sendActionBar(damageCheckResult.victimId(), damageCheckResult.feedbackForVictim()); + } + if (damageCheckResult.attackerId() != null && damageCheckResult.feedbackForAttacker() != null) { + sendActionBar(damageCheckResult.attackerId(), damageCheckResult.feedbackForAttacker()); + } + } + /** * Swaps most legacy color codes to adventure minimessage tags. * @param symbol Usually '&'. diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c91acd3..0849d12 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -2,7 +2,7 @@ name: PreventStabby version: ${project.version} main: me.youhavetrouble.preventstabby.PreventStabby authors: [YouHaveTrouble] -api-version: 1.13 +api-version: 1.20 description: Stop people from getting stabbed! soft-depend: - WorldGuard