Upload folder via GUI - src

This commit is contained in:
Git Manager GUI
2026-06-03 21:38:24 +02:00
parent 76c4c8a008
commit 4c4a1fa549
5 changed files with 435 additions and 0 deletions

View File

@@ -0,0 +1,214 @@
package de.sudoplugin;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
public class SudoCommand implements CommandExecutor, TabCompleter {
private final SudoPlugin plugin;
private final Map<String, String> commandMap = new LinkedHashMap<>();
// Cooldown: UUID des Ausführers -> Zeitpunkt letzter Nutzung (ms)
private final Map<UUID, Map<UUID, Long>> cooldownPerTarget = new HashMap<>();
private final Map<UUID, Long> cooldownGlobal = new HashMap<>();
public SudoCommand(SudoPlugin plugin) {
this.plugin = plugin;
loadCommands();
}
public void loadCommands() {
commandMap.clear();
File file = new File(plugin.getDataFolder(), "commands.yml");
if (!file.exists()) {
plugin.getLogger().warning("commands.yml nicht gefunden!");
return;
}
YamlConfiguration cfg = YamlConfiguration.loadConfiguration(file);
for (Map<?, ?> entry : cfg.getMapList("commands")) {
String name = (String) entry.get("name");
String args = entry.containsKey("args") ? (String) entry.get("args") : "";
if (name != null && !name.isBlank())
commandMap.put(name.toLowerCase(), args == null ? "" : args.toLowerCase());
}
plugin.getLogger().info(commandMap.size() + " Befehle aus commands.yml geladen.");
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
// /sudo reload
if (args.length == 1 && args[0].equalsIgnoreCase("reload")) {
if (!sender.hasPermission("sudoplugin.use")) {
sender.sendMessage(plugin.msg("no-permission"));
return true;
}
plugin.reloadConfig();
plugin.openLogFile();
loadCommands();
sender.sendMessage(plugin.msg("reload-success"));
return true;
}
if (args.length < 2) {
sender.sendMessage(plugin.msg("usage"));
return true;
}
// Konsolen-Check
boolean isConsole = !(sender instanceof Player);
if (isConsole && !plugin.getConfig().getBoolean("security.allow-console", true)) {
sender.sendMessage(plugin.msg("no-permission"));
return true;
}
if (!isConsole && !sender.hasPermission("sudoplugin.use")) {
sender.sendMessage(plugin.msg("no-permission"));
return true;
}
Player target = Bukkit.getPlayer(args[0]);
if (target == null) {
sender.sendMessage(plugin.msg("player-not-found", "{player}", args[0]));
return true;
}
// Self-sudo Check
if (!isConsole && !plugin.getConfig().getBoolean("security.allow-self-sudo", false)) {
if (((Player) sender).getUniqueId().equals(target.getUniqueId())) {
sender.sendMessage(plugin.msg("self-sudo-denied"));
return true;
}
}
// OP-Check
if (!isConsole && !plugin.getConfig().getBoolean("security.allow-sudo-on-op", false)) {
if (target.isOp() && !sender.isOp()) {
sender.sendMessage(plugin.msg("op-sudo-denied"));
return true;
}
}
// Blocked-Commands Check
List<String> blocked = plugin.getConfig().getStringList("security.blocked-commands");
if (blocked.stream().anyMatch(b -> b.equalsIgnoreCase(args[1]))) {
sender.sendMessage(plugin.msg("command-blocked"));
return true;
}
// Cooldown Check
if (!isConsole) {
Player senderPlayer = (Player) sender;
String bypassPerm = plugin.getConfig().getString("cooldown.bypass-permission", "sudoplugin.cooldown.bypass");
int cooldownSecs = plugin.getConfig().getInt("cooldown.seconds", 0);
boolean perTarget = plugin.getConfig().getBoolean("cooldown.per-target", false);
if (cooldownSecs > 0 && !senderPlayer.hasPermission(bypassPerm)) {
long now = System.currentTimeMillis();
long last = 0;
if (perTarget) {
last = cooldownPerTarget
.computeIfAbsent(senderPlayer.getUniqueId(), k -> new HashMap<>())
.getOrDefault(target.getUniqueId(), 0L);
} else {
last = cooldownGlobal.getOrDefault(senderPlayer.getUniqueId(), 0L);
}
long diff = (now - last) / 1000;
if (diff < cooldownSecs) {
long remaining = cooldownSecs - diff;
sender.sendMessage(plugin.msg("cooldown-active", "{seconds}", String.valueOf(remaining)));
return true;
}
// Cooldown setzen
if (perTarget) {
cooldownPerTarget.computeIfAbsent(senderPlayer.getUniqueId(), k -> new HashMap<>())
.put(target.getUniqueId(), now);
} else {
cooldownGlobal.put(senderPlayer.getUniqueId(), now);
}
}
}
// Befehl zusammenbauen & ausführen
StringBuilder fullCommand = new StringBuilder(args[1]);
for (int i = 2; i < args.length; i++) fullCommand.append(" ").append(args[i]);
String commandToRun = fullCommand.toString();
target.performCommand(commandToRun);
// Sender benachrichtigen
if (plugin.getConfig().getBoolean("notifications.notify-sender", true)) {
sender.sendMessage(plugin.msg("success", "{cmd}", commandToRun, "{player}", target.getName()));
}
// Zielspieler benachrichtigen
if (plugin.getConfig().getBoolean("notifications.notify-target", false)) {
String notifyMsg = SudoPlugin.colorize(
plugin.getConfig().getString("notifications.notify-message", "&eEin Admin hat einen Befehl als du ausgeführt."));
target.sendMessage(notifyMsg);
}
// Konsolen-Log
String logEntry = sender.getName() + " -> /" + commandToRun + " als " + target.getName();
if (plugin.getConfig().getBoolean("notifications.log-to-console", true)) {
plugin.getLogger().info(logEntry);
}
// Datei-Log
if (plugin.getConfig().getBoolean("notifications.log-to-file", false)) {
plugin.writeLog(logEntry);
}
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
boolean isConsole = !(sender instanceof Player);
if (!isConsole && !sender.hasPermission("sudoplugin.use")) return new ArrayList<>();
if (args.length == 1) {
return Bukkit.getOnlinePlayers().stream()
.map(Player::getName)
.filter(n -> n.toLowerCase().startsWith(args[0].toLowerCase()))
.collect(Collectors.toList());
}
if (args.length == 2) {
List<String> blocked = plugin.getConfig().getStringList("security.blocked-commands");
return commandMap.keySet().stream()
.filter(c -> c.startsWith(args[1].toLowerCase()))
.filter(c -> blocked.stream().noneMatch(b -> b.equalsIgnoreCase(c)))
.collect(Collectors.toList());
}
if (args.length == 3) {
String argType = commandMap.getOrDefault(args[1].toLowerCase(), "");
if (argType.equals("player")) {
return Bukkit.getOnlinePlayers().stream()
.map(Player::getName)
.filter(n -> n.toLowerCase().startsWith(args[2].toLowerCase()))
.collect(Collectors.toList());
}
if (argType.equals("gamemode")) {
return Arrays.asList("survival", "creative", "adventure", "spectator").stream()
.filter(m -> m.startsWith(args[2].toLowerCase()))
.collect(Collectors.toList());
}
}
return new ArrayList<>();
}
}

