Improve Team prefix performance

This change vastly improves performance for faction team prefix update
operations.
This commit is contained in:
eueln 2014-10-22 11:54:00 -05:00 committed by t00thpick1
parent 90e57740a2
commit 7f2ef4cbd5
5 changed files with 192 additions and 82 deletions

View File

@ -4,7 +4,7 @@ import com.massivecraft.factions.Conf;
import com.massivecraft.factions.Faction; import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions; import com.massivecraft.factions.Factions;
import com.massivecraft.factions.event.FactionRenameEvent; import com.massivecraft.factions.event.FactionRenameEvent;
import com.massivecraft.factions.scoreboards.FScoreboard; import com.massivecraft.factions.scoreboards.FTeamWrapper;
import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.struct.Permission;
import com.massivecraft.factions.util.MiscUtil; import com.massivecraft.factions.util.MiscUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -74,7 +74,7 @@ public class CmdTag extends FCommand {
faction.msg("<i>The faction %s<i> changed their name to %s.", fme.getColorTo(faction) + oldtag, myFaction.getTag(faction)); faction.msg("<i>The faction %s<i> changed their name to %s.", fme.getColorTo(faction) + oldtag, myFaction.getTag(faction));
} }
FScoreboard.applyUpdates(myFaction); FTeamWrapper.updatePrefixes(myFaction);
} }
} }

View File

@ -3,7 +3,7 @@ package com.massivecraft.factions.cmd;
import com.massivecraft.factions.Conf; import com.massivecraft.factions.Conf;
import com.massivecraft.factions.Faction; import com.massivecraft.factions.Faction;
import com.massivecraft.factions.event.FactionRelationEvent; import com.massivecraft.factions.event.FactionRelationEvent;
import com.massivecraft.factions.scoreboards.FScoreboard; import com.massivecraft.factions.scoreboards.FTeamWrapper;
import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.struct.Permission;
import com.massivecraft.factions.struct.Relation; import com.massivecraft.factions.struct.Relation;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -86,7 +86,7 @@ public abstract class FRelationCommand extends FCommand {
myFaction.msg("<i>This will have no effect while your faction is peaceful."); myFaction.msg("<i>This will have no effect while your faction is peaceful.");
} }
FScoreboard.applyUpdates(myFaction); FTeamWrapper.updatePrefixes(myFaction);
FScoreboard.applyUpdates(them); FTeamWrapper.updatePrefixes(them);
} }
} }

View File

@ -4,6 +4,7 @@ import com.massivecraft.factions.*;
import com.massivecraft.factions.event.FPlayerJoinEvent; import com.massivecraft.factions.event.FPlayerJoinEvent;
import com.massivecraft.factions.event.FPlayerLeaveEvent; import com.massivecraft.factions.event.FPlayerLeaveEvent;
import com.massivecraft.factions.scoreboards.FScoreboard; import com.massivecraft.factions.scoreboards.FScoreboard;
import com.massivecraft.factions.scoreboards.FTeamWrapper;
import com.massivecraft.factions.scoreboards.sidebar.FDefaultSidebar; import com.massivecraft.factions.scoreboards.sidebar.FDefaultSidebar;
import com.massivecraft.factions.struct.Permission; import com.massivecraft.factions.struct.Permission;
import com.massivecraft.factions.struct.Relation; import com.massivecraft.factions.struct.Relation;
@ -526,11 +527,11 @@ public class FactionsPlayerListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
final public void onFactionJoin(FPlayerJoinEvent event) { final public void onFactionJoin(FPlayerJoinEvent event) {
FScoreboard.applyUpdatesLater(event.getFaction()); FTeamWrapper.applyUpdatesLater(event.getFaction());
} }
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onFactionLeave(FPlayerLeaveEvent event) { public void onFactionLeave(FPlayerLeaveEvent event) {
FScoreboard.applyUpdatesLater(event.getFaction()); FTeamWrapper.applyUpdatesLater(event.getFaction());
} }
} }

View File

