add exception printing by default to all futures

This commit is contained in:
Pyrbu 2024-12-18 07:08:46 +01:00
parent e30d6a5782
commit e621ac6908
8 changed files with 40 additions and 13 deletions

View file

@ -7,13 +7,13 @@ import lol.pyr.znpcsplus.conversion.DataImporter;
import lol.pyr.znpcsplus.conversion.DataImporterRegistry; import lol.pyr.znpcsplus.conversion.DataImporterRegistry;
import lol.pyr.znpcsplus.npc.NpcEntryImpl; import lol.pyr.znpcsplus.npc.NpcEntryImpl;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl; import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
import lol.pyr.znpcsplus.util.FutureUtil;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
public class ImportCommand implements CommandHandler { public class ImportCommand implements CommandHandler {
private final NpcRegistryImpl npcRegistry; private final NpcRegistryImpl npcRegistry;
@ -33,7 +33,7 @@ public class ImportCommand implements CommandHandler {
if (importer == null) context.halt(Component.text("Importer not found! Possible importers: " + if (importer == null) context.halt(Component.text("Importer not found! Possible importers: " +
String.join(", ", importerRegistry.getIds()), NamedTextColor.RED)); String.join(", ", importerRegistry.getIds()), NamedTextColor.RED));
CompletableFuture.runAsync(() -> { FutureUtil.exceptionPrintingRunAsync(() -> {
if (!importer.isValid()) { if (!importer.isValid()) {
context.send(Component.text("There is no data to import from this importer!", NamedTextColor.RED)); context.send(Component.text("There is no data to import from this importer!", NamedTextColor.RED));
return; return;

View file

@ -4,6 +4,7 @@ import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.adventure.command.CommandHandler; import lol.pyr.director.adventure.command.CommandHandler;
import lol.pyr.director.common.command.CommandExecutionException; import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl; import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
import lol.pyr.znpcsplus.util.FutureUtil;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
@ -20,7 +21,7 @@ public class LoadAllCommand implements CommandHandler {
@Override @Override
public void run(CommandContext context) throws CommandExecutionException { public void run(CommandContext context) throws CommandExecutionException {
CompletableFuture.runAsync(() -> { FutureUtil.exceptionPrintingRunAsync(() -> {
npcRegistry.reload(); npcRegistry.reload();
context.send(Component.text("All NPCs have been re-loaded from storage", NamedTextColor.GREEN)); context.send(Component.text("All NPCs have been re-loaded from storage", NamedTextColor.GREEN));
}); });

View file

@ -4,6 +4,7 @@ import lol.pyr.director.adventure.command.CommandContext;
import lol.pyr.director.adventure.command.CommandHandler; import lol.pyr.director.adventure.command.CommandHandler;
import lol.pyr.director.common.command.CommandExecutionException; import lol.pyr.director.common.command.CommandExecutionException;
import lol.pyr.znpcsplus.npc.NpcRegistryImpl; import lol.pyr.znpcsplus.npc.NpcRegistryImpl;
import lol.pyr.znpcsplus.util.FutureUtil;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
@ -20,7 +21,7 @@ public class SaveAllCommand implements CommandHandler {
@Override @Override
public void run(CommandContext context) throws CommandExecutionException { public void run(CommandContext context) throws CommandExecutionException {
CompletableFuture.runAsync(() -> { FutureUtil.exceptionPrintingRunAsync(() -> {
npcRegistry.save(); npcRegistry.save();
context.send(Component.text("All NPCs have been saved to storage", NamedTextColor.GREEN)); context.send(Component.text("All NPCs have been saved to storage", NamedTextColor.GREEN));
}); });

View file

@ -8,6 +8,7 @@ import lol.pyr.znpcsplus.api.entity.EntityProperty;
import lol.pyr.znpcsplus.api.entity.PropertyHolder; import lol.pyr.znpcsplus.api.entity.PropertyHolder;
import lol.pyr.znpcsplus.packets.PacketFactory; import lol.pyr.znpcsplus.packets.PacketFactory;
import lol.pyr.znpcsplus.reflection.Reflections; import lol.pyr.znpcsplus.reflection.Reflections;
import lol.pyr.znpcsplus.util.FutureUtil;
import lol.pyr.znpcsplus.util.NpcLocation; import lol.pyr.znpcsplus.util.NpcLocation;
import lol.pyr.znpcsplus.util.Viewable; import lol.pyr.znpcsplus.util.Viewable;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -67,7 +68,7 @@ public class PacketEntity implements PropertyHolder {
} }
public CompletableFuture<Void> spawn(Player player) { public CompletableFuture<Void> spawn(Player player) {
return CompletableFuture.runAsync(() -> { return FutureUtil.exceptionPrintingRunAsync(() -> {
if (type == EntityTypes.PLAYER) packetFactory.spawnPlayer(player, this, properties).join(); if (type == EntityTypes.PLAYER) packetFactory.spawnPlayer(player, this, properties).join();
else packetFactory.spawnEntity(player, this, properties); else packetFactory.spawnEntity(player, this, properties);
if (vehicleId != null) { if (vehicleId != null) {

View file

@ -5,6 +5,7 @@ import com.google.gson.JsonParser;
import lol.pyr.znpcsplus.config.ConfigManager; import lol.pyr.znpcsplus.config.ConfigManager;
import lol.pyr.znpcsplus.reflection.Reflections; import lol.pyr.znpcsplus.reflection.Reflections;
import lol.pyr.znpcsplus.skin.SkinImpl; import lol.pyr.znpcsplus.skin.SkinImpl;
import lol.pyr.znpcsplus.util.FutureUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -42,7 +43,7 @@ public class MojangSkinCache {
if (idCache.containsKey(name.toLowerCase())) return fetchByUUID(idCache.get(name.toLowerCase()).getId()); if (idCache.containsKey(name.toLowerCase())) return fetchByUUID(idCache.get(name.toLowerCase()).getId());
return CompletableFuture.supplyAsync(() -> { return FutureUtil.exceptionPrintingSupplyAsync(() -> {
URL url = parseUrl("https://api.mojang.com/users/profiles/minecraft/" + name); URL url = parseUrl("https://api.mojang.com/users/profiles/minecraft/" + name);
HttpURLConnection connection = null; HttpURLConnection connection = null;
try { try {
@ -75,7 +76,7 @@ public class MojangSkinCache {
if (idCache.containsKey(name.toLowerCase())) return fetchByUUID(idCache.get(name.toLowerCase()).getId()); if (idCache.containsKey(name.toLowerCase())) return fetchByUUID(idCache.get(name.toLowerCase()).getId());
return CompletableFuture.supplyAsync(() -> { return FutureUtil.exceptionPrintingSupplyAsync(() -> {
URL url = parseUrl("https://api.ashcon.app/mojang/v2/user/" + name); URL url = parseUrl("https://api.ashcon.app/mojang/v2/user/" + name);
HttpURLConnection connection = null; HttpURLConnection connection = null;
try { try {
@ -106,7 +107,7 @@ public class MojangSkinCache {
} }
public CompletableFuture<SkinImpl> fetchByUrl(URL url, String variant) { public CompletableFuture<SkinImpl> fetchByUrl(URL url, String variant) {
return CompletableFuture.supplyAsync(() -> { return FutureUtil.exceptionPrintingSupplyAsync(() -> {
URL apiUrl = parseUrl("https://api.mineskin.org/generate/url"); URL apiUrl = parseUrl("https://api.mineskin.org/generate/url");
HttpURLConnection connection = null; HttpURLConnection connection = null;
try { try {
@ -170,7 +171,7 @@ public class MojangSkinCache {
if (!skin.isExpired()) return CompletableFuture.completedFuture(skin); if (!skin.isExpired()) return CompletableFuture.completedFuture(skin);
} }
return CompletableFuture.supplyAsync(() -> { return FutureUtil.exceptionPrintingSupplyAsync(() -> {
URL url = parseUrl("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false"); URL url = parseUrl("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false");
HttpURLConnection connection = null; HttpURLConnection connection = null;
try { try {

View file

@ -5,6 +5,7 @@ import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
import lol.pyr.znpcsplus.skin.BaseSkinDescriptor; import lol.pyr.znpcsplus.skin.BaseSkinDescriptor;
import lol.pyr.znpcsplus.skin.SkinImpl; import lol.pyr.znpcsplus.skin.SkinImpl;
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache; import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
import lol.pyr.znpcsplus.util.FutureUtil;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.net.URL; import java.net.URL;
@ -18,11 +19,11 @@ public class PrefetchedDescriptor implements BaseSkinDescriptor, SkinDescriptor
} }
public static CompletableFuture<PrefetchedDescriptor> forPlayer(MojangSkinCache cache, String name) { public static CompletableFuture<PrefetchedDescriptor> forPlayer(MojangSkinCache cache, String name) {
return CompletableFuture.supplyAsync(() -> new PrefetchedDescriptor(cache.fetchByName(name).join())); return FutureUtil.exceptionPrintingSupplyAsync(() -> new PrefetchedDescriptor(cache.fetchByName(name).join()));
} }
public static CompletableFuture<PrefetchedDescriptor> fromUrl(MojangSkinCache cache, URL url, String variant) { public static CompletableFuture<PrefetchedDescriptor> fromUrl(MojangSkinCache cache, URL url, String variant) {
return CompletableFuture.supplyAsync(() -> new PrefetchedDescriptor(cache.fetchByUrl(url, variant).join())); return FutureUtil.exceptionPrintingSupplyAsync(() -> new PrefetchedDescriptor(cache.fetchByUrl(url, variant).join()));
} }
@Override @Override

View file

@ -2,11 +2,33 @@ package lol.pyr.znpcsplus.util;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
public class FutureUtil { public class FutureUtil {
public static CompletableFuture<Void> allOf(Collection<CompletableFuture<?>> futures) { public static CompletableFuture<Void> allOf(Collection<CompletableFuture<?>> futures) {
return CompletableFuture.runAsync(() -> { return exceptionPrintingRunAsync(() -> {
for (CompletableFuture<?> future : futures) future.join(); for (CompletableFuture<?> future : futures) future.join();
}); });
} }
public static <T> CompletableFuture<T> newExceptionPrintingFuture() {
return new CompletableFuture<T>().exceptionally(throwable -> {
throwable.printStackTrace();
return null;
});
}
public static CompletableFuture<Void> exceptionPrintingRunAsync(Runnable runnable) {
return CompletableFuture.runAsync(runnable).exceptionally(throwable -> {
throwable.printStackTrace();
return null;
});
}
public static <T> CompletableFuture<T> exceptionPrintingSupplyAsync(Supplier<T> supplier) {
return CompletableFuture.supplyAsync(supplier).exceptionally(throwable -> {
throwable.printStackTrace();
return null;
});
}
} }

View file

@ -30,7 +30,7 @@ public abstract class Viewable {
private void tryRunQueue() { private void tryRunQueue() {
if (visibilityTaskQueue.isEmpty() || queueRunning) return; if (visibilityTaskQueue.isEmpty() || queueRunning) return;
queueRunning = true; queueRunning = true;
CompletableFuture.runAsync(() -> { FutureUtil.exceptionPrintingRunAsync(() -> {
while (!visibilityTaskQueue.isEmpty()) try { while (!visibilityTaskQueue.isEmpty()) try {
visibilityTaskQueue.remove().run(); visibilityTaskQueue.remove().run();
} catch (Exception e) { } catch (Exception e) {