9 Commits

16 changed files with 1872 additions and 583 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# Ignoriere Build-Ordner
target/
# Ignoriere ZIP-Dateien
*.zip

View File

@@ -6,7 +6,8 @@
<groupId>de.viper</groupId> <groupId>de.viper</groupId>
<artifactId>SurvivalPlus</artifactId> <artifactId>SurvivalPlus</artifactId>
<version>1.0.5-Beta</version> <version>1.0.9-Beta</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>SurvivalPlus</name> <name>SurvivalPlus</name>
@@ -111,6 +112,8 @@
<include>shop.yml</include> <include>shop.yml</include>
<include>warps.yml</include> <include>warps.yml</include>
<include>tablist.yml</include> <include>tablist.yml</include>
<include>blockedcommands.yml</include>
<include>claims.yml</include>
</includes> </includes>
</resource> </resource>
</resources> </resources>

View File

@@ -0,0 +1,193 @@
package de.viper.survivalplus.Manager;
import de.viper.survivalplus.SurvivalPlus;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class CommandBlocker implements Listener, CommandExecutor {
private final SurvivalPlus plugin;
private FileConfiguration blockedCommandsConfig;
private File blockedCommandsFile;
private List<String> blockedCommands;
public CommandBlocker(SurvivalPlus plugin) {
this.plugin = plugin;
// Lade blockedcommands.yml
try {
blockedCommandsFile = new File(plugin.getDataFolder(), "blockedcommands.yml");
if (!blockedCommandsFile.exists()) {
plugin.saveResource("blockedcommands.yml", false);
}
blockedCommandsConfig = YamlConfiguration.loadConfiguration(blockedCommandsFile);
blockedCommands = blockedCommandsConfig.getStringList("blocked-commands");
if (blockedCommands == null) {
blockedCommands = new ArrayList<>();
}
} catch (Exception ignored) {
blockedCommands = new ArrayList<>();
}
// Registriere Listener und Command
plugin.getServer().getPluginManager().registerEvents(this, plugin);
plugin.getCommand("sp").setExecutor(this);
}
/**
* Verarbeitet /sp cb Befehle
*/
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length < 2 || !args[0].equalsIgnoreCase("cb")) {
return false; // Wird von anderen /sp Subcommands behandelt
}
String subCommand = args[1].toLowerCase();
switch (subCommand) {
case "add":
return handleAddCommand(sender, args);
case "remove":
return handleRemoveCommand(sender, args);
case "list":
return handleListCommand(sender);
default:
sender.sendMessage("§cUnbekannter Subcommand! Verfügbare Subcommands: add, remove, list");
return true;
}
}
/**
* /sp cb add <command>
*/
private boolean handleAddCommand(CommandSender sender, String[] args) {
if (!sender.hasPermission("survivalplus.commandblocker.add")) {
sender.sendMessage("§cDu hast keine Berechtigung für diesen Befehl!");
return true;
}
if (args.length < 3) {
sender.sendMessage("§eBenutzung: /sp cb add <command>");
return true;
}
String commandToBlock = args[2].toLowerCase().replaceFirst("^/", "").trim();
if (commandToBlock.isEmpty()) {
sender.sendMessage("§cBitte gib einen gültigen Befehl an!");
return true;
}
try {
if (blockedCommands.contains(commandToBlock)) {
sender.sendMessage("§cDer Befehl §e/" + commandToBlock + "§c ist bereits blockiert!");
return true;
}
blockedCommands.add(commandToBlock);
blockedCommandsConfig.set("blocked-commands", blockedCommands);
blockedCommandsConfig.save(blockedCommandsFile);
sender.sendMessage("§aDer Befehl §e/" + commandToBlock + "§a wurde zur Blockierliste hinzugefügt.");
} catch (Exception ignored) {
sender.sendMessage("§cFehler beim Hinzufügen des Befehls!");
}
return true;
}
/**
* /sp cb remove <command>
*/
private boolean handleRemoveCommand(CommandSender sender, String[] args) {
if (!sender.hasPermission("survivalplus.commandblocker.remove")) {
sender.sendMessage("§cDu hast keine Berechtigung für diesen Befehl!");
return true;
}
if (args.length < 3) {
sender.sendMessage("§eBenutzung: /sp cb remove <command>");
return true;
}
String commandToUnblock = args[2].toLowerCase().replaceFirst("^/", "").trim();
if (commandToUnblock.isEmpty()) {
sender.sendMessage("§cBitte gib einen gültigen Befehl an!");
return true;
}
try {
if (!blockedCommands.contains(commandToUnblock)) {
sender.sendMessage("§cDer Befehl §e/" + commandToUnblock + "§c ist nicht blockiert!");
return true;
}
blockedCommands.remove(commandToUnblock);
blockedCommandsConfig.set("blocked-commands", blockedCommands);
blockedCommandsConfig.save(blockedCommandsFile);
sender.sendMessage("§aDer Befehl §e/" + commandToUnblock + "§a wurde aus der Blockierliste entfernt.");
} catch (Exception ignored) {
sender.sendMessage("§cFehler beim Entfernen des Befehls!");
}
return true;
}
/**
* /sp cb list
*/
private boolean handleListCommand(CommandSender sender) {
if (!sender.hasPermission("survivalplus.commandblocker.list")) {
sender.sendMessage("§cDu hast keine Berechtigung für diesen Befehl!");
return true;
}
try {
if (blockedCommands.isEmpty()) {
sender.sendMessage("§eEs sind keine Befehle blockiert.");
return true;
}
sender.sendMessage("§6=== Blockierte Befehle ===");
for (String cmd : blockedCommands) {
sender.sendMessage("§e- /" + cmd);
}
sender.sendMessage("§6=====================");
} catch (Exception ignored) {
sender.sendMessage("§cFehler beim Abrufen der Blockierliste!");
}
return true;
}
/**
* Blockiere Befehle, wenn sie in der Liste sind
*/
@EventHandler
public void onPlayerCommand(PlayerCommandPreprocessEvent event) {
Player player = event.getPlayer();
if (player.hasPermission("survivalplus.commandblocker.bypass")) {
return; // Spieler mit Bypass-Berechtigung ignorieren
}
try {
String command = event.getMessage().toLowerCase().replaceFirst("^/", "").trim();
// Extrahiere den Hauptbefehl (ohne Argumente)
String mainCommand = command.split("\\s+")[0];
if (blockedCommands.contains(mainCommand)) {
event.setCancelled(true);
player.sendMessage("§cDieser Befehl ist blockiert!");
}
} catch (Exception ignored) {
// Keine Konsolenausgabe
}
}
}

View File