@ -1,40 +1,40 @@
package com.massivecraft.factions.scoreboards; package com.massivecraft.factions.scoreboards;
import com.massivecraft.factions.*; import com.massivecraft.factions.*;
import com.massivecraft.factions.zcore.util.TL;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scoreboard.DisplaySlot; import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
public class FScoreboard { public class FScoreboard {
private static Map<FPlayer, FScoreboard> fscoreboards = new HashMap<FPlayer, FScoreboard>(); private static final Map<FPlayer, FScoreboard> fscoreboards = new HashMap<FPlayer, FScoreboard>();
private final Scoreboard scoreboard; private final Scoreboard scoreboard;
private final FPlayer fplayer; private final FPlayer fplayer;
private final BufferedObjective bufferedObjective; private final BufferedObjective bufferedObjective;
private final Map<Faction, Team> factionTeams = new HashMap<Faction, Team>();
private int factionTeamPtr;
private FSidebarProvider defaultProvider; private FSidebarProvider defaultProvider;
private FSidebarProvider temporaryProvider; private FSidebarProvider temporaryProvider;
private boolean removed = false; private boolean removed = false;
public static void init(FPlayer fplayer) { public static void init(FPlayer fplayer) {
fscoreboards.put(fplayer, new FScoreboard(fplayer)); FScoreboard fboard = new FScoreboard(fplayer);
fscoreboards.put(fplayer, fboard);
if (fplayer.hasFaction()) { if (fplayer.hasFaction()) {
FScoreboard.applyUpdates(fplayer.getFaction()); FTeamWrapper.applyUpdates(fplayer.getFaction());
} }
FTeamWrapper.track(fboard);
} }
public static void remove(FPlayer fplayer) { public static void remove(FPlayer fplayer) {
fscoreboards.remove(fplayer).removed = true; FScoreboard fboard = fscoreboards.remove(fplayer);
fboard.removed = true;
FTeamWrapper.untrack(fboard);
} }
public static FScoreboard get(FPlayer fplayer) { public static FScoreboard get(FPlayer fplayer) {
@ -45,31 +45,20 @@ public class FScoreboard {
return fscoreboards.get(FPlayers.i.get(player)); return fscoreboards.get(FPlayers.i.get(player));
} }
public static void applyUpdatesLater(final Faction faction) {
Bukkit.getScheduler().runTask(P.p, new Runnable() {
@Override
public void run() {
applyUpdates(faction);
}
});
}
public static void applyUpdates(Faction faction) {
for (FScoreboard fscoreboard : fscoreboards.values()) {
fscoreboard.updateFactionTeam(faction);
}
}
private FScoreboard(FPlayer fplayer) { private FScoreboard(FPlayer fplayer) {
this.fplayer = fplayer; this.fplayer = fplayer;
this.scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); this.scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
this.bufferedObjective = new BufferedObjective(scoreboard); this.bufferedObjective = new BufferedObjective(scoreboard);
for (Faction faction : Factions.i.get()) { fplayer.getPlayer().setScoreboard(scoreboard);
updateFactionTeam(faction);
} }
fplayer.getPlayer().setScoreboard(scoreboard); protected FPlayer getFPlayer() {
return fplayer;
}
protected Scoreboard getScoreboard() {
return scoreboard;
} }
public void setSidebarVisibility(boolean visible) { public void setSidebarVisibility(boolean visible) {
@ -128,50 +117,4 @@ public class FScoreboard {
bufferedObjective.flip(); bufferedObjective.flip();
} }
} }
public void updateFactionTeam(Faction faction) {
Team team = factionTeams.get(faction);
Set<FPlayer> factionMembers = faction.getFPlayers();
if (!Factions.i.get().contains(faction)) {
// Faction was disbanded
if (team != null) {
factionTeams.remove(faction);
team.unregister();
}
return;
}
if (team == null) {
team = scoreboard.registerNewTeam("faction_" + (factionTeamPtr++));
factionTeams.put(faction, team);
}
for (OfflinePlayer player : team.getPlayers()) {
if (!player.isOnline() || !factionMembers.contains(FPlayers.i.get(player.getPlayer()))) {
// Player is offline or no longer in faction
team.removePlayer(player);
}
}
for (FPlayer fmember : factionMembers) {
if (!fmember.isOnline()) {
continue;
}
if (!team.hasPlayer(fmember.getPlayer())) {
// Scoreboard team doesn't have player; add him/her
team.addPlayer(fmember.getPlayer());
}
}
// Update faction prefix
if(P.p.getConfig().getBoolean("scoreboard.default-prefixes", false)) {
String prefix = TL.DEFAULT_PREFIX.toString();
prefix = prefix.replace("{relationcolor}", faction.getRelationTo(this.fplayer).getColor().toString());
prefix = prefix.replace("{faction}", faction.getTag().substring(0, Math.min("{faction}".length() + 16 - prefix.length(), faction.getTag().length())));
if (team.getPrefix() == null || !team.getPrefix().equals(prefix)) {
team.setPrefix(prefix);
}
}
}
} }

View File

