From b414f96257a238e4dc827cafea8837154d285098 Mon Sep 17 00:00:00 2001 From: youhavetrouble Date: Fri, 23 Jun 2023 00:28:44 +0200 Subject: [PATCH] new shared logic to determine attacker and victim --- .../preventstabby/PreventStabby.java | 12 +- .../preventstabby/config/ConfigCache.java | 18 +++ .../preventstabby/util/DamageUtil.java | 138 ++++++++++++++++++ 3 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 src/main/java/me/youhavetrouble/preventstabby/util/DamageUtil.java diff --git a/src/main/java/me/youhavetrouble/preventstabby/PreventStabby.java b/src/main/java/me/youhavetrouble/preventstabby/PreventStabby.java index d9c7e25..c6497e6 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/PreventStabby.java +++ b/src/main/java/me/youhavetrouble/preventstabby/PreventStabby.java @@ -6,11 +6,8 @@ import me.youhavetrouble.preventstabby.hooks.PlaceholderApiHook; import me.youhavetrouble.preventstabby.hooks.WorldGuardHook; import me.youhavetrouble.preventstabby.players.PlayerManager; import me.youhavetrouble.preventstabby.players.SmartCache; -import me.youhavetrouble.preventstabby.util.PluginMessages; -import me.youhavetrouble.preventstabby.util.PreventStabbyListener; -import me.youhavetrouble.preventstabby.util.DatabaseSQLite; +import me.youhavetrouble.preventstabby.util.*; import lombok.Getter; -import me.youhavetrouble.preventstabby.util.Util; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import org.bstats.bukkit.Metrics; import org.bukkit.command.CommandSender; @@ -26,6 +23,8 @@ public final class PreventStabby extends JavaPlugin { @Getter private static PreventStabby plugin; private ConfigCache configCache; private PlayerManager playerManager; + + private DamageUtil damageUtil; private DatabaseSQLite sqLite; private SmartCache smartCache; private static boolean worldGuardHook; @@ -48,6 +47,7 @@ public final class PreventStabby extends JavaPlugin { } adventure = BukkitAudiences.create(this); playerManager = new PlayerManager(); + damageUtil = new DamageUtil(this); smartCache = new SmartCache(); smartCache.runSmartCache(); @@ -118,6 +118,10 @@ public final class PreventStabby extends JavaPlugin { return playerManager; } + public DamageUtil getDamageUtil() { + return damageUtil; + } + public DatabaseSQLite getSqLite() {return sqLite;} public SmartCache getSmartCache() { diff --git a/src/main/java/me/youhavetrouble/preventstabby/config/ConfigCache.java b/src/main/java/me/youhavetrouble/preventstabby/config/ConfigCache.java index 91264f8..635f163 100644 --- a/src/main/java/me/youhavetrouble/preventstabby/config/ConfigCache.java +++ b/src/main/java/me/youhavetrouble/preventstabby/config/ConfigCache.java @@ -27,6 +27,11 @@ public class ConfigCache { cant_do_that_during_combat, cannot_attack_mounts_attacker, cannot_attack_mounts_victim, force_pvp_on, force_pvp_off, force_pvp_none, placeholder_combat_time, placeholder_not_in_combat, cannot_attack_pvp_force_off, placeholder_pvp_forced_true, placeholder_pvp_forced_false, placeholder_pvp_forced_none; + + public final String cannotAttackForcedPvpOff, cannotAttackTeleportOrSpawnProtectionAttacker, + cannotAttackTeleportOrSpawnProtectionVictim, cannotAttackPetsTeleportOrSpawnProtectionAttacker, + cannotAttackMountsTeleportOrSpawnProtectionAttacker; + @Getter private final double lava_and_fire_stopper_radius; @Getter private final long cache_time, combat_time, login_protection_time, teleport_protection_time; @Getter private final Set combatBlockedCommands = new HashSet<>(); @@ -99,6 +104,12 @@ public class ConfigCache { addDefault("placeholder.pvp_forced_true", "PvP is forced on"); addDefault("placeholder.pvp_forced_false", "PvP is forced off"); addDefault("placeholder.pvp_forced_none", "PvP is not forced"); + + addDefault("messages.cannot_attack_teleport_or_spawn_protection", "You can't attack players that have recently teleported or logged in"); + addDefault("messages.cannot_attack_teleport_or_spawn_protection_attacker", "You can't attack players while you have recently teleported or logged in"); + addDefault("messages.cannot_attack_pets_teleport_or_spawn_protection_attacker", "You can't attack pets while you have recently teleported or logged in"); + addDefault("messages.cannot_attack_mounts_teleport_or_spawn_protection_attacker", "You can't attack mounts while you have recently teleported or logged in"); + addDefault("messages.cannot_attack_teleport_or_spawn_protection_victim", "You can't attack players that have recently teleported or logged in"); } }; @@ -147,6 +158,7 @@ public class ConfigCache { this.cannot_attack_mounts_victim = config.getString("messages.cannot_attack_mounts_victim", "You can't attack mounts of players that have PvP turned off"); this.cannot_attack_mounts_attacker = config.getString("messages.cannot_attack_mounts_attacker", "You can't attack mounts while you have PvP turned off"); this.cannot_attack_pvp_force_off = config.getString("messages.cannot_attack_pvp_force_off", "PvP is forcibly disabled"); + this.no_permission = config.getString("messages.no_permission", "You don't have permission to use that."); this.no_such_command = config.getString("messages.no_such_command", "No such command."); this.pvp_enabled_other = config.getString("messages.pvp_enabled_others", "You've enabled %player%'s PvP."); @@ -164,6 +176,12 @@ public class ConfigCache { this.placeholder_pvp_forced_true = config.getString("placeholder.pvp_forced_true", "PvP is forced on"); this.placeholder_pvp_forced_false = config.getString("placeholder.pvp_forced_false", "PvP is forced off"); this.placeholder_pvp_forced_none = config.getString("placeholder.pvp_forced_none", "PvP is not forced"); + + this.cannotAttackForcedPvpOff = config.getString("messages.cannot_attack_pvp_force_off", "PvP is forcibly disabled"); + this.cannotAttackTeleportOrSpawnProtectionAttacker = config.getString("messages.cannot_attack_teleport_or_spawn_protection_attacker", "You can't attack players while they have teleport or spawn protection"); + this.cannotAttackPetsTeleportOrSpawnProtectionAttacker = config.getString("messages.cannot_attack_pets_teleport_or_spawn_protection_attacker", "You can't attack pets while you have teleport or spawn protection"); + this.cannotAttackMountsTeleportOrSpawnProtectionAttacker = config.getString("messages.cannot_attack_mounts_teleport_or_spawn_protection_attacker", "You can't attack mounts while you have teleport or spawn protection"); + this.cannotAttackTeleportOrSpawnProtectionVictim = config.getString("messages.cannot_attack_teleport_or_spawn_protection_victim", "You can't attack players while you have teleport or spawn protection"); } diff --git a/src/main/java/me/youhavetrouble/preventstabby/util/DamageUtil.java b/src/main/java/me/youhavetrouble/preventstabby/util/DamageUtil.java new file mode 100644 index 0000000..0e47c39 --- /dev/null +++ b/src/main/java/me/youhavetrouble/preventstabby/util/DamageUtil.java @@ -0,0 +1,138 @@ +package me.youhavetrouble.preventstabby.util; + +import me.youhavetrouble.preventstabby.PreventStabby; +import me.youhavetrouble.preventstabby.config.ConfigCache; +import me.youhavetrouble.preventstabby.players.PlayerManager; +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 DamageUtil { + + private final ConfigCache config; + private final PlayerManager playerManager; + + public DamageUtil(PreventStabby plugin) { + this.config = plugin.getConfigCache(); + this.playerManager = plugin.getPlayerManager(); + } + + public DamageCheckResult canDamage(Entity attacker, Entity victim) { + + Target attackerData = getUuidOfActualPlayer(attacker); + Target victimData = getUuidOfActualPlayer(victim); + if (attackerData == null || victimData == null) return new DamageCheckResult(true, null, null); + + if (playerManager.hasLoginProtection(attackerData.uuid) || playerManager.hasTeleportProtection(attackerData.uuid)) { + String message = null; + switch (victimData.classifier) { + case PLAYER: + message = config.cannotAttackTeleportOrSpawnProtectionAttacker; + break; + case PET: + message = config.cannotAttackPetsTeleportOrSpawnProtectionAttacker; + break; + case MOUNT: + message = config.cannotAttackMountsTeleportOrSpawnProtectionAttacker; + break; + } + return new DamageCheckResult(false, message, null); + } + if (playerManager.hasLoginProtection(victimData.uuid) || playerManager.hasTeleportProtection(victimData.uuid)) { + String message = null; + if (victimData.classifier == EntityClassifier.PLAYER) { + message = config.cannotAttackTeleportOrSpawnProtectionVictim; + } + return new DamageCheckResult(false, message, null); + } + + switch (playerManager.getForcedPvpState()) { + case NONE: + default: + break; + case DISABLED: + return new DamageCheckResult(false, config.cannotAttackForcedPvpOff, null); + case ENABLED: + return new DamageCheckResult(true, null, null); + } + + return 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 + private 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 projectile = (Projectile) entity; + if (projectile.getShooter() instanceof Player) { + Player shooter = (Player) projectile.getShooter(); + 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 tameable = (Tameable) entity; + 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 { + public final UUID uuid; + public final EntityClassifier classifier; + + private Target(UUID uuid, EntityClassifier classifier) { + this.uuid = uuid; + this.classifier = classifier; + } + } + + public enum EntityClassifier { + PLAYER, + PET, + MOUNT, + OTHER + } + +}