@@ -3,21 +3,30 @@ package de.viper.survivalplus.Manager;
import de.viper.survivalplus.SurvivalPlus; import de.viper.survivalplus.SurvivalPlus;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.ScoreboardManager;
import org.bukkit.scoreboard.Team;
import me.clip.placeholderapi.PlaceholderAPI; import me.clip.placeholderapi.PlaceholderAPI;
import net.luckperms.api.LuckPerms; import net.luckperms.api.LuckPerms;
import net.luckperms.api.LuckPermsProvider; import net.luckperms.api.LuckPermsProvider;
import net.luckperms.api.model.user.User; import net.luckperms.api.model.user.User;
import java.io.File;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.Map;
public class TablistManager { public class TablistManager implements Listener {
private final SurvivalPlus plugin; private final SurvivalPlus plugin;
private final List<String> headerAnim = new ArrayList<>(); private final List<String> headerAnim = new ArrayList<>();
@@ -34,15 +43,45 @@ public class TablistManager {
private String staffPermission; private String staffPermission;
private String separatorLine; private String separatorLine;
private LuckPerms luckPerms; private LuckPerms luckPerms;
private boolean hasPlaceholderAPI;
private final Scoreboard scoreboard;
private final Map<String, Team> prefixTeams;
private FileConfiguration nicknameConfig;
public TablistManager(SurvivalPlus plugin) { public TablistManager(SurvivalPlus plugin) {
this.plugin = plugin; this.plugin = plugin;
this.prefixTeams = new HashMap<>();
// Scoreboard initialisieren
ScoreboardManager scoreboardManager = Bukkit.getScoreboardManager();
this.scoreboard = scoreboardManager != null ? scoreboardManager.getMainScoreboard() : null;
// Resource sicherstellen, Config laden // Resource sicherstellen, Config laden
try { plugin.saveResource("tablist.yml", false); } catch (Exception ignored) {} try {
try { plugin.reloadTablistConfig(); } catch (Throwable ignored) {} File tablistFile = new File(plugin.getDataFolder(), "tablist.yml");
if (!tablistFile.exists()) {
plugin.saveResource("tablist.yml", false);
}
} catch (Exception ignored) {}
try {
plugin.reloadTablistConfig();
} catch (Exception ignored) {}
FileConfiguration config = plugin.getTablistConfig(); FileConfiguration config = plugin.getTablistConfig();
// Nicknames.yml laden
try {
File nicknameFile = new File(plugin.getDataFolder(), "nicknames.yml");
if (!nicknameFile.exists()) {
plugin.saveResource("nicknames.yml", false);
}
this.nicknameConfig = YamlConfiguration.loadConfiguration(nicknameFile);
} catch (Exception ignored) {
this.nicknameConfig = null; // Keine Konsolenausgabe
}
// Konfigurationswerte laden // Konfigurationswerte laden
this.enabled = config.getBoolean("enabled", true); this.enabled = config.getBoolean("enabled", true);
this.serverName = config.getString("server-name", "SurvivalPlus"); this.serverName = config.getString("server-name", "SurvivalPlus");
@@ -57,13 +96,16 @@ public class TablistManager {
// LuckPerms API initialisieren // LuckPerms API initialisieren
try { try {
this.luckPerms = LuckPermsProvider.get(); this.luckPerms = LuckPermsProvider.get();
} catch (IllegalStateException e) { } catch (Throwable e) {
plugin.getLogger().warning("LuckPerms nicht gefunden! Versuche Fallback auf PlaceholderAPI."); luckPerms = null; // Keine Konsolenausgabe
} }
// Prüfen, ob PlaceholderAPI verfügbar ist // Prüfen, ob PlaceholderAPI verfügbar ist
if (!Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) { this.hasPlaceholderAPI = Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI");
plugin.getLogger().warning("PlaceholderAPI nicht gefunden! Verwende Standard-Prefix als Fallback.");
// Chat-Listener registrieren
if (enabled) {
Bukkit.getPluginManager().registerEvents(this, plugin);
} }
if (!enabled) { if (!enabled) {
@@ -112,17 +154,29 @@ public class TablistManager {
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Bukkit.getOnlinePlayers()) {
try { try {
// Spieler-Prefix abrufen (LuckPerms primär, PlaceholderAPI als Fallback) // Nickname oder Spielername verwenden
String prefix = getPlayerPrefix(player); String displayName = getNickname(player);
int ping = getPlayerPing(player); if (displayName == null || displayName.trim().isEmpty()) {
// Korrigierte Formatierung: Gesamten String durch color-Methode leiten displayName = player.getName();
String prefixedName = color(prefix + player.getName() + "&8 | &e" + ping + "ms"); }
player.setPlayerListName(prefixedName);
// Header mit Spielername und Statistiken // Spielername für die Tablist setzen
String playerListName;
String prefix = getPlayerPrefix(player);
if (luckPerms == null && !hasPlaceholderAPI) {
playerListName = displayName;
updateNametag(player, "", displayName);
} else {
int ping = getPlayerPing(player);
playerListName = color(prefix + displayName + (ping >= 0 ? "&8 | &e" + ping + "ms" : ""));
updateNametag(player, prefix, displayName);
}
player.setPlayerListName(playerListName);
// Header mit Spielername/Nickname und Statistiken
String headerRaw = headerAnim.get(headerIndex) String headerRaw = headerAnim.get(headerIndex)
.replace("{server}", serverName) .replace("{server}", serverName)
.replace("{player}", player.getName()) .replace("{player}", displayName)
.replace("{online}", String.valueOf(onlinePlayers)) .replace("{online}", String.valueOf(onlinePlayers))
.replace("{staff}", String.valueOf(onlineStaff)); .replace("{staff}", String.valueOf(onlineStaff));
String footerRaw = footerAnim.get(footerIndex); String footerRaw = footerAnim.get(footerIndex);
@@ -161,12 +215,9 @@ public class TablistManager {
done = tryStringMethod(player, header, footer); done = tryStringMethod(player, header, footer);
} }
// 3) Wenn alles fehlschlägt -> Log // 3) Keine Warnung bei Fehlschlag, da dies normal sein kann
if (!done) { } catch (Exception ignored) {
plugin.getLogger().warning("Tablist: Keine geeignete Methode gefunden für Spieler " + player.getName()); // Keine Konsolenausgabe für Fehler bei der Tablist
}
} catch (Throwable t) {
plugin.getLogger().log(Level.FINE, "Fehler beim Setzen der Tablist für Spieler " + player.getName(), t);
} }
} }
@@ -176,28 +227,170 @@ public class TablistManager {
}.runTaskTimer(plugin, 0L, interval); }.runTaskTimer(plugin, 0L, interval);
} }
/**
* Nickname aus nicknames.yml abrufen
*/
private String getNickname(Player player) {
if (nicknameConfig == null) return null;
try {
String uuid = player.getUniqueId().toString();
String nickname = nicknameConfig.getString(uuid);
if (nickname != null && !nickname.trim().isEmpty()) {
try {
File debugFile = new File(plugin.getDataFolder(), "debug.yml");
FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile);
debugConfig.set(player.getUniqueId().toString() + ".nickname", nickname);
debugConfig.save(debugFile);
} catch (Exception ignored) {}
return nickname;
}
} catch (Exception ignored) {
// Keine Konsolenausgabe
}
return null;
}
/**
* Nametag über dem Kopf aktualisieren
*/
private void updateNametag(Player player, String prefix, String displayName) {
if (scoreboard == null) return;
try {
String teamName = generateTeamName(player, prefix);
Team team = scoreboard.getTeam(teamName);
// Team erstellen oder aktualisieren
if (team == null) {
team = scoreboard.registerNewTeam(teamName);
}
// Prefix zwingend setzen, wenn LuckPerms installiert ist
String coloredPrefix = color(prefix != null && !prefix.trim().isEmpty() ? prefix : (luckPerms != null ? "&7[Spieler] " : ""));
team.setPrefix(coloredPrefix);
// Spieler dem Team hinzufügen
String entry = displayName != null && !displayName.trim().isEmpty() ? displayName : player.getName();
if (!team.hasEntry(entry)) {
// Spieler aus anderen Teams entfernen, um Konflikte zu vermeiden
for (Team existingTeam : scoreboard.getTeams()) {
if (!existingTeam.getName().equals(teamName)) {
existingTeam.removeEntry(entry);
existingTeam.removeEntry(player.getName());
}
}
team.addEntry(entry);
}
// Team für alle Spieler sichtbar machen
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
if (onlinePlayer.getScoreboard() != scoreboard) {
onlinePlayer.setScoreboard(scoreboard);
}
}
// Debug-Ausgabe für Nametag
try {
File debugFile = new File(plugin.getDataFolder(), "debug.yml");
FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile);
debugConfig.set(player.getUniqueId().toString() + ".nametag_prefix", coloredPrefix);
debugConfig.set(player.getUniqueId().toString() + ".nametag_entry", entry);
debugConfig.save(debugFile);
} catch (Exception ignored) {}
} catch (Exception ignored) {
// Keine Konsolenausgabe
}
}
/**
* Eindeutigen Teamnamen generieren
*/
private String generateTeamName(Player player, String prefix) {
// Verwende UUID für eindeutige Teamnamen, falls kein Prefix vorhanden
if (prefix == null || prefix.trim().isEmpty()) {
return "nametag_" + player.getUniqueId().toString().substring(0, 8);
}
// Verwende Prefix für Teamnamen, max 16 Zeichen (Bukkit-Beschränkung)
String sanitizedPrefix = prefix.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();
return "prefix_" + sanitizedPrefix.substring(0, Math.min(sanitizedPrefix.length(), 12));
}
/** /**
* Spieler-Prefix abrufen (LuckPerms primär, PlaceholderAPI als Fallback) * Spieler-Prefix abrufen (LuckPerms primär, PlaceholderAPI als Fallback)
*/ */
private String getPlayerPrefix(Player player) { private String getPlayerPrefix(Player player) {
// Versuche LuckPerms-API zuerst // Wenn LuckPerms installiert ist, Prefix zwingend abrufen
if (luckPerms != null) { if (luckPerms != null) {
// Versuche LuckPerms-API zuerst
try { try {
User user = luckPerms.getPlayerAdapter(Player.class).getUser(player); User user = luckPerms.getPlayerAdapter(Player.class).getUser(player);
String prefix = user.getCachedData().getMetaData().getPrefix(); String prefix = user.getCachedData().getMetaData().getPrefix();
return (prefix == null || prefix.isEmpty()) ? "&7[Spieler] " : prefix + " "; if (prefix != null && !prefix.trim().isEmpty()) {
} catch (Exception e) { try {
plugin.getLogger().log(Level.FINE, "Fehler beim Abrufen des Prefix aus LuckPerms für Spieler " + player.getName(), e); File debugFile = new File(plugin.getDataFolder(), "debug.yml");
FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile);
debugConfig.set(player.getUniqueId().toString() + ".prefix", prefix);
debugConfig.save(debugFile);
} catch (Exception ignored) {}
return prefix + " ";
} }
} catch (Exception ignored) {
// Keine Konsolenausgabe
} }
// Fallback auf PlaceholderAPI // Fallback auf PlaceholderAPI, wenn LuckPerms installiert ist
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) { if (hasPlaceholderAPI) {
try {
String prefix = PlaceholderAPI.setPlaceholders(player, "%luckperms_prefix%"); String prefix = PlaceholderAPI.setPlaceholders(player, "%luckperms_prefix%");
return (prefix == null || prefix.isEmpty()) ? "&7[Spieler] " : prefix + " "; if (prefix != null && !prefix.trim().isEmpty()) {
try {
File debugFile = new File(plugin.getDataFolder(), "debug.yml");
FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile);
debugConfig.set(player.getUniqueId().toString() + ".prefix", prefix);
debugConfig.save(debugFile);
} catch (Exception ignored) {}
return prefix + " ";
}
} catch (Exception ignored) {
// Keine Konsolenausgabe
}
} }
// Letzter Fallback: Standard-Prefix // Standard-Prefix, wenn LuckPerms installiert ist, aber kein Prefix definiert
try {
File debugFile = new File(plugin.getDataFolder(), "debug.yml");
FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile);
debugConfig.set(player.getUniqueId().toString() + ".prefix", "&7[Spieler]");
debugConfig.save(debugFile);
} catch (Exception ignored) {}
return "&7[Spieler] ";
}
// Wenn LuckPerms nicht installiert ist, aber PlaceholderAPI vorhanden ist
if (hasPlaceholderAPI) {
try {
String prefix = PlaceholderAPI.setPlaceholders(player, "%luckperms_prefix%");
if (prefix != null && !prefix.trim().isEmpty()) {
try {
File debugFile = new File(plugin.getDataFolder(), "debug.yml");
FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile);
debugConfig.set(player.getUniqueId().toString() + ".prefix", prefix);
debugConfig.save(debugFile);
} catch (Exception ignored) {}
return prefix + " ";
}
} catch (Exception ignored) {
// Keine Konsolenausgabe
}
}
// Standard-Prefix, wenn weder LuckPerms noch PlaceholderAPI einen Prefix liefern
try {
File debugFile = new File(plugin.getDataFolder(), "debug.yml");
FileConfiguration debugConfig = YamlConfiguration.loadConfiguration(debugFile);
debugConfig.set(player.getUniqueId().toString() + ".prefix", "&7[Spieler]");
debugConfig.save(debugFile);
} catch (Exception ignored) {}
return "&7[Spieler] "; return "&7[Spieler] ";
} }
@@ -209,9 +402,28 @@ public class TablistManager {
Method getHandle = player.getClass().getMethod("getHandle"); Method getHandle = player.getClass().getMethod("getHandle");
Object entityPlayer = getHandle.invoke(player); Object entityPlayer = getHandle.invoke(player);
return entityPlayer.getClass().getField("ping").getInt(entityPlayer); return entityPlayer.getClass().getField("ping").getInt(entityPlayer);
} catch (Exception e) { } catch (Exception ignored) {
plugin.getLogger().log(Level.FINE, "Fehler beim Abrufen des Pings für Spieler " + player.getName(), e); return -1; // Keine Konsolenausgabe
return -1; }
}
/**
* Chat-Format modifizieren
*/
@EventHandler
public void onPlayerChat(AsyncPlayerChatEvent event) {
try {
Player player = event.getPlayer();
String displayName = getNickname(player);
if (displayName == null || displayName.trim().isEmpty()) {
displayName = player.getName();
}
String prefix = getPlayerPrefix(player);
String format = color(prefix + displayName + "&7: &f") + "%2$s";
event.setFormat(format);
} catch (Exception ignored) {
// Keine Konsolenausgabe
} }
} }
@@ -225,7 +437,9 @@ public class TablistManager {
try { try {
textMethod = compClass.getMethod("text", CharSequence.class); textMethod = compClass.getMethod("text", CharSequence.class);
} catch (NoSuchMethodException ignored) { } catch (NoSuchMethodException ignored) {
try { textMethod = compClass.getMethod("text", String.class); } catch (NoSuchMethodException ignored2) {} try {
textMethod = compClass.getMethod("text", String.class);
} catch (NoSuchMethodException ignored2) {}
} }
Object headerComp = null; Object headerComp = null;
@@ -243,8 +457,8 @@ public class TablistManager {
Method deserialize = miniMsgClass.getMethod("deserialize", String.class); Method deserialize = miniMsgClass.getMethod("deserialize", String.class);
headerComp = deserialize.invoke(miniMsg, headerRaw); headerComp = deserialize.invoke(miniMsg, headerRaw);
footerComp = deserialize.invoke(miniMsg, footerRaw); footerComp = deserialize.invoke(miniMsg, footerRaw);
} catch (Throwable t) { } catch (Exception ignored) {
// kein MiniMessage // Kein MiniMessage
} }
} }
@@ -265,10 +479,7 @@ public class TablistManager {
return true; return true;
} }
} }
} catch (ClassNotFoundException cnf) { } catch (Exception ignored) {
return false;
} catch (Throwable t) {
plugin.getLogger().log(Level.FINER, "Adventure-Variante fehlgeschlagen: " + t.getMessage());
return false; return false;
} }
return false; return false;
@@ -295,8 +506,7 @@ public class TablistManager {
mf.invoke(player, footer); mf.invoke(player, footer);
return true; return true;
} }
} catch (Throwable t) { } catch (Exception ignored) {
plugin.getLogger().log(Level.FINER, "String-Variante fehlgeschlagen: " + t.getMessage());
return false; return false;
} }
return false; return false;

View File

