Upload folder via GUI - src

This commit is contained in:
Git Manager GUI
2026-04-07 19:55:07 +02:00
parent fa07b66b76
commit 1179398aed
3 changed files with 157 additions and 228 deletions

View File

@@ -0,0 +1,142 @@
package net.viper.statusapibridge;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class StatusAPIBridge extends JavaPlugin implements Listener {
private Economy economy;
private String statusApiUrl;
private int pushDelayTicks;
private int liveSyncIntervalTicks;
private final Map<UUID, Double> lastPushedBalance = new ConcurrentHashMap<>();
private final ExecutorService httpExecutor = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r, "StatusAPIBridge-HTTP");
t.setDaemon(true);
return t;
});
@Override
public void onEnable() {
saveDefaultConfig();
statusApiUrl = getConfig().getString("statusapi-url", "http://127.0.0.1:9191").trim();
pushDelayTicks = getConfig().getInt("push-delay-ticks", 40);
liveSyncIntervalTicks = Math.max(20, getConfig().getInt("live-sync-interval-ticks", 20));
if (!setupEconomy()) {
getLogger().warning("Vault/Economy nicht gefunden Economy-Push deaktiviert.");
} else {
getLogger().info("Vault Economy gefunden: " + economy.getName());
}
Bukkit.getPluginManager().registerEvents(this, this);
// Live-Sync: Alle X Ticks online Spieler prüfen und bei Balance-Änderung pushen.
Bukkit.getScheduler().runTaskTimer(this, this::pushChangedBalancesForOnlinePlayers, liveSyncIntervalTicks, liveSyncIntervalTicks);
getLogger().info("StatusAPIBridge gestartet. Ziel: " + statusApiUrl);
}
@Override
public void onDisable() {
httpExecutor.shutdownNow();
}
private boolean setupEconomy() {
if (getServer().getPluginManager().getPlugin("Vault") == null) return false;
RegisteredServiceProvider<Economy> rsp = getServer().getServicesManager().getRegistration(Economy.class);
if (rsp == null) return false;
economy = rsp.getProvider();
return economy != null;
}
@EventHandler(priority = EventPriority.MONITOR)
public void onJoin(PlayerJoinEvent e) {
if (economy == null) return;
Player player = e.getPlayer();
// Verzögert pushen, damit das Economy-Plugin den Account vollständig geladen hat
Bukkit.getScheduler().runTaskLater(this, () -> {
if (player.isOnline()) pushEconomy(player);
}, pushDelayTicks);
}
@EventHandler(priority = EventPriority.MONITOR)
public void onQuit(PlayerQuitEvent e) {
if (economy == null) return;
Player player = e.getPlayer();
// Synchron lesen, dann async senden
double balance = economy.getBalance(player);
pushEconomyAsync(player.getUniqueId(), player.getName(), balance);
lastPushedBalance.remove(player.getUniqueId());
}
public void pushEconomy(Player player) {
double balance = economy.getBalance(player);
pushEconomyAsync(player.getUniqueId(), player.getName(), balance);
}
private void pushEconomyAsync(UUID uuid, String name, double balance) {
httpExecutor.execute(() -> {
try {
String json = "{\"uuid\":\"" + uuid + "\",\"name\":\"" + escapeName(name) + "\",\"balance\":" + balance + "}";
sendPost(statusApiUrl + "/economy/update", json);
lastPushedBalance.put(uuid, balance);
} catch (Exception e) {
getLogger().warning("Economy-Push fehlgeschlagen fuer " + name + ": " + e.getMessage());
}
});
}
private void pushChangedBalancesForOnlinePlayers() {
if (economy == null) return;
for (Player player : Bukkit.getOnlinePlayers()) {
double current = economy.getBalance(player);
Double last = lastPushedBalance.get(player.getUniqueId());
if (last == null || Math.abs(current - last) > 0.000001d) {
pushEconomyAsync(player.getUniqueId(), player.getName(), current);
}
}
}
private void sendPost(String urlStr, String json) throws Exception {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setConnectTimeout(3000);
conn.setReadTimeout(3000);
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
byte[] body = json.getBytes(StandardCharsets.UTF_8);
conn.setRequestProperty("Content-Length", String.valueOf(body.length));
try (OutputStream os = conn.getOutputStream()) {
os.write(body);
}
int code = conn.getResponseCode();
if (code != 200) {
getLogger().warning("StatusAPI antwortete mit Code " + code + " fuer " + urlStr);
}
conn.disconnect();
}
private String escapeName(String name) {
if (name == null) return "";
return name.replace("\\", "\\\\").replace("\"", "\\\"");
}
}

