Upload folder via GUI - src
This commit is contained in:
214
src/main/java/de/sudoplugin/SudoCommand.java
Normal file
214
src/main/java/de/sudoplugin/SudoCommand.java
Normal 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<>();
|
||||
}
|
||||
}
|
||||
72
src/main/java/de/sudoplugin/SudoPlugin.java
Normal file
72
src/main/java/de/sudoplugin/SudoPlugin.java
Normal 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);
|
||||
}
|
||||
}
|
||||
63
src/main/resources/commands.yml
Normal file
63
src/main/resources/commands.yml
Normal 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
|
||||
69
src/main/resources/config.yml
Normal file
69
src/main/resources/config.yml
Normal 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."
|
||||
17
src/main/resources/plugin.yml
Normal file
17
src/main/resources/plugin.yml
Normal 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
|
||||
Reference in New Issue
Block a user