@@ -11,6 +11,7 @@ import de.viper.survivalplus.recipe.BackpackRecipe;
import de.viper.survivalplus.Manager.StatsManager; import de.viper.survivalplus.Manager.StatsManager;
import de.viper.survivalplus.Manager.BlockManager; import de.viper.survivalplus.Manager.BlockManager;
import de.viper.survivalplus.util.LockSystem; import de.viper.survivalplus.util.LockSystem;
import de.viper.survivalplus.util.Claim;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
@@ -34,28 +35,23 @@ import de.viper.survivalplus.commands.ReportCommand;
import de.viper.survivalplus.Manager.ShopManager; import de.viper.survivalplus.Manager.ShopManager;
import de.viper.survivalplus.commands.HealCommand; import de.viper.survivalplus.commands.HealCommand;
import de.viper.survivalplus.Manager.TablistManager; import de.viper.survivalplus.Manager.TablistManager;
import de.viper.survivalplus.Manager.CommandBlocker;
import de.viper.survivalplus.Manager.WarpManager; import de.viper.survivalplus.Manager.WarpManager;
import de.viper.survivalplus.commands.SetWarpCommand; import de.viper.survivalplus.commands.SetWarpCommand;
import de.viper.survivalplus.commands.WarpsCommand; import de.viper.survivalplus.commands.WarpsCommand;
import de.viper.survivalplus.fun.FunChallengeManager; import de.viper.survivalplus.fun.FunChallengeManager;
import de.viper.survivalplus.listeners.ChallengeCollectListener; import de.viper.survivalplus.listeners.ChallengeCollectListener;
import de.viper.survivalplus.commands.StartFunChallengeCommand; import de.viper.survivalplus.commands.StartFunChallengeCommand;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.HashMap; import java.util.HashMap;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.logging.Level; import java.util.logging.Level;
// Zusätzliche Imports für Block-/Permission-Handling
import org.bukkit.GameRule; import org.bukkit.GameRule;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@@ -65,6 +61,17 @@ import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault; import org.bukkit.permissions.PermissionDefault;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import java.util.ArrayList;
import java.util.List;
import de.viper.survivalplus.util.BannerManager;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.charset.StandardCharsets;
public class SurvivalPlus extends JavaPlugin { public class SurvivalPlus extends JavaPlugin {
@@ -87,15 +94,12 @@ public class SurvivalPlus extends JavaPlugin {
private FileConfiguration mobCapConfig; private FileConfiguration mobCapConfig;
private FileConfiguration tablistConfig; private FileConfiguration tablistConfig;
private File tablistFile; private File tablistFile;
private File nicknamesFile; private File nicknamesFile;
private FileConfiguration nicknamesConfig; private FileConfiguration nicknamesConfig;
private SpawnProtectionListener spawnProtectionListener; private SpawnProtectionListener spawnProtectionListener;
private int autoClearTaskId = -1; private int autoClearTaskId = -1;
private StatsManager statsManager; private StatsManager statsManager;
private NewbieProtectionListener newbieListener; private NewbieProtectionListener newbieListener;
// Listener als Felder speichern
private MobLeashLimitListener mobLeashLimitListener; private MobLeashLimitListener mobLeashLimitListener;
private MobCapListener mobCapListener; private MobCapListener mobCapListener;
private SleepListener sleepListener; private SleepListener sleepListener;
@@ -107,41 +111,112 @@ public class SurvivalPlus extends JavaPlugin {
private FunChallengeManager challengeManager; private FunChallengeManager challengeManager;
private NamespacedKey droppedKey; private NamespacedKey droppedKey;
private Map<UUID, Integer> progressMap = new HashMap<>(); private Map<UUID, Integer> progressMap = new HashMap<>();
// WarpManager als Feld
private WarpManager warpManager; private WarpManager warpManager;
// FunChallengeManager als Feld
private FunChallengeManager funChallengeManager; private FunChallengeManager funChallengeManager;
private File blockedCommandsFile;
private FileConfiguration blockedCommandsConfig;
private LockSystem lockSystem;
private PluginCommand pluginCommand;
private Map<String, Claim> claims = new HashMap<>();
private File claimsFile;
private FileConfiguration claimsConfig;
private Map<UUID, Integer> playerClaimCounts = new HashMap<>();
private Map<UUID, Location> point1Selections = new HashMap<>();
private Map<UUID, Location> point2Selections = new HashMap<>();
private BannerManager bannerManager;
private File debugFile;
private PrintWriter debugWriter;
private File consoleFile;
private PrintWriter consoleWriter;
// ------------------- Tablist Config -------------------
public void reloadTablistConfig() { public void reloadTablistConfig() {
// Lädt die tablist.yml aus dem Plugin-Ordner neu
if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml"); if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml");
if (!tablistFile.exists()) { if (!tablistFile.exists()) {
saveResource("tablist.yml", false); // kopiert die default tablist.yml, falls sie fehlt saveResource("tablist.yml", false);
} }
tablistConfig = YamlConfiguration.loadConfiguration(tablistFile); tablistConfig = YamlConfiguration.loadConfiguration(tablistFile);
} }
public FileConfiguration getTablistConfig() { public FileConfiguration getTablistConfig() {
// Stellt sicher, dass die Config geladen ist
if (tablistConfig == null) { if (tablistConfig == null) {
reloadTablistConfig(); reloadTablistConfig();
} }
return tablistConfig; return tablistConfig;
} }
public void reloadBlockedCommandsConfig() {
if (blockedCommandsFile == null) blockedCommandsFile = new File(getDataFolder(), "blockedcommands.yml");
if (!blockedCommandsFile.exists()) {
try {
saveResource("blockedcommands.yml", false);
} catch (IllegalArgumentException e) {
getLogger().warning("Die Ressource 'blockedcommands.yml' wurde nicht gefunden. Erstelle eine leere Konfiguration.");
blockedCommandsConfig = new YamlConfiguration();
blockedCommandsConfig.createSection("blocked-commands");
try {
blockedCommandsConfig.save(blockedCommandsFile);
} catch (IOException ex) {
getLogger().log(Level.SEVERE, "Fehler beim Speichern der blockedcommands.yml", ex);
}
return;
}
}
blockedCommandsConfig = YamlConfiguration.loadConfiguration(blockedCommandsFile);
}
public FileConfiguration getBlockedCommandsConfig() {
if (blockedCommandsConfig == null) {
reloadBlockedCommandsConfig();
}
return blockedCommandsConfig;
}
public void saveBlockedCommandsConfig() {
try {
blockedCommandsConfig.save(blockedCommandsFile);
} catch (IOException ignored) {}
}
@Override @Override
public void onEnable() { public void onEnable() {
// Default-Config sicherstellen
saveDefaultConfig(); saveDefaultConfig();
// bStats initialisieren // Version aus plugin.yml
String pluginVersion = getDescription().getVersion();
// Sicherstellen, dass 'version:' ganz oben steht
ensureConfigVersion(getConfig(), new File(getDataFolder(), "config.yml"), pluginVersion);
ensureVersionAtTop(new File(getDataFolder(), "lang.yml"), pluginVersion);
ensureVersionAtTop(new File(getDataFolder(), "help.yml"), pluginVersion);
ensureVersionAtTop(new File(getDataFolder(), "tablist.yml"), pluginVersion);
// Debug-Logging initialisieren
if (getConfig().getBoolean("debug-logging", false)) {
try {
// Ordner erstellen
File debugFolder = new File(getDataFolder(), "Debug");
if (!debugFolder.exists()) {
debugFolder.mkdirs();
}
// debug.log für Fehler
debugFile = new File(debugFolder, "debug.log");
if (!debugFile.exists()) debugFile.createNewFile();
debugWriter = new PrintWriter(new FileWriter(debugFile, true), true);
// console.log für komplette Plugin-Infos
consoleFile = new File(debugFolder, "console.log");
if (!consoleFile.exists()) consoleFile.createNewFile();
consoleWriter = new PrintWriter(new FileWriter(consoleFile, true), true);
logConsole("Debug-Logging ist aktiviert. Alle Plugin-Logs werden in Debug/console.log gespeichert.");
} catch (IOException e) {
getLogger().warning("Konnte Debug-Dateien nicht erstellen: " + e.getMessage());
}
}
int pluginId = 26886; int pluginId = 26886;
Metrics metrics = new Metrics(this, pluginId); Metrics metrics = new Metrics(this, pluginId);
metrics.addCustomChart(new SimplePie( metrics.addCustomChart(new SimplePie(
"default_gamemode", "default_gamemode",
() -> Bukkit.getDefaultGameMode().toString() () -> Bukkit.getDefaultGameMode().toString()
@@ -155,7 +230,9 @@ public void onEnable() {
() -> getConfig().getString("language", "default") () -> getConfig().getString("language", "default")
)); ));
// Konfigurationen/Dateien laden bannerManager = new BannerManager(this);
bannerManager.displayConsoleBanner(); // Banner beim Serverstart
updateConfigFiles(); updateConfigFiles();
createHomesFile(); createHomesFile();
createGravesFile(); createGravesFile();
@@ -164,11 +241,9 @@ public void onEnable() {
createLeashesFile(); createLeashesFile();
createMobCapFile(); createMobCapFile();
createNicknamesFile(); createNicknamesFile();
reloadBlockedCommandsConfig();
// PluginManager holen (vor Listener-Registrierung!) loadClaims();
PluginManager pluginManager = getServer().getPluginManager(); PluginManager pluginManager = getServer().getPluginManager();
// Permission registrieren: survivalplus.notify für OPs standardmäßig aktiv
try { try {
Permission notifyPerm = new Permission("survivalplus.notify", PermissionDefault.OP); Permission notifyPerm = new Permission("survivalplus.notify", PermissionDefault.OP);
if (pluginManager.getPermission("survivalplus.notify") == null) { if (pluginManager.getPermission("survivalplus.notify") == null) {
@@ -178,53 +253,45 @@ public void onEnable() {
} catch (Exception e) { } catch (Exception e) {
getLogger().warning("Fehler beim Registrieren der Permission survivalplus.notify: " + e.getMessage()); getLogger().warning("Fehler beim Registrieren der Permission survivalplus.notify: " + e.getMessage());
} }
try {
// NamespacedKey für Item-Drop-Markierung erzeugen Permission claimPerm = new Permission("survivalplus.claim.use", PermissionDefault.TRUE);
Permission trustPerm = new Permission("survivalplus.claim.trust", PermissionDefault.TRUE);
if (pluginManager.getPermission("survivalplus.claim.use") == null) {
pluginManager.addPermission(claimPerm);
getLogger().info("Permission survivalplus.claim.use erfolgreich registriert.");
}
if (pluginManager.getPermission("survivalplus.claim.trust") == null) {
pluginManager.addPermission(trustPerm);
getLogger().info("Permission survivalplus.claim.trust erfolgreich registriert.");
}
} catch (Exception e) {
getLogger().warning("Fehler beim Registrieren der Claim-Permissions: " + e.getMessage());
}
droppedKey = new NamespacedKey(this, "droppedItem"); droppedKey = new NamespacedKey(this, "droppedItem");
// FunChallengeManager initialisieren und laden
funChallengeManager = new FunChallengeManager(); funChallengeManager = new FunChallengeManager();
funChallengeManager.load(getConfig()); funChallengeManager.load(getConfig());
// Listener registrieren mit droppedKey
pluginManager.registerEvents(new ChallengeCollectListener(funChallengeManager, droppedKey), this); pluginManager.registerEvents(new ChallengeCollectListener(funChallengeManager, droppedKey), this);
pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this); pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this);
// FriendCommand
FriendCommand friendCommand = new FriendCommand(this, friendsConfig, langConfig, getLogger()); FriendCommand friendCommand = new FriendCommand(this, friendsConfig, langConfig, getLogger());
getCommand("day").setExecutor(new DayCommand(this)); getCommand("day").setExecutor(new DayCommand(this));
getCommand("night").setExecutor(new NightCommand(this)); getCommand("night").setExecutor(new NightCommand(this));
CommandBlocker commandBlocker = new CommandBlocker(this);
// TradeManager und ReportManager initialisieren pluginCommand = new PluginCommand(this);
getCommand("sp").setExecutor(pluginCommand);
TradeManager tradeManager = new TradeManager(this); TradeManager tradeManager = new TradeManager(this);
ReportManager reportManager = new ReportManager(this); ReportManager reportManager = new ReportManager(this);
// Report Commands registrieren
getCommand("report").setExecutor(new ReportCommand(this, reportManager)); getCommand("report").setExecutor(new ReportCommand(this, reportManager));
getCommand("showreport").setExecutor(new ShowReportCommand(this, reportManager)); getCommand("showreport").setExecutor(new ShowReportCommand(this, reportManager));
getCommand("clearreport").setExecutor(new ClearReportCommand(this, reportManager)); getCommand("clearreport").setExecutor(new ClearReportCommand(this, reportManager));
// Trade Commands registrieren
getCommand("trade").setExecutor(new TradeCommand(this, tradeManager)); getCommand("trade").setExecutor(new TradeCommand(this, tradeManager));
getCommand("tradeaccept").setExecutor(new TradeAcceptCommand(this, tradeManager)); getCommand("tradeaccept").setExecutor(new TradeAcceptCommand(this, tradeManager));
// StatsManager initialisieren
statsManager = new StatsManager(this); statsManager = new StatsManager(this);
// warpManager initialisieren
warpManager = new WarpManager(this); warpManager = new WarpManager(this);
// TablistManager starten
TablistManager tablistManager = new TablistManager(this); TablistManager tablistManager = new TablistManager(this);
// Listener-Instanzen
sitListener = new SitListener(this); sitListener = new SitListener(this);
afkListener = new AFKListener(this); afkListener = new AFKListener(this);
graveListener = new GraveListener(this); graveListener = new GraveListener(this);
playerJoinListener = new PlayerJoinListener(friendCommand); playerJoinListener = new PlayerJoinListener(friendCommand);
// Commands registrieren (Rest)
getCommand("gm").setExecutor(new GamemodeCommand(this)); getCommand("gm").setExecutor(new GamemodeCommand(this));
getCommand("sp").setExecutor(new PluginCommand(this)); getCommand("sp").setExecutor(new PluginCommand(this));
getCommand("sethome").setExecutor(new HomeCommand(this)); getCommand("sethome").setExecutor(new HomeCommand(this));
@@ -262,18 +329,14 @@ public void onEnable() {
getCommand("startchallenge").setExecutor(new StartFunChallengeCommand(this, funChallengeManager)); getCommand("startchallenge").setExecutor(new StartFunChallengeCommand(this, funChallengeManager));
getCommand("kit").setExecutor(new KitCommand(this)); getCommand("kit").setExecutor(new KitCommand(this));
getCommand("heal").setExecutor(new HealCommand(this)); getCommand("heal").setExecutor(new HealCommand(this));
getCommand("sp").setExecutor(commandBlocker);
// LootChestManager + Befehle
LootChestManager lootChestManager = new LootChestManager(this); LootChestManager lootChestManager = new LootChestManager(this);
pluginManager.registerEvents(lootChestManager, this); pluginManager.registerEvents(lootChestManager, this);
getCommand("lootchests").setExecutor(lootChestManager); getCommand("lootchests").setExecutor(lootChestManager);
getCommand("tploot").setExecutor(lootChestManager); getCommand("tploot").setExecutor(lootChestManager);
getCommand("claim").setExecutor(new ClaimCommand(this));
// BlockManager
BlockManager blockManager = new BlockManager(); BlockManager blockManager = new BlockManager();
FileConfiguration config = getConfig(); FileConfiguration config = getConfig();
// Listener registrieren
BackpackRecipe.register(this, langConfig); BackpackRecipe.register(this, langConfig);
pluginManager.registerEvents(new ChatBlockListener(blockManager), this); pluginManager.registerEvents(new ChatBlockListener(blockManager), this);
pluginManager.registerEvents(new InventoryClickListener(this), this); pluginManager.registerEvents(new InventoryClickListener(this), this);
@@ -297,92 +360,155 @@ public void onEnable() {
pluginManager.registerEvents(new WarpInventoryListener(this, warpManager), this); pluginManager.registerEvents(new WarpInventoryListener(this, warpManager), this);
pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this); pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this);
pluginManager.registerEvents(new BlockDetectionListener(this), this); pluginManager.registerEvents(new BlockDetectionListener(this), this);
pluginManager.registerEvents(new ClaimListener(this), this);
LockSystem lockSystem = new LockSystem(this); lockSystem = new LockSystem(this);
pluginManager.registerEvents(lockSystem, this); pluginManager.registerEvents(lockSystem, this);
getCommand("sp").setExecutor(lockSystem); getCommand("sp").setExecutor(lockSystem);
getCommand("sp").setExecutor(new CommandExecutor() {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!command.getName().equalsIgnoreCase("sp")) {
return false;
}
if (args.length == 0) {
return pluginCommand.onCommand(sender, command, label, args);
}
String subCommand = args[0].toLowerCase();
if (subCommand.equals("cb")) {
return commandBlocker.onCommand(sender, command, label, args);
} else if (subCommand.equals("lock") || subCommand.equals("unlock") ||
subCommand.equals("friendadd") || subCommand.equals("friendremove")) {
return lockSystem.onCommand(sender, command, label, args);
}
return pluginCommand.onCommand(sender, command, label, args);
}
});
pluginManager.registerEvents(new RepairSignListener(getConfig(), getLangConfig()), this); pluginManager.registerEvents(new RepairSignListener(getConfig(), getLangConfig()), this);
pluginManager.registerEvents(new ToolUpgradeListener(this), this); pluginManager.registerEvents(new ToolUpgradeListener(this), this);
pluginManager.registerEvents(new NickLoadListener(this), this); pluginManager.registerEvents(new NickLoadListener(this), this);
// AutoClear starten
startAutoClearTask(); startAutoClearTask();
spawnArmorStandExample(); spawnArmorStandExample();
getLogger().info(getMessage("plugin.enabled")); getLogger().info(getMessage("plugin.enabled"));
// === Gamerule keepInventory aus Config setzen ===
if (getConfig().getBoolean("set-keepinventory", true)) { if (getConfig().getBoolean("set-keepinventory", true)) {
Bukkit.getScheduler().runTaskLater(this, () -> { Bukkit.getScheduler().runTaskLater(this, () -> {
if (Bukkit.getWorlds().isEmpty()) return; if (Bukkit.getWorlds().isEmpty()) return;
Bukkit.getWorlds().forEach(world -> { Bukkit.getWorlds().forEach(world -> {
world.setGameRule(GameRule.KEEP_INVENTORY, false); world.setGameRule(GameRule.KEEP_INVENTORY, false);
getLogger().info("Gamerule keepInventory in Welt '" + world.getName() + "' wurde auf false gesetzt."); getLogger().info("Gamerule keepInventory in Welt '" + world.getName() + "' wurde auf false gesetzt.");
}); });
}, 20L); }, 20L);
} }
// === Force Survival Mode aktivieren ===
if (getConfig().getBoolean("force-survival", true)) { if (getConfig().getBoolean("force-survival", true)) {
pluginManager.registerEvents(new ForceSurvivalListener(this), this); pluginManager.registerEvents(new ForceSurvivalListener(this), this);
getLogger().info("Force-Survival ist aktiv. Spieler werden beim Joinen in Survival gesetzt."); getLogger().info("Force-Survival ist aktiv. Spieler werden beim Joinen in Survival gesetzt.");
} }
// === Animierte Tablist konfigurieren und starten ===
try { try {
// tablist.yml laden / defaults setzen
if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml"); if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml");
if (!tablistFile.exists()) { if (!tablistFile.exists()) {
saveResource("tablist.yml", false); saveResource("tablist.yml", false);
} }
tablistConfig = YamlConfiguration.loadConfiguration(tablistFile); tablistConfig = YamlConfiguration.loadConfiguration(tablistFile);
// Standardwerte aus Resource als Defaults setzen (falls vorhanden)
InputStream defStream = getResource("tablist.yml"); InputStream defStream = getResource("tablist.yml");
if (defStream != null) { if (defStream != null) {
tablistConfig.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(defStream))); tablistConfig.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(defStream)));
} }
getLogger().info("Animierte Tablist wurde geladen!"); getLogger().info("Animierte Tablist wurde geladen!");
} catch (Exception e) { } catch (Exception e) {
getLogger().log(Level.WARNING, "Fehler beim Laden der Tablist-Konfiguration", e); getLogger().log(Level.WARNING, "Fehler beim Laden der Tablist-Konfiguration", e);
} }
// === Gamerules anwenden (kurze Verzögerung, damit Welten geladen sind) ===
Bukkit.getScheduler().runTaskLater(this, this::applyBlockRules, 20L); Bukkit.getScheduler().runTaskLater(this, this::applyBlockRules, 20L);
} }
/**
* Liest Config und setzt GameRule sowie entfernt verbotene Blöcke aus Inventaren online
*/
public void applyBlockRules() { public void applyBlockRules() {
boolean cmdAllowed = getConfig().getBoolean("blocks.command-blocks.enabled", true); boolean cmdAllowed = getConfig().getBoolean("blocks.command-blocks.enabled", true);
boolean structAllowed = getConfig().getBoolean("blocks.structure-blocks.enabled", true); boolean structAllowed = getConfig().getBoolean("blocks.structure-blocks.enabled", true);
for (World world : Bukkit.getWorlds()) { for (World world : Bukkit.getWorlds()) {
try { try {
// moderner API-Aufruf
world.setGameRule(GameRule.COMMAND_BLOCK_OUTPUT, cmdAllowed); world.setGameRule(GameRule.COMMAND_BLOCK_OUTPUT, cmdAllowed);
} catch (NoSuchMethodError | NoClassDefFoundError e) { } catch (NoSuchMethodError | NoClassDefFoundError e) {
// Fallback für ältere Server-Implementationen
world.setGameRuleValue(GameRule.COMMAND_BLOCK_OUTPUT.getName(), Boolean.toString(cmdAllowed)); world.setGameRuleValue(GameRule.COMMAND_BLOCK_OUTPUT.getName(), Boolean.toString(cmdAllowed));
} }
getLogger().info("Gamerule commandBlockOutput in Welt '" + world.getName() + "' gesetzt auf " + cmdAllowed); getLogger().info("Gamerule commandBlockOutput in Welt '" + world.getName() + "' gesetzt auf " + cmdAllowed);
} }
// Entferne verbotenes Zeug aus Inventaren aller online-Spieler direkt beim Start
removeForbiddenBlocksFromInventories(cmdAllowed, structAllowed); removeForbiddenBlocksFromInventories(cmdAllowed, structAllowed);
getLogger().info("Block-Regeln angewendet: CommandBlocks erlaubt=" + cmdAllowed + ", StructureBlocks erlaubt=" + structAllowed); getLogger().info("Block-Regeln angewendet: CommandBlocks erlaubt=" + cmdAllowed + ", StructureBlocks erlaubt=" + structAllowed);
} }
/** Entfernt Command-/Structure-Blöcke aus Inventaren falls deaktiviert, ausgenommen Admins */ private void ensureVersionAtTop(File file, String version) {
try {
if (!file.exists()) return; // Datei existiert nicht
List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
if (!lines.isEmpty() && lines.get(0).startsWith("version:")) {
// Alte Versionsnummer ersetzen
lines.set(0, "version: " + version);
} else {
// Version an den Anfang setzen
lines.add(0, "version: " + version);
}
Files.write(file.toPath(), lines, StandardCharsets.UTF_8);
} catch (IOException e) {
getLogger().warning("Konnte Version in " + file.getName() + " nicht setzen: " + e.getMessage());
}
}
/**
* Speziell für config.yml:
* - Setzt die Version in der geladenen FileConfiguration (getConfig()) und speichert sie,
* - und sorgt anschließend dafür, dass die 'version:'-Zeile ganz oben in der Datei steht.
*/
private void ensureConfigVersion(FileConfiguration config, File file, String version) {
try {
if (!file.exists()) return; // nichts zu tun, Datei existiert nicht
// 1) Version in der geladenen Config setzen und speichern (Bukkit nutzt diese Config im Speicher)
String current = config.getString("version", "");
if (!version.equals(current)) {
config.set("version", version);
try {
config.save(file);
} catch (IOException e) {
getLogger().warning("Konnte config.yml nicht speichern: " + e.getMessage());
}
}
// 2) Text-Nachbearbeitung: sicherstellen, dass 'version:' als erste Zeile steht
List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
// Entferne alle vorhandenen version:-Zeilen (falls irgendwo)
int foundIndex = -1;
for (int i = 0; i < lines.size(); i++) {
if (lines.get(i).trim().startsWith("version:")) {
foundIndex = i;
break;
}
}
if (foundIndex == 0) {
// bereits oben -> ersetzen
lines.set(0, "version: " + version);
} else {
// entferne alte Stelle (wenn vorhanden)
if (foundIndex > 0) {
lines.remove(foundIndex);
}
// füge neue version ganz oben ein
lines.add(0, "version: " + version);
}
Files.write(file.toPath(), lines, StandardCharsets.UTF_8);
getLogger().info("config.yml: Version oben gesetzt auf " + version);
} catch (IOException e) {
getLogger().warning("Konnte Version in config.yml nicht setzen: " + e.getMessage());
}
}
private void removeForbiddenBlocksFromInventories(boolean cmdAllowed, boolean structAllowed) { private void removeForbiddenBlocksFromInventories(boolean cmdAllowed, boolean structAllowed) {
for (Player p : Bukkit.getOnlinePlayers()) { for (Player p : Bukkit.getOnlinePlayers()) {
if (p.hasPermission("survivalplus.notify")) { if (p.hasPermission("survivalplus.notify")) {
continue; // Admins dürfen Blöcke behalten continue;
} }
Inventory inv = p.getInventory(); Inventory inv = p.getInventory();
boolean removedCommandBlock = false; boolean removedCommandBlock = false;
@@ -397,14 +523,12 @@ private void removeForbiddenBlocksFromInventories(boolean cmdAllowed, boolean st
removedStructureBlock = true; removedStructureBlock = true;
p.sendMessage(ChatColor.RED + "[SurvivalPlus] Structure-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind."); p.sendMessage(ChatColor.RED + "[SurvivalPlus] Structure-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind.");
} }
// Benachrichtige Admins über entfernte Blöcke
if ((removedCommandBlock || removedStructureBlock) && getConfig().getBoolean("blocks.notify-admins-on-possession", true)) { if ((removedCommandBlock || removedStructureBlock) && getConfig().getBoolean("blocks.notify-admins-on-possession", true)) {
notifyAdmins(p.getName(), removedCommandBlock, removedStructureBlock); notifyAdmins(p.getName(), removedCommandBlock, removedStructureBlock);
} }
} }
} }
/** Benachrichtigt Admins über entfernte Blöcke */
private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean hadStructureBlock) { private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean hadStructureBlock) {
String baseTag = ChatColor.GRAY + "[" + ChatColor.GREEN + "SurvivalPlus" + ChatColor.GRAY + "] "; String baseTag = ChatColor.GRAY + "[" + ChatColor.GREEN + "SurvivalPlus" + ChatColor.GRAY + "] ";
for (Player admin : Bukkit.getOnlinePlayers()) { for (Player admin : Bukkit.getOnlinePlayers()) {
@@ -421,15 +545,138 @@ private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean ha
} }
} }
private void createClaimsFile() {
claimsFile = new File(getDataFolder(), "claims.yml");
if (!claimsFile.exists()) {
try {
claimsFile.createNewFile();
} catch (IOException e) {
getLogger().log(Level.SEVERE, "Fehler beim Erstellen der claims.yml", e);
}
}
claimsConfig = YamlConfiguration.loadConfiguration(claimsFile);
}
private void loadClaims() {
createClaimsFile();
for (String key : claimsConfig.getKeys(false)) {
try {
UUID owner = UUID.fromString(claimsConfig.getString(key + ".owner"));
String worldName = claimsConfig.getString(key + ".world");
int x1 = claimsConfig.getInt(key + ".x1");
int z1 = claimsConfig.getInt(key + ".z1");
int x2 = claimsConfig.getInt(key + ".x2");
int z2 = claimsConfig.getInt(key + ".z2");
Claim claim = new Claim(owner, worldName, x1, z1, x2, z2);
List<String> trustedList = claimsConfig.getStringList(key + ".trusted");
for (String trustedStr : trustedList) {
claim.addTrusted(UUID.fromString(trustedStr));
}
claims.put(key, claim);
playerClaimCounts.merge(owner, 1, Integer::sum);
} catch (Exception e) {
getLogger().warning("Invalid claim data for key: " + key);
}
}
}
public void saveClaims() {
for (Map.Entry<String, Claim> entry : claims.entrySet()) {
String key = entry.getKey();
Claim claim = entry.getValue();
claimsConfig.set(key + ".owner", claim.getOwner().toString());
claimsConfig.set(key + ".x1", claim.getX1());
claimsConfig.set(key + ".z1", claim.getZ1());
claimsConfig.set(key + ".x2", claim.getX2());
claimsConfig.set(key + ".z2", claim.getZ2());
claimsConfig.set(key + ".world", claim.getWorldName());
List<String> trustedList = new ArrayList<>();
for (UUID trusted : claim.getTrusted()) {
trustedList.add(trusted.toString());
}
claimsConfig.set(key + ".trusted", trustedList);
}
try {
claimsConfig.save(claimsFile);
} catch (IOException e) {
getLogger().log(Level.SEVERE, "Fehler beim Speichern der claims.yml", e);
}
}
public Claim getClaim(Location location) {
for (Claim claim : claims.values()) {
if (claim.isInside(location)) {
return claim;
}
}
return null;
}
public void addClaim(Claim claim, Player player) {
String key = claim.getWorldName() + ":" + claim.getX1() + ":" + claim.getZ1() + ":" + claim.getX2() + ":" + claim.getZ2();
claims.put(key, claim);
playerClaimCounts.merge(player.getUniqueId(), 1, Integer::sum);
saveClaims();
}
public void removeClaim(Location location, Player player) {
String key = null;
for (Map.Entry<String, Claim> entry : claims.entrySet()) {
if (entry.getValue().isInside(location)) {
key = entry.getKey();
break;
}
}
if (key != null) {
claims.remove(key);
playerClaimCounts.merge(player.getUniqueId(), -1, Integer::sum);
saveClaims();
}
}
public void removeClaimByKey(String key, UUID playerUUID) {
claims.remove(key);
playerClaimCounts.merge(playerUUID, -1, Integer::sum);
saveClaims();
}
public Map<String, Claim> getClaims() {
return claims;
}
public int getClaimCount(Player player) {
return playerClaimCounts.getOrDefault(player.getUniqueId(), 0);
}
public void setPoint1(Player player, Location location) {
point1Selections.put(player.getUniqueId(), location);
}
public void setPoint2(Player player, Location location) {
point2Selections.put(player.getUniqueId(), location);
}
public Location getPoint1(Player player) {
return point1Selections.get(player.getUniqueId());
}
public Location getPoint2(Player player) {
return point2Selections.get(player.getUniqueId());
}
public void clearSelections(Player player) {
point1Selections.remove(player.getUniqueId());
point2Selections.remove(player.getUniqueId());
}
public boolean hasOverlap(Claim newClaim) {
for (Claim existingClaim : claims.values()) {
if (existingClaim.overlaps(newClaim)) {
return true;
}
}
return false;
}
@@ -480,6 +727,9 @@ private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean ha
@Override @Override
public void onDisable() { public void onDisable() {
if (debugWriter != null) {
debugWriter.close();
}
if (autoClearTaskId != -1) { if (autoClearTaskId != -1) {
Bukkit.getScheduler().cancelTask(autoClearTaskId); Bukkit.getScheduler().cancelTask(autoClearTaskId);
} }
@@ -928,4 +1178,34 @@ private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean ha
e.printStackTrace(); e.printStackTrace();
} }
} }
public BannerManager getBannerManager() {
return bannerManager;
}
// Nur Fehler/Exceptions
public void log(String msg) {
if (getConfig().getBoolean("debug-logging", false) && debugWriter != null) {
debugWriter.println("[" + new java.util.Date() + "] " + msg);
} else {
getLogger().info(msg);
}
}
public void logError(String msg, Throwable t) {
if (getConfig().getBoolean("debug-logging", false) && debugWriter != null) {
debugWriter.println("[" + new java.util.Date() + "] ERROR: " + msg);
t.printStackTrace(debugWriter);
} else {
getLogger().log(Level.SEVERE, msg, t);
}
}
// Komplette Plugin-Logs in console.log
public void logConsole(String msg) {
if (getConfig().getBoolean("debug-logging", false) && consoleWriter != null) {
consoleWriter.println("[" + new java.util.Date() + "] " + msg);
}
getLogger().info(msg); // Optional: zusätzlich Konsole ausgeben
}
} }

