diff --git a/src/main/java/io/github/jack1424/realtimeweather/Configurator.java b/src/main/java/io/github/jack1424/realtimeweather/Configurator.java new file mode 100644 index 0000000..1c72477 --- /dev/null +++ b/src/main/java/io/github/jack1424/realtimeweather/Configurator.java @@ -0,0 +1,201 @@ +package io.github.jack1424.realtimeweather; + +import org.bukkit.configuration.file.FileConfiguration; +import org.json.simple.parser.ParseException; + +import javax.naming.ConfigurationException; +import java.io.IOException; +import java.time.ZoneId; +import java.time.zone.ZoneRulesException; +import java.util.Objects; +import java.util.TimeZone; + +public class Configurator { + private final RealTimeWeather rtw; + private final FileConfiguration configFile; + private TimeZone timeZone; + private boolean debug, timeEnabled, weatherEnabled, blockTimeSetCommand, blockWeatherCommand; + private long timeSyncInterval, weatherSyncInterval; + private String apiKey, lat, lon; + + public Configurator(RealTimeWeather rtw) { + this.rtw = rtw; + configFile = rtw.getConfig(); + + refreshValues(); + } + + public void refreshValues() { + setDebugEnabled(configFile.getBoolean("Debug")); + + setTimeEnabled(configFile.getBoolean("SyncTime")); + if (isTimeEnabled()) + try { + setBlockTimeSetCommand(configFile.getBoolean("BlockTimeSetCommand")); + setTimeSyncInterval(configFile.getLong("TimeSyncInterval")); + setTimeZone(configFile.getString("Timezone")); + } catch (ConfigurationException e) { + rtw.getLogger().severe((e.getMessage())); + rtw.getLogger().severe("Error loading time configuration. Check that the values in your configuration file are valid."); + rtw.getLogger().severe("Disabling time sync..."); + + setTimeEnabled(false); + } + + setWeatherEnabled(configFile.getBoolean("SyncWeather")); + if (isWeatherEnabled()) + try { + setBlockWeatherCommand(configFile.getBoolean("BlockWeatherCommand")); + setWeatherSyncInterval(configFile.getLong("WeatherSyncInterval")); + setAPIKey(configFile.getString("APIKey")); + setLat(configFile.getString("Latitude")); + setLon(configFile.getString("Longitude")); + } catch (ConfigurationException e) { + rtw.getLogger().severe(e.getMessage()); + rtw.getLogger().severe("Error loading weather configuration. Check that the values in your configuration file are valid."); + rtw.getLogger().severe("Disabling weather sync..."); + + setWeatherEnabled(false); + } + } + + public boolean debugEnabled() { + return debug; + } + + public void setDebugEnabled(boolean value) { + debug = value; + rtw.getLogger().warning("Debug set to " + value); + } + + public boolean isTimeEnabled() { + return timeEnabled; + } + + public void setTimeEnabled(boolean value) { + timeEnabled = value; + rtw.debug("SyncTime set to " + value); + } + + public boolean getBlockTimeSetCommand() { + return blockTimeSetCommand; + } + + public void setBlockTimeSetCommand(boolean value) { + blockTimeSetCommand = value; + rtw.debug("BlockTimeSetCommand set to " + value); + } + + public long getTimeSyncInterval() { + return timeSyncInterval; + } + + public void setTimeSyncInterval(long value) throws ConfigurationException { + if (value < 0) + throw new ConfigurationException("Time sync interval cannot be less than 0"); + + timeSyncInterval = value; + rtw.debug("TimeSyncInterval set to " + value); + } + + public TimeZone getTimeZone() { + return timeZone; + } + + public void setTimeZone(String value) throws ConfigurationException { + try { + timeZone = TimeZone.getTimeZone(ZoneId.of(Objects.requireNonNull(value))); + } catch (ZoneRulesException | NullPointerException e) { + throw new ConfigurationException("Timezone not valid"); + } + + rtw.debug("TimeZone set to " + value); + } + + public boolean isWeatherEnabled() { + return weatherEnabled; + } + + public void setWeatherEnabled(boolean value) { + weatherEnabled = value; + rtw.debug("SyncWeather set to " + value); + } + + public boolean getBlockWeatherCommand() { + return blockWeatherCommand; + } + + public void setBlockWeatherCommand(boolean value) { + blockWeatherCommand = value; + rtw.debug("BlockWeatherCommand set to " + value); + } + + public long getWeatherSyncInterval() { + return weatherSyncInterval; + } + + public void setWeatherSyncInterval(long value) throws ConfigurationException { + if (value < 0) + throw new ConfigurationException("WeatherSyncInterval cannot be less than 0"); + + weatherSyncInterval = value; + rtw.debug("WeatherSyncInterval set to " + value); + } + + public String getAPIKey() { + return apiKey; + } + + public void setAPIKey(String value) throws ConfigurationException { + try { + new RequestObject(Objects.requireNonNull(value), "0", "0"); + } catch (NullPointerException e) { + throw new ConfigurationException("The APIKey cannot be blank"); + } + catch (IOException | ParseException e) { + e.printStackTrace(); + throw new ConfigurationException("There was an error when validating this APIKey (this does not mean that the API key is invalid)"); + } + + apiKey = value; + rtw.debug("APIKey set to " + value); + } + + public String getLat() { + return lat; + } + + public void setLat(String value) throws ConfigurationException { + try { + double doubleValue = Double.parseDouble(Objects.requireNonNull(value)); + if (doubleValue < -90 || doubleValue > 90) + throw new ConfigurationException("The entered latitude cannot be less than -90 or greater than 90"); + } catch (NullPointerException e) { + throw new ConfigurationException("The latitude cannot be blank"); + } catch (NumberFormatException e) { + throw new ConfigurationException("The entered latitude might not be a number (or is too long)"); + } + + lat = value; + rtw.debug("Latitude set to " + value); + } + + public String getLon() { + return lon; + } + + public void setLon(String value) throws ConfigurationException { + try { + double doubleValue = Double.parseDouble(Objects.requireNonNull(value)); + if (doubleValue < -180 || doubleValue > 180) + throw new ConfigurationException("The entered longitude cannot be less than -180 or greater than 180"); + } catch (NullPointerException e) { + throw new ConfigurationException("The longitude cannot be blank"); + } catch (NumberFormatException e) { + throw new ConfigurationException("The entered longitude might not be a number (or is too long)"); + } + + lon = value; + rtw.debug("Longitude set to " + value); + } +} diff --git a/src/main/java/io/github/jack1424/realtimeweather/EventHandler.java b/src/main/java/io/github/jack1424/realtimeweather/EventHandler.java new file mode 100644 index 0000000..dcc973f --- /dev/null +++ b/src/main/java/io/github/jack1424/realtimeweather/EventHandler.java @@ -0,0 +1,32 @@ +package io.github.jack1424.realtimeweather; + +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.server.ServerCommandEvent; + +public class EventHandler implements Listener { + private final Configurator config; + + public EventHandler(RealTimeWeather rtw) { + config = rtw.getConfigurator(); + } + + @org.bukkit.event.EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onOperatorSet(PlayerCommandPreprocessEvent event) { + if ((config.getBlockTimeSetCommand() && config.isTimeEnabled() && event.getMessage().contains("time set")) + || (config.getBlockWeatherCommand() && config.isWeatherEnabled() && event.getMessage().contains("weather"))) { + event.setCancelled(true); + event.getPlayer().sendMessage("Command cancelled (RealTimeWeather is controlling this)"); + } + } + + @org.bukkit.event.EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onOperatorSetConsole(ServerCommandEvent event) { + if ((config.getBlockTimeSetCommand() && config.isTimeEnabled() && event.getCommand().contains("time set")) + || (config.getBlockWeatherCommand() && config.isWeatherEnabled() && event.getCommand().contains("weather"))) { + event.setCancelled(true); + event.getSender().sendMessage("Command cancelled (RealTimeWeather is controlling this)"); + } + } +} diff --git a/src/main/java/io/github/jack1424/realtimeweather/RealTimeWeather.java b/src/main/java/io/github/jack1424/realtimeweather/RealTimeWeather.java index 6f0158c..12500b6 100644 --- a/src/main/java/io/github/jack1424/realtimeweather/RealTimeWeather.java +++ b/src/main/java/io/github/jack1424/realtimeweather/RealTimeWeather.java @@ -3,49 +3,39 @@ package io.github.jack1424.realtimeweather; import org.bstats.bukkit.Metrics; import org.bstats.charts.SimplePie; 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 java.time.ZoneId; -import java.time.zone.ZoneRulesException; import java.util.Calendar; -import java.util.Objects; -import java.util.TimeZone; import java.util.logging.Logger; @SuppressWarnings("deprecation") -public final class RealTimeWeather extends JavaPlugin implements Listener { +public final class RealTimeWeather extends JavaPlugin { private Logger logger; - private ZoneId timezone; - private boolean timeEnabled, weatherEnabled, debug, blockTimeSetCommand, blockWeatherCommand; + private Configurator config; @Override public void onEnable() { logger = getLogger(); logger.info("Starting..."); + logger.info("Loading configuration..."); saveDefaultConfig(); + config = new Configurator(this); - debug = getConfig().getBoolean("Debug"); - - timeEnabled = getConfig().getBoolean("SyncTime"); - if (timeEnabled) + debug("TimeSync: " + config.isTimeEnabled()); + if (config.isTimeEnabled()) setupTime(); - weatherEnabled = getConfig().getBoolean("SyncWeather"); - if (weatherEnabled) + debug("WeatherSync: " + config.isWeatherEnabled()); + if (config.isWeatherEnabled()) setupWeather(); - getServer().getPluginManager().registerEvents(this, this); + getServer().getPluginManager().registerEvents(new EventHandler(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))); + metrics.addCustomChart(new SimplePie("weather_sync_enabled", () -> String.valueOf(config.isWeatherEnabled()))); + metrics.addCustomChart(new SimplePie("time_sync_enabled", () -> String.valueOf(config.isTimeEnabled()))); logger.info("Started!"); } @@ -56,112 +46,55 @@ public final class RealTimeWeather extends JavaPlugin implements Listener { if (world.getEnvironment().equals(World.Environment.NORMAL)) { debug("Re-enabling normal daylight and weather cycles..."); - if (timeEnabled) + if (config.isTimeEnabled()) world.setGameRuleValue("doDaylightCycle", "true"); - if (weatherEnabled) + if (config.isWeatherEnabled()) world.setGameRuleValue("doWeatherCycle", "true"); } logger.info("Stopping..."); } - @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) - public void onOperatorSet(PlayerCommandPreprocessEvent event) { - if ((blockTimeSetCommand && timeEnabled && event.getMessage().contains("time set")) || (blockWeatherCommand && 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 ((blockTimeSetCommand && timeEnabled && event.getCommand().contains("time set")) || (blockWeatherCommand && weatherEnabled && event.getCommand().contains("weather"))) { - event.setCancelled(true); - event.getSender().sendMessage("Command cancelled (RealTimeWeather is controlling this)"); - } - } - private void setupTime() { - long timeSyncInterval; - - try { - timezone = ZoneId.of(Objects.requireNonNull(getConfig().getString("Timezone"))); - timeSyncInterval = getConfig().getLong("TimeSyncInterval"); - blockTimeSetCommand = getConfig().getBoolean("BlockTimeSetCommand"); - } 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..."); - debug("Syncing time with " + timezone.toString()); + debug("Syncing time with " + config.getTimeZone().getDisplayName()); for (World world : getServer().getWorlds()) if (world.getEnvironment().equals(World.Environment.NORMAL)) world.setGameRuleValue("doDaylightCycle", "false"); getServer().getScheduler().scheduleSyncRepeatingTask(this, () -> { - if (timeEnabled) { - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timezone)); + if (config.isTimeEnabled()) { + Calendar cal = Calendar.getInstance(config.getTimeZone()); 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) + 1)) - 6000); } - }, 0L, timeSyncInterval); + }, 0L, config.getTimeSyncInterval()); } private void setupWeather() { - long weatherSyncInterval; - - String apiKey = getConfig().getString("APIKey"); - String lat = getConfig().getString("Latitude"), lon = getConfig().getString("Longitude"); - try { - weatherSyncInterval = getConfig().getLong("WeatherSyncInterval"); - blockWeatherCommand = getConfig().getBoolean("blockWeatherCommand"); - - RequestObject request = new RequestObject(apiKey, lat, lon); - - int response = request.getResponseCode(); - if (response > 499) { - logger.severe("There was a server error when requesting weather information. Please try again later"); - throw new Exception("Server/client error"); - } - else if (response > 399) { - String message = "Error when getting weather information: "; - - if (response == 401) - logger.severe(message + "API key incorrect"); - else if (response == 404) - logger.severe(message + "Zip/Country code incorrect"); - else - logger.severe("Unknown error"); - - logger.severe("Please check that the values set in the config file are correct"); - - throw new Exception("Configuration error"); - } + new RequestObject(config.getAPIKey(), config.getLat(), config.getLon()); } catch (Exception e) { - debug(e.getMessage()); + logger.severe(e.getMessage()); logger.severe("Disabling weather sync..."); - weatherEnabled = false; + config.setWeatherEnabled(false); return; } for (World world : getServer().getWorlds()) if (world.getEnvironment().equals(World.Environment.NORMAL)) world.setGameRuleValue("doWeatherCycle", "false"); - + + debug("Enabling weather sync..."); + getServer().getScheduler().scheduleSyncRepeatingTask(this, () -> { debug("Syncing weather..."); try { - RequestObject request = new RequestObject(apiKey, lat, lon); + RequestObject request = new RequestObject(config.getAPIKey(), config.getLat(), config.getLon()); debug("Setting weather (Rain: " + request.isRaining() + ", Thunder: " + request.isThundering() + ")..."); for (World world : getServer().getWorlds()) @@ -173,11 +106,17 @@ public final class RealTimeWeather extends JavaPlugin implements Listener { logger.severe("There was an error when attempting to get weather information"); debug(e.getMessage()); } - }, 0L, weatherSyncInterval); + }, 0L, config.getWeatherSyncInterval()); + + debug("Weather sync enabled"); } - private void debug(String message) { - if (debug) { + public Configurator getConfigurator() { + return config; + } + + public void debug(String message) { + if (config.debugEnabled()) { logger.info("[DEBUG] " + message); } } diff --git a/src/main/java/io/github/jack1424/realtimeweather/RequestObject.java b/src/main/java/io/github/jack1424/realtimeweather/RequestObject.java index 5c494cf..5768ad2 100644 --- a/src/main/java/io/github/jack1424/realtimeweather/RequestObject.java +++ b/src/main/java/io/github/jack1424/realtimeweather/RequestObject.java @@ -5,24 +5,34 @@ import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; +import javax.naming.ConfigurationException; import javax.net.ssl.HttpsURLConnection; import java.io.IOException; +import java.net.ProtocolException; import java.net.URL; import java.util.Scanner; public class RequestObject { - private final int responseCode; private boolean rain = false, thunder = false; - public RequestObject(String apiKey, String lat, String lon) throws IOException, ParseException { + public RequestObject(String apiKey, String lat, String lon) throws IOException, ParseException, ConfigurationException { URL url = new URL(String.format("https://api.openweathermap.org/data/2.5/weather?lat=%s&lon=%s&appid=%s", lat, lon, apiKey)); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); con.setRequestMethod("GET"); con.connect(); - responseCode = con.getResponseCode(); - if (responseCode > 399) - return; + int responseCode = con.getResponseCode(); + if (responseCode > 499) { + throw new ProtocolException("Server/client error (HTTP error " + responseCode + ")"); + } + else if (responseCode > 399) { + String message = "Error when getting weather information: "; + + if (responseCode == 401) + throw new ConfigurationException(message + "API key invalid. Check the Wiki for troubleshooting steps."); + else + throw new ProtocolException(message + "Unknown error"); + } Scanner scanner = new Scanner(url.openStream()); StringBuilder data = new StringBuilder(); @@ -46,10 +56,6 @@ public class RequestObject { } } - public int getResponseCode() { - return responseCode; - } - public boolean isRaining() { return rain; }