diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/Configuration.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/Configuration.java new file mode 100644 index 00000000..5145613f --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/Configuration.java @@ -0,0 +1,256 @@ +package de.bluecolored.bluemap.core.config; + +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; + +import com.google.common.base.Preconditions; + +import de.bluecolored.bluemap.core.render.RenderSettings; +import de.bluecolored.bluemap.core.web.WebServerConfig; +import ninja.leaping.configurate.ConfigurationNode; + +public class Configuration implements WebServerConfig { + +private String version; + + private boolean downloadAccepted = false; + + private boolean webserverEnabled = true; + private int webserverPort = 8100; + private int webserverMaxConnections = 100; + private InetAddress webserverBindAdress = null; + + private Path dataPath = Paths.get("data"); + + private Path webRoot = Paths.get("web"); + private Path webDataPath = webRoot.resolve("data"); + + private int renderThreadCount = 0; + + private Collection mapConfigs = new ArrayList<>(); + + public Configuration(ConfigurationNode node) throws IOException { + version = node.getNode("version").getString("-"); + downloadAccepted = node.getNode("accept-download").getBoolean(false); + + dataPath = toFolder(node.getNode("data").getString("data")); + + loadWebConfig(node.getNode("web")); + + int defaultCount = Runtime.getRuntime().availableProcessors(); + renderThreadCount = node.getNode("renderThreadCount").getInt(defaultCount); + if (renderThreadCount <= 0) renderThreadCount = defaultCount; + + loadMapConfigs(node.getNode("maps")); + } + + private void loadWebConfig(ConfigurationNode node) throws IOException { + webserverEnabled = node.getNode("enabled").getBoolean(false); + + String webRootString = node.getNode("webroot").getString(); + if (webserverEnabled && webRootString == null) throw new IOException("Invalid configuration: Node web.webroot is not defined"); + webRoot = toFolder(webRootString); + + if (webserverEnabled) { + webserverPort = node.getNode("port").getInt(8100); + webserverMaxConnections = node.getNode("maxConnectionCount").getInt(100); + + String webserverBindAdressString = node.getNode("ip").getString(""); + if (webserverBindAdressString.isEmpty()) { + webserverBindAdress = InetAddress.getLocalHost(); + } else { + webserverBindAdress = InetAddress.getByName(webserverBindAdressString); + } + } + + String webDataString = node.getNode("web-data").getString(node.getNode("data").getString()); + if (webDataString != null) + webDataPath = toFolder(webDataString); + else if (webRoot != null) + webDataPath = webRoot.resolve("data"); + else + throw new IOException("Invalid configuration: Node web.data is not defined in config"); + } + + 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(); + } + + 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; + } + + @Override + public Path getWebRoot() { + return webRoot; + } + + public String getVersion() { + return version; + } + + public boolean isDownloadAccepted() { + return downloadAccepted; + } + + public int getRenderThreadCount() { + return renderThreadCount; + } + + public Collection getMapConfigs(){ + return mapConfigs; + } + + public class MapConfig implements RenderSettings { + + private String id; + private String name; + private String world; + + private boolean renderCaves; + private float ambientOcclusion; + private float lighting; + + private int maxY, minY, sliceY; + + private int hiresTileSize; + private float hiresViewDistance; + + private int lowresPointsPerHiresTile; + private int lowresPointsPerLowresTile; + private float lowresViewDistance; + + 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"); + + 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"); + + this.renderCaves = node.getNode("renderCaves").getBoolean(false); + this.ambientOcclusion = node.getNode("ambientOcclusion").getFloat(0.25f); + this.lighting = node.getNode("lighting").getFloat(0.8f); + + this.maxY = node.getNode("maxY").getInt(RenderSettings.super.getMaxY()); + this.minY = node.getNode("minY").getInt(RenderSettings.super.getMinY()); + this.sliceY = node.getNode("sliceY").getInt(RenderSettings.super.getSliceY()); + + this.hiresTileSize = node.getNode("hires", "tileSize").getInt(32); + this.hiresViewDistance = node.getNode("hires", "viewDistance").getFloat(3.5f); + + this.lowresPointsPerHiresTile = node.getNode("lowres", "pointsPerHiresTile").getInt(4); + this.lowresPointsPerLowresTile = node.getNode("lowres", "pointsPerLowresTile").getInt(50); + this.lowresViewDistance = node.getNode("lowres", "viewDistance").getFloat(4f); + + //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 boolean isRenderCaves() { + return renderCaves; + } + + @Override + public float getAmbientOcclusionStrenght() { + return ambientOcclusion; + } + + @Override + public float getLightShadeMultiplier() { + return lighting; + } + + public int getHiresTileSize() { + return hiresTileSize; + } + + public float getHiresViewDistance() { + return hiresViewDistance; + } + + public int getLowresPointsPerHiresTile() { + return lowresPointsPerHiresTile; + } + + public int getLowresPointsPerLowresTile() { + return lowresPointsPerLowresTile; + } + + public float getLowresViewDistance() { + return lowresViewDistance; + } + + @Override + public boolean isExcludeFacesWithoutSunlight() { + return !isRenderCaves(); + } + + @Override + public int getMaxY() { + return maxY; + } + + @Override + public int getMinY() { + return minY; + } + + @Override + public int getSliceY() { + return sliceY; + } + + } + +} diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/ConfigurationFile.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/ConfigurationFile.java index e0092b8f..98349a2b 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/ConfigurationFile.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/ConfigurationFile.java @@ -26,43 +26,32 @@ import java.io.File; import java.io.IOException; -import java.net.InetAddress; +import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.nio.file.Path; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collection; +import java.util.HashSet; +import java.util.Set; import org.apache.commons.io.FileUtils; -import com.google.common.base.Preconditions; - -import de.bluecolored.bluemap.core.render.RenderSettings; +import de.bluecolored.bluemap.core.BlueMap; import de.bluecolored.bluemap.core.resourcepack.ResourcePack; -import de.bluecolored.bluemap.core.web.WebServerConfig; -import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.commented.CommentedConfigurationNode; import ninja.leaping.configurate.hocon.HoconConfigurationLoader; import ninja.leaping.configurate.loader.ConfigurationLoader; -public class ConfigurationFile implements WebServerConfig { +public class ConfigurationFile { - private String configVersion; + private static final Set CONFIG_PLACEHOLDERS = new HashSet<>(); - private boolean downloadAccepted; + static { + CONFIG_PLACEHOLDERS.add(new Placeholder("version", BlueMap.VERSION)); + CONFIG_PLACEHOLDERS.add(new Placeholder("datetime-iso", () -> LocalDateTime.now().withNano(0).toString())); + CONFIG_PLACEHOLDERS.add(new Placeholder("minecraft-client-url", ResourcePack.MINECRAFT_CLIENT_URL)); + } - private boolean webserverEnabled; - private int webserverPort; - private int webserverMaxConnections; - private InetAddress webserverBindAdress; - - private Path webRoot; - private Path webDataPath; - - private int renderThreadCount; - - private Collection mapConfigs; + private Configuration config; private ConfigurationFile(File configFile) throws IOException { ConfigurationLoader configLoader = HoconConfigurationLoader.builder() @@ -71,236 +60,36 @@ private ConfigurationFile(File configFile) throws IOException { CommentedConfigurationNode rootNode = configLoader.load(); - configVersion = rootNode.getNode("version").getString("-"); - downloadAccepted = rootNode.getNode("accept-download").getBoolean(false); - - loadWebConfig(rootNode.getNode("web")); - - int defaultCount = (int) Math.max(Math.min(Runtime.getRuntime().availableProcessors() * 0.75, 16), 1); - renderThreadCount = rootNode.getNode("renderThreadCount").getInt(defaultCount); - if (renderThreadCount <= 0) renderThreadCount = defaultCount; - - loadMapConfigs(rootNode.getNode("maps")); + config = new Configuration(rootNode); } - private void loadWebConfig(ConfigurationNode node) throws IOException { - webserverEnabled = node.getNode("enabled").getBoolean(false); - - String webRootString = node.getNode("webroot").getString(); - if (webserverEnabled && webRootString == null) throw new IOException("Invalid configuration: Node web.webroot is not defined"); - webRoot = toFolder(webRootString); - - if (webserverEnabled) { - webserverPort = node.getNode("port").getInt(8100); - webserverMaxConnections = node.getNode("maxConnectionCount").getInt(100); - - String webserverBindAdressString = node.getNode("ip").getString(""); - if (webserverBindAdressString.isEmpty()) { - webserverBindAdress = InetAddress.getLocalHost(); - } else { - webserverBindAdress = InetAddress.getByName(webserverBindAdressString); - } - } - - String webDataString = node.getNode("data").getString(); - if (webDataString != null) - webDataPath = toFolder(webDataString); - else if (webRoot != null) - webDataPath = webRoot.resolve("data"); - else - throw new IOException("Invalid configuration: Node web.data is not defined in config"); - } - - private void loadMapConfigs(ConfigurationNode node) throws IOException { - mapConfigs = new ArrayList<>(); - for (ConfigurationNode mapConfigNode : node.getChildrenList()) { - mapConfigs.add(new MapConfig(mapConfigNode)); - } - } - - 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; - } - - @Override - public Path getWebRoot() { - return webRoot; - } - - public String getConfigVersion() { - return configVersion; - } - - public boolean isDownloadAccepted() { - return downloadAccepted; - } - - public int getRenderThreadCount() { - return renderThreadCount; - } - - public Collection getMapConfigs(){ - return mapConfigs; - } - - 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(); + public Configuration getConfig() { + return config; } public static ConfigurationFile loadOrCreate(File configFile) throws IOException { + return loadOrCreate(configFile, ConfigurationFile.class.getResource("/bluemap.conf")); + } + + public static ConfigurationFile loadOrCreate(File configFile, URL defaultConfig) throws IOException { if (!configFile.exists()) { configFile.getParentFile().mkdirs(); - FileUtils.copyURLToFile(ConfigurationFile.class.getResource("/bluemap.conf"), configFile, 10000, 10000); + FileUtils.copyURLToFile(defaultConfig, configFile, 10000, 10000); //replace placeholder String content = new String(Files.readAllBytes(configFile.toPath()), StandardCharsets.UTF_8); - content = content.replaceAll("%resource-file%", ResourcePack.MINECRAFT_CLIENT_URL); - content = content.replaceAll("%date%", LocalDateTime.now().withNano(0).toString()); + for (Placeholder placeholder : CONFIG_PLACEHOLDERS) { + content = placeholder.apply(content); + } Files.write(configFile.toPath(), content.getBytes(StandardCharsets.UTF_8)); } return new ConfigurationFile(configFile); } - public class MapConfig implements RenderSettings { - - private String id; - private String name; - private String world; - - private boolean renderCaves; - private float ambientOcclusion; - private float lighting; - - private int maxY, minY, sliceY; - - private int hiresTileSize; - private float hiresViewDistance; - - private int lowresPointsPerHiresTile; - private int lowresPointsPerLowresTile; - private float lowresViewDistance; - - 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"); - - 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"); - - this.renderCaves = node.getNode("renderCaves").getBoolean(false); - this.ambientOcclusion = node.getNode("ambientOcclusion").getFloat(0.25f); - this.lighting = node.getNode("lighting").getFloat(0.8f); - - this.maxY = node.getNode("maxY").getInt(RenderSettings.super.getMaxY()); - this.minY = node.getNode("minY").getInt(RenderSettings.super.getMinY()); - this.sliceY = node.getNode("sliceY").getInt(RenderSettings.super.getSliceY()); - - this.hiresTileSize = node.getNode("hires", "tileSize").getInt(32); - this.hiresViewDistance = node.getNode("hires", "viewDistance").getFloat(3.5f); - - this.lowresPointsPerHiresTile = node.getNode("lowres", "pointsPerHiresTile").getInt(4); - this.lowresPointsPerLowresTile = node.getNode("lowres", "pointsPerLowresTile").getInt(50); - this.lowresViewDistance = node.getNode("lowres", "viewDistance").getFloat(4f); - - //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 boolean isRenderCaves() { - return renderCaves; - } - - @Override - public float getAmbientOcclusionStrenght() { - return ambientOcclusion; - } - - @Override - public float getLightShadeMultiplier() { - return lighting; - } - - public int getHiresTileSize() { - return hiresTileSize; - } - - public float getHiresViewDistance() { - return hiresViewDistance; - } - - public int getLowresPointsPerHiresTile() { - return lowresPointsPerHiresTile; - } - - public int getLowresPointsPerLowresTile() { - return lowresPointsPerLowresTile; - } - - public float getLowresViewDistance() { - return lowresViewDistance; - } - - @Override - public boolean isExcludeFacesWithoutSunlight() { - return !isRenderCaves(); - } - - @Override - public int getMaxY() { - return maxY; - } - - @Override - public int getMinY() { - return minY; - } - - @Override - public int getSliceY() { - return sliceY; - } - + public static void registerPlaceholder(Placeholder placeholder) { + CONFIG_PLACEHOLDERS.add(placeholder); } } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/Placeholder.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/Placeholder.java new file mode 100644 index 00000000..4606b2d2 --- /dev/null +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/config/Placeholder.java @@ -0,0 +1,24 @@ +package de.bluecolored.bluemap.core.config; + +import java.util.function.Supplier; +import java.util.regex.Pattern; + +public class Placeholder { + + private String name; + private Supplier valueSupplier; + + public Placeholder(String name, String value) { + this(name, () -> value); + } + + public Placeholder(String name, Supplier valueSupplier) { + this.name = name; + this.valueSupplier = valueSupplier; + } + + public String apply(String config) { + return config.replaceAll(Pattern.quote("%" + name + "%"), valueSupplier.get()); + } + +} diff --git a/BlueMapCore/src/main/resources/bluemap.conf b/BlueMapCore/src/main/resources/bluemap.conf index cfc95e0e..548fcffa 100644 --- a/BlueMapCore/src/main/resources/bluemap.conf +++ b/BlueMapCore/src/main/resources/bluemap.conf @@ -8,24 +8,32 @@ # !! Don't change this !! # This is used to detect version-changes in the configuration # and update configuration correctly. -version: "1.0.0" +version: "%version%" # 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: %resource-file% -# (Alternatively you can download the file yourself and store it here: ./config/bluemap/resourcepacks/client.jar) +# 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.jar) # This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compilant 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.) -# %date% +# %datetime-iso% accept-download: false +# 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 or to save e.g. the render-progress to resume it later. +data: "data" + web { # With this setting you can disable the web-server. # This is usefull if you want to only render the map-data for later use, or if you setup your own webserver. enabled: true # The webroot of the website that displays the map. - webroot: "bluemap/web" + webroot: "web" # The IP-Adress that the webserver binds to. # If this setting is commented out, bluemap tries to find the default ip-adress of your system. @@ -43,7 +51,7 @@ web { # Unncomment this to override the path where bluemap stores the data-files. # Default is "/data" - #data: "path/to/data/folder" + #web-data: "path/to/data/folder" } # This changes the amount of threads that BlueMap will use to render the maps. @@ -158,4 +166,4 @@ maps: [ #maxY: 126 } -] \ No newline at end of file +] diff --git a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java index 87cb6efc..6e1be6dc 100644 --- a/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java +++ b/BlueMapSponge/src/main/java/de/bluecolored/bluemap/sponge/SpongePlugin.java @@ -56,7 +56,8 @@ import de.bluecolored.bluemap.core.BlueMap; import de.bluecolored.bluemap.core.config.ConfigurationFile; -import de.bluecolored.bluemap.core.config.ConfigurationFile.MapConfig; +import de.bluecolored.bluemap.core.config.Configuration; +import de.bluecolored.bluemap.core.config.Configuration.MapConfig; import de.bluecolored.bluemap.core.logger.Logger; import de.bluecolored.bluemap.core.mca.MCAWorld; import de.bluecolored.bluemap.core.metrics.Metrics; @@ -95,7 +96,7 @@ public class SpongePlugin { @Inject private MetricsLite2 metrics; - private ConfigurationFile config; + private Configuration config; private ResourcePack resourcePack; private Map worlds; @@ -129,10 +130,10 @@ public synchronized void load() throws IOException, NoSuchResourceException { //load configs File configFile = getConfigPath().resolve("bluemap.conf").toFile(); - config = ConfigurationFile.loadOrCreate(configFile); + config = ConfigurationFile.loadOrCreate(configFile).getConfig(); //load resources - File defaultResourceFile = getConfigPath().resolve("resourcepacks").resolve("client.jar").toFile(); + File defaultResourceFile = getConfigPath().resolve("resourcepacks").resolve("minecraft-client.jar").toFile(); File textureExportFile = config.getWebDataPath().resolve("textures.json").toFile(); if (!defaultResourceFile.exists()) { @@ -162,8 +163,8 @@ public synchronized void load() throws IOException, NoSuchResourceException { try { CompoundTag levelSponge = (CompoundTag) NBTUtil.readTag(new File(worldFolder, "level_sponge.dat")); CompoundTag spongeData = levelSponge.getCompoundTag("SpongeData"); - long least = spongeData.getLong("UUIDLeast"); long most = spongeData.getLong("UUIDMost"); + long least = spongeData.getLong("UUIDLeast"); worldUUID = new UUID(most, least); } catch (Exception e) { Logger.global.logError("Failed to load map '" + id + "': Failed to read level_sponge.dat", e); @@ -232,7 +233,7 @@ public synchronized void load() throws IOException, NoSuchResourceException { webSettings.setName(map.getName(), map.getId()); webSettings.setFrom(map.getTileRenderer(), map.getId()); } - for (ConfigurationFile.MapConfig map : config.getMapConfigs()) { + for (MapConfig map : config.getMapConfigs()) { webSettings.setHiresViewDistance(map.getHiresViewDistance(), map.getId()); webSettings.setLowresViewDistance(map.getLowresViewDistance(), map.getId()); } diff --git a/BlueMapSponge/src/main/resources/bluemap-sponge.conf b/BlueMapSponge/src/main/resources/bluemap-sponge.conf new file mode 100644 index 00000000..4811f4bb --- /dev/null +++ b/BlueMapSponge/src/main/resources/bluemap-sponge.conf @@ -0,0 +1,164 @@ +## ## +## BlueMap ## +## ## +## by Blue (Lukas Rieger) ## +## http://bluecolored.de/ ## +## ## + +# !! Don't change this !! +# This is used to detect version-changes in the configuration +# and update configuration correctly. +version: "%version%" + +# 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.jar) +# This file contains resources that belong to mojang and you must not redistribute it or do anything else that is not compilant 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 + +# 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" + +web { + # With this setting you can disable the web-server. + # This is usefull if you want to only render the map-data for later use, or if you setup your own webserver. + enabled: true + + # The webroot of the website that displays the map. + webroot: "bluemap/web" + + # The IP-Adress that the webserver binds to. + # If this setting is commented out, bluemap tries to find the default ip-adress of your system. + # If you only want to access it locally use "localhost". + #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 + + # Unncomment this to override the path where bluemap stores the data-files. + # Default is "/data" + #web-data: "path/to/data/folder" +} + +# 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. +# If this value is commented out BlueMap tries to find the optimal thread count to max out render-performance +#renderThreadCount: 2 + +# This is an array with multiple configured maps. +# You can define multiple maps, for different worlds with different render-settings here +maps: [ + + { + # The id of this map + # Should only contain word-charactes: [a-zA-Z0-9_] + id: "world" + + # The name of this map + # This defines the display name of this map, you can change this at any time + # Default is the id of this map + name: "World" + + # The path to the save-folder of the world to render + world: "world" + + # If this is false, BlueMap tries to omit all blocks that are not visible from above-ground. + # More specific: Block-Faces that have a sunlight/skylight value of 0 are removed. + # This improves the performance of the map on slower devices by a lot, but might cause some blocks to disappear that should normally be visible. + # Default is false + renderCaves: false + + # AmbientOcclusion adds soft shadows into corners, which gives the map a much better look. + # This has only a small impact on render-time and has no impact on the web-performance of the map. + # The value defines the strength of the shading, a value of 0 disables ambientOcclusion. + # Default is 0.25 + ambientOcclusion: 0.25 + + # Lighting uses the light-data in minecraft to shade each block-face. + # If this is enabled, caves and inside buildings without torches will be darker. + # The value defines the strength of the shading and a value of 0 disables lighting (every block will be fully lit). + # Default is 0.8 + lighting: 0.8 + + # Using this, BlueMap pretends that every Block above the defined value is AIR. + # Default is disabled + #sliceY: 90 + + # With the below values you can just not render blocks at certain heights. + # This can be used to ignore the nethers ceiling. + # Default is no min or max y value + #minY: 50 + #maxY: 126 + + # HIRES is the high-resolution render of the map. Where you see every block. + hires { + # Defines the size of one map-tile in blocks. + # If you change this value, the lowres values might need adjustment as well! + # Default is 32 + tileSize: 32 + + # The View-Distance for hires tiles on the web-map (the value is the radius in tiles) + # Default is 3.5 + viewDistance: 3.5 + } + + # LOWRES is the low-resolution render of the map. THats the model that you see if you zoom far out to get an overview. + lowres { + # Defines resolution of the lowres model. E.g. If the hires.tileSize is 32, a value of 4 means that every 8*8 blocks will be summarized by one point on the lowres map. + # Calculation: 32 / 4 = 8 + # You can only use values that result in an integer if you use the above calculation! + # Default is 4 + pointsPerHiresTile: 4 + + # Defines the size of one lowres-map-tile in points. + # Default is 50 + pointsPerLowresTile: 50 + + # The View-Distance for lowres tiles on the web-map (the value is the radius in tiles) + # Default is 4 + viewDistance: 4 + } + } + + # Here another example for the End-Map + # Things we dont want to change from default we can just omit + { + id: "end" + name: "End" + world: "world/DIM1" + + # In the end is no light, so we need to enable this or we don't see anything. + renderCaves: true + + # Same here, we don't want a dark map. But not completely disabled, so we see the effect of e.g torches. + lighting: 0.4 + } + + # Here another example for the Nether-Map + { + id: "nether" + name: "Nether" + world: "world/DIM-1" + + renderCaves: true + lighting: 0.6 + + # We slice the whole world at y:90 so evrery block above 90 will be air. + # This way we dont render the nethers ceiling. + sliceY: 90 + + # Instead of slicing we also could do this, that would look like an x-ray view through the ceiling. + #maxY: 126 + } + +]