Flags for Block Explode (#1899)

* add Block Explosion support for TNT_DAMAGE flag

* prevent block explosion from damaging entities

* seperated flags for block explode

* invert and cancel

* pattern instanceof
This commit is contained in:
Huynh Tien 2022-01-02 08:42:46 +07:00 committed by GitHub
parent dffe8a811e
commit 7088a2736f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 80 additions and 6 deletions

View File

@ -10,6 +10,7 @@ import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockExplodeEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
@ -50,8 +51,8 @@ public class TNTListener extends FlagListener {
// Stop TNT from being damaged if it is being caused by a visitor with a flaming arrow
if (e.getEntity() instanceof Projectile projectile) {
// Find out who fired it
if (projectile.getShooter() instanceof Player && projectile.getFireTicks() > 0
&& !checkIsland(e, (Player)projectile.getShooter(), e.getBlock().getLocation(), Flags.TNT_PRIMING)) {
if (projectile.getShooter() instanceof Player shooter && projectile.getFireTicks() > 0
&& !checkIsland(e, shooter, e.getBlock().getLocation(), Flags.TNT_PRIMING)) {
// Remove the arrow
projectile.remove();
e.setCancelled(true);
@ -82,12 +83,17 @@ public class TNTListener extends FlagListener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onExplosion(final EntityExplodeEvent e) {
// Check world and types
if (getIWM().inWorld(e.getLocation()) && TNT_TYPES.contains(e.getEntityType())) {
// Remove any blocks from the explosion list if required
e.blockList().removeIf(b -> protect(b.getLocation()));
e.setCancelled(protect(e.getLocation()));
if (!getIWM().inWorld(e.getLocation()) || !TNT_TYPES.contains(e.getEntityType())) {
return;
}
if (protect(e.getLocation())) {
// This is protected as a whole, so just cancel the event
e.setCancelled(true);
} else {
// Remove any blocks from the explosion list if required
e.blockList().removeIf(b -> protect(b.getLocation()));
}
}
protected boolean protect(Location location) {
@ -109,4 +115,43 @@ public class TNTListener extends FlagListener {
e.setCancelled(protect(e.getEntity().getLocation()));
}
}
protected boolean protectBlockExplode(Location location) {
return getIslands().getProtectedIslandAt(location).map(i -> !i.isAllowed(Flags.BLOCK_EXPLODE_DAMAGE))
.orElseGet(() -> !Flags.WORLD_BLOCK_EXPLODE_DAMAGE.isSetForWorld(location.getWorld()));
}
/**
* Prevents block explosion from breaking blocks
* @param e - event
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onExplosion(final BlockExplodeEvent e) {
// Check world
if (!getIWM().inWorld(e.getBlock().getLocation())) {
return;
}
if (protectBlockExplode(e.getBlock().getLocation())) {
// This is protected as a whole, so just cancel the event
e.setCancelled(true);
} else {
// Remove any blocks from the explosion list if required
e.blockList().removeIf(b -> protectBlockExplode(b.getLocation()));
}
}
/**
* Prevents block explosion from damaging entities.
* @param e event
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onExplosion(final EntityDamageEvent e) {
// Check if this in world and a block explosion
if (getIWM().inWorld(e.getEntity().getLocation())
&& e.getCause().equals(EntityDamageEvent.DamageCause.BLOCK_EXPLOSION)) {
// Check if it is disallowed, then cancel it.
e.setCancelled(protectBlockExplode(e.getEntity().getLocation()));
}
}
}

View File

@ -392,6 +392,14 @@ public final class Flags {
public static final Flag TNT_DAMAGE = new Flag.Builder("TNT_DAMAGE", Material.TNT).type(Type.SETTING)
.mode(Flag.Mode.ADVANCED).build();
/**
* If {@code false}, prevents Block Explode from breaking blocks and damaging nearby entities.
* @since 1.19.1
* @see TNTListener
*/
public static final Flag BLOCK_EXPLODE_DAMAGE = new Flag.Builder("BLOCK_EXPLODE_DAMAGE", Material.TNT_MINECART).type(Type.SETTING)
.mode(Flag.Mode.ADVANCED).build();
/**
* If {@code false}, prevents TNT from breaking blocks and damaging nearby entities outside of island boundaries.
* @since 1.15.3
@ -401,6 +409,15 @@ public final class Flags {
.type(Type.WORLD_SETTING)
.build();
/**
* If {@code false}, prevents Block Explode from breaking blocks and damaging nearby entities outside of island boundaries.
* @since 1.19.1
* @see TNTListener
*/
public static final Flag WORLD_BLOCK_EXPLODE_DAMAGE = new Flag.Builder("WORLD_BLOCK_EXPLODE_DAMAGE", Material.TNT_MINECART)
.type(Type.WORLD_SETTING)
.build();
/*
* World Settings - they apply to every island in the game worlds.
*/

View File

@ -815,6 +815,12 @@ protection:
name: "Barrels"
description: "Toggle barrel interaction"
hint: "Barrel access disabled"
BLOCK_EXPLODE_DAMAGE:
description: |-
&a Allow Bed & Respawn Anchors
&a to break blocks and damage
&a entities.
name: "Block explode damage"
COMPOSTER:
name: "Composters"
description: "Toggle composter interaction"
@ -1320,6 +1326,12 @@ protection:
description: |-
&a If active, withers can
&a damage blocks and players
WORLD_BLOCK_EXPLODE_DAMAGE:
description: |-
&a Allow Bed & Respawn Anchors
&a to break blocks and damage
&a entities outside of island limits.
name: "World block explode damage"
WORLD_TNT_DAMAGE:
description: |-
&a Allow TNT and TNT minecarts