diff --git a/src/main/java/dev/viper/weathertime/WeatherTimeSyncPlugin.java b/src/main/java/dev/viper/weathertime/WeatherTimeSyncPlugin.java index ac431ec..7ed4f9d 100644 --- a/src/main/java/dev/viper/weathertime/WeatherTimeSyncPlugin.java +++ b/src/main/java/dev/viper/weathertime/WeatherTimeSyncPlugin.java @@ -1,729 +1,87 @@ package dev.viper.weathertime; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.platform.bukkit.BukkitAudiences; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.command.*; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.scheduler.BukkitRunnable; -import org.json.JSONArray; -import org.json.JSONObject; - -import java.io.File; -import java.io.IOException; -import java.time.Instant; -import java.time.ZoneId; import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.*; -public class WeatherTimeSyncPlugin extends JavaPlugin implements Listener { +/** + * Zentrale Datenklasse für Wetter- und Zeitinformationen. + * Erweiterung: enthält jetzt auch Luftfeuchtigkeit, Windgeschwindigkeit und Sonnenauf/untergang. + */ +public class WeatherTimeData { - private String apiKey; - private int updateInterval; - private final Map worldConfigs = new HashMap<>(); - private final Map worldWeatherData = new HashMap<>(); - private final Map> playersWithDisplay = new HashMap<>(); - private final Map playerLocations = new HashMap<>(); - private final Map playerGUIs = new HashMap<>(); - private BukkitAudiences audiences; - private BukkitRunnable weatherUpdateTask; - private BukkitRunnable syncTask; - private final Set processedLocations = new HashSet<>(); - private FileConfiguration langConfig; + private final ZonedDateTime dateTime; // Lokale Zeit am Standort + private final String weatherMain; // Hauptwetterbeschreibung (z. B. "Clear", "Rain") + private final double tempCelsius; // Temperatur in °C - @Override - public void onEnable() { - saveDefaultConfig(); - loadLanguageConfig(); - loadConfig(); - audiences = BukkitAudiences.create(this); + private final int humidity; // Luftfeuchtigkeit in % + private final double windSpeed; // Windgeschwindigkeit (m/s oder mph) + private final ZonedDateTime sunrise; // Sonnenaufgang + private final ZonedDateTime sunset; // Sonnenuntergang - Objects.requireNonNull(getCommand("wetter")).setExecutor(new WetterCommand()); - Objects.requireNonNull(getCommand("weatherforecast")).setExecutor(new WeatherForecastCommand()); - Objects.requireNonNull(getCommand("toggleweather")).setExecutor(new ToggleWeatherCommand()); - - getServer().getPluginManager().registerEvents(this, this); - - setDoDaylightCycleForWorlds(); - startWeatherUpdateTask(); - startSyncTask(); - initializePlayerDisplays(); + public WeatherTimeData( + ZonedDateTime dateTime, + String weatherMain, + double tempCelsius, + int humidity, + double windSpeed, + ZonedDateTime sunrise, + ZonedDateTime sunset) { + this.dateTime = dateTime; + this.weatherMain = weatherMain; + this.tempCelsius = tempCelsius; + this.humidity = humidity; + this.windSpeed = windSpeed; + this.sunrise = sunrise; + this.sunset = sunset; } - @Override - public void onDisable() { - if (weatherUpdateTask != null) weatherUpdateTask.cancel(); - if (syncTask != null) syncTask.cancel(); - if (audiences != null) audiences.close(); - for (Player player : Bukkit.getOnlinePlayers()) { - if (playerGUIs.containsKey(player.getUniqueId())) player.closeInventory(); + public ZonedDateTime getDateTime() { + return dateTime; + } + + public String getWeatherMain() { + return weatherMain; + } + + public double getTemp(String unit) { + return "F".equalsIgnoreCase(unit) + ? (tempCelsius * 9 / 5) + 32 + : tempCelsius; + } + + public int getHumidity() { + return humidity; + } + + public double getWindSpeed() { + return windSpeed; + } + + public ZonedDateTime getSunrise() { + return sunrise; + } + + public ZonedDateTime getSunset() { + return sunset; + } + + public String getFormattedTime(String format) { + int hour = dateTime.getHour(); + int minute = dateTime.getMinute(); + if ("12h".equalsIgnoreCase(format)) { + String ampm = hour >= 12 ? "PM" : "AM"; + hour = hour % 12; + if (hour == 0) hour = 12; + return String.format("%02d:%02d %s", hour, minute, ampm); } + return String.format("%02d:%02d", hour, minute); } - // =============== Config & Sprache =============== - private void loadConfig() { - FileConfiguration cfg = getConfig(); - apiKey = cfg.getString("api-key", "").trim(); - updateInterval = cfg.getInt("update-interval", 60); - worldConfigs.clear(); - - WorldConfig defaultConfig = new WorldConfig( - cfg.getBoolean("defaults.enabled", true), - cfg.getString("defaults.location", "Berlin,de"), - cfg.getString("defaults.units", "metric"), - cfg.getString("defaults.time-format", "24h"), - cfg.getBoolean("defaults.display-actionbar", true), - cfg.getBoolean("defaults.display-weather-icon", true), - cfg.getString("defaults.display-position", "top-right"), - cfg.getInt("defaults.padding-right", 100), - cfg.getBoolean("defaults.sync-in-game-weather", true) - ); - worldConfigs.put("defaults", defaultConfig); - - if (cfg.isConfigurationSection("worlds")) { - for (String worldName : cfg.getConfigurationSection("worlds").getKeys(false)) { - WorldConfig worldConfig = new WorldConfig( - cfg.getBoolean("worlds." + worldName + ".enabled", defaultConfig.enabled), - cfg.getString("worlds." + worldName + ".location", defaultConfig.location), - cfg.getString("worlds." + worldName + ".units", defaultConfig.units), - cfg.getString("worlds." + worldName + ".time-format", defaultConfig.timeFormat), - cfg.getBoolean("worlds." + worldName + ".display-actionbar", defaultConfig.displayActionbar), - cfg.getBoolean("worlds." + worldName + ".display-weather-icon", defaultConfig.displayWeatherIcon), - cfg.getString("worlds." + worldName + ".display-position", defaultConfig.displayPosition), - cfg.getInt("worlds." + worldName + ".padding-right", defaultConfig.paddingRight), - cfg.getBoolean("worlds." + worldName + ".sync-in-game-weather", defaultConfig.syncInGameWeather) - ); - worldConfigs.put(worldName, worldConfig); - } - } - if (apiKey.isEmpty()) { - getLogger().severe("API-Key ist nicht gesetzt! Bitte in config.yml eintragen."); - } - } - - private void loadLanguageConfig() { - File langFile = new File(getDataFolder(), "lang.yml"); - try { - langConfig = YamlConfiguration.loadConfiguration(langFile); - if (!langFile.exists()) { - saveResource("lang.yml", false); - langConfig = YamlConfiguration.loadConfiguration(langFile); - } else if (langConfig.getConfigurationSection("languages") == null) { - saveResource("lang.yml", true); - langConfig = YamlConfiguration.loadConfiguration(langFile); - } - } catch (Exception e) { - saveResource("lang.yml", true); - langConfig = YamlConfiguration.loadConfiguration(langFile); - } - } - - private void setDoDaylightCycleForWorlds() { - for (World world : Bukkit.getWorlds()) { - WorldConfig config = worldConfigs.getOrDefault(world.getName(), worldConfigs.get("defaults")); - if (config.enabled) world.setGameRuleValue("doDaylightCycle", "false"); - } - } - - private void initializePlayerDisplays() { - playersWithDisplay.clear(); - for (Player player : Bukkit.getOnlinePlayers()) { - Set worlds = new HashSet<>(); - for (World world : Bukkit.getWorlds()) { - WorldConfig config = worldConfigs.getOrDefault(world.getName(), worldConfigs.get("defaults")); - if (config.enabled && config.displayActionbar) worlds.add(world.getName()); - } - playersWithDisplay.put(player.getUniqueId(), worlds); - } - } - - private void startWeatherUpdateTask() { - weatherUpdateTask = new BukkitRunnable() { - @Override - public void run() { - processedLocations.clear(); - updateWeatherDataForAllWorlds(); - } - }; - weatherUpdateTask.runTaskTimerAsynchronously(this, 0L, updateInterval * 20L); - } - - private void startSyncTask() { - syncTask = new BukkitRunnable() { - @Override - public void run() { - for (World world : Bukkit.getWorlds()) { - WorldConfig config = worldConfigs.getOrDefault(world.getName(), worldConfigs.get("defaults")); - if (!config.enabled) continue; - WeatherTimeData data = worldWeatherData.get(world.getName()); - if (data != null) { - syncMinecraftTime(world, data.getDateTime()); - updateActionbarForWorld(world, data); - } - } - } - }; - syncTask.runTaskTimer(this, 0L, 20L); - } - - private void updateWeatherDataForAllWorlds() { - for (World world : Bukkit.getWorlds()) { - WorldConfig config = worldConfigs.getOrDefault(world.getName(), worldConfigs.get("defaults")); - if (!config.enabled) { - worldWeatherData.remove(world.getName()); - continue; - } - if (processedLocations.contains(config.location)) { - for (String otherWorld : worldWeatherData.keySet()) { - WorldConfig otherConfig = worldConfigs.getOrDefault(otherWorld, worldConfigs.get("defaults")); - if (otherConfig.location.equals(config.location)) { - WeatherTimeData existingData = worldWeatherData.get(otherWorld); - if (existingData != null) { - worldWeatherData.put(world.getName(), existingData); - break; - } - } - } - continue; - } - try { - WeatherFetcher fetcher = new WeatherFetcher(apiKey, config.location, config.units, getLogger()); - WeatherTimeData weatherData = fetcher.fetchAsWeatherTimeData(); - worldWeatherData.put(world.getName(), weatherData); - processedLocations.add(config.location); - - new BukkitRunnable() { - @Override - public void run() { - syncMinecraftTime(world, weatherData.getDateTime()); - if (config.syncInGameWeather) { - switch (weatherData.getWeatherMain().toLowerCase()) { - case "rain": - case "drizzle": - world.setStorm(true); - world.setThundering(false); - break; - case "thunderstorm": - world.setStorm(true); - world.setThundering(true); - break; - case "snow": - world.setStorm(true); - world.setThundering(false); - break; - default: - world.setStorm(false); - world.setThundering(false); - } - } - } - }.runTask(this); - } catch (Exception e) { - getLogger().warning("Fehler beim Abrufen von Wetter/Zeit für Welt " + world.getName() + ": " + e.getMessage()); - } - } - } - - private void syncMinecraftTime(World world, ZonedDateTime dateTime) { + public long toMinecraftTime() { int hour = dateTime.getHour(); int minute = dateTime.getMinute(); int second = dateTime.getSecond(); - int minecraftTime = ((hour + 18) % 24) * 1000 + (minute * 1000 / 60) + (second * 1000 / 3600); - world.setTime(minecraftTime); - world.setGameRuleValue("doDaylightCycle", "false"); - } - - // === Anzeige (Actionbar, jetzt mit Luftfeuchtigkeit, Wind, Sonne) === - private void updateActionbarForWorld(World world, WeatherTimeData data) { - WorldConfig config = worldConfigs.getOrDefault(world.getName(), worldConfigs.get("defaults")); - if (!config.enabled || !config.displayActionbar) return; - - for (Player player : world.getPlayers()) { - if (!playersWithDisplay.getOrDefault(player.getUniqueId(), new HashSet<>()).contains(world.getName())) - continue; - - WeatherTimeData playerData = data; - String location = playerLocations.getOrDefault(player.getUniqueId(), ""); - if (!location.isEmpty()) { - try { - WeatherFetcher fetcher = new WeatherFetcher(apiKey, location, config.units, getLogger()); - playerData = fetcher.fetchAsWeatherTimeData(); - } catch (Exception e) { - String countryCode = getCountryCode(config.location); - audiences.player(player).sendMessage(Component.text( - getLocalizedMessage("forecast_error", countryCode, - "location", location, - "error", e.getMessage()), - NamedTextColor.RED)); - continue; - } - } - - String dateStr = playerData.getDateTime().format(DateTimeFormatter.ofPattern("dd.MM.yyyy")); - String timeStr = playerData.getFormattedTime(config.timeFormat); - String tempUnit = config.units.equalsIgnoreCase("metric") ? "°C" : "°F"; - String weatherIcon = config.displayWeatherIcon ? getWeatherSymbol(playerData.getWeatherMain()) + " " : ""; - String tempStr = String.format("%.1f%s", playerData.getTemp(config.units.equalsIgnoreCase("metric") ? "C" : "F"), tempUnit); - - String humidityStr = "💧 " + playerData.getHumidity() + "%"; - String windStr = "🌬️ " + String.format("%.1f", playerData.getWindSpeed()) + (config.units.equalsIgnoreCase("metric") ? " m/s" : " mph"); - String sunriseStr = "🌅 " + playerData.getSunrise().format(DateTimeFormatter.ofPattern("HH:mm")); - String sunsetStr = "🌇 " + playerData.getSunset().format(DateTimeFormatter.ofPattern("HH:mm")); - - Component message = Component.text() - .append(Component.text(dateStr + " ", NamedTextColor.AQUA, TextDecoration.BOLD)) - .append(Component.text("| " + timeStr + " ", NamedTextColor.YELLOW)) - .append(Component.text("| " + weatherIcon, NamedTextColor.WHITE)) - .append(Component.text("| " + tempStr + " ", NamedTextColor.GREEN)) - .append(Component.text("| " + humidityStr + " ", NamedTextColor.AQUA)) - .append(Component.text("| " + windStr + " ", NamedTextColor.GRAY)) - .append(Component.text("| " + sunriseStr + " ", NamedTextColor.GOLD)) - .append(Component.text("| " + sunsetStr, NamedTextColor.DARK_RED)) - .build(); - - audiences.player(player).sendActionBar(message); - } - } - - // === Events (z.B. Weltwechsel) === - @EventHandler - public void onPlayerChangedWorld(PlayerChangedWorldEvent event) { - Player player = event.getPlayer(); - World world = player.getWorld(); - WorldConfig config = worldConfigs.getOrDefault(world.getName(), worldConfigs.get("defaults")); - if (!config.enabled) return; - WeatherTimeData data = worldWeatherData.get(world.getName()); - if (data == null) return; - String countryCode = getCountryCode(config.location); - String localizedWeather = getLocalizedWeatherMain(data.getWeatherMain(), countryCode); - String tempUnit = config.units.equalsIgnoreCase("metric") ? "°C" : "°F"; - String city = config.location.split(",")[0]; - String message = String.format("%s: %s, %.1f%s", city, localizedWeather, data.getTemp(config.units.equalsIgnoreCase("metric") ? "C" : "F"), tempUnit); - audiences.player(player).sendActionBar(Component.text(message, NamedTextColor.GREEN)); - } - - @EventHandler - public void onInventoryClick(InventoryClickEvent event) { - Player player = (Player) event.getWhoClicked(); - Inventory expectedGUI = playerGUIs.get(player.getUniqueId()); - if (expectedGUI == null || event.getInventory() != expectedGUI) return; - event.setCancelled(true); - ItemStack clickedItem = event.getCurrentItem(); - if (clickedItem == null || clickedItem.getType() == Material.AIR) return; - - WorldConfig config = worldConfigs.getOrDefault(player.getWorld().getName(), worldConfigs.get("defaults")); - String countryCode = getCountryCode(config.location); - - if (clickedItem.getType() == Material.BOOK) { - player.closeInventory(); - audiences.player(player).sendMessage(Component.text( - getLocalizedMessage("gui_setlocation_prompt", countryCode), NamedTextColor.YELLOW)); - } else if (clickedItem.getType() == Material.REDSTONE_TORCH) { - String worldName = player.getWorld().getName(); - Set worlds = playersWithDisplay.computeIfAbsent(player.getUniqueId(), k -> new HashSet<>()); - if (worlds.contains(worldName)) { - worlds.remove(worldName); - audiences.player(player).sendMessage(Component.text( - getLocalizedMessage("toggle_disabled", countryCode, "world", worldName), NamedTextColor.RED)); - } else { - worlds.add(worldName); - audiences.player(player).sendMessage(Component.text( - getLocalizedMessage("toggle_enabled", countryCode, "world", worldName), NamedTextColor.GREEN)); - } - } else if (clickedItem.getType() == Material.PAPER) { - player.closeInventory(); - new WeatherForecastCommand().onCommand(player, null, "weatherforecast", new String[]{}); - } else if (clickedItem.getType() == Material.OAK_SIGN) { - player.closeInventory(); - String infoMessage = "RealTimeWeather Plugin\nVersion: 1.0\nAutor: M_Viper\nGetestete Minecraft-Version: 1.21.1 - 1.21.8"; - audiences.player(player).sendMessage(Component.text(infoMessage, NamedTextColor.AQUA)); - } - } - - @EventHandler - public void onInventoryClose(InventoryCloseEvent event) { - playerGUIs.remove(event.getPlayer().getUniqueId()); - } - - // === Hilfsmethoden & Modellklassen === - - private String getLocalizedMessage(String key, String countryCode, String... placeholders) { - String path = "languages." + (countryCode.isEmpty() ? "en" : countryCode.toLowerCase()) + "." + key; - String message = langConfig.getString(path); - if (message == null) { - path = "languages.en." + key; - message = langConfig.getString(path, key); - } - for (int i = 0; i < placeholders.length - 1; i += 2) { - message = message.replace("{" + placeholders[i] + "}", placeholders[i + 1]); - } - return message; - } - - private String getWeatherSymbol(String weatherMain) { - switch (weatherMain.toLowerCase()) { - case "clear": return "☀️"; - case "clouds": return "☁️"; - case "rain": return "🌧️"; - case "thunderstorm": return "⛈️"; - case "snow": return "❄️"; - case "mist": - case "fog": - case "haze": return "🌫️"; - default: return weatherMain; - } - } - - private String getLocalizedWeatherMain(String weatherMain, String countryCode) { - String key = "weather." + weatherMain.toLowerCase(); - return getLocalizedMessage(key, countryCode); - } - - private String getCountryCode(String location) { - if (location == null || !location.contains(",")) return "en"; - String[] parts = location.split(","); - String countryCode = parts.length > 1 ? parts[1].trim().toLowerCase() : "en"; - if (!langConfig.contains("languages." + countryCode)) return "en"; - return countryCode; - } - - private Inventory createWeatherGUI(Player player) { - String countryCode = getCountryCode(worldConfigs.getOrDefault(player.getWorld().getName(), worldConfigs.get("defaults")).location); - Inventory inv = Bukkit.createInventory(null, 9, getLocalizedMessage("gui_title", countryCode)); - ItemStack setLocation = new ItemStack(Material.BOOK); - ItemStack toggleWeather = new ItemStack(Material.REDSTONE_TORCH); - ItemStack forecast = new ItemStack(Material.PAPER); - ItemStack info = new ItemStack(Material.OAK_SIGN); - - ItemMeta setLocationMeta = setLocation.getItemMeta(); - setLocationMeta.setDisplayName(getLocalizedMessage("gui_setlocation", countryCode)); - setLocationMeta.setLore(Collections.singletonList(getLocalizedMessage("gui_setlocation_lore", countryCode))); - setLocation.setItemMeta(setLocationMeta); - - ItemMeta toggleWeatherMeta = toggleWeather.getItemMeta(); - toggleWeatherMeta.setDisplayName(getLocalizedMessage("gui_toggleweather", countryCode)); - toggleWeatherMeta.setLore(Collections.singletonList(getLocalizedMessage("gui_toggleweather_lore", countryCode))); - toggleWeather.setItemMeta(toggleWeatherMeta); - - ItemMeta forecastMeta = forecast.getItemMeta(); - forecastMeta.setDisplayName(getLocalizedMessage("gui_forecast", countryCode)); - forecastMeta.setLore(Collections.singletonList(getLocalizedMessage("gui_forecast_lore", countryCode))); - forecast.setItemMeta(forecastMeta); - - ItemMeta infoMeta = info.getItemMeta(); - infoMeta.setDisplayName(getLocalizedMessage("gui_info", countryCode)); - infoMeta.setLore(Collections.singletonList(getLocalizedMessage("gui_info_lore", countryCode))); - info.setItemMeta(infoMeta); - - inv.setItem(2, setLocation); - inv.setItem(3, toggleWeather); - inv.setItem(4, forecast); - inv.setItem(5, info); - - playerGUIs.put(player.getUniqueId(), inv); - return inv; - } - - // ==== PlayerConfig etc. wie gehabt ==== - private class PlayerConfig { - private final File configFile; - private final FileConfiguration config; - public PlayerConfig(UUID playerId) { - File playerDir = new File(getDataFolder(), "players"); - playerDir.mkdirs(); - configFile = new File(playerDir, playerId.toString() + ".yml"); - config = YamlConfiguration.loadConfiguration(configFile); - } - public String getLocation() { - return config.getString("location", ""); - } - public void setLocation(String location) { - config.set("location", location); - try { - config.save(configFile); - } catch (IOException e) { - getLogger().warning("Fehler beim Speichern der Spieler-Konfiguration: " + e.getMessage()); - } - } - } - - // ==== Commands ==== - private class WetterCommand implements CommandExecutor { - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - String countryCode = getCountryCode(worldConfigs.get("defaults").location); - if (args.length == 0) { - audiences.sender(sender).sendMessage(Component.text(getLocalizedMessage("usage", countryCode), NamedTextColor.RED)); - return true; - } - switch (args[0].toLowerCase(Locale.ROOT)) { - case "help": { - Component helpMessage = Component.text() - .append(Component.text(getLocalizedMessage("help_header", countryCode), NamedTextColor.AQUA, TextDecoration.BOLD)) - .append(Component.newline()) - .append(Component.text("/wetter help", NamedTextColor.YELLOW)) - .append(Component.text(" - " + getLocalizedMessage("help_help", countryCode), NamedTextColor.WHITE)) - .append(Component.newline()) - .append(Component.text("/wetter reload", NamedTextColor.YELLOW)) - .append(Component.text(" - " + getLocalizedMessage("help_reload", countryCode), NamedTextColor.WHITE)) - .append(Component.newline()) - .append(Component.text("/wetter setlocation ", NamedTextColor.YELLOW)) - .append(Component.text(" - " + getLocalizedMessage("help_setlocation", countryCode), NamedTextColor.WHITE)) - .append(Component.newline()) - .append(Component.text("/wetter query", NamedTextColor.YELLOW)) - .append(Component.text(" - " + getLocalizedMessage("help_query", countryCode), NamedTextColor.WHITE)) - .append(Component.newline()) - .append(Component.text("/wetter info", NamedTextColor.YELLOW)) - .append(Component.text(" - " + getLocalizedMessage("help_info", countryCode), NamedTextColor.WHITE)) - .append(Component.newline()) - .append(Component.text("/wetter gui", NamedTextColor.YELLOW)) - .append(Component.text(" - " + getLocalizedMessage("help_gui", countryCode), NamedTextColor.WHITE)) - .append(Component.newline()) - .append(Component.text("/weatherforecast", NamedTextColor.YELLOW)) - .append(Component.text(" - " + getLocalizedMessage("help_weatherforecast", countryCode), NamedTextColor.WHITE)) - .append(Component.newline()) - .append(Component.text("/toggleweather", NamedTextColor.YELLOW)) - .append(Component.text(" - " + getLocalizedMessage("help_toggleweather", countryCode), NamedTextColor.WHITE)) - .build(); - audiences.sender(sender).sendMessage(helpMessage); - return true; - } - case "reload": { - if (!sender.hasPermission("realtimeweather.reload")) { - audiences.sender(sender).sendMessage(Component.text(getLocalizedMessage("no_permission", countryCode), NamedTextColor.RED)); - return true; - } - if (weatherUpdateTask != null) weatherUpdateTask.cancel(); - if (syncTask != null) syncTask.cancel(); - reloadConfig(); - loadConfig(); - loadLanguageConfig(); - worldWeatherData.clear(); - processedLocations.clear(); - initializePlayerDisplays(); - setDoDaylightCycleForWorlds(); - startWeatherUpdateTask(); - startSyncTask(); - processedLocations.clear(); - updateWeatherDataForAllWorlds(); - audiences.sender(sender).sendMessage(Component.text(getLocalizedMessage("reload_success", countryCode), NamedTextColor.GREEN)); - return true; - } - case "setlocation": { - if (!(sender instanceof Player)) { - audiences.sender(sender).sendMessage(Component.text(getLocalizedMessage("only_players", countryCode), NamedTextColor.RED)); - return true; - } - if (args.length != 2) { - audiences.sender(sender).sendMessage(Component.text(getLocalizedMessage("usage_setlocation", countryCode), NamedTextColor.RED)); - return true; - } - Player player = (Player) sender; - String location = args[1]; - new BukkitRunnable() { - @Override - public void run() { - try { - WeatherFetcher fetcher = new WeatherFetcher(apiKey, location, "metric", getLogger()); - fetcher.fetchAsWeatherTimeData(); - PlayerConfig playerConfig = new PlayerConfig(player.getUniqueId()); - playerConfig.setLocation(location); - playerLocations.put(player.getUniqueId(), location); - String cc = getCountryCode(location); - audiences.player(player).sendMessage(Component.text(getLocalizedMessage("location_set", cc, "location", location), NamedTextColor.GREEN)); - } catch (Exception e) { - audiences.player(player).sendMessage(Component.text(getLocalizedMessage("invalid_location", countryCode, "location", location), NamedTextColor.RED)); - } - } - }.runTaskAsynchronously(WeatherTimeSyncPlugin.this); - return true; - } - case "query": { - if (!(sender instanceof Player)) { - audiences.sender(sender).sendMessage(Component.text(getLocalizedMessage("only_players", countryCode), NamedTextColor.RED)); - return true; - } - Player queryPlayer = (Player) sender; - WorldConfig config = worldConfigs.getOrDefault(queryPlayer.getWorld().getName(), worldConfigs.get("defaults")); - if (!config.enabled) { - audiences.player(queryPlayer).sendMessage(Component.text(getLocalizedMessage("plugin_disabled", countryCode, "world", queryPlayer.getWorld().getName()), NamedTextColor.RED)); - return true; - } - String queryLocation = playerLocations.getOrDefault(queryPlayer.getUniqueId(), config.location); - new BukkitRunnable() { - @Override - public void run() { - try { - WeatherFetcher fetcher = new WeatherFetcher(apiKey, queryLocation, config.units, getLogger()); - WeatherTimeData data = fetcher.fetchAsWeatherTimeData(); - String cc = getCountryCode(queryLocation); - String localizedWeather = getLocalizedWeatherMain(data.getWeatherMain(), cc); - String tempUnit = config.units.equalsIgnoreCase("metric") ? "°C" : "°F"; - String city = queryLocation.split(",")[0]; - String message = String.format("%s: %s, %.1f%s", city, localizedWeather, data.getTemp(config.units.equalsIgnoreCase("metric") ? "C" : "F"), tempUnit); - audiences.player(queryPlayer).sendMessage(Component.text(message, NamedTextColor.GREEN)); - } catch (Exception e) { - audiences.player(queryPlayer).sendMessage(Component.text(getLocalizedMessage("forecast_error", countryCode, "location", queryLocation, "error", e.getMessage()), NamedTextColor.RED)); - } - } - }.runTaskAsynchronously(WeatherTimeSyncPlugin.this); - return true; - } - case "info": { - String infoMessage = "RealTimeWeather Plugin\nVersion: 1.0\nAutor: M_Viper\nGetestete Minecraft-Version: 1.21.1 - 1.21.8"; - audiences.sender(sender).sendMessage(Component.text(infoMessage, NamedTextColor.AQUA)); - return true; - } - case "gui": { - if (!(sender instanceof Player)) { - audiences.sender(sender).sendMessage(Component.text(getLocalizedMessage("only_players", countryCode), NamedTextColor.RED)); - return true; - } - Player guiPlayer = (Player) sender; - WorldConfig guiConfig = worldConfigs.getOrDefault(guiPlayer.getWorld().getName(), worldConfigs.get("defaults")); - if (!guiConfig.enabled) { - String cc = getCountryCode(guiConfig.location); - audiences.player(guiPlayer).sendMessage(Component.text(getLocalizedMessage("plugin_disabled", cc, "world", guiPlayer.getWorld().getName()), NamedTextColor.RED)); - return true; - } - guiPlayer.openInventory(createWeatherGUI(guiPlayer)); - return true; - } - default: - audiences.sender(sender).sendMessage(Component.text(getLocalizedMessage("usage", countryCode), NamedTextColor.RED)); - return true; - } - } - } - - private class WeatherForecastCommand implements CommandExecutor { - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (!(sender instanceof Player)) { - String countryCode = getCountryCode(worldConfigs.get("defaults").location); - audiences.sender(sender).sendMessage(Component.text(getLocalizedMessage("only_players", countryCode), NamedTextColor.RED)); - return true; - } - Player player = (Player) sender; - WorldConfig config = worldConfigs.getOrDefault(player.getWorld().getName(), worldConfigs.get("defaults")); - if (!config.enabled) { - String countryCode = getCountryCode(config.location); - audiences.player(player).sendMessage(Component.text(getLocalizedMessage("plugin_disabled", countryCode, "world", player.getWorld().getName()), NamedTextColor.RED)); - return true; - } - String location = playerLocations.getOrDefault(player.getUniqueId(), config.location); - new BukkitRunnable() { - @Override - public void run() { - try { - WeatherFetcher fetcher = new WeatherFetcher(apiKey, location, config.units, getLogger()); - JSONObject json = fetcher.fetchForecast(); - JSONArray list = json.getJSONArray("list"); - - String[] locationParts = location.split(","); - String countryCode = locationParts.length > 1 ? locationParts[1].trim() : ""; - String city = locationParts[0].trim(); - - String forecastMessage = getLocalizedMessage("forecast_header", countryCode, "location", city); - Component message = Component.text(forecastMessage, NamedTextColor.AQUA); - - for (int i = 0; i < list.length() && i < 40; i += 8) { - JSONObject forecast = list.getJSONObject(i); - long dt = forecast.getLong("dt"); - String weatherMain = forecast.getJSONArray("weather").getJSONObject(0).getString("main"); - double temp = forecast.getJSONObject("main").getDouble("temp"); - ZonedDateTime dateTime = Instant.ofEpochSecond(dt).atZone(ZoneId.of("UTC")); - - String localizedWeatherMain = getLocalizedWeatherMain(weatherMain, countryCode); - - message = message.append(Component.newline()) - .append(Component.text( - dateTime.format(DateTimeFormatter.ofPattern("dd.MM.yyyy")) + ": " + - localizedWeatherMain + ", " + String.format("%.1f%s", temp, config.units.equalsIgnoreCase("metric") ? "°C" : "°F"), - NamedTextColor.GREEN)); - } - audiences.player(player).sendMessage(message); - } catch (Exception e) { - String countryCode = getCountryCode(config.location); - audiences.player(player).sendMessage(Component.text( - getLocalizedMessage("forecast_error", countryCode, "location", location, "error", e.getMessage()), - NamedTextColor.RED)); - } - } - }.runTaskAsynchronously(WeatherTimeSyncPlugin.this); - return true; - } - } - - private class ToggleWeatherCommand implements CommandExecutor { - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (!(sender instanceof Player)) { - String countryCode = getCountryCode(worldConfigs.get("defaults").location); - audiences.sender(sender).sendMessage(Component.text(getLocalizedMessage("only_players", countryCode), NamedTextColor.RED)); - return true; - } - Player player = (Player) sender; - String worldName = player.getWorld().getName(); - WorldConfig config = worldConfigs.getOrDefault(worldName, worldConfigs.get("defaults")); - if (!config.enabled) { - String countryCode = getCountryCode(config.location); - audiences.player(player).sendMessage(Component.text(getLocalizedMessage("plugin_disabled", countryCode, "world", worldName), NamedTextColor.RED)); - return true; - } - String countryCode = getCountryCode(config.location); - Set worlds = playersWithDisplay.computeIfAbsent(player.getUniqueId(), k -> new HashSet<>()); - if (worlds.contains(worldName)) { - worlds.remove(worldName); - audiences.player(player).sendMessage(Component.text(getLocalizedMessage("toggle_disabled", countryCode, "world", worldName), NamedTextColor.RED)); - } else { - worlds.add(worldName); - audiences.player(player).sendMessage(Component.text(getLocalizedMessage("toggle_enabled", countryCode, "world", worldName), NamedTextColor.GREEN)); - } - return true; - } - } - - // Modellklasse WorldConfig (nur als Speicher für die Welten-Settings) - private static class WorldConfig { - boolean enabled; - String location; - String units; - String timeFormat; - boolean displayActionbar; - boolean displayWeatherIcon; - String displayPosition; - int paddingRight; - boolean syncInGameWeather; - - public WorldConfig(boolean enabled, String location, String units, String timeFormat, - boolean displayActionbar, boolean displayWeatherIcon, - String displayPosition, int paddingRight, boolean syncInGameWeather) { - this.enabled = enabled; - this.location = location; - this.units = units; - this.timeFormat = timeFormat; - this.displayActionbar = displayActionbar; - this.displayWeatherIcon = displayWeatherIcon; - this.displayPosition = displayPosition; - this.paddingRight = paddingRight; - this.syncInGameWeather = syncInGameWeather; - } + return ((hour + 18) % 24) * 1000L + + (minute * 1000L / 60) + + (second * 1000L / 3600); } }