1463 lines
73 KiB
Java
1463 lines
73 KiB
Java
package com.viper.autosortchest;
|
|
|
|
import org.bukkit.Location;
|
|
import org.bukkit.World;
|
|
import org.bukkit.block.Block;
|
|
import org.bukkit.block.Chest;
|
|
import org.bukkit.block.Sign;
|
|
import org.bukkit.block.data.type.WallSign;
|
|
import org.bukkit.command.Command;
|
|
import org.bukkit.command.CommandExecutor;
|
|
import org.bukkit.command.CommandSender;
|
|
import org.bukkit.configuration.file.FileConfiguration;
|
|
import org.bukkit.configuration.file.YamlConfiguration;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.event.EventHandler;
|
|
import org.bukkit.event.EventPriority;
|
|
import org.bukkit.event.Listener;
|
|
import org.bukkit.event.block.Action;
|
|
import org.bukkit.event.block.BlockBreakEvent;
|
|
import org.bukkit.event.block.SignChangeEvent;
|
|
import org.bukkit.event.inventory.InventoryCloseEvent;
|
|
import org.bukkit.inventory.Inventory;
|
|
import org.bukkit.inventory.ItemStack;
|
|
import org.bukkit.plugin.java.JavaPlugin;
|
|
import org.bukkit.scheduler.BukkitRunnable;
|
|
import org.bukkit.ChatColor;
|
|
import org.bukkit.Material;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.util.*;
|
|
|
|
public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|
private File playerDataFile;
|
|
private FileConfiguration playerData;
|
|
private FileConfiguration config;
|
|
private final Map<UUID, Map<Material, Long>> fullChestMessageTracker = new HashMap<>();
|
|
private static final long MESSAGE_COOLDOWN = 5 * 60 * 1000; // 5 Minuten in Millisekunden
|
|
private static final String CONFIG_VERSION = "1.3";
|
|
|
|
@Override
|
|
public void onEnable() {
|
|
// Lade Standard-Konfiguration
|
|
saveDefaultConfig();
|
|
config = getConfig();
|
|
|
|
// Lade players.yml
|
|
playerDataFile = new File(getDataFolder(), "players.yml");
|
|
if (!playerDataFile.exists()) {
|
|
saveResource("players.yml", false);
|
|
}
|
|
loadPlayerData();
|
|
|
|
// Registriere Events
|
|
getServer().getPluginManager().registerEvents(this, this);
|
|
|
|
// Registriere Befehle
|
|
this.getCommand("asc").setExecutor(this);
|
|
|
|
// Starte periodischen Task
|
|
new BukkitRunnable() {
|
|
@Override
|
|
public void run() {
|
|
checkInputChests();
|
|
}
|
|
}.runTaskTimer(this, 20L, 20L); // Alle 1 Sekunde (20 Ticks)
|
|
|
|
// Starte Task zum Bereinigen des Message-Trackers
|
|
new BukkitRunnable() {
|
|
@Override
|
|
public void run() {
|
|
cleanMessageTracker();
|
|
}
|
|
}.runTaskTimer(this, 20L * 60, 20L * 60); // Alle Minute
|
|
|
|
// Aktualisiere Konfiguration und Schilder
|
|
updateConfig();
|
|
updateExistingSigns();
|
|
|
|
getLogger().info("AutoSortChest Plugin aktiviert! Version: " + getDescription().getVersion());
|
|
}
|
|
|
|
@Override
|
|
public void onDisable() {
|
|
savePlayerData();
|
|
getLogger().info("AutoSortChest Plugin deaktiviert!");
|
|
}
|
|
|
|
private void savePlayerData() {
|
|
if (playerData == null || playerDataFile == null) {
|
|
getLogger().warning("Kann players.yml nicht speichern: playerData oder playerDataFile ist null");
|
|
return;
|
|
}
|
|
try {
|
|
playerData.save(playerDataFile);
|
|
getLogger().info("players.yml erfolgreich gespeichert");
|
|
} catch (IOException e) {
|
|
getLogger().warning("Fehler beim Speichern der players.yml: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
private void loadPlayerData() {
|
|
if (playerDataFile == null) {
|
|
playerDataFile = new File(getDataFolder(), "players.yml");
|
|
}
|
|
try {
|
|
if (!playerDataFile.exists()) {
|
|
saveResource("players.yml", false);
|
|
getLogger().info("Neue players.yml erstellt");
|
|
}
|
|
playerData = YamlConfiguration.loadConfiguration(playerDataFile);
|
|
if (playerData.getConfigurationSection("players") == null) {
|
|
getLogger().warning("Abschnitt 'players' in players.yml fehlt. Initialisiere leer.");
|
|
playerData.createSection("players");
|
|
savePlayerData();
|
|
} else {
|
|
int playerCount = playerData.getConfigurationSection("players").getKeys(false).size();
|
|
getLogger().info("players.yml geladen mit " + playerCount + " Spieler-Einträgen");
|
|
}
|
|
} catch (Exception e) {
|
|
getLogger().warning("Fehler beim Laden von players.yml: " + e.getMessage());
|
|
playerData = new YamlConfiguration();
|
|
playerData.createSection("players");
|
|
savePlayerData();
|
|
}
|
|
}
|
|
|
|
private void updateConfig() {
|
|
File configFile = new File(getDataFolder(), "config.yml");
|
|
InputStream defaultConfigStream = getResource("config.yml");
|
|
FileConfiguration defaultConfig;
|
|
|
|
// Lade Standardkonfiguration
|
|
if (defaultConfigStream == null) {
|
|
getLogger().warning("Standard-config.yml nicht gefunden in Plugin-Ressourcen! Verwende Fallback-Werte.");
|
|
defaultConfig = new YamlConfiguration();
|
|
} else {
|
|
try {
|
|
defaultConfig = YamlConfiguration.loadConfiguration(new InputStreamReader(defaultConfigStream));
|
|
getLogger().info("Standard-config.yml erfolgreich geladen.");
|
|
} catch (Exception e) {
|
|
getLogger().warning("Fehler beim Laden von Standard-config.yml: " + e.getMessage());
|
|
defaultConfig = new YamlConfiguration();
|
|
}
|
|
}
|
|
|
|
// Prüfe Konfigurationsversion
|
|
String currentVersion = config.getString("version", "1.0");
|
|
boolean versionUpdated = false;
|
|
if (!currentVersion.equals(CONFIG_VERSION)) {
|
|
getLogger().info("Aktualisiere config.yml von Version " + currentVersion + " auf " + CONFIG_VERSION);
|
|
config.set("version", CONFIG_VERSION);
|
|
versionUpdated = true;
|
|
}
|
|
|
|
// Setze Standardwerte für fehlende Schlüssel
|
|
if (!config.contains("debug")) {
|
|
config.set("debug", defaultConfig.getBoolean("debug", false));
|
|
getLogger().info("Setze Standardwert: debug = " + config.getBoolean("debug"));
|
|
}
|
|
|
|
// Prüfe und setze sign-colors.input
|
|
if (!config.contains("sign-colors.input")) {
|
|
config.createSection("sign-colors.input");
|
|
config.set("sign-colors.input.line1", defaultConfig.getString("sign-colors.input.line1", "&6"));
|
|
config.set("sign-colors.input.line2", defaultConfig.getString("sign-colors.input.line2", "&0"));
|
|
config.set("sign-colors.input.line4", defaultConfig.getString("sign-colors.input.line4", "&f"));
|
|
getLogger().info("Setze Standardwerte für sign-colors.input");
|
|
} else {
|
|
if (!config.contains("sign-colors.input.line1")) {
|
|
config.set("sign-colors.input.line1", defaultConfig.getString("sign-colors.input.line1", "&6"));
|
|
getLogger().info("Setze Standardwert: sign-colors.input.line1 = " + config.getString("sign-colors.input.line1"));
|
|
}
|
|
if (!config.contains("sign-colors.input.line2")) {
|
|
config.set("sign-colors.input.line2", defaultConfig.getString("sign-colors.input.line2", "&0"));
|
|
getLogger().info("Setze Standardwert: sign-colors.input.line2 = " + config.getString("sign-colors.input.line2"));
|
|
}
|
|
if (!config.contains("sign-colors.input.line4")) {
|
|
config.set("sign-colors.input.line4", defaultConfig.getString("sign-colors.input.line4", "&f"));
|
|
getLogger().info("Setze Standardwert: sign-colors.input.line4 = " + config.getString("sign-colors.input.line4"));
|
|
}
|
|
}
|
|
|
|
// Prüfe und setze sign-colors.target
|
|
if (!config.contains("sign-colors.target")) {
|
|
config.createSection("sign-colors.target");
|
|
config.set("sign-colors.target.line1", defaultConfig.getString("sign-colors.target.line1", "&6"));
|
|
config.set("sign-colors.target.line2", defaultConfig.getString("sign-colors.target.line2", "&0"));
|
|
config.set("sign-colors.target.line3", defaultConfig.getString("sign-colors.target.line3", "&f"));
|
|
config.set("sign-colors.target.line4", defaultConfig.getString("sign-colors.target.line4", "&f"));
|
|
getLogger().info("Setze Standardwerte für sign-colors.target");
|
|
} else {
|
|
if (!config.contains("sign-colors.target.line1")) {
|
|
config.set("sign-colors.target.line1", defaultConfig.getString("sign-colors.target.line1", "&6"));
|
|
getLogger().info("Setze Standardwert: sign-colors.target.line1 = " + config.getString("sign-colors.target.line1"));
|
|
}
|
|
if (!config.contains("sign-colors.target.line2")) {
|
|
config.set("sign-colors.target.line2", defaultConfig.getString("sign-colors.target.line2", "&0"));
|
|
getLogger().info("Setze Standardwert: sign-colors.target.line2 = " + config.getString("sign-colors.target.line2"));
|
|
}
|
|
if (!config.contains("sign-colors.target.line3")) {
|
|
config.set("sign-colors.target.line3", defaultConfig.getString("sign-colors.target.line3", "&f"));
|
|
getLogger().info("Setze Standardwert: sign-colors.target.line3 = " + config.getString("sign-colors.target.line3"));
|
|
}
|
|
if (!config.contains("sign-colors.target.line4")) {
|
|
config.set("sign-colors.target.line4", defaultConfig.getString("sign-colors.target.line4", "&f"));
|
|
getLogger().info("Setze Standardwert: sign-colors.target.line4 = " + config.getString("sign-colors.target.line4"));
|
|
}
|
|
}
|
|
|
|
// Prüfe und setze sign-colors.full
|
|
if (!config.contains("sign-colors.full")) {
|
|
config.createSection("sign-colors.full");
|
|
config.set("sign-colors.full.line1", defaultConfig.getString("sign-colors.full.line1", "&c"));
|
|
config.set("sign-colors.full.line2", defaultConfig.getString("sign-colors.full.line2", "&4"));
|
|
config.set("sign-colors.full.line3", defaultConfig.getString("sign-colors.full.line3", "&e"));
|
|
config.set("sign-colors.full.line4", defaultConfig.getString("sign-colors.full.line4", "&e"));
|
|
getLogger().info("Setze Standardwerte für sign-colors.full");
|
|
} else {
|
|
if (!config.contains("sign-colors.full.line1")) {
|
|
config.set("sign-colors.full.line1", defaultConfig.getString("sign-colors.full.line1", "&c"));
|
|
getLogger().info("Setze Standardwert: sign-colors.full.line1 = " + config.getString("sign-colors.full.line1"));
|
|
}
|
|
if (!config.contains("sign-colors.full.line2")) {
|
|
config.set("sign-colors.full.line2", defaultConfig.getString("sign-colors.full.line2", "&4"));
|
|
getLogger().info("Setze Standardwert: sign-colors.full.line2 = " + config.getString("sign-colors.full.line2"));
|
|
}
|
|
if (!config.contains("sign-colors.full.line3")) {
|
|
config.set("sign-colors.full.line3", defaultConfig.getString("sign-colors.full.line3", "&e"));
|
|
getLogger().info("Setze Standardwert: sign-colors.full.line3 = " + config.getString("sign-colors.full.line3"));
|
|
}
|
|
if (!config.contains("sign-colors.full.line4")) {
|
|
config.set("sign-colors.full.line4", defaultConfig.getString("sign-colors.full.line4", "&e"));
|
|
getLogger().info("Setze Standardwert: sign-colors.full.line4 = " + config.getString("sign-colors.full.line4"));
|
|
}
|
|
}
|
|
|
|
// Prüfe und setze messages
|
|
if (!config.contains("messages.no-chest-near-sign")) {
|
|
config.set("messages.no-chest-near-sign", defaultConfig.getString("messages.no-chest-near-sign", "&cKeine Truhe in der Nähe des Schildes!"));
|
|
getLogger().info("Setze Standardwert: messages.no-chest-near-sign");
|
|
}
|
|
if (!config.contains("messages.no-item-in-hand")) {
|
|
config.set("messages.no-item-in-hand", defaultConfig.getString("messages.no-item-in-hand", "&cDu musst ein Item in der Hand halten!"));
|
|
getLogger().info("Setze Standardwert: messages.no-item-in-hand");
|
|
}
|
|
if (!config.contains("messages.not-your-chest")) {
|
|
config.set("messages.not-your-chest", defaultConfig.getString("messages.not-your-chest", "&cDiese Truhe gehört dir nicht!"));
|
|
getLogger().info("Setze Standardwert: messages.not-your-chest");
|
|
}
|
|
if (!config.contains("messages.input-chest-set")) {
|
|
config.set("messages.input-chest-set", defaultConfig.getString("messages.input-chest-set", "&aEingangstruhe erfolgreich gesetzt!"));
|
|
getLogger().info("Setze Standardwert: messages.input-chest-set");
|
|
}
|
|
if (!config.contains("messages.target-chest-set")) {
|
|
config.set("messages.target-chest-set", defaultConfig.getString("messages.target-chest-set", "&aZieltruhe für %item% erfolgreich gesetzt!"));
|
|
getLogger().info("Setze Standardwert: messages.target-chest-set");
|
|
}
|
|
if (!config.contains("messages.target-chest-missing")) {
|
|
config.set("messages.target-chest-missing", defaultConfig.getString("messages.target-chest-missing", "&cZieltruhe für %item% fehlt!"));
|
|
getLogger().info("Setze Standardwert: messages.target-chest-missing");
|
|
}
|
|
String targetChestFull = config.getString("messages.target-chest-full", "");
|
|
String defaultTargetChestFull = defaultConfig.getString("messages.target-chest-full", "&cZieltruhe für %item% ist voll! Koordinaten: (%x%, %y%, %z%)");
|
|
if (!config.contains("messages.target-chest-full") || !targetChestFull.equals(defaultTargetChestFull)) {
|
|
config.set("messages.target-chest-full", defaultTargetChestFull);
|
|
getLogger().info("Setze oder aktualisiere Standardwert: messages.target-chest-full = " + defaultTargetChestFull);
|
|
}
|
|
|
|
// --- NEUE NACHRICHTEN FÜR ÖFFENTLICHEN MODUS ---
|
|
if (!config.contains("messages.mode-changed")) {
|
|
config.set("messages.mode-changed", defaultConfig.getString("messages.mode-changed", "&aModus gewechselt: &e%mode%"));
|
|
getLogger().info("Setze Standardwert: messages.mode-changed");
|
|
}
|
|
if (!config.contains("messages.mode-public")) {
|
|
config.set("messages.mode-public", defaultConfig.getString("messages.mode-public", "&aÖffentlich"));
|
|
getLogger().info("Setze Standardwert: messages.mode-public");
|
|
}
|
|
if (!config.contains("messages.mode-private")) {
|
|
config.set("messages.mode-private", defaultConfig.getString("messages.mode-private", "&cPrivat"));
|
|
getLogger().info("Setze Standardwert: messages.mode-private");
|
|
}
|
|
// ----------------------------------------------
|
|
|
|
if (!config.contains("messages.help")) {
|
|
String helpMessage = "&6&l=== AutoSortChest Hilfe ===\n" +
|
|
"&eEingangstruhe erstellen:\n" +
|
|
"&f1. Platziere ein Schild an einer Truhe.\n" +
|
|
"&f2. Schreibe:\n" +
|
|
" &7[asc]\n" +
|
|
" &7input\n" +
|
|
"&fDein Name wird automatisch in Zeile 4 eingetragen.\n" +
|
|
"&eZieltruhe erstellen:\n" +
|
|
"&f1. Platziere ein Schild an einer Truhe.\n" +
|
|
"&f2. Schreibe:\n" +
|
|
" &7[asc]\n" +
|
|
" &7ziel\n" +
|
|
"&f3. Rechtsklicke mit einem Item in der Hand.\n" +
|
|
"&eBefehle:\n" +
|
|
"&f- &b/asc help &f- Zeigt diese Hilfe.\n" +
|
|
"&f- &b/asc info &f- Zeigt Plugin-Informationen.\n" +
|
|
"&f- &b/asc reload &f- Lädt die Konfiguration neu (OP).\n" +
|
|
"&6&l====================";
|
|
config.set("messages.help", defaultConfig.getString("messages.help", helpMessage));
|
|
getLogger().info("Setze Standardwert: messages.help");
|
|
}
|
|
if (!config.contains("messages.info")) {
|
|
String infoMessage = "&6&l=== AutoSortChest Info ===\n" +
|
|
"&ePlugin: &fAutoSortChest\n" +
|
|
"&eVersion: &f%version%\n" +
|
|
"&eKonfigurationsversion: &f%config_version%\n" +
|
|
"&eErsteller: &f%author%\n" +
|
|
"&eBeschreibung: &fAutomatisches Sortieren von Items in Truhen.\n" +
|
|
"&6&l====================";
|
|
config.set("messages.info", defaultConfig.getString("messages.info", infoMessage));
|
|
getLogger().info("Setze Standardwert: messages.info");
|
|
}
|
|
if (!config.contains("messages.no-permission")) {
|
|
config.set("messages.no-permission", defaultConfig.getString("messages.no-permission", "&cDu hast keine Berechtigung für diesen Befehl!"));
|
|
getLogger().info("Setze Standardwert: messages.no-permission");
|
|
}
|
|
if (!config.contains("messages.reload-success")) {
|
|
config.set("messages.reload-success", defaultConfig.getString("messages.reload-success", "&aKonfiguration erfolgreich neu geladen!"));
|
|
getLogger().info("Setze Standardwert: messages.reload-success");
|
|
}
|
|
if (!config.contains("messages.sign-break-denied")) {
|
|
config.set("messages.sign-break-denied", defaultConfig.getString("messages.sign-break-denied", "&cDu musst Shift gedrückt halten, um dieses Schild oder die Truhe abzubauen!"));
|
|
getLogger().info("Setze Standardwert: messages.sign-break-denied");
|
|
}
|
|
|
|
// Speichere die aktualisierte Konfiguration
|
|
try {
|
|
config.save(configFile);
|
|
if (configFile.exists() && configFile.length() > 0) {
|
|
getLogger().info("config.yml erfolgreich aktualisiert und gespeichert auf Version " + CONFIG_VERSION);
|
|
} else {
|
|
getLogger().warning("config.yml wurde nicht korrekt gespeichert (Datei existiert nicht oder ist leer)");
|
|
}
|
|
} catch (IOException e) {
|
|
getLogger().warning("Fehler beim Speichern der config.yml: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
private void updateExistingSigns() {
|
|
if (playerData == null) {
|
|
getLogger().warning("playerData ist null. Kann bestehende Schilder nicht aktualisieren.");
|
|
return;
|
|
}
|
|
if (playerData.getConfigurationSection("players") == null) {
|
|
getLogger().warning("Abschnitt 'players' in players.yml fehlt. Keine Schilder zum Aktualisieren.");
|
|
return;
|
|
}
|
|
|
|
for (String uuidString : playerData.getConfigurationSection("players").getKeys(false)) {
|
|
UUID playerUUID;
|
|
try {
|
|
playerUUID = UUID.fromString(uuidString);
|
|
} catch (IllegalArgumentException e) {
|
|
getLogger().warning("Ungültige UUID in players.yml: " + uuidString);
|
|
continue;
|
|
}
|
|
|
|
String path = "players." + uuidString;
|
|
|
|
// Eingangstruhe
|
|
String inputPath = path + ".input-chest";
|
|
if (playerData.contains(inputPath)) {
|
|
String worldName = playerData.getString(inputPath + ".world");
|
|
World world = getServer().getWorld(worldName);
|
|
if (world == null) {
|
|
getLogger().warning("Welt " + worldName + " für Eingangstruhe von Spieler UUID " + uuidString + " nicht gefunden");
|
|
continue;
|
|
}
|
|
int x = playerData.getInt(inputPath + ".x");
|
|
int y = playerData.getInt(inputPath + ".y");
|
|
int z = playerData.getInt(inputPath + ".z");
|
|
Location chestLocation = new Location(world, x, y, z);
|
|
Block chestBlock = chestLocation.getBlock();
|
|
|
|
if (!(chestBlock.getState() instanceof Chest)) {
|
|
getLogger().warning("Eingangstruhe bei " + chestLocation + " ist keine Truhe");
|
|
continue;
|
|
}
|
|
|
|
for (Block face : new Block[] {
|
|
chestBlock.getRelative(1, 0, 0),
|
|
chestBlock.getRelative(-1, 0, 0),
|
|
chestBlock.getRelative(0, 0, 1),
|
|
chestBlock.getRelative(0, 0, -1)
|
|
}) {
|
|
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, chestBlock)) {
|
|
String[] lines = sign.getLines();
|
|
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
|
|
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
|
|
String line3 = ChatColor.stripColor((String) (lines[3] != null ? lines[3] : ""));
|
|
if (line0.equalsIgnoreCase("[asc]") && line1.equalsIgnoreCase("input")) {
|
|
sign.setLine(0, getSignColor("input", "line1") + "[asc]");
|
|
sign.setLine(1, getSignColor("input", "line2") + "input");
|
|
sign.setLine(3, getSignColor("input", "line4") + line3);
|
|
sign.update();
|
|
if (isDebug()) {
|
|
getLogger().fine("Eingangsschild bei " + face.getLocation() + " für Spieler UUID " + uuidString + " aktualisiert");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Zieltruhen
|
|
String targetPath = path + ".target-chests";
|
|
if (playerData.contains(targetPath)) {
|
|
for (String itemType : playerData.getConfigurationSection(targetPath).getKeys(false)) {
|
|
String targetChestPath = targetPath + "." + itemType;
|
|
String worldName = playerData.getString(targetChestPath + ".world");
|
|
World world = getServer().getWorld(worldName);
|
|
if (world == null) {
|
|
getLogger().warning("Welt " + worldName + " für Zieltruhe von Item " + itemType + " nicht gefunden");
|
|
continue;
|
|
}
|
|
int x = playerData.getInt(targetChestPath + ".x");
|
|
int y = playerData.getInt(targetChestPath + ".y");
|
|
int z = playerData.getInt(targetChestPath + ".z");
|
|
Location chestLocation = new Location(world, x, y, z);
|
|
Block chestBlock = chestLocation.getBlock();
|
|
|
|
if (!(chestBlock.getState() instanceof Chest)) {
|
|
getLogger().warning("Zieltruhe für Item " + itemType + " bei " + chestLocation + " ist keine Truhe");
|
|
continue;
|
|
}
|
|
|
|
Chest chest = (Chest) chestBlock.getState();
|
|
Inventory inventory = chest.getInventory();
|
|
boolean isFull = isInventoryFull(inventory);
|
|
|
|
for (Block face : new Block[] {
|
|
chestBlock.getRelative(1, 0, 0),
|
|
chestBlock.getRelative(-1, 0, 0),
|
|
chestBlock.getRelative(0, 0, 1),
|
|
chestBlock.getRelative(0, 0, -1)
|
|
}) {
|
|
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, chestBlock)) {
|
|
String[] lines = sign.getLines();
|
|
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
|
|
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
|
|
String line2 = ChatColor.stripColor((String) (lines[2] != null ? lines[2] : ""));
|
|
String line3 = ChatColor.stripColor((String) (lines[3] != null ? lines[3] : ""));
|
|
if (line0.equalsIgnoreCase("[asc]") && line1.equalsIgnoreCase("ziel")) {
|
|
String colorType = isFull ? "full" : "target";
|
|
sign.setLine(0, getSignColor(colorType, "line1") + "[asc]");
|
|
sign.setLine(1, getSignColor(colorType, "line2") + "ziel");
|
|
sign.setLine(2, getSignColor(colorType, "line3") + line2);
|
|
sign.setLine(3, getSignColor(colorType, "line4") + line3);
|
|
sign.update();
|
|
if (isDebug()) {
|
|
getLogger().fine("Zieltruhe-Schild für Item " + itemType + " bei " + face.getLocation() + " aktualisiert (voll: " + isFull + ")");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean isInventoryFull(Inventory inventory) {
|
|
for (ItemStack item : inventory.getContents()) {
|
|
if (item == null || item.getAmount() < item.getMaxStackSize()) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private boolean isChestPublic(Sign sign) {
|
|
String line3 = sign.getLine(3); // MIT Farbcodes!
|
|
String line3Clean = ChatColor.stripColor(line3);
|
|
return line3Clean.toLowerCase().contains("[public]");
|
|
}
|
|
|
|
private boolean isDebug() {
|
|
return config != null && config.getBoolean("debug", false);
|
|
}
|
|
|
|
private String getMessage(String key) {
|
|
if (config == null) {
|
|
return ChatColor.RED + "Fehlende Konfiguration: " + key;
|
|
}
|
|
String message = config.getString("messages." + key, "Fehlende Nachricht: " + key);
|
|
return ChatColor.translateAlternateColorCodes('&', message);
|
|
}
|
|
|
|
private String getSignColor(String type, String line) {
|
|
if (config == null) {
|
|
return "&f";
|
|
}
|
|
String color = config.getString("sign-colors." + type + "." + line, "&f");
|
|
return ChatColor.translateAlternateColorCodes('&', color);
|
|
}
|
|
|
|
private boolean isSignAttachedToChest(Block signBlock, Block chestBlock) {
|
|
if (!(signBlock.getBlockData() instanceof WallSign)) {
|
|
if (isDebug()) getLogger().fine("Schild bei " + signBlock.getLocation() + " ist kein Wandschild");
|
|
return false;
|
|
}
|
|
WallSign wallSign = (WallSign) signBlock.getBlockData();
|
|
Block attachedBlock = signBlock.getRelative(wallSign.getFacing().getOppositeFace());
|
|
boolean attached = attachedBlock.equals(chestBlock);
|
|
if (!attached && isDebug()) {
|
|
getLogger().fine("Schild bei " + signBlock.getLocation() + " ist nicht an Truhe bei " + chestBlock.getLocation() + " angebracht");
|
|
}
|
|
return attached;
|
|
}
|
|
|
|
private void setInputChestLocation(UUID playerUUID, Location location) {
|
|
String path = "players." + playerUUID + ".input-chest";
|
|
playerData.set(path + ".world", location.getWorld().getName());
|
|
playerData.set(path + ".x", location.getBlockX());
|
|
playerData.set(path + ".y", location.getBlockY());
|
|
playerData.set(path + ".z", location.getBlockZ());
|
|
savePlayerData();
|
|
}
|
|
|
|
private void setTargetChestLocation(UUID playerUUID, Location location, Material itemType) {
|
|
String path = "players." + playerUUID + ".target-chests." + itemType.name();
|
|
playerData.set(path + ".world", location.getWorld().getName());
|
|
playerData.set(path + ".x", location.getBlockX());
|
|
playerData.set(path + ".y", location.getBlockY());
|
|
playerData.set(path + ".z", location.getBlockZ());
|
|
savePlayerData();
|
|
getLogger().info("Zieltruhe für " + getServer().getPlayer(playerUUID).getName() + " (" + itemType.name() + ") gesetzt bei " + location);
|
|
}
|
|
|
|
private Location getTargetChestLocation(UUID playerUUID, Material itemType) {
|
|
String path = "players." + playerUUID + ".target-chests." + itemType.name();
|
|
if (!playerData.contains(path)) {
|
|
if (isDebug()) getLogger().fine("Keine Zieltruhe für Item " + itemType.name() + " für Spieler UUID " + playerUUID);
|
|
return null;
|
|
}
|
|
|
|
String worldName = playerData.getString(path + ".world");
|
|
World world = getServer().getWorld(worldName);
|
|
if (world == null) {
|
|
getLogger().warning("Welt " + worldName + " für Zieltruhe von Item " + itemType.name() + " nicht gefunden");
|
|
return null;
|
|
}
|
|
|
|
int x = playerData.getInt(path + ".x");
|
|
int y = playerData.getInt(path + ".y");
|
|
int z = playerData.getInt(path + ".z");
|
|
|
|
return new Location(world, x, y, z);
|
|
}
|
|
|
|
private void cleanMessageTracker() {
|
|
long currentTime = System.currentTimeMillis();
|
|
fullChestMessageTracker.entrySet().removeIf(entry -> {
|
|
Map<Material, Long> messages = entry.getValue();
|
|
messages.entrySet().removeIf(msg -> currentTime - msg.getValue() > MESSAGE_COOLDOWN);
|
|
return messages.isEmpty();
|
|
});
|
|
}
|
|
|
|
private boolean canSendFullChestMessage(UUID playerUUID, Material material) {
|
|
Map<Material, Long> playerMessages = fullChestMessageTracker.computeIfAbsent(playerUUID, k -> new HashMap<>());
|
|
Long lastMessageTime = playerMessages.get(material);
|
|
long currentTime = System.currentTimeMillis();
|
|
|
|
if (lastMessageTime == null || currentTime - lastMessageTime > MESSAGE_COOLDOWN) {
|
|
playerMessages.put(material, currentTime);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
|
if (!command.getName().equalsIgnoreCase("asc")) return false;
|
|
|
|
if (!(sender instanceof Player)) {
|
|
sender.sendMessage(ChatColor.RED + "Dieser Befehl ist nur für Spieler!");
|
|
return true;
|
|
}
|
|
|
|
Player player = (Player) sender;
|
|
|
|
if (args.length == 0 || args[0].equalsIgnoreCase("help")) {
|
|
String helpMessage = getMessage("help");
|
|
player.sendMessage(helpMessage.split("\n"));
|
|
return true;
|
|
}
|
|
|
|
if (args[0].equalsIgnoreCase("info")) {
|
|
String infoMessage = getMessage("info")
|
|
.replace("%version%", getDescription().getVersion())
|
|
.replace("%config_version%", config != null ? config.getString("version", CONFIG_VERSION) : CONFIG_VERSION)
|
|
.replace("%author%", String.join(", ", getDescription().getAuthors()));
|
|
player.sendMessage(infoMessage.split("\n"));
|
|
return true;
|
|
}
|
|
|
|
if (args[0].equalsIgnoreCase("reload")) {
|
|
if (!player.hasPermission("autosortchest.reload")) {
|
|
player.sendMessage(getMessage("no-permission"));
|
|
return true;
|
|
}
|
|
reloadConfig();
|
|
config = getConfig();
|
|
loadPlayerData();
|
|
updateConfig();
|
|
updateExistingSigns();
|
|
player.sendMessage(getMessage("reload-success"));
|
|
getLogger().info("Konfiguration und Spielerdaten neu geladen durch " + player.getName());
|
|
return true;
|
|
}
|
|
|
|
String helpMessage = getMessage("help");
|
|
player.sendMessage(helpMessage.split("\n"));
|
|
return true;
|
|
}
|
|
|
|
@EventHandler
|
|
public void onSignChange(SignChangeEvent event) {
|
|
Player player = event.getPlayer();
|
|
UUID playerUUID = player.getUniqueId();
|
|
Block signBlock = event.getBlock();
|
|
String[] lines = event.getLines();
|
|
|
|
if (lines.length >= 2 && lines[0].equalsIgnoreCase("[asc]") && lines[1].equalsIgnoreCase("input")) {
|
|
Block chestBlock = null;
|
|
if (signBlock.getBlockData() instanceof WallSign wallSign) {
|
|
Block attachedBlock = signBlock.getRelative(wallSign.getFacing().getOppositeFace());
|
|
if (attachedBlock.getState() instanceof Chest) {
|
|
chestBlock = attachedBlock;
|
|
}
|
|
}
|
|
|
|
if (chestBlock == null) {
|
|
player.sendMessage(getMessage("no-chest-near-sign"));
|
|
getLogger().warning("Keine Truhe an Schild bei " + signBlock.getLocation() + " für Spieler " + player.getName());
|
|
return;
|
|
}
|
|
|
|
event.setLine(0, getSignColor("input", "line1") + "[asc]");
|
|
event.setLine(1, getSignColor("input", "line2") + "input");
|
|
event.setLine(3, getSignColor("input", "line4") + player.getName());
|
|
setInputChestLocation(playerUUID, chestBlock.getLocation());
|
|
player.sendMessage(getMessage("input-chest-set"));
|
|
getLogger().info("Eingangstruhe für " + player.getName() + " gesetzt bei " + chestBlock.getLocation());
|
|
}
|
|
}
|
|
|
|
@EventHandler
|
|
public void onPlayerInteract(org.bukkit.event.player.PlayerInteractEvent event) {
|
|
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
|
|
|
Player player = event.getPlayer();
|
|
UUID playerUUID = player.getUniqueId();
|
|
Block clickedBlock = event.getClickedBlock();
|
|
ItemStack itemInHand = event.getItem();
|
|
|
|
if (clickedBlock == null) return;
|
|
|
|
// Schild-Interaktion
|
|
if (clickedBlock.getState() instanceof Sign sign) {
|
|
String[] lines = sign.getLines();
|
|
if (lines.length >= 2 && ChatColor.stripColor((String) (lines[0] != null ? lines[0] : "")).equalsIgnoreCase("[asc]")) {
|
|
|
|
// Truhe finden
|
|
Block chestBlock = null;
|
|
if (sign.getBlockData() instanceof WallSign wallSign) {
|
|
Block attachedBlock = sign.getBlock().getRelative(wallSign.getFacing().getOppositeFace());
|
|
if (attachedBlock.getState() instanceof Chest) {
|
|
chestBlock = attachedBlock;
|
|
}
|
|
}
|
|
|
|
if (chestBlock == null) {
|
|
player.sendMessage(getMessage("no-chest-near-sign"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
|
|
String line1Clean = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
|
|
|
|
// --- LOGIK FÜR ZIELTRUHEN (ZIEL) ---
|
|
if (line1Clean.equalsIgnoreCase("ziel")) {
|
|
String line3Raw = lines[3] != null ? lines[3] : "";
|
|
String line3Clean = ChatColor.stripColor(line3Raw);
|
|
String pureOwnerName = line3Clean.replace("[Public]", "").replace("[public]", "").trim();
|
|
|
|
boolean isOwner = pureOwnerName.equalsIgnoreCase(player.getName());
|
|
|
|
// 1. FALL: MODUS WECHSELN (Shift + Klick + Leere Hand)
|
|
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && player.isSneaking() && (itemInHand == null || itemInHand.getType() == Material.AIR)) {
|
|
if (isOwner) {
|
|
boolean isPublic = isChestPublic(sign);
|
|
String newModeText;
|
|
String newLine4;
|
|
|
|
if (isPublic) {
|
|
// Wechsel zu Privat
|
|
newModeText = getMessage("mode-private");
|
|
newLine4 = getSignColor("target", "line4") + pureOwnerName;
|
|
} else {
|
|
// Wechsel zu Öffentlich
|
|
newModeText = getMessage("mode-public");
|
|
newLine4 = getSignColor("target", "line4") + pureOwnerName + " " + ChatColor.RESET + "[Public]";
|
|
}
|
|
|
|
sign.setLine(3, newLine4);
|
|
sign.update();
|
|
player.sendMessage(getMessage("mode-changed").replace("%mode%", newModeText));
|
|
event.setCancelled(true);
|
|
return;
|
|
} else {
|
|
player.sendMessage(getMessage("not-your-chest"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
}
|
|
// 2. FALL: ITEM ZUWEISEN (Klick + Item in Hand)
|
|
String line2Clean = ChatColor.stripColor((String) (lines[2] != null ? lines[2] : ""));
|
|
|
|
if (line2Clean.isEmpty()) {
|
|
if (itemInHand == null || itemInHand.getType() == Material.AIR) {
|
|
player.sendMessage(getMessage("no-item-in-hand"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
|
|
// Wenn das Schild noch KEINEN Owner hat, darf jeder es "übernehmen"
|
|
if (!pureOwnerName.isEmpty() && !pureOwnerName.equalsIgnoreCase("Unknown") && !isOwner) {
|
|
player.sendMessage(getMessage("not-your-chest"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
|
|
Chest chest = (Chest) chestBlock.getState();
|
|
boolean isFull = isInventoryFull(chest.getInventory());
|
|
String colorType = isFull ? "full" : "target";
|
|
|
|
sign.setLine(0, getSignColor(colorType, "line1") + "[asc]");
|
|
sign.setLine(1, getSignColor(colorType, "line2") + "ziel");
|
|
sign.setLine(2, getSignColor(colorType, "line3") + itemInHand.getType().name());
|
|
|
|
// Wenn noch kein Name da war, setze ihn
|
|
String finalLine4 = line3Raw;
|
|
if (pureOwnerName.isEmpty() || pureOwnerName.equalsIgnoreCase("Unknown")) {
|
|
finalLine4 = getSignColor("target", "line4") + player.getName();
|
|
}
|
|
|
|
sign.setLine(3, finalLine4);
|
|
sign.update();
|
|
|
|
setTargetChestLocation(player.getUniqueId(), chestBlock.getLocation(), itemInHand.getType());
|
|
player.sendMessage(getMessage("target-chest-set").replace("%item%", itemInHand.getType().name()));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
|
|
// Zugriffsschutz für konfigurierte Truhen
|
|
// Wenn nicht Owner und NICHT öffentlich -> Zugriff verweigern
|
|
if (!isOwner && !isChestPublic(sign)) {
|
|
player.sendMessage(getMessage("not-your-chest"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
|
|
// Wenn Owner oder Öffentlich -> Truhe öffnen lassen (Event nicht canceln)
|
|
return;
|
|
}
|
|
|
|
// --- LOGIK FÜR EINGANGSTRUHEN (INPUT) ---
|
|
if (line1Clean.equalsIgnoreCase("input")) {
|
|
String line3Raw = lines[3] != null ? lines[3] : "";
|
|
String line3Clean = ChatColor.stripColor(line3Raw);
|
|
String pureOwnerName = line3Clean.replace("[Public]", "").replace("[public]", "").trim();
|
|
boolean isOwner = pureOwnerName.equalsIgnoreCase(player.getName());
|
|
|
|
// 1. FALL: MODUS WECHSELN (Shift + Klick + Leere Hand)
|
|
if (player.isSneaking() && (itemInHand == null || itemInHand.getType() == Material.AIR)) {
|
|
if (isOwner) {
|
|
boolean isPublic = isChestPublic(sign);
|
|
String newModeText;
|
|
String newLine4;
|
|
|
|
if (isPublic) {
|
|
newModeText = getMessage("mode-private");
|
|
newLine4 = getSignColor("input", "line4") + pureOwnerName;
|
|
} else {
|
|
newModeText = getMessage("mode-public");
|
|
newLine4 = getSignColor("input", "line4") + pureOwnerName + " " + ChatColor.RESET + "[Public]";
|
|
}
|
|
|
|
sign.setLine(3, newLine4);
|
|
sign.update();
|
|
player.sendMessage(getMessage("mode-changed").replace("%mode%", newModeText));
|
|
event.setCancelled(true);
|
|
return;
|
|
} else {
|
|
player.sendMessage(getMessage("not-your-chest"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Zugriffsschutz
|
|
if (!isOwner && !isChestPublic(sign)) {
|
|
player.sendMessage(getMessage("not-your-chest"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Truhe-Interaktion (wenn man direkt auf die Truhe klickt und nicht auf das Schild)
|
|
if (clickedBlock.getState() instanceof Chest) {
|
|
Block chestBlock = clickedBlock;
|
|
Block signBlock = null;
|
|
|
|
// Suche Schild
|
|
for (Block face : new Block[] {
|
|
chestBlock.getRelative(1, 0, 0),
|
|
chestBlock.getRelative(-1, 0, 0),
|
|
chestBlock.getRelative(0, 0, 1),
|
|
chestBlock.getRelative(0, 0, -1)
|
|
}) {
|
|
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, chestBlock)) {
|
|
String[] lines = sign.getLines();
|
|
if (lines.length >= 2 && ChatColor.stripColor((String) (lines[0] != null ? lines[0] : "")).equalsIgnoreCase("[asc]")) {
|
|
signBlock = face;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (signBlock != null) {
|
|
Sign sign = (Sign) signBlock.getState();
|
|
String[] lines = sign.getLines();
|
|
String line1Clean = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
|
|
|
|
// NUR FÜR ZIELTRUHEN
|
|
if (line1Clean.equalsIgnoreCase("ziel")) {
|
|
String line3Raw = lines[3] != null ? lines[3] : "";
|
|
String line3Clean = ChatColor.stripColor(line3Raw);
|
|
String pureOwnerName = line3Clean.replace("[public]", "").replace("[Public]", "").trim();
|
|
boolean isOwner = pureOwnerName.equalsIgnoreCase(player.getName());
|
|
|
|
// 1. FALL: MODUS WECHSELN
|
|
if (player.isSneaking() && (itemInHand == null || itemInHand.getType() == Material.AIR)) {
|
|
if (isOwner) {
|
|
boolean isPublic = isChestPublic(sign);
|
|
String newModeText;
|
|
String newLine4;
|
|
|
|
String baseName = getSignColor("target", "line4") + pureOwnerName;
|
|
|
|
if (isPublic) {
|
|
newModeText = getMessage("mode-private");
|
|
newLine4 = baseName;
|
|
} else {
|
|
newModeText = getMessage("mode-public");
|
|
newLine4 = baseName + " " + ChatColor.RESET + "[Public]";
|
|
}
|
|
|
|
sign.setLine(3, newLine4);
|
|
sign.update();
|
|
player.sendMessage(getMessage("mode-changed").replace("%mode%", newModeText));
|
|
event.setCancelled(true);
|
|
return;
|
|
} else {
|
|
player.sendMessage(getMessage("not-your-chest"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// 2. FALL: ITEM ZUWEISEN
|
|
String line2Clean = ChatColor.stripColor((String) (lines[2] != null ? lines[2] : ""));
|
|
if (line2Clean.isEmpty()) {
|
|
if (itemInHand == null || itemInHand.getType() == Material.AIR) {
|
|
player.sendMessage(getMessage("no-item-in-hand"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
|
|
if (!pureOwnerName.isEmpty() && !pureOwnerName.equalsIgnoreCase("Unknown") && !isOwner) {
|
|
player.sendMessage(getMessage("not-your-chest"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
|
|
Chest chest = (Chest) chestBlock.getState();
|
|
boolean isFull = isInventoryFull(chest.getInventory());
|
|
String colorType = isFull ? "full" : "target";
|
|
|
|
sign.setLine(0, getSignColor(colorType, "line1") + "[asc]");
|
|
sign.setLine(1, getSignColor(colorType, "line2") + "ziel");
|
|
sign.setLine(2, getSignColor(colorType, "line3") + itemInHand.getType().name());
|
|
|
|
String finalLine4 = line3Raw;
|
|
if (pureOwnerName.isEmpty() || pureOwnerName.equalsIgnoreCase("Unknown")) {
|
|
finalLine4 = getSignColor("target", "line4") + player.getName();
|
|
}
|
|
|
|
sign.setLine(3, finalLine4);
|
|
sign.update();
|
|
|
|
setTargetChestLocation(player.getUniqueId(), chestBlock.getLocation(), itemInHand.getType());
|
|
player.sendMessage(getMessage("target-chest-set").replace("%item%", itemInHand.getType().name()));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
|
|
// Wenn nicht Owner und nicht öffentlich -> Zugriff verweigern
|
|
if (!isOwner && !isChestPublic(sign)) {
|
|
player.sendMessage(getMessage("not-your-chest"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// FALL: EINGANGSTRUHE
|
|
if (line1Clean.equalsIgnoreCase("input")) {
|
|
String line3Raw = lines[3] != null ? lines[3] : "";
|
|
String line3Clean = ChatColor.stripColor(line3Raw);
|
|
String pureOwnerName = line3Clean.replace("[public]", "").replace("[Public]", "").trim();
|
|
boolean isOwner = pureOwnerName.equalsIgnoreCase(player.getName());
|
|
|
|
// Moduswechsel
|
|
if (player.isSneaking() && (itemInHand == null || itemInHand.getType() == Material.AIR)) {
|
|
if (isOwner) {
|
|
boolean isPublic = isChestPublic(sign);
|
|
String newModeText;
|
|
String newLine4;
|
|
|
|
String baseName = getSignColor("input", "line4") + pureOwnerName;
|
|
|
|
if (isPublic) {
|
|
newModeText = getMessage("mode-private");
|
|
newLine4 = baseName;
|
|
} else {
|
|
newModeText = getMessage("mode-public");
|
|
newLine4 = baseName + " " + ChatColor.RESET + "[Public]";
|
|
}
|
|
sign.setLine(3, newLine4);
|
|
sign.update();
|
|
player.sendMessage(getMessage("mode-changed").replace("%mode%", newModeText));
|
|
event.setCancelled(true);
|
|
return;
|
|
} else {
|
|
player.sendMessage(getMessage("not-your-chest"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!isOwner && !isChestPublic(sign)) {
|
|
player.sendMessage(getMessage("not-your-chest"));
|
|
event.setCancelled(true);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@EventHandler(priority = EventPriority.HIGHEST)
|
|
public void onBlockBreak(BlockBreakEvent event) {
|
|
Block block = event.getBlock();
|
|
Player player = event.getPlayer();
|
|
Block signBlock = null;
|
|
String signOwner = "";
|
|
boolean isAscChest = false;
|
|
|
|
if (isDebug()) {
|
|
getLogger().fine("BlockBreakEvent ausgelöst bei " + block.getLocation() + " durch Spieler " + player.getName() + ", GameMode: " + player.getGameMode() + ", Sneaking: " + player.isSneaking() + ", OP: " + player.isOp() + ", Berechtigung autosortchest.bypass: " + player.hasPermission("autosortchest.bypass"));
|
|
}
|
|
|
|
// Fall 1: Schild wird abgebaut
|
|
if (block.getState() instanceof Sign sign) {
|
|
String[] lines = sign.getLines();
|
|
if (lines.length >= 2 && ChatColor.stripColor((String) (lines[0] != null ? lines[0] : "")).equalsIgnoreCase("[asc]") &&
|
|
(ChatColor.stripColor((String) (lines[1] != null ? lines[1] : "")).equalsIgnoreCase("input") || ChatColor.stripColor((String) (lines[1] != null ? lines[1] : "")).equalsIgnoreCase("ziel"))) {
|
|
signBlock = block;
|
|
signOwner = ChatColor.stripColor((String) (lines[3] != null ? lines[3] : ""));
|
|
if (isDebug()) {
|
|
getLogger().fine("Schild erkannt bei " + block.getLocation() + ", Besitzer: " + signOwner);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fall 2: Truhe wird abgebaut
|
|
if (block.getState() instanceof Chest chestBlock) {
|
|
for (Block face : new Block[] {
|
|
block.getRelative(1, 0, 0),
|
|
block.getRelative(-1, 0, 0),
|
|
block.getRelative(0, 0, 1),
|
|
block.getRelative(0, 0, -1)
|
|
}) {
|
|
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, block)) {
|
|
String[] lines = sign.getLines();
|
|
if (lines.length >= 2 && ChatColor.stripColor((String) (lines[0] != null ? lines[0] : "")).equalsIgnoreCase("[asc]") &&
|
|
(ChatColor.stripColor((String) (lines[1] != null ? lines[1] : "")).equalsIgnoreCase("input") || ChatColor.stripColor((String) (lines[1] != null ? lines[1] : "")).equalsIgnoreCase("ziel"))) {
|
|
signBlock = face;
|
|
signOwner = ChatColor.stripColor((String) (lines[3] != null ? lines[3] : ""));
|
|
isAscChest = true;
|
|
if (isDebug()) {
|
|
getLogger().fine("Truhe mit [asc]-Schild erkannt bei " + block.getLocation() + ", Schild bei " + face.getLocation() + ", Besitzer: " + signOwner);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Kein [asc]-Schild oder keine Truhe mit [asc]-Schild
|
|
if (signBlock == null) {
|
|
if (isDebug()) {
|
|
getLogger().fine("Kein [asc]-Schild oder Truhe mit [asc]-Schild bei " + block.getLocation());
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Prüfe Besitzer
|
|
boolean isOwner = signOwner.isEmpty() || signOwner.equalsIgnoreCase(player.getName());
|
|
|
|
if (!isOwner) {
|
|
player.sendMessage(getMessage("not-your-chest"));
|
|
event.setCancelled(true);
|
|
getLogger().warning("Spieler " + player.getName() + " versuchte, " + (isAscChest ? "Truhe" : "Schild") + " bei " + block.getLocation() + " abzubauen, das nicht ihm gehört (Besitzer: " + signOwner + ")");
|
|
return;
|
|
}
|
|
|
|
// Prüfe Shift-Taste (Berechtigungen ignorieren)
|
|
if (!player.isSneaking()) {
|
|
player.sendMessage(getMessage("sign-break-denied"));
|
|
event.setCancelled(true);
|
|
if (isDebug()) {
|
|
getLogger().fine("Spieler " + player.getName() + " versuchte, " + (isAscChest ? "Truhe" : "Schild") + " bei " + block.getLocation() + " ohne Shift abzubauen");
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (isDebug()) {
|
|
getLogger().fine("Spieler " + player.getName() + " hat " + (isAscChest ? "Truhe" : "Schild") + " bei " + block.getLocation() + " erfolgreich abgebaut");
|
|
}
|
|
}
|
|
|
|
@EventHandler
|
|
public void onInventoryClose(InventoryCloseEvent event) {
|
|
if (!(event.getInventory().getHolder() instanceof Chest chest)) return;
|
|
|
|
Player player = (Player) event.getPlayer();
|
|
Block chestBlock = chest.getBlock();
|
|
Block signBlock = null;
|
|
|
|
// Suche nach einem an die Truhe angehängten Schild
|
|
for (Block face : new Block[] {
|
|
chestBlock.getRelative(1, 0, 0),
|
|
chestBlock.getRelative(-1, 0, 0),
|
|
chestBlock.getRelative(0, 0, 1),
|
|
chestBlock.getRelative(0, 0, -1)
|
|
}) {
|
|
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, chestBlock)) {
|
|
String[] lines = sign.getLines();
|
|
if (lines.length >= 2 && ChatColor.stripColor((String) (lines[0] != null ? lines[0] : "")).equalsIgnoreCase("[asc]") && ChatColor.stripColor((String) (lines[1] != null ? lines[1] : "")).equalsIgnoreCase("ziel")) {
|
|
signBlock = face;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (signBlock == null) {
|
|
if (isDebug()) getLogger().fine("Keine Zieltruhe-Schild an Truhe bei " + chestBlock.getLocation());
|
|
return;
|
|
}
|
|
|
|
Sign sign = (Sign) signBlock.getState();
|
|
String[] lines = sign.getLines();
|
|
String signOwner = ChatColor.stripColor((String) (lines[3] != null ? lines[3] : ""));
|
|
if (!signOwner.equalsIgnoreCase(player.getName())) {
|
|
if (isDebug()) getLogger().fine("Schild bei " + signBlock.getLocation() + " gehört nicht Spieler " + player.getName() + " (Besitzer: " + signOwner + ")");
|
|
return;
|
|
}
|
|
|
|
boolean isFull = isInventoryFull(chest.getInventory());
|
|
String colorType = isFull ? "full" : "target";
|
|
|
|
String currentLine0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
|
|
String currentLine1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
|
|
String currentLine2 = ChatColor.stripColor((String) (lines[2] != null ? lines[2] : ""));
|
|
String currentLine3 = ChatColor.stripColor((String) (lines[3] != null ? lines[3] : ""));
|
|
|
|
if (currentLine0.equalsIgnoreCase("[asc]") && currentLine1.equalsIgnoreCase("ziel")) {
|
|
sign.setLine(0, getSignColor(colorType, "line1") + "[asc]");
|
|
sign.setLine(1, getSignColor(colorType, "line2") + "ziel");
|
|
sign.setLine(2, getSignColor(colorType, "line3") + currentLine2);
|
|
sign.setLine(3, getSignColor(colorType, "line4") + currentLine3);
|
|
sign.update();
|
|
if (isDebug()) {
|
|
getLogger().fine("Zieltruhe-Schild bei " + signBlock.getLocation() + " aktualisiert nach Inventar-Schließung (voll: " + isFull + ")");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void distributeItems(Player player, Inventory sourceInventory) {
|
|
UUID playerUUID = player.getUniqueId();
|
|
Block chestBlock = ((Chest) sourceInventory.getHolder()).getBlock();
|
|
|
|
// Prüfe, ob die Truhe leer ist
|
|
boolean hasItems = false;
|
|
for (ItemStack item : sourceInventory.getContents()) {
|
|
if (item != null && item.getType() != Material.AIR) {
|
|
hasItems = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!hasItems) {
|
|
if (isDebug()) getLogger().fine("Eingangstruhe bei " + chestBlock.getLocation() + " ist leer");
|
|
return;
|
|
}
|
|
|
|
for (int slot = 0; slot < sourceInventory.getSize(); slot++) {
|
|
ItemStack item = sourceInventory.getItem(slot);
|
|
if (item == null || item.getType() == Material.AIR) continue;
|
|
|
|
Location targetChestLocation = getTargetChestLocation(playerUUID, item.getType());
|
|
if (targetChestLocation == null) {
|
|
if (isDebug()) getLogger().fine("Keine Zieltruhe für Item " + item.getType().name() + " für Spieler " + player.getName());
|
|
continue;
|
|
}
|
|
|
|
if (!(targetChestLocation.getBlock().getState() instanceof Chest)) {
|
|
if (canSendFullChestMessage(playerUUID, item.getType())) {
|
|
player.sendMessage(getMessage("target-chest-missing").replace("%item%", item.getType().name()));
|
|
}
|
|
playerData.set("players." + playerUUID + ".target-chests." + item.getType().name(), null);
|
|
savePlayerData();
|
|
getLogger().warning("Zieltruhe für " + item.getType().name() + " fehlt bei " + targetChestLocation);
|
|
continue;
|
|
}
|
|
|
|
Chest targetChest = (Chest) targetChestLocation.getBlock().getState();
|
|
Inventory targetInventory = targetChest.getInventory();
|
|
|
|
boolean isValidTarget = false;
|
|
String signOwner = "Unbekannt";
|
|
Block signBlock = null;
|
|
for (Block face : new Block[] {
|
|
targetChest.getBlock().getRelative(1, 0, 0),
|
|
targetChest.getBlock().getRelative(-1, 0, 0),
|
|
targetChest.getBlock().getRelative(0, 0, 1),
|
|
targetChest.getBlock().getRelative(0, 0, -1)
|
|
}) {
|
|
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, targetChest.getBlock())) {
|
|
String[] lines = sign.getLines();
|
|
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
|
|
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
|
|
String line3 = ChatColor.stripColor((String) (lines[3] != null ? lines[3] : ""));
|
|
if (isDebug()) {
|
|
getLogger().fine("Prüfe Zieltruhe-Schild bei " + face.getLocation() + ": Zeile 1='" + line0 + "', Zeile 2='" + line1 + "', Zeile 4='" + line3 + "' für Spieler " + player.getName());
|
|
}
|
|
if (line0.equalsIgnoreCase("[asc]") && line1.equalsIgnoreCase("ziel")) {
|
|
signOwner = line3.isEmpty() ? "Unbekannt" : line3;
|
|
if (line3.equalsIgnoreCase(player.getName())) {
|
|
isValidTarget = true;
|
|
signBlock = face;
|
|
if (isDebug()) {
|
|
getLogger().fine("Gültiges Zieltruhe-Schild gefunden bei " + face.getLocation() + " für Spieler " + player.getName());
|
|
}
|
|
break;
|
|
}
|
|
} else if (isDebug()) {
|
|
getLogger().fine("Zieltruhe-Schild bei " + face.getLocation() + " hat ungültige Zeilen: [asc]=" + line0 + ", ziel=" + line1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!isValidTarget) {
|
|
if (canSendFullChestMessage(playerUUID, item.getType())) {
|
|
player.sendMessage(getMessage("not-your-chest"));
|
|
}
|
|
getLogger().warning("Zieltruhe bei " + targetChestLocation + " gehört nicht Spieler " + player.getName() + " (Besitzer: " + signOwner + ")");
|
|
continue;
|
|
}
|
|
|
|
ItemStack itemToTransfer = item.clone();
|
|
Map<Integer, ItemStack> leftover = targetInventory.addItem(itemToTransfer);
|
|
boolean isFull = isInventoryFull(targetInventory);
|
|
|
|
if (signBlock != null) {
|
|
Sign sign = (Sign) signBlock.getState();
|
|
String[] lines = sign.getLines();
|
|
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
|
|
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
|
|
String line2 = ChatColor.stripColor((String) (lines[2] != null ? lines[2] : ""));
|
|
String line3 = ChatColor.stripColor((String) (lines[3] != null ? lines[3] : ""));
|
|
if (line0.equalsIgnoreCase("[asc]") && line1.equalsIgnoreCase("ziel")) {
|
|
String colorType = isFull ? "full" : "target";
|
|
sign.setLine(0, getSignColor(colorType, "line1") + "[asc]");
|
|
sign.setLine(1, getSignColor(colorType, "line2") + "ziel");
|
|
sign.setLine(2, getSignColor(colorType, "line3") + line2);
|
|
sign.setLine(3, getSignColor(colorType, "line4") + line3);
|
|
sign.update();
|
|
if (isDebug()) {
|
|
getLogger().fine("Zieltruhe-Schild bei " + signBlock.getLocation() + " aktualisiert (voll: " + isFull + ")");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (leftover.isEmpty()) {
|
|
sourceInventory.setItem(slot, null);
|
|
} else {
|
|
if (canSendFullChestMessage(playerUUID, item.getType())) {
|
|
String message = getMessage("target-chest-full")
|
|
.replace("%item%", item.getType().name())
|
|
.replace("%x%", String.valueOf(targetChestLocation.getBlockX()))
|
|
.replace("%y%", String.valueOf(targetChestLocation.getBlockY()))
|
|
.replace("%z%", String.valueOf(targetChestLocation.getBlockZ()));
|
|
player.sendMessage(message);
|
|
}
|
|
for (ItemStack leftoverItem : leftover.values()) {
|
|
if (leftoverItem != null && leftoverItem.getType() == item.getType()) {
|
|
item.setAmount(leftoverItem.getAmount());
|
|
sourceInventory.setItem(slot, item);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void checkInputChests() {
|
|
if (playerData == null) {
|
|
getLogger().warning("playerData ist null. Kann Eingangstruhe nicht prüfen.");
|
|
return;
|
|
}
|
|
if (playerData.getConfigurationSection("players") == null) {
|
|
getLogger().warning("Abschnitt 'players' in players.yml fehlt. Keine Eingangstruhe zu prüfen.");
|
|
return;
|
|
}
|
|
|
|
for (String uuidString : playerData.getConfigurationSection("players").getKeys(false)) {
|
|
UUID ownerUUID;
|
|
try {
|
|
ownerUUID = UUID.fromString(uuidString);
|
|
} catch (IllegalArgumentException e) {
|
|
getLogger().warning("Ungültige UUID in players.yml: " + uuidString);
|
|
continue;
|
|
}
|
|
|
|
String path = "players." + uuidString + ".input-chest";
|
|
if (!playerData.contains(path)) continue;
|
|
|
|
String worldName = playerData.getString(path + ".world");
|
|
World world = getServer().getWorld(worldName);
|
|
if (world == null) {
|
|
getLogger().warning("Welt " + worldName + " für Eingangstruhe von UUID " + uuidString + " nicht gefunden");
|
|
continue;
|
|
}
|
|
|
|
int x = playerData.getInt(path + ".x");
|
|
int y = playerData.getInt(path + ".y");
|
|
int z = playerData.getInt(path + ".z");
|
|
Location location = new Location(world, x, y, z);
|
|
|
|
if (!(location.getBlock().getState() instanceof Chest)) {
|
|
if (isDebug()) {
|
|
getLogger().fine("Eingangstruhe bei " + location + " existiert nicht");
|
|
}
|
|
continue;
|
|
}
|
|
|
|
Chest chest = (Chest) location.getBlock().getState();
|
|
Block inputSignBlock = null;
|
|
boolean isPublic = false;
|
|
String ownerName = "Unknown";
|
|
|
|
// Schild suchen und Status prüfen
|
|
for (Block face : new Block[] {
|
|
chest.getBlock().getRelative(1, 0, 0),
|
|
chest.getBlock().getRelative(-1, 0, 0),
|
|
chest.getBlock().getRelative(0, 0, 1),
|
|
chest.getBlock().getRelative(0, 0, -1)
|
|
}) {
|
|
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, chest.getBlock())) {
|
|
String[] lines = sign.getLines();
|
|
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
|
|
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
|
|
|
|
if (line0.equalsIgnoreCase("[asc]") && line1.equalsIgnoreCase("input")) {
|
|
inputSignBlock = face;
|
|
String line3Raw = lines[3] != null ? lines[3] : "";
|
|
String line3Clean = ChatColor.stripColor(line3Raw);
|
|
|
|
isPublic = line3Clean.toLowerCase().endsWith("[public]");
|
|
ownerName = line3Clean.replace(" [Public]", "").replace(" [public]", "").trim();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (inputSignBlock == null) {
|
|
if (isDebug()) getLogger().fine("Kein Eingangsschild an Truhe bei " + location);
|
|
continue;
|
|
}
|
|
|
|
// Wenn das Inventar leer ist, brauchen wir nichts tun
|
|
boolean hasItems = false;
|
|
for (ItemStack item : chest.getInventory().getContents()) {
|
|
if (item != null && item.getType() != Material.AIR) {
|
|
hasItems = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!hasItems) continue;
|
|
|
|
// Jetzt kommt der entscheidende Teil für die Multiplayer-Funktionalität:
|
|
// Wenn PRIVATE: Nur sortieren, wenn der Owner ONLINE ist.
|
|
// Wenn ÖFFENTLICH: Immer sortieren, aber wir brauchen einen "fiktiven" Player für die Fehlermeldungen
|
|
// oder wir senden Meldungen an alle Online-Spieler, die in der Nähe sind?
|
|
// Der Einfachheit halber: Wenn Öffentlich, sortieren wir stumm oder senden Meldungen an den Owner wenn er online ist.
|
|
|
|
Player ownerPlayer = getServer().getPlayer(ownerUUID);
|
|
|
|
if (!isPublic) {
|
|
// Privat: Nur wenn Owner online
|
|
if (ownerPlayer == null || !ownerPlayer.isOnline()) continue;
|
|
} else {
|
|
// Öffentlich: Wenn Owner offline, können wir keine "Truhe voll" Nachrichten an den Owner senden.
|
|
// Wir sortieren trotzdem.
|
|
// Wir setzen ownerPlayer auf null, damit distributeItems weiß, dass niemand Besitzer ist (für Messages).
|
|
}
|
|
|
|
// Wir rufen distributeItems auf.
|
|
// WICHTIG: distributeItems nutzt `player.getUniqueId()` um die Zieltruhen zu finden.
|
|
// Das funktioniert auch, wenn ownerPlayer null ist, solange wir die UUID übergeben.
|
|
// Wir müssen aber aufpassen, dass `distributeItems` nicht crasht, wenn player null ist.
|
|
|
|
distributeItemsForOwner(ownerUUID, ownerPlayer, chest.getInventory());
|
|
}
|
|
}
|
|
|
|
// 4. KORRIGIERTE distributeItemsForOwner Methode:
|
|
private void distributeItemsForOwner(UUID ownerUUID, Player ownerPlayer, Inventory sourceInventory) {
|
|
boolean hasItems = false;
|
|
for (ItemStack item : sourceInventory.getContents()) {
|
|
if (item != null && item.getType() != Material.AIR) {
|
|
hasItems = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!hasItems) return;
|
|
|
|
// Owner-Name ermitteln
|
|
String ownerName = "Unknown";
|
|
if (ownerPlayer != null) {
|
|
ownerName = ownerPlayer.getName();
|
|
} else {
|
|
// Offline-Namen aus PlayerData holen wenn möglich
|
|
org.bukkit.OfflinePlayer offlinePlayer = getServer().getOfflinePlayer(ownerUUID);
|
|
if (offlinePlayer.hasPlayedBefore()) {
|
|
ownerName = offlinePlayer.getName();
|
|
}
|
|
}
|
|
|
|
for (int slot = 0; slot < sourceInventory.getSize(); slot++) {
|
|
ItemStack item = sourceInventory.getItem(slot);
|
|
if (item == null || item.getType() == Material.AIR) continue;
|
|
|
|
Location targetChestLocation = getTargetChestLocation(ownerUUID, item.getType());
|
|
if (targetChestLocation == null) continue;
|
|
|
|
if (!(targetChestLocation.getBlock().getState() instanceof Chest)) {
|
|
if (ownerPlayer != null && canSendFullChestMessage(ownerUUID, item.getType())) {
|
|
ownerPlayer.sendMessage(getMessage("target-chest-missing").replace("%item%", item.getType().name()));
|
|
}
|
|
playerData.set("players." + ownerUUID + ".target-chests." + item.getType().name(), null);
|
|
savePlayerData();
|
|
continue;
|
|
}
|
|
|
|
Chest targetChest = (Chest) targetChestLocation.getBlock().getState();
|
|
Inventory targetInventory = targetChest.getInventory();
|
|
|
|
boolean isValidTarget = false;
|
|
Block signBlock = null;
|
|
|
|
for (Block face : new Block[] {
|
|
targetChest.getBlock().getRelative(1, 0, 0),
|
|
targetChest.getBlock().getRelative(-1, 0, 0),
|
|
targetChest.getBlock().getRelative(0, 0, 1),
|
|
targetChest.getBlock().getRelative(0, 0, -1)
|
|
}) {
|
|
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, targetChest.getBlock())) {
|
|
String[] lines = sign.getLines();
|
|
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
|
|
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
|
|
String line3Clean = ChatColor.stripColor((String) (lines[3] != null ? lines[3] : ""));
|
|
|
|
String signOwnerName = line3Clean.replace("[Public]", "").replace("[public]", "").trim();
|
|
|
|
if (line0.equalsIgnoreCase("[asc]") && line1.equalsIgnoreCase("ziel")) {
|
|
if (signOwnerName.equalsIgnoreCase(ownerName) || signOwnerName.equalsIgnoreCase("Unknown")) {
|
|
isValidTarget = true;
|
|
signBlock = face;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!isValidTarget) continue;
|
|
|
|
ItemStack itemToTransfer = item.clone();
|
|
Map<Integer, ItemStack> leftover = targetInventory.addItem(itemToTransfer);
|
|
boolean isFull = isInventoryFull(targetInventory);
|
|
|
|
if (signBlock != null) {
|
|
Sign sign = (Sign) signBlock.getState();
|
|
String[] lines = sign.getLines();
|
|
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
|
|
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
|
|
String line2 = ChatColor.stripColor((String) (lines[2] != null ? lines[2] : ""));
|
|
String line3Raw = lines[3] != null ? lines[3] : "";
|
|
|
|
if (line0.equalsIgnoreCase("[asc]") && line1.equalsIgnoreCase("ziel")) {
|
|
String colorType = isFull ? "full" : "target";
|
|
sign.setLine(0, getSignColor(colorType, "line1") + "[asc]");
|
|
sign.setLine(1, getSignColor(colorType, "line2") + "ziel");
|
|
sign.setLine(2, getSignColor(colorType, "line3") + line2);
|
|
sign.setLine(3, line3Raw);
|
|
sign.update();
|
|
}
|
|
}
|
|
|
|
if (leftover.isEmpty()) {
|
|
sourceInventory.setItem(slot, null);
|
|
} else {
|
|
if (ownerPlayer != null && canSendFullChestMessage(ownerUUID, item.getType())) {
|
|
String message = getMessage("target-chest-full")
|
|
.replace("%item%", item.getType().name())
|
|
.replace("%x%", String.valueOf(targetChestLocation.getBlockX()))
|
|
.replace("%y%", String.valueOf(targetChestLocation.getBlockY()))
|
|
.replace("%z%", String.valueOf(targetChestLocation.getBlockZ()));
|
|
ownerPlayer.sendMessage(message);
|
|
}
|
|
for (ItemStack leftoverItem : leftover.values()) {
|
|
if (leftoverItem != null && leftoverItem.getType() == item.getType()) {
|
|
item.setAmount(leftoverItem.getAmount());
|
|
sourceInventory.setItem(slot, item);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |