Load and reload BlueMapSponge off the server-thread

This commit is contained in:
Blue (Lukas Rieger) 2019-11-23 15:20:11 +01:00
parent 0d7657dcd7
commit 3f2d5e7e14
2 changed files with 78 additions and 64 deletions

View File

@ -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 com.google.common.collect.Lists;
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 class Commands {
.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();
}

View File

@ -38,6 +38,7 @@ import java.util.HashMap;
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 class SpongePlugin {
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 class SpongePlugin {
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 class SpongePlugin {
}
//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 class SpongePlugin {
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 class SpongePlugin {
}
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 class SpongePlugin {
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 class SpongePlugin {
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 @@ public class SpongePlugin {
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!");