9 Commits
1.1 ... 1.5

12 changed files with 1207 additions and 197 deletions

48
pom.xml
View File

@@ -7,7 +7,7 @@
<groupId>dev.viper</groupId> <groupId>dev.viper</groupId>
<artifactId>RealTimeWeather</artifactId> <artifactId>RealTimeWeather</artifactId>
<version>1.0</version> <version>1.5</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>RealTimeWeather</name> <name>RealTimeWeather</name>
@@ -15,8 +15,8 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source> <maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target> <maven.compiler.target>21</maven.compiler.target>
</properties> </properties>
<repositories> <repositories>
@@ -46,18 +46,36 @@
<version>20231013</version> <version>20231013</version>
</dependency> </dependency>
<!-- Adventure API --> <!-- Adventure API (nur für Chat-Nachrichten, NICHT für ActionBar) -->
<dependency> <dependency>
<groupId>net.kyori</groupId> <groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId> <artifactId>adventure-api</artifactId>
<version>4.17.0</version> <version>4.17.0</version>
<scope>compile</scope>
</dependency> </dependency>
<!-- Adventure Platform Bukkit --> <!-- Adventure Platform Bukkit -->
<dependency> <dependency>
<groupId>net.kyori</groupId> <groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId> <artifactId>adventure-platform-bukkit</artifactId>
<version>4.3.3</version> <version>4.3.4</version>
<scope>compile</scope>
</dependency>
<!-- Adventure Text Serializer Legacy -->
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-legacy</artifactId>
<version>4.17.0</version>
<scope>compile</scope>
</dependency>
<!-- bStats Bukkit Library -->
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>3.1.0</version>
<scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@@ -65,7 +83,7 @@
<plugins> <plugins>
<plugin> <plugin>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version> <version>3.13.0</version>
<configuration> <configuration>
<source>${maven.compiler.source}</source> <source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target> <target>${maven.compiler.target}</target>
@@ -75,7 +93,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version> <version>3.5.1</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@@ -87,21 +105,19 @@
<pattern>org.json</pattern> <pattern>org.json</pattern>
<shadedPattern>dev.viper.shaded.org.json</shadedPattern> <shadedPattern>dev.viper.shaded.org.json</shadedPattern>
</relocation> </relocation>
<!-- Shade Adventure API --> <!-- Shade ALLE Adventure/Kyori Packages zusammen -->
<relocation> <relocation>
<pattern>net.kyori.adventure</pattern> <pattern>net.kyori</pattern>
<shadedPattern>dev.viper.shaded.net.kyori.adventure</shadedPattern> <shadedPattern>dev.viper.shaded.net.kyori</shadedPattern>
</relocation> </relocation>
<!-- Shade Adventure Platform Bukkit --> <!-- Shade bStats -->
<relocation> <relocation>
<pattern>net.kyori.platform.bukkit</pattern> <pattern>org.bstats</pattern>
<shadedPattern>dev.viper.shaded.net.kyori.platform.bukkit</shadedPattern> <shadedPattern>dev.viper.shaded.org.bstats</shadedPattern>
</relocation> </relocation>
</relocations> </relocations>
<createDependencyReducedPom>false</createDependencyReducedPom> <createDependencyReducedPom>false</createDependencyReducedPom>
<!-- Minimieren, um die JAR-Größe zu reduzieren (optional) --> <minimizeJar>false</minimizeJar>
<minimizeJar>true</minimizeJar>
<!-- Filter, um unnötige Klassen auszuschließen -->
<filters> <filters>
<filter> <filter>
<artifact>*:*</artifact> <artifact>*:*</artifact>

View File

@@ -0,0 +1,32 @@
package dev.viper.weathertime;
public enum DisplayMode {
COMPACT("Kompakt", 5),
STANDARD("Standard", 10),
DETAILED("Detailliert", 15);
private final String displayName;
private final int lineCount;
DisplayMode(String displayName, int lineCount) {
this.displayName = displayName;
this.lineCount = lineCount;
}
public String getDisplayName() {
return displayName;
}
public int getLineCount() {
return lineCount;
}
public static DisplayMode fromString(String mode) {
for (DisplayMode dm : values()) {
if (dm.name().equalsIgnoreCase(mode)) {
return dm;
}
}
return STANDARD;
}
}

View File

