Dateien nach "src/main/java/de/viper/survivalplus/listeners" hochladen
This commit is contained in:
120
src/main/java/de/viper/survivalplus/listeners/AFKListener.java
Normal file
120
src/main/java/de/viper/survivalplus/listeners/AFKListener.java
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import de.viper.survivalplus.SurvivalPlus;
|
||||||
|
import de.viper.survivalplus.tasks.AFKManager;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.*;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
public class AFKListener implements Listener {
|
||||||
|
|
||||||
|
private final SurvivalPlus plugin;
|
||||||
|
private AFKManager afkManager;
|
||||||
|
private boolean afkEnabled;
|
||||||
|
private FileConfiguration config;
|
||||||
|
|
||||||
|
private BukkitRunnable afkTask;
|
||||||
|
|
||||||
|
public AFKListener(SurvivalPlus plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.config = plugin.getConfig();
|
||||||
|
loadSettings();
|
||||||
|
|
||||||
|
if (afkEnabled) {
|
||||||
|
startTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadSettings() {
|
||||||
|
this.afkEnabled = config.getBoolean("afk.enabled", true);
|
||||||
|
|
||||||
|
long afkAfter = config.getLong("afk.afk-after-seconds", 300);
|
||||||
|
long kickAfter = config.getLong("afk.kick-after-seconds", 0);
|
||||||
|
this.afkManager = new AFKManager(plugin, afkAfter, kickAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startTask() {
|
||||||
|
if (afkTask != null) {
|
||||||
|
afkTask.cancel();
|
||||||
|
}
|
||||||
|
afkTask = new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
afkManager.checkAFKStatus(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
afkTask.runTaskTimer(plugin, 20L, 100L);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleActivity(Player player) {
|
||||||
|
if (!afkEnabled) return;
|
||||||
|
|
||||||
|
afkManager.updateActivity(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.bukkit.event.EventHandler
|
||||||
|
public void onMove(PlayerMoveEvent event) {
|
||||||
|
if (!event.getFrom().toVector().equals(event.getTo().toVector())) {
|
||||||
|
handleActivity(event.getPlayer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.bukkit.event.EventHandler
|
||||||
|
public void onChat(AsyncPlayerChatEvent event) {
|
||||||
|
handleActivity(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.bukkit.event.EventHandler
|
||||||
|
public void onInteract(PlayerInteractEvent event) {
|
||||||
|
handleActivity(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.bukkit.event.EventHandler
|
||||||
|
public void onInventoryClick(InventoryClickEvent event) {
|
||||||
|
if (event.getWhoClicked() instanceof Player player) {
|
||||||
|
handleActivity(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.bukkit.event.EventHandler
|
||||||
|
public void onBlockPlace(BlockPlaceEvent event) {
|
||||||
|
handleActivity(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.bukkit.event.EventHandler
|
||||||
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
|
handleActivity(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.bukkit.event.EventHandler
|
||||||
|
public void onJoin(PlayerJoinEvent event) {
|
||||||
|
afkManager.updateActivity(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.bukkit.event.EventHandler
|
||||||
|
public void onQuit(PlayerQuitEvent event) {
|
||||||
|
afkManager.reset(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadConfig(FileConfiguration config) {
|
||||||
|
this.config = config;
|
||||||
|
loadSettings();
|
||||||
|
|
||||||
|
if (afkTask != null) {
|
||||||
|
afkTask.cancel();
|
||||||
|
afkTask = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (afkEnabled) {
|
||||||
|
startTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,27 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.entity.ArmorStand;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||||
|
|
||||||
|
public class ArmorStandDestroyListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onArmorStandInteract(PlayerInteractAtEntityEvent event) {
|
||||||
|
if (!(event.getRightClicked() instanceof ArmorStand armorStand)) return;
|
||||||
|
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
|
||||||
|
if (!player.hasPermission("survivalplus.armorstand.destroy")) {
|
||||||
|
player.sendMessage(ChatColor.RED + "Du hast keine Berechtigung, diesen ArmorStand zu entfernen.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
armorStand.remove();
|
||||||
|
player.sendMessage(ChatColor.YELLOW + "ArmorStand wurde erfolgreich entfernt.");
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,111 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class BackpackListener implements Listener {
|
||||||
|
|
||||||
|
private final FileConfiguration backpackConfig;
|
||||||
|
private final FileConfiguration langConfig;
|
||||||
|
private final Logger logger;
|
||||||
|
private final File backpackFile;
|
||||||
|
|
||||||
|
public BackpackListener(FileConfiguration backpackConfig, FileConfiguration langConfig, Logger logger, File backpackFile) {
|
||||||
|
this.backpackConfig = backpackConfig;
|
||||||
|
this.langConfig = langConfig;
|
||||||
|
this.logger = logger;
|
||||||
|
this.backpackFile = backpackFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onRightClick(PlayerInteractEvent event) {
|
||||||
|
if (!event.hasItem() || !event.getAction().toString().contains("RIGHT")) return;
|
||||||
|
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
ItemStack item = event.getItem();
|
||||||
|
|
||||||
|
if (item == null || item.getType() != Material.CHEST) {
|
||||||
|
logger.fine("Kein Rucksack-Item: " + (item != null ? item.getType() : "null"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!item.hasItemMeta()) {
|
||||||
|
logger.fine("Item hat kein ItemMeta: " + item.getType());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemMeta meta = item.getItemMeta();
|
||||||
|
if (!meta.hasDisplayName()) {
|
||||||
|
logger.fine("Item hat keinen Display-Namen: " + item.getType());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String expectedName = ChatColor.translateAlternateColorCodes('&', langConfig.getString("backpack.name", "&eRucksack"));
|
||||||
|
if (!meta.getDisplayName().equals(expectedName)) {
|
||||||
|
logger.fine("Item hat falschen Namen: " + meta.getDisplayName() + ", erwartet: " + expectedName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.setCancelled(true);
|
||||||
|
|
||||||
|
UUID uuid = player.getUniqueId();
|
||||||
|
String inventoryTitle = ChatColor.translateAlternateColorCodes('&', langConfig.getString("backpack.inventory-title", "&eDein Rucksack"));
|
||||||
|
|
||||||
|
Inventory backpackInv = Bukkit.createInventory(null, 27, inventoryTitle);
|
||||||
|
logger.info("Öffne Rucksack-Inventar für Spieler " + player.getName() + " (" + uuid + ")");
|
||||||
|
|
||||||
|
for (int i = 0; i < 27; i++) {
|
||||||
|
String path = uuid + ".slot" + i;
|
||||||
|
if (backpackConfig.contains(path)) {
|
||||||
|
backpackInv.setItem(i, backpackConfig.getItemStack(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
player.openInventory(backpackInv);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onClose(InventoryCloseEvent event) {
|
||||||
|
String expectedTitle = ChatColor.translateAlternateColorCodes('&', langConfig.getString("backpack.inventory-title", "&eDein Rucksack"));
|
||||||
|
if (!event.getView().getTitle().equals(expectedTitle)) return;
|
||||||
|
|
||||||
|
Player player = (Player) event.getPlayer();
|
||||||
|
UUID uuid = player.getUniqueId();
|
||||||
|
Inventory inv = event.getInventory();
|
||||||
|
|
||||||
|
logger.info("Speichere Rucksack-Inventar für Spieler " + player.getName() + " (" + uuid + ")");
|
||||||
|
|
||||||
|
for (int i = 0; i < inv.getSize(); i++) {
|
||||||
|
String path = uuid + ".slot" + i;
|
||||||
|
ItemStack item = inv.getItem(i);
|
||||||
|
backpackConfig.set(path, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!backpackFile.exists()) {
|
||||||
|
backpackFile.createNewFile();
|
||||||
|
logger.info("backpacks.yml wurde erstellt.");
|
||||||
|
}
|
||||||
|
backpackConfig.save(backpackFile);
|
||||||
|
logger.info("Rucksack-Inventar gespeichert für " + player.getName());
|
||||||
|
} catch (IOException e) {
|
||||||
|
player.sendMessage(ChatColor.RED + "Fehler beim Speichern deines Rucksacks.");
|
||||||
|
logger.severe("Fehler beim Speichern der backpacks.yml: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,46 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import org.bukkit.entity.ArmorStand;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||||
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||||
|
|
||||||
|
public class DebugArmorStandListener implements Listener {
|
||||||
|
|
||||||
|
private static final double MAX_DISTANCE = 3.0;
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
|
||||||
|
if (event.getRightClicked() instanceof ArmorStand armorStand) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (armorStand.getScoreboardTags().contains("debugArmorStand")) {
|
||||||
|
if (armorStand.getLocation().distance(player.getLocation()) <= MAX_DISTANCE) {
|
||||||
|
armorStand.remove();
|
||||||
|
player.sendMessage("§aDebug-ArmorStand wurde entfernt.");
|
||||||
|
event.setCancelled(true);
|
||||||
|
} else {
|
||||||
|
player.sendMessage("§cDieser Debug-ArmorStand ist zu weit entfernt.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
|
||||||
|
if (event.getEntity() instanceof ArmorStand armorStand) {
|
||||||
|
if (armorStand.getScoreboardTags().contains("debugArmorStand")) {
|
||||||
|
if (event.getDamager() instanceof Player player) {
|
||||||
|
if (armorStand.getLocation().distance(player.getLocation()) <= MAX_DISTANCE) {
|
||||||
|
armorStand.remove();
|
||||||
|
player.sendMessage("§aDebug-ArmorStand wurde zerstört.");
|
||||||
|
event.setCancelled(true);
|
||||||
|
} else {
|
||||||
|
player.sendMessage("§cDieser Debug-ArmorStand ist zu weit entfernt.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
174
src/main/java/de/viper/survivalplus/listeners/GraveListener.java
Normal file
174
src/main/java/de/viper/survivalplus/listeners/GraveListener.java
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import de.viper.survivalplus.SurvivalPlus;
|
||||||
|
import org.bukkit.*;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.Chest;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.entity.ArmorStand;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class GraveListener implements Listener {
|
||||||
|
|
||||||
|
private final SurvivalPlus plugin;
|
||||||
|
private final HashMap<Location, UUID> graveOwners = new HashMap<>();
|
||||||
|
private long despawnTime;
|
||||||
|
|
||||||
|
public GraveListener(SurvivalPlus plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
reloadConfig(plugin.getConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadConfig(FileConfiguration config) {
|
||||||
|
this.despawnTime = config.getLong("graves.despawn-time", 1800);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||||
|
if (event.getKeepInventory()) return;
|
||||||
|
|
||||||
|
Player player = event.getEntity();
|
||||||
|
UUID playerId = player.getUniqueId();
|
||||||
|
FileConfiguration gravesConfig = plugin.getGravesConfig();
|
||||||
|
FileConfiguration lang = plugin.getLangConfig();
|
||||||
|
|
||||||
|
Location deathLocation = player.getLocation().clone();
|
||||||
|
Block block = deathLocation.getBlock();
|
||||||
|
|
||||||
|
// Save to graves.yml
|
||||||
|
gravesConfig.set("graves." + playerId + ".world", deathLocation.getWorld().getName());
|
||||||
|
gravesConfig.set("graves." + playerId + ".x", deathLocation.getX());
|
||||||
|
gravesConfig.set("graves." + playerId + ".y", deathLocation.getY());
|
||||||
|
gravesConfig.set("graves." + playerId + ".z", deathLocation.getZ());
|
||||||
|
plugin.saveGravesConfig();
|
||||||
|
|
||||||
|
// Suche Platz für Truhe
|
||||||
|
if (block.isEmpty() || block.getType().isAir()) {
|
||||||
|
block.setType(Material.CHEST);
|
||||||
|
} else {
|
||||||
|
for (int i = 1; i <= 10; i++) {
|
||||||
|
Block above = block.getRelative(0, i, 0);
|
||||||
|
if (above.isEmpty() || above.getType().isAir()) {
|
||||||
|
above.setType(Material.CHEST);
|
||||||
|
block = above;
|
||||||
|
deathLocation = block.getLocation();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block.getType() == Material.CHEST) {
|
||||||
|
Chest chest = (Chest) block.getState();
|
||||||
|
for (ItemStack item : event.getDrops()) {
|
||||||
|
if (item != null && item.getType() != Material.AIR) {
|
||||||
|
chest.getInventory().addItem(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event.getDrops().clear();
|
||||||
|
|
||||||
|
graveOwners.put(block.getLocation(), playerId);
|
||||||
|
|
||||||
|
player.sendMessage(String.format(
|
||||||
|
lang.getString("graves.created", "§aDein Grab wurde bei x=%.2f, y=%.2f, z=%.2f erstellt!"),
|
||||||
|
deathLocation.getX(), deathLocation.getY(), deathLocation.getZ()
|
||||||
|
));
|
||||||
|
|
||||||
|
// ArmorStand mit "Grab von <Name>" in Rot über der Truhe
|
||||||
|
Location standLocation = deathLocation.clone().add(0.5, 1.2, 0.5);
|
||||||
|
ArmorStand stand = deathLocation.getWorld().spawn(standLocation, ArmorStand.class);
|
||||||
|
stand.setVisible(false);
|
||||||
|
stand.setCustomName("§cGrab von " + player.getName());
|
||||||
|
stand.setCustomNameVisible(true);
|
||||||
|
stand.setMarker(true);
|
||||||
|
stand.setGravity(false);
|
||||||
|
stand.setInvulnerable(true);
|
||||||
|
stand.setSilent(true);
|
||||||
|
stand.setSmall(true);
|
||||||
|
|
||||||
|
// Entfernen nach Zeit
|
||||||
|
if (despawnTime >= 0) {
|
||||||
|
final Block graveBlock = block;
|
||||||
|
final Location graveLocation = graveBlock.getLocation();
|
||||||
|
final Player deadPlayer = player;
|
||||||
|
final FileConfiguration langConfigFinal = lang;
|
||||||
|
|
||||||
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (graveBlock.getType() == Material.CHEST) {
|
||||||
|
graveBlock.setType(Material.AIR);
|
||||||
|
graveOwners.remove(graveLocation);
|
||||||
|
|
||||||
|
removeArmorStand(graveLocation);
|
||||||
|
|
||||||
|
deadPlayer.sendMessage(String.format(
|
||||||
|
langConfigFinal.getString("graves.despawned", "§cDein Grab bei x=%.2f, y=%.2f, z=%.2f ist verschwunden!"),
|
||||||
|
graveLocation.getX(), graveLocation.getY(), graveLocation.getZ()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.runTaskLater(plugin, despawnTime * 20L);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Überwache, ob Truhe geleert wurde
|
||||||
|
final Block chestBlockFinal = block;
|
||||||
|
final Player playerFinal = player;
|
||||||
|
final FileConfiguration langFinal = lang;
|
||||||
|
|
||||||
|
new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (chestBlockFinal.getType() != Material.CHEST) {
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Chest c = (Chest) chestBlockFinal.getState();
|
||||||
|
boolean empty = true;
|
||||||
|
for (ItemStack item : c.getInventory().getContents()) {
|
||||||
|
if (item != null && item.getType() != Material.AIR) {
|
||||||
|
empty = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty) {
|
||||||
|
c.getBlock().setType(Material.AIR);
|
||||||
|
graveOwners.remove(c.getLocation());
|
||||||
|
removeArmorStand(c.getLocation());
|
||||||
|
|
||||||
|
playerFinal.sendMessage(String.format(
|
||||||
|
langFinal.getString("graves.emptied", "§7Dein Grab bei x=%.2f, y=%.2f, z=%.2f wurde geleert."),
|
||||||
|
c.getX(), c.getY(), c.getZ()
|
||||||
|
));
|
||||||
|
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.runTaskTimer(plugin, 20L, 60L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeArmorStand(Location chestLocation) {
|
||||||
|
List<Entity> entities = chestLocation.getWorld().getNearbyEntities(chestLocation.clone().add(0.5, 1.2, 0.5), 0.5, 1, 0.5)
|
||||||
|
.stream().filter(e -> e instanceof ArmorStand).toList();
|
||||||
|
for (Entity entity : entities) {
|
||||||
|
entity.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOwner(Player player, Location location) {
|
||||||
|
return graveOwners.getOrDefault(location, null) != null &&
|
||||||
|
graveOwners.get(location).equals(player.getUniqueId());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,69 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import de.viper.survivalplus.SurvivalPlus;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
public class InventoryClickListener implements Listener {
|
||||||
|
private final SurvivalPlus plugin;
|
||||||
|
|
||||||
|
public InventoryClickListener(SurvivalPlus plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onInventoryClick(InventoryClickEvent event) {
|
||||||
|
FileConfiguration lang = plugin.getLangConfig();
|
||||||
|
String guiTitle = event.getView().getTitle();
|
||||||
|
String homeGuiTitle = lang.getString("homelist.gui-title", "Deine Homes");
|
||||||
|
if (!guiTitle.equals(homeGuiTitle)) {
|
||||||
|
plugin.getLogger().log(Level.FINE, "Ignoriere Klick in GUI mit Titel: " + guiTitle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.getLogger().log(Level.FINE, "Verarbeite Klick in Home-Liste GUI für Spieler: " + event.getWhoClicked().getName());
|
||||||
|
event.setCancelled(true);
|
||||||
|
if (!(event.getWhoClicked() instanceof Player) || event.getCurrentItem() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player player = (Player) event.getWhoClicked();
|
||||||
|
String homeName = event.getCurrentItem().getItemMeta().getDisplayName().replace("§a", "");
|
||||||
|
String path = "homes." + player.getUniqueId() + "." + homeName.toLowerCase();
|
||||||
|
|
||||||
|
FileConfiguration homes = plugin.getHomesConfig();
|
||||||
|
if (!homes.contains(path)) {
|
||||||
|
player.sendMessage(lang.getString("homelist.home-deleted", "§cDieses Home existiert nicht mehr!"));
|
||||||
|
player.closeInventory();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String worldName = homes.getString(path + ".world");
|
||||||
|
World world = plugin.getServer().getWorld(worldName);
|
||||||
|
if (world == null) {
|
||||||
|
player.sendMessage(lang.getString("homelist.world-not-found", "§cDie Welt dieses Homes existiert nicht!"));
|
||||||
|
player.closeInventory();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location loc = new Location(
|
||||||
|
world,
|
||||||
|
homes.getDouble(path + ".x"),
|
||||||
|
homes.getDouble(path + ".y"),
|
||||||
|
homes.getDouble(path + ".z"),
|
||||||
|
(float) homes.getDouble(path + ".yaw"),
|
||||||
|
(float) homes.getDouble(path + ".pitch")
|
||||||
|
);
|
||||||
|
|
||||||
|
player.teleport(loc);
|
||||||
|
player.sendMessage(lang.getString("homelist.teleported", "§aZum Home %name% teleportiert!")
|
||||||
|
.replace("%name%", homeName));
|
||||||
|
player.closeInventory();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,53 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import de.viper.survivalplus.SurvivalPlus;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
|
public class LoginListener implements Listener {
|
||||||
|
|
||||||
|
private final SurvivalPlus plugin;
|
||||||
|
|
||||||
|
public LoginListener(SurvivalPlus plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
|
||||||
|
if (!player.hasPlayedBefore()) {
|
||||||
|
// Erster Login
|
||||||
|
sendWelcomeMessage(player, true);
|
||||||
|
} else {
|
||||||
|
// Wiederkehrer
|
||||||
|
sendWelcomeMessage(player, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendWelcomeMessage(Player player, boolean firstJoin) {
|
||||||
|
String messageKey = firstJoin ? "welcome.first-join-message" : "welcome.return-message";
|
||||||
|
String soundKey = firstJoin ? "welcome.first-join-sound" : "welcome.return-sound";
|
||||||
|
String volumeKey = firstJoin ? "welcome.first-join-sound-volume" : "welcome.return-sound-volume";
|
||||||
|
String pitchKey = firstJoin ? "welcome.first-join-sound-pitch" : "welcome.return-sound-pitch";
|
||||||
|
|
||||||
|
String rawMessage = plugin.getLangConfig().getString(messageKey, "&6Willkommen, &e{player}&6!");
|
||||||
|
String message = ChatColor.translateAlternateColorCodes('&', rawMessage.replace("{player}", player.getName()));
|
||||||
|
player.sendMessage(message);
|
||||||
|
|
||||||
|
String soundName = plugin.getLangConfig().getString(soundKey, "ENTITY_PLAYER_LEVELUP");
|
||||||
|
float volume = (float) plugin.getLangConfig().getDouble(volumeKey, 1.0);
|
||||||
|
float pitch = (float) plugin.getLangConfig().getDouble(pitchKey, 1.0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Sound sound = Sound.valueOf(soundName);
|
||||||
|
player.playSound(player.getLocation(), sound, volume, pitch);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
plugin.getLogger().warning("Ungültiger Sound-Name in lang.yml: " + soundName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,181 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import de.viper.survivalplus.SurvivalPlus;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.entity.Animals;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||||
|
import org.bukkit.event.entity.EntityDeathEvent;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class MobCapListener implements Listener {
|
||||||
|
|
||||||
|
private final SurvivalPlus plugin;
|
||||||
|
private boolean enabled;
|
||||||
|
private int maxAnimalsPerChunk;
|
||||||
|
private final Map<String, Map<UUID, UUID>> chunkAnimalMap = new HashMap<>(); // Chunk -> Tier-UUID -> Spieler-UUID
|
||||||
|
|
||||||
|
public MobCapListener(SurvivalPlus plugin, FileConfiguration config) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
reloadConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadConfig(FileConfiguration config) {
|
||||||
|
this.enabled = config.getBoolean("mob-cap.enabled", true);
|
||||||
|
this.maxAnimalsPerChunk = config.getInt("mob-cap.max-animals-per-chunk", 10);
|
||||||
|
plugin.getLogger().info("MobCapListener: enabled=" + enabled + ", maxAnimalsPerChunk=" + maxAnimalsPerChunk);
|
||||||
|
|
||||||
|
// Bereinige bestehende Daten
|
||||||
|
chunkAnimalMap.clear();
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
plugin.getMobCapConfig().set("mobcap", null); // Bereinige mobcap.yml
|
||||||
|
plugin.saveMobCapConfig();
|
||||||
|
plugin.getLogger().info("MobCapListener: Daten bereinigt, da enabled=false");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lade Zuordnungen aus mobcap.yml
|
||||||
|
FileConfiguration mobCapConfig = plugin.getMobCapConfig();
|
||||||
|
if (mobCapConfig.contains("mobcap")) {
|
||||||
|
for (String chunkKey : mobCapConfig.getConfigurationSection("mobcap").getKeys(false)) {
|
||||||
|
Map<UUID, UUID> animalToPlayer = new HashMap<>();
|
||||||
|
for (String animalIdStr : mobCapConfig.getConfigurationSection("mobcap." + chunkKey).getKeys(false)) {
|
||||||
|
try {
|
||||||
|
UUID animalId = UUID.fromString(animalIdStr);
|
||||||
|
String playerIdStr = mobCapConfig.getString("mobcap." + chunkKey + "." + animalIdStr);
|
||||||
|
if (playerIdStr != null) {
|
||||||
|
UUID playerId = UUID.fromString(playerIdStr);
|
||||||
|
Entity entity = plugin.getServer().getEntity(animalId);
|
||||||
|
if (entity instanceof Animals) {
|
||||||
|
animalToPlayer.put(animalId, playerId);
|
||||||
|
} else {
|
||||||
|
// Entferne ungültige Einträge
|
||||||
|
mobCapConfig.set("mobcap." + chunkKey + "." + animalIdStr, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
plugin.getLogger().warning("Ungültige UUID in mobcap.yml: " + animalIdStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chunkAnimalMap.put(chunkKey, animalToPlayer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scanne alle Welten nach Tieren
|
||||||
|
for (org.bukkit.World world : plugin.getServer().getWorlds()) {
|
||||||
|
for (Chunk chunk : world.getLoadedChunks()) {
|
||||||
|
String chunkKey = getChunkKey(chunk);
|
||||||
|
Map<UUID, UUID> animalToPlayer = chunkAnimalMap.computeIfAbsent(chunkKey, k -> new HashMap<>());
|
||||||
|
for (Entity entity : chunk.getEntities()) {
|
||||||
|
if (entity instanceof Animals) {
|
||||||
|
UUID id = entity.getUniqueId();
|
||||||
|
if (!animalToPlayer.containsKey(id)) {
|
||||||
|
animalToPlayer.put(id, null); // Kein Spieler zugeordnet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Speichere aktualisierte mobcap.yml
|
||||||
|
saveChunkAnimalMap();
|
||||||
|
plugin.getLogger().info("MobCapListener: Nach Reload " + chunkAnimalMap.size() + " Chunks mit Tieren gefunden.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onCreatureSpawn(CreatureSpawnEvent event) {
|
||||||
|
if (!enabled) return;
|
||||||
|
|
||||||
|
LivingEntity entity = event.getEntity();
|
||||||
|
if (!(entity instanceof Animals)) return;
|
||||||
|
|
||||||
|
Chunk chunk = entity.getLocation().getChunk();
|
||||||
|
String chunkKey = getChunkKey(chunk);
|
||||||
|
Map<UUID, UUID> animalToPlayer = chunkAnimalMap.computeIfAbsent(chunkKey, k -> new HashMap<>());
|
||||||
|
|
||||||
|
int animalCount = animalToPlayer.size();
|
||||||
|
if (animalCount >= maxAnimalsPerChunk) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
plugin.getLogger().info("Spawn von " + entity.getType() + " in Chunk " + chunkKey + " verhindert: Limit von " + maxAnimalsPerChunk + " erreicht.");
|
||||||
|
|
||||||
|
// HINWEIS: Wenn du dem Züchter eine Nachricht schicken willst, nutze EntityBreedEvent
|
||||||
|
// Hier ist das nicht möglich, weil man beim Spawn keinen Spielerzugriff hat
|
||||||
|
} else {
|
||||||
|
animalToPlayer.put(entity.getUniqueId(), null); // Kein Spieler zugeordnet
|
||||||
|
saveChunkAnimalMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
|
||||||
|
if (!enabled) return;
|
||||||
|
|
||||||
|
if (!(event.getRightClicked() instanceof Animals)) return;
|
||||||
|
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
Entity entity = event.getRightClicked();
|
||||||
|
Chunk chunk = entity.getLocation().getChunk();
|
||||||
|
String chunkKey = getChunkKey(chunk);
|
||||||
|
Map<UUID, UUID> animalToPlayer = chunkAnimalMap.computeIfAbsent(chunkKey, k -> new HashMap<>());
|
||||||
|
|
||||||
|
int animalCount = animalToPlayer.size();
|
||||||
|
if (animalCount >= maxAnimalsPerChunk) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
player.sendMessage(plugin.getMessage("mob-cap.limit-reached").replace("%max%", String.valueOf(maxAnimalsPerChunk)));
|
||||||
|
plugin.getLogger().info("Interaktion mit " + entity.getType() + " in Chunk " + chunkKey + " verhindert: Limit von " + maxAnimalsPerChunk + " erreicht.");
|
||||||
|
} else {
|
||||||
|
animalToPlayer.put(entity.getUniqueId(), player.getUniqueId());
|
||||||
|
saveChunkAnimalMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onEntityDeath(EntityDeathEvent event) {
|
||||||
|
if (!enabled) return;
|
||||||
|
|
||||||
|
if (!(event.getEntity() instanceof Animals)) return;
|
||||||
|
|
||||||
|
LivingEntity entity = event.getEntity();
|
||||||
|
Chunk chunk = entity.getLocation().getChunk();
|
||||||
|
String chunkKey = getChunkKey(chunk);
|
||||||
|
Map<UUID, UUID> animalToPlayer = chunkAnimalMap.get(chunkKey);
|
||||||
|
|
||||||
|
if (animalToPlayer != null) {
|
||||||
|
UUID animalId = entity.getUniqueId();
|
||||||
|
animalToPlayer.remove(animalId);
|
||||||
|
if (animalToPlayer.isEmpty()) {
|
||||||
|
chunkAnimalMap.remove(chunkKey);
|
||||||
|
}
|
||||||
|
saveChunkAnimalMap();
|
||||||
|
plugin.getLogger().info("Tier " + entity.getType() + " in Chunk " + chunkKey + " gestorben. Verbleibende Tiere: " + animalToPlayer.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getChunkKey(Chunk chunk) {
|
||||||
|
return chunk.getWorld().getName() + "," + chunk.getX() + "," + chunk.getZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveChunkAnimalMap() {
|
||||||
|
FileConfiguration mobCapConfig = plugin.getMobCapConfig();
|
||||||
|
mobCapConfig.set("mobcap", null); // Bereinige vorherige Daten
|
||||||
|
for (Map.Entry<String, Map<UUID, UUID>> entry : chunkAnimalMap.entrySet()) {
|
||||||
|
String chunkKey = entry.getKey();
|
||||||
|
Map<UUID, UUID> animalToPlayer = entry.getValue();
|
||||||
|
for (Map.Entry<UUID, UUID> animalEntry : animalToPlayer.entrySet()) {
|
||||||
|
mobCapConfig.set("mobcap." + chunkKey + "." + animalEntry.getKey().toString(),
|
||||||
|
animalEntry.getValue() != null ? animalEntry.getValue().toString() : null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plugin.saveMobCapConfig();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,253 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import de.viper.survivalplus.SurvivalPlus;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.entity.EntityDeathEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class MobLeashLimitListener implements Listener {
|
||||||
|
|
||||||
|
private final SurvivalPlus plugin;
|
||||||
|
private boolean enabled;
|
||||||
|
private int maxLeashCount;
|
||||||
|
private final Map<UUID, Set<UUID>> leashedEntities = new HashMap<>();
|
||||||
|
private final Map<UUID, Integer> leashCounts = new HashMap<>();
|
||||||
|
private final Map<UUID, UUID> entityToPlayer = new HashMap<>();
|
||||||
|
|
||||||
|
public MobLeashLimitListener(SurvivalPlus plugin, FileConfiguration config) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
reloadConfig(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadConfig(FileConfiguration config) {
|
||||||
|
this.enabled = config.getBoolean("mob-leash-limit.enabled", true);
|
||||||
|
this.maxLeashCount = config.getInt("mob-leash-limit.max-leash-count", 5);
|
||||||
|
plugin.getLogger().info("MobLeashLimitListener: enabled=" + enabled + ", maxLeashCount=" + maxLeashCount);
|
||||||
|
|
||||||
|
// Bereinige bestehende Daten
|
||||||
|
leashedEntities.clear();
|
||||||
|
leashCounts.clear();
|
||||||
|
entityToPlayer.clear();
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
plugin.getLeashesConfig().set("leashes", null); // Bereinige leashes.yml
|
||||||
|
plugin.saveLeashesConfig();
|
||||||
|
plugin.getLogger().info("MobLeashLimitListener: Daten bereinigt, da enabled=false");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lade Zuordnungen aus leashes.yml
|
||||||
|
FileConfiguration leashesConfig = plugin.getLeashesConfig();
|
||||||
|
if (leashesConfig.contains("leashes")) {
|
||||||
|
for (String entityIdStr : leashesConfig.getConfigurationSection("leashes").getKeys(false)) {
|
||||||
|
UUID entityId;
|
||||||
|
try {
|
||||||
|
entityId = UUID.fromString(entityIdStr);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
plugin.getLogger().warning("Ungültige UUID in leashes.yml: " + entityIdStr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String playerIdStr = leashesConfig.getString("leashes." + entityIdStr);
|
||||||
|
if (playerIdStr != null) {
|
||||||
|
try {
|
||||||
|
UUID playerId = UUID.fromString(playerIdStr);
|
||||||
|
LivingEntity entity = (LivingEntity) plugin.getServer().getEntity(entityId);
|
||||||
|
if (entity != null && entity.isLeashed()) {
|
||||||
|
Set<UUID> playerLeashedEntities = leashedEntities.computeIfAbsent(playerId, k -> new HashSet<>());
|
||||||
|
playerLeashedEntities.add(entityId);
|
||||||
|
leashCounts.put(playerId, playerLeashedEntities.size());
|
||||||
|
entityToPlayer.put(entityId, playerId);
|
||||||
|
} else {
|
||||||
|
// Entferne ungültige Einträge aus leashes.yml
|
||||||
|
leashesConfig.set("leashes." + entityIdStr, null);
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
plugin.getLogger().warning("Ungültige Spieler-UUID in leashes.yml für Entity " + entityIdStr + ": " + playerIdStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scanne alle Welten nach angeleinten Tieren, die noch nicht in leashes.yml sind
|
||||||
|
for (org.bukkit.World world : plugin.getServer().getWorlds()) {
|
||||||
|
for (LivingEntity entity : world.getLivingEntities()) {
|
||||||
|
if (entity.isLeashed() && !entityToPlayer.containsKey(entity.getUniqueId())) {
|
||||||
|
// Nur Tiere zählen, die von einem Spieler gehalten werden (für neue Leashes)
|
||||||
|
if (entity.getLeashHolder() instanceof Player) {
|
||||||
|
Player player = (Player) entity.getLeashHolder();
|
||||||
|
UUID playerId = player.getUniqueId();
|
||||||
|
UUID entityId = entity.getUniqueId();
|
||||||
|
|
||||||
|
Set<UUID> playerLeashedEntities = leashedEntities.computeIfAbsent(playerId, k -> new HashSet<>());
|
||||||
|
playerLeashedEntities.add(entityId);
|
||||||
|
leashCounts.put(playerId, playerLeashedEntities.size());
|
||||||
|
entityToPlayer.put(entityId, playerId);
|
||||||
|
|
||||||
|
// Speichere in leashes.yml
|
||||||
|
leashesConfig.set("leashes." + entityId.toString(), playerId.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prüfe, ob das neue Limit überschritten wird
|
||||||
|
for (Map.Entry<UUID, Set<UUID>> entry : leashedEntities.entrySet()) {
|
||||||
|
UUID playerId = entry.getKey();
|
||||||
|
Set<UUID> playerLeashedEntities = entry.getValue();
|
||||||
|
if (playerLeashedEntities.size() > maxLeashCount) {
|
||||||
|
Player player = plugin.getServer().getPlayer(playerId);
|
||||||
|
if (player != null && player.isOnline()) {
|
||||||
|
player.sendMessage(plugin.getMessage("mob-leash-limit.limit-adjusted")
|
||||||
|
.replace("%count%", String.valueOf(playerLeashedEntities.size()))
|
||||||
|
.replace("%max%", String.valueOf(maxLeashCount)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entferne leere Einträge
|
||||||
|
leashedEntities.entrySet().removeIf(entry -> entry.getValue().isEmpty());
|
||||||
|
leashCounts.entrySet().removeIf(entry -> entry.getValue() == 0);
|
||||||
|
|
||||||
|
// Speichere aktualisierte leashes.yml
|
||||||
|
plugin.saveLeashesConfig();
|
||||||
|
|
||||||
|
plugin.getLogger().info("MobLeashLimitListener: Nach Reload " + leashedEntities.size() + " Spieler mit angeleinten Tieren gefunden.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
|
||||||
|
if (!enabled) return;
|
||||||
|
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
ItemStack itemInHand = player.getInventory().getItemInMainHand();
|
||||||
|
UUID playerId = player.getUniqueId();
|
||||||
|
LivingEntity entity = (LivingEntity) event.getRightClicked();
|
||||||
|
UUID entityId = entity.getUniqueId();
|
||||||
|
|
||||||
|
if (itemInHand != null && itemInHand.getType() == Material.LEAD) {
|
||||||
|
Set<UUID> playerLeashedEntities = leashedEntities.computeIfAbsent(playerId, k -> new HashSet<>());
|
||||||
|
int currentCount = playerLeashedEntities.size();
|
||||||
|
plugin.getLogger().info("PlayerInteractEntity: player=" + player.getName() + ", currentCount=" + currentCount + ", maxLeashCount=" + maxLeashCount);
|
||||||
|
|
||||||
|
if (playerLeashedEntities.contains(entityId)) {
|
||||||
|
// Ableinen
|
||||||
|
playerLeashedEntities.remove(entityId);
|
||||||
|
leashCounts.put(playerId, currentCount - 1);
|
||||||
|
entityToPlayer.remove(entityId);
|
||||||
|
plugin.getLeashesConfig().set("leashes." + entityId.toString(), null);
|
||||||
|
plugin.saveLeashesConfig();
|
||||||
|
player.sendMessage(plugin.getMessage("mob-leash-limit.unleashed")
|
||||||
|
.replace("%count%", String.valueOf(currentCount - 1)));
|
||||||
|
|
||||||
|
// Entferne leere Einträge
|
||||||
|
if (playerLeashedEntities.isEmpty()) {
|
||||||
|
leashedEntities.remove(playerId);
|
||||||
|
leashCounts.remove(playerId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Anleinen
|
||||||
|
if (currentCount >= maxLeashCount) {
|
||||||
|
player.sendMessage(plugin.getMessage("mob-leash-limit.max-reached")
|
||||||
|
.replace("%count%", String.valueOf(maxLeashCount)));
|
||||||
|
event.setCancelled(true);
|
||||||
|
} else {
|
||||||
|
playerLeashedEntities.add(entityId);
|
||||||
|
leashCounts.put(playerId, currentCount + 1);
|
||||||
|
entityToPlayer.put(entityId, playerId);
|
||||||
|
plugin.getLeashesConfig().set("leashes." + entityId.toString(), playerId.toString());
|
||||||
|
plugin.saveLeashesConfig();
|
||||||
|
player.sendMessage(plugin.getMessage("mob-leash-limit.leashed")
|
||||||
|
.replace("%count%", String.valueOf(currentCount + 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onEntityDeath(EntityDeathEvent event) {
|
||||||
|
if (!enabled) {
|
||||||
|
UUID entityId = event.getEntity().getUniqueId();
|
||||||
|
entityToPlayer.remove(entityId);
|
||||||
|
plugin.getLeashesConfig().set("leashes." + entityId.toString(), null);
|
||||||
|
plugin.saveLeashesConfig();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LivingEntity entity = event.getEntity();
|
||||||
|
UUID entityId = entity.getUniqueId();
|
||||||
|
UUID playerId = entityToPlayer.remove(entityId);
|
||||||
|
|
||||||
|
if (playerId != null) {
|
||||||
|
Set<UUID> playerLeashedEntities = leashedEntities.getOrDefault(playerId, new HashSet<>());
|
||||||
|
playerLeashedEntities.remove(entityId);
|
||||||
|
int newCount = playerLeashedEntities.size();
|
||||||
|
leashCounts.put(playerId, newCount);
|
||||||
|
|
||||||
|
// Entferne aus leashes.yml
|
||||||
|
plugin.getLeashesConfig().set("leashes." + entityId.toString(), null);
|
||||||
|
plugin.saveLeashesConfig();
|
||||||
|
|
||||||
|
// Entferne leere Einträge
|
||||||
|
if (playerLeashedEntities.isEmpty()) {
|
||||||
|
leashedEntities.remove(playerId);
|
||||||
|
leashCounts.remove(playerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Player player = plugin.getServer().getPlayer(playerId);
|
||||||
|
if (player != null && player.isOnline()) {
|
||||||
|
player.sendMessage(plugin.getMessage("mob-leash-limit.entity-died")
|
||||||
|
.replace("%count%", String.valueOf(newCount)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateLeashCount(Player player) {
|
||||||
|
UUID playerId = player.getUniqueId();
|
||||||
|
Set<UUID> playerLeashedEntities = leashedEntities.getOrDefault(playerId, new HashSet<>());
|
||||||
|
// Entferne nicht existierende oder nicht angeleinte Entities
|
||||||
|
playerLeashedEntities.removeIf(entityId -> {
|
||||||
|
LivingEntity entity = (LivingEntity) plugin.getServer().getEntity(entityId);
|
||||||
|
if (entity == null || !entity.isLeashed()) {
|
||||||
|
plugin.getLeashesConfig().set("leashes." + entityId.toString(), null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
int currentCount = playerLeashedEntities.size();
|
||||||
|
leashCounts.put(playerId, currentCount);
|
||||||
|
|
||||||
|
// Aktualisiere entityToPlayer-Map
|
||||||
|
entityToPlayer.entrySet().removeIf(entry -> entry.getValue().equals(playerId) && !playerLeashedEntities.contains(entry.getKey()));
|
||||||
|
|
||||||
|
// Entferne leere Einträge
|
||||||
|
if (playerLeashedEntities.isEmpty()) {
|
||||||
|
leashedEntities.remove(playerId);
|
||||||
|
leashCounts.remove(playerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Falls disabled, bereinige die Daten für diesen Spieler
|
||||||
|
if (!enabled) {
|
||||||
|
playerLeashedEntities.clear();
|
||||||
|
leashedEntities.remove(playerId);
|
||||||
|
leashCounts.remove(playerId);
|
||||||
|
entityToPlayer.entrySet().removeIf(entry -> entry.getValue().equals(playerId));
|
||||||
|
plugin.getLeashesConfig().set("leashes", null);
|
||||||
|
plugin.saveLeashesConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.getLogger().info("updateLeashCount: player=" + player.getName() + ", currentCount=" + currentCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLeashCount(Player player) {
|
||||||
|
updateLeashCount(player);
|
||||||
|
return leashCounts.getOrDefault(player.getUniqueId(), 0);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,139 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import de.viper.survivalplus.SurvivalPlus;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class OreAlarmListener implements Listener {
|
||||||
|
|
||||||
|
private static final long TIME_FRAME_MILLIS = 30 * 1000;
|
||||||
|
|
||||||
|
private final SurvivalPlus plugin;
|
||||||
|
|
||||||
|
private final Map<UUID, Map<Material, OreData>> playerOreData = new HashMap<>();
|
||||||
|
|
||||||
|
private FileConfiguration config;
|
||||||
|
|
||||||
|
// Schwellenwert wird jetzt aus der Config geladen (Fallback DEFAULT_THRESHOLD)
|
||||||
|
private int threshold;
|
||||||
|
|
||||||
|
public OreAlarmListener(SurvivalPlus plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.config = plugin.getConfig();
|
||||||
|
loadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadSettings() {
|
||||||
|
this.threshold = config.getInt("ore-alarm.threshold", 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloadet die Config, lädt die Einstellungen neu und leert gespeicherte Daten.
|
||||||
|
*/
|
||||||
|
public void reloadConfig(FileConfiguration newConfig) {
|
||||||
|
this.config = newConfig;
|
||||||
|
loadSettings();
|
||||||
|
playerOreData.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
Material blockType = event.getBlock().getType();
|
||||||
|
|
||||||
|
if (!isMonitoredOre(blockType)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID playerId = player.getUniqueId();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
|
playerOreData.putIfAbsent(playerId, new HashMap<>());
|
||||||
|
Map<Material, OreData> oreMap = playerOreData.get(playerId);
|
||||||
|
|
||||||
|
oreMap.putIfAbsent(blockType, new OreData(0, now));
|
||||||
|
OreData data = oreMap.get(blockType);
|
||||||
|
|
||||||
|
if (now - data.startTime > TIME_FRAME_MILLIS) {
|
||||||
|
data.count = 1;
|
||||||
|
data.startTime = now;
|
||||||
|
} else {
|
||||||
|
data.count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
oreMap.put(blockType, data);
|
||||||
|
|
||||||
|
int threshold = calculateDynamicThreshold(playerId, blockType);
|
||||||
|
if (data.count >= threshold) {
|
||||||
|
String oreName = prettifyMaterialName(blockType);
|
||||||
|
|
||||||
|
String rawMessage = plugin.getLangConfig().getString("orealarm.message",
|
||||||
|
"§c[Erz-Alarm] Spieler §e%player% §chat in %seconds% Sekunden ungewöhnlich viele %ore% abgebaut: §e%count%");
|
||||||
|
|
||||||
|
String message = rawMessage
|
||||||
|
.replace("%player%", player.getName())
|
||||||
|
.replace("%ore%", oreName)
|
||||||
|
.replace("%count%", Integer.toString(data.count))
|
||||||
|
.replace("%seconds%", Long.toString(TIME_FRAME_MILLIS / 1000));
|
||||||
|
|
||||||
|
Bukkit.getOnlinePlayers().stream()
|
||||||
|
.filter(p -> p.isOp() || p.hasPermission("survivalplus.orealarm"))
|
||||||
|
.forEach(p -> p.sendMessage(message));
|
||||||
|
|
||||||
|
data.count = 0;
|
||||||
|
data.startTime = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMonitoredOre(Material material) {
|
||||||
|
switch (material) {
|
||||||
|
case DIAMOND_ORE:
|
||||||
|
case DEEPSLATE_DIAMOND_ORE:
|
||||||
|
case REDSTONE_ORE:
|
||||||
|
case DEEPSLATE_REDSTONE_ORE:
|
||||||
|
case GOLD_ORE:
|
||||||
|
case DEEPSLATE_GOLD_ORE:
|
||||||
|
case IRON_ORE:
|
||||||
|
case DEEPSLATE_IRON_ORE:
|
||||||
|
case LAPIS_ORE:
|
||||||
|
case DEEPSLATE_LAPIS_ORE:
|
||||||
|
case EMERALD_ORE:
|
||||||
|
case DEEPSLATE_EMERALD_ORE:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int calculateDynamicThreshold(UUID playerId, Material ore) {
|
||||||
|
// Nutzt jetzt das geladene threshold, kann später erweitert werden
|
||||||
|
return threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String prettifyMaterialName(Material material) {
|
||||||
|
String name = material.name().toLowerCase();
|
||||||
|
name = name.replace("_ore", " Erz");
|
||||||
|
name = name.replace("deepslate ", "Tiefgeschichtetes ");
|
||||||
|
name = Character.toUpperCase(name.charAt(0)) + name.substring(1);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class OreData {
|
||||||
|
int count;
|
||||||
|
long startTime;
|
||||||
|
|
||||||
|
OreData(int count, long startTime) {
|
||||||
|
this.count = count;
|
||||||
|
this.startTime = startTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,85 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import de.viper.survivalplus.SurvivalPlus;
|
||||||
|
import net.md_5.bungee.api.ChatColor; // Bungee ChatColor für RGB/Hex Unterstützung
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.SignChangeEvent;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class SignColorListener implements Listener {
|
||||||
|
|
||||||
|
private final SurvivalPlus plugin;
|
||||||
|
|
||||||
|
// Muster für Hex-Farbcodes (#FFFFFF)
|
||||||
|
private static final Pattern HEX_PATTERN = Pattern.compile("#[a-fA-F0-9]{6}");
|
||||||
|
// Muster für RGB-Farben rgb(255,255,255)
|
||||||
|
private static final Pattern RGB_PATTERN = Pattern.compile("rgb\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)");
|
||||||
|
|
||||||
|
public SignColorListener(SurvivalPlus plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onSignChange(SignChangeEvent event) {
|
||||||
|
for (int i = 0; i < event.getLines().length; i++) {
|
||||||
|
String line = event.getLine(i);
|
||||||
|
if (line != null && !line.isEmpty()) {
|
||||||
|
// 1. &-Codes übersetzen (z.B. &a -> §a)
|
||||||
|
String translated = ChatColor.translateAlternateColorCodes('&', line);
|
||||||
|
|
||||||
|
// 2. Hex-Farben ersetzen
|
||||||
|
translated = replaceHexColors(translated);
|
||||||
|
|
||||||
|
// 3. RGB-Farben ersetzen
|
||||||
|
translated = replaceRgbColors(translated);
|
||||||
|
|
||||||
|
event.setLine(i, translated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String replaceHexColors(String input) {
|
||||||
|
Matcher matcher = HEX_PATTERN.matcher(input);
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|
||||||
|
while (matcher.find()) {
|
||||||
|
String hexCode = matcher.group();
|
||||||
|
// ChatColor.of akzeptiert Hex-Farbcode mit #
|
||||||
|
String color = ChatColor.of(hexCode).toString();
|
||||||
|
matcher.appendReplacement(sb, color);
|
||||||
|
}
|
||||||
|
matcher.appendTail(sb);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String replaceRgbColors(String input) {
|
||||||
|
Matcher matcher = RGB_PATTERN.matcher(input);
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|
||||||
|
while (matcher.find()) {
|
||||||
|
int r = clampColorValue(matcher.group(1));
|
||||||
|
int g = clampColorValue(matcher.group(2));
|
||||||
|
int b = clampColorValue(matcher.group(3));
|
||||||
|
|
||||||
|
String hex = String.format("#%02X%02X%02X", r, g, b);
|
||||||
|
String color = ChatColor.of(hex).toString();
|
||||||
|
|
||||||
|
matcher.appendReplacement(sb, color);
|
||||||
|
}
|
||||||
|
matcher.appendTail(sb);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int clampColorValue(String val) {
|
||||||
|
int v;
|
||||||
|
try {
|
||||||
|
v = Integer.parseInt(val);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
v = 0;
|
||||||
|
}
|
||||||
|
return Math.min(255, Math.max(0, v));
|
||||||
|
}
|
||||||
|
}
|
128
src/main/java/de/viper/survivalplus/listeners/SitListener.java
Normal file
128
src/main/java/de/viper/survivalplus/listeners/SitListener.java
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import de.viper.survivalplus.SurvivalPlus;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.ArmorStand;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
public class SitListener implements Listener {
|
||||||
|
private final SurvivalPlus plugin;
|
||||||
|
private final Map<UUID, ArmorStand> sittingPlayers = new HashMap<>();
|
||||||
|
|
||||||
|
public SitListener(SurvivalPlus plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSitting(Player player) {
|
||||||
|
return sittingPlayers.containsKey(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sitPlayer(Player player, Location location) {
|
||||||
|
if (sittingPlayers.containsKey(player.getUniqueId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erstelle einen unsichtbaren ArmorStand als Sitz
|
||||||
|
ArmorStand armorStand = player.getWorld().spawn(location, ArmorStand.class);
|
||||||
|
armorStand.setGravity(false);
|
||||||
|
armorStand.setMarker(true);
|
||||||
|
armorStand.setInvisible(true);
|
||||||
|
armorStand.setInvulnerable(true);
|
||||||
|
armorStand.addPassenger(player);
|
||||||
|
|
||||||
|
sittingPlayers.put(player.getUniqueId(), armorStand);
|
||||||
|
FileConfiguration lang = plugin.getLangConfig();
|
||||||
|
player.sendMessage(lang.getString("sit.success", "§aDu hast dich hingesetzt!"));
|
||||||
|
plugin.getLogger().log(Level.FINE, "Spieler " + player.getName() + " sitzt bei " + locationToString(location));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void standUp(Player player) {
|
||||||
|
UUID playerId = player.getUniqueId();
|
||||||
|
ArmorStand armorStand = sittingPlayers.remove(playerId);
|
||||||
|
if (armorStand != null) {
|
||||||
|
armorStand.remove();
|
||||||
|
FileConfiguration lang = plugin.getLangConfig();
|
||||||
|
player.sendMessage(lang.getString("sit.stand-up", "§aDu bist aufgestanden!"));
|
||||||
|
plugin.getLogger().log(Level.FINE, "Spieler " + player.getName() + " ist aufgestanden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||||
|
if (event.getHand() != EquipmentSlot.HAND || event.getAction() != Action.RIGHT_CLICK_BLOCK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
FileConfiguration lang = plugin.getLangConfig();
|
||||||
|
|
||||||
|
if (!player.hasPermission("survivalplus.sit")) {
|
||||||
|
player.sendMessage(lang.getString("no-permission", "§cDu hast keine Berechtigung für diesen Befehl!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block block = event.getClickedBlock();
|
||||||
|
if (block == null || !isStair(block.getType())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wenn der Spieler bereits sitzt, stehe auf
|
||||||
|
if (sittingPlayers.containsKey(player.getUniqueId())) {
|
||||||
|
standUp(player);
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setze den Spieler genau auf der Treppenstufe
|
||||||
|
Location location = block.getLocation();
|
||||||
|
location.setX(location.getX() + 0.5);
|
||||||
|
location.setY(location.getY() + 0.5); // Genau auf der Treppenstufe (halbe Blockhöhe)
|
||||||
|
location.setZ(location.getZ() + 0.5);
|
||||||
|
sitPlayer(player, location);
|
||||||
|
event.setCancelled(true); // Verhindere andere Interaktionen mit der Treppe
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerMove(PlayerMoveEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
UUID playerId = player.getUniqueId();
|
||||||
|
if (!sittingPlayers.containsKey(playerId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prüfe, ob der Spieler sich bewegt hat (nur Positionsänderung, nicht Kopfbewegung)
|
||||||
|
Location from = event.getFrom();
|
||||||
|
Location to = event.getTo();
|
||||||
|
if (from.getX() != to.getX() || from.getY() != to.getY() || from.getZ() != to.getZ()) {
|
||||||
|
standUp(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
standUp(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isStair(Material material) {
|
||||||
|
return material.name().endsWith("_STAIRS");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String locationToString(Location loc) {
|
||||||
|
return String.format("x=%.2f, y=%.2f, z=%.2f, world=%s", loc.getX(), loc.getY(), loc.getZ(), loc.getWorld().getName());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,68 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import de.viper.survivalplus.SurvivalPlus;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerBedEnterEvent;
|
||||||
|
import org.bukkit.event.player.PlayerBedLeaveEvent;
|
||||||
|
|
||||||
|
public class SleepListener implements Listener {
|
||||||
|
|
||||||
|
private final SurvivalPlus plugin;
|
||||||
|
private double requiredPercentage;
|
||||||
|
|
||||||
|
public SleepListener(SurvivalPlus plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
reloadConfig(plugin.getConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadConfig(FileConfiguration config) {
|
||||||
|
this.requiredPercentage = config.getDouble("sleep.required-percentage", 50.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerBedEnter(PlayerBedEnterEvent event) {
|
||||||
|
Bukkit.getScheduler().runTaskLater(plugin, () -> checkSleepProgress(event.getPlayer().getWorld()), 1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerBedLeave(PlayerBedLeaveEvent event) {
|
||||||
|
Bukkit.getScheduler().runTaskLater(plugin, () -> checkSleepProgress(event.getPlayer().getWorld()), 1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSleepProgress(World world) {
|
||||||
|
long time = world.getTime();
|
||||||
|
if (time < 12541 || time > 23458) return; // Nur bei Nacht prüfen
|
||||||
|
|
||||||
|
int sleeping = 0;
|
||||||
|
int total = 0;
|
||||||
|
|
||||||
|
for (Player player : world.getPlayers()) {
|
||||||
|
if (player.isSleepingIgnored()) continue;
|
||||||
|
total++;
|
||||||
|
if (player.isSleeping()) sleeping++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (total == 0) return;
|
||||||
|
|
||||||
|
double percent = (sleeping * 100.0) / total;
|
||||||
|
|
||||||
|
if (percent >= requiredPercentage) {
|
||||||
|
world.setTime(0);
|
||||||
|
world.setStorm(false);
|
||||||
|
world.setThundering(false);
|
||||||
|
Bukkit.broadcastMessage(plugin.getMessage("sleep.skipped")
|
||||||
|
.replace("%sleeping%", String.valueOf(sleeping))
|
||||||
|
.replace("%total%", String.valueOf(total)));
|
||||||
|
} else {
|
||||||
|
Bukkit.broadcastMessage(plugin.getMessage("sleep.progress")
|
||||||
|
.replace("%sleeping%", String.valueOf(sleeping))
|
||||||
|
.replace("%total%", String.valueOf(total))
|
||||||
|
.replace("%required%", String.valueOf(requiredPercentage)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,75 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import de.viper.survivalplus.SurvivalPlus;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
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.entity.EntityDamageByEntityEvent;
|
||||||
|
|
||||||
|
public class SpawnProtectionListener implements Listener {
|
||||||
|
|
||||||
|
private final SurvivalPlus plugin;
|
||||||
|
private final int radius;
|
||||||
|
private final boolean protectBlockBreak;
|
||||||
|
private final boolean protectBlockPlace;
|
||||||
|
private final boolean protectPvP;
|
||||||
|
private final String bypassPermission;
|
||||||
|
|
||||||
|
public SpawnProtectionListener(SurvivalPlus plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.radius = plugin.getConfig().getInt("spawnprotection.radius", 20);
|
||||||
|
this.protectBlockBreak = plugin.getConfig().getBoolean("spawnprotection.protect-block-break", true);
|
||||||
|
this.protectBlockPlace = plugin.getConfig().getBoolean("spawnprotection.protect-block-place", true);
|
||||||
|
this.protectPvP = plugin.getConfig().getBoolean("spawnprotection.protect-pvp", true);
|
||||||
|
this.bypassPermission = plugin.getConfig().getString("spawnprotection.bypass-permission", "survivalplus.spawnprotection.bypass");
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInSpawnProtection(Location loc) {
|
||||||
|
if (loc == null) return false;
|
||||||
|
Location spawn = loc.getWorld().getSpawnLocation();
|
||||||
|
return spawn.distance(loc) <= radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canBypass(Player player) {
|
||||||
|
// Nur OPs oder Spieler mit spezieller Berechtigung dürfen bypassen
|
||||||
|
return player.isOp() || player.hasPermission(bypassPermission);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
|
if (!protectBlockBreak) return;
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (isInSpawnProtection(event.getBlock().getLocation()) && !canBypass(player)) {
|
||||||
|
player.sendMessage(plugin.getMessage("spawnprotection.blockbreak-denied"));
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onBlockPlace(BlockPlaceEvent event) {
|
||||||
|
if (!protectBlockPlace) return;
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (isInSpawnProtection(event.getBlock().getLocation()) && !canBypass(player)) {
|
||||||
|
player.sendMessage(plugin.getMessage("spawnprotection.blockplace-denied"));
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
|
||||||
|
if (!protectPvP) return;
|
||||||
|
if (!(event.getEntity() instanceof Player)) return;
|
||||||
|
if (!(event.getDamager() instanceof Player)) return;
|
||||||
|
|
||||||
|
Player damaged = (Player) event.getEntity();
|
||||||
|
Player damager = (Player) event.getDamager();
|
||||||
|
|
||||||
|
if (isInSpawnProtection(damaged.getLocation()) && !canBypass(damager)) {
|
||||||
|
damager.sendMessage(plugin.getMessage("spawnprotection.pvp-denied"));
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,81 @@
|
|||||||
|
package de.viper.survivalplus.listeners;
|
||||||
|
|
||||||
|
import de.viper.survivalplus.Manager.StatsManager;
|
||||||
|
import de.viper.survivalplus.SurvivalPlus;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
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.entity.PlayerDeathEvent;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class StatsListener implements Listener {
|
||||||
|
|
||||||
|
private final SurvivalPlus plugin;
|
||||||
|
private final StatsManager statsManager;
|
||||||
|
|
||||||
|
// Spielzeit-Tracking
|
||||||
|
private final Map<UUID, Long> joinTimes = new HashMap<>();
|
||||||
|
|
||||||
|
public StatsListener(SurvivalPlus plugin, StatsManager statsManager) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.statsManager = statsManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
|
joinTimes.put(event.getPlayer().getUniqueId(), System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
|
UUID uuid = event.getPlayer().getUniqueId();
|
||||||
|
long joinTime = joinTimes.getOrDefault(uuid, System.currentTimeMillis());
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long secondsPlayed = (now - joinTime) / 1000;
|
||||||
|
|
||||||
|
statsManager.addPlayTime(uuid, secondsPlayed);
|
||||||
|
statsManager.saveStats();
|
||||||
|
|
||||||
|
joinTimes.remove(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||||
|
Player player = event.getEntity();
|
||||||
|
UUID uuid = player.getUniqueId();
|
||||||
|
statsManager.addDeaths(uuid, 1);
|
||||||
|
statsManager.saveStats();
|
||||||
|
|
||||||
|
// Optional: Kill-Stat beim Killer erhöhen
|
||||||
|
if (player.getKiller() != null) {
|
||||||
|
Player killer = player.getKiller();
|
||||||
|
statsManager.addKills(killer.getUniqueId(), 1);
|
||||||
|
statsManager.saveStats();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
UUID uuid = player.getUniqueId();
|
||||||
|
statsManager.addBlocksBroken(uuid, 1);
|
||||||
|
statsManager.saveStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onBlockPlace(BlockPlaceEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
UUID uuid = player.getUniqueId();
|
||||||
|
statsManager.addBlocksPlaced(uuid, 1);
|
||||||
|
statsManager.saveStats();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user