Compare commits

1 Commits
Author SHA1 Message Date
Dawson dc99c375f6 Updated for 1.19 2025-06-10 09:38:21 -04:00
3 changed files with 60 additions and 307 deletions

No files matched your search

+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>me.tigerhix.lib</groupId>
<artifactId>scoreboard</artifactId>
<version>1.0.1-SNAPSHOT</version>
<version>1.1.0-SNAPSHOT</version>
<packaging>jar</packaging>
@@ -1,22 +1,23 @@
package me.tigerhix.lib.scoreboard.type;
import me.tigerhix.lib.scoreboard.common.Strings;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
public class Entry {
private String name;
private TextComponent name;
private int position;
public Entry(String name, int position) {
this.name = Strings.format(name);
this.name = LegacyComponentSerializer.legacySection().deserialize(name);
this.position = position;
}
public String getName() {
public TextComponent getName() {
return name;
}
public void setName(String name) {
public void setName(TextComponent name) {
this.name = name;
}
@@ -1,31 +1,22 @@
package me.tigerhix.lib.scoreboard.type;
import com.destroystokyo.paper.profile.PlayerProfile;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import me.tigerhix.lib.scoreboard.ScoreboardLib;
import me.tigerhix.lib.scoreboard.common.Strings;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.*;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.Team;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class SimpleScoreboard implements Scoreboard {
private static final String TEAM_PREFIX = "Scoreboard_";
private static int TEAM_COUNTER = 0;
private final org.bukkit.scoreboard.Scoreboard scoreboard;
private final Objective objective;
@@ -34,9 +25,8 @@ public class SimpleScoreboard implements Scoreboard {
private boolean activated;
private ScoreboardHandler handler;
private Map<FakePlayer, Integer> entryCache = new ConcurrentHashMap<>();
private Table<String, Integer, FakePlayer> playerCache = HashBasedTable.create();
private Table<Team, String, String> teamCache = HashBasedTable.create();
// We use a map to track teams by line number for easy updating.
private final Map<Integer, Team> teams = new HashMap<>();
private BukkitRunnable updateTask;
public SimpleScoreboard(Player holder) {
@@ -75,7 +65,7 @@ public class SimpleScoreboard implements Scoreboard {
}
}
// Unregister teams that are created for this scoreboard
for (Team team : teamCache.rowKeySet()) {
for (Team team : teams.values()) {
team.unregister();
}
// Stop updating
@@ -127,88 +117,15 @@ public class SimpleScoreboard implements Scoreboard {
if (!objective.getDisplayName().equals(finalTitle)) objective.setDisplayName(Strings.format(finalTitle));
// Entries
List<Entry> passed = handler.getEntries(holder);
Map<String, Integer> appeared = new HashMap<>();
Map<FakePlayer, Integer> current = new HashMap<>();
if (passed == null) return;
for (Entry entry : passed) {
// Handle the entry
String key = entry.getName();
Integer score = entry.getPosition();
if (key.length() > 48) key = key.substring(0, 47);
String appearance;
if (key.length() > 16) {
appearance = key.substring(16);
} else {
appearance = key;
}
if (!appeared.containsKey(appearance)) appeared.put(appearance, -1);
appeared.put(appearance, appeared.get(appearance) + 1);
// Get fake player
FakePlayer faker = getFakePlayer(key, appeared.get(appearance));
// Set score
objective.getScore(faker).setScore(score);
// Update references
entryCache.put(faker, score);
current.put(faker, score);
}
appeared.clear();
// Remove duplicated or non-existent entries
for (FakePlayer fakePlayer : entryCache.keySet()) {
if (!current.containsKey(fakePlayer)) {
entryCache.remove(fakePlayer);
scoreboard.resetScores(fakePlayer.getName());
}
}
}
TextComponent key = entry.getName();
int score = entry.getPosition();
@SuppressWarnings("deprecation")
private FakePlayer getFakePlayer(String text, int offset) {
Team team = null;
String name;
// If the text has a length less than 16, teams need not to be be created
if (text.length() <= 16) {
name = text + Strings.repeat(" ", offset);
} else {
String prefix;
String suffix = "";
offset++;
// Otherwise, iterate through the string and cut off prefix and suffix
prefix = text.substring(0, 16 - offset);
name = text.substring(16 - offset);
if (name.length() > 16) name = name.substring(0, 16);
if (text.length() > 32) suffix = text.substring(32 - offset);
// If teams already exist, use them
for (Team other : teamCache.rowKeySet()) {
if (other.getPrefix().equals(prefix) && other.getSuffix().equals(suffix)) {
team = other;
}
}
// Otherwise create them
if (team == null) {
team = scoreboard.registerNewTeam(TEAM_PREFIX + TEAM_COUNTER++);
team.setPrefix(prefix);
team.setSuffix(suffix);
teamCache.put(team, prefix, suffix);
}
setLine(score, key);
// Update references
}
FakePlayer faker;
if (!playerCache.contains(name, offset)) {
faker = new FakePlayer(name, team, offset);
playerCache.put(name, offset, faker);
if (faker.getTeam() != null) {
faker.getTeam().addPlayer(faker);
}
} else {
faker = playerCache.get(name, offset);
if (team != null && faker.getTeam() != null) {
faker.getTeam().removePlayer(faker);
}
faker.setTeam(team);
if (faker.getTeam() != null) {
faker.getTeam().addPlayer(faker);
}
}
return faker;
}
public Objective getObjective() {
@@ -219,223 +136,58 @@ public class SimpleScoreboard implements Scoreboard {
return scoreboard;
}
private static class FakePlayer implements OfflinePlayer {
private final String name;
/**
* Sets the title of the scoreboard.
* @param title The new title (supports ChatColor).
*/
public void setTitle(String title) {
this.objective.setDisplayName(title);
}
private Team team;
private int offset;
/**
* Sets a specific line on the scoreboard to a rich TextComponent.
* @param line The line number (from top to bottom, 15 is highest).
* @param component The BaseComponent (e.g., TextComponent) to display.
*/
public void setLine(int line, Component component) {
Team team = getTeamForLine(line);
FakePlayer(String name, Team team, int offset) {
this.name = name;
this.team = team;
this.offset = offset;
// In 1.13+ we can set the prefix/suffix directly with components.
team.prefix(component);
// Set the score to show this line.
objective.getScore(getEntryForLine(line)).setScore(line);
}
/**
* Retrieves or creates a team for a given line number.
* Teams are used to hold the prefix, which is our component content.
*/
private Team getTeamForLine(int line) {
if (teams.containsKey(line)) {
return teams.get(line);
}
public Team getTeam() {
return team;
}
// Team name must be unique. Line number is a good candidate.
Team team = scoreboard.registerNewTeam("line" + line);
public void setTeam(Team team) {
this.team = team;
}
// Each team needs a unique entry to display. We use ChatColor codes.
// This entry is what gets the score, but it will be invisible.
String entry = getEntryForLine(line);
team.addEntry(entry);
public int getOffset() {
return offset;
}
public String getFullName() {
if (team == null) return name;
if (team.getSuffix() == null) return team.getPrefix() + name;
return team.getPrefix() + name + team.getSuffix();
}
@Override
public boolean isOnline() {
return true;
}
@Override
public String getName() {
return name;
}
@Override
public UUID getUniqueId() {
return UUID.randomUUID();
}
@Override
public @NotNull PlayerProfile getPlayerProfile() {
return null;
}
@Override
public boolean isBanned() {
return false;
}
@Override
public boolean isWhitelisted() {
return false;
}
@Override
public void setWhitelisted(boolean whitelisted) {
}
@Override
public Player getPlayer() {
return null;
}
@Override
public long getFirstPlayed() {
return 0;
}
@Override
public long getLastPlayed() {
return 0;
}
@Override
public boolean hasPlayedBefore() {
return false;
}
@Override
public Location getBedSpawnLocation() {
return null;
}
@Override
public long getLastLogin() {
return 0;
}
@Override
public long getLastSeen() {
return 0;
}
@Override
public void incrementStatistic(@NotNull Statistic statistic) throws IllegalArgumentException {
}
@Override
public void decrementStatistic(@NotNull Statistic statistic) throws IllegalArgumentException {
}
@Override
public void incrementStatistic(@NotNull Statistic statistic, int i) throws IllegalArgumentException {
}
@Override
public void decrementStatistic(@NotNull Statistic statistic, int i) throws IllegalArgumentException {
}
@Override
public void setStatistic(@NotNull Statistic statistic, int i) throws IllegalArgumentException {
}
@Override
public int getStatistic(@NotNull Statistic statistic) throws IllegalArgumentException {
return 0;
}
@Override
public void incrementStatistic(@NotNull Statistic statistic, @NotNull Material material) throws IllegalArgumentException {
}
@Override
public void decrementStatistic(@NotNull Statistic statistic, @NotNull Material material) throws IllegalArgumentException {
}
@Override
public int getStatistic(@NotNull Statistic statistic, @NotNull Material material) throws IllegalArgumentException {
return 0;
}
@Override
public void incrementStatistic(@NotNull Statistic statistic, @NotNull Material material, int i) throws IllegalArgumentException {
}
@Override
public void decrementStatistic(@NotNull Statistic statistic, @NotNull Material material, int i) throws IllegalArgumentException {
}
@Override
public void setStatistic(@NotNull Statistic statistic, @NotNull Material material, int i) throws IllegalArgumentException {
}
@Override
public void incrementStatistic(@NotNull Statistic statistic, @NotNull EntityType entityType) throws IllegalArgumentException {
}
@Override
public void decrementStatistic(@NotNull Statistic statistic, @NotNull EntityType entityType) throws IllegalArgumentException {
}
@Override
public int getStatistic(@NotNull Statistic statistic, @NotNull EntityType entityType) throws IllegalArgumentException {
return 0;
}
@Override
public void incrementStatistic(@NotNull Statistic statistic, @NotNull EntityType entityType, int i) throws IllegalArgumentException {
}
@Override
public void decrementStatistic(@NotNull Statistic statistic, @NotNull EntityType entityType, int i) {
}
@Override
public void setStatistic(@NotNull Statistic statistic, @NotNull EntityType entityType, int i) {
}
@Override
public @Nullable Location getLastDeathLocation() {
return null;
}
@Override
public Map<String, Object> serialize() {
return null;
}
@Override
public boolean isOp() {
return false;
}
@Override
public void setOp(boolean op) {
}
@Override
public String toString() {
return "FakePlayer{" +
"name='" + name + '\'' +
", team=" + team
+ '}';
}
teams.put(line, team);
return team;
}
/**
* Gets the unique, invisible entry name for a given line.
* We use ChatColor codes to make them unique and not display in chat.
*/
private String getEntryForLine(int line) {
return ChatColor.values()[line].toString() + ChatColor.RESET;
}
}