128 lines
4.1 KiB
Java
128 lines
4.1 KiB
Java
package eu.m724.realweather.weather;
|
|
|
|
import java.util.List;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.CompletionException;
|
|
import java.util.stream.Collectors;
|
|
|
|
import org.bukkit.Server;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.event.EventHandler;
|
|
import org.bukkit.event.Listener;
|
|
import org.bukkit.event.player.PlayerJoinEvent;
|
|
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.weather.WeatherProvider;
|
|
|
|
public class AsyncWeatherRetriever extends BukkitRunnable implements Listener { // TODO split this
|
|
private WeatherProvider weatherProvider;
|
|
|
|
private boolean dynamic = GlobalConstants.getWeatherConfig().dynamic;
|
|
private Mapper mapper = GlobalConstants.getMapper();
|
|
private Plugin plugin = GlobalConstants.getPlugin();
|
|
private Server server = plugin.getServer();
|
|
private PlayerWeatherDirectory playerWeatherDirectory = GlobalConstants.getPlayerWeatherDirectory();
|
|
|
|
public AsyncWeatherRetriever(WeatherProvider weatherProvider) {
|
|
this.weatherProvider = weatherProvider;
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
DebugLogger.info("Weather retrieval", 3);
|
|
long delay = 6000;
|
|
|
|
if (dynamic) {
|
|
if (server.getOnlinePlayers().size() == 0) return;
|
|
|
|
List<Player> 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<Weather[]> 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<weathers.length; i++) {
|
|
Player player = players.get(i);
|
|
Weather weather = weathers[i];
|
|
|
|
playerWeatherDirectory.weathers.put(player, weather);
|
|
|
|
AsyncWeatherUpdateEvent event =
|
|
new AsyncWeatherUpdateEvent(player, 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;
|
|
}
|
|
} else {
|
|
Coordinates point = mapper.getPoint();
|
|
CompletableFuture<Weather> 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;
|
|
}
|
|
|
|
}
|
|
|
|
DebugLogger.info("Scheduling restart with delay %d", 3, delay);
|
|
runTaskLaterAsynchronously(plugin, delay);
|
|
}
|
|
|
|
@EventHandler
|
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
|
Player player = event.getPlayer();
|
|
|
|
Coordinates coordinates = mapper.locationToCoordinates(player.getLocation());
|
|
|
|
CompletableFuture<Weather> weatherFuture = weatherProvider.getWeather(coordinates);
|
|
DebugLogger.info("A player joined so I requested weather", 3);
|
|
|
|
weatherFuture.thenAccept(weather -> {
|
|
playerWeatherDirectory.weathers.put(player, weather);
|
|
|
|
AsyncWeatherUpdateEvent weatherEvent =
|
|
new AsyncWeatherUpdateEvent(player, weather);
|
|
|
|
server.getPluginManager().callEvent(weatherEvent);
|
|
}); // TODO is this really safe?
|
|
}
|
|
|
|
}
|