diff --git a/src/main/java/com/massivecraft/factions/Conf.java b/src/main/java/com/massivecraft/factions/Conf.java index 274095dd..3f6f2125 100644 --- a/src/main/java/com/massivecraft/factions/Conf.java +++ b/src/main/java/com/massivecraft/factions/Conf.java @@ -231,6 +231,12 @@ public class Conf { public static Set territoryBypassProtectedMaterials = EnumSet.noneOf(Material.class); // Dependency check public static boolean dependencyCheck = true; + + public static Set territoryCancelAndAllowItemUseMaterial = new HashSet<>(); + public static Set territoryDenySwitchMaterials = new HashSet<>(); + public static Set territoryBypasssProtectedMaterials = EnumSet.noneOf(Material.class); + public static boolean allowCreeperEggingChests = true; + // Economy settings public static boolean econEnabled = false; public static String econUniverseAccount = ""; @@ -343,6 +349,7 @@ public class Conf { // faction- public static int defaultMaxVaults = 0; public static boolean disableFlightOnFactionClaimChange = true; + public static boolean sendFactionChangeMessage = true; public static Backend backEnd = Backend.JSON; @@ -388,11 +395,108 @@ public class Conf { territoryEnemyDenyCommands.add("tpaccept"); territoryEnemyDenyCommands.add("tpa"); + territoryDenySwitchMaterials.add(XMaterial.ACACIA_FENCE_GATE.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.BIRCH_FENCE_GATE.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.DARK_OAK_FENCE_GATE.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.JUNGLE_FENCE_GATE.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.OAK_FENCE_GATE.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.SPRUCE_FENCE_GATE.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.ACACIA_DOOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.BIRCH_DOOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.DARK_OAK_DOOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.JUNGLE_DOOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.OAK_DOOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.SPRUCE_DOOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.DISPENSER.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.CHEST.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.TRAPPED_CHEST.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.ACACIA_BUTTON.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.BIRCH_BUTTON.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.DARK_OAK_BUTTON.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.JUNGLE_BUTTON.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.OAK_BUTTON.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.SPRUCE_BUTTON.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.DROPPER.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.HOPPER.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.ITEM_FRAME.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.ACACIA_TRAPDOOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.BIRCH_TRAPDOOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.DARK_OAK_TRAPDOOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.JUNGLE_TRAPDOOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.OAK_TRAPDOOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.SPRUCE_TRAPDOOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.LEVER.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.COMPARATOR.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.REPEATER.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.ACACIA_BUTTON.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.BIRCH_BUTTON.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.DARK_OAK_BUTTON.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.JUNGLE_BUTTON.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.OAK_BUTTON.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.SPRUCE_BUTTON.parseMaterial()); + + territoryDenySwitchMaterials.add(XMaterial.PURPLE_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.WHITE_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.MAGENTA_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.LIGHT_BLUE_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.CYAN_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.BLUE_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.BROWN_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.ORANGE_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.GREEN_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.RED_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.BLACK_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.GRAY_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.LIME_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.LIGHT_GRAY_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.PINK_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.YELLOW_SHULKER_BOX.parseMaterial()); + territoryDenySwitchMaterials.add(XMaterial.SHULKER_BOX.parseMaterial()); + + // 1.14 Barrel is a container. + territoryDenySwitchMaterials.add(XMaterial.BARREL.parseMaterial()); + + territoryCancelAndAllowItemUseMaterial.add(XMaterial.GOLDEN_APPLE.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.APPLE.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.ENCHANTED_GOLDEN_APPLE.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.COOKED_BEEF.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.COOKED_MUTTON.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.COOKED_CHICKEN.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.COOKED_COD.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.COOKED_PORKCHOP.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.COOKED_RABBIT.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.COOKED_SALMON.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.ENDER_PEARL.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.POTION.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.SPLASH_POTION.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.CREEPER_SPAWN_EGG.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.BOW.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.DIAMOND_HELMET.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.DIAMOND_CHESTPLATE.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.DIAMOND_LEGGINGS.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.DIAMOND_BOOTS.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.IRON_HELMET.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.IRON_CHESTPLATE.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.IRON_LEGGINGS.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.IRON_BOOTS.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.LEATHER_HELMET.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.LEATHER_CHESTPLATE.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.LEATHER_LEGGINGS.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.LEATHER_BOOTS.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.CHAINMAIL_HELMET.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.CHAINMAIL_CHESTPLATE.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.CHAINMAIL_LEGGINGS.parseMaterial()); + territoryCancelAndAllowItemUseMaterial.add(XMaterial.CHAINMAIL_BOOTS.parseMaterial()); + + /// TODO: Consider removing this in a future release, as permissions works just fine now territoryProtectedMaterials.add(Material.BEACON); // Config is not loading if value is empty ??? territoryBypassProtectedMaterials.add(Material.COOKIE); + territoryBypassProtectedMaterials.add(Material.CHEST); + territoryBypassProtectedMaterials.add(Material.TRAPPED_CHEST); + territoryDenyUsageMaterials.add(XMaterial.FIRE_CHARGE.parseMaterial()); territoryDenyUsageMaterials.add(Material.FLINT_AND_STEEL); diff --git a/src/main/java/com/massivecraft/factions/cmd/alts/CmdAlts.java b/src/main/java/com/massivecraft/factions/cmd/alts/CmdAlts.java index 1a2232b2..0400f038 100644 --- a/src/main/java/com/massivecraft/factions/cmd/alts/CmdAlts.java +++ b/src/main/java/com/massivecraft/factions/cmd/alts/CmdAlts.java @@ -12,6 +12,7 @@ public class CmdAlts extends FCommand { public CmdInviteAlt cmdInviteAlt = new CmdInviteAlt(); public CmdAltsList cmdAltsList = new CmdAltsList(); + public CmdKickAlt cmdKickAlt = new CmdKickAlt(); public CmdAlts() { @@ -22,6 +23,7 @@ public class CmdAlts extends FCommand { this.addSubCommand(this.cmdInviteAlt); this.addSubCommand(this.cmdAltsList); + this.addSubCommand(this.cmdKickAlt); this.requirements = new CommandRequirements.Builder(Permission.ALTS) .playerOnly() diff --git a/src/main/java/com/massivecraft/factions/cmd/alts/CmdKickAlt.java b/src/main/java/com/massivecraft/factions/cmd/alts/CmdKickAlt.java new file mode 100644 index 00000000..1007a42d --- /dev/null +++ b/src/main/java/com/massivecraft/factions/cmd/alts/CmdKickAlt.java @@ -0,0 +1,136 @@ +package com.massivecraft.factions.cmd.alts; + +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.FactionsPlugin; +import com.massivecraft.factions.cmd.CommandContext; +import com.massivecraft.factions.cmd.CommandRequirements; +import com.massivecraft.factions.cmd.FCommand; +import com.massivecraft.factions.event.FPlayerLeaveEvent; +import com.massivecraft.factions.struct.Permission; +import com.massivecraft.factions.struct.Role; +import com.massivecraft.factions.zcore.fperms.Access; +import com.massivecraft.factions.zcore.fperms.PermissableAction; +import com.massivecraft.factions.zcore.util.TL; +import org.bukkit.Bukkit; +import org.bukkit.command.ConsoleCommandSender; + +public class CmdKickAlt extends FCommand { + + public CmdKickAlt(){ + super(); + this.aliases.add("kick"); + this.requiredArgs.add("player name"); + + this.requirements = new CommandRequirements.Builder(Permission.KICK) + .playerOnly() + .memberOnly() + .withAction(PermissableAction.KICK) + .build(); + } + + @Override + public void perform(CommandContext context) { + if (!FactionsPlugin.getInstance().getConfig().getBoolean("f-alts.Enabled", false)) { + context.fPlayer.msg(TL.GENERIC_DISABLED); + return; + } + + FPlayer toKick = context.argIsSet(0) ? context.argAsBestFPlayerMatch(0) : null; + if (toKick == null) { + context.msg(TL.COMMAND_ALTKICK_NOTMEMBER); + return; + } + + if (context.fPlayer == toKick) { + context.msg(TL.COMMAND_KICK_SELF); + context.msg(TL.GENERIC_YOUMAYWANT.toString() + FactionsPlugin.instance.cmdBase.cmdLeave.getUsageTemplate(context)); + return; + } + + Faction toKickFaction = toKick.getFaction(); + + if (toKickFaction.isWilderness()) { + context.sender.sendMessage(TL.COMMAND_KICK_NONE.toString()); + return; + } + + // players with admin-level "disband" permission can bypass these + // requirements + if (!Permission.KICK_ANY.has(context.sender)) { + if (toKickFaction != context.faction) { + context.msg(TL.COMMAND_KICK_NOTMEMBER, toKick.describeTo(context.fPlayer, true), context.faction.describeTo(context.fPlayer)); + return; + } + + if (!toKick.isAlt()) { + context.msg(TL.COMMAND_ALTKICK_NOTALT); + return; + } + + if (!Conf.canLeaveWithNegativePower && toKick.getPower() < 0) { + context.msg(TL.COMMAND_KICK_NEGATIVEPOWER); + return; + } + } + + Access access = context.faction.getAccess(context.fPlayer, PermissableAction.KICK); + // This statement allows us to check if they've specifically denied it, + // or default to + // the old setting of allowing moderators to kick + if (access != Access.ALLOW && !context.assertMinRole(Role.MODERATOR)) { + context.msg(TL.GENERIC_NOPERMISSION, "kick"); + return; + } + + + // if economy is enabled, they're not on the bypass list, and this + // command has a cost set, make sure they can pay + if (!context.canAffordCommand(Conf.econCostKick, TL.COMMAND_KICK_TOKICK.toString())) { + return; + } + + // trigger the leave event (cancellable) [reason:kicked] + FPlayerLeaveEvent event = new FPlayerLeaveEvent(toKick, toKick.getFaction(), FPlayerLeaveEvent.PlayerLeaveReason.KICKED); + Bukkit.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + + + // then make 'em pay (if applicable) + if (!context.payForCommand(Conf.econCostKick, TL.COMMAND_KICK_TOKICK.toString(), TL.COMMAND_KICK_FORKICK.toString())) { + return; + } + + + toKickFaction.msg(TL.COMMAND_KICK_FACTION, context.fPlayer.describeTo(toKickFaction, true), toKick.describeTo(toKickFaction, true)); + + toKick.msg(TL.COMMAND_KICK_KICKED, context.fPlayer.describeTo(toKick, true), toKickFaction.describeTo(toKick)); + + if (toKickFaction != context.faction) { + context.msg(TL.COMMAND_KICK_KICKS, toKick.describeTo(context.fPlayer), toKickFaction.describeTo(context.fPlayer)); + } + + if (Conf.logFactionKick) { + FactionsPlugin.instance.log((context.sender instanceof ConsoleCommandSender ? "A console command" : context.fPlayer.getName()) + " kicked " + toKick.getName() + " from the faction: " + + toKickFaction.getTag()); + } + // SHOULD NOT BE POSSIBLE BUT KEPT INCASE + if (toKick.getRole() == Role.LEADER) { + toKickFaction.promoteNewLeader(); + } + + + toKickFaction.removeAltPlayer(toKick); + toKickFaction.deinvite(toKick); + toKick.resetFactionData(); + } + + @Override + public TL getUsageTranslation() { + return TL.COMMAND_ALTKICK_DESCRIPTION; + } + +} \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/integration/Worldguard.java b/src/main/java/com/massivecraft/factions/integration/Worldguard.java index 457f2a7d..eba5f402 100644 --- a/src/main/java/com/massivecraft/factions/integration/Worldguard.java +++ b/src/main/java/com/massivecraft/factions/integration/Worldguard.java @@ -3,137 +3,288 @@ package com.massivecraft.factions.integration; import com.massivecraft.factions.FLocation; import com.massivecraft.factions.FactionsPlugin; import com.sk89q.worldedit.BlockVector; -import com.sk89q.worldedit.Vector; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.domains.Association; import com.sk89q.worldguard.protection.ApplicableRegionSet; -import com.sk89q.worldguard.protection.flags.DefaultFlag; +import com.sk89q.worldguard.protection.association.Associables; +import com.sk89q.worldguard.protection.association.RegionAssociable; +import com.sk89q.worldguard.protection.flags.StateFlag; import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion; import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Map; - -import static com.sk89q.worldguard.bukkit.BukkitUtil.toVector; /* - * Worldguard Region Checking - * Author: Spathizilla + * WorldGuard Permission Checking. + * https://github.com/elBukkit/MagicPlugin/blob/master/Magic/src/main/java/com/elmakers/mine/bukkit/protection/WorldGuardAPI.java + * Original Authors: NathonWolf, killme + * Converted & Adapted: Savag3life */ public class Worldguard { - private static WorldGuardPlugin wg; - private static boolean enabled = false; + private Object worldGuard; + private WorldGuardPlugin worldGuardPlugin; + private Object regionContainer; + private Method regionContainerGetMethod; + private Method createQueryMethod; + private Method regionQueryTestStateMethod; + private Method locationAdaptMethod; + private Method worldAdaptMethod; + private Method regionManagerGetMethod; + private Constructor vectorConstructor; + private Method vectorConstructorAsAMethodBecauseWhyNot; + private StateFlag buildFlag; + private StateFlag breakFlag; + private boolean initialized = false; - public static void init(Plugin plugin) { - Plugin wgplug = plugin.getServer().getPluginManager().getPlugin("WorldGuard"); - if (wgplug == null || !(wgplug instanceof WorldGuardPlugin)) { - enabled = false; - wg = null; - FactionsPlugin.getInstance().log("Could not hook to WorldGuard. WorldGuard checks are disabled."); + private static Worldguard instance; + + public Worldguard() { + instance = this; + + Plugin p = Bukkit.getPluginManager().getPlugin("WorldGuard"); + + if (p == null) { + FactionsPlugin.instance.log("Could not find WorldGuard! Support will not be added."); + return; + } + if (p instanceof WorldGuardPlugin) { + worldGuardPlugin = (WorldGuardPlugin) p; + + try { + Class worldGuardClass = Class.forName("com.sk89q.worldguard.WorldGuard"); + Method getInstanceMethod = worldGuardClass.getMethod("getInstance"); + worldGuard = getInstanceMethod.invoke(null); + FactionsPlugin.instance.log("Found WorldGuard 7+"); + } catch (Exception ex) { FactionsPlugin.instance.log("Found WorldGuard <7"); } + } + } + + public boolean isEnabled() { + return worldGuardPlugin != null; + } + + public static Worldguard getInstance() { return instance; } + + protected RegionAssociable getAssociable(Player player) { + RegionAssociable associable; + if (player == null) { + associable = Associables.constant(Association.NON_MEMBER); } else { - wg = (WorldGuardPlugin) wgplug; - enabled = true; - FactionsPlugin.getInstance().log("Successfully hooked to WorldGuard."); + associable = worldGuardPlugin.wrapPlayer(player); + } + + return associable; + } + + /** + * Credits to the people listed above for using reflections to load WorldGuard 6.0 & 7.0 in 1 class! + */ + private void initialize() { + if (!initialized) { + initialized = true; + if (worldGuard != null) { + try { + Method getPlatFormMethod = worldGuard.getClass().getMethod("getPlatform"); + Object platform = getPlatFormMethod.invoke(worldGuard); + Method getRegionContainerMethod = platform.getClass().getMethod("getRegionContainer"); + regionContainer = getRegionContainerMethod.invoke(platform); + createQueryMethod = regionContainer.getClass().getMethod("createQuery"); + Class worldEditLocationClass = Class.forName("com.sk89q.worldedit.util.Location"); + Class worldEditWorldClass = Class.forName("com.sk89q.worldedit.world.World"); + Class worldEditAdapterClass = Class.forName("com.sk89q.worldedit.bukkit.BukkitAdapter"); + worldAdaptMethod = worldEditAdapterClass.getMethod("adapt", World.class); + locationAdaptMethod = worldEditAdapterClass.getMethod("adapt", Location.class); + regionContainerGetMethod = regionContainer.getClass().getMethod("get", worldEditWorldClass); + Class regionQueryClass = Class.forName("com.sk89q.worldguard.protection.regions.RegionQuery"); + regionQueryTestStateMethod = regionQueryClass.getMethod("testState", worldEditLocationClass, RegionAssociable.class, StateFlag[].class); + + Class flagsClass = Class.forName("com.sk89q.worldguard.protection.flags.Flags"); + + buildFlag = (StateFlag) flagsClass.getField("BUILD").get(null); + breakFlag = (StateFlag) flagsClass.getField("BREAK").get(null); + + } catch (Exception ex) { + FactionsPlugin.instance.log("We failed to load some part of World Guard. Support will be removed!"); + FactionsPlugin.instance.log("WorldGuard 7.0.0 support is currently in BETA. Please be careful!"); + regionContainer = null; + return; + } + } else { + regionContainer = worldGuardPlugin.getRegionContainer(); + try { + createQueryMethod = regionContainer.getClass().getMethod("createQuery"); + regionContainerGetMethod = regionContainer.getClass().getMethod("get", World.class); + Class regionQueryClass = Class.forName("com.sk89q.worldguard.bukkit.RegionQuery"); + regionQueryTestStateMethod = regionQueryClass.getMethod("testState", Location.class, RegionAssociable.class, StateFlag[].class); + + Class flagsClass = Class.forName("com.sk89q.worldguard.protection.flags.DefaultFlag"); + + buildFlag = (StateFlag) flagsClass.getField("BUILD").get(null); + breakFlag = (StateFlag) flagsClass.getField("BREAK").get(null); + + } catch (Exception ex) { + FactionsPlugin.instance.log("We failed to load some part of World Guard. Support will be removed!"); + FactionsPlugin.instance.log("WorldGuard 7.0.0 support is currently in BETA. Please be careful!"); + regionContainer = null; + return; + } + } + + try { + Class vectorClass = Class.forName("com.sk89q.worldedit.Vector"); + vectorConstructor = vectorClass.getConstructor(Double.TYPE, Double.TYPE, Double.TYPE); + regionManagerGetMethod = RegionManager.class.getMethod("getApplicableRegions", vectorClass); + } catch (Exception ex) { + try { + Class vectorClass = Class.forName("com.sk89q.worldedit.math.BlockVector3"); + vectorConstructorAsAMethodBecauseWhyNot = vectorClass.getMethod("at", Double.TYPE, Double.TYPE, Double.TYPE); + regionManagerGetMethod = RegionManager.class.getMethod("getApplicableRegions", vectorClass); + } catch (Exception sodonewiththis) { + FactionsPlugin.instance.log("We failed to load Vector Classes from WorldGuard! Support will be removed!"); + FactionsPlugin.instance.log("WorldGuard 7.0.0 support is currently in BETA. Please be careful!"); + regionContainer = null; + return; + } + } } } - public static boolean isEnabled() { - return enabled; - } - - // PVP Flag check - // Returns: - // True: PVP is allowed - // False: PVP is disallowed - @SuppressWarnings("deprecation") - public static boolean isPVP(Player player) { - if (!enabled) { - // No WG hooks so we'll always bypass this check. - return true; - } - - Location loc = player.getLocation(); - World world = loc.getWorld(); - Vector pt = toVector(loc); - - RegionManager regionManager = wg.getRegionManager(world); - ApplicableRegionSet set = regionManager.getApplicableRegions(pt); - return set.allows(DefaultFlag.PVP); - } - - // Check if player can build at location by worldguards rules. - // Returns: - // True: Player can build in the region. - // False: Player can not build in the region. - public static boolean playerCanBuild(Player player, Location loc) { - if (!enabled) { - // No WG hooks so we'll always bypass this check. - return false; - } - - World world = loc.getWorld(); - Vector pt = toVector(loc); - - return wg.getRegionManager(world).getApplicableRegions(pt).size() > 0 && wg.canBuild(player, loc); - } - - // Check for Regions in chunk the chunk - // Returns: - // True: Regions found within chunk - // False: No regions found within chunk - - public static boolean checkForRegionsInChunk(FLocation floc) { - Chunk chunk = floc.getWorld().getChunkAt((int) floc.getX(), (int) floc.getZ()); - - return checkForRegionsInChunk(chunk); - } - - public static boolean checkForRegionsInChunk(Location loc) { - Chunk chunk = loc.getWorld().getChunkAt(loc); - - return checkForRegionsInChunk(chunk); - } - - public static boolean checkForRegionsInChunk(Chunk chunk) { - if (!enabled) { - // No WG hooks so we'll always bypass this check. - return false; - } - - World world = chunk.getWorld(); - int minChunkX = chunk.getX() << 4; - int minChunkZ = chunk.getZ() << 4; - int maxChunkX = minChunkX + 15; - int maxChunkZ = minChunkZ + 15; - - int worldHeight = world.getMaxHeight(); // Allow for heights other than default - - BlockVector minChunk = new BlockVector(minChunkX, 0, minChunkZ); - BlockVector maxChunk = new BlockVector(maxChunkX, worldHeight, maxChunkZ); - - RegionManager regionManager = wg.getRegionManager(world); - ProtectedCuboidRegion region = new ProtectedCuboidRegion("wgfactionoverlapcheck", minChunk, maxChunk); - Map allregions = regionManager.getRegions(); - Collection allregionslist = new ArrayList<>(allregions.values()); - List overlaps; - boolean foundregions = false; - + private RegionManager getRegionManager(World world) { + initialize(); + if (regionContainer == null || regionContainerGetMethod == null) return null; + RegionManager regionManager = null; try { - overlaps = region.getIntersectingRegions(allregionslist); - foundregions = overlaps != null && !overlaps.isEmpty(); - } catch (Exception e) { - e.printStackTrace(); + if (worldAdaptMethod != null) { + Object worldEditWorld = worldAdaptMethod.invoke(null, world); + regionManager = (RegionManager)regionContainerGetMethod.invoke(regionContainer, worldEditWorld); + } else { + regionManager = (RegionManager)regionContainerGetMethod.invoke(regionContainer, world); + } + } catch (Exception ex) { + FactionsPlugin.instance.log("An error occurred looking up a WorldGuard RegionManager"); } + return regionManager; + } - return foundregions; + private ApplicableRegionSet getRegionSet(Location location) { + RegionManager regionManager = getRegionManager(location.getWorld()); + if (regionManager == null) return null; + try { + Object vector = vectorConstructorAsAMethodBecauseWhyNot == null + ? vectorConstructor.newInstance(location.getX(), location.getY(), location.getZ()) + : vectorConstructorAsAMethodBecauseWhyNot.invoke(null, location.getX(), location.getY(), location.getZ()); + return (ApplicableRegionSet)regionManagerGetMethod.invoke(regionManager, vector); + } catch (Exception ex) { + FactionsPlugin.instance.log("An error occurred looking up a WorldGuard ApplicableRegionSet"); + FactionsPlugin.instance.log("WorldGuard 7.0.0 support is currently in BETA. Please be careful!"); + } + return null; + } + + + /** + * Used to check WorldGuard to see if a Player has permission to place a block. + * @param player player in question. + * @param location Location of block placed. + * @return + */ + public boolean hasBuildPermission(Player player, Location location) { + initialize(); + if (createQueryMethod != null && regionContainer != null) { + try { + Object query = createQueryMethod.invoke(regionContainer); + if (locationAdaptMethod != null) { + Object loc = locationAdaptMethod.invoke(null, location); + return (boolean)regionQueryTestStateMethod.invoke(query, loc, getAssociable(player), new StateFlag[]{buildFlag}); + } else return (boolean)regionQueryTestStateMethod.invoke(query, location, getAssociable(player), new StateFlag[]{buildFlag}); + } catch (Exception ex) { + FactionsPlugin.instance.log("An error occurred querying WorldGuard! Report this issue to SF Developers!"); + FactionsPlugin.instance.log("WorldGuard 7.0.0 support is currently in BETA. Please be careful!"); + } + } + return true; + } + + /** + * Used to check WorldGuard to see if a player has permission to break a block. + * @param player player in question. + * @param location Location of block broken. + * @return + */ + public boolean hasBreakPermission(Player player, Location location) { + initialize(); + if (createQueryMethod != null && regionContainer != null) { + try { + Object query = createQueryMethod.invoke(regionContainer); + if (locationAdaptMethod != null) { + Object loc = locationAdaptMethod.invoke(null, location); + return (boolean) regionQueryTestStateMethod.invoke(query, loc, getAssociable(player), new StateFlag[]{breakFlag}); + } else return (boolean) regionQueryTestStateMethod.invoke(query, location, getAssociable(player), new StateFlag[]{breakFlag}); + + } catch (Exception ex) { + FactionsPlugin.instance.log("An error occurred querying WorldGuard! Report this issue to SF Developers!"); + FactionsPlugin.instance.log("WorldGuard 7.0.0 support is currently in BETA. Please be careful!"); + } + } + return true; + } + + public boolean checkForRegionsInChunk(FLocation floc) { return checkForRegionsInChunk(floc.getChunk()); } + + /** + * Used for checking if regions are located in a chunk + * @param chunk Chunk in question. + * @return + */ + public boolean checkForRegionsInChunk(Chunk chunk) { + initialize(); + if (createQueryMethod != null && regionContainer != null) { + try { + World world = chunk.getWorld(); + int minChunkX = chunk.getX() << 4; + int minChunkZ = chunk.getZ() << 4; + int maxChunkX = minChunkX + 15; + int maxChunkZ = minChunkZ + 15; + + int worldHeight = world.getMaxHeight(); // Allow for heights other than default + + BlockVector minChunk = new BlockVector(minChunkX, 0, minChunkZ); + BlockVector maxChunk = new BlockVector(maxChunkX, worldHeight, maxChunkZ); + + ProtectedCuboidRegion region = new ProtectedCuboidRegion("wgfactionoverlapcheck", minChunk, maxChunk); + + Collection allregionslist = new ArrayList<>(getRegionManager(world).getRegions().values()); + List overlaps = region.getIntersectingRegions(allregionslist); + + return overlaps != null && !overlaps.isEmpty(); + } catch (Exception ex) { + FactionsPlugin.instance.log("An error occurred querying WorldGuard! Report this issue to SF Developers!"); + FactionsPlugin.instance.log("WorldGuard 7.0.0 support is currently in BETA. Please be careful!"); + } + } + return false; + } + + /** + * General check for WorldGuard region @ location. + * @param player player in question. + * @param location Location of block broken. + * @return + */ + public boolean playerCanBuild(Player player, Location location) { + return hasBuildPermission(player, location) && hasBreakPermission(player, location); } } \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java index 24aef961..917b954d 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java @@ -5,6 +5,7 @@ import com.massivecraft.factions.integration.Worldguard; import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.struct.Relation; import com.massivecraft.factions.struct.Role; +import com.massivecraft.factions.util.ItemBuilder; import com.massivecraft.factions.util.Particles.ParticleEffect; import com.massivecraft.factions.util.XMaterial; import com.massivecraft.factions.zcore.fperms.Access; @@ -25,6 +26,7 @@ import org.bukkit.event.block.*; import org.bukkit.event.entity.EntityChangeBlockEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.hanging.HangingBreakByEntityEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.potion.PotionEffect; @@ -40,54 +42,36 @@ public class FactionsBlockListener implements Listener { private HashMap bannerCooldownMap = new HashMap<>(); public static boolean playerCanBuildDestroyBlock(Player player, Location location, String action, boolean justCheck) { - String name = player.getName(); - if (Conf.playersWhoBypassAllProtection.contains(name)) - return true; + if (Conf.playersWhoBypassAllProtection.contains(player.getName())) return true; FPlayer me = FPlayers.getInstance().getById(player.getUniqueId().toString()); - Faction myFaction = me.getFaction(); - if (me.isAdminBypassing()) - return true; + if (me.isAdminBypassing()) return true; FLocation loc = new FLocation(location); Faction otherFaction = Board.getInstance().getFactionAt(loc); + Faction myFaction = me.getFaction(); if (otherFaction.isWilderness()) { - if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) - return true; - - if (!Conf.wildernessDenyBuild || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName())) - return true; // This is not faction territory. Use whatever you like here. - - if (!justCheck) - me.msg("You can't " + action + " in the wilderness."); - + if (Conf.worldGuardBuildPriority && Worldguard.getInstance().playerCanBuild(player, location)) return true; + if (location.getWorld() != null) { + if (!Conf.wildernessDenyBuild || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName())) + return true; + } + if (!justCheck) me.msg(TL.ACTION_DENIED_WILDERNESS, action); return false; } else if (otherFaction.isSafeZone()) { - if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) - return true; - - if (!Conf.safeZoneDenyBuild || Permission.MANAGE_SAFE_ZONE.has(player)) - return true; - - if (!justCheck) - me.msg("You can't " + action + " in a safe zone."); - + if (Conf.worldGuardBuildPriority && Worldguard.getInstance().playerCanBuild(player, location)) return true; + if (!Conf.safeZoneDenyBuild || Permission.MANAGE_SAFE_ZONE.has(player)) return true; + if (!justCheck) me.msg(TL.ACTION_DENIED_SAFEZONE, action); return false; } else if (otherFaction.isWarZone()) { - if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) - return true; - - if (!Conf.warZoneDenyBuild || Permission.MANAGE_WAR_ZONE.has(player)) - return true; - - if (!justCheck) - me.msg("You can't " + action + " in a war zone."); - + if (Conf.worldGuardBuildPriority && Worldguard.getInstance().playerCanBuild(player, location)) return true; + if (!Conf.warZoneDenyBuild || Permission.MANAGE_WAR_ZONE.has(player)) return true; + if (!justCheck) me.msg(TL.ACTION_DENIED_WARZONE, action); return false; } else if (!otherFaction.getId().equals(myFaction.getId())) { // If the faction target is not my own - if (FactionsPlugin.getInstance().getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) + if (FactionsPlugin.instance.getConfig().getBoolean("hcf.raidable", false) && otherFaction.getLandRounded() > otherFaction.getPowerRounded()) return true; // Get faction pain build access relation to me boolean pain = !justCheck && otherFaction.getAccess(me, PermissableAction.PAIN_BUILD) == Access.ALLOW; @@ -110,16 +94,17 @@ public class FactionsBlockListener implements Listener { me.msg(TL.ACTIONS_OWNEDTERRITORYDENY.toString().replace("{owners}", myFaction.getOwnerListString(loc))); if (shouldHurt) { player.damage(Conf.actionDeniedPainAmount); - if ((Board.getInstance().getFactionAt(loc).getTag(myFaction)) != null) - me.msg(TL.ACTIONS_NOPERMISSIONPAIN.toString().replace("{action}", action.toString()).replace("{faction}", Board.getInstance().getFactionAt(loc).getTag(myFaction))); + me.msg(TL.ACTIONS_NOPERMISSIONPAIN.toString().replace("{action}", action.toString()).replace("{faction}", Board.getInstance().getFactionAt(loc).getTag(myFaction))); } return false; } else if (!landOwned && access == Access.DENY) { // If land is not owned but access is set to DENY anyway if (shouldHurt) { player.damage(Conf.actionDeniedPainAmount); - me.msg(TL.ACTIONS_NOPERMISSIONPAIN.toString().replace("{action}", action.toString()).replace("{faction}", Board.getInstance().getFactionAt(loc).getTag(myFaction))); + if ((Board.getInstance().getFactionAt(loc).getTag(myFaction)) != null) + me.msg(TL.ACTIONS_NOPERMISSIONPAIN.toString().replace("{action}", action.toString()).replace("{faction}", Board.getInstance().getFactionAt(loc).getTag(myFaction))); } - me.msg(TL.ACTIONS_NOPERMISSION.toString().replace("{faction}", myFaction.getTag(me.getFaction())).replace("{action}", action.toString())); + if (myFaction.getTag(me.getFaction()) != null && action != null) + me.msg(TL.ACTIONS_NOPERMISSION.toString().replace("{faction}", myFaction.getTag(me.getFaction())).replace("{action}", action.toString())); return false; } else if (access == Access.ALLOW) return true; me.msg(TL.ACTIONS_NOPERMISSION.toString().replace("{faction}", myFaction.getTag(me.getFaction())).replace("{action}", action.toString())); @@ -142,14 +127,10 @@ public class FactionsBlockListener implements Listener { @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onBlockPlace(BlockPlaceEvent event) { - if (!event.canBuild()) { - return; - } - + if (!event.canBuild()) return; + // special case for flint&steel, which should only be prevented by DenyUsage list - if (event.getBlockPlaced().getType() == Material.FIRE) { - return; - } + if (event.getBlockPlaced().getType() == Material.FIRE) return; if (!playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "build", false)) { event.setCancelled(true); @@ -166,17 +147,12 @@ public class FactionsBlockListener implements Listener { @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onBlockFromTo(BlockFromToEvent event) { - if (!Conf.handleExploitLiquidFlow) { - return; - } + if (!Conf.handleExploitLiquidFlow) return; if (event.getBlock().isLiquid()) { if (event.getToBlock().isEmpty()) { Faction from = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); Faction to = Board.getInstance().getFactionAt(new FLocation(event.getToBlock())); - if (from == to) { - // not concerned with inter-faction events - return; - } + if (from == to) return; // from faction != to faction if (to.isNormal()) { if (from.isNormal() && from.getRelationTo(to).isAlly()) { @@ -197,31 +173,27 @@ public class FactionsBlockListener implements Listener { @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onBlockPistonExtend(BlockPistonExtendEvent event) { - if (!Conf.pistonProtectionThroughDenyBuild) { - return; - } - + if (!Conf.pistonProtectionThroughDenyBuild) return; Faction pistonFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); // target end-of-the-line empty (air) block which is being pushed into, including if piston itself would extend into air Block targetBlock = event.getBlock().getRelative(event.getDirection(), event.getLength() + 1); // if potentially pushing into air/water/lava in another territory, we need to check it out - if ((targetBlock.isEmpty() || targetBlock.isLiquid()) && !canPistonMoveBlock(pistonFaction, targetBlock.getLocation())) { + if ((targetBlock.isEmpty() || targetBlock.isLiquid()) && !canPistonMoveBlock(pistonFaction, targetBlock.getLocation())) 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 target block as done above - */ } + @EventHandler public void onVaultPlace(BlockPlaceEvent e) { if (e.getItemInHand().getType() == Material.CHEST) { - ItemStack vault = FactionsPlugin.getInstance().createItem(Material.CHEST, 1, (short) 0, FactionsPlugin.getInstance().color(FactionsPlugin.getInstance().getConfig().getString("fvault.Item.Name")), FactionsPlugin.getInstance().colorList(FactionsPlugin.getInstance().getConfig().getStringList("fvault.Item.Lore"))); + + ItemStack vault = new ItemBuilder(Material.CHEST) + .amount(1).name(FactionsPlugin.instance.getConfig().getString("fvault.Item.Name")) + .lore(FactionsPlugin.instance.getConfig().getStringList("fvault.Item.Lore")) + .build(); + if (e.getItemInHand().isSimilar(vault)) { FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); if (fme.getFaction().getVault() != null) { @@ -244,10 +216,8 @@ public class FactionsBlockListener implements Listener { if (blockLoc.getX() == start.getLocation().getX() && blockLoc.getY() == start.getLocation().getY() && blockLoc.getZ() == start.getLocation().getZ()) { continue; } - Material blockMaterial = blockLoc.getBlock().getType(); - - if (blockMaterial == Material.CHEST || (FactionsPlugin.getInstance().getConfig().getBoolean("fvault.No-Hoppers-near-vault") && blockMaterial == Material.HOPPER)) { + if (blockMaterial == Material.CHEST || (FactionsPlugin.instance.getConfig().getBoolean("fvault.No-Hoppers-near-vault") && blockMaterial == Material.HOPPER)) { e.setCancelled(true); fme.msg(TL.COMMAND_GETVAULT_CHESTNEAR); return; @@ -255,7 +225,6 @@ public class FactionsBlockListener implements Listener { } } } - fme.msg(TL.COMMAND_GETVAULT_SUCCESS); fme.getFaction().setVault(e.getBlockPlaced().getLocation()); @@ -263,21 +232,12 @@ public class FactionsBlockListener implements Listener { } } - @EventHandler (ignoreCancelled = true) + @EventHandler public void onHopperPlace(BlockPlaceEvent e) { - if (e.getItemInHand().getType() != Material.HOPPER || !FactionsPlugin.getInstance().getConfig().getBoolean("fvault.No-Hoppers-near-vault")) { - return; - } - + if (e.getItemInHand().getType() != Material.HOPPER && !FactionsPlugin.instance.getConfig().getBoolean("fvault.No-Hoppers-near-vault")) return; Faction factionAt = Board.getInstance().getFactionAt(new FLocation(e.getBlockPlaced().getLocation())); - - if (factionAt.isWilderness() || factionAt.getVault() == null) { - return; - } - - + if (factionAt.isWilderness() || factionAt.getVault() == null) return; FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); - Block start = e.getBlockPlaced(); int radius = 1; for (double x = start.getLocation().getX() - radius; x <= start.getLocation().getX() + radius; x++) { @@ -288,7 +248,7 @@ public class FactionsBlockListener implements Listener { continue; } - if (blockLoc.getBlock().getType() == Material.CHEST) { + if (blockLoc.getBlock().getType() == XMaterial.CHEST.parseMaterial()) { if (factionAt.getVault().equals(blockLoc)) { e.setCancelled(true); fme.msg(TL.COMMAND_VAULT_NO_HOPPER); @@ -304,32 +264,21 @@ public class FactionsBlockListener implements Listener { @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onBlockPistonRetract(BlockPistonRetractEvent event) { // if not a sticky piston, retraction should be fine - if (!event.isSticky() || !Conf.pistonProtectionThroughDenyBuild) { - return; - } + if (!event.isSticky() || !Conf.pistonProtectionThroughDenyBuild) return; - if (event.getBlocks().isEmpty()) { - return; - } - Location targetLoc = event.getBlocks().get(0).getLocation(); + Location targetLoc = event.getRetractLocation(); Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(targetLoc)); // Check if the piston is moving in a faction's territory. This disables pistons entirely in faction territory. - if (otherFaction.isNormal() && FactionsPlugin.getInstance().getConfig().getBoolean("disable-pistons-in-territory", false)) { + if (otherFaction.isNormal() && FactionsPlugin.instance.getConfig().getBoolean("disable-pistons-in-territory", false)) { event.setCancelled(true); return; } // if potentially retracted block is just air/water/lava, no worries - if (targetLoc.getBlock().isEmpty() || targetLoc.getBlock().isLiquid()) { - return; - } - + if (targetLoc.getBlock().isEmpty() || targetLoc.getBlock().isLiquid()) return; Faction pistonFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); - - if (!canPistonMoveBlock(pistonFaction, targetLoc)) { - event.setCancelled(true); - } + if (!canPistonMoveBlock(pistonFaction, targetLoc)) event.setCancelled(true); } @EventHandler @@ -349,16 +298,13 @@ public class FactionsBlockListener implements Listener { @EventHandler public void onBannerPlace(BlockPlaceEvent e) { - if (FactionsPlugin.getInstance().mc17) { - return; - } + if (FactionsPlugin.getInstance().mc17) return; + if (e.getItemInHand().getType().name().contains("BANNER")) { ItemStack bannerInHand = e.getItemInHand(); FPlayer fme = FPlayers.getInstance().getByPlayer(e.getPlayer()); ItemStack warBanner = fme.getFaction().getBanner(); - if (warBanner == null) { - return; - } + if (warBanner == null) return; ItemMeta warmeta = warBanner.getItemMeta(); warmeta.setDisplayName(FactionsPlugin.getInstance().color(FactionsPlugin.getInstance().getConfig().getString("fbanners.Item.Name"))); warmeta.setLore(FactionsPlugin.getInstance().colorList(FactionsPlugin.getInstance().getConfig().getStringList("fbanners.Item.Lore"))); @@ -440,9 +386,8 @@ public class FactionsBlockListener implements Listener { @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onFrostWalker(EntityBlockFormEvent event) { - if (event.getEntity() == null || event.getEntity().getType() != EntityType.PLAYER || event.getBlock() == null) { + if (event.getEntity() == null || event.getEntity().getType() != EntityType.PLAYER || event.getBlock() == null) return; - } Player player = (Player) event.getEntity(); Location location = event.getBlock().getLocation(); @@ -450,14 +395,10 @@ public class FactionsBlockListener implements Listener { // only notify every 10 seconds FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); boolean justCheck = fPlayer.getLastFrostwalkerMessage() + 10000 > System.currentTimeMillis(); - if (!justCheck) { - fPlayer.setLastFrostwalkerMessage(); - } + if (!justCheck) fPlayer.setLastFrostwalkerMessage(); // Check if they have build permissions here. If not, block this from happening. - if (!playerCanBuildDestroyBlock(player, location, "frostwalk", justCheck)) { - event.setCancelled(true); - } + if (!playerCanBuildDestroyBlock(player, location, "frostwalk", justCheck)) event.setCancelled(true); } @EventHandler @@ -506,36 +447,29 @@ public class FactionsBlockListener implements Listener { } private boolean canPistonMoveBlock(Faction pistonFaction, Location target) { - Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(target)); - if (pistonFaction == otherFaction) - return true; + if (pistonFaction == otherFaction) return true; if (otherFaction.isWilderness()) return !Conf.wildernessDenyBuild || Conf.worldsNoWildernessProtection.contains(target.getWorld().getName()); - - else if (otherFaction.isSafeZone()) - return !Conf.safeZoneDenyBuild; - - else if (otherFaction.isWarZone()) - return !Conf.warZoneDenyBuild; + else if (otherFaction.isSafeZone()) return !Conf.safeZoneDenyBuild; + else if (otherFaction.isWarZone()) return !Conf.warZoneDenyBuild; Relation rel = pistonFaction.getRelationTo(otherFaction); - return !rel.confDenyBuild(otherFaction.hasPlayersOnline()); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onBlockBreak(BlockBreakEvent event) { - FPlayer fme = FPlayers.getInstance().getByPlayer(event.getPlayer()); if (!playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "destroy", false)) { event.setCancelled(true); return; } - if (!fme.hasFaction()) + FPlayer fme = FPlayers.getInstance().getByPlayer(event.getPlayer()); + if (fme == null || !fme.hasFaction()) { return; - + } if (event.getBlock().getType() == XMaterial.SPAWNER.parseMaterial()) { if (!fme.isAdminBypassing()) { Access access = fme.getFaction().getAccess(fme, PermissableAction.SPAWNER); @@ -546,16 +480,27 @@ public class FactionsBlockListener implements Listener { } } + @EventHandler(priority = EventPriority.HIGHEST) + public void FrameRemove(HangingBreakByEntityEvent event) { + if (event.getRemover() == null) return; + if ((event.getRemover() instanceof Player)) { + if (event.getEntity().getType().equals(EntityType.ITEM_FRAME)) { + Player p = (Player) event.getRemover(); + if (!playerCanBuildDestroyBlock(p, event.getEntity().getLocation(), "destroy", true)) { + event.setCancelled(true); + } + } + } + } + @EventHandler public void onFarmLandDamage(EntityChangeBlockEvent event) { if (event.getEntity() instanceof Player) { Player player = (Player) event.getEntity(); if (!playerCanBuildDestroyBlock(player, event.getBlock().getLocation(), PermissableAction.DESTROY.name(), true)) { - FPlayer me = FPlayers.getInstance().getById(player.getUniqueId().toString()); + FPlayer me = FPlayers.getInstance().getByPlayer(player); Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock().getLocation())); - Faction myFaction = me.getFaction(); - - me.msg("You can't jump on farmland in the territory of " + otherFaction.getTag(myFaction)); + me.msg(TL.ACTION_DENIED_OTHER, otherFaction.getTag(), "trample crops"); event.setCancelled(true); } } diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java index 765a5007..9b0d4cb4 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java @@ -139,7 +139,6 @@ public class FactionsEntityListener implements Listener { // this should trigger if the attacker shootin the arrow is a mob return; } - } } } else { @@ -226,25 +225,18 @@ public class FactionsEntityListener implements Listener { } private void cancelFFly(Player player) { - if (player == null) { - return; - } - + if (player == null) return; FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - if (fPlayer.isFlying()) { - fPlayer.setFFlying(false, true); - } + if (fPlayer.isFlying()) fPlayer.setFFlying(false, true); } public void cancelFStuckTeleport(Player player) { - if (player == null) { - return; - } + if (player == null) return; + UUID uuid = player.getUniqueId(); - if (FactionsPlugin.getInstance().getStuckMap().containsKey(uuid)) { + if (FactionsPlugin.getInstance().getStuckMap().containsKey(uuid)) FPlayers.getInstance().getByPlayer(player).msg(TL.COMMAND_STUCK_CANCELLED); FactionsPlugin.getInstance().getStuckMap().remove(uuid); - } } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @@ -294,10 +286,9 @@ public class FactionsEntityListener implements Listener { private boolean checkExplosionForBlock(Entity boomer, Block block) { Faction faction = Board.getInstance().getFactionAt(new FLocation(block.getLocation())); - if (faction.noExplosionsInTerritory() || (faction.isPeaceful() && Conf.peacefulTerritoryDisableBoom)) { - // faction is peaceful and has explosions set to disabled + if (faction.noExplosionsInTerritory() || (faction.isPeaceful() && Conf.peacefulTerritoryDisableBoom)) return false; - } + // faction is peaceful and has explosions set to disabled boolean online = faction.hasPlayersOnline(); @@ -325,9 +316,8 @@ public class FactionsEntityListener implements Listener { @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onEntityCombustByEntity(EntityCombustByEntityEvent event) { EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent(event.getCombuster(), event.getEntity(), EntityDamageEvent.DamageCause.FIRE, 0d); - if (!this.canDamagerHurtDamagee(sub, false)) { - event.setCancelled(true); - } + if (!this.canDamagerHurtDamagee(sub, false)) event.setCancelled(true); + } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @@ -340,14 +330,11 @@ public class FactionsEntityListener implements Listener { break; } } - if (!badjuju) { - return; - } + if (!badjuju) return; ProjectileSource thrower = event.getPotion().getShooter(); - if (!(thrower instanceof Entity)) { - return; - } + if (!(thrower instanceof Entity)) return; + if (thrower instanceof Player) { Player player = (Player) thrower; @@ -361,16 +348,14 @@ public class FactionsEntityListener implements Listener { // scan through affected entities to make sure they're all valid targets for (LivingEntity target : event.getAffectedEntities()) { EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent((Entity) thrower, target, EntityDamageEvent.DamageCause.CUSTOM, 0); - if (!this.canDamagerHurtDamagee(sub, true)) { + if (!this.canDamagerHurtDamagee(sub, true)) event.setIntensity(target, 0.0); // affected entity list doesn't accept modification (so no iter.remove()), but this works - } } } public boolean isPlayerInSafeZone(Entity damagee) { - if (!(damagee instanceof Player)) { - return false; - } + if (!(damagee instanceof Player)) return false; + return Board.getInstance().getFactionAt(new FLocation(damagee.getLocation())).isSafeZone(); } @@ -382,15 +367,13 @@ public class FactionsEntityListener implements Listener { Entity damager = sub.getDamager(); Entity damagee = sub.getEntity(); - if (!(damagee instanceof Player)) { - return true; - } + if (!(damagee instanceof Player)) return true; + FPlayer defender = FPlayers.getInstance().getByPlayer((Player) damagee); - if (defender == null || defender.getPlayer() == null) { - return true; - } + if (defender == null || defender.getPlayer() == null) return true; + Location defenderLoc = defender.getPlayer().getLocation(); Faction defLocFaction = Board.getInstance().getFactionAt(new FLocation(defenderLoc)); @@ -399,17 +382,11 @@ public class FactionsEntityListener implements Listener { if (damager instanceof Projectile) { Projectile projectile = (Projectile) damager; - if (!(projectile.getShooter() instanceof Entity)) { - return true; - } - + if (!(projectile.getShooter() instanceof Entity)) return true; damager = (Entity) projectile.getShooter(); } - if (damager == damagee) // ender pearl usage and other self-inflicted damage - { - return true; - } + if (damager == damagee) return true; // ender pearl usage and other self-inflicted damage // Players can not take attack damage in a SafeZone, or possibly peaceful territory if (defLocFaction.noPvPInTerritory()) { @@ -423,19 +400,16 @@ public class FactionsEntityListener implements Listener { return !defLocFaction.noMonstersInTerritory(); } - if (!(damager instanceof Player)) { - return true; - } + if (!(damager instanceof Player)) return true; + FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager); - if (attacker == null || attacker.getPlayer() == null) { - return true; - } + if (attacker == null || attacker.getPlayer() == null) return true; + + + if (Conf.playersWhoBypassAllProtection.contains(attacker.getName())) return true; - if (Conf.playersWhoBypassAllProtection.contains(attacker.getName())) { - return true; - } if (attacker.hasLoginPvpDisabled()) { if (notify) { @@ -454,13 +428,11 @@ public class FactionsEntityListener implements Listener { return false; } - if (locFaction.isWarZone() && Conf.warZoneFriendlyFire) { - return true; - } + if (locFaction.isWarZone() && Conf.warZoneFriendlyFire) return true; + + + if (Conf.worldsIgnorePvP.contains(defenderLoc.getWorld().getName())) return true; - if (Conf.worldsIgnorePvP.contains(defenderLoc.getWorld().getName())) { - return true; - } Faction defendFaction = defender.getFaction(); Faction attackFaction = attacker.getFaction(); @@ -505,9 +477,8 @@ public class FactionsEntityListener implements Listener { } // Players without faction may be hurt anywhere - if (!defender.hasFaction()) { - return true; - } + if (!defender.hasFaction()) return true; + // You can never hurt faction members or allies if (relation.isMember() || relation.isAlly() || relation.isTruce()) { @@ -546,9 +517,8 @@ public class FactionsEntityListener implements Listener { @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onCreatureSpawn(CreatureSpawnEvent event) { - if (event.getLocation() == null) { - return; - } + if (event.getLocation() == null) return; + if (Conf.safeZoneNerfedCreatureTypes.contains(event.getEntityType()) && Board.getInstance().getFactionAt(new FLocation(event.getLocation())).noMonstersInTerritory()) { event.setCancelled(true); @@ -559,14 +529,10 @@ public class FactionsEntityListener implements Listener { public void onEntityTarget(EntityTargetEvent event) { // if there is a target Entity target = event.getTarget(); - if (target == null) { - return; - } + if (target == null) return; // We are interested in blocking targeting for certain mobs: - if (!Conf.safeZoneNerfedCreatureTypes.contains(MiscUtil.creatureTypeFromEntity(event.getEntity()))) { - return; - } + if (!Conf.safeZoneNerfedCreatureTypes.contains(MiscUtil.creatureTypeFromEntity(event.getEntity()))) return; // in case the target is in a safe zone. if (Board.getInstance().getFactionAt(new FLocation(target.getLocation())).noMonstersInTerritory()) { @@ -635,9 +601,8 @@ public class FactionsEntityListener implements Listener { Entity entity = event.getEntity(); // for now, only interested in Enderman and Wither boss tomfoolery - if (!(entity instanceof Enderman) && !(entity instanceof Wither)) { - return; - } + if (!(entity instanceof Enderman) && !(entity instanceof Wither)) return; + Location loc = event.getBlock().getLocation(); @@ -659,9 +624,9 @@ public class FactionsEntityListener implements Listener { @EventHandler public void onTravel(PlayerPortalEvent event) { - if (!FactionsPlugin.getInstance().getConfig().getBoolean("portals.limit", false)) { + if (!FactionsPlugin.getInstance().getConfig().getBoolean("portals.limit", false)) return; // Don't do anything if they don't want us to. - } + TravelAgent agent = event.getPortalTravelAgent(); @@ -738,30 +703,27 @@ public class FactionsEntityListener implements Listener { } private boolean stopEndermanBlockManipulation(Location loc) { - if (loc == null) { - return false; - } + if (loc == null) return false; + // quick check to see if all Enderman deny options are enabled; if so, no need to check location if (Conf.wildernessDenyEndermanBlocks && Conf.territoryDenyEndermanBlocks && Conf.territoryDenyEndermanBlocksWhenOffline && Conf.safeZoneDenyEndermanBlocks && - Conf.warZoneDenyEndermanBlocks) { - return true; - } + Conf.warZoneDenyEndermanBlocks) return true; + FLocation fLoc = new FLocation(loc); Faction claimFaction = Board.getInstance().getFactionAt(fLoc); - if (claimFaction.isWilderness()) { + if (claimFaction.isWilderness()) return Conf.wildernessDenyEndermanBlocks; - } else if (claimFaction.isNormal()) { + else if (claimFaction.isNormal()) return claimFaction.hasPlayersOnline() ? Conf.territoryDenyEndermanBlocks : Conf.territoryDenyEndermanBlocksWhenOffline; - } else if (claimFaction.isSafeZone()) { + else if (claimFaction.isSafeZone()) return Conf.safeZoneDenyEndermanBlocks; - } else if (claimFaction.isWarZone()) { + else if (claimFaction.isWarZone()) return Conf.warZoneDenyEndermanBlocks; - } return false; } diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java index 53b5bd40..4151637c 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java @@ -39,6 +39,7 @@ import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.player.*; +import org.bukkit.scheduler.BukkitTask; import java.util.*; import java.util.logging.Level; @@ -50,16 +51,11 @@ public class FactionsPlayerListener implements Listener { public static Set corners; // Holds the next time a player can have a map shown. private HashMap showTimes = new HashMap<>(); - // for handling people who repeatedly spam attempts to open a door (or similar) in another faction's territory - private Map interactSpammers = new HashMap<>(); public FactionsPlayerListener() { - for (Player player : FactionsPlugin.getInstance().getServer().getOnlinePlayers()) { - initPlayer(player); - } - if (!FactionsPlugin.getInstance().mc17) { - loadCorners(); - } + for (Player player : FactionsPlugin.getInstance().getServer().getOnlinePlayers()) initPlayer(player); + if (positionTask == null) startPositionCheck(); + if (!FactionsPlugin.getInstance().mc17) loadCorners(); } public static void loadCorners() { @@ -295,25 +291,23 @@ public class FactionsPlayerListener implements Listener { } private static boolean CheckPlayerAccess(Player player, FPlayer me, FLocation loc, Faction factionToCheck, Access access, PermissableAction action, boolean pain) { - boolean doPain = pain && Conf.handleExploitInteractionSpam; - if (access != null && access != Access.UNDEFINED) { - // TODO: Update this once new access values are added other than just allow / deny. + boolean doPain = pain || Conf.handleExploitInteractionSpam; // Painbuild should take priority. But we want to use exploit interaction as well. + if (access != null) { boolean landOwned = (factionToCheck.doesLocationHaveOwnersSet(loc) && !factionToCheck.getOwnerList(loc).isEmpty()); if ((landOwned && factionToCheck.getOwnerListString(loc).contains(player.getName())) || (me.getRole() == Role.LEADER && me.getFactionId().equals(factionToCheck.getId()))) { return true; } else if (landOwned && !factionToCheck.getOwnerListString(loc).contains(player.getName())) { - me.msg("You can't do that in this territory, it is owned by: " + factionToCheck.getOwnerListString(loc)); - if (doPain) { - player.damage(Conf.actionDeniedPainAmount); - } + me.msg(TL.ACTIONS_OWNEDTERRITORYDENY, factionToCheck.getOwnerListString(loc)); + if (doPain) player.damage(Conf.actionDeniedPainAmount); return false; } else if (!landOwned && access == Access.ALLOW) { return true; } else { - me.msg("You cannot " + action + " in the territory of " + factionToCheck.getTag(me.getFaction())); + me.msg(TL.PLAYER_USE_TERRITORY, action, factionToCheck.getTag(me.getFaction())); return false; } } + // Approves any permission check if the player in question is a leader AND owns the faction. if (me.getRole().equals(Role.LEADER) && me.getFaction().equals(factionToCheck)) return true; if (factionToCheck != null) { @@ -329,20 +323,16 @@ public class FactionsPlayerListener implements Listener { return GetPermissionFromUsableBlock(block.getType()); } - /// - /// This will try to resolve a permission action based on the item material, if it's not usable, will return null - /// private static PermissableAction GetPermissionFromUsableBlock(Material material) { // Check for doors that might have diff material name in old version. if (material.name().contains("DOOR") || material.name().contains("FENCE_GATE")) return PermissableAction.DOOR; - if (material.name().toUpperCase().contains("BUTTON") || material.name().toUpperCase().contains("PRESSURE")) + if (material.name().toUpperCase().contains("BUTTON") || material.name().toUpperCase().contains("PRESSURE") || material.name().contains("DIODE") || material.name().contains("COMPARATOR")) return PermissableAction.BUTTON; - if (FactionsPlugin.getInstance().mc113) { + if (FactionsPlugin.instance.mc113 || FactionsPlugin.instance.mc114) { switch (material) { case LEVER: return PermissableAction.LEVER; - case ACACIA_BUTTON: case BIRCH_BUTTON: case DARK_OAK_BUTTON: @@ -350,6 +340,8 @@ public class FactionsPlayerListener implements Listener { case OAK_BUTTON: case SPRUCE_BUTTON: case STONE_BUTTON: + case COMPARATOR: + case REPEATER: return PermissableAction.BUTTON; case ACACIA_DOOR: @@ -424,11 +416,10 @@ public class FactionsPlayerListener implements Listener { case IRON_DOOR: case JUNGLE_DOOR: case SPRUCE_DOOR: - case ACACIA_FENCE_GATE: case BIRCH_FENCE_GATE: - case DARK_OAK_FENCE_GATE: case OAK_FENCE_GATE: + case DARK_OAK_FENCE_GATE: case JUNGLE_FENCE_GATE: case SPRUCE_FENCE_GATE: return PermissableAction.DOOR; @@ -469,41 +460,34 @@ public class FactionsPlayerListener implements Listener { me.login(); // set kills / deaths - // Check for Faction announcements. Let's delay this so they actually see it. - Bukkit.getScheduler().runTaskLater(FactionsPlugin.getInstance(), () -> { - if (me.isOnline()) { - me.getFaction().sendUnreadAnnouncements(me); - } - }, 33L); // Don't ask me why. + Bukkit.getScheduler().runTaskLater(FactionsPlugin.instance, () -> { + if (me.isOnline()) me.getFaction().sendUnreadAnnouncements(me); + }, 33L); - if (FactionsPlugin.getInstance().getConfig().getBoolean("scoreboard.default-enabled", false)) { + if (FactionsPlugin.instance.getConfig().getBoolean("scoreboard.default-enabled", false)) { FScoreboard.init(me); - FScoreboard.get(me).setDefaultSidebar(new FDefaultSidebar(), FactionsPlugin.getInstance().getConfig().getInt("scoreboard.default-update-interval", 20)); + FScoreboard.get(me).setDefaultSidebar(new FDefaultSidebar(), FactionsPlugin.instance.getConfig().getInt("scoreboard.default-update-interval", 20)); FScoreboard.get(me).setSidebarVisibility(me.showScoreboard()); } Faction myFaction = me.getFaction(); if (!myFaction.isWilderness()) { for (FPlayer other : myFaction.getFPlayersWhereOnline(true)) { - if (other != me && other.isMonitoringJoins()) { - other.msg(TL.FACTION_LOGIN, me.getName()); - } + if (other != me && other.isMonitoringJoins()) other.msg(TL.FACTION_LOGIN, me.getName()); } } - fallMap.put(me.getPlayer(), false); - Bukkit.getScheduler().scheduleSyncDelayedTask(FactionsPlugin.getInstance(), () -> fallMap.remove(me.getPlayer()), 180L); - + Bukkit.getScheduler().scheduleSyncDelayedTask(FactionsPlugin.instance, () -> fallMap.remove(me.getPlayer()), 180L); if (me.isSpyingChat() && !player.hasPermission(Permission.CHATSPY.node)) { me.setSpyingChat(false); - FactionsPlugin.getInstance().log(Level.INFO, "Found %s spying chat without permission on login. Disabled their chat spying.", player.getName()); + FactionsPlugin.instance.log(Level.INFO, "Found %s spying chat without permission on login. Disabled their chat spying.", player.getName()); } if (me.isAdminBypassing() && !player.hasPermission(Permission.BYPASS.node)) { me.setIsAdminBypassing(false); - FactionsPlugin.getInstance().log(Level.INFO, "Found %s on admin Bypass without permission on login. Disabled it for them.", player.getName()); + FactionsPlugin.instance.log(Level.INFO, "Found %s on admin Bypass without permission on login. Disabled it for them.", player.getName()); } @@ -537,23 +521,19 @@ public class FactionsPlayerListener implements Listener { me.logout(); // cache kills / deaths // if player is waiting for fstuck teleport but leaves, remove - if (FactionsPlugin.getInstance().getStuckMap().containsKey(me.getPlayer().getUniqueId())) { + if (FactionsPlugin.instance.getStuckMap().containsKey(me.getPlayer().getUniqueId())) { FPlayers.getInstance().getByPlayer(me.getPlayer()).msg(TL.COMMAND_STUCK_CANCELLED); - FactionsPlugin.getInstance().getStuckMap().remove(me.getPlayer().getUniqueId()); - FactionsPlugin.getInstance().getTimers().remove(me.getPlayer().getUniqueId()); + FactionsPlugin.instance.getStuckMap().remove(me.getPlayer().getUniqueId()); + FactionsPlugin.instance.getTimers().remove(me.getPlayer().getUniqueId()); } Faction myFaction = me.getFaction(); - if (!myFaction.isWilderness()) { - myFaction.memberLoggedOff(); - } + if (!myFaction.isWilderness()) myFaction.memberLoggedOff(); if (!myFaction.isWilderness()) { - for (FPlayer player : myFaction.getFPlayersWhereOnline(true)) { - if (player != me && player.isMonitoringJoins()) { - player.msg(TL.FACTION_LOGOUT, me.getName()); - } - } + for (FPlayer player : myFaction.getFPlayersWhereOnline(true)) + if (player != me && player.isMonitoringJoins()) player.msg(TL.FACTION_LOGOUT, me.getName()); + } CmdSeeChunk.seeChunkMap.remove(event.getPlayer().getName()); @@ -570,23 +550,16 @@ public class FactionsPlayerListener implements Listener { .replace("{chunks}", faction.getAllClaims().size() + "") .replace("{power}", faction.getPower() + "") .replace("{leader}", faction.getFPlayerAdmin() + ""); - return string; } public void enableFly(FPlayer me) { - if (!me.getPlayer().hasPermission(Permission.FLY.node)) return; + if (!FactionsPlugin.instance.getConfig().getBoolean("ffly.AutoEnable")) return; // Looks prettier sorry me.setFFlying(true, false); - - if (FactionsPlugin.getInstance().getConfig().getBoolean("ffly.AutoEnable")) { - me.setFlying(true); - CmdFly.flyMap.put(me.getName(), true); - if (CmdFly.particleTask == null) - if (FactionsPlugin.getInstance().getConfig().getBoolean("ffly.Particles.Enabled")) - CmdFly.startParticles(); - } - if (CmdFly.flyTask == null) CmdFly.startFlyCheck(); - } + CmdFly.flyMap.put(me.getName(), true); + if (CmdFly.particleTask == null) + CmdFly.startParticles(); + } //inspect @@ -639,11 +612,9 @@ public class FactionsPlayerListener implements Listener { Player player = e.getPlayer(); if (player.getItemInHand().getType() == Material.ENDER_PEARL) { FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); - if (fPlayer.isFlying()) { - if (Conf.noEnderpearlsInFly) { - fPlayer.msg(TL.COMMAND_FLY_NO_EPEARL); - e.setCancelled(true); - } + if (fPlayer.isFlying() && Conf.noEnderpearlsInFly) { + fPlayer.msg(TL.COMMAND_FLY_NO_EPEARL); + e.setCancelled(true); } } } @@ -653,16 +624,59 @@ public class FactionsPlayerListener implements Listener { return (result.length() == 3 ? result + "0" : result) + "/hrs ago"; } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onPlayerMove(PlayerMoveEvent event) { - Player player = event.getPlayer(); + public static BukkitTask positionTask = null; + public static Map lastLocations = new HashMap<>(); + + public void startPositionCheck() { + positionTask = Bukkit.getScheduler().runTaskTimer(FactionsPlugin.instance, () -> { + if (Bukkit.getOnlinePlayers().size() > 0) { + for (Player player : Bukkit.getOnlinePlayers()) { + if (!lastLocations.containsKey(player.getUniqueId())) { + lastLocations.put(player.getUniqueId(), player.getLocation()); + continue; + } + refreshPosition(player, lastLocations.get(player.getUniqueId()), player.getLocation()); + lastLocations.put(player.getUniqueId(), player.getLocation()); + if (CmdFly.flyMap.containsKey(player.getName())) { + String name = player.getName(); + if (!player.isFlying() + || player.getGameMode() == GameMode.CREATIVE + || !FactionsPlugin.instance.mc17 && player.getGameMode() == GameMode.SPECTATOR) { + continue; + } + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); + Faction myFaction = fPlayer.getFaction(); + if (myFaction.isWilderness()) { + Bukkit.getScheduler().runTask(FactionsPlugin.instance, () -> fPlayer.setFlying(false)); + CmdFly.flyMap.remove(player.getName()); + continue; + } + Bukkit.getScheduler().runTask(FactionsPlugin.instance, () -> { + if (!fPlayer.checkIfNearbyEnemies()) { + FLocation myFloc = new FLocation(player.getLocation()); + if (Board.getInstance().getFactionAt(myFloc) != myFaction) { + if (!CmdFly.checkBypassPerms(fPlayer, player, Board.getInstance().getFactionAt(myFloc))) { + fPlayer.setFFlying(false, false); + CmdFly.flyMap.remove(name); + } + } + } + }); + } + + } + } + }, 5L, 10L); + } + + public void refreshPosition(Player player, Location oldLocation, Location newLocation) { FPlayer me = FPlayers.getInstance().getByPlayer(player); // clear visualization - if (event.getFrom().getBlockX() != event.getTo().getBlockX() - || event.getFrom().getBlockY() != event.getTo().getBlockY() - || event.getFrom().getBlockZ() != event.getTo().getBlockZ()) { - VisualizeUtil.clear(event.getPlayer()); + if (oldLocation.getBlockX() != newLocation.getBlockX() + || oldLocation.getBlockY() != newLocation.getBlockY() + || oldLocation.getBlockZ() != newLocation.getBlockZ()) { + VisualizeUtil.clear(player); if (me.isWarmingUp()) { me.clearWarmup(); me.msg(TL.WARMUPS_CANCELLED); @@ -670,23 +684,20 @@ public class FactionsPlayerListener implements Listener { } // quick check to make sure player is moving between chunks; good performance boost - if (event.getFrom().getBlockX() >> 4 == event.getTo().getBlockX() >> 4 - && event.getFrom().getBlockZ() >> 4 == event.getTo().getBlockZ() >> 4 - && event.getFrom().getWorld() == event.getTo().getWorld()) { + if (oldLocation.getBlockX() >> 4 == newLocation.getBlockX() >> 4 + && oldLocation.getBlockZ() >> 4 == newLocation.getBlockZ() >> 4 + && oldLocation.getWorld() == newLocation.getWorld()) { return; } // Did we change coord? FLocation from = me.getLastStoodAt(); - FLocation to = new FLocation(event.getTo()); + FLocation to = new FLocation(player.getLocation()); - if (from.equals(to)) { - return; - } + if (from.equals(to)) return; // Yes we did change coord (: - me.setLastStoodAt(to); // Did we change "host"(faction)? @@ -696,26 +707,30 @@ public class FactionsPlayerListener implements Listener { if (changedFaction) { - Bukkit.getServer().getPluginManager().callEvent(new FPlayerEnteredFactionEvent(factionTo, factionFrom, me)); - if (FactionsPlugin.getInstance().getConfig().getBoolean("Title.Show-Title")) { - String title = FactionsPlugin.getInstance().getConfig().getString("Title.Format.Title"); + Bukkit.getScheduler().runTask(FactionsPlugin.instance, () -> Bukkit.getServer().getPluginManager().callEvent(new FPlayerEnteredFactionEvent(factionTo, factionFrom, me))); + if (FactionsPlugin.instance.getConfig().getBoolean("Title.Show-Title")) { + String title = FactionsPlugin.instance.getConfig().getString("Title.Format.Title"); title = title.replace("{Faction}", factionTo.getColorTo(me) + factionTo.getTag()); title = parseAllPlaceholders(title, factionTo, player); - String subTitle = FactionsPlugin.getInstance().getConfig().getString("Title.Format.Subtitle").replace("{Description}", factionTo.getDescription()).replace("{Faction}", factionTo.getColorTo(me) + factionTo.getTag()); + String subTitle = FactionsPlugin.instance.getConfig().getString("Title.Format.Subtitle").replace("{Description}", factionTo.getDescription()).replace("{Faction}", factionTo.getColorTo(me) + factionTo.getTag()); subTitle = parseAllPlaceholders(subTitle, factionTo, player); - if (!FactionsPlugin.getInstance().mc17) { - if (!FactionsPlugin.getInstance().mc18) { - me.getPlayer().sendTitle(FactionsPlugin.getInstance().color(title), FactionsPlugin.getInstance().color(subTitle), FactionsPlugin.getInstance().getConfig().getInt("Title.Options.FadeInTime"), - FactionsPlugin.getInstance().getConfig().getInt("Title.Options.ShowTime"), - FactionsPlugin.getInstance().getConfig().getInt("Title.Options.FadeOutTime")); - } else { - me.getPlayer().sendTitle(FactionsPlugin.getInstance().color(title), FactionsPlugin.getInstance().color(subTitle)); - } + final String finalTitle = title; + final String finalsubTitle = subTitle; + if (!FactionsPlugin.instance.mc17) { + Bukkit.getScheduler().runTaskLater(FactionsPlugin.instance, () -> { + if (!FactionsPlugin.instance.mc18) { + me.getPlayer().sendTitle(FactionsPlugin.instance.color(finalTitle), FactionsPlugin.instance.color(finalsubTitle), FactionsPlugin.instance.getConfig().getInt("Title.Options.FadeInTime"), + FactionsPlugin.instance.getConfig().getInt("Title.Options.ShowTime"), + FactionsPlugin.instance.getConfig().getInt("Title.Options.FadeOutTime")); + } else { + me.getPlayer().sendTitle(FactionsPlugin.instance.color(finalTitle), FactionsPlugin.instance.color(finalsubTitle)); + } + }, 5); } } // enable fly :) - if (FactionsPlugin.getInstance().factionsFlight && me.hasFaction() && !me.isFlying()) { + if (FactionsPlugin.instance.factionsFlight && me.hasFaction() && !me.isFlying()) { if (factionTo == me.getFaction()) enableFly(me); // bypass checks Relation relationTo = factionTo.getRelationTo(me); @@ -729,10 +744,10 @@ public class FactionsPlayerListener implements Listener { Bukkit.getScheduler().runTask(FactionsPlugin.instance, () -> enableFly(me)); } } + if (me.getAutoClaimFor() != null) { - me.attemptClaim(me.getAutoClaimFor(), event.getTo(), true); - if (Conf.disableFlightOnFactionClaimChange && event.getPlayer().getGameMode() != GameMode.CREATIVE) - CmdFly.disableFlight(me); + me.attemptClaim(me.getAutoClaimFor(), newLocation, true); + if (Conf.disableFlightOnFactionClaimChange) CmdFly.disableFlight(me); } else if (me.isAutoSafeClaimEnabled()) { if (!Permission.MANAGE_SAFE_ZONE.has(player)) { me.setIsAutoSafeClaimEnabled(false); @@ -754,27 +769,26 @@ public class FactionsPlayerListener implements Listener { } } - if (me.isMapAutoUpdating()) { if (showTimes.containsKey(player.getUniqueId()) && (showTimes.get(player.getUniqueId()) > System.currentTimeMillis())) { - if (FactionsPlugin.getInstance().getConfig().getBoolean("findfactionsexploit.log", false)) { - FactionsPlugin.getInstance().log(Level.WARNING, "%s tried to show a faction map too soon and triggered exploit blocker.", player.getName()); + if (FactionsPlugin.instance.getConfig().getBoolean("findfactionsexploit.log", false)) { + FactionsPlugin.instance.log(Level.WARNING, "%s tried to show a faction map too soon and triggered exploit blocker.", player.getName()); } } else { me.sendFancyMessage(Board.getInstance().getMap(me, to, player.getLocation().getYaw())); - showTimes.put(player.getUniqueId(), System.currentTimeMillis() + FactionsPlugin.getInstance().getConfig().getLong("findfactionsexploit.cooldown", 2000)); + showTimes.put(player.getUniqueId(), System.currentTimeMillis() + FactionsPlugin.instance.getConfig().getLong("findfactionsexploit.cooldown", 2000)); } } else { Faction myFaction = me.getFaction(); String ownersTo = myFaction.getOwnerListString(to); if (changedFaction) { - me.sendFactionHereMessage(factionFrom); - if (Conf.ownedAreasEnabled && Conf.ownedMessageOnBorder && myFaction == factionTo && !ownersTo.isEmpty() && me.hasNotificationsEnabled()) { + if (Conf.sendFactionChangeMessage) me.sendFactionHereMessage(factionFrom); + if (Conf.ownedAreasEnabled && Conf.ownedMessageOnBorder && myFaction == factionTo && !ownersTo.isEmpty()) { me.sendMessage(TL.GENERIC_OWNERS.format(ownersTo)); } } else if (Conf.ownedAreasEnabled && Conf.ownedMessageInsideTerritory && myFaction == factionTo && !myFaction.isWilderness()) { String ownersFrom = myFaction.getOwnerListString(from); - if (Conf.ownedMessageByChunk || !ownersFrom.equals(ownersTo) && me.hasNotificationsEnabled()) { + if (Conf.ownedMessageByChunk || !ownersFrom.equals(ownersTo)) { if (!ownersTo.isEmpty()) { me.sendMessage(TL.GENERIC_OWNERS.format(ownersTo)); } else if (!TL.GENERIC_PUBLICLAND.toString().isEmpty()) { @@ -792,15 +806,16 @@ public class FactionsPlayerListener implements Listener { if (fme.isInFactionsChest()) fme.setInFactionsChest(false); } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler public void onPlayerInteract(PlayerInteractEvent event) { - // only need to check right-clicks and physical as of MC 1.4+; good performance boost - if (event.getAction().equals(Action.LEFT_CLICK_BLOCK) || event.getAction().equals(Action.LEFT_CLICK_AIR)) + if (event.getAction().equals(Action.LEFT_CLICK_AIR) || event.getAction().equals(Action.LEFT_CLICK_BLOCK)) return; + Block block = event.getClickedBlock(); Player player = event.getPlayer(); - // Check if the material is bypassing protection - if (block == null) return; // clicked in air, apparently + + if (block == null) return; + Material type; if (event.getItem() != null) { @@ -810,26 +825,31 @@ public class FactionsPlayerListener implements Listener { type = null; } - if (Conf.territoryBypassProtectedMaterials.contains(block.getType())) return; + // Creeper Egg Bypass. + if (Conf.allowCreeperEggingChests && block.getType() == Material.CHEST && type == XMaterial.CREEPER_SPAWN_EGG.parseMaterial() && event.getPlayer().isSneaking()) { + return; + } - if (GetPermissionFromUsableBlock(event.getClickedBlock().getType()) != null) { + + // territoryBypasssProtectedMaterials totally bypass the protection system + if (Conf.territoryBypasssProtectedMaterials.contains(block.getType())) return; + // Do type null checks so if XMaterial has a parsing issue and fills null as a value it will not bypass. + // territoryCancelAndAllowItemUseMaterial bypass the protection system but only if they're not clicking on territoryDenySwitchMaterials + // if they're clicking on territoryDenySwitchMaterials, let the protection system handle the permissions + if (type != null && !Conf.territoryDenySwitchMaterials.contains(block.getType())) { + if (Conf.territoryCancelAndAllowItemUseMaterial.contains(type)) { + return; + } + } + + if (GetPermissionFromUsableBlock(block.getType()) != null) { if (!canPlayerUseBlock(player, block, false)) { event.setCancelled(true); event.setUseInteractedBlock(Event.Result.DENY); return; } } - if (event.getPlayer().getItemInHand() != null) { - Material handItem = event.getPlayer().getItemInHand().getType(); - if (handItem.isEdible() - || handItem.equals(XMaterial.POTION.parseMaterial()) - || handItem.equals(XMaterial.LINGERING_POTION.parseMaterial()) - || handItem.equals(XMaterial.SPLASH_POTION.parseMaterial())) { - return; - } - } - if (event.getItem() == null) return; if (type != null && !playerCanUseItemHere(player, block.getLocation(), event.getItem().getType(), false, PermissableAction.ITEM)) { event.setCancelled(true); event.setUseInteractedBlock(Event.Result.DENY); @@ -837,7 +857,7 @@ public class FactionsPlayerListener implements Listener { } @EventHandler - public void onInentorySee(InventoryClickEvent e) { + public void onInventorySee(InventoryClickEvent e) { if (e.getCurrentItem() == null) return; @@ -850,7 +870,6 @@ public class FactionsPlayerListener implements Listener { @EventHandler public void onPlayerBoneMeal(PlayerInteractEvent event) { Block block = event.getClickedBlock(); - if (event.getAction() == Action.RIGHT_CLICK_BLOCK && block.getType() == XMaterial.GRASS_BLOCK.parseMaterial() && event.hasItem() && event.getItem().getType() == XMaterial.BONE_MEAL.parseMaterial()) { if (!FactionsBlockListener.playerCanBuildDestroyBlock(event.getPlayer(), block.getLocation(), PermissableAction.BUILD.name(), true)) { @@ -935,9 +954,7 @@ public class FactionsPlayerListener implements Listener { @EventHandler(priority = EventPriority.HIGH) public void onPlayerInteractGUI(InventoryClickEvent event) { - if (event.getClickedInventory() == null) { - return; - } + if (event.getClickedInventory() == null) return; if (event.getClickedInventory().getHolder() instanceof FactionGUI) { event.setCancelled(true); ((FactionGUI) event.getClickedInventory().getHolder()).onClick(event.getRawSlot(), event.getClick()); @@ -946,23 +963,18 @@ public class FactionsPlayerListener implements Listener { @EventHandler(priority = EventPriority.HIGH) public void onPlayerMoveGUI(InventoryDragEvent event) { - if (event.getInventory().getHolder() instanceof FactionGUI) { - event.setCancelled(true); - } + if (event.getInventory().getHolder() instanceof FactionGUI) event.setCancelled(true); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onPlayerKick(PlayerKickEvent event) { FPlayer badGuy = FPlayers.getInstance().getByPlayer(event.getPlayer()); - if (badGuy == null) { - return; - } + if (badGuy == null) return; // if player was banned (not just kicked), get rid of their stored info if (Conf.removePlayerDataWhenBanned && event.getReason().equals("Banned by admin.")) { - if (badGuy.getRole() == Role.LEADER) { - badGuy.getFaction().promoteNewLeader(); - } + if (badGuy.getRole() == Role.LEADER) badGuy.getFaction().promoteNewLeader(); + badGuy.leave(false); badGuy.remove(); @@ -980,7 +992,7 @@ public class FactionsPlayerListener implements Listener { } public Set getCorners() { - return this.corners; + return corners; } @EventHandler @@ -1020,23 +1032,6 @@ public class FactionsPlayerListener implements Listener { @EventHandler public void onDisconnect(PlayerQuitEvent e) { FPlayer fPlayer = FPlayers.getInstance().getByPlayer(e.getPlayer()); - if (fPlayer.isInFactionsChest()) fPlayer.setInFactionsChest(false); - } - - private static class InteractAttemptSpam { - private int attempts = 0; - private long lastAttempt = System.currentTimeMillis(); - - // returns the current attempt count - public int increment() { - long now = System.currentTimeMillis(); - if (now > lastAttempt + 2000) { - attempts = 1; - } else { - attempts++; - } - lastAttempt = now; - return attempts; - } + if (fPlayer.isInFactionsChest()) fPlayer.setInFactionsChest(false); } } diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TL.java b/src/main/java/com/massivecraft/factions/zcore/util/TL.java index a066685a..5b728f44 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/TL.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/TL.java @@ -56,6 +56,12 @@ public enum TL { ACTIONS_MUSTBE("Youmust be {role} to {action}."), ACTIONS_NOSAMEROLE("{role} can't control each other..."), ACTIONS_NOFACTION("You are not member of any faction."), + + ACTION_DENIED_SAFEZONE("You can't use %1$s in safezone!"), + ACTION_DENIED_WARZONE("You can't use %1$s in warzone!"), + ACTION_DENIED_WILDERNESS("You can't use %1$s in wilderness!"), + ACTION_DENIED_OTHER("%1$s does not allow you to %2$s here!"), + /** * Command translations */