diff --git a/.classpath b/.classpath index f7e4a1d..5d5961d 100644 --- a/.classpath +++ b/.classpath @@ -14,20 +14,21 @@ + - - + - + + diff --git a/DOMAINS.md b/DOMAINS.md new file mode 100644 index 0000000..3924204 --- /dev/null +++ b/DOMAINS.md @@ -0,0 +1,7 @@ +If you're using a firewall, you must whitelist the following domains: +- weather: + * api.openweathermap.org +- thunder: + * ws1.blitzortung.org + * ws7.blitzortung.org + * ws8.blitzortung.org \ No newline at end of file diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml new file mode 100644 index 0000000..4aaa9e1 --- /dev/null +++ b/dependency-reduced-pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + eu.m724 + realweather + 0.9-SNAPSHOT + + + + true + src/main/resources + + + + + maven-shade-plugin + 3.6.0 + + + package + + shade + + + true + + + eu.m724:wtapi + org.java-websocket:Java-WebSocket + + + + + + + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + 724rocks + https://git.724.rocks/api/packages/Minecon724/maven + + + + + org.spigotmc + spigot-api + 1.20.6-R0.1-SNAPSHOT + provided + + + + 17 + 17 + + diff --git a/pom.xml b/pom.xml index c5030e3..2f0eab6 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ eu.m724 wtapi - 0.2 + 0.3 @@ -57,6 +57,7 @@ eu.m724:wtapi + org.java-websocket:Java-WebSocket diff --git a/src/main/java/eu/m724/realweather/GlobalConstants.java b/src/main/java/eu/m724/realweather/GlobalConstants.java new file mode 100644 index 0000000..bb4a5ba --- /dev/null +++ b/src/main/java/eu/m724/realweather/GlobalConstants.java @@ -0,0 +1,33 @@ +package eu.m724.realweather; + +import org.bukkit.plugin.Plugin; + +import eu.m724.realweather.mapper.Mapper; +import eu.m724.realweather.thunder.ThunderConfig; +import eu.m724.realweather.time.TimeConfig; +import eu.m724.realweather.weather.WeatherConfig; + +public class GlobalConstants { + static WeatherConfig weatherConfig; + static TimeConfig timeConfig; + static ThunderConfig thunderConfig; + static Mapper mapper; + static Plugin plugin; + + public static WeatherConfig getWeatherConfig() { + return weatherConfig; + } + public static TimeConfig getTimeConfig() { + return timeConfig; + } + public static ThunderConfig getThunderConfig() { + return thunderConfig; + } + public static Mapper getMapper() { + return mapper; + } + public static Plugin getPlugin() { + return plugin; + } + +} diff --git a/src/main/java/eu/m724/realweather/RealWeatherPlugin.java b/src/main/java/eu/m724/realweather/RealWeatherPlugin.java index 4299f62..c9d5ecc 100644 --- a/src/main/java/eu/m724/realweather/RealWeatherPlugin.java +++ b/src/main/java/eu/m724/realweather/RealWeatherPlugin.java @@ -11,8 +11,10 @@ import org.bukkit.plugin.java.JavaPlugin; import com.google.common.base.Charsets; +import eu.m724.realweather.commands.GeoCommand; import eu.m724.realweather.mapper.Mapper; import eu.m724.realweather.mapper.MapperConfig; +import eu.m724.realweather.mapper.MapperEventHandler; import eu.m724.realweather.object.UserException; import eu.m724.realweather.thunder.ThunderConfig; import eu.m724.realweather.thunder.ThunderMaster; @@ -38,7 +40,7 @@ public class RealWeatherPlugin extends JavaPlugin { logger = getLogger(); File dataFolder = getDataFolder(); - File modulesFolder = new File(dataFolder, "modules"); + File modulesFolder = new File("modules"); modulesFolder.mkdir(); YamlConfiguration configuration, @@ -47,12 +49,17 @@ public class RealWeatherPlugin extends JavaPlugin { DebugLogger.info("loading configurations", 1); + if (!new File(dataFolder, "config.yml").exists()) { + logger.info("This is the first run of this plugin."); + logger.info("Please shutdown the server and input your API keys and settings"); + } + try { - configuration = getConfig(new File(dataFolder, "config.yml")); - mapConfiguration = getConfig(new File(dataFolder, "map.yml")); - weatherConfiguration = getConfig(new File(modulesFolder, "weather.yml")); - thunderConfiguration = getConfig(new File(modulesFolder, "thunder.yml")); - timeConfiguration = getConfig(new File(modulesFolder, "time.yml")); + configuration = getConfig("config.yml"); + mapConfiguration = getConfig("map.yml"); + weatherConfiguration = getConfig("modules/weather.yml"); + thunderConfiguration = getConfig("modules/thunder.yml"); + timeConfiguration = getConfig("modules/time.yml"); } catch (IOException e) { logger.severe("Failed to load config!"); e.printStackTrace(); @@ -64,29 +71,33 @@ public class RealWeatherPlugin extends JavaPlugin { DebugLogger.baseLogger = logger; DebugLogger.debugLevel = configuration.getInt("debug"); - if (configuration.getBoolean("enabled")) { + if (!configuration.getBoolean("enabled")) { logger.info("plugin disabled by admin"); getServer().getPluginManager().disablePlugin(this); + return; } + + GlobalConstants.plugin = this; DebugLogger.info("loading mapper", 1); - mapper = new Mapper( + GlobalConstants.mapper = new Mapper( MapperConfig.fromConfiguration(mapConfiguration)); + GlobalConstants.mapper.registerEvents(this); try { DebugLogger.info("loading weather", 1); - weatherMaster = new WeatherMaster( - WeatherConfig.fromConfiguration(weatherConfiguration), mapper); + GlobalConstants.weatherConfig = WeatherConfig.fromConfiguration(weatherConfiguration); + weatherMaster = new WeatherMaster(GlobalConstants.weatherConfig); weatherMaster.init(); DebugLogger.info("loading thunder", 1); - thunderMaster = new ThunderMaster( - ThunderConfig.fromConfiguration(thunderConfiguration), mapper, this); + GlobalConstants.thunderConfig = ThunderConfig.fromConfiguration(thunderConfiguration); + thunderMaster = new ThunderMaster(GlobalConstants.thunderConfig); thunderMaster.init(); DebugLogger.info("loading time", 1); - timeMaster = new TimeMaster( - TimeConfig.fromConfiguration(timeConfiguration), mapper); + GlobalConstants.timeConfig = TimeConfig.fromConfiguration(timeConfiguration); + timeMaster = new TimeMaster(GlobalConstants.timeConfig); timeMaster.init(); } catch (UserException e) { logger.severe("There are errors in your config:"); @@ -102,15 +113,18 @@ public class RealWeatherPlugin extends JavaPlugin { getServer().getPluginManager().disablePlugin(this); } + + getCommand("geo").setExecutor(new GeoCommand()); DebugLogger.info("ended loading", 1); } - public YamlConfiguration getConfig(File configFile) throws IOException { + public YamlConfiguration getConfig(String configFilePath) throws IOException { + File configFile = new File(this.getDataFolder(), configFilePath); YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); if (!configFile.exists()) { - final InputStream defConfigStream = getResource("config.yml"); + final InputStream defConfigStream = getResource(configFilePath); if (defConfigStream == null) return null; diff --git a/src/main/java/eu/m724/realweather/commands/GeoCommand.java b/src/main/java/eu/m724/realweather/commands/GeoCommand.java new file mode 100644 index 0000000..29cea71 --- /dev/null +++ b/src/main/java/eu/m724/realweather/commands/GeoCommand.java @@ -0,0 +1,56 @@ +package eu.m724.realweather.commands; + + +import org.bukkit.Location; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import eu.m724.realweather.GlobalConstants; +import eu.m724.wtapi.object.Coordinates; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; + +public class GeoCommand implements CommandExecutor { + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + Player player = sender instanceof Player ? (Player) sender : null; + + if (args.length == 0) { + if (player != null) { + Location location = player.getLocation(); + Coordinates coordinates = GlobalConstants.getMapper().locationToCoordinates(location); + String text = String.format("Position: %f %f %f\nGeolocation: %f %f", location.getX(), location.getY(), location.getZ(), coordinates.latitude, coordinates.longitude); + BaseComponent component = TextComponent.fromLegacy(text); // TODO add color + player.spigot().sendMessage(component); + } else { + sender.sendMessage("Add arguments to use this command in console"); + } + } else if (args.length >= 2) { + double latitude = Double.parseDouble(args[0]); + double longitude = Double.parseDouble(args[0]); + + Coordinates coordinates = new Coordinates(latitude, longitude); + Location location = GlobalConstants.getMapper().coordinatesToLocation(player.getWorld(), coordinates); + + String text = String.format("Position: %f %f %f\nGeolocation: %f %f", location.getX(), location.getY(), location.getZ(), coordinates.latitude, coordinates.longitude); + BaseComponent component = TextComponent.fromLegacy(text); + player.spigot().sendMessage(component); + + if (args.length == 3) { + if (args[2].equalsIgnoreCase("tp") && player != null && player.hasPermission("realweather.geo.tp")) { + Location targetLoc = + location.getWorld().getHighestBlockAt(location).getLocation().add(0, 1, 0); + player.teleport(targetLoc); + } + } + + } else { + sender.sendMessage("Not enough arguments"); + } + return true; + } + +} diff --git a/src/main/java/eu/m724/realweather/mapper/Mapper.java b/src/main/java/eu/m724/realweather/mapper/Mapper.java index 27c843f..f1b1a08 100644 --- a/src/main/java/eu/m724/realweather/mapper/Mapper.java +++ b/src/main/java/eu/m724/realweather/mapper/Mapper.java @@ -1,20 +1,26 @@ package eu.m724.realweather.mapper; +import java.util.ArrayList; import java.util.List; import org.bukkit.Location; import org.bukkit.World; +import org.bukkit.plugin.Plugin; import eu.m724.wtapi.object.Coordinates; public class Mapper { private MapperConfig config; - private List worlds; + private List worlds = new ArrayList<>(); public Mapper(MapperConfig config) { this.config = config; } + public void registerEvents(Plugin plugin) { + plugin.getServer().getPluginManager().registerEvents(new MapperEventHandler(this), plugin); + } + public Coordinates locationToCoordinates(Location location) { double latitude = -location.getZ() / config.scaleLatitude; double longitude = location.getX() / config.scaleLongitude; diff --git a/src/main/java/eu/m724/realweather/thunder/ThunderConfig.java b/src/main/java/eu/m724/realweather/thunder/ThunderConfig.java index 24be3c1..1a54d70 100644 --- a/src/main/java/eu/m724/realweather/thunder/ThunderConfig.java +++ b/src/main/java/eu/m724/realweather/thunder/ThunderConfig.java @@ -2,8 +2,6 @@ package eu.m724.realweather.thunder; import org.bukkit.configuration.ConfigurationSection; -import eu.m724.realweather.time.TimeConfig; - public class ThunderConfig { public boolean enabled; diff --git a/src/main/java/eu/m724/realweather/thunder/ThunderMaster.java b/src/main/java/eu/m724/realweather/thunder/ThunderMaster.java index d484d98..b2d5dc2 100644 --- a/src/main/java/eu/m724/realweather/thunder/ThunderMaster.java +++ b/src/main/java/eu/m724/realweather/thunder/ThunderMaster.java @@ -2,32 +2,26 @@ package eu.m724.realweather.thunder; import java.util.ArrayList; -import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import eu.m724.realweather.DebugLogger; +import eu.m724.realweather.GlobalConstants; import eu.m724.realweather.mapper.Mapper; import eu.m724.realweather.object.UserException; -import eu.m724.wtapi.provider.WeatherProvider; import eu.m724.wtapi.provider.exception.ProviderException; -import eu.m724.wtapi.provider.impl.openweathermap.OpenWeatherMapProvider; import eu.m724.wtapi.thunder.ThunderProvider; -import eu.m724.wtapi.thunder.impl.lightningmaps.LightningMapsProvider; -import eu.m724.wtapi.thunder.impl.lightningmaps.TimedStrike; +import eu.m724.wtapi.thunder.impl.blitzortung.BlitzortungProvider; public class ThunderMaster { private ThunderConfig config; - private Mapper mapper; private ThunderProvider provider; - private Plugin plugin; private ThunderTask thunderTask; - ArrayList strikes = new ArrayList<>(); + private Mapper mapper = GlobalConstants.getMapper(); + private Plugin plugin = GlobalConstants.getPlugin(); - public ThunderMaster(ThunderConfig config, Mapper mapper, Plugin plugin) { + public ThunderMaster(ThunderConfig config) { this.config = config; - this.mapper = mapper; - this.plugin = plugin; } /** @@ -46,11 +40,8 @@ public class ThunderMaster { provider.init(); - provider.registerStrikeHandler(coords -> { - strikes.add(new TimedStrike(System.currentTimeMillis() + provider.getDelay(), coords)); - }); - - thunderTask = new ThunderTask(this, mapper); + thunderTask = new ThunderTask(provider); + thunderTask.init(); thunderTask.runTaskTimer(plugin, 0, config.refresh); DebugLogger.info("thunder loaded", 1); @@ -58,8 +49,8 @@ public class ThunderMaster { private ThunderProvider createProvider() { switch (config.provider) { - case "lightningmaps": - return new LightningMapsProvider(); + case "blitzortung": + return new BlitzortungProvider(); } return null; diff --git a/src/main/java/eu/m724/realweather/thunder/ThunderTask.java b/src/main/java/eu/m724/realweather/thunder/ThunderTask.java index 2da03e1..cc1fc86 100644 --- a/src/main/java/eu/m724/realweather/thunder/ThunderTask.java +++ b/src/main/java/eu/m724/realweather/thunder/ThunderTask.java @@ -1,38 +1,53 @@ package eu.m724.realweather.thunder; +import java.util.ArrayList; + import org.bukkit.Location; import org.bukkit.entity.EntityType; import org.bukkit.scheduler.BukkitRunnable; import eu.m724.realweather.DebugLogger; +import eu.m724.realweather.GlobalConstants; import eu.m724.realweather.mapper.Mapper; -import eu.m724.wtapi.thunder.impl.lightningmaps.TimedStrike; +import eu.m724.wtapi.thunder.ThunderProvider; +import eu.m724.wtapi.thunder.impl.blitzortung.TimedStrike; class ThunderTask extends BukkitRunnable { - private ThunderMaster thunderMaster; - private Mapper mapper; + private ThunderProvider thunderProvider; + private Mapper mapper = GlobalConstants.getMapper(); + private ArrayList strikes = new ArrayList<>(); - public ThunderTask(ThunderMaster thunderMaster, Mapper mapper) { - this.thunderMaster = thunderMaster; - this.mapper = mapper; + public ThunderTask(ThunderProvider thunderProvider) { + this.thunderProvider = thunderProvider; + } + + public void init() { + thunderProvider.registerStrikeHandler(coords -> { + strikes.add(new TimedStrike(System.currentTimeMillis() + thunderProvider.getDelay(), coords)); + }); + thunderProvider.start(); + DebugLogger.info("thunderprovider started", 3); } @Override public void run() { DebugLogger.info("thundertask running", 3); - while (thunderMaster.strikes.size() > 0) { - TimedStrike strike = thunderMaster.strikes.get(0); - thunderMaster.strikes.remove(0); + thunderProvider.tick(); + + while (strikes.size() > 0) { + TimedStrike strike = strikes.get(0); + strikes.remove(0); DebugLogger.info("strike: %f %f", 2, strike.coordinates.latitude, strike.coordinates.longitude); mapper.getWorlds().forEach(w -> { Location location = mapper.coordinatesToLocation(w, strike.coordinates); - DebugLogger.info("in %s that converts to: %d %d %d", 2, w.getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ()); + DebugLogger.info("in %s that converts to: %d %d", 2, w.getName(), location.getBlockX(), location.getBlockZ()); - if (w.getChunkAt(location).isLoaded()) { - location.setY(w.getHighestBlockYAt(location)); - w.spawnEntity(location, EntityType.LIGHTNING_BOLT); + // for some reason all isloaded etc methods utilizing the Chunk object actually load that chunk before + if (w.isChunkLoaded(location.getBlockX() / 16, location.getBlockZ() / 16)) { + location.setY(w.getHighestBlockYAt(location) + 1); + w.strikeLightning(location); DebugLogger.info("spawnd lightning in %s on y level %d", 2, w.getName(), location.getBlockY()); } diff --git a/src/main/java/eu/m724/realweather/time/TimeMaster.java b/src/main/java/eu/m724/realweather/time/TimeMaster.java index 5008fd8..fb46b74 100644 --- a/src/main/java/eu/m724/realweather/time/TimeMaster.java +++ b/src/main/java/eu/m724/realweather/time/TimeMaster.java @@ -1,23 +1,16 @@ package eu.m724.realweather.time; -import java.util.ArrayList; - import eu.m724.realweather.DebugLogger; +import eu.m724.realweather.GlobalConstants; import eu.m724.realweather.mapper.Mapper; import eu.m724.realweather.object.UserException; -import eu.m724.realweather.thunder.ThunderConfig; -import eu.m724.wtapi.provider.exception.ProviderException; -import eu.m724.wtapi.thunder.ThunderProvider; -import eu.m724.wtapi.thunder.impl.lightningmaps.LightningMapsProvider; -import eu.m724.wtapi.thunder.impl.lightningmaps.TimedStrike; public class TimeMaster { private TimeConfig config; - private Mapper mapper; + private Mapper mapper = GlobalConstants.getMapper(); - public TimeMaster(TimeConfig config, Mapper mapper) { + public TimeMaster(TimeConfig config) { this.config = config; - this.mapper = mapper; } /** diff --git a/src/main/java/eu/m724/realweather/weather/AsyncWeatherRetrieveTask.java b/src/main/java/eu/m724/realweather/weather/AsyncWeatherRetrieveTask.java new file mode 100644 index 0000000..1e16a8a --- /dev/null +++ b/src/main/java/eu/m724/realweather/weather/AsyncWeatherRetrieveTask.java @@ -0,0 +1,106 @@ +package eu.m724.realweather.weather; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +import org.bukkit.Server; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +import eu.m724.realweather.DebugLogger; +import eu.m724.realweather.GlobalConstants; +import eu.m724.realweather.mapper.Mapper; +import eu.m724.realweather.weather.event.AsyncWeatherUpdateEvent; +import eu.m724.wtapi.object.Coordinates; +import eu.m724.wtapi.object.Weather; +import eu.m724.wtapi.provider.WeatherProvider; + +public class AsyncWeatherRetrieveTask extends BukkitRunnable { + private WeatherProvider weatherProvider; + private boolean dynamic; // TODO handle config some other way + + private Mapper mapper = GlobalConstants.getMapper(); + private Plugin plugin = GlobalConstants.getPlugin(); + private Server server = plugin.getServer(); + + public AsyncWeatherRetrieveTask(WeatherProvider weatherProvider, boolean dynamic) { + this.weatherProvider = weatherProvider; + this.dynamic = dynamic; + } + + @Override + public void run() { + long delay = 6000; + + if (dynamic) { + if (server.getOnlinePlayers().size() == 0) return; + + List players = server.getOnlinePlayers().stream() + .filter(player -> player.hasPermission("realweather.dynamic")) + .filter(player -> mapper.getWorlds().contains(player.getWorld())) + .collect(Collectors.toUnmodifiableList()); + + Coordinates[] coordinates = players.stream() + .map(player -> mapper.locationToCoordinates(player.getLocation())) + .toArray(Coordinates[]::new); + + CompletableFuture weathersFuture = + weatherProvider.getWeatherBulk(coordinates); + + float hourly = weatherProvider.getQuotaHourly() / (float)(weatherProvider.getBulkLimit() * players.size()); + int minTickDelay = (int) (72000 / hourly); + + delay = Math.max(6000, minTickDelay); + + try { + Weather[] weathers = weathersFuture.join(); + for (int i=0; i 0) + e.printStackTrace(); + + delay = 200; + } + } else { + Coordinates point = mapper.getPoint(); + CompletableFuture weatherFuture = weatherProvider.getWeather(point); + + try { + Weather weather = weatherFuture.join(); + + AsyncWeatherUpdateEvent event = + new AsyncWeatherUpdateEvent(null, weather); + + server.getPluginManager().callEvent(event); + } catch (CompletionException e) { // TODO handle finer exceptions + DebugLogger.info("failed to retrieve weather data", 1); + + if (DebugLogger.getDebugLevel() > 0) + e.printStackTrace(); + + delay = 200; + } + + } + + runTaskLaterAsynchronously(plugin, delay); + } + +} diff --git a/src/main/java/eu/m724/realweather/weather/DynamicWeatherApplier.java b/src/main/java/eu/m724/realweather/weather/DynamicWeatherApplier.java new file mode 100644 index 0000000..a88b83e --- /dev/null +++ b/src/main/java/eu/m724/realweather/weather/DynamicWeatherApplier.java @@ -0,0 +1,50 @@ +package eu.m724.realweather.weather; + +import java.util.List; + +import org.bukkit.WeatherType; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import eu.m724.realweather.DebugLogger; +import eu.m724.wtapi.object.Weather; +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; + +public class DynamicWeatherApplier extends BukkitRunnable { + private List players; + private Weather[] weathers; + + public DynamicWeatherApplier(List players, Weather[] weathers) { + this.players = players; + this.weathers = weathers; + } + + @Override + public void run() { + DebugLogger.info("applying weather for %d players", 2, players.size()); + + for (int i=0; i