diff --git a/src/main/java/viper/ButtonControl.java b/src/main/java/viper/ButtonControl.java new file mode 100644 index 0000000..26bd490 --- /dev/null +++ b/src/main/java/viper/ButtonControl.java @@ -0,0 +1,136 @@ +package viper; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.data.Lightable; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.ShapedRecipe; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.List; + +public class ButtonControl extends JavaPlugin { + private ConfigManager configManager; + private DataManager dataManager; + + @Override + public void onEnable() { + configManager = new ConfigManager(this); + dataManager = new DataManager(this); + + getServer().getPluginManager().registerEvents(new ButtonListener(this, configManager, dataManager), this); + + registerRecipes(); + + // Scheduler zum Prüfen der Tageslichtsensoren alle 10 Sekunden (20 Ticks = 1 Sekunde) + getServer().getScheduler().runTaskTimer(this, this::checkDaylightSensors, 0L, 20L * 10); + } + + private void registerRecipes() { + ItemStack controlButton = new ItemStack(Material.STONE_BUTTON); + ItemMeta buttonMeta = controlButton.getItemMeta(); + buttonMeta.setDisplayName("§6Steuer-Button"); + controlButton.setItemMeta(buttonMeta); + + NamespacedKey buttonKey = new NamespacedKey(this, "control_button"); + ShapedRecipe buttonRecipe = new ShapedRecipe(buttonKey, controlButton); + buttonRecipe.shape("123", "456", "789"); + buttonRecipe.setIngredient('2', Material.STONE_BUTTON); + buttonRecipe.setIngredient('5', Material.STONE_BUTTON); + buttonRecipe.setIngredient('8', Material.STONE_BUTTON); + Bukkit.addRecipe(buttonRecipe); + + ItemStack controlDaylight = new ItemStack(Material.DAYLIGHT_DETECTOR); + ItemMeta daylightMeta = controlDaylight.getItemMeta(); + daylightMeta.setDisplayName("§6Steuer-Tageslichtsensor"); + controlDaylight.setItemMeta(daylightMeta); + + NamespacedKey daylightKey = new NamespacedKey(this, "control_daylight"); + ShapedRecipe daylightRecipe = new ShapedRecipe(daylightKey, controlDaylight); + daylightRecipe.shape("123", "456", "789"); + daylightRecipe.setIngredient('2', Material.DAYLIGHT_DETECTOR); + daylightRecipe.setIngredient('5', Material.DAYLIGHT_DETECTOR); + daylightRecipe.setIngredient('8', Material.DAYLIGHT_DETECTOR); + Bukkit.addRecipe(daylightRecipe); + } + + // Prüft alle platzierten Tageslichtsensoren und schaltet Lampen bei Tag aus und bei Nacht an + public void checkDaylightSensors() { + List allControllers = dataManager.getAllPlacedControllers(); + for (String controllerLoc : allControllers) { + String buttonId = dataManager.getButtonIdForPlacedController(controllerLoc); + if (buttonId == null) continue; + + String[] parts = controllerLoc.split(","); + if (parts.length != 4) continue; + + World world = getServer().getWorld(parts[0]); + if (world == null) continue; + + Location loc = new Location(world, + Integer.parseInt(parts[1]), + Integer.parseInt(parts[2]), + Integer.parseInt(parts[3])); + + Block block = loc.getBlock(); + if (block.getType() != Material.DAYLIGHT_DETECTOR) continue; + + long time = loc.getWorld().getTime(); + boolean isDay = time >= 0 && time < 13000; + + List connectedBlocks = dataManager.getConnectedBlocks(buttonId); + if (connectedBlocks == null) continue; + + for (String targetLocStr : connectedBlocks) { + String[] targetParts = targetLocStr.split(","); + if (targetParts.length != 4) continue; + + World targetWorld = getServer().getWorld(targetParts[0]); + if (targetWorld == null) continue; + + Location targetLoc = new Location(targetWorld, + Integer.parseInt(targetParts[1]), + Integer.parseInt(targetParts[2]), + Integer.parseInt(targetParts[3])); + + Block targetBlock = targetLoc.getBlock(); + + if (targetBlock.getType() == Material.REDSTONE_LAMP) { + Lightable lamp = (Lightable) targetBlock.getBlockData(); + lamp.setLit(!isDay); + targetBlock.setBlockData(lamp); + } + } + } + } + + // Befehlsverarbeitung + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (command.getName().equalsIgnoreCase("bc") && args.length > 0 && args[0].equalsIgnoreCase("info")) { + sender.sendMessage("§6[ButtonControl] §7Informationen zum Plugin:"); + sender.sendMessage("§eVersion: §f" + getDescription().getVersion()); + sender.sendMessage("§eErsteller: §fM_Viper"); + sender.sendMessage("§ePlugin: §fButtonControl"); + sender.sendMessage("§eGetestet für Minecraft: §f1.21.5 - 1.21.8"); + sender.sendMessage("§eWeitere Infos: §fTüren & Lampen mit Buttons oder Tageslichtsensoren steuern"); + return true; + } + return false; + } + + public ConfigManager getConfigManager() { + return configManager; + } + + public DataManager getDataManager() { + return dataManager; + } +} diff --git a/src/main/java/viper/ButtonListener.java b/src/main/java/viper/ButtonListener.java new file mode 100644 index 0000000..6cccdae --- /dev/null +++ b/src/main/java/viper/ButtonListener.java @@ -0,0 +1,215 @@ +package viper; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.data.type.Door; +import org.bukkit.block.data.Lightable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class ButtonListener implements Listener { + private final ButtonControl plugin; + private final ConfigManager configManager; + private final DataManager dataManager; + + public ButtonListener(ButtonControl plugin, ConfigManager configManager, DataManager dataManager) { + this.plugin = plugin; + this.configManager = configManager; + this.dataManager = dataManager; + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + String playerUUID = event.getPlayer().getUniqueId().toString(); + + ItemStack item = event.getItem(); + Block block = event.getClickedBlock(); + + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && block != null && + (block.getType() == Material.STONE_BUTTON || block.getType() == Material.DAYLIGHT_DETECTOR)) { + + String blockLocation = block.getWorld().getName() + "," + block.getX() + "," + block.getY() + "," + block.getZ(); + String buttonId = dataManager.getButtonIdForPlacedController(playerUUID, blockLocation); + + if (buttonId != null) { + event.setCancelled(true); + List connectedBlocks = dataManager.getConnectedBlocks(playerUUID, buttonId); + if (connectedBlocks != null && !connectedBlocks.isEmpty()) { + + boolean anyDoorOpened = false; + boolean anyDoorClosed = false; + boolean anyLampOn = false; + boolean anyLampOff = false; + + for (String loc : connectedBlocks) { + String[] parts = loc.split(","); + Location location = new Location(plugin.getServer().getWorld(parts[0]), + Integer.parseInt(parts[1]), + Integer.parseInt(parts[2]), + Integer.parseInt(parts[3])); + Block targetBlock = location.getBlock(); + if (isDoor(targetBlock.getType())) { + Door door = (Door) targetBlock.getBlockData(); + boolean wasOpen = door.isOpen(); + door.setOpen(!wasOpen); + targetBlock.setBlockData(door); + + if (!wasOpen) { + anyDoorOpened = true; + } else { + anyDoorClosed = true; + } + } else if (targetBlock.getType() == Material.REDSTONE_LAMP) { + Lightable lamp = (Lightable) targetBlock.getBlockData(); + boolean wasLit = lamp.isLit(); + lamp.setLit(!wasLit); + targetBlock.setBlockData(lamp); + + if (!wasLit) { + anyLampOn = true; + } else { + anyLampOff = true; + } + } + } + + if (anyDoorOpened) { + event.getPlayer().sendMessage(configManager.getMessage("doors-open")); + } + if (anyDoorClosed) { + event.getPlayer().sendMessage(configManager.getMessage("doors-closed")); + } + if (anyLampOn) { + event.getPlayer().sendMessage(configManager.getMessage("lamps-on")); + } + if (anyLampOff) { + event.getPlayer().sendMessage(configManager.getMessage("lamps-off")); + } + + } else { + event.getPlayer().sendMessage(configManager.getMessage("no-blocks-connected")); + } + } + return; + } + + if (item == null || (!item.getType().equals(Material.STONE_BUTTON) && !item.getType().equals(Material.DAYLIGHT_DETECTOR))) { + return; + } + + if (!item.hasItemMeta() || !item.getItemMeta().getDisplayName().contains("§6Steuer-")) { + return; + } + + if (event.getAction() != Action.RIGHT_CLICK_BLOCK || block == null) { + return; + } + + if (isDoor(block.getType()) || block.getType() == Material.REDSTONE_LAMP) { + event.setCancelled(true); + + String buttonId = item.getItemMeta().hasLore() ? item.getItemMeta().getLore().get(0) : UUID.randomUUID().toString(); + List connectedBlocks = dataManager.getConnectedBlocks(playerUUID, buttonId); + if (connectedBlocks == null) { + connectedBlocks = new ArrayList<>(); + } + + int maxDoors = configManager.getMaxDoors(); + int maxLamps = configManager.getMaxLamps(); + int doorCount = (int) connectedBlocks.stream().filter(loc -> isDoor(getMaterialFromLocation(loc))).count(); + int lampCount = (int) connectedBlocks.stream().filter(loc -> getMaterialFromLocation(loc) == Material.REDSTONE_LAMP).count(); + + if (isDoor(block.getType()) && doorCount >= maxDoors) { + event.getPlayer().sendMessage(configManager.getMessage("max-doors-reached")); + return; + } + if (block.getType() == Material.REDSTONE_LAMP && lampCount >= maxLamps) { + event.getPlayer().sendMessage(configManager.getMessage("max-lamps-reached")); + return; + } + + String blockLocation = block.getWorld().getName() + "," + block.getX() + "," + block.getY() + "," + block.getZ(); + if (!connectedBlocks.contains(blockLocation)) { + connectedBlocks.add(blockLocation); + dataManager.setConnectedBlocks(playerUUID, buttonId, connectedBlocks); + updateButtonLore(item, buttonId); + event.getPlayer().sendMessage(configManager.getMessage("block-connected")); + } else { + event.getPlayer().sendMessage(configManager.getMessage("block-already-connected")); + } + } + } + + @EventHandler + public void onBlockPlace(BlockPlaceEvent event) { + String playerUUID = event.getPlayer().getUniqueId().toString(); + + ItemStack item = event.getItemInHand(); + Block block = event.getBlockPlaced(); + + if (item == null || (!item.getType().equals(Material.STONE_BUTTON) && !item.getType().equals(Material.DAYLIGHT_DETECTOR))) { + return; + } + + if (!item.hasItemMeta() || !item.getItemMeta().getDisplayName().contains("§6Steuer-")) { + return; + } + + String buttonId = item.getItemMeta().hasLore() ? item.getItemMeta().getLore().get(0) : UUID.randomUUID().toString(); + String blockLocation = block.getWorld().getName() + "," + block.getX() + "," + block.getY() + "," + block.getZ(); + dataManager.addPlacedController(playerUUID, blockLocation, buttonId); + event.getPlayer().sendMessage(configManager.getMessage("controller-placed")); + } + + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + String playerUUID = event.getPlayer().getUniqueId().toString(); + + Block block = event.getBlock(); + String blockLocation = block.getWorld().getName() + "," + block.getX() + "," + block.getY() + "," + block.getZ(); + String buttonId = dataManager.getButtonIdForPlacedController(playerUUID, blockLocation); + + if (buttonId != null) { + dataManager.removePlacedController(playerUUID, blockLocation); + dataManager.setConnectedBlocks(playerUUID, buttonId, null); + event.getPlayer().sendMessage(configManager.getMessage("controller-removed")); + } + } + + private boolean isDoor(Material material) { + return material.toString().endsWith("_DOOR"); + } + + private Material getMaterialFromLocation(String locString) { + String[] parts = locString.split(","); + if (parts.length != 4) return null; + Location loc = new Location(plugin.getServer().getWorld(parts[0]), + Integer.parseInt(parts[1]), + Integer.parseInt(parts[2]), + Integer.parseInt(parts[3])); + return loc.getBlock().getType(); + } + + private void updateButtonLore(ItemStack item, String buttonId) { + ItemMeta meta = item.getItemMeta(); + if (meta != null) { + List lore = meta.hasLore() ? meta.getLore() : new ArrayList<>(); + if (!lore.contains(buttonId)) { + lore.add(buttonId); + meta.setLore(lore); + item.setItemMeta(meta); + } + } + } +} diff --git a/src/main/java/viper/ConfigManager.java b/src/main/java/viper/ConfigManager.java new file mode 100644 index 0000000..3de3023 --- /dev/null +++ b/src/main/java/viper/ConfigManager.java @@ -0,0 +1,65 @@ +package viper; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; + +public class ConfigManager { + private final ButtonControl plugin; + private FileConfiguration config; + private FileConfiguration lang; + private File configFile; + private File langFile; + + public ConfigManager(ButtonControl plugin) { + this.plugin = plugin; + loadConfig(); + loadLang(); + } + + private void loadConfig() { + configFile = new File(plugin.getDataFolder(), "config.yml"); + if (!configFile.exists()) { + plugin.saveResource("config.yml", false); + } + config = YamlConfiguration.loadConfiguration(configFile); + } + + private void loadLang() { + langFile = new File(plugin.getDataFolder(), "lang.yml"); + if (!langFile.exists()) { + plugin.saveResource("lang.yml", false); + } + lang = YamlConfiguration.loadConfiguration(langFile); + } + + public int getMaxDoors() { + return config.getInt("max-doors", 20); + } + + public int getMaxLamps() { + return config.getInt("max-lamps", 50); + } + + public String getMessage(String key) { + return lang.getString(key, "Nachricht nicht gefunden: " + key); + } + + public void saveConfig() { + try { + config.save(configFile); + } catch (IOException e) { + plugin.getLogger().severe("Konnte config.yml nicht speichern: " + e.getMessage()); + } + } + + public void saveLang() { + try { + lang.save(langFile); + } catch (IOException e) { + plugin.getLogger().severe("Konnte lang.yml nicht speichern: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/viper/DataManager.java b/src/main/java/viper/DataManager.java new file mode 100644 index 0000000..54264ed --- /dev/null +++ b/src/main/java/viper/DataManager.java @@ -0,0 +1,118 @@ +package viper; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class DataManager { + private final ButtonControl plugin; + private FileConfiguration data; + private File dataFile; + + public DataManager(ButtonControl plugin) { + this.plugin = plugin; + loadData(); + } + + private void loadData() { + dataFile = new File(plugin.getDataFolder(), "data.yml"); + if (!dataFile.exists()) { + plugin.saveResource("data.yml", false); + } + data = YamlConfiguration.loadConfiguration(dataFile); + } + + // --- Spielerbasierte Methoden --- + + public List getConnectedBlocks(String playerUUID, String buttonId) { + return data.getStringList("players." + playerUUID + ".buttons." + buttonId); + } + + public void setConnectedBlocks(String playerUUID, String buttonId, List blocks) { + data.set("players." + playerUUID + ".buttons." + buttonId, blocks); + saveData(); + } + + public void addPlacedController(String playerUUID, String location, String buttonId) { + data.set("players." + playerUUID + ".placed-controllers." + location, buttonId); + saveData(); + } + + public String getButtonIdForPlacedController(String playerUUID, String location) { + return data.getString("players." + playerUUID + ".placed-controllers." + location); + } + + public void removePlacedController(String playerUUID, String location) { + data.set("players." + playerUUID + ".placed-controllers." + location, null); + saveData(); + } + + public List getAllPlacedControllers(String playerUUID) { + if (data.getConfigurationSection("players." + playerUUID + ".placed-controllers") == null) { + return new ArrayList<>(); + } + Set keys = data.getConfigurationSection("players." + playerUUID + ".placed-controllers").getKeys(false); + return new ArrayList<>(keys); + } + + // --- Neue globale Methoden für Tageslichtsensoren etc. --- + + /** + * Gibt alle Controller-Orte aller Spieler zurück (global). + * Nützlich für Tageslichtsensoren. + */ + public List getAllPlacedControllers() { + List allControllers = new ArrayList<>(); + if (data.getConfigurationSection("players") == null) { + return allControllers; + } + Set players = data.getConfigurationSection("players").getKeys(false); + for (String playerUUID : players) { + allControllers.addAll(getAllPlacedControllers(playerUUID)); + } + return allControllers; + } + + /** + * Holt die Button-ID für einen platzierten Controller an einem Ort, ohne Spieler-UUID (global). + * Da Controller pro Spieler gespeichert sind, suchen wir alle Spieler ab. + */ + public String getButtonIdForPlacedController(String location) { + if (data.getConfigurationSection("players") == null) return null; + Set players = data.getConfigurationSection("players").getKeys(false); + for (String playerUUID : players) { + String buttonId = getButtonIdForPlacedController(playerUUID, location); + if (buttonId != null) return buttonId; + } + return null; + } + + /** + * Holt die verbundenen Blöcke für eine Button-ID (global). + * Da die verbundenen Blöcke pro Spieler gespeichert sind, suchen wir alle Spieler ab. + */ + public List getConnectedBlocks(String buttonId) { + if (data.getConfigurationSection("players") == null) return null; + Set players = data.getConfigurationSection("players").getKeys(false); + for (String playerUUID : players) { + List connected = getConnectedBlocks(playerUUID, buttonId); + if (connected != null && !connected.isEmpty()) { + return connected; + } + } + return null; + } + + public void saveData() { + try { + data.save(dataFile); + } catch (IOException e) { + plugin.getLogger().severe("Konnte data.yml nicht speichern: " + e.getMessage()); + } + } +}