From 00fb9c1d7e43c9dc1ab270a2adfd281c3e06b0f4 Mon Sep 17 00:00:00 2001 From: allenlol <1124796703@qq.com> Date: Fri, 24 Aug 2018 17:13:11 -0700 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=20ScoreboardAPI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 支持 1.7-1.8 + 48字符串支持 --- .../taboolib/scoreboard/SimpleScoreboard.java | 251 ++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 src/main/java/me/skymc/taboolib/scoreboard/SimpleScoreboard.java diff --git a/src/main/java/me/skymc/taboolib/scoreboard/SimpleScoreboard.java b/src/main/java/me/skymc/taboolib/scoreboard/SimpleScoreboard.java new file mode 100644 index 0000000..c1f4c7c --- /dev/null +++ b/src/main/java/me/skymc/taboolib/scoreboard/SimpleScoreboard.java @@ -0,0 +1,251 @@ +package me.skymc.taboolib.scoreboard; + +import com.google.common.base.Charsets; +import com.google.common.base.Splitter; + +import com.google.common.collect.Lists; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.*; + +import java.lang.reflect.Constructor; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + + +public class SimpleScoreboard { + + private static Map cache = new HashMap<>(); + + private Scoreboard scoreboard; + private String title; + private Map scores; + private Objective obj; + private List teams; + private List removed; + private Set updated; + + public SimpleScoreboard(String title) { + this.scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); + this.title = ChatColor.translateAlternateColorCodes('&', title); + this.scores = new ConcurrentHashMap<>(); + this.teams = Collections.synchronizedList(Lists.newArrayList()); + this.removed = Lists.newArrayList(); + this.updated = Collections.synchronizedSet(new HashSet<>()); + } + + public void add(String text, Integer score) { + text = ChatColor.translateAlternateColorCodes('&', text); + + if (remove(score, text, false) || !scores.containsValue(score)) { + updated.add(text); + } + + scores.put(text, score); + } + + public boolean remove(Integer score, String text) { + return remove(score, text, true); + } + + public boolean remove(Integer score, String n, boolean b) { + String toRemove = get(score, n); + + if (toRemove == null) + return false; + + scores.remove(toRemove); + + if(b) + removed.add(score); + + return true; + } + + public String get(int score, String n) { + String str = null; + + for (Map.Entry entry : scores.entrySet()) { + if (entry.getValue().equals(score) && + !entry.getKey().equals(n)) { + str = entry.getKey(); + } + } + + return str; + } + + private Map.Entry createTeam(String text, int pos) { + Team team; + ChatColor color = ChatColor.values()[pos]; + OfflinePlayer result; + + if (!cache.containsKey(color.toString())) + cache.put(color.toString(), getOfflinePlayerSkipLookup(color.toString())); + + result = cache.get(color.toString()); + + try { + team = scoreboard.registerNewTeam("text-" + (teams.size() + 1)); + } catch (IllegalArgumentException e) { + team = scoreboard.getTeam("text-" + (teams.size())); + } + + applyText(team, text, result); + + teams.add(team); + return new AbstractMap.SimpleEntry<>(team, result); + } + + private void applyText(Team team, String text, OfflinePlayer result) { + Iterator iterator = Splitter.fixedLength(16).split(text).iterator(); + String prefix = iterator.next(); + + team.setPrefix(prefix); + + if(!team.hasPlayer(result)) + team.addPlayer(result); + + if (text.length() > 16) { + String prefixColor = ChatColor.getLastColors(prefix); + String suffix = iterator.next(); + + if (prefix.endsWith(String.valueOf(ChatColor.COLOR_CHAR))) { + prefix = prefix.substring(0, prefix.length() - 1); + team.setPrefix(prefix); + prefixColor = ChatColor.getByChar(suffix.charAt(0)).toString(); + suffix = suffix.substring(1); + } + + if (prefixColor == null) + prefixColor = ""; + + if (suffix.length() > 16) { + suffix = suffix.substring(0, (13 - prefixColor.length())); // cut off suffix, done if text is over 30 characters + } + + team.setSuffix((prefixColor.equals("") ? ChatColor.RESET : prefixColor) + suffix); + } + } + + public void update() { + if (updated.isEmpty()) { + return; + } + + if (obj == null) { + obj = scoreboard.registerNewObjective((title.length() > 16 ? title.substring(0, 15) : title), "dummy"); + obj.setDisplayName(title); + obj.setDisplaySlot(DisplaySlot.SIDEBAR); + } + + removed.stream().forEach((remove) -> { + for (String s : scoreboard.getEntries()) { + Score score = obj.getScore(s); + + if (score == null) + continue; + + if (score.getScore() != remove) + continue; + + scoreboard.resetScores(s); + } + }); + + removed.clear(); + + int index = scores.size(); + + for (Map.Entry text : scores.entrySet()) { + Team t = scoreboard.getTeam(ChatColor.values()[text.getValue()].toString()); + Map.Entry team; + + if(!updated.contains(text.getKey())) { + continue; + } + + if(t != null) { + String color = ChatColor.values()[text.getValue()].toString(); + + if (!cache.containsKey(color)) { + cache.put(color, getOfflinePlayerSkipLookup(color)); + } + + team = new AbstractMap.SimpleEntry<>(t, cache.get(color)); + applyText(team.getKey(), text.getKey(), team.getValue()); + index -= 1; + + continue; + } else { + team = createTeam(text.getKey(), text.getValue()); + } + + Integer score = text.getValue() != null ? text.getValue() : index; + + obj.getScore(team.getValue()).setScore(score); + index -= 1; + } + + updated.clear(); + } + + public void setTitle(String title) { + this.title = ChatColor.translateAlternateColorCodes('&', title); + + if(obj != null) + obj.setDisplayName(this.title); + } + + public void reset() { + for (Team t : teams) + t.unregister(); + teams.clear(); + scores.clear(); + } + + public Scoreboard getScoreboard() { + return scoreboard; + } + + public void send(Player... players) { + for (Player p : players) + p.setScoreboard(scoreboard); + } + + private final UUID invalidUserUUID = UUID.nameUUIDFromBytes("InvalidUsername".getBytes(Charsets.UTF_8)); + private Class gameProfileClass; + private Constructor gameProfileConstructor; + private Constructor craftOfflinePlayerConstructor; + + @SuppressWarnings("deprecation") + private OfflinePlayer getOfflinePlayerSkipLookup(String name) { + try { + if (gameProfileConstructor == null) { + try { // 1.7 + gameProfileClass = Class.forName("net.minecraft.util.com.mojang.authlib.GameProfile"); + } catch (ClassNotFoundException e) { // 1.8 + gameProfileClass = Class.forName("com.mojang.authlib.GameProfile"); + } + gameProfileConstructor = gameProfileClass.getDeclaredConstructor(UUID.class, String.class); + gameProfileConstructor.setAccessible(true); + } + if (craftOfflinePlayerConstructor == null) { + Class serverClass = Bukkit.getServer().getClass(); + Class craftOfflinePlayerClass = Class.forName(serverClass.getName() + .replace("CraftServer", "CraftOfflinePlayer")); + craftOfflinePlayerConstructor = craftOfflinePlayerClass.getDeclaredConstructor( + serverClass, gameProfileClass + ); + craftOfflinePlayerConstructor.setAccessible(true); + } + Object gameProfile = gameProfileConstructor.newInstance(invalidUserUUID, name); + Object craftOfflinePlayer = craftOfflinePlayerConstructor.newInstance(Bukkit.getServer(), gameProfile); + return (OfflinePlayer) craftOfflinePlayer; + } catch (Throwable t) { // Fallback if fail + return Bukkit.getOfflinePlayer(name); + } + } +}