Fix falling block and vehicle block change handling (#1424)

This commit is contained in:
Adam 2021-07-16 12:22:15 -04:00 committed by GitHub
parent fadc1aab30
commit d930e45440
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 106 additions and 61 deletions

View File

@ -19,7 +19,6 @@
package me.ryanhamshire.GriefPrevention;
import me.ryanhamshire.GriefPrevention.util.BoundingBox;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Location;
@ -740,34 +739,9 @@ public class BlockEventHandler implements Listener
}
}
// Handle arrows igniting TNT.
// Arrow ignition is handled by the EntityChangeBlockEvent.
if (igniteEvent.getCause() == IgniteCause.ARROW)
{
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(igniteEvent.getBlock().getLocation(), false, null);
if (claim == null)
{
// Only TNT can be ignited by arrows, so the targeted block will be destroyed by completion.
if (!GriefPrevention.instance.config_fireDestroys || !GriefPrevention.instance.config_fireSpreads)
igniteEvent.setCancelled(true);
return;
}
if (igniteEvent.getIgnitingEntity() instanceof Projectile)
{
ProjectileSource shooter = ((Projectile) igniteEvent.getIgnitingEntity()).getShooter();
// Allow ignition if arrow was shot by a player with build permission.
if (shooter instanceof Player && claim.checkPermission((Player) shooter, ClaimPermission.Build, igniteEvent) == null) return;
// Allow ignition if arrow was shot by a dispenser in the same claim.
if (shooter instanceof BlockProjectileSource &&
GriefPrevention.instance.dataStore.getClaimAt(((BlockProjectileSource) shooter).getBlock().getLocation(), false, claim) == claim)
return;
}
// Block all other ignition by arrows in claims.
igniteEvent.setCancelled(true);
return;
}
@ -926,11 +900,12 @@ public class BlockEventHandler implements Listener
//don't track in worlds where claims are not enabled
if (!GriefPrevention.instance.claimsEnabledForWorld(event.getEntity().getWorld())) return;
if (event.getHitBlock() == null || event.getHitBlock().getType() != Material.CHORUS_FLOWER)
return;
Block block = event.getHitBlock();
// Ensure projectile affects block.
if (block == null || block.getType() != Material.CHORUS_FLOWER)
return;
Claim claim = dataStore.getClaimAt(block.getLocation(), false, null);
if (claim == null)
return;
@ -943,8 +918,7 @@ public class BlockEventHandler implements Listener
if (shooter == null)
{
event.getHitBlock().setType(Material.AIR);
Bukkit.getScheduler().runTask(GriefPrevention.instance, () -> event.getHitBlock().setBlockData(block.getBlockData()));
event.setCancelled(true);
return;
}
@ -952,8 +926,7 @@ public class BlockEventHandler implements Listener
if (allowContainer != null)
{
event.getHitBlock().setType(Material.AIR);
Bukkit.getScheduler().runTask(GriefPrevention.instance, () -> event.getHitBlock().setBlockData(block.getBlockData()));
event.setCancelled(true);
GriefPrevention.sendMessage(shooter, TextMode.Err, allowContainer.get());
return;
}

View File

