Refactor EnginePermBuild to more suitable structure.

This commit is contained in:
ulumulu1510 2017-04-03 12:33:13 +02:00
parent 093dbde473
commit edfabb7718
5 changed files with 313 additions and 357 deletions

View File

@ -10,7 +10,8 @@ public class EngineMain
*/ */
public static boolean canPlayerBuildAt(Object senderObject, PS ps, boolean verboose) public static boolean canPlayerBuildAt(Object senderObject, PS ps, boolean verboose)
{ {
return EnginePermBuild.canPlayerBuildAt(senderObject, ps, verboose); Boolean ret = EnginePermBuild.protect(ProtectCase.BUILD, verboose, senderObject, ps, null, null);
return ret == null || !ret;
} }
} }

View File

@ -18,8 +18,9 @@ import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
@ -32,7 +33,6 @@ import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.hanging.HangingBreakByEntityEvent; import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingPlaceEvent; import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.player.PlayerBucketEmptyEvent; import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.event.player.PlayerBucketFillEvent;
@ -51,7 +51,65 @@ public class EnginePermBuild extends Engine
public static EnginePermBuild get() { return i; } public static EnginePermBuild get() { return i; }
// -------------------------------------------- // // -------------------------------------------- //
// PERM: BUILD // LOGIC > PROTECT
// -------------------------------------------- //
public static Boolean isProtected(ProtectCase protectCase, boolean verboose, MPlayer mplayer, PS ps, Object object)
{
if (mplayer == null) return null;
if (protectCase == null) return null;
String name = mplayer.getName();
if (MConf.get().playersWhoBypassAllProtection.contains(name)) return false;
if (mplayer.isOverriding()) return false;
MPerm perm = protectCase.getPerm(object);
if (perm == null) return null;
if (protectCase != ProtectCase.BUILD) return !perm.has(mplayer, ps, verboose);
if (!perm.has(mplayer, ps, false) && MPerm.getPermPainbuild().has(mplayer, ps, false))
{
if (!verboose) return false;
Faction hostFaction = BoardColl.get().getFactionAt(ps);
mplayer.msg("<b>It is painful to build in the territory of %s<b>.", hostFaction.describeTo(mplayer));
Player player = mplayer.getPlayer();
if (player != null) player.damage(MConf.get().actionDeniedPainAmount);
}
return !perm.has(mplayer, ps, verboose);
}
public static Boolean protect(ProtectCase protectCase, boolean verboose, Object senderObject, PS ps, Object object, Cancellable cancellable)
{
Boolean ret = isProtected(protectCase, verboose, MPlayer.get(senderObject), ps, object);
if (Boolean.TRUE.equals(ret) && cancellable != null) cancellable.setCancelled(true);
return ret;
}
public static Boolean build(Entity entity, Block block, Event event)
{
if (!(event instanceof Cancellable)) return true;
boolean verboose = !isFake(event);
return protect(ProtectCase.BUILD, verboose, entity, PS.valueOf(block), block, (Cancellable) event);
}
public static Boolean useItem(Entity entity, Block block, Material material, Cancellable cancellable)
{
return protect(ProtectCase.USE_ITEM, true, entity, PS.valueOf(block), material, cancellable);
}
public static Boolean useEntity(Entity player, Entity entity, boolean verboose, Cancellable cancellable)
{
return protect(ProtectCase.USE_ENTITY, verboose, player, PS.valueOf(entity), entity, cancellable);
}
public static Boolean useBlock(Player player, Block block, boolean verboose, Cancellable cancellable)
{
return protect(ProtectCase.USE_BLOCK, verboose, player, PS.valueOf(block), block, cancellable);
}
// -------------------------------------------- //
// LOGIC > PROTECT > BUILD
// -------------------------------------------- // // -------------------------------------------- //
public static boolean canPlayerBuildAt(Object senderObject, PS ps, boolean verboose) public static boolean canPlayerBuildAt(Object senderObject, PS ps, boolean verboose)
@ -59,83 +117,116 @@ public class EnginePermBuild extends Engine
MPlayer mplayer = MPlayer.get(senderObject); MPlayer mplayer = MPlayer.get(senderObject);
if (mplayer == null) return false; if (mplayer == null) return false;
String name = mplayer.getName(); Boolean ret = isProtected(ProtectCase.BUILD, verboose, mplayer, ps, null);
if (MConf.get().playersWhoBypassAllProtection.contains(name)) return true; return !Boolean.TRUE.equals(ret);
if (mplayer.isOverriding()) return true;
if (!MPerm.getPermBuild().has(mplayer, ps, false) && MPerm.getPermPainbuild().has(mplayer, ps, false))
{
if (verboose)
{
Faction hostFaction = BoardColl.get().getFactionAt(ps);
mplayer.msg("<b>It is painful to build in the territory of %s<b>.", hostFaction.describeTo(mplayer));
Player player = mplayer.getPlayer();
if (player != null)
{
player.damage(MConf.get().actionDeniedPainAmount);
}
}
return true;
} }
return MPerm.getPermBuild().has(mplayer, ps, verboose); // -------------------------------------------- //
} // BUILD > BLOCK
// -------------------------------------------- //
@EventHandler(priority = EventPriority.NORMAL) @EventHandler(priority = EventPriority.NORMAL)
public void blockBuild(BlockPlaceEvent event) public void build(BlockPlaceEvent event) { build(event.getPlayer(), event.getBlock(), event); }
{
if (!event.canBuild()) return;
boolean verboose = ! isFake(event);
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), verboose)) return;
event.setBuild(false);
event.setCancelled(true);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void blockBuild(BlockBreakEvent event) public void build(BlockBreakEvent event) { build(event.getPlayer(), event.getBlock(), event); }
{
boolean verboose = ! isFake(event);
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), verboose)) return;
event.setCancelled(true);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void blockBuild(BlockDamageEvent event) public void build(BlockDamageEvent event) { build(event.getPlayer(), event.getBlock(), event); }
{
if ( ! event.getInstaBreak()) return;
boolean verboose = ! isFake(event);
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), verboose)) return;
event.setCancelled(true);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void blockBuild(SignChangeEvent event) public void build(SignChangeEvent event) { build(event.getPlayer(), event.getBlock(), event); }
{
boolean verboose = ! isFake(event);
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), verboose)) return;
event.setCancelled(true);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void blockBuild(BlockPistonExtendEvent event) public void build(HangingPlaceEvent event) { build(event.getPlayer(), event.getBlock(), event); }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void build(HangingBreakByEntityEvent event) { build(event.getRemover(), event.getEntity().getLocation().getBlock(), event); }
// -------------------------------------------- //
// USE > ITEM
// -------------------------------------------- //
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void useBlockItem(PlayerInteractEvent event)
{
// If the player right clicks (or is physical with) a block ...
if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.PHYSICAL) return;
Block block = event.getClickedBlock();
Player player = event.getPlayer();
if (block == null) return;
// ... and we are either allowed to use this block ...
Boolean ret = useBlock(player, block, true, event);
if (Boolean.TRUE.equals(ret)) return;
// ... or are allowed to right click with the item, this event is safe to perform.
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
useItem(player, block, event.getMaterial(), event);
}
// For some reason onPlayerInteract() sometimes misses bucket events depending on distance
// (something like 2-3 blocks away isn't detected), but these separate bucket events below always fire without fail
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void useItem(PlayerBucketEmptyEvent event) { useItem(event.getPlayer(), event.getBlockClicked(), event.getBucket(), event); }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void useItem(PlayerBucketFillEvent event) { useItem(event.getPlayer(), event.getBlockClicked(), event.getBucket(), event); }
// -------------------------------------------- //
// USE > ENTITY
// -------------------------------------------- //
// This event will not fire for Minecraft 1.8 armor stands.
// Armor stands are handled in EngineSpigot instead.
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void useEntity(PlayerInteractEntityEvent event)
{
// Ignore Off Hand
if (isOffHand(event)) return;
useEntity(event.getPlayer(), event.getRightClicked(), true, event);
}
// -------------------------------------------- //
// BUILD > ENTITY
// -------------------------------------------- //
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void buildEntity(EntityDamageByEntityEvent event)
{
// If a player ...
Entity damager = MUtil.getLiableDamager(event);
if (MUtil.isntPlayer(damager)) return;
Player player = (Player)damager;
// ... damages an entity which is edited on damage ...
Entity entity = event.getEntity();
if (entity == null || !EnumerationUtil.isEntityTypeEditOnDamage(entity.getType())) return;
// ... and the player can't build there, cancel the event
build(player, entity.getLocation().getBlock(), event);
}
// -------------------------------------------- //
// BUILD > PISTON
// -------------------------------------------- //
/*
* NOTE: These piston listeners are only called on 1.7 servers.
*
* Originally each affected block in the territory was tested, but since we found that pistons can only push
* up to 12 blocks and the width of any territory is 16 blocks, it should be safe (and much more lightweight) to test
* only the final target block as done below.
*/
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void buildPiston(BlockPistonExtendEvent event)
{ {
// Is using Spigot or is checking deactivated by MConf? // Is using Spigot or is checking deactivated by MConf?
if (IntegrationSpigot.get().isIntegrationActive() || ! MConf.get().handlePistonProtectionThroughDenyBuild) return; if (IntegrationSpigot.get().isIntegrationActive() || !MConf.get().handlePistonProtectionThroughDenyBuild) return;
Block block = event.getBlock();
// Targets end-of-the-line empty (air) block which is being pushed into, including if piston itself would extend into air // Targets end-of-the-line empty (air) block which is being pushed into, including if piston itself would extend into air
Block block = event.getBlock();
Block targetBlock = block.getRelative(event.getDirection(), event.getLength() + 1); Block targetBlock = block.getRelative(event.getDirection(), event.getLength() + 1);
// Factions involved // Factions involved
@ -145,22 +236,15 @@ public class EnginePermBuild extends Engine
// Members of a faction might not have build rights in their own territory, but pistons should still work regardless // Members of a faction might not have build rights in their own territory, but pistons should still work regardless
if (targetFaction == pistonFaction) return; if (targetFaction == pistonFaction) return;
// if potentially pushing into air/water/lava in another territory, we need to check it out // If potentially pushing into air/water/lava in another territory, we need to check it out
if ((targetBlock.isEmpty() || targetBlock.isLiquid()) && ! MPerm.getPermBuild().has(pistonFaction, targetFaction)) if (!targetBlock.isEmpty() && !targetBlock.isLiquid()) return;
{ if (MPerm.getPermBuild().has(pistonFaction, targetFaction)) return;
event.setCancelled(true); event.setCancelled(true);
} }
/*
* note that I originally was testing the territory of each affected block, but since I found that pistons can only push
* up to 12 blocks and the width of any territory is 16 blocks, it should be safe (and much more lightweight) to test
* only the final target block as done above
*/
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void blockBuild(BlockPistonRetractEvent event) public void buildPiston(BlockPistonRetractEvent event)
{ {
// Is using Spigot or is checking deactivated by MConf? // Is using Spigot or is checking deactivated by MConf?
if (IntegrationSpigot.get().isIntegrationActive() || ! MConf.get().handlePistonProtectionThroughDenyBuild) return; if (IntegrationSpigot.get().isIntegrationActive() || ! MConf.get().handlePistonProtectionThroughDenyBuild) return;
@ -180,269 +264,83 @@ public class EnginePermBuild extends Engine
// Members of a faction might not have build rights in their own territory, but pistons should still work regardless // Members of a faction might not have build rights in their own territory, but pistons should still work regardless
if (targetFaction == pistonFaction) return; if (targetFaction == pistonFaction) return;
if (MPerm.getPermBuild().has(pistonFaction, targetFaction)) return; if (MPerm.getPermBuild().has(pistonFaction, targetFaction)) return;
event.setCancelled(true); event.setCancelled(true);
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) // -------------------------------------------- //
public void blockBuild(HangingPlaceEvent event) // BUILD > FIRE
{ // -------------------------------------------- //
boolean verboose = ! isFake(event);
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getEntity().getLocation()), verboose)) return;
event.setCancelled(true);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void blockBuild(HangingBreakEvent event)
{
if (! (event instanceof HangingBreakByEntityEvent)) return;
HangingBreakByEntityEvent entityEvent = (HangingBreakByEntityEvent)event;
Entity breaker = entityEvent.getRemover();
if (MUtil.isntPlayer(breaker)) return;
boolean verboose = ! isFake(event);
if ( ! canPlayerBuildAt(breaker, PS.valueOf(event.getEntity().getLocation()), verboose))
{
event.setCancelled(true);
}
}
// Check for punching out fires where players should not be able to
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.NORMAL) @EventHandler(priority = EventPriority.NORMAL)
public void blockBuild(PlayerInteractEvent event) public void buildFire(PlayerInteractEvent event)
{ {
// ... if it is a left click on block ... // If it is a left click on block and the clicked block is not null...
if (event.getAction() != Action.LEFT_CLICK_BLOCK) return; if (event.getAction() != Action.LEFT_CLICK_BLOCK || event.getClickedBlock() == null) return;
// .. and the clicked block is not null ...
if (event.getClickedBlock() == null) return;
// ... and the potential block is not null either ...
Block potentialBlock = event.getClickedBlock().getRelative(BlockFace.UP, 1); Block potentialBlock = event.getClickedBlock().getRelative(BlockFace.UP, 1);
// .. and the potential block is not null ...
if (potentialBlock == null) return; if (potentialBlock == null) return;
Material blockType = potentialBlock.getType();
// ... and we're only going to check for fire ... (checking everything else would be bad performance wise) // ... and we're only going to check for fire ... (checking everything else would be bad performance wise)
if (potentialBlock.getType() != Material.FIRE) return; if (blockType != Material.FIRE) return;
// ... check if they can build ... // ... check if they can't build, cancel the event ...
if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(potentialBlock), true)) return; if (!Boolean.FALSE.equals(build(event.getPlayer(), potentialBlock, event))) return;
// ... nope, cancel it // ... and compensate for client side prediction
event.setCancelled(true); event.getPlayer().sendBlockChange(potentialBlock.getLocation(), blockType, potentialBlock.getState().getRawData());
// .. and compensate for client side prediction
event.getPlayer().sendBlockChange(potentialBlock.getLocation(), potentialBlock.getType(), potentialBlock.getState().getRawData());
} }
// -------------------------------------------- //
// BUILD > MOVE
// -------------------------------------------- //
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void blockLiquidFlow(BlockFromToEvent event) public void buildMove(BlockFromToEvent event)
{ {
if ( ! MConf.get().protectionLiquidFlowEnabled) return; if ( ! MConf.get().protectionLiquidFlowEnabled) return;
// Prepare fields // Prepare fields
Block fromBlock = event.getBlock(); Block fromBlock = event.getBlock();
int fromChunkX = fromBlock.getX() >> 4; int chunkFromX = fromBlock.getX() >> 4;
int fromChunkZ = fromBlock.getZ() >> 4; int chunkFromZ = fromBlock.getZ() >> 4;
BlockFace blockFace = event.getFace(); BlockFace face = event.getFace();
int toChunkX = (fromBlock.getX() + blockFace.getModX()) >> 4; int chunkToX = (fromBlock.getX() + face.getModX()) >> 4;
int toChunkZ = (fromBlock.getZ() + blockFace.getModZ()) >> 4; int chunkToZ = (fromBlock.getZ() + face.getModZ()) >> 4;
// If a liquid (or dragon egg) moves from one chunk to another ... // If a liquid (or dragon egg) moves from one chunk to another ...
if (toChunkX == fromChunkX && toChunkZ == fromChunkZ) return; if (chunkToX == chunkFromX && chunkToZ == chunkFromZ) return;
// ... get the correct board for this block ...
Board board = BoardColl.get().getFixed(fromBlock.getWorld().getName().toLowerCase(), false); Board board = BoardColl.get().getFixed(fromBlock.getWorld().getName().toLowerCase(), false);
if (board == null) return; if (board == null) return;
// ... get the access map ...
Map<PS, TerritoryAccess> map = board.getMapRaw(); Map<PS, TerritoryAccess> map = board.getMapRaw();
if (map.isEmpty()) return; if (map.isEmpty()) return;
PS fromPs = PS.valueOf(fromChunkX, fromChunkZ); // ... get the faction ids from and to ...
PS toPs = PS.valueOf(toChunkX, toChunkZ); PS fromPs = PS.valueOf(chunkFromX, chunkFromZ);
TerritoryAccess fromTerritoryAccess = map.get(fromPs); PS toPs = PS.valueOf(chunkToX, chunkToZ);
TerritoryAccess toTerritoryAccess = map.get(toPs); TerritoryAccess fromTa = map.get(fromPs);
String fromFactionId = fromTerritoryAccess != null ? fromTerritoryAccess.getHostFactionId() : Factions.ID_NONE; TerritoryAccess toTa = map.get(toPs);
String toFactionId = toTerritoryAccess != null ? toTerritoryAccess.getHostFactionId() : Factions.ID_NONE; String fromId = fromTa != null ? fromTa.getHostFactionId() : Factions.ID_NONE;
String toId = toTa != null ? toTa.getHostFactionId() : Factions.ID_NONE;
// ... and the chunks belong to different factions ... // ... and the chunks belong to different factions ...
if (toFactionId.equals(fromFactionId)) return; if (toId.equals(fromId)) return;
Faction fromFaction = FactionColl.get().getFixed(fromFactionId);
if (fromFaction == null) fromFaction = FactionColl.get().getNone();
Faction toFaction = FactionColl.get().getFixed(toFactionId);
if (toFaction == null) toFaction = FactionColl.get().getNone();
if (toFaction == fromFaction) return;
// ... and the faction "from" can not build at "to" ... // ... and the faction "from" can not build at "to" ...
if (MPerm.getPermBuild().has(fromFaction, toFaction)) return; Faction fromFac = FactionColl.get().getFixed(fromId);
Faction toFac = FactionColl.get().getFixed(toId);
// ... cancel! if (MPerm.getPermBuild().has(fromFac, toFac)) return;
event.setCancelled(true);
}
// -------------------------------------------- //
// ASSORTED BUILD AND INTERACT
// -------------------------------------------- //
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerDamageEntity(EntityDamageByEntityEvent event)
{
// If a player ...
Entity edamager = MUtil.getLiableDamager(event);
if (MUtil.isntPlayer(edamager)) return;
Player player = (Player)edamager;
// ... damages an entity which is edited on damage ...
Entity edamagee = event.getEntity();
if (edamagee == null) return;
if ( ! EnumerationUtil.isEntityTypeEditOnDamage(edamagee.getType())) return;
// ... and the player can't build there ...
if (canPlayerBuildAt(player, PS.valueOf(edamagee.getLocation()), true)) return;
// ... then cancel the event.
event.setCancelled(true);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerInteract(PlayerInteractEvent event)
{
// only need to check right-clicks and physical as of MC 1.4+; good performance boost
if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.PHYSICAL) return;
Block block = event.getClickedBlock();
Player player = event.getPlayer();
if (block == null) return; // clicked in air, apparently
if ( ! canPlayerUseBlock(player, block, true))
{
event.setCancelled(true);
return;
}
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; // only interested on right-clicks for below
if ( ! playerCanUseItemHere(player, PS.valueOf(block), event.getMaterial(), true))
{
event.setCancelled(true);
return;
}
}
public static boolean playerCanUseItemHere(Player player, PS ps, Material material, boolean verboose)
{
if (MUtil.isntPlayer(player)) return true;
if ( ! EnumerationUtil.isMaterialEditTool(material)) return true;
String name = player.getName();
if (MConf.get().playersWhoBypassAllProtection.contains(name)) return true;
MPlayer mplayer = MPlayer.get(player);
if (mplayer.isOverriding()) return true;
return MPerm.getPermBuild().has(mplayer, ps, verboose);
}
public static boolean canPlayerUseBlock(Player player, Block block, boolean verboose)
{
if (MUtil.isntPlayer(player)) return true;
String name = player.getName();
if (MConf.get().playersWhoBypassAllProtection.contains(name)) return true;
MPlayer me = MPlayer.get(player);
if (me.isOverriding()) return true;
PS ps = PS.valueOf(block);
Material material = block.getType();
if (EnumerationUtil.isMaterialEditOnInteract(material) && ! MPerm.getPermBuild().has(me, ps, verboose)) return false;
if (EnumerationUtil.isMaterialContainer(material) && ! MPerm.getPermContainer().has(me, ps, verboose)) return false;
if (EnumerationUtil.isMaterialDoor(material) && ! MPerm.getPermDoor().has(me, ps, verboose)) return false;
if (material == Material.STONE_BUTTON && ! MPerm.getPermButton().has(me, ps, verboose)) return false;
if (material == Material.LEVER && ! MPerm.getPermLever().has(me, ps, verboose)) return false;
return true;
}
// This event will not fire for Minecraft 1.8 armor stands.
// Armor stands are handled in EngineSpigot instead.
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerInteractEntity(PlayerInteractEntityEvent event)
{
// Ignore Off Hand
if (isOffHand(event)) return;
// Gather Info
final Player player = event.getPlayer();
final Entity entity = event.getRightClicked();
final boolean verboose = true;
// If we can't use ...
if (canPlayerUseEntity(player, entity, verboose)) return;
// ... block use.
event.setCancelled(true);
}
public static boolean canPlayerUseEntity(Player player, Entity entity, boolean verboose)
{
// If a player ...
if (MUtil.isntPlayer(player)) return true;
// ... interacts with an entity ...
if (entity == null) return true;
EntityType type = entity.getType();
PS ps = PS.valueOf(entity.getLocation());
// ... and the player does not bypass all protections ...
String name = player.getName();
if (MConf.get().playersWhoBypassAllProtection.contains(name)) return true;
// ... and the player is not using admin mode ...
MPlayer me = MPlayer.get(player);
if (me.isOverriding()) return true;
// ... check container entity rights ...
if (EnumerationUtil.isEntityTypeContainer(type) && ! MPerm.getPermContainer().has(me, ps, verboose)) return false;
// ... check build entity rights ...
if (EnumerationUtil.isEntityTypeEditOnInteract(type) && ! MPerm.getPermBuild().has(me, ps, verboose)) return false;
// ... otherwise we may use the entity.
return true;
}
// For some reason onPlayerInteract() sometimes misses bucket events depending on distance (something like 2-3 blocks away isn't detected),
// but these separate bucket events below always fire without fail
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event)
{
Block block = event.getBlockClicked();
Player player = event.getPlayer();
if (playerCanUseItemHere(player, PS.valueOf(block), event.getBucket(), true)) return;
event.setCancelled(true);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerBucketFill(PlayerBucketFillEvent event)
{
Block block = event.getBlockClicked();
Player player = event.getPlayer();
if (playerCanUseItemHere(player, PS.valueOf(block), event.getBucket(), true)) return;
// ... cancel the event!
event.setCancelled(true); event.setCancelled(true);
} }

