From ee52016a8709b4596b9ab888b7f9163abfa1479e Mon Sep 17 00:00:00 2001 From: t00thpick1 Date: Sun, 19 Oct 2014 01:37:25 -0400 Subject: [PATCH] Abstract Data storage method for future implementations. Thanks to Ryan from Reactive MC Also included: -Heavily optimized loading process -Optimizations for various commands. --- .../java/com/massivecraft/factions/Board.java | 285 +----- .../java/com/massivecraft/factions/Conf.java | 10 +- .../com/massivecraft/factions/FLocation.java | 17 +- .../com/massivecraft/factions/FPlayer.java | 725 ++------------- .../com/massivecraft/factions/FPlayers.java | 54 +- .../com/massivecraft/factions/Faction.java | 757 +++------------- .../com/massivecraft/factions/Factions.java | 206 +---- .../java/com/massivecraft/factions/P.java | 37 +- .../massivecraft/factions/cmd/CmdAdmin.java | 4 +- .../massivecraft/factions/cmd/CmdConvert.java | 39 + .../massivecraft/factions/cmd/CmdCreate.java | 12 +- .../factions/cmd/CmdDescription.java | 2 +- .../massivecraft/factions/cmd/CmdDisband.java | 4 +- .../massivecraft/factions/cmd/CmdHome.java | 4 +- .../massivecraft/factions/cmd/CmdJoin.java | 2 +- .../massivecraft/factions/cmd/CmdList.java | 12 +- .../com/massivecraft/factions/cmd/CmdMap.java | 2 +- .../massivecraft/factions/cmd/CmdOpen.java | 12 +- .../massivecraft/factions/cmd/CmdOwner.java | 2 +- .../factions/cmd/CmdOwnerList.java | 4 +- .../factions/cmd/CmdPeaceful.java | 2 +- .../factions/cmd/CmdPermanent.java | 2 +- .../factions/cmd/CmdSafeunclaimall.java | 2 +- .../massivecraft/factions/cmd/CmdSaveAll.java | 6 +- .../massivecraft/factions/cmd/CmdSethome.java | 2 +- .../massivecraft/factions/cmd/CmdShow.java | 2 +- .../factions/cmd/CmdShowInvites.java | 2 +- .../com/massivecraft/factions/cmd/CmdTag.java | 17 +- .../massivecraft/factions/cmd/CmdUnclaim.java | 10 +- .../factions/cmd/CmdUnclaimall.java | 2 +- .../factions/cmd/CmdWarunclaimall.java | 2 +- .../massivecraft/factions/cmd/FCmdRoot.java | 2 + .../massivecraft/factions/cmd/FCommand.java | 18 +- .../factions/event/FactionCreateEvent.java | 7 +- .../factions/event/FactionDisbandEvent.java | 4 +- .../factions/integration/Econ.java | 15 - .../listeners/FactionsBlockListener.java | 10 +- .../listeners/FactionsChatListener.java | 10 +- .../listeners/FactionsEntityListener.java | 30 +- .../listeners/FactionsPlayerListener.java | 38 +- .../factions/scoreboards/FInfoBoard.java | 0 .../factions/scoreboards/FScoreboard.java | 2 +- .../factions/scoreboards/FTeamWrapper.java | 4 +- .../factions/util/AutoLeaveProcessTask.java | 4 +- .../factions/util/LazyLocation.java | 8 +- .../massivecraft/factions/util/MiscUtil.java | 23 + .../massivecraft/factions/zcore/MPlugin.java | 9 +- .../zcore/MPluginSecretPlayerListener.java | 11 +- .../factions/zcore/persist/EM.java | 62 -- .../factions/zcore/persist/Entity.java | 54 -- .../zcore/persist/EntityCollection.java | 467 ---------- .../factions/zcore/persist/MemoryBoard.java | 230 +++++ .../factions/zcore/persist/MemoryFPlayer.java | 829 ++++++++++++++++++ .../zcore/persist/MemoryFPlayers.java | 72 ++ .../factions/zcore/persist/MemoryFaction.java | 733 ++++++++++++++++ .../zcore/persist/MemoryFactions.java | 171 ++++ .../factions/zcore/persist/PlayerEntity.java | 50 -- .../zcore/persist/PlayerEntityCollection.java | 44 - .../factions/zcore/persist/SaveTask.java | 7 +- .../zcore/persist/json/FactionsJSON.java | 51 ++ .../zcore/persist/json/JSONBoard.java | 108 +++ .../zcore/persist/json/JSONFPlayer.java | 32 + .../zcore/persist/json/JSONFPlayers.java | 188 ++++ .../zcore/persist/json/JSONFaction.java | 16 + .../zcore/persist/json/JSONFactions.java | 258 ++++++ 65 files changed, 3229 insertions(+), 2577 deletions(-) create mode 100644 src/main/java/com/massivecraft/factions/cmd/CmdConvert.java create mode 100644 src/main/java/com/massivecraft/factions/scoreboards/FInfoBoard.java delete mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/EM.java delete mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/Entity.java delete mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/EntityCollection.java create mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/MemoryBoard.java create mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayer.java create mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayers.java create mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java create mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/MemoryFactions.java delete mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/PlayerEntity.java delete mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/PlayerEntityCollection.java create mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/json/FactionsJSON.java create mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/json/JSONBoard.java create mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayer.java create mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayers.java create mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFaction.java create mode 100644 src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFactions.java diff --git a/src/main/java/com/massivecraft/factions/Board.java b/src/main/java/com/massivecraft/factions/Board.java index a514b08a..a9d42f45 100644 --- a/src/main/java/com/massivecraft/factions/Board.java +++ b/src/main/java/com/massivecraft/factions/Board.java @@ -1,145 +1,65 @@ package com.massivecraft.factions; -import com.google.gson.reflect.TypeToken; -import com.massivecraft.factions.struct.Relation; -import com.massivecraft.factions.util.AsciiCompass; -import com.massivecraft.factions.zcore.util.DiscUtil; -import org.bukkit.ChatColor; - -import java.io.File; -import java.lang.reflect.Type; import java.util.*; -import java.util.Map.Entry; + +import com.massivecraft.factions.zcore.persist.json.JSONBoard; -public class Board { - - private static transient File file = new File(P.p.getDataFolder(), "board.json"); - private static transient HashMap flocationIds = new HashMap(); - +public abstract class Board { + protected static Board instance = getBoardImpl(); //----------------------------------------------// // Get and Set //----------------------------------------------// - public static String getIdAt(FLocation flocation) { - if (!flocationIds.containsKey(flocation)) { - return "0"; + public abstract String getIdAt(FLocation flocation); + + private static Board getBoardImpl() { + switch (Conf.backEnd) { + case JSON: + return new JSONBoard(); } - - return flocationIds.get(flocation); + return null; } - public static Faction getFactionAt(FLocation flocation) { - return Factions.i.get(getIdAt(flocation)); + public static Board getInstance() { + return instance; } - public static void setIdAt(String id, FLocation flocation) { - clearOwnershipAt(flocation); + public abstract Faction getFactionAt(FLocation flocation); - if (id.equals("0")) { - removeAt(flocation); - } + public abstract void setIdAt(String id, FLocation flocation); - flocationIds.put(flocation, id); - } + public abstract void setFactionAt(Faction faction, FLocation flocation); - public static void setFactionAt(Faction faction, FLocation flocation) { - setIdAt(faction.getId(), flocation); - } - - public static void removeAt(FLocation flocation) { - clearOwnershipAt(flocation); - flocationIds.remove(flocation); - } + public abstract void removeAt(FLocation 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 abstract void clearOwnershipAt(FLocation flocation); - public static void unclaimAll(String factionId) { - Faction faction = Factions.i.get(factionId); - if (faction != null && faction.isNormal()) { - faction.clearAllClaimOwnership(); - } - - Iterator> iter = flocationIds.entrySet().iterator(); - while (iter.hasNext()) { - Entry entry = iter.next(); - if (entry.getValue().equals(factionId)) { - iter.remove(); - } - } - } + public abstract void unclaimAll(String factionId); // Is this coord NOT completely surrounded by coords claimed by the same faction? // Simpler: Is there any nearby coord with a faction other than the faction here? - public static boolean isBorderLocation(FLocation flocation) { - Faction faction = getFactionAt(flocation); - FLocation a = flocation.getRelative(1, 0); - FLocation b = flocation.getRelative(-1, 0); - FLocation c = flocation.getRelative(0, 1); - FLocation d = flocation.getRelative(0, -1); - return faction != getFactionAt(a) || faction != getFactionAt(b) || faction != getFactionAt(c) || faction != getFactionAt(d); - } + public abstract boolean isBorderLocation(FLocation flocation); // Is this coord connected to any coord claimed by the specified faction? - public static boolean isConnectedLocation(FLocation flocation, Faction faction) { - FLocation a = flocation.getRelative(1, 0); - FLocation b = flocation.getRelative(-1, 0); - FLocation c = flocation.getRelative(0, 1); - FLocation d = flocation.getRelative(0, -1); - return faction == getFactionAt(a) || faction == getFactionAt(b) || faction == getFactionAt(c) || faction == getFactionAt(d); - } + public abstract boolean isConnectedLocation(FLocation flocation, Faction faction); //----------------------------------------------// // Cleaner. Remove orphaned foreign keys //----------------------------------------------// - public static void clean() { - Iterator> iter = flocationIds.entrySet().iterator(); - while (iter.hasNext()) { - Entry entry = iter.next(); - if (!Factions.i.exists(entry.getValue())) { - P.p.log("Board cleaner removed " + entry.getValue() + " from " + entry.getKey()); - iter.remove(); - } - } - } + public abstract void clean(); //----------------------------------------------// // Coord count //----------------------------------------------// - public static int getFactionCoordCount(String factionId) { - int ret = 0; - for (String thatFactionId : flocationIds.values()) { - if (thatFactionId.equals(factionId)) { - ret += 1; - } - } - return ret; - } + public abstract int getFactionCoordCount(String factionId); - public static int getFactionCoordCount(Faction faction) { - return getFactionCoordCount(faction.getId()); - } + public abstract int getFactionCoordCount(Faction faction); - public static int getFactionCoordCountInWorld(Faction faction, String worldName) { - String factionId = faction.getId(); - int ret = 0; - Iterator> iter = flocationIds.entrySet().iterator(); - while (iter.hasNext()) { - Entry entry = iter.next(); - if (entry.getValue().equals(factionId) && entry.getKey().getWorldName().equals(worldName)) { - ret += 1; - } - } - return ret; - } + public abstract int getFactionCoordCountInWorld(Faction faction, String worldName); //----------------------------------------------// // Map generation @@ -149,158 +69,9 @@ public class Board { * The map is relative to a coord and a faction north is in the direction of decreasing x east is in the direction * of decreasing z */ - public static ArrayList getMap(Faction faction, FLocation flocation, double inDegrees) { - ArrayList ret = new ArrayList(); - Faction factionLoc = getFactionAt(flocation); - ret.add(P.p.txt.titleize("(" + flocation.getCoordString() + ") " + factionLoc.getTag(faction))); + public abstract ArrayList getMap(Faction faction, FLocation flocation, double inDegrees); - int halfWidth = Conf.mapWidth / 2; - int halfHeight = Conf.mapHeight / 2; - FLocation topLeft = flocation.getRelative(-halfWidth, -halfHeight); - int width = halfWidth * 2 + 1; - int height = halfHeight * 2 + 1; + public abstract boolean forceSave(); - if (Conf.showMapFactionKey) { - height--; - } - - Map fList = new HashMap(); - int chrIdx = 0; - - // For each row - for (int dz = 0; dz < height; dz++) { - // Draw and add that row - String row = ""; - for (int dx = 0; dx < width; dx++) { - if (dx == halfWidth && dz == halfHeight) { - row += ChatColor.AQUA + "+"; - } else { - FLocation flocationHere = topLeft.getRelative(dx, dz); - Faction factionHere = getFactionAt(flocationHere); - Relation relation = faction.getRelationTo(factionHere); - if (factionHere.isNone()) { - row += ChatColor.GRAY + "-"; - } else if (factionHere.isSafeZone()) { - row += Conf.colorPeaceful + "+"; - } else if (factionHere.isWarZone()) { - row += ChatColor.DARK_RED + "+"; - } else if (factionHere == faction || - factionHere == factionLoc || - relation.isAtLeast(Relation.ALLY) || - (Conf.showNeutralFactionsOnMap && relation.equals(Relation.NEUTRAL)) || - (Conf.showEnemyFactionsOnMap && relation.equals(Relation.ENEMY))) { - if (!fList.containsKey(factionHere.getTag())) { - fList.put(factionHere.getTag(), Conf.mapKeyChrs[chrIdx++]); - } - char tag = fList.get(factionHere.getTag()); - row += factionHere.getColorTo(faction) + "" + tag; - } else { - row += ChatColor.GRAY + "-"; - } - } - } - ret.add(row); - } - - // Get the compass - ArrayList asciiCompass = AsciiCompass.getAsciiCompass(inDegrees, ChatColor.RED, P.p.txt.parse("")); - - // Add the compass - ret.set(1, asciiCompass.get(0) + ret.get(1).substring(3 * 3)); - ret.set(2, asciiCompass.get(1) + ret.get(2).substring(3 * 3)); - ret.set(3, asciiCompass.get(2) + ret.get(3).substring(3 * 3)); - - // Add the faction key - if (Conf.showMapFactionKey) { - String fRow = ""; - for (String key : fList.keySet()) { - fRow += String.format("%s%s: %s ", ChatColor.GRAY, fList.get(key), key); - } - ret.add(fRow); - } - - return ret; - } - - - // -------------------------------------------- // - // Persistance - // -------------------------------------------- // - - public static Map> dumpAsSaveFormat() { - Map> worldCoordIds = new HashMap>(); - - String worldName, coords; - String id; - - for (Entry entry : flocationIds.entrySet()) { - worldName = entry.getKey().getWorldName(); - coords = entry.getKey().getCoordString(); - id = entry.getValue(); - if (!worldCoordIds.containsKey(worldName)) { - worldCoordIds.put(worldName, new TreeMap()); - } - - worldCoordIds.get(worldName).put(coords, id); - } - - return worldCoordIds; - } - - public static void loadFromSaveFormat(Map> worldCoordIds) { - flocationIds.clear(); - - String worldName; - String[] coords; - int x, z; - String factionId; - - for (Entry> entry : worldCoordIds.entrySet()) { - worldName = entry.getKey(); - 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); - } - } - } - - public static boolean save() { - //Factions.log("Saving board to disk"); - - try { - DiscUtil.write(file, P.p.gson.toJson(dumpAsSaveFormat())); - } catch (Exception e) { - e.printStackTrace(); - P.p.log("Failed to save the board to disk."); - return false; - } - - return true; - } - - public static boolean load() { - P.p.log("Loading board from disk"); - - if (!file.exists()) { - P.p.log("No board to load from disk. Creating new file."); - save(); - return true; - } - - try { - Type type = new TypeToken>>() { - }.getType(); - Map> worldCoordIds = P.p.gson.fromJson(DiscUtil.read(file), type); - loadFromSaveFormat(worldCoordIds); - } catch (Exception e) { - e.printStackTrace(); - P.p.log("Failed to load the board from disk."); - return false; - } - - return true; - } + public abstract boolean load(); } diff --git a/src/main/java/com/massivecraft/factions/Conf.java b/src/main/java/com/massivecraft/factions/Conf.java index 3aae25c2..19e2be41 100644 --- a/src/main/java/com/massivecraft/factions/Conf.java +++ b/src/main/java/com/massivecraft/factions/Conf.java @@ -260,9 +260,11 @@ public class Conf { public static Set worldsIgnorePvP = new LinkedHashSet(); public static Set worldsNoWildernessProtection = new LinkedHashSet(); + public static Backend backEnd = Backend.JSON; + public static transient int mapHeight = 8; public static transient int mapWidth = 39; - public static transient char[] mapKeyChrs = "\\/#?$%=&^ABCDEFGHJKLMNOPQRSTUVWXYZ1234567890abcdeghjmnopqrsuvwxyz".toCharArray(); + public static transient char[] mapKeyChrs = "\\/#$%=&^ABCDEFGHJKLMNOPQRSTUVWXYZ1234567890abcdeghjmnopqrsuvwxyz?".toCharArray(); static { baseCommandAliases.add("f"); @@ -355,5 +357,11 @@ public class Conf { public static void save() { P.p.persist.save(i); } + + public enum Backend { + JSON, + //MYSQL, TODO + ; + } } diff --git a/src/main/java/com/massivecraft/factions/FLocation.java b/src/main/java/com/massivecraft/factions/FLocation.java index c64bb8bf..15cc0a8e 100644 --- a/src/main/java/com/massivecraft/factions/FLocation.java +++ b/src/main/java/com/massivecraft/factions/FLocation.java @@ -1,18 +1,20 @@ package com.massivecraft.factions; import com.massivecraft.factions.util.MiscUtil; + import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.entity.Player; +import java.io.Serializable; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; -public class FLocation { - +public class FLocation implements Serializable { + private static final long serialVersionUID = -8292915234027387983L; private String worldName = "world"; private int x = 0; private int z = 0; @@ -88,6 +90,17 @@ public class FLocation { return "[" + this.getWorldName() + "," + this.getCoordString() + "]"; } + public static FLocation fromString(String string) { + int index = string.indexOf(",", 0); + int start = 1; + String worldName = string.substring(start, index); + start = index + 1; + index = string.indexOf(",", start); + int x = Integer.valueOf(string.substring(start, index)); + int y = Integer.valueOf(string.substring(index + 1, string.length() - 1)); + return new FLocation(worldName, x, y); + } + //----------------------------------------------// // Block/Chunk/Region Value Transformation //----------------------------------------------// diff --git a/src/main/java/com/massivecraft/factions/FPlayer.java b/src/main/java/com/massivecraft/factions/FPlayer.java index 19a5b7bd..7bfd0fb6 100644 --- a/src/main/java/com/massivecraft/factions/FPlayer.java +++ b/src/main/java/com/massivecraft/factions/FPlayer.java @@ -1,29 +1,17 @@ package com.massivecraft.factions; -import com.massivecraft.factions.event.FPlayerLeaveEvent; -import com.massivecraft.factions.event.LandClaimEvent; +import java.util.List; + import com.massivecraft.factions.iface.EconomyParticipator; import com.massivecraft.factions.iface.RelationParticipator; -import com.massivecraft.factions.integration.Econ; -import com.massivecraft.factions.integration.Worldguard; -import com.massivecraft.factions.scoreboards.FScoreboard; -import com.massivecraft.factions.scoreboards.sidebar.FInfoSidebar; import com.massivecraft.factions.struct.ChatMode; -import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.struct.Relation; import com.massivecraft.factions.struct.Role; -import com.massivecraft.factions.util.RelationUtil; -import com.massivecraft.factions.zcore.persist.PlayerEntity; -import org.bukkit.Bukkit; + import org.bukkit.ChatColor; import org.bukkit.Location; -import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - /** * Logged in players always have exactly one FPlayer instance. Logged out players may or may not have an FPlayer @@ -36,520 +24,165 @@ import java.util.UUID; * necessary. */ -public class FPlayer extends PlayerEntity implements EconomyParticipator { - //private transient String playerName; - private transient FLocation lastStoodAt = new FLocation(); // Where did this player stand the last time we checked? +public interface FPlayer extends EconomyParticipator { + public Faction getFaction(); - // FIELD: factionId - private String factionId; + public String getFactionId(); - public Faction getFaction() { - if (this.factionId == null) { - return null; - } - return Factions.i.get(this.factionId); - } + public boolean hasFaction(); - public String getFactionId() { - return this.factionId; - } + public void setFaction(Faction faction); - public boolean hasFaction() { - return !factionId.equals("0"); - } + public Role getRole(); - public void setFaction(Faction faction) { - Faction oldFaction = this.getFaction(); - if (oldFaction != null) { - oldFaction.removeFPlayer(this); - } - faction.addFPlayer(this); - this.factionId = faction.getId(); - } + public void setRole(Role role); - // FIELD: role - private Role role; + public double getPowerBoost(); - public Role getRole() { - return this.role; - } + public void setPowerBoost(double powerBoost); - public void setRole(Role role) { - this.role = role; - } + public Faction getAutoClaimFor(); - // FIELD: title - private String title; + public void setAutoClaimFor(Faction faction); - // FIELD: power - private double power; + public boolean isAutoSafeClaimEnabled(); - // FIELD: powerBoost - // special increase/decrease to min and max power for this player - private double powerBoost; + public void setIsAutoSafeClaimEnabled(boolean enabled); - public double getPowerBoost() { - return this.powerBoost; - } + public boolean isAutoWarClaimEnabled(); - public void setPowerBoost(double powerBoost) { - this.powerBoost = powerBoost; - } + public void setIsAutoWarClaimEnabled(boolean enabled); - // FIELD: lastPowerUpdateTime - private long lastPowerUpdateTime; + public boolean isAdminBypassing(); - // FIELD: lastLoginTime - private long lastLoginTime; + public void setIsAdminBypassing(boolean val); - // FIELD: mapAutoUpdating - private transient boolean mapAutoUpdating; + public void setChatMode(ChatMode chatMode); - // FIELD: autoClaimEnabled - private transient Faction autoClaimFor; + public ChatMode getChatMode(); - public Faction getAutoClaimFor() { - return autoClaimFor; - } + public void setSpyingChat(boolean chatSpying); - public void setAutoClaimFor(Faction faction) { - this.autoClaimFor = faction; - if (this.autoClaimFor != null) { - // TODO: merge these into same autoclaim - this.autoSafeZoneEnabled = false; - this.autoWarZoneEnabled = false; - } - } - - // FIELD: autoSafeZoneEnabled - private transient boolean autoSafeZoneEnabled; - - public boolean isAutoSafeClaimEnabled() { - return autoSafeZoneEnabled; - } - - public void setIsAutoSafeClaimEnabled(boolean enabled) { - this.autoSafeZoneEnabled = enabled; - if (enabled) { - this.autoClaimFor = null; - this.autoWarZoneEnabled = false; - } - } - - // FIELD: autoWarZoneEnabled - private transient boolean autoWarZoneEnabled; - - public boolean isAutoWarClaimEnabled() { - return autoWarZoneEnabled; - } - - public void setIsAutoWarClaimEnabled(boolean enabled) { - this.autoWarZoneEnabled = enabled; - if (enabled) { - this.autoClaimFor = null; - this.autoSafeZoneEnabled = false; - } - } - - private transient boolean isAdminBypassing = false; - - public boolean isAdminBypassing() { - return this.isAdminBypassing; - } - - public void setIsAdminBypassing(boolean val) { - this.isAdminBypassing = val; - } - - // FIELD: loginPvpDisabled - private transient boolean loginPvpDisabled; - - // FIELD: deleteMe - private transient boolean deleteMe; - - // FIELD: chatMode - private ChatMode chatMode; - - public void setChatMode(ChatMode chatMode) { - this.chatMode = chatMode; - } - - public ChatMode getChatMode() { - if (this.factionId.equals("0") || !Conf.factionOnlyChat) { - this.chatMode = ChatMode.PUBLIC; - } - return chatMode; - } - - // FIELD: chatSpy - private transient boolean spyingChat = false; - - public void setSpyingChat(boolean chatSpying) { - this.spyingChat = chatSpying; - } - - public boolean isSpyingChat() { - return spyingChat; - } + public boolean isSpyingChat(); // FIELD: account - public String getAccountId() { - return this.getId(); - } + public String getAccountId(); - // -------------------------------------------- // - // Construct - // -------------------------------------------- // + public void resetFactionData(boolean doSpoutUpdate); - // GSON need this noarg constructor. - public FPlayer() { - this.resetFactionData(false); - this.power = Conf.powerPlayerStarting; - this.lastPowerUpdateTime = System.currentTimeMillis(); - this.lastLoginTime = System.currentTimeMillis(); - this.mapAutoUpdating = false; - this.autoClaimFor = null; - this.autoSafeZoneEnabled = false; - this.autoWarZoneEnabled = false; - this.loginPvpDisabled = Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0; - this.deleteMe = false; - this.powerBoost = 0.0; + public void resetFactionData(); - if (!Conf.newPlayerStartingFactionID.equals("0") && Factions.i.exists(Conf.newPlayerStartingFactionID)) { - this.factionId = Conf.newPlayerStartingFactionID; - } - } + public long getLastLoginTime(); - public final void resetFactionData(boolean doSpoutUpdate) { - // clean up any territory ownership in old faction, if there is one - if (Factions.i.exists(this.getFactionId())) { - Faction currentFaction = this.getFaction(); - currentFaction.removeFPlayer(this); - if (currentFaction.isNormal()) { - currentFaction.clearClaimOwnership(this); - } - } + public void setLastLoginTime(long lastLoginTime); - this.factionId = "0"; // The default neutral faction - this.chatMode = ChatMode.PUBLIC; - this.role = Role.NORMAL; - this.title = ""; - this.autoClaimFor = null; - } + public boolean isMapAutoUpdating(); - public void resetFactionData() { - this.resetFactionData(true); - } + public void setMapAutoUpdating(boolean mapAutoUpdating); - // -------------------------------------------- // - // Getters And Setters - // -------------------------------------------- // + public boolean hasLoginPvpDisabled(); + public FLocation getLastStoodAt(); - public long getLastLoginTime() { - return lastLoginTime; - } + public void setLastStoodAt(FLocation flocation); + public String getTitle(); - public void setLastLoginTime(long lastLoginTime) { - losePowerFromBeingOffline(); - this.lastLoginTime = lastLoginTime; - this.lastPowerUpdateTime = lastLoginTime; - if (Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0) { - this.loginPvpDisabled = true; - } - } + public void setTitle(String title); - public boolean isMapAutoUpdating() { - return mapAutoUpdating; - } + public String getName(); - public void setMapAutoUpdating(boolean mapAutoUpdating) { - this.mapAutoUpdating = mapAutoUpdating; - } - - public boolean hasLoginPvpDisabled() { - if (!loginPvpDisabled) { - return false; - } - if (this.lastLoginTime + (Conf.noPVPDamageToOthersForXSecondsAfterLogin * 1000) < System.currentTimeMillis()) { - this.loginPvpDisabled = false; - return false; - } - return true; - } - - public FLocation getLastStoodAt() { - return this.lastStoodAt; - } - - public void setLastStoodAt(FLocation flocation) { - this.lastStoodAt = flocation; - } - - public void markForDeletion(boolean delete) { - deleteMe = delete; - } - - //----------------------------------------------// - // Title, Name, Faction Tag and Chat - //----------------------------------------------// - - // Base: - - public String getTitle() { - return this.hasFaction() ? title : ""; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getName() { - if (isOnline()) { - return getPlayer().getName(); - } - OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(getId())); - return player.getName() != null ? player.getName() : getId(); - } - - public String getTag() { - return this.hasFaction() ? this.getFaction().getTag() : ""; - } + public String getTag(); // Base concatenations: - public String getNameAndSomething(String something) { - String ret = this.role.getPrefix(); - if (something.length() > 0) { - ret += something + " "; - } - ret += this.getName(); - return ret; - } + public String getNameAndSomething(String something); - public String getNameAndTitle() { - return this.getNameAndSomething(this.getTitle()); - } + public String getNameAndTitle(); - public String getNameAndTag() { - return this.getNameAndSomething(this.getTag()); - } + public String getNameAndTag(); // Colored concatenations: // These are used in information messages - public String getNameAndTitle(Faction faction) { - return this.getColorTo(faction) + this.getNameAndTitle(); - } + public String getNameAndTitle(Faction faction); - public String getNameAndTitle(FPlayer fplayer) { - return this.getColorTo(fplayer) + this.getNameAndTitle(); - } - - /*public String getNameAndTag(Faction faction) - { - return this.getRelationColor(faction)+this.getNameAndTag(); - } - public String getNameAndTag(FPlayer fplayer) - { - return this.getRelationColor(fplayer)+this.getNameAndTag(); - }*/ - - // TODO: Removed for refactoring. - - /*public String getNameAndRelevant(Faction faction) - { - // Which relation? - Relation rel = this.getRelationTo(faction); - - // For member we show title - if (rel == Relation.MEMBER) { - return rel.getColor() + this.getNameAndTitle(); - } - - // For non members we show tag - return rel.getColor() + this.getNameAndTag(); - } - public String getNameAndRelevant(FPlayer fplayer) - { - return getNameAndRelevant(fplayer.getFaction()); - }*/ + public String getNameAndTitle(FPlayer fplayer); // Chat Tag: // These are injected into the format of global chat messages. - public String getChatTag() { - return this.hasFaction() ? String.format(Conf.chatTagFormat, this.role.getPrefix() + this.getTag()) : ""; - } + public String getChatTag(); // Colored Chat Tag - public String getChatTag(Faction faction) { - return this.hasFaction() ? this.getRelationTo(faction).getColor() + getChatTag() : ""; - } + public String getChatTag(Faction faction); - public String getChatTag(FPlayer fplayer) { - return this.hasFaction() ? this.getColorTo(fplayer) + getChatTag() : ""; - } + public String getChatTag(FPlayer fplayer); // ------------------------------- // Relation and relation colors // ------------------------------- @Override - public String describeTo(RelationParticipator that, boolean ucfirst) { - return RelationUtil.describeThatToMe(this, that, ucfirst); - } + public String describeTo(RelationParticipator that, boolean ucfirst); @Override - public String describeTo(RelationParticipator that) { - return RelationUtil.describeThatToMe(this, that); - } + public String describeTo(RelationParticipator that); @Override - public Relation getRelationTo(RelationParticipator rp) { - return RelationUtil.getRelationTo(this, rp); - } + public Relation getRelationTo(RelationParticipator rp); @Override - public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful) { - return RelationUtil.getRelationTo(this, rp, ignorePeaceful); - } + public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful); - public Relation getRelationToLocation() { - return Board.getFactionAt(new FLocation(this)).getRelationTo(this); - } + public Relation getRelationToLocation(); @Override - public ChatColor getColorTo(RelationParticipator rp) { - return RelationUtil.getColorOfThatToMe(this, rp); - } + public ChatColor getColorTo(RelationParticipator rp); //----------------------------------------------// // Health //----------------------------------------------// - public void heal(int amnt) { - Player player = this.getPlayer(); - if (player == null) { - return; - } - player.setHealth(player.getHealth() + amnt); - } + public void heal(int amnt); //----------------------------------------------// // Power //----------------------------------------------// - public double getPower() { - this.updatePower(); - return this.power; - } + public double getPower(); - protected void alterPower(double delta) { - this.power += delta; - if (this.power > this.getPowerMax()) { - this.power = this.getPowerMax(); - } else if (this.power < this.getPowerMin()) { - this.power = this.getPowerMin(); - } - } + public void alterPower(double delta); - public double getPowerMax() { - return Conf.powerPlayerMax + this.powerBoost; - } + public double getPowerMax(); - public double getPowerMin() { - return Conf.powerPlayerMin + this.powerBoost; - } + public double getPowerMin(); - public int getPowerRounded() { - return (int) Math.round(this.getPower()); - } + public int getPowerRounded(); - public int getPowerMaxRounded() { - return (int) Math.round(this.getPowerMax()); - } + public int getPowerMaxRounded(); - public int getPowerMinRounded() { - return (int) Math.round(this.getPowerMin()); - } + public int getPowerMinRounded(); - protected void updatePower() { - if (this.isOffline()) { - losePowerFromBeingOffline(); - if (!Conf.powerRegenOffline) { - return; - } - } - long now = System.currentTimeMillis(); - long millisPassed = now - this.lastPowerUpdateTime; - this.lastPowerUpdateTime = now; + public void updatePower(); - Player thisPlayer = this.getPlayer(); - if (thisPlayer != null && thisPlayer.isDead()) { - return; // don't let dead players regain power until they respawn - } + public void losePowerFromBeingOffline(); - int millisPerMinute = 60 * 1000; - this.alterPower(millisPassed * Conf.powerPerMinute / millisPerMinute); - } - - protected void losePowerFromBeingOffline() { - if (Conf.powerOfflineLossPerDay > 0.0 && this.power > Conf.powerOfflineLossLimit) { - long now = System.currentTimeMillis(); - long millisPassed = now - this.lastPowerUpdateTime; - this.lastPowerUpdateTime = now; - - double loss = millisPassed * Conf.powerOfflineLossPerDay / (24 * 60 * 60 * 1000); - if (this.power - loss < Conf.powerOfflineLossLimit) { - loss = this.power; - } - this.alterPower(-loss); - } - } - - public void onDeath() { - this.updatePower(); - this.alterPower(-Conf.powerPerDeath); - } + public void onDeath(); //----------------------------------------------// // Territory //----------------------------------------------// - public boolean isInOwnTerritory() { - return Board.getFactionAt(new FLocation(this)) == this.getFaction(); - } + public boolean isInOwnTerritory(); - public boolean isInOthersTerritory() { - Faction factionHere = Board.getFactionAt(new FLocation(this)); - return factionHere != null && factionHere.isNormal() && factionHere != this.getFaction(); - } + public boolean isInOthersTerritory(); - public boolean isInAllyTerritory() { - return Board.getFactionAt(new FLocation(this)).getRelationTo(this).isAlly(); - } + public boolean isInAllyTerritory(); - public boolean isInNeutralTerritory() { - return Board.getFactionAt(new FLocation(this)).getRelationTo(this).isNeutral(); - } + public boolean isInNeutralTerritory(); - public boolean isInEnemyTerritory() { - return Board.getFactionAt(new FLocation(this)).getRelationTo(this).isEnemy(); - } + public boolean isInEnemyTerritory(); - public void sendFactionHereMessage() { - Faction toShow = Board.getFactionAt(getLastStoodAt()); - if (shouldShowScoreboard(toShow)) { - // Shows them the scoreboard instead of sending a message in chat. Will disappear after a few seconds. - FScoreboard.get(this).setTemporarySidebar(new FInfoSidebar(toShow)); - } else { - String msg = P.p.txt.parse("") + " ~ " + toShow.getTag(this); - if (toShow.getDescription().length() > 0) { - msg += " - " + toShow.getDescription(); - } - this.sendMessage(msg); - } - } + public void sendFactionHereMessage(); /** * Check if the scoreboard should be shown. Simple method to be used by above method. @@ -558,227 +191,37 @@ public class FPlayer extends PlayerEntity implements EconomyParticipator { * * @return true if should show, otherwise false. */ - private boolean shouldShowScoreboard(Faction toShow) { - return !toShow.isWarZone() && !toShow.isNone() && !toShow.isSafeZone() && P.p.getConfig().contains("scoreboard.finfo") && P.p.getConfig().getBoolean("scoreboard.finfo-enabled", false) && P.p.cmdBase.cmdSB.showBoard(this); - } + public boolean shouldShowScoreboard(Faction toShow); // ------------------------------- // Actions // ------------------------------- - public void leave(boolean makePay) { - Faction myFaction = this.getFaction(); - makePay = makePay && Econ.shouldBeUsed() && !this.isAdminBypassing(); + public void leave(boolean makePay); - if (myFaction == null) { - resetFactionData(); - return; - } + public boolean canClaimForFaction(Faction forFaction); - boolean perm = myFaction.isPermanent(); + public boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure); - if (!perm && this.getRole() == Role.ADMIN && myFaction.getFPlayers().size() > 1) { - msg("You must give the admin role to someone else first."); - return; - } + public boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure); - if (!Conf.canLeaveWithNegativePower && this.getPower() < 0) { - msg("You cannot leave until your power is positive."); - return; - } + public void msg(String str, Object... args); - // if economy is enabled and they're not on the bypass list, make sure they can pay - if (makePay && !Econ.hasAtLeast(this, Conf.econCostLeave, "to leave your faction.")) { - return; - } + public String getId(); - FPlayerLeaveEvent leaveEvent = new FPlayerLeaveEvent(this, myFaction, FPlayerLeaveEvent.PlayerLeaveReason.LEAVE); - Bukkit.getServer().getPluginManager().callEvent(leaveEvent); - if (leaveEvent.isCancelled()) { - return; - } + public Player getPlayer(); - // then make 'em pay (if applicable) - if (makePay && !Econ.modifyMoney(this, -Conf.econCostLeave, "to leave your faction.", "for leaving your faction.")) { - return; - } + public boolean isOnline(); - // Am I the last one in the faction? - if (myFaction.getFPlayers().size() == 1) { - // Transfer all money - if (Econ.shouldBeUsed()) { - Econ.transferMoney(this, myFaction, this, Econ.getBalance(myFaction.getAccountId())); - } - } + public void sendMessage(String message); - if (myFaction.isNormal()) { - for (FPlayer fplayer : myFaction.getFPlayersWhereOnline(true)) { - fplayer.msg("%s left %s.", this.describeTo(fplayer, true), myFaction.describeTo(fplayer)); - } + public void sendMessage(List messages); - if (Conf.logFactionLeave) { - P.p.log(this.getName() + " left the faction: " + myFaction.getTag()); - } - } + public boolean isOnlineAndVisibleTo(Player me); - myFaction.removeAnnouncements(this); - this.resetFactionData(); + public void remove(); - if (myFaction.isNormal() && !perm && myFaction.getFPlayers().isEmpty()) { - // Remove this faction - for (FPlayer fplayer : FPlayers.i.getOnline()) { - fplayer.msg("%s was disbanded.", myFaction.describeTo(fplayer, true)); - } + public boolean isOffline(); - myFaction.detach(); - if (Conf.logFactionDisband) { - P.p.log("The faction " + myFaction.getTag() + " (" + myFaction.getId() + ") was disbanded due to the last player (" + this.getName() + ") leaving."); - } - } - } - - public boolean canClaimForFaction(Faction forFaction) { - return !forFaction.isNone() && (this.isAdminBypassing() || (forFaction == this.getFaction() && this.getRole().isAtLeast(Role.MODERATOR)) || (forFaction.isSafeZone() && Permission.MANAGE_SAFE_ZONE.has(getPlayer())) || (forFaction.isWarZone() && Permission.MANAGE_WAR_ZONE.has(getPlayer()))); - } - - public boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure) { - String error = null; - FLocation flocation = new FLocation(location); - Faction myFaction = getFaction(); - Faction currentFaction = Board.getFactionAt(flocation); - int ownedLand = forFaction.getLandRounded(); - - if (Conf.worldGuardChecking && Worldguard.checkForRegionsInChunk(location)) { - // Checks for WorldGuard regions in the chunk attempting to be claimed - error = P.p.txt.parse("This land is protected"); - } else if (Conf.worldsNoClaiming.contains(flocation.getWorldName())) { - error = P.p.txt.parse("Sorry, this world has land claiming disabled."); - } else if (this.isAdminBypassing()) { - return true; - } else if (forFaction.isSafeZone() && Permission.MANAGE_SAFE_ZONE.has(getPlayer())) { - return true; - } else if (forFaction.isWarZone() && Permission.MANAGE_WAR_ZONE.has(getPlayer())) { - return true; - } else if (myFaction != forFaction) { - error = P.p.txt.parse("You can't claim land for %s.", forFaction.describeTo(this)); - } else if (forFaction == currentFaction) { - error = P.p.txt.parse("%s already own this land.", forFaction.describeTo(this, true)); - } else if (this.getRole().value < Role.MODERATOR.value) { - error = P.p.txt.parse("You must be %s to claim land.", Role.MODERATOR.toString()); - } else if (forFaction.getFPlayers().size() < Conf.claimsRequireMinFactionMembers) { - error = P.p.txt.parse("Factions must have at least %s members to claim land.", Conf.claimsRequireMinFactionMembers); - } else if (currentFaction.isSafeZone()) { - error = P.p.txt.parse("You can not claim a Safe Zone."); - } else if (currentFaction.isWarZone()) { - error = P.p.txt.parse("You can not claim a War Zone."); - } else if (ownedLand >= forFaction.getPowerRounded()) { - error = P.p.txt.parse("You can't claim more land! You need more power!"); - } else if (Conf.claimedLandsMax != 0 && ownedLand >= Conf.claimedLandsMax && forFaction.isNormal()) { - error = P.p.txt.parse("Limit reached. You can't claim more land!"); - } else if (currentFaction.getRelationTo(forFaction) == Relation.ALLY) { - error = P.p.txt.parse("You can't claim the land of your allies."); - } else if (Conf.claimsMustBeConnected && !this.isAdminBypassing() && myFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.isConnectedLocation(flocation, myFaction) && (!Conf.claimsCanBeUnconnectedIfOwnedByOtherFaction || !currentFaction.isNormal())) { - if (Conf.claimsCanBeUnconnectedIfOwnedByOtherFaction) { - error = P.p.txt.parse("You can only claim additional land which is connected to your first claim or controlled by another faction!"); - } else { - error = P.p.txt.parse("You can only claim additional land which is connected to your first claim!"); - } - } else if (currentFaction.isNormal()) { - if (myFaction.isPeaceful()) { - error = P.p.txt.parse("%s owns this land. Your faction is peaceful, so you cannot claim land from other factions.", currentFaction.getTag(this)); - } else if (currentFaction.isPeaceful()) { - error = P.p.txt.parse("%s owns this land, and is a peaceful faction. You cannot claim land from them.", currentFaction.getTag(this)); - } else if (!currentFaction.hasLandInflation()) { - // TODO more messages WARN current faction most importantly - error = P.p.txt.parse("%s owns this land and is strong enough to keep it.", currentFaction.getTag(this)); - } else if (!Board.isBorderLocation(flocation)) { - error = P.p.txt.parse("You must start claiming land at the border of the territory."); - } - } - // TODO: Add more else if statements. - - if (notifyFailure && error != null) { - msg(error); - } - return error == null; - } - - public boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure) { - // notifyFailure is false if called by auto-claim; no need to notify on every failure for it - // return value is false on failure, true on success - - FLocation flocation = new FLocation(location); - Faction currentFaction = Board.getFactionAt(flocation); - - int ownedLand = forFaction.getLandRounded(); - - if (!this.canClaimForFactionAtLocation(forFaction, location, notifyFailure)) { - return false; - } - - // if economy is enabled and they're not on the bypass list, make sure they can pay - boolean mustPay = Econ.shouldBeUsed() && !this.isAdminBypassing() && !forFaction.isSafeZone() && !forFaction.isWarZone(); - double cost = 0.0; - EconomyParticipator payee = null; - if (mustPay) { - cost = Econ.calculateClaimCost(ownedLand, currentFaction.isNormal()); - - if (Conf.econClaimUnconnectedFee != 0.0 && forFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.isConnectedLocation(flocation, forFaction)) { - cost += Conf.econClaimUnconnectedFee; - } - - if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts && this.hasFaction()) { - payee = this.getFaction(); - } else { - payee = this; - } - - if (!Econ.hasAtLeast(payee, cost, "to claim this land")) { - return false; - } - } - - LandClaimEvent claimEvent = new LandClaimEvent(flocation, forFaction, this); - Bukkit.getServer().getPluginManager().callEvent(claimEvent); - if (claimEvent.isCancelled()) { - return false; - } - - // then make 'em pay (if applicable) - if (mustPay && !Econ.modifyMoney(payee, -cost, "to claim this land", "for claiming this land")) { - return false; - } - - // announce success - Set informTheseFPlayers = new HashSet(); - informTheseFPlayers.add(this); - informTheseFPlayers.addAll(forFaction.getFPlayersWhereOnline(true)); - for (FPlayer fp : informTheseFPlayers) { - fp.msg("%s claimed land for %s from %s.", this.describeTo(fp, true), forFaction.describeTo(fp), currentFaction.describeTo(fp)); - } - - Board.setFactionAt(forFaction, flocation); - - if (Conf.logLandClaims) { - P.p.log(this.getName() + " claimed land at (" + flocation.getCoordString() + ") for the faction: " + forFaction.getTag()); - } - - return true; - } - - // -------------------------------------------- // - // Persistence - // -------------------------------------------- // - - @Override - public boolean shouldBeSaved() { - if (!this.hasFaction() && (this.getPowerRounded() == this.getPowerMaxRounded() || this.getPowerRounded() == (int) Math.round(Conf.powerPlayerStarting))) { - return false; - } - return !this.deleteMe; - } - - public void msg(String str, Object... args) { - this.sendMessage(P.p.txt.parse(str, args)); - } + public void setId(String id); } diff --git a/src/main/java/com/massivecraft/factions/FPlayers.java b/src/main/java/com/massivecraft/factions/FPlayers.java index 3077633d..fdcc94a0 100644 --- a/src/main/java/com/massivecraft/factions/FPlayers.java +++ b/src/main/java/com/massivecraft/factions/FPlayers.java @@ -1,38 +1,40 @@ package com.massivecraft.factions; -import com.google.gson.reflect.TypeToken; -import com.massivecraft.factions.zcore.persist.PlayerEntityCollection; +import java.util.Collection; -import java.io.File; -import java.lang.reflect.Type; -import java.util.Map; -import java.util.concurrent.ConcurrentSkipListMap; -import java.util.concurrent.CopyOnWriteArrayList; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; -public class FPlayers extends PlayerEntityCollection { +import com.massivecraft.factions.zcore.persist.json.JSONFPlayers; - public static FPlayers i = new FPlayers(); +public abstract class FPlayers { + protected static FPlayers instance = getFPlayersImpl(); - P p = P.p; + public abstract void clean(); - private FPlayers() { - super(FPlayer.class, new CopyOnWriteArrayList(), new ConcurrentSkipListMap(String.CASE_INSENSITIVE_ORDER), new File(P.p.getDataFolder(), "players.json"), P.p.gson); - - this.setCreative(true); + public static FPlayers getInstance() { + return instance; } - @Override - public Type getMapType() { - return new TypeToken>() { - }.getType(); - } - - public void clean() { - for (FPlayer fplayer : this.get()) { - if (!Factions.i.exists(fplayer.getFactionId())) { - p.log("Reset faction data (invalid faction) for player " + fplayer.getName()); - fplayer.resetFactionData(false); - } + private static FPlayers getFPlayersImpl() { + switch (Conf.backEnd) { + case JSON: + return new JSONFPlayers(); } + return null; } + + public abstract Collection getOnlinePlayers(); + + public abstract FPlayer getByPlayer(Player player); + + public abstract Collection getAllFPlayers(); + + public abstract void forceSave(); + + public abstract FPlayer getByOfflinePlayer(OfflinePlayer player); + + public abstract FPlayer getById(String string); + + public abstract void load(); } diff --git a/src/main/java/com/massivecraft/factions/Faction.java b/src/main/java/com/massivecraft/factions/Faction.java index d4593d32..962342ee 100644 --- a/src/main/java/com/massivecraft/factions/Faction.java +++ b/src/main/java/com/massivecraft/factions/Faction.java @@ -2,733 +2,214 @@ package com.massivecraft.factions; import com.massivecraft.factions.iface.EconomyParticipator; import com.massivecraft.factions.iface.RelationParticipator; -import com.massivecraft.factions.integration.Econ; -import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.struct.Relation; import com.massivecraft.factions.struct.Role; -import com.massivecraft.factions.util.LazyLocation; -import com.massivecraft.factions.util.MiscUtil; -import com.massivecraft.factions.util.RelationUtil; -import com.massivecraft.factions.zcore.persist.Entity; -import org.bukkit.Bukkit; + import org.bukkit.ChatColor; import org.bukkit.Location; -import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import java.util.*; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; +public interface Faction extends EconomyParticipator { + public HashMap> getAnnouncements(); -public class Faction extends Entity implements EconomyParticipator { + public void addAnnouncement(FPlayer fPlayer, String msg); - // FIELD: relationWish - private Map relationWish; + public void sendUnreadAnnouncements(FPlayer fPlayer); - // FIELD: claimOwnership - private Map> claimOwnership = new ConcurrentHashMap>(); + public void removeAnnouncements(FPlayer fPlayer); - // FIELD: fplayers - // speedy lookup of players in faction - private transient Set fplayers = new HashSet(); + public Set getInvites(); - private HashMap> announcements; + public String getId(); - public HashMap> getAnnouncements() { - return this.announcements; - } + public void invite(FPlayer fplayer); - public void addAnnouncement(FPlayer fPlayer, String msg) { - List list = announcements.containsKey(fPlayer.getId()) ? announcements.get(fPlayer.getId()) : new ArrayList(); - list.add(msg); - announcements.put(fPlayer.getId(), list); - } + public void deinvite(FPlayer fplayer); - public void sendUnreadAnnouncements(FPlayer fPlayer) { - if (!announcements.containsKey(fPlayer.getId())) { - return; - } - fPlayer.sendMessage(ChatColor.LIGHT_PURPLE + "--Unread Faction Announcements--"); - for (String s : announcements.get(fPlayer.getPlayer().getUniqueId().toString())) { - fPlayer.sendMessage(s); - } - fPlayer.sendMessage(ChatColor.LIGHT_PURPLE + "--Unread Faction Announcements--"); - announcements.remove(fPlayer.getId()); - } - - public void removeAnnouncements(FPlayer fPlayer) { - if (announcements.containsKey(fPlayer.getId())) { - announcements.remove(fPlayer.getId()); - } - } - - - // FIELD: invites - private Set invites; - - public Set getInvites() { - return invites; - } - - public void invite(FPlayer fplayer) { - this.invites.add(fplayer.getId()); - } - - public void deinvite(FPlayer fplayer) { - this.invites.remove(fplayer.getId()); - } - - public boolean isInvited(FPlayer fplayer) { - return this.invites.contains(fplayer.getId()); - } + public boolean isInvited(FPlayer fplayer); - // FIELD: open - private boolean open; - - public boolean getOpen() { - return open; - } - - public void setOpen(boolean isOpen) { - open = isOpen; - } - - // FIELD: peaceful - // "peaceful" status can only be set by server admins/moderators/ops, and prevents PvP and land capture to/from the faction - private boolean peaceful; - - public boolean isPeaceful() { - return this.peaceful; - } - - public void setPeaceful(boolean isPeaceful) { - this.peaceful = isPeaceful; - } - - // FIELD: peacefulExplosionsEnabled - private boolean peacefulExplosionsEnabled; - - public void setPeacefulExplosionsEnabled(boolean val) { - peacefulExplosionsEnabled = val; - } - - public boolean getPeacefulExplosionsEnabled() { - return this.peacefulExplosionsEnabled; - } - - public boolean noExplosionsInTerritory() { - return this.peaceful && !peacefulExplosionsEnabled; - } - - // FIELD: permanent - // "permanent" status can only be set by server admins/moderators/ops, and allows the faction to remain even with 0 members - private boolean permanent; - - public boolean isPermanent() { - return permanent || !this.isNormal(); - } - - public void setPermanent(boolean isPermanent) { - permanent = isPermanent; - } - - // FIELD: tag - private String tag; - - public String getTag() { - return this.tag; - } - - public String getTag(String prefix) { - return prefix + this.tag; - } - - public String getTag(Faction otherFaction) { - if (otherFaction == null) { - return getTag(); - } - return this.getTag(this.getColorTo(otherFaction).toString()); - } + public boolean getOpen(); - public String getTag(FPlayer otherFplayer) { - if (otherFplayer == null) { - return getTag(); - } - return this.getTag(this.getColorTo(otherFplayer).toString()); - } + public void setOpen(boolean isOpen); - public void setTag(String str) { - if (Conf.factionTagForceUpperCase) { - str = str.toUpperCase(); - } - this.tag = str; - } - - public String getComparisonTag() { - return MiscUtil.getComparisonString(this.tag); - } - - // FIELD: description - private String description; - - public String getDescription() { - return this.description; - } - - public void setDescription(String value) { - this.description = value; - } - - // FIELD: home - private LazyLocation home; - - public void setHome(Location home) { - this.home = new LazyLocation(home); - } - - public boolean hasHome() { - return this.getHome() != null; - } - - public Location getHome() { - confirmValidHome(); - return (this.home != null) ? this.home.getLocation() : null; - } - - public void confirmValidHome() { - if (!Conf.homesMustBeInClaimedTerritory || this.home == null || (this.home.getLocation() != null && Board.getFactionAt(new FLocation(this.home.getLocation())) == this)) { - return; - } - - msg("Your faction home has been un-set since it is no longer in your territory."); - this.home = null; - } - - // FIELD: lastPlayerLoggedOffTime - private transient long lastPlayerLoggedOffTime; - - // FIELD: account (fake field) - // Bank functions - public double money; - - public String getAccountId() { - String aid = "faction-" + this.getId(); - - // We need to override the default money given to players. - if (!Econ.hasAccount(aid)) { - Econ.setBalance(aid, 0); - } - - return aid; - } - - // FIELD: permanentPower - private Integer permanentPower; - - public Integer getPermanentPower() { - return this.permanentPower; - } - - public void setPermanentPower(Integer permanentPower) { - this.permanentPower = permanentPower; - } - - public boolean hasPermanentPower() { - return this.permanentPower != null; - } - - // FIELD: powerBoost - // special increase/decrease to default and max power for this faction - private double powerBoost; - - public double getPowerBoost() { - return this.powerBoost; - } - - public void setPowerBoost(double powerBoost) { - this.powerBoost = powerBoost; - } - - - // -------------------------------------------- // - // Construct - // -------------------------------------------- // - - public Faction() { - this.relationWish = new HashMap(); - this.invites = new HashSet(); - this.open = Conf.newFactionsDefaultOpen; - this.tag = "???"; - this.description = "Default faction description :("; - this.lastPlayerLoggedOffTime = 0; - this.peaceful = false; - this.peacefulExplosionsEnabled = false; - this.permanent = false; - this.money = 0.0; - this.powerBoost = 0.0; - this.announcements = new HashMap>(); - } + public boolean isPeaceful(); - // -------------------------------------------- // - // Extra Getters And Setters - // -------------------------------------------- // + public void setPeaceful(boolean isPeaceful); - public boolean noPvPInTerritory() { - return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisablePVP); - } + public void setPeacefulExplosionsEnabled(boolean val); - public boolean noMonstersInTerritory() { - return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisableMonsters); - } + public boolean getPeacefulExplosionsEnabled(); + public boolean noExplosionsInTerritory(); - // ------------------------------- - // Understand the types - // ------------------------------- + public boolean isPermanent(); - public boolean isNormal() { - return !(this.isNone() || this.isSafeZone() || this.isWarZone()); - } + public void setPermanent(boolean isPermanent); - public boolean isNone() { - return this.getId().equals("0"); - } + public String getTag(); - public boolean isSafeZone() { - return this.getId().equals("-1"); - } + public String getTag(String prefix); - public boolean isWarZone() { - return this.getId().equals("-2"); - } + public String getTag(Faction otherFaction); - public boolean isPlayerFreeType() { - return this.isSafeZone() || this.isWarZone(); - } + public String getTag(FPlayer otherFplayer); + public void setTag(String str); + + public String getComparisonTag(); + + public String getDescription(); + + public void setDescription(String value); + + public void setHome(Location home); + + public boolean hasHome(); + + public Location getHome(); + + public void confirmValidHome(); + + public String getAccountId(); + + public Integer getPermanentPower(); + + public void setPermanentPower(Integer permanentPower); + + public boolean hasPermanentPower(); + + public double getPowerBoost(); + + public void setPowerBoost(double powerBoost); + + public boolean noPvPInTerritory(); + + public boolean noMonstersInTerritory(); + + public boolean isNormal(); + + public boolean isNone(); + + public boolean isSafeZone(); + + public boolean isWarZone(); + + public boolean isPlayerFreeType(); // ------------------------------- // Relation and relation colors // ------------------------------- @Override - public String describeTo(RelationParticipator that, boolean ucfirst) { - return RelationUtil.describeThatToMe(this, that, ucfirst); - } + public String describeTo(RelationParticipator that, boolean ucfirst); @Override - public String describeTo(RelationParticipator that) { - return RelationUtil.describeThatToMe(this, that); - } + public String describeTo(RelationParticipator that); @Override - public Relation getRelationTo(RelationParticipator rp) { - return RelationUtil.getRelationTo(this, rp); - } + public Relation getRelationTo(RelationParticipator rp); @Override - public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful) { - return RelationUtil.getRelationTo(this, rp, ignorePeaceful); - } + public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful); @Override - public ChatColor getColorTo(RelationParticipator rp) { - return RelationUtil.getColorOfThatToMe(this, rp); - } + public ChatColor getColorTo(RelationParticipator rp); - public Relation getRelationWish(Faction otherFaction) { - if (this.relationWish.containsKey(otherFaction.getId())) { - return this.relationWish.get(otherFaction.getId()); - } - return Relation.NEUTRAL; - } + public Relation getRelationWish(Faction otherFaction); - public void setRelationWish(Faction otherFaction, Relation relation) { - if (this.relationWish.containsKey(otherFaction.getId()) && relation.equals(Relation.NEUTRAL)) { - this.relationWish.remove(otherFaction.getId()); - } else { - this.relationWish.put(otherFaction.getId(), relation); - } - } + public void setRelationWish(Faction otherFaction, Relation relation); - //----------------------------------------------// + // ----------------------------------------------// // Power - //----------------------------------------------// - public double getPower() { - if (this.hasPermanentPower()) { - return this.getPermanentPower(); - } + // ----------------------------------------------// + public double getPower(); - double ret = 0; - for (FPlayer fplayer : fplayers) { - ret += fplayer.getPower(); - } - if (Conf.powerFactionMax > 0 && ret > Conf.powerFactionMax) { - ret = Conf.powerFactionMax; - } - return ret + this.powerBoost; - } + public double getPowerMax(); - public double getPowerMax() { - if (this.hasPermanentPower()) { - return this.getPermanentPower(); - } + public int getPowerRounded(); - double ret = 0; - for (FPlayer fplayer : fplayers) { - ret += fplayer.getPowerMax(); - } - if (Conf.powerFactionMax > 0 && ret > Conf.powerFactionMax) { - ret = Conf.powerFactionMax; - } - return ret + this.powerBoost; - } + public int getPowerMaxRounded(); - public int getPowerRounded() { - return (int) Math.round(this.getPower()); - } + public int getLandRounded(); - public int getPowerMaxRounded() { - return (int) Math.round(this.getPowerMax()); - } + public int getLandRoundedInWorld(String worldName); - public int getLandRounded() { - return Board.getFactionCoordCount(this); - } - - public int getLandRoundedInWorld(String worldName) { - return Board.getFactionCoordCountInWorld(this, worldName); - } - - public boolean hasLandInflation() { - return this.getLandRounded() > this.getPowerRounded(); - } + public boolean hasLandInflation(); // ------------------------------- // FPlayers // ------------------------------- // maintain the reference list of FPlayers in this faction - public void refreshFPlayers() { - fplayers.clear(); - if (this.isPlayerFreeType()) { - return; - } + public void refreshFPlayers(); - for (FPlayer fplayer : FPlayers.i.get()) { - if (fplayer.getFaction() == this) { - fplayers.add(fplayer); - } - } - } + public boolean addFPlayer(FPlayer fplayer); - protected boolean addFPlayer(FPlayer fplayer) { - return !this.isPlayerFreeType() && fplayers.add(fplayer); + public boolean removeFPlayer(FPlayer fplayer); - } + public Set getFPlayers(); - protected boolean removeFPlayer(FPlayer fplayer) { - return !this.isPlayerFreeType() && fplayers.remove(fplayer); + public Set getFPlayersWhereOnline(boolean online); - } + public FPlayer getFPlayerAdmin(); - public Set getFPlayers() { - // return a shallow copy of the FPlayer list, to prevent tampering and concurrency issues - return new HashSet(fplayers); - } + public ArrayList getFPlayersWhereRole(Role role); - public Set getFPlayersWhereOnline(boolean online) { - Set ret = new HashSet(); + public ArrayList getOnlinePlayers(); - for (FPlayer fplayer : fplayers) { - if (fplayer.isOnline() == online) { - ret.add(fplayer); - } - } + // slightly faster check than getOnlinePlayers() if you just want to see if + // there are any players online + public boolean hasPlayersOnline(); - return ret; - } + public void memberLoggedOff(); - public FPlayer getFPlayerAdmin() { - if (!this.isNormal()) { - return null; - } + // used when current leader is about to be removed from the faction; + // promotes new leader, or disbands faction if no other members left + public void promoteNewLeader(); - for (FPlayer fplayer : fplayers) { - if (fplayer.getRole() == Role.ADMIN) { - return fplayer; - } - } - return null; - } - - public ArrayList getFPlayersWhereRole(Role role) { - ArrayList ret = new ArrayList(); - if (!this.isNormal()) { - return ret; - } - - for (FPlayer fplayer : fplayers) { - if (fplayer.getRole() == role) { - ret.add(fplayer); - } - } - - return ret; - } - - public ArrayList getOnlinePlayers() { - ArrayList ret = new ArrayList(); - if (this.isPlayerFreeType()) { - return ret; - } - - for (Player player : P.p.getServer().getOnlinePlayers()) { - FPlayer fplayer = FPlayers.i.get(player); - if (fplayer.getFaction() == this) { - ret.add(player); - } - } - - return ret; - } - - // slightly faster check than getOnlinePlayers() if you just want to see if there are any players online - public boolean hasPlayersOnline() { - // only real factions can have players online, not safe zone / war zone - if (this.isPlayerFreeType()) { - return false; - } - - for (Player player : P.p.getServer().getOnlinePlayers()) { - FPlayer fplayer = FPlayers.i.get(player); - if (fplayer != null && fplayer.getFaction() == this) { - return true; - } - } - - // even if all players are technically logged off, maybe someone was on recently enough to not consider them officially offline yet - return Conf.considerFactionsReallyOfflineAfterXMinutes > 0 && System.currentTimeMillis() < lastPlayerLoggedOffTime + (Conf.considerFactionsReallyOfflineAfterXMinutes * 60000); - } - - public void memberLoggedOff() { - if (this.isNormal()) { - lastPlayerLoggedOffTime = System.currentTimeMillis(); - } - } - - // used when current leader is about to be removed from the faction; promotes new leader, or disbands faction if no other members left - public void promoteNewLeader() { - if (!this.isNormal()) { - return; - } - if (this.isPermanent() && Conf.permanentFactionsDisableLeaderPromotion) { - return; - } - - FPlayer oldLeader = this.getFPlayerAdmin(); - - // get list of moderators, or list of normal members if there are no moderators - ArrayList replacements = this.getFPlayersWhereRole(Role.MODERATOR); - if (replacements == null || replacements.isEmpty()) { - replacements = this.getFPlayersWhereRole(Role.NORMAL); - } - - if (replacements == null || replacements.isEmpty()) { // faction admin is the only member; one-man faction - if (this.isPermanent()) { - if (oldLeader != null) { - oldLeader.setRole(Role.NORMAL); - } - return; - } - - // no members left and faction isn't permanent, so disband it - if (Conf.logFactionDisband) { - P.p.log("The faction " + this.getTag() + " (" + this.getId() + ") has been disbanded since it has no members left."); - } - - for (FPlayer fplayer : FPlayers.i.getOnline()) { - fplayer.msg("The faction %s was disbanded.", this.getTag(fplayer)); - } - - this.detach(); - } else { // promote new faction admin - if (oldLeader != null) { - oldLeader.setRole(Role.NORMAL); - } - replacements.get(0).setRole(Role.ADMIN); - this.msg("Faction admin %s has been removed. %s has been promoted as the new faction admin.", oldLeader == null ? "" : oldLeader.getName(), replacements.get(0).getName()); - P.p.log("Faction " + this.getTag() + " (" + this.getId() + ") admin was removed. Replacement admin: " + replacements.get(0).getName()); - } - } - - - //----------------------------------------------// + // ----------------------------------------------// // Messages - //----------------------------------------------// - public void msg(String message, Object... args) { - message = P.p.txt.parse(message, args); + // ----------------------------------------------// + public void msg(String message, Object... args); - for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { - fplayer.sendMessage(message); - } - } + public void sendMessage(String message); - public void sendMessage(String message) { - for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { - fplayer.sendMessage(message); - } - } + public void sendMessage(List messages); - public void sendMessage(List messages) { - for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { - fplayer.sendMessage(messages); - } - } - - //----------------------------------------------// + // ----------------------------------------------// // Ownership of specific claims - //----------------------------------------------// + // ----------------------------------------------// - public Map> getClaimOwnership() { - return claimOwnership; - } + public Map> getClaimOwnership(); - public void clearAllClaimOwnership() { - claimOwnership.clear(); - } + public void clearAllClaimOwnership(); - public void clearClaimOwnership(FLocation loc) { - claimOwnership.remove(loc); - } + public void clearClaimOwnership(FLocation loc); - public void clearClaimOwnership(FPlayer player) { - if (id == null || id.isEmpty()) { - return; - } + public void clearClaimOwnership(FPlayer player); - Set ownerData; + public int getCountOfClaimsWithOwners(); - for (Entry> entry : claimOwnership.entrySet()) { - ownerData = entry.getValue(); + public boolean doesLocationHaveOwnersSet(FLocation loc); - if (ownerData == null) { - continue; - } + public boolean isPlayerInOwnerList(FPlayer player, FLocation loc); - Iterator iter = ownerData.iterator(); - while (iter.hasNext()) { - if (iter.next().equals(player.getId())) { - iter.remove(); - } - } + public void setPlayerAsOwner(FPlayer player, FLocation loc); - if (ownerData.isEmpty()) { - claimOwnership.remove(entry.getKey()); - } - } - } + public void removePlayerAsOwner(FPlayer player, FLocation loc); - public int getCountOfClaimsWithOwners() { - return claimOwnership.isEmpty() ? 0 : claimOwnership.size(); - } + public Set getOwnerList(FLocation loc); - public boolean doesLocationHaveOwnersSet(FLocation loc) { - if (claimOwnership.isEmpty() || !claimOwnership.containsKey(loc)) { - return false; - } + public String getOwnerListString(FLocation loc); - Set ownerData = claimOwnership.get(loc); - return ownerData != null && !ownerData.isEmpty(); - } + public boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc); - public boolean isPlayerInOwnerList(FPlayer player, FLocation loc) { - if (claimOwnership.isEmpty()) { - return false; - } - Set ownerData = claimOwnership.get(loc); - if (ownerData == null) { - return false; - } - return ownerData.contains(player.getId()); - } - - public void setPlayerAsOwner(FPlayer player, FLocation loc) { - Set ownerData = claimOwnership.get(loc); - if (ownerData == null) { - ownerData = new HashSet(); - } - ownerData.add(player.getId()); - claimOwnership.put(loc, ownerData); - } - - public void removePlayerAsOwner(FPlayer player, FLocation loc) { - Set ownerData = claimOwnership.get(loc); - if (ownerData == null) { - return; - } - ownerData.remove(player.getId()); - claimOwnership.put(loc, ownerData); - } - - public Set getOwnerList(FLocation loc) { - return claimOwnership.get(loc); - } - - public String getOwnerListString(FLocation loc) { - Set ownerData = claimOwnership.get(loc); - if (ownerData == null || ownerData.isEmpty()) { - return ""; - } - - String ownerList = ""; - - Iterator iter = ownerData.iterator(); - while (iter.hasNext()) { - if (!ownerList.isEmpty()) { - ownerList += ", "; - } - OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(UUID.fromString(iter.next())); - ownerList += offlinePlayer != null ? offlinePlayer.getName() : "null player"; - } - return ownerList; - } - - public boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc) { - // in own faction, with sufficient role or permission to bypass ownership? - if (fplayer.getFaction() == this && (fplayer.getRole().isAtLeast(Conf.ownedAreaModeratorsBypass ? Role.MODERATOR : Role.ADMIN) || Permission.OWNERSHIP_BYPASS.has(fplayer.getPlayer()))) { - return true; - } - - // make sure claimOwnership is initialized - if (claimOwnership.isEmpty()) { - 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 - return ownerData == null || ownerData.isEmpty() || ownerData.contains(fplayer.getId()); - } - - - //----------------------------------------------// + // ----------------------------------------------// // Persistance and entity management - //----------------------------------------------// + // ----------------------------------------------// + public void remove(); - - @Override - public void postDetach() { - if (Econ.shouldBeUsed()) { - Econ.setBalance(getAccountId(), 0); - } - - // Clean the board - Board.clean(); - - // Clean the fplayers - FPlayers.i.clean(); - } + public void setId(String id); } diff --git a/src/main/java/com/massivecraft/factions/Factions.java b/src/main/java/com/massivecraft/factions/Factions.java index a00a2653..cb24f0d6 100644 --- a/src/main/java/com/massivecraft/factions/Factions.java +++ b/src/main/java/com/massivecraft/factions/Factions.java @@ -1,184 +1,50 @@ package com.massivecraft.factions; -import com.google.gson.reflect.TypeToken; -import com.massivecraft.factions.util.MiscUtil; -import com.massivecraft.factions.zcore.persist.EntityCollection; -import com.massivecraft.factions.zcore.util.TL; -import com.massivecraft.factions.zcore.util.TextUtil; -import org.bukkit.ChatColor; - -import java.io.File; -import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.logging.Level; +import java.util.Set; -public class Factions extends EntityCollection { +import com.massivecraft.factions.zcore.persist.json.JSONFactions; - public static Factions i = new Factions(); +public abstract class Factions { + protected static Factions instance = getFactionsImpl(); - P p = P.p; + public abstract Faction getFactionById(String id); - private Factions() { - super(Faction.class, new CopyOnWriteArrayList(), new ConcurrentHashMap(), new File(P.p.getDataFolder(), "factions.json"), P.p.gson); + public abstract Faction getByTag(String str); + + public abstract Faction getBestTagMatch(String start); + + public abstract boolean isTagTaken(String str); + + public abstract boolean isValidFactionId(String id); + + public abstract Faction createFaction(); + + public abstract void removeFaction(String id); + + public abstract Set getFactionTags(); + + public abstract ArrayList getAllFactions(); + + public abstract Faction getNone(); + + public abstract Faction getSafeZone(); + + public abstract Faction getWarZone(); + + public abstract void forceSave(); + + public static Factions getInstance() { + return instance; } - @Override - public Type getMapType() { - return new TypeToken>() { - }.getType(); - } - - @Override - public boolean loadFromDisc() { - if (!super.loadFromDisc()) { - return false; - } - - // Make sure the default neutral faction exists - if (!this.exists("0")) { - Faction faction = this.create("0"); - faction.setTag(TL.WILDERNESS.toString()); - faction.setDescription(TL.WILDERNESS_DESCRIPTION.toString()); - } else { - if (!this.get("0").getTag().equalsIgnoreCase(TL.WILDERNESS.toString())) { - get("0").setTag(TL.WILDERNESS.toString()); - } - if (!this.get("0").getDescription().equalsIgnoreCase(TL.WILDERNESS_DESCRIPTION.toString())) { - get("0").setDescription(TL.WILDERNESS_DESCRIPTION.toString()); - } - } - - // Make sure the safe zone faction exists - if (!this.exists("-1")) { - Faction faction = this.create("-1"); - faction.setTag(TL.SAFEZONE.toString()); - faction.setDescription(TL.SAFEZONE_DESCRIPTION.toString()); - } else { - if (!getSafeZone().getTag().equalsIgnoreCase(TL.SAFEZONE.toString())) { - getSafeZone().setTag(TL.SAFEZONE.toString()); - } - if (!getSafeZone().getDescription().equalsIgnoreCase(TL.SAFEZONE_DESCRIPTION.toString())) { - getSafeZone().setDescription(TL.SAFEZONE_DESCRIPTION.toString()); - } - // if SafeZone has old pre-1.6.0 name, rename it to remove troublesome " " - Faction faction = this.getSafeZone(); - if (faction.getTag().contains(" ")) { - faction.setTag(TL.SAFEZONE.toString()); - } - } - - // Make sure the war zone faction exists - if (!this.exists("-2")) { - Faction faction = this.create("-2"); - faction.setTag(TL.WARZONE.toString()); - faction.setDescription(TL.WARZONE_DESCRIPTION.toString()); - } else { - if (!getWarZone().getTag().equalsIgnoreCase(TL.WARZONE.toString())) { - getWarZone().setTag(TL.WARZONE.toString()); - } - if (!getWarZone().getDescription().equalsIgnoreCase(TL.WARZONE_DESCRIPTION.toString())) { - getWarZone().setDescription(TL.WARZONE_DESCRIPTION.toString()); - } - // if WarZone has old pre-1.6.0 name, rename it to remove troublesome " " - Faction faction = this.getWarZone(); - if (faction.getTag().contains(" ")) { - faction.setTag(TL.WARZONE.toString()); - } - } - - // populate all faction player lists - for (Faction faction : i.get()) { - faction.refreshFPlayers(); - } - - return true; - } - - - //----------------------------------------------// - // GET - //----------------------------------------------// - - @Override - public Faction get(String id) { - if (!this.exists(id)) { - p.log(Level.WARNING, "Non existing factionId " + id + " requested! Issuing cleaning!"); - Board.clean(); - FPlayers.i.clean(); - } - - return super.get(id); - } - - public Faction getNone() { - return this.get("0"); - } - - public Faction getSafeZone() { - return this.get("-1"); - } - - public Faction getWarZone() { - return this.get("-2"); - } - - - //----------------------------------------------// - // Faction tag - //----------------------------------------------// - - public static ArrayList validateTag(String str) { - ArrayList errors = new ArrayList(); - - if (MiscUtil.getComparisonString(str).length() < Conf.factionTagLengthMin) { - errors.add(P.p.txt.parse("The faction tag can't be shorter than %s chars.", Conf.factionTagLengthMin)); - } - - if (str.length() > Conf.factionTagLengthMax) { - errors.add(P.p.txt.parse("The faction tag can't be longer than %s chars.", Conf.factionTagLengthMax)); - } - - for (char c : str.toCharArray()) { - if (!MiscUtil.substanceChars.contains(String.valueOf(c))) { - errors.add(P.p.txt.parse("Faction tag must be alphanumeric. \"%s\" is not allowed.", c)); - } - } - - return errors; - } - - // Loops through all faction tags. Case and color insensitive. - public Faction getByTag(String str) { - String compStr = MiscUtil.getComparisonString(str); - for (Faction faction : this.get()) { - if (faction.getComparisonTag().equals(compStr)) { - return faction; - } + private static Factions getFactionsImpl() { + switch (Conf.backEnd) { + case JSON: + return new JSONFactions(); } return null; } - public Faction getBestTagMatch(String searchFor) { - Map tag2faction = new HashMap(); - - // TODO: Slow index building - for (Faction faction : this.get()) { - tag2faction.put(ChatColor.stripColor(faction.getTag()), faction); - } - - String tag = TextUtil.getBestStartWithCI(tag2faction.keySet(), searchFor); - if (tag == null) { - return null; - } - return tag2faction.get(tag); - } - - public boolean isTagTaken(String str) { - return this.getByTag(str) != null; - } - + public abstract void load(); } diff --git a/src/main/java/com/massivecraft/factions/P.java b/src/main/java/com/massivecraft/factions/P.java index 5c9fbed2..d3deef45 100644 --- a/src/main/java/com/massivecraft/factions/P.java +++ b/src/main/java/com/massivecraft/factions/P.java @@ -12,6 +12,7 @@ import com.massivecraft.factions.struct.ChatMode; import com.massivecraft.factions.util.*; import com.massivecraft.factions.zcore.MPlugin; import com.massivecraft.factions.zcore.util.TextUtil; + import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -77,9 +78,18 @@ public class P extends MPlugin { // Load Conf from disk Conf.load(); Essentials.setup(); - FPlayers.i.loadFromDisc(); - Factions.i.loadFromDisc(); - Board.load(); + FPlayers.getInstance().load(); + Factions.getInstance().load(); + for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { + Faction faction = Factions.getInstance().getFactionById(fPlayer.getFactionId()); + if (faction == null) { + log("Invalid faction id on " + fPlayer.getName() + ":" + fPlayer.getFactionId()); + fPlayer.resetFactionData(false); + continue; + } + faction.addFPlayer(fPlayer); + } + Board.getInstance().load(); // Add Base Commands this.cmdBase = new FCmdRoot(); @@ -122,7 +132,6 @@ public class P extends MPlugin { public void onDisable() { // only save data if plugin actually completely loaded successfully if (this.loadSuccessful) { - Board.save(); Conf.save(); } if (AutoLeaveTask != null) { @@ -150,7 +159,7 @@ public class P extends MPlugin { @Override public void postAutoSave() { - Board.save(); + Board.getInstance().forceSave(); Conf.save(); } @@ -204,7 +213,7 @@ public class P extends MPlugin { if (player == null) { return false; } - FPlayer me = FPlayers.i.get(player); + FPlayer me = FPlayers.getInstance().getByPlayer(player); return me != null && me.getChatMode().isAtLeast(ChatMode.ALLIANCE); } @@ -230,7 +239,7 @@ public class P extends MPlugin { return tag; } - FPlayer me = FPlayers.i.get(speaker); + FPlayer me = FPlayers.getInstance().getByPlayer(speaker); if (me == null) { return tag; } @@ -239,7 +248,7 @@ public class P extends MPlugin { if (listener == null || !Conf.chatTagRelationColored) { tag = me.getChatTag().trim(); } else { - FPlayer you = FPlayers.i.get(listener); + FPlayer you = FPlayers.getInstance().getByPlayer(listener); if (you == null) { tag = me.getChatTag().trim(); } else // everything checks out, give the colored tag @@ -260,7 +269,7 @@ public class P extends MPlugin { return ""; } - FPlayer me = FPlayers.i.get(player); + FPlayer me = FPlayers.getInstance().getByPlayer(player); if (me == null) { return ""; } @@ -270,17 +279,13 @@ public class P extends MPlugin { // Get a list of all faction tags (names) public Set getFactionTags() { - Set tags = new HashSet(); - for (Faction faction : Factions.i.get()) { - tags.add(faction.getTag()); - } - return tags; + return Factions.getInstance().getFactionTags(); } // Get a list of all players in the specified faction public Set getPlayersInFaction(String factionTag) { Set players = new HashSet(); - Faction faction = Factions.i.getByTag(factionTag); + Faction faction = Factions.getInstance().getByTag(factionTag); if (faction != null) { for (FPlayer fplayer : faction.getFPlayers()) { players.add(fplayer.getName()); @@ -292,7 +297,7 @@ public class P extends MPlugin { // Get a list of all online players in the specified faction public Set getOnlinePlayersInFaction(String factionTag) { Set players = new HashSet(); - Faction faction = Factions.i.getByTag(factionTag); + Faction faction = Factions.getInstance().getByTag(factionTag); if (faction != null) { for (FPlayer fplayer : faction.getFPlayersWhereOnline(true)) { players.add(fplayer.getName()); diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdAdmin.java b/src/main/java/com/massivecraft/factions/cmd/CmdAdmin.java index aa5d4e9b..73d62ad0 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdAdmin.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdAdmin.java @@ -53,7 +53,7 @@ public class CmdAdmin extends FCommand { // only perform a FPlayerJoinEvent when newLeader isn't actually in the faction if (fyou.getFaction() != targetFaction) { - FPlayerJoinEvent event = new FPlayerJoinEvent(FPlayers.i.get(me), targetFaction, FPlayerJoinEvent.PlayerJoinReason.LEADER); + FPlayerJoinEvent event = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), targetFaction, FPlayerJoinEvent.PlayerJoinReason.LEADER); Bukkit.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return; @@ -78,7 +78,7 @@ public class CmdAdmin extends FCommand { msg("You have promoted %s to the position of faction admin.", fyou.describeTo(fme, true)); // Inform all players - for (FPlayer fplayer : FPlayers.i.getOnline()) { + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { fplayer.msg("%s gave %s the leadership of %s.", senderIsConsole ? "A server admin" : fme.describeTo(fplayer, true), fyou.describeTo(fplayer), targetFaction.describeTo(fplayer)); } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdConvert.java b/src/main/java/com/massivecraft/factions/cmd/CmdConvert.java new file mode 100644 index 00000000..cfc319d3 --- /dev/null +++ b/src/main/java/com/massivecraft/factions/cmd/CmdConvert.java @@ -0,0 +1,39 @@ +package com.massivecraft.factions.cmd; + +import org.bukkit.command.ConsoleCommandSender; + +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.Conf.Backend; +import com.massivecraft.factions.zcore.persist.json.FactionsJSON; + +public class CmdConvert extends FCommand { + + public CmdConvert() { + this.aliases.add("convert"); + + this.requiredArgs.add("[MYSQL|JSON]"); + } + + @Override + public void perform() { + if (!(this.sender instanceof ConsoleCommandSender)) { + this.sender.sendMessage("Console only command"); + } + Backend nb = Backend.valueOf(this.argAsString(0).toUpperCase()); + if (nb == Conf.backEnd) { + this.sender.sendMessage("Already running that backend"); + return; + } + switch (nb) { + case JSON: + FactionsJSON.convertTo(); + break; + default: + this.sender.sendMessage("Invalid backend"); + return; + + } + Conf.backEnd = nb; + } + +} diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java b/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java index bf45f706..a7c23313 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdCreate.java @@ -5,6 +5,8 @@ import com.massivecraft.factions.event.FPlayerJoinEvent; import com.massivecraft.factions.event.FactionCreateEvent; import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.struct.Role; +import com.massivecraft.factions.util.MiscUtil; + import org.bukkit.Bukkit; import java.util.ArrayList; @@ -37,12 +39,12 @@ public class CmdCreate extends FCommand { return; } - if (Factions.i.isTagTaken(tag)) { + if (Factions.getInstance().isTagTaken(tag)) { msg("That tag is already in use."); return; } - ArrayList tagValidationErrors = Factions.validateTag(tag); + ArrayList tagValidationErrors = MiscUtil.validateTag(tag); if (tagValidationErrors.size() > 0) { sendMessage(tagValidationErrors); return; @@ -65,7 +67,7 @@ public class CmdCreate extends FCommand { return; } - Faction faction = Factions.i.create(); + Faction faction = Factions.getInstance().createFaction(); // TODO: Why would this even happen??? Auto increment clash?? if (faction == null) { @@ -77,7 +79,7 @@ public class CmdCreate extends FCommand { faction.setTag(tag); // trigger the faction join event for the creator - FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.i.get(me), faction, FPlayerJoinEvent.PlayerJoinReason.CREATE); + FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), faction, FPlayerJoinEvent.PlayerJoinReason.CREATE); Bukkit.getServer().getPluginManager().callEvent(joinEvent); // join event cannot be cancelled or you'll have an empty faction @@ -85,7 +87,7 @@ public class CmdCreate extends FCommand { fme.setRole(Role.ADMIN); fme.setFaction(faction); - for (FPlayer follower : FPlayers.i.getOnline()) { + for (FPlayer follower : FPlayers.getInstance().getOnlinePlayers()) { follower.msg("%s created a new faction %s", fme.describeTo(follower, true), faction.getTag(follower)); } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdDescription.java b/src/main/java/com/massivecraft/factions/cmd/CmdDescription.java index 4a0d29e5..65bd8871 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdDescription.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdDescription.java @@ -41,7 +41,7 @@ public class CmdDescription extends FCommand { } // Broadcast the description to everyone - for (FPlayer fplayer : FPlayers.i.getOnline()) { + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { fplayer.msg("The faction %s changed their description to:", myFaction.describeTo(fplayer)); fplayer.sendMessage(myFaction.getDescription()); // players can inject "&" or "`" or "" or whatever in their description; &k is particularly interesting looking } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdDisband.java b/src/main/java/com/massivecraft/factions/cmd/CmdDisband.java index 33a86dc5..78150b98 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdDisband.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdDisband.java @@ -68,7 +68,7 @@ public class CmdDisband extends FCommand { } // Inform all players - for (FPlayer fplayer : FPlayers.i.getOnline()) { + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { String who = senderIsConsole ? "A server admin" : fme.describeTo(fplayer); if (fplayer.getFaction() == faction) { fplayer.msg("%s disbanded your faction.", who); @@ -92,6 +92,6 @@ public class CmdDisband extends FCommand { } } - faction.detach(); + Factions.getInstance().removeFaction(faction.getId()); } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdHome.java b/src/main/java/com/massivecraft/factions/cmd/CmdHome.java index 4154ca0d..c70a09ee 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdHome.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdHome.java @@ -61,7 +61,7 @@ public class CmdHome extends FCommand { return; } - Faction faction = Board.getFactionAt(new FLocation(me.getLocation())); + Faction faction = Board.getInstance().getFactionAt(new FLocation(me.getLocation())); Location loc = me.getLocation().clone(); // if player is not in a safe zone or their own faction territory, only allow teleport if no enemies are nearby @@ -78,7 +78,7 @@ public class CmdHome extends FCommand { continue; } - FPlayer fp = FPlayers.i.get(p); + FPlayer fp = FPlayers.getInstance().getByPlayer(p); if (fme.getRelationTo(fp) != Relation.ENEMY) { continue; } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdJoin.java b/src/main/java/com/massivecraft/factions/cmd/CmdJoin.java index 67faa253..b86574f2 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdJoin.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdJoin.java @@ -77,7 +77,7 @@ public class CmdJoin extends FCommand { } // trigger the join event (cancellable) - FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.i.get(me), faction, FPlayerJoinEvent.PlayerJoinReason.COMMAND); + FPlayerJoinEvent joinEvent = new FPlayerJoinEvent(FPlayers.getInstance().getByPlayer(me), faction, FPlayerJoinEvent.PlayerJoinReason.COMMAND); Bukkit.getServer().getPluginManager().callEvent(joinEvent); if (joinEvent.isCancelled()) { return; diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdList.java b/src/main/java/com/massivecraft/factions/cmd/CmdList.java index d9184014..76a5747d 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdList.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdList.java @@ -36,10 +36,10 @@ public class CmdList extends FCommand { return; } - ArrayList factionList = new ArrayList(Factions.i.get()); - factionList.remove(Factions.i.getNone()); - factionList.remove(Factions.i.getSafeZone()); - factionList.remove(Factions.i.getWarZone()); + ArrayList factionList = Factions.getInstance().getAllFactions(); + factionList.remove(Factions.getInstance().getNone()); + factionList.remove(Factions.getInstance().getSafeZone()); + factionList.remove(Factions.getInstance().getWarZone()); // Sort by total followers first Collections.sort(factionList, new Comparator() { @@ -90,7 +90,7 @@ public class CmdList extends FCommand { sendMessage(p.txt.getPage(lines, this.argAsInt(0, 1), "Faction List")); */ - factionList.add(0, Factions.i.getNone()); + factionList.add(0, Factions.getInstance().getNone()); final int pageheight = 9; int pagenumber = this.argAsInt(0, 1); @@ -110,7 +110,7 @@ public class CmdList extends FCommand { for (Faction faction : factionList.subList(start, end)) { if (faction.isNone()) { - lines.add(p.txt.parse("Factionless %d online", Factions.i.getNone().getFPlayersWhereOnline(true).size())); + lines.add(p.txt.parse("Factionless %d online", Factions.getInstance().getNone().getFPlayersWhereOnline(true).size())); continue; } lines.add(p.txt.parse("%s %d/%d online, %d/%d/%d", faction.getTag(fme), faction.getFPlayersWhereOnline(true).size(), faction.getFPlayers().size(), faction.getLandRounded(), faction.getPowerRounded(), faction.getPowerMaxRounded())); diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdMap.java b/src/main/java/com/massivecraft/factions/cmd/CmdMap.java index 5e19bd9b..afb9c37f 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdMap.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdMap.java @@ -56,7 +56,7 @@ public class CmdMap extends FCommand { } public void showMap() { - sendMessage(Board.getMap(myFaction, new FLocation(fme), fme.getPlayer().getLocation().getYaw())); + sendMessage(Board.getInstance().getMap(myFaction, new FLocation(fme), fme.getPlayer().getLocation().getYaw())); } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdOpen.java b/src/main/java/com/massivecraft/factions/cmd/CmdOpen.java index b8916c0a..e2b0b9e8 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdOpen.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdOpen.java @@ -1,8 +1,8 @@ package com.massivecraft.factions.cmd; import com.massivecraft.factions.Conf; -import com.massivecraft.factions.Faction; -import com.massivecraft.factions.Factions; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.FPlayers; import com.massivecraft.factions.struct.Permission; public class CmdOpen extends FCommand { @@ -35,12 +35,12 @@ public class CmdOpen extends FCommand { String open = myFaction.getOpen() ? "open" : "closed"; // Inform - myFaction.msg("%s changed the faction to %s.", fme.describeTo(myFaction, true), open); - for (Faction faction : Factions.i.get()) { - if (faction == myFaction) { + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + if (fplayer.getFactionId() == myFaction.getId()) { + fplayer.msg("%s changed the faction to %s.", open); continue; } - faction.msg("The faction %s is now %s", myFaction.getTag(faction), open); + fplayer.msg("The faction %s is now %s", myFaction.getTag(fplayer.getFaction()), open); } } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdOwner.java b/src/main/java/com/massivecraft/factions/cmd/CmdOwner.java index 8a963464..93da81bd 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdOwner.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdOwner.java @@ -49,7 +49,7 @@ public class CmdOwner extends FCommand { FLocation flocation = new FLocation(fme); - Faction factionHere = Board.getFactionAt(flocation); + Faction factionHere = Board.getInstance().getFactionAt(flocation); if (factionHere != myFaction) { if (!hasBypass) { fme.msg("This land is not claimed by your faction, so you can't set ownership of it."); diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdOwnerList.java b/src/main/java/com/massivecraft/factions/cmd/CmdOwnerList.java index a749453b..b5c88fca 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdOwnerList.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdOwnerList.java @@ -39,13 +39,13 @@ public class CmdOwnerList extends FCommand { FLocation flocation = new FLocation(fme); - if (Board.getFactionAt(flocation) != myFaction) { + if (Board.getInstance().getFactionAt(flocation) != myFaction) { if (!hasBypass) { fme.msg("This land is not claimed by your faction."); return; } - myFaction = Board.getFactionAt(flocation); + myFaction = Board.getInstance().getFactionAt(flocation); if (!myFaction.isNormal()) { fme.msg("This land is not claimed by any faction, thus no owners."); return; diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPeaceful.java b/src/main/java/com/massivecraft/factions/cmd/CmdPeaceful.java index 65dca9f2..9a8a538b 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPeaceful.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPeaceful.java @@ -40,7 +40,7 @@ public class CmdPeaceful extends FCommand { } // Inform all players - for (FPlayer fplayer : FPlayers.i.getOnline()) { + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { if (fplayer.getFaction() == faction) { fplayer.msg((fme == null ? "A server admin" : fme.describeTo(fplayer, true)) + " has " + change + " your faction."); } else { diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdPermanent.java b/src/main/java/com/massivecraft/factions/cmd/CmdPermanent.java index 847361c8..a61e0dd6 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdPermanent.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdPermanent.java @@ -44,7 +44,7 @@ public class CmdPermanent extends FCommand { P.p.log((fme == null ? "A server admin" : fme.getName()) + " " + change + " the faction \"" + faction.getTag() + "\"."); // Inform all players - for (FPlayer fplayer : FPlayers.i.getOnline()) { + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { if (fplayer.getFaction() == faction) { fplayer.msg((fme == null ? "A server admin" : fme.describeTo(fplayer, true)) + " " + change + " your faction."); } else { diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSafeunclaimall.java b/src/main/java/com/massivecraft/factions/cmd/CmdSafeunclaimall.java index 563006e7..32624344 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSafeunclaimall.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSafeunclaimall.java @@ -28,7 +28,7 @@ public class CmdSafeunclaimall extends FCommand { @Override public void perform() { - Board.unclaimAll(Factions.i.getSafeZone().getId()); + Board.getInstance().unclaimAll(Factions.getInstance().getSafeZone().getId()); msg("You unclaimed ALL safe zone land."); if (Conf.logLandUnclaims) { diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSaveAll.java b/src/main/java/com/massivecraft/factions/cmd/CmdSaveAll.java index 1316f969..b5fe6026 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSaveAll.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSaveAll.java @@ -27,9 +27,9 @@ public class CmdSaveAll extends FCommand { @Override public void perform() { - FPlayers.i.saveToDisc(); - Factions.i.saveToDisc(); - Board.save(); + FPlayers.getInstance().forceSave(); + Factions.getInstance().forceSave(); + Board.getInstance().forceSave(); Conf.save(); msg("Factions saved to disk!"); } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdSethome.java b/src/main/java/com/massivecraft/factions/cmd/CmdSethome.java index e7532838..066157c0 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdSethome.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdSethome.java @@ -50,7 +50,7 @@ public class CmdSethome extends FCommand { // Can the player set the faction home HERE? if (!Permission.BYPASS.has(me) && Conf.homesMustBeInClaimedTerritory && - Board.getFactionAt(new FLocation(me)) != faction) { + Board.getInstance().getFactionAt(new FLocation(me)) != faction) { fme.msg("Sorry, your faction home can only be set inside your own claimed territory."); return; } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdShow.java b/src/main/java/com/massivecraft/factions/cmd/CmdShow.java index 13fc757f..5c6655ae 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdShow.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdShow.java @@ -90,7 +90,7 @@ public class CmdShow extends FCommand { // List relation String allyList = p.txt.parse("Allies: "); String enemyList = p.txt.parse("Enemies: "); - for (Faction otherFaction : Factions.i.get()) { + for (Faction otherFaction : Factions.getInstance().getAllFactions()) { if (otherFaction == faction) { continue; } diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdShowInvites.java b/src/main/java/com/massivecraft/factions/cmd/CmdShowInvites.java index 77166972..bd66067e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdShowInvites.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdShowInvites.java @@ -19,7 +19,7 @@ public class CmdShowInvites extends FCommand { public void perform() { StringBuilder sb = new StringBuilder(); for (String id : myFaction.getInvites()) { - FPlayer fp = FPlayers.i.get(id); + FPlayer fp = FPlayers.getInstance().getById(id); sb.append(fp != null ? fp.getName() : id).append(" "); } msg("Players with pending invites: %s", sb.toString().trim()); diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTag.java b/src/main/java/com/massivecraft/factions/cmd/CmdTag.java index b98f54bc..882e6a4c 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTag.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTag.java @@ -1,12 +1,15 @@ package com.massivecraft.factions.cmd; import com.massivecraft.factions.Conf; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.FPlayers; import com.massivecraft.factions.Faction; import com.massivecraft.factions.Factions; import com.massivecraft.factions.event.FactionRenameEvent; import com.massivecraft.factions.scoreboards.FTeamWrapper; import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.util.MiscUtil; + import org.bukkit.Bukkit; import java.util.ArrayList; @@ -33,13 +36,12 @@ public class CmdTag extends FCommand { String tag = this.argAsString(0); // TODO does not first test cover selfcase? - if (Factions.i.isTagTaken(tag) && !MiscUtil.getComparisonString(tag).equals(myFaction.getComparisonTag())) { + if (Factions.getInstance().isTagTaken(tag) && !MiscUtil.getComparisonString(tag).equals(myFaction.getComparisonTag())) { msg("That tag is already taken"); return; } - ArrayList errors = new ArrayList(); - errors.addAll(Factions.validateTag(tag)); + ArrayList errors = MiscUtil.validateTag(tag); if (errors.size() > 0) { sendMessage(errors); return; @@ -66,12 +68,13 @@ public class CmdTag extends FCommand { myFaction.setTag(tag); // Inform - myFaction.msg("%s changed your faction tag to %s", fme.describeTo(myFaction, true), myFaction.getTag(myFaction)); - for (Faction faction : Factions.i.get()) { - if (faction == myFaction) { + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + if (fplayer.getFactionId() == myFaction.getId()) { + fplayer.msg("%s changed your faction tag to %s", fme.describeTo(myFaction, true), myFaction.getTag(myFaction)); continue; } - faction.msg("The faction %s changed their name to %s.", fme.getColorTo(faction) + oldtag, myFaction.getTag(faction)); + Faction faction = fplayer.getFaction(); + fplayer.msg("The faction %s changed their name to %s.", fme.getColorTo(faction) + oldtag, myFaction.getTag(faction)); } FTeamWrapper.updatePrefixes(myFaction); diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdUnclaim.java b/src/main/java/com/massivecraft/factions/cmd/CmdUnclaim.java index ba45115a..2dd224f1 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdUnclaim.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdUnclaim.java @@ -28,11 +28,11 @@ public class CmdUnclaim extends FCommand { @Override public void perform() { FLocation flocation = new FLocation(fme); - Faction otherFaction = Board.getFactionAt(flocation); + Faction otherFaction = Board.getInstance().getFactionAt(flocation); if (otherFaction.isSafeZone()) { if (Permission.MANAGE_SAFE_ZONE.has(sender)) { - Board.removeAt(flocation); + Board.getInstance().removeAt(flocation); msg("Safe zone was unclaimed."); if (Conf.logLandUnclaims) { @@ -44,7 +44,7 @@ public class CmdUnclaim extends FCommand { return; } else if (otherFaction.isWarZone()) { if (Permission.MANAGE_WAR_ZONE.has(sender)) { - Board.removeAt(flocation); + Board.getInstance().removeAt(flocation); msg("War zone was unclaimed."); if (Conf.logLandUnclaims) { @@ -57,7 +57,7 @@ public class CmdUnclaim extends FCommand { } if (fme.isAdminBypassing()) { - Board.removeAt(flocation); + Board.getInstance().removeAt(flocation); otherFaction.msg("%s unclaimed some of your land.", fme.describeTo(otherFaction, true)); msg("You unclaimed this land."); @@ -103,7 +103,7 @@ public class CmdUnclaim extends FCommand { } } - Board.removeAt(flocation); + Board.getInstance().removeAt(flocation); myFaction.msg("%s unclaimed some land.", fme.describeTo(myFaction, true)); if (Conf.logLandUnclaims) { diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdUnclaimall.java b/src/main/java/com/massivecraft/factions/cmd/CmdUnclaimall.java index 9ff4330e..61d95604 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdUnclaimall.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdUnclaimall.java @@ -45,7 +45,7 @@ public class CmdUnclaimall extends FCommand { Bukkit.getServer().getPluginManager().callEvent(unclaimAllEvent); // this event cannot be cancelled - Board.unclaimAll(myFaction.getId()); + Board.getInstance().unclaimAll(myFaction.getId()); myFaction.msg("%s unclaimed ALL of your faction's land.", fme.describeTo(myFaction, true)); if (Conf.logLandUnclaims) { diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdWarunclaimall.java b/src/main/java/com/massivecraft/factions/cmd/CmdWarunclaimall.java index bbb7c608..1d70a12e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdWarunclaimall.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdWarunclaimall.java @@ -28,7 +28,7 @@ public class CmdWarunclaimall extends FCommand { @Override public void perform() { - Board.unclaimAll(Factions.i.getWarZone().getId()); + Board.getInstance().unclaimAll(Factions.getInstance().getWarZone().getId()); msg("You unclaimed ALL war zone land."); if (Conf.logLandUnclaims) { diff --git a/src/main/java/com/massivecraft/factions/cmd/FCmdRoot.java b/src/main/java/com/massivecraft/factions/cmd/FCmdRoot.java index a9b1cb61..f9e0c490 100644 --- a/src/main/java/com/massivecraft/factions/cmd/FCmdRoot.java +++ b/src/main/java/com/massivecraft/factions/cmd/FCmdRoot.java @@ -56,6 +56,7 @@ public class FCmdRoot extends FCommand { public CmdShowInvites cmdShowInvites = new CmdShowInvites(); public CmdAnnounce cmdAnnounce = new CmdAnnounce(); public CmdSeeChunk cmdSeeChunk = new CmdSeeChunk(); + public CmdConvert cmdConvert = new CmdConvert(); public FCmdRoot() { super(); @@ -128,6 +129,7 @@ public class FCmdRoot extends FCommand { this.addSubCommand(this.cmdShowInvites); this.addSubCommand(this.cmdAnnounce); this.addSubCommand(this.cmdSeeChunk); + this.addSubCommand(this.cmdConvert); } @Override diff --git a/src/main/java/com/massivecraft/factions/cmd/FCommand.java b/src/main/java/com/massivecraft/factions/cmd/FCommand.java index 274f0ae4..91a3809e 100644 --- a/src/main/java/com/massivecraft/factions/cmd/FCommand.java +++ b/src/main/java/com/massivecraft/factions/cmd/FCommand.java @@ -41,7 +41,7 @@ public abstract class FCommand extends MCommand

{ @Override public void execute(CommandSender sender, List args, List> commandChain) { if (sender instanceof Player) { - this.fme = FPlayers.i.get((Player) sender); + this.fme = FPlayers.getInstance().getByPlayer((Player) sender); this.myFaction = this.fme.getFaction(); } else { this.fme = null; @@ -85,19 +85,17 @@ public abstract class FCommand extends MCommand

{ return false; } - FPlayer fplayer = FPlayers.i.get((Player) sender); - - if (!fplayer.hasFaction()) { + if (!fme.hasFaction()) { sender.sendMessage(p.txt.parse("You are not member of any faction.")); return false; } - if (this.senderMustBeModerator && !fplayer.getRole().isAtLeast(Role.MODERATOR)) { + if (this.senderMustBeModerator && !fme.getRole().isAtLeast(Role.MODERATOR)) { sender.sendMessage(p.txt.parse("Only faction moderators can %s.", this.getHelpShort())); return false; } - if (this.senderMustBeAdmin && !fplayer.getRole().isAtLeast(Role.ADMIN)) { + if (this.senderMustBeAdmin && !fme.getRole().isAtLeast(Role.ADMIN)) { sender.sendMessage(p.txt.parse("Only faction admins can %s.", this.getHelpShort())); return false; } @@ -143,7 +141,7 @@ public abstract class FCommand extends MCommand

{ if (name != null) { OfflinePlayer player = Bukkit.getOfflinePlayer(name); - FPlayer fplayer = FPlayers.i.get(player); + FPlayer fplayer = FPlayers.getInstance().getByOfflinePlayer(player); if (fplayer != null) { ret = fplayer; } @@ -194,18 +192,18 @@ public abstract class FCommand extends MCommand

{ // First we try an exact match if (faction == null) { - faction = Factions.i.getByTag(name); // Checks for faction name match. + faction = Factions.getInstance().getByTag(name); // Checks for faction name match. } // Next we match faction tags if (faction == null) { - faction = Factions.i.getBestTagMatch(name); + faction = Factions.getInstance().getBestTagMatch(name); } // Next we match player names if (faction == null) { OfflinePlayer player = Bukkit.getOfflinePlayer(name); - FPlayer fplayer = FPlayers.i.get(player); + FPlayer fplayer = FPlayers.getInstance().getByOfflinePlayer(player); if (fplayer != null) { faction = fplayer.getFaction(); } diff --git a/src/main/java/com/massivecraft/factions/event/FactionCreateEvent.java b/src/main/java/com/massivecraft/factions/event/FactionCreateEvent.java index ac7188ec..0afc612c 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionCreateEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionCreateEvent.java @@ -2,7 +2,6 @@ package com.massivecraft.factions.event; import com.massivecraft.factions.FPlayer; import com.massivecraft.factions.FPlayers; -import com.massivecraft.factions.Factions; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; @@ -26,11 +25,7 @@ public class FactionCreateEvent extends Event implements Cancellable { } public FPlayer getFPlayer() { - return FPlayers.i.get(sender); - } - - public String getFactionId() { - return Factions.i.getNextId(); + return FPlayers.getInstance().getByPlayer(sender); } public String getFactionTag() { diff --git a/src/main/java/com/massivecraft/factions/event/FactionDisbandEvent.java b/src/main/java/com/massivecraft/factions/event/FactionDisbandEvent.java index 4abdd90d..5504b875 100644 --- a/src/main/java/com/massivecraft/factions/event/FactionDisbandEvent.java +++ b/src/main/java/com/massivecraft/factions/event/FactionDisbandEvent.java @@ -15,12 +15,12 @@ public class FactionDisbandEvent extends FactionEvent implements Cancellable { private Player sender; public FactionDisbandEvent(Player sender, String factionId) { - super(Factions.i.get(factionId)); + super(Factions.getInstance().getFactionById(factionId)); this.sender = sender; } public FPlayer getFPlayer() { - return FPlayers.i.get(sender); + return FPlayers.getInstance().getByPlayer(sender); } public Player getPlayer() { diff --git a/src/main/java/com/massivecraft/factions/integration/Econ.java b/src/main/java/com/massivecraft/factions/integration/Econ.java index bcefd888..2c6b92d6 100644 --- a/src/main/java/com/massivecraft/factions/integration/Econ.java +++ b/src/main/java/com/massivecraft/factions/integration/Econ.java @@ -47,8 +47,6 @@ public class Econ { } P.p.cmdBase.cmdHelp.updateHelp(); - - oldMoneyDoTransfer(); } public static boolean shouldBeUsed() { @@ -330,19 +328,6 @@ public class Econ { return econ.format(amount); } - public static void oldMoneyDoTransfer() { - if (!shouldBeUsed()) { - return; - } - - for (Faction faction : Factions.i.get()) { - if (faction.money > 0) { - econ.depositPlayer(faction.getAccountId(), faction.money); - faction.money = 0; - } - } - } - // calculate the cost for claiming land public static double calculateClaimCost(int ownedLand, boolean takingFromAnotherFaction) { if (!shouldBeUsed()) { diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java index e8155db0..952d1b44 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsBlockListener.java @@ -72,7 +72,7 @@ public class FactionsBlockListener implements Listener { return; } - Faction pistonFaction = Board.getFactionAt(new FLocation(event.getBlock())); + Faction pistonFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); // target end-of-the-line empty (air) block which is being pushed into, including if piston itself would extend into air Block targetBlock = event.getBlock().getRelative(event.getDirection(), event.getLength() + 1); @@ -104,7 +104,7 @@ public class FactionsBlockListener implements Listener { return; } - Faction pistonFaction = Board.getFactionAt(new FLocation(event.getBlock())); + Faction pistonFaction = Board.getInstance().getFactionAt(new FLocation(event.getBlock())); if (!canPistonMoveBlock(pistonFaction, targetLoc)) { event.setCancelled(true); @@ -114,7 +114,7 @@ public class FactionsBlockListener implements Listener { private boolean canPistonMoveBlock(Faction pistonFaction, Location target) { - Faction otherFaction = Board.getFactionAt(new FLocation(target)); + Faction otherFaction = Board.getInstance().getFactionAt(new FLocation(target)); if (pistonFaction == otherFaction) { return true; @@ -155,13 +155,13 @@ public class FactionsBlockListener implements Listener { return true; } - FPlayer me = FPlayers.i.get(player.getUniqueId().toString()); + FPlayer me = FPlayers.getInstance().getById(player.getUniqueId().toString()); if (me.isAdminBypassing()) { return true; } FLocation loc = new FLocation(location); - Faction otherFaction = Board.getFactionAt(loc); + Faction otherFaction = Board.getInstance().getFactionAt(loc); if (otherFaction.isNone()) { if (Conf.worldGuardBuildPriority && Worldguard.playerCanBuild(player, location)) { diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsChatListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsChatListener.java index ebd7d242..34ccc4ec 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsChatListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsChatListener.java @@ -32,7 +32,7 @@ public class FactionsChatListener implements Listener { Player talkingPlayer = event.getPlayer(); String msg = event.getMessage(); - FPlayer me = FPlayers.i.get(talkingPlayer); + FPlayer me = FPlayers.getInstance().getByPlayer(talkingPlayer); ChatMode chat = me.getChatMode(); // Is it a faction chat message? @@ -45,7 +45,7 @@ public class FactionsChatListener implements Listener { Bukkit.getLogger().log(Level.INFO, ChatColor.stripColor("FactionChat " + myFaction.getTag() + ": " + message)); //Send to any players who are spying chat - for (FPlayer fplayer : FPlayers.i.getOnline()) { + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { if (fplayer.isSpyingChat() && fplayer.getFaction() != myFaction) { fplayer.sendMessage("[FCspy] " + myFaction.getTag() + ": " + message); } @@ -61,7 +61,7 @@ public class FactionsChatListener implements Listener { myFaction.sendMessage(message); //Send to all our allies - for (FPlayer fplayer : FPlayers.i.getOnline()) { + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { if (myFaction.getRelationTo(fplayer) == Relation.ALLY) { fplayer.sendMessage(message); } @@ -94,7 +94,7 @@ public class FactionsChatListener implements Listener { Player talkingPlayer = event.getPlayer(); String msg = event.getMessage(); String eventFormat = event.getFormat(); - FPlayer me = FPlayers.i.get(talkingPlayer); + FPlayer me = FPlayers.getInstance().getByPlayer(talkingPlayer); int InsertIndex; if (!Conf.chatTagReplaceString.isEmpty() && eventFormat.contains(Conf.chatTagReplaceString)) { @@ -132,7 +132,7 @@ public class FactionsChatListener implements Listener { event.setCancelled(true); for (Player listeningPlayer : event.getRecipients()) { - FPlayer you = FPlayers.i.get(listeningPlayer); + FPlayer you = FPlayers.getInstance().getByPlayer(listeningPlayer); String yourFormat = formatStart + me.getChatTag(you).trim() + formatEnd; try { listeningPlayer.sendMessage(String.format(yourFormat, talkingPlayer.getDisplayName(), msg)); diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java index 843a57de..95a9e905 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsEntityListener.java @@ -40,8 +40,8 @@ public class FactionsEntityListener implements Listener { } Player player = (Player) entity; - FPlayer fplayer = FPlayers.i.get(player); - Faction faction = Board.getFactionAt(new FLocation(player.getLocation())); + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + Faction faction = Board.getInstance().getFactionAt(new FLocation(player.getLocation())); PowerLossEvent powerLossEvent = new PowerLossEvent(faction, fplayer); // Check for no power loss conditions @@ -110,7 +110,7 @@ public class FactionsEntityListener implements Listener { Location loc = event.getLocation(); Entity boomer = event.getEntity(); - Faction faction = Board.getFactionAt(new FLocation(loc)); + Faction faction = Board.getInstance().getFactionAt(new FLocation(loc)); if (faction.noExplosionsInTerritory()) { // faction is peaceful and has explosions set to disabled @@ -207,7 +207,7 @@ public class FactionsEntityListener implements Listener { if(thrower instanceof Player){ Player player = (Player) thrower; - FPlayer fPlayer = FPlayers.i.get(player); + FPlayer fPlayer = FPlayers.getInstance().getByPlayer(player); if(badjuju && fPlayer.getFaction().isPeaceful()){ event.setCancelled(true); return; @@ -230,7 +230,7 @@ public class FactionsEntityListener implements Listener { if (!(damagee instanceof Player)) { return false; } - if (Board.getFactionAt(new FLocation(damagee.getLocation())).isSafeZone()) { + if (Board.getInstance().getFactionAt(new FLocation(damagee.getLocation())).isSafeZone()) { return true; } return false; @@ -249,14 +249,14 @@ public class FactionsEntityListener implements Listener { return true; } - FPlayer defender = FPlayers.i.get((Player) damagee); + FPlayer defender = FPlayers.getInstance().getByPlayer((Player) damagee); if (defender == null || defender.getPlayer() == null) { return true; } Location defenderLoc = defender.getPlayer().getLocation(); - Faction defLocFaction = Board.getFactionAt(new FLocation(defenderLoc)); + Faction defLocFaction = Board.getInstance().getFactionAt(new FLocation(defenderLoc)); // for damage caused by projectiles, getDamager() returns the projectile... what we need to know is the source if (damager instanceof Projectile) { @@ -272,7 +272,7 @@ public class FactionsEntityListener implements Listener { if (defLocFaction.noPvPInTerritory()) { if (damager instanceof Player) { if (notify) { - FPlayer attacker = FPlayers.i.get((Player) damager); + FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager); attacker.msg("You can't hurt other players in " + (defLocFaction.isSafeZone() ? "a SafeZone." : "peaceful territory.")); } return false; @@ -284,7 +284,7 @@ public class FactionsEntityListener implements Listener { return true; } - FPlayer attacker = FPlayers.i.get((Player) damager); + FPlayer attacker = FPlayers.getInstance().getByPlayer((Player) damager); if (attacker == null || attacker.getPlayer() == null) { return true; @@ -301,7 +301,7 @@ public class FactionsEntityListener implements Listener { return false; } - Faction locFaction = Board.getFactionAt(new FLocation(attacker)); + Faction locFaction = Board.getInstance().getFactionAt(new FLocation(attacker)); // so we know from above that the defender isn't in a safezone... what about the attacker, sneaky dog that he might be? if (locFaction.noPvPInTerritory()) { @@ -407,7 +407,7 @@ public class FactionsEntityListener implements Listener { return; } - if (Conf.safeZoneNerfedCreatureTypes.contains(event.getEntityType()) && Board.getFactionAt(new FLocation(event.getLocation())).noMonstersInTerritory()) { + if (Conf.safeZoneNerfedCreatureTypes.contains(event.getEntityType()) && Board.getInstance().getFactionAt(new FLocation(event.getLocation())).noMonstersInTerritory()) { event.setCancelled(true); } } @@ -430,7 +430,7 @@ public class FactionsEntityListener implements Listener { } // in case the target is in a safe zone. - if (Board.getFactionAt(new FLocation(target.getLocation())).noMonstersInTerritory()) { + if (Board.getInstance().getFactionAt(new FLocation(target.getLocation())).noMonstersInTerritory()) { event.setCancelled(true); } } @@ -442,7 +442,7 @@ public class FactionsEntityListener implements Listener { } if (event.getCause() == RemoveCause.EXPLOSION) { Location loc = event.getEntity().getLocation(); - Faction faction = Board.getFactionAt(new FLocation(loc)); + Faction faction = Board.getInstance().getFactionAt(new FLocation(loc)); if (faction.noExplosionsInTerritory()) { // faction is peaceful and has explosions set to disabled event.setCancelled(true); @@ -505,7 +505,7 @@ public class FactionsEntityListener implements Listener { event.setCancelled(true); } } else if (entity instanceof Wither) { - Faction faction = Board.getFactionAt(new FLocation(loc)); + Faction faction = Board.getInstance().getFactionAt(new FLocation(loc)); // it's a bit crude just using fireball protection, but I'd rather not add in a whole new set of xxxBlockWitherExplosion or whatever if ((faction.isNone() && Conf.wildernessBlockFireballs && !Conf.worldsNoWildernessProtection.contains(loc.getWorld().getName())) || (faction.isNormal() && (faction.hasPlayersOnline() ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline)) || @@ -530,7 +530,7 @@ public class FactionsEntityListener implements Listener { } FLocation fLoc = new FLocation(loc); - Faction claimFaction = Board.getFactionAt(fLoc); + Faction claimFaction = Board.getInstance().getFactionAt(fLoc); if (claimFaction.isNone()) { return Conf.wildernessDenyEndermanBlocks; diff --git a/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java b/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java index da4af5ce..6b118292 100644 --- a/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java +++ b/src/main/java/com/massivecraft/factions/listeners/FactionsPlayerListener.java @@ -41,7 +41,7 @@ public class FactionsPlayerListener implements Listener { @EventHandler(priority = EventPriority.NORMAL) public void onPlayerJoin(PlayerJoinEvent event) { // Make sure that all online players do have a fplayer. - final FPlayer me = FPlayers.i.get(event.getPlayer()); + final FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); // Update the lastLoginTime for this fplayer me.setLastLoginTime(System.currentTimeMillis()); @@ -68,7 +68,7 @@ public class FactionsPlayerListener implements Listener { @EventHandler(priority = EventPriority.NORMAL) public void onPlayerQuit(PlayerQuitEvent event) { - FPlayer me = FPlayers.i.get(event.getPlayer()); + FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); // Make sure player's power is up to date when they log off. me.getPower(); @@ -103,7 +103,7 @@ public class FactionsPlayerListener implements Listener { } Player player = event.getPlayer(); - FPlayer me = FPlayers.i.get(player); + FPlayer me = FPlayers.getInstance().getByPlayer(player); // Did we change coord? FLocation from = me.getLastStoodAt(); @@ -118,8 +118,8 @@ public class FactionsPlayerListener implements Listener { me.setLastStoodAt(to); // Did we change "host"(faction)? - Faction factionFrom = Board.getFactionAt(from); - Faction factionTo = Board.getFactionAt(to); + Faction factionFrom = Board.getInstance().getFactionAt(from); + Faction factionTo = Board.getInstance().getFactionAt(to); boolean changedFaction = (factionFrom != factionTo); if (me.isMapAutoUpdating()) { @@ -128,7 +128,7 @@ public class FactionsPlayerListener implements Listener { P.p.log(Level.WARNING, "%s tried to show a faction map too soon and triggered exploit blocker.", player.getName()); } } else { - me.sendMessage(Board.getMap(me.getFaction(), to, player.getLocation().getYaw())); + me.sendMessage(Board.getInstance().getMap(me.getFaction(), to, player.getLocation().getYaw())); showTimes.put(player.getUniqueId(), System.currentTimeMillis() + P.p.getConfig().getLong("findfactionsexploit.cooldown", 2000)); } } else { @@ -158,8 +158,8 @@ public class FactionsPlayerListener implements Listener { if (!Permission.MANAGE_SAFE_ZONE.has(player)) { me.setIsAutoSafeClaimEnabled(false); } else { - if (!Board.getFactionAt(to).isSafeZone()) { - Board.setFactionAt(Factions.i.getSafeZone(), to); + if (!Board.getInstance().getFactionAt(to).isSafeZone()) { + Board.getInstance().setFactionAt(Factions.getInstance().getSafeZone(), to); me.msg("This land is now a safe zone."); } } @@ -167,8 +167,8 @@ public class FactionsPlayerListener implements Listener { if (!Permission.MANAGE_WAR_ZONE.has(player)) { me.setIsAutoWarClaimEnabled(false); } else { - if (!Board.getFactionAt(to).isWarZone()) { - Board.setFactionAt(Factions.i.getWarZone(), to); + if (!Board.getInstance().getFactionAt(to).isWarZone()) { + Board.getInstance().setFactionAt(Factions.getInstance().getWarZone(), to); me.msg("This land is now a war zone."); } } @@ -203,7 +203,7 @@ public class FactionsPlayerListener implements Listener { } int count = attempt.increment(); if (count >= 10) { - FPlayer me = FPlayers.i.get(name); + FPlayer me = FPlayers.getInstance().getByPlayer(player); me.msg("Ouch, that is starting to hurt. You should give it a rest."); player.damage(NumberConversions.floor((double) count / 10)); } @@ -249,13 +249,13 @@ public class FactionsPlayerListener implements Listener { return true; } - FPlayer me = FPlayers.i.get(player); + FPlayer me = FPlayers.getInstance().getByPlayer(player); if (me.isAdminBypassing()) { return true; } FLocation loc = new FLocation(location); - Faction otherFaction = Board.getFactionAt(loc); + Faction otherFaction = Board.getInstance().getFactionAt(loc); if (otherFaction.hasPlayersOnline()) { if (!Conf.territoryDenyUseageMaterials.contains(material)) { @@ -328,14 +328,14 @@ public class FactionsPlayerListener implements Listener { return true; } - FPlayer me = FPlayers.i.get(player); + FPlayer me = FPlayers.getInstance().getByPlayer(player); if (me.isAdminBypassing()) { return true; } Material material = block.getType(); FLocation loc = new FLocation(block); - Faction otherFaction = Board.getFactionAt(loc); + Faction otherFaction = Board.getInstance().getFactionAt(loc); // no door/chest/whatever protection in wilderness, war zones, or safe zones if (!otherFaction.isNormal()) { @@ -393,7 +393,7 @@ public class FactionsPlayerListener implements Listener { @EventHandler(priority = EventPriority.HIGH) public void onPlayerRespawn(PlayerRespawnEvent event) { - FPlayer me = FPlayers.i.get(event.getPlayer()); + FPlayer me = FPlayers.getInstance().getByPlayer(event.getPlayer()); me.getPower(); // update power, so they won't have gained any while dead @@ -445,7 +445,7 @@ public class FactionsPlayerListener implements Listener { fullCmd = fullCmd.toLowerCase(); - FPlayer me = FPlayers.i.get(player); + FPlayer me = FPlayers.getInstance().getByPlayer(player); String shortCmd; // command without the slash at the beginning if (fullCmd.startsWith("/")) { @@ -509,7 +509,7 @@ public class FactionsPlayerListener implements Listener { return; } - FPlayer badGuy = FPlayers.i.get(event.getPlayer()); + FPlayer badGuy = FPlayers.getInstance().getByPlayer(event.getPlayer()); if (badGuy == null) { return; } @@ -521,7 +521,7 @@ public class FactionsPlayerListener implements Listener { } badGuy.leave(false); - badGuy.detach(); + badGuy.remove(); } } diff --git a/src/main/java/com/massivecraft/factions/scoreboards/FInfoBoard.java b/src/main/java/com/massivecraft/factions/scoreboards/FInfoBoard.java new file mode 100644 index 00000000..e69de29b diff --git a/src/main/java/com/massivecraft/factions/scoreboards/FScoreboard.java b/src/main/java/com/massivecraft/factions/scoreboards/FScoreboard.java index f100200f..9d0efd4c 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/FScoreboard.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/FScoreboard.java @@ -49,7 +49,7 @@ public class FScoreboard { } public static FScoreboard get(Player player) { - return fscoreboards.get(FPlayers.i.get(player)); + return fscoreboards.get(FPlayers.getInstance().getByPlayer(player)); } private FScoreboard(FPlayer fplayer) { diff --git a/src/main/java/com/massivecraft/factions/scoreboards/FTeamWrapper.java b/src/main/java/com/massivecraft/factions/scoreboards/FTeamWrapper.java index 23c19c96..ed2ba314 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/FTeamWrapper.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/FTeamWrapper.java @@ -40,7 +40,7 @@ public class FTeamWrapper { FTeamWrapper wrapper = wrappers.get(faction); Set factionMembers = faction.getFPlayers(); - if (wrapper != null && !Factions.i.get().contains(faction)) { + if (wrapper != null && Factions.getInstance().getFactionById(faction.getId()) != null) { // Faction was disbanded wrapper.unregister(); wrappers.remove(faction); @@ -53,7 +53,7 @@ public class FTeamWrapper { } for (OfflinePlayer player : wrapper.getPlayers()) { - if (!player.isOnline() || !factionMembers.contains(FPlayers.i.get(player))) { + if (!player.isOnline() || !factionMembers.contains(FPlayers.getInstance().getByOfflinePlayer(player))) { // Player is offline or no longer in faction wrapper.removePlayer(player); } diff --git a/src/main/java/com/massivecraft/factions/util/AutoLeaveProcessTask.java b/src/main/java/com/massivecraft/factions/util/AutoLeaveProcessTask.java index 15393dcc..14cce15e 100644 --- a/src/main/java/com/massivecraft/factions/util/AutoLeaveProcessTask.java +++ b/src/main/java/com/massivecraft/factions/util/AutoLeaveProcessTask.java @@ -15,7 +15,7 @@ public class AutoLeaveProcessTask extends BukkitRunnable { private transient double toleranceMillis; public AutoLeaveProcessTask() { - ArrayList fplayers = new ArrayList(FPlayers.i.get()); + ArrayList fplayers = new ArrayList(FPlayers.getInstance().getAllFPlayers()); this.iterator = fplayers.listIterator(); this.toleranceMillis = Conf.autoLeaveAfterDaysOfInactivity * 24 * 60 * 60 * 1000; this.readyToGo = true; @@ -61,7 +61,7 @@ public class AutoLeaveProcessTask extends BukkitRunnable { fplayer.leave(false); iterator.remove(); // go ahead and remove this list's link to the FPlayer object - fplayer.detach(); + fplayer.remove(); } } diff --git a/src/main/java/com/massivecraft/factions/util/LazyLocation.java b/src/main/java/com/massivecraft/factions/util/LazyLocation.java index 3edecff7..5bd62f19 100644 --- a/src/main/java/com/massivecraft/factions/util/LazyLocation.java +++ b/src/main/java/com/massivecraft/factions/util/LazyLocation.java @@ -1,5 +1,7 @@ package com.massivecraft.factions.util; +import java.io.Serializable; + import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; @@ -9,9 +11,9 @@ import org.bukkit.World; * yet when an object of this class is created, only when the Location is first accessed. */ -public class LazyLocation { - - private Location location = null; +public class LazyLocation implements Serializable { + private static final long serialVersionUID = -6049901271320963314L; + private transient Location location = null; private String worldName; private double x; private double y; diff --git a/src/main/java/com/massivecraft/factions/util/MiscUtil.java b/src/main/java/com/massivecraft/factions/util/MiscUtil.java index 7eb8a646..aa098cfa 100644 --- a/src/main/java/com/massivecraft/factions/util/MiscUtil.java +++ b/src/main/java/com/massivecraft/factions/util/MiscUtil.java @@ -5,6 +5,10 @@ import org.bukkit.entity.Creature; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.P; + +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -55,5 +59,24 @@ public class MiscUtil { return ret.toLowerCase(); } + public static ArrayList validateTag(String str) { + ArrayList errors = new ArrayList(); + + if (getComparisonString(str).length() < Conf.factionTagLengthMin) { + errors.add(P.p.txt.parse("The faction tag can't be shorter than %s chars.", Conf.factionTagLengthMin)); + } + + if (str.length() > Conf.factionTagLengthMax) { + errors.add(P.p.txt.parse("The faction tag can't be longer than %s chars.", Conf.factionTagLengthMax)); + } + + for (char c : str.toCharArray()) { + if (!substanceChars.contains(String.valueOf(c))) { + errors.add(P.p.txt.parse("Faction tag must be alphanumeric. \"%s\" is not allowed.", c)); + } + } + + return errors; + } } diff --git a/src/main/java/com/massivecraft/factions/zcore/MPlugin.java b/src/main/java/com/massivecraft/factions/zcore/MPlugin.java index b5663052..faad3ff9 100644 --- a/src/main/java/com/massivecraft/factions/zcore/MPlugin.java +++ b/src/main/java/com/massivecraft/factions/zcore/MPlugin.java @@ -3,13 +3,16 @@ package com.massivecraft.factions.zcore; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; +import com.massivecraft.factions.Board; import com.massivecraft.factions.Conf; -import com.massivecraft.factions.zcore.persist.EM; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.Factions; import com.massivecraft.factions.zcore.persist.SaveTask; import com.massivecraft.factions.zcore.util.PermUtil; import com.massivecraft.factions.zcore.util.Persist; import com.massivecraft.factions.zcore.util.TL; import com.massivecraft.factions.zcore.util.TextUtil; + import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; @@ -180,7 +183,9 @@ public abstract class MPlugin extends JavaPlugin { } // only save data if plugin actually loaded successfully if (loadSuccessful) { - EM.saveAllToDisc(); + Factions.getInstance().forceSave(); + FPlayers.getInstance().forceSave(); + Board.getInstance().forceSave(); } log("Disabled"); } diff --git a/src/main/java/com/massivecraft/factions/zcore/MPluginSecretPlayerListener.java b/src/main/java/com/massivecraft/factions/zcore/MPluginSecretPlayerListener.java index cfae8c4e..16de69d3 100644 --- a/src/main/java/com/massivecraft/factions/zcore/MPluginSecretPlayerListener.java +++ b/src/main/java/com/massivecraft/factions/zcore/MPluginSecretPlayerListener.java @@ -1,10 +1,7 @@ package com.massivecraft.factions.zcore; +import com.massivecraft.factions.FPlayers; import com.massivecraft.factions.listeners.FactionsPlayerListener; -import com.massivecraft.factions.zcore.persist.EM; -import com.massivecraft.factions.zcore.persist.Entity; -import com.massivecraft.factions.zcore.persist.EntityCollection; -import com.massivecraft.factions.zcore.persist.PlayerEntityCollection; import org.bukkit.Bukkit; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -50,10 +47,6 @@ public class MPluginSecretPlayerListener implements Listener { @EventHandler(priority = EventPriority.LOWEST) public void onPlayerPreLogin(PlayerLoginEvent event) { - for (EntityCollection ecoll : EM.class2Entities.values()) { - if (ecoll instanceof PlayerEntityCollection) { - ecoll.get(event.getPlayer().getName()); - } - } + FPlayers.getInstance().getByPlayer(event.getPlayer()); } } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/EM.java b/src/main/java/com/massivecraft/factions/zcore/persist/EM.java deleted file mode 100644 index 080b58fb..00000000 --- a/src/main/java/com/massivecraft/factions/zcore/persist/EM.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.massivecraft.factions.zcore.persist; - -import java.util.LinkedHashMap; -import java.util.Map; - -public class EM { - - public static Map, EntityCollection> class2Entities = new LinkedHashMap, EntityCollection>(); - - @SuppressWarnings("unchecked") - public static EntityCollection getEntitiesCollectionForEntityClass(Class entityClass) { - return (EntityCollection) class2Entities.get(entityClass); - } - - public static void setEntitiesCollectionForEntityClass(Class entityClass, EntityCollection entities) { - class2Entities.put(entityClass, entities); - } - - // -------------------------------------------- // - // ATTACH AND DETACH - // -------------------------------------------- // - - @SuppressWarnings("unchecked") - public static void attach(T entity) { - EntityCollection ec = (EntityCollection) getEntitiesCollectionForEntityClass(entity.getClass()); - ec.attach(entity); - } - - @SuppressWarnings("unchecked") - public static void detach(T entity) { - EntityCollection ec = (EntityCollection) getEntitiesCollectionForEntityClass(entity.getClass()); - ec.detach(entity); - } - - @SuppressWarnings("unchecked") - public static boolean attached(T entity) { - EntityCollection ec = (EntityCollection) getEntitiesCollectionForEntityClass(entity.getClass()); - return ec.attached(entity); - } - - @SuppressWarnings("unchecked") - public static boolean detached(T entity) { - EntityCollection ec = (EntityCollection) getEntitiesCollectionForEntityClass(entity.getClass()); - return ec.detached(entity); - } - - // -------------------------------------------- // - // DISC - // -------------------------------------------- // - - public static void saveAllToDisc() { - for (EntityCollection ec : class2Entities.values()) { - ec.saveToDisc(); - } - } - - public static void loadAllFromDisc() { - for (EntityCollection ec : class2Entities.values()) { - ec.loadFromDisc(); - } - } -} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/Entity.java b/src/main/java/com/massivecraft/factions/zcore/persist/Entity.java deleted file mode 100644 index a39ff2d2..00000000 --- a/src/main/java/com/massivecraft/factions/zcore/persist/Entity.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.massivecraft.factions.zcore.persist; - -public abstract class Entity { - - public Entity() { - } - - protected transient String id = null; - - public String getId() { - return id; - } - - protected void setId(String id) { - this.id = id; - } - - public boolean shouldBeSaved() { - return true; - } - - // -------------------------------------------- // - // ATTACH AND DETACH - // -------------------------------------------- // - - public void attach() { - EM.attach(this); - } - - public void detach() { - EM.detach(this); - } - - public boolean attached() { - return EM.attached(this); - } - - public boolean detached() { - return EM.detached(this); - } - - // -------------------------------------------- // - // EVENTS - // -------------------------------------------- // - - public void preDetach() { - - } - - public void postDetach() { - - } - -} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/EntityCollection.java b/src/main/java/com/massivecraft/factions/zcore/persist/EntityCollection.java deleted file mode 100644 index d38167a1..00000000 --- a/src/main/java/com/massivecraft/factions/zcore/persist/EntityCollection.java +++ /dev/null @@ -1,467 +0,0 @@ -package com.massivecraft.factions.zcore.persist; - -import com.google.gson.Gson; -import com.massivecraft.factions.FLocation; -import com.massivecraft.factions.FPlayer; -import com.massivecraft.factions.Faction; -import com.massivecraft.factions.zcore.util.DiscUtil; -import com.massivecraft.factions.zcore.util.TextUtil; -import com.massivecraft.factions.zcore.util.UUIDFetcher; -import org.apache.commons.lang.StringUtils; -import org.bukkit.Bukkit; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Type; -import java.util.*; -import java.util.Map.Entry; -import java.util.logging.Level; - -public abstract class EntityCollection { - - // -------------------------------------------- // - // FIELDS - // -------------------------------------------- // - - // These must be instantiated in order to allow for different configuration (orders, comparators etc) - private Collection entities; - protected Map id2entity; - - // If the entities are creative they will create a new instance if a non existent id was requested - private boolean creative; - - public boolean isCreative() { - return creative; - } - - public void setCreative(boolean creative) { - this.creative = creative; - } - - // This is the auto increment for the primary key "id" - private int nextId; - - // This ugly crap is necessary due to java type erasure - private Class entityClass; - - public abstract Type getMapType(); // This is special stuff for GSON. - - // Info on how to persist - private Gson gson; - - public Gson getGson() { - return gson; - } - - public void setGson(Gson gson) { - this.gson = gson; - } - - private File file; - - public File getFile() { - return file; - } - - public void setFile(File file) { - this.file = file; - } - - // -------------------------------------------- // - // CONSTRUCTORS - // -------------------------------------------- // - - public EntityCollection(Class entityClass, Collection entities, Map id2entity, File file, Gson gson, boolean creative) { - this.entityClass = entityClass; - this.entities = entities; - this.id2entity = id2entity; - this.file = file; - this.gson = gson; - this.creative = creative; - this.nextId = 1; - - EM.setEntitiesCollectionForEntityClass(this.entityClass, this); - } - - public EntityCollection(Class entityClass, Collection entities, Map id2entity, File file, Gson gson) { - this(entityClass, entities, id2entity, file, gson, false); - } - - // -------------------------------------------- // - // GET - // -------------------------------------------- // - - public Collection get() { - return entities; - } - - public Map getMap() { - return this.id2entity; - } - - public E get(String id) { - if (this.creative) { - return this.getCreative(id); - } - return id2entity.get(id); - } - - public E getCreative(String id) { - E e = id2entity.get(id); - if (e != null) { - return e; - } - return this.create(id); - } - - public boolean exists(String id) { - if (id == null) { - return false; - } - return id2entity.get(id) != null; - } - - public E getBestIdMatch(String pattern) { - String id = TextUtil.getBestStartWithCI(this.id2entity.keySet(), pattern); - if (id == null) { - return null; - } - return this.id2entity.get(id); - } - - // -------------------------------------------- // - // CREATE - // -------------------------------------------- // - - public synchronized E create() { - return this.create(this.getNextId()); - } - - public synchronized E create(String id) { - if (!this.isIdFree(id)) { - return null; - } - - E e = null; - try { - e = this.entityClass.newInstance(); - } catch (Exception ignored) { - ignored.printStackTrace(); - } - - e.setId(id); - this.entities.add(e); - this.id2entity.put(e.getId(), e); - this.updateNextIdForId(id); - return e; - } - - // -------------------------------------------- // - // ATTACH AND DETACH - // -------------------------------------------- // - - public void attach(E entity) { - if (entity.getId() != null) { - return; - } - entity.setId(this.getNextId()); - this.entities.add(entity); - this.id2entity.put(entity.getId(), entity); - } - - public void detach(E entity) { - entity.preDetach(); - this.entities.remove(entity); - this.id2entity.remove(entity.getId()); - entity.postDetach(); - } - - public void detach(String id) { - E entity = this.id2entity.get(id); - if (entity == null) { - return; - } - this.detach(entity); - } - - public boolean attached(E entity) { - return this.entities.contains(entity); - } - - public boolean detached(E entity) { - return !this.attached(entity); - } - - // -------------------------------------------- // - // DISC - // -------------------------------------------- // - - // we don't want to let saveToDisc() run multiple iterations simultaneously - private boolean saveIsRunning = false; - - public boolean saveToDisc() { - if (saveIsRunning) { - return true; - } - saveIsRunning = true; - - Map entitiesThatShouldBeSaved = new HashMap(); - for (E entity : this.entities) { - if (entity.shouldBeSaved()) { - entitiesThatShouldBeSaved.put(entity.getId(), entity); - } - } - - saveIsRunning = false; - return this.saveCore(this.file, entitiesThatShouldBeSaved); - } - - private boolean saveCore(File target, Map entities) { - return DiscUtil.writeCatch(target, this.gson.toJson(entities)); - } - - public boolean loadFromDisc() { - Map id2entity = this.loadCore(); - if (id2entity == null) { - return false; - } - this.entities.clear(); - this.entities.addAll(id2entity.values()); - this.id2entity.clear(); - this.id2entity.putAll(id2entity); - this.fillIds(); - return true; - } - - private Map loadCore() { - if (!this.file.exists()) { - return new HashMap(); - } - - String content = DiscUtil.readCatch(this.file); - if (content == null) { - return null; - } - - Type type = this.getMapType(); - if (type.toString().contains("FPlayer")) { - Map data = this.gson.fromJson(content, type); - Set list = whichKeysNeedMigration(data.keySet()); - Set invalidList = whichKeysAreInvalid(list); - list.removeAll(invalidList); - - if (list.size() > 0) { - // We've got some converting to do! - Bukkit.getLogger().log(Level.INFO, "Factions is now updating players.json"); - - // First we'll make a backup, because god forbid anybody heed a warning - File file = new File(this.file.getParentFile(), "players.json.old"); - try { - file.createNewFile(); - } catch (IOException e) { - e.printStackTrace(); - } - saveCore(file, (Map) data); - Bukkit.getLogger().log(Level.INFO, "Backed up your old data at " + file.getAbsolutePath()); - - // Start fetching those UUIDs - Bukkit.getLogger().log(Level.INFO, "Please wait while Factions converts " + list.size() + " old player names to UUID. This may take a while."); - UUIDFetcher fetcher = new UUIDFetcher(new ArrayList(list)); - try { - Map response = fetcher.call(); - for (String s : list) { - // Are we missing any responses? - if (!response.containsKey(s)) { - // They don't have a UUID so they should just be removed - invalidList.add(s); - } - } - for (String value : response.keySet()) { - // For all the valid responses, let's replace their old named entry with a UUID key - String id = response.get(value).toString(); - - FPlayer player = data.get(value); - - if (player == null) { - // The player never existed here, and shouldn't persist - invalidList.add(value); - continue; - } - - player.setId(id); // Update the object so it knows - - data.remove(value); // Out with the old... - data.put(id, player); // And in with the new - } - } catch (Exception e) { - e.printStackTrace(); - } - if (invalidList.size() > 0) { - for (String name : invalidList) { - // Remove all the invalid names we collected - data.remove(name); - } - Bukkit.getLogger().log(Level.INFO, "While converting we found names that either don't have a UUID or aren't players and removed them from storage."); - Bukkit.getLogger().log(Level.INFO, "The following names were detected as being invalid: " + StringUtils.join(invalidList, ", ")); - } - saveCore(this.file, (Map) data); // Update the flatfile - Bukkit.getLogger().log(Level.INFO, "Done converting players.json to UUID."); - } - return (Map) data; - } else { - Map data = this.gson.fromJson(content, type); - - // Do we have any names that need updating in claims or invites? - - int needsUpdate = 0; - for (String string : data.keySet()) { - Faction f = data.get(string); - needsUpdate += whichKeysNeedMigration(f.getInvites()).size(); - Map> claims = f.getClaimOwnership(); - for (FLocation key : f.getClaimOwnership().keySet()) { - needsUpdate += whichKeysNeedMigration(claims.get(key)).size(); - } - } - - if (needsUpdate > 0) { - // We've got some converting to do! - Bukkit.getLogger().log(Level.INFO, "Factions is now updating factions.json"); - - // First we'll make a backup, because god forbid anybody heed a warning - File file = new File(this.file.getParentFile(), "factions.json.old"); - try { - file.createNewFile(); - } catch (IOException e) { - e.printStackTrace(); - } - saveCore(file, (Map) data); - Bukkit.getLogger().log(Level.INFO, "Backed up your old data at " + file.getAbsolutePath()); - - Bukkit.getLogger().log(Level.INFO, "Please wait while Factions converts " + needsUpdate + " old player names to UUID. This may take a while."); - - // Update claim ownership - - for (String string : data.keySet()) { - Faction f = data.get(string); - Map> claims = f.getClaimOwnership(); - for (FLocation key : claims.keySet()) { - Set set = claims.get(key); - - Set list = whichKeysNeedMigration(set); - - if (list.size() > 0) { - UUIDFetcher fetcher = new UUIDFetcher(new ArrayList(list)); - try { - Map response = fetcher.call(); - for (String value : response.keySet()) { - // Let's replace their old named entry with a UUID key - String id = response.get(value).toString(); - set.remove(value.toLowerCase()); // Out with the old... - set.add(id); // And in with the new - } - } catch (Exception e) { - e.printStackTrace(); - } - claims.put(key, set); // Update - } - } - } - - // Update invites - - for (String string : data.keySet()) { - Faction f = data.get(string); - Set invites = f.getInvites(); - Set list = whichKeysNeedMigration(invites); - - if (list.size() > 0) { - UUIDFetcher fetcher = new UUIDFetcher(new ArrayList(list)); - try { - Map response = fetcher.call(); - for (String value : response.keySet()) { - // Let's replace their old named entry with a UUID key - String id = response.get(value).toString(); - invites.remove(value.toLowerCase()); // Out with the old... - invites.add(id); // And in with the new - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - saveCore(this.file, (Map) data); // Update the flatfile - Bukkit.getLogger().log(Level.INFO, "Done converting factions.json to UUID."); - } - return (Map) data; - } - } - - private Set whichKeysNeedMigration(Set keys) { - HashSet list = new HashSet(); - for (String value : keys) { - if (!value.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { - // Not a valid UUID.. - if (value.matches("[a-zA-Z0-9_]{2,16}")) { - // Valid playername, we'll mark this as one for conversion to UUID - list.add(value); - } - } - } - return list; - } - - private Set whichKeysAreInvalid(Set keys) { - Set list = new HashSet(); - for (String value : keys) { - if (!value.matches("[a-zA-Z0-9_]{2,16}")) { - // Not a valid player name.. go ahead and mark it for removal - list.add(value); - } - } - return list; - } - - // -------------------------------------------- // - // ID MANAGEMENT - // -------------------------------------------- // - - public String getNextId() { - while (!isIdFree(this.nextId)) { - this.nextId += 1; - } - return Integer.toString(this.nextId); - } - - public boolean isIdFree(String id) { - return !this.id2entity.containsKey(id); - } - - public boolean isIdFree(int id) { - return this.isIdFree(Integer.toString(id)); - } - - protected synchronized void fillIds() { - this.nextId = 1; - for (Entry entry : this.id2entity.entrySet()) { - String id = entry.getKey(); - E entity = entry.getValue(); - entity.id = id; - this.updateNextIdForId(id); - } - } - - protected synchronized void updateNextIdForId(int id) { - if (this.nextId < id) { - this.nextId = id + 1; - } - } - - protected void updateNextIdForId(String id) { - try { - int idAsInt = Integer.parseInt(id); - this.updateNextIdForId(idAsInt); - } catch (Exception ignored) { - } - } -} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryBoard.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryBoard.java new file mode 100644 index 00000000..755f301a --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryBoard.java @@ -0,0 +1,230 @@ +package com.massivecraft.factions.zcore.persist; + +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.P; +import com.massivecraft.factions.struct.Relation; +import com.massivecraft.factions.util.AsciiCompass; + +import org.bukkit.ChatColor; + +import java.util.*; +import java.util.Map.Entry; + + +public abstract class MemoryBoard extends Board { + public HashMap flocationIds = new HashMap(); + + //----------------------------------------------// + // Get and Set + //----------------------------------------------// + public String getIdAt(FLocation flocation) { + if (!flocationIds.containsKey(flocation)) { + return "0"; + } + + return flocationIds.get(flocation); + } + + public Faction getFactionAt(FLocation flocation) { + return Factions.getInstance().getFactionById(getIdAt(flocation)); + } + + public void setIdAt(String id, FLocation flocation) { + clearOwnershipAt(flocation); + + if (id.equals("0")) { + removeAt(flocation); + } + + flocationIds.put(flocation, id); + } + + public void setFactionAt(Faction faction, FLocation flocation) { + setIdAt(faction.getId(), flocation); + } + + public 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 void clearOwnershipAt(FLocation flocation) { + Faction faction = getFactionAt(flocation); + if (faction != null && faction.isNormal()) { + faction.clearClaimOwnership(flocation); + } + } + + public void unclaimAll(String factionId) { + Faction faction = Factions.getInstance().getFactionById(factionId); + if (faction != null && faction.isNormal()) { + faction.clearAllClaimOwnership(); + } + clean(factionId); + } + + public void clean(String factionId) { + Iterator> iter = flocationIds.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry = iter.next(); + if (entry.getValue().equals(factionId)) { + iter.remove(); + } + } + } + + // Is this coord NOT completely surrounded by coords claimed by the same faction? + // Simpler: Is there any nearby coord with a faction other than the faction here? + public boolean isBorderLocation(FLocation flocation) { + Faction faction = getFactionAt(flocation); + FLocation a = flocation.getRelative(1, 0); + FLocation b = flocation.getRelative(-1, 0); + FLocation c = flocation.getRelative(0, 1); + FLocation d = flocation.getRelative(0, -1); + return faction != getFactionAt(a) || faction != getFactionAt(b) || faction != getFactionAt(c) || faction != getFactionAt(d); + } + + // Is this coord connected to any coord claimed by the specified faction? + public boolean isConnectedLocation(FLocation flocation, Faction faction) { + FLocation a = flocation.getRelative(1, 0); + FLocation b = flocation.getRelative(-1, 0); + FLocation c = flocation.getRelative(0, 1); + FLocation d = flocation.getRelative(0, -1); + return faction == getFactionAt(a) || faction == getFactionAt(b) || faction == getFactionAt(c) || faction == getFactionAt(d); + } + + + //----------------------------------------------// + // Cleaner. Remove orphaned foreign keys + //----------------------------------------------// + + public void clean() { + Iterator> iter = flocationIds.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry = iter.next(); + if (!Factions.getInstance().isValidFactionId(entry.getValue())) { + P.p.log("Board cleaner removed " + entry.getValue() + " from " + entry.getKey()); + iter.remove(); + } + } + } + + //----------------------------------------------// + // Coord count + //----------------------------------------------// + + public int getFactionCoordCount(String factionId) { + int ret = 0; + for (String thatFactionId : flocationIds.values()) { + if (thatFactionId.equals(factionId)) { + ret += 1; + } + } + return ret; + } + + public int getFactionCoordCount(Faction faction) { + return getFactionCoordCount(faction.getId()); + } + + public int getFactionCoordCountInWorld(Faction faction, String worldName) { + String factionId = faction.getId(); + int ret = 0; + Iterator> iter = flocationIds.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry = iter.next(); + if (entry.getValue().equals(factionId) && entry.getKey().getWorldName().equals(worldName)) { + ret += 1; + } + } + return ret; + } + + //----------------------------------------------// + // Map generation + //----------------------------------------------// + + /** + * The map is relative to a coord and a faction north is in the direction of decreasing x east is in the direction + * of decreasing z + */ + public ArrayList getMap(Faction faction, FLocation flocation, double inDegrees) { + ArrayList ret = new ArrayList(); + Faction factionLoc = getFactionAt(flocation); + ret.add(P.p.txt.titleize("(" + flocation.getCoordString() + ") " + factionLoc.getTag(faction))); + + int halfWidth = Conf.mapWidth / 2; + int halfHeight = Conf.mapHeight / 2; + FLocation topLeft = flocation.getRelative(-halfWidth, -halfHeight); + int width = halfWidth * 2 + 1; + int height = halfHeight * 2 + 1; + + if (Conf.showMapFactionKey) { + height--; + } + + Map fList = new HashMap(); + int chrIdx = 0; + + // For each row + for (int dz = 0; dz < height; dz++) { + // Draw and add that row + String row = ""; + for (int dx = 0; dx < width; dx++) { + if (dx == halfWidth && dz == halfHeight) { + row += ChatColor.AQUA + "+"; + } else { + FLocation flocationHere = topLeft.getRelative(dx, dz); + Faction factionHere = getFactionAt(flocationHere); + Relation relation = faction.getRelationTo(factionHere); + if (factionHere.isNone()) { + row += ChatColor.GRAY + "-"; + } else if (factionHere.isSafeZone()) { + row += Conf.colorPeaceful + "+"; + } else if (factionHere.isWarZone()) { + row += ChatColor.DARK_RED + "+"; + } else if (factionHere == faction || + factionHere == factionLoc || + relation.isAtLeast(Relation.ALLY) || + (Conf.showNeutralFactionsOnMap && relation.equals(Relation.NEUTRAL)) || + (Conf.showEnemyFactionsOnMap && relation.equals(Relation.ENEMY))) { + if (!fList.containsKey(factionHere.getTag())) { + fList.put(factionHere.getTag(), Conf.mapKeyChrs[Math.min(chrIdx++, Conf.mapKeyChrs.length - 1)]); + } + char tag = fList.get(factionHere.getTag()); + row += factionHere.getColorTo(faction) + "" + tag; + } else { + row += ChatColor.GRAY + "-"; + } + } + } + ret.add(row); + } + + // Get the compass + ArrayList asciiCompass = AsciiCompass.getAsciiCompass(inDegrees, ChatColor.RED, P.p.txt.parse("")); + + // Add the compass + ret.set(1, asciiCompass.get(0) + ret.get(1).substring(3 * 3)); + ret.set(2, asciiCompass.get(1) + ret.get(2).substring(3 * 3)); + ret.set(3, asciiCompass.get(2) + ret.get(3).substring(3 * 3)); + + // Add the faction key + if (Conf.showMapFactionKey) { + String fRow = ""; + for (String key : fList.keySet()) { + fRow += String.format("%s%s: %s ", ChatColor.GRAY, fList.get(key), key); + } + ret.add(fRow); + } + + return ret; + } + + public abstract void convertFrom(MemoryBoard old); +} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayer.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayer.java new file mode 100644 index 00000000..638e375e --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayer.java @@ -0,0 +1,829 @@ +package com.massivecraft.factions.zcore.persist; + +import com.massivecraft.factions.Board; +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.P; +import com.massivecraft.factions.event.FPlayerLeaveEvent; +import com.massivecraft.factions.event.LandClaimEvent; +import com.massivecraft.factions.iface.EconomyParticipator; +import com.massivecraft.factions.iface.RelationParticipator; +import com.massivecraft.factions.integration.Econ; +import com.massivecraft.factions.integration.Worldguard; +import com.massivecraft.factions.scoreboards.FScoreboard; +import com.massivecraft.factions.scoreboards.sidebar.FInfoSidebar; +import com.massivecraft.factions.struct.ChatMode; +import com.massivecraft.factions.struct.Permission; +import com.massivecraft.factions.struct.Relation; +import com.massivecraft.factions.struct.Role; +import com.massivecraft.factions.util.RelationUtil; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + + +/** + * Logged in players always have exactly one FPlayer instance. Logged out players may or may not have an FPlayer + * instance. They will always have one if they are part of a faction. This is because only players with a faction are + * saved to disk (in order to not waste disk space). + *

+ * The FPlayer is linked to a minecraft player using the player name. + *

+ * The same instance is always returned for the same player. This means you can use the == operator. No .equals method + * necessary. + */ + +public abstract class MemoryFPlayer implements FPlayer { + // FIELD: factionId + protected String factionId; + + // FIELD: role + protected Role role; + // FIELD: title + protected String title; + + // FIELD: power + protected double power; + + // FIELD: powerBoost + // special increase/decrease to min and max power for this player + protected double powerBoost; + + // FIELD: lastPowerUpdateTime + protected long lastPowerUpdateTime; + + // FIELD: lastLoginTime + protected long lastLoginTime; + + // FIELD: chatMode + protected ChatMode chatMode; + + protected String id; + + //private transient String playerName; + protected transient FLocation lastStoodAt = new FLocation(); // Where did this player stand the last time we checked? + + // FIELD: mapAutoUpdating + protected transient boolean mapAutoUpdating; + + // FIELD: autoClaimEnabled + protected transient Faction autoClaimFor; + + // FIELD: autoSafeZoneEnabled + protected transient boolean autoSafeZoneEnabled; + + // FIELD: autoWarZoneEnabled + protected transient boolean autoWarZoneEnabled; + + protected transient boolean isAdminBypassing = false; + + // FIELD: loginPvpDisabled + protected transient boolean loginPvpDisabled; + + // FIELD: chatSpy + protected transient boolean spyingChat = false; + + public Faction getFaction() { + if (this.factionId == null) { + return null; + } + return Factions.getInstance().getFactionById(this.factionId); + } + + public String getFactionId() { + return this.factionId; + } + + public boolean hasFaction() { + return !factionId.equals("0"); + } + + public void setFaction(Faction faction) { + Faction oldFaction = this.getFaction(); + if (oldFaction != null) { + oldFaction.removeFPlayer(this); + } + faction.addFPlayer(this); + this.factionId = faction.getId(); + } + + public Role getRole() { + return this.role; + } + + public void setRole(Role role) { + this.role = role; + } + + public double getPowerBoost() { + return this.powerBoost; + } + + public void setPowerBoost(double powerBoost) { + this.powerBoost = powerBoost; + } + + public Faction getAutoClaimFor() { + return autoClaimFor; + } + + public void setAutoClaimFor(Faction faction) { + this.autoClaimFor = faction; + if (this.autoClaimFor != null) { + // TODO: merge these into same autoclaim + this.autoSafeZoneEnabled = false; + this.autoWarZoneEnabled = false; + } + } + + public boolean isAutoSafeClaimEnabled() { + return autoSafeZoneEnabled; + } + + public void setIsAutoSafeClaimEnabled(boolean enabled) { + this.autoSafeZoneEnabled = enabled; + if (enabled) { + this.autoClaimFor = null; + this.autoWarZoneEnabled = false; + } + } + + public boolean isAutoWarClaimEnabled() { + return autoWarZoneEnabled; + } + + public void setIsAutoWarClaimEnabled(boolean enabled) { + this.autoWarZoneEnabled = enabled; + if (enabled) { + this.autoClaimFor = null; + this.autoSafeZoneEnabled = false; + } + } + + public boolean isAdminBypassing() { + return this.isAdminBypassing; + } + + public void setIsAdminBypassing(boolean val) { + this.isAdminBypassing = val; + } + + public void setChatMode(ChatMode chatMode) { + this.chatMode = chatMode; + } + + public ChatMode getChatMode() { + if (this.factionId.equals("0") || !Conf.factionOnlyChat) { + this.chatMode = ChatMode.PUBLIC; + } + return chatMode; + } + + public void setSpyingChat(boolean chatSpying) { + this.spyingChat = chatSpying; + } + + public boolean isSpyingChat() { + return spyingChat; + } + + // FIELD: account + public String getAccountId() { + return this.getId(); + } + + public MemoryFPlayer() { } + + public MemoryFPlayer(String id) { + this.id = id; + this.resetFactionData(false); + this.power = Conf.powerPlayerStarting; + this.lastPowerUpdateTime = System.currentTimeMillis(); + this.lastLoginTime = System.currentTimeMillis(); + this.mapAutoUpdating = false; + this.autoClaimFor = null; + this.autoSafeZoneEnabled = false; + this.autoWarZoneEnabled = false; + this.loginPvpDisabled = Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0; + this.powerBoost = 0.0; + + if (!Conf.newPlayerStartingFactionID.equals("0") && Factions.getInstance().isValidFactionId(Conf.newPlayerStartingFactionID)) { + this.factionId = Conf.newPlayerStartingFactionID; + } + } + + public MemoryFPlayer(MemoryFPlayer other) { + this.factionId = other.factionId; + this.id = other.id; + this.power = other.power; + this.lastLoginTime = other.lastLoginTime; + this.mapAutoUpdating = other.mapAutoUpdating; + this.autoClaimFor = other.autoClaimFor; + this.autoSafeZoneEnabled = other.autoSafeZoneEnabled; + this.autoWarZoneEnabled = other.autoWarZoneEnabled; + this.loginPvpDisabled = other.loginPvpDisabled; + this.powerBoost = other.powerBoost; + this.role = other.role; + this.title = other.title; + this.chatMode = other.chatMode; + this.spyingChat = other.spyingChat; + this.lastStoodAt = other.lastStoodAt; + this.isAdminBypassing = other.isAdminBypassing; + } + + public void resetFactionData(boolean doSpoutUpdate) { + // clean up any territory ownership in old faction, if there is one + if (factionId != null && Factions.getInstance().isValidFactionId(this.getFactionId())) { + Faction currentFaction = this.getFaction(); + currentFaction.removeFPlayer(this); + if (currentFaction.isNormal()) { + currentFaction.clearClaimOwnership(this); + } + } + + this.factionId = "0"; // The default neutral faction + this.chatMode = ChatMode.PUBLIC; + this.role = Role.NORMAL; + this.title = ""; + this.autoClaimFor = null; + } + + public void resetFactionData() { + this.resetFactionData(true); + } + + // -------------------------------------------- // + // Getters And Setters + // -------------------------------------------- // + + + public long getLastLoginTime() { + return lastLoginTime; + } + + + public void setLastLoginTime(long lastLoginTime) { + losePowerFromBeingOffline(); + this.lastLoginTime = lastLoginTime; + this.lastPowerUpdateTime = lastLoginTime; + if (Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0) { + this.loginPvpDisabled = true; + } + } + + public boolean isMapAutoUpdating() { + return mapAutoUpdating; + } + + public void setMapAutoUpdating(boolean mapAutoUpdating) { + this.mapAutoUpdating = mapAutoUpdating; + } + + public boolean hasLoginPvpDisabled() { + if (!loginPvpDisabled) { + return false; + } + if (this.lastLoginTime + (Conf.noPVPDamageToOthersForXSecondsAfterLogin * 1000) < System.currentTimeMillis()) { + this.loginPvpDisabled = false; + return false; + } + return true; + } + + public FLocation getLastStoodAt() { + return this.lastStoodAt; + } + + public void setLastStoodAt(FLocation flocation) { + this.lastStoodAt = flocation; + } + + //----------------------------------------------// + // Title, Name, Faction Tag and Chat + //----------------------------------------------// + + // Base: + + public String getTitle() { + return this.hasFaction() ? title : ""; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getName() { + if (isOnline()) { + return getPlayer().getName(); + } + OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(getId())); + return player.getName() != null ? player.getName() : getId(); + } + + public String getTag() { + return this.hasFaction() ? this.getFaction().getTag() : ""; + } + + // Base concatenations: + + public String getNameAndSomething(String something) { + String ret = this.role.getPrefix(); + if (something.length() > 0) { + ret += something + " "; + } + ret += this.getName(); + return ret; + } + + public String getNameAndTitle() { + return this.getNameAndSomething(this.getTitle()); + } + + public String getNameAndTag() { + return this.getNameAndSomething(this.getTag()); + } + + // Colored concatenations: + // These are used in information messages + + public String getNameAndTitle(Faction faction) { + return this.getColorTo(faction) + this.getNameAndTitle(); + } + + public String getNameAndTitle(MemoryFPlayer fplayer) { + return this.getColorTo(fplayer) + this.getNameAndTitle(); + } + + // Chat Tag: + // These are injected into the format of global chat messages. + + public String getChatTag() { + return this.hasFaction() ? String.format(Conf.chatTagFormat, this.role.getPrefix() + this.getTag()) : ""; + } + + // Colored Chat Tag + public String getChatTag(Faction faction) { + return this.hasFaction() ? this.getRelationTo(faction).getColor() + getChatTag() : ""; + } + + public String getChatTag(MemoryFPlayer fplayer) { + return this.hasFaction() ? this.getColorTo(fplayer) + getChatTag() : ""; + } + + // ------------------------------- + // Relation and relation colors + // ------------------------------- + + @Override + public String describeTo(RelationParticipator that, boolean ucfirst) { + return RelationUtil.describeThatToMe(this, that, ucfirst); + } + + @Override + public String describeTo(RelationParticipator that) { + return RelationUtil.describeThatToMe(this, that); + } + + @Override + public Relation getRelationTo(RelationParticipator rp) { + return RelationUtil.getRelationTo(this, rp); + } + + @Override + public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful) { + return RelationUtil.getRelationTo(this, rp, ignorePeaceful); + } + + public Relation getRelationToLocation() { + return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this); + } + + @Override + public ChatColor getColorTo(RelationParticipator rp) { + return RelationUtil.getColorOfThatToMe(this, rp); + } + + //----------------------------------------------// + // Health + //----------------------------------------------// + public void heal(int amnt) { + Player player = this.getPlayer(); + if (player == null) { + return; + } + player.setHealth(player.getHealth() + amnt); + } + + + //----------------------------------------------// + // Power + //----------------------------------------------// + public double getPower() { + this.updatePower(); + return this.power; + } + + public void alterPower(double delta) { + this.power += delta; + if (this.power > this.getPowerMax()) { + this.power = this.getPowerMax(); + } else if (this.power < this.getPowerMin()) { + this.power = this.getPowerMin(); + } + } + + public double getPowerMax() { + return Conf.powerPlayerMax + this.powerBoost; + } + + public double getPowerMin() { + return Conf.powerPlayerMin + this.powerBoost; + } + + public int getPowerRounded() { + return (int) Math.round(this.getPower()); + } + + public int getPowerMaxRounded() { + return (int) Math.round(this.getPowerMax()); + } + + public int getPowerMinRounded() { + return (int) Math.round(this.getPowerMin()); + } + + public void updatePower() { + if (this.isOffline()) { + losePowerFromBeingOffline(); + if (!Conf.powerRegenOffline) { + return; + } + } + long now = System.currentTimeMillis(); + long millisPassed = now - this.lastPowerUpdateTime; + this.lastPowerUpdateTime = now; + + Player thisPlayer = this.getPlayer(); + if (thisPlayer != null && thisPlayer.isDead()) { + return; // don't let dead players regain power until they respawn + } + + int millisPerMinute = 60 * 1000; + this.alterPower(millisPassed * Conf.powerPerMinute / millisPerMinute); + } + + public void losePowerFromBeingOffline() { + if (Conf.powerOfflineLossPerDay > 0.0 && this.power > Conf.powerOfflineLossLimit) { + long now = System.currentTimeMillis(); + long millisPassed = now - this.lastPowerUpdateTime; + this.lastPowerUpdateTime = now; + + double loss = millisPassed * Conf.powerOfflineLossPerDay / (24 * 60 * 60 * 1000); + if (this.power - loss < Conf.powerOfflineLossLimit) { + loss = this.power; + } + this.alterPower(-loss); + } + } + + public void onDeath() { + this.updatePower(); + this.alterPower(-Conf.powerPerDeath); + } + + //----------------------------------------------// + // Territory + //----------------------------------------------// + public boolean isInOwnTerritory() { + return Board.getInstance().getFactionAt(new FLocation(this)) == this.getFaction(); + } + + public boolean isInOthersTerritory() { + Faction factionHere = Board.getInstance().getFactionAt(new FLocation(this)); + return factionHere != null && factionHere.isNormal() && factionHere != this.getFaction(); + } + + public boolean isInAllyTerritory() { + return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isAlly(); + } + + public boolean isInNeutralTerritory() { + return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isNeutral(); + } + + public boolean isInEnemyTerritory() { + return Board.getInstance().getFactionAt(new FLocation(this)).getRelationTo(this).isEnemy(); + } + + public void sendFactionHereMessage() { + Faction toShow = Board.getInstance().getFactionAt(getLastStoodAt()); + if (shouldShowScoreboard(toShow)) { + // Shows them the scoreboard instead of sending a message in chat. Will disappear after a few seconds. + FScoreboard.get(this).setTemporarySidebar(new FInfoSidebar(toShow)); + } else { + String msg = P.p.txt.parse("") + " ~ " + toShow.getTag(this); + if (toShow.getDescription().length() > 0) { + msg += " - " + toShow.getDescription(); + } + this.sendMessage(msg); + } + } + + /** + * Check if the scoreboard should be shown. Simple method to be used by above method. + * @param toShow Faction to be shown. + * @return true if should show, otherwise false. + */ + public boolean shouldShowScoreboard(Faction toShow) { + return !toShow.isWarZone() && !toShow.isNone() && !toShow.isSafeZone() && P.p.getConfig().contains("scoreboard.finfo") && P.p.getConfig().getBoolean("scoreboard.finfo-enabled", false) && P.p.cmdBase.cmdSB.showBoard(this); + } + + // ------------------------------- + // Actions + // ------------------------------- + + public void leave(boolean makePay) { + Faction myFaction = this.getFaction(); + makePay = makePay && Econ.shouldBeUsed() && !this.isAdminBypassing(); + + if (myFaction == null) { + resetFactionData(); + return; + } + + boolean perm = myFaction.isPermanent(); + + if (!perm && this.getRole() == Role.ADMIN && myFaction.getFPlayers().size() > 1) { + msg("You must give the admin role to someone else first."); + return; + } + + if (!Conf.canLeaveWithNegativePower && this.getPower() < 0) { + msg("You cannot leave until your power is positive."); + return; + } + + // if economy is enabled and they're not on the bypass list, make sure they can pay + if (makePay && !Econ.hasAtLeast(this, Conf.econCostLeave, "to leave your faction.")) { + return; + } + + FPlayerLeaveEvent leaveEvent = new FPlayerLeaveEvent(this, myFaction, FPlayerLeaveEvent.PlayerLeaveReason.LEAVE); + Bukkit.getServer().getPluginManager().callEvent(leaveEvent); + if (leaveEvent.isCancelled()) { + return; + } + + // then make 'em pay (if applicable) + if (makePay && !Econ.modifyMoney(this, -Conf.econCostLeave, "to leave your faction.", "for leaving your faction.")) { + return; + } + + // Am I the last one in the faction? + if (myFaction.getFPlayers().size() == 1) { + // Transfer all money + if (Econ.shouldBeUsed()) { + Econ.transferMoney(this, myFaction, this, Econ.getBalance(myFaction.getAccountId())); + } + } + + if (myFaction.isNormal()) { + for (FPlayer fplayer : myFaction.getFPlayersWhereOnline(true)) { + fplayer.msg("%s left %s.", this.describeTo(fplayer, true), myFaction.describeTo(fplayer)); + } + + if (Conf.logFactionLeave) { + P.p.log(this.getName() + " left the faction: " + myFaction.getTag()); + } + } + + myFaction.removeAnnouncements(this); + this.resetFactionData(); + + if (myFaction.isNormal() && !perm && myFaction.getFPlayers().isEmpty()) { + // Remove this faction + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + fplayer.msg("%s was disbanded.", myFaction.describeTo(fplayer, true)); + } + + Factions.getInstance().removeFaction(myFaction.getId()); + if (Conf.logFactionDisband) { + P.p.log("The faction " + myFaction.getTag() + " (" + myFaction.getId() + ") was disbanded due to the last player (" + this.getName() + ") leaving."); + } + } + } + + public boolean canClaimForFaction(Faction forFaction) { + return !forFaction.isNone() && (this.isAdminBypassing() || (forFaction == this.getFaction() && this.getRole().isAtLeast(Role.MODERATOR)) || (forFaction.isSafeZone() && Permission.MANAGE_SAFE_ZONE.has(getPlayer())) || (forFaction.isWarZone() && Permission.MANAGE_WAR_ZONE.has(getPlayer()))); + } + + public boolean canClaimForFactionAtLocation(Faction forFaction, Location location, boolean notifyFailure) { + String error = null; + FLocation flocation = new FLocation(location); + Faction myFaction = getFaction(); + Faction currentFaction = Board.getInstance().getFactionAt(flocation); + int ownedLand = forFaction.getLandRounded(); + + if (Conf.worldGuardChecking && Worldguard.checkForRegionsInChunk(location)) { + // Checks for WorldGuard regions in the chunk attempting to be claimed + error = P.p.txt.parse("This land is protected"); + } else if (Conf.worldsNoClaiming.contains(flocation.getWorldName())) { + error = P.p.txt.parse("Sorry, this world has land claiming disabled."); + } else if (this.isAdminBypassing()) { + return true; + } else if (forFaction.isSafeZone() && Permission.MANAGE_SAFE_ZONE.has(getPlayer())) { + return true; + } else if (forFaction.isWarZone() && Permission.MANAGE_WAR_ZONE.has(getPlayer())) { + return true; + } else if (myFaction != forFaction) { + error = P.p.txt.parse("You can't claim land for %s.", forFaction.describeTo(this)); + } else if (forFaction == currentFaction) { + error = P.p.txt.parse("%s already own this land.", forFaction.describeTo(this, true)); + } else if (this.getRole().value < Role.MODERATOR.value) { + error = P.p.txt.parse("You must be %s to claim land.", Role.MODERATOR.toString()); + } else if (forFaction.getFPlayers().size() < Conf.claimsRequireMinFactionMembers) { + error = P.p.txt.parse("Factions must have at least %s members to claim land.", Conf.claimsRequireMinFactionMembers); + } else if (currentFaction.isSafeZone()) { + error = P.p.txt.parse("You can not claim a Safe Zone."); + } else if (currentFaction.isWarZone()) { + error = P.p.txt.parse("You can not claim a War Zone."); + } else if (ownedLand >= forFaction.getPowerRounded()) { + error = P.p.txt.parse("You can't claim more land! You need more power!"); + } else if (Conf.claimedLandsMax != 0 && ownedLand >= Conf.claimedLandsMax && forFaction.isNormal()) { + error = P.p.txt.parse("Limit reached. You can't claim more land!"); + } else if (currentFaction.getRelationTo(forFaction) == Relation.ALLY) { + error = P.p.txt.parse("You can't claim the land of your allies."); + } else if (Conf.claimsMustBeConnected && !this.isAdminBypassing() && myFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.getInstance().isConnectedLocation(flocation, myFaction) && (!Conf.claimsCanBeUnconnectedIfOwnedByOtherFaction || !currentFaction.isNormal())) { + if (Conf.claimsCanBeUnconnectedIfOwnedByOtherFaction) { + error = P.p.txt.parse("You can only claim additional land which is connected to your first claim or controlled by another faction!"); + } else { + error = P.p.txt.parse("You can only claim additional land which is connected to your first claim!"); + } + } else if (currentFaction.isNormal()) { + if (myFaction.isPeaceful()) { + error = P.p.txt.parse("%s owns this land. Your faction is peaceful, so you cannot claim land from other factions.", currentFaction.getTag(this)); + } else if (currentFaction.isPeaceful()) { + error = P.p.txt.parse("%s owns this land, and is a peaceful faction. You cannot claim land from them.", currentFaction.getTag(this)); + } else if (!currentFaction.hasLandInflation()) { + // TODO more messages WARN current faction most importantly + error = P.p.txt.parse("%s owns this land and is strong enough to keep it.", currentFaction.getTag(this)); + } else if (!Board.getInstance().isBorderLocation(flocation)) { + error = P.p.txt.parse("You must start claiming land at the border of the territory."); + } + } + // TODO: Add more else if statements. + + if (notifyFailure && error != null) { + msg(error); + } + return error == null; + } + + public boolean attemptClaim(Faction forFaction, Location location, boolean notifyFailure) { + // notifyFailure is false if called by auto-claim; no need to notify on every failure for it + // return value is false on failure, true on success + + FLocation flocation = new FLocation(location); + Faction currentFaction = Board.getInstance().getFactionAt(flocation); + + int ownedLand = forFaction.getLandRounded(); + + if (!this.canClaimForFactionAtLocation(forFaction, location, notifyFailure)) { + return false; + } + + // if economy is enabled and they're not on the bypass list, make sure they can pay + boolean mustPay = Econ.shouldBeUsed() && !this.isAdminBypassing() && !forFaction.isSafeZone() && !forFaction.isWarZone(); + double cost = 0.0; + EconomyParticipator payee = null; + if (mustPay) { + cost = Econ.calculateClaimCost(ownedLand, currentFaction.isNormal()); + + if (Conf.econClaimUnconnectedFee != 0.0 && forFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.getInstance().isConnectedLocation(flocation, forFaction)) { + cost += Conf.econClaimUnconnectedFee; + } + + if (Conf.bankEnabled && Conf.bankFactionPaysLandCosts && this.hasFaction()) { + payee = this.getFaction(); + } else { + payee = this; + } + + if (!Econ.hasAtLeast(payee, cost, "to claim this land")) { + return false; + } + } + + LandClaimEvent claimEvent = new LandClaimEvent(flocation, forFaction, this); + Bukkit.getServer().getPluginManager().callEvent(claimEvent); + if (claimEvent.isCancelled()) { + return false; + } + + // then make 'em pay (if applicable) + if (mustPay && !Econ.modifyMoney(payee, -cost, "to claim this land", "for claiming this land")) { + return false; + } + + // announce success + Set informTheseFPlayers = new HashSet(); + informTheseFPlayers.add(this); + informTheseFPlayers.addAll(forFaction.getFPlayersWhereOnline(true)); + for (FPlayer fp : informTheseFPlayers) { + fp.msg("%s claimed land for %s from %s.", this.describeTo(fp, true), forFaction.describeTo(fp), currentFaction.describeTo(fp)); + } + + Board.getInstance().setFactionAt(forFaction, flocation); + + if (Conf.logLandClaims) { + P.p.log(this.getName() + " claimed land at (" + flocation.getCoordString() + ") for the faction: " + forFaction.getTag()); + } + + return true; + } + + public boolean shouldBeSaved() { + if (!this.hasFaction() && (this.getPowerRounded() == this.getPowerMaxRounded() || this.getPowerRounded() == (int) Math.round(Conf.powerPlayerStarting))) { + return false; + } + return true; + } + + public void msg(String str, Object... args) { + this.sendMessage(P.p.txt.parse(str, args)); + } + + public Player getPlayer() { + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + if (player.getUniqueId().toString().equals(this.getId())) { + return player; + } + } + return null; + } + + public boolean isOnline() { + return this.getPlayer() != null; + } + + // make sure target player should be able to detect that this player is online + public boolean isOnlineAndVisibleTo(Player player) { + Player target = this.getPlayer(); + return target != null && player.canSee(target); + } + + public boolean isOffline() { + return !isOnline(); + } + + // -------------------------------------------- // + // Message Sending Helpers + // -------------------------------------------- // + + public void sendMessage(String msg) { + Player player = this.getPlayer(); + if (player == null) { + return; + } + player.sendMessage(msg); + } + + public void sendMessage(List msgs) { + for (String msg : msgs) { + this.sendMessage(msg); + } + } + + public String getNameAndTitle(FPlayer fplayer) { + return this.getColorTo(fplayer) + this.getNameAndTitle(); + } + + @Override + public String getChatTag(FPlayer fplayer) { + return this.hasFaction() ? this.getRelationTo(fplayer).getColor() + getChatTag() : ""; + } + + @Override + public String getId() { + return id; + } + + public abstract void remove(); + + @Override + public void setId(String id) { + this.id = id; + } +} \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayers.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayers.java new file mode 100644 index 00000000..f131d76f --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFPlayers.java @@ -0,0 +1,72 @@ +package com.massivecraft.factions.zcore.persist; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.P; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentSkipListMap; + +public abstract class MemoryFPlayers extends FPlayers { + public Map fPlayers = new ConcurrentSkipListMap(String.CASE_INSENSITIVE_ORDER); + + public void clean() { + for (FPlayer fplayer : this.fPlayers.values()) { + if (!Factions.getInstance().isValidFactionId(fplayer.getFactionId())) { + P.p.log("Reset faction data (invalid faction:" + fplayer.getFactionId() + ") for player " + fplayer.getName()); + fplayer.resetFactionData(false); + } + } + } + + public Collection getOnlinePlayers() { + Set entities = new HashSet(); + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + entities.add(this.getByPlayer(player)); + } + return entities; + } + + @Override + public FPlayer getByPlayer(Player player) { + return getById(player.getUniqueId().toString()); + } + + @Override + public List getAllFPlayers() { + return new ArrayList(fPlayers.values()); + } + + @Override + public abstract void forceSave(); + + public abstract void load(); + + @Override + public FPlayer getByOfflinePlayer(OfflinePlayer player) { + return getById(player.getUniqueId().toString()); + } + + @Override + public FPlayer getById(String id) { + FPlayer player = fPlayers.get(id); + if (player == null) { + player = generateFPlayer(id); + } + return player; + } + + public abstract FPlayer generateFPlayer(String id); + + public abstract void convertFrom(MemoryFPlayers old); +} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java new file mode 100644 index 00000000..3be89f1b --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java @@ -0,0 +1,733 @@ +package com.massivecraft.factions.zcore.persist; + +import com.massivecraft.factions.Board; +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.P; +import com.massivecraft.factions.iface.EconomyParticipator; +import com.massivecraft.factions.iface.RelationParticipator; +import com.massivecraft.factions.integration.Econ; +import com.massivecraft.factions.struct.Permission; +import com.massivecraft.factions.struct.Relation; +import com.massivecraft.factions.struct.Role; +import com.massivecraft.factions.util.LazyLocation; +import com.massivecraft.factions.util.MiscUtil; +import com.massivecraft.factions.util.RelationUtil; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class MemoryFaction implements Faction, EconomyParticipator { + protected String id = null; + protected boolean peacefulExplosionsEnabled; + protected boolean permanent; + protected String tag; + protected String description; + protected boolean open; + protected boolean peaceful; + protected Integer permanentPower; + protected LazyLocation home; + protected transient long lastPlayerLoggedOffTime; + protected double money; + protected double powerBoost; + protected Map relationWish; + protected Map> claimOwnership = new ConcurrentHashMap>(); + protected transient Set fplayers = new HashSet(); + protected Set invites; + protected HashMap> announcements; + + public HashMap> getAnnouncements() { + return this.announcements; + } + + public void addAnnouncement(FPlayer fPlayer, String msg) { + List list = announcements.containsKey(fPlayer.getId()) ? announcements.get(fPlayer.getId()) : new ArrayList(); + list.add(msg); + announcements.put(fPlayer.getId(), list); + } + + public void sendUnreadAnnouncements(FPlayer fPlayer) { + if (!announcements.containsKey(fPlayer.getId())) { + return; + } + fPlayer.sendMessage(ChatColor.LIGHT_PURPLE + "--Unread Faction Announcements--"); + for (String s : announcements.get(fPlayer.getPlayer().getUniqueId().toString())) { + fPlayer.sendMessage(s); + } + fPlayer.sendMessage(ChatColor.LIGHT_PURPLE + "--Unread Faction Announcements--"); + announcements.remove(fPlayer.getId()); + } + + public void removeAnnouncements(FPlayer fPlayer) { + if (announcements.containsKey(fPlayer.getId())) { + announcements.remove(fPlayer.getId()); + } + } + + public Set getInvites() { + return invites; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void invite(FPlayer fplayer) { + this.invites.add(fplayer.getId()); + } + + public void deinvite(FPlayer fplayer) { + this.invites.remove(fplayer.getId()); + } + + public boolean isInvited(FPlayer fplayer) { + return this.invites.contains(fplayer.getId()); + } + + public boolean getOpen() { + return open; + } + + public void setOpen(boolean isOpen) { + open = isOpen; + } + + public boolean isPeaceful() { + return this.peaceful; + } + + public void setPeaceful(boolean isPeaceful) { + this.peaceful = isPeaceful; + } + + public void setPeacefulExplosionsEnabled(boolean val) { + peacefulExplosionsEnabled = val; + } + + public boolean getPeacefulExplosionsEnabled() { + return this.peacefulExplosionsEnabled; + } + + public boolean noExplosionsInTerritory() { + return this.peaceful && !peacefulExplosionsEnabled; + } + + public boolean isPermanent() { + return permanent || !this.isNormal(); + } + + public void setPermanent(boolean isPermanent) { + permanent = isPermanent; + } + + public String getTag() { + return this.tag; + } + + public String getTag(String prefix) { + return prefix + this.tag; + } + + public String getTag(Faction otherFaction) { + if (otherFaction == null) { + return getTag(); + } + return this.getTag(this.getColorTo(otherFaction).toString()); + } + + public String getTag(FPlayer otherFplayer) { + if (otherFplayer == null) { + return getTag(); + } + return this.getTag(this.getColorTo(otherFplayer).toString()); + } + + public void setTag(String str) { + if (Conf.factionTagForceUpperCase) { + str = str.toUpperCase(); + } + this.tag = str; + } + + public String getComparisonTag() { + return MiscUtil.getComparisonString(this.tag); + } + + public String getDescription() { + return this.description; + } + + public void setDescription(String value) { + this.description = value; + } + + public void setHome(Location home) { + this.home = new LazyLocation(home); + } + + public boolean hasHome() { + return this.getHome() != null; + } + + public Location getHome() { + confirmValidHome(); + return (this.home != null) ? this.home.getLocation() : null; + } + + public void confirmValidHome() { + if (!Conf.homesMustBeInClaimedTerritory || this.home == null || (this.home.getLocation() != null && Board.getInstance().getFactionAt(new FLocation(this.home.getLocation())) == this)) { + return; + } + + msg("Your faction home has been un-set since it is no longer in your territory."); + this.home = null; + } + + public String getAccountId() { + String aid = "faction-" + this.getId(); + + // We need to override the default money given to players. + if (!Econ.hasAccount(aid)) { + Econ.setBalance(aid, 0); + } + + return aid; + } + + public Integer getPermanentPower() { + return this.permanentPower; + } + + public void setPermanentPower(Integer permanentPower) { + this.permanentPower = permanentPower; + } + + public boolean hasPermanentPower() { + return this.permanentPower != null; + } + + public double getPowerBoost() { + return this.powerBoost; + } + + public void setPowerBoost(double powerBoost) { + this.powerBoost = powerBoost; + } + + // -------------------------------------------- // + // Construct + // -------------------------------------------- // + public MemoryFaction() { } + + public MemoryFaction(String id) { + this.id = id; + this.relationWish = new HashMap(); + this.invites = new HashSet(); + this.open = Conf.newFactionsDefaultOpen; + this.tag = "???"; + this.description = "Default faction description :("; + this.lastPlayerLoggedOffTime = 0; + this.peaceful = false; + this.peacefulExplosionsEnabled = false; + this.permanent = false; + this.money = 0.0; + this.powerBoost = 0.0; + this.announcements = new HashMap>(); + } + + public MemoryFaction(MemoryFaction old) { + id = old.id; + peacefulExplosionsEnabled = old.peacefulExplosionsEnabled; + permanent = old.permanent; + tag = old.tag; + description = old.description; + open = old.open; + peaceful = old.peaceful; + permanentPower = old.permanentPower; + home = old.home; + lastPlayerLoggedOffTime = old.lastPlayerLoggedOffTime; + money = old.money; + powerBoost = old.powerBoost; + relationWish = old.relationWish; + claimOwnership = old.claimOwnership; + fplayers = new HashSet(); + invites = old.invites; + announcements = old.announcements; + } + + // -------------------------------------------- // + // Extra Getters And Setters + // -------------------------------------------- // + public boolean noPvPInTerritory() { + return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisablePVP); + } + + public boolean noMonstersInTerritory() { + return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisableMonsters); + } + + // ------------------------------- + // Understand the types + // ------------------------------- + + public boolean isNormal() { + return !(this.isNone() || this.isSafeZone() || this.isWarZone()); + } + + public boolean isNone() { + return this.getId().equals("0"); + } + + public boolean isSafeZone() { + return this.getId().equals("-1"); + } + + public boolean isWarZone() { + return this.getId().equals("-2"); + } + + public boolean isPlayerFreeType() { + return this.isSafeZone() || this.isWarZone(); + } + + // ------------------------------- + // Relation and relation colors + // ------------------------------- + + @Override + public String describeTo(RelationParticipator that, boolean ucfirst) { + return RelationUtil.describeThatToMe(this, that, ucfirst); + } + + @Override + public String describeTo(RelationParticipator that) { + return RelationUtil.describeThatToMe(this, that); + } + + @Override + public Relation getRelationTo(RelationParticipator rp) { + return RelationUtil.getRelationTo(this, rp); + } + + @Override + public Relation getRelationTo(RelationParticipator rp, boolean ignorePeaceful) { + return RelationUtil.getRelationTo(this, rp, ignorePeaceful); + } + + @Override + public ChatColor getColorTo(RelationParticipator rp) { + return RelationUtil.getColorOfThatToMe(this, rp); + } + + public Relation getRelationWish(Faction otherFaction) { + if (this.relationWish.containsKey(otherFaction.getId())) { + return this.relationWish.get(otherFaction.getId()); + } + return Relation.NEUTRAL; + } + + public void setRelationWish(Faction otherFaction, Relation relation) { + if (this.relationWish.containsKey(otherFaction.getId()) && relation.equals(Relation.NEUTRAL)) { + this.relationWish.remove(otherFaction.getId()); + } else { + this.relationWish.put(otherFaction.getId(), relation); + } + } + + // ----------------------------------------------// + // Power + // ----------------------------------------------// + public double getPower() { + if (this.hasPermanentPower()) { + return this.getPermanentPower(); + } + + double ret = 0; + for (FPlayer fplayer : fplayers) { + ret += fplayer.getPower(); + } + if (Conf.powerFactionMax > 0 && ret > Conf.powerFactionMax) { + ret = Conf.powerFactionMax; + } + return ret + this.powerBoost; + } + + public double getPowerMax() { + if (this.hasPermanentPower()) { + return this.getPermanentPower(); + } + + double ret = 0; + for (FPlayer fplayer : fplayers) { + ret += fplayer.getPowerMax(); + } + if (Conf.powerFactionMax > 0 && ret > Conf.powerFactionMax) { + ret = Conf.powerFactionMax; + } + return ret + this.powerBoost; + } + + public int getPowerRounded() { + return (int) Math.round(this.getPower()); + } + + public int getPowerMaxRounded() { + return (int) Math.round(this.getPowerMax()); + } + + public int getLandRounded() { + return Board.getInstance().getFactionCoordCount(this); + } + + public int getLandRoundedInWorld(String worldName) { + return Board.getInstance().getFactionCoordCountInWorld(this, worldName); + } + + public boolean hasLandInflation() { + return this.getLandRounded() > this.getPowerRounded(); + } + + // ------------------------------- + // FPlayers + // ------------------------------- + + // maintain the reference list of FPlayers in this faction + public void refreshFPlayers() { + fplayers.clear(); + if (this.isPlayerFreeType()) { + return; + } + + for (FPlayer fplayer : FPlayers.getInstance().getAllFPlayers()) { + if (fplayer.getFactionId().equalsIgnoreCase(id)) { + fplayers.add(fplayer); + } + } + } + + public boolean addFPlayer(FPlayer fplayer) { + return !this.isPlayerFreeType() && fplayers.add(fplayer); + + } + + public boolean removeFPlayer(FPlayer fplayer) { + return !this.isPlayerFreeType() && fplayers.remove(fplayer); + + } + + public Set getFPlayers() { + // return a shallow copy of the FPlayer list, to prevent tampering and + // concurrency issues + return new HashSet(fplayers); + } + + public Set getFPlayersWhereOnline(boolean online) { + Set ret = new HashSet(); + + for (FPlayer fplayer : fplayers) { + if (fplayer.isOnline() == online) { + ret.add(fplayer); + } + } + + return ret; + } + + public FPlayer getFPlayerAdmin() { + if (!this.isNormal()) { + return null; + } + + for (FPlayer fplayer : fplayers) { + if (fplayer.getRole() == Role.ADMIN) { + return fplayer; + } + } + return null; + } + + public ArrayList getFPlayersWhereRole(Role role) { + ArrayList ret = new ArrayList(); + if (!this.isNormal()) { + return ret; + } + + for (FPlayer fplayer : fplayers) { + if (fplayer.getRole() == role) { + ret.add(fplayer); + } + } + + return ret; + } + + public ArrayList getOnlinePlayers() { + ArrayList ret = new ArrayList(); + if (this.isPlayerFreeType()) { + return ret; + } + + for (Player player : P.p.getServer().getOnlinePlayers()) { + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + if (fplayer.getFaction() == this) { + ret.add(player); + } + } + + return ret; + } + + // slightly faster check than getOnlinePlayers() if you just want to see if + // there are any players online + public boolean hasPlayersOnline() { + // only real factions can have players online, not safe zone / war zone + if (this.isPlayerFreeType()) { + return false; + } + + for (Player player : P.p.getServer().getOnlinePlayers()) { + FPlayer fplayer = FPlayers.getInstance().getByPlayer(player); + if (fplayer != null && fplayer.getFaction() == this) { + return true; + } + } + + // even if all players are technically logged off, maybe someone was on + // recently enough to not consider them officially offline yet + return Conf.considerFactionsReallyOfflineAfterXMinutes > 0 && System.currentTimeMillis() < lastPlayerLoggedOffTime + (Conf.considerFactionsReallyOfflineAfterXMinutes * 60000); + } + + public void memberLoggedOff() { + if (this.isNormal()) { + lastPlayerLoggedOffTime = System.currentTimeMillis(); + } + } + + // used when current leader is about to be removed from the faction; + // promotes new leader, or disbands faction if no other members left + public void promoteNewLeader() { + if (!this.isNormal()) { + return; + } + if (this.isPermanent() && Conf.permanentFactionsDisableLeaderPromotion) { + return; + } + + FPlayer oldLeader = this.getFPlayerAdmin(); + + // get list of moderators, or list of normal members if there are no moderators + ArrayList replacements = this.getFPlayersWhereRole(Role.MODERATOR); + if (replacements == null || replacements.isEmpty()) { + replacements = this.getFPlayersWhereRole(Role.NORMAL); + } + + if (replacements == null || replacements.isEmpty()) { // faction admin is the only member; one-man faction + if (this.isPermanent()) { + if (oldLeader != null) { + oldLeader.setRole(Role.NORMAL); + } + return; + } + + // no members left and faction isn't permanent, so disband it + if (Conf.logFactionDisband) { + P.p.log("The faction " + this.getTag() + " (" + this.getId() + ") has been disbanded since it has no members left."); + } + + for (FPlayer fplayer : FPlayers.getInstance().getOnlinePlayers()) { + fplayer.msg("The faction %s was disbanded.", this.getTag(fplayer)); + } + + Factions.getInstance().removeFaction(getId()); + } else { // promote new faction admin + if (oldLeader != null) { + oldLeader.setRole(Role.NORMAL); + } + replacements.get(0).setRole(Role.ADMIN); + this.msg("Faction admin %s has been removed. %s has been promoted as the new faction admin.", oldLeader == null ? "" : oldLeader.getName(), replacements.get(0).getName()); + P.p.log("Faction " + this.getTag() + " (" + this.getId() + ") admin was removed. Replacement admin: " + replacements.get(0).getName()); + } + } + + // ----------------------------------------------// + // Messages + // ----------------------------------------------// + public void msg(String message, Object... args) { + message = P.p.txt.parse(message, args); + + for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { + fplayer.sendMessage(message); + } + } + + public void sendMessage(String message) { + for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { + fplayer.sendMessage(message); + } + } + + public void sendMessage(List messages) { + for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) { + fplayer.sendMessage(messages); + } + } + + // ----------------------------------------------// + // Ownership of specific claims + // ----------------------------------------------// + + public Map> getClaimOwnership() { + return claimOwnership; + } + + public void clearAllClaimOwnership() { + claimOwnership.clear(); + } + + public void clearClaimOwnership(FLocation loc) { + claimOwnership.remove(loc); + } + + public void clearClaimOwnership(FPlayer player) { + if (id == null || id.isEmpty()) { + return; + } + + Set ownerData; + + for (Entry> entry : claimOwnership.entrySet()) { + ownerData = entry.getValue(); + + if (ownerData == null) { + continue; + } + + Iterator iter = ownerData.iterator(); + while (iter.hasNext()) { + if (iter.next().equals(player.getId())) { + iter.remove(); + } + } + + if (ownerData.isEmpty()) { + claimOwnership.remove(entry.getKey()); + } + } + } + + public int getCountOfClaimsWithOwners() { + return claimOwnership.isEmpty() ? 0 : claimOwnership.size(); + } + + public boolean doesLocationHaveOwnersSet(FLocation loc) { + if (claimOwnership.isEmpty() || !claimOwnership.containsKey(loc)) { + return false; + } + + Set ownerData = claimOwnership.get(loc); + return ownerData != null && !ownerData.isEmpty(); + } + + public boolean isPlayerInOwnerList(FPlayer player, FLocation loc) { + if (claimOwnership.isEmpty()) { + return false; + } + Set ownerData = claimOwnership.get(loc); + if (ownerData == null) { + return false; + } + return ownerData.contains(player.getId()); + } + + public void setPlayerAsOwner(FPlayer player, FLocation loc) { + Set ownerData = claimOwnership.get(loc); + if (ownerData == null) { + ownerData = new HashSet(); + } + ownerData.add(player.getId()); + claimOwnership.put(loc, ownerData); + } + + public void removePlayerAsOwner(FPlayer player, FLocation loc) { + Set ownerData = claimOwnership.get(loc); + if (ownerData == null) { + return; + } + ownerData.remove(player.getId()); + claimOwnership.put(loc, ownerData); + } + + public Set getOwnerList(FLocation loc) { + return claimOwnership.get(loc); + } + + public String getOwnerListString(FLocation loc) { + Set ownerData = claimOwnership.get(loc); + if (ownerData == null || ownerData.isEmpty()) { + return ""; + } + + String ownerList = ""; + + Iterator iter = ownerData.iterator(); + while (iter.hasNext()) { + if (!ownerList.isEmpty()) { + ownerList += ", "; + } + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(UUID.fromString(iter.next())); + ownerList += offlinePlayer != null ? offlinePlayer.getName() : "null player"; + } + return ownerList; + } + + public boolean playerHasOwnershipRights(FPlayer fplayer, FLocation loc) { + // in own faction, with sufficient role or permission to bypass + // ownership? + if (fplayer.getFaction() == this && (fplayer.getRole().isAtLeast(Conf.ownedAreaModeratorsBypass ? Role.MODERATOR : Role.ADMIN) || Permission.OWNERSHIP_BYPASS.has(fplayer.getPlayer()))) { + return true; + } + + // make sure claimOwnership is initialized + if (claimOwnership.isEmpty()) { + 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 + return ownerData == null || ownerData.isEmpty() || ownerData.contains(fplayer.getId()); + } + + // ----------------------------------------------// + // Persistance and entity management + // ----------------------------------------------// + public void remove() { + if (Econ.shouldBeUsed()) { + Econ.setBalance(getAccountId(), 0); + } + + // Clean the board + ((MemoryBoard) Board.getInstance()).clean(id); + + for (FPlayer fPlayer : fplayers) { + fPlayer.resetFactionData(false); + } + } +} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFactions.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFactions.java new file mode 100644 index 00000000..f9467a05 --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFactions.java @@ -0,0 +1,171 @@ +package com.massivecraft.factions.zcore.persist; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.ChatColor; + +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.util.MiscUtil; +import com.massivecraft.factions.zcore.util.TL; + +public abstract class MemoryFactions extends Factions { + public Map factions = new ConcurrentHashMap(); + public int nextId = 1; + + public abstract void load(); { + // Make sure the default neutral faction exists + if (!factions.containsKey("0")) { + Faction faction = generateFactionObject("0"); + factions.put("0", faction); + faction.setTag(TL.WILDERNESS.toString()); + faction.setDescription(TL.WILDERNESS_DESCRIPTION.toString()); + } else { + Faction faction = factions.get("0"); + if (!faction.getTag().equalsIgnoreCase(TL.WILDERNESS.toString())) { + faction.setTag(TL.WILDERNESS.toString()); + } + if (!faction.getDescription().equalsIgnoreCase(TL.WILDERNESS_DESCRIPTION.toString())) { + faction.setDescription(TL.WILDERNESS_DESCRIPTION.toString()); + } + } + + // Make sure the safe zone faction exists + if (!factions.containsKey("-1")) { + Faction faction = generateFactionObject("-1"); + factions.put("-1", faction); + faction.setTag(TL.SAFEZONE.toString()); + faction.setDescription(TL.SAFEZONE_DESCRIPTION.toString()); + } else { + Faction faction = factions.get("-1"); + if (!faction.getTag().equalsIgnoreCase(TL.SAFEZONE.toString())) { + faction.setTag(TL.SAFEZONE.toString()); + } + if (!faction.getDescription().equalsIgnoreCase(TL.SAFEZONE_DESCRIPTION.toString())) { + faction.setDescription(TL.SAFEZONE_DESCRIPTION.toString()); + } + // if SafeZone has old pre-1.6.0 name, rename it to remove troublesome " " + if (faction.getTag().contains(" ")) { + faction.setTag(TL.SAFEZONE.toString()); + } + } + + // Make sure the war zone faction exists + if (!factions.containsKey("-2")) { + Faction faction = generateFactionObject("-2"); + factions.put("-2", faction); + faction.setTag(TL.WARZONE.toString()); + faction.setDescription(TL.WARZONE_DESCRIPTION.toString()); + } else { + Faction faction = factions.get("-2"); + if (!faction.getTag().equalsIgnoreCase(TL.WARZONE.toString())) { + faction.setTag(TL.WARZONE.toString()); + } + if (!faction.getDescription().equalsIgnoreCase(TL.WARZONE_DESCRIPTION.toString())) { + faction.setDescription(TL.WARZONE_DESCRIPTION.toString()); + } + // if WarZone has old pre-1.6.0 name, rename it to remove troublesome " " + if (faction.getTag().contains(" ")) { + faction.setTag(TL.WARZONE.toString()); + } + } + } + + public Faction getFactionById(String id) { + return factions.get(id); + } + + public abstract Faction generateFactionObject(String string); + + public Faction getByTag(String str) { + String compStr = MiscUtil.getComparisonString(str); + for (Faction faction : factions.values()) { + if (faction.getComparisonTag().equals(compStr)) { + return faction; + } + } + return null; + } + + public Faction getBestTagMatch(String start) { + int best = 0; + start = start.toLowerCase(); + int minlength = start.length(); + Faction bestMatch = null; + for (Faction faction : factions.values()) { + String candidate = faction.getTag(); + candidate = ChatColor.stripColor(candidate); + if (candidate.length() < minlength) { + continue; + } + if (!candidate.toLowerCase().startsWith(start)) { + continue; + } + + // The closer to zero the better + int lendiff = candidate.length() - minlength; + if (lendiff == 0) { + return faction; + } + if (lendiff < best || best == 0) { + best = lendiff; + bestMatch = faction; + } + } + + return bestMatch; + } + + public boolean isTagTaken(String str) { + return this.getByTag(str) != null; + } + public boolean isValidFactionId(String id) { + return factions.containsKey(id); + } + + public Faction createFaction() { + Faction faction = generateFactionObject(); + factions.put(faction.getId(), faction); + return faction; + } + + public Set getFactionTags() { + Set tags = new HashSet(); + for (Faction faction : factions.values()) { + tags.add(faction.getTag()); + } + return tags; + } + + public abstract Faction generateFactionObject(); + + public void removeFaction(String id) { + factions.remove(id).remove(); + } + + @Override + public ArrayList getAllFactions() { + return new ArrayList(factions.values()); + } + + @Override + public Faction getNone() { + return factions.get("0"); + } + + @Override + public Faction getSafeZone() { + return factions.get("-1"); + } + + @Override + public Faction getWarZone() { + return factions.get("-2"); + } + + public abstract void convertFrom(MemoryFactions old); +} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/PlayerEntity.java b/src/main/java/com/massivecraft/factions/zcore/persist/PlayerEntity.java deleted file mode 100644 index 1e967487..00000000 --- a/src/main/java/com/massivecraft/factions/zcore/persist/PlayerEntity.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.massivecraft.factions.zcore.persist; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; - -import java.util.List; - -public class PlayerEntity extends Entity { - - public Player getPlayer() { - for (Player player : Bukkit.getServer().getOnlinePlayers()) { - if (player.getUniqueId().toString().equals(this.getId())) { - return player; - } - } - return null; - } - - public boolean isOnline() { - return this.getPlayer() != null; - } - - // make sure target player should be able to detect that this player is online - public boolean isOnlineAndVisibleTo(Player player) { - Player target = this.getPlayer(); - return target != null && player.canSee(target); - } - - public boolean isOffline() { - return !isOnline(); - } - - // -------------------------------------------- // - // Message Sending Helpers - // -------------------------------------------- // - - public void sendMessage(String msg) { - Player player = this.getPlayer(); - if (player == null) { - return; - } - player.sendMessage(msg); - } - - public void sendMessage(List msgs) { - for (String msg : msgs) { - this.sendMessage(msg); - } - } -} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/PlayerEntityCollection.java b/src/main/java/com/massivecraft/factions/zcore/persist/PlayerEntityCollection.java deleted file mode 100644 index adc349f0..00000000 --- a/src/main/java/com/massivecraft/factions/zcore/persist/PlayerEntityCollection.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.massivecraft.factions.zcore.persist; - -import com.google.gson.Gson; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -import java.io.File; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * The PlayerEntityCollection is an EntityCollection with the extra features a player skin usually requires. - *

- * This entity collection is not only creative. It even creates the instance for the player when the player logs in to - * the server. - *

- * This way we can be sure that PlayerEntityCollection.get() will contain all entities in - * PlayerEntityCollection.getOnline() - */ -public abstract class PlayerEntityCollection extends EntityCollection { - - public PlayerEntityCollection(Class entityClass, Collection entities, Map id2entity, File file, Gson gson) { - super(entityClass, entities, id2entity, file, gson, true); - } - - public E get(OfflinePlayer player) { - return this.get(player.getUniqueId().toString()); - } - - public E get(Player player) { - return this.get(player.getUniqueId().toString()); - } - - public Set getOnline() { - Set entities = new HashSet(); - for (Player player : Bukkit.getServer().getOnlinePlayers()) { - entities.add(this.get(player)); - } - return entities; - } -} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/SaveTask.java b/src/main/java/com/massivecraft/factions/zcore/persist/SaveTask.java index c4167c0c..fd0e573b 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/SaveTask.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/SaveTask.java @@ -1,5 +1,8 @@ package com.massivecraft.factions.zcore.persist; +import com.massivecraft.factions.Board; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.Factions; import com.massivecraft.factions.zcore.MPlugin; public class SaveTask implements Runnable { @@ -18,7 +21,9 @@ public class SaveTask implements Runnable { } running = true; p.preAutoSave(); - EM.saveAllToDisc(); + Factions.getInstance().forceSave(); + FPlayers.getInstance().forceSave(); + Board.getInstance().forceSave(); p.postAutoSave(); running = false; } diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/FactionsJSON.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/FactionsJSON.java new file mode 100644 index 00000000..1b1d9e68 --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/FactionsJSON.java @@ -0,0 +1,51 @@ +package com.massivecraft.factions.zcore.persist.json; + +import java.util.logging.Logger; + +import org.bukkit.scheduler.BukkitRunnable; + +import com.massivecraft.factions.Board; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.P; +import com.massivecraft.factions.zcore.persist.MemoryBoard; +import com.massivecraft.factions.zcore.persist.MemoryFPlayers; +import com.massivecraft.factions.zcore.persist.MemoryFactions; + +public class FactionsJSON { + + public static void convertTo() { + if (!(Factions.getInstance() instanceof MemoryFactions)) { + return; + } + if (!(FPlayers.getInstance() instanceof MemoryFPlayers)) { + return; + } + if (!(Board.getInstance() instanceof MemoryBoard)) { + return; + } + new BukkitRunnable() { + @Override + public void run() { + Logger logger = P.p.getLogger(); + logger.info("Beginning Board conversion to JSON"); + new JSONBoard().convertFrom((MemoryBoard) Board.getInstance()); + logger.info("Board Converted"); + logger.info("Beginning FPlayers conversion to JSON"); + new JSONFPlayers().convertFrom((MemoryFPlayers) FPlayers.getInstance()); + logger.info("FPlayers Converted"); + logger.info("Beginning Factions conversion to JSON"); + new JSONFactions().convertFrom((MemoryFactions) Factions.getInstance()); + logger.info("Factions Converted"); + logger.info("Refreshing object caches"); + for (FPlayer fPlayer : FPlayers.getInstance().getAllFPlayers()) { + Faction faction = Factions.getInstance().getFactionById(fPlayer.getFactionId()); + faction.addFPlayer(fPlayer); + } + logger.info("Conversion Complete"); + } + }.runTaskAsynchronously(P.p); + } +} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONBoard.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONBoard.java new file mode 100644 index 00000000..46d29a7c --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONBoard.java @@ -0,0 +1,108 @@ +package com.massivecraft.factions.zcore.persist.json; + +import com.massivecraft.factions.Board; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.P; +import com.massivecraft.factions.zcore.persist.MemoryBoard; +import com.massivecraft.factions.zcore.util.DiscUtil; + +import com.google.gson.reflect.TypeToken; + +import java.io.File; +import java.lang.reflect.Type; +import java.util.*; +import java.util.Map.Entry; + + +public class JSONBoard extends MemoryBoard { + private static transient File file = new File(P.p.getDataFolder(), "board.json"); + + // -------------------------------------------- // + // Persistance + // -------------------------------------------- // + + public Map> dumpAsSaveFormat() { + Map> worldCoordIds = new HashMap>(); + + String worldName, coords; + String id; + + for (Entry entry : flocationIds.entrySet()) { + worldName = entry.getKey().getWorldName(); + coords = entry.getKey().getCoordString(); + id = entry.getValue(); + if (!worldCoordIds.containsKey(worldName)) { + worldCoordIds.put(worldName, new TreeMap()); + } + + worldCoordIds.get(worldName).put(coords, id); + } + + return worldCoordIds; + } + + public void loadFromSaveFormat(Map> worldCoordIds) { + flocationIds.clear(); + + String worldName; + String[] coords; + int x, z; + String factionId; + + for (Entry> entry : worldCoordIds.entrySet()) { + worldName = entry.getKey(); + 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); + } + } + } + + public boolean forceSave() { + //Factions.log("Saving board to disk"); + + try { + DiscUtil.write(file, P.p.gson.toJson(dumpAsSaveFormat())); + } catch (Exception e) { + e.printStackTrace(); + P.p.log("Failed to save the board to disk."); + return false; + } + + return true; + } + + public boolean load() { + P.p.log("Loading board from disk"); + + if (!file.exists()) { + P.p.log("No board to load from disk. Creating new file."); + forceSave(); + return true; + } + + try { + Type type = new TypeToken>>() { + }.getType(); + Map> worldCoordIds = P.p.gson.fromJson(DiscUtil.read(file), type); + loadFromSaveFormat(worldCoordIds); + P.p.log("Loaded " + flocationIds.size() + " board locations"); + } catch (Exception e) { + e.printStackTrace(); + P.p.log("Failed to load the board from disk."); + return false; + } + + return true; + } + + @Override + public void convertFrom(MemoryBoard old) { + this.flocationIds = old.flocationIds; + forceSave(); + Board.instance = this; + } +} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayer.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayer.java new file mode 100644 index 00000000..6b642103 --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayer.java @@ -0,0 +1,32 @@ +package com.massivecraft.factions.zcore.persist.json; + +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.zcore.persist.MemoryFPlayer; + +public class JSONFPlayer extends MemoryFPlayer { + private transient boolean remove = false; + + public JSONFPlayer(MemoryFPlayer arg0) { + super(arg0); + } + + public JSONFPlayer() { + remove = false; + } + + public JSONFPlayer(String id) { + super(id); + } + + @Override + public void remove() { + remove = true; + } + + public boolean shouldBeSaved() { + if (!this.hasFaction() && (this.getPowerRounded() == this.getPowerMaxRounded() || this.getPowerRounded() == (int) Math.round(Conf.powerPlayerStarting))) { + return false; + } + return !remove; + } +} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayers.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayers.java new file mode 100644 index 00000000..fb2aa1ff --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFPlayers.java @@ -0,0 +1,188 @@ +package com.massivecraft.factions.zcore.persist.json; + +import com.google.common.base.Function; +import com.google.common.collect.Maps; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.P; +import com.massivecraft.factions.zcore.persist.MemoryFPlayer; +import com.massivecraft.factions.zcore.persist.MemoryFPlayers; +import com.massivecraft.factions.zcore.util.DiscUtil; +import com.massivecraft.factions.zcore.util.UUIDFetcher; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.Map.Entry; +import java.util.logging.Level; + +public class JSONFPlayers extends MemoryFPlayers { + // Info on how to persist + private Gson gson; + + public Gson getGson() { + return gson; + } + + public void setGson(Gson gson) { + this.gson = gson; + } + + private File file; + + public JSONFPlayers() { + file = new File(P.p.getDataFolder(), "players.json"); + gson = P.p.gson; + } + + public void convertFrom(MemoryFPlayers old) { + this.fPlayers.putAll(Maps.transformValues(old.fPlayers, new Function() { + @Override + public JSONFPlayer apply(FPlayer arg0) { + return new JSONFPlayer((MemoryFPlayer) arg0); + } + })); + forceSave(); + FPlayers.instance = this; + } + + public void forceSave() { + Map entitiesThatShouldBeSaved = new HashMap(); + for (FPlayer entity : this.fPlayers.values()) { + if (((MemoryFPlayer) entity).shouldBeSaved()) { + entitiesThatShouldBeSaved.put(entity.getId(), (JSONFPlayer) entity); + } + } + this.saveCore(this.file, entitiesThatShouldBeSaved); + } + + private boolean saveCore(File target, Map data) { + return DiscUtil.writeCatch(target, this.gson.toJson(data)); + } + + public void load() { + Map fplayers = this.loadCore(); + if (fplayers == null) { + return; + } + this.fPlayers.clear(); + this.fPlayers.putAll(fplayers); + P.p.log("Loaded " + fPlayers.size() + " players"); + } + + private Map loadCore() { + if (!this.file.exists()) { + return new HashMap(); + } + + String content = DiscUtil.readCatch(this.file); + if (content == null) { + return null; + } + + Map data = this.gson.fromJson(content, new TypeToken>(){}.getType()); + Set list = new HashSet(); + Set invalidList = new HashSet(); + for (Entry entry : data.entrySet()) { + String key = entry.getKey(); + entry.getValue().setId(key); + if (doesKeyNeedMigration(key)) { + if (!isKeyInvalid(key)) { + list.add(key); + } else { + invalidList.add(key); + } + } + } + + if (list.size() > 0) { + // We've got some converting to do! + Bukkit.getLogger().log(Level.INFO, "Factions is now updating players.json"); + + // First we'll make a backup, because god forbid anybody heed a + // warning + File file = new File(this.file.getParentFile(), "players.json.old"); + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + saveCore(file, (Map) data); + Bukkit.getLogger().log(Level.INFO, "Backed up your old data at " + file.getAbsolutePath()); + + // Start fetching those UUIDs + Bukkit.getLogger().log(Level.INFO, "Please wait while Factions converts " + list.size() + " old player names to UUID. This may take a while."); + UUIDFetcher fetcher = new UUIDFetcher(new ArrayList(list)); + try { + Map response = fetcher.call(); + for (String s : list) { + // Are we missing any responses? + if (!response.containsKey(s)) { + // They don't have a UUID so they should just be removed + invalidList.add(s); + } + } + for (String value : response.keySet()) { + // For all the valid responses, let's replace their old + // named entry with a UUID key + String id = response.get(value).toString(); + + JSONFPlayer player = data.get(value); + + if (player == null) { + // The player never existed here, and shouldn't persist + invalidList.add(value); + continue; + } + + player.setId(id); // Update the object so it knows + + data.remove(value); // Out with the old... + data.put(id, player); // And in with the new + } + } catch (Exception e) { + e.printStackTrace(); + } + if (invalidList.size() > 0) { + for (String name : invalidList) { + // Remove all the invalid names we collected + data.remove(name); + } + Bukkit.getLogger().log(Level.INFO, "While converting we found names that either don't have a UUID or aren't players and removed them from storage."); + Bukkit.getLogger().log(Level.INFO, "The following names were detected as being invalid: " + StringUtils.join(invalidList, ", ")); + } + saveCore(this.file, (Map) data); // Update the + // flatfile + Bukkit.getLogger().log(Level.INFO, "Done converting players.json to UUID."); + } + return (Map) data; + } + + private boolean doesKeyNeedMigration(String key) { + if (!key.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { + // Not a valid UUID.. + if (key.matches("[a-zA-Z0-9_]{2,16}")) { + // Valid playername, we'll mark this as one for conversion + // to UUID + return true; + } + } + return false; + } + + private boolean isKeyInvalid(String key) { + return !key.matches("[a-zA-Z0-9_]{2,16}"); + } + + @Override + public FPlayer generateFPlayer(String id) { + FPlayer player = new JSONFPlayer(id); + this.fPlayers.put(player.getId(), player); + return player; + } +} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFaction.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFaction.java new file mode 100644 index 00000000..26ef8f8a --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFaction.java @@ -0,0 +1,16 @@ +package com.massivecraft.factions.zcore.persist.json; + +import com.massivecraft.factions.zcore.persist.MemoryFaction; + +public class JSONFaction extends MemoryFaction { + + public JSONFaction(MemoryFaction arg0) { + super(arg0); + } + + public JSONFaction() {} + + public JSONFaction(String id) { + super(id); + } +} diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFactions.java b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFactions.java new file mode 100644 index 00000000..c88a80c1 --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/persist/json/JSONFactions.java @@ -0,0 +1,258 @@ +package com.massivecraft.factions.zcore.persist.json; + +import com.google.common.base.Function; +import com.google.common.collect.Maps; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.P; +import com.massivecraft.factions.zcore.persist.MemoryFaction; +import com.massivecraft.factions.zcore.persist.MemoryFactions; +import com.massivecraft.factions.zcore.util.DiscUtil; +import com.massivecraft.factions.zcore.util.UUIDFetcher; + +import org.bukkit.Bukkit; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.Map.Entry; +import java.util.logging.Level; + +public class JSONFactions extends MemoryFactions { + // Info on how to persist + private Gson gson; + + public Gson getGson() { + return gson; + } + + public void setGson(Gson gson) { + this.gson = gson; + } + + private File file; + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + + // -------------------------------------------- // + // CONSTRUCTORS + // -------------------------------------------- // + + public JSONFactions() { + this.file = new File(P.p.getDataFolder(), "factions.json"); + this.gson = P.p.gson; + this.nextId = 1; + } + + public void forceSave() { + Map entitiesThatShouldBeSaved = new HashMap(); + for (Faction entity : this.factions.values()) { + entitiesThatShouldBeSaved.put(entity.getId(), (JSONFaction) entity); + } + + this.saveCore(this.file, entitiesThatShouldBeSaved); + } + + private boolean saveCore(File target, Map entities) { + return DiscUtil.writeCatch(target, this.gson.toJson(entities)); + } + + public void load() { + Map factions = this.loadCore(); + if (factions == null) { + return ; + } + this.factions.clear(); + this.factions.putAll(factions); + P.p.log("Loaded " + factions.size() + " Factions"); + } + + private Map loadCore() { + if (!this.file.exists()) { + return new HashMap(); + } + + String content = DiscUtil.readCatch(this.file); + if (content == null) { + return null; + } + + Map data = this.gson.fromJson(content, new TypeToken>(){}.getType()); + + this.nextId = 1; + // Do we have any names that need updating in claims or invites? + + int needsUpdate = 0; + for (Entry entry : data.entrySet()) { + String id = entry.getKey(); + Faction f = entry.getValue(); + f.setId(id); + this.updateNextIdForId(id); + needsUpdate += whichKeysNeedMigration(f.getInvites()).size(); + for (Set keys : f.getClaimOwnership().values()) { + needsUpdate += whichKeysNeedMigration(keys).size(); + } + } + + if (needsUpdate > 0) { + // We've got some converting to do! + Bukkit.getLogger().log(Level.INFO, "Factions is now updating factions.json"); + + // First we'll make a backup, because god forbid anybody heed a + // warning + File file = new File(this.file.getParentFile(), "factions.json.old"); + try { + file.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + saveCore(file, (Map) data); + Bukkit.getLogger().log(Level.INFO, "Backed up your old data at " + file.getAbsolutePath()); + + Bukkit.getLogger().log(Level.INFO, "Please wait while Factions converts " + needsUpdate + " old player names to UUID. This may take a while."); + + // Update claim ownership + + for (String string : data.keySet()) { + Faction f = data.get(string); + Map> claims = f.getClaimOwnership(); + for (FLocation key : claims.keySet()) { + Set set = claims.get(key); + + Set list = whichKeysNeedMigration(set); + + if (list.size() > 0) { + UUIDFetcher fetcher = new UUIDFetcher(new ArrayList(list)); + try { + Map response = fetcher.call(); + for (String value : response.keySet()) { + // Let's replace their old named entry with a + // UUID key + String id = response.get(value).toString(); + set.remove(value.toLowerCase()); // Out with the + // old... + set.add(id); // And in with the new + } + } catch (Exception e) { + e.printStackTrace(); + } + claims.put(key, set); // Update + } + } + } + + // Update invites + + for (String string : data.keySet()) { + Faction f = data.get(string); + Set invites = f.getInvites(); + Set list = whichKeysNeedMigration(invites); + + if (list.size() > 0) { + UUIDFetcher fetcher = new UUIDFetcher(new ArrayList(list)); + try { + Map response = fetcher.call(); + for (String value : response.keySet()) { + // Let's replace their old named entry with a UUID + // key + String id = response.get(value).toString(); + invites.remove(value.toLowerCase()); // Out with the + // old... + invites.add(id); // And in with the new + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + saveCore(this.file, (Map) data); // Update the flatfile + Bukkit.getLogger().log(Level.INFO, "Done converting factions.json to UUID."); + } + return data; + } + + private Set whichKeysNeedMigration(Set keys) { + HashSet list = new HashSet(); + for (String value : keys) { + if (!value.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")) { + // Not a valid UUID.. + if (value.matches("[a-zA-Z0-9_]{2,16}")) { + // Valid playername, we'll mark this as one for conversion + // to UUID + list.add(value); + } + } + } + return list; + } + + // -------------------------------------------- // + // ID MANAGEMENT + // -------------------------------------------- // + + public String getNextId() { + while (!isIdFree(this.nextId)) { + this.nextId += 1; + } + return Integer.toString(this.nextId); + } + + public boolean isIdFree(String id) { + return !this.factions.containsKey(id); + } + + public boolean isIdFree(int id) { + return this.isIdFree(Integer.toString(id)); + } + + protected synchronized void updateNextIdForId(int id) { + if (this.nextId < id) { + this.nextId = id + 1; + } + } + + protected void updateNextIdForId(String id) { + try { + int idAsInt = Integer.parseInt(id); + this.updateNextIdForId(idAsInt); + } catch (Exception ignored) { + } + } + + @Override + public Faction generateFactionObject() { + String id = getNextId(); + Faction faction = new JSONFaction(id); + updateNextIdForId(id); + return faction; + } + + @Override + public Faction generateFactionObject(String id) { + Faction faction = new JSONFaction(id); + return faction; + } + + @Override + public void convertFrom(MemoryFactions old) { + this.factions.putAll(Maps.transformValues(old.factions, new Function() { + @Override + public JSONFaction apply(Faction arg0) { + return new JSONFaction((MemoryFaction) arg0); + } + })); + this.nextId = old.nextId; + forceSave(); + Factions.instance = this; + } +}