@@ -0,0 +1,21 @@
package dev.viper.weathertime;
import org.bstats.bukkit.Metrics;
import org.bukkit.plugin.java.JavaPlugin;
public class MetricsManager {
private final Metrics metrics;
public MetricsManager(JavaPlugin plugin) {
int pluginId = 26865; // Deine Plugin-ID von bStats
this.metrics = new Metrics(plugin, pluginId);
// Optional: Eigene Charts hinzufügen
// metrics.addCustomChart(new Metrics.SingleLineChart("custom_chart", () -> 1));
}
public Metrics getMetrics() {
return metrics;
}
}

View File

@@ -0,0 +1,69 @@
package dev.viper.weathertime;
import org.bukkit.World;
public class MoonPhase {
/**
* Berechnet die aktuelle Mondphase basierend auf der Minecraft-Zeit
*/
public static String getPhase(World world) {
long fullTime = world.getFullTime();
long daysPassed = fullTime / 24000L;
int phase = (int) (daysPassed % 8);
switch (phase) {
case 0: return "🌑 Neumond";
case 1: return "🌒 Zunehmende Sichel";
case 2: return "🌓 Erstes Viertel";
case 3: return "🌔 Zunehmender Mond";
case 4: return "🌕 Vollmond";
case 5: return "🌖 Abnehmender Mond";
case 6: return "🌗 Letztes Viertel";
case 7: return "🌘 Abnehmende Sichel";
default: return "🌑 Neumond";
}
}
/**
* Gibt nur das Emoji der Mondphase zurück
*/
public static String getEmoji(World world) {
long fullTime = world.getFullTime();
long daysPassed = fullTime / 24000L;
int phase = (int) (daysPassed % 8);
switch (phase) {
case 0: return "🌑";
case 1: return "🌒";
case 2: return "🌓";
case 3: return "🌔";
case 4: return "🌕";
case 5: return "🌖";
case 6: return "🌗";
case 7: return "🌘";
default: return "🌑";
}
}
/**
* Gibt den Namen der Mondphase zurück (ohne Emoji)
*/
public static String getName(World world) {
long fullTime = world.getFullTime();
long daysPassed = fullTime / 24000L;
int phase = (int) (daysPassed % 8);
switch (phase) {
case 0: return "Neumond";
case 1: return "Zunehmende Sichel";
case 2: return "Erstes Viertel";
case 3: return "Zunehmender Mond";
case 4: return "Vollmond";
case 5: return "Abnehmender Mond";
case 6: return "Letztes Viertel";
case 7: return "Abnehmende Sichel";
default: return "Neumond";
}
}
}

View File

@@ -0,0 +1,64 @@
package dev.viper.weathertime;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.json.JSONObject;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;
import java.util.function.Consumer;
public class UpdateChecker {
private final JavaPlugin plugin;
private final int resourceId;
public UpdateChecker(JavaPlugin plugin, int resourceId) {
this.plugin = plugin;
this.resourceId = resourceId;
}
public void getLatestVersion(Consumer<String> consumer) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
InputStream inputStream = null;
Scanner scanner = null;
try {
HttpURLConnection connection = (HttpURLConnection)
new URL("https://api.spiget.org/v2/resources/" + resourceId + "/versions/latest").openConnection();
connection.setRequestMethod("GET");
connection.addRequestProperty("User-Agent", "Mozilla/5.0");
inputStream = connection.getInputStream();
scanner = new Scanner(inputStream);
String response = scanner.useDelimiter("\\A").next();
JSONObject json = new JSONObject(response);
String versionName = json.optString("name");
// Nur Zahlen + Punkte behalten (z.B. "version 1.1" -> "1.1")
String cleanVersion = versionName.replaceAll("[^0-9.]", "").trim();
consumer.accept(cleanVersion.isEmpty() ? versionName : cleanVersion);
} catch (Exception e) {
plugin.getLogger().warning("Konnte keine Update-Info abrufen: " + e.getMessage());
} finally {
if (scanner != null) {
try {
scanner.close();
} catch (Exception e) {
// Ignore
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) {
// Ignore
}
}
}
});
}
}

View File