View File

@@ -0,0 +1,226 @@
package de.viper.survivalplus.commands;
import de.viper.survivalplus.SurvivalPlus;
import de.viper.survivalplus.util.Claim;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
public class ClaimCommand implements CommandExecutor {
private SurvivalPlus plugin;
private static final int MAX_CLAIMS = 10;
private static final int MAX_AREA = 10000; // 100x100 blocks
public ClaimCommand(SurvivalPlus plugin) {
this.plugin = plugin;
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage(plugin.getMessage("commands.player-only"));
return true;
}
Player player = (Player) sender;
if (args.length == 0) {
if (!player.hasPermission("survivalplus.claim.use")) {
player.sendMessage(plugin.getMessage("commands.no-permission"));
return true;
}
Location point1 = plugin.getPoint1(player);
Location point2 = plugin.getPoint2(player);
if (point1 == null || point2 == null) {
player.sendMessage(plugin.getMessage("claim.points-not-set"));
return true;
}
if (!point1.getWorld().equals(point2.getWorld())) {
player.sendMessage(plugin.getMessage("claim.different-worlds"));
return true;
}
int x1 = point1.getBlockX();
int z1 = point1.getBlockZ();
int x2 = point2.getBlockX();
int z2 = point2.getBlockZ();
int width = Math.abs(x2 - x1) + 1;
int length = Math.abs(z2 - z1) + 1;
if (width * length > MAX_AREA) {
player.sendMessage(plugin.getMessage("claim.too-large").replace("%max%", String.valueOf(MAX_AREA)));
return true;
}
Claim newClaim = new Claim(player, point1.getWorld().getName(), x1, z1, x2, z2);
if (plugin.hasOverlap(newClaim)) {
player.sendMessage(plugin.getMessage("claim.overlap"));
return true;
}
if (plugin.getClaimCount(player) >= MAX_CLAIMS) {
player.sendMessage(plugin.getMessage("claim.max-reached").replace("%max%", String.valueOf(MAX_CLAIMS)));
return true;
}
plugin.addClaim(newClaim, player);
player.sendMessage(plugin.getMessage("claim.success").replace("%count%", String.valueOf(plugin.getClaimCount(player))).replace("%max%", String.valueOf(MAX_CLAIMS)));
plugin.clearSelections(player);
return true;
}
switch (args[0].toLowerCase()) {
case "mark":
if (!player.hasPermission("survivalplus.claim.use")) {
player.sendMessage(plugin.getMessage("commands.no-permission"));
return true;
}
if (args.length < 2 || (!args[1].equals("1") && !args[1].equals("2"))) {
player.sendMessage(plugin.getMessage("claim.usage-mark"));
return true;
}
Location location = player.getLocation();
if (args[1].equals("1")) {
plugin.setPoint1(player, location);
player.sendMessage(plugin.getMessage("claim.point1-set").replace("%x%", String.valueOf(location.getBlockX())).replace("%z%", String.valueOf(location.getBlockZ())));
} else {
plugin.setPoint2(player, location);
player.sendMessage(plugin.getMessage("claim.point2-set").replace("%x%", String.valueOf(location.getBlockX())).replace("%z%", String.valueOf(location.getBlockZ())));
}
return true;
case "unclaim":
if (args.length == 1) {
if (!player.hasPermission("survivalplus.claim.use")) {
player.sendMessage(plugin.getMessage("commands.no-permission"));
return true;
}
Claim claim = plugin.getClaim(player.getLocation());
if (claim == null || !claim.getOwner().equals(player.getUniqueId())) {
player.sendMessage(plugin.getMessage("claim.not-owner"));
return true;
}
plugin.removeClaim(player.getLocation(), player);
player.sendMessage(plugin.getMessage("claim.unclaimed"));
return true;
} else if (args.length == 2 && player.isOp()) {
Player target = Bukkit.getPlayer(args[1]);
UUID targetUUID;
if (target != null) {
targetUUID = target.getUniqueId();
} else {
try {
targetUUID = UUID.fromString(args[1]);
} catch (IllegalArgumentException e) {
player.sendMessage(plugin.getMessage("commands.player-not-found"));
return true;
}
}
int removedCount = removePlayerClaims(targetUUID);
if (removedCount > 0) {
player.sendMessage(plugin.getMessage("claim.op-unclaimed")
.replace("%player%", args[1])
.replace("%count%", String.valueOf(removedCount)));
} else {
player.sendMessage(plugin.getMessage("claim.no-claims-found")
.replace("%player%", args[1]));
}
return true;
} else {
player.sendMessage(plugin.getMessage("claim.usage"));
return true;
}
case "trust":
if (!player.hasPermission("survivalplus.claim.trust")) {
player.sendMessage(plugin.getMessage("commands.no-permission"));
return true;
}
if (args.length < 2) {
player.sendMessage(plugin.getMessage("claim.usage-trust"));
return true;
}
Player target = Bukkit.getPlayer(args[1]);
if (target == null) {
player.sendMessage(plugin.getMessage("commands.player-not-found"));
return true;
}
Claim claim = plugin.getClaim(player.getLocation());
if (claim == null || !claim.getOwner().equals(player.getUniqueId())) {
player.sendMessage(plugin.getMessage("claim.not-owner"));
return true;
}
claim.addTrusted(target.getUniqueId());
player.sendMessage(plugin.getMessage("claim.trusted").replace("%player%", args[1]));
plugin.saveClaims();
break;
case "untrust":
if (!player.hasPermission("survivalplus.claim.trust")) {
player.sendMessage(plugin.getMessage("commands.no-permission"));
return true;
}
if (args.length < 2) {
player.sendMessage(plugin.getMessage("claim.usage-untrust"));
return true;
}
target = Bukkit.getPlayer(args[1]);
if (target == null) {
player.sendMessage(plugin.getMessage("commands.player-not-found"));
return true;
}
claim = plugin.getClaim(player.getLocation());
if (claim == null || !claim.getOwner().equals(player.getUniqueId())) {
player.sendMessage(plugin.getMessage("claim.not-owner"));
return true;
}
claim.removeTrusted(target.getUniqueId());
player.sendMessage(plugin.getMessage("claim.untrusted").replace("%player%", args[1]));
plugin.saveClaims();
break;
case "info":
if (!player.hasPermission("survivalplus.claim.use")) {
player.sendMessage(plugin.getMessage("commands.no-permission"));
return true;
}
claim = plugin.getClaim(player.getLocation());
if (claim == null) {
player.sendMessage(plugin.getMessage("claim.no-claim-at-location"));
return true;
}
String ownerName = Bukkit.getOfflinePlayer(claim.getOwner()).getName();
if (ownerName == null) {
ownerName = claim.getOwner().toString(); // Fallback to UUID if name not found
}
player.sendMessage(plugin.getMessage("claim.info")
.replace("%owner%", ownerName)
.replace("%world%", claim.getWorldName())
.replace("%x1%", String.valueOf(claim.getX1()))
.replace("%z1%", String.valueOf(claim.getZ1()))
.replace("%x2%", String.valueOf(claim.getX2()))
.replace("%z2%", String.valueOf(claim.getZ2())));
return true;
default:
player.sendMessage(plugin.getMessage("claim.usage"));
}
return true;
}
private int removePlayerClaims(UUID targetUUID) {
Map<String, Claim> claims = new HashMap<>(plugin.getClaims());
int removedCount = 0;
for (Map.Entry<String, Claim> entry : claims.entrySet()) {
if (entry.getValue().getOwner().equals(targetUUID)) {
plugin.removeClaimByKey(entry.getKey(), targetUUID);
removedCount++;
}
}
if (removedCount > 0) {
plugin.saveClaims();
}
return removedCount;
}
}

