From 508f953ce98286b7662b0046edfa79a0a7f75962 Mon Sep 17 00:00:00 2001 From: Brettflan Date: Sat, 30 Jul 2011 20:17:00 -0500 Subject: [PATCH] Faction admins can now mark already claimed areas as owned by specific faction members. Ownership can include multiple members. New command /f owner *[player name], to set/remove ownership. This command is only available to the faction admin and optionally the faction moderators. If no player name is specified, it will either set ownership to the player running the command (if no owner is currently set) or completely clear ownership of the territory. New command /f ownerlist, to view a list of owners for the current area. Only works inside your own faction's territory. New conf.json options "ownedAreasEnabled", "ownedAreasModeratorsCanSet", "ownedAreaModeratorsBypass", "ownedAreaDenyBuild", "ownedAreaProtectMaterials", and "ownedAreaDenyUseage" (all defaulting to true) to determine whether faction moderators can set or bypass ownership (faction admin always can), and what sort of protection these owned areas have against normal members of the faction (members other than the owner(s), faction admin, and probably faction moderators). New conf.json option "ownedAreasLimitPerFaction" to limit how many owned areas can be set. New permission node "factions.ownershipBypass" which allows a player to bypass ownership protection, but only within the person's own faction. various little tweaks and improvements to other code moderate speed boost to FLocation code made commandDisable permissions work for any command alias of a command, instead of just the first one --- src/com/massivecraft/factions/Board.java | 39 ++++- src/com/massivecraft/factions/Conf.java | 9 ++ src/com/massivecraft/factions/FLocation.java | 7 +- src/com/massivecraft/factions/FPlayer.java | 7 +- src/com/massivecraft/factions/Faction.java | 147 ++++++++++++++++++ src/com/massivecraft/factions/Factions.java | 22 ++- .../factions/commands/FBaseCommand.java | 10 +- .../factions/commands/FCommandHelp.java | 12 ++ .../factions/commands/FCommandOwner.java | 100 ++++++++++++ .../factions/commands/FCommandOwnerList.java | 59 +++++++ .../listeners/FactionsBlockListener.java | 16 +- .../listeners/FactionsEntityListener.java | 11 +- .../listeners/FactionsPlayerListener.java | 50 ++++-- .../util/MapFLocToStringSetTypeAdapter.java | 112 +++++++++++++ .../{ => util}/MyLocationTypeAdapter.java | 3 +- src/plugin.yml | 88 +++++++++-- 16 files changed, 643 insertions(+), 49 deletions(-) create mode 100644 src/com/massivecraft/factions/commands/FCommandOwner.java create mode 100644 src/com/massivecraft/factions/commands/FCommandOwnerList.java create mode 100644 src/com/massivecraft/factions/util/MapFLocToStringSetTypeAdapter.java rename src/com/massivecraft/factions/{ => util}/MyLocationTypeAdapter.java (96%) diff --git a/src/com/massivecraft/factions/Board.java b/src/com/massivecraft/factions/Board.java index 21609f00..cb1b31b3 100644 --- a/src/com/massivecraft/factions/Board.java +++ b/src/com/massivecraft/factions/Board.java @@ -42,6 +42,8 @@ public class Board { } public static void setIdAt(int id, FLocation flocation) { + clearOwnershipAt(flocation); + if (id == 0) { removeAt(flocation); } @@ -54,10 +56,24 @@ public class Board { } public static void removeAt(FLocation flocation) { + clearOwnershipAt(flocation); flocationIds.remove(flocation); } + // not to be confused with claims, ownership referring to further member-specific ownership of a claim + public static void clearOwnershipAt(FLocation flocation) { + Faction faction = getFactionAt(flocation); + if (faction != null && faction.isNormal()) { + faction.clearClaimOwnership(flocation); + } + } + public static void unclaimAll(int factionId) { + Faction faction = Faction.get(factionId); + if (faction != null && faction.isNormal()) { + faction.clearAllClaimOwnership(); + } + Iterator> iter = flocationIds.entrySet().iterator(); while (iter.hasNext()) { Entry entry = iter.next(); @@ -215,10 +231,13 @@ public class Board { public static Map> dumpAsSaveFormat() { Map> worldCoordIds = new HashMap>(); + String worldName, coords; + Integer id; + for (Entry entry : flocationIds.entrySet()) { - String worldName = entry.getKey().getWorldName(); - String coords = entry.getKey().getCoordString(); - Integer id = entry.getValue(); + worldName = entry.getKey().getWorldName(); + coords = entry.getKey().getCoordString(); + id = entry.getValue(); if ( ! worldCoordIds.containsKey(worldName)) { worldCoordIds.put(worldName, new TreeMap()); } @@ -232,13 +251,17 @@ public class Board { public static void loadFromSaveFormat(Map> worldCoordIds) { flocationIds.clear(); + String worldName; + String[] coords; + int x, z, factionId; + for (Entry> entry : worldCoordIds.entrySet()) { - String worldName = entry.getKey(); + worldName = entry.getKey(); for (Entry entry2 : entry.getValue().entrySet()) { - String[] coords = entry2.getKey().trim().split("[,\\s]+"); - int x = Integer.parseInt(coords[0]); - int z = Integer.parseInt(coords[1]); - int factionId = entry2.getValue(); + coords = entry2.getKey().trim().split("[,\\s]+"); + x = Integer.parseInt(coords[0]); + z = Integer.parseInt(coords[1]); + factionId = entry2.getValue(); flocationIds.put(new FLocation(worldName, x, z), factionId); } } diff --git a/src/com/massivecraft/factions/Conf.java b/src/com/massivecraft/factions/Conf.java index 7de2e83a..a5911cc4 100644 --- a/src/com/massivecraft/factions/Conf.java +++ b/src/com/massivecraft/factions/Conf.java @@ -96,6 +96,15 @@ public class Conf { public static boolean territoryBlockTNT = false; public static boolean territoryBlockTNTWhenOffline = false; + // for claimed areas where further faction-member ownership can be defined + public static boolean ownedAreasEnabled = true; + public static int ownedAreasLimitPerFaction = 0; + public static boolean ownedAreasModeratorsCanSet = false; + public static boolean ownedAreaModeratorsBypass = true; + public static boolean ownedAreaDenyBuild = true; + public static boolean ownedAreaProtectMaterials = true; + public static boolean ownedAreaDenyUseage = true; + public static boolean safeZoneDenyBuild = true; public static boolean safeZoneDenyUseage = true; public static boolean safeZoneBlockTNT = true; diff --git a/src/com/massivecraft/factions/FLocation.java b/src/com/massivecraft/factions/FLocation.java index d144b52f..56bc5417 100644 --- a/src/com/massivecraft/factions/FLocation.java +++ b/src/com/massivecraft/factions/FLocation.java @@ -14,7 +14,7 @@ public class FLocation { private int x = 0; private int z = 0; - private final static transient double cellSize = 16; +// private final static transient double cellSize = 16; //----------------------------------------------// // Constructors @@ -31,7 +31,9 @@ public class FLocation { } public FLocation(Location location) { - this(location.getWorld().getName(), (int) Math.floor(location.getX() / cellSize) , (int) Math.floor(location.getZ() / cellSize)); +// this(location.getWorld().getName(), (int) Math.floor(location.getX() / cellSize) , (int) Math.floor(location.getZ() / cellSize)); + // handy dandy rapid bitshifting instead of division + this(location.getWorld().getName(), location.getBlockX() >> 4, location.getBlockZ() >> 4); } public FLocation(Player player) { @@ -107,6 +109,7 @@ public class FLocation { // Comparison //----------------------------------------------// + @Override public int hashCode() { int hash = 3; hash = 19 * hash + (this.worldName != null ? this.worldName.hashCode() : 0); diff --git a/src/com/massivecraft/factions/FPlayer.java b/src/com/massivecraft/factions/FPlayer.java index 94d3870a..7d757020 100644 --- a/src/com/massivecraft/factions/FPlayer.java +++ b/src/com/massivecraft/factions/FPlayer.java @@ -69,6 +69,11 @@ public class FPlayer { } public void resetFactionData() { + // clean up any territory ownership in old faction, if there is one + if (this.factionId > 0 && Faction.exists(this.factionId)) { + Faction.get(factionId).clearClaimOwnership(playerName); + } + this.factionId = 0; // The default neutral faction this.factionChatting = false; this.role = Role.NORMAL; @@ -103,7 +108,7 @@ public class FPlayer { return Faction.get(factionId); } - private int getFactionId() { + public int getFactionId() { return factionId; } diff --git a/src/com/massivecraft/factions/Faction.java b/src/com/massivecraft/factions/Faction.java index b3235acf..f0baf011 100644 --- a/src/com/massivecraft/factions/Faction.java +++ b/src/com/massivecraft/factions/Faction.java @@ -28,6 +28,7 @@ public class Faction { private transient int id; private Map relationWish; + private Map> claimOwnership; private Set invites; // Where string is a lowercase player name private boolean open; private String tag; @@ -397,6 +398,152 @@ public class Faction { return this.getRelation(fplayer).getColor(); } + //----------------------------------------------// + // Ownership of specific claims + //----------------------------------------------// + + private boolean isClaimOwnershipEmpty() { + if (claimOwnership == null) { + claimOwnership = new HashMap>(); + return true; + } + return claimOwnership.isEmpty(); + } + + public void clearAllClaimOwnership() { + claimOwnership.clear(); + } + + public void clearClaimOwnership(FLocation loc) { + claimOwnership.remove(loc); + } + + public void clearClaimOwnership(String playerName) { + if (playerName == null || playerName.isEmpty()) { + return; + } + + isClaimOwnershipEmpty(); + + Set ownerData; + String player = playerName.toLowerCase(); + + for (Entry> entry : claimOwnership.entrySet()) { + ownerData = entry.getValue(); + + if (ownerData == null) { + continue; + } + + Iterator iter = ownerData.iterator(); + while (iter.hasNext()) { + if (iter.next().equals(player)) { + iter.remove(); + } + } + + if (ownerData.isEmpty()) { + claimOwnership.remove(entry.getKey()); + } + } + } + + public int getCountOfClaimsWithOwners() { + return isClaimOwnershipEmpty() ? 0 : claimOwnership.size(); + } + + public boolean doesLocationHaveOwnersSet(FLocation loc) { + if (isClaimOwnershipEmpty() || !claimOwnership.containsKey(loc)) { + return false; + } + Set ownerData = claimOwnership.get(loc); + return ownerData != null && !ownerData.isEmpty(); + } + + public boolean isPlayerInOwnerList(String playerName, FLocation loc) { + if (isClaimOwnershipEmpty()) { + return false; + } + Set ownerData = claimOwnership.get(loc); + if (ownerData == null) { + return false; + } + if (ownerData.contains(playerName.toLowerCase())) { + return true; + } + return false; + } + + public void setPlayerAsOwner(String playerName, FLocation loc) { + isClaimOwnershipEmpty(); + Set ownerData = claimOwnership.get(loc); + if (ownerData == null) { + ownerData = new HashSet(); + } + ownerData.add(playerName.toLowerCase()); + claimOwnership.put(loc, ownerData); + } + + public void removePlayerAsOwner(String playerName, FLocation loc) { + isClaimOwnershipEmpty(); + Set ownerData = claimOwnership.get(loc); + if (ownerData == null) { + return; + } + ownerData.remove(playerName.toLowerCase()); + claimOwnership.put(loc, ownerData); + } + + public Set getOwnerList(FLocation loc) { + isClaimOwnershipEmpty(); + return claimOwnership.get(loc); + } + + public String getOwnerListString(FLocation loc) { + isClaimOwnershipEmpty(); + Set ownerData = claimOwnership.get(loc); + if (ownerData == null || ownerData.isEmpty()) { + return ""; + } + + String ownerList = ""; + + Iterator iter = ownerData.iterator(); + while (iter.hasNext()) { + if (!ownerList.isEmpty()) { + ownerList += ", "; + } + ownerList += iter.next(); + } + return ownerList; + } + + public boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc) { + // different faction? + if (fplayer.getFactionId() != id) { + return false; + } + + // sufficient role to bypass ownership? + if (fplayer.getRole() == (Conf.ownedAreaModeratorsBypass ? Role.MODERATOR : Role.ADMIN)) { + return true; + } + + // make sure claimOwnership is initialized + if (isClaimOwnershipEmpty()) { + return true; + } + + // need to check the ownership list, then + Set ownerData = claimOwnership.get(loc); + + // if no owner list, owner list is empty, or player is in owner list, they're allowed + if (ownerData == null || ownerData.isEmpty() || ownerData.contains(fplayer.getName().toLowerCase())) { + return true; + } + + return false; + } //----------------------------------------------// diff --git a/src/com/massivecraft/factions/Factions.java b/src/com/massivecraft/factions/Factions.java index d9a1c299..4cad945e 100644 --- a/src/com/massivecraft/factions/Factions.java +++ b/src/com/massivecraft/factions/Factions.java @@ -2,10 +2,12 @@ package com.massivecraft.factions; import java.io.File; import java.lang.reflect.Modifier; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -25,6 +27,8 @@ import com.massivecraft.factions.listeners.FactionsChatEarlyListener; import com.massivecraft.factions.listeners.FactionsEntityListener; import com.massivecraft.factions.listeners.FactionsPlayerListener; import com.massivecraft.factions.util.JarLoader; +import com.massivecraft.factions.util.MapFLocToStringSetTypeAdapter; +import com.massivecraft.factions.util.MyLocationTypeAdapter; import com.nijiko.permissions.PermissionHandler; import com.nijikokun.bukkit.Permissions.Permissions; @@ -32,6 +36,7 @@ import com.earth2me.essentials.chat.EssentialsChat; import com.earth2me.essentials.chat.IEssentialsChatListener; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; /** * The data is saved to disk every 30min and on plugin disable. @@ -71,15 +76,18 @@ public class Factions extends JavaPlugin { // Load the gson library we require File gsonfile = new File("./lib/gson.jar"); if ( ! JarLoader.load(gsonfile)) { - log(Level.SEVERE, "Disabling myself as "+gsonfile+" is missing."); + log(Level.SEVERE, "Disabling myself as "+gsonfile.getPath()+" is missing from the root Minecraft server folder."); this.getServer().getPluginManager().disablePlugin(this); return; } + Type mapFLocToStringSetType = new TypeToken>>(){}.getType(); + gson = new GsonBuilder() .setPrettyPrinting() .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE) .registerTypeAdapter(Location.class, new MyLocationTypeAdapter()) + .registerTypeAdapter(mapFLocToStringSetType, new MapFLocToStringSetTypeAdapter()) .create(); // Add the commands @@ -106,6 +114,8 @@ public class Factions extends JavaPlugin { commands.add(new FCommandMap()); commands.add(new FCommandMod()); commands.add(new FCommandOpen()); + commands.add(new FCommandOwner()); + commands.add(new FCommandOwnerList()); commands.add(new FCommandPower()); commands.add(new FCommandRelationAlly()); commands.add(new FCommandRelationEnemy()); @@ -137,8 +147,6 @@ public class Factions extends JavaPlugin { setupPermissions(); integrateEssentialsChat(); - // preload could apparently cause issues; removed since "softdepend" is now available - // Register events PluginManager pm = this.getServer().getPluginManager(); pm.registerEvent(Event.Type.PLAYER_CHAT, this.playerListener, Event.Priority.Highest, this); @@ -177,7 +185,9 @@ public class Factions extends JavaPlugin { this.getServer().getScheduler().cancelTask(saveTask); saveTask = null; } - saveAll(); + if (gson != null) { + saveAll(); + } unhookEssentialsChat(); } @@ -369,6 +379,10 @@ public class Factions extends JavaPlugin { return hasPerm(sender, "factions.viewAnyPower"); } + public static boolean hasPermOwnershipBypass(CommandSender sender) { + return hasPerm(sender, "factions.ownershipBypass"); + } + public static boolean isCommandDisabled(CommandSender sender, String command) { return (hasPerm(sender, "factions.commandDisable."+command) && !hasPerm(sender, "factions.commandDisable.none")); } diff --git a/src/com/massivecraft/factions/commands/FBaseCommand.java b/src/com/massivecraft/factions/commands/FBaseCommand.java index 60cc7cbc..4df12573 100644 --- a/src/com/massivecraft/factions/commands/FBaseCommand.java +++ b/src/com/massivecraft/factions/commands/FBaseCommand.java @@ -2,6 +2,7 @@ package com.massivecraft.factions.commands; import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; import java.util.List; import org.bukkit.command.CommandSender; @@ -89,9 +90,12 @@ public class FBaseCommand { } // make sure player doesn't have their access to the command revoked - if (Factions.isCommandDisabled(sender, aliases.get(0))) { - sendMessage("You lack the permissions to "+this.helpDescription.toLowerCase()+"."); - return false; + Iterator iter = aliases.iterator(); + while (iter.hasNext()) { + if (Factions.isCommandDisabled(sender, iter.next())) { + sendMessage("You lack the permissions to "+this.helpDescription.toLowerCase()+"."); + return false; + } } if (parameters.size() < requiredParameters.size()) { diff --git a/src/com/massivecraft/factions/commands/FCommandHelp.java b/src/com/massivecraft/factions/commands/FCommandHelp.java index e804e232..476bea68 100644 --- a/src/com/massivecraft/factions/commands/FCommandHelp.java +++ b/src/com/massivecraft/factions/commands/FCommandHelp.java @@ -92,10 +92,22 @@ public class FCommandHelp extends FBaseCommand { pageLines = new ArrayList(); pageLines.add( new FCommandMap().getUseageTemplate() ); + pageLines.add(""); + pageLines.add(""); + pageLines.add( new FCommandOwner().getUseageTemplate() ); + pageLines.add( new FCommandOwnerList().getUseageTemplate() ); + pageLines.add(""); + pageLines.add("Claimed land with ownership set is further protected so"); + pageLines.add("that only the owner(s), faction admin, and possibly the"); + pageLines.add("faction moderators have full access."); + helpPages.add(pageLines); + + pageLines = new ArrayList(); pageLines.add( new FCommandRelationAlly().getUseageTemplate() ); pageLines.add( new FCommandRelationNeutral().getUseageTemplate() ); pageLines.add( new FCommandRelationEnemy().getUseageTemplate() ); pageLines.add(""); + pageLines.add(""); pageLines.add("Set the relation you WISH to have with another faction."); pageLines.add("Your default relation with other factions will be neutral."); pageLines.add("If BOTH factions choose \"ally\" you will be allies."); diff --git a/src/com/massivecraft/factions/commands/FCommandOwner.java b/src/com/massivecraft/factions/commands/FCommandOwner.java new file mode 100644 index 00000000..0ba17535 --- /dev/null +++ b/src/com/massivecraft/factions/commands/FCommandOwner.java @@ -0,0 +1,100 @@ +package com.massivecraft.factions.commands; + +import com.massivecraft.factions.Board; +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.struct.Role; + + +public class FCommandOwner extends FBaseCommand { + + public FCommandOwner() { + aliases.add("owner"); + + optionalParameters.add("player name"); + + helpDescription = "set ownership of claimed land"; + } + + @Override + public void perform() { + boolean hasBypass = Factions.hasPermAdminBypass(player); + + if ( ! hasBypass && ! assertHasFaction()) { + return; + } + + if( isLocked() ) { + sendLockMessage(); + return; + } + + if ( ! Conf.ownedAreasEnabled) { + me.sendMessage("Sorry, but owned areas are disabled on this server."); + return; + } + + Faction myFaction = me.getFaction(); + + if (!hasBypass && Conf.ownedAreasLimitPerFaction > 0 && myFaction.getCountOfClaimsWithOwners() >= Conf.ownedAreasLimitPerFaction) { + me.sendMessage("Sorry, but you have reached the server's limit of "+Conf.ownedAreasLimitPerFaction+" owned areas per faction."); + return; + } + + if (!hasBypass && !assertMinRole(Conf.ownedAreasModeratorsCanSet ? Role.MODERATOR : Role.ADMIN)) { + return; + } + + FLocation flocation = new FLocation(me); + + if (Board.getIdAt(flocation) != myFaction.getId()) { + if (!hasBypass) { + me.sendMessage("This land is not claimed by your faction, so you can't set ownership of it."); + return; + } + + myFaction = Board.getFactionAt(flocation); + if (!myFaction.isNormal()) { + me.sendMessage("This land is not claimed by a faction. Ownership is not possible."); + return; + } + } + + FPlayer target; + + if (parameters.size() > 0) { + target = findFPlayer(parameters.get(0), false); + } else { + target = me; + } + if (target == null) { + return; + } + + String playerName = target.getName(); + + if (target.getFaction().getId() != myFaction.getId()) { + me.sendMessage(playerName + " is not a member of this faction."); + return; + } + + // if no player name was passed, and this claim does already have owners set, clear them + if (parameters.isEmpty() && myFaction.doesLocationHaveOwnersSet(flocation)) { + myFaction.clearClaimOwnership(flocation); + me.sendMessage("You have cleared ownership for this claimed area."); + return; + } + + if (myFaction.isPlayerInOwnerList(playerName, flocation)) { + myFaction.removePlayerAsOwner(playerName, flocation); + me.sendMessage("You have removed ownership of this claimed land from "+playerName+"."); + return; + } + + myFaction.setPlayerAsOwner(playerName, flocation); + me.sendMessage("You have added "+playerName+" to the owner list for this claimed land."); + } +} diff --git a/src/com/massivecraft/factions/commands/FCommandOwnerList.java b/src/com/massivecraft/factions/commands/FCommandOwnerList.java new file mode 100644 index 00000000..6e0bc8a1 --- /dev/null +++ b/src/com/massivecraft/factions/commands/FCommandOwnerList.java @@ -0,0 +1,59 @@ +package com.massivecraft.factions.commands; + +import java.util.Set; +import java.util.Iterator; + +import com.massivecraft.factions.Board; +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; + + +public class FCommandOwnerList extends FBaseCommand { + + public FCommandOwnerList() { + aliases.add("ownerlist"); + + helpDescription = "list owner(s) of this claimed land"; + } + + @Override + public void perform() { + boolean hasBypass = Factions.hasPermAdminBypass(player); + + if ( ! hasBypass && ! assertHasFaction()) { + return; + } + + if ( ! Conf.ownedAreasEnabled) { + me.sendMessage("Owned areas are disabled on this server."); + return; + } + + Faction myFaction = me.getFaction(); + FLocation flocation = new FLocation(me); + + if (Board.getIdAt(flocation) != myFaction.getId()) { + if (!hasBypass) { + me.sendMessage("This land is not claimed by your faction."); + return; + } + + myFaction = Board.getFactionAt(flocation); + if (!myFaction.isNormal()) { + me.sendMessage("This land is not claimed by any faction, thus no owners."); + return; + } + } + + String owners = myFaction.getOwnerListString(flocation); + + if (owners == null || owners.isEmpty()) { + me.sendMessage("No owners are set here; everyone in the faction has access."); + return; + } + + me.sendMessage("Current owner(s) of this land: "+owners); + } +} diff --git a/src/com/massivecraft/factions/listeners/FactionsBlockListener.java b/src/com/massivecraft/factions/listeners/FactionsBlockListener.java index 384010c2..d258f924 100644 --- a/src/com/massivecraft/factions/listeners/FactionsBlockListener.java +++ b/src/com/massivecraft/factions/listeners/FactionsBlockListener.java @@ -153,10 +153,10 @@ public class FactionsBlockListener extends BlockListener { return true; } - Faction otherFaction = Board.getFactionAt(new FLocation(block)); - + FLocation loc = new FLocation(block); + Faction otherFaction = Board.getFactionAt(loc); FPlayer me = FPlayer.get(player); - + if (otherFaction.isNone()) { if (!Conf.wildernessDenyBuild || Factions.hasPermAdminBypass(player)) { return true; // This is not faction territory. Use whatever you like here. @@ -193,6 +193,16 @@ public class FactionsBlockListener extends BlockListener { return false; } } + // Also cancel if player doesn't have ownership rights for this claim + else if ( + Conf.ownedAreasEnabled + && Conf.ownedAreaDenyBuild + && !myFaction.playerHasOwnershipRights(me, loc) + && !Factions.hasPermOwnershipBypass(player) + ) { + me.sendMessage("You can't "+action+" in this territory, it is owned by: "+myFaction.getOwnerListString(loc)); + return false; + } return true; } diff --git a/src/com/massivecraft/factions/listeners/FactionsEntityListener.java b/src/com/massivecraft/factions/listeners/FactionsEntityListener.java index b3176fa2..d3b76fd3 100644 --- a/src/com/massivecraft/factions/listeners/FactionsEntityListener.java +++ b/src/com/massivecraft/factions/listeners/FactionsEntityListener.java @@ -311,7 +311,6 @@ public class FactionsEntityListener extends EntityListener { } Faction otherFaction = Board.getFactionAt(loc); - FPlayer me = FPlayer.get(player); if (otherFaction.isNone()) { @@ -351,6 +350,16 @@ public class FactionsEntityListener extends EntityListener { return false; } } + // Also cancel if player doesn't have ownership rights for this claim + else if ( + Conf.ownedAreasEnabled + && Conf.ownedAreaDenyBuild + && !myFaction.playerHasOwnershipRights(me, loc) + && !Factions.hasPermOwnershipBypass(player) + ) { + me.sendMessage("You can't "+action+" paintings in this territory, it is owned by: "+myFaction.getOwnerListString(loc)); + return false; + } return true; } diff --git a/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java b/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java index 7d5b48ce..11bd1edf 100644 --- a/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java +++ b/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java @@ -123,16 +123,20 @@ public class FactionsPlayerListener extends PlayerListener{ // Make sure player's power is up to date when they log off. FPlayer me = FPlayer.get(event.getPlayer()); me.getPower(); - me.getFaction().memberLoggedOff(); + Faction myFaction = me.getFaction(); + if (myFaction != null) { + myFaction.memberLoggedOff(); + } } @Override public void onPlayerMove(PlayerMoveEvent event) { - FPlayer me = FPlayer.get(event.getPlayer()); + Player player = event.getPlayer(); + FPlayer me = FPlayer.get(player); // Did we change coord? FLocation from = me.getLastStoodAt(); - FLocation to = new FLocation(event.getPlayer().getLocation()); + FLocation to = new FLocation(player.getLocation()); if (from.equals(to)) { return; @@ -143,7 +147,7 @@ public class FactionsPlayerListener extends PlayerListener{ me.setLastStoodAt(to); if (me.isMapAutoUpdating()) { - me.sendMessage(Board.getMap(me.getFaction(), to, me.getPlayer().getLocation().getYaw())); + me.sendMessage(Board.getMap(me.getFaction(), to, player.getLocation().getYaw())); } else { // Did we change "host"(faction)? Faction factionFrom = Board.getFactionAt(from); @@ -173,7 +177,7 @@ public class FactionsPlayerListener extends PlayerListener{ me.attemptClaim(false); } else if (me.autoSafeZoneEnabled()) { - if (!Factions.hasPermManageSafeZone((CommandSender)event.getPlayer())) { + if (!Factions.hasPermManageSafeZone((CommandSender)player)) { me.enableAutoSafeZone(false); } else { FLocation playerFlocation = new FLocation(me); @@ -185,7 +189,7 @@ public class FactionsPlayerListener extends PlayerListener{ } } else if (me.autoWarZoneEnabled()) { - if (!Factions.hasPermManageWarZone((CommandSender)event.getPlayer())) { + if (!Factions.hasPermManageWarZone((CommandSender)player)) { me.enableAutoWarZone(false); } else { FLocation playerFlocation = new FLocation(me); @@ -232,7 +236,8 @@ public class FactionsPlayerListener extends PlayerListener{ return true; } - Faction otherFaction = Board.getFactionAt(new FLocation(block)); + FLocation loc = new FLocation(block); + Faction otherFaction = Board.getFactionAt(loc); if (otherFaction.hasPlayersOnline()){ if ( ! Conf.territoryDenyUseageMaterials.contains(material)) { @@ -272,8 +277,20 @@ public class FactionsPlayerListener extends PlayerListener{ boolean areEnemies = myFaction.getRelation(otherFaction).isEnemy(); // Cancel if we are not in our own territory - if (myFaction != otherFaction && (areEnemies ? Conf.territoryEnemyDenyUseage : Conf.territoryDenyUseage)) { - me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the territory of "+otherFaction.getTag(myFaction)); + if (myFaction != otherFaction) { + if (areEnemies ? Conf.territoryEnemyDenyUseage : Conf.territoryDenyUseage) { + me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the territory of "+otherFaction.getTag(myFaction)); + return false; + } + } + // Also cancel if player doesn't have ownership rights for this claim + else if ( + Conf.ownedAreasEnabled + && Conf.ownedAreaDenyUseage + && !myFaction.playerHasOwnershipRights(me, loc) + && !Factions.hasPermOwnershipBypass(player) + ) { + me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in this territory, it is owned by: "+myFaction.getOwnerListString(loc)); return false; } @@ -287,8 +304,8 @@ public class FactionsPlayerListener extends PlayerListener{ } Material material = block.getType(); - - Faction otherFaction = Board.getFactionAt(new FLocation(block)); + FLocation loc = new FLocation(block); + Faction otherFaction = Board.getFactionAt(loc); // We only care about some material types. if (otherFaction.hasPlayersOnline()){ @@ -313,6 +330,17 @@ public class FactionsPlayerListener extends PlayerListener{ me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the territory of "+otherFaction.getTag(myFaction)); return false; } + // Also cancel if player doesn't have ownership rights for this claim + else if ( + myFaction == otherFaction + && Conf.ownedAreasEnabled + && Conf.ownedAreaProtectMaterials + && !myFaction.playerHasOwnershipRights(me, loc) + && !Factions.hasPermOwnershipBypass(player) + ) { + me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in this territory, it is owned by: "+myFaction.getOwnerListString(loc)); + return false; + } return true; } diff --git a/src/com/massivecraft/factions/util/MapFLocToStringSetTypeAdapter.java b/src/com/massivecraft/factions/util/MapFLocToStringSetTypeAdapter.java new file mode 100644 index 00000000..5f8e77fb --- /dev/null +++ b/src/com/massivecraft/factions/util/MapFLocToStringSetTypeAdapter.java @@ -0,0 +1,112 @@ +package com.massivecraft.factions.util; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.Map.Entry; + +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.Factions; + + +public class MapFLocToStringSetTypeAdapter implements JsonDeserializer>>, JsonSerializer>> { + + @Override + public Map> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + try { + JsonObject obj = json.getAsJsonObject(); + if (obj == null) { + return null; + } + + Map> locationMap = new HashMap>(); + Set nameSet; + Iterator iter; + String worldName; + String[] coords; + int x, z; + + for (Entry entry : obj.entrySet()) { + worldName = entry.getKey(); + for (Entry entry2 : entry.getValue().getAsJsonObject().entrySet()) { + coords = entry2.getKey().trim().split("[,\\s]+"); + x = Integer.parseInt(coords[0]); + z = Integer.parseInt(coords[1]); + + nameSet = new HashSet(); + iter = entry2.getValue().getAsJsonArray().iterator(); + while (iter.hasNext()) { + nameSet.add(iter.next().getAsString()); + } + + locationMap.put(new FLocation(worldName, x, z), nameSet); + } + } + + return locationMap; + + } catch (Exception ex) { + ex.printStackTrace(); + Factions.log(Level.WARNING, "Error encountered while deserializing a Map of FLocations to String Sets."); + return null; + } + } + + @Override + public JsonElement serialize(Map> src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + + try { + if (src != null) { + FLocation loc; + String locWorld; + Set nameSet; + Iterator iter; + JsonArray nameArray; + JsonPrimitive nameElement; + + for (Entry> entry : src.entrySet()) { + loc = entry.getKey(); + locWorld = loc.getWorldName(); + nameSet = entry.getValue(); + + if (nameSet == null || nameSet.isEmpty()) { + continue; + } + + nameArray = new JsonArray(); + iter = nameSet.iterator(); + while (iter.hasNext()) { + nameElement = new JsonPrimitive(iter.next()); + nameArray.add(nameElement); + } + + if ( ! obj.has(locWorld)) { + obj.add(locWorld, new JsonObject()); + } + + obj.get(locWorld).getAsJsonObject().add(loc.getCoordString(), nameArray); + } + } + return obj; + + } catch (Exception ex) { + ex.printStackTrace(); + Factions.log(Level.WARNING, "Error encountered while serializing a Map of FLocations to String Sets."); + return obj; + } + } +} diff --git a/src/com/massivecraft/factions/MyLocationTypeAdapter.java b/src/com/massivecraft/factions/util/MyLocationTypeAdapter.java similarity index 96% rename from src/com/massivecraft/factions/MyLocationTypeAdapter.java rename to src/com/massivecraft/factions/util/MyLocationTypeAdapter.java index 0c31e17b..71d56ea2 100644 --- a/src/com/massivecraft/factions/MyLocationTypeAdapter.java +++ b/src/com/massivecraft/factions/util/MyLocationTypeAdapter.java @@ -1,4 +1,4 @@ -package com.massivecraft.factions; +package com.massivecraft.factions.util; import java.lang.reflect.Type; import java.util.logging.Level; @@ -13,6 +13,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; +import com.massivecraft.factions.Factions; public class MyLocationTypeAdapter implements JsonDeserializer, JsonSerializer { diff --git a/src/plugin.yml b/src/plugin.yml index 1e210faa..0c7843d8 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -19,16 +19,17 @@ permissions: factions.participate: true factions.create: true factions.viewAnyPower: true + factions.adminBypass: true + factions.config: true + factions.disband: true + factions.lock: true factions.manageSafeZone: true factions.manageWarZone: true - factions.adminBypass: true + factions.ownershipBypass: true factions.reload: true factions.saveall: true - factions.lock: true - factions.disband: true factions.worldOptions: true factions.commandDisable.none: true - factions.config: true factions.participate: description: Allows the player to participate in a faction default: true @@ -38,14 +39,26 @@ permissions: factions.viewAnyPower: description: Allows the player to view the power level of anyone else default: true + factions.adminBypass: + description: Allows the player to bypass many normal restrictions, and use the bypass command + default: op + factions.config: + description: Can use /f config command to change conf.json options + default: op + factions.disband: + description: Can use the /f disband command to disband any faction + default: op + factions.lock: + description: Can use the /f lock [on/off] command to temporarily lock the data files from being overwritten + default: op factions.manageSafeZone: description: Allows the player to claim land as a safe zone, and to build/destroy within safe zones default: op factions.manageWarZone: description: Allows the player to claim land as a war zone, and to build/destroy within war zones default: op - factions.adminBypass: - description: Allows the player to bypass many normal restrictions, and use the bypass command + factions.ownershipBypass: + description: Allows the player to bypass ownership restrictions within own faction's territory default: op factions.reload: description: Can use the /f reload command to reload data file(s) from disk @@ -53,18 +66,9 @@ permissions: factions.saveall: description: Can use the /f saveall command to save all data to disk default: op - factions.lock: - description: Can use the /f lock [on/off] command to temporarily lock the data files from being overwritten - default: op - factions.disband: - description: Can use the /f disband command to disband any faction - default: op factions.worldOptions: description: Can use the /f worldnoclaim and /f worldnopowerloss commands default: op - factions.config: - description: Can use /f config command to change conf.json options - default: op factions.commandDisable.none: description: no commands disabled (ignore all other commandDisable permissions) default: op @@ -86,6 +90,9 @@ permissions: factions.commandDisable.chat: description: chat command disabled default: false + factions.commandDisable.c: + description: chat command disabled + default: false factions.commandDisable.claim: description: claim command disabled default: false @@ -95,6 +102,9 @@ permissions: factions.commandDisable.deinvite: description: deinvite command disabled default: false + factions.commandDisable.deinv: + description: deinvite command disabled + default: false factions.commandDisable.desc: description: desc command disabled default: false @@ -104,12 +114,21 @@ permissions: factions.commandDisable.help: description: help command disabled default: false + factions.commandDisable.h: + description: help command disabled + default: false + factions.commandDisable.?: + description: help command disabled + default: false factions.commandDisable.home: description: home command disabled default: false factions.commandDisable.invite: description: invite command disabled default: false + factions.commandDisable.inv: + description: invite command disabled + default: false factions.commandDisable.join: description: join command disabled default: false @@ -122,6 +141,9 @@ permissions: factions.commandDisable.list: description: list command disabled default: false + factions.commandDisable.ls: + description: list command disabled + default: false factions.commandDisable.lock: description: lock command disabled default: false @@ -134,9 +156,21 @@ permissions: factions.commandDisable.open: description: open command disabled default: false + factions.commandDisable.close: + description: open command disabled + default: false + factions.commandDisable.owner: + description: owner command disabled + default: false + factions.commandDisable.ownerlist: + description: ownerlist command disabled + default: false factions.commandDisable.power: description: power command disabled default: false + factions.commandDisable.pow: + description: power command disabled + default: false factions.commandDisable.ally: description: ally command disabled default: false @@ -152,18 +186,30 @@ permissions: factions.commandDisable.safeclaim: description: safeclaim command disabled default: false + factions.commandDisable.safe: + description: safeclaim command disabled + default: false factions.commandDisable.safeunclaimall: description: safeunclaimall command disabled default: false + factions.commandDisable.safedeclaimall: + description: safeunclaimall command disabled + default: false factions.commandDisable.saveall: description: saveall command disabled default: false + factions.commandDisable.save: + description: saveall command disabled + default: false factions.commandDisable.sethome: description: sethome command disabled default: false factions.commandDisable.show: description: show command disabled default: false + factions.commandDisable.who: + description: show command disabled + default: false factions.commandDisable.tag: description: tag command disabled default: false @@ -173,18 +219,30 @@ permissions: factions.commandDisable.unclaim: description: unclaim command disabled default: false + factions.commandDisable.declaim: + description: unclaim command disabled + default: false factions.commandDisable.unclaimall: description: unclaimall command disabled default: false + factions.commandDisable.declaimall: + description: unclaimall command disabled + default: false factions.commandDisable.version: description: version command disabled default: false factions.commandDisable.warclaim: description: warclaim command disabled default: false + factions.commandDisable.war: + description: warclaim command disabled + default: false factions.commandDisable.warunclaimall: description: warunclaimall command disabled default: false + factions.commandDisable.wardeclaimall: + description: warunclaimall command disabled + default: false factions.commandDisable.worldnoclaim: description: worldnoclaim command disabled default: false