From edfabb7718f64683bd354e439e97a7ef421906c3 Mon Sep 17 00:00:00 2001 From: ulumulu1510 Date: Mon, 3 Apr 2017 12:33:13 +0200 Subject: [PATCH] Refactor EnginePermBuild to more suitable structure. --- .../factions/engine/EngineMain.java | 3 +- .../factions/engine/EnginePermBuild.java | 598 ++++++++---------- .../factions/engine/ProtectCase.java | 60 ++ .../integration/lwc/FactionsLwcModule.java | 2 +- .../integration/spigot/EngineSpigot.java | 7 +- 5 files changed, 313 insertions(+), 357 deletions(-) create mode 100644 src/com/massivecraft/factions/engine/ProtectCase.java diff --git a/src/com/massivecraft/factions/engine/EngineMain.java b/src/com/massivecraft/factions/engine/EngineMain.java index b234ae92..77895c22 100644 --- a/src/com/massivecraft/factions/engine/EngineMain.java +++ b/src/com/massivecraft/factions/engine/EngineMain.java @@ -10,7 +10,8 @@ public class EngineMain */ 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; } } diff --git a/src/com/massivecraft/factions/engine/EnginePermBuild.java b/src/com/massivecraft/factions/engine/EnginePermBuild.java index d41d036a..344fa170 100644 --- a/src/com/massivecraft/factions/engine/EnginePermBuild.java +++ b/src/com/massivecraft/factions/engine/EnginePermBuild.java @@ -18,8 +18,9 @@ import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; 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.entity.EntityDamageByEntityEvent; import org.bukkit.event.hanging.HangingBreakByEntityEvent; -import org.bukkit.event.hanging.HangingBreakEvent; import org.bukkit.event.hanging.HangingPlaceEvent; import org.bukkit.event.player.PlayerBucketEmptyEvent; import org.bukkit.event.player.PlayerBucketFillEvent; @@ -51,399 +51,297 @@ public class EnginePermBuild extends Engine 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("It is painful to build in the territory of %s.", 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) { MPlayer mplayer = MPlayer.get(senderObject); if (mplayer == null) return false; - - String name = mplayer.getName(); - if (MConf.get().playersWhoBypassAllProtection.contains(name)) return true; - - 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("It is painful to build in the territory of %s.", hostFaction.describeTo(mplayer)); - Player player = mplayer.getPlayer(); - if (player != null) - { - player.damage(MConf.get().actionDeniedPainAmount); - } - } - return true; - } - - return MPerm.getPermBuild().has(mplayer, ps, verboose); + + Boolean ret = isProtected(ProtectCase.BUILD, verboose, mplayer, ps, null); + return !Boolean.TRUE.equals(ret); } - + + // -------------------------------------------- // + // BUILD > BLOCK + // -------------------------------------------- // + @EventHandler(priority = EventPriority.NORMAL) - public void blockBuild(BlockPlaceEvent 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); - } + public void build(BlockPlaceEvent event) { build(event.getPlayer(), event.getBlock(), event); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void blockBuild(BlockBreakEvent event) - { - boolean verboose = ! isFake(event); - - if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), verboose)) return; - - event.setCancelled(true); - } + public void build(BlockBreakEvent event) { build(event.getPlayer(), event.getBlock(), event); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void blockBuild(BlockDamageEvent event) - { - if ( ! event.getInstaBreak()) return; - - boolean verboose = ! isFake(event); - - if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), verboose)) return; - - event.setCancelled(true); - } + public void build(BlockDamageEvent event) { build(event.getPlayer(), event.getBlock(), event); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void blockBuild(SignChangeEvent event) - { - boolean verboose = ! isFake(event); - - if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), verboose)) return; - - event.setCancelled(true); - } - + public void build(SignChangeEvent event) { build(event.getPlayer(), event.getBlock(), event); } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void blockBuild(BlockPistonExtendEvent event) - { - // Is using Spigot or is checking deactivated by MConf? - 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 - Block targetBlock = block.getRelative(event.getDirection(), event.getLength() + 1); - - // Factions involved - Faction pistonFaction = BoardColl.get().getFactionAt(PS.valueOf(block)); - Faction targetFaction = BoardColl.get().getFactionAt(PS.valueOf(targetBlock)); - - // Members of a faction might not have build rights in their own territory, but pistons should still work regardless - if (targetFaction == pistonFaction) return; - - // 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)) - { - 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 - */ - - } - + public void build(HangingPlaceEvent event) { build(event.getPlayer(), event.getBlock(), event); } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void blockBuild(BlockPistonRetractEvent event) - { - // Is using Spigot or is checking deactivated by MConf? - if (IntegrationSpigot.get().isIntegrationActive() || ! MConf.get().handlePistonProtectionThroughDenyBuild) return; - - // If not a sticky piston, retraction should be fine - if ( ! event.isSticky()) return; - - Block retractBlock = event.getRetractLocation().getBlock(); - PS retractPs = PS.valueOf(retractBlock); - - // if potentially retracted block is just air/water/lava, no worries - if (retractBlock.isEmpty() || retractBlock.isLiquid()) return; - - // Factions involved - Faction pistonFaction = BoardColl.get().getFactionAt(PS.valueOf(event.getBlock())); - Faction targetFaction = BoardColl.get().getFactionAt(retractPs); - - // Members of a faction might not have build rights in their own territory, but pistons should still work regardless - if (targetFaction == pistonFaction) return; - - if (MPerm.getPermBuild().has(pistonFaction, targetFaction)) return; - - event.setCancelled(true); - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void blockBuild(HangingPlaceEvent event) - { - 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") - @EventHandler(priority = EventPriority.NORMAL) - public void blockBuild(PlayerInteractEvent event) - { - // ... if it is a left click on block ... - if (event.getAction() != Action.LEFT_CLICK_BLOCK) return; - - // .. and the clicked block is not null ... - if (event.getClickedBlock() == null) return; - - Block potentialBlock = event.getClickedBlock().getRelative(BlockFace.UP, 1); - - // .. and the potential block is not null ... - if (potentialBlock == null) return; - - // ... and we're only going to check for fire ... (checking everything else would be bad performance wise) - if (potentialBlock.getType() != Material.FIRE) return; - - // ... check if they can build ... - if (canPlayerBuildAt(event.getPlayer(), PS.valueOf(potentialBlock), true)) return; - - // ... nope, cancel it - event.setCancelled(true); - - // .. and compensate for client side prediction - event.getPlayer().sendBlockChange(potentialBlock.getLocation(), potentialBlock.getType(), potentialBlock.getState().getRawData()); - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void blockLiquidFlow(BlockFromToEvent event) - { - if ( ! MConf.get().protectionLiquidFlowEnabled) return; - - // Prepare fields - Block fromBlock = event.getBlock(); - int fromChunkX = fromBlock.getX() >> 4; - int fromChunkZ = fromBlock.getZ() >> 4; - BlockFace blockFace = event.getFace(); - int toChunkX = (fromBlock.getX() + blockFace.getModX()) >> 4; - int toChunkZ = (fromBlock.getZ() + blockFace.getModZ()) >> 4; - - // If a liquid (or dragon egg) moves from one chunk to another ... - if (toChunkX == fromChunkX && toChunkZ == fromChunkZ) return; - - Board board = BoardColl.get().getFixed(fromBlock.getWorld().getName().toLowerCase(), false); - if (board == null) return; - Map map = board.getMapRaw(); - if (map.isEmpty()) return; - - PS fromPs = PS.valueOf(fromChunkX, fromChunkZ); - PS toPs = PS.valueOf(toChunkX, toChunkZ); - TerritoryAccess fromTerritoryAccess = map.get(fromPs); - TerritoryAccess toTerritoryAccess = map.get(toPs); - String fromFactionId = fromTerritoryAccess != null ? fromTerritoryAccess.getHostFactionId() : Factions.ID_NONE; - String toFactionId = toTerritoryAccess != null ? toTerritoryAccess.getHostFactionId() : Factions.ID_NONE; - - // ... and the chunks belong to different factions ... - if (toFactionId.equals(fromFactionId)) 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" ... - if (MPerm.getPermBuild().has(fromFaction, toFaction)) return; - - // ... cancel! - event.setCancelled(true); - } + public void build(HangingBreakByEntityEvent event) { build(event.getRemover(), event.getEntity().getLocation().getBlock(), event); } // -------------------------------------------- // - // ASSORTED BUILD AND INTERACT + // USE > ITEM // -------------------------------------------- // @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerDamageEntity(EntityDamageByEntityEvent event) + public void useBlockItem(PlayerInteractEvent 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 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; - 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; + // ... and we are either allowed to use this block ... + Boolean ret = useBlock(player, block, true, event); + if (Boolean.TRUE.equals(ret)) return; - 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; + // ... 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 onPlayerInteractEntity(PlayerInteractEntityEvent event) + public void useEntity(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); + useEntity(event.getPlayer(), event.getRightClicked(), true, event); } - - public static boolean canPlayerUseEntity(Player player, Entity entity, boolean verboose) + + // -------------------------------------------- // + // BUILD > ENTITY + // -------------------------------------------- // + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void buildEntity(EntityDamageByEntityEvent event) { // 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; + 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); } - - // 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 + + // -------------------------------------------- // + // 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 onPlayerBucketEmpty(PlayerBucketEmptyEvent event) + public void buildPiston(BlockPistonExtendEvent event) { - Block block = event.getBlockClicked(); - Player player = event.getPlayer(); - - if (playerCanUseItemHere(player, PS.valueOf(block), event.getBucket(), true)) return; - + // Is using Spigot or is checking deactivated by MConf? + if (IntegrationSpigot.get().isIntegrationActive() || !MConf.get().handlePistonProtectionThroughDenyBuild) return; + + // 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); + + // Factions involved + Faction pistonFaction = BoardColl.get().getFactionAt(PS.valueOf(block)); + Faction targetFaction = BoardColl.get().getFactionAt(PS.valueOf(targetBlock)); + + // Members of a faction might not have build rights in their own territory, but pistons should still work regardless + if (targetFaction == pistonFaction) return; + + // If potentially pushing into air/water/lava in another territory, we need to check it out + if (!targetBlock.isEmpty() && !targetBlock.isLiquid()) return; + if (MPerm.getPermBuild().has(pistonFaction, targetFaction)) return; + event.setCancelled(true); } - + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - public void onPlayerBucketFill(PlayerBucketFillEvent event) + public void buildPiston(BlockPistonRetractEvent event) { - Block block = event.getBlockClicked(); - Player player = event.getPlayer(); - - if (playerCanUseItemHere(player, PS.valueOf(block), event.getBucket(), true)) return; - + // Is using Spigot or is checking deactivated by MConf? + if (IntegrationSpigot.get().isIntegrationActive() || ! MConf.get().handlePistonProtectionThroughDenyBuild) return; + + // If not a sticky piston, retraction should be fine + if ( ! event.isSticky()) return; + + Block retractBlock = event.getRetractLocation().getBlock(); + PS retractPs = PS.valueOf(retractBlock); + + // if potentially retracted block is just air/water/lava, no worries + if (retractBlock.isEmpty() || retractBlock.isLiquid()) return; + + // Factions involved + Faction pistonFaction = BoardColl.get().getFactionAt(PS.valueOf(event.getBlock())); + Faction targetFaction = BoardColl.get().getFactionAt(retractPs); + + // Members of a faction might not have build rights in their own territory, but pistons should still work regardless + if (targetFaction == pistonFaction) return; + if (MPerm.getPermBuild().has(pistonFaction, targetFaction)) return; + event.setCancelled(true); } - + + // -------------------------------------------- // + // BUILD > FIRE + // -------------------------------------------- // + + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.NORMAL) + public void buildFire(PlayerInteractEvent event) + { + // If it is a left click on block and the clicked block is not null... + if (event.getAction() != Action.LEFT_CLICK_BLOCK || event.getClickedBlock() == null) return; + + // ... and the potential block is not null either ... + Block potentialBlock = event.getClickedBlock().getRelative(BlockFace.UP, 1); + 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) + if (blockType != Material.FIRE) return; + + // ... check if they can't build, cancel the event ... + if (!Boolean.FALSE.equals(build(event.getPlayer(), potentialBlock, event))) return; + + // ... and compensate for client side prediction + event.getPlayer().sendBlockChange(potentialBlock.getLocation(), blockType, potentialBlock.getState().getRawData()); + } + + // -------------------------------------------- // + // BUILD > MOVE + // -------------------------------------------- // + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void buildMove(BlockFromToEvent event) + { + if ( ! MConf.get().protectionLiquidFlowEnabled) return; + + // Prepare fields + Block fromBlock = event.getBlock(); + int chunkFromX = fromBlock.getX() >> 4; + int chunkFromZ = fromBlock.getZ() >> 4; + BlockFace face = event.getFace(); + int chunkToX = (fromBlock.getX() + face.getModX()) >> 4; + int chunkToZ = (fromBlock.getZ() + face.getModZ()) >> 4; + + // If a liquid (or dragon egg) moves from one chunk to another ... + if (chunkToX == chunkFromX && chunkToZ == chunkFromZ) return; + + // ... get the correct board for this block ... + Board board = BoardColl.get().getFixed(fromBlock.getWorld().getName().toLowerCase(), false); + if (board == null) return; + + // ... get the access map ... + Map map = board.getMapRaw(); + if (map.isEmpty()) return; + + // ... get the faction ids from and to ... + PS fromPs = PS.valueOf(chunkFromX, chunkFromZ); + PS toPs = PS.valueOf(chunkToX, chunkToZ); + TerritoryAccess fromTa = map.get(fromPs); + TerritoryAccess toTa = map.get(toPs); + 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 ... + if (toId.equals(fromId)) return; + + // ... and the faction "from" can not build at "to" ... + Faction fromFac = FactionColl.get().getFixed(fromId); + Faction toFac = FactionColl.get().getFixed(toId); + if (MPerm.getPermBuild().has(fromFac, toFac)) return; + + // ... cancel the event! + event.setCancelled(true); + } + } diff --git a/src/com/massivecraft/factions/engine/ProtectCase.java b/src/com/massivecraft/factions/engine/ProtectCase.java new file mode 100644 index 00000000..5196e03f --- /dev/null +++ b/src/com/massivecraft/factions/engine/ProtectCase.java @@ -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; + } + } + +} diff --git a/src/com/massivecraft/factions/integration/lwc/FactionsLwcModule.java b/src/com/massivecraft/factions/integration/lwc/FactionsLwcModule.java index f4b9d7ca..f014c796 100644 --- a/src/com/massivecraft/factions/integration/lwc/FactionsLwcModule.java +++ b/src/com/massivecraft/factions/integration/lwc/FactionsLwcModule.java @@ -52,7 +52,7 @@ public class FactionsLwcModule extends JavaModule if ( ! MConf.get().lwcMustHaveBuildRightsToCreate) return; // ... and the player don't have build rights here ... - // NOTE: We verbosely check the build rights so that a proper info message is sent + // NOTE: We verbosely check the build rights so that a proper info message is sent if (EnginePermBuild.canPlayerBuildAt(event.getPlayer(), PS.valueOf(event.getBlock()), true)) return; // ... then cancel the event. diff --git a/src/com/massivecraft/factions/integration/spigot/EngineSpigot.java b/src/com/massivecraft/factions/integration/spigot/EngineSpigot.java index ae4bdc15..fffcaab5 100644 --- a/src/com/massivecraft/factions/integration/spigot/EngineSpigot.java +++ b/src/com/massivecraft/factions/integration/spigot/EngineSpigot.java @@ -53,11 +53,8 @@ public class EngineSpigot extends Engine // Only care for armor stands. if (entity.getType() != EntityType.ARMOR_STAND) return; - // If we can't use ... - if (EnginePermBuild.canPlayerUseEntity(player, entity, verboose)) return; - - // ... block use. - event.setCancelled(true); + // If we can't use, block it + EnginePermBuild.useEntity(player, entity, verboose, event); } /*