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