View File

@@ -0,0 +1,73 @@
package de.viper.survivalplus.listeners;
import de.viper.survivalplus.SurvivalPlus;
import de.viper.survivalplus.util.Claim;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class ClaimListener implements Listener {
private final SurvivalPlus plugin;
private final Map<UUID, Claim> lastClaim = new HashMap<>();
public ClaimListener(SurvivalPlus plugin) {
this.plugin = plugin;
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
Player player = event.getPlayer();
if (player.isOp()) return;
Claim claim = plugin.getClaim(event.getBlock().getLocation());
if (claim != null && !claim.getOwner().equals(player.getUniqueId()) && !claim.getTrusted().contains(player.getUniqueId())) {
event.setCancelled(true);
player.sendMessage(plugin.getMessage("claim.no-break"));
}
}
@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
Player player = event.getPlayer();
if (player.isOp()) return;
Claim claim = plugin.getClaim(event.getBlock().getLocation());
if (claim != null && !claim.getOwner().equals(player.getUniqueId()) && !claim.getTrusted().contains(player.getUniqueId())) {
event.setCancelled(true);
player.sendMessage(plugin.getMessage("claim.no-place"));
}
}
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
Player player = event.getPlayer();
UUID playerId = player.getUniqueId();
Claim currentClaim = plugin.getClaim(event.getTo());
// Prüfe, ob sich der Claim-Status geändert hat
Claim previousClaim = lastClaim.getOrDefault(playerId, null);
if (currentClaim != previousClaim) {
if (currentClaim != null) {
// Spieler betritt einen Claim
String ownerName = plugin.getServer().getOfflinePlayer(currentClaim.getOwner()).getName();
if (ownerName == null) {
ownerName = currentClaim.getOwner().toString(); // Fallback auf UUID
}
player.sendMessage(plugin.getMessage("claim.enter").replace("%owner%", ownerName));
} else if (previousClaim != null) {
// Spieler verlässt einen Claim
String ownerName = plugin.getServer().getOfflinePlayer(previousClaim.getOwner()).getName();
if (ownerName == null) {
ownerName = previousClaim.getOwner().toString(); // Fallback auf UUID
}
player.sendMessage(plugin.getMessage("claim.leave").replace("%owner%", ownerName));
}
lastClaim.put(playerId, currentClaim);
}
}
}

View File

