From 3f2d5e7e14a6ab2116d0fc0d34cbffadf2917213 Mon Sep 17 00:00:00 2001 From: "Blue (Lukas Rieger)" Date: Sat, 23 Nov 2019 15:20:11 +0100 Subject: [PATCH] Load and reload BlueMapSponge off the server-thread --- .../bluecolored/bluemap/sponge/Commands.java | 35 +++--- .../bluemap/sponge/SpongePlugin.java | 107 ++++++++++-------- 2 files changed, 78 insertions(+), 64 deletions(-) diff --git a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Commands.java b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Commands.java index 6bbf5939..6275298c 100644 --- a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Commands.java +++ b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/Commands.java @@ -1,6 +1,5 @@ package de.bluecolored.bluemap.sponge; -import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; @@ -28,7 +27,6 @@ import de.bluecolored.bluemap.core.logger.Logger; import de.bluecolored.bluemap.core.render.hires.HiresModelManager; -import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException; import de.bluecolored.bluemap.core.world.Block; import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException; import de.bluecolored.bluemap.core.world.World; @@ -96,23 +94,26 @@ public CommandSpec createReloadCommand() { .description(Text.of("Reloads all resources and configuration-files")) .permission("bluemap.reload") .executor((source, args) -> { - try { source.sendMessage(Text.of(TextColors.GOLD, "Reloading BlueMap...")); - plugin.reload(); - if (plugin.isLoaded()) { - source.sendMessage(Text.of(TextColors.GREEN, "BlueMap reloaded!")); - return CommandResult.success(); - } else { - source.sendMessage(Text.of(TextColors.RED, "Could not load BlueMap! See the console for details!")); - return CommandResult.empty(); - } - } catch (IOException | NoSuchResourceException ex) { - Logger.global.logError("Failed to reload BlueMap!", ex); - - source.sendMessage(Text.of(TextColors.RED, "There was an error reloading BlueMap! See the console for details!")); - return CommandResult.empty(); - } + plugin.getAsyncExecutor().submit(() -> { + try { + plugin.reload(); + + if (plugin.isLoaded()) { + source.sendMessage(Text.of(TextColors.GREEN, "BlueMap reloaded!")); + } else { + source.sendMessage(Text.of(TextColors.RED, "Could not load BlueMap! See the console for details!")); + } + + } catch (Exception ex) { + Logger.global.logError("Failed to reload BlueMap!", ex); + + source.sendMessage(Text.of(TextColors.RED, "There was an error reloading BlueMap! See the console for details!")); + } + }); + + return CommandResult.success(); }) .build(); } 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 1a8b6a28..cc21bb7d 100644 --- a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java +++ b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java @@ -38,6 +38,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; @@ -123,13 +124,10 @@ public SpongePlugin(org.slf4j.Logger logger) { instance = this; } - public synchronized void load() throws IOException, NoSuchResourceException { + public synchronized void load() throws ExecutionException, IOException, NoSuchResourceException, InterruptedException { if (loaded) return; unload(); //ensure nothing is left running (from a failed load or something) - //init commands - Sponge.getCommandManager().register(this, new Commands(this).createRootCommand(), "bluemap"); - //load configs File configFile = getConfigPath().resolve("bluemap.conf").toFile(); config = ConfigurationFile.loadOrCreate(configFile, SpongePlugin.class.getResource("/bluemap-sponge.conf")).getConfig(); @@ -143,7 +141,9 @@ public synchronized void load() throws IOException, NoSuchResourceException { unload(); //only register reload command - Sponge.getCommandManager().register(this, new Commands(this).createStandaloneReloadCommand(), "bluemap"); + syncExecutor.submit(() -> //just to be save we do this on the server thread + Sponge.getCommandManager().register(this, new Commands(this).createStandaloneReloadCommand(), "bluemap") + ).get(); return; } @@ -232,7 +232,9 @@ public synchronized void load() throws IOException, NoSuchResourceException { } //start map updater - updateHandler = new MapUpdateHandler(); + syncExecutor.submit(() -> + this.updateHandler = new MapUpdateHandler() + ).get(); //create/update webfiles WebFilesManager webFilesManager = new WebFilesManager(config.getWebRoot()); @@ -257,6 +259,11 @@ public synchronized void load() throws IOException, NoSuchResourceException { webServer.updateWebfiles(); webServer.start(); } + + //init commands + syncExecutor.submit(() -> //just to be save we do this on the server thread + Sponge.getCommandManager().register(this, new Commands(this).createRootCommand(), "bluemap") + ).get(); //metrics Sponge.getScheduler().createTaskBuilder() @@ -272,20 +279,25 @@ public synchronized void load() throws IOException, NoSuchResourceException { } public synchronized void unload() { + try { + syncExecutor.submit(() -> { //just to be save we do this on the server thread + //unregister commands + Sponge.getCommandManager().getOwnedBy(this).forEach(Sponge.getCommandManager()::removeMapping); + + //unregister listeners + if (updateHandler != null) Sponge.getEventManager().unregisterListeners(updateHandler); + + //stop scheduled tasks + Sponge.getScheduler().getScheduledTasks(this).forEach(t -> t.cancel()); + }).get(); + } catch (InterruptedException | ExecutionException unexpected) { + throw new RuntimeException("Unexpected exception!", unexpected); //should never happen + } //stop services if (renderManager != null) renderManager.stop(); if (webServer != null) webServer.close(); - //unregister listeners - if (updateHandler != null) Sponge.getEventManager().unregisterListeners(updateHandler); - - //unregister commands - Sponge.getCommandManager().getOwnedBy(this).forEach(Sponge.getCommandManager()::removeMapping); - - //stop scheduled tasks - Sponge.getScheduler().getScheduledTasks(this).forEach(t -> t.cancel()); - //save render-manager state if (updateHandler != null) updateHandler.flushTileBuffer(); //first write all buffered tiles to the render manager to save them too if (renderManager != null) { @@ -320,7 +332,7 @@ public synchronized void unload() { loaded = false; } - public synchronized void reload() throws IOException, NoSuchResourceException { + public synchronized void reload() throws IOException, NoSuchResourceException, ExecutionException, InterruptedException { unload(); load(); } @@ -330,37 +342,42 @@ public void onServerStart(GameStartingServerEvent evt) { syncExecutor = Sponge.getScheduler().createSyncExecutor(this); asyncExecutor = Sponge.getScheduler().createAsyncExecutor(this); - try { - load(); - if (isLoaded()) Logger.global.logInfo("Loaded!"); - } catch (IOException | NoSuchResourceException e) { - Logger.global.logError("Failed to load!", e); - } + asyncExecutor.execute(() -> { + try { + load(); + if (isLoaded()) Logger.global.logInfo("Loaded!"); + } catch (Exception e) { + Logger.global.logError("Failed to load!", e); + } + }); } @Listener public void onServerStop(GameStoppingEvent evt) { - unload(); - Logger.global.logInfo("Saved and stopped!"); + asyncExecutor.execute(() -> { + unload(); + Logger.global.logInfo("Saved and stopped!"); + }); } @Listener public void onServerReload(GameReloadEvent evt) { - try { - reload(); - Logger.global.logInfo("Reloaded!"); - } catch (IOException | NoSuchResourceException e) { - Logger.global.logError("Failed to load!", e); - } + asyncExecutor.execute(() -> { + try { + Logger.global.logInfo("Reloading..."); + reload(); + Logger.global.logInfo("Reloaded!"); + } catch (Exception e) { + Logger.global.logError("Failed to load!", e); + } + }); } private void handleMissingResources(File resourceFile, File configFile) { if (config.isDownloadAccepted()) { //download file async - Sponge.getScheduler().createTaskBuilder() - .async() - .execute(() -> { + asyncExecutor.execute(() -> { try { Logger.global.logInfo("Downloading " + ResourcePack.MINECRAFT_CLIENT_URL + " to " + resourceFile + " ..."); ResourcePack.downloadDefaultResource(resourceFile); @@ -369,20 +386,16 @@ private void handleMissingResources(File resourceFile, File configFile) { return; } - //reload bluemap on server thread - Sponge.getScheduler().createTaskBuilder() - .execute(() -> { - try { - Logger.global.logInfo("Download finished! Reloading..."); - reload(); - Logger.global.logInfo("Reloaded!"); - } catch (IOException | NoSuchResourceException e) { - Logger.global.logError("Failed to reload BlueMap!", e); - } - }) - .submit(SpongePlugin.getInstance()); - }) - .submit(SpongePlugin.getInstance()); + // and reload + Logger.global.logInfo("Download finished! Reloading..."); + try { + reload(); + } catch (Exception e) { + Logger.global.logError("Failed to reload Bluemap!", e); + return; + } + Logger.global.logInfo("Reloaded!"); + }); } else { Logger.global.logWarning("BlueMap is missing important resources!");