Files
RealTimeWeather/src/main/java/io/github/jack1424/realtimeweather/RealTimeWeather.java
Jack Fitch 66350d3b23 add bStats
2022-10-22 11:55:44 -04:00

210 lines
6.9 KiB
Java

package io.github.jack1424.realtimeweather;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bukkit.GameRule;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.server.ServerCommandEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import javax.net.ssl.HttpsURLConnection;
import java.io.IOException;
import java.net.URL;
import java.time.ZoneId;
import java.time.zone.ZoneRulesException;
import java.util.*;
import java.util.logging.Logger;
public final class RealTimeWeather extends JavaPlugin implements Listener {
private Logger logger;
private ZoneId timezone;
private boolean timeEnabled, weatherEnabled, debug;
@Override
public void onEnable() {
logger = getLogger();
logger.info("Starting...");
saveDefaultConfig();
debug = getConfig().getBoolean("Debug");
timeEnabled = getConfig().getBoolean("SyncTime");
if (timeEnabled)
setupTime();
weatherEnabled = getConfig().getBoolean("SyncWeather");
if (weatherEnabled)
setupWeather();
getServer().getPluginManager().registerEvents(this, this);
debug("Enabling metrics...");
Metrics metrics = new Metrics(this, 16709);
metrics.addCustomChart(new SimplePie("weather_sync_enabled", () -> String.valueOf(weatherEnabled)));
metrics.addCustomChart(new SimplePie("time_sync_enabled", () -> String.valueOf(timeEnabled)));
logger.info("Started!");
}
@Override
public void onDisable() {
for (World world : getServer().getWorlds())
if (world.getEnvironment().equals(World.Environment.NORMAL)) {
debug("Re-enabling normal daylight and weather cycles...");
if (timeEnabled)
world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, true);
if (weatherEnabled)
world.setGameRule(GameRule.DO_WEATHER_CYCLE, true);
}
logger.info("Stopping...");
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onOperatorSet(PlayerCommandPreprocessEvent event) {
if ((timeEnabled && event.getMessage().contains("time set")) || (weatherEnabled && event.getMessage().contains("weather"))) {
event.setCancelled(true);
event.getPlayer().sendMessage("Command cancelled (RealTimeWeather is controlling this)");
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onOperatorSetConsole(ServerCommandEvent event) {
if ((timeEnabled && event.getCommand().contains("time set")) || (weatherEnabled && event.getCommand().contains("weather"))) {
event.setCancelled(true);
event.getSender().sendMessage("Command cancelled (RealTimeWeather is controlling this)");
}
}
private void setupTime() {
try {
timezone = ZoneId.of(Objects.requireNonNull(getConfig().getString("Timezone")));
} catch (NullPointerException|ZoneRulesException e) {
logger.severe("Error loading timezone. Check that the values in your configuration file are valid.");
debug(e.getMessage());
logger.severe("Disabling time sync...");
timeEnabled = false;
return;
}
debug("Enabling time zone sync (every second)");
debug("Syncing time with " + timezone.toString());
for (World world : getServer().getWorlds())
if (world.getEnvironment().equals(World.Environment.NORMAL))
world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false);
getServer().getScheduler().scheduleSyncRepeatingTask(this, () -> {
if (timeEnabled) {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timezone));
for (World world : getServer().getWorlds())
if (world.getEnvironment().equals(World.Environment.NORMAL))
world.setTime((1000 * cal.get(Calendar.HOUR_OF_DAY)) + (16 * cal.get(Calendar.MINUTE)) - 6000); // TODO: Time is one minute behind
}
}, 0L, 20L); // TODO: Does this really need to update every second?
}
private void setupWeather() {
String apiKey = getConfig().getString("APIKey");
String zipCode = getConfig().getString("ZipCode");
String countryCode = getConfig().getString("CountryCode");
String lat, lon;
try {
HttpsURLConnection con = (HttpsURLConnection) new URL(String.format("https://api.openweathermap.org/geo/1.0/zip?zip=%s,%s&appid=%s", zipCode, countryCode, apiKey)).openConnection();
con.setRequestMethod("GET");
con.connect();
int response = con.getResponseCode();
if (response > 499) {
logger.severe("There was a server error when requesting weather information. Please try again later");
throw new Exception("Server error");
}
else if (response > 399) {
String message = "Error when getting weather information: ";
switch (response) {
case 401 -> logger.severe(message + "API key incorrect");
case 404 -> logger.severe(message + "Zip/Country code incorrect");
default -> logger.severe("Unknown error");
}
logger.severe("Please check that the values set in the config file are correct");
throw new Exception("Configuration error");
}
JSONObject obj = makeWeatherRequest(con.getURL());
lat = String.valueOf(obj.get("lat"));
lon = String.valueOf(obj.get("lon"));
} catch (Exception e) {
debug(e.getMessage());
logger.severe("Disabling weather sync...");
weatherEnabled = false;
return;
}
getServer().getScheduler().scheduleSyncRepeatingTask(this, () -> {
debug("Syncing weather...");
boolean rain = false, thunder = false;
try {
JSONObject obj = makeWeatherRequest(new URL(String.format("https://api.openweathermap.org/data/2.5/weather?lat=%s&lon=%s&appid=%s", lat, lon, apiKey)));
JSONArray conditions = (JSONArray) obj.get("weather");
for (Object rawCondition : conditions) {
JSONObject condition = (JSONObject) rawCondition;
int id = Integer.parseInt(String.valueOf(condition.get("id")));
debug("Weather ID: " + id);
while (id >= 10)
id /= 10;
if (!rain)
rain = id == 2 || id == 3 || id == 5 || id == 6;
if (!thunder)
thunder = id == 2;
}
} catch (Exception e) {
logger.severe("There was an error when attempting to get weather information");
debug(e.getMessage());
}
debug("Setting weather (Rain: " + rain + ", Thunder: " + thunder + ")...");
for (World world : getServer().getWorlds())
if (world.getEnvironment().equals(World.Environment.NORMAL)) {
world.setStorm(rain);
world.setThundering(thunder);
}
}, 0L, 6000L);
}
private JSONObject makeWeatherRequest(URL url) throws IOException, ParseException {
Scanner scanner = new Scanner(url.openStream());
StringBuilder data = new StringBuilder();
while (scanner.hasNext()) {
data.append(scanner.nextLine());
}
scanner.close();
JSONParser parser = new JSONParser();
return (JSONObject) parser.parse(data.toString());
}
private void debug(String message) {
if (debug) {
logger.info("[DEBUG] " + message);
}
}
}