@@ -26,10 +26,12 @@ public class NewbieProtectionListener implements Listener {
private final SurvivalPlus plugin; private final SurvivalPlus plugin;
private final boolean enabled; private final boolean enabled;
private final int durationMinutes; private final int durationMinutes;
private final int COOLDOWN_SECONDS = 60; // Abklingzeit für Nachrichten in Sekunden (1 Minute)
// Maps für Zeiten und BossBars // Maps für Zeiten, BossBars und Nachrichten-Abklingzeit
private final Map<UUID, Integer> remainingSeconds = new HashMap<>(); private final Map<UUID, Integer> remainingSeconds = new HashMap<>();
private final Map<UUID, BossBar> bossBars = new HashMap<>(); private final Map<UUID, BossBar> bossBars = new HashMap<>();
private final Map<UUID, Long> messageCooldowns = new HashMap<>();
// YAML Datei // YAML Datei
private File dataFile; private File dataFile;
@@ -89,14 +91,29 @@ public class NewbieProtectionListener implements Listener {
if (!(event.getEntity() instanceof Player)) return; if (!(event.getEntity() instanceof Player)) return;
Player victim = (Player) event.getEntity(); Player victim = (Player) event.getEntity();
UUID vid = victim.getUniqueId(); UUID victimId = victim.getUniqueId();
Integer timeLeft = remainingSeconds.get(vid); Integer timeLeft = remainingSeconds.get(victimId);
if (timeLeft != null && timeLeft > 0) { if (timeLeft != null && timeLeft > 0) {
event.setCancelled(true); event.setCancelled(true);
// Prüfe Abklingzeit für Opfer
long currentTime = System.currentTimeMillis() / 1000;
long lastMessageTimeVictim = messageCooldowns.getOrDefault(victimId, 0L);
if (currentTime >= lastMessageTimeVictim + COOLDOWN_SECONDS) {
victim.sendMessage(ChatColor.GREEN + "Du bist noch im Neulingsschutz!"); victim.sendMessage(ChatColor.GREEN + "Du bist noch im Neulingsschutz!");
messageCooldowns.put(victimId, currentTime);
}
// Prüfe Abklingzeit für Angreifer, falls es ein Spieler ist
if (event.getDamager() instanceof Player) { if (event.getDamager() instanceof Player) {
((Player) event.getDamager()).sendMessage(ChatColor.RED + victim.getName() + " ist noch geschützt!"); Player damager = (Player) event.getDamager();
UUID damagerId = damager.getUniqueId();
long lastMessageTimeDamager = messageCooldowns.getOrDefault(damagerId, 0L);
if (currentTime >= lastMessageTimeDamager + COOLDOWN_SECONDS) {
damager.sendMessage(ChatColor.RED + victim.getName() + " ist noch geschützt!");
messageCooldowns.put(damagerId, currentTime);
}
} }
} }
} }
@@ -158,7 +175,6 @@ public class NewbieProtectionListener implements Listener {
} }
} }
// WICHTIG: Public gemacht, damit von SurvivalPlus.java aufrufbar
public void saveData() { public void saveData() {
if (dataConfig == null) return; if (dataConfig == null) return;
for (Map.Entry<UUID, Integer> entry : remainingSeconds.entrySet()) { for (Map.Entry<UUID, Integer> entry : remainingSeconds.entrySet()) {

View File

@@ -0,0 +1,28 @@
package de.viper.survivalplus.util;
import de.viper.survivalplus.SurvivalPlus;
import java.util.Arrays;
import java.util.List;
public class BannerManager {
private final SurvivalPlus plugin;
public BannerManager(SurvivalPlus plugin) {
this.plugin = plugin;
}
public void displayConsoleBanner() {
String version = plugin.getDescription().getVersion();
List<String> banner = Arrays.asList(
"******************************",
"* SurvivalPlus " + version + " *",
"* *",
"* M_Viper *",
"******************************"
);
for (String line : banner) {
plugin.getLogger().info(line);
}
}
}

View File

@@ -0,0 +1,91 @@
package de.viper.survivalplus.util;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class Claim {
private UUID owner;
private Set<UUID> trusted = new HashSet<>();
private int x1, z1, x2, z2;
private String worldName;
public Claim(Player owner, String worldName, int x1, int z1, int x2, int z2) {
this.owner = owner.getUniqueId();
this.worldName = worldName;
this.x1 = Math.min(x1, x2);
this.z1 = Math.min(z1, z2);
this.x2 = Math.max(x1, x2);
this.z2 = Math.max(z1, z2);
trusted.add(owner.getUniqueId());
}
public Claim(UUID owner, String worldName, int x1, int z1, int x2, int z2) {
this.owner = owner;
this.worldName = worldName;
this.x1 = Math.min(x1, x2);
this.z1 = Math.min(z1, z2);
this.x2 = Math.max(x1, x2);
this.z2 = Math.max(z1, z2);
trusted.add(owner);
}
public boolean canInteract(UUID uuid) {
return trusted.contains(uuid);
}
public void addTrusted(UUID uuid) {
trusted.add(uuid);
}
public void removeTrusted(UUID uuid) {
trusted.remove(uuid);
}
public UUID getOwner() {
return owner;
}
public Set<UUID> getTrusted() {
return trusted;
}
public int getX1() {
return x1;
}
public int getZ1() {
return z1;
}
public int getX2() {
return x2;
}
public int getZ2() {
return z2;
}
public String getWorldName() {
return worldName;
}
public boolean isInside(Location location) {
if (!location.getWorld().getName().equals(worldName)) {
return false;
}
int x = location.getBlockX();
int z = location.getBlockZ();
return x >= x1 && x <= x2 && z >= z1 && z <= z2;
}
public boolean overlaps(Claim other) {
if (!this.worldName.equals(other.worldName)) {
return false;
}
return !(this.x2 < other.x1 || this.x1 > other.x2 || this.z2 < other.z1 || this.z1 > other.z2);
}
}

View File

@@ -0,0 +1,4 @@
blocked-commands:
- op
- ban
- kick

View File

View File

@@ -1,3 +1,9 @@
# Version (Nicht Ändern!)
version: 1.0.9
# Debug-Option
debug-logging: false
# Neulings Schutz # Neulings Schutz
newbie-protection: newbie-protection:
enabled: true enabled: true

View File

@@ -3,17 +3,57 @@ footer: "&6==========================="
commands: commands:
gm: gm:
description: "&eWechselt den Spielmodus (survival, creative, adventure, spectator)." description: "&eÄndert den Spielmodus eines Spielers (survival, creative, adventure, spectator)."
usage: "&b/gm [spieler]" usage: "&b/gm <modus> [spieler]"
sp: sp:
description: "&eHauptbefehl für SurvivalPlus mit Unterbefehlen." description: "&eHauptbefehl für SurvivalPlus mit Unterbefehlen."
usage: "&b/sp " usage: "&b/sp [reload | help | info | share | lock]"
share: sp_reload:
description: "&eTeilt deine aktuellen Koordinaten nach Bestätigung mit allen Spielern." description: "&eLädt das Plugin neu."
usage: "&b/sp reload"
sp_help:
description: "&eZeigt die Hilfe für SurvivalPlus-Befehle an."
usage: "&b/sp help"
sp_info:
description: "&eZeigt Informationen über das Plugin an."
usage: "&b/sp info"
sp_share:
description: "&eTeilt deine Koordinaten nach Bestätigung mit allen Spielern."
usage: "&b/sp share" usage: "&b/sp share"
sp_cb_add:
description: "&eFügt einen Befehl zur Blockierliste hinzu."
usage: "&b/sp cb add <befehl>"
sp_cb_remove:
description: "&eEntfernt einen Befehl aus der Blockierliste."
usage: "&b/sp cb remove <befehl>"
sp_cb_list:
description: "&eZeigt die Liste der blockierten Befehle an."
usage: "&b/sp cb list"
sp_lock_lock:
description: "&eSperrt einen Container (z.B. Kiste oder Tür)."
usage: "&b/sp lock "
sp_lock_unlock:
description: "&eEntsperrt einen Container (z.B. Kiste oder Tür)."
usage: "&b/sp lock "
sp_lock_friendadd:
description: "&eFügt einen Freund zum Container-Sperrsystem hinzu."
usage: "&b/sp lock friendadd <Spieler>"
sp_lock_friendremove:
description: "&eEntfernt einen Freund aus dem Container-Sperrsystem."
usage: "&b/sp lock friendremove <Spieler>"
shareconfirm: shareconfirm:
description: "&eBestätigt das Teilen deiner Koordinaten mit allen Spielern." description: "&eBestätigt das Teilen deiner Koordinaten mit allen Spielern."
usage: "&b/sp shareconfirm" usage: "&b/sp shareconfirm"
@@ -23,71 +63,90 @@ commands:
usage: "&b/sp sharecancel" usage: "&b/sp sharecancel"
sethome: sethome:
description: "&eSetzt einen neuen Homepunkt." description: "&eSetzt ein Home mit dem angegebenen Namen."
usage: "&b/sethome " usage: "&b/sethome <name>"
delhome: delhome:
description: "&eLöscht einen Homepunkt." description: "&eLöscht ein Home mit dem angegebenen Namen."
usage: "&b/delhome " usage: "&b/delhome <name>"
homelist: homelist:
description: "&eZeigt alle deine Homes." description: "&eÖffnet eine GUI mit allen Homes."
usage: "&b/homelist" usage: "&b/homelist"
home: home:
description: "&eTeleportiert dich zu einem gespeicherten Home." description: "&eTeleportiert zu einem Home."
usage: "&b/home " usage: "&b/home <name>"
inv: inv:
description: "&eÖffnet dein Inventar oder das eines anderen Spielers." description: "&eÖffnet das Inventar (eigenes oder das eines anderen Spielers)."
usage: "&b/inv " usage: "&b/inv [spieler]"
ec: ec:
description: "&eÖffnet deine Endertruhe oder die eines anderen Spielers." description: "&eÖffnet die Endertruhe (eigene oder die eines anderen Spielers)."
usage: "&b/ec [spieler]" usage: "&b/ec [spieler]"
setspawn:
description: "&eSetzt den Spawnpunkt der Welt."
usage: "&b/setspawn"
setworldspawn: setworldspawn:
description: "&eSetzt den globalen Weltspawnpunkt." description: "&eSetzt den Weltspawnpunkt auf die Position des Spielers."
usage: "&b/setworldspawn" usage: "&b/setworldspawn"
setspawn:
description: "&eSetzt den Server-Spawnpunkt auf die Position des Spielers."
usage: "&b/setspawn"
clearchat: clearchat:
description: "&eLöscht den Chat für alle Spieler." description: "&eLöscht den Chat für alle Spieler."
usage: "&b/clearchat" usage: "&b/clearchat"
clearitems: clearitems:
description: "&eEntfernt alle Items auf dem Boden." description: "&eLöscht alle herumliegenden Items."
usage: "&b/clearitems" usage: "&b/clearitems"
closedoors: closedoors:
description: "&eSchließt alle Türen im angegebenen Radius." description: "&eSchließt alle Türen im angegebenen Radius."
usage: "&b/closedoors " usage: "&b/closedoors <radius>"
sit: sit:
description: "&eSetzt dich hin oder steht wieder auf." description: "&eLässt den Spieler sich hinsetzen oder aufstehen."
usage: "&b/sit" usage: "&b/sit"
back: back:
description: "&eTeleportiert dich zurück zum letzten Todespunkt." description: "&eTeleportiert zum letzten Todespunkt."
usage: "&b/back" usage: "&b/back"
friend: friend:
description: "&eVerwalte deine Freundesliste (hinzufügen, entfernen, anzeigen, teleportieren). Unterstützt anklickbare Anfragen und Bestätigungen." description: "&eVerwaltet die Freundesliste (hinzufügen, entfernen, anzeigen, teleportieren)."
usage: "&b/friend [Spieler]" usage: "&b/friend [add | accept | deny | list | del | tp] [Spieler]"
subcommands:
add:
description: "&eFügt einen Spieler zur Freundesliste hinzu."
usage: "&b/friend add <Spieler>"
accept:
description: "&eAkzeptiert eine Freundschaftsanfrage."
usage: "&b/friend accept <Spieler>"
deny:
description: "&eLehnt eine Freundschaftsanfrage ab."
usage: "&b/friend deny <Spieler>"
list:
description: "&eZeigt die Freundesliste an."
usage: "&b/friend list"
del:
description: "&eEntfernt einen Spieler aus der Freundesliste."
usage: "&b/friend del <Spieler>"
tp:
description: "&eTeleportiert dich zu einem Freund."
usage: "&b/friend tp <Spieler>"
ir: ir:
description: "&eBenennt Items um." description: "&eBenennt das Item in der Hand um."
usage: "&b/ir " usage: "&b/ir <neuer_name>"
showarmorstands: showarmorstands:
description: "&eZeigt unsichtbare ArmorStands an." description: "&eMacht alle unsichtbaren Armor Stands sichtbar."
usage: "&b/showarmorstands" usage: "&b/showarmorstands"
cleardebugarmorstands: cleardebugarmorstands:
description: "&eLöscht alle Debug ArmorStands." description: "&eEntfernt alle Debug-ArmorStands."
usage: "&b/cleardebugarmorstands" usage: "&b/cleardebugarmorstands"
trash: trash:
@@ -95,76 +154,72 @@ commands:
usage: "&b/trash" usage: "&b/trash"
workbench: workbench:
description: "&eÖffnet eine Werkbank GUI." description: "&eÖffnet eine Werkbank-GUI."
usage: "&b/workbench" usage: "&b/workbench"
anvil: anvil:
description: "&eÖffnet eine Amboss GUI." description: "&eÖffnet eine Amboss-GUI."
usage: "&b/anvil" usage: "&b/anvil"
stats: stats:
description: "&eZeigt deine persönlichen Statistiken an." description: "&eZeigt deine Statistiken an."
usage: "&b/stats" usage: "&b/stats"
spawn: spawn:
description: "&eTeleportiert dich zum Welt-Spawnpunkt." description: "&eTeleportiert dich zum Weltspawnpunkt."
usage: "&b/spawn" usage: "&b/spawn"
lock:
description: "&eSchützt Container mit dem LockSystem."
usage: "&b/lock [Spieler]"
tp: tp:
description: "&eTeleportiert dich zu einem anderen Spieler." description: "&eTeleportiert dich zu einem Spieler."
usage: "&b/tp " usage: "&b/tp <Spieler>"
tphere: tphere:
description: "&eTeleportiert einen Spieler zu dir." description: "&eTeleportiert einen Spieler zu dir."
usage: "&b/tphere " usage: "&b/tphere <Spieler>"
tpa: tpa:
description: "&eSendet eine Teleport-Anfrage an einen Spieler." description: "&eSendet eine Teleportanfrage an einen Spieler."
usage: "&b/tpa " usage: "&b/tpa <Spieler>"
tpaccept: tpaccept:
description: "&eAkzeptiert eine Teleport-Anfrage." description: "&eAkzeptiert eine Teleportanfrage."
usage: "&b/tpaccept" usage: "&b/tpaccept"
tpdeny: tpdeny:
description: "&eLehnt eine Teleport-Anfrage ab." description: "&eLehnt eine Teleportanfrage ab."
usage: "&b/tpdeny" usage: "&b/tpdeny"
block: block:
description: "&eBlockiert Nachrichten eines Spielers." description: "&eBlockiert einen Spieler."
usage: "&b/block " usage: "&b/block <Spieler>"
unblock: unblock:
description: "&eHebt eine Blockierung auf." description: "&eEntblockt einen Spieler."
usage: "&b/unblock " usage: "&b/unblock <Spieler>"
blocklist: blocklist:
description: "&eZeigt eine Liste blockierter Spieler." description: "&eZeigt eine Liste der blockierten Spieler."
usage: "&b/blocklist" usage: "&b/blocklist"
kit: kit:
description: "&eErhalte dein Starterkit." description: "&eHolt das Starterkit."
usage: "&b/kit" usage: "&b/kit"
leashcount: leashcount:
description: "&eZeigt die Anzahl der angeleinten Tiere an." description: "&eZeigt die Anzahl der geleinten Tiere an."
usage: "&b/leashcount" usage: "&b/leashcount"
nick: nick:
description: "&eÄndert deinen angezeigten Namen mit Farben (&) und Hex-Farben (#RRGGBB)." description: "&eÄndert deinen Nicknamen mit Farb- und Hex-Support."
usage: "&b/nick " usage: "&b/nick <Name>"
trade: lootchests:
description: "&eStartet einen Handel mit einem Spieler." description: "&eZeigt eine Liste aller aktiven Loot-Kisten an. Admins können per Klick teleportieren."
usage: "&b/trade " usage: "&b/lootchests"
tradeaccept: tploot:
description: "&eAkzeptiert eine Handelsanfrage." description: "&eTeleportiert dich zu einer Loot-Kiste (nur Admins)."
usage: "&b/tradeaccept " usage: "&b/tploot <welt> <x> <y> <z>"
day: day:
description: "&eSetzt die Zeit auf Tag." description: "&eSetzt die Zeit auf Tag."
@@ -174,33 +229,78 @@ commands:
description: "&eSetzt die Zeit auf Nacht." description: "&eSetzt die Zeit auf Nacht."
usage: "&b/night" usage: "&b/night"
trade:
description: "&eStartet einen Handel mit einem Spieler."
usage: "&b/trade <Spieler>"
tradeaccept:
description: "&eAkzeptiert eine Handelsanfrage."
usage: "&b/tradeaccept <Spieler>"
report: report:
description: "&eMeldet einen Spieler an die Admins." description: "&eMeldet einen Spieler an die Admins."
usage: "&b/report [Grund]" usage: "&b/report <Spieler> [Grund]"
showreport: showreport:
description: "&eZeigt alle Reports eines Spielers an." description: "&eZeigt alle Reports eines Spielers an."
usage: "&b/showreport " usage: "&b/showreport <Spieler>"
clearreport: clearreport:
description: "&eLöscht alle Reports eines Spielers." description: "&eLöscht alle Reports eines Spielers."
usage: "&b/clearreport " usage: "&b/clearreport <Spieler>"
shop: shop:
description: "&eVerwaltet den Server-Shop (z.B. Items hinzufügen)." description: "&eVerwaltet den Server-Shop (z.B. Items hinzufügen)."
usage: "&b/shop add " usage: "&b/shop add <item> <basispreis> <lagerbestand>"
setwarp:
description: "&eSetzt einen persönlichen Warp mit dem Item in der Hand."
usage: "&b/setwarp <name>"
delwarp:
description: "&eLöscht einen persönlichen Warp."
usage: "&b/delwarp <name>"
warps:
description: "&eÖffnet die GUI mit allen Spieler-Warps."
usage: "&b/warps"
startchallenge:
description: "&eStartet eine Fun-Challenge."
usage: "&b/startchallenge <name>"
heal:
description: "&eHeilt einen Spieler vollständig."
usage: "&b/heal [spieler]"
claim:
description: "&eVerwaltet Claims für den Anti-Grief-Schutz."
usage: "&b/claim [mark <1|2>| unclaim | trust <spieler> | untrust <spieler>]"
subcommands:
mark:
description: "&eMarkiert die erste oder zweite Ecke eines zu schützenden Bereichs."
usage: "&b/claim mark <1|2>"
unclaim:
description: "&eGibt den geschützten Bereich frei, in dem du stehst."
usage: "&b/claim unclaim"
trust:
description: "&eFügt einen Spieler als vertrauenswürdig hinzu, sodass er im Bereich bauen kann."
usage: "&b/claim trust <spieler>"
untrust:
description: "&eEntfernt die Vertrauensberechtigung eines Spielers für den Bereich."
usage: "&b/claim untrust <spieler>"
messages: messages:
header: "&6=== Befehle ===" header: "&6=== Befehle ==="
footer: "&6================" footer: "&6================"
navigation: navigation:
prev: "&7« Vorherige " prev: "&7« Vorherige Seite"
next: "&7 Nächste »" next: "&7Nächste Seite »"
prev-disabled: "&8« " prev-disabled: "&8« Vorherige Seite"
next-disabled: "&8 »" next-disabled: "&8Nächste Seite »"
page: "&fSeite {current} von {total}" page: "&fSeite {current} von {total}"
sp: sp:
invalid-subcommand: "&cUngültiger Unterbefehl! Verwendung: /sp [reload|help|info|share]" invalid-subcommand: "&cUngültiger Unterbefehl! Verwendung: /sp [reload|help|info|share|lock]"
no-permission: "&cDu hast keine Berechtigung für diesen Befehl!" no-permission: "&cDu hast keine Berechtigung für diesen Befehl!"
plugin: plugin:
reloaded: "&aSurvivalPlus wurde erfolgreich neu geladen!" reloaded: "&aSurvivalPlus wurde erfolgreich neu geladen!"

View File

@@ -402,5 +402,31 @@ inventory:
no-permission-others: "§cDu hast keine Berechtigung, das Inventar anderer Spieler anzusehen!" no-permission-others: "§cDu hast keine Berechtigung, das Inventar anderer Spieler anzusehen!"
player-only: "§cDieser Befehl ist nur für Spieler!" player-only: "§cDieser Befehl ist nur für Spieler!"
claim:
points-not-set: "&cDu musst zuerst zwei Punkte markieren! Verwende /claim mark <1|2>."
different-worlds: "&cDie markierten Punkte müssen in derselben Welt liegen!"
too-large: "&cDer Bereich ist zu groß! Maximal erlaubt: %max% Blöcke²."
overlap: "&cDieser Bereich überschneidet sich mit einem bestehenden Claim!"
max-reached: "&cDu hast das Maximum von %max% Claims erreicht!"
success: "&aBereich beansprucht! (%count%/%max%)"
unclaimed: "&aBereich freigegeben!"
not-owner: "&cDies ist nicht dein Claim!"
point1-set: "&aPunkt 1 gesetzt bei x=%x%, z=%z%."
point2-set: "&aPunkt 2 gesetzt bei x=%x%, z=%z%."
trusted: "&a%player% ist jetzt in diesem Claim vertraut!"
untrusted: "&a%player% ist in diesem Claim nicht mehr vertraut!"
no-break: "&cDu kannst in diesem beanspruchten Bereich keine Blöcke abbauen!"
no-place: "&cDu kannst in diesem beanspruchten Bereich keine Blöcke platzieren!"
op-unclaimed: "&a%count% Claims von %player% wurden entfernt!"
no-claims-found: "&cKeine Claims für %player% gefunden!"
no-claim-at-location: "&cKein Claim an dieser Position!"
info:
- "&eClaim-Info:"
- "&7Besitzer: &e%owner%"
- "&7Welt: &e%world%"
- "&7Koordinaten: &eX1: %x1%, Z1: %z1% bis X2: %x2%, Z2: %z2%"
enter: "&aDu hast das Gebiet von %owner% betreten."
leave: "&eDu hast das Gebiet von %owner% verlassen."
force-survival: force-survival:
join-message: "§aDu wurdest in den Survivalmodus gesetzt!" join-message: "§aDu wurdest in den Survivalmodus gesetzt!"

View File

@@ -1,5 +1,7 @@
name: SurvivalPlus name: SurvivalPlus
version: 1.0.5 version: 1.0.9
main: de.viper.survivalplus.SurvivalPlus main: de.viper.survivalplus.SurvivalPlus
api-version: 1.21 api-version: 1.21
softdepend: [LuckPerms, PlaceholderAPI] softdepend: [LuckPerms, PlaceholderAPI]
@@ -7,284 +9,283 @@ author: Viper
description: A plugin for enhancing survival gameplay in Minecraft. description: A plugin for enhancing survival gameplay in Minecraft.
commands: commands:
sp:
description: Hauptbefehl für SurvivalPlus (Command-Blocker, Reload, Info, etc.)
usage: /<command> [cb add|cb remove|cb list|reload|help|info|share] [args]
permission: survivalplus.sp
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
ir: ir:
description: Benennt das Item in der Hand um. description: Benennt das Item in der Hand um.
usage: /ir <neuer_name> usage: /<command> <neuer_name>
permission: survivalplus.itemrename permission: survivalplus.itemrename
permission-message: "§cDu hast keine Berechtigung für diesen Befehl." permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
gm: gm:
description: Ändert den Spielmodus eines Spielers description: Ändert den Spielmodus eines Spielers
usage: /<command> <modus> [spieler] usage: /<command> <modus> [spieler]
aliases: [gamemode] aliases: [gamemode]
permission: survivalplus.gamemode permission: survivalplus.gamemode
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
sp:
description: Zeigt Plugin-Informationen oder führt weitere Befehle aus
usage: /<command> [reload|help|info|share] [seite]
permission: survivalplus.sp
sethome: sethome:
description: Setzt ein Home mit dem angegebenen Namen description: Setzt ein Home mit dem angegebenen Namen
usage: /<command> <name> usage: /<command> <name>
permission: survivalplus.homes.set permission: survivalplus.homes.set
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
delhome: delhome:
description: Löscht ein Home mit dem angegebenen Namen description: Löscht ein Home mit dem angegebenen Namen
usage: /<command> <name> usage: /<command> <name>
permission: survivalplus.homes.delete permission: survivalplus.homes.delete
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
homelist: homelist:
description: Öffnet eine GUI mit allen Homes description: Öffnet eine GUI mit allen Homes
usage: /<command> usage: /<command>
permission: survivalplus.homes.list permission: survivalplus.homes.list
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
home: home:
description: Teleportiert zu einem Home description: Teleportiert zu einem Home
usage: /<command> <name> usage: /<command> <name>
permission: survivalplus.homes permission: survivalplus.homes
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
inv: inv:
description: Öffnet das Inventar (eigenes oder das eines anderen Spielers) description: Öffnet das Inventar (eigenes oder das eines anderen Spielers)
usage: /<command> [spieler] usage: /<command> [spieler]
permission: survivalplus.inventory.own permission: survivalplus.inventory.own
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
ec: ec:
description: Öffnet die Endertruhe (eigene oder die eines anderen Spielers) description: Öffnet die Endertruhe (eigene oder die eines anderen Spielers)
usage: /<command> [spieler] usage: /<command> [spieler]
permission: survivalplus.enderchest.own permission: survivalplus.enderchest.own
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
setworldspawn: setworldspawn:
description: Setzt den Weltspawnpunkt auf die Position des Spielers description: Setzt den Weltspawnpunkt auf die Position des Spielers
usage: /<command> usage: /<command>
permission: survivalplus.setworldspawn permission: survivalplus.setworldspawn
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
setspawn: setspawn:
description: Setzt den Server-Spawnpunkt auf die Position des Spielers description: Setzt den Server-Spawnpunkt auf die Position des Spielers
usage: /<command> usage: /<command>
permission: survivalplus.setspawn permission: survivalplus.setspawn
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
clearchat: clearchat:
description: Löscht den Chat für alle Spieler description: Löscht den Chat für alle Spieler
usage: /<command> usage: /<command>
permission: survivalplus.clearchat permission: survivalplus.clearchat
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
clearitems: clearitems:
description: Löscht alle herumliegenden Items description: Löscht alle herumliegenden Items
usage: /<command> usage: /<command>
permission: survivalplus.clearitems permission: survivalplus.clearitems
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
closedoors: closedoors:
description: Schließt alle Türen im angegebenen Radius description: Schließt alle Türen im angegebenen Radius
usage: /<command> <radius> usage: /<command> <radius>
permission: survivalplus.closedoors permission: survivalplus.closedoors
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
sit: sit:
description: Lässt den Spieler sich hinsetzen description: Lässt den Spieler sich hinsetzen
usage: /<command> usage: /<command>
permission: survivalplus.sit permission: survivalplus.sit
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
back: back:
description: Teleportiert zum letzten Todespunkt description: Teleportiert zum letzten Todespunkt
usage: /<command> usage: /<command>
permission: survivalplus.back permission: survivalplus.back
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
friend: friend:
description: Verwaltet die Freundesliste description: Verwaltet die Freundesliste
usage: /<command> [add|accept|deny|list|del|tp] [Spielername] usage: /<command> [add|accept|deny|list|del|tp] [Spielername]
permission: survivalplus.friend permission: survivalplus.friend
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
stats: stats:
description: Zeigt deine Statistiken an description: Zeigt deine Statistiken an
usage: /stats usage: /<command>
permission: survivalplus.stats permission: survivalplus.stats
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
showarmorstands: showarmorstands:
description: Macht alle unsichtbaren Armor Stands sichtbar. description: Macht alle unsichtbaren Armor Stands sichtbar.
usage: /showarmorstands usage: /<command>
permission: survivalplus.showarmorstands permission: survivalplus.showarmorstands
permission-message: "§cDu hast keine Rechte für diesen Befehl." permission-message: "§cDu hast keine Rechte für diesen Befehl."
cleardebugarmorstands: cleardebugarmorstands:
description: Entfernt alle Debug-ArmorStands description: Entfernt alle Debug-ArmorStands
usage: /cleardebugarmorstands usage: /<command>
permission: survivalplus.cleardebugarmorstands permission: survivalplus.cleardebugarmorstands
permission-message: "§cDu hast keine Rechte für diesen Befehl." permission-message: "§cDu hast keine Rechte für diesen Befehl."
trash: trash:
description: Öffnet den Mülleimer description: Öffnet den Mülleimer
usage: /trash usage: /<command>
permission: survivalplus.trash permission: survivalplus.trash
permission-message: "§cDu hast keine Berechtigung für diesen Befehl." permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
workbench: workbench:
description: Öffnet eine Werkbank GUI description: Öffnet eine Werkbank GUI
usage: /workbench usage: /<command>
permission: survivalplus.workbench permission: survivalplus.workbench
permission-message: "§cDu hast keine Berechtigung für diesen Befehl." permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
anvil: anvil:
description: Öffnet eine Amboss GUI description: Öffnet eine Amboss GUI
usage: /anvil usage: /<command>
permission: survivalplus.anvil permission: survivalplus.anvil
permission-message: "§cDu hast keine Berechtigung für diesen Befehl." permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
leashcount: leashcount:
description: Zeigt die Anzahl der geleinten Tiere an. description: Zeigt die Anzahl der geleinten Tiere an.
usage: /leashcount usage: /<command>
permission: survivalplus.leashcount permission: survivalplus.leashcount
permission-message: "§cDu hast keine Berechtigung für diesen Befehl." permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
splock: splock:
description: Verwaltet das Sperrsystem für Kisten und Türen description: Verwaltet das Sperrsystem für Kisten und Türen
usage: /sp lock|unlock|friendadd|friendremove [Spieler] usage: /<command> lock|unlock|friendadd|friendremove [Spieler]
permission: survivalplus.lock permission: survivalplus.lock
permission-message: "§cDu hast keine Berechtigung für diesen Befehl." permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
tp: tp:
description: Teleportiere dich zu einem Spieler description: Teleportiere dich zu einem Spieler
usage: /tp <Spieler> usage: /<command> <Spieler>
permission: survivalplus.tp
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
tphere: tphere:
description: Teleportiere einen Spieler zu dir description: Teleportiere einen Spieler zu dir
usage: /tphere <Spieler> usage: /<command> <Spieler>
permission: survivalplus.tphere
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
tpa: tpa:
description: Sende eine Teleportanfrage an einen Spieler description: Sende eine Teleportanfrage an einen Spieler
usage: /tpa <Spieler> usage: /<command> <Spieler>
permission: survivalplus.tpa
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
tpaccept: tpaccept:
description: Akzeptiere eine Teleportanfrage description: Akzeptiere eine Teleportanfrage
usage: /tpaccept usage: /<command>
permission: survivalplus.tpaccept
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
tpdeny: tpdeny:
description: Lehne eine Teleportanfrage ab description: Lehne eine Teleportanfrage ab
usage: /tpdeny usage: /<command>
permission: survivalplus.tpdeny
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
block: block:
description: Blockiere einen Spieler description: Blockiere einen Spieler
usage: /block <Spieler> usage: /<command> <Spieler>
permission: survivalplus.block permission: survivalplus.block
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
unblock: unblock:
description: Entblocke einen Spieler description: Entblocke einen Spieler
usage: /unblock <Spieler> usage: /<command> <Spieler>
permission: survivalplus.unlock permission: survivalplus.unblock
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
blocklist: blocklist:
description: Zeige eine Liste der blockierten Spieler description: Zeige eine Liste der blockierten Spieler
usage: /blocklist usage: /<command>
permission: survivalplus.blocklist permission: survivalplus.blocklist
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
kit: kit:
description: Hol dir das Starterkit! description: Hol dir das Starterkit!
usage: /kit usage: /<command>
permission: survivalplus.kit permission: survivalplus.kit
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
nick: nick:
description: Ändert deinen Nicknamen mit Farb- und Hex-Support. description: Ändert deinen Nicknamen mit Farb- und Hex-Support.
usage: /nick <Name> usage: /<command> <Name>
permission: survivalplus.nick permission: survivalplus.nick
permission-message: "§cDu hast keine Berechtigung, deinen Nick zu ändern!" permission-message: "§cDu hast keine Berechtigung, deinen Nick zu ändern!"
lootchests: lootchests:
description: Zeigt eine Liste aller aktiven Loot-Kisten an. Admins können per Klick zu einer Kiste teleportieren. description: Zeigt eine Liste aller aktiven Loot-Kisten an. Admins können per Klick zu einer Kiste teleportieren.
usage: /lootchests usage: /<command>
permission: survivalplus.lootchests permission: survivalplus.lootchests
permission-message: "§cDu hast keine Berechtigung für diesen Befehl!" permission-message: "§cDu hast keine Berechtigung für diesen Befehl!"
tploot: tploot:
description: Teleportiere dich zu einer Loot-Kiste (nur Admins) description: Teleportiere dich zu einer Loot-Kiste (nur Admins)
usage: /tploot <welt> <x> <y> <z> usage: /<command> <welt> <x> <y> <z>
permission: survivalplus.lootchests permission: survivalplus.lootchests
permission-message: "§cDu hast keine Berechtigung für diesen Befehl!" permission-message: "§cDu hast keine Berechtigung für diesen Befehl!"
day: day:
description: Setzt die Zeit auf Tag description: Setzt die Zeit auf Tag
usage: /day usage: /<command>
permission: survivalplus.day permission: survivalplus.day
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
night: night:
description: Setzt die Zeit auf Nacht description: Setzt die Zeit auf Nacht
usage: /night usage: /<command>
permission: survivalplus.night permission: survivalplus.night
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
trade: trade:
description: Startet einen Handel mit einem Spieler description: Startet einen Handel mit einem Spieler
usage: /trade <Spieler> usage: /<command> <Spieler>
permission: survivalplus.trade permission: survivalplus.trade
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
tradeaccept: tradeaccept:
description: Akzeptiert eine Handelsanfrage description: Akzeptiert eine Handelsanfrage
usage: /tradeaccept <Spieler> usage: /<command> <Spieler>
permission: survivalplus.tradeaccept permission: survivalplus.tradeaccept
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
report: report:
description: Meldet einen Spieler an die Admins description: Meldet einen Spieler an die Admins
usage: /report <Spieler> [Grund] usage: /<command> <Spieler> [Grund]
permission: survivalplus.report permission: survivalplus.report
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
showreport: showreport:
description: Zeigt alle Reports eines Spielers an description: Zeigt alle Reports eines Spielers an
usage: /showreport <Spieler> usage: /<command> <Spieler>
permission: survivalplus.report.show permission: survivalplus.report.show
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
clearreport: clearreport:
description: Löscht alle Reports eines Spielers description: Löscht alle Reports eines Spielers
usage: /clearreport <Spieler> usage: /<command> <Spieler>
permission: survivalplus.report.clear permission: survivalplus.report.clear
permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
shop: shop:
description: Verwalten des Server-Shops (z.B. Items hinzufügen) description: Verwalten des Server-Shops (z.B. Items hinzufügen)
usage: /shop add <item> <basispreis> <lagerbestand> usage: /<command> add <item> <basispreis> <lagerbestand>
permission: survivalplus.shop permission: survivalplus.shop
permission-message: "§cDu hast keine Berechtigung für diesen Befehl." permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
spawn: spawn:
description: Teleportiert dich zum Weltspawnpunkt. description: Teleportiert dich zum Weltspawnpunkt.
usage: /spawn usage: /<command>
permission: survivalplus.spawn permission: survivalplus.spawn
permission-message: "§cDu hast keine Berechtigung für diesen Befehl." permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
setwarp: setwarp:
description: Setzt einen persönlichen Warp mit dem Item in der Hand. description: Setzt einen persönlichen Warp mit dem Item in der Hand.
usage: /setwarp <name> usage: /<command> <name>
permission: survivalplus.setwarp permission: survivalplus.setwarp
permission-message: "§cDu hast keine Berechtigung für diesen Befehl." permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
delwarp: delwarp:
description: Löscht einen persönlichen Warp. description: Löscht einen persönlichen Warp.
usage: /delwarp <name> usage: /<command> <name>
permission: survivalplus.delwarp permission: survivalplus.delwarp
permission-message: "§cDu hast keine Berechtigung für diesen Befehl." permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
warps: warps:
description: Öffnet die GUI mit allen Spieler-Warps. description: Öffnet die GUI mit allen Spieler-Warps.
usage: /warps usage: /<command>
permission: survivalplus.warps permission: survivalplus.warps
permission-message: "§cDu hast keine Berechtigung für diesen Befehl." permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
startchallenge: startchallenge:
description: Startet eine Fun-Challenge description: Startet eine Fun-Challenge
usage: /startchallenge <name> usage: /<command> <name>
permission: survivalplus.startchallenge permission: survivalplus.startchallenge
permission-message: "§cDu hast keine Berechtigung für diesen Befehl." permission-message: "§cDu hast keine Berechtigung für diesen Befehl."
heal: heal:
description: Heilt einen Spieler vollständig description: Heilt einen Spieler vollständig
usage: /heal [spieler] usage: /<command> [spieler]
permission: survivalplus.heal permission: survivalplus.heal
permission-message: "§cDu hast keine Berechtigung, Spieler zu heilen!" permission-message: "§cDu hast keine Berechtigung, Spieler zu heilen!"
survivalplus.notify: claim:
description: Erhält Benachrichtigungen, wenn ein Spieler einen Command- oder Structure-Block besitzt description: Manages claims for anti-griefing
default: op usage: /<command> [unclaim | trust <player> | untrust <player>]
aliases: [cl]
survivalplus.claim.use:
description: Allows claiming and unclaiming chunks
default: true
survivalplus.claim.trust:
description: Allows trusting/untrusting players in claims
default: true
permissions: permissions:
survivalplus.*: survivalplus.*:
description: Gibt Zugriff auf alle SurvivalPlus-Befehle description: Gibt Zugriff auf alle SurvivalPlus-Befehle
default: op default: op
children: children:
survivalplus.commandblocker.add: true
survivalplus.commandblocker.remove: true
survivalplus.commandblocker.list: true
survivalplus.commandblocker.bypass: true
survivalplus.gamemode: true survivalplus.gamemode: true
survivalplus.gamemode.others: true survivalplus.gamemode.others: true
survivalplus.sp: true survivalplus.sp: true
@@ -315,194 +316,221 @@ permissions:
survivalplus.workbench: true survivalplus.workbench: true
survivalplus.anvil: true survivalplus.anvil: true
survivalplus.leashcount: true survivalplus.leashcount: true
survivalplus.lock: true
survivalplus.tp: true
survivalplus.tphere: true
survivalplus.tpa: true
survivalplus.tpaccept: true
survivalplus.tpdeny: true
survivalplus.block: true
survivalplus.unblock: true
survivalplus.blocklist: true
survivalplus.kit: true
survivalplus.nick: true survivalplus.nick: true
survivalplus.lootchests: true survivalplus.lootchests: true
survivalplus.day: true
survivalplus.night: true
survivalplus.trade: true
survivalplus.tradeaccept: true
survivalplus.report: true
survivalplus.report.show: true
survivalplus.report.clear: true
survivalplus.shop: true
survivalplus.spawn: true
survivalplus.setwarp: true
survivalplus.delwarp: true
survivalplus.warps: true
survivalplus.startchallenge: true survivalplus.startchallenge: true
survivalplus.heal: true survivalplus.heal: true
survivalplus.heal.others: true survivalplus.heal.others: true
survivalplus.notify: true survivalplus.notify: true
survivalplus.chunkanimals: true
survivalplus.lootchests: survivalplus.commandblocker.add:
description: Erlaubt das Verwalten und Teleportieren zu Loot-Kisten description: Erlaubt das Hinzufügen von Befehlen zur Blockierliste
default: op
survivalplus.commandblocker.remove:
description: Erlaubt das Entfernen von Befehlen aus der Blockierliste
default: op
survivalplus.commandblocker.list:
description: Erlaubt das Anzeigen der Blockierliste
default: op
survivalplus.commandblocker.bypass:
description: Erlaubt das Umgehen blockierter Befehle
default: op default: op
survivalplus.gamemode: survivalplus.gamemode:
description: Erlaubt das Ändern des eigenen Spielmodus description: Erlaubt das Ändern des eigenen Spielmodus
default: op default: op
survivalplus.gamemode.others: survivalplus.gamemode.others:
description: Erlaubt das Ändern des Spielmodus anderer Spieler description: Erlaubt das Ändern des Spielmodus anderer Spieler
default: op default: op
survivalplus.sp: survivalplus.sp:
description: Erlaubt den Zugriff auf den /sp-Befehl description: Erlaubt den Zugriff auf den /sp-Befehl
default: op default: op
survivalplus.share: survivalplus.share:
description: Erlaubt das Teilen der eigenen Koordinaten mit /sp share description: Erlaubt das Teilen der eigenen Koordinaten mit /sp share
default: true default: true
survivalplus.homes.set: survivalplus.homes.set:
description: Erlaubt das Setzen von Homes description: Erlaubt das Setzen von Homes
default: true default: true
survivalplus.homes.delete: survivalplus.homes.delete:
description: Erlaubt das Löschen von Homes description: Erlaubt das Löschen von Homes
default: true default: true
survivalplus.homes.list: survivalplus.homes.list:
description: Erlaubt das Öffnen der Home-Liste GUI description: Erlaubt das Öffnen der Home-Liste GUI
default: true default: true
survivalplus.homes: survivalplus.homes:
description: Erlaubt das Teleportieren zu Homes description: Erlaubt das Teleportieren zu Homes
default: true default: true
survivalplus.homes.unlimited: survivalplus.homes.unlimited:
description: Erlaubt unbegrenzte Homes description: Erlaubt unbegrenzte Homes
default: op default: op
survivalplus.inventory.own: survivalplus.inventory.own:
description: Erlaubt das Ansehen des eigenen Inventars description: Erlaubt das Ansehen des eigenen Inventars
default: true default: true
survivalplus.inventory.others: survivalplus.inventory.others:
description: Erlaubt das Ansehen des Inventars anderer Spieler description: Erlaubt das Ansehen des Inventars anderer Spieler
default: op default: op
survivalplus.enderchest.own: survivalplus.enderchest.own:
description: Erlaubt das Ansehen der eigenen Endertruhe description: Erlaubt das Ansehen der eigenen Endertruhe
default: true default: true
survivalplus.enderchest.others: survivalplus.enderchest.others:
description: Erlaubt das Ansehen der Endertruhen anderer Spieler description: Erlaubt das Ansehen der Endertruhen anderer Spieler
default: op default: op
survivalplus.setworldspawn: survivalplus.setworldspawn:
description: Erlaubt das Setzen des Weltspawnpunkts description: Erlaubt das Setzen des Weltspawnpunkts
default: op default: op
survivalplus.setspawn: survivalplus.setspawn:
description: Erlaubt das Setzen des Server-Spawnpunkts description: Erlaubt das Setzen des Server-Spawnpunkts
default: op default: op
survivalplus.clearchat: survivalplus.clearchat:
description: Erlaubt das Löschen des Chats description: Erlaubt das Löschen des Chats
default: op default: op
survivalplus.clearitems: survivalplus.clearitems:
description: Erlaubt das manuelle Löschen der herumliegenden Items description: Erlaubt das manuelle Löschen der herumliegenden Items
default: op default: op
survivalplus.closedoors: survivalplus.closedoors:
description: Erlaubt das Schließen von Türen mit /closedoors description: Erlaubt das Schließen von Türen mit /closedoors
default: op default: op
survivalplus.sit: survivalplus.sit:
description: Erlaubt das Sitzen auf Treppen oder mit /sit description: Erlaubt das Sitzen auf Treppen oder mit /sit
default: true default: true
survivalplus.graves:
description: Erlaubt das Erstellen von Gräbern bei Tod
default: true
survivalplus.back: survivalplus.back:
description: Erlaubt das Teleportieren zum letzten Todespunkt description: Erlaubt das Teleportieren zum letzten Todespunkt
default: true default: true
survivalplus.graves:
description: Erlaubt das Erstellen von Gräbern bei Tod
default: true
survivalplus.friend: survivalplus.friend:
description: Erlaubt die Verwaltung der Freundesliste description: Erlaubt die Verwaltung der Freundesliste
default: true default: true
survivalplus.itemrename: survivalplus.itemrename:
description: Erlaubt das Umbenennen von Items mit /ir description: Erlaubt das Umbenennen von Items mit /ir
default: true default: true
survivalplus.stats: survivalplus.stats:
description: Erlaubt den Zugriff auf den /stats-Befehl description: Erlaubt den Zugriff auf den /stats-Befehl
default: true default: true
survivalplus.showarmorstands: survivalplus.showarmorstands:
description: Erlaubt das Sichtbarmachen von Armor Stands mit /showarmorstands description: Erlaubt das Sichtbarmachen von Armor Stands mit /showarmorstands
default: op default: op
survivalplus.cleardebugarmorstands: survivalplus.cleardebugarmorstands:
description: Erlaubt das Entfernen von Debug-ArmorStands description: Erlaubt das Entfernen von Debug-ArmorStands
default: op default: op
survivalplus.trash: survivalplus.trash:
description: Erlaubt die Nutzung von /trash description: Erlaubt die Nutzung von /trash
default: true default: true
survivalplus.workbench: survivalplus.workbench:
description: Erlaubt die Nutzung von /workbench description: Erlaubt die Nutzung von /workbench
default: true default: true
survivalplus.anvil: survivalplus.anvil:
description: Erlaubt die Nutzung von /anvil description: Erlaubt die Nutzung von /anvil
default: true default: true
survivalplus.leashcount: survivalplus.leashcount:
description: Erlaubt die Nutzung von /leashcount description: Erlaubt die Nutzung von /leashcount
default: true default: true
survivalplus.chunkanimals:
description: Erlaubt das Anzeigen der Anzahl der Tiere im aktuellen Chunk
default: op
survivalplus.lock: survivalplus.lock:
description: Erlaubt das Verwenden von /lock-Befehlen description: Erlaubt das Verwenden von /lock-Befehlen
default: true default: true
survivalplus.tp: survivalplus.tp:
description: Erlaube das Teleportieren zu anderen Spielern description: Erlaubt das Teleportieren zu anderen Spielern
default: op default: op
survivalplus.tphere: survivalplus.tphere:
description: Erlaube das Teleportieren anderer Spieler zu dir description: Erlaubt das Teleportieren anderer Spieler zu dir
default: op default: op
survivalplus.tpa: survivalplus.tpa:
description: Erlaube das Senden von Teleportanfragen description: Erlaubt das Senden von Teleportanfragen
default: true default: true
survivalplus.tpaccept: survivalplus.tpaccept:
description: Erlaube das Annehmen von Teleportanfragen description: Erlaubt das Annehmen von Teleportanfragen
default: true default: true
survivalplus.tpdeny: survivalplus.tpdeny:
description: Erlaube das Ablehnen von Teleportanfragen description: Erlaubt das Ablehnen von Teleportanfragen
default: true default: true
survivalplus.block: survivalplus.block:
description: Erlaubt das Blockieren anderer Spieler im Chat description: Erlaubt das Blockieren anderer Spieler im Chat
default: true default: true
survivalplus.unblock:
survivalplus.info: description: Erlaubt das Entblocken anderer Spieler im Chat
description: Erlaubt den Zugriff auf /sp info default: true
survivalplus.blocklist:
description: Erlaubt das Anzeigen der blockierten Spieler
default: true
survivalplus.kit:
description: Erlaubt das Abrufen des Starterkits
default: true default: true
survivalplus.nick: survivalplus.nick:
description: Erlaubt es, den eigenen Nicknamen zu ändern (mit Farben & Hex) description: Erlaubt das Ändern des eigenen Nicknamens (mit Farben & Hex)
default: op
survivalplus.lootchests:
description: Erlaubt das Verwalten und Teleportieren zu Loot-Kisten
default: op
survivalplus.day:
description: Erlaubt das Setzen der Zeit auf Tag
default: op
survivalplus.night:
description: Erlaubt das Setzen der Zeit auf Nacht
default: op
survivalplus.trade:
description: Erlaubt das Starten eines Handels
default: true
survivalplus.tradeaccept:
description: Erlaubt das Akzeptieren eines Handels
default: true
survivalplus.report:
description: Erlaubt das Melden von Spielern
default: true
survivalplus.report.show:
description: Erlaubt das Anzeigen von Spieler-Reports
default: op
survivalplus.report.clear:
description: Erlaubt das Löschen von Spieler-Reports
default: op default: op
survivalplus.shop: survivalplus.shop:
description: Erlaubt die Nutzung des Shop-Befehls description: Erlaubt die Nutzung des Shop-Befehls
default: op default: op
survivalplus.spawn: survivalplus.spawn:
description: Erlaubt die Nutzung des /spawn Befehls description: Erlaubt die Nutzung des /spawn Befehls
default: true default: true
survivalplus.setwarp: survivalplus.setwarp:
description: Erlaubt das Setzen von persönlichen Warps description: Erlaubt das Setzen von persönlichen Warps
default: true default: true
survivalplus.delwarp:
description: Erlaubt das Löschen von persönlichen Warps
default: true
survivalplus.warps: survivalplus.warps:
description: Erlaubt das Öffnen der Warps-GUI description: Erlaubt das Öffnen der Warps-GUI
default: true default: true
survivalplus.startchallenge:
delwarp: description: Erlaubt das Starten von Fun-Challenges
description: Erlaubt das Löschen von persönlichen Warps default: op
default: true survivalplus.heal:
description: Erlaubt das Heilen des eigenen Spielers
default: op
survivalplus.heal.others:
description: Erlaubt das Heilen anderer Spieler
default: op
survivalplus.notify:
description: Erhält Benachrichtigungen, wenn ein Spieler einen Command- oder Structure-Block besitzt
default: op
survivalplus.chunkanimals:
description: Erlaubt das Anzeigen der Anzahl der Tiere im aktuellen Chunk
default: op