@ -85,13 +85,13 @@ import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.vehicle.VehicleDamageEvent;
import org.bukkit.event.weather.LightningStrikeEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.projectiles.BlockProjectileSource;
import org.bukkit.projectiles.ProjectileSource;
import org.bukkit.util.Vector;
@ -149,41 +149,50 @@ public class EntityEventHandler implements Listener
{
event.setCancelled(true);
}
else if (GriefPrevention.instance.config_claims_worldModes.get(event.getBlock().getWorld()) != ClaimsMode.Disabled)
else if (!GriefPrevention.instance.config_claims_ravagersBreakBlocks && event.getEntityType() == EntityType.RAVAGER)
{
if (event.getEntityType() == EntityType.WITHER)
{
Claim claim = this.dataStore.getClaimAt(event.getBlock().getLocation(), false, null);
if (claim == null || !claim.areExplosivesAllowed || !GriefPrevention.instance.config_blockClaimExplosions)
{
event.setCancelled(true);
}
}
else if (!GriefPrevention.instance.config_claims_ravagersBreakBlocks && event.getEntityType() == EntityType.RAVAGER)
event.setCancelled(true);
}
// All other handling depends on claims being enabled.
else if (GriefPrevention.instance.config_claims_worldModes.get(event.getBlock().getWorld()) == ClaimsMode.Disabled)
{
return;
}
// Handle projectiles changing blocks: TNT ignition, tridents knocking down pointed dripstone, etc.
if (event.getEntity() instanceof Projectile)
{
handleProjectileChangeBlock(event, (Projectile) event.getEntity());
}
else if (event.getEntityType() == EntityType.WITHER)
{
Claim claim = this.dataStore.getClaimAt(event.getBlock().getLocation(), false, null);
if (claim == null || !claim.areExplosivesAllowed || !GriefPrevention.instance.config_blockClaimExplosions)
{
event.setCancelled(true);
}
}
//don't allow crops to be trampled, except by a player with build permission
else if (event.getTo() == Material.DIRT && event.getBlock().getType() == Material.FARMLAND)
//don't allow crops to be trampled, except by a player with build permission
else if (event.getTo() == Material.DIRT && event.getBlock().getType() == Material.FARMLAND)
{
if (event.getEntityType() != EntityType.PLAYER)
{
if (event.getEntityType() != EntityType.PLAYER)
event.setCancelled(true);
}
else
{
Player player = (Player) event.getEntity();
Block block = event.getBlock();
if (GriefPrevention.instance.allowBreak(player, block, block.getLocation()) != null)
{
event.setCancelled(true);
}
else
{
Player player = (Player) event.getEntity();
Block block = event.getBlock();
if (GriefPrevention.instance.allowBreak(player, block, block.getLocation()) != null)
{
event.setCancelled(true);
}
}
}
}
//Prevent breaking lilypads via collision with a boat. Thanks Jikoo.
// Prevent breaking lily pads via collision with a boat.
else if (event.getEntity() instanceof Vehicle && !event.getEntity().getPassengers().isEmpty())
{
Entity driver = event.getEntity().getPassengers().get(0);
@ -226,6 +235,7 @@ public class EntityEventHandler implements Listener
if (GriefPrevention.instance.config_claims_worldModes.get(newLocation.getWorld()) == ClaimsMode.Creative)
{
event.setCancelled(true);
entity.remove();
return;
}
@ -236,15 +246,77 @@ public class EntityEventHandler implements Listener
//when not allowed, drop as item instead of forming a block
event.setCancelled(true);
ItemStack itemStack = new ItemStack(entity.getMaterial(), 1);
Item item = block.getWorld().dropItem(entity.getLocation(), itemStack);
item.setVelocity(new Vector());
// Just in case, skip already dead entities.
if (entity.isDead())
{
return;
}
// Remove entity so it doesn't continuously spawn drops.
entity.remove();
ItemStack itemStack = new ItemStack(entity.getBlockData().getMaterial(), 1);
block.getWorld().dropItemNaturally(entity.getLocation(), itemStack);
}
}
}
}
}
private void handleProjectileChangeBlock(EntityChangeBlockEvent event, Projectile projectile)
{
Block block = event.getBlock();
Claim claim = this.dataStore.getClaimAt(block.getLocation(), false, null);
// Wilderness rules
if (claim == null)
{
// TNT change means ignition. If no claim is present, use global fire rules.
if (block.getType() == Material.TNT)
{
if (!GriefPrevention.instance.config_fireDestroys || !GriefPrevention.instance.config_fireSpreads)
event.setCancelled(true);
return;
}
// No modification in the wilderness in creative mode.
if (instance.creativeRulesApply(block.getLocation()) || instance.config_claims_worldModes.get(block.getWorld()) == ClaimsMode.SurvivalRequiringClaims)
{
event.setCancelled(true);
return;
}
// Unclaimed area is fair game.
return;
}
ProjectileSource shooter = projectile.getShooter();
if (shooter instanceof Player)
{
Supplier<String> denial = claim.checkPermission((Player) shooter, ClaimPermission.Build, event);
// If the player cannot place the material being broken, disallow.
if (denial != null)
{
// Unlike entities where arrows rebound and may cause multiple alerts,
// projectiles lodged in blocks do not continuously re-trigger events.
GriefPrevention.sendMessage((Player) shooter, TextMode.Err, denial.get());
event.setCancelled(true);
}
return;
}
// Allow change if projectile was shot by a dispenser in the same claim.
if (shooter instanceof BlockProjectileSource &&
GriefPrevention.instance.dataStore.getClaimAt(((BlockProjectileSource) shooter).getBlock().getLocation(), false, claim) == claim)
return;
// Prevent change in all other cases.
event.setCancelled(true);
}
//Used by "sand cannon" fix to ignore fallingblocks that fell through End Portals
//This is largely due to a CB issue with the above event
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)