@ -0,0 +1,166 @@
package com.massivecraft.factions.scoreboards;
import com.massivecraft.factions.*;
import com.massivecraft.factions.zcore.util.TL;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team;
import java.util.*;
public class FTeamWrapper {
private static final Map<Faction, FTeamWrapper> wrappers = new HashMap<Faction, FTeamWrapper>();
private static final List<FScoreboard> tracking = new ArrayList<FScoreboard>();
private static int factionTeamPtr;
private final Map<FScoreboard, Team> teams = new HashMap<FScoreboard, Team>();
private final String teamName;
private final Faction faction;
private final Set<UUID> members = new HashSet<UUID>();
public static void applyUpdatesLater(final Faction faction) {
Bukkit.getScheduler().runTask(P.p, new Runnable() {
@Override
public void run() {
applyUpdates(faction);
}
});
}
public static void applyUpdates(Faction faction) {
FTeamWrapper wrapper = wrappers.get(faction);
Set<FPlayer> factionMembers = faction.getFPlayers();
if (wrapper != null && !Factions.i.get().contains(faction)) {
// Faction was disbanded
wrapper.unregister();
wrappers.remove(faction);
return;
}
if (wrapper == null) {
wrapper = new FTeamWrapper(faction);
wrappers.put(faction, wrapper);
}
for (OfflinePlayer player : wrapper.getPlayers()) {
if (!player.isOnline() || !factionMembers.contains(FPlayers.i.get(player))) {
// Player is offline or no longer in faction
wrapper.removePlayer(player);
}
}
for (FPlayer fmember : factionMembers) {
if (!fmember.isOnline()) {
continue;
}
// Scoreboard might not have player; add him/her
wrapper.addPlayer(fmember.getPlayer());
}
wrapper.updatePrefixes();
}
public static void updatePrefixes(Faction faction) {
wrappers.get(faction).updatePrefixes();
}
protected static void track(FScoreboard fboard) {
tracking.add(fboard);
for (FTeamWrapper wrapper : wrappers.values()) {
wrapper.add(fboard);
}
}
protected static void untrack(FScoreboard fboard) {
tracking.remove(fboard);
for (FTeamWrapper wrapper : wrappers.values()) {
wrapper.remove(fboard);
}
}
private FTeamWrapper(Faction faction) {
this.teamName = "faction_" + (factionTeamPtr++);
this.faction = faction;
for (FScoreboard fboard : tracking) {
add(fboard);
}
}
private void add(FScoreboard fboard) {
Scoreboard board = fboard.getScoreboard();
Team team = board.registerNewTeam(teamName);
teams.put(fboard, team);
for (OfflinePlayer player : getPlayers()) {
team.addPlayer(player);
}
updatePrefix(fboard);
}
private void remove(FScoreboard fboard) {
teams.remove(fboard).unregister();
}
private void updatePrefixes() {
if (P.p.getConfig().getBoolean("scoreboard.default-prefixes", false)) {
for (FScoreboard fboard : teams.keySet()) {
updatePrefix(fboard);
}
}
}
private void updatePrefix(FScoreboard fboard) {
if (P.p.getConfig().getBoolean("scoreboard.default-prefixes", false)) {
for (Map.Entry<FScoreboard, Team> entry : teams.entrySet()) {
FPlayer fplayer = entry.getKey().getFPlayer();
Team team = entry.getValue();
String prefix = TL.DEFAULT_PREFIX.toString();
prefix = prefix.replace("{relationcolor}", faction.getRelationTo(fplayer).getColor().toString());
prefix = prefix.replace("{faction}", faction.getTag().substring(0, Math.min("{faction}".length() + 16 - prefix.length(), faction.getTag().length())));
if (team.getPrefix() == null || !team.getPrefix().equals(prefix)) {
team.setPrefix(prefix);
}
}
}
}
private void addPlayer(OfflinePlayer player) {
if (members.add(player.getUniqueId())) {
for (Team team : teams.values()) {
team.addPlayer(player);
}
}
}
private void removePlayer(OfflinePlayer player) {
if (members.remove(player.getUniqueId())) {
for (Team team : teams.values()) {
team.removePlayer(player);
}
}
}
private Set<OfflinePlayer> getPlayers() {
Set<OfflinePlayer> ret = new HashSet<OfflinePlayer>();
for (UUID uuid : members) {
ret.add(Bukkit.getOfflinePlayer(uuid));
}
return ret;
}
private void unregister() {
for (Team team : teams.values()) {
team.unregister();
}
teams.clear();
}
}