View File

@ -0,0 +1,60 @@
package com.massivecraft.factions.engine;
import com.massivecraft.factions.entity.MPerm;
import com.massivecraft.factions.util.EnumerationUtil;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
public enum ProtectCase
{
// -------------------------------------------- //
// ENUM
// -------------------------------------------- //
BUILD,
USE_BLOCK,
USE_ITEM,
USE_ENTITY,
// END OF LIST
;
// -------------------------------------------- //
// PERM
// -------------------------------------------- //
public MPerm getPerm(Object object)
{
switch (this)
{
case BUILD:
return MPerm.getPermBuild();
case USE_ITEM:
if (!(object instanceof Material)) return null;
if (!EnumerationUtil.isMaterialEditTool((Material) object)) return null;
return MPerm.getPermBuild();
case USE_ENTITY:
if (!(object instanceof Entity)) return null;
Entity entity = (Entity) object;
EntityType type = entity.getType();
if (EnumerationUtil.isEntityTypeContainer(type)) return MPerm.getPermContainer();
if (EnumerationUtil.isEntityTypeEditOnInteract(type)) return MPerm.getPermBuild();
case USE_BLOCK:
if (!(object instanceof Material)) return null;
Material material = (Material) object;
if (EnumerationUtil.isMaterialEditOnInteract(material)) return MPerm.getPermBuild();
if (EnumerationUtil.isMaterialContainer(material)) return MPerm.getPermContainer();
if (EnumerationUtil.isMaterialDoor(material)) return MPerm.getPermDoor();
if (material == Material.STONE_BUTTON) return MPerm.getPermButton();
if (material == Material.LEVER) return MPerm.getPermLever();
default:
return null;
}
}
}

View File

@ -53,11 +53,8 @@ public class EngineSpigot extends Engine
// Only care for armor stands. // Only care for armor stands.
if (entity.getType() != EntityType.ARMOR_STAND) return; if (entity.getType() != EntityType.ARMOR_STAND) return;
// If we can't use ... // If we can't use, block it
if (EnginePermBuild.canPlayerUseEntity(player, entity, verboose)) return; EnginePermBuild.useEntity(player, entity, verboose, event);
// ... block use.
event.setCancelled(true);
} }
/* /*