View File

@@ -0,0 +1,8 @@
# URL der BungeeCord StatusAPI (kein Slash am Ende)
statusapi-url: "http://127.0.0.1:9191"
# Wie viele Ticks nach dem Join wird die Balance gepusht? (20 Ticks = 1 Sekunde)
push-delay-ticks: 40
# Live-Sync Intervall fuer Economy-Updates waehrend der Spieler online ist (mind. 20 Ticks = 1 Sekunde)
live-sync-interval-ticks: 20

View File

@@ -1,228 +1,7 @@
name: StatusAPI
main: net.viper.status.StatusAPI
version: 4.1.0
author: M_Viper
description: StatusAPI für BungeeCord inkl. Update-Checker, Modul-System und ChatModule
# Mindestanforderung: Minecraft 1.20 / BungeeCord mit PlayerChatEvent-Unterstützung
softdepend:
- LuckPerms
- Geyser-BungeeCord
commands:
# ── Verify Modul ──────────────────────────────────────────
verify:
description: Verifiziere dich mit einem Token
usage: /verify <token>
# ── ForumBridge Modul ─────────────────────────────────────
forumlink:
description: Verknüpfe deinen Minecraft-Account mit dem Forum
usage: /forumlink <token>
# ── NetworkInfo Modul ─────────────────────────────────────
netinfo:
description: Zeigt erweiterte Proxy- und Systeminfos an
usage: /netinfo
antibot:
description: Zeigt AntiBot-Status und Verwaltung
usage: /antibot <status|clearblocks|unblock|profile|reload>
# ── ChatModule Kanal ────────────────────────────────────
channel:
description: Kanal wechseln oder Kanalliste anzeigen
usage: /channel [kanalname]
aliases: [ch, kanal]
# ── ChatModule HelpOp ───────────────────────────────────
helpop:
description: Sende eine Hilfeanfrage an das Team
usage: /helpop <Nachricht>
# ── ChatModule Privat-Nachrichten ───────────────────────
msg:
description: Sende eine private Nachricht
usage: /msg <Spieler> <Nachricht>
aliases: [tell, w, whisper]
r:
description: Antworte auf die letzte private Nachricht
usage: /r <Nachricht>
aliases: [reply, antwort]
# ── ChatModule Blockieren ───────────────────────────────
ignore:
description: Spieler ignorieren
usage: /ignore <Spieler>
aliases: [block]
unignore:
description: Spieler nicht mehr ignorieren
usage: /unignore <Spieler>
aliases: [unblock]
# ── ChatModule Mute (Admin) ─────────────────────────────
chatmute:
description: Spieler im Chat stumm schalten
usage: /chatmute <Spieler> [Minuten]
aliases: [gmute]
chatunmute:
description: Chat-Stummschaltung aufheben
usage: /chatunmute <Spieler>
aliases: [gunmute]
# ── ChatModule Selbst-Mute ──────────────────────────────
chataus:
description: Eigenen Chat-Empfang ein-/ausschalten
usage: /chataus
aliases: [togglechat, chaton, chatoff]
# ── ChatModule Broadcast ────────────────────────────────
broadcast:
description: Nachricht an alle Spieler senden
usage: /broadcast <Nachricht>
aliases: [bc, alert]
# ── ChatModule Emoji ────────────────────────────────────
emoji:
description: Liste aller verfügbaren Emojis
usage: /emoji
aliases: [emojis]
# ── ChatModule Social Spy ───────────────────────────────
socialspy:
description: Private Nachrichten mitlesen (Admin)
usage: /socialspy
aliases: [spy]
# ── ChatModule Reload ───────────────────────────────────
chatreload:
description: Chat-Konfiguration neu laden
usage: /chatreload
# ── ChatModule Admin-Info ───────────────────────────────
chatinfo:
description: Chat-Informationen ueber einen Spieler anzeigen (Admin)
usage: /chatinfo <Spieler>
# ── ChatModule Chat-History ─────────────────────────────
chathist:
description: Chat-History aus dem Logfile anzeigen (Admin)
usage: /chathist [Spieler] [Anzahl]
# ── ChatModule Mentions ─────────────────────────────────
mentions:
description: Mention-Benachrichtigungen ein-/ausschalten
usage: /mentions
aliases: [mention]
# ── ChatModule Plugin-Bypass ────────────────────────────
chatbypass:
description: ChatModule fuer naechste Eingabe ueberspringen (fuer Plugin-Dialoge wie CMI)
usage: /chatbypass
aliases: [cbp]
# ── ChatModule Account-Verknuepfung ─────────────────────
linkdiscord:
description: Minecraft-Account mit Discord verknuepfen
usage: /linkdiscord
aliases: [discordlink]
linktelegram:
description: Minecraft-Account mit Telegram verknuepfen
usage: /linktelegram
aliases: [telegramlink]
unlink:
description: Account-Verknuepfung aufheben
usage: /unlink <discord|telegram|all>
# ── ChatModule Report ───────────────────────────────────
report:
description: Spieler melden
usage: /report <Spieler> <Grund>
reports:
description: Offene Reports anzeigen (Admin)
usage: /reports [all]
reportclose:
description: Report schliessen (Admin)
usage: /reportclose <ID>
permissions:
# ── StatusAPI Core ────────────────────────────────────────
statusapi.update.notify:
description: Erlaubt Update-Benachrichtigungen
default: op
statusapi.netinfo:
description: Zugriff auf /netinfo
default: op
statusapi.antibot:
description: Zugriff auf /antibot
default: op
# ── ChatModule Kanaele ──────────────────────────────────
chat.channel.local:
description: Zugang zum Local-Kanal
default: true
chat.channel.trade:
description: Zugang zum Trade-Kanal
default: true
chat.channel.staff:
description: Zugang zum Staff-Kanal
default: false
# ── ChatModule HelpOp ───────────────────────────────────
chat.helpop.receive:
description: HelpOp-Nachrichten empfangen
default: false
# ── ChatModule Mute ─────────────────────────────────────
chat.mute:
description: Spieler muten / unmuten
default: false
# ── ChatModule Broadcast ────────────────────────────────
chat.broadcast:
description: Broadcast-Nachrichten senden
default: false
# ── ChatModule Social Spy ───────────────────────────────
chat.socialspy:
description: Private Nachrichten mitlesen
default: false
# ── ChatModule Admin ────────────────────────────────────
chat.admin.bypass:
description: Admin-Bypass - Kann nicht geblockt/gemutet werden
default: op
chat.admin.notify:
description: Benachrichtigungen ueber Mutes und Blocks erhalten
default: false
# ── ChatModule Report ───────────────────────────────────
chat.report:
description: Spieler reporten (/report)
default: true
# ── ChatModule Farben ───────────────────────────────────
chat.color:
description: Farbcodes (&a, &b, ...) im Chat nutzen
default: false
chat.color.format:
description: Formatierungen (&l, &o, &n, ...) im Chat nutzen
default: false
# ── ChatModule Filter ───────────────────────────────────
chat.filter.bypass:
description: Chat-Filter (Anti-Spam, Caps, Blacklist) umgehen
default: false
name: StatusAPIBridge
version: 1.0.0
main: net.viper.statusapibridge.StatusAPIBridge
api-version: 1.21
description: Sendet Vault-Economy-Daten an die BungeeCord StatusAPI
authors: [Viper]
softdepend: [Vault]