@@ -0,0 +1,97 @@
package dev.viper.weathertime;
import org.bukkit.ChatColor;
public class WeatherColors {
/**
* Gibt die Farbe basierend auf der Temperatur zurück
*/
public static ChatColor getTemperatureColor(double tempCelsius) {
if (tempCelsius < 0) {
return ChatColor.AQUA; // Unter 0°C - Hellblau (eisig)
} else if (tempCelsius < 10) {
return ChatColor.BLUE; // 0-10°C - Blau (kalt)
} else if (tempCelsius < 20) {
return ChatColor.GREEN; // 10-20°C - Grün (mild)
} else if (tempCelsius < 30) {
return ChatColor.YELLOW; // 20-30°C - Gelb (warm)
} else {
return ChatColor.RED; // Über 30°C - Rot (heiß)
}
}
/**
* Gibt die Farbe basierend auf dem Wetter zurück
*/
public static ChatColor getWeatherColor(String weatherMain) {
switch (weatherMain.toLowerCase()) {
case "clear":
return ChatColor.GOLD; // Sonnig - Gold
case "clouds":
return ChatColor.GRAY; // Bewölkt - Grau
case "rain":
case "drizzle":
return ChatColor.BLUE; // Regen - Blau
case "thunderstorm":
return ChatColor.DARK_PURPLE; // Gewitter - Dunkelviolett
case "snow":
return ChatColor.WHITE; // Schnee - Weiß
case "mist":
case "fog":
case "haze":
return ChatColor.DARK_GRAY; // Nebel - Dunkelgrau
default:
return ChatColor.WHITE;
}
}
/**
* Gibt die Farbe basierend auf der Luftfeuchtigkeit zurück
*/
public static ChatColor getHumidityColor(int humidity) {
if (humidity < 30) {
return ChatColor.RED; // Trocken
} else if (humidity < 60) {
return ChatColor.GREEN; // Angenehm
} else if (humidity < 80) {
return ChatColor.YELLOW; // Feucht
} else {
return ChatColor.AQUA; // Sehr feucht
}
}
/**
* Gibt die Farbe basierend auf der Windgeschwindigkeit zurück (m/s)
*/
public static ChatColor getWindSpeedColor(double windSpeed) {
if (windSpeed < 5) {
return ChatColor.GREEN; // Leicht
} else if (windSpeed < 10) {
return ChatColor.YELLOW; // Mäßig
} else if (windSpeed < 15) {
return ChatColor.GOLD; // Frisch
} else if (windSpeed < 20) {
return ChatColor.RED; // Stark
} else {
return ChatColor.DARK_RED; // Sturm
}
}
/**
* Gibt die Farbe basierend auf dem UV-Index zurück
*/
public static ChatColor getUVIndexColor(int uvIndex) {
if (uvIndex <= 2) {
return ChatColor.GREEN; // Niedrig
} else if (uvIndex <= 5) {
return ChatColor.YELLOW; // Mäßig
} else if (uvIndex <= 7) {
return ChatColor.GOLD; // Hoch
} else if (uvIndex <= 10) {
return ChatColor.RED; // Sehr hoch
} else {
return ChatColor.DARK_RED; // Extrem
}
}
}

View File

