Upload folder via GUI - src
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user