diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdShow.java b/src/main/java/com/massivecraft/factions/cmd/CmdShow.java index 191e06d0..084841bc 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdShow.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdShow.java @@ -1,27 +1,39 @@ package com.massivecraft.factions.cmd; import com.massivecraft.factions.Conf; -import com.massivecraft.factions.FPlayer; import com.massivecraft.factions.Faction; -import com.massivecraft.factions.Factions; -import com.massivecraft.factions.integration.Econ; +import com.massivecraft.factions.P; import com.massivecraft.factions.struct.Permission; -import com.massivecraft.factions.struct.Relation; -import com.massivecraft.factions.util.MiscUtil; import com.massivecraft.factions.zcore.util.TL; +import com.massivecraft.factions.zcore.util.TagReplacer; +import com.massivecraft.factions.zcore.util.TagUtil; import mkremins.fanciful.FancyMessage; -import org.bukkit.ChatColor; import java.util.ArrayList; import java.util.List; public class CmdShow extends FCommand { - private static final int ARBITRARY_LIMIT = 25000; + + List defaults = new ArrayList(); public CmdShow() { this.aliases.add("show"); this.aliases.add("who"); + // add defaults to /f show in case config doesnt have it + defaults.add("{header}"); + defaults.add("Description: {description}"); + defaults.add("Joining: {joining} {peaceful}"); + defaults.add("Land / Power / Maxpower: {chunks} / {power} / {maxPower}"); + defaults.add("Faction Home: {world}, {x}, {y}, {z}"); + defaults.add("Founded: {create-date}"); + defaults.add("This faction is permanent, remaining even with no members."); + defaults.add("Land value: {land-value} {land-refund}"); + defaults.add("Balance: {balance}"); + defaults.add("Allies({allies}/{max-allies}): {allies-list}"); + defaults.add("Online: ({online}/{members}): {online-list}"); + defaults.add("Offline: ({offline}/{members}): {offline-list}"); + // this.requiredArgs.add(""); this.optionalArgs.put("faction tag", "yours"); @@ -39,140 +51,49 @@ public class CmdShow extends FCommand { if (this.argIsSet(0)) { faction = this.argAsFaction(0); } - if (faction == null) { return; } - // if economy is enabled, they're not on the bypass list, and this - // command has a cost set, make 'em pay + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay if (!payForCommand(Conf.econCostShow, TL.COMMAND_SHOW_TOSHOW, TL.COMMAND_SHOW_FORSHOW)) { return; } - String peaceStatus = ""; - if (faction.isPeaceful()) { - peaceStatus = " " + Conf.colorNeutral + TL.COMMAND_SHOW_PEACEFUL.toString(); + List show = P.p.getConfig().getStringList("show"); + if (show == null || show.isEmpty()) { + show = defaults; } - double powerBoost = faction.getPowerBoost(); - String boost = (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_SHOW_BONUS.toString() : TL.COMMAND_SHOW_PENALTY.toString() + powerBoost + ")"); - - List allies = new ArrayList(); - List enemies = new ArrayList(); - if (!faction.isNone()) { - FancyMessage currentAllies = new FancyMessage(TL.COMMAND_SHOW_ALLIES.toString()).color(ChatColor.GOLD); - FancyMessage currentEnemies = new FancyMessage(TL.COMMAND_SHOW_ENEMIES.toString()).color(ChatColor.GOLD); - - boolean firstAlly = true; - boolean firstEnemy = true; - for (Faction otherFaction : Factions.getInstance().getAllFactions()) { - if (otherFaction == faction) { - continue; - } - - Relation rel = otherFaction.getRelationTo(faction); - String s = otherFaction.getTag(fme); - if (rel.isAlly()) { - if (firstAlly) { - currentAllies.then(s).tooltip(getToolTips(otherFaction)); - } else { - currentAllies.then(", " + s).tooltip(getToolTips(otherFaction)); - } - firstAlly = false; - - if (currentAllies.toJSONString().length() > ARBITRARY_LIMIT) { - allies.add(currentAllies); - currentAllies = new FancyMessage(""); - } - } else if (rel.isEnemy()) { - if (firstEnemy) { - currentEnemies.then(s).tooltip(getToolTips(otherFaction)); - } else { - currentEnemies.then(", " + s).tooltip(getToolTips(otherFaction)); - } - firstEnemy = false; - - if (currentEnemies.toJSONString().length() > ARBITRARY_LIMIT) { - enemies.add(currentEnemies); - currentEnemies = new FancyMessage(""); - } - } - } - allies.add(currentAllies); - enemies.add(currentEnemies); - } - - List online = new ArrayList(); - List offline = new ArrayList(); - if (!faction.isNone()) { - FancyMessage currentOnline = new FancyMessage(TL.COMMAND_SHOW_MEMBERSONLINE.toString()).color(ChatColor.GOLD); - FancyMessage currentOffline = new FancyMessage(TL.COMMAND_SHOW_MEMBERSOFFLINE.toString()).color(ChatColor.GOLD); - boolean firstOnline = true; - boolean firstOffline = true; - for (FPlayer p : MiscUtil.rankOrder(faction.getFPlayers())) { - String name = p.getNameAndTitle(); - if (p.isOnline()) { - if (firstOnline) { - currentOnline.then(name).tooltip(getToolTips(p)); - } else { - currentOnline.then(", " + name).tooltip(getToolTips(p)); - } - firstOnline = false; - - if (currentOnline.toJSONString().length() > ARBITRARY_LIMIT) { - online.add(currentOnline); - currentOnline = new FancyMessage(); - } - } else { - if (firstOffline) { - currentOffline.then(name).tooltip(getToolTips(p)); - } else { - currentOffline.then(", " + name).tooltip(getToolTips(p)); - } - firstOffline = false; - - if (currentOffline.toJSONString().length() > ARBITRARY_LIMIT) { - offline.add(currentOffline); - currentOffline = new FancyMessage(); - } - } - } - online.add(currentOnline); - offline.add(currentOffline); - } - - // Send all at once ;D - msg(p.txt.titleize(faction.getTag(fme))); - msg(TL.COMMAND_SHOW_DESCRIPTION, faction.getDescription()); if (!faction.isNormal()) { - return; - } - msg(TL.COMMAND_SHOW_JOINING.toString() + peaceStatus, (faction.getOpen() ? TL.COMMAND_SHOW_UNINVITED.toString() : TL.COMMAND_SHOW_INVITATION.toString())); - msg(TL.COMMAND_SHOW_POWER, faction.getLandRounded(), faction.getPowerRounded(), faction.getPowerMaxRounded(), boost); - if (faction.isPermanent()) { - msg(TL.COMMAND_SHOW_PERMANENT); - } - // show the land value - if (Econ.shouldBeUsed()) { - double value = Econ.calculateTotalLandValue(faction.getLandRounded()); - double refund = value * Conf.econClaimRefundMultiplier; - if (value > 0) { - String stringValue = Econ.moneyString(value); - String stringRefund = (refund > 0.0) ? (TL.COMMAND_SHOW_DEPRECIATED.format(Econ.moneyString(refund))) : ""; - msg(TL.COMMAND_SHOW_LANDVALUE, stringValue, stringRefund); - } - - // Show bank contents - if (Conf.bankEnabled) { - msg(TL.COMMAND_SHOW_BANKCONTAINS, Econ.moneyString(Econ.getBalance(faction.getAccountId()))); + String tag = faction.getTag(fme); + // send header and that's all + String header = show.get(0); + if (TagReplacer.HEADER.contains(header)) { + msg(p.txt.titleize(tag)); + } else { + msg(p.txt.parse(TagReplacer.FACTION.replace(header, tag))); } + return; // we only show header for non-normal factions } - sendFancyMessage(allies); - sendFancyMessage(enemies); - sendFancyMessage(online); - sendFancyMessage(offline); + for (String raw : show) { + String parsed = TagUtil.parsePlain(faction, fme, raw); // use relations + if (TagUtil.hasFancy(parsed)) { + List fancy = TagUtil.parseFancy(faction, fme, parsed); + if (fancy != null) { + sendFancyMessage(fancy); + } + continue; + } + if (!parsed.contains("{notFrozen}") && !parsed.contains("{notPermanent}")) { + if (parsed.contains("{ig}")) { + // replaces all variables with no home TL + parsed = parsed.substring(0, parsed.indexOf("{ig}")) + TL.COMMAND_SHOW_NOHOME.toString(); + } + msg(p.txt.parse(parsed)); + } + } } @Override diff --git a/src/main/java/com/massivecraft/factions/cmd/CmdTop.java b/src/main/java/com/massivecraft/factions/cmd/CmdTop.java index 50391550..dc456645 100644 --- a/src/main/java/com/massivecraft/factions/cmd/CmdTop.java +++ b/src/main/java/com/massivecraft/factions/cmd/CmdTop.java @@ -173,6 +173,8 @@ public class CmdTop extends FCommand { private String getValue(Faction faction, String criteria) { if (criteria.equalsIgnoreCase("online")) { return String.valueOf(faction.getFPlayersWhereOnline(true).size()); + } else if (criteria.equalsIgnoreCase("start")) { + return TL.sdf.format(faction.getFoundedDate()); } else if (criteria.equalsIgnoreCase("members")) { return String.valueOf(faction.getFPlayers().size()); } else if (criteria.equalsIgnoreCase("land")) { diff --git a/src/main/java/com/massivecraft/factions/scoreboards/FSidebarProvider.java b/src/main/java/com/massivecraft/factions/scoreboards/FSidebarProvider.java index d010344b..1a2ed9b7 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/FSidebarProvider.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/FSidebarProvider.java @@ -1,11 +1,36 @@ package com.massivecraft.factions.scoreboards; import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.P; +import com.massivecraft.factions.zcore.util.TL; +import com.massivecraft.factions.zcore.util.TagUtil; import java.util.List; public abstract class FSidebarProvider { + public abstract String getTitle(FPlayer fplayer); public abstract List getLines(FPlayer fplayer); -} + + public String replaceTags(FPlayer fPlayer, String s) { + return qualityAssure(TagUtil.parsePlain(fPlayer, s)); + } + + public String replaceTags(Faction faction, FPlayer fPlayer, String s) { + return qualityAssure(TagUtil.parsePlain(faction, fPlayer, s)); + } + + private String qualityAssure(String line) { + if (line.contains("{notFrozen}") || line.contains("{notPermanent}")) { + return "n/a"; // we dont support support these error variables in scoreboards + } + if (line.contains("{ig}")) { + // since you can't really fit a whole "Faction Home: world, x, y, z" on one line + // we assume it's broken up into two lines, so returning our tl will suffice. + return TL.COMMAND_SHOW_NOHOME.toString(); + } + return P.p.txt.parse(line); // finally add color :) + } +} \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FDefaultSidebar.java b/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FDefaultSidebar.java index 970464a4..d92e18b4 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FDefaultSidebar.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FDefaultSidebar.java @@ -2,12 +2,7 @@ package com.massivecraft.factions.scoreboards.sidebar; import com.massivecraft.factions.FPlayer; import com.massivecraft.factions.P; -import com.massivecraft.factions.integration.Econ; import com.massivecraft.factions.scoreboards.FSidebarProvider; -import com.massivecraft.factions.zcore.util.TL; - -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import java.util.List; import java.util.ListIterator; @@ -16,7 +11,7 @@ public class FDefaultSidebar extends FSidebarProvider { @Override public String getTitle(FPlayer fplayer) { - return replace(fplayer, P.p.getConfig().getString("scoreboard.default-title", "i love drt")); + return replaceTags(fplayer, P.p.getConfig().getString("scoreboard.default-title", "i love drt")); } @Override @@ -25,15 +20,8 @@ public class FDefaultSidebar extends FSidebarProvider { ListIterator it = lines.listIterator(); while (it.hasNext()) { - it.set(replace(fplayer, it.next())); + it.set(replaceTags(fplayer, it.next())); } return lines; } - - private String replace(FPlayer fplayer, String s) { - String faction = !fplayer.getFaction().isNone() ? fplayer.getFaction().getTag() : TL.GENERIC_FACTIONLESS.toString(); - String powerBoost = String.valueOf((int) fplayer.getPowerBoost()); - s = s.replace("{name}", fplayer.getName()).replace("{power}", String.valueOf(fplayer.getPowerRounded())).replace("{balance}", String.valueOf(Econ.getFriendlyBalance(fplayer.getPlayer().getUniqueId()))).replace("{faction}", faction).replace("{maxPower}", String.valueOf(fplayer.getPowerMaxRounded())).replace("{totalOnline}", String.valueOf(Bukkit.getServer().getOnlinePlayers().size())).replace("{powerBoost}", powerBoost); - return ChatColor.translateAlternateColorCodes('&', s); - } -} +} \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FInfoSidebar.java b/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FInfoSidebar.java index b93e7b36..d3752728 100644 --- a/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FInfoSidebar.java +++ b/src/main/java/com/massivecraft/factions/scoreboards/sidebar/FInfoSidebar.java @@ -4,7 +4,6 @@ import com.massivecraft.factions.FPlayer; import com.massivecraft.factions.Faction; import com.massivecraft.factions.P; import com.massivecraft.factions.scoreboards.FSidebarProvider; -import org.bukkit.ChatColor; import java.util.List; import java.util.ListIterator; @@ -27,16 +26,8 @@ public class FInfoSidebar extends FSidebarProvider { ListIterator it = lines.listIterator(); while (it.hasNext()) { - it.set(replaceFInfoTags(it.next())); + it.set(replaceTags(faction, fplayer, it.next())); } - return lines; } - - private String replaceFInfoTags(String s) { - boolean raidable = faction.getLandRounded() > faction.getPower(); - FPlayer fLeader = faction.getFPlayerAdmin(); - String leader = fLeader == null ? "Server" : fLeader.getName().substring(0, fLeader.getName().length() > 14 ? 13 : fLeader.getName().length()); - return ChatColor.translateAlternateColorCodes('&', s.replace("{power}", String.valueOf(faction.getPowerRounded())).replace("{online}", String.valueOf(faction.getOnlinePlayers().size())).replace("{members}", String.valueOf(faction.getFPlayers().size())).replace("{leader}", leader).replace("{chunks}", String.valueOf(faction.getLandRounded())).replace("{raidable}", String.valueOf(raidable)).replace("{warps}", String.valueOf(faction.getWarps().size()))); - } -} +} \ No newline at end of file diff --git a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java index aef9a557..800fa2af 100644 --- a/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java +++ b/src/main/java/com/massivecraft/factions/zcore/persist/MemoryFaction.java @@ -31,6 +31,7 @@ public abstract class MemoryFaction implements Faction, EconomyParticipator { protected boolean peaceful; protected Integer permanentPower; protected LazyLocation home; + protected long foundedDate; protected transient long lastPlayerLoggedOffTime; protected double money; protected double powerBoost; @@ -208,6 +209,17 @@ public abstract class MemoryFaction implements Faction, EconomyParticipator { return (this.home != null) ? this.home.getLocation() : null; } + public long getFoundedDate() { + if(this.foundedDate == 0) { + setFoundedDate(System.currentTimeMillis()); + } + return this.foundedDate; + } + + public void setFoundedDate(long newDate) { + this.foundedDate = newDate; + } + public void confirmValidHome() { if (!Conf.homesMustBeInClaimedTerritory || this.home == null || (this.home.getLocation() != null && Board.getInstance().getFactionAt(new FLocation(this.home.getLocation())) == this)) { return; @@ -282,6 +294,7 @@ public abstract class MemoryFaction implements Faction, EconomyParticipator { this.permanent = false; this.money = 0.0; this.powerBoost = 0.0; + this.foundedDate = System.currentTimeMillis(); } public MemoryFaction(MemoryFaction old) { @@ -291,6 +304,7 @@ public abstract class MemoryFaction implements Faction, EconomyParticipator { tag = old.tag; description = old.description; open = old.open; + foundedDate = old.foundedDate; peaceful = old.peaceful; permanentPower = old.permanentPower; home = old.home; diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TL.java b/src/main/java/com/massivecraft/factions/zcore/util/TL.java index 0b828036..de31cc14 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/TL.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/TL.java @@ -19,6 +19,8 @@ package com.massivecraft.factions.zcore.util; import org.bukkit.ChatColor; import org.bukkit.configuration.file.YamlConfiguration; +import java.text.SimpleDateFormat; + /** * An enum for requesting strings from the language file. The contents of this enum file may be subject to frequent * changes. @@ -436,6 +438,7 @@ public enum TL { COMMAND_SHOW_JOINING("Joining: %1$s "), COMMAND_SHOW_INVITATION("invitation is required"), COMMAND_SHOW_UNINVITED("no invitation is needed"), + COMMAND_SHOW_NOHOME("n/a"), COMMAND_SHOW_POWER("Land / Power / Maxpower: %1$d/%2$d/%3$d %4$s."), COMMAND_SHOW_BONUS(" (bonus: "), COMMAND_SHOW_PENALTY(" (penalty: "), @@ -564,6 +567,7 @@ public enum TL { GENERIC_SERVERADMIN("A server admin"), GENERIC_DISABLED("disabled"), GENERIC_ENABLED("enabled"), + GENERIC_INFINITY("∞"), GENERIC_CONSOLEONLY("This command cannot be run as a player."), GENERIC_PLAYERONLY("This command can only be used by ingame players."), GENERIC_ASKYOURLEADER(" Ask your leader to:"), @@ -593,6 +597,12 @@ public enum TL { CHAT_TRUCE("truce chat"), CHAT_PUBLIC("public chat"), + /** + * Economy stuff + */ + + ECON_OFF("no %s"), // no balance, no value, no refund, etc + /** * Relations */ @@ -691,6 +701,7 @@ public enum TL { private String path; private String def; private static YamlConfiguration LANG; + public static SimpleDateFormat sdf; /** * Lang enum constructor. @@ -723,6 +734,7 @@ public enum TL { */ public static void setFile(YamlConfiguration config) { LANG = config; + sdf = new SimpleDateFormat(DATE_FORMAT.toString()); } @Override diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TagReplacer.java b/src/main/java/com/massivecraft/factions/zcore/util/TagReplacer.java new file mode 100644 index 00000000..758c0f91 --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/util/TagReplacer.java @@ -0,0 +1,260 @@ +package com.massivecraft.factions.zcore.util; + +import com.massivecraft.factions.*; +import com.massivecraft.factions.integration.Econ; +import com.massivecraft.factions.struct.Relation; +import org.apache.commons.lang.time.DurationFormatUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * Link between config and in-game messages
+ * Changes based on faction / player
+ * Interfaces the config lists with {} variables to plugin + */ +public enum TagReplacer { + + /** + * Fancy variables, used by f show + */ + ALLIES_LIST(TagType.FANCY, "{allies-list}"), + ONLINE_LIST(TagType.FANCY, "{online-list}"), + ENEMIES_LIST(TagType.FANCY, "{enemies-list}"), + OFFLINE_LIST(TagType.FANCY, "{offline-list}"), + + /** + * Player variables, require a player + */ + PLAYER_GROUP(TagType.PLAYER, "{group}"), + LAST_SEEN(TagType.PLAYER, "{last-seen}"), + PLAYER_BALANCE(TagType.PLAYER, "{player-balance}"), + + /** + * Faction variables, require at least a player + */ + HOME_X(TagType.FACTION, "{x}"), + HOME_Y(TagType.FACTION, "{y}"), + HOME_Z(TagType.FACTION, "{z}"), + CHUNKS(TagType.FACTION, "{chunks}"), + WARPS(TagType.FACTION, "{warps}"), + HEADER(TagType.FACTION, "{header}"), + POWER(TagType.FACTION, "{power}"), + MAX_POWER(TagType.FACTION, "{maxPower}"), + POWER_BOOST(TagType.FACTION, "{power-boost}"), + LEADER(TagType.FACTION, "{leader}"), + JOINING(TagType.FACTION, "{joining}"), + FACTION(TagType.FACTION, "{faction}"), + PLAYER_NAME(TagType.FACTION, "{name}"), + HOME_WORLD(TagType.FACTION, "{world}"), + RAIDABLE(TagType.FACTION, "{raidable}"), + PEACEFUL(TagType.FACTION, "{peaceful}"), + PERMANENT(TagType.FACTION, "permanent"), // no braces needed + TIME_LEFT(TagType.FACTION, "{time-left}"), + LAND_VALUE(TagType.FACTION, "{land-value}"), + DESCRIPTION(TagType.FACTION, "{description}"), + CREATE_DATE(TagType.FACTION, "{create-date}"), + LAND_REFUND(TagType.FACTION, "{land-refund}"), + BANK_BALANCE(TagType.FACTION, "{balance}"), + ALLIES_COUNT(TagType.FACTION, "{allies}"), + ENEMIES_COUNT(TagType.FACTION, "{enemies}"), + ONLINE_COUNT(TagType.FACTION, "{online}"), + OFFLINE_COUNT(TagType.FACTION, "{offline}"), + FACTION_SIZE(TagType.FACTION, "{members}"), + + /** + * General variables, require no faction or player + */ + MAX_WARPS(TagType.GENERAL, "{max-warps}"), + MAX_ALLIES(TagType.GENERAL, "{max-allies}"), + MAX_ENEMIES(TagType.GENERAL, "{max-enemies}"), + FACTIONLESS(TagType.GENERAL, "{factionless}"), + TOTAL_ONLINE(TagType.GENERAL, "{total-online}"); + + private TagType type; + private String tag; + + protected enum TagType { + FANCY(0), PLAYER(1), FACTION(2), GENERAL(3); + public int id; + + TagType(int id) { + this.id = id; + } + } + + TagReplacer(TagType type, String tag) { + this.type = type; + this.tag = tag; + } + + /** + * Protected access to this generic server related variable + * + * @return value for this generic server related variable
+ */ + protected String getValue() { + switch (this) { + case TOTAL_ONLINE: + return String.valueOf(Bukkit.getOnlinePlayers().size()); + case FACTIONLESS: + return String.valueOf(Factions.getInstance().getNone().getFPlayersWhereOnline(true).size()); + case MAX_ALLIES: + if (P.p.getConfig().getBoolean("max-relations.enabled", true)) { + return String.valueOf(P.p.getConfig().getInt("max-relations.ally", 10)); + } + return TL.GENERIC_INFINITY.toString(); + case MAX_ENEMIES: + if (P.p.getConfig().getBoolean("max-relations.enabled", true)) { + return String.valueOf(P.p.getConfig().getInt("max-relations.enemy", 10)); + } + return TL.GENERIC_INFINITY.toString(); + case MAX_WARPS: + return String.valueOf(P.p.getConfig().getInt("max-warps", 5)); + } + return null; + } + + /** + * Gets the value for this (as in the instance this is called from) variable! + * + * @param fac Target faction + * @param fp Target player (can be null) + * @return the value for this enum! + */ + protected String getValue(Faction fac, FPlayer fp) { + if (this.type == TagType.GENERAL) { + return getValue(); + } + if (fp != null) { + switch (this) { + case HEADER: + return P.p.txt.titleize(fac.getTag(fp)); + case PLAYER_NAME: + return fp.getName(); + case FACTION: + return !fac.isNone() ? fac.getTag(fp) : TL.GENERIC_FACTIONLESS.toString(); + case LAST_SEEN: + long lastSeen = System.currentTimeMillis() - fp.getLastLoginTime(); + String humanized = DurationFormatUtils.formatDurationWords(lastSeen, true, true) + TL.COMMAND_STATUS_AGOSUFFIX; + String last = fp.isOnline() ? ChatColor.GREEN + TL.COMMAND_STATUS_ONLINE.toString() : + (lastSeen < 432000000 ? ChatColor.YELLOW + humanized : ChatColor.RED + humanized); + return String.format(TL.COMMAND_STATUS_FORMAT.toString(), + ChatColor.GOLD + fp.getRole().getPrefix() + fp.getName() + ChatColor.RESET, last).trim(); + case PLAYER_GROUP: + return P.p.getPrimaryGroup(Bukkit.getOfflinePlayer(UUID.fromString(fp.getId()))); + case PLAYER_BALANCE: + return Econ.isSetup() ? Econ.getFriendlyBalance(fp) : TL.ECON_OFF.format("balance"); + } + } + switch (this) { + case DESCRIPTION: + return fac.getDescription(); + case FACTION: + return fac.getTag(); + case JOINING: + return (fac.getOpen() ? TL.COMMAND_SHOW_UNINVITED.toString() : TL.COMMAND_SHOW_INVITATION.toString()); + case PEACEFUL: + return fac.isPeaceful() ? Conf.colorNeutral + TL.COMMAND_SHOW_PEACEFUL.toString() : ""; + case PERMANENT: + return fac.isPermanent() ? "permanent" : "{notPermanent}"; + case CHUNKS: + return String.valueOf(fac.getLandRounded()); + case POWER: + return String.valueOf(fac.getPowerRounded()); + case MAX_POWER: + return String.valueOf(fac.getPowerMaxRounded()); + case POWER_BOOST: + double powerBoost = fac.getPowerBoost(); + return (powerBoost == 0.0) ? "" : (powerBoost > 0.0 ? TL.COMMAND_SHOW_BONUS.toString() : TL.COMMAND_SHOW_PENALTY.toString() + powerBoost + ")"); + case LEADER: + FPlayer fAdmin = fac.getFPlayerAdmin(); + return fAdmin == null ? "Server" : fAdmin.getName().substring(0, fAdmin.getName().length() > 14 ? 13 : fAdmin.getName().length()); + case WARPS: + return String.valueOf(fac.getWarps().size()); + case CREATE_DATE: + return TL.sdf.format(fac.getFoundedDate()); + case RAIDABLE: + boolean raid = P.p.getConfig().getBoolean("hcf.raidable", false) && fac.getLandRounded() >= fac.getPowerRounded(); + return raid ? TL.RAIDABLE_TRUE.toString() : TL.RAIDABLE_FALSE.toString(); + case HOME_WORLD: + return fac.hasHome() ? fac.getHome().getWorld().getName() : "{ig}"; + case HOME_X: + return fac.hasHome() ? String.valueOf(fac.getHome().getBlockX()) : "{ig}"; + case HOME_Y: + return fac.hasHome() ? String.valueOf(fac.getHome().getBlockY()) : "{ig}"; + case HOME_Z: + return fac.hasHome() ? String.valueOf(fac.getHome().getBlockZ()) : "{ig}"; + case LAND_VALUE: + return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandValue(fac.getLandRounded())) : TL.ECON_OFF.format("value"); + case LAND_REFUND: + return Econ.shouldBeUsed() ? Econ.moneyString(Econ.calculateTotalLandRefund(fac.getLandRounded())) : TL.ECON_OFF.format("refund"); + case BANK_BALANCE: + if (Econ.shouldBeUsed()) { + return Conf.bankEnabled ? Econ.moneyString(Econ.getBalance(fac.getAccountId())) : TL.ECON_OFF.format("balance"); + } + return TL.ECON_OFF.format("balance"); + case ALLIES_COUNT: + return String.valueOf(fac.getRelationCount(Relation.ALLY)); + case ENEMIES_COUNT: + return String.valueOf(fac.getRelationCount(Relation.ENEMY)); + case ONLINE_COUNT: + return String.valueOf(fac.getOnlinePlayers().size()); + case OFFLINE_COUNT: + return String.valueOf(fac.getFPlayers().size() - fac.getOnlinePlayers().size()); + case FACTION_SIZE: + return String.valueOf(fac.getFPlayers().size()); + } + return null; + } + + /** + * Returns a list of all the variables we can use for this type
+ * + * @param type the type we want + * @return a list of all the variables with this type + */ + protected static List getByType(TagType type) { + List tagReplacers = new ArrayList(); + for (TagReplacer tagReplacer : TagReplacer.values()) { + if (type == TagType.FANCY) { + if (tagReplacer.type == TagType.FANCY) { + tagReplacers.add(tagReplacer); + } + } else if (tagReplacer.type.id >= type.id) { + tagReplacers.add(tagReplacer); + } + } + return tagReplacers; + } + + /** + * @param original raw line with variables + * @param value what to replace var in raw line with + * @return the string with the new value + */ + public String replace(String original, String value) { + return original.replace(tag, value); + } + + /** + * @param toSearch raw line with variables + * @return if the raw line contains this enums variable + */ + public boolean contains(String toSearch) { + return toSearch.contains(tag); + } + + /** + * Gets the tag associated with this enum that we should replace + * + * @return the {....} variable that is located in config + */ + public String getTag() { + return this.tag; + } +} diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TagUtil.java b/src/main/java/com/massivecraft/factions/zcore/util/TagUtil.java new file mode 100644 index 00000000..9d6a6f0f --- /dev/null +++ b/src/main/java/com/massivecraft/factions/zcore/util/TagUtil.java @@ -0,0 +1,226 @@ +package com.massivecraft.factions.zcore.util; + + +import com.massivecraft.factions.FPlayer; +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.MiscUtil; +import mkremins.fanciful.FancyMessage; +import org.bukkit.ChatColor; + +import java.util.ArrayList; +import java.util.List; + +import static com.massivecraft.factions.zcore.util.TagReplacer.TagType; + +public class TagUtil { + + private static final int ARBITRARY_LIMIT = 25000; + + /** + * Replaces all variables in a plain raw line for a faction + * + * @param faction for faction + * @param line raw line from config with variables to replace for + * @return clean line + */ + public static String parsePlain(Faction faction, String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FACTION)) { + if (tagReplacer.contains(line)) { + line = tagReplacer.replace(line, tagReplacer.getValue(faction, null)); + } + } + return line; + } + + /** + * Replaces all variables in a plain raw line for a player + * + * @param fplayer for player + * @param line raw line from config with variables to replace for + * @return clean line + */ + public static String parsePlain(FPlayer fplayer, String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.PLAYER)) { + if (tagReplacer.contains(line)) { + String rep = tagReplacer.getValue(fplayer.getFaction(), fplayer); + if(rep == null) { + rep = ""; // this should work, but it's not a good way to handle whatever is going wrong + } + line = tagReplacer.replace(line, rep); + } + } + return line; + } + + /** + * Replaces all variables in a plain raw line for a faction, using relations from fplayer + * + * @param faction for faction + * @param fplayer from player + * @param line raw line from config with variables to replace for + * @return clean line + */ + public static String parsePlain(Faction faction, FPlayer fplayer, String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.PLAYER)) { + if (tagReplacer.contains(line)) { + line = tagReplacer.replace(line, tagReplacer.getValue(faction, fplayer)); + } + } + return line; + } + + /** + * Scan a line and parse the fancy variable into a fancy list + * + * @param faction for faction (viewers faction) + * @param fme for player (viewer) + * @param line fancy message prefix + * @return + */ + public static List parseFancy(Faction faction, FPlayer fme, String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FANCY)) { + if (tagReplacer.contains(line)) { + String clean = line.replace(tagReplacer.getTag(), ""); // remove tag + return getFancy(faction, fme, tagReplacer, clean); + } + } + return null; + } + + /** + * Checks if a line has fancy variables + * + * @param line raw line from config with variables + * @return if the line has fancy variables + */ + public static boolean hasFancy(String line) { + for (TagReplacer tagReplacer : TagReplacer.getByType(TagType.FANCY)) { + if (tagReplacer.contains(line)) { + return true; + } + } + return false; + } + + /** + * Lets get fancy. + * + * @param target Faction to get relate from + * @param fme Player to relate to + * @param prefix First part of the fancy message + * @return list of fancy messages to send + */ + protected static List getFancy(Faction target, FPlayer fme, TagReplacer type, String prefix) { + List fancyMessages = new ArrayList(); + switch (type) { + case ALLIES_LIST: + FancyMessage currentAllies = P.p.txt.parseFancy(prefix); + boolean firstAlly = true; + for (Faction otherFaction : Factions.getInstance().getAllFactions()) { + if (otherFaction == target) { + continue; + } + String s = otherFaction.getTag(fme); + if (otherFaction.getRelationTo(target).isAlly()) { + currentAllies.then(firstAlly ? s : ", " + s); + currentAllies.tooltip(tipFaction(otherFaction)).color(fme.getColorTo(otherFaction)); + firstAlly = false; + if (currentAllies.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentAllies); + currentAllies = new FancyMessage(""); + } + } + } + fancyMessages.add(currentAllies); + return fancyMessages; // we must return here and not outside the switch + case ENEMIES_LIST: + FancyMessage currentEnemies = P.p.txt.parseFancy(prefix); + boolean firstEnemy = true; + for (Faction otherFaction : Factions.getInstance().getAllFactions()) { + if (otherFaction == target) { + continue; + } + String s = otherFaction.getTag(fme); + if (otherFaction.getRelationTo(target).isEnemy()) { + currentEnemies.then(firstEnemy ? s : ", " + s); + currentEnemies.tooltip(tipFaction(otherFaction)).color(fme.getColorTo(otherFaction)); + firstEnemy = false; + if (currentEnemies.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentEnemies); + currentEnemies = new FancyMessage(""); + } + } + } + fancyMessages.add(currentEnemies); + return fancyMessages; // we must return here and not outside the switch + case ONLINE_LIST: + FancyMessage currentOnline = P.p.txt.parseFancy(prefix); + boolean firstOnline = true; + for (FPlayer p : MiscUtil.rankOrder(target.getFPlayersWhereOnline(true))) { + String name = p.getNameAndTitle(); + currentOnline.then(firstOnline ? name : ", " + name); + currentOnline.tooltip(tipPlayer(p)).color(fme.getColorTo(p)); + firstOnline = false; + if (currentOnline.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentOnline); + currentOnline = new FancyMessage(""); + } + } + fancyMessages.add(currentOnline); + return fancyMessages; // we must return here and not outside the switch + case OFFLINE_LIST: + FancyMessage currentOffline = P.p.txt.parseFancy(prefix); + boolean firstOffline = true; + for (FPlayer p : MiscUtil.rankOrder(target.getFPlayers())) { + String name = p.getNameAndTitle(); + if (!p.isOnline()) { + currentOffline.then(firstOffline ? name : ", " + name); + currentOffline.tooltip(tipPlayer(p)).color(fme.getColorTo(p)); + firstOffline = false; + if (currentOffline.toJSONString().length() > ARBITRARY_LIMIT) { + fancyMessages.add(currentOffline); + currentOffline = new FancyMessage(""); + } + } + } + fancyMessages.add(currentOffline); + return fancyMessages; // we must return here and not outside the switch + } + return null; + } + + /** + * Parses tooltip variables from config + *
+ * Supports variables for factions only (type 2) + * + * @param faction faction to tooltip for + * @return list of tooltips for a fancy message + */ + private static List tipFaction(Faction faction) { + List lines = new ArrayList(); + for (String line : P.p.getConfig().getStringList("tooltips.list")) { + lines.add(ChatColor.translateAlternateColorCodes('&', TagUtil.parsePlain(faction, line))); + } + return lines; + } + + /** + * Parses tooltip variables from config + *
+ * Supports variables for players and factions (types 1 and 2) + * + * @param fplayer player to tooltip for + * @return list of tooltips for a fancy message + */ + private static List tipPlayer(FPlayer fplayer) { + List lines = new ArrayList(); + for (String line : P.p.getConfig().getStringList("tooltips.show")) { + lines.add(ChatColor.translateAlternateColorCodes('&', TagUtil.parsePlain(fplayer, line))); + } + return lines; + } +} diff --git a/src/main/java/com/massivecraft/factions/zcore/util/TextUtil.java b/src/main/java/com/massivecraft/factions/zcore/util/TextUtil.java index 46131104..70a2d49e 100644 --- a/src/main/java/com/massivecraft/factions/zcore/util/TextUtil.java +++ b/src/main/java/com/massivecraft/factions/zcore/util/TextUtil.java @@ -1,5 +1,6 @@ package com.massivecraft.factions.zcore.util; +import mkremins.fanciful.FancyMessage; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -53,6 +54,44 @@ public class TextUtil { return ret.toString(); } + // -------------------------------------------- // + // Fancy parsing + // -------------------------------------------- // + + public FancyMessage parseFancy(String prefix) { + return toFancy(parse(prefix)); + } + + public static FancyMessage toFancy(String first) { + String text = ""; + FancyMessage message = new FancyMessage(text); + ChatColor color = null; + char[] chars = first.toCharArray(); + + for(int i = 0; i < chars.length; i++){ + if (chars[i] == '§') { + if(color != null) { + message.then(text).color(color); + text = ""; + color = ChatColor.getByChar(chars[i+1]); + } else { + color = ChatColor.getByChar(chars[i+1]); + } + i++; // skip color char + } else { + text += chars[i]; + } + } + if(text.length() > 0) { + if(color != null) { + message.then(text).color(color); + } else { + message.text(text); + } + } + return message; + } + // -------------------------------------------- // // Color parsing // -------------------------------------------- // diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 124164e6..d028f631 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -207,4 +207,27 @@ hcf: # heavy operation if set to a large number. # If this is set to 0, we won't even bother checking which is how Factions has # always been. - buffer-zone: 0 \ No newline at end of file + buffer-zone: 0 + +############################################################ +# +------------------------------------------------------+ # +# | Configurable /f show | # +# +------------------------------------------------------+ # +############################################################ + +# You can use any variable here, including fancy messages. Color codes and or tags work fine. +# Lines that arent defined wont be sent (home not set, faction not peaceful / permanent, dtr freeze) +show: + # First line can be {header} for default header, or any string (we recommend &m for smooth lines ;p) + - '{header}' + - '
Description: {description}' + - 'Joining: {joining} {peaceful}' + - 'Land / Power / Maxpower: {chunks}/{power}/{maxPower}' + - 'Faction Home: {world}, {x}, {y}, {z}' # if no home is set, {z} = COMMAND_SHOW_NOHOME, from lang.yml + - 'Founded: {create-date}' + - 'This faction is permanent, remaining even with no members.' # only shows if faction is permanent + - 'Land value: {land-value} {land-refund}' + - 'Balance: {balance}' + - 'Allies({allies}/{max-allies}): {allies-list} ' + - 'Online: ({online}/{members}): {online-list}' + - 'Offline: ({offline}/{members}): {offline-list}' \ No newline at end of file