realweather/src/main/java/eu/m724/realweather/weather/AsyncWeatherRetriever.java
Minecon724 aae479740a
some refactoring I don't remember it was yesterday
commiting just in case because I'm about to do something risky
2024-06-22 09:31:21 +02:00

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?
}
}