From c63ec971d6344ad2e99aa23ed2552c17a9b979a8 Mon Sep 17 00:00:00 2001 From: "Blue (Lukas Rieger)" Date: Wed, 19 Aug 2020 20:17:49 +0200 Subject: [PATCH] Fix players not shown after spigot reload and tidy up a lot of exception-handling --- .../bluemap/bukkit/BukkitCommands.java | 4 ++- .../bluemap/bukkit/BukkitPlugin.java | 16 ++++++++++-- .../bluecolored/bluemap/cli/BlueMapCLI.java | 6 ++--- .../bluemap/common/RenderManager.java | 14 ++++++---- .../common/plugin/MapUpdateHandler.java | 2 +- .../bluemap/common/plugin/Plugin.java | 6 +++++ .../common/plugin/commands/Commands.java | 3 ++- .../common/plugin/skins/PlayerSkin.java | 4 +-- .../bluemap/core/mca/MCAWorld.java | 26 +++++++------------ .../bluemap/core/metrics/Metrics.java | 5 +++- .../core/render/lowres/LowresModel.java | 4 +++ .../core/resourcepack/BlockStateResource.java | 8 +++--- .../core/resourcepack/TextureGallery.java | 4 +-- .../bluemap/core/util/FileUtils.java | 5 ++-- .../bluemap/core/world/BlockState.java | 2 +- .../bluemap/sponge/SpongeCommands.java | 4 ++- .../bluemap/sponge/SpongePlugin.java | 13 +++++----- 17 files changed, 78 insertions(+), 48 deletions(-) diff --git a/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitCommands.java b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitCommands.java index 8779020e..506300f1 100644 --- a/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitCommands.java +++ b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitCommands.java @@ -86,7 +86,9 @@ public void onTabComplete(TabCompleteEvent evt) { completions.sort((s1, s2) -> s1.compareToIgnoreCase(s2)); evt.setCompletions(completions); } - } catch (InterruptedException | ExecutionException | TimeoutException ignore) {} + } catch (InterruptedException ignore) { + Thread.currentThread().interrupt(); + } catch (ExecutionException | TimeoutException ignore) {} } private class CommandProxy extends BukkitCommand { diff --git a/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitPlugin.java b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitPlugin.java index b51cff4b..0cfa0005 100644 --- a/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitPlugin.java +++ b/BlueMapBukkit/src/main/java/de/bluecolored/bluemap/bukkit/BukkitPlugin.java @@ -56,6 +56,7 @@ import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener; import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface; import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.resourcepack.ParseResourceException; public class BukkitPlugin extends JavaPlugin implements ServerInterface, Listener { @@ -113,6 +114,15 @@ public void onEnable() { //tab completions getServer().getPluginManager().registerEvents(commands, this); + //update online-player collections + this.onlinePlayerList.clear(); + this.onlinePlayerMap.clear(); + for (org.bukkit.entity.Player player : getServer().getOnlinePlayers()) { + BukkitPlayer bukkitPlayer = new BukkitPlayer(player); + onlinePlayerMap.put(player.getUniqueId(), bukkitPlayer); + onlinePlayerList.add(bukkitPlayer); + } + //start updating players getServer().getScheduler().runTaskTimer(this, this::updateSomePlayers, 1, 1); @@ -122,8 +132,9 @@ public void onEnable() { Logger.global.logInfo("Loading..."); this.bluemap.load(); if (bluemap.isLoaded()) Logger.global.logInfo("Loaded!"); - } catch (Throwable t) { - Logger.global.logError("Failed to load!", t); + } catch (IOException | ParseResourceException | RuntimeException e) { + Logger.global.logError("Failed to load!", e); + this.bluemap.unload(); } }); } @@ -165,6 +176,7 @@ public UUID getUUIDForWorld(File worldFolder) throws IOException { try { return futureUUID.get(); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw new IOException(e); } catch (ExecutionException e) { if (e.getCause() instanceof IOException) { diff --git a/BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java b/BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java index d3d9f5a4..6d66cac3 100644 --- a/BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java +++ b/BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java @@ -222,7 +222,7 @@ public void renderMaps() throws IOException { while(renderManager.getRenderTaskCount() != 0) { try { Thread.sleep(200); - } catch (InterruptedException e) {} + } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } long now = System.currentTimeMillis(); @@ -390,7 +390,7 @@ public static void main(String[] args) throws IOException, ParseResourceExceptio //wait a second to let the webserver start, looks nicer in the log try { Thread.sleep(1000); - } catch (InterruptedException ignore) {} + } catch (InterruptedException ignore) { Thread.currentThread().interrupt(); } } @@ -452,7 +452,7 @@ private static void printHelp() { filename = file.getAbsolutePath(); } } - } catch (Exception ex) {} + } catch (IOException ex) {} String command = "java -jar " + filename; diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/RenderManager.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/RenderManager.java index 31c884c7..f391238d 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/RenderManager.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/RenderManager.java @@ -75,7 +75,6 @@ public synchronized void stop() { for (int i = 0; i < renderThreads.length; i++) { if (renderThreads[i] != null) { renderThreads[i].interrupt(); - renderThreads[i] = null; } } @@ -141,7 +140,7 @@ public boolean removeRenderTask(RenderTask renderTask) { private void renderThread() { RenderTicket ticket = null; - while (!Thread.interrupted() && running) { + while (running) { synchronized (renderTickets) { ticket = renderTickets.poll(); if (ticket != null) renderTicketMap.remove(ticket); @@ -163,17 +162,22 @@ private void renderThread() { if (ticket != null) { try { ticket.render(); - } catch (Exception e) { + } catch (RuntimeException e) { //catch possible runtime exceptions, display them, and wait a while .. then resurrect this render-thread Logger.global.logError("Unexpected exception in render-thread!", e); try { Thread.sleep(10000); - } catch (InterruptedException interrupt) { break; } + } catch (InterruptedException interrupt) { Thread.currentThread().interrupt(); break; } } } else { try { Thread.sleep(1000); // we don't need a super fast response time, so waiting a second is totally fine - } catch (InterruptedException interrupt) { break; } + } catch (InterruptedException interrupt) { Thread.currentThread().interrupt(); break; } + } + + if (Thread.interrupted()) { + Thread.currentThread().interrupt(); + break; } } } diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/MapUpdateHandler.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/MapUpdateHandler.java index ac69cd1a..e7bfe570 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/MapUpdateHandler.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/MapUpdateHandler.java @@ -66,7 +66,7 @@ public void onWorldSaveToDisk(final UUID world) { } } - } catch (InterruptedException ignore) {} + } catch (InterruptedException ignore) { Thread.currentThread().interrupt(); } }).start(); } diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java index 4c99bdac..8d823c27 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java @@ -262,6 +262,7 @@ public synchronized void load() throws IOException, ParseResourceException { } } } catch (InterruptedException ex){ + Thread.currentThread().interrupt(); return; } }); @@ -316,6 +317,7 @@ public synchronized void load() throws IOException, ParseResourceException { Thread.sleep(TimeUnit.MINUTES.toMillis(30)); } } catch (InterruptedException ex){ + Thread.currentThread().interrupt(); return; } }); @@ -339,9 +341,13 @@ public synchronized void unload() { //stop scheduled threads if (metricsThread != null) metricsThread.interrupt(); + try {metricsThread.join(1000);} catch (InterruptedException ignore) { Thread.currentThread().interrupt(); } + if (metricsThread.isAlive()) Logger.global.logWarning("The metricsThread did not terminate correctly in time!"); metricsThread = null; if (periodicalSaveThread != null) periodicalSaveThread.interrupt(); + try {periodicalSaveThread.join(1000);} catch (InterruptedException ignore) { Thread.currentThread().interrupt(); } + if (periodicalSaveThread.isAlive()) Logger.global.logWarning("The periodicalSaveThread did not terminate correctly in time!"); periodicalSaveThread = null; //stop services diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/Commands.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/Commands.java index b32ea461..65169787 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/Commands.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/commands/Commands.java @@ -60,6 +60,7 @@ import de.bluecolored.bluemap.core.mca.Chunk; import de.bluecolored.bluemap.core.mca.ChunkAnvil112; import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.resourcepack.ParseResourceException; import de.bluecolored.bluemap.core.world.Block; import de.bluecolored.bluemap.core.world.World; @@ -307,7 +308,7 @@ public int reloadCommand(CommandContext context) { source.sendMessage(Text.of(TextColor.RED, "Could not load BlueMap! See the console for details!")); } - } catch (Exception ex) { + } catch (IOException | ParseResourceException | RuntimeException ex) { Logger.global.logError("Failed to reload BlueMap!", ex); source.sendMessage(Text.of(TextColor.RED, "There was an error reloading BlueMap! See the console for details!")); diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/skins/PlayerSkin.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/skins/PlayerSkin.java index a0b7bd99..52412125 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/skins/PlayerSkin.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/skins/PlayerSkin.java @@ -73,7 +73,7 @@ public void update(File storageFolder) { Logger.global.logDebug("Failed to load player-skin from mojang-servers: " + e); } catch (IOException e) { Logger.global.logError("Failed to write player-head image!", e); - } catch (InterruptedException ignore) {} + } catch (InterruptedException ignore) { Thread.currentThread().interrupt(); } }).start(); } @@ -87,7 +87,7 @@ public BufferedImage createHead(BufferedImage skinTexture) { Graphics2D g = head.createGraphics(); g.drawImage(layer1, 0, 0, null); g.drawImage(layer2, 0, 0, null); - } catch (Throwable t) { // There might be problems with headless servers when loading the graphics class + } catch (Throwable t) { // There might be problems with headless servers when loading the graphics class, so we catch every exception and error on purpose here Logger.global.noFloodWarning("headless-graphics-fail", "Could not access Graphics2D to render player-skin texture. Try adding '-Djava.awt.headless=true' to your startup flags or ignore this warning."); diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java index bbf95e66..200793f1 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/mca/MCAWorld.java @@ -142,15 +142,9 @@ private MCAWorld( } public BlockState getBlockState(Vector3i pos) { - try { - - Vector2i chunkPos = blockToChunk(pos); - Chunk chunk = getChunk(chunkPos); - return chunk.getBlockState(pos); - - } catch (Exception ex) { - return BlockState.MISSING; - } + Vector2i chunkPos = blockToChunk(pos); + Chunk chunk = getChunk(chunkPos); + return chunk.getBlockState(pos); } @Override @@ -200,22 +194,22 @@ public Chunk getChunk(Vector2i chunkPos) { Chunk chunk = CHUNK_CACHE.get(new WorldChunkHash(this, chunkPos), () -> this.loadChunkOrEmpty(chunkPos, 2, 1000)); return chunk; } catch (UncheckedExecutionException | ExecutionException e) { + if (e.getCause() instanceof InterruptedException) Thread.currentThread().interrupt(); throw new RuntimeException(e.getCause()); } } - private Chunk loadChunkOrEmpty(Vector2i chunkPos, int tries, long tryInterval) { + private Chunk loadChunkOrEmpty(Vector2i chunkPos, int tries, long tryInterval) throws InterruptedException { Exception loadException = null; for (int i = 0; i < tries; i++) { try { return loadChunk(chunkPos); - } catch (Exception e) { + } catch (IOException | RuntimeException e) { + if (loadException != null) e.addSuppressed(loadException); loadException = e; if (tryInterval > 0 && i+1 < tries) { - try { - Thread.sleep(tryInterval); - } catch (InterruptedException interrupt) {} + Thread.sleep(tryInterval); } } } @@ -261,7 +255,7 @@ private Chunk loadChunk(Vector2i chunkPos) throws IOException { } else { throw new IOException("Invalid data tag: " + (tag == null ? "null" : tag.getClass().getName())); } - } catch (Exception e) { + } catch (RuntimeException | IOException e) { throw new IOException("Exception trying to load chunk (" + chunkPos + ")", e); } } @@ -312,7 +306,7 @@ public Collection getChunkList(long modifiedSinceMillis, Predicate * (Do not use this method to sync file-access from different threads!) */ - public static void waitForFile(File file, long time, TimeUnit unit) throws InterruptedException { + public static void waitForFile(File file, long time, TimeUnit unit) throws InterruptedException, TimeoutException { long start = System.currentTimeMillis(); long timeout = start + TimeUnit.MILLISECONDS.convert(time, unit); long sleepTime = 1; while(!file.canWrite() || !file.canRead()){ Thread.sleep(sleepTime); sleepTime = (long) Math.min(Math.ceil(sleepTime * 1.5), 1000); - if (System.currentTimeMillis() > timeout) throw new InterruptedException(); + if (System.currentTimeMillis() > timeout) throw new TimeoutException(); } } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/BlockState.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/BlockState.java index 9c901969..ac829d51 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/BlockState.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/BlockState.java @@ -183,7 +183,7 @@ public static BlockState fromString(String serializedBlockState) throws IllegalA String blockId = m.group(1).trim(); return new BlockState(blockId, pt); - } catch (Exception ex) { + } catch (RuntimeException ex) { throw new IllegalArgumentException("'" + serializedBlockState + "' could not be parsed to a BlockState!"); } } diff --git a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongeCommands.java b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongeCommands.java index bd19b154..e9dc4bf8 100644 --- a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongeCommands.java +++ b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongeCommands.java @@ -116,7 +116,9 @@ public List getSuggestions(CommandSource source, String arguments, Locat completions.add(text); } } - } catch (InterruptedException | ExecutionException | TimeoutException ignore) {} + } catch (InterruptedException ignore) { + Thread.currentThread().interrupt(); + } catch (ExecutionException | TimeoutException ignore) {} completions.sort((s1, s2) -> s1.compareToIgnoreCase(s2)); return completions; diff --git a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java index 832e51a7..0237bcc8 100644 --- a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java +++ b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java @@ -58,6 +58,7 @@ import de.bluecolored.bluemap.common.plugin.serverinterface.ServerEventListener; import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface; import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.resourcepack.ParseResourceException; import de.bluecolored.bluemap.sponge.SpongeCommands.SpongeCommandProxy; import net.querz.nbt.CompoundTag; import net.querz.nbt.NBTUtil; @@ -123,8 +124,8 @@ public void onServerStart(GameStartingServerEvent evt) { Logger.global.logInfo("Loading..."); bluemap.load(); if (bluemap.isLoaded()) Logger.global.logInfo("Loaded!"); - } catch (Throwable t) { - Logger.global.logError("Failed to load!", t); + } catch (IOException | ParseResourceException | RuntimeException e) { + Logger.global.logError("Failed to load!", e); } }); } @@ -144,13 +145,13 @@ public void onServerReload(GameReloadEvent evt) { Logger.global.logInfo("Reloading..."); bluemap.reload(); Logger.global.logInfo("Reloaded!"); - } catch (Exception e) { + } catch (IOException | ParseResourceException | RuntimeException e) { Logger.global.logError("Failed to load!", e); + bluemap.unload(); } }); } - @Listener public void onPlayerJoin(ClientConnectionEvent.Join evt) { SpongePlayer player = new SpongePlayer(evt.getTargetEntity()); @@ -186,8 +187,8 @@ public UUID getUUIDForWorld(File worldFolder) throws IOException { long most = spongeData.getLong("UUIDMost"); long least = spongeData.getLong("UUIDLeast"); return new UUID(most, least); - } catch (Throwable t) { - throw new IOException("Failed to read level_sponge.dat", t); + } catch (IOException | RuntimeException e) { + throw new IOException("Failed to read level_sponge.dat", e); } }