Upload folder via GUI - src

This commit is contained in:
Git Manager GUI
2026-05-10 23:12:09 +02:00
parent 6694c40842
commit 87274ffc9c
3 changed files with 223 additions and 75 deletions

View File

@@ -801,6 +801,32 @@ public class StatusAPI extends Plugin implements Runnable {
return; return;
} }
// POST /ticket/update TicketSystem Daten (von StatusAPIBridge)
if ("POST".equalsIgnoreCase(method) && "/ticket/update".equalsIgnoreCase(pathOnly)) {
String body = readBody(in, headers);
String uuidStr = extractJsonString(body, "uuid");
if (uuidStr != null && !uuidStr.isEmpty()) {
try {
UUID uid = UUID.fromString(uuidStr.trim());
String myOpen = extractJsonString(body, "my_open");
if (myOpen != null)
net.viper.status.modules.scoreboard.ScoreboardModule.ticketMyOpen.put(uid, Integer.parseInt(myOpen));
} catch (Exception ignored) {}
}
try {
String totOpen = extractJsonString(body, "total_open");
String totClaimed = extractJsonString(body, "total_claimed");
String ratGood = extractJsonString(body, "rating_good");
String ratBad = extractJsonString(body, "rating_bad");
if (totOpen != null) net.viper.status.modules.scoreboard.ScoreboardModule.ticketTotalOpen.set(Integer.parseInt(totOpen));
if (totClaimed != null) net.viper.status.modules.scoreboard.ScoreboardModule.ticketTotalClaimed.set(Integer.parseInt(totClaimed));
if (ratGood != null) net.viper.status.modules.scoreboard.ScoreboardModule.ticketRatingGood.set(Integer.parseInt(ratGood));
if (ratBad != null) net.viper.status.modules.scoreboard.ScoreboardModule.ticketRatingBad.set(Integer.parseInt(ratBad));
} catch (Exception ignored) {}
sendHttpResponse(out, "{\"success\":true}", 200);
return;
}
// POST /player/data Koordinaten, Gamemode, Exp, Food, Speed // POST /player/data Koordinaten, Gamemode, Exp, Food, Speed
if ("POST".equalsIgnoreCase(method) && "/player/data".equalsIgnoreCase(pathOnly)) { if ("POST".equalsIgnoreCase(method) && "/player/data".equalsIgnoreCase(pathOnly)) {
String body = readBody(in, headers); String body = readBody(in, headers);

View File

@@ -39,6 +39,7 @@ public class ScoreboardModule implements Module, Listener {
private static final String CONFIG_FILE = "scoreboard.properties"; private static final String CONFIG_FILE = "scoreboard.properties";
private static final String OBJ_NAME = "vpsb"; private static final String OBJ_NAME = "vpsb";
private static final String OBJ_NAME_ADMIN = "vpsbadmin"; private static final String OBJ_NAME_ADMIN = "vpsbadmin";
private static final String OBJ_NAME_SUPP = "vpsbsupp";
public static final ConcurrentHashMap<UUID, Double> playerHealth = new ConcurrentHashMap<>(); public static final ConcurrentHashMap<UUID, Double> playerHealth = new ConcurrentHashMap<>();
public static final ConcurrentHashMap<UUID, String> playerCompass = new ConcurrentHashMap<>(); public static final ConcurrentHashMap<UUID, String> playerCompass = new ConcurrentHashMap<>();
@@ -53,6 +54,18 @@ public class ScoreboardModule implements Module, Listener {
public static final ConcurrentHashMap<UUID, Integer> playerFood = new ConcurrentHashMap<>(); public static final ConcurrentHashMap<UUID, Integer> playerFood = new ConcurrentHashMap<>();
public static final ConcurrentHashMap<UUID, Double> playerSpeed = new ConcurrentHashMap<>(); public static final ConcurrentHashMap<UUID, Double> playerSpeed = new ConcurrentHashMap<>();
// ── TicketSystem Placeholder ──────────────────────────────────────────────
/** Eigene aktive Tickets des Spielers (OPEN + CLAIMED + FORWARDED) */
public static final ConcurrentHashMap<UUID, Integer> ticketMyOpen = new ConcurrentHashMap<>();
/** Alle offenen Tickets gesamt (Status: OPEN) für Supporter & Admin */
public static final java.util.concurrent.atomic.AtomicInteger ticketTotalOpen = new java.util.concurrent.atomic.AtomicInteger(0);
/** Alle Tickets in Bearbeitung gesamt (Status: CLAIMED) für Admin */
public static final java.util.concurrent.atomic.AtomicInteger ticketTotalClaimed = new java.util.concurrent.atomic.AtomicInteger(0);
/** Positive Bewertungen gesamt für Admin */
public static final java.util.concurrent.atomic.AtomicInteger ticketRatingGood = new java.util.concurrent.atomic.AtomicInteger(0);
/** Negative Bewertungen gesamt für Admin */
public static final java.util.concurrent.atomic.AtomicInteger ticketRatingBad = new java.util.concurrent.atomic.AtomicInteger(0);
private final ConcurrentHashMap<UUID, Long> joinTimes = new ConcurrentHashMap<>(); private final ConcurrentHashMap<UUID, Long> joinTimes = new ConcurrentHashMap<>();
// Spieler, die das Scoreboard ausgeblendet haben // Spieler, die das Scoreboard ausgeblendet haben
/** FIX: Referenz auf NetworkInfoModule für TPS-Fallback */ /** FIX: Referenz auf NetworkInfoModule für TPS-Fallback */
@@ -65,9 +78,11 @@ public class ScoreboardModule implements Module, Listener {
private final Set<UUID> hiddenPlayers = ConcurrentHashMap.newKeySet(); private final Set<UUID> hiddenPlayers = ConcurrentHashMap.newKeySet();
// Spieler, die manuell auf Player-Board gezwungen wurden (Override) // Spieler, die manuell auf Player-Board gezwungen wurden (Override)
private final Set<UUID> forcePlayerView = ConcurrentHashMap.newKeySet(); private final Set<UUID> forcePlayerView = ConcurrentHashMap.newKeySet();
// Spieler, die manuell auf Supporter-Board gezwungen wurden
private final Set<UUID> forceSupporterView = ConcurrentHashMap.newKeySet();
// Spieler, die manuell auf Admin-Board gezwungen wurden (ohne Perm) // Spieler, die manuell auf Admin-Board gezwungen wurden (ohne Perm)
private final Set<UUID> forceAdminView = ConcurrentHashMap.newKeySet(); private final Set<UUID> forceAdminView = ConcurrentHashMap.newKeySet();
private boolean enabled = true; private boolean enabled = true;
private int updateInterval = 500; // Millisekunden private int updateInterval = 500; // Millisekunden
@@ -79,7 +94,9 @@ public class ScoreboardModule implements Module, Listener {
private float waveSpeed = 0.05f; // Bewegung pro Tick private float waveSpeed = 0.05f; // Bewegung pro Tick
private String title = "&6&lViper Network"; private String title = "&6&lViper Network";
private String adminTitle = "&c&l[Admin] &4&lPanel"; private String adminTitle = "&c&l[Admin] &4&lPanel";
private String adminPermission = "statusapi.scoreboard.admin"; private String supporterTitle = "&e&l[Support] &6&lPanel";
private String adminPermission = "statusapi.scoreboard.admin";
private String supporterPermission = "statusapi.scoreboard.supporter";
private String timeFormat = "HH:mm"; private String timeFormat = "HH:mm";
private String dateFormat = "dd.MM.yyyy"; private String dateFormat = "dd.MM.yyyy";
private String timeZone = "Europe/Berlin"; private String timeZone = "Europe/Berlin";
@@ -90,8 +107,9 @@ public class ScoreboardModule implements Module, Listener {
private int tickerWidth = 24; private int tickerWidth = 24;
// Key = Zeilennummer (1-based), Value = Liste der Inhalte pro Page // Key = Zeilennummer (1-based), Value = Liste der Inhalte pro Page
// Zeilen mit nur 1 Eintrag rotieren nicht, Zeilen mit 2+ Eintraegen wechseln // Zeilen mit nur 1 Eintrag rotieren nicht, Zeilen mit 2+ Eintraegen wechseln
private Map<Integer, List<String>> playerLineMap = new LinkedHashMap<>(); private Map<Integer, List<String>> playerLineMap = new LinkedHashMap<>();
private Map<Integer, List<String>> adminLineMap = new LinkedHashMap<>(); private Map<Integer, List<String>> adminLineMap = new LinkedHashMap<>();
private Map<Integer, List<String>> supporterLineMap = new LinkedHashMap<>();
private int rotationInterval = 4; // Sekunden pro Page private int rotationInterval = 4; // Sekunden pro Page
// News-Ticker // News-Ticker
private String newsText = ""; private String newsText = "";
@@ -120,8 +138,9 @@ public class ScoreboardModule implements Module, Listener {
private final ConcurrentHashMap<UUID, Integer> tickerPos = new ConcurrentHashMap<>(); private final ConcurrentHashMap<UUID, Integer> tickerPos = new ConcurrentHashMap<>();
private final ConcurrentHashMap<UUID, Integer> rainbowIdx = new ConcurrentHashMap<>(); private final ConcurrentHashMap<UUID, Integer> rainbowIdx = new ConcurrentHashMap<>();
private final Set<UUID> created = ConcurrentHashMap.newKeySet(); private final Set<UUID> created = ConcurrentHashMap.newKeySet();
private final Set<UUID> createdAdmin = ConcurrentHashMap.newKeySet(); private final Set<UUID> createdAdmin = ConcurrentHashMap.newKeySet();
private final Set<UUID> createdSupporter = ConcurrentHashMap.newKeySet();
private static final ChatColor[] RAINBOW = { private static final ChatColor[] RAINBOW = {
ChatColor.RED, ChatColor.GOLD, ChatColor.YELLOW, ChatColor.RED, ChatColor.GOLD, ChatColor.YELLOW,
@@ -177,11 +196,12 @@ public class ScoreboardModule implements Module, Listener {
if (titleTask != null) { titleTask.cancel(); titleTask = null; } if (titleTask != null) { titleTask.cancel(); titleTask = null; }
if (newsTask != null) { newsTask.cancel(); newsTask = null; } if (newsTask != null) { newsTask.cancel(); newsTask = null; }
for (ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) { for (ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) {
if (created.contains(p.getUniqueId())) removeObjectiveAndTeams(p, OBJ_NAME, "vt"); if (created.contains(p.getUniqueId())) removeObjectiveAndTeams(p, OBJ_NAME, "vt");
if (createdAdmin.contains(p.getUniqueId())) removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); if (createdAdmin.contains(p.getUniqueId())) removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta");
if (createdSupporter.contains(p.getUniqueId())) removeObjectiveAndTeams(p, OBJ_NAME_SUPP, "vts");
} }
created.clear(); createdAdmin.clear(); tickerPos.clear(); rainbowIdx.clear(); created.clear(); createdAdmin.clear(); createdSupporter.clear(); tickerPos.clear(); rainbowIdx.clear();
hiddenPlayers.clear(); forceAdminView.clear(); forcePlayerView.clear(); newsPos.clear(); hiddenPlayers.clear(); forceAdminView.clear(); forcePlayerView.clear(); forceSupporterView.clear(); newsPos.clear();
} }
@EventHandler @EventHandler
@@ -195,6 +215,7 @@ public class ScoreboardModule implements Module, Listener {
// Nur State initialisieren onSwitch baut das Scoreboard auf // Nur State initialisieren onSwitch baut das Scoreboard auf
created.remove(id); created.remove(id);
createdAdmin.remove(id); createdAdmin.remove(id);
createdSupporter.remove(id);
} }
@EventHandler @EventHandler
@@ -203,15 +224,17 @@ public class ScoreboardModule implements Module, Listener {
ProxiedPlayer p = e.getPlayer(); ProxiedPlayer p = e.getPlayer();
UUID id = p.getUniqueId(); UUID id = p.getUniqueId();
// Altes Objective sauber entfernen tickAll übernimmt den Neuaufbau // Altes Objective sauber entfernen tickAll übernimmt den Neuaufbau
if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); } if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); }
if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); } if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); }
if (createdSupporter.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_SUPP, "vts"); createdSupporter.remove(id); }
// Kein verzögerter sendAll-Call mehr tickAll baut nach max. 500ms neu auf // Kein verzögerter sendAll-Call mehr tickAll baut nach max. 500ms neu auf
} }
@EventHandler @EventHandler
public void onQuit(PlayerDisconnectEvent e) { public void onQuit(PlayerDisconnectEvent e) {
UUID id = e.getPlayer().getUniqueId(); UUID id = e.getPlayer().getUniqueId();
tickerPos.remove(id); rainbowIdx.remove(id); created.remove(id); createdAdmin.remove(id); tickerPos.remove(id); rainbowIdx.remove(id); created.remove(id); createdAdmin.remove(id); createdSupporter.remove(id);
forcePlayerView.remove(id); forceSupporterView.remove(id); forceAdminView.remove(id);
playerHealth.remove(id); playerCompass.remove(id); playerTps.remove(id); playerHealth.remove(id); playerCompass.remove(id); playerTps.remove(id);
playerX.remove(id); playerY.remove(id); playerZ.remove(id); playerX.remove(id); playerY.remove(id); playerZ.remove(id);
playerWorld.remove(id); playerGamemode.remove(id); playerWorld.remove(id); playerGamemode.remove(id);
@@ -230,9 +253,10 @@ public class ScoreboardModule implements Module, Listener {
if (!p.isConnected()) continue; if (!p.isConnected()) continue;
UUID id = p.getUniqueId(); UUID id = p.getUniqueId();
if (hiddenPlayers.contains(id)) continue; if (hiddenPlayers.contains(id)) continue;
boolean isAdmin = !forcePlayerView.contains(id) boolean isAdmin = !forceSupporterView.contains(id) && !forcePlayerView.contains(id)
&& (p.hasPermission(adminPermission) || forceAdminView.contains(id)); && (p.hasPermission(adminPermission) || forceAdminView.contains(id));
Set<UUID> activeCreated = isAdmin ? createdAdmin : created; boolean isSupporter = !isAdmin && (forceSupporterView.contains(id) || (!forcePlayerView.contains(id) && p.hasPermission(supporterPermission)));
Set<UUID> activeCreated = isAdmin ? createdAdmin : isSupporter ? createdSupporter : created;
if (!activeCreated.contains(id)) continue; if (!activeCreated.contains(id)) continue;
// Position vorrücken // Position vorrücken
@@ -267,7 +291,7 @@ public class ScoreboardModule implements Module, Listener {
// Team-Packet nur für diese Zeile senden // Team-Packet nur für diese Zeile senden
net.md_5.bungee.protocol.packet.Team team = new net.md_5.bungee.protocol.packet.Team(); net.md_5.bungee.protocol.packet.Team team = new net.md_5.bungee.protocol.packet.Team();
team.setName((isAdmin ? "vta" : "vt") + lineIdx); team.setName((isAdmin ? "vta" : isSupporter ? "vts" : "vt") + lineIdx);
team.setMode((byte) 2); // UPDATE team.setMode((byte) 2); // UPDATE
net.md_5.bungee.api.chat.TextComponent tc = net.md_5.bungee.api.chat.TextComponent tc =
new net.md_5.bungee.api.chat.TextComponent(""); new net.md_5.bungee.api.chat.TextComponent("");
@@ -293,15 +317,15 @@ public class ScoreboardModule implements Module, Listener {
if (!p.isConnected()) continue; if (!p.isConnected()) continue;
UUID id = p.getUniqueId(); UUID id = p.getUniqueId();
if (hiddenPlayers.contains(id)) continue; if (hiddenPlayers.contains(id)) continue;
boolean isAdmin = !forcePlayerView.contains(id) boolean isAdmin = !forceSupporterView.contains(id) && !forcePlayerView.contains(id)
&& (p.hasPermission(adminPermission) || forceAdminView.contains(id)); && (p.hasPermission(adminPermission) || forceAdminView.contains(id));
Set<UUID> activeCreated = isAdmin ? createdAdmin : created; boolean isSupporter = !isAdmin && (forceSupporterView.contains(id) || (!forcePlayerView.contains(id) && p.hasPermission(supporterPermission)));
if (!activeCreated.contains(id)) continue; // noch nicht aufgebaut Set<UUID> activeCreated = isAdmin ? createdAdmin : isSupporter ? createdSupporter : created;
try { try {
int rIdx = (rainbowIdx.getOrDefault(id, 0) + 1) % 10000; int rIdx = (rainbowIdx.getOrDefault(id, 0) + 1) % 10000;
rainbowIdx.put(id, rIdx); rainbowIdx.put(id, rIdx);
String activeObjName = isAdmin ? OBJ_NAME_ADMIN : OBJ_NAME; String activeObjName = isAdmin ? OBJ_NAME_ADMIN : isSupporter ? OBJ_NAME_SUPP : OBJ_NAME;
String rawTitle = isAdmin ? adminTitle : title; String rawTitle = isAdmin ? adminTitle : isSupporter ? supporterTitle : title;
String titleStr = rainbow(c(rawTitle), rIdx); String titleStr = rainbow(c(rawTitle), rIdx);
ScoreboardObjective obj = new ScoreboardObjective(); ScoreboardObjective obj = new ScoreboardObjective();
obj.setName(activeObjName); obj.setName(activeObjName);
@@ -348,9 +372,10 @@ public class ScoreboardModule implements Module, Listener {
} }
// forcePlayerView hat Vorrang vor Perm und forceAdminView // forcePlayerView hat Vorrang vor Perm und forceAdminView
boolean isAdmin = !forcePlayerView.contains(id) boolean isAdmin = !forceSupporterView.contains(id) && !forcePlayerView.contains(id)
&& (p.hasPermission(adminPermission) || forceAdminView.contains(id)); && (p.hasPermission(adminPermission) || forceAdminView.contains(id));
boolean isSupporter = !isAdmin && (forceSupporterView.contains(id)
|| (!forcePlayerView.contains(id) && p.hasPermission(supporterPermission)));
String rawTicker = stripColors(tickerText); String rawTicker = stripColors(tickerText);
int tLen = Math.max(1, rawTicker.length()); int tLen = Math.max(1, rawTicker.length());
int tOff = (tickerPos.getOrDefault(id, 0) + tickerSpeed) % tLen; int tOff = (tickerPos.getOrDefault(id, 0) + tickerSpeed) % tLen;
@@ -403,8 +428,22 @@ public class ScoreboardModule implements Module, Listener {
String servers = String.valueOf(ProxyServer.getInstance().getServers().size()); String servers = String.valueOf(ProxyServer.getInstance().getServers().size());
String proxymem = getRam(); String proxymem = getRam();
// ── TicketSystem ──────────────────────────────────────────────────────
String ticketMyOpenStr = String.valueOf(ticketMyOpen.getOrDefault(id, 0));
String ticketTotalOpenStr = String.valueOf(ticketTotalOpen.get());
String ticketTotalClaimedStr = String.valueOf(ticketTotalClaimed.get());
String ticketRatingGoodStr = String.valueOf(ticketRatingGood.get());
String ticketRatingBadStr = String.valueOf(ticketRatingBad.get());
int _tGood = ticketRatingGood.get();
int _tBad = ticketRatingBad.get();
String ticketRatingPctStr = (_tGood + _tBad == 0) ? "-"
: String.valueOf(Math.round(_tGood * 100.0 / (_tGood + _tBad)));
// Per-Zeile Rotation: Zeilen mit mehreren Inhalten wechseln automatisch // Per-Zeile Rotation: Zeilen mit mehreren Inhalten wechseln automatisch
Map<Integer, List<String>> lineMap = (isAdmin && !adminLineMap.isEmpty()) ? adminLineMap : playerLineMap; Map<Integer, List<String>> lineMap = isAdmin ? adminLineMap
: isSupporter ? supporterLineMap
: playerLineMap;
if (lineMap.isEmpty()) lineMap = playerLineMap;
// Aktueller Page-Index basierend auf Zeit // Aktueller Page-Index basierend auf Zeit
int pageIdx = (rotationInterval > 0) int pageIdx = (rotationInterval > 0)
? (int)((System.currentTimeMillis() / 1000) / rotationInterval) ? (int)((System.currentTimeMillis() / 1000) / rotationInterval)
@@ -424,36 +463,41 @@ public class ScoreboardModule implements Module, Listener {
} }
} }
List<String> lines = new ArrayList<>(); List<String> lines = new ArrayList<>();
boolean hasTicker = !tickerText.isEmpty() && !isAdmin; boolean hasTicker = !tickerText.isEmpty() && !isAdmin && !isSupporter;
if (hasTicker) lines.add(ticker(rawTicker, tOff, rIdx)); if (hasTicker) lines.add(ticker(rawTicker, tOff, rIdx));
// Maximale Inhaltszeilen: MAX_LINES insgesamt (Ticker zählt als eine) // Maximale Inhaltszeilen: MAX_LINES insgesamt (Ticker zählt als eine)
for (String tpl : srcLines) { for (String tpl : srcLines) {
if (lines.size() >= MAX_LINES) break; if (lines.size() >= MAX_LINES) break;
lines.add(c(ph(tpl, pn, rank, money, srv, comp, hp, hpNum, ping, online, maxpl, tps, ram, time, playtime, lines.add(c(ph(tpl, pn, rank, money, srv, comp, hp, hpNum, ping, online, maxpl, tps, ram, time, playtime,
xCoord, yCoord, zCoord, world, gamemode, exp, food, foodSym, speed, uptime, servers, proxymem, date, news))); xCoord, yCoord, zCoord, world, gamemode, exp, food, foodSym, speed, uptime, servers, proxymem, date, news,
ticketMyOpenStr, ticketTotalOpenStr, ticketTotalClaimedStr,
ticketRatingGoodStr, ticketRatingBadStr, ticketRatingPctStr)));
} }
// Immer genau MAX_LINES Zeilen (Rest mit Leerzeilen auffüllen) // Immer genau MAX_LINES Zeilen (Rest mit Leerzeilen auffüllen)
if (lines.size() > MAX_LINES) lines = new ArrayList<>(lines.subList(0, MAX_LINES)); if (lines.size() > MAX_LINES) lines = new ArrayList<>(lines.subList(0, MAX_LINES));
while (lines.size() < MAX_LINES) lines.add(" "); while (lines.size() < MAX_LINES) lines.add(" ");
// Admin-Scoreboard hat eigenen Objective-Namen und Titel // Objective-Name und Titel je nach Rolle
String activeObjName = isAdmin ? OBJ_NAME_ADMIN : OBJ_NAME; String activeObjName = isAdmin ? OBJ_NAME_ADMIN
String titleStr = isAdmin : isSupporter ? OBJ_NAME_SUPP
? rainbow(c(adminTitle), rIdx) : OBJ_NAME;
: rainbow(c(title), rIdx); String titleStr = isAdmin ? rainbow(c(adminTitle), rIdx)
: isSupporter ? rainbow(c(supporterTitle), rIdx)
: rainbow(c(title), rIdx);
// Wenn Admin-Status wechselt: altes Objective entfernen // Wenn Rolle wechselt: altes Objective sauber entfernen
// Wechsel zwischen Player- und Admin-Board: if (isAdmin) {
// Altes Objective + alle zugehörigen Teams sauber entfernen if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); }
if (isAdmin && created.contains(id)) { if (createdSupporter.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_SUPP, "vts"); createdSupporter.remove(id); }
removeObjectiveAndTeams(p, OBJ_NAME, "vt"); } else if (isSupporter) {
created.remove(id); if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); }
} else if (!isAdmin && createdAdmin.contains(id)) { if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); }
removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); } else {
createdAdmin.remove(id); if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); }
if (createdSupporter.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_SUPP, "vts"); createdSupporter.remove(id); }
} }
Set<UUID> activeCreated = isAdmin ? createdAdmin : created; Set<UUID> activeCreated = isAdmin ? createdAdmin : isSupporter ? createdSupporter : created;
// Objective CREATE (einmalig) oder UPDATE_TITLE // Objective CREATE (einmalig) oder UPDATE_TITLE
boolean justCreated = !activeCreated.contains(id); boolean justCreated = !activeCreated.contains(id);
@@ -505,7 +549,7 @@ public class ScoreboardModule implements Module, Listener {
sendPkt.invoke(p, score); sendPkt.invoke(p, score);
Team team = new Team(); Team team = new Team();
team.setName((isAdmin ? "vta" : "vt") + i); team.setName((isAdmin ? "vta" : isSupporter ? "vts" : "vt") + i);
// CREATE wenn das Objective gerade frisch angelegt wurde, sonst UPDATE // CREATE wenn das Objective gerade frisch angelegt wurde, sonst UPDATE
team.setMode(justCreated ? (byte) 0 : (byte) 2); team.setMode(justCreated ? (byte) 0 : (byte) 2);
// Hex-Farben: BaseComponent[] als Container-TextComponent verpacken // Hex-Farben: BaseComponent[] als Container-TextComponent verpacken
@@ -787,7 +831,9 @@ public class ScoreboardModule implements Module, Listener {
String tps, String ram, String time, String playtime, String tps, String ram, String time, String playtime,
String x, String y, String z, String world, String gamemode, String x, String y, String z, String world, String gamemode,
String exp, String food, String foodSymbol, String speed, String exp, String food, String foodSymbol, String speed,
String uptime, String servers, String proxymem, String date, String news) { String uptime, String servers, String proxymem, String date, String news,
String ticketMyOpen, String ticketTotalOpen, String ticketTotalClaimed,
String ticketRatingGood, String ticketRatingBad, String ticketRatingPct) {
if (tpl == null) return " "; if (tpl == null) return " ";
String s = tpl String s = tpl
.replace("%player%", player) .replace("%rank%", rank) .replace("%player%", player) .replace("%rank%", rank)
@@ -805,7 +851,14 @@ public class ScoreboardModule implements Module, Listener {
.replace("%uptime%", uptime) .replace("%servers%", servers) .replace("%uptime%", uptime) .replace("%servers%", servers)
.replace("%proxymem%", proxymem) .replace("%proxymem%", proxymem)
.replace("%date%", date) .replace("%date%", date)
.replace("%news%", news); .replace("%news%", news)
// ── TicketSystem ──────────────────────────────────────────────────
.replace("%ticket_my_open%", ticketMyOpen)
.replace("%ticket_open%", ticketTotalOpen)
.replace("%ticket_claimed%", ticketTotalClaimed)
.replace("%ticket_rating_good%", ticketRatingGood)
.replace("%ticket_rating_bad%", ticketRatingBad)
.replace("%ticket_rating_pct%", ticketRatingPct);
s = applyGradients(s); s = applyGradients(s);
s = s.replace("%line%", c(separator)); s = s.replace("%line%", c(separator));
return s.isEmpty() ? " " : s; return s.isEmpty() ? " " : s;
@@ -1179,7 +1232,8 @@ public class ScoreboardModule implements Module, Listener {
"scoreboard.enabled=true\n" + "scoreboard.enabled=true\n" +
"scoreboard.update_interval=500\n" + "scoreboard.update_interval=500\n" +
"scoreboard.title=&lViper Network\n" + "scoreboard.title=&lViper Network\n" +
"scoreboard.admin_title=&l[Admin] Panel\n\n" + "scoreboard.admin_title=&l[Admin] Panel\n" +
"scoreboard.supporter_title=&l[Support] Panel\n\n" +
"scoreboard.ticker.text=\n" + "scoreboard.ticker.text=\n" +
"scoreboard.ticker.width=26\n" + "scoreboard.ticker.width=26\n" +
"scoreboard.ticker.speed=1\n\n" + "scoreboard.ticker.speed=1\n\n" +
@@ -1190,7 +1244,8 @@ public class ScoreboardModule implements Module, Listener {
"scoreboard.rainbow.speed=10\n" + "scoreboard.rainbow.speed=10\n" +
"# Leer = voller HSB-Regenbogen\n" + "# Leer = voller HSB-Regenbogen\n" +
"scoreboard.rainbow.colors=#FF0000,#FF6600,#FFFF00,#00FF00,#00FFFF,#0000FF,#FF00FF\n\n" + "scoreboard.rainbow.colors=#FF0000,#FF6600,#FFFF00,#00FF00,#00FFFF,#0000FF,#FF00FF\n\n" +
"scoreboard.admin_permission=statusapi.scoreboard.admin\n\n" + "scoreboard.admin_permission=statusapi.scoreboard.admin\n" +
"scoreboard.supporter_permission=statusapi.scoreboard.supporter\n\n" +
"scoreboard.time_format=HH:mm\n" + "scoreboard.time_format=HH:mm\n" +
"scoreboard.date_format=dd.MM.yyyy\n" + "scoreboard.date_format=dd.MM.yyyy\n" +
"scoreboard.timezone=Europe/Berlin\n" + "scoreboard.timezone=Europe/Berlin\n" +
@@ -1252,7 +1307,25 @@ public class ScoreboardModule implements Module, Listener {
"scoreboard.admin_lines.13=%news%\n" + "scoreboard.admin_lines.13=%news%\n" +
"scoreboard.admin_lines.14=%line%\n" + "scoreboard.admin_lines.14=%line%\n" +
"scoreboard.admin_lines.15=&7%compass%\n" + "scoreboard.admin_lines.15=&7%compass%\n" +
"scoreboard.admin_lines.15.2=&7Pos: X:&f%x% &7Y:&f%y% &7Z:&f%z%\n"; "scoreboard.admin_lines.15.2=&7Pos: X:&f%x% &7Y:&f%y% &7Z:&f%z%\n" +
"# ===================================================\n" +
"# SUPPORTER-ZEILEN\n" +
"# ===================================================\n" +
"scoreboard.supporter_lines.1=%line%\n" +
"scoreboard.supporter_lines.2=%gradient:&6:&f:&6:&l> Support Panel:%\n" +
"scoreboard.supporter_lines.3=&7%rank% &f%player%\n" +
"scoreboard.supporter_lines.4=&7Ping: &f%ping%ms &8| &7%server%\n" +
"scoreboard.supporter_lines.5=\n" +
"scoreboard.supporter_lines.6=%gradient:&6:&f:&6:&l> Tickets:%\n" +
"scoreboard.supporter_lines.7=&7Offen: &c%ticket_open%\n" +
"scoreboard.supporter_lines.8=&7Meine Tickets: &e%ticket_my_open%\n" +
"scoreboard.supporter_lines.9=\n" +
"scoreboard.supporter_lines.10=%gradient:&6:&f:&6:&l> Server Info:%\n" +
"scoreboard.supporter_lines.11=&7Online: &f%online% &8/ &7%maxplayers%\n" +
"scoreboard.supporter_lines.12=&7Zeit: &f%time%\n" +
"scoreboard.supporter_lines.13=\n" +
"scoreboard.supporter_lines.14=%line%\n" +
"scoreboard.supporter_lines.15=&7%compass%\n";
try (OutputStream out = new FileOutputStream(f)) { try (OutputStream out = new FileOutputStream(f)) {
out.write(content.getBytes(StandardCharsets.UTF_8)); out.write(content.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) { } catch (Exception e) {
@@ -1283,6 +1356,7 @@ public class ScoreboardModule implements Module, Listener {
updateInterval = Math.max(250, pi(g.apply("scoreboard.update_interval", "500"), 500)); updateInterval = Math.max(250, pi(g.apply("scoreboard.update_interval", "500"), 500));
title = g.apply("scoreboard.title", "&6&lViper Network"); title = g.apply("scoreboard.title", "&6&lViper Network");
adminTitle = g.apply("scoreboard.admin_title", "&c&l[Admin] &4&lPanel"); adminTitle = g.apply("scoreboard.admin_title", "&c&l[Admin] &4&lPanel");
supporterTitle = g.apply("scoreboard.supporter_title", "&e&l[Support] &6&lPanel");
tickerText = g.apply("scoreboard.ticker.text", " Viper Network "); tickerText = g.apply("scoreboard.ticker.text", " Viper Network ");
tickerWidth = pi(g.apply("scoreboard.ticker.width", "26"), 26); tickerWidth = pi(g.apply("scoreboard.ticker.width", "26"), 26);
tickerSpeed = pi(g.apply("scoreboard.ticker.speed", "1"), 1); tickerSpeed = pi(g.apply("scoreboard.ticker.speed", "1"), 1);
@@ -1319,7 +1393,8 @@ public class ScoreboardModule implements Module, Listener {
} else { } else {
waveColors = null; // HSB-Fallback waveColors = null; // HSB-Fallback
} }
adminPermission = g.apply("scoreboard.admin_permission", "statusapi.scoreboard.admin"); adminPermission = g.apply("scoreboard.admin_permission", "statusapi.scoreboard.admin");
supporterPermission = g.apply("scoreboard.supporter_permission", "statusapi.scoreboard.supporter");
timeFormat = g.apply("scoreboard.time_format", "HH:mm"); timeFormat = g.apply("scoreboard.time_format", "HH:mm");
dateFormat = g.apply("scoreboard.date_format", "dd.MM.yyyy"); dateFormat = g.apply("scoreboard.date_format", "dd.MM.yyyy");
timeZone = g.apply("scoreboard.timezone", "Europe/Berlin"); timeZone = g.apply("scoreboard.timezone", "Europe/Berlin");
@@ -1355,10 +1430,13 @@ public class ScoreboardModule implements Module, Listener {
loadLineMap(map, "scoreboard.lines.", playerLineMap); loadLineMap(map, "scoreboard.lines.", playerLineMap);
adminLineMap.clear(); adminLineMap.clear();
loadLineMap(map, "scoreboard.admin_lines.", adminLineMap); loadLineMap(map, "scoreboard.admin_lines.", adminLineMap);
supporterLineMap.clear();
loadLineMap(map, "scoreboard.supporter_lines.", supporterLineMap);
plugin.getLogger().info("[ScoreboardModule] " plugin.getLogger().info("[ScoreboardModule] "
+ playerLineMap.size() + " Player-Zeilen, " + playerLineMap.size() + " Player-Zeilen, "
+ adminLineMap.size() + " Admin-Zeilen. RotInterval=" + rotationInterval + "s"); + adminLineMap.size() + " Admin-Zeilen, "
+ supporterLineMap.size() + " Supporter-Zeilen. RotInterval=" + rotationInterval + "s");
} }
/** /**
@@ -1466,56 +1544,73 @@ public class ScoreboardModule implements Module, Listener {
switch (sub) { switch (sub) {
case "hide": case "hide":
// Erst sauber entfernen, dann verstecken if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); }
if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); } if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); }
if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); } if (createdSupporter.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_SUPP, "vts"); createdSupporter.remove(id); }
hiddenPlayers.add(id); hiddenPlayers.add(id);
p.sendMessage(msg("&7Scoreboard &causgeblendet&7. (/sb zum Einblenden)")); p.sendMessage(msg("&7Scoreboard &causgeblendet&7. (/sb zum Einblenden)"));
break; break;
case "show": case "show":
// Sauber entfernen → nächster tickAll baut neu auf if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); }
if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); } if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); }
if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); } if (createdSupporter.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_SUPP, "vts"); createdSupporter.remove(id); }
hiddenPlayers.remove(id); hiddenPlayers.remove(id);
p.sendMessage(msg("&7Scoreboard &aeingeblendet&7.")); p.sendMessage(msg("&7Scoreboard &aeingeblendet&7."));
break; break;
case "player": case "player":
// Aktuell angezeigtes Board sauber entfernen, dann auf Player umschalten if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); }
if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); } if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); }
if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); } if (createdSupporter.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_SUPP, "vts"); createdSupporter.remove(id); }
forcePlayerView.add(id); // überschreibt Admin-Perm forcePlayerView.add(id);
forceAdminView.remove(id); forceAdminView.remove(id);
forceSupporterView.remove(id);
hiddenPlayers.remove(id); hiddenPlayers.remove(id);
p.sendMessage(msg("&7Zeige &eSpieler&7-Scoreboard.")); p.sendMessage(msg("&7Zeige &eSpieler&7-Scoreboard."));
break; break;
case "supporter":
if (!p.hasPermission(supporterPermission) && !p.hasPermission(adminPermission)) {
p.sendMessage(msg("&cKeine Berechtigung."));
return;
}
if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); }
if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); }
if (createdSupporter.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_SUPP, "vts"); createdSupporter.remove(id); }
forceSupporterView.add(id);
forceAdminView.remove(id);
forcePlayerView.remove(id);
hiddenPlayers.remove(id);
p.sendMessage(msg("&7Zeige &6Supporter&7-Scoreboard."));
break;
case "admin": case "admin":
if (!p.hasPermission(adminPermission)) { if (!p.hasPermission(adminPermission)) {
p.sendMessage(msg("&cKeine Berechtigung.")); p.sendMessage(msg("&cKeine Berechtigung."));
return; return;
} }
// Aktuell angezeigtes Board sauber entfernen, dann auf Admin umschalten if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); }
if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); } if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); }
if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); } if (createdSupporter.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_SUPP, "vts"); createdSupporter.remove(id); }
forceAdminView.add(id); forceAdminView.add(id);
forcePlayerView.remove(id); // Admin-Perm wieder aktiv forcePlayerView.remove(id);
forceSupporterView.remove(id);
hiddenPlayers.remove(id); hiddenPlayers.remove(id);
p.sendMessage(msg("&7Zeige &cAdmin&7-Scoreboard.")); p.sendMessage(msg("&7Zeige &cAdmin&7-Scoreboard."));
break; break;
default: // "toggle" default: // "toggle"
if (hiddenPlayers.contains(id)) { if (hiddenPlayers.contains(id)) {
// Einblenden: sauber entfernen → neu aufbauen if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); }
if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); } if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); }
if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); } if (createdSupporter.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_SUPP, "vts"); createdSupporter.remove(id); }
hiddenPlayers.remove(id); hiddenPlayers.remove(id);
p.sendMessage(msg("&7Scoreboard &aeingeblendet&7.")); p.sendMessage(msg("&7Scoreboard &aeingeblendet&7."));
} else { } else {
// Ausblenden if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); }
if (created.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME, "vt"); created.remove(id); } if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); }
if (createdAdmin.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta"); createdAdmin.remove(id); } if (createdSupporter.contains(id)) { removeObjectiveAndTeams(p, OBJ_NAME_SUPP, "vts"); createdSupporter.remove(id); }
hiddenPlayers.add(id); hiddenPlayers.add(id);
p.sendMessage(msg("&7Scoreboard &causgeblendet&7. (/sb zum Einblenden)")); p.sendMessage(msg("&7Scoreboard &causgeblendet&7. (/sb zum Einblenden)"));
} }

View File

@@ -3,6 +3,9 @@
# %ping% %online% %maxplayers% %time% %playtime% %news% # %ping% %online% %maxplayers% %time% %playtime% %news%
# %x% %y% %z% %world% %gamemode% %exp% %food% %foodsym% %speed% # %x% %y% %z% %world% %gamemode% %exp% %food% %foodsym% %speed%
# Platzhalter Admin: %tps% %ram% %proxymem% %uptime% %servers% # Platzhalter Admin: %tps% %ram% %proxymem% %uptime% %servers%
# Ticket (Spieler): %ticket_my_open%
# Ticket (Supporter): %ticket_open%
# Ticket (Admin): %ticket_open% %ticket_claimed% %ticket_rating_good% %ticket_rating_bad% %ticket_rating_pct%
# Gradient: %gradient:FARBE1:FARBE2:TEXT% (beliebig viele Farb-Stopps) # Gradient: %gradient:FARBE1:FARBE2:TEXT% (beliebig viele Farb-Stopps)
# Sonstiges: %line% # Sonstiges: %line%
# Farben: &-Codes und Hex &#FF6600 # Farben: &-Codes und Hex &#FF6600
@@ -12,6 +15,7 @@ scoreboard.enabled=true
scoreboard.update_interval=500 scoreboard.update_interval=500
scoreboard.title=&lViper Network scoreboard.title=&lViper Network
scoreboard.admin_title=&l[Admin] Panel scoreboard.admin_title=&l[Admin] Panel
scoreboard.supporter_title=&l[Support] Panel
# Laufschrift leer lassen zum Deaktivieren # Laufschrift leer lassen zum Deaktivieren
scoreboard.ticker.text= scoreboard.ticker.text=
@@ -28,6 +32,7 @@ scoreboard.rainbow.speed=10
scoreboard.rainbow.colors=#FF0000,#FF6600,#FFFF00,#00FF00,#00FFFF,#0000FF,#FF00FF scoreboard.rainbow.colors=#FF0000,#FF6600,#FFFF00,#00FF00,#00FFFF,#0000FF,#FF00FF
scoreboard.admin_permission=statusapi.scoreboard.admin scoreboard.admin_permission=statusapi.scoreboard.admin
scoreboard.supporter_permission=statusapi.scoreboard.supporter
scoreboard.time_format=HH:mm scoreboard.time_format=HH:mm
scoreboard.date_format=dd.MM.yyyy scoreboard.date_format=dd.MM.yyyy
@@ -92,6 +97,9 @@ scoreboard.lines.13=%news%
scoreboard.lines.14=%line% scoreboard.lines.14=%line%
scoreboard.lines.15=&7%compass% scoreboard.lines.15=&7%compass%
# TicketSystem-Zeilen (auskommentiert nach Bedarf einbinden):
# scoreboard.lines.X=&7Tickets: &e%ticket_my_open%
# =================================================== # ===================================================
# ADMIN-ZEILEN # ADMIN-ZEILEN
# =================================================== # ===================================================
@@ -108,8 +116,27 @@ scoreboard.admin_lines.8.2=&7Proxy: &f%uptime%
scoreboard.admin_lines.9= scoreboard.admin_lines.9=
scoreboard.admin_lines.10=&7TPS: &a%tps% scoreboard.admin_lines.10=&7TPS: &a%tps%
scoreboard.admin_lines.11= scoreboard.admin_lines.11=
scoreboard.admin_lines.12=&7Spieler: &f%online% &8| &7%maxplayers% scoreboard.admin_lines.12=%gradient:&b:&f:&b:&l> Tickets:%
scoreboard.admin_lines.13=%news% scoreboard.admin_lines.13=&7Offen: &c%ticket_open% &8| &7Aktiv: &e%ticket_claimed%
scoreboard.admin_lines.14=%line% scoreboard.admin_lines.14=&7Bewertung: &a%ticket_rating_good%&8/&c%ticket_rating_bad% &7(&f%ticket_rating_pct%&7%&7)
scoreboard.admin_lines.15=&7%compass% scoreboard.admin_lines.15=%line%
scoreboard.admin_lines.15.2=&7Pos: X:&f%x% &7Y:&f%y% &7Z:&f%z% scoreboard.admin_lines.15.2=&7%compass%
# ===================================================
# SUPPORTER-ZEILEN
# ===================================================
scoreboard.supporter_lines.1=%line%
scoreboard.supporter_lines.2=%gradient:&6:&f:&6:&l> Support Panel:%
scoreboard.supporter_lines.3=&7%rank% &f%player%
scoreboard.supporter_lines.4=&7Ping: &f%ping%ms &8| &7%server%
scoreboard.supporter_lines.5=
scoreboard.supporter_lines.6=%gradient:&6:&f:&6:&l> Tickets:%
scoreboard.supporter_lines.7=&7Offen: &c%ticket_open%
scoreboard.supporter_lines.8=&7Meine Tickets: &e%ticket_my_open%
scoreboard.supporter_lines.9=
scoreboard.supporter_lines.10=%gradient:&6:&f:&6:&l> Server Info:%
scoreboard.supporter_lines.11=&7Online: &f%online% &8/ &7%maxplayers%
scoreboard.supporter_lines.12=&7Zeit: &f%time%
scoreboard.supporter_lines.13=
scoreboard.supporter_lines.14=%line%
scoreboard.supporter_lines.15=&7%compass%