Upload folder via GUI - src

This commit is contained in:
Git Manager GUI
2026-04-24 12:42:38 +02:00
parent 70d264f9bf
commit 8b43fe4264
2 changed files with 96 additions and 8 deletions

View File

@@ -774,8 +774,31 @@ public class StatusAPI extends Plugin implements Runnable {
boolean escape = false;
while (i < json.length()) {
char ch = json.charAt(i++);
if (escape) { sb.append(ch); escape = false; }
else {
if (escape) {
switch (ch) {
case 'n': sb.append('\n'); break;
case 'r': sb.append('\r'); break;
case 't': sb.append('\t'); break;
case '"': sb.append('"'); break;
case '\\': sb.append('\\'); break;
case '/': sb.append('/'); break;
case 'b': sb.append('\b'); break;
case 'f': sb.append('\f'); break;
case 'u':
if (i + 4 <= json.length()) {
try {
int cp = Integer.parseInt(json.substring(i, i + 4), 16);
sb.append((char) cp);
i += 4;
} catch (NumberFormatException ignored) {
sb.append("\\u");
}
}
break;
default: sb.append(ch); break;
}
escape = false;
} else {
if (ch == '\\') escape = true;
else if (ch == '"') break;
else sb.append(ch);

View File

@@ -3,6 +3,9 @@ package net.viper.status.modules.broadcast;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.plugin.Listener;
import net.viper.status.module.Module;
@@ -20,6 +23,9 @@ import java.util.concurrent.TimeUnit;
* Fixes:
* - loadSchedules(): ID-Split nutzt jetzt indexOf/lastIndexOf statt split("\\.") mit length==2-Check.
* Damit werden auch clientScheduleIds die Punkte enthalten korrekt geladen. (Bug #2)
* - handleBroadcast(): &-Farbcodes werden jetzt auch in der Nachricht selbst übersetzt. (Bug #3)
* - handleBroadcast(): Literal \n in der Nachricht wird als echter Zeilenumbruch gerendert. (Bug #4)
* - handleBroadcast(): URLs (http/https) werden als anklickbare TextComponents eingebettet. (Bug #5)
*/
public class BroadcastModule implements Module, Listener {
@@ -115,24 +121,83 @@ public class BroadcastModule implements Module, Listener {
finalPrefix = prefixColorCode + usedPrefix + ChatColor.RESET;
}
String coloredMessage = (messageColorCode.isEmpty() ? "" : messageColorCode) + message;
// FIX #1: &-Farbcodes auch in der Nachricht selbst übersetzen
String translatedMessage = ChatColor.translateAlternateColorCodes('&', message);
String coloredMessage = (messageColorCode.isEmpty() ? "" : messageColorCode) + translatedMessage;
String out = format
.replace("%name%", sourceName)
.replace("%prefix%", finalPrefix)
.replace("%prefixColored%", finalPrefix)
.replace("%message%", message)
.replace("%message%", translatedMessage)
.replace("%messageColored%",coloredMessage)
.replace("%type%", type);
TextComponent tc = new TextComponent(out);
// FIX #2: \r entfernen (Windows CRLF -> nur LF), Literal \\n als Fallback
out = out.replace("\r\n", "\n").replace("\r", "").replace("\\n", "\n");
// FIX #3: Nachricht mit anklickbaren URLs aufbauen
BaseComponent[] components = buildClickableComponents(out);
int sent = 0;
for (ProxiedPlayer p : plugin.getProxy().getPlayers()) {
try { p.sendMessage(tc); sent++; } catch (Throwable ignored) {}
try { p.sendMessage(components); sent++; } catch (Throwable ignored) {}
}
plugin.getLogger().info("[BroadcastModule] Broadcast gesendet (Empfänger=" + sent + "): " + message);
return true;
}
/**
* Baut ein BaseComponent-Array aus einem formatierten String.
* URLs (http/https) werden als anklickbare TextComponents eingebettet.
* Unterstützt auch echte Newlines (\n) als Zeilenumbruch.
*/
private BaseComponent[] buildClickableComponents(String text) {
// Regex für URLs
java.util.regex.Pattern urlPattern = java.util.regex.Pattern.compile(
"(https?://[^\\s\\n]+)", java.util.regex.Pattern.CASE_INSENSITIVE);
ComponentBuilder builder = new ComponentBuilder("");
// Zeilenweise aufteilen (echte \n)
String[] lines = text.split("\n", -1);
for (int li = 0; li < lines.length; li++) {
if (li > 0) {
// Zeilenumbruch als eigene Komponente
builder.append(TextComponent.fromLegacyText("\n"));
}
String line = lines[li];
java.util.regex.Matcher matcher = urlPattern.matcher(line);
int lastEnd = 0;
while (matcher.find()) {
// Text vor der URL (mit Minecraft-Farbcodes)
if (matcher.start() > lastEnd) {
String before = line.substring(lastEnd, matcher.start());
builder.append(TextComponent.fromLegacyText(before));
}
// URL selbst: anklickbar + unterstrichen
String url = matcher.group(1);
TextComponent urlComponent = new TextComponent(url);
urlComponent.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url));
// Farbe der URL auf Cyan setzen damit sie sich abhebt
urlComponent.setColor(ChatColor.AQUA);
urlComponent.setUnderlined(true);
builder.append(urlComponent, ComponentBuilder.FormatRetention.NONE);
lastEnd = matcher.end();
}
// Restlicher Text nach der letzten URL
if (lastEnd < line.length()) {
builder.append(TextComponent.fromLegacyText(line.substring(lastEnd)));
}
}
return builder.create();
}
private String normalizeColorCode(String code) {
if (code == null) return "";
code = code.trim();