Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Fixed player splash potions not working and reworked potion dispense behaviour #115

Merged
merged 9 commits into from
Nov 5, 2024
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
### Added
- Protection against wind charges being used to push animals and villagers, protected by the husbandry permission.
- Protection against wind charges being used to push armour stands. Requires the build permission.
- Protection against witches affecting animals and villagers with splash potions. Bypassed by the mob griefing flag.

### Changed
- Splash potions are now completely negated if dispensed into a claim, with per entity checks only required when dispensed onto outer edge of claim.

### Fixed
- Dispense flag cancels splash potions entirely, rather than just ones thrown by a dispenser.

## [0.3.5]

Expand All @@ -18,7 +25,6 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
### Fixed
- Server crashing due to math error when certain claim partition configurations are attempting to be visualised.


## [0.3.4]

### Fixed
Expand Down
6 changes: 4 additions & 2 deletions src/main/kotlin/dev/mizarc/bellclaims/domain/flags/Flag.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ enum class Flag(val rules: Array<RuleExecutor>) {
RuleBehaviour.creeperExplode,
RuleBehaviour.creeperDamageStaticEntity,
RuleBehaviour.creeperDamageHangingEntity,
RuleBehaviour.potBreak
RuleBehaviour.potBreak,
RuleBehaviour.mobSplashPotion
)),

