diff --git a/plugin.yml b/plugin.yml index 64093aa3..8b15f9c8 100644 --- a/plugin.yml +++ b/plugin.yml @@ -30,6 +30,7 @@ permissions: factions.join.others: true factions.leader.any: true factions.officer.any: true + factions.access.any: true factions.kit.halfmod: description: Can use adminmode and chat spy children: @@ -43,6 +44,8 @@ permissions: factions.kit.halfplayer: description: Can do all but create factions. children: + factions.access: true + factions.access.view: true factions.autoclaim: true factions.cape: true factions.cape.*: true @@ -75,6 +78,12 @@ permissions: factions.unclaim: true factions.unclaimall: true factions.version: true + factions.access: + description: grant territory access for your faction, with the proper fperm + factions.access.any: + description: grant territory access for any faction + factions.access.view: + description: view territory access info for your faction factions.adminmode: description: enable admin bypass mode factions.autoclaim: diff --git a/src/com/massivecraft/factions/Board.java b/src/com/massivecraft/factions/Board.java index f10eaf18..ea1d7f8d 100644 --- a/src/com/massivecraft/factions/Board.java +++ b/src/com/massivecraft/factions/Board.java @@ -16,6 +16,7 @@ import org.bukkit.block.Block; import com.google.gson.reflect.TypeToken; import com.massivecraft.factions.integration.LWCFeatures; import com.massivecraft.factions.iface.RelationParticipator; +import com.massivecraft.factions.struct.TerritoryAccess; import com.massivecraft.factions.util.AsciiCompass; import com.massivecraft.factions.zcore.util.DiscUtil; @@ -23,21 +24,25 @@ import com.massivecraft.factions.zcore.util.DiscUtil; public class Board { private static transient File file = new File(P.p.getDataFolder(), "board.json"); - private static transient HashMap flocationIds = new HashMap(); + private static transient HashMap flocationIds = new HashMap(); //----------------------------------------------// // Get and Set //----------------------------------------------// public static String getIdAt(FLocation flocation) { - if ( ! flocationIds.containsKey(flocation)) - { - return "0"; - } + if ( ! flocationIds.containsKey(flocation)) return "0"; + return flocationIds.get(flocation).getHostFactionID(); + } + + public static TerritoryAccess getTerritoryAccessAt(FLocation flocation) + { + if ( ! flocationIds.containsKey(flocation)) + flocationIds.put(flocation, new TerritoryAccess("0")); return flocationIds.get(flocation); } - + public static Faction getFactionAt(FLocation flocation) { return Factions.i.get(getIdAt(flocation)); @@ -54,11 +59,9 @@ public class Board public static void setIdAt(String id, FLocation flocation) { if (id == "0") - { removeAt(flocation); - } - - flocationIds.put(flocation, id); + + flocationIds.put(flocation, new TerritoryAccess(id)); } public static void setFactionAt(Faction faction, FLocation flocation) @@ -76,11 +79,11 @@ public class Board public static void unclaimAll(String factionId) { - Iterator> iter = flocationIds.entrySet().iterator(); + Iterator> iter = flocationIds.entrySet().iterator(); while (iter.hasNext()) { - Entry entry = iter.next(); - if (entry.getValue().equals(factionId)) + Entry entry = iter.next(); + if (entry.getValue().getHostFactionID().equals(factionId)) { if(Conf.onUnclaimResetLwcLocks && LWCFeatures.getEnabled()) LWCFeatures.clearAllChests(entry.getKey()); @@ -119,15 +122,15 @@ public class Board public static void clean() { - Iterator> iter = flocationIds.entrySet().iterator(); + Iterator> iter = flocationIds.entrySet().iterator(); while (iter.hasNext()) { - Entry entry = iter.next(); - if ( ! Factions.i.exists(entry.getValue())) + Entry entry = iter.next(); + if ( ! Factions.i.exists(entry.getValue().getHostFactionID())) { if(Conf.onUnclaimResetLwcLocks && LWCFeatures.getEnabled()) LWCFeatures.clearAllChests(entry.getKey()); - P.p.log("Board cleaner removed "+entry.getValue()+" from "+entry.getKey()); + P.p.log("Board cleaner removed "+entry.getValue().getHostFactionID()+" from "+entry.getKey()); iter.remove(); } } @@ -140,9 +143,9 @@ public class Board public static int getFactionCoordCount(String factionId) { int ret = 0; - for (String thatFactionId : flocationIds.values()) + for (TerritoryAccess thatFactionId : flocationIds.values()) { - if(thatFactionId.equals(factionId)) + if(thatFactionId.getHostFactionID().equals(factionId)) { ret += 1; } @@ -159,10 +162,10 @@ public class Board { String factionId = faction.getId(); int ret = 0; - Iterator> iter = flocationIds.entrySet().iterator(); + Iterator> iter = flocationIds.entrySet().iterator(); while (iter.hasNext()) { - Entry entry = iter.next(); - if (entry.getValue().equals(factionId) && entry.getKey().getWorldName().equals(worldName)) + Entry entry = iter.next(); + if (entry.getValue().getHostFactionID().equals(factionId) && entry.getKey().getWorldName().equals(worldName)) { ret += 1; } @@ -252,48 +255,48 @@ public class Board // Persistance // -------------------------------------------- // - public static Map> dumpAsSaveFormat() + public static Map> dumpAsSaveFormat() { - Map> worldCoordIds = new HashMap>(); + Map> worldCoordIds = new HashMap>(); String worldName, coords; - String id; + TerritoryAccess data; - for (Entry entry : flocationIds.entrySet()) + for (Entry entry : flocationIds.entrySet()) { worldName = entry.getKey().getWorldName(); coords = entry.getKey().getCoordString(); - id = entry.getValue(); + data = entry.getValue(); if ( ! worldCoordIds.containsKey(worldName)) { - worldCoordIds.put(worldName, new TreeMap()); + worldCoordIds.put(worldName, new TreeMap()); } - worldCoordIds.get(worldName).put(coords, id); + worldCoordIds.get(worldName).put(coords, data); } return worldCoordIds; } - public static void loadFromSaveFormat(Map> worldCoordIds) + public static void loadFromSaveFormat(Map> worldCoordIds) { flocationIds.clear(); String worldName; String[] coords; int x, z; - String factionId; + TerritoryAccess data; - for (Entry> entry : worldCoordIds.entrySet()) + for (Entry> entry : worldCoordIds.entrySet()) { worldName = entry.getKey(); - for (Entry entry2 : entry.getValue().entrySet()) + for (Entry entry2 : entry.getValue().entrySet()) { 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); + data = entry2.getValue(); + flocationIds.put(new FLocation(worldName, x, z), data); } } } @@ -329,8 +332,8 @@ public class Board try { - Type type = new TypeToken>>(){}.getType(); - Map> worldCoordIds = P.p.gson.fromJson(DiscUtil.read(file), type); + Type type = new TypeToken>>(){}.getType(); + Map> worldCoordIds = P.p.gson.fromJson(DiscUtil.read(file), type); loadFromSaveFormat(worldCoordIds); } catch (Exception e) diff --git a/src/com/massivecraft/factions/P.java b/src/com/massivecraft/factions/P.java index 38d9f8d7..bab619e5 100644 --- a/src/com/massivecraft/factions/P.java +++ b/src/com/massivecraft/factions/P.java @@ -1,10 +1,8 @@ package com.massivecraft.factions; import java.lang.reflect.Modifier; -import java.lang.reflect.Type; import java.util.Arrays; import java.util.HashSet; -import java.util.Map; import java.util.Set; import org.bukkit.block.Block; @@ -16,7 +14,6 @@ import org.bukkit.Location; import org.bukkit.Material; import com.massivecraft.factions.adapters.FFlagTypeAdapter; -import com.massivecraft.factions.adapters.FLocToStringSetTypeAdapter; import com.massivecraft.factions.adapters.FPermTypeAdapter; import com.massivecraft.factions.adapters.LocationTypeAdapter; import com.massivecraft.factions.adapters.RelTypeAdapter; @@ -38,13 +35,13 @@ import com.massivecraft.factions.listeners.FactionsServerListener; import com.massivecraft.factions.struct.FFlag; import com.massivecraft.factions.struct.FPerm; import com.massivecraft.factions.struct.Rel; +import com.massivecraft.factions.struct.TerritoryAccess; import com.massivecraft.factions.util.AutoLeaveTask; import com.massivecraft.factions.util.LazyLocation; import com.massivecraft.factions.zcore.MPlugin; import com.massivecraft.factions.zcore.util.TextUtil; import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; public class P extends MPlugin @@ -135,14 +132,12 @@ public class P extends MPlugin @Override public GsonBuilder getGsonBuilder() { - Type mapFLocToStringSetType = new TypeToken>>(){}.getType(); - return new GsonBuilder() .setPrettyPrinting() .disableHtmlEscaping() .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE) .registerTypeAdapter(LazyLocation.class, new LocationTypeAdapter()) - .registerTypeAdapter(mapFLocToStringSetType, new FLocToStringSetTypeAdapter()) + .registerTypeAdapter(TerritoryAccess.class, new TerritoryAccess()) .registerTypeAdapter(Rel.class, new RelTypeAdapter()) .registerTypeAdapter(FPerm.class, new FPermTypeAdapter()) .registerTypeAdapter(FFlag.class, new FFlagTypeAdapter()); diff --git a/src/com/massivecraft/factions/cmd/CmdAccess.java b/src/com/massivecraft/factions/cmd/CmdAccess.java new file mode 100644 index 00000000..047cd53a --- /dev/null +++ b/src/com/massivecraft/factions/cmd/CmdAccess.java @@ -0,0 +1,110 @@ +package com.massivecraft.factions.cmd; + +import com.massivecraft.factions.Board; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.struct.FPerm; +import com.massivecraft.factions.struct.Permission; +import com.massivecraft.factions.struct.TerritoryAccess; +import com.massivecraft.factions.zcore.util.TextUtil; + + +public class CmdAccess extends FCommand +{ + public CmdAccess() + { + super(); + this.aliases.add("access"); + + this.optionalArgs.put("view|p|f|player|faction", "view"); + this.optionalArgs.put("name", "you"); + + this.setHelpShort("view or grant access for the claimed territory you are in"); + + this.disableOnLock = true; + + senderMustBePlayer = true; + senderMustBeMember = false; + senderMustBeOfficer = false; + senderMustBeLeader = false; + } + + @Override + public void perform() + { + String type = this.argAsString(0); + type = (type == null) ? "" : type.toLowerCase(); + + TerritoryAccess territory = Board.getTerritoryAccessAt(new FLocation(me.getLocation())); + Faction locFaction = territory.getHostFaction(); + boolean accessAny = Permission.ACCESS_ANY.has(sender, false); + + if (type.isEmpty() || type.equals("view")) + { + if ( ! accessAny && ! Permission.ACCESS_VIEW.has(sender, true)) return; + if ( ! accessAny && ! territory.doesHostFactionMatch(fme)) + { + msg("This territory isn't controlled by your faction, so you can't view the access list."); + return; + } + showAccessList(territory, locFaction); + return; + } + + if ( ! accessAny && ! Permission.ACCESS.has(sender, true)) return; + if ( ! accessAny && ! FPerm.ACCESS.has(fme, locFaction, true)) return; + + boolean doPlayer = true; + if (type.equals("f") || type.equals("faction")) + { + doPlayer = false; + } + else if (!type.equals("p") && !type.equals("player")) + { + msg("You must specify \"p\" or \"player\" to indicate a player or \"f\" or \"faction\" to indicate a faction."); + msg("ex. /f access p SomePlayer -or- /f access f SomeFaction"); + msg("Alternately, you can use the command with nothing (or \"view\") specified to simply view the access list."); + return; + } + + String target = ""; + boolean added; + + if (doPlayer) + { + FPlayer targetPlayer = this.argAsBestFPlayerMatch(1, fme); + if (targetPlayer == null) return; + added = territory.toggleFPlayer(targetPlayer); + target = "Player \""+targetPlayer.getName()+"\""; + } + else + { + Faction targetFaction = this.argAsFaction(1, myFaction); + if (targetFaction == null) return; + added = territory.toggleFaction(targetFaction); + target = "Faction \""+targetFaction.getTag()+"\""; + } + + msg("%s has been %s the access list for this territory.", target, TextUtil.parseColor(added ? "added to" : "removed from")); + showAccessList(territory, locFaction); + } + + private void showAccessList(TerritoryAccess territory, Faction locFaction) + { + msg("Host faction %s has %s in this territory.", locFaction.getTag(), TextUtil.parseColor(territory.isHostFactionAllowed() ? "normal access" : "restricted access")); + + String players = territory.fplayerList(); + String factions = territory.factionList(); + + if (factions.isEmpty()) + msg("No factions have been explicitly granted access."); + else + msg("Factions with explicit access: " + factions); + + if (players.isEmpty()) + msg("No players have been explicitly granted access."); + else + msg("Players with explicit access: " + players); + } +} diff --git a/src/com/massivecraft/factions/cmd/FCmdRoot.java b/src/com/massivecraft/factions/cmd/FCmdRoot.java index bc714cfb..fcb84a49 100644 --- a/src/com/massivecraft/factions/cmd/FCmdRoot.java +++ b/src/com/massivecraft/factions/cmd/FCmdRoot.java @@ -7,6 +7,7 @@ import com.massivecraft.factions.P; public class FCmdRoot extends FCommand { + public CmdAccess cmdAccess = new CmdAccess(); public CmdLeader cmdLeader = new CmdLeader(); public CmdAutoClaim cmdAutoClaim = new CmdAutoClaim(); public CmdAdmin cmdBypass = new CmdAdmin(); @@ -89,6 +90,7 @@ public class FCmdRoot extends FCommand this.addSubCommand(this.cmdAutoClaim); this.addSubCommand(this.cmdUnclaim); this.addSubCommand(this.cmdUnclaimall); + this.addSubCommand(this.cmdAccess); this.addSubCommand(this.cmdKick); this.addSubCommand(this.cmdOfficer); this.addSubCommand(this.cmdLeader); diff --git a/src/com/massivecraft/factions/struct/FPerm.java b/src/com/massivecraft/factions/struct/FPerm.java index 88504182..7140afca 100644 --- a/src/com/massivecraft/factions/struct/FPerm.java +++ b/src/com/massivecraft/factions/struct/FPerm.java @@ -1,6 +1,7 @@ package com.massivecraft.factions.struct; import java.util.Arrays; +import java.util.EnumSet; import java.util.HashSet; import java.util.Set; @@ -35,6 +36,7 @@ public enum FPerm WITHDRAW("withdraw", "withdraw money", Rel.LEADER, Rel.OFFICER), TERRITORY("territory", "claim or unclaim", Rel.LEADER, Rel.OFFICER), CAPE("cape", "set the cape", Rel.LEADER, Rel.OFFICER), + ACCESS("access", "grant territory access", Rel.LEADER, Rel.OFFICER), DISBAND("disband", "disband the faction", Rel.LEADER), PERMS("perms", "manage permissions", Rel.LEADER), ; @@ -71,6 +73,7 @@ public enum FPerm public static FPerm parse(String str) { str = str.toLowerCase(); + if (str.startsWith("a")) return ACCESS; if (str.startsWith("bui")) return BUILD; if (str.startsWith("pa")) return PAINBUILD; if (str.startsWith("do")) return DOOR; @@ -125,7 +128,14 @@ public enum FPerm } return ret; } - + + // Perms which apply strictly to granting territory access + private static final Set TerritoryPerms = EnumSet.of(BUILD, DOOR, BUTTON, LEVER, CONTAINER); + public boolean isTerritoryPerm() + { + return TerritoryPerms.contains(this); + } + private static final String errorpattern = "%s does not allow you to %s."; public boolean has(Object testSubject, Faction hostFaction, boolean informIfNot) { @@ -170,7 +180,26 @@ public enum FPerm } public boolean has(Object testSubject, FLocation floc, boolean informIfNot) { - Faction factionThere = Board.getFactionAt(floc); + TerritoryAccess access = Board.getTerritoryAccessAt(floc); + Faction factionThere = access.getHostFaction(); + if (this.isTerritoryPerm()) + { + if (access.subjectHasAccess(testSubject)) return true; + if ( ! access.isHostFactionAllowed() && access.doesHostFactionMatch(testSubject) && ! FPerm.ACCESS.has(testSubject, factionThere)) + { + if (informIfNot) + { + FPlayer notify = null; + if (testSubject instanceof Player) + notify = FPlayers.i.get((Player)testSubject); + else if (testSubject instanceof FPlayer) + notify = (FPlayer)testSubject; + if (notify != null) + notify.msg("This territory owned by your faction has restricted access."); + } + return false; + } + } return this.has(testSubject, factionThere, informIfNot); } public boolean has(Object testSubject, Location loc, boolean informIfNot) diff --git a/src/com/massivecraft/factions/struct/Permission.java b/src/com/massivecraft/factions/struct/Permission.java index 383782a7..360eb3ef 100644 --- a/src/com/massivecraft/factions/struct/Permission.java +++ b/src/com/massivecraft/factions/struct/Permission.java @@ -5,6 +5,9 @@ import com.massivecraft.factions.P; public enum Permission { + ACCESS("access"), + ACCESS_ANY("access.any"), + ACCESS_VIEW("access.view"), ADMIN("adminmode"), AUTOCLAIM("autoclaim"), CAPE("cape"), diff --git a/src/com/massivecraft/factions/struct/TerritoryAccess.java b/src/com/massivecraft/factions/struct/TerritoryAccess.java new file mode 100644 index 00000000..6bace464 --- /dev/null +++ b/src/com/massivecraft/factions/struct/TerritoryAccess.java @@ -0,0 +1,337 @@ +package com.massivecraft.factions.struct; + +import java.lang.reflect.Type; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.logging.Level; + +import org.bukkit.entity.Player; + +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.P; + +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.FPlayers; + + +public class TerritoryAccess implements JsonDeserializer, JsonSerializer +{ + private String hostFactionID; + private boolean hostFactionAllowed = true; + private Set factionIDs = new LinkedHashSet(); + private Set fplayerIDs = new LinkedHashSet(); + + + public TerritoryAccess(String factionID) + { + hostFactionID = factionID; + } + + public TerritoryAccess() {} + + + public void setHostFactionID(String factionID) + { + hostFactionID = factionID; + hostFactionAllowed = true; + factionIDs.clear(); + fplayerIDs.clear(); + } + public String getHostFactionID() + { + return hostFactionID; + } + public Faction getHostFaction() + { + return Factions.i.get(hostFactionID); + } + + // considered "default" if host faction is still allowed and nobody has been granted access + public boolean isDefault() + { + return this.hostFactionAllowed && factionIDs.isEmpty() && fplayerIDs.isEmpty(); + } + + public boolean isHostFactionAllowed() + { + return this.hostFactionAllowed; + } + public void setHostFactionAllowed(boolean allowed) + { + this.hostFactionAllowed = allowed; + } + + public boolean doesHostFactionMatch(Object testSubject) + { + if (testSubject instanceof String) + return hostFactionID.equals((String)testSubject); + else if (testSubject instanceof Player) + return hostFactionID.equals(FPlayers.i.get((Player)testSubject).getFactionId()); + else if (testSubject instanceof FPlayer) + return hostFactionID.equals(((FPlayer)testSubject).getFactionId()); + else if (testSubject instanceof Faction) + return hostFactionID.equals(((Faction)testSubject).getId()); + return false; + } + + public void addFaction(String factionID) + { + factionIDs.add(factionID); + } + public void addFaction(Faction faction) + { + addFaction(faction.getId()); + } + + public void addFPlayer(String fplayerID) + { + fplayerIDs.add(fplayerID); + } + public void addFPlayer(FPlayer fplayer) + { + addFPlayer(fplayer.getId()); + } + + public void removeFaction(String factionID) + { + factionIDs.remove(factionID); + } + public void removeFaction(Faction faction) + { + removeFaction(faction.getId()); + } + + public void removeFPlayer(String fplayerID) + { + fplayerIDs.remove(fplayerID); + } + public void removeFPlayer(FPlayer fplayer) + { + removeFPlayer(fplayer.getId()); + } + + // return true if faction was added, false if it was removed + public boolean toggleFaction(String factionID) + { + // if the host faction, special handling + if (doesHostFactionMatch(factionID)) + { + hostFactionAllowed ^= true; + return hostFactionAllowed; + } + + if (factionIDs.contains(factionID)) + { + removeFaction(factionID); + return false; + } + addFaction(factionID); + return true; + } + public boolean toggleFaction(Faction faction) + { + return toggleFaction(faction.getId()); + } + + public boolean toggleFPlayer(String fplayerID) + { + if (fplayerIDs.contains(fplayerID)) + { + removeFPlayer(fplayerID); + return false; + } + addFPlayer(fplayerID); + return true; + } + public boolean toggleFPlayer(FPlayer fplayer) + { + return toggleFPlayer(fplayer.getId()); + } + + public String factionList() + { + StringBuilder list = new StringBuilder(); + for (String factionID : factionIDs) + { + if (list.length() > 0) + list.append(", "); + list.append(Factions.i.get(factionID).getTag()); + } + return list.toString(); + } + + public String fplayerList() + { + StringBuilder list = new StringBuilder(); + for (String fplayerID : fplayerIDs) + { + if (list.length() > 0) + list.append(", "); + list.append(fplayerID); + } + return list.toString(); + } + + // these return false if not granted explicit access, or true if granted explicit access (in FPlayer or Faction lists) + // they do not take into account hostFactionAllowed, which will need to be checked separately (as to not override FPerms which are denied for faction members and such) + public boolean subjectHasAccess(Object testSubject) + { + if (testSubject instanceof Player) + return fPlayerHasAccess(FPlayers.i.get((Player)testSubject)); + else if (testSubject instanceof FPlayer) + return fPlayerHasAccess((FPlayer)testSubject); + else if (testSubject instanceof Faction) + return factionHasAccess((Faction)testSubject); + return false; + } + public boolean fPlayerHasAccess(FPlayer fplayer) + { + if (factionHasAccess(fplayer.getFactionId())) return true; + return fplayerIDs.contains(fplayer.getId()); + } + public boolean factionHasAccess(Faction faction) + { + return factionHasAccess(faction.getId()); + } + public boolean factionHasAccess(String factionID) + { + return factionIDs.contains(factionID); + } + + + //----------------------------------------------// + // JSON Serialize/Deserialize Type Adapters + //----------------------------------------------// + + @Override + public TerritoryAccess deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException + { + try + { + // if stored as simple string, it's just the faction ID and default values are to be used + if (json.isJsonPrimitive()) + { + String factionID = json.getAsString(); + return new TerritoryAccess(factionID); + } + + // otherwise, it's stored as an object and all data should be present + JsonObject obj = json.getAsJsonObject(); + if (obj == null) return null; + + String factionID = obj.get("ID").getAsString(); + boolean hostAllowed = obj.get("open").getAsBoolean(); + JsonArray factions = obj.getAsJsonArray("factions"); + JsonArray fplayers = obj.getAsJsonArray("fplayers"); + + TerritoryAccess access = new TerritoryAccess(factionID); + access.setHostFactionAllowed(hostAllowed); + + Iterator iter = factions.iterator(); + while (iter.hasNext()) + { + access.addFaction(iter.next().getAsString()); + } + + iter = fplayers.iterator(); + while (iter.hasNext()) + { + access.addFPlayer(iter.next().getAsString()); + } + + return access; + + } + catch (Exception ex) + { + ex.printStackTrace(); + P.p.log(Level.WARNING, "Error encountered while deserializing TerritoryAccess data."); + return null; + } + } + + @Override + public JsonElement serialize(TerritoryAccess src, Type typeOfSrc, JsonSerializationContext context) + { + try + { + if (src == null) return null; + + // if default values, store as simple string + if (src.isDefault()) + { + // if Wilderness (faction "0") and default access values, no need to store it + if (src.getHostFactionID().equals("0")) + return null; + + return new JsonPrimitive(src.getHostFactionID()); + } + + // otherwise, store all data + JsonObject obj = new JsonObject(); + + JsonArray factions = new JsonArray(); + JsonArray fplayers = new JsonArray(); + + Iterator iter = src.factionIDs.iterator(); + while (iter.hasNext()) + { + factions.add(new JsonPrimitive(iter.next())); + } + + iter = src.fplayerIDs.iterator(); + while (iter.hasNext()) + { + fplayers.add(new JsonPrimitive(iter.next())); + } + + obj.addProperty("ID", src.getHostFactionID()); + obj.addProperty("open", src.isHostFactionAllowed()); + obj.add("factions", factions); + obj.add("fplayers", fplayers); + + return obj; + + } + catch (Exception ex) + { + ex.printStackTrace(); + P.p.log(Level.WARNING, "Error encountered while serializing TerritoryAccess data."); + return null; + } + } + + + //----------------------------------------------// + // Comparison + //----------------------------------------------// + + @Override + public int hashCode() + { + return this.hostFactionID.hashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (obj == this) + return true; + if (!(obj instanceof TerritoryAccess)) + return false; + + TerritoryAccess that = (TerritoryAccess) obj; + return this.hostFactionID.equals(that.hostFactionID) && this.hostFactionAllowed == that.hostFactionAllowed && this.factionIDs == that.factionIDs && this.fplayerIDs == that.fplayerIDs; + } +} \ No newline at end of file