Update: Versionierung in config/lang/help/tablist.yml + Debug-System

This commit is contained in:
2025-08-27 20:07:30 +02:00
parent a69200ee17
commit 7fb9afa9d3
13 changed files with 1042 additions and 327 deletions

View File

@@ -6,7 +6,7 @@
<groupId>de.viper</groupId>
<artifactId>SurvivalPlus</artifactId>
<version>1.0.7-Beta</version>
<version>1.0.9-Beta</version>
<packaging>jar</packaging>
@@ -113,6 +113,7 @@
<include>warps.yml</include>
<include>tablist.yml</include>
<include>blockedcommands.yml</include>
<include>claims.yml</include>
</includes>
</resource>
</resources>

View File

@@ -58,13 +58,19 @@ public class TablistManager implements Listener {
// Resource sicherstellen, Config laden
try {
plugin.saveResource("tablist.yml", false);
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();
// Nicknames.yml laden
try {
File nicknameFile = new File(plugin.getDataFolder(), "nicknames.yml");

View File

@@ -11,6 +11,7 @@ import de.viper.survivalplus.recipe.BackpackRecipe;
import de.viper.survivalplus.Manager.StatsManager;
import de.viper.survivalplus.Manager.BlockManager;
import de.viper.survivalplus.util.LockSystem;
import de.viper.survivalplus.util.Claim;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
@@ -38,24 +39,19 @@ import de.viper.survivalplus.Manager.CommandBlocker;
import de.viper.survivalplus.Manager.WarpManager;
import de.viper.survivalplus.commands.SetWarpCommand;
import de.viper.survivalplus.commands.WarpsCommand;
import de.viper.survivalplus.fun.FunChallengeManager;
import de.viper.survivalplus.listeners.ChallengeCollectListener;
import de.viper.survivalplus.commands.StartFunChallengeCommand;
import java.util.Map;
import java.util.UUID;
import java.util.HashMap;
import org.bukkit.NamespacedKey;
import org.bukkit.plugin.PluginManager;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.logging.Level;
// Zusätzliche Imports für Block-/Permission-Handling
import org.bukkit.GameRule;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
@@ -68,6 +64,15 @@ 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 {
@@ -89,15 +94,12 @@ public class SurvivalPlus extends JavaPlugin {
private FileConfiguration mobCapConfig;
private FileConfiguration tablistConfig;
private File tablistFile;
private File nicknamesFile;
private FileConfiguration nicknamesConfig;
private SpawnProtectionListener spawnProtectionListener;
private int autoClearTaskId = -1;
private StatsManager statsManager;
private NewbieProtectionListener newbieListener;
// Listener als Felder speichern
private MobLeashLimitListener mobLeashLimitListener;
private MobCapListener mobCapListener;
private SleepListener sleepListener;
@@ -109,32 +111,33 @@ public class SurvivalPlus extends JavaPlugin {
private FunChallengeManager challengeManager;
private NamespacedKey droppedKey;
private Map<UUID, Integer> progressMap = new HashMap<>();
// WarpManager als Feld
private WarpManager warpManager;
// FunChallengeManager als Feld
private FunChallengeManager funChallengeManager;
private File blockedCommandsFile;
private FileConfiguration blockedCommandsConfig;
// Felder für Executor-Instanzen
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() {
// Lädt die tablist.yml aus dem Plugin-Ordner neu
if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml");
if (!tablistFile.exists()) {
saveResource("tablist.yml", false); // kopiert die default tablist.yml, falls sie fehlt
saveResource("tablist.yml", false);
}
tablistConfig = YamlConfiguration.loadConfiguration(tablistFile);
}
public FileConfiguration getTablistConfig() {
// Stellt sicher, dass die Config geladen ist
if (tablistConfig == null) {
reloadTablistConfig();
}
@@ -174,329 +177,506 @@ public class SurvivalPlus extends JavaPlugin {
} catch (IOException ignored) {}
}
@Override
public void onEnable() {
// Default-Config sicherstellen
saveDefaultConfig();
@Override
public void onEnable() {
saveDefaultConfig();
// bStats initialisieren
int pluginId = 26886;
Metrics metrics = new Metrics(this, pluginId);
// Version aus plugin.yml
String pluginVersion = getDescription().getVersion();
metrics.addCustomChart(new SimplePie(
"default_gamemode",
() -> Bukkit.getDefaultGameMode().toString()
));
metrics.addCustomChart(new SingleLineChart(
"online_players",
() -> Bukkit.getOnlinePlayers().size()
));
metrics.addCustomChart(new SimplePie(
"plugin_language",
() -> getConfig().getString("language", "default")
));
// 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);
// Konfigurationen/Dateien laden
updateConfigFiles();
createHomesFile();
createGravesFile();
createBackpackFile();
createFriendsFile();
createLeashesFile();
createMobCapFile();
createNicknamesFile();
reloadBlockedCommandsConfig();
// Debug-Logging initialisieren
if (getConfig().getBoolean("debug-logging", false)) {
try {
// Ordner erstellen
File debugFolder = new File(getDataFolder(), "Debug");
if (!debugFolder.exists()) {
debugFolder.mkdirs();
}
// PluginManager holen (vor Listener-Registrierung!)
PluginManager pluginManager = getServer().getPluginManager();
// debug.log für Fehler
debugFile = new File(debugFolder, "debug.log");
if (!debugFile.exists()) debugFile.createNewFile();
debugWriter = new PrintWriter(new FileWriter(debugFile, true), true);
// Permission registrieren: survivalplus.notify für OPs standardmäßig aktiv
try {
Permission notifyPerm = new Permission("survivalplus.notify", PermissionDefault.OP);
if (pluginManager.getPermission("survivalplus.notify") == null) {
pluginManager.addPermission(notifyPerm);
getLogger().info("Permission survivalplus.notify erfolgreich registriert.");
}
} catch (Exception e) {
getLogger().warning("Fehler beim Registrieren der Permission survivalplus.notify: " + e.getMessage());
}
// 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);
// NamespacedKey für Item-Drop-Markierung erzeugen
droppedKey = new NamespacedKey(this, "droppedItem");
// FunChallengeManager initialisieren und laden
funChallengeManager = new FunChallengeManager();
funChallengeManager.load(getConfig());
// Listener registrieren mit droppedKey
pluginManager.registerEvents(new ChallengeCollectListener(funChallengeManager, droppedKey), this);
pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this);
// FriendCommand
FriendCommand friendCommand = new FriendCommand(this, friendsConfig, langConfig, getLogger());
getCommand("day").setExecutor(new DayCommand(this));
getCommand("night").setExecutor(new NightCommand(this));
CommandBlocker commandBlocker = new CommandBlocker(this);
pluginCommand = new PluginCommand(this);
getCommand("sp").setExecutor(pluginCommand);
// TradeManager und ReportManager initialisieren
TradeManager tradeManager = new TradeManager(this);
ReportManager reportManager = new ReportManager(this);
// Report Commands registrieren
getCommand("report").setExecutor(new ReportCommand(this, reportManager));
getCommand("showreport").setExecutor(new ShowReportCommand(this, reportManager));
getCommand("clearreport").setExecutor(new ClearReportCommand(this, reportManager));
// Trade Commands registrieren
getCommand("trade").setExecutor(new TradeCommand(this, tradeManager));
getCommand("tradeaccept").setExecutor(new TradeAcceptCommand(this, tradeManager));
// StatsManager initialisieren
statsManager = new StatsManager(this);
// warpManager initialisieren
warpManager = new WarpManager(this);
// TablistManager starten
TablistManager tablistManager = new TablistManager(this);
// Listener-Instanzen
sitListener = new SitListener(this);
afkListener = new AFKListener(this);
graveListener = new GraveListener(this);
playerJoinListener = new PlayerJoinListener(friendCommand);
// Commands registrieren (Rest)
getCommand("gm").setExecutor(new GamemodeCommand(this));
getCommand("sp").setExecutor(new PluginCommand(this));
getCommand("sethome").setExecutor(new HomeCommand(this));
getCommand("delhome").setExecutor(new HomeCommand(this));
getCommand("homelist").setExecutor(new HomeCommand(this));
getCommand("inv").setExecutor(new InventoryCommand(this));
getCommand("ec").setExecutor(new EnderchestCommand(this));
getCommand("setspawn").setExecutor(new SetSpawnCommand(this));
getCommand("setworldspawn").setExecutor(new SetWorldSpawnCommand(this));
getCommand("clearchat").setExecutor(new ClearChatCommand());
getCommand("clearitems").setExecutor(new ClearItemsCommand(this));
getCommand("closedoors").setExecutor(new CloseDoorsCommand(this));
getCommand("sit").setExecutor(new SitCommand(this, sitListener));
getCommand("back").setExecutor(new BackCommand(this));
getCommand("friend").setExecutor(friendCommand);
getCommand("ir").setExecutor(new ItemRenameCommand(this));
getCommand("showarmorstands").setExecutor(new ShowArmorStandsCommand(this));
getCommand("cleardebugarmorstands").setExecutor(new ClearDebugArmorStandsCommand(this));
getCommand("trash").setExecutor(new TrashCommand());
getCommand("workbench").setExecutor(new WorkbenchCommand());
getCommand("anvil").setExecutor(new AnvilCommand());
getCommand("nick").setExecutor(new NickCommand(this));
getCommand("shop").setExecutor(new ShopCommand(this));
getCommand("stats").setExecutor(new StatsCommand(this, statsManager));
getCommand("spawn").setExecutor(new SpawnCommand(this));
getCommand("setwarp").setExecutor(new SetWarpCommand(this, warpManager));
getCommand("warps").setExecutor(new WarpsCommand(this, warpManager));
getCommand("delwarp").setExecutor(new DelWarpCommand(this, warpManager));
TeleportCommands teleportCommands = new TeleportCommands(this);
getCommand("tp").setExecutor(teleportCommands);
getCommand("tphere").setExecutor(teleportCommands);
getCommand("tpa").setExecutor(teleportCommands);
getCommand("tpaccept").setExecutor(teleportCommands);
getCommand("tpdeny").setExecutor(teleportCommands);
getCommand("startchallenge").setExecutor(new StartFunChallengeCommand(this, funChallengeManager));
getCommand("kit").setExecutor(new KitCommand(this));
getCommand("heal").setExecutor(new HealCommand(this));
getCommand("sp").setExecutor(commandBlocker);
// LootChestManager + Befehle
LootChestManager lootChestManager = new LootChestManager(this);
pluginManager.registerEvents(lootChestManager, this);
getCommand("lootchests").setExecutor(lootChestManager);
getCommand("tploot").setExecutor(lootChestManager);
// BlockManager
BlockManager blockManager = new BlockManager();
FileConfiguration config = getConfig();
// Listener registrieren
BackpackRecipe.register(this, langConfig);
pluginManager.registerEvents(new ChatBlockListener(blockManager), this);
pluginManager.registerEvents(new InventoryClickListener(this), this);
pluginManager.registerEvents(sitListener, this);
pluginManager.registerEvents(afkListener, this);
pluginManager.registerEvents(graveListener, this);
pluginManager.registerEvents(new BackpackListener(backpackConfig, langConfig, getLogger(), backpackFile), this);
pluginManager.registerEvents(new StatsListener(this, statsManager), this);
pluginManager.registerEvents(new LoginListener(this), this);
pluginManager.registerEvents(new DebugArmorStandListener(), this);
pluginManager.registerEvents(new ArmorStandDestroyListener(), this);
pluginManager.registerEvents(new FirstJoinListener(), this);
pluginManager.registerEvents(playerJoinListener, this);
pluginManager.registerEvents(new SignColorListener(this), this);
pluginManager.registerEvents(new SleepListener(this), this);
pluginManager.registerEvents(new OreAlarmListener(this), this);
pluginManager.registerEvents(new MobLeashLimitListener(this, getConfig()), this);
pluginManager.registerEvents(new MobCapListener(this, getConfig()), this);
pluginManager.registerEvents(new SpawnProtectionListener(this), this);
pluginManager.registerEvents(new NewbieProtectionListener(this), this);
pluginManager.registerEvents(new WarpInventoryListener(this, warpManager), this);
pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this);
pluginManager.registerEvents(new BlockDetectionListener(this), this);
lockSystem = new LockSystem(this);
pluginManager.registerEvents(lockSystem, this);
getCommand("sp").setExecutor(lockSystem);
// Kombinierter Executor für /sp, um alle Subcommands zu handhaben
getCommand("sp").setExecutor(new CommandExecutor() {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!command.getName().equalsIgnoreCase("sp")) {
return false;
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());
}
if (args.length == 0) {
}
int pluginId = 26886;
Metrics metrics = new Metrics(this, pluginId);
metrics.addCustomChart(new SimplePie(
"default_gamemode",
() -> Bukkit.getDefaultGameMode().toString()
));
metrics.addCustomChart(new SingleLineChart(
"online_players",
() -> Bukkit.getOnlinePlayers().size()
));
metrics.addCustomChart(new SimplePie(
"plugin_language",
() -> getConfig().getString("language", "default")
));
bannerManager = new BannerManager(this);
bannerManager.displayConsoleBanner(); // Banner beim Serverstart
updateConfigFiles();
createHomesFile();
createGravesFile();
createBackpackFile();
createFriendsFile();
createLeashesFile();
createMobCapFile();
createNicknamesFile();
reloadBlockedCommandsConfig();
loadClaims();
PluginManager pluginManager = getServer().getPluginManager();
try {
Permission notifyPerm = new Permission("survivalplus.notify", PermissionDefault.OP);
if (pluginManager.getPermission("survivalplus.notify") == null) {
pluginManager.addPermission(notifyPerm);
getLogger().info("Permission survivalplus.notify erfolgreich registriert.");
}
} catch (Exception e) {
getLogger().warning("Fehler beim Registrieren der Permission survivalplus.notify: " + e.getMessage());
}
try {
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");
funChallengeManager = new FunChallengeManager();
funChallengeManager.load(getConfig());
pluginManager.registerEvents(new ChallengeCollectListener(funChallengeManager, droppedKey), this);
pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this);
FriendCommand friendCommand = new FriendCommand(this, friendsConfig, langConfig, getLogger());
getCommand("day").setExecutor(new DayCommand(this));
getCommand("night").setExecutor(new NightCommand(this));
CommandBlocker commandBlocker = new CommandBlocker(this);
pluginCommand = new PluginCommand(this);
getCommand("sp").setExecutor(pluginCommand);
TradeManager tradeManager = new TradeManager(this);
ReportManager reportManager = new ReportManager(this);
getCommand("report").setExecutor(new ReportCommand(this, reportManager));
getCommand("showreport").setExecutor(new ShowReportCommand(this, reportManager));
getCommand("clearreport").setExecutor(new ClearReportCommand(this, reportManager));
getCommand("trade").setExecutor(new TradeCommand(this, tradeManager));
getCommand("tradeaccept").setExecutor(new TradeAcceptCommand(this, tradeManager));
statsManager = new StatsManager(this);
warpManager = new WarpManager(this);
TablistManager tablistManager = new TablistManager(this);
sitListener = new SitListener(this);
afkListener = new AFKListener(this);
graveListener = new GraveListener(this);
playerJoinListener = new PlayerJoinListener(friendCommand);
getCommand("gm").setExecutor(new GamemodeCommand(this));
getCommand("sp").setExecutor(new PluginCommand(this));
getCommand("sethome").setExecutor(new HomeCommand(this));
getCommand("delhome").setExecutor(new HomeCommand(this));
getCommand("homelist").setExecutor(new HomeCommand(this));
getCommand("inv").setExecutor(new InventoryCommand(this));
getCommand("ec").setExecutor(new EnderchestCommand(this));
getCommand("setspawn").setExecutor(new SetSpawnCommand(this));
getCommand("setworldspawn").setExecutor(new SetWorldSpawnCommand(this));
getCommand("clearchat").setExecutor(new ClearChatCommand());
getCommand("clearitems").setExecutor(new ClearItemsCommand(this));
getCommand("closedoors").setExecutor(new CloseDoorsCommand(this));
getCommand("sit").setExecutor(new SitCommand(this, sitListener));
getCommand("back").setExecutor(new BackCommand(this));
getCommand("friend").setExecutor(friendCommand);
getCommand("ir").setExecutor(new ItemRenameCommand(this));
getCommand("showarmorstands").setExecutor(new ShowArmorStandsCommand(this));
getCommand("cleardebugarmorstands").setExecutor(new ClearDebugArmorStandsCommand(this));
getCommand("trash").setExecutor(new TrashCommand());
getCommand("workbench").setExecutor(new WorkbenchCommand());
getCommand("anvil").setExecutor(new AnvilCommand());
getCommand("nick").setExecutor(new NickCommand(this));
getCommand("shop").setExecutor(new ShopCommand(this));
getCommand("stats").setExecutor(new StatsCommand(this, statsManager));
getCommand("spawn").setExecutor(new SpawnCommand(this));
getCommand("setwarp").setExecutor(new SetWarpCommand(this, warpManager));
getCommand("warps").setExecutor(new WarpsCommand(this, warpManager));
getCommand("delwarp").setExecutor(new DelWarpCommand(this, warpManager));
TeleportCommands teleportCommands = new TeleportCommands(this);
getCommand("tp").setExecutor(teleportCommands);
getCommand("tphere").setExecutor(teleportCommands);
getCommand("tpa").setExecutor(teleportCommands);
getCommand("tpaccept").setExecutor(teleportCommands);
getCommand("tpdeny").setExecutor(teleportCommands);
getCommand("startchallenge").setExecutor(new StartFunChallengeCommand(this, funChallengeManager));
getCommand("kit").setExecutor(new KitCommand(this));
getCommand("heal").setExecutor(new HealCommand(this));
getCommand("sp").setExecutor(commandBlocker);
LootChestManager lootChestManager = new LootChestManager(this);
pluginManager.registerEvents(lootChestManager, this);
getCommand("lootchests").setExecutor(lootChestManager);
getCommand("tploot").setExecutor(lootChestManager);
getCommand("claim").setExecutor(new ClaimCommand(this));
BlockManager blockManager = new BlockManager();
FileConfiguration config = getConfig();
BackpackRecipe.register(this, langConfig);
pluginManager.registerEvents(new ChatBlockListener(blockManager), this);
pluginManager.registerEvents(new InventoryClickListener(this), this);
pluginManager.registerEvents(sitListener, this);
pluginManager.registerEvents(afkListener, this);
pluginManager.registerEvents(graveListener, this);
pluginManager.registerEvents(new BackpackListener(backpackConfig, langConfig, getLogger(), backpackFile), this);
pluginManager.registerEvents(new StatsListener(this, statsManager), this);
pluginManager.registerEvents(new LoginListener(this), this);
pluginManager.registerEvents(new DebugArmorStandListener(), this);
pluginManager.registerEvents(new ArmorStandDestroyListener(), this);
pluginManager.registerEvents(new FirstJoinListener(), this);
pluginManager.registerEvents(playerJoinListener, this);
pluginManager.registerEvents(new SignColorListener(this), this);
pluginManager.registerEvents(new SleepListener(this), this);
pluginManager.registerEvents(new OreAlarmListener(this), this);
pluginManager.registerEvents(new MobLeashLimitListener(this, getConfig()), this);
pluginManager.registerEvents(new MobCapListener(this, getConfig()), this);
pluginManager.registerEvents(new SpawnProtectionListener(this), this);
pluginManager.registerEvents(new NewbieProtectionListener(this), this);
pluginManager.registerEvents(new WarpInventoryListener(this, warpManager), this);
pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this);
pluginManager.registerEvents(new BlockDetectionListener(this), this);
pluginManager.registerEvents(new ClaimListener(this), this);
lockSystem = new LockSystem(this);
pluginManager.registerEvents(lockSystem, this);
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);
}
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 ToolUpgradeListener(this), this);
pluginManager.registerEvents(new NickLoadListener(this), this);
startAutoClearTask();
spawnArmorStandExample();
getLogger().info(getMessage("plugin.enabled"));
if (getConfig().getBoolean("set-keepinventory", true)) {
Bukkit.getScheduler().runTaskLater(this, () -> {
if (Bukkit.getWorlds().isEmpty()) return;
Bukkit.getWorlds().forEach(world -> {
world.setGameRule(GameRule.KEEP_INVENTORY, false);
getLogger().info("Gamerule keepInventory in Welt '" + world.getName() + "' wurde auf false gesetzt.");
});
}, 20L);
}
});
pluginManager.registerEvents(new RepairSignListener(getConfig(), getLangConfig()), this);
pluginManager.registerEvents(new ToolUpgradeListener(this), this);
pluginManager.registerEvents(new NickLoadListener(this), this);
// AutoClear starten
startAutoClearTask();
spawnArmorStandExample();
getLogger().info(getMessage("plugin.enabled"));
// === Gamerule keepInventory aus Config setzen ===
if (getConfig().getBoolean("set-keepinventory", true)) {
Bukkit.getScheduler().runTaskLater(this, () -> {
if (Bukkit.getWorlds().isEmpty()) return;
Bukkit.getWorlds().forEach(world -> {
world.setGameRule(GameRule.KEEP_INVENTORY, false);
getLogger().info("Gamerule keepInventory in Welt '" + world.getName() + "' wurde auf false gesetzt.");
});
}, 20L);
}
// === Force Survival Mode aktivieren ===
if (getConfig().getBoolean("force-survival", true)) {
pluginManager.registerEvents(new ForceSurvivalListener(this), this);
getLogger().info("Force-Survival ist aktiv. Spieler werden beim Joinen in Survival gesetzt.");
}
// === Animierte Tablist konfigurieren und starten ===
try {
// tablist.yml laden / defaults setzen
if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml");
if (!tablistFile.exists()) {
saveResource("tablist.yml", false);
if (getConfig().getBoolean("force-survival", true)) {
pluginManager.registerEvents(new ForceSurvivalListener(this), this);
getLogger().info("Force-Survival ist aktiv. Spieler werden beim Joinen in Survival gesetzt.");
}
tablistConfig = YamlConfiguration.loadConfiguration(tablistFile);
// Standardwerte aus Resource als Defaults setzen (falls vorhanden)
InputStream defStream = getResource("tablist.yml");
if (defStream != null) {
tablistConfig.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(defStream)));
}
getLogger().info("Animierte Tablist wurde geladen!");
} catch (Exception 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);
}
/**
* Liest Config und setzt GameRule sowie entfernt verbotene Blöcke aus Inventaren online
*/
public void applyBlockRules() {
boolean cmdAllowed = getConfig().getBoolean("blocks.command-blocks.enabled", true);
boolean structAllowed = getConfig().getBoolean("blocks.structure-blocks.enabled", true);
for (World world : Bukkit.getWorlds()) {
try {
// moderner API-Aufruf
world.setGameRule(GameRule.COMMAND_BLOCK_OUTPUT, cmdAllowed);
} catch (NoSuchMethodError | NoClassDefFoundError e) {
// Fallback für ältere Server-Implementationen
world.setGameRuleValue(GameRule.COMMAND_BLOCK_OUTPUT.getName(), Boolean.toString(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);
getLogger().info("Block-Regeln angewendet: CommandBlocks erlaubt=" + cmdAllowed + ", StructureBlocks erlaubt=" + structAllowed);
}
/** Entfernt Command-/Structure-Blöcke aus Inventaren falls deaktiviert, ausgenommen Admins */
private void removeForbiddenBlocksFromInventories(boolean cmdAllowed, boolean structAllowed) {
for (Player p : Bukkit.getOnlinePlayers()) {
if (p.hasPermission("survivalplus.notify")) {
continue; // Admins dürfen Blöcke behalten
}
Inventory inv = p.getInventory();
boolean removedCommandBlock = false;
boolean removedStructureBlock = false;
if (!cmdAllowed && inv.contains(Material.COMMAND_BLOCK)) {
inv.remove(Material.COMMAND_BLOCK);
removedCommandBlock = true;
p.sendMessage(ChatColor.RED + "[SurvivalPlus] Command-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind.");
}
if (!structAllowed && inv.contains(Material.STRUCTURE_BLOCK)) {
inv.remove(Material.STRUCTURE_BLOCK);
removedStructureBlock = true;
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)) {
notifyAdmins(p.getName(), removedCommandBlock, removedStructureBlock);
}
}
}
/** Benachrichtigt Admins über entfernte Blöcke */
private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean hadStructureBlock) {
String baseTag = ChatColor.GRAY + "[" + ChatColor.GREEN + "SurvivalPlus" + ChatColor.GRAY + "] ";
for (Player admin : Bukkit.getOnlinePlayers()) {
if (admin.hasPermission("survivalplus.notify")) {
if (hadCommandBlock) {
admin.sendMessage(baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
ChatColor.RED + " hatte einen Command-Block im Inventar, der entfernt wurde.");
if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml");
if (!tablistFile.exists()) {
saveResource("tablist.yml", false);
}
if (hadStructureBlock) {
admin.sendMessage(baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
ChatColor.RED + " hatte einen Structure-Block im Inventar, der entfernt wurde.");
tablistConfig = YamlConfiguration.loadConfiguration(tablistFile);
InputStream defStream = getResource("tablist.yml");
if (defStream != null) {
tablistConfig.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(defStream)));
}
getLogger().info("Animierte Tablist wurde geladen!");
} catch (Exception e) {
getLogger().log(Level.WARNING, "Fehler beim Laden der Tablist-Konfiguration", e);
}
Bukkit.getScheduler().runTaskLater(this, this::applyBlockRules, 20L);
}
public void applyBlockRules() {
boolean cmdAllowed = getConfig().getBoolean("blocks.command-blocks.enabled", true);
boolean structAllowed = getConfig().getBoolean("blocks.structure-blocks.enabled", true);
for (World world : Bukkit.getWorlds()) {
try {
world.setGameRule(GameRule.COMMAND_BLOCK_OUTPUT, cmdAllowed);
} catch (NoSuchMethodError | NoClassDefFoundError e) {
world.setGameRuleValue(GameRule.COMMAND_BLOCK_OUTPUT.getName(), Boolean.toString(cmdAllowed));
}
getLogger().info("Gamerule commandBlockOutput in Welt '" + world.getName() + "' gesetzt auf " + cmdAllowed);
}
removeForbiddenBlocksFromInventories(cmdAllowed, structAllowed);
getLogger().info("Block-Regeln angewendet: CommandBlocks erlaubt=" + cmdAllowed + ", StructureBlocks erlaubt=" + structAllowed);
}
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) {
for (Player p : Bukkit.getOnlinePlayers()) {
if (p.hasPermission("survivalplus.notify")) {
continue;
}
Inventory inv = p.getInventory();
boolean removedCommandBlock = false;
boolean removedStructureBlock = false;
if (!cmdAllowed && inv.contains(Material.COMMAND_BLOCK)) {
inv.remove(Material.COMMAND_BLOCK);
removedCommandBlock = true;
p.sendMessage(ChatColor.RED + "[SurvivalPlus] Command-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind.");
}
if (!structAllowed && inv.contains(Material.STRUCTURE_BLOCK)) {
inv.remove(Material.STRUCTURE_BLOCK);
removedStructureBlock = true;
p.sendMessage(ChatColor.RED + "[SurvivalPlus] Structure-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind.");
}
if ((removedCommandBlock || removedStructureBlock) && getConfig().getBoolean("blocks.notify-admins-on-possession", true)) {
notifyAdmins(p.getName(), removedCommandBlock, removedStructureBlock);
}
}
}
}
private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean hadStructureBlock) {
String baseTag = ChatColor.GRAY + "[" + ChatColor.GREEN + "SurvivalPlus" + ChatColor.GRAY + "] ";
for (Player admin : Bukkit.getOnlinePlayers()) {
if (admin.hasPermission("survivalplus.notify")) {
if (hadCommandBlock) {
admin.sendMessage(baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
ChatColor.RED + " hatte einen Command-Block im Inventar, der entfernt wurde.");
}
if (hadStructureBlock) {
admin.sendMessage(baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
ChatColor.RED + " hatte einen Structure-Block im Inventar, der entfernt wurde.");
}
}
}
}
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;
}
@@ -547,6 +727,9 @@ private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean ha
@Override
public void onDisable() {
if (debugWriter != null) {
debugWriter.close();
}
if (autoClearTaskId != -1) {
Bukkit.getScheduler().cancelTask(autoClearTaskId);
}
@@ -995,4 +1178,34 @@ private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean ha
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 boolean enabled;
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, BossBar> bossBars = new HashMap<>();
private final Map<UUID, Long> messageCooldowns = new HashMap<>();
// YAML Datei
private File dataFile;
@@ -89,14 +91,29 @@ public class NewbieProtectionListener implements Listener {
if (!(event.getEntity() instanceof Player)) return;
Player victim = (Player) event.getEntity();
UUID vid = victim.getUniqueId();
Integer timeLeft = remainingSeconds.get(vid);
UUID victimId = victim.getUniqueId();
Integer timeLeft = remainingSeconds.get(victimId);
if (timeLeft != null && timeLeft > 0) {
event.setCancelled(true);
victim.sendMessage(ChatColor.GREEN + "Du bist noch im Neulingsschutz!");
// 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!");
messageCooldowns.put(victimId, currentTime);
}
// Prüfe Abklingzeit für Angreifer, falls es ein Spieler ist
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() {
if (dataConfig == null) return;
for (Map.Entry<UUID, Integer> entry : remainingSeconds.entrySet()) {
@@ -176,4 +192,4 @@ public class NewbieProtectionListener implements Listener {
int sec = totalSec % 60;
return String.format("%02d:%02d", min, sec);
}
}
}

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

View File

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

View File

@@ -273,6 +273,23 @@ commands:
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:
header: "&6=== Befehle ==="
footer: "&6================"

View File

@@ -402,5 +402,31 @@ inventory:
no-permission-others: "§cDu hast keine Berechtigung, das Inventar anderer Spieler anzusehen!"
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:
join-message: "§aDu wurdest in den Survivalmodus gesetzt!"

View File

@@ -1,5 +1,6 @@
name: SurvivalPlus
version: 1.0.7
version: 1.0.9
main: de.viper.survivalplus.SurvivalPlus
api-version: 1.21
@@ -265,6 +266,17 @@ commands:
permission: survivalplus.heal
permission-message: "§cDu hast keine Berechtigung, Spieler zu heilen!"
claim:
description: Manages claims for anti-griefing
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:
survivalplus.*:
description: Gibt Zugriff auf alle SurvivalPlus-Befehle