View File

@@ -0,0 +1,72 @@
package de.sudoplugin;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class SudoPlugin extends JavaPlugin {
private PrintWriter logWriter;
private static final DateTimeFormatter LOG_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public void onEnable() {
saveDefaultConfig();
if (!new File(getDataFolder(), "commands.yml").exists()) {
saveResource("commands.yml", false);
}
openLogFile();
SudoCommand sudoCommand = new SudoCommand(this);
getCommand("sudo").setExecutor(sudoCommand);
getCommand("sudo").setTabCompleter(sudoCommand);
getLogger().info("SudoPlugin aktiviert!");
}
@Override
public void onDisable() {
if (logWriter != null) logWriter.close();
getLogger().info("SudoPlugin deaktiviert!");
}
public void openLogFile() {
if (logWriter != null) { logWriter.close(); logWriter = null; }
if (!getConfig().getBoolean("notifications.log-to-file", false)) return;
try {
File logFile = new File(getDataFolder(), "sudo.log");
logWriter = new PrintWriter(new FileWriter(logFile, true), true);
} catch (IOException e) {
getLogger().warning("Konnte sudo.log nicht öffnen: " + e.getMessage());
}
}
public void writeLog(String entry) {
if (logWriter == null) return;
logWriter.println("[" + LocalDateTime.now().format(LOG_FORMAT) + "] " + entry);
}
/** Gibt eine formatierte Nachricht aus der config zurück. */
public String msg(String key) {
String prefix = colorize(getConfig().getString("messages.prefix", "&8[&cSudo&8] &r"));
String message = colorize(getConfig().getString("messages." + key, "&c[" + key + " fehlt in config.yml]"));
return prefix + message;
}
/** Wie msg(), aber mit Platzhalter-Ersetzung. */
public String msg(String key, String... replacements) {
String m = msg(key);
for (int i = 0; i + 1 < replacements.length; i += 2) {
m = m.replace(replacements[i], replacements[i + 1]);
}
return m;
}
public static String colorize(String s) {
return org.bukkit.ChatColor.translateAlternateColorCodes('&', s);
}
}

