package com.massivecraft.factions.integration; import com.massivecraft.factions.FLocation; import com.massivecraft.factions.FactionsPlugin; import com.sk89q.worldedit.BlockVector; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; import com.sk89q.worldguard.domains.Association; import com.sk89q.worldguard.protection.ApplicableRegionSet; import com.sk89q.worldguard.protection.association.Associables; import com.sk89q.worldguard.protection.association.RegionAssociable; import com.sk89q.worldguard.protection.flags.DefaultFlag; 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.*; /* * 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 Worldguard instance; /** * @author FactionsUUID Team */ 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 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 static Worldguard getInstance() { return instance; } public boolean isEnabled() { return worldGuardPlugin != null; } protected RegionAssociable getAssociable(Player player) { RegionAssociable associable; if (player == null) { associable = Associables.constant(Association.NON_MEMBER); } else { associable = worldGuardPlugin.wrapPlayer(player); } return associable; } public static boolean isPvPDisabled(Location l) { try { ApplicableRegionSet regionSet = Objects.requireNonNull(instance.getRegionManager(l.getWorld())).getApplicableRegions(l); if (regionSet.size() < 1) { try { return Objects.requireNonNull(Objects.requireNonNull(instance.getRegionManager(l.getWorld())).getRegion("__global__")).getFlags().get(DefaultFlag.PVP) == StateFlag.State.DENY; } catch (Exception e) { if (!(e instanceof NullPointerException)) { e.printStackTrace(); } return false; } } else { boolean return_flag = false; int return_priority = -1; for (ProtectedRegion region : regionSet) { if (region.getFlags().containsKey(DefaultFlag.PVP)) { StateFlag.State pvp_flag = (StateFlag.State) region.getFlags().get(DefaultFlag.PVP); int region_priority = region.getPriority(); if (return_priority == -1) { return_flag = pvp_flag == StateFlag.State.DENY; return_priority = region_priority; } else if (region_priority > return_priority) { return_flag = pvp_flag == StateFlag.State.DENY; return_priority = region_priority; } } } return return_flag; } } catch (Exception e) { return false; } } /** * 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; } } } } private RegionManager getRegionManager(World world) { initialize(); if (regionContainer == null || regionContainerGetMethod == null) return null; RegionManager regionManager = null; try { 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; } 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); } }