diff --git a/src/com/massivecraft/factions/Conf.java b/src/com/massivecraft/factions/Conf.java index 9e1fcc3a..e142fd84 100644 --- a/src/com/massivecraft/factions/Conf.java +++ b/src/com/massivecraft/factions/Conf.java @@ -170,6 +170,16 @@ public class Conf // Spout features public static boolean spoutFactionTagsOverNames = true; // show faction tags over names over player heads public static boolean spoutFactionTitlesOverNames = true; // whether to include player's title in that + public static boolean spoutHealthBarUnderNames = true; // Show healthbar under player names. + public static String spoutHealthBarLeft = "{c}["; + public static String spoutHealthBarSolid = "|"; + public static String spoutHealthBarBetween = "&8"; + public static String spoutHealthBarEmpty = "|"; + public static String spoutHealthBarRight = "{c}]"; + public static double spoutHealthBarSolidsPerEmpty = 1d; + public static String spoutHealthBarColorTag = "{c}"; + public static int spoutHealthBarWidth = 30; + public static Map spoutHealthBarColorUnderQuota = new LinkedHashMap(); public static boolean spoutFactionLeaderCapes = true; // Show capes on faction admins, colored based on the viewer's relation to the target player public static boolean spoutFactionOfficerCapes = true; // same, but for faction moderators public static int spoutTerritoryDisplayPosition = 3; // permanent territory display, instead of by chat; 0 = disabled, 1 = top left, 2 = top center, 3+ = top right @@ -296,6 +306,13 @@ public class Conf monsters.add(EntityType.SLIME); monsters.add(EntityType.SPIDER); monsters.add(EntityType.ZOMBIE); + + spoutHealthBarColorUnderQuota.put(1.0d, "&2"); + spoutHealthBarColorUnderQuota.put(0.8d, "&a"); + spoutHealthBarColorUnderQuota.put(0.5d, "&e"); + spoutHealthBarColorUnderQuota.put(0.4d, "&6"); + spoutHealthBarColorUnderQuota.put(0.3d, "&c"); + spoutHealthBarColorUnderQuota.put(0.2d, "&4"); } // -------------------------------------------- // diff --git a/src/com/massivecraft/factions/integration/SpoutFeatures.java b/src/com/massivecraft/factions/integration/SpoutFeatures.java index 5444b8e8..4359dfe9 100644 --- a/src/com/massivecraft/factions/integration/SpoutFeatures.java +++ b/src/com/massivecraft/factions/integration/SpoutFeatures.java @@ -15,6 +15,7 @@ import org.bukkit.plugin.Plugin; import org.bukkit.entity.Player; import com.massivecraft.factions.struct.Rel; +import com.massivecraft.factions.util.HealthBarUtil; import org.getspout.spoutapi.gui.Color; import org.getspout.spoutapi.player.SpoutPlayer; @@ -131,6 +132,20 @@ public class SpoutFeatures updateSingle(playerA, playerB); } } + + // update how this player looks in the eyes of all other players + public static void updateMyAppearance(Player player) + { + if (!enabled() || player == null) return; + + Set players = FPlayers.i.getOnline(); + FPlayer playerA = FPlayers.i.get(player); + + for (FPlayer playerB : players) + { + updateSingle(playerB, playerA); + } + } // as above method, but with a delay added; useful for after-login update which doesn't always propagate if done immediately public static void updateAppearancesShortly(final Player player) @@ -207,24 +222,34 @@ public class SpoutFeatures String viewedTitle = viewed.getTitle(); Rel viewedRole = viewed.getRole(); - if ((Conf.spoutFactionTagsOverNames || Conf.spoutFactionTitlesOverNames) && viewer != viewed) + if ((Conf.spoutFactionTagsOverNames || Conf.spoutFactionTitlesOverNames || Conf.spoutHealthBarUnderNames) && viewer != viewed) { + String title = pViewed.getDisplayName(); + if (viewedFaction.isNormal()) { String addTag = ""; if (Conf.spoutFactionTagsOverNames) + { addTag += viewedFaction.getTag(viewed.getColorTo(viewer).toString() + "[") + "]"; - + } + String rolePrefix = viewedRole.getPrefix(); if (Conf.spoutFactionTitlesOverNames && (!viewedTitle.isEmpty() || !rolePrefix.isEmpty())) + { addTag += (addTag.isEmpty() ? "" : " ") + viewedRole.getPrefix() + viewedTitle; + } - pViewed.setTitleFor(pViewer, addTag + "\n" + pViewed.getDisplayName()); + title = addTag + "\n" + title; } - else + + if (Conf.spoutHealthBarUnderNames) { - pViewed.setTitleFor(pViewer, pViewed.getDisplayName()); + title += "\n"; + title += HealthBarUtil.getHealthbar(pViewed.getHealth() / 20d); } + + pViewed.setTitleFor(pViewer, title); } if diff --git a/src/com/massivecraft/factions/listeners/FactionsEntityListener.java b/src/com/massivecraft/factions/listeners/FactionsEntityListener.java index 4ddb8156..cf095cb4 100644 --- a/src/com/massivecraft/factions/listeners/FactionsEntityListener.java +++ b/src/com/massivecraft/factions/listeners/FactionsEntityListener.java @@ -26,6 +26,7 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntityRegainHealthEvent; import org.bukkit.event.entity.EntityTargetEvent; import org.bukkit.event.entity.PotionSplashEvent; import org.bukkit.event.painting.PaintingBreakByEntityEvent; @@ -41,6 +42,7 @@ import com.massivecraft.factions.FPlayer; import com.massivecraft.factions.FPlayers; import com.massivecraft.factions.Faction; import com.massivecraft.factions.P; +import com.massivecraft.factions.integration.SpoutFeatures; import com.massivecraft.factions.struct.FFlag; import com.massivecraft.factions.struct.Rel; import com.massivecraft.factions.util.MiscUtil; @@ -405,4 +407,30 @@ public class FactionsEntityListener implements Listener event.setCancelled(true); } + + // -------------------------------------------- // + // HEALTH BAR + // -------------------------------------------- // + + @EventHandler(priority = EventPriority.MONITOR) + public void monitorEntityDamageEvent(EntityDamageEvent event) + { + if (event.isCancelled()) return; + if ( ! Conf.spoutHealthBarUnderNames) return; + Entity entity = event.getEntity(); + if ( ! (entity instanceof Player)) return; + Player player = (Player)entity; + SpoutFeatures.updateMyAppearance(player); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void monitorEntityRegainHealthEvent(EntityRegainHealthEvent event) + { + if (event.isCancelled()) return; + if ( ! Conf.spoutHealthBarUnderNames) return; + Entity entity = event.getEntity(); + if ( ! (entity instanceof Player)) return; + Player player = (Player)entity; + SpoutFeatures.updateMyAppearance(player); + } } diff --git a/src/com/massivecraft/factions/util/HealthBarUtil.java b/src/com/massivecraft/factions/util/HealthBarUtil.java new file mode 100644 index 00000000..0a6b2c95 --- /dev/null +++ b/src/com/massivecraft/factions/util/HealthBarUtil.java @@ -0,0 +1,70 @@ +package com.massivecraft.factions.util; + +import java.util.Map.Entry; + +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.zcore.util.TextUtil; + +public class HealthBarUtil +{ + public static String getHealthbar(double healthQuota, int barLength) + { + // Ensure between 0 and 1; + healthQuota = fixQuota(healthQuota); + + // What color is the health bar? + String color = getColorFromHealthQuota(healthQuota); + + // how much solid should there be? + int solidCount = (int) Math.ceil(barLength * healthQuota); + + // The rest is empty + int emptyCount = (int) ((barLength - solidCount) / Conf.spoutHealthBarSolidsPerEmpty); + + // Create the non-parsed bar + String ret = Conf.spoutHealthBarLeft + TextUtil.repeat(Conf.spoutHealthBarSolid, solidCount) + Conf.spoutHealthBarBetween + TextUtil.repeat(Conf.spoutHealthBarEmpty, emptyCount) + Conf.spoutHealthBarRight; + + // Replace color tag + ret = ret.replace("{c}", color); + + // Parse amp color codes + ret = TextUtil.parseColorAmp(ret); + + return ret; + } + + public static String getHealthbar(double healthQuota) + { + return getHealthbar(healthQuota, Conf.spoutHealthBarWidth); + } + + public static double fixQuota(double healthQuota) + { + if (healthQuota > 1) + { + return 1d; + } + else if (healthQuota < 0) + { + return 0d; + } + return healthQuota; + } + + public static String getColorFromHealthQuota(double healthQuota) + { + Double currentRoof = null; + String ret = null; + for (Entry entry : Conf.spoutHealthBarColorUnderQuota.entrySet()) + { + double roof = entry.getKey(); + String color = entry.getValue(); + if (healthQuota <= roof && (currentRoof == null || roof <= currentRoof)) + { + currentRoof = roof; + ret = color; + } + } + return ret; + } +} \ No newline at end of file