diff --git a/.gitignore b/.gitignore index 1ea6ffe2..839d056d 100644 --- a/.gitignore +++ b/.gitignore @@ -31,8 +31,8 @@ node_modules/ package-lock.json # exclude generated resource -BlueMapCore/src/main/resources/webroot.zip -BlueMapCore/src/main/resources/resourceExtensions.zip +BlueMapCore/src/main/resources/de/bluecolored/bluemap/webroot.zip +BlueMapCore/src/main/resources/de/bluecolored/bluemap/resourceExtensions.zip #exclude-test-data data/test-render diff --git a/BlueMapBukkit/src/main/resources/bluemap-bukkit-defaults.conf b/BlueMapBukkit/src/main/resources/bluemap-bukkit-defaults.conf deleted file mode 100644 index 98e58691..00000000 --- a/BlueMapBukkit/src/main/resources/bluemap-bukkit-defaults.conf +++ /dev/null @@ -1,17 +0,0 @@ -accept-download: false -metrics: true -renderThreadCount: -2 -data: "bluemap" -webroot: "bluemap/web" -useCookies: true -webserver { - enabled: true - port: 8100 - maxConnectionCount: 100 -} -liveUpdates { - enabled: true - hiddenGameModes: [] - hideInvisible: true - hideSneaking: false -} diff --git a/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/core-defaults.conf b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/core-defaults.conf new file mode 100644 index 00000000..ace808ab --- /dev/null +++ b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/core-defaults.conf @@ -0,0 +1,4 @@ +accept-download: false +renderThreadCount: -2 +metrics: true +data: "bluemap" \ No newline at end of file diff --git a/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/core.conf b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/core.conf new file mode 100644 index 00000000..a813fd58 --- /dev/null +++ b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/core.conf @@ -0,0 +1,31 @@ +## ## +## BlueMap ## +## Core-Config ## +## ## + +# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula), +# you confirm that you own a license to Minecraft (Java Edition) +# and you agree that BlueMap will download and use this file for you: %minecraft-client-url% +# (Alternatively you can download the file yourself and store it here: /minecraft-client-%minecraft-client-version%.jar) +# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA. +# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.) +# %datetime-iso% +accept-download: false + +# This changes the amount of threads that BlueMap will use to render the maps. +# A higher value can improve render-speed but could impact performance on the host machine. +# This should be always below or equal to the number of available processor-cores. +# Zero or a negative value means the amount of of available processor-cores subtracted by the value. +# (So a value of -2 with 6 cores results in 4 render-processes) +# Default is -2 +renderThreadCount: -2 + +# If this is true, BlueMap might send really basic metrics reports containg only the implementation-type and the version that is being used to https://metrics.bluecolored.de/bluemap/ +# This allows me to track the basic usage of BlueMap and helps me stay motivated to further develop this tool! Please leave it on :) +# An example report looks like this: {"implementation":"bukkit","version":"%version%"} +# Default is true +metrics: true + +# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later. +# Default is "bluemap" +data: "bluemap" \ No newline at end of file diff --git a/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/plugin-defaults.conf b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/plugin-defaults.conf new file mode 100644 index 00000000..ef3bb021 --- /dev/null +++ b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/plugin-defaults.conf @@ -0,0 +1,5 @@ +liveUpdates: true +skinDownload: true +hiddenGameModes: [] +hideInvisible: true +hideSneaking: false \ No newline at end of file diff --git a/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/plugin.conf b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/plugin.conf new file mode 100644 index 00000000..67f297e2 --- /dev/null +++ b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/plugin.conf @@ -0,0 +1,27 @@ +## ## +## BlueMap ## +## Plugin-Config ## +## ## + +# If the server should send live-updates and player-positions. +# This only works if the integrated webserver is enabled. +# Default is true +liveUpdates: true + +# Download the skin from mojang-serves when a player joins your server, so it can be used for the player-markers. +# Default is true +skinDownload: true + +# A list of gamemodes that will prevent a player from appearing on the map. +# Possible values are: survival, creative, spectator, adventure +hiddenGameModes: [ + "spectator" +] + +# If this is true, players that have an invisibility (potion-)effect will be hidden on the map. +# Default is true +hideInvisible: true + +# If this is true, players that are sneaking will be hidden on the map. +# Default is false +hideSneaking: false \ No newline at end of file diff --git a/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/render-defaults.conf b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/render-defaults.conf new file mode 100644 index 00000000..2f276c92 --- /dev/null +++ b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/render-defaults.conf @@ -0,0 +1,3 @@ +webroot: "bluemap/web" +useCookies: true +maps: [] diff --git a/BlueMapBukkit/src/main/resources/bluemap-bukkit.conf b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/render.conf similarity index 53% rename from BlueMapBukkit/src/main/resources/bluemap-bukkit.conf rename to BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/render.conf index bf44441c..8961e331 100644 --- a/BlueMapBukkit/src/main/resources/bluemap-bukkit.conf +++ b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/render.conf @@ -1,68 +1,16 @@ ## ## ## BlueMap ## -## ## -## by Blue (Lukas Rieger) ## -## http://bluecolored.de/ ## +## Render-Config ## ## ## -# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula), -# you confirm that you own a license to Minecraft (Java Edition) -# and you agree that BlueMap will download and use this file for you: %minecraft-client-url% -# (Alternatively you can download the file yourself and store it here: /minecraft-client-%minecraft-client-version%.jar) -# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA. -# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.) -# %datetime-iso% -accept-download: false - -# This changes the amount of threads that BlueMap will use to render the maps. -# A higher value can improve render-speed but could impact performance on the host machine. -# This should be always below or equal to the number of available processor-cores. -# Zero or a negative value means the amount of of available processor-cores subtracted by the value. -# (So a value of -2 with 6 cores results in 4 render-processes) -# Default is -2 -renderThreadCount: -2 - -# If this is true, BlueMap might send really basic metrics reports containg only the implementation-type and the version that is being used to https://metrics.bluecolored.de/bluemap/ -# This allows me to track the basic usage of BlueMap and helps me stay motivated to further develop this tool! Please leave it on :) -# An example report looks like this: {"implementation":"bukkit","version":"%version%"} -metrics: true - -# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later. -data: "bluemap" - -# The webroot of the website that displays the map. +# The folder (webroot) where the map-data and web-application files will be saved. +# Default is "bluemap/web" webroot: "bluemap/web" -# Unncomment this to override the path where bluemap stores the data-files. -# Default is "/data" -#webdata: "path/to/data/folder" - # If the web-application should use cookies to save the configurations of a user. # Default is true useCookies: true -webserver { - # With this setting you can disable the integrated web-server. - # This is usefull if you want to only render the map-data for later use, or if you setup your own webserver. - # Default is enabled - enabled: true - - # The IP-Adress that the webserver binds to. - # Use "0.0.0.0" to bind to all available local adresses. - # If you only want to access it locally use "localhost". - # Default is "0.0.0.0" - #ip: "localhost" - #ip: "127.0.0.1" - - # The port that the webserver listenes to. - # Default is 8100 - port: 8100 - - # Max number of simultaneous connections that the webserver allows - # Default is 100 - maxConnectionCount: 100 -} - # This is an array with multiple configured maps. # You can define multiple maps, for different worlds with different render-settings here maps: [ @@ -129,6 +77,16 @@ maps: [ # Changing this value requires a re-render of the map. # Default is true useCompression: true + + # Normally BlueMap detects if a chunk has not yet generated it's light-data and omits rendering those chunks. + # If this is set to true BlueMap will render Chunks even if there is no light-data! + # This can be usefull for example if some mod prevents light-data from being saved correctly. + # However, this also has a few drawbacks: + # - For those chunks, every block will always be fully lit + # - Night-mode might not work correctly + # - Caves will always be rendered (ignoring the 'renderCaves' setting) + # Default is false + ignoreMissingLightData: false } # Here another example for the End-Map @@ -166,23 +124,3 @@ maps: [ } ] - -liveUpdates { - # If the server should send live-updates and player-positions. - # Default is true - enabled: true - - # A list of gamemodes that will prevent a player from appearing on the map. - # Possible values are: survival, creative, spectator, adventure - hiddenGameModes: [ - "spectator" - ] - - # If this is true, players that have an invisibility (potion-)effect will be hidden on the map. - # Default is true - hideInvisible: true - - # If this is true, players that are sneaking will be hidden on the map. - # Default is false - hideSneaking: false -} diff --git a/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf new file mode 100644 index 00000000..55e8c255 --- /dev/null +++ b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf @@ -0,0 +1,4 @@ +enabled: true +webroot: "bluemap/web" +port: 8100 +maxConnectionCount: 100 \ No newline at end of file diff --git a/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/webserver.conf b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/webserver.conf new file mode 100644 index 00000000..5764c34b --- /dev/null +++ b/BlueMapBukkit/src/main/resources/de/bluecolored/bluemap/webserver.conf @@ -0,0 +1,29 @@ +## ## +## BlueMap ## +## Webserver-Config ## +## ## + +# With this setting you can disable the integrated web-server. +# This is usefull if you want to only render the map-data for later use, or if you setup your own webserver. +# Default is enabled +enabled: true + +# The webroot that the server will host to the web. +# Usually this should be set to the same directory like in the Core-Config! +# Default is "bluemap/web" +webroot: "bluemap/web" + +# The IP-Adress that the webserver binds to. +# Use "0.0.0.0" to bind to all available local adresses. +# If you only want to access it locally use "localhost". +# Default is "0.0.0.0" +#ip: "localhost" +#ip: "123.45.6.78" + +# The port that the webserver listenes to. +# Default is 8100 +port: 8100 + +# Max number of simultaneous connections that the webserver allows +# Default is 100 +maxConnectionCount: 100 \ No newline at end of file diff --git a/BlueMapCLI/build.gradle b/BlueMapCLI/build.gradle index 9ba8f697..56fe99e9 100644 --- a/BlueMapCLI/build.gradle +++ b/BlueMapCLI/build.gradle @@ -10,7 +10,7 @@ jar { } build.dependsOn shadowJar { - destinationDir = file '../build/release' + destinationDir = file '../build/unsupported' archiveFileName = "BlueMap-${version}-cli.jar" //relocate 'com.flowpowered.math', 'de.bluecolored.shadow.flowpowered.math' //DON'T relocate this, because the API depends on it 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 6d66cac3..787bde1f 100644 --- a/BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java +++ b/BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java @@ -32,14 +32,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; @@ -50,137 +43,47 @@ import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; -import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.time.DurationFormatUtils; import com.flowpowered.math.GenericMath; import com.flowpowered.math.vector.Vector2i; -import com.google.common.base.Preconditions; -import de.bluecolored.bluemap.common.BlueMapWebServer; +import de.bluecolored.bluemap.common.BlueMapService; import de.bluecolored.bluemap.common.MapType; +import de.bluecolored.bluemap.common.MissingResourcesException; import de.bluecolored.bluemap.common.RenderManager; import de.bluecolored.bluemap.common.RenderTask; -import de.bluecolored.bluemap.core.config.ConfigManager; -import de.bluecolored.bluemap.core.config.MainConfig; -import de.bluecolored.bluemap.core.config.MainConfig.MapConfig; +import de.bluecolored.bluemap.core.BlueMap; +import de.bluecolored.bluemap.core.config.WebServerConfig; import de.bluecolored.bluemap.core.logger.Logger; -import de.bluecolored.bluemap.core.mca.MCAWorld; -import de.bluecolored.bluemap.core.metrics.Metrics; -import de.bluecolored.bluemap.core.render.RenderSettings; -import de.bluecolored.bluemap.core.render.TileRenderer; import de.bluecolored.bluemap.core.render.hires.HiresModelManager; -import de.bluecolored.bluemap.core.render.lowres.LowresModelManager; -import de.bluecolored.bluemap.core.resourcepack.ParseResourceException; -import de.bluecolored.bluemap.core.resourcepack.ResourcePack; -import de.bluecolored.bluemap.core.web.WebFilesManager; +import de.bluecolored.bluemap.core.web.FileRequestHandler; import de.bluecolored.bluemap.core.web.WebSettings; -import de.bluecolored.bluemap.core.world.SlicedWorld; -import de.bluecolored.bluemap.core.world.World; +import de.bluecolored.bluemap.core.webserver.HttpRequestHandler; +import de.bluecolored.bluemap.core.webserver.WebServer; public class BlueMapCLI { - - private ConfigManager configManager; - private File configFolder; - private ResourcePack resourcePack; - private boolean forceRender; - public BlueMapCLI(ConfigManager configManager, File configFolder, boolean forceRender) { - this.configManager = configManager; - this.configFolder = configFolder; - this.forceRender = forceRender; - this.resourcePack = null; - } - - public void renderMaps() throws IOException { - Preconditions.checkNotNull(resourcePack); + public void renderMaps(BlueMapService blueMap, boolean forceRender, boolean forceGenerateWebapp) throws IOException { + blueMap.createOrUpdateWebApp(forceGenerateWebapp); + WebSettings webSettings = blueMap.updateWebAppSettings(); - MainConfig config = configManager.getMainConfig(); - configManager.loadResourceConfigs(resourcePack); + RenderManager renderManager = new RenderManager(blueMap.getCoreConfig().getRenderThreadCount()); + File rmstate = new File(blueMap.getCoreConfig().getDataFolder(), "rmstate"); - config.getWebDataPath().toFile().mkdirs(); - - Map maps = new HashMap<>(); - - for (MapConfig mapConfig : config.getMapConfigs()) { - File worldFolder = new File(mapConfig.getWorldPath()); - if (!worldFolder.exists() || !worldFolder.isDirectory()) { - throw new IOException("Save folder '" + worldFolder + "' does not exist or is not a directory!"); - } - - Logger.global.logInfo("Preparing renderer for map '" + mapConfig.getId() + "' ..."); - World world = MCAWorld.load(worldFolder.toPath(), UUID.randomUUID(), configManager.getBlockIdConfig(), configManager.getBlockPropertiesConfig(), configManager.getBiomeConfig()); - - //slice world if configured - if (!mapConfig.getMin().equals(RenderSettings.DEFAULT_MIN) || !mapConfig.getMax().equals(RenderSettings.DEFAULT_MAX)) { - if (mapConfig.isRenderEdges()) { - world = new SlicedWorld(world, mapConfig.getMin(), mapConfig.getMax()); - } else { - world = new SlicedWorld( - world, - mapConfig.getMin().min(mapConfig.getMin().sub(2, 2, 2)), // protect from int-overflow - mapConfig.getMax().max(mapConfig.getMax().add(2, 2, 2)) // protect from int-overflow - ); - } - } - - HiresModelManager hiresModelManager = new HiresModelManager( - config.getWebDataPath().resolve(mapConfig.getId()).resolve("hires"), - resourcePack, - mapConfig, - new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize()) - ); - - LowresModelManager lowresModelManager = new LowresModelManager( - config.getWebDataPath().resolve(mapConfig.getId()).resolve("lowres"), - new Vector2i(mapConfig.getLowresPointsPerLowresTile(), mapConfig.getLowresPointsPerLowresTile()), - new Vector2i(mapConfig.getLowresPointsPerHiresTile(), mapConfig.getLowresPointsPerHiresTile()), - mapConfig.useGzipCompression() - ); - - TileRenderer tileRenderer = new TileRenderer(hiresModelManager, lowresModelManager); - - MapType mapType = new MapType(mapConfig.getId(), mapConfig.getName(), world, tileRenderer); - maps.put(mapConfig.getId(), mapType); - } - - Logger.global.logInfo("Writing settings.json ..."); - WebSettings webSettings = new WebSettings(config.getWebDataPath().resolve("settings.json").toFile()); - webSettings.set(config.isUseCookies(), "useCookies"); - webSettings.setAllMapsEnabled(false); - for (MapType map : maps.values()) { - webSettings.setMapEnabled(true, map.getId()); - webSettings.setFrom(map.getTileRenderer(), map.getId()); - webSettings.setFrom(map.getWorld(), map.getId()); - } - int ordinal = 0; - for (MapConfig map : config.getMapConfigs()) { - if (!maps.containsKey(map.getId())) continue; //don't add not loaded maps - webSettings.setOrdinal(ordinal++, map.getId()); - webSettings.setFrom(map, map.getId()); - } - webSettings.save(); - - Logger.global.logInfo("Writing textures.json ..."); - File textureExportFile = config.getWebDataPath().resolve("textures.json").toFile(); - resourcePack.saveTextureFile(textureExportFile); - - RenderManager renderManager = new RenderManager(config.getRenderThreadCount()); - File rmstate = new File(configFolder, "rmstate"); - - if (rmstate.exists()) { + if (!forceRender && rmstate.exists()) { try ( InputStream in = new GZIPInputStream(new FileInputStream(rmstate)); DataInputStream din = new DataInputStream(in); ){ - renderManager.readState(din, maps.values()); - Logger.global.logInfo("Found unfinished render, continuing ... (If you want to start a new render, delete the this file: " + rmstate.getCanonicalPath()); + renderManager.readState(din, blueMap.getMaps().values()); + Logger.global.logInfo("Found unfinished render, continuing ... (If you want to start a new render, delete the this file: " + rmstate.getCanonicalPath() + " or force a full render using -f)"); } catch (IOException ex) { Logger.global.logError("Failed to read saved render-state! Remove the file " + rmstate.getCanonicalPath() + " to start a new render.", ex); return; } } else { - for (MapType map : maps.values()) { + for (MapType map : blueMap.getMaps().values()) { Logger.global.logInfo("Creating render-task for map '" + map.getId() + "' ..."); Logger.global.logInfo("Collecting tiles ..."); @@ -214,6 +117,30 @@ public void renderMaps() throws IOException { Logger.global.logInfo("Starting render ..."); renderManager.start(); + Thread shutdownHook = new Thread(() -> { + Logger.global.logInfo("Stopping render ..."); + renderManager.stop(); + + Logger.global.logInfo("Saving tiles ..."); + RenderTask currentTask = renderManager.getCurrentRenderTask(); + if (currentTask != null){ + currentTask.getMapType().getTileRenderer().save(); + } + + Logger.global.logInfo("Saving render-state ..."); + try ( + OutputStream os = new GZIPOutputStream(new FileOutputStream(rmstate)); + DataOutputStream dos = new DataOutputStream(os); + ){ + renderManager.writeState(dos); + + Logger.global.logInfo("Render saved and stopped! Restart the render (without using -f) to resume."); + } catch (IOException ex) { + Logger.global.logError("Failed to save render-state!", ex); + } + }); + Runtime.getRuntime().addShutdownHook(shutdownHook); + long startTime = System.currentTimeMillis(); long lastLogUpdate = startTime; @@ -266,12 +193,16 @@ public void renderMaps() throws IOException { } } - renderManager.stop(); + //render finished and saved, so this is no longer needed + Runtime.getRuntime().removeShutdownHook(shutdownHook); + //stop render-threads + renderManager.stop(); + //render finished, so remove render state file rmstate.delete(); - for (MapType map : maps.values()) { + for (MapType map : blueMap.getMaps().values()) { webSettings.set(startTime, "maps", map.getId(), "last-render"); } @@ -284,134 +215,112 @@ public void renderMaps() throws IOException { Logger.global.logInfo("Render finished!"); } - public void startWebserver() throws IOException { + public void startWebserver(BlueMapService blueMap) throws IOException { Logger.global.logInfo("Starting webserver ..."); - BlueMapWebServer webserver = new BlueMapWebServer(configManager.getMainConfig()); - webserver.start(); + WebServerConfig config = blueMap.getWebServerConfig(); + HttpRequestHandler requestHandler = new FileRequestHandler(config.getWebRoot().toPath(), "BlueMap v" + BlueMap.VERSION); + + WebServer webServer = new WebServer( + config.getWebserverPort(), + config.getWebserverMaxConnections(), + config.getWebserverBindAdress(), + requestHandler + ); + webServer.start(); } - private boolean loadResources() throws IOException, ParseResourceException { - Logger.global.logInfo("Loading resources ..."); - - MainConfig config = configManager.getMainConfig(); - - File defaultResourceFile = config.getDataPath().resolve("minecraft-client-" + ResourcePack.MINECRAFT_CLIENT_VERSION + ".jar").toFile(); - File resourceExtensionsFile = config.getDataPath().resolve("resourceExtensions.zip").toFile(); - File textureExportFile = config.getWebDataPath().resolve("textures.json").toFile(); - - if (!defaultResourceFile.exists()) { - if (!handleMissingResources(defaultResourceFile)) return false; - } - - resourceExtensionsFile.delete(); - FileUtils.copyURLToFile(BlueMapCLI.class.getResource("/resourceExtensions.zip"), resourceExtensionsFile, 10000, 10000); - - //find more resource packs - File resourcePackFolder = configFolder.toPath().resolve("resourcepacks").toFile(); - resourcePackFolder.mkdirs(); - File[] resourcePacks = resourcePackFolder.listFiles(); - Arrays.sort(resourcePacks); //load resource packs in alphabetical order so you can reorder them by renaming - - List resources = new ArrayList<>(resourcePacks.length + 1); - resources.add(defaultResourceFile); - for (File file : resourcePacks) resources.add(file); - resources.add(resourceExtensionsFile); - - resourcePack = new ResourcePack(); - if (textureExportFile.exists()) resourcePack.loadTextureFile(textureExportFile); - resourcePack.load(resources); - resourcePack.saveTextureFile(textureExportFile); - - return true; - } - - private boolean handleMissingResources(File resourceFile) throws IOException { - if (configManager.getMainConfig().isDownloadAccepted()) { - try { - Logger.global.logInfo("Downloading " + ResourcePack.MINECRAFT_CLIENT_URL + " to " + resourceFile.getCanonicalPath() + " ..."); - ResourcePack.downloadDefaultResource(resourceFile); - return true; - } catch (IOException e) { - Logger.global.logError("Failed to download resources!", e); - return false; - } - } else { - Logger.global.logWarning("BlueMap is missing important resources!"); - Logger.global.logWarning("You need to accept the download of the required files in order of BlueMap to work!"); - Logger.global.logWarning("Please check " + configManager.getMainConfigFile().getCanonicalPath() + " and try again!"); - return false; - } - } - - public static void main(String[] args) throws IOException, ParseResourceException { + public static void main(String[] args) { CommandLineParser parser = new DefaultParser(); + BlueMapCLI cli = new BlueMapCLI(); + BlueMapService blueMap = null; + try { CommandLine cmd = parser.parse(BlueMapCLI.createOptions(), args, false); - + //help if (cmd.hasOption("h")) { BlueMapCLI.printHelp(); return; } - //load config + //config folder File configFolder = new File("."); if (cmd.hasOption("c")) { configFolder = new File(cmd.getOptionValue("c")); configFolder.mkdirs(); } - - URL cliConfigUrl = BlueMapCLI.class.getResource("/bluemap-cli.conf"); - URL cliDefaultsUrl = BlueMapCLI.class.getResource("/bluemap-cli-defaults.conf"); - - ConfigManager config = new ConfigManager(configFolder, cliConfigUrl, cliDefaultsUrl); - boolean configCreated = !config.getMainConfigFile().exists(); - config.loadMainConfig(); - - if (configCreated) { - Logger.global.logInfo("No config file found! Created default config here: " + config.getMainConfigFile().getCanonicalPath()); - return; - } - - WebFilesManager webFilesManager = new WebFilesManager(config.getMainConfig().getWebRoot()); - if (webFilesManager.needsUpdate()) { - Logger.global.logInfo("Updating webfiles in " + config.getMainConfig().getWebRoot().normalize() + "..."); - webFilesManager.updateFiles(); - } - - BlueMapCLI bluemap = new BlueMapCLI(config, configFolder, cmd.hasOption("f")); - if (config.getMainConfig().isWebserverEnabled()) { - //start webserver - bluemap.startWebserver(); + blueMap = new BlueMapService(configFolder); + boolean noActions = true; - //wait a second to let the webserver start, looks nicer in the log - try { - Thread.sleep(1000); - } catch (InterruptedException ignore) { Thread.currentThread().interrupt(); } + if (cmd.hasOption("w")) { + noActions = false; + + cli.startWebserver(blueMap); + Thread.sleep(1000); //wait a second to let the webserver start, looks nicer in the log if anything comes after that } - - if (!config.getMainConfig().getMapConfigs().isEmpty()) { - //load resources - if (bluemap.loadResources()) { - - //metrics - if (config.getMainConfig().isMetricsEnabled()) Metrics.sendReportAsync("CLI"); - - //render maps - bluemap.renderMaps(); - - //since we don't need it any more, free some memory - bluemap.resourcePack = null; + if (cmd.hasOption("r")) { + noActions = false; + + boolean force = cmd.hasOption("f"); + cli.renderMaps(blueMap, force, cmd.hasOption("g")); + } else { + if (cmd.hasOption("g")) { + noActions = false; + blueMap.createOrUpdateWebApp(true); + } + if (cmd.hasOption("s")) { + noActions = false; + blueMap.updateWebAppSettings(); } } + // if nothing has been defined to do + if (noActions) { + + if ( + !blueMap.getCoreConfigFile().exists() || + !blueMap.getRenderConfigFile().exists() || + !blueMap.getWebServerConfigFile().exists() + ) { + Logger.global.logInfo("Generating default config files for you, here: " + configFolder.getCanonicalPath().toString() + "\n"); + } + + //generate all configs + blueMap.getCoreConfig(); + blueMap.getRenderConfig(); + blueMap.getWebServerConfig(); + + //print help + BlueMapCLI.printHelp(); + System.exit(1); + return; + } + + } catch (MissingResourcesException e) { + Logger.global.logWarning("BlueMap is missing important resources!"); + Logger.global.logWarning("You need to accept the download of the required files in order of BlueMap to work!"); + try { Logger.global.logWarning("Please check: " + blueMap.getCoreConfigFile().getCanonicalPath()); } catch (NullPointerException | IOException ignored) {} + System.exit(2); + return; } catch (ParseException e) { Logger.global.logError("Failed to parse provided arguments!", e); BlueMapCLI.printHelp(); + System.exit(1); + return; + } catch (IOException e) { + Logger.global.logError("An IO-error occurred!", e); + System.exit(1); + return; + } catch (InterruptedException ex) { + System.exit(1); + return; + } catch (RuntimeException e) { + Logger.global.logError("An unexpected error occurred!", e); + System.exit(1); return; } } @@ -429,7 +338,13 @@ private static Options createOptions() { .desc("Sets path of the folder containing the configuration-files to use (configurations will be generated here if they don't exist)") .build() ); + + options.addOption("w", "webserver", false, "Starts the web-server, configured in the 'webserver.conf' file"); + options.addOption("g", "generate-webapp", false, "Generates the files for the web-app to the folder, configured in the 'render.conf' file (this is done automatically when rendering if the 'index.html' file in the webroot can't be found)"); + options.addOption("s", "generate-websettings", false, "Generates the settings for the web-app, using the settings from the 'render.conf' file (this is done automatically when rendering)"); + + options.addOption("r", "render", false, "Renders the maps configured in the 'render.conf' file"); options.addOption("f", "force-render", false, "Forces rendering everything, instead of only rendering chunks that have been modified since the last render"); return options; @@ -438,7 +353,7 @@ private static Options createOptions() { private static void printHelp() { HelpFormatter formatter = new HelpFormatter(); - String filename = "bluemapcli.jar"; + String filename = "bluemap-cli.jar"; try { File file = new File(BlueMapCLI.class.getProtectionDomain() .getCodeSource() @@ -452,11 +367,22 @@ private static void printHelp() { filename = file.getAbsolutePath(); } } - } catch (IOException ex) {} + } catch (IOException ignore) {} String command = "java -jar " + filename; - formatter.printHelp(command + " [options]", "\nOptions:", createOptions(), ""); + StringBuilder footer = new StringBuilder(); + footer.append("Examples:\n\n"); + footer.append(command + " -c './config/'\n"); + footer.append("Generates the default/example configurations in a folder named 'config' if they are not already present\n\n"); + footer.append(command + " -r\n"); + footer.append("Render the configured maps\n\n"); + footer.append(command + " -w\n"); + footer.append("Start only the webserver without doing anything else\n\n"); + footer.append(command + " -gs\n"); + footer.append("Generate the web-app and settings without starting a render\n\n"); + + formatter.printHelp(command + " [options]", "\nOptions:", createOptions(), "\n" + footer.toString()); } } diff --git a/BlueMapCLI/src/main/resources/bluemap-cli-defaults.conf b/BlueMapCLI/src/main/resources/bluemap-cli-defaults.conf deleted file mode 100644 index 647dc385..00000000 --- a/BlueMapCLI/src/main/resources/bluemap-cli-defaults.conf +++ /dev/null @@ -1,11 +0,0 @@ -accept-download: false -metrics: true -renderThreadCount: 0 -data: "." -webroot: "web" -useCookies: true -webserver { - enabled: false - port: 8100 - maxConnectionCount: 100 -} diff --git a/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/core-defaults.conf b/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/core-defaults.conf new file mode 100644 index 00000000..c50150b4 --- /dev/null +++ b/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/core-defaults.conf @@ -0,0 +1,4 @@ +accept-download: false +renderThreadCount: 0 +metrics: true +data: "data" \ No newline at end of file diff --git a/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/core.conf b/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/core.conf new file mode 100644 index 00000000..c9f8dfc3 --- /dev/null +++ b/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/core.conf @@ -0,0 +1,31 @@ +## ## +## BlueMap ## +## Core-Config ## +## ## + +# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula), +# you confirm that you own a license to Minecraft (Java Edition) +# and you agree that BlueMap will download and use this file for you: %minecraft-client-url% +# (Alternatively you can download the file yourself and store it here: /minecraft-client-%minecraft-client-version%.jar) +# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA. +# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.) +# %datetime-iso% +accept-download: false + +# This changes the amount of threads that BlueMap will use to render the maps. +# A higher value can improve render-speed but could impact performance on the host machine. +# This should be always below or equal to the number of available processor-cores. +# Zero or a negative value means the amount of of available processor-cores subtracted by the value. +# (So a value of -2 with 6 cores results in 4 render-processes) +# Default is 0 +renderThreadCount: 0 + +# If this is true, BlueMap might send really basic metrics reports containg only the implementation-type and the version that is being used to https://metrics.bluecolored.de/bluemap/ +# This allows me to track the basic usage of BlueMap and helps me stay motivated to further develop this tool! Please leave it on :) +# An example report looks like this: {"implementation":"bukkit","version":"%version%"} +# Default is true +metrics: true + +# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later. +# Default is "data" +data: "data" \ No newline at end of file diff --git a/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/render-defaults.conf b/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/render-defaults.conf new file mode 100644 index 00000000..47620ad1 --- /dev/null +++ b/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/render-defaults.conf @@ -0,0 +1,3 @@ +webroot: "web" +useCookies: true +maps: [] diff --git a/BlueMapCLI/src/main/resources/bluemap-cli.conf b/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/render.conf similarity index 59% rename from BlueMapCLI/src/main/resources/bluemap-cli.conf rename to BlueMapCLI/src/main/resources/de/bluecolored/bluemap/render.conf index 5ee2904e..a320afc7 100644 --- a/BlueMapCLI/src/main/resources/bluemap-cli.conf +++ b/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/render.conf @@ -1,66 +1,16 @@ ## ## ## BlueMap ## -## ## -## by Blue (Lukas Rieger) ## -## http://bluecolored.de/ ## +## Render-Config ## ## ## -# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula), -# you confirm that you own a license to Minecraft (Java Edition) -# and you agree that BlueMap will download and use this file for you: %minecraft-client-url% -# (Alternatively you can download the file yourself and store it here: /minecraft-client-%minecraft-client-version%.jar) -# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA. -# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.) -# %datetime-iso% -accept-download: false - -# This changes the amount of threads that BlueMap will use to render the maps. -# A higher value can improve render-speed but could impact performance on the host machine. -# This should be always below or equal to the number of available processor-cores. -# Zero or a negative value means the amount of of available processor-cores subtracted by the value. -# (So a value of -2 with 6 cores results in 4 render-processes) -# Default is 0 -renderThreadCount: 0 - -# If this is true, BlueMap might send really basic metrics reports containg only the implementation-type and the version that is being used to https://metrics.bluecolored.de/bluemap/ -# This allows me to track the basic usage of BlueMap and helps me stay motivated to further develop this tool! Please leave it on :) -# An example report looks like this: {"implementation":"cli","version":"%version%"} -metrics: true - -# The folder where bluemap saves data-files it needs during runtime -data: "." - -# The webroot of the website that displays the map. +# The folder (webroot) where the map-data and web-application files will be saved. +# Default is "web" webroot: "web" -# Unncomment this to override the path where bluemap stores the data-files. -# Default is "/data" -#webdata: "path/to/data/folder" - # If the web-application should use cookies to save the configurations of a user. +# Default is true useCookies: true -webserver { - # With this setting you can enable the integrated web-server. - # Default is disabled - enabled: false - - # The IP-Adress that the webserver binds to. - # Use "0.0.0.0" to bind to all available local adresses. - # If you only want to access it locally use "localhost". - # Default is "0.0.0.0" - #ip: "localhost" - #ip: "127.0.0.1" - - # The port that the webserver listenes to. - # Default is 8100 - port: 8100 - - # Max number of simultaneous connections that the webserver allows - # Default is 100 - maxConnectionCount: 100 -} - # This is an array with multiple configured maps. # You can define multiple maps, for different worlds with different render-settings here maps: [ @@ -127,6 +77,16 @@ maps: [ # Changing this value requires a re-render of the map. # Default is true useCompression: true + + # Normally BlueMap detects if a chunk has not yet generated it's light-data and omits rendering those chunks. + # If this is set to true BlueMap will render Chunks even if there is no light-data! + # This can be usefull for example if some mod prevents light-data from being saved correctly. + # However, this also has a few drawbacks: + # - For those chunks, every block will always be fully lit + # - Night-mode might not work correctly + # - Caves will always be rendered (ignoring the 'renderCaves' setting) + # Default is false + ignoreMissingLightData: false } # Here another example for the End-Map diff --git a/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf b/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf new file mode 100644 index 00000000..6f1defd4 --- /dev/null +++ b/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf @@ -0,0 +1,4 @@ +enabled: true +webroot: "web" +port: 8100 +maxConnectionCount: 100 \ No newline at end of file diff --git a/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/webserver.conf b/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/webserver.conf new file mode 100644 index 00000000..d8807f75 --- /dev/null +++ b/BlueMapCLI/src/main/resources/de/bluecolored/bluemap/webserver.conf @@ -0,0 +1,24 @@ +## ## +## BlueMap ## +## Webserver-Config ## +## ## + +# The webroot that the server will host to the web. +# Usually this should be set to the same directory like in the Core-Config! +# Default is "web" +webroot: "web" + +# The IP-Adress that the webserver binds to. +# Use "0.0.0.0" to bind to all available local adresses. +# If you only want to access it locally use "localhost". +# Default is "0.0.0.0" +#ip: "localhost" +#ip: "123.45.6.78" + +# The port that the webserver listenes to. +# Default is 8100 +port: 8100 + +# Max number of simultaneous connections that the webserver allows +# Default is 100 +maxConnectionCount: 100 \ No newline at end of file diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapService.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapService.java new file mode 100644 index 00000000..cf75b474 --- /dev/null +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapService.java @@ -0,0 +1,336 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.common; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.commons.io.FileUtils; + +import com.flowpowered.math.vector.Vector2i; + +import de.bluecolored.bluemap.common.plugin.Plugin; +import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface; +import de.bluecolored.bluemap.core.config.ConfigManager; +import de.bluecolored.bluemap.core.config.CoreConfig; +import de.bluecolored.bluemap.core.config.MapConfig; +import de.bluecolored.bluemap.core.config.RenderConfig; +import de.bluecolored.bluemap.core.config.WebServerConfig; +import de.bluecolored.bluemap.core.logger.Logger; +import de.bluecolored.bluemap.core.mca.MCAWorld; +import de.bluecolored.bluemap.core.render.RenderSettings; +import de.bluecolored.bluemap.core.render.TileRenderer; +import de.bluecolored.bluemap.core.render.hires.HiresModelManager; +import de.bluecolored.bluemap.core.render.lowres.LowresModelManager; +import de.bluecolored.bluemap.core.resourcepack.ParseResourceException; +import de.bluecolored.bluemap.core.resourcepack.ResourcePack; +import de.bluecolored.bluemap.core.web.WebFilesManager; +import de.bluecolored.bluemap.core.web.WebSettings; +import de.bluecolored.bluemap.core.world.SlicedWorld; +import de.bluecolored.bluemap.core.world.World; + +/** + * This is the attempt to generalize as many actions as possible to have CLI and Plugins run on the same general setup-code. + */ +public class BlueMapService { + private File configFolder; + private ThrowingFunction worldUUIDProvider; + private ThrowingFunction worldNameProvider; + + private ConfigManager configManager; + private boolean resourceConfigLoaded = false; + + private CoreConfig coreConfig; + private RenderConfig renderConfig; + private WebServerConfig webServerConfig; + + private ResourcePack resourcePack; + + private Map worlds; + private Map maps; + + public BlueMapService(File configFolder) { + this.configFolder = configFolder; + + Map uuids = new HashMap<>(); + this.worldUUIDProvider = file -> { + UUID uuid = uuids.get(file); + if (uuid == null) { + uuid = UUID.randomUUID(); + uuids.put(file, uuid); + } + return uuid; + }; + + this.worldNameProvider = uuid -> null; + + configManager = new ConfigManager(); + } + + public BlueMapService(ServerInterface serverInterface) { + this.configFolder = serverInterface.getConfigFolder(); + this.worldUUIDProvider = serverInterface::getUUIDForWorld; + this.worldNameProvider = serverInterface::getWorldName; + + this.configManager = new ConfigManager(); + } + + public synchronized void createOrUpdateWebApp(boolean force) throws IOException { + WebFilesManager webFilesManager = new WebFilesManager(getRenderConfig().getWebRoot()); + if (force || webFilesManager.needsUpdate()) { + webFilesManager.updateFiles(); + } + } + + public synchronized WebSettings updateWebAppSettings() throws IOException { + WebSettings webSettings = new WebSettings(new File(getRenderConfig().getWebRoot(), "data" + File.separator + "settings.json")); + webSettings.set(getRenderConfig().isUseCookies(), "useCookies"); + webSettings.setAllMapsEnabled(false); + for (MapType map : getMaps().values()) { + webSettings.setMapEnabled(true, map.getId()); + webSettings.setFrom(map.getTileRenderer(), map.getId()); + webSettings.setFrom(map.getWorld(), map.getId()); + } + int ordinal = 0; + for (MapConfig map : getRenderConfig().getMapConfigs()) { + if (!getMaps().containsKey(map.getId())) continue; //don't add not loaded maps + webSettings.setOrdinal(ordinal++, map.getId()); + webSettings.setFrom(map, map.getId()); + } + webSettings.save(); + + return webSettings; + } + + public synchronized Map getWorlds() throws IOException { + if (worlds == null) loadWorldsAndMaps(); + return worlds; + } + + public synchronized Map getMaps() throws IOException { + if (maps == null) loadWorldsAndMaps(); + return maps; + } + + private synchronized void loadWorldsAndMaps() throws IOException { + maps = new HashMap<>(); + worlds = new HashMap<>(); + + for (MapConfig mapConfig : getRenderConfig().getMapConfigs()) { + String id = mapConfig.getId(); + String name = mapConfig.getName(); + + File worldFolder = new File(mapConfig.getWorldPath()); + if (!worldFolder.exists() || !worldFolder.isDirectory()) { + Logger.global.logWarning("Failed to load map '" + id + "': '" + worldFolder.getCanonicalPath() + "' does not exist or is no directory!"); + continue; + } + + UUID worldUUID; + try { + worldUUID = worldUUIDProvider.apply(worldFolder); + } catch (IOException e) { + Logger.global.logError("Failed to load map '" + id + "': Failed to get UUID for the world!", e); + continue; + } + + World world = worlds.get(worldUUID); + if (world == null) { + try { + world = MCAWorld.load(worldFolder.toPath(), worldUUID, getConfigManager().getBlockIdConfig(), getConfigManager().getBlockPropertiesConfig(), getConfigManager().getBiomeConfig(), worldNameProvider.apply(worldUUID), true); + worlds.put(worldUUID, world); + } catch (MissingResourcesException e) { + throw e; // rethrow this to stop loading and display resource-missing message + } catch (IOException e) { + Logger.global.logError("Failed to load map '" + id + "': Failed to read level.dat", e); + continue; + } + } + + //slice world if configured + if (!mapConfig.getMin().equals(RenderSettings.DEFAULT_MIN) || !mapConfig.getMax().equals(RenderSettings.DEFAULT_MAX)) { + if (mapConfig.isRenderEdges()) { + world = new SlicedWorld(world, mapConfig.getMin(), mapConfig.getMax()); + } else { + world = new SlicedWorld( + world, + mapConfig.getMin().min(mapConfig.getMin().sub(2, 2, 2)), // protect from int-overflow + mapConfig.getMax().max(mapConfig.getMax().add(2, 2, 2)) // protect from int-overflow + ); + } + } + + HiresModelManager hiresModelManager = new HiresModelManager( + getRenderConfig().getWebRoot().toPath().resolve("data").resolve(id).resolve("hires"), + getResourcePack(), + mapConfig, + new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize()) + ); + + LowresModelManager lowresModelManager = new LowresModelManager( + getRenderConfig().getWebRoot().toPath().resolve("data").resolve(id).resolve("lowres"), + new Vector2i(mapConfig.getLowresPointsPerLowresTile(), mapConfig.getLowresPointsPerLowresTile()), + new Vector2i(mapConfig.getLowresPointsPerHiresTile(), mapConfig.getLowresPointsPerHiresTile()), + mapConfig.useGzipCompression() + ); + + TileRenderer tileRenderer = new TileRenderer(hiresModelManager, lowresModelManager); + + MapType mapType = new MapType(id, name, world, tileRenderer); + maps.put(id, mapType); + } + + worlds = Collections.unmodifiableMap(worlds); + maps = Collections.unmodifiableMap(maps); + } + + public synchronized ResourcePack getResourcePack() throws IOException, MissingResourcesException { + if (resourcePack == null) { + File defaultResourceFile = new File(getCoreConfig().getDataFolder(), "minecraft-client-" + ResourcePack.MINECRAFT_CLIENT_VERSION + ".jar"); + File resourceExtensionsFile = new File(getCoreConfig().getDataFolder(), "resourceExtensions.zip"); + + File textureExportFile = new File(getRenderConfig().getWebRoot(), "data" + File.separator + "textures.json"); + + if (!defaultResourceFile.exists()) { + if (getCoreConfig().isDownloadAccepted()) { + + //download file + try { + Logger.global.logInfo("Downloading " + ResourcePack.MINECRAFT_CLIENT_URL + " to " + defaultResourceFile + " ..."); + ResourcePack.downloadDefaultResource(defaultResourceFile); + } catch (IOException e) { + throw new IOException("Failed to download resources!", e); + } + + } else { + throw new MissingResourcesException(); + } + } + + Logger.global.logInfo("Loading resources..."); + + resourceExtensionsFile.delete(); + FileUtils.copyURLToFile(Plugin.class.getResource("/de/bluecolored/bluemap/resourceExtensions.zip"), resourceExtensionsFile, 10000, 10000); + + //find more resource packs + File resourcePackFolder = new File(configFolder, "resourcepacks"); + resourcePackFolder.mkdirs(); + File[] resourcePacks = resourcePackFolder.listFiles(); + Arrays.sort(resourcePacks); //load resource packs in alphabetical order so you can reorder them by renaming + + List resources = new ArrayList<>(resourcePacks.length + 1); + resources.add(defaultResourceFile); + for (File file : resourcePacks) resources.add(file); + resources.add(resourceExtensionsFile); + + try { + resourcePack = new ResourcePack(); + if (textureExportFile.exists()) resourcePack.loadTextureFile(textureExportFile); + resourcePack.load(resources); + resourcePack.saveTextureFile(textureExportFile); + } catch (ParseResourceException e) { + throw new IOException("Failed to parse resources!", e); + } + + } + + return resourcePack; + } + + public synchronized ConfigManager getConfigManager() throws IOException { + if (!resourceConfigLoaded) { + configManager.loadResourceConfigs(configFolder, getResourcePack()); + resourceConfigLoaded = true; + } + + return configManager; + } + + public File getCoreConfigFile() { + return new File(configFolder, "core.conf"); + } + + public synchronized CoreConfig getCoreConfig() throws IOException { + if (coreConfig == null) { + coreConfig = new CoreConfig(configManager.loadOrCreate( + getCoreConfigFile(), + Plugin.class.getResource("/de/bluecolored/bluemap/core.conf"), + Plugin.class.getResource("/de/bluecolored/bluemap/core-defaults.conf"), + true, + true + )); + } + + return coreConfig; + } + + public File getRenderConfigFile() { + return new File(configFolder, "render.conf"); + } + + public synchronized RenderConfig getRenderConfig() throws IOException { + if (renderConfig == null) { + renderConfig = new RenderConfig(configManager.loadOrCreate( + getRenderConfigFile(), + Plugin.class.getResource("/de/bluecolored/bluemap/render.conf"), + Plugin.class.getResource("/de/bluecolored/bluemap/render-defaults.conf"), + true, + true + )); + } + + return renderConfig; + } + + public File getWebServerConfigFile() { + return new File(configFolder, "webserver.conf"); + } + + public synchronized WebServerConfig getWebServerConfig() throws IOException { + if (webServerConfig == null) { + webServerConfig = new WebServerConfig(configManager.loadOrCreate( + getWebServerConfigFile(), + Plugin.class.getResource("/de/bluecolored/bluemap/webserver.conf"), + Plugin.class.getResource("/de/bluecolored/bluemap/webserver-defaults.conf"), + true, + true + )); + } + + return webServerConfig; + } + + public File getConfigFolder() { + return configFolder; + } + +} diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapWebServer.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapWebServer.java deleted file mode 100644 index bdfd1fe9..00000000 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/BlueMapWebServer.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of BlueMap, licensed under the MIT License (MIT). - * - * Copyright (c) Blue (Lukas Rieger) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package de.bluecolored.bluemap.common; - -import java.io.IOException; - -import de.bluecolored.bluemap.common.live.LiveAPIRequestHandler; -import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface; -import de.bluecolored.bluemap.core.config.LiveAPISettings; -import de.bluecolored.bluemap.core.logger.Logger; -import de.bluecolored.bluemap.core.web.FileRequestHandler; -import de.bluecolored.bluemap.core.web.WebFilesManager; -import de.bluecolored.bluemap.core.web.WebServerConfig; -import de.bluecolored.bluemap.core.webserver.WebServer; - -public class BlueMapWebServer extends WebServer { - - private WebFilesManager webFilesManager; - - - public BlueMapWebServer(WebServerConfig config) { - super( - config.getWebserverPort(), - config.getWebserverMaxConnections(), - config.getWebserverBindAdress(), - new FileRequestHandler(config.getWebRoot(), "BlueMap/Webserver") - ); - - this.webFilesManager = new WebFilesManager(config.getWebRoot()); - } - - public BlueMapWebServer(WebServerConfig config, LiveAPISettings liveSettings, ServerInterface server) { - super( - config.getWebserverPort(), - config.getWebserverMaxConnections(), - config.getWebserverBindAdress(), - new LiveAPIRequestHandler(server, liveSettings, new FileRequestHandler(config.getWebRoot(), "BlueMap/Webserver")) - ); - - this.webFilesManager = new WebFilesManager(config.getWebRoot()); - } - - public void updateWebfiles() throws IOException { - if (webFilesManager.needsUpdate()) { - Logger.global.logInfo("Webfiles are missing or outdated, updating..."); - webFilesManager.updateFiles(); - } - } - -} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebServerConfig.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/MissingResourcesException.java similarity index 82% rename from BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebServerConfig.java rename to BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/MissingResourcesException.java index df43550b..27d2cf9c 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebServerConfig.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/MissingResourcesException.java @@ -22,19 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package de.bluecolored.bluemap.core.web; +package de.bluecolored.bluemap.common; -import java.net.InetAddress; -import java.nio.file.Path; - -public interface WebServerConfig { - - Path getWebRoot(); - - InetAddress getWebserverBindAdress(); - - int getWebserverPort(); - - int getWebserverMaxConnections(); +import java.io.IOException; +public class MissingResourcesException extends IOException { + private static final long serialVersionUID = 2084565069965755048L; } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/LiveAPISettings.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/ThrowingFunction.java similarity index 83% rename from BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/LiveAPISettings.java rename to BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/ThrowingFunction.java index 121008e9..fafde08b 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/LiveAPISettings.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/ThrowingFunction.java @@ -22,18 +22,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package de.bluecolored.bluemap.core.config; +package de.bluecolored.bluemap.common; -import java.util.Collection; +public interface ThrowingFunction { -public interface LiveAPISettings { - - boolean isLiveUpdatesEnabled(); - - Collection getHiddenGameModes(); - - boolean isHideInvisible(); - - boolean isHideSneaking(); + R apply(T t) throws E; } diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/api/BlueMapAPIImpl.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/api/BlueMapAPIImpl.java index f8c23c94..e484aca3 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/api/BlueMapAPIImpl.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/api/BlueMapAPIImpl.java @@ -55,25 +55,25 @@ public class BlueMapAPIImpl extends BlueMapAPI { private static final String IMAGE_ROOT_PATH = "images"; - public Plugin blueMap; + public Plugin plugin; public RenderAPIImpl renderer; public Map worlds; public Map maps; - public BlueMapAPIImpl(Plugin blueMap) { - this.blueMap = blueMap; + public BlueMapAPIImpl(Plugin plugin) { + this.plugin = plugin; - this.renderer = new RenderAPIImpl(this, blueMap.getRenderManager()); + this.renderer = new RenderAPIImpl(this, plugin.getRenderManager()); worlds = new HashMap<>(); - for (World world : blueMap.getWorlds()) { + for (World world : plugin.getWorlds()) { BlueMapWorldImpl w = new BlueMapWorldImpl(this, world); worlds.put(w.getUuid(), w); } maps = new HashMap<>(); - for (MapType map : blueMap.getMapTypes()) { + for (MapType map : plugin.getMapTypes()) { BlueMapMapImpl m = new BlueMapMapImpl(this, map); maps.put(m.getId(), m); } @@ -86,7 +86,7 @@ public RenderAPIImpl getRenderAPI() { @Override public MarkerAPIImpl getMarkerAPI() throws IOException { - return new MarkerAPIImpl(this, blueMap.getMainConfig().getWebDataPath().resolve("markers.json").toFile()); + return new MarkerAPIImpl(this, new File(plugin.getRenderConfig().getWebRoot(), "data" + File.separator + "markers.json")); } @Override @@ -104,15 +104,9 @@ public String createImage(BufferedImage image, String path) throws IOException { path = path.replaceAll("[^a-zA-Z_\\.\\-\\/]", "_"); String separator = FileSystems.getDefault().getSeparator(); - Path webRoot = blueMap.getMainConfig().getWebRoot().toAbsolutePath(); - Path webDataRoot = blueMap.getMainConfig().getWebDataPath().toAbsolutePath(); - - Path imagePath; - if (webDataRoot.startsWith(webRoot)) { - imagePath = webDataRoot.resolve(Paths.get(IMAGE_ROOT_PATH, path.replace("/", separator) + ".png")).toAbsolutePath(); - } else { - imagePath = webRoot.resolve("assets").resolve(Paths.get(IMAGE_ROOT_PATH, path.replace("/", separator) + ".png")).toAbsolutePath(); - } + Path webRoot = plugin.getRenderConfig().getWebRoot().toPath().toAbsolutePath(); + Path webDataRoot = webRoot.resolve("data"); + Path imagePath = webDataRoot.resolve(Paths.get(IMAGE_ROOT_PATH, path.replace("/", separator) + ".png")).toAbsolutePath(); File imageFile = imagePath.toFile(); imageFile.getParentFile().mkdirs(); diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/live/LiveAPIRequestHandler.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/live/LiveAPIRequestHandler.java index f61c611e..0f17d1cb 100644 --- a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/live/LiveAPIRequestHandler.java +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/live/LiveAPIRequestHandler.java @@ -31,9 +31,9 @@ import com.google.gson.stream.JsonWriter; +import de.bluecolored.bluemap.common.plugin.PluginConfig; import de.bluecolored.bluemap.common.plugin.serverinterface.Player; import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface; -import de.bluecolored.bluemap.core.config.LiveAPISettings; import de.bluecolored.bluemap.core.webserver.HttpRequest; import de.bluecolored.bluemap.core.webserver.HttpRequestHandler; import de.bluecolored.bluemap.core.webserver.HttpResponse; @@ -45,9 +45,9 @@ public class LiveAPIRequestHandler implements HttpRequestHandler { private Map liveAPIRequests; private ServerInterface server; - private LiveAPISettings config; + private PluginConfig config; - public LiveAPIRequestHandler(ServerInterface server, LiveAPISettings config, HttpRequestHandler notFoundHandler) { + public LiveAPIRequestHandler(ServerInterface server, PluginConfig config, HttpRequestHandler notFoundHandler) { this.server = server; this.notFoundHandler = notFoundHandler; @@ -63,7 +63,13 @@ public LiveAPIRequestHandler(ServerInterface server, LiveAPISettings config, Htt public HttpResponse handle(HttpRequest request) { if (!config.isLiveUpdatesEnabled()) return this.notFoundHandler.handle(request); - HttpRequestHandler handler = liveAPIRequests.get(request.getPath()); + String path = request.getPath(); + + //normalize path + if (path.startsWith("/")) path = path.substring(1); + if (path.endsWith("/")) path = path.substring(0, path.length() - 1); + + HttpRequestHandler handler = liveAPIRequests.get(path); if (handler != null) return handler.handle(request); return this.notFoundHandler.handle(request); 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 9a30d8d4..fde373e2 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 @@ -30,217 +30,113 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; -import org.apache.commons.io.FileUtils; - -import com.flowpowered.math.vector.Vector2i; - -import de.bluecolored.bluemap.common.BlueMapWebServer; +import de.bluecolored.bluemap.common.BlueMapService; import de.bluecolored.bluemap.common.MapType; +import de.bluecolored.bluemap.common.MissingResourcesException; import de.bluecolored.bluemap.common.RenderManager; import de.bluecolored.bluemap.common.api.BlueMapAPIImpl; +import de.bluecolored.bluemap.common.live.LiveAPIRequestHandler; import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface; import de.bluecolored.bluemap.common.plugin.skins.PlayerSkinUpdater; -import de.bluecolored.bluemap.core.config.ConfigManager; -import de.bluecolored.bluemap.core.config.MainConfig; -import de.bluecolored.bluemap.core.config.MainConfig.MapConfig; +import de.bluecolored.bluemap.core.BlueMap; +import de.bluecolored.bluemap.core.config.CoreConfig; +import de.bluecolored.bluemap.core.config.RenderConfig; +import de.bluecolored.bluemap.core.config.WebServerConfig; import de.bluecolored.bluemap.core.logger.Logger; -import de.bluecolored.bluemap.core.mca.MCAWorld; import de.bluecolored.bluemap.core.metrics.Metrics; -import de.bluecolored.bluemap.core.render.RenderSettings; -import de.bluecolored.bluemap.core.render.TileRenderer; -import de.bluecolored.bluemap.core.render.hires.HiresModelManager; -import de.bluecolored.bluemap.core.render.lowres.LowresModelManager; import de.bluecolored.bluemap.core.resourcepack.ParseResourceException; import de.bluecolored.bluemap.core.resourcepack.ResourcePack; -import de.bluecolored.bluemap.core.web.WebFilesManager; -import de.bluecolored.bluemap.core.web.WebSettings; -import de.bluecolored.bluemap.core.world.SlicedWorld; +import de.bluecolored.bluemap.core.web.FileRequestHandler; +import de.bluecolored.bluemap.core.webserver.HttpRequestHandler; +import de.bluecolored.bluemap.core.webserver.WebServer; import de.bluecolored.bluemap.core.world.World; public class Plugin { public static final String PLUGIN_ID = "bluemap"; public static final String PLUGIN_NAME = "BlueMap"; - - private BlueMapAPIImpl api; - + private String implementationType; - private ServerInterface serverInterface; - - private MainConfig config; - private ResourcePack resourcePack; + + private BlueMapService blueMap; + private BlueMapAPIImpl api; private Map worlds; private Map maps; - + + private RenderManager renderManager; + private WebServer webServer; + private Thread periodicalSaveThread; + private Thread metricsThread; + + private PluginConfig pluginConfig; private MapUpdateHandler updateHandler; private PlayerSkinUpdater skinUpdater; - private RenderManager renderManager; - private BlueMapWebServer webServer; - - private Thread periodicalSaveThread; - private Thread metricsThread; - private boolean loaded = false; public Plugin(String implementationType, ServerInterface serverInterface) { this.implementationType = implementationType.toLowerCase(); - this.serverInterface = serverInterface; - - this.maps = new HashMap<>(); - this.worlds = new HashMap<>(); } public synchronized void load() throws IOException, ParseResourceException { if (loaded) return; unload(); //ensure nothing is left running (from a failed load or something) - //load configs - URL defaultSpongeConfig = Plugin.class.getResource("/bluemap-" + implementationType + ".conf"); - URL spongeConfigDefaults = Plugin.class.getResource("/bluemap-" + implementationType + "-defaults.conf"); - ConfigManager configManager = new ConfigManager(serverInterface.getConfigFolder(), defaultSpongeConfig, spongeConfigDefaults); - configManager.loadMainConfig(); - config = configManager.getMainConfig(); - - //load resources - File defaultResourceFile = config.getDataPath().resolve("minecraft-client-" + ResourcePack.MINECRAFT_CLIENT_VERSION + ".jar").toFile(); - File resourceExtensionsFile = config.getDataPath().resolve("resourceExtensions.zip").toFile(); - File textureExportFile = config.getWebDataPath().resolve("textures.json").toFile(); - - if (!defaultResourceFile.exists()) { - if (config.isDownloadAccepted()) { - - //download file - try { - Logger.global.logInfo("Downloading " + ResourcePack.MINECRAFT_CLIENT_URL + " to " + defaultResourceFile + " ..."); - ResourcePack.downloadDefaultResource(defaultResourceFile); - } catch (IOException e) { - Logger.global.logError("Failed to download resources!", e); - return; - } - - } else { - Logger.global.logWarning("BlueMap is missing important resources!"); - Logger.global.logWarning("You need to accept the download of the required files in order of BlueMap to work!"); - try { Logger.global.logWarning("Please check: " + configManager.getMainConfigFile().getCanonicalPath()); } catch (IOException ignored) {} - Logger.global.logInfo("If you have changed the config you can simply reload the plugin using: /bluemap reload"); - - return; - } - } + blueMap = new BlueMapService(serverInterface); - resourceExtensionsFile.delete(); - FileUtils.copyURLToFile(Plugin.class.getResource("/resourceExtensions.zip"), resourceExtensionsFile, 10000, 10000); + //load configs + CoreConfig coreConfig = blueMap.getCoreConfig(); + RenderConfig renderConfig = blueMap.getRenderConfig(); + WebServerConfig webServerConfig = blueMap.getWebServerConfig(); + + //load plugin config + pluginConfig = new PluginConfig(blueMap.getConfigManager().loadOrCreate( + new File(serverInterface.getConfigFolder(), "plugin.conf"), + Plugin.class.getResource("/plugin.conf"), + Plugin.class.getResource("/plugin-defaults.conf"), + true, + true + )); - //find more resource packs - File resourcePackFolder = new File(serverInterface.getConfigFolder(), "resourcepacks"); - resourcePackFolder.mkdirs(); - File[] resourcePacks = resourcePackFolder.listFiles(); - Arrays.sort(resourcePacks); //load resource packs in alphabetical order so you can reorder them by renaming - - List resources = new ArrayList<>(resourcePacks.length + 1); - resources.add(defaultResourceFile); - for (File file : resourcePacks) resources.add(file); - resources.add(resourceExtensionsFile); - - resourcePack = new ResourcePack(); - if (textureExportFile.exists()) resourcePack.loadTextureFile(textureExportFile); - resourcePack.load(resources); - resourcePack.saveTextureFile(textureExportFile); - - configManager.loadResourceConfigs(resourcePack); - - //load maps - for (MapConfig mapConfig : config.getMapConfigs()) { - String id = mapConfig.getId(); - String name = mapConfig.getName(); + //try load resources + try { + blueMap.getResourcePack(); + } catch (MissingResourcesException ex) { + Logger.global.logWarning("BlueMap is missing important resources!"); + Logger.global.logWarning("You need to accept the download of the required files in order of BlueMap to work!"); + try { Logger.global.logWarning("Please check: " + blueMap.getCoreConfigFile().getCanonicalPath()); } catch (IOException ignored) {} + Logger.global.logInfo("If you have changed the config you can simply reload the plugin using: /bluemap reload"); - File worldFolder = new File(mapConfig.getWorldPath()); - if (!worldFolder.exists() || !worldFolder.isDirectory()) { - Logger.global.logError("Failed to load map '" + id + "': '" + worldFolder.getCanonicalPath() + "' does not exist or is no directory!", new IOException()); - continue; - } - - UUID worldUUID; - try { - worldUUID = serverInterface.getUUIDForWorld(worldFolder); - } catch (IOException e) { - Logger.global.logError("Failed to load map '" + id + "': Failed to get UUID for the world!", e); - continue; - } - - World world = worlds.get(worldUUID); - if (world == null) { - try { - world = MCAWorld.load(worldFolder.toPath(), worldUUID, configManager.getBlockIdConfig(), configManager.getBlockPropertiesConfig(), configManager.getBiomeConfig(), serverInterface.getWorldName(worldUUID), true); - worlds.put(worldUUID, world); - } catch (IOException e) { - Logger.global.logError("Failed to load map '" + id + "': Failed to read level.dat", e); - continue; - } - } - - //slice world if configured - if (!mapConfig.getMin().equals(RenderSettings.DEFAULT_MIN) || !mapConfig.getMax().equals(RenderSettings.DEFAULT_MAX)) { - if (mapConfig.isRenderEdges()) { - world = new SlicedWorld(world, mapConfig.getMin(), mapConfig.getMax()); - } else { - world = new SlicedWorld( - world, - mapConfig.getMin().min(mapConfig.getMin().sub(2, 2, 2)), // protect from int-overflow - mapConfig.getMax().max(mapConfig.getMax().add(2, 2, 2)) // protect from int-overflow - ); - } - } - - HiresModelManager hiresModelManager = new HiresModelManager( - config.getWebDataPath().resolve(id).resolve("hires"), - resourcePack, - mapConfig, - new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize()) - ); - - LowresModelManager lowresModelManager = new LowresModelManager( - config.getWebDataPath().resolve(id).resolve("lowres"), - new Vector2i(mapConfig.getLowresPointsPerLowresTile(), mapConfig.getLowresPointsPerLowresTile()), - new Vector2i(mapConfig.getLowresPointsPerHiresTile(), mapConfig.getLowresPointsPerHiresTile()), - mapConfig.useGzipCompression() - ); - - TileRenderer tileRenderer = new TileRenderer(hiresModelManager, lowresModelManager); - - MapType mapType = new MapType(id, name, world, tileRenderer); - maps.put(id, mapType); - } - if (maps.isEmpty()) { - Logger.global.logWarning("There are no valid maps configured, please check your config! Disabling BlueMap..."); unload(); return; } + //load worlds and maps + worlds = blueMap.getWorlds(); + maps = blueMap.getMaps(); + + //warn if no maps are configured + if (maps.isEmpty()) { + Logger.global.logWarning("There are no valid maps configured, please check your render-config! Disabling BlueMap..."); + } + //initialize render manager - renderManager = new RenderManager(config.getRenderThreadCount()); + renderManager = new RenderManager(coreConfig.getRenderThreadCount()); renderManager.start(); //load render-manager state try { - File saveFile = config.getDataPath().resolve("rmstate").toFile(); - saveFile.getParentFile().mkdirs(); + File saveFile = getRenderManagerSaveFile(); if (saveFile.exists()) { try (DataInputStream in = new DataInputStream(new GZIPInputStream(new FileInputStream(saveFile)))) { renderManager.readState(in, getMapTypes()); @@ -272,38 +168,31 @@ public synchronized void load() throws IOException, ParseResourceException { this.updateHandler = new MapUpdateHandler(this); serverInterface.registerListener(updateHandler); + //update webapp and settings + blueMap.createOrUpdateWebApp(false); + blueMap.updateWebAppSettings(); + //start skin updater - if (config.isLiveUpdatesEnabled()) { - this.skinUpdater = new PlayerSkinUpdater(config.getWebRoot().resolve("assets").resolve("playerheads").toFile()); + if (pluginConfig.isLiveUpdatesEnabled()) { + this.skinUpdater = new PlayerSkinUpdater(new File(renderConfig.getWebRoot(), "assets" + File.separator + "playerheads")); serverInterface.registerListener(skinUpdater); } - //create/update webfiles - WebFilesManager webFilesManager = new WebFilesManager(config.getWebRoot()); - if (webFilesManager.needsUpdate()) { - webFilesManager.updateFiles(); - } - - WebSettings webSettings = new WebSettings(config.getWebDataPath().resolve("settings.json").toFile()); - webSettings.set(config.isUseCookies(), "useCookies"); - webSettings.setAllMapsEnabled(false); - for (MapType map : maps.values()) { - webSettings.setMapEnabled(true, map.getId()); - webSettings.setFrom(map.getTileRenderer(), map.getId()); - webSettings.setFrom(map.getWorld(), map.getId()); - } - int ordinal = 0; - for (MapConfig map : config.getMapConfigs()) { - if (!maps.containsKey(map.getId())) continue; //don't add not loaded maps - webSettings.setOrdinal(ordinal++, map.getId()); - webSettings.setFrom(map, map.getId()); - } - webSettings.save(); - - //start webserver - if (config.isWebserverEnabled()) { - webServer = new BlueMapWebServer(config, config, serverInterface); - webServer.updateWebfiles(); + //create and start webserver + if (webServerConfig.isWebserverEnabled()) { + HttpRequestHandler requestHandler = new FileRequestHandler(webServerConfig.getWebRoot().toPath(), "BlueMap v" + BlueMap.VERSION); + + //inject live api if enabled + if (pluginConfig.isLiveUpdatesEnabled()) { + requestHandler = new LiveAPIRequestHandler(serverInterface, pluginConfig, requestHandler); + } + + webServer = new WebServer( + webServerConfig.getWebserverPort(), + webServerConfig.getWebserverMaxConnections(), + webServerConfig.getWebserverBindAdress(), + requestHandler + ); webServer.start(); } @@ -313,7 +202,8 @@ public synchronized void load() throws IOException, ParseResourceException { Thread.sleep(TimeUnit.MINUTES.toMillis(1)); while (true) { - if (serverInterface.isMetricsEnabled(config.isMetricsEnabled())) Metrics.sendReport(this.implementationType); + if (serverInterface.isMetricsEnabled(coreConfig.isMetricsEnabled())) Metrics.sendReport(this.implementationType); + Thread.sleep(TimeUnit.MINUTES.toMillis(30)); } } catch (InterruptedException ex){ @@ -369,25 +259,27 @@ public synchronized void unload() { } //save renders - for (MapType map : maps.values()) { - map.getTileRenderer().save(); + if (maps != null) { + for (MapType map : maps.values()) { + map.getTileRenderer().save(); + } } //clear resources and configs + blueMap = null; + worlds = null; + maps = null; renderManager = null; webServer = null; updateHandler = null; - resourcePack = null; - config = null; - maps.clear(); - worlds.clear(); + pluginConfig = null; loaded = false; } public void saveRenderManagerState() throws IOException { - File saveFile = config.getDataPath().resolve("rmstate").toFile(); - saveFile.getParentFile().mkdirs(); + File saveFile = getRenderManagerSaveFile(); + if (saveFile.exists()) saveFile.delete(); saveFile.createNewFile(); @@ -405,12 +297,24 @@ public ServerInterface getServerInterface() { return serverInterface; } - public MainConfig getMainConfig() { - return config; + public CoreConfig getCoreConfig() throws IOException { + return blueMap.getCoreConfig(); } - public ResourcePack getResourcePack() { - return resourcePack; + public RenderConfig getRenderConfig() throws IOException { + return blueMap.getRenderConfig(); + } + + public WebServerConfig getWebServerConfig() throws IOException { + return blueMap.getWebServerConfig(); + } + + public PluginConfig getPluginConfig() { + return pluginConfig; + } + + public ResourcePack getResourcePack() throws IOException { + return blueMap.getResourcePack(); } public World getWorld(UUID uuid){ @@ -429,11 +333,20 @@ public RenderManager getRenderManager() { return renderManager; } + public File getRenderManagerSaveFile() throws IOException { + if (blueMap == null) return null; + + File saveFile = new File(blueMap.getCoreConfig().getDataFolder(), "rmstate"); + saveFile.getParentFile().mkdirs(); + + return saveFile; + } + public MapUpdateHandler getUpdateHandler() { return updateHandler; } - public BlueMapWebServer getWebServer() { + public WebServer getWebServer() { return webServer; } diff --git a/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/PluginConfig.java b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/PluginConfig.java new file mode 100644 index 00000000..64f049b5 --- /dev/null +++ b/BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/PluginConfig.java @@ -0,0 +1,84 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.common.plugin; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import ninja.leaping.configurate.ConfigurationNode; + +public class PluginConfig { + + private boolean liveUpdatesEnabled = false; + private boolean skinDownloadEnabled = false; + private Collection hiddenGameModes = Collections.emptyList(); + private boolean hideInvisible = false; + private boolean hideSneaking = false; + + public PluginConfig(ConfigurationNode node) { + + //liveUpdates + liveUpdatesEnabled = node.getNode("liveUpdates").getBoolean(true); + + //skinDownloadEnabled + skinDownloadEnabled = node.getNode("skinDownload").getBoolean(true); + + //hiddenGameModes + hiddenGameModes = new ArrayList<>(); + for (ConfigurationNode gameModeNode : node.getNode("hiddenGameModes").getChildrenList()) { + hiddenGameModes.add(gameModeNode.getString()); + } + hiddenGameModes = Collections.unmodifiableCollection(hiddenGameModes); + + //hideInvisible + hideInvisible = node.getNode("hideInvisible").getBoolean(true); + + //hideSneaking + hideSneaking = node.getNode("hideSneaking").getBoolean(false); + + } + + public boolean isLiveUpdatesEnabled() { + return this.liveUpdatesEnabled; + } + + public boolean isSkinDownloadEnabled() { + return this.skinDownloadEnabled; + } + + public Collection getHiddenGameModes() { + return this.hiddenGameModes; + } + + public boolean isHideInvisible() { + return this.hideInvisible; + } + + public boolean isHideSneaking() { + return this.hideSneaking; + } + +} diff --git a/BlueMapCore/build.gradle b/BlueMapCore/build.gradle index 582b6741..3973af26 100644 --- a/BlueMapCore/build.gradle +++ b/BlueMapCore/build.gradle @@ -19,7 +19,7 @@ dependencies { processResources { from(sourceSets.main.resources.srcDirs) { - include 'core.json' + include 'de/bluecolored/bluemap/version.json' expand ( version: project.version @@ -54,7 +54,7 @@ task webpackWebroot(type: NpmTask) { task zipWebroot(type: Zip) { from fileTree('build/generated/webroot/') archiveName 'webroot.zip' - destinationDir(file('src/main/resources/')) + destinationDir(file('src/main/resources/de/bluecolored/bluemap/')) outputs.upToDateWhen { false } } @@ -70,7 +70,7 @@ task buildWebroot { task zipResourceExtensions(type: Zip) { from fileTree('src/main/resourceExtensions') archiveName 'resourceExtensions.zip' - destinationDir(file('src/main/resources/')) + destinationDir(file('src/main/resources/de/bluecolored/bluemap/')) outputs.upToDateWhen { false } } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/BlueMap.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/BlueMap.java index 4a601816..6f4870b3 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/BlueMap.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/BlueMap.java @@ -35,9 +35,9 @@ public class BlueMap { static { String version = "DEV"; try { - version = GsonConfigurationLoader.builder().setURL(BlueMap.class.getResource("/core.json")).build().load().getNode("version").getString("DEV"); + version = GsonConfigurationLoader.builder().setURL(BlueMap.class.getResource("/de/bluecolored/bluemap/version.json")).build().load().getNode("version").getString("DEV"); } catch (IOException ex) { - Logger.global.logError("Failed to load core.json from resources!", ex); + Logger.global.logError("Failed to load version.json from resources!", ex); } if (version.equals("${version}")) version = "DEV"; diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/ConfigManager.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/ConfigManager.java index 89f00861..8fbc0341 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/ConfigManager.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/ConfigManager.java @@ -37,6 +37,8 @@ import java.util.Set; import java.util.stream.Collectors; +import com.google.common.base.Preconditions; + import de.bluecolored.bluemap.core.BlueMap; import de.bluecolored.bluemap.core.logger.Logger; import de.bluecolored.bluemap.core.resourcepack.ResourcePack; @@ -58,157 +60,22 @@ public class ConfigManager { CONFIG_PLACEHOLDERS.add(new Placeholder("minecraft-client-version", ResourcePack.MINECRAFT_CLIENT_VERSION)); } - private File configFolder; - - private URL defaultMainConfig; - private URL mainConfigDefaultValues; - - private MainConfig mainConfig; private BlockIdConfig blockIdConfig; private BlockPropertiesConfig blockPropertiesConfig; private BiomeConfig biomeConfig; /** - * Manages all configurations BlueMap needs to render stuff. + * Loads or creates a config file for BlueMap. * - * @param configFolder The folder containing all configuration-files - * @param defaultMainConfig The default main-configuration file, used if a new configuration is generated - * @param mainConfigDefaultValues The default values that are used for the main-configuration file (if they are undefined) + * @param configFile The config file to load + * @param defaultConfig The default config that is used as a template if the config file does not exist (can be null) + * @param defaultValues The default values used if a key is not present in the config (can be null) + * @param usePlaceholders Whether to replace placeholders from the defaultConfig if it is newly generated + * @param generateEmptyConfig Whether to generate an empty config file if no default config is provided + * @return + * @throws IOException */ - public ConfigManager(File configFolder, URL defaultMainConfig, URL mainConfigDefaultValues) { - this.defaultMainConfig = defaultMainConfig; - this.configFolder = configFolder; - } - - public MainConfig getMainConfig() { - return mainConfig; - } - - public File getMainConfigFile() { - return new File(configFolder, "bluemap.conf"); - } - - public BlockIdConfig getBlockIdConfig() { - return blockIdConfig; - } - - public File getBlockIdConfigFile() { - return new File(configFolder, "blockIds.json"); - } - - public BlockPropertiesConfig getBlockPropertiesConfig() { - return blockPropertiesConfig; - } - - public File getBlockPropertiesConfigFile() { - return new File(configFolder, "blockProperties.json"); - } - - public BiomeConfig getBiomeConfig() { - return biomeConfig; - } - - public File getBiomeConfigFile() { - return new File(configFolder, "biomes.json"); - } - - public File getBlockColorConfigFile() { - return new File(configFolder, "blockColors.json"); - } - - public void loadMainConfig() throws IOException { - mainConfig = new MainConfig( - loadOrCreate( - getMainConfigFile(), - defaultMainConfig, - mainConfigDefaultValues, - true, - true - ) - ); - } - - public void loadResourceConfigs(ResourcePack resourcePack) throws IOException { - - //load blockColors.json from resources, config-folder and resourcepack - URL blockColorsConfigUrl = BlueMap.class.getResource("/blockColors.json"); - ConfigurationNode blockColorsConfigNode = loadOrCreate( - getBlockColorConfigFile(), - null, - blockColorsConfigUrl, - false, - false - ); - blockColorsConfigNode = joinFromResourcePack(resourcePack, "blockColors.json", blockColorsConfigNode); - resourcePack.getBlockColorCalculator().loadColorConfig(blockColorsConfigNode); - - //load blockIds.json from resources, config-folder and resourcepack - URL blockIdsConfigUrl = BlueMap.class.getResource("/blockIds.json"); - ConfigurationNode blockIdsConfigNode = loadOrCreate( - getBlockIdConfigFile(), - null, - blockIdsConfigUrl, - false, - false - ); - blockIdsConfigNode = joinFromResourcePack(resourcePack, "blockIds.json", blockIdsConfigNode); - blockIdConfig = new BlockIdConfig( - blockIdsConfigNode, - getLoader(makeAutogen(getBlockIdConfigFile())) - ); - - //load blockProperties.json from resources, config-folder and resourcepack - URL blockPropertiesConfigUrl = BlueMap.class.getResource("/blockProperties.json"); - ConfigurationNode blockPropertiesConfigNode = loadOrCreate( - getBlockPropertiesConfigFile(), - null, - blockPropertiesConfigUrl, - false, - false - ); - blockPropertiesConfigNode = joinFromResourcePack(resourcePack, "blockProperties.json", blockPropertiesConfigNode); - blockPropertiesConfig = new BlockPropertiesConfig( - blockPropertiesConfigNode, - resourcePack, - getLoader(makeAutogen(getBlockPropertiesConfigFile())) - ); - - //load biomes.json from resources, config-folder and resourcepack - URL biomeConfigUrl = BlueMap.class.getResource("/biomes.json"); - ConfigurationNode biomeConfigNode = loadOrCreate( - getBiomeConfigFile(), - null, - biomeConfigUrl, - false, - false - ); - biomeConfigNode = joinFromResourcePack(resourcePack, "biomes.json", biomeConfigNode); - biomeConfig = new BiomeConfig( - biomeConfigNode, - getLoader(makeAutogen(getBiomeConfigFile())) - ); - } - - private ConfigurationNode joinFromResourcePack(ResourcePack resourcePack, String configFileName, ConfigurationNode defaultConfig) { - ConfigurationNode joinedNode = null; - for (Resource resource : resourcePack.getConfigAdditions(configFileName)) { - try { - ConfigurationNode node = getLoader(configFileName, resource.read()).load(); - if (joinedNode == null) joinedNode = node; - else joinedNode.mergeValuesFrom(node); - } catch (IOException ex) { - Logger.global.logWarning("Failed to load an additional " + configFileName + " from the resource-pack! " + ex); - } - } - - if (joinedNode == null) return defaultConfig; - - joinedNode.mergeValuesFrom(defaultConfig); - - return joinedNode; - } - - private ConfigurationNode loadOrCreate(File configFile, URL defaultConfig, URL defaultValues, boolean usePlaceholders, boolean generateEmptyConfig) throws IOException { + public ConfigurationNode loadOrCreate(File configFile, URL defaultConfig, URL defaultValues, boolean usePlaceholders, boolean generateEmptyConfig) throws IOException { ConfigurationNode configNode; if (!configFile.exists()) { @@ -255,6 +122,103 @@ private ConfigurationNode loadOrCreate(File configFile, URL defaultConfig, URL d return configNode; } + public void loadResourceConfigs(File configFolder, ResourcePack resourcePack) throws IOException { + + //load blockColors.json from resources, config-folder and resourcepack + URL blockColorsConfigUrl = BlueMap.class.getResource("/de/bluecolored/bluemap/blockColors.json"); + File blockColorsConfigFile = new File(configFolder, "blockColors.json"); + ConfigurationNode blockColorsConfigNode = loadOrCreate( + blockColorsConfigFile, + null, + blockColorsConfigUrl, + false, + false + ); + blockColorsConfigNode = joinFromResourcePack(resourcePack, "blockColors.json", blockColorsConfigNode); + resourcePack.getBlockColorCalculator().loadColorConfig(blockColorsConfigNode); + + //load blockIds.json from resources, config-folder and resourcepack + URL blockIdsConfigUrl = BlueMap.class.getResource("/de/bluecolored/bluemap/blockIds.json"); + File blockIdsConfigFile = new File(configFolder, "blockIds.json"); + ConfigurationNode blockIdsConfigNode = loadOrCreate( + blockIdsConfigFile, + null, + blockIdsConfigUrl, + false, + false + ); + blockIdsConfigNode = joinFromResourcePack(resourcePack, "blockIds.json", blockIdsConfigNode); + blockIdConfig = new BlockIdConfig( + blockIdsConfigNode, + getLoader(makeAutogen(blockIdsConfigFile)) + ); + + //load blockProperties.json from resources, config-folder and resourcepack + URL blockPropertiesConfigUrl = BlueMap.class.getResource("/de/bluecolored/bluemap/blockProperties.json"); + File blockPropertiesConfigFile = new File(configFolder, "blockProperties.json"); + ConfigurationNode blockPropertiesConfigNode = loadOrCreate( + blockPropertiesConfigFile, + null, + blockPropertiesConfigUrl, + false, + false + ); + blockPropertiesConfigNode = joinFromResourcePack(resourcePack, "blockProperties.json", blockPropertiesConfigNode); + blockPropertiesConfig = new BlockPropertiesConfig( + blockPropertiesConfigNode, + resourcePack, + getLoader(makeAutogen(blockPropertiesConfigFile)) + ); + + //load biomes.json from resources, config-folder and resourcepack + URL biomeConfigUrl = BlueMap.class.getResource("/de/bluecolored/bluemap/biomes.json"); + File biomeConfigFile = new File(configFolder, "biomes.json"); + ConfigurationNode biomeConfigNode = loadOrCreate( + biomeConfigFile, + null, + biomeConfigUrl, + false, + false + ); + biomeConfigNode = joinFromResourcePack(resourcePack, "biomes.json", biomeConfigNode); + biomeConfig = new BiomeConfig( + biomeConfigNode, + getLoader(makeAutogen(biomeConfigFile)) + ); + + } + + public BlockIdConfig getBlockIdConfig() { + return blockIdConfig; + } + + public BlockPropertiesConfig getBlockPropertiesConfig() { + return blockPropertiesConfig; + } + + public BiomeConfig getBiomeConfig() { + return biomeConfig; + } + + private ConfigurationNode joinFromResourcePack(ResourcePack resourcePack, String configFileName, ConfigurationNode defaultConfig) { + ConfigurationNode joinedNode = null; + for (Resource resource : resourcePack.getConfigAdditions(configFileName)) { + try { + ConfigurationNode node = getLoader(configFileName, resource.read()).load(); + if (joinedNode == null) joinedNode = node; + else joinedNode.mergeValuesFrom(node); + } catch (IOException ex) { + Logger.global.logWarning("Failed to load an additional " + configFileName + " from the resource-pack! " + ex); + } + } + + if (joinedNode == null) return defaultConfig; + + joinedNode.mergeValuesFrom(defaultConfig); + + return joinedNode; + } + private File makeAutogen(File file) throws IOException { File autogenFile = file.getCanonicalFile().toPath().getParent().resolve("missing-configs").resolve(file.getName()).toFile(); autogenFile.getParentFile().mkdirs(); @@ -280,5 +244,13 @@ private ConfigurationLoader getLoader(File file){ if (file.getName().endsWith(".yaml") || file.getName().endsWith(".yml")) return YAMLConfigurationLoader.builder().setFile(file).build(); else return HoconConfigurationLoader.builder().setFile(file).build(); } + + public static File toFolder(String pathString) throws IOException { + Preconditions.checkNotNull(pathString); + + File file = new File(pathString); + if (file.exists() && !file.isDirectory()) throw new IOException("Invalid configuration: Path '" + file.getAbsolutePath() + "' is a file (should be a directory)"); + return file; + } } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/CoreConfig.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/CoreConfig.java new file mode 100644 index 00000000..66d09ae0 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/CoreConfig.java @@ -0,0 +1,76 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.core.config; + +import java.io.File; +import java.io.IOException; + +import ninja.leaping.configurate.ConfigurationNode; + +public class CoreConfig { + + private boolean downloadAccepted = false; + private int renderThreadCount = 0; + private boolean metricsEnabled = false; + private File dataFolder = new File("data"); + + + public CoreConfig(ConfigurationNode node) throws IOException { + + //accept-download + downloadAccepted = node.getNode("accept-download").getBoolean(false); + + //renderThreadCount + int processors = Runtime.getRuntime().availableProcessors(); + renderThreadCount = node.getNode("renderThreadCount").getInt(0); + if (renderThreadCount <= 0) renderThreadCount = processors + renderThreadCount; + if (renderThreadCount <= 0) renderThreadCount = 1; + + //metrics + metricsEnabled = node.getNode("metrics").getBoolean(false); + + //data + dataFolder = ConfigManager.toFolder(node.getNode("data").getString("data")); + + } + + public File getDataFolder() { + if (!dataFolder.exists()) dataFolder.mkdirs(); + return dataFolder; + } + + public boolean isDownloadAccepted() { + return downloadAccepted; + } + + public boolean isMetricsEnabled() { + return metricsEnabled; + } + + public int getRenderThreadCount() { + return renderThreadCount; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/MainConfig.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/MainConfig.java deleted file mode 100644 index c7da1a5d..00000000 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/MainConfig.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * This file is part of BlueMap, licensed under the MIT License (MIT). - * - * Copyright (c) Blue (Lukas Rieger) - * Copyright (c) contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package de.bluecolored.bluemap.core.config; - -import java.io.File; -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.regex.Pattern; - -import com.flowpowered.math.vector.Vector2i; -import com.flowpowered.math.vector.Vector3i; -import com.google.common.base.Preconditions; - -import de.bluecolored.bluemap.core.render.RenderSettings; -import de.bluecolored.bluemap.core.util.ConfigUtils; -import de.bluecolored.bluemap.core.web.WebServerConfig; -import ninja.leaping.configurate.ConfigurationNode; - -public class MainConfig implements WebServerConfig, LiveAPISettings { - private static final Pattern VALID_ID_PATTERN = Pattern.compile("[a-zA-Z0-9_]+"); - - private boolean downloadAccepted = false; - private boolean metricsEnabled = false; - - private boolean webserverEnabled = true; - private int webserverPort = 8100; - private int webserverMaxConnections = 100; - private InetAddress webserverBindAdress = null; - private boolean useCookies; - - private Path dataPath = Paths.get("data"); - - private Path webRoot = Paths.get("web"); - private Path webDataPath = webRoot.resolve("data"); - - private int renderThreadCount = 0; - - private List mapConfigs = new ArrayList<>(); - - private boolean liveUpdatesEnabled = false; - private Collection hiddenGameModes = Collections.emptyList(); - private boolean hideInvisible = false; - private boolean hideSneaking = false; - - public MainConfig(ConfigurationNode node) throws OutdatedConfigException, IOException { - checkOutdated(node); - - //acceppt-download - downloadAccepted = node.getNode("accept-download").getBoolean(false); - - //renderThreadCount - int processors = Runtime.getRuntime().availableProcessors(); - renderThreadCount = node.getNode("renderThreadCount").getInt(0); - if (renderThreadCount <= 0) renderThreadCount = processors + renderThreadCount; - if (renderThreadCount <= 0) renderThreadCount = 1; - - //metrics - metricsEnabled = node.getNode("metrics").getBoolean(false); - - //data - dataPath = toFolder(node.getNode("data").getString("data")); - - //webroot - String webRootString = node.getNode("webroot").getString(); - if (webserverEnabled && webRootString == null) throw new IOException("Invalid configuration: Node webroot is not defined"); - webRoot = toFolder(webRootString); - - //webdata - String webDataString = node.getNode("webdata").getString(); - if (webDataString != null) - webDataPath = toFolder(webDataString); - else - webDataPath = webRoot.resolve("data"); - - useCookies = node.getNode("useCookies").getBoolean(true); - - //webserver - loadWebConfig(node.getNode("webserver")); - - //maps - loadMapConfigs(node.getNode("maps")); - - //live-updates - ConfigurationNode liveNode = node.getNode("liveUpdates"); - liveUpdatesEnabled = liveNode.getNode("enabled").getBoolean(true); - - hiddenGameModes = new ArrayList<>(); - for (ConfigurationNode gameModeNode : liveNode.getNode("hiddenGameModes").getChildrenList()) { - hiddenGameModes.add(gameModeNode.getString()); - } - hiddenGameModes = Collections.unmodifiableCollection(hiddenGameModes); - - hideInvisible = liveNode.getNode("hideInvisible").getBoolean(true); - hideSneaking = liveNode.getNode("hideSneaking").getBoolean(false); - } - - private void loadWebConfig(ConfigurationNode node) throws IOException { - //enabled - webserverEnabled = node.getNode("enabled").getBoolean(false); - - if (webserverEnabled) { - //ip - String webserverBindAdressString = node.getNode("ip").getString(""); - if (webserverBindAdressString.isEmpty() || webserverBindAdressString.equals("0.0.0.0") || webserverBindAdressString.equals("::0")) { - webserverBindAdress = new InetSocketAddress(0).getAddress(); // 0.0.0.0 - } else if (webserverBindAdressString.equals("#getLocalHost")) { - webserverBindAdress = InetAddress.getLocalHost(); - } else { - webserverBindAdress = InetAddress.getByName(webserverBindAdressString); - } - - //port - webserverPort = node.getNode("port").getInt(8100); - - //maxConnectionCount - webserverMaxConnections = node.getNode("maxConnectionCount").getInt(100); - } - - } - - private void loadMapConfigs(ConfigurationNode node) throws IOException { - mapConfigs = new ArrayList<>(); - for (ConfigurationNode mapConfigNode : node.getChildrenList()) { - mapConfigs.add(new MapConfig(mapConfigNode)); - } - } - - private Path toFolder(String pathString) throws IOException { - Preconditions.checkNotNull(pathString); - - File file = new File(pathString); - if (file.exists() && !file.isDirectory()) throw new IOException("Invalid configuration: Path '" + file.getAbsolutePath() + "' is a file (should be a directory)"); - if (!file.exists() && !file.mkdirs()) throw new IOException("Invalid configuration: Folders to path '" + file.getAbsolutePath() + "' could not be created"); - return file.toPath(); - } - - @Override - public Path getWebRoot() { - return webRoot; - } - - public Path getDataPath() { - return dataPath; - } - - public boolean isUseCookies() { - return useCookies; - } - - public boolean isWebserverEnabled() { - return webserverEnabled; - } - - - public Path getWebDataPath() { - return webDataPath; - } - - @Override - public int getWebserverPort() { - return webserverPort; - } - - @Override - public int getWebserverMaxConnections() { - return webserverMaxConnections; - } - - @Override - public InetAddress getWebserverBindAdress() { - return webserverBindAdress; - } - - public boolean isDownloadAccepted() { - return downloadAccepted; - } - - public boolean isMetricsEnabled() { - return metricsEnabled; - } - - public int getRenderThreadCount() { - return renderThreadCount; - } - - public List getMapConfigs(){ - return mapConfigs; - } - - @Override - public boolean isLiveUpdatesEnabled() { - return this.liveUpdatesEnabled; - } - - @Override - public Collection getHiddenGameModes() { - return this.hiddenGameModes; - } - - @Override - public boolean isHideInvisible() { - return this.hideInvisible; - } - - @Override - public boolean isHideSneaking() { - return this.hideSneaking; - } - - public class MapConfig implements RenderSettings { - - private String id; - private String name; - private String world; - - private Vector2i startPos; - private int skyColor; - private float ambientLight; - - private boolean renderCaves; - - private Vector3i min, max; - private boolean renderEdges; - - private boolean useGzip; - private boolean ignoreMissingLightData; - - private int hiresTileSize; - - private int lowresPointsPerHiresTile; - private int lowresPointsPerLowresTile; - - private MapConfig(ConfigurationNode node) throws IOException { - this.id = node.getNode("id").getString(""); - if (id.isEmpty()) throw new IOException("Invalid configuration: Node maps[?].id is not defined"); - if (!VALID_ID_PATTERN.matcher(id).matches()) throw new IOException("Invalid configuration: Node maps[?].id '" + id + "' has invalid characters in it"); - - this.name = node.getNode("name").getString(id); - - this.world = node.getNode("world").getString(""); - if (world.isEmpty()) throw new IOException("Invalid configuration: Node maps[?].world is not defined"); - - if (!node.getNode("startPos").isVirtual()) this.startPos = ConfigUtils.readVector2i(node.getNode("startPos")); - - if (!node.getNode("skyColor").isVirtual()) this.skyColor = ConfigUtils.readColorInt(node.getNode("skyColor")); - else this.skyColor = 0x7dabff; - - this.ambientLight = node.getNode("ambientLight").getFloat(0f); - - this.renderCaves = node.getNode("renderCaves").getBoolean(false); - - int minX = node.getNode("minX").getInt(RenderSettings.super.getMin().getX()); - int maxX = node.getNode("maxX").getInt(RenderSettings.super.getMax().getX()); - int minZ = node.getNode("minZ").getInt(RenderSettings.super.getMin().getZ()); - int maxZ = node.getNode("maxZ").getInt(RenderSettings.super.getMax().getZ()); - int minY = node.getNode("minY").getInt(RenderSettings.super.getMin().getY()); - int maxY = node.getNode("maxY").getInt(RenderSettings.super.getMax().getY()); - this.min = new Vector3i(minX, minY, minZ); - this.max = new Vector3i(maxX, maxY, maxZ); - - this.renderEdges = node.getNode("renderEdges").getBoolean(true); - - this.useGzip = node.getNode("useCompression").getBoolean(true); - this.ignoreMissingLightData = node.getNode("ignoreMissingLightData").getBoolean(false); - - this.hiresTileSize = node.getNode("hires", "tileSize").getInt(32); - - this.lowresPointsPerHiresTile = node.getNode("lowres", "pointsPerHiresTile").getInt(4); - this.lowresPointsPerLowresTile = node.getNode("lowres", "pointsPerLowresTile").getInt(50); - - //check valid configuration values - double blocksPerPoint = (double) this.hiresTileSize / (double) this.lowresPointsPerHiresTile; - if (blocksPerPoint != Math.floor(blocksPerPoint)) throw new IOException("Invalid configuration: Invalid map resolution settings of map " + id + ": hires.tileSize / lowres.pointsPerTile has to be an integer result"); - } - - public String getId() { - return id; - } - - public String getName() { - return name; - } - - public String getWorldPath() { - return world; - } - - public Vector2i getStartPos() { - return startPos; - } - - public int getSkyColor() { - return skyColor; - } - - public float getAmbientLight() { - return ambientLight; - } - - public boolean isRenderCaves() { - return renderCaves; - } - - public int getHiresTileSize() { - return hiresTileSize; - } - - public int getLowresPointsPerHiresTile() { - return lowresPointsPerHiresTile; - } - - public int getLowresPointsPerLowresTile() { - return lowresPointsPerLowresTile; - } - - @Override - public boolean isExcludeFacesWithoutSunlight() { - return !isRenderCaves(); - } - - @Override - public Vector3i getMin() { - return min; - } - - @Override - public Vector3i getMax() { - return max; - } - - @Override - public boolean isRenderEdges() { - return renderEdges; - } - - @Override - public boolean useGzipCompression() { - return useGzip; - } - - public boolean isIgnoreMissingLightData() { - return ignoreMissingLightData; - } - - } - - private void checkOutdated(ConfigurationNode node) throws OutdatedConfigException { - // check for config-nodes from version 0.1.x - assertNotPresent(node.getNode("version")); - assertNotPresent(node.getNode("web")); - for (ConfigurationNode map : node.getNode("maps").getChildrenList()) { - assertNotPresent(map.getNode("sliceY")); - } - } - - private void assertNotPresent(ConfigurationNode node) throws OutdatedConfigException { - if (!node.isVirtual()) throw new OutdatedConfigException("Configurtion-node '" + ConfigUtils.nodePathToString(node) + "' is no longer used, please update your configuration!"); - } - -} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/MapConfig.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/MapConfig.java new file mode 100644 index 00000000..f1f20be1 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/MapConfig.java @@ -0,0 +1,187 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.core.config; + +import java.io.IOException; +import java.util.regex.Pattern; + +import com.flowpowered.math.vector.Vector2i; +import com.flowpowered.math.vector.Vector3i; + +import de.bluecolored.bluemap.core.render.RenderSettings; +import de.bluecolored.bluemap.core.util.ConfigUtils; +import ninja.leaping.configurate.ConfigurationNode; + +public class MapConfig implements RenderSettings { + private static final Pattern VALID_ID_PATTERN = Pattern.compile("[a-zA-Z0-9_]+"); + + private String id; + private String name; + private String world; + + private Vector2i startPos; + private int skyColor; + private float ambientLight; + + private boolean renderCaves; + + private Vector3i min, max; + private boolean renderEdges; + + private boolean useGzip; + private boolean ignoreMissingLightData; + + private int hiresTileSize; + + private int lowresPointsPerHiresTile; + private int lowresPointsPerLowresTile; + + public MapConfig(ConfigurationNode node) throws IOException { + + //id + this.id = node.getNode("id").getString(""); + if (id.isEmpty()) throw new IOException("Invalid configuration: Node maps[?].id is not defined"); + if (!VALID_ID_PATTERN.matcher(id).matches()) throw new IOException("Invalid configuration: Node maps[?].id '" + id + "' has invalid characters in it"); + + //name + this.name = node.getNode("name").getString(id); + + //world + this.world = node.getNode("world").getString(""); + if (world.isEmpty()) throw new IOException("Invalid configuration: Node maps[?].world is not defined"); + + //startPos + if (!node.getNode("startPos").isVirtual()) this.startPos = ConfigUtils.readVector2i(node.getNode("startPos")); + + //skyColor + if (!node.getNode("skyColor").isVirtual()) this.skyColor = ConfigUtils.readColorInt(node.getNode("skyColor")); + else this.skyColor = 0x7dabff; + + //ambientLight + this.ambientLight = node.getNode("ambientLight").getFloat(0f); + + //renderCaves + this.renderCaves = node.getNode("renderCaves").getBoolean(false); + + //bounds + int minX = node.getNode("minX").getInt(RenderSettings.super.getMin().getX()); + int maxX = node.getNode("maxX").getInt(RenderSettings.super.getMax().getX()); + int minZ = node.getNode("minZ").getInt(RenderSettings.super.getMin().getZ()); + int maxZ = node.getNode("maxZ").getInt(RenderSettings.super.getMax().getZ()); + int minY = node.getNode("minY").getInt(RenderSettings.super.getMin().getY()); + int maxY = node.getNode("maxY").getInt(RenderSettings.super.getMax().getY()); + this.min = new Vector3i(minX, minY, minZ); + this.max = new Vector3i(maxX, maxY, maxZ); + + //renderEdges + this.renderEdges = node.getNode("renderEdges").getBoolean(true); + + //useCompression + this.useGzip = node.getNode("useCompression").getBoolean(true); + + //ignoreMissingLightData + this.ignoreMissingLightData = node.getNode("ignoreMissingLightData").getBoolean(false); + + //tile-settings + this.hiresTileSize = node.getNode("hires", "tileSize").getInt(32); + this.lowresPointsPerHiresTile = node.getNode("lowres", "pointsPerHiresTile").getInt(4); + this.lowresPointsPerLowresTile = node.getNode("lowres", "pointsPerLowresTile").getInt(50); + + //check valid tile configuration values + double blocksPerPoint = (double) this.hiresTileSize / (double) this.lowresPointsPerHiresTile; + if (blocksPerPoint != Math.floor(blocksPerPoint)) throw new IOException("Invalid configuration: Invalid map resolution settings of map " + id + ": hires.tileSize / lowres.pointsPerTile has to be an integer result"); + + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getWorldPath() { + return world; + } + + public Vector2i getStartPos() { + return startPos; + } + + public int getSkyColor() { + return skyColor; + } + + public float getAmbientLight() { + return ambientLight; + } + + public boolean isRenderCaves() { + return renderCaves; + } + + public boolean isIgnoreMissingLightData() { + return ignoreMissingLightData; + } + + public int getHiresTileSize() { + return hiresTileSize; + } + + public int getLowresPointsPerHiresTile() { + return lowresPointsPerHiresTile; + } + + public int getLowresPointsPerLowresTile() { + return lowresPointsPerLowresTile; + } + + @Override + public boolean isExcludeFacesWithoutSunlight() { + return !isRenderCaves(); + } + + @Override + public Vector3i getMin() { + return min; + } + + @Override + public Vector3i getMax() { + return max; + } + + @Override + public boolean isRenderEdges() { + return renderEdges; + } + + @Override + public boolean useGzipCompression() { + return useGzip; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/OutdatedConfigException.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/RenderConfig.java similarity index 55% rename from BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/OutdatedConfigException.java rename to BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/RenderConfig.java index 6d0abc15..56c80ce0 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/OutdatedConfigException.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/RenderConfig.java @@ -24,19 +24,49 @@ */ package de.bluecolored.bluemap.core.config; +import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; -public class OutdatedConfigException extends IOException { - private static final long serialVersionUID = -942567050110586060L; +import ninja.leaping.configurate.ConfigurationNode; - public OutdatedConfigException() {} - - public OutdatedConfigException(String message) { - super(message); +public class RenderConfig { + + private File webRoot = new File("web"); + private boolean useCookies; + private List mapConfigs = new ArrayList<>(); + + public RenderConfig(ConfigurationNode node) throws IOException { + + //webroot + String webRootString = node.getNode("webroot").getString(); + if (webRootString == null) throw new IOException("Invalid configuration: Node webroot is not defined"); + webRoot = ConfigManager.toFolder(webRootString); + + //cookies + useCookies = node.getNode("useCookies").getBoolean(true); + + //maps + mapConfigs = new ArrayList<>(); + for (ConfigurationNode mapConfigNode : node.getNode("maps").getChildrenList()) { + mapConfigs.add(new MapConfig(mapConfigNode)); + } + + } + + public File getWebRoot() { + if (!webRoot.exists()) webRoot.mkdirs(); + return webRoot; } - public OutdatedConfigException(String message, Throwable cause) { - super(message, cause); + public boolean isUseCookies() { + return useCookies; } + public List getMapConfigs(){ + return mapConfigs; + } + + } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/WebServerConfig.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/WebServerConfig.java new file mode 100644 index 00000000..58223d61 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/WebServerConfig.java @@ -0,0 +1,94 @@ +/* + * This file is part of BlueMap, licensed under the MIT License (MIT). + * + * Copyright (c) Blue (Lukas Rieger) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package de.bluecolored.bluemap.core.config; + +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; + +import ninja.leaping.configurate.ConfigurationNode; + +public class WebServerConfig { + + private boolean enabled = true; + private File webRoot = new File("web"); + + private InetAddress bindAdress = null; + private int port = 8100; + private int maxConnections = 100; + + public WebServerConfig(ConfigurationNode node) throws IOException { + + //enabled + enabled = node.getNode("enabled").getBoolean(false); + + if (enabled) { + //webroot + String webRootString = node.getNode("webroot").getString(); + if (webRootString == null) throw new IOException("Invalid configuration: Node webroot is not defined"); + webRoot = ConfigManager.toFolder(webRootString); + + //ip + String bindAdressString = node.getNode("ip").getString(""); + if (bindAdressString.isEmpty() || bindAdressString.equals("0.0.0.0") || bindAdressString.equals("::0")) { + bindAdress = new InetSocketAddress(0).getAddress(); // 0.0.0.0 + } else if (bindAdressString.equals("#getLocalHost")) { + bindAdress = InetAddress.getLocalHost(); + } else { + bindAdress = InetAddress.getByName(bindAdressString); + } + + //port + port = node.getNode("port").getInt(8100); + + //maxConnectionCount + maxConnections = node.getNode("maxConnectionCount").getInt(100); + } + + } + + public boolean isWebserverEnabled() { + return enabled; + } + + public File getWebRoot() { + if (!webRoot.exists()) webRoot.mkdirs(); + return webRoot; + } + + public InetAddress getWebserverBindAdress() { + return bindAdress; + } + + public int getWebserverPort() { + return port; + } + + public int getWebserverMaxConnections() { + return maxConnections; + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/FileRequestHandler.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/FileRequestHandler.java index ca77973d..cd2f9a81 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/FileRequestHandler.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/FileRequestHandler.java @@ -84,6 +84,10 @@ public HttpResponse handle(HttpRequest request) { private HttpResponse generateResponse(HttpRequest request) { String path = request.getPath(); + //normalize path + if (path.startsWith("/")) path = path.substring(1); + if (path.endsWith("/")) path = path.substring(0, path.length() - 1); + Path filePath = webRoot; try { filePath = webRoot.resolve(path); @@ -102,6 +106,13 @@ private HttpResponse generateResponse(HttpRequest request) { File file = filePath.toFile(); + // redirect to have correct relative paths + if (file.isDirectory() && !request.getPath().endsWith("/")) { + HttpResponse response = new HttpResponse(HttpStatusCode.SEE_OTHER); + response.addHeader("Location", "/" + path + "/" + (request.getGETParamString().isEmpty() ? "" : "?" + request.getGETParamString())); + return response; + } + if (!file.exists() || file.isDirectory()){ file = new File(filePath.toString() + ".gz"); isDeflated = true; @@ -164,7 +175,7 @@ private HttpResponse generateResponse(HttpRequest request) { //add content type header String filetype = file.getName().toString(); - if (filetype.endsWith(".gz")) filetype = filetype.substring(3); + if (filetype.endsWith(".gz")) filetype = filetype.substring(0, filetype.length() - 3); int pointIndex = filetype.lastIndexOf('.'); if (pointIndex >= 0) filetype = filetype.substring(pointIndex + 1); diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebFilesManager.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebFilesManager.java index 3d73d14d..50b123e5 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebFilesManager.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebFilesManager.java @@ -27,7 +27,6 @@ import java.io.File; import java.io.IOException; import java.net.URL; -import java.nio.file.Path; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -36,20 +35,20 @@ public class WebFilesManager { - private Path webRoot; + private File webRoot; - public WebFilesManager(Path webRoot) { + public WebFilesManager(File webRoot) { this.webRoot = webRoot; } public boolean needsUpdate() { - if (!webRoot.resolve("index.html").toFile().exists()) return true; + if (!new File(webRoot, "index.html").exists()) return true; return false; } public void updateFiles() throws IOException { - URL fileResource = getClass().getResource("/webroot.zip"); + URL fileResource = getClass().getResource("/de/bluecolored/bluemap/webroot.zip"); File tempFile = File.createTempFile("bluemap_webroot_extraction", null); try { @@ -58,9 +57,9 @@ public void updateFiles() throws IOException { Enumeration entries = zipFile.entries(); while(entries.hasMoreElements()) { ZipEntry zipEntry = entries.nextElement(); - if (zipEntry.isDirectory()) webRoot.resolve(zipEntry.getName()).toFile().mkdirs(); + if (zipEntry.isDirectory()) new File(webRoot, zipEntry.getName()).mkdirs(); else { - File target = webRoot.resolve(zipEntry.getName()).toFile(); + File target = new File(webRoot, zipEntry.getName()); FileUtils.copyInputStreamToFile(zipFile.getInputStream(zipEntry), target); } } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebSettings.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebSettings.java index fc33c212..7ded88a1 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebSettings.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/web/WebSettings.java @@ -32,7 +32,7 @@ import com.flowpowered.math.vector.Vector2i; import com.flowpowered.math.vector.Vector3f; -import de.bluecolored.bluemap.core.config.MainConfig.MapConfig; +import de.bluecolored.bluemap.core.config.MapConfig; import de.bluecolored.bluemap.core.render.TileRenderer; import de.bluecolored.bluemap.core.util.MathUtils; import de.bluecolored.bluemap.core.world.World; diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpRequest.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpRequest.java index 9142546b..30df3462 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpRequest.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/webserver/HttpRequest.java @@ -58,6 +58,7 @@ public class HttpRequest { private String path = null; private Map getParams = null; + private String getParamString = null; public HttpRequest(String method, String adress, String version, Map> header) { this.method = method; @@ -119,16 +120,21 @@ public Map getGETParams() { if (getParams == null) parseAdress(); return Collections.unmodifiableMap(getParams); } + + public String getGETParamString() { + if (getParamString == null) parseAdress(); + return getParamString; + } private void parseAdress() { String adress = this.adress; if (adress.isEmpty()) adress = "/"; String[] adressParts = adress.split("\\?", 2); String path = adressParts[0]; - String getParamString = adressParts.length > 1 ? adressParts[1] : ""; + this.getParamString = adressParts.length > 1 ? adressParts[1] : ""; Map getParams = new HashMap<>(); - for (String getParam : getParamString.split("&")){ + for (String getParam : this.getParamString.split("&")){ if (getParam.isEmpty()) continue; String[] kv = getParam.split("=", 2); String key = kv[0]; @@ -136,10 +142,6 @@ private void parseAdress() { getParams.put(key, value); } - //normalize path - if (path.startsWith("/")) path = path.substring(1); - if (path.endsWith("/")) path = path.substring(0, path.length() - 1); - this.path = path; this.getParams = getParams; } diff --git a/BlueMapCore/src/main/resources/biomes.json b/BlueMapCore/src/main/resources/de/bluecolored/bluemap/biomes.json similarity index 100% rename from BlueMapCore/src/main/resources/biomes.json rename to BlueMapCore/src/main/resources/de/bluecolored/bluemap/biomes.json diff --git a/BlueMapCore/src/main/resources/blockColors.json b/BlueMapCore/src/main/resources/de/bluecolored/bluemap/blockColors.json similarity index 100% rename from BlueMapCore/src/main/resources/blockColors.json rename to BlueMapCore/src/main/resources/de/bluecolored/bluemap/blockColors.json diff --git a/BlueMapCore/src/main/resources/blockIds.json b/BlueMapCore/src/main/resources/de/bluecolored/bluemap/blockIds.json similarity index 100% rename from BlueMapCore/src/main/resources/blockIds.json rename to BlueMapCore/src/main/resources/de/bluecolored/bluemap/blockIds.json diff --git a/BlueMapCore/src/main/resources/blockProperties.json b/BlueMapCore/src/main/resources/de/bluecolored/bluemap/blockProperties.json similarity index 100% rename from BlueMapCore/src/main/resources/blockProperties.json rename to BlueMapCore/src/main/resources/de/bluecolored/bluemap/blockProperties.json diff --git a/BlueMapCore/src/main/resources/core.json b/BlueMapCore/src/main/resources/de/bluecolored/bluemap/version.json similarity index 100% rename from BlueMapCore/src/main/resources/core.json rename to BlueMapCore/src/main/resources/de/bluecolored/bluemap/version.json diff --git a/BlueMapFabric/src/main/resources/bluemap-fabric-defaults.conf b/BlueMapFabric/src/main/resources/bluemap-fabric-defaults.conf deleted file mode 100644 index 98e58691..00000000 --- a/BlueMapFabric/src/main/resources/bluemap-fabric-defaults.conf +++ /dev/null @@ -1,17 +0,0 @@ -accept-download: false -metrics: true -renderThreadCount: -2 -data: "bluemap" -webroot: "bluemap/web" -useCookies: true -webserver { - enabled: true - port: 8100 - maxConnectionCount: 100 -} -liveUpdates { - enabled: true - hiddenGameModes: [] - hideInvisible: true - hideSneaking: false -} diff --git a/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/core-defaults.conf b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/core-defaults.conf new file mode 100644 index 00000000..ace808ab --- /dev/null +++ b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/core-defaults.conf @@ -0,0 +1,4 @@ +accept-download: false +renderThreadCount: -2 +metrics: true +data: "bluemap" \ No newline at end of file diff --git a/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/core.conf b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/core.conf new file mode 100644 index 00000000..a813fd58 --- /dev/null +++ b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/core.conf @@ -0,0 +1,31 @@ +## ## +## BlueMap ## +## Core-Config ## +## ## + +# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula), +# you confirm that you own a license to Minecraft (Java Edition) +# and you agree that BlueMap will download and use this file for you: %minecraft-client-url% +# (Alternatively you can download the file yourself and store it here: /minecraft-client-%minecraft-client-version%.jar) +# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA. +# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.) +# %datetime-iso% +accept-download: false + +# This changes the amount of threads that BlueMap will use to render the maps. +# A higher value can improve render-speed but could impact performance on the host machine. +# This should be always below or equal to the number of available processor-cores. +# Zero or a negative value means the amount of of available processor-cores subtracted by the value. +# (So a value of -2 with 6 cores results in 4 render-processes) +# Default is -2 +renderThreadCount: -2 + +# If this is true, BlueMap might send really basic metrics reports containg only the implementation-type and the version that is being used to https://metrics.bluecolored.de/bluemap/ +# This allows me to track the basic usage of BlueMap and helps me stay motivated to further develop this tool! Please leave it on :) +# An example report looks like this: {"implementation":"bukkit","version":"%version%"} +# Default is true +metrics: true + +# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later. +# Default is "bluemap" +data: "bluemap" \ No newline at end of file diff --git a/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/plugin-defaults.conf b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/plugin-defaults.conf new file mode 100644 index 00000000..ef3bb021 --- /dev/null +++ b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/plugin-defaults.conf @@ -0,0 +1,5 @@ +liveUpdates: true +skinDownload: true +hiddenGameModes: [] +hideInvisible: true +hideSneaking: false \ No newline at end of file diff --git a/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/plugin.conf b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/plugin.conf new file mode 100644 index 00000000..67f297e2 --- /dev/null +++ b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/plugin.conf @@ -0,0 +1,27 @@ +## ## +## BlueMap ## +## Plugin-Config ## +## ## + +# If the server should send live-updates and player-positions. +# This only works if the integrated webserver is enabled. +# Default is true +liveUpdates: true + +# Download the skin from mojang-serves when a player joins your server, so it can be used for the player-markers. +# Default is true +skinDownload: true + +# A list of gamemodes that will prevent a player from appearing on the map. +# Possible values are: survival, creative, spectator, adventure +hiddenGameModes: [ + "spectator" +] + +# If this is true, players that have an invisibility (potion-)effect will be hidden on the map. +# Default is true +hideInvisible: true + +# If this is true, players that are sneaking will be hidden on the map. +# Default is false +hideSneaking: false \ No newline at end of file diff --git a/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/render-defaults.conf b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/render-defaults.conf new file mode 100644 index 00000000..2f276c92 --- /dev/null +++ b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/render-defaults.conf @@ -0,0 +1,3 @@ +webroot: "bluemap/web" +useCookies: true +maps: [] diff --git a/BlueMapSponge/src/main/resources/bluemap-sponge.conf b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/render.conf similarity index 56% rename from BlueMapSponge/src/main/resources/bluemap-sponge.conf rename to BlueMapFabric/src/main/resources/de/bluecolored/bluemap/render.conf index c126f710..1efd4978 100644 --- a/BlueMapSponge/src/main/resources/bluemap-sponge.conf +++ b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/render.conf @@ -1,62 +1,16 @@ ## ## ## BlueMap ## -## ## -## by Blue (Lukas Rieger) ## -## http://bluecolored.de/ ## +## Render-Config ## ## ## -# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula), -# you confirm that you own a license to Minecraft (Java Edition) -# and you agree that BlueMap will download and use this file for you: %minecraft-client-url% -# (Alternatively you can download the file yourself and store it here: /minecraft-client-%minecraft-client-version%.jar) -# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA. -# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.) -# %datetime-iso% -accept-download: false - -# This changes the amount of threads that BlueMap will use to render the maps. -# A higher value can improve render-speed but could impact performance on the host machine. -# This should be always below or equal to the number of available processor-cores. -# Zero or a negative value means the amount of of available processor-cores subtracted by the value. -# (So a value of -2 with 6 cores results in 4 render-processes) -# Default is -2 -renderThreadCount: -2 - -# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later. -data: "bluemap" - -# The webroot of the website that displays the map. +# The folder (webroot) where the map-data and web-application files will be saved. +# Default is "bluemap/web" webroot: "bluemap/web" -# Unncomment this to override the path where bluemap stores the data-files. -# Default is "/data" -#webdata: "path/to/data/folder" - # If the web-application should use cookies to save the configurations of a user. +# Default is true useCookies: true -webserver { - # With this setting you can disable the integrated web-server. - # This is usefull if you want to only render the map-data for later use, or if you setup your own webserver. - # Default is enabled - enabled: true - - # The IP-Adress that the webserver binds to. - # Use "0.0.0.0" to bind to all available local adresses. - # If you only want to access it locally use "localhost". - # Default is "0.0.0.0" - #ip: "localhost" - #ip: "127.0.0.1" - - # The port that the webserver listenes to. - # Default is 8100 - port: 8100 - - # Max number of simultaneous connections that the webserver allows - # Default is 100 - maxConnectionCount: 100 -} - # This is an array with multiple configured maps. # You can define multiple maps, for different worlds with different render-settings here maps: [ @@ -123,6 +77,16 @@ maps: [ # Changing this value requires a re-render of the map. # Default is true useCompression: true + + # Normally BlueMap detects if a chunk has not yet generated it's light-data and omits rendering those chunks. + # If this is set to true BlueMap will render Chunks even if there is no light-data! + # This can be usefull for example if some mod prevents light-data from being saved correctly. + # However, this also has a few drawbacks: + # - For those chunks, every block will always be fully lit + # - Night-mode might not work correctly + # - Caves will always be rendered (ignoring the 'renderCaves' setting) + # Default is false + ignoreMissingLightData: false } # Here another example for the End-Map @@ -160,23 +124,3 @@ maps: [ } ] - -liveUpdates { - # If the server should send live-updates and player-positions. - # Default is true - enabled: true - - # A list of gamemodes that will prevent a player from appearing on the map. - # Possible values are: survival, creative, spectator, adventure - hiddenGameModes: [ - "spectator" - ] - - # If this is true, players that have an invisibility (potion-)effect will be hidden on the map. - # Default is true - hideInvisible: true - - # If this is true, players that are sneaking will be hidden on the map. - # Default is false - hideSneaking: false -} diff --git a/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf new file mode 100644 index 00000000..55e8c255 --- /dev/null +++ b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf @@ -0,0 +1,4 @@ +enabled: true +webroot: "bluemap/web" +port: 8100 +maxConnectionCount: 100 \ No newline at end of file diff --git a/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/webserver.conf b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/webserver.conf new file mode 100644 index 00000000..5764c34b --- /dev/null +++ b/BlueMapFabric/src/main/resources/de/bluecolored/bluemap/webserver.conf @@ -0,0 +1,29 @@ +## ## +## BlueMap ## +## Webserver-Config ## +## ## + +# With this setting you can disable the integrated web-server. +# This is usefull if you want to only render the map-data for later use, or if you setup your own webserver. +# Default is enabled +enabled: true + +# The webroot that the server will host to the web. +# Usually this should be set to the same directory like in the Core-Config! +# Default is "bluemap/web" +webroot: "bluemap/web" + +# The IP-Adress that the webserver binds to. +# Use "0.0.0.0" to bind to all available local adresses. +# If you only want to access it locally use "localhost". +# Default is "0.0.0.0" +#ip: "localhost" +#ip: "123.45.6.78" + +# The port that the webserver listenes to. +# Default is 8100 +port: 8100 + +# Max number of simultaneous connections that the webserver allows +# Default is 100 +maxConnectionCount: 100 \ No newline at end of file diff --git a/BlueMapForge/src/main/resources/bluemap-forge-defaults.conf b/BlueMapForge/src/main/resources/bluemap-forge-defaults.conf deleted file mode 100644 index 98e58691..00000000 --- a/BlueMapForge/src/main/resources/bluemap-forge-defaults.conf +++ /dev/null @@ -1,17 +0,0 @@ -accept-download: false -metrics: true -renderThreadCount: -2 -data: "bluemap" -webroot: "bluemap/web" -useCookies: true -webserver { - enabled: true - port: 8100 - maxConnectionCount: 100 -} -liveUpdates { - enabled: true - hiddenGameModes: [] - hideInvisible: true - hideSneaking: false -} diff --git a/BlueMapForge/src/main/resources/de/bluecolored/bluemap/core-defaults.conf b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/core-defaults.conf new file mode 100644 index 00000000..ace808ab --- /dev/null +++ b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/core-defaults.conf @@ -0,0 +1,4 @@ +accept-download: false +renderThreadCount: -2 +metrics: true +data: "bluemap" \ No newline at end of file diff --git a/BlueMapForge/src/main/resources/de/bluecolored/bluemap/core.conf b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/core.conf new file mode 100644 index 00000000..a813fd58 --- /dev/null +++ b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/core.conf @@ -0,0 +1,31 @@ +## ## +## BlueMap ## +## Core-Config ## +## ## + +# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula), +# you confirm that you own a license to Minecraft (Java Edition) +# and you agree that BlueMap will download and use this file for you: %minecraft-client-url% +# (Alternatively you can download the file yourself and store it here: /minecraft-client-%minecraft-client-version%.jar) +# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA. +# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.) +# %datetime-iso% +accept-download: false + +# This changes the amount of threads that BlueMap will use to render the maps. +# A higher value can improve render-speed but could impact performance on the host machine. +# This should be always below or equal to the number of available processor-cores. +# Zero or a negative value means the amount of of available processor-cores subtracted by the value. +# (So a value of -2 with 6 cores results in 4 render-processes) +# Default is -2 +renderThreadCount: -2 + +# If this is true, BlueMap might send really basic metrics reports containg only the implementation-type and the version that is being used to https://metrics.bluecolored.de/bluemap/ +# This allows me to track the basic usage of BlueMap and helps me stay motivated to further develop this tool! Please leave it on :) +# An example report looks like this: {"implementation":"bukkit","version":"%version%"} +# Default is true +metrics: true + +# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later. +# Default is "bluemap" +data: "bluemap" \ No newline at end of file diff --git a/BlueMapForge/src/main/resources/de/bluecolored/bluemap/plugin-defaults.conf b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/plugin-defaults.conf new file mode 100644 index 00000000..ef3bb021 --- /dev/null +++ b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/plugin-defaults.conf @@ -0,0 +1,5 @@ +liveUpdates: true +skinDownload: true +hiddenGameModes: [] +hideInvisible: true +hideSneaking: false \ No newline at end of file diff --git a/BlueMapForge/src/main/resources/de/bluecolored/bluemap/plugin.conf b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/plugin.conf new file mode 100644 index 00000000..67f297e2 --- /dev/null +++ b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/plugin.conf @@ -0,0 +1,27 @@ +## ## +## BlueMap ## +## Plugin-Config ## +## ## + +# If the server should send live-updates and player-positions. +# This only works if the integrated webserver is enabled. +# Default is true +liveUpdates: true + +# Download the skin from mojang-serves when a player joins your server, so it can be used for the player-markers. +# Default is true +skinDownload: true + +# A list of gamemodes that will prevent a player from appearing on the map. +# Possible values are: survival, creative, spectator, adventure +hiddenGameModes: [ + "spectator" +] + +# If this is true, players that have an invisibility (potion-)effect will be hidden on the map. +# Default is true +hideInvisible: true + +# If this is true, players that are sneaking will be hidden on the map. +# Default is false +hideSneaking: false \ No newline at end of file diff --git a/BlueMapForge/src/main/resources/de/bluecolored/bluemap/render-defaults.conf b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/render-defaults.conf new file mode 100644 index 00000000..2f276c92 --- /dev/null +++ b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/render-defaults.conf @@ -0,0 +1,3 @@ +webroot: "bluemap/web" +useCookies: true +maps: [] diff --git a/BlueMapForge/src/main/resources/bluemap-forge.conf b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/render.conf similarity index 53% rename from BlueMapForge/src/main/resources/bluemap-forge.conf rename to BlueMapForge/src/main/resources/de/bluecolored/bluemap/render.conf index c56e51a9..1efd4978 100644 --- a/BlueMapForge/src/main/resources/bluemap-forge.conf +++ b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/render.conf @@ -1,68 +1,16 @@ ## ## ## BlueMap ## -## ## -## by Blue (Lukas Rieger) ## -## http://bluecolored.de/ ## +## Render-Config ## ## ## -# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula), -# you confirm that you own a license to Minecraft (Java Edition) -# and you agree that BlueMap will download and use this file for you: %minecraft-client-url% -# (Alternatively you can download the file yourself and store it here: /minecraft-client-%minecraft-client-version%.jar) -# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA. -# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.) -# %datetime-iso% -accept-download: false - -# This changes the amount of threads that BlueMap will use to render the maps. -# A higher value can improve render-speed but could impact performance on the host machine. -# This should be always below or equal to the number of available processor-cores. -# Zero or a negative value means the amount of of available processor-cores subtracted by the value. -# (So a value of -2 with 6 cores results in 4 render-processes) -# Default is -2 -renderThreadCount: -2 - -# If this is true, BlueMap might send really basic metrics reports containg only the implementation-type and the version that is being used to https://metrics.bluecolored.de/bluemap/ -# This allows me to track the basic usage of BlueMap and helps me stay motivated to further develop this tool! Please leave it on :) -# An example report looks like this: {"implementation":"forge","version":"%version%"} -metrics: true - -# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later. -data: "bluemap" - -# The webroot of the website that displays the map. +# The folder (webroot) where the map-data and web-application files will be saved. +# Default is "bluemap/web" webroot: "bluemap/web" -# Unncomment this to override the path where bluemap stores the data-files. -# Default is "/data" -#webdata: "path/to/data/folder" - # If the web-application should use cookies to save the configurations of a user. # Default is true useCookies: true -webserver { - # With this setting you can disable the integrated web-server. - # This is usefull if you want to only render the map-data for later use, or if you setup your own webserver. - # Default is enabled - enabled: true - - # The IP-Adress that the webserver binds to. - # Use "0.0.0.0" to bind to all available local adresses. - # If you only want to access it locally use "localhost". - # Default is "0.0.0.0" - #ip: "localhost" - #ip: "127.0.0.1" - - # The port that the webserver listenes to. - # Default is 8100 - port: 8100 - - # Max number of simultaneous connections that the webserver allows - # Default is 100 - maxConnectionCount: 100 -} - # This is an array with multiple configured maps. # You can define multiple maps, for different worlds with different render-settings here maps: [ @@ -129,6 +77,16 @@ maps: [ # Changing this value requires a re-render of the map. # Default is true useCompression: true + + # Normally BlueMap detects if a chunk has not yet generated it's light-data and omits rendering those chunks. + # If this is set to true BlueMap will render Chunks even if there is no light-data! + # This can be usefull for example if some mod prevents light-data from being saved correctly. + # However, this also has a few drawbacks: + # - For those chunks, every block will always be fully lit + # - Night-mode might not work correctly + # - Caves will always be rendered (ignoring the 'renderCaves' setting) + # Default is false + ignoreMissingLightData: false } # Here another example for the End-Map @@ -166,23 +124,3 @@ maps: [ } ] - -liveUpdates { - # If the server should send live-updates and player-positions. - # Default is true - enabled: true - - # A list of gamemodes that will prevent a player from appearing on the map. - # Possible values are: survival, creative, spectator, adventure - hiddenGameModes: [ - "spectator" - ] - - # If this is true, players that have an invisibility (potion-)effect will be hidden on the map. - # Default is true - hideInvisible: true - - # If this is true, players that are sneaking will be hidden on the map. - # Default is false - hideSneaking: false -} diff --git a/BlueMapForge/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf new file mode 100644 index 00000000..55e8c255 --- /dev/null +++ b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf @@ -0,0 +1,4 @@ +enabled: true +webroot: "bluemap/web" +port: 8100 +maxConnectionCount: 100 \ No newline at end of file diff --git a/BlueMapForge/src/main/resources/de/bluecolored/bluemap/webserver.conf b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/webserver.conf new file mode 100644 index 00000000..5764c34b --- /dev/null +++ b/BlueMapForge/src/main/resources/de/bluecolored/bluemap/webserver.conf @@ -0,0 +1,29 @@ +## ## +## BlueMap ## +## Webserver-Config ## +## ## + +# With this setting you can disable the integrated web-server. +# This is usefull if you want to only render the map-data for later use, or if you setup your own webserver. +# Default is enabled +enabled: true + +# The webroot that the server will host to the web. +# Usually this should be set to the same directory like in the Core-Config! +# Default is "bluemap/web" +webroot: "bluemap/web" + +# The IP-Adress that the webserver binds to. +# Use "0.0.0.0" to bind to all available local adresses. +# If you only want to access it locally use "localhost". +# Default is "0.0.0.0" +#ip: "localhost" +#ip: "123.45.6.78" + +# The port that the webserver listenes to. +# Default is 8100 +port: 8100 + +# Max number of simultaneous connections that the webserver allows +# Default is 100 +maxConnectionCount: 100 \ No newline at end of file diff --git a/BlueMapSponge/src/main/resources/bluemap-sponge-defaults.conf b/BlueMapSponge/src/main/resources/bluemap-sponge-defaults.conf deleted file mode 100644 index cf42dfc8..00000000 --- a/BlueMapSponge/src/main/resources/bluemap-sponge-defaults.conf +++ /dev/null @@ -1,17 +0,0 @@ -accept-download: false -metrics: false -renderThreadCount: -2 -data: "bluemap" -webroot: "bluemap/web" -useCookies: true -webserver { - enabled: true - port: 8100 - maxConnectionCount: 100 -} -liveUpdates { - enabled: true - hiddenGameModes: [] - hideInvisible: true - hideSneaking: false -} diff --git a/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/core-defaults.conf b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/core-defaults.conf new file mode 100644 index 00000000..e51cf511 --- /dev/null +++ b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/core-defaults.conf @@ -0,0 +1,4 @@ +accept-download: false +renderThreadCount: -2 +metrics: false +data: "bluemap" \ No newline at end of file diff --git a/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/core.conf b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/core.conf new file mode 100644 index 00000000..179e4c3a --- /dev/null +++ b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/core.conf @@ -0,0 +1,25 @@ +## ## +## BlueMap ## +## Core-Config ## +## ## + +# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula), +# you confirm that you own a license to Minecraft (Java Edition) +# and you agree that BlueMap will download and use this file for you: %minecraft-client-url% +# (Alternatively you can download the file yourself and store it here: /minecraft-client-%minecraft-client-version%.jar) +# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA. +# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.) +# %datetime-iso% +accept-download: false + +# This changes the amount of threads that BlueMap will use to render the maps. +# A higher value can improve render-speed but could impact performance on the host machine. +# This should be always below or equal to the number of available processor-cores. +# Zero or a negative value means the amount of of available processor-cores subtracted by the value. +# (So a value of -2 with 6 cores results in 4 render-processes) +# Default is -2 +renderThreadCount: -2 + +# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later. +# Default is "bluemap" +data: "bluemap" \ No newline at end of file diff --git a/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/plugin-defaults.conf b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/plugin-defaults.conf new file mode 100644 index 00000000..1fbe5b17 --- /dev/null +++ b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/plugin-defaults.conf @@ -0,0 +1,5 @@ +liveUpdates: true +skinDownload: false +hiddenGameModes: [] +hideInvisible: true +hideSneaking: false \ No newline at end of file diff --git a/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/plugin.conf b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/plugin.conf new file mode 100644 index 00000000..a3d3a014 --- /dev/null +++ b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/plugin.conf @@ -0,0 +1,27 @@ +## ## +## BlueMap ## +## Plugin-Config ## +## ## + +# If the server should send live-updates and player-positions. +# This only works if the integrated webserver is enabled. +# Default is true +liveUpdates: true + +# Download the skin from mojang-serves when a player joins your server, so it can be used for the player-markers. +# Default is false +skinDownload: false + +# A list of gamemodes that will prevent a player from appearing on the map. +# Possible values are: survival, creative, spectator, adventure +hiddenGameModes: [ + "spectator" +] + +# If this is true, players that have an invisibility (potion-)effect will be hidden on the map. +# Default is true +hideInvisible: true + +# If this is true, players that are sneaking will be hidden on the map. +# Default is false +hideSneaking: false \ No newline at end of file diff --git a/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/render-defaults.conf b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/render-defaults.conf new file mode 100644 index 00000000..2f276c92 --- /dev/null +++ b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/render-defaults.conf @@ -0,0 +1,3 @@ +webroot: "bluemap/web" +useCookies: true +maps: [] diff --git a/BlueMapFabric/src/main/resources/bluemap-fabric.conf b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/render.conf similarity index 53% rename from BlueMapFabric/src/main/resources/bluemap-fabric.conf rename to BlueMapSponge/src/main/resources/de/bluecolored/bluemap/render.conf index c56e51a9..1efd4978 100644 --- a/BlueMapFabric/src/main/resources/bluemap-fabric.conf +++ b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/render.conf @@ -1,68 +1,16 @@ ## ## ## BlueMap ## -## ## -## by Blue (Lukas Rieger) ## -## http://bluecolored.de/ ## +## Render-Config ## ## ## -# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula), -# you confirm that you own a license to Minecraft (Java Edition) -# and you agree that BlueMap will download and use this file for you: %minecraft-client-url% -# (Alternatively you can download the file yourself and store it here: /minecraft-client-%minecraft-client-version%.jar) -# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compliant with mojang's EULA. -# BlueMap uses resources in this file to generate the 3D-Models used for the map and texture them. (BlueMap will not work without those resources.) -# %datetime-iso% -accept-download: false - -# This changes the amount of threads that BlueMap will use to render the maps. -# A higher value can improve render-speed but could impact performance on the host machine. -# This should be always below or equal to the number of available processor-cores. -# Zero or a negative value means the amount of of available processor-cores subtracted by the value. -# (So a value of -2 with 6 cores results in 4 render-processes) -# Default is -2 -renderThreadCount: -2 - -# If this is true, BlueMap might send really basic metrics reports containg only the implementation-type and the version that is being used to https://metrics.bluecolored.de/bluemap/ -# This allows me to track the basic usage of BlueMap and helps me stay motivated to further develop this tool! Please leave it on :) -# An example report looks like this: {"implementation":"forge","version":"%version%"} -metrics: true - -# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later. -data: "bluemap" - -# The webroot of the website that displays the map. +# The folder (webroot) where the map-data and web-application files will be saved. +# Default is "bluemap/web" webroot: "bluemap/web" -# Unncomment this to override the path where bluemap stores the data-files. -# Default is "/data" -#webdata: "path/to/data/folder" - # If the web-application should use cookies to save the configurations of a user. # Default is true useCookies: true -webserver { - # With this setting you can disable the integrated web-server. - # This is usefull if you want to only render the map-data for later use, or if you setup your own webserver. - # Default is enabled - enabled: true - - # The IP-Adress that the webserver binds to. - # Use "0.0.0.0" to bind to all available local adresses. - # If you only want to access it locally use "localhost". - # Default is "0.0.0.0" - #ip: "localhost" - #ip: "127.0.0.1" - - # The port that the webserver listenes to. - # Default is 8100 - port: 8100 - - # Max number of simultaneous connections that the webserver allows - # Default is 100 - maxConnectionCount: 100 -} - # This is an array with multiple configured maps. # You can define multiple maps, for different worlds with different render-settings here maps: [ @@ -129,6 +77,16 @@ maps: [ # Changing this value requires a re-render of the map. # Default is true useCompression: true + + # Normally BlueMap detects if a chunk has not yet generated it's light-data and omits rendering those chunks. + # If this is set to true BlueMap will render Chunks even if there is no light-data! + # This can be usefull for example if some mod prevents light-data from being saved correctly. + # However, this also has a few drawbacks: + # - For those chunks, every block will always be fully lit + # - Night-mode might not work correctly + # - Caves will always be rendered (ignoring the 'renderCaves' setting) + # Default is false + ignoreMissingLightData: false } # Here another example for the End-Map @@ -166,23 +124,3 @@ maps: [ } ] - -liveUpdates { - # If the server should send live-updates and player-positions. - # Default is true - enabled: true - - # A list of gamemodes that will prevent a player from appearing on the map. - # Possible values are: survival, creative, spectator, adventure - hiddenGameModes: [ - "spectator" - ] - - # If this is true, players that have an invisibility (potion-)effect will be hidden on the map. - # Default is true - hideInvisible: true - - # If this is true, players that are sneaking will be hidden on the map. - # Default is false - hideSneaking: false -} diff --git a/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf new file mode 100644 index 00000000..55e8c255 --- /dev/null +++ b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/webserver-defaults.conf @@ -0,0 +1,4 @@ +enabled: true +webroot: "bluemap/web" +port: 8100 +maxConnectionCount: 100 \ No newline at end of file diff --git a/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/webserver.conf b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/webserver.conf new file mode 100644 index 00000000..5764c34b --- /dev/null +++ b/BlueMapSponge/src/main/resources/de/bluecolored/bluemap/webserver.conf @@ -0,0 +1,29 @@ +## ## +## BlueMap ## +## Webserver-Config ## +## ## + +# With this setting you can disable the integrated web-server. +# This is usefull if you want to only render the map-data for later use, or if you setup your own webserver. +# Default is enabled +enabled: true + +# The webroot that the server will host to the web. +# Usually this should be set to the same directory like in the Core-Config! +# Default is "bluemap/web" +webroot: "bluemap/web" + +# The IP-Adress that the webserver binds to. +# Use "0.0.0.0" to bind to all available local adresses. +# If you only want to access it locally use "localhost". +# Default is "0.0.0.0" +#ip: "localhost" +#ip: "123.45.6.78" + +# The port that the webserver listenes to. +# Default is 8100 +port: 8100 + +# Max number of simultaneous connections that the webserver allows +# Default is 100 +maxConnectionCount: 100 \ No newline at end of file diff --git a/README.md b/README.md index f4fe0530..d9ca7fad 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ The plugins/mods automatically update your map as soon as something changes in y It is however already quite stable and usable. There are just some features still missing, and some blocks - especially tile-entities - will not render correctly/at all. See below for a list of what is planned for future releases. +![screenshot](https://bluecolored.de/paste/BlueMapScreenshot.jpg) + ### Download You can choose a version and download BlueMap from [here](https://github.com/BlueMap-Minecraft/BlueMap/releases). @@ -41,7 +43,6 @@ The `mc/xx`-branches are for other minecraft-versions. ### Todo / planned features Here is a *(surely incomplete)* list of things that i want to include in future versions. *(They are not in any specific order. There is no guarantee that any of those things will ever be included.)* -- live player positions - render more tile-entities (banners, shulker-chests, etc..) - render entities (armor-stands, item-frames, maybe even cows and such..) - free-flight-controls diff --git a/build.gradle b/build.gradle index 26457e38..9846d50e 100644 --- a/build.gradle +++ b/build.gradle @@ -47,10 +47,10 @@ allprojects { license { header rootProject.file('HEADER') excludes([ - '*.conf', - '*.yml', - '*.zip', - '*.json' + '**/*.conf', + '**/*.yml', + '**/*.zip', + '**/*.json' ]) } }