-
-
Save mkotb/d99eccdcc78a43ffb707 to your computer and use it in GitHub Desktop.
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<String, OfflinePlayer> cache = new HashMap<>(); | |
private Scoreboard scoreboard; | |
private String title; | |
private Map<String, Integer> scores; | |
private Objective obj; | |
private List<Team> teams; | |
private List<Integer> removed; | |
private Set<String> 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<String, Integer> entry : scores.entrySet()) { | |
if (entry.getValue().equals(score) && | |
!entry.getKey().equals(n)) { | |
str = entry.getKey(); | |
} | |
} | |
return str; | |
} | |
private Map.Entry<Team, OfflinePlayer> 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<String> 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<String, Integer> text : scores.entrySet()) { | |
Team t = scoreboard.getTeam(ChatColor.values()[text.getValue()].toString()); | |
Map.Entry<Team, OfflinePlayer> 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); | |
} | |
} | |
} |
you suck ducks
ok
It doesn't work on Java 7.
Amazing class! Thank you.
Small bug: Line 195 should read "obj.setDisplayName(this.title);"
@M44rtenz Java 7 doesn't have streams. Idek why you're using Java 7, that's outdated now.
Mine is still flickering 1.8 - 1.9 Any fixes? The community needs this.
This is how I am making my scoreboard and it flickers:
`public void hubScoreboard(Player p) {
new BukkitRunnable() {
final ColorScrollPlus cs = new ColorScrollPlus(ChatColor.WHITE, "VenomSurge", "§a", "§f", "§a", true, false,
ScrollType.FORWARD);
ScoreboardAPI scoreboard;
public void run() {
if (cs.getScrollType() == ScrollType.FORWARD) {
if (cs.getPosition() >= cs.getString().length()) {
cs.setScrollType(ScrollType.BACKWARD);
}
} else {
if (cs.getPosition() <= -1) {
cs.setScrollType(ScrollType.FORWARD);
}
}
scoreboard = new ScoreboardAPI(cs.next());
scoreboard.add(C.dgray + C.bold + C.strike + "---------------", 7);
if (plugin.permPlug.getRank(p).equals(RankType.OWNER)) {
scoreboard.add(C.white + "Rank: " + RankUtil.Owner, 6);
} else if (plugin.permPlug.getRank(p).equals(RankType.ADMIN)) {
scoreboard.add(C.white + "Rank: " + RankUtil.Admin, 6);
} else if (plugin.permPlug.getRank(p).equals(RankType.MOD)) {
scoreboard.add(C.white + "Rank: " + RankUtil.Mod, 6);
} else if (plugin.permPlug.getRank(p).equals(RankType.HELPER)) {
scoreboard.add(C.white + "Rank: " + RankUtil.Helper, 6);
} else if (plugin.permPlug.getRank(p).equals(RankType.MEMBER)) {
scoreboard.add(C.white + "Rank: " + C.yellow + C.bold + "MEMBER", 6);
}
scoreboard.add(C.white + "Votes: " + C.green + "0", 5);
scoreboard.add(" ", 4);
scoreboard.add(C.white + "Lobby: " + C.green + "#1", 3);
scoreboard.add(C.white + "Online: " + C.green + Bukkit.getOnlinePlayers().size(), 2);
scoreboard.add(C.dgray + C.bold + C.strike + "---------------", 1);
scoreboard.update();
scoreboard.send(p);
}
}.runTaskTimer(plugin, 0, 3);
}`
It doesn't work for multiple players, right? (I mean if someone has e.g. 200 Coins and then the scoreboard updates for a player with 500 coins, player 1 & 2 have 500 coins in the scoreboard)
I'm not getting update:
@eventhandler
public void wow(PlayerJoinEvent e) {
SimpleScoreboard ss = new SimpleScoreboard("WoW");
ss.add("Money: "+ a, 13);
ss.update();
ss.send(e.getPlayer());
new BukkitRunnable() {
@Override
public void run() {
a = new Random().nextInt(900);
ss.update();
for (Player p : Bukkit.getServer().getOnlinePlayers()) {
ss.update();
ss.send(p);
}
}
}.runTaskTimerAsynchronously(this, 20, 10);
It works perfect on 1.8, thanks a lot 👍
I just wrote some new code in it ;)
Anyway I can get this to work for 1.7 with 40 lines I'm guessing using suffix and prefix?
nice credit 😢