View File

@@ -0,0 +1,63 @@
# SudoPlugin - Verfügbare Befehle für Tab-Completion
# Hier kannst du Befehle hinzufügen oder entfernen.
#
# Format:
# - name: Befehlsname (ohne /)
# args: "player" # optionaler Typ für arg3-Completion
# # Mögliche Werte: player, gamemode, leer lassen wenn nichts
#
# Beispiel eigener Befehl:
# - name: meinbefehl
# args: ""
commands:
- name: msg
args: player
- name: tell
args: player
- name: w
args: player
- name: whisper
args: player
- name: me
args: ""
- name: say
args: ""
- name: tp
args: player
- name: tpa
args: player
- name: tpaccept
args: ""
- name: tpdeny
args: ""
- name: gamemode
args: gamemode
- name: give
args: ""
- name: fly
args: ""
- name: speed
args: ""
- name: heal
args: ""
- name: feed
args: ""
- name: spawn
args: ""
- name: home
args: ""
- name: sethome
args: ""
- name: warp
args: ""
- name: kit
args: ""
- name: pay
args: player
- name: balance
args: ""
- name: seen
args: player
- name: ignore
args: player

View File

@@ -0,0 +1,69 @@
# -----------------------------------------------
# SudoPlugin - Konfiguration
# -----------------------------------------------
# Sprache der Plugin-Nachrichten
# Verfügbare Werte: de, en
language: de
# -----------------------------------------------
# BENACHRICHTIGUNGEN
# -----------------------------------------------
notifications:
# Soll der Zielspieler informiert werden wenn ein Befehl als er ausgeführt wird?
notify-target: false
notify-message: "&eEin Admin hat einen Befehl als du ausgeführt."
# Soll der ausführende Spieler eine Bestätigungsnachricht sehen?
notify-sender: true
# Soll in der Konsole geloggt werden?
log-to-console: true
# Soll ein Eintrag in eine Log-Datei geschrieben werden? (plugins/SudoPlugin/sudo.log)
log-to-file: false
# -----------------------------------------------
# BERECHTIGUNGEN & SICHERHEIT
# -----------------------------------------------
security:
# Kann ein Spieler /sudo auf sich selbst ausführen?
allow-self-sudo: false
# Können Spieler mit sudoplugin.use auch andere OPs mit sudo ansprechen?
allow-sudo-on-op: false
# Kann /sudo auch von der Konsole aus genutzt werden?
allow-console: true
# Bestimmte Befehle komplett sperren (werden nie ausgeführt, egal was in commands.yml steht)
# Beispiel: [op, deop, stop]
blocked-commands: []
# -----------------------------------------------
# COOLDOWN
# -----------------------------------------------
cooldown:
# Cooldown zwischen sudo-Befehlen in Sekunden (0 = deaktiviert)
seconds: 0
# Soll der Cooldown pro Zielspieler gelten (true) oder global pro Ausführer (false)?
per-target: false
# Spieler mit dieser Permission sind vom Cooldown ausgenommen
bypass-permission: sudoplugin.cooldown.bypass
# -----------------------------------------------
# NACHRICHTEN-FORMAT
# -----------------------------------------------
messages:
prefix: "&8[&cSudo&8] &r"
no-permission: "&cDu hast keine Berechtigung."
player-not-found: "&cSpieler '{player}' ist nicht online."
usage: "&cVerwendung: /sudo <spieler> <befehl> [argumente...]"
success: "&aBefehl &f/{cmd} &awurde als &f{player} &aausgeführt."
self-sudo-denied: "&cDu kannst /sudo nicht auf dich selbst anwenden."
op-sudo-denied: "&cDu kannst /sudo nicht auf einen OP anwenden."
command-blocked: "&cDieser Befehl ist in der Konfiguration gesperrt."
cooldown-active: "&cBitte warte noch &f{seconds}s &cbevor du /sudo erneut nutzt."
reload-success: "&aKonfiguration erfolgreich neu geladen."

View File

@@ -0,0 +1,17 @@
name: SudoPlugin
version: 1.0.0
main: de.sudoplugin.SudoPlugin
api-version: 1.20
author: M_Viper
description: Lets admins run commands as other players
commands:
sudo:
description: Execute a command as another player
usage: /sudo <player> <command> [args...]
permission: sudoplugin.use
permissions:
sudoplugin.use:
description: Allows use of the /sudo command
default: op