diff --git a/src/main/java/com/nexomc/protectionlib/ProtectionCompatibility.kt b/src/main/java/com/nexomc/protectionlib/ProtectionCompatibility.kt index 46ba1fe..7950a7c 100644 --- a/src/main/java/com/nexomc/protectionlib/ProtectionCompatibility.kt +++ b/src/main/java/com/nexomc/protectionlib/ProtectionCompatibility.kt @@ -1,6 +1,7 @@ package com.nexomc.protectionlib import org.bukkit.Location +import org.bukkit.entity.Entity import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -33,4 +34,11 @@ abstract class ProtectionCompatibility(val mainPlugin: JavaPlugin, v * @return true if he can use the item at the location */ abstract fun canUse(player: Player, target: Location): Boolean + + /** + * @param player Player looking to use an item + * @param entity Entity that players trying to damage + * @return true if he can use the item at the location + */ + abstract fun canDamage(player: Player, entity: Entity): Boolean } diff --git a/src/main/java/com/nexomc/protectionlib/ProtectionLib.kt b/src/main/java/com/nexomc/protectionlib/ProtectionLib.kt index 4e21842..baf6022 100644 --- a/src/main/java/com/nexomc/protectionlib/ProtectionLib.kt +++ b/src/main/java/com/nexomc/protectionlib/ProtectionLib.kt @@ -15,6 +15,7 @@ import com.nexomc.protectionlib.compatibilities.WorldGuardCompat import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import org.bukkit.Bukkit import org.bukkit.Location +import org.bukkit.entity.Entity import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -68,6 +69,13 @@ object ProtectionLib { }.onFailure { if (debug) it.printStackTrace() }.getOrDefault(true) } + @JvmStatic + fun canDamage(player: Player, entity: Entity): Boolean { + return runCatching { + compatibilities.all { it.canDamage(player, entity) } + }.onFailure { if (debug) it.printStackTrace() }.getOrDefault(true) + } + private inline fun handleCompatibility(pluginName: String, mainPlugin: JavaPlugin, constructor: CompatibilityConstructor) { runCatching { val plugin = Bukkit.getPluginManager().getPlugin(pluginName) as? T ?: return diff --git a/src/main/java/com/nexomc/protectionlib/compatibilities/BentoBoxCompat.kt b/src/main/java/com/nexomc/protectionlib/compatibilities/BentoBoxCompat.kt index 568342e..4e3899a 100644 --- a/src/main/java/com/nexomc/protectionlib/compatibilities/BentoBoxCompat.kt +++ b/src/main/java/com/nexomc/protectionlib/compatibilities/BentoBoxCompat.kt @@ -2,7 +2,11 @@ package com.nexomc.protectionlib.compatibilities import com.nexomc.protectionlib.ProtectionCompatibility import org.bukkit.Location +import org.bukkit.entity.Animals +import org.bukkit.entity.Entity +import org.bukkit.entity.Monster import org.bukkit.entity.Player +import org.bukkit.entity.Villager import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin import world.bentobox.bentobox.BentoBox @@ -51,4 +55,30 @@ class BentoBoxCompat(mainPlugin: JavaPlugin, plugin: BentoBox) : ProtectionCompa override fun canUse(player: Player, target: Location): Boolean { return !plugin.iwm.inWorld(target) || plugin.islands.locationIsOnIsland(player, target) } + + /** + * @param player Player looking to use an item + * @param entity Entity that players trying to damage + * @return true if he can damage the entity + */ + override fun canDamage(player: Player, entity: Entity): Boolean { + return when (entity) { + is Animals -> canDo(player, entity.location, Flags.HURT_ANIMALS) + is Monster -> canDo(player, entity.location, Flags.HURT_MONSTERS) + is Villager -> canDo(player, entity.location, Flags.HURT_VILLAGERS) + + is Player -> { + val iwm = plugin.iwm + val world = entity.location.world + when { + iwm.inWorld(world) -> canDo(player, entity.location, Flags.PVP_OVERWORLD) + iwm.isNether(world) -> canDo(player, entity.location, Flags.PVP_NETHER) + iwm.isEnd(world) -> canDo(player, entity.location, Flags.PVP_END) + else -> true + } + } + + else -> true + } + } } diff --git a/src/main/java/com/nexomc/protectionlib/compatibilities/CrashClaimCompat.kt b/src/main/java/com/nexomc/protectionlib/compatibilities/CrashClaimCompat.kt index 4e04b1a..4aa1395 100644 --- a/src/main/java/com/nexomc/protectionlib/compatibilities/CrashClaimCompat.kt +++ b/src/main/java/com/nexomc/protectionlib/compatibilities/CrashClaimCompat.kt @@ -5,6 +5,7 @@ import net.crashcraft.crashclaim.CrashClaim import net.crashcraft.crashclaim.api.CrashClaimAPI import net.crashcraft.crashclaim.permissions.PermissionRoute import org.bukkit.Location +import org.bukkit.entity.Entity import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -51,4 +52,15 @@ class CrashClaimCompat(mainPlugin: JavaPlugin, plugin: CrashClaim) : ProtectionC return crashClaim.permissionHelper.bypassManager.isBypass(player.uniqueId) || crashClaim.getClaim(target)?.hasPermission(player.uniqueId, target, PermissionRoute.INTERACTIONS) != false } + + /** + * @param player Player looking to use an item + * @param entity Entity that players trying to damage + * @return true if he can use the item at the location + */ + override fun canDamage(player: Player, entity: Entity): Boolean { + return crashClaim.permissionHelper.bypassManager.isBypass(player.uniqueId) || + crashClaim.getClaim(entity.location)?.hasPermission(player.uniqueId, entity.location, PermissionRoute.ENTITIES) != false + } + } diff --git a/src/main/java/com/nexomc/protectionlib/compatibilities/FactionsUuidCompat.kt b/src/main/java/com/nexomc/protectionlib/compatibilities/FactionsUuidCompat.kt index dee059e..da23499 100644 --- a/src/main/java/com/nexomc/protectionlib/compatibilities/FactionsUuidCompat.kt +++ b/src/main/java/com/nexomc/protectionlib/compatibilities/FactionsUuidCompat.kt @@ -2,10 +2,12 @@ package com.nexomc.protectionlib.compatibilities import com.massivecraft.factions.FactionsPlugin import com.massivecraft.factions.listeners.FactionsBlockListener +import com.massivecraft.factions.listeners.FactionsEntityListener import com.massivecraft.factions.listeners.FactionsPlayerListener import com.massivecraft.factions.perms.PermissibleActions import com.nexomc.protectionlib.ProtectionCompatibility import org.bukkit.Location +import org.bukkit.entity.Entity import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -47,4 +49,13 @@ class FactionsUuidCompat(mainPlugin: JavaPlugin, plugin: FactionsPlugin) : Prote override fun canUse(player: Player, target: Location): Boolean { return !plugin.worldUtil().isEnabled(target.world) || FactionsPlayerListener.canInteractHere(player, target) } + + /** + * @param player Player looking to use an item + * @param entity Entity that players trying to damage + * @return true if he can use the item at the location + */ + override fun canDamage(player: Player, entity: Entity): Boolean { + return !plugin.worldUtil().isEnabled(entity.location.world) || FactionsEntityListener.canDamage(player, entity, false) + } } diff --git a/src/main/java/com/nexomc/protectionlib/compatibilities/GriefPreventionCompat.kt b/src/main/java/com/nexomc/protectionlib/compatibilities/GriefPreventionCompat.kt index cc92b2b..23dfedd 100644 --- a/src/main/java/com/nexomc/protectionlib/compatibilities/GriefPreventionCompat.kt +++ b/src/main/java/com/nexomc/protectionlib/compatibilities/GriefPreventionCompat.kt @@ -6,6 +6,7 @@ import me.ryanhamshire.GriefPrevention.ClaimPermission import me.ryanhamshire.GriefPrevention.GriefPrevention import me.ryanhamshire.GriefPrevention.PlayerData import org.bukkit.Location +import org.bukkit.entity.Entity import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -47,6 +48,18 @@ class GriefPreventionCompat(mainPlugin: JavaPlugin, plugin: GriefPrevention) : P return checkPermission(player, target, ClaimPermission.Access) } + /** + * @param player Player trying to damage an entity + * @param entity Entity that a player is trying to damage + * @return true if he can damage the entity + */ + override fun canDamage(player: Player, entity: Entity): Boolean { + return when (entity) { + is Player -> checkPermission(player, entity.location, ClaimPermission.Inventory) + else -> checkPermission(player, entity.location, ClaimPermission.Build) + } + } + private fun checkPermission(player: Player, target: Location, permission: ClaimPermission): Boolean { val playerData: PlayerData = plugin.dataStore.getPlayerData(player.uniqueId).takeUnless { it.ignoreClaims } ?: return true val claim = plugin.dataStore.getClaimAt(target, false, playerData.lastClaim) ?: return true diff --git a/src/main/java/com/nexomc/protectionlib/compatibilities/HuskClaimCompat.kt b/src/main/java/com/nexomc/protectionlib/compatibilities/HuskClaimCompat.kt index c7e2244..cf6842b 100644 --- a/src/main/java/com/nexomc/protectionlib/compatibilities/HuskClaimCompat.kt +++ b/src/main/java/com/nexomc/protectionlib/compatibilities/HuskClaimCompat.kt @@ -7,6 +7,7 @@ import net.william278.huskclaims.api.BukkitHuskClaimsAPI import net.william278.huskclaims.api.HuskClaimsAPI import net.william278.huskclaims.libraries.cloplib.operation.OperationType import org.bukkit.Location +import org.bukkit.entity.Entity import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -47,4 +48,22 @@ class HuskClaimCompat(mainPlugin: JavaPlugin, plugin: BukkitHuskClaims) : Protec val trustLevel = huskClaimsBukkit.getTrustLevelAt(position, onlineUser) return trustLevel.isEmpty || trustLevel.get().flags.contains(OperationType.BLOCK_INTERACT) } + + override fun canDamage(player: Player, entity: Entity): Boolean { + val operation = if (entity is Player) { + OperationType.PLAYER_DAMAGE_PLAYER + } else { + OperationType.PLAYER_DAMAGE_ENTITY + } + + return hasOperation(player, entity.location, operation) + } + + private fun hasOperation(player: Player, location: Location, operation: OperationType): Boolean { + val onlineUser = huskClaimsCommon.getOnlineUser(player.uniqueId) + val position = huskClaimsBukkit.getPosition(location) + + val trustLevel = huskClaimsBukkit.getTrustLevelAt(position, onlineUser) + return trustLevel.isEmpty || trustLevel.get().flags.contains(operation) + } } diff --git a/src/main/java/com/nexomc/protectionlib/compatibilities/HuskTownsCompat.kt b/src/main/java/com/nexomc/protectionlib/compatibilities/HuskTownsCompat.kt index 157bf8f..6ccca1b 100644 --- a/src/main/java/com/nexomc/protectionlib/compatibilities/HuskTownsCompat.kt +++ b/src/main/java/com/nexomc/protectionlib/compatibilities/HuskTownsCompat.kt @@ -6,6 +6,7 @@ import net.william278.husktowns.api.BukkitHuskTownsAPI import net.william278.husktowns.api.HuskTownsAPI import net.william278.husktowns.libraries.cloplib.operation.OperationType import org.bukkit.Location +import org.bukkit.entity.Entity import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -31,6 +32,16 @@ class HuskTownsCompat(mainPlugin: JavaPlugin, plugin: BukkitHuskTowns) : Protect return isOperationAllowed(player, target, OperationType.BLOCK_INTERACT) } + override fun canDamage(player: Player, entity: Entity): Boolean { + val type = if (entity is Player) { + OperationType.PLAYER_DAMAGE_PLAYER + } else { + OperationType.PLAYER_DAMAGE_ENTITY + } + + return isOperationAllowed(player, entity.location, type) + } + private fun isOperationAllowed(player: Player, location: Location, type: OperationType): Boolean { val user = bukkitAPI.getOnlineUser(player) val position = bukkitAPI.getPosition(location) diff --git a/src/main/java/com/nexomc/protectionlib/compatibilities/LandsCompat.kt b/src/main/java/com/nexomc/protectionlib/compatibilities/LandsCompat.kt index 356312d..f39efb1 100644 --- a/src/main/java/com/nexomc/protectionlib/compatibilities/LandsCompat.kt +++ b/src/main/java/com/nexomc/protectionlib/compatibilities/LandsCompat.kt @@ -6,6 +6,8 @@ import me.angeschossen.lands.api.flags.type.Flags import me.angeschossen.lands.api.flags.type.RoleFlag import me.angeschossen.lands.api.land.LandWorld import org.bukkit.Location +import org.bukkit.entity.Entity +import org.bukkit.entity.Monster import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -49,6 +51,16 @@ class LandsCompat(mainPlugin: JavaPlugin, plugin: Plugin) : ProtectionCompatibil return hasFlag(target, player, Flags.INTERACT_GENERAL) } + override fun canDamage(player: Player, entity: Entity): Boolean { + val flag = when (entity) { + is Player -> Flags.ATTACK_PLAYER + is Monster -> Flags.ATTACK_MONSTER + else -> Flags.ATTACK_ANIMAL + } + + return hasFlag(entity.location, player, flag) + } + /** * Checks if a player's role has a flag at the given position. * This does check bypass perms and wilderness flags (/lands admin menu) as well. diff --git a/src/main/java/com/nexomc/protectionlib/compatibilities/NoBuildPlusCompat.kt b/src/main/java/com/nexomc/protectionlib/compatibilities/NoBuildPlusCompat.kt index 6c6411a..a546a2b 100644 --- a/src/main/java/com/nexomc/protectionlib/compatibilities/NoBuildPlusCompat.kt +++ b/src/main/java/com/nexomc/protectionlib/compatibilities/NoBuildPlusCompat.kt @@ -2,6 +2,7 @@ package com.nexomc.protectionlib.compatibilities import com.nexomc.protectionlib.ProtectionCompatibility import org.bukkit.Location +import org.bukkit.entity.Entity import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -26,4 +27,8 @@ class NoBuildPlusCompat(mainPlugin: JavaPlugin, plugin: NoBuildPlus) : Protectio override fun canUse(player: Player, target: Location): Boolean { return !plugin.api.canExecute(target.world.name, Flags.use) } + + override fun canDamage(player: Player, entity: Entity): Boolean { + return !plugin.api.canExecute(entity.location.world.name, Flags.mob_damage) + } } diff --git a/src/main/java/com/nexomc/protectionlib/compatibilities/PlotSquaredCompat.kt b/src/main/java/com/nexomc/protectionlib/compatibilities/PlotSquaredCompat.kt index a471343..c94c65e 100644 --- a/src/main/java/com/nexomc/protectionlib/compatibilities/PlotSquaredCompat.kt +++ b/src/main/java/com/nexomc/protectionlib/compatibilities/PlotSquaredCompat.kt @@ -3,6 +3,7 @@ package com.nexomc.protectionlib.compatibilities import com.nexomc.protectionlib.ProtectionCompatibility import com.plotsquared.core.plot.Plot import org.bukkit.Location +import org.bukkit.entity.Entity import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -34,6 +35,10 @@ class PlotSquaredCompat(mainPlugin: JavaPlugin, plugin: Plugin) : ProtectionComp return target.plotFromLocation()?.isDenied(player.uniqueId) != true } + override fun canDamage(player: Player, entity: Entity): Boolean { + return entity.location.plotFromLocation()?.isDenied(player.uniqueId) != true + } + private fun Location.plotFromLocation(): Plot? { return Plot.getPlot(adaptBukkitLocation(this) ?: return null) } diff --git a/src/main/java/com/nexomc/protectionlib/compatibilities/ResidenceCompat.kt b/src/main/java/com/nexomc/protectionlib/compatibilities/ResidenceCompat.kt index db0390a..e1131dd 100644 --- a/src/main/java/com/nexomc/protectionlib/compatibilities/ResidenceCompat.kt +++ b/src/main/java/com/nexomc/protectionlib/compatibilities/ResidenceCompat.kt @@ -5,6 +5,7 @@ import com.bekvon.bukkit.residence.containers.Flags import com.bekvon.bukkit.residence.protection.ClaimedResidence import com.nexomc.protectionlib.ProtectionCompatibility import org.bukkit.Location +import org.bukkit.entity.Entity import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -52,4 +53,14 @@ class ResidenceCompat(mainPlugin: JavaPlugin, plugin: Residence) : ProtectionCom // No single use flag, so just check if player is on their own island return canDo(player, target, Flags.use) } + + override fun canDamage(player: Player, entity: Entity): Boolean { + val flag = if (entity is Player) { + Flags.pvp + } else { + Flags.damage + } + + return canDo(player, entity.location, flag) + } } diff --git a/src/main/java/com/nexomc/protectionlib/compatibilities/TownyCompat.kt b/src/main/java/com/nexomc/protectionlib/compatibilities/TownyCompat.kt index 18acb61..f99180d 100644 --- a/src/main/java/com/nexomc/protectionlib/compatibilities/TownyCompat.kt +++ b/src/main/java/com/nexomc/protectionlib/compatibilities/TownyCompat.kt @@ -1,10 +1,14 @@ package com.nexomc.protectionlib.compatibilities import com.nexomc.protectionlib.ProtectionCompatibility +import com.palmergames.bukkit.towny.Towny import com.palmergames.bukkit.towny.`object`.TownyPermission +import com.palmergames.bukkit.towny.utils.CombatUtil import com.palmergames.bukkit.towny.utils.PlayerCacheUtil import org.bukkit.Location +import org.bukkit.entity.Entity import org.bukkit.entity.Player +import org.bukkit.event.entity.EntityDamageEvent import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -56,4 +60,8 @@ class TownyCompat(mainPlugin: JavaPlugin, plugin: Plugin) : ProtectionCompatibil TownyPermission.ActionType.ITEM_USE ) } + + override fun canDamage(player: Player, entity: Entity): Boolean { + return !CombatUtil.preventDamageCall(player, entity, EntityDamageEvent.DamageCause.ENTITY_ATTACK) + } } diff --git a/src/main/java/com/nexomc/protectionlib/compatibilities/WorldGuardCompat.kt b/src/main/java/com/nexomc/protectionlib/compatibilities/WorldGuardCompat.kt index 2a42b7d..4a42fb8 100644 --- a/src/main/java/com/nexomc/protectionlib/compatibilities/WorldGuardCompat.kt +++ b/src/main/java/com/nexomc/protectionlib/compatibilities/WorldGuardCompat.kt @@ -7,6 +7,9 @@ import com.sk89q.worldguard.WorldGuard import com.sk89q.worldguard.bukkit.WorldGuardPlugin import com.sk89q.worldguard.protection.flags.Flags import org.bukkit.Location +import org.bukkit.entity.Animals +import org.bukkit.entity.Entity +import org.bukkit.entity.Monster import org.bukkit.entity.Player import org.bukkit.plugin.Plugin import org.bukkit.plugin.java.JavaPlugin @@ -52,6 +55,20 @@ class WorldGuardCompat(mainPlugin: JavaPlugin, plugin: WorldGuardPlugin) : Prote return WorldGuard.getInstance().platform.regionContainer.createQuery().testBuild(BukkitAdapter.adapt(target), localPlayer, Flags.USE) || hasBypass(player, localPlayer) } + override fun canDamage(player: Player, entity: Entity): Boolean { + val localPlayer = plugin.wrapPlayer(player) + val query = WorldGuard.getInstance().platform.regionContainer.createQuery() + val location = BukkitAdapter.adapt(entity.location) + + val flag = when (entity) { + is Player -> Flags.PVP + is Animals -> Flags.DAMAGE_ANIMALS + else -> return true + } + + return query.testState(location, localPlayer, flag) || hasBypass(player, localPlayer) + } + private fun hasBypass(player: Player, localPlayer: LocalPlayer): Boolean { return WorldGuard.getInstance().platform.sessionManager.hasBypass(localPlayer, BukkitAdapter.adapt(player.world)) }