/**
Expand Down Expand Up @@ -72,7 +73,8 @@ enum class Flag(val rules: Array<RuleExecutor>) {
Dispensers(arrayOf(
RuleBehaviour.dispense,
RuleBehaviour.dispensedSplashPotion,
RuleBehaviour.dispensedLingeringPotion
RuleBehaviour.dispensedLingeringPotionSplash,
RuleBehaviour.dispensedLingeringPotionEffect
)),

Sponge(arrayOf(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package dev.mizarc.bellclaims.interaction.behaviours

import com.destroystokyo.paper.MaterialSetTag
import com.destroystokyo.paper.MaterialTags
import org.bukkit.Material
import org.bukkit.World
Expand All @@ -20,8 +19,6 @@ import dev.mizarc.bellclaims.domain.partitions.Position2D
import dev.mizarc.bellclaims.domain.partitions.Position3D
import org.bukkit.Location
import org.bukkit.block.BlockState
import org.bukkit.block.BlockType
import org.bukkit.block.data.BlockData
import org.bukkit.block.data.Directional
import org.bukkit.block.data.type.DecoratedPot
import org.bukkit.entity.*
Expand All @@ -30,12 +27,14 @@ import org.bukkit.event.entity.EntityBreakDoorEvent
import org.bukkit.event.entity.EntityDamageByBlockEvent
import org.bukkit.event.entity.EntityDamageByEntityEvent
import org.bukkit.event.entity.EntityDamageEvent
import org.bukkit.event.entity.LingeringPotionSplashEvent
import org.bukkit.event.entity.PotionSplashEvent
import org.bukkit.event.hanging.HangingBreakByEntityEvent
import org.bukkit.event.hanging.HangingBreakEvent
import org.bukkit.event.weather.LightningStrikeEvent
import org.bukkit.event.world.StructureGrowEvent
import org.bukkit.inventory.ItemStack
import org.bukkit.projectiles.BlockProjectileSource

/**
* A data structure that contains the type of event [eventClass], the function to handle the result of the event
Expand Down Expand Up @@ -98,8 +97,12 @@ class RuleBehaviour {
Companion::blockDispenseInClaim)
val dispensedSplashPotion = RuleExecutor(PotionSplashEvent::class.java,
Companion::cancelSplashPotionEffect, Companion::potionSplashInClaim)
val dispensedLingeringPotion = RuleExecutor(AreaEffectCloudApplyEvent::class.java,
val dispensedLingeringPotionEffect = RuleExecutor(AreaEffectCloudApplyEvent::class.java,
Companion::cancelLingeringPotionEffect, Companion::areaEffectCloudApplyInClaim)
val dispensedLingeringPotionSplash = RuleExecutor(LingeringPotionSplashEvent::class.java,
Companion::cancelLingeringPotionSplash, Companion::lingeringPotionSplashInClaim)
val mobSplashPotion = RuleExecutor(PotionSplashEvent::class.java,
Companion::cancelMobSplashPotionEffect, Companion::potionSplashInClaim)
val spongeAbsorb = RuleExecutor(SpongeAbsorbEvent::class.java, Companion::cancelSpongeAbsorbEvent,
Companion::spongeAbsorbInClaim)
val lightningDamage = RuleExecutor(LightningStrikeEvent::class.java, Companion::cancelLightningStrikeEvent,
Expand Down Expand Up @@ -673,6 +676,13 @@ class RuleBehaviour {
partitionService: PartitionService): List<Claim> {
if (event !is PotionSplashEvent) return listOf()
val affectedClaims = mutableListOf<Claim>()

// Include the claim the potion lands in
val potionClaim = partitionService.getByLocation(event.entity.location)?.let {
claimService.getById(it.claimId) }
if (potionClaim != null) affectedClaims.add(potionClaim)

// Include through all affected entities
for (entity in event.affectedEntities) {
val partition = partitionService.getByLocation(entity.location) ?: continue
val claim = claimService.getById(partition.claimId) ?: continue
Expand All @@ -681,13 +691,54 @@ class RuleBehaviour {
return affectedClaims
}

private fun lingeringPotionSplashInClaim(event: Event, claimService: ClaimService,
partitionService: PartitionService): List<Claim> {
if (event !is LingeringPotionSplashEvent) return listOf()
val claim = partitionService.getByLocation(event.entity.location)?.let {
claimService.getById(it.claimId) } ?: return listOf()
return listOf(claim)
}

private fun cancelSplashPotionEffect(event: Event, claimService: ClaimService,
partitionService: PartitionService, flagService: FlagService): Boolean {
if (event !is PotionSplashEvent) return false
val projectile = event.entity as Projectile
val dispenser = projectile.shooter as? BlockProjectileSource
if (dispenser == null) return false
val dispenserClaim = partitionService.getByLocation(dispenser.block.location)?.let {
claimService.getById(it.claimId) }
val potionClaim = partitionService.getByLocation(projectile.location)?.let {
claimService.getById(it.claimId) }

// Cancel if the potion is thrown into the claim
if (dispenserClaim != potionClaim) {
event.isCancelled = true
return true
}

// For the splash affect, cancel out non-monster mobs that are inside the claim
for (entity in event.affectedEntities) {
if (entity !is Monster) {
event.setIntensity(entity, 0.0)
}
val entityClaim = partitionService.getByLocation(entity.location)?.let {
claimService.getById(it.claimId) }
if (entityClaim == dispenserClaim) continue
if (entity !is Monster) event.setIntensity(entity, 0.0)
}
return true
}

private fun cancelMobSplashPotionEffect(event: Event, claimService: ClaimService,
partitionService: PartitionService, flagService: FlagService): Boolean {
if (event !is PotionSplashEvent) return false
val projectile = event.entity as Projectile
val monster = projectile.shooter as? Monster
if (monster == null) return false

// For the splash affect, cancel out non-monster mobs that are inside the claim
for (entity in event.affectedEntities) {
val entityClaim = partitionService.getByLocation(entity.location)?.let {
claimService.getById(it.claimId) } ?: continue
if (flagService.doesClaimHaveFlag(entityClaim, Flag.MobGriefing)) continue
if (entity is Animals || entity is AbstractVillager) event.setIntensity(entity, 0.0)
}
return true
}
Expand All @@ -704,11 +755,41 @@ class RuleBehaviour {
return affectedClaims
}

private fun cancelLingeringPotionSplash(event: Event, claimService: ClaimService,
partitionService: PartitionService, flagService: FlagService): Boolean {
if (event !is LingeringPotionSplashEvent) return false
val projectile = event.entity
val dispenser = projectile.shooter as? BlockProjectileSource
if (dispenser == null) return false

val dispenserClaim = partitionService.getByLocation(dispenser.block.location)?.let {
claimService.getById(it.claimId) }
val projectileClaim = partitionService.getByLocation(projectile.location)?.let {
claimService.getById(it.claimId) }

if (dispenserClaim == projectileClaim) return false
event.isCancelled = true
return true
}

private fun cancelLingeringPotionEffect(event: Event, claimService: ClaimService,
partitionService: PartitionService, flagService: FlagService): Boolean {
if (event !is AreaEffectCloudApplyEvent) return false
event.affectedEntities.removeAll { it !is Monster }
return false
if (event.entity.source is Player || event.entity.source is Monster) return false
val potionClaim = partitionService.getByLocation(event.entity.location)?.let {
claimService.getById(it.claimId) }

// Check each entity to see if they should be affected
val affectedEntities = event.affectedEntities.toMutableList()
for (entity in event.affectedEntities) {
val entityClaim = partitionService.getByLocation(entity.location)?.let {
claimService.getById(it.claimId) } ?: continue
if (entityClaim == potionClaim) continue
if (entity !is Monster) affectedEntities.remove(entity)
}
event.affectedEntities.clear()
event.affectedEntities.addAll(affectedEntities)
return true
}

private fun cancelBlockDispenseEvent(event: Event, claimService: ClaimService,
Expand Down