diff --git a/lib/SpoutAPI.jar b/lib/SpoutAPI.jar new file mode 100644 index 00000000..ffa25c34 Binary files /dev/null and b/lib/SpoutAPI.jar differ diff --git a/src/com/massivecraft/factions/Conf.java b/src/com/massivecraft/factions/Conf.java index 3e686efe..7180f944 100644 --- a/src/com/massivecraft/factions/Conf.java +++ b/src/com/massivecraft/factions/Conf.java @@ -151,6 +151,17 @@ public class Conf { public static transient Set safeZoneNerfedCreatureTypes = EnumSet.noneOf(CreatureType.class); + // Spout features + public static boolean spoutFactionTagsOverNames = true; + public static boolean spoutFactionTitlesOverNames = true; + public static boolean spoutFactionAdminCapes = true; + public static boolean spoutFactionModeratorCapes = true; + public static String capeAlly = "http://www.wimbli.com/minecraft/factions_capes/capeAlly.png"; + public static String capeEnemy = "http://www.wimbli.com/minecraft/factions_capes/capeEnemy.png"; + public static String capeMember = "http://www.wimbli.com/minecraft/factions_capes/capeMember.png"; + public static String capeNeutral = "http://www.wimbli.com/minecraft/factions_capes/capeNeutral.png"; + public static String capePeaceful = "http://www.wimbli.com/minecraft/factions_capes/capePeaceful.png"; + // Economy settings public static boolean econIConomyEnabled = false; public static boolean econEssentialsEcoEnabled = false; diff --git a/src/com/massivecraft/factions/FPlayer.java b/src/com/massivecraft/factions/FPlayer.java index 9f134333..5ac1350d 100644 --- a/src/com/massivecraft/factions/FPlayer.java +++ b/src/com/massivecraft/factions/FPlayer.java @@ -78,6 +78,10 @@ public class FPlayer { this.factionChatting = false; this.role = Role.NORMAL; this.title = ""; + + if (playerName != null && !playerName.isEmpty()) { + SpoutFeatures.updateAppearances(this.getPlayer()); + } } // -------------------------------------------- // @@ -114,6 +118,7 @@ public class FPlayer { public void setFaction(Faction faction) { this.factionId = faction.getId(); + SpoutFeatures.updateAppearances(this.getPlayer()); } public boolean hasFaction() { @@ -126,6 +131,7 @@ public class FPlayer { public void setRole(Role role) { this.role = role; + SpoutFeatures.updateAppearances(this.getPlayer()); } public boolean isFactionChatting() { @@ -485,7 +491,7 @@ public class FPlayer { this.resetFactionData(); - if (myFaction.isNormal() && myFaction.getFPlayers().size() == 0) { + if (myFaction.isNormal() && myFaction.getFPlayers().isEmpty()) { // Remove this faction for (FPlayer fplayer : FPlayer.getAllOnline()) { fplayer.sendMessage("The faction "+myFaction.getTag(fplayer)+Conf.colorSystem+" was disbanded."); diff --git a/src/com/massivecraft/factions/Factions.java b/src/com/massivecraft/factions/Factions.java index 1f7e5f2d..1014cd34 100644 --- a/src/com/massivecraft/factions/Factions.java +++ b/src/com/massivecraft/factions/Factions.java @@ -146,6 +146,7 @@ public class Factions extends JavaPlugin { setupPermissions(); integrateEssentialsChat(); + SpoutFeatures.setup(this); Econ.setup(this); Econ.monitorPlugins(); @@ -207,7 +208,7 @@ public class Factions extends JavaPlugin { if (test != null) { Permissions = ((Permissions)test).getHandler(); - Factions.log("Found and will use plugin "+((Permissions)test).getDescription().getFullName()); + Factions.log("Found and will use "+test.getDescription().getFullName()+" for permissions"); } else { Factions.log("Permissions plugin not detected, defaulting to Bukkit superperms system"); } diff --git a/src/com/massivecraft/factions/SpoutFeatures.java b/src/com/massivecraft/factions/SpoutFeatures.java new file mode 100644 index 00000000..d78eb4b8 --- /dev/null +++ b/src/com/massivecraft/factions/SpoutFeatures.java @@ -0,0 +1,176 @@ +package com.massivecraft.factions; + +import java.util.Set; + +import org.bukkit.plugin.Plugin; +import org.bukkit.entity.Player; + +import com.massivecraft.factions.struct.Relation; +import com.massivecraft.factions.struct.Role; + +import org.getspout.spoutapi.player.AppearanceManager; +import org.getspout.spoutapi.player.SpoutPlayer; +import org.getspout.spoutapi.SpoutManager; + + +public class SpoutFeatures { + private transient static AppearanceManager spoutApp; + private transient static boolean spoutMe = false; + + public static void setup(Factions factions) { + Plugin test = factions.getServer().getPluginManager().getPlugin("Spout"); + + if (test != null && test.isEnabled()) { + setAvailable(true, test.getDescription().getFullName()); + } + else { + setAvailable(false, ""); + } + } + + // set integration availability + public static void setAvailable(boolean enable, String pluginName) { + spoutMe = enable; + if (spoutMe) { + spoutApp = SpoutManager.getAppearanceManager(); + Factions.log("Found and will use features of "+pluginName); + } + else { + spoutApp = null; + } + } + + // If any Spout feature is enabled in conf.json, and we're successfully hooked into it + public static boolean enabled() { + return spoutMe && ( + Conf.spoutFactionTagsOverNames + || Conf.spoutFactionTitlesOverNames + || Conf.spoutFactionAdminCapes + || Conf.spoutFactionModeratorCapes + ); + } + + + // update all appearances between every player + public static void updateAppearances() { + if (!enabled()) { + return; + } + + Set players = FPlayer.getAllOnline(); + Faction factionA; + + for (FPlayer playerA : players) { + factionA = playerA.getFaction(); + for (FPlayer playerB : players) { + updateSingle(playerB.getPlayer(), playerA.getPlayer(), factionA.getRelation(playerB), factionA, playerA.getTitle(), playerA.getRole()); + } + } + } + + // update all appearances related to a specific player + public static void updateAppearances(Player player) { + if (!enabled() || player == null) { + return; + } + + Set players = FPlayer.getAllOnline(); + FPlayer playerA = FPlayer.get(player); + Faction factionA = playerA.getFaction(); + + for (FPlayer playerB : players) { + Player player2 = playerB.getPlayer(); + Relation rel = factionA.getRelation(playerB); + updateSingle(player2, player, rel, factionA, playerA.getTitle(), playerA.getRole()); + updateSingle(player, player2, rel, playerB.getFaction(), playerB.getTitle(), playerB.getRole()); + } + } + + // update all appearances related to a single faction + public static void updateAppearances(Faction faction) { + if (!enabled() || faction == null) { + return; + } + + Set players = FPlayer.getAllOnline(); + Faction factionA, factionB; + + for (FPlayer playerA : players) { + factionA = playerA.getFaction(); + + for (FPlayer playerB : players) { + factionB = playerB.getFaction(); + if (factionA != faction && factionB != faction) { + continue; + } + updateSingle(playerB.getPlayer(), playerA.getPlayer(), factionA.getRelation(factionB), factionA, playerA.getTitle(), playerA.getRole()); + } + } + } + + // update all appearances between two factions + public static void updateAppearances(Faction factionA, Faction factionB) { + if (!enabled() || factionA == null || factionB == null) { + return; + } + + for (FPlayer playerA : factionA.getFPlayersWhereOnline(true)) { + for (FPlayer playerB : factionB.getFPlayersWhereOnline(true)) { + Player player1 = playerA.getPlayer(); + Player player2 = playerB.getPlayer(); + Relation rel = factionA.getRelation(factionB); + updateSingle(player2, player1, rel, factionA, playerA.getTitle(), playerA.getRole()); + updateSingle(player1, player2, rel, factionB, playerB.getTitle(), playerB.getRole()); + } + } + } + + + // update a single appearance; internal use only by above public methods + private static void updateSingle(Player viewer, Player viewed, Relation relation, Faction viewedFaction, String viewedTitle, Role viewedRole) { + if (viewer == null || viewed == null) { + return; + } + + SpoutPlayer sPlayer = SpoutManager.getPlayer(viewer); + + if (Conf.spoutFactionTagsOverNames || Conf.spoutFactionTitlesOverNames) { + String addTag = ""; + if (Conf.spoutFactionTagsOverNames) { + addTag += !viewedFaction.isNormal() ? "Factionless" : viewedFaction.getTag(relation.getColor().toString() + "[") + "]"; + } + String rolePrefix = viewedRole.getPrefix(); + if (Conf.spoutFactionTitlesOverNames && (!viewedTitle.isEmpty() || !rolePrefix.isEmpty())) { + addTag += (addTag.isEmpty() ? "" : " ") + viewedRole.getPrefix() + viewedTitle; + } + spoutApp.setPlayerTitle(sPlayer, viewed, addTag + "\n" + viewed.getDisplayName()); + } + + if ( + (Conf.spoutFactionAdminCapes && viewedRole.equals(Role.ADMIN)) + || (Conf.spoutFactionModeratorCapes && viewedRole.equals(Role.MODERATOR)) + ) { + String cape = ""; + if (!viewedFaction.isNormal()) { + // yeah, no cape if no faction + } + else if (viewedFaction.isPeaceful()) { + cape = Conf.capePeaceful; + } + else if (relation.isNeutral()) { + cape = Conf.capeNeutral; + } + else if (relation.isMember()) { + cape = Conf.capeMember; + } + else if (relation.isEnemy()) { + cape = Conf.capeEnemy; + } + else if (relation.isAlly()) { + cape = Conf.capeAlly; + } + spoutApp.setPlayerCloak(sPlayer, viewed, cape); + } + } + +} diff --git a/src/com/massivecraft/factions/commands/FCommandConfig.java b/src/com/massivecraft/factions/commands/FCommandConfig.java index 634c6274..61217450 100644 --- a/src/com/massivecraft/factions/commands/FCommandConfig.java +++ b/src/com/massivecraft/factions/commands/FCommandConfig.java @@ -13,6 +13,7 @@ import org.bukkit.entity.Player; import com.massivecraft.factions.Conf; import com.massivecraft.factions.Factions; +import com.massivecraft.factions.SpoutFeatures; public class FCommandConfig extends FBaseCommand { @@ -226,6 +227,9 @@ public class FCommandConfig extends FBaseCommand { } // save change to disk Conf.save(); + + // in case some Spout related setting was changed + SpoutFeatures.updateAppearances(); } } diff --git a/src/com/massivecraft/factions/commands/FCommandDisband.java b/src/com/massivecraft/factions/commands/FCommandDisband.java index aff357cb..29832e9d 100644 --- a/src/com/massivecraft/factions/commands/FCommandDisband.java +++ b/src/com/massivecraft/factions/commands/FCommandDisband.java @@ -2,8 +2,11 @@ package com.massivecraft.factions.commands; import org.bukkit.command.CommandSender; +import com.massivecraft.factions.Conf; import com.massivecraft.factions.Faction; import com.massivecraft.factions.Factions; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.SpoutFeatures; public class FCommandDisband extends FBaseCommand { @@ -27,12 +30,21 @@ public class FCommandDisband extends FBaseCommand { if( parameters.size() > 0) { Faction faction = Faction.findByTag(parameters.get(0)); - if( faction != null && faction.getId() > 0 ) { - sendMessage("Faction " + faction.getTag() + " got disbanded"); - Faction.delete( faction.getId() ); - } else { + if( faction == null || !faction.isNormal()) { sendMessage("Faction " + parameters.get(0) + "not found"); + return; } + + // Inform all players + for (FPlayer fplayer : FPlayer.getAllOnline()) { + if (fplayer.getFaction() == faction) { + fplayer.sendMessage(me.getNameAndRelevant(fplayer)+Conf.colorSystem+" disbanded your faction."); + } else { + fplayer.sendMessage(me.getNameAndRelevant(fplayer)+Conf.colorSystem+" disbanded the faction "+faction.getTag(fplayer)+"."); + } + } + Faction.delete( faction.getId() ); + SpoutFeatures.updateAppearances(); } } diff --git a/src/com/massivecraft/factions/commands/FCommandPeaceful.java b/src/com/massivecraft/factions/commands/FCommandPeaceful.java index 6c392cca..4e5eb66d 100644 --- a/src/com/massivecraft/factions/commands/FCommandPeaceful.java +++ b/src/com/massivecraft/factions/commands/FCommandPeaceful.java @@ -2,8 +2,11 @@ package com.massivecraft.factions.commands; import org.bukkit.command.CommandSender; +import com.massivecraft.factions.Conf; import com.massivecraft.factions.Faction; import com.massivecraft.factions.Factions; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.SpoutFeatures; public class FCommandPeaceful extends FBaseCommand { @@ -32,13 +35,24 @@ public class FCommandPeaceful extends FBaseCommand { return; } - if( faction != null && faction.isPeaceful() ) { - sendMessage("Faction \"" + parameters.get(0) + "\" peaceful designation removed"); + String change; + if(faction.isPeaceful()) { + change = "removed peaceful status from"; faction.setPeaceful(false); } else { - sendMessage("Faction \"" + faction.getTag() + "\" has been designated as peaceful"); + change = "granted peaceful status to"; faction.setPeaceful(true); } + // Inform all players + for (FPlayer fplayer : FPlayer.getAllOnline()) { + if (fplayer.getFaction() == faction) { + fplayer.sendMessage(me.getNameAndRelevant(fplayer)+Conf.colorSystem+" has "+change+" your faction."); + } else { + fplayer.sendMessage(me.getNameAndRelevant(fplayer)+Conf.colorSystem+" has "+change+" the faction \"" + faction.getTag(fplayer) + "\"."); + } + } + + SpoutFeatures.updateAppearances(faction); } } diff --git a/src/com/massivecraft/factions/commands/FCommandTag.java b/src/com/massivecraft/factions/commands/FCommandTag.java index 71c51ffd..dd372b22 100644 --- a/src/com/massivecraft/factions/commands/FCommandTag.java +++ b/src/com/massivecraft/factions/commands/FCommandTag.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import com.massivecraft.factions.Conf; import com.massivecraft.factions.Faction; +import com.massivecraft.factions.SpoutFeatures; import com.massivecraft.factions.struct.Role; import com.massivecraft.factions.util.TextUtil; @@ -66,6 +67,10 @@ public class FCommandTag extends FBaseCommand { } faction.sendMessage(Conf.colorSystem+"The faction "+me.getRelationColor(faction)+oldtag+Conf.colorSystem+" changed their name to "+myFaction.getTag(faction)); } + + if (Conf.spoutFactionTagsOverNames) { + SpoutFeatures.updateAppearances(myFaction); + } } } diff --git a/src/com/massivecraft/factions/commands/FCommandTitle.java b/src/com/massivecraft/factions/commands/FCommandTitle.java index 690a92ba..7e67b38b 100644 --- a/src/com/massivecraft/factions/commands/FCommandTitle.java +++ b/src/com/massivecraft/factions/commands/FCommandTitle.java @@ -3,6 +3,7 @@ package com.massivecraft.factions.commands; import com.massivecraft.factions.Conf; import com.massivecraft.factions.FPlayer; import com.massivecraft.factions.Faction; +import com.massivecraft.factions.SpoutFeatures; import com.massivecraft.factions.util.TextUtil; public class FCommandTitle extends FBaseCommand { @@ -51,6 +52,10 @@ public class FCommandTitle extends FBaseCommand { // Inform Faction myFaction = me.getFaction(); myFaction.sendMessage(me.getNameAndRelevant(myFaction)+Conf.colorSystem+" changed a title: "+you.getNameAndRelevant(myFaction)); + + if (Conf.spoutFactionTitlesOverNames) { + SpoutFeatures.updateAppearances(player); + } } } diff --git a/src/com/massivecraft/factions/commands/FRelationCommand.java b/src/com/massivecraft/factions/commands/FRelationCommand.java index f5c6f073..5e75ac55 100644 --- a/src/com/massivecraft/factions/commands/FRelationCommand.java +++ b/src/com/massivecraft/factions/commands/FRelationCommand.java @@ -5,6 +5,7 @@ import org.bukkit.ChatColor; import com.massivecraft.factions.Conf; import com.massivecraft.factions.Faction; import com.massivecraft.factions.Factions; +import com.massivecraft.factions.SpoutFeatures; import com.massivecraft.factions.struct.Relation; import com.massivecraft.factions.struct.Role; @@ -72,5 +73,7 @@ public class FRelationCommand extends FBaseCommand { otherFaction.sendMessage(Conf.colorSystem+"This will have no effect while their faction is peaceful."); myFaction.sendMessage(Conf.colorSystem+"This will have no effect while your faction is peaceful."); } + + SpoutFeatures.updateAppearances(myFaction, otherFaction); } } diff --git a/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java b/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java index f2b24e67..14f575bf 100644 --- a/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java +++ b/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java @@ -2,6 +2,7 @@ package com.massivecraft.factions.listeners; import java.util.logging.Logger; import java.util.Iterator; +import java.util.UnknownFormatConversionException; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -28,9 +29,11 @@ import com.massivecraft.factions.FLocation; import com.massivecraft.factions.FPlayer; import com.massivecraft.factions.Faction; import com.massivecraft.factions.Factions; +import com.massivecraft.factions.SpoutFeatures; import com.massivecraft.factions.struct.Role; import com.massivecraft.factions.struct.Relation; import com.massivecraft.factions.util.TextUtil; +import java.util.logging.Level; @@ -97,7 +100,16 @@ public class FactionsPlayerListener extends PlayerListener{ for (Player listeningPlayer : event.getRecipients()) { FPlayer you = FPlayer.get(listeningPlayer); String yourFormat = formatStart + me.getChatTag(you).trim() + formatEnd; - listeningPlayer.sendMessage(String.format(yourFormat, talkingPlayer.getDisplayName(), msg)); + try { + listeningPlayer.sendMessage(String.format(yourFormat, talkingPlayer.getDisplayName(), msg)); + } + catch (UnknownFormatConversionException ex) { + Factions.log(Level.SEVERE, "Critical error in chat message formatting! Complete format string: "+yourFormat); + Factions.log(Level.SEVERE, "First half of event.getFormat() string: "+formatStart); + Factions.log(Level.SEVERE, "Second half of event.getFormat() string: "+formatEnd); + ex.printStackTrace(); + return; + } } // Write to the log... We will write the non colored message. @@ -120,6 +132,8 @@ public class FactionsPlayerListener extends PlayerListener{ // Run the member auto kick routine. Twice to get to the admins... FPlayer.autoLeaveOnInactivityRoutine(); FPlayer.autoLeaveOnInactivityRoutine(); + + SpoutFeatures.updateAppearances(event.getPlayer()); } @Override @@ -436,6 +450,7 @@ public class FactionsPlayerListener extends PlayerListener{ while (iter.hasNext()) { cmdCheck = iter.next(); if (cmdCheck == null) { + iter.remove(); continue; } @@ -456,6 +471,7 @@ public class FactionsPlayerListener extends PlayerListener{ while (iter.hasNext()) { cmdCheck = iter.next(); if (cmdCheck == null) { + iter.remove(); continue; } diff --git a/src/com/massivecraft/factions/listeners/FactionsServerListener.java b/src/com/massivecraft/factions/listeners/FactionsServerListener.java index ed12ec62..e394d024 100644 --- a/src/com/massivecraft/factions/listeners/FactionsServerListener.java +++ b/src/com/massivecraft/factions/listeners/FactionsServerListener.java @@ -6,6 +6,7 @@ import org.bukkit.event.server.PluginDisableEvent; import org.bukkit.event.server.PluginEnableEvent; import com.massivecraft.factions.Econ; +import com.massivecraft.factions.SpoutFeatures; public class FactionsServerListener extends ServerListener { @@ -15,9 +16,12 @@ public class FactionsServerListener extends ServerListener { if (Econ.iConomyHooked() && name.equals("iConomy")) { Econ.iConomySet(false); } - if (Econ.essentialsEcoHooked() && name.equals("Essentials")) { + else if (Econ.essentialsEcoHooked() && name.equals("Essentials")) { Econ.essentialsEcoSet(false); } + else if (name.equals("Spout")) { + SpoutFeatures.setAvailable(false, ""); + } } @Override @@ -30,5 +34,8 @@ public class FactionsServerListener extends ServerListener { else if (!Econ.essentialsEcoHooked() && name.equals("Essentials")) { Econ.essentialsEcoSet(true); } + else if (name.equals("Spout")) { + SpoutFeatures.setAvailable(true, plug.getDescription().getFullName()); + } } } \ No newline at end of file diff --git a/src/plugin.yml b/src/plugin.yml index b8c3aa8b..ec376ec6 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -8,7 +8,9 @@ softdepend: - HeroChat - iChat - LocalAreaChat + - nChat - iConomy + - Spout commands: f: description: All of the Factions commands