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;
}
// 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
if ("POST".equalsIgnoreCase(method) && "/player/data".equalsIgnoreCase(pathOnly)) {
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 OBJ_NAME = "vpsb";
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, 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, 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<>();
// Spieler, die das Scoreboard ausgeblendet haben
/** 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();
// 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)
private final Set<UUID> forceAdminView = ConcurrentHashMap.newKeySet();
private final Set<UUID> forceAdminView = ConcurrentHashMap.newKeySet();
private boolean enabled = true;
private int updateInterval = 500; // Millisekunden
@@ -79,7 +94,9 @@ public class ScoreboardModule implements Module, Listener {
private float waveSpeed = 0.05f; // Bewegung pro Tick
private String title = "&6&lViper Network";
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 dateFormat = "dd.MM.yyyy";
private String timeZone = "Europe/Berlin";
@@ -90,8 +107,9 @@ public class ScoreboardModule implements Module, Listener {
private int tickerWidth = 24;
// Key = Zeilennummer (1-based), Value = Liste der Inhalte pro Page
// 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>> adminLineMap = new LinkedHashMap<>();
private Map<Integer, List<String>> playerLineMap = 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
// News-Ticker
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> rainbowIdx = new ConcurrentHashMap<>();
private final Set<UUID> created = ConcurrentHashMap.newKeySet();
private final Set<UUID> createdAdmin = ConcurrentHashMap.newKeySet();
private final Set<UUID> created = ConcurrentHashMap.newKeySet();
private final Set<UUID> createdAdmin = ConcurrentHashMap.newKeySet();
private final Set<UUID> createdSupporter = ConcurrentHashMap.newKeySet();
private static final ChatColor[] RAINBOW = {
ChatColor.RED, ChatColor.GOLD, ChatColor.YELLOW,
@@ -177,11 +196,12 @@ public class ScoreboardModule implements Module, Listener {
if (titleTask != null) { titleTask.cancel(); titleTask = null; }
if (newsTask != null) { newsTask.cancel(); newsTask = null; }
for (ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) {
if (created.contains(p.getUniqueId())) removeObjectiveAndTeams(p, OBJ_NAME, "vt");
if (createdAdmin.contains(p.getUniqueId())) removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta");
if (created.contains(p.getUniqueId())) removeObjectiveAndTeams(p, OBJ_NAME, "vt");
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();
hiddenPlayers.clear(); forceAdminView.clear(); forcePlayerView.clear(); newsPos.clear();
created.clear(); createdAdmin.clear(); createdSupporter.clear(); tickerPos.clear(); rainbowIdx.clear();
hiddenPlayers.clear(); forceAdminView.clear(); forcePlayerView.clear(); forceSupporterView.clear(); newsPos.clear();
}
@EventHandler
@@ -195,6 +215,7 @@ public class ScoreboardModule implements Module, Listener {
// Nur State initialisieren onSwitch baut das Scoreboard auf
created.remove(id);
createdAdmin.remove(id);
createdSupporter.remove(id);
}
@EventHandler
@@ -203,15 +224,17 @@ public class ScoreboardModule implements Module, Listener {
ProxiedPlayer p = e.getPlayer();
UUID id = p.getUniqueId();
// Altes Objective sauber entfernen tickAll übernimmt den Neuaufbau
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 (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); }
// Kein verzögerter sendAll-Call mehr tickAll baut nach max. 500ms neu auf
}
@EventHandler
public void onQuit(PlayerDisconnectEvent e) {
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);
playerX.remove(id); playerY.remove(id); playerZ.remove(id);
playerWorld.remove(id); playerGamemode.remove(id);
@@ -230,9 +253,10 @@ public class ScoreboardModule implements Module, Listener {
if (!p.isConnected()) continue;
UUID id = p.getUniqueId();
if (hiddenPlayers.contains(id)) continue;
boolean isAdmin = !forcePlayerView.contains(id)
boolean isAdmin = !forceSupporterView.contains(id) && !forcePlayerView.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;
// Position vorrücken
@@ -267,7 +291,7 @@ public class ScoreboardModule implements Module, Listener {
// Team-Packet nur für diese Zeile senden
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
net.md_5.bungee.api.chat.TextComponent tc =
new net.md_5.bungee.api.chat.TextComponent("");
@@ -293,15 +317,15 @@ public class ScoreboardModule implements Module, Listener {
if (!p.isConnected()) continue;
UUID id = p.getUniqueId();
if (hiddenPlayers.contains(id)) continue;
boolean isAdmin = !forcePlayerView.contains(id)
boolean isAdmin = !forceSupporterView.contains(id) && !forcePlayerView.contains(id)
&& (p.hasPermission(adminPermission) || forceAdminView.contains(id));
Set<UUID> activeCreated = isAdmin ? createdAdmin : created;
if (!activeCreated.contains(id)) continue; // noch nicht aufgebaut
boolean isSupporter = !isAdmin && (forceSupporterView.contains(id) || (!forcePlayerView.contains(id) && p.hasPermission(supporterPermission)));
Set<UUID> activeCreated = isAdmin ? createdAdmin : isSupporter ? createdSupporter : created;
try {
int rIdx = (rainbowIdx.getOrDefault(id, 0) + 1) % 10000;
rainbowIdx.put(id, rIdx);
String activeObjName = isAdmin ? OBJ_NAME_ADMIN : OBJ_NAME;
String rawTitle = isAdmin ? adminTitle : title;
String activeObjName = isAdmin ? OBJ_NAME_ADMIN : isSupporter ? OBJ_NAME_SUPP : OBJ_NAME;
String rawTitle = isAdmin ? adminTitle : isSupporter ? supporterTitle : title;
String titleStr = rainbow(c(rawTitle), rIdx);
ScoreboardObjective obj = new ScoreboardObjective();
obj.setName(activeObjName);
@@ -348,9 +372,10 @@ public class ScoreboardModule implements Module, Listener {
}
// 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));
boolean isSupporter = !isAdmin && (forceSupporterView.contains(id)
|| (!forcePlayerView.contains(id) && p.hasPermission(supporterPermission)));
String rawTicker = stripColors(tickerText);
int tLen = Math.max(1, rawTicker.length());
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 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
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
int pageIdx = (rotationInterval > 0)
? (int)((System.currentTimeMillis() / 1000) / rotationInterval)
@@ -424,36 +463,41 @@ public class ScoreboardModule implements Module, Listener {
}
}
List<String> lines = new ArrayList<>();
boolean hasTicker = !tickerText.isEmpty() && !isAdmin;
boolean hasTicker = !tickerText.isEmpty() && !isAdmin && !isSupporter;
if (hasTicker) lines.add(ticker(rawTicker, tOff, rIdx));
// Maximale Inhaltszeilen: MAX_LINES insgesamt (Ticker zählt als eine)
for (String tpl : srcLines) {
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,
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)
if (lines.size() > MAX_LINES) lines = new ArrayList<>(lines.subList(0, MAX_LINES));
while (lines.size() < MAX_LINES) lines.add(" ");
// Admin-Scoreboard hat eigenen Objective-Namen und Titel
String activeObjName = isAdmin ? OBJ_NAME_ADMIN : OBJ_NAME;
String titleStr = isAdmin
? rainbow(c(adminTitle), rIdx)
: rainbow(c(title), rIdx);
// Objective-Name und Titel je nach Rolle
String activeObjName = isAdmin ? OBJ_NAME_ADMIN
: isSupporter ? OBJ_NAME_SUPP
: OBJ_NAME;
String titleStr = isAdmin ? rainbow(c(adminTitle), rIdx)
: isSupporter ? rainbow(c(supporterTitle), rIdx)
: rainbow(c(title), rIdx);
// Wenn Admin-Status wechselt: altes Objective entfernen
// Wechsel zwischen Player- und Admin-Board:
// Altes Objective + alle zugehörigen Teams sauber entfernen
if (isAdmin && created.contains(id)) {
removeObjectiveAndTeams(p, OBJ_NAME, "vt");
created.remove(id);
} else if (!isAdmin && createdAdmin.contains(id)) {
removeObjectiveAndTeams(p, OBJ_NAME_ADMIN, "vta");
createdAdmin.remove(id);
// Wenn Rolle wechselt: altes Objective sauber entfernen
if (isAdmin) {
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); }
} else if (isSupporter) {
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); }
} else {
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
boolean justCreated = !activeCreated.contains(id);
@@ -505,7 +549,7 @@ public class ScoreboardModule implements Module, Listener {
sendPkt.invoke(p, score);
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
team.setMode(justCreated ? (byte) 0 : (byte) 2);
// 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 x, String y, String z, String world, String gamemode,
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 " ";
String s = tpl
.replace("%player%", player) .replace("%rank%", rank)
@@ -805,7 +851,14 @@ public class ScoreboardModule implements Module, Listener {
.replace("%uptime%", uptime) .replace("%servers%", servers)
.replace("%proxymem%", proxymem)
.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 = s.replace("%line%", c(separator));
return s.isEmpty() ? " " : s;
@@ -1179,7 +1232,8 @@ public class ScoreboardModule implements Module, Listener {
"scoreboard.enabled=true\n" +
"scoreboard.update_interval=500\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.width=26\n" +
"scoreboard.ticker.speed=1\n\n" +
@@ -1190,7 +1244,8 @@ public class ScoreboardModule implements Module, Listener {
"scoreboard.rainbow.speed=10\n" +
"# Leer = voller HSB-Regenbogen\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.date_format=dd.MM.yyyy\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.14=%line%\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)) {
out.write(content.getBytes(StandardCharsets.UTF_8));
} 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));
title = g.apply("scoreboard.title", "&6&lViper Network");
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 ");
tickerWidth = pi(g.apply("scoreboard.ticker.width", "26"), 26);
tickerSpeed = pi(g.apply("scoreboard.ticker.speed", "1"), 1);
@@ -1319,7 +1393,8 @@ public class ScoreboardModule implements Module, Listener {
} else {
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");
dateFormat = g.apply("scoreboard.date_format", "dd.MM.yyyy");
timeZone = g.apply("scoreboard.timezone", "Europe/Berlin");
@@ -1355,10 +1430,13 @@ public class ScoreboardModule implements Module, Listener {
loadLineMap(map, "scoreboard.lines.", playerLineMap);
adminLineMap.clear();
loadLineMap(map, "scoreboard.admin_lines.", adminLineMap);
supporterLineMap.clear();
loadLineMap(map, "scoreboard.supporter_lines.", supporterLineMap);
plugin.getLogger().info("[ScoreboardModule] "
+ 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) {
case "hide":
// Erst sauber entfernen, dann verstecken
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 (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); }
hiddenPlayers.add(id);
p.sendMessage(msg("&7Scoreboard &causgeblendet&7. (/sb zum Einblenden)"));
break;
case "show":
// Sauber entfernen → nächster tickAll baut neu auf
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 (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); }
hiddenPlayers.remove(id);
p.sendMessage(msg("&7Scoreboard &aeingeblendet&7."));
break;
case "player":
// Aktuell angezeigtes Board sauber entfernen, dann auf Player umschalten
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); }
forcePlayerView.add(id); // überschreibt Admin-Perm
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); }
forcePlayerView.add(id);
forceAdminView.remove(id);
forceSupporterView.remove(id);
hiddenPlayers.remove(id);
p.sendMessage(msg("&7Zeige &eSpieler&7-Scoreboard."));
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":
if (!p.hasPermission(adminPermission)) {
p.sendMessage(msg("&cKeine Berechtigung."));
return;
}
// Aktuell angezeigtes Board sauber entfernen, dann auf Admin 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 (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); }
forceAdminView.add(id);
forcePlayerView.remove(id); // Admin-Perm wieder aktiv
forcePlayerView.remove(id);
forceSupporterView.remove(id);
hiddenPlayers.remove(id);
p.sendMessage(msg("&7Zeige &cAdmin&7-Scoreboard."));
break;
default: // "toggle"
if (hiddenPlayers.contains(id)) {
// Einblenden: sauber entfernen → neu aufbauen
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 (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); }
hiddenPlayers.remove(id);
p.sendMessage(msg("&7Scoreboard &aeingeblendet&7."));
} else {
// Ausblenden
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 (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); }
hiddenPlayers.add(id);
p.sendMessage(msg("&7Scoreboard &causgeblendet&7. (/sb zum Einblenden)"));
}

View File

@@ -3,6 +3,9 @@
# %ping% %online% %maxplayers% %time% %playtime% %news%
# %x% %y% %z% %world% %gamemode% %exp% %food% %foodsym% %speed%
# 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)
# Sonstiges: %line%
# Farben: &-Codes und Hex &#FF6600
@@ -12,6 +15,7 @@ scoreboard.enabled=true
scoreboard.update_interval=500
scoreboard.title=&lViper Network
scoreboard.admin_title=&l[Admin] Panel
scoreboard.supporter_title=&l[Support] Panel
# Laufschrift leer lassen zum Deaktivieren
scoreboard.ticker.text=
@@ -28,6 +32,7 @@ scoreboard.rainbow.speed=10
scoreboard.rainbow.colors=#FF0000,#FF6600,#FFFF00,#00FF00,#00FFFF,#0000FF,#FF00FF
scoreboard.admin_permission=statusapi.scoreboard.admin
scoreboard.supporter_permission=statusapi.scoreboard.supporter
scoreboard.time_format=HH:mm
scoreboard.date_format=dd.MM.yyyy
@@ -92,6 +97,9 @@ scoreboard.lines.13=%news%
scoreboard.lines.14=%line%
scoreboard.lines.15=&7%compass%
# TicketSystem-Zeilen (auskommentiert nach Bedarf einbinden):
# scoreboard.lines.X=&7Tickets: &e%ticket_my_open%
# ===================================================
# ADMIN-ZEILEN
# ===================================================
@@ -108,8 +116,27 @@ scoreboard.admin_lines.8.2=&7Proxy: &f%uptime%
scoreboard.admin_lines.9=
scoreboard.admin_lines.10=&7TPS: &a%tps%
scoreboard.admin_lines.11=
scoreboard.admin_lines.12=&7Spieler: &f%online% &8| &7%maxplayers%
scoreboard.admin_lines.13=%news%
scoreboard.admin_lines.14=%line%
scoreboard.admin_lines.15=&7%compass%
scoreboard.admin_lines.15.2=&7Pos: X:&f%x% &7Y:&f%y% &7Z:&f%z%
scoreboard.admin_lines.12=%gradient:&b:&f:&b:&l> Tickets:%
scoreboard.admin_lines.13=&7Offen: &c%ticket_open% &8| &7Aktiv: &e%ticket_claimed%
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=%line%
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%