@@ -44,16 +44,16 @@ public class WeatherFetcher {
"https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=%s", "https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=%s",
location, apiKey, effectiveUnits); location, apiKey, effectiveUnits);
BufferedReader in = null;
try { try {
JSONObject json; JSONObject json;
try (BufferedReader in = new BufferedReader(new InputStreamReader(openConnectionStream(urlString)))) { in = new BufferedReader(new InputStreamReader(openConnectionStream(urlString)));
StringBuilder content = new StringBuilder(); StringBuilder content = new StringBuilder();
String inputLine; String inputLine;
while ((inputLine = in.readLine()) != null) { while ((inputLine = in.readLine()) != null) {
content.append(inputLine); content.append(inputLine);
}
json = new JSONObject(content.toString());
} }
json = new JSONObject(content.toString());
// Fehlerfall: Antwort-Code ungleich 200 // Fehlerfall: Antwort-Code ungleich 200
if (json.has("cod") && json.getInt("cod") != 200) { if (json.has("cod") && json.getInt("cod") != 200) {
@@ -79,11 +79,18 @@ public class WeatherFetcher {
} }
// Temperatur immer in Celsius für WeatherTimeData speichern // Temperatur immer in Celsius für WeatherTimeData speichern
double tempCelsius = effectiveUnits.equals("imperial") ? (temperature - 32) * 5 / 9 : temperature; double tempCelsius = effectiveUnits.equals("imperial") ? (temperature - 32) * 5.0 / 9.0 : temperature;
// NEUE FELDER AUSLESEN // FELDER AUSLESEN
int humidity = json.getJSONObject("main").getInt("humidity"); int humidity = json.getJSONObject("main").getInt("humidity");
double windSpeed = json.getJSONObject("wind").optDouble("speed", 0.0); double windSpeed = json.getJSONObject("wind").optDouble("speed", 0.0);
double windDeg = json.getJSONObject("wind").optDouble("deg", 0.0);
int pressure = json.getJSONObject("main").optInt("pressure", 1013);
int clouds = json.getJSONObject("clouds").optInt("all", 0);
double feelsLikeTemp = json.getJSONObject("main").optDouble("feels_like", temperature);
double feelsLikeCelsius = effectiveUnits.equals("imperial") ? (feelsLikeTemp - 32) * 5.0 / 9.0 : feelsLikeTemp;
int visibility = json.optInt("visibility", 10000); // Standard 10km
ZonedDateTime sunrise = Instant.ofEpochSecond(json.getJSONObject("sys").getLong("sunrise")) ZonedDateTime sunrise = Instant.ofEpochSecond(json.getJSONObject("sys").getLong("sunrise"))
.atZone(ZoneId.of("UTC")) .atZone(ZoneId.of("UTC"))
@@ -94,13 +101,22 @@ public class WeatherFetcher {
.plusSeconds(timezoneShift); .plusSeconds(timezoneShift);
return new WeatherTimeData(dateTime, weatherMain, tempCelsius, return new WeatherTimeData(dateTime, weatherMain, tempCelsius,
humidity, windSpeed, sunrise, sunset); humidity, windSpeed, windDeg, sunrise, sunset,
pressure, clouds, feelsLikeCelsius, visibility);
} catch (RuntimeException ru) { } catch (RuntimeException ru) {
throw ru; throw ru;
} catch (Exception ex) { } catch (Exception ex) {
logger.warning("Fehler beim Abrufen von OpenWeatherMap: " + ex.getMessage()); logger.warning("Fehler beim Abrufen von OpenWeatherMap: " + ex.getMessage());
throw new RuntimeException("Verbindung oder API-Fehler: " + ex.getMessage(), ex); throw new RuntimeException("Verbindung oder API-Fehler: " + ex.getMessage(), ex);
} finally {
if (in != null) {
try {
in.close();
} catch (Exception e) {
// Ignore
}
}
} }
} }
@@ -115,7 +131,9 @@ public class WeatherFetcher {
"https://api.openweathermap.org/data/2.5/forecast?q=%s&appid=%s&units=%s", "https://api.openweathermap.org/data/2.5/forecast?q=%s&appid=%s&units=%s",
location, apiKey, effectiveUnits); location, apiKey, effectiveUnits);
try (BufferedReader in = new BufferedReader(new InputStreamReader(openConnectionStream(urlString)))) { BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(openConnectionStream(urlString)));
StringBuilder content = new StringBuilder(); StringBuilder content = new StringBuilder();
String inputLine; String inputLine;
while ((inputLine = in.readLine()) != null) { while ((inputLine = in.readLine()) != null) {
@@ -131,6 +149,14 @@ public class WeatherFetcher {
} catch (Exception e) { } catch (Exception e) {
logger.warning("Fehler beim Abrufen der Wettervorhersage: " + e.getMessage()); logger.warning("Fehler beim Abrufen der Wettervorhersage: " + e.getMessage());
throw new RuntimeException("Fehler beim Abrufen der Wettervorhersage: " + e.getMessage(), e); throw new RuntimeException("Fehler beim Abrufen der Wettervorhersage: " + e.getMessage(), e);
} finally {
if (in != null) {
try {
in.close();
} catch (Exception e) {
// Ignore
}
}
} }
} }
@@ -145,12 +171,24 @@ public class WeatherFetcher {
int status = connection.getResponseCode(); int status = connection.getResponseCode();
if (status != 200) { if (status != 200) {
String err = "(keine Fehlerdetails)"; String err = "(keine Fehlerdetails)";
try (BufferedReader errIn = new BufferedReader(new InputStreamReader(connection.getErrorStream()))) { BufferedReader errIn = null;
try {
errIn = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String l; String l;
while ((l = errIn.readLine()) != null) sb.append(l); while ((l = errIn.readLine()) != null) sb.append(l);
err = sb.toString(); err = sb.toString();
} catch (Exception suppress) {} } catch (Exception suppress) {
// Ignore
} finally {
if (errIn != null) {
try {
errIn.close();
} catch (Exception e) {
// Ignore
}
}
}
throw new RuntimeException("HTTP-Fehlercode: " + status + " " + err); throw new RuntimeException("HTTP-Fehlercode: " + status + " " + err);
} }
return connection.getInputStream(); return connection.getInputStream();

View File

@@ -4,7 +4,8 @@ import java.time.ZonedDateTime;
/** /**
* Zentrale Datenklasse für Wetter- und Zeitinformationen. * Zentrale Datenklasse für Wetter- und Zeitinformationen.
* Erweiterung: enthält jetzt auch Luftfeuchtigkeit, Windgeschwindigkeit und Sonnenauf/untergang. * Erweiterung: enthält jetzt auch Luftfeuchtigkeit, Windgeschwindigkeit, Windrichtung,
* Sonnenauf/untergang, Luftdruck, Wolkendichte und UV-Index.
*/ */
public class WeatherTimeData { public class WeatherTimeData {
@@ -14,24 +15,40 @@ public class WeatherTimeData {
private final int humidity; // Luftfeuchtigkeit in % private final int humidity; // Luftfeuchtigkeit in %
private final double windSpeed; // Windgeschwindigkeit (m/s oder mph) private final double windSpeed; // Windgeschwindigkeit (m/s oder mph)
private final double windDeg; // Windrichtung in Grad (0-360)
private final ZonedDateTime sunrise; // Sonnenaufgang private final ZonedDateTime sunrise; // Sonnenaufgang
private final ZonedDateTime sunset; // Sonnenuntergang private final ZonedDateTime sunset; // Sonnenuntergang
private final int pressure; // Luftdruck in hPa
private final int clouds; // Wolkendichte in %
private final double feelsLike; // Gefühlte Temperatur in °C
private final int visibility; // Sichtweite in Metern
public WeatherTimeData( public WeatherTimeData(
ZonedDateTime dateTime, ZonedDateTime dateTime,
String weatherMain, String weatherMain,
double tempCelsius, double tempCelsius,
int humidity, int humidity,
double windSpeed, double windSpeed,
double windDeg,
ZonedDateTime sunrise, ZonedDateTime sunrise,
ZonedDateTime sunset) { ZonedDateTime sunset,
int pressure,
int clouds,
double feelsLike,
int visibility) {
this.dateTime = dateTime; this.dateTime = dateTime;
this.weatherMain = weatherMain; this.weatherMain = weatherMain;
this.tempCelsius = tempCelsius; this.tempCelsius = tempCelsius;
this.humidity = humidity; this.humidity = humidity;
this.windSpeed = windSpeed; this.windSpeed = windSpeed;
this.windDeg = windDeg;
this.sunrise = sunrise; this.sunrise = sunrise;
this.sunset = sunset; this.sunset = sunset;
this.pressure = pressure;
this.clouds = clouds;
this.feelsLike = feelsLike;
this.visibility = visibility;
} }
public ZonedDateTime getDateTime() { public ZonedDateTime getDateTime() {
@@ -44,7 +61,7 @@ public class WeatherTimeData {
public double getTemp(String unit) { public double getTemp(String unit) {
return "F".equalsIgnoreCase(unit) return "F".equalsIgnoreCase(unit)
? (tempCelsius * 9 / 5) + 32 ? (tempCelsius * 9.0 / 5.0) + 32.0
: tempCelsius; : tempCelsius;
} }
@@ -56,6 +73,10 @@ public class WeatherTimeData {
return windSpeed; return windSpeed;
} }
public double getWindDeg() {
return windDeg;
}
public ZonedDateTime getSunrise() { public ZonedDateTime getSunrise() {
return sunrise; return sunrise;
} }
@@ -64,6 +85,62 @@ public class WeatherTimeData {
return sunset; return sunset;
} }
public int getPressure() {
return pressure;
}
public int getClouds() {
return clouds;
}
public double getFeelsLike(String unit) {
return "F".equalsIgnoreCase(unit)
? (feelsLike * 9.0 / 5.0) + 32.0
: feelsLike;
}
public int getVisibility() {
return visibility;
}
/**
* Berechnet einen einfachen UV-Index basierend auf Tageszeit, Wolken und Wetter
* (0-11+: 0-2=niedrig, 3-5=mäßig, 6-7=hoch, 8-10=sehr hoch, 11+=extrem)
*/
public int getUVIndex() {
int hour = dateTime.getHour();
// Nachts ist UV-Index 0
if (hour < 6 || hour > 20) {
return 0;
}
// Basis UV-Index je nach Tageszeit (Maximum mittags)
int baseUV;
if (hour >= 11 && hour <= 13) {
baseUV = 9; // Mittags am höchsten
} else if (hour >= 10 && hour <= 14) {
baseUV = 7;
} else if (hour >= 9 && hour <= 15) {
baseUV = 5;
} else {
baseUV = 3;
}
// Reduzierung durch Wolken
baseUV = baseUV - (clouds / 20);
// Reduzierung bei Regen/Schnee/Gewitter
if (weatherMain.equalsIgnoreCase("rain") ||
weatherMain.equalsIgnoreCase("drizzle") ||
weatherMain.equalsIgnoreCase("thunderstorm") ||
weatherMain.equalsIgnoreCase("snow")) {
baseUV = Math.max(1, baseUV / 2);
}
return Math.max(0, Math.min(11, baseUV));
}
public String getFormattedTime(String format) { public String getFormattedTime(String format) {
int hour = dateTime.getHour(); int hour = dateTime.getHour();
int minute = dateTime.getMinute(); int minute = dateTime.getMinute();

View File

@@ -0,0 +1,83 @@
package dev.viper.weathertime;
public class WindDirection {
/**
* Konvertiert Windrichtung in Grad (0-360) zu Himmelsrichtung
*/
public static String getDirection(double degrees) {
// Normalisiere auf 0-360
degrees = degrees % 360;
if (degrees < 0) degrees += 360;
if (degrees >= 337.5 || degrees < 22.5) {
return "N"; // Nord
} else if (degrees >= 22.5 && degrees < 67.5) {
return "NO"; // Nordost
} else if (degrees >= 67.5 && degrees < 112.5) {
return "O"; // Ost
} else if (degrees >= 112.5 && degrees < 157.5) {
return "SO"; // Südost
} else if (degrees >= 157.5 && degrees < 202.5) {
return "S"; // Süd
} else if (degrees >= 202.5 && degrees < 247.5) {
return "SW"; // Südwest
} else if (degrees >= 247.5 && degrees < 292.5) {
return "W"; // West
} else {
return "NW"; // Nordwest
}
}
/**
* Gibt den Pfeil-Emoji basierend auf der Windrichtung zurück
*/
public static String getArrow(double degrees) {
degrees = degrees % 360;
if (degrees < 0) degrees += 360;
if (degrees >= 337.5 || degrees < 22.5) {
return ""; // Nord (Wind kommt von Norden, weht nach Süden)
} else if (degrees >= 22.5 && degrees < 67.5) {
return ""; // Nordost
} else if (degrees >= 67.5 && degrees < 112.5) {
return ""; // Ost
} else if (degrees >= 112.5 && degrees < 157.5) {
return ""; // Südost
} else if (degrees >= 157.5 && degrees < 202.5) {
return ""; // Süd
} else if (degrees >= 202.5 && degrees < 247.5) {
return ""; // Südwest
} else if (degrees >= 247.5 && degrees < 292.5) {
return ""; // West
} else {
return ""; // Nordwest
}
}
/**
* Gibt die volle Bezeichnung der Windrichtung zurück
*/
public static String getFullName(double degrees) {
degrees = degrees % 360;
if (degrees < 0) degrees += 360;
if (degrees >= 337.5 || degrees < 22.5) {
return "Nord";
} else if (degrees >= 22.5 && degrees < 67.5) {
return "Nordost";
} else if (degrees >= 67.5 && degrees < 112.5) {
return "Ost";
} else if (degrees >= 112.5 && degrees < 157.5) {
return "Südost";
} else if (degrees >= 157.5 && degrees < 202.5) {
return "Süd";
} else if (degrees >= 202.5 && degrees < 247.5) {
return "Südwest";
} else if (degrees >= 247.5 && degrees < 292.5) {
return "West";
} else {
return "Nordwest";
}
}
}

View File

@@ -1,39 +1,61 @@
# OpenWeatherMap API-Key hier eintragen # ============================================================
# RealTimeWeather config.yml
# ============================================================
# OpenWeatherMap API-Key
# Kostenlos erhältlich unter: https://openweathermap.org/api
api-key: "DEIN_API_KEY_HIER" api-key: "DEIN_API_KEY_HIER"
# Update-Intervall in Sekunden (Standard: 60) # Wie oft Wetter & Zeit von der API abgerufen werden (in Sekunden)
# Empfohlen: 60300 (zu niedrige Werte können das API-Limit überschreiten)
update-interval: 60 update-interval: 60
# ------------------------------------------------------------
# Standard-Einstellungen (gelten wenn keine Welt-spezifischen
# Einstellungen definiert sind)
# ------------------------------------------------------------
defaults: defaults:
# Plugin für diese Welt aktiv?
enabled: true enabled: true
location: "Berlin,de" # Stadt,Land
units: "metric" # metric = °C, imperial = °F # Standort für Wetter & Zeit Format: "Stadt,Länderkürzel"
time-format: "24h" # oder "12h" # Beispiele: "Berlin,de" | "London,gb" | "New York,us"
display-actionbar: true location: "Berlin,de"
display-weather-icon: true
display-position: "top-right" # Temperatureinheit: "metric" (°C) oder "imperial" (°F)
padding-right: 100 units: "metric"
# Uhrzeitformat: "24h" oder "12h"
time-format: "24h"
# Soll das Ingame-Wetter mit der echten API synchronisiert werden?
# (Regen, Gewitter, Schnee, Klar etc.)
sync-in-game-weather: true sync-in-game-weather: true
# ------------------------------------------------------------
# Welt-spezifische Einstellungen
# Nicht definierte Felder erben vom "defaults"-Block oben.
# ------------------------------------------------------------
worlds: worlds:
world: world:
enabled: true enabled: true
location: "Berlin,de" location: "Berlin,de"
units: "metric" units: "metric"
time-format: "24h" time-format: "24h"
display-actionbar: true
display-weather-icon: true
display-position: "top-left"
padding-right: 50
sync-in-game-weather: true sync-in-game-weather: true
world_nether: world_nether:
# Nether hat kein Wetter/Tageslicht Plugin hier deaktivieren
enabled: false
location: "Berlin,de"
units: "metric"
time-format: "24h"
sync-in-game-weather: false
world_the_end:
# End hat kein Wetter/Tageslicht Plugin hier deaktivieren
enabled: false enabled: false
location: "Berlin,de" location: "Berlin,de"
units: "metric" units: "metric"
time-format: "24h" time-format: "24h"
display-actionbar: true
display-weather-icon: false
display-position: "top-right"
padding-right: 150
sync-in-game-weather: false sync-in-game-weather: false

View File

@@ -1,32 +1,43 @@
name: RealTimeWeather name: RealTimeWeather
version: 1.0 version: 1.5
main: dev.viper.weathertime.WeatherTimeSyncPlugin main: dev.viper.weathertime.WeatherTimeSyncPlugin
api-version: 1.21 api-version: 1.21
authors: [M_Viper]
description: Synchronizes real-time weather and time from OpenWeatherMap with your Minecraft world.
commands: commands:
wetter: wetter:
description: Manages real-time weather and time synchronization description: Manages real-time weather and time synchronization
usage: /<command> reload | setlocation <city,country> | query | info | gui | help usage: /<command> <reload|setlocation|query|mode|info|gui|help>
permission: realtimeweather.use permission: realtimeweather.use
weatherforecast: weatherforecast:
description: Shows the weather forecast for the player's location description: Shows the 5-day weather forecast for the player's location
usage: /<command> usage: /<command>
permission: realtimeweather.forecast permission: realtimeweather.forecast
toggleweather: toggleweather:
description: Toggles the weather display for the current world description: Toggles the scoreboard weather display for the current world
usage: /<command> usage: /<command>
permission: realtimeweather.toggle permission: realtimeweather.toggle
permissions: permissions:
realtimeweather.use: realtimeweather.use:
description: Allows usage of the /wetter command description: Allows usage of the /wetter command (query, info, gui, mode, help)
default: true default: true
children:
realtimeweather.setlocation: true
realtimeweather.setlocation:
description: Allows setting a custom weather location via /wetter setlocation
default: true
realtimeweather.forecast: realtimeweather.forecast:
description: Allows usage of the /weatherforecast command description: Allows usage of the /weatherforecast command
default: true default: true
realtimeweather.toggle: realtimeweather.toggle:
description: Allows usage of the /toggleweather command description: Allows toggling the scoreboard weather display via /toggleweather
default: true default: true
realtimeweather.reload: realtimeweather.reload:
description: Allows reloading the plugin configuration description: Allows reloading the plugin configuration via /wetter reload
default: op default: op