mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-09-27 22:57:36 +02:00
Merge branch 'base'
This commit is contained in:
commit
5514771b6a
4
.gitignore
vendored
4
.gitignore
vendored
@ -31,8 +31,8 @@ node_modules/
|
|||||||
package-lock.json
|
package-lock.json
|
||||||
|
|
||||||
# exclude generated resource
|
# exclude generated resource
|
||||||
BlueMapCore/src/main/resources/webroot.zip
|
BlueMapCore/src/main/resources/de/bluecolored/bluemap/webroot.zip
|
||||||
BlueMapCore/src/main/resources/resourceExtensions.zip
|
BlueMapCore/src/main/resources/de/bluecolored/bluemap/resourceExtensions.zip
|
||||||
|
|
||||||
#exclude-test-data
|
#exclude-test-data
|
||||||
data/test-render
|
data/test-render
|
||||||
|
@ -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
|
|
||||||
}
|
|
@ -0,0 +1,4 @@
|
|||||||
|
accept-download: false
|
||||||
|
renderThreadCount: -2
|
||||||
|
metrics: true
|
||||||
|
data: "bluemap"
|
@ -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: <data>/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"
|
@ -0,0 +1,5 @@
|
|||||||
|
liveUpdates: true
|
||||||
|
skinDownload: true
|
||||||
|
hiddenGameModes: []
|
||||||
|
hideInvisible: true
|
||||||
|
hideSneaking: false
|
@ -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
|
@ -0,0 +1,3 @@
|
|||||||
|
webroot: "bluemap/web"
|
||||||
|
useCookies: true
|
||||||
|
maps: []
|
@ -1,68 +1,16 @@
|
|||||||
## ##
|
## ##
|
||||||
## BlueMap ##
|
## BlueMap ##
|
||||||
## ##
|
## Render-Config ##
|
||||||
## by Blue (Lukas Rieger) ##
|
|
||||||
## http://bluecolored.de/ ##
|
|
||||||
## ##
|
## ##
|
||||||
|
|
||||||
# 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),
|
# The folder (webroot) where the map-data and web-application files will be saved.
|
||||||
# you confirm that you own a license to Minecraft (Java Edition)
|
# Default is "bluemap/web"
|
||||||
# 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: <data>/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.
|
|
||||||
webroot: "bluemap/web"
|
webroot: "bluemap/web"
|
||||||
|
|
||||||
# Unncomment this to override the path where bluemap stores the data-files.
|
|
||||||
# Default is "<webroot>/data"
|
|
||||||
#webdata: "path/to/data/folder"
|
|
||||||
|
|
||||||
# If the web-application should use cookies to save the configurations of a user.
|
# If the web-application should use cookies to save the configurations of a user.
|
||||||
# Default is true
|
# Default is true
|
||||||
useCookies: 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.
|
# This is an array with multiple configured maps.
|
||||||
# You can define multiple maps, for different worlds with different render-settings here
|
# You can define multiple maps, for different worlds with different render-settings here
|
||||||
maps: [
|
maps: [
|
||||||
@ -129,6 +77,16 @@ maps: [
|
|||||||
# Changing this value requires a re-render of the map.
|
# Changing this value requires a re-render of the map.
|
||||||
# Default is true
|
# Default is true
|
||||||
useCompression: 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
|
# 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
|
|
||||||
}
|
|
@ -0,0 +1,4 @@
|
|||||||
|
enabled: true
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
port: 8100
|
||||||
|
maxConnectionCount: 100
|
@ -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
|
@ -10,7 +10,7 @@ jar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build.dependsOn shadowJar {
|
build.dependsOn shadowJar {
|
||||||
destinationDir = file '../build/release'
|
destinationDir = file '../build/unsupported'
|
||||||
archiveFileName = "BlueMap-${version}-cli.jar"
|
archiveFileName = "BlueMap-${version}-cli.jar"
|
||||||
|
|
||||||
//relocate 'com.flowpowered.math', 'de.bluecolored.shadow.flowpowered.math' //DON'T relocate this, because the API depends on it
|
//relocate 'com.flowpowered.math', 'de.bluecolored.shadow.flowpowered.math' //DON'T relocate this, because the API depends on it
|
||||||
|
@ -32,14 +32,7 @@
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
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.GZIPInputStream;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
@ -50,137 +43,47 @@
|
|||||||
import org.apache.commons.cli.Option;
|
import org.apache.commons.cli.Option;
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
import org.apache.commons.lang3.time.DurationFormatUtils;
|
import org.apache.commons.lang3.time.DurationFormatUtils;
|
||||||
|
|
||||||
import com.flowpowered.math.GenericMath;
|
import com.flowpowered.math.GenericMath;
|
||||||
import com.flowpowered.math.vector.Vector2i;
|
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.MapType;
|
||||||
|
import de.bluecolored.bluemap.common.MissingResourcesException;
|
||||||
import de.bluecolored.bluemap.common.RenderManager;
|
import de.bluecolored.bluemap.common.RenderManager;
|
||||||
import de.bluecolored.bluemap.common.RenderTask;
|
import de.bluecolored.bluemap.common.RenderTask;
|
||||||
import de.bluecolored.bluemap.core.config.ConfigManager;
|
import de.bluecolored.bluemap.core.BlueMap;
|
||||||
import de.bluecolored.bluemap.core.config.MainConfig;
|
import de.bluecolored.bluemap.core.config.WebServerConfig;
|
||||||
import de.bluecolored.bluemap.core.config.MainConfig.MapConfig;
|
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
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.hires.HiresModelManager;
|
||||||
import de.bluecolored.bluemap.core.render.lowres.LowresModelManager;
|
import de.bluecolored.bluemap.core.web.FileRequestHandler;
|
||||||
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.web.WebSettings;
|
||||||
import de.bluecolored.bluemap.core.world.SlicedWorld;
|
import de.bluecolored.bluemap.core.webserver.HttpRequestHandler;
|
||||||
import de.bluecolored.bluemap.core.world.World;
|
import de.bluecolored.bluemap.core.webserver.WebServer;
|
||||||
|
|
||||||
public class BlueMapCLI {
|
public class BlueMapCLI {
|
||||||
|
|
||||||
private ConfigManager configManager;
|
public void renderMaps(BlueMapService blueMap, boolean forceRender, boolean forceGenerateWebapp) throws IOException {
|
||||||
private File configFolder;
|
blueMap.createOrUpdateWebApp(forceGenerateWebapp);
|
||||||
private ResourcePack resourcePack;
|
WebSettings webSettings = blueMap.updateWebAppSettings();
|
||||||
private boolean forceRender;
|
|
||||||
|
|
||||||
public BlueMapCLI(ConfigManager configManager, File configFolder, boolean forceRender) {
|
RenderManager renderManager = new RenderManager(blueMap.getCoreConfig().getRenderThreadCount());
|
||||||
this.configManager = configManager;
|
File rmstate = new File(blueMap.getCoreConfig().getDataFolder(), "rmstate");
|
||||||
this.configFolder = configFolder;
|
|
||||||
this.forceRender = forceRender;
|
|
||||||
this.resourcePack = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void renderMaps() throws IOException {
|
if (!forceRender && rmstate.exists()) {
|
||||||
Preconditions.checkNotNull(resourcePack);
|
|
||||||
|
|
||||||
MainConfig config = configManager.getMainConfig();
|
|
||||||
configManager.loadResourceConfigs(resourcePack);
|
|
||||||
|
|
||||||
config.getWebDataPath().toFile().mkdirs();
|
|
||||||
|
|
||||||
Map<String, MapType> 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()) {
|
|
||||||
try (
|
try (
|
||||||
InputStream in = new GZIPInputStream(new FileInputStream(rmstate));
|
InputStream in = new GZIPInputStream(new FileInputStream(rmstate));
|
||||||
DataInputStream din = new DataInputStream(in);
|
DataInputStream din = new DataInputStream(in);
|
||||||
){
|
){
|
||||||
renderManager.readState(din, maps.values());
|
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());
|
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) {
|
} catch (IOException ex) {
|
||||||
Logger.global.logError("Failed to read saved render-state! Remove the file " + rmstate.getCanonicalPath() + " to start a new render.", ex);
|
Logger.global.logError("Failed to read saved render-state! Remove the file " + rmstate.getCanonicalPath() + " to start a new render.", ex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} 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("Creating render-task for map '" + map.getId() + "' ...");
|
||||||
Logger.global.logInfo("Collecting tiles ...");
|
Logger.global.logInfo("Collecting tiles ...");
|
||||||
|
|
||||||
@ -214,6 +117,30 @@ public void renderMaps() throws IOException {
|
|||||||
Logger.global.logInfo("Starting render ...");
|
Logger.global.logInfo("Starting render ...");
|
||||||
renderManager.start();
|
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 startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
long lastLogUpdate = startTime;
|
long lastLogUpdate = startTime;
|
||||||
@ -266,12 +193,16 @@ public void renderMaps() throws IOException {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//render finished and saved, so this is no longer needed
|
||||||
|
Runtime.getRuntime().removeShutdownHook(shutdownHook);
|
||||||
|
|
||||||
|
//stop render-threads
|
||||||
renderManager.stop();
|
renderManager.stop();
|
||||||
|
|
||||||
//render finished, so remove render state file
|
//render finished, so remove render state file
|
||||||
rmstate.delete();
|
rmstate.delete();
|
||||||
|
|
||||||
for (MapType map : maps.values()) {
|
for (MapType map : blueMap.getMaps().values()) {
|
||||||
webSettings.set(startTime, "maps", map.getId(), "last-render");
|
webSettings.set(startTime, "maps", map.getId(), "last-render");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,69 +215,27 @@ public void renderMaps() throws IOException {
|
|||||||
Logger.global.logInfo("Render finished!");
|
Logger.global.logInfo("Render finished!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startWebserver() throws IOException {
|
public void startWebserver(BlueMapService blueMap) throws IOException {
|
||||||
Logger.global.logInfo("Starting webserver ...");
|
Logger.global.logInfo("Starting webserver ...");
|
||||||
|
|
||||||
BlueMapWebServer webserver = new BlueMapWebServer(configManager.getMainConfig());
|
WebServerConfig config = blueMap.getWebServerConfig();
|
||||||
webserver.start();
|
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 {
|
public static void main(String[] args) {
|
||||||
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<File> 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 {
|
|
||||||
CommandLineParser parser = new DefaultParser();
|
CommandLineParser parser = new DefaultParser();
|
||||||
|
|
||||||
|
BlueMapCLI cli = new BlueMapCLI();
|
||||||
|
BlueMapService blueMap = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CommandLine cmd = parser.parse(BlueMapCLI.createOptions(), args, false);
|
CommandLine cmd = parser.parse(BlueMapCLI.createOptions(), args, false);
|
||||||
|
|
||||||
@ -356,62 +245,82 @@ public static void main(String[] args) throws IOException, ParseResourceExceptio
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//load config
|
//config folder
|
||||||
File configFolder = new File(".");
|
File configFolder = new File(".");
|
||||||
if (cmd.hasOption("c")) {
|
if (cmd.hasOption("c")) {
|
||||||
configFolder = new File(cmd.getOptionValue("c"));
|
configFolder = new File(cmd.getOptionValue("c"));
|
||||||
configFolder.mkdirs();
|
configFolder.mkdirs();
|
||||||
}
|
}
|
||||||
|
|
||||||
URL cliConfigUrl = BlueMapCLI.class.getResource("/bluemap-cli.conf");
|
blueMap = new BlueMapService(configFolder);
|
||||||
URL cliDefaultsUrl = BlueMapCLI.class.getResource("/bluemap-cli-defaults.conf");
|
boolean noActions = true;
|
||||||
|
|
||||||
ConfigManager config = new ConfigManager(configFolder, cliConfigUrl, cliDefaultsUrl);
|
if (cmd.hasOption("w")) {
|
||||||
boolean configCreated = !config.getMainConfigFile().exists();
|
noActions = false;
|
||||||
config.loadMainConfig();
|
|
||||||
|
|
||||||
if (configCreated) {
|
cli.startWebserver(blueMap);
|
||||||
Logger.global.logInfo("No config file found! Created default config here: " + config.getMainConfigFile().getCanonicalPath());
|
Thread.sleep(1000); //wait a second to let the webserver start, looks nicer in the log if anything comes after that
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebFilesManager webFilesManager = new WebFilesManager(config.getMainConfig().getWebRoot());
|
} catch (MissingResourcesException e) {
|
||||||
if (webFilesManager.needsUpdate()) {
|
Logger.global.logWarning("BlueMap is missing important resources!");
|
||||||
Logger.global.logInfo("Updating webfiles in " + config.getMainConfig().getWebRoot().normalize() + "...");
|
Logger.global.logWarning("You need to accept the download of the required files in order of BlueMap to work!");
|
||||||
webFilesManager.updateFiles();
|
try { Logger.global.logWarning("Please check: " + blueMap.getCoreConfigFile().getCanonicalPath()); } catch (NullPointerException | IOException ignored) {}
|
||||||
}
|
System.exit(2);
|
||||||
|
return;
|
||||||
BlueMapCLI bluemap = new BlueMapCLI(config, configFolder, cmd.hasOption("f"));
|
|
||||||
|
|
||||||
if (config.getMainConfig().isWebserverEnabled()) {
|
|
||||||
//start webserver
|
|
||||||
bluemap.startWebserver();
|
|
||||||
|
|
||||||
//wait a second to let the webserver start, looks nicer in the log
|
|
||||||
try {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
} catch (InterruptedException ignore) { Thread.currentThread().interrupt(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
Logger.global.logError("Failed to parse provided arguments!", e);
|
Logger.global.logError("Failed to parse provided arguments!", e);
|
||||||
BlueMapCLI.printHelp();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -430,6 +339,12 @@ private static Options createOptions() {
|
|||||||
.build()
|
.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");
|
options.addOption("f", "force-render", false, "Forces rendering everything, instead of only rendering chunks that have been modified since the last render");
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
@ -438,7 +353,7 @@ private static Options createOptions() {
|
|||||||
private static void printHelp() {
|
private static void printHelp() {
|
||||||
HelpFormatter formatter = new HelpFormatter();
|
HelpFormatter formatter = new HelpFormatter();
|
||||||
|
|
||||||
String filename = "bluemapcli.jar";
|
String filename = "bluemap-cli.jar";
|
||||||
try {
|
try {
|
||||||
File file = new File(BlueMapCLI.class.getProtectionDomain()
|
File file = new File(BlueMapCLI.class.getProtectionDomain()
|
||||||
.getCodeSource()
|
.getCodeSource()
|
||||||
@ -452,11 +367,22 @@ private static void printHelp() {
|
|||||||
filename = file.getAbsolutePath();
|
filename = file.getAbsolutePath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {}
|
} catch (IOException ignore) {}
|
||||||
|
|
||||||
String command = "java -jar " + filename;
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
accept-download: false
|
|
||||||
metrics: true
|
|
||||||
renderThreadCount: 0
|
|
||||||
data: "."
|
|
||||||
webroot: "web"
|
|
||||||
useCookies: true
|
|
||||||
webserver {
|
|
||||||
enabled: false
|
|
||||||
port: 8100
|
|
||||||
maxConnectionCount: 100
|
|
||||||
}
|
|
@ -0,0 +1,4 @@
|
|||||||
|
accept-download: false
|
||||||
|
renderThreadCount: 0
|
||||||
|
metrics: true
|
||||||
|
data: "data"
|
@ -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: <data>/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"
|
@ -0,0 +1,3 @@
|
|||||||
|
webroot: "web"
|
||||||
|
useCookies: true
|
||||||
|
maps: []
|
@ -1,66 +1,16 @@
|
|||||||
## ##
|
## ##
|
||||||
## BlueMap ##
|
## BlueMap ##
|
||||||
## ##
|
## Render-Config ##
|
||||||
## by Blue (Lukas Rieger) ##
|
|
||||||
## http://bluecolored.de/ ##
|
|
||||||
## ##
|
## ##
|
||||||
|
|
||||||
# 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),
|
# The folder (webroot) where the map-data and web-application files will be saved.
|
||||||
# you confirm that you own a license to Minecraft (Java Edition)
|
# Default is "web"
|
||||||
# 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: <data>/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.
|
|
||||||
webroot: "web"
|
webroot: "web"
|
||||||
|
|
||||||
# Unncomment this to override the path where bluemap stores the data-files.
|
|
||||||
# Default is "<webroot>/data"
|
|
||||||
#webdata: "path/to/data/folder"
|
|
||||||
|
|
||||||
# If the web-application should use cookies to save the configurations of a user.
|
# If the web-application should use cookies to save the configurations of a user.
|
||||||
|
# Default is true
|
||||||
useCookies: 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.
|
# This is an array with multiple configured maps.
|
||||||
# You can define multiple maps, for different worlds with different render-settings here
|
# You can define multiple maps, for different worlds with different render-settings here
|
||||||
maps: [
|
maps: [
|
||||||
@ -127,6 +77,16 @@ maps: [
|
|||||||
# Changing this value requires a re-render of the map.
|
# Changing this value requires a re-render of the map.
|
||||||
# Default is true
|
# Default is true
|
||||||
useCompression: 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
|
# Here another example for the End-Map
|
@ -0,0 +1,4 @@
|
|||||||
|
enabled: true
|
||||||
|
webroot: "web"
|
||||||
|
port: 8100
|
||||||
|
maxConnectionCount: 100
|
@ -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
|
@ -0,0 +1,336 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* 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<File, UUID, IOException> worldUUIDProvider;
|
||||||
|
private ThrowingFunction<UUID, String, IOException> worldNameProvider;
|
||||||
|
|
||||||
|
private ConfigManager configManager;
|
||||||
|
private boolean resourceConfigLoaded = false;
|
||||||
|
|
||||||
|
private CoreConfig coreConfig;
|
||||||
|
private RenderConfig renderConfig;
|
||||||
|
private WebServerConfig webServerConfig;
|
||||||
|
|
||||||
|
private ResourcePack resourcePack;
|
||||||
|
|
||||||
|
private Map<UUID, World> worlds;
|
||||||
|
private Map<String, MapType> maps;
|
||||||
|
|
||||||
|
public BlueMapService(File configFolder) {
|
||||||
|
this.configFolder = configFolder;
|
||||||
|
|
||||||
|
Map<File, UUID> 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<UUID, World> getWorlds() throws IOException {
|
||||||
|
if (worlds == null) loadWorldsAndMaps();
|
||||||
|
return worlds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Map<String, MapType> 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<File> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -22,19 +22,10 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.web;
|
package de.bluecolored.bluemap.common;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
public interface WebServerConfig {
|
|
||||||
|
|
||||||
Path getWebRoot();
|
|
||||||
|
|
||||||
InetAddress getWebserverBindAdress();
|
|
||||||
|
|
||||||
int getWebserverPort();
|
|
||||||
|
|
||||||
int getWebserverMaxConnections();
|
|
||||||
|
|
||||||
|
public class MissingResourcesException extends IOException {
|
||||||
|
private static final long serialVersionUID = 2084565069965755048L;
|
||||||
}
|
}
|
@ -22,18 +22,10 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.config;
|
package de.bluecolored.bluemap.common;
|
||||||
|
|
||||||
import java.util.Collection;
|
public interface ThrowingFunction<T, R, E extends Throwable> {
|
||||||
|
|
||||||
public interface LiveAPISettings {
|
R apply(T t) throws E;
|
||||||
|
|
||||||
boolean isLiveUpdatesEnabled();
|
|
||||||
|
|
||||||
Collection<String> getHiddenGameModes();
|
|
||||||
|
|
||||||
boolean isHideInvisible();
|
|
||||||
|
|
||||||
boolean isHideSneaking();
|
|
||||||
|
|
||||||
}
|
}
|
@ -55,25 +55,25 @@ public class BlueMapAPIImpl extends BlueMapAPI {
|
|||||||
|
|
||||||
private static final String IMAGE_ROOT_PATH = "images";
|
private static final String IMAGE_ROOT_PATH = "images";
|
||||||
|
|
||||||
public Plugin blueMap;
|
public Plugin plugin;
|
||||||
public RenderAPIImpl renderer;
|
public RenderAPIImpl renderer;
|
||||||
|
|
||||||
public Map<UUID, BlueMapWorldImpl> worlds;
|
public Map<UUID, BlueMapWorldImpl> worlds;
|
||||||
public Map<String, BlueMapMapImpl> maps;
|
public Map<String, BlueMapMapImpl> maps;
|
||||||
|
|
||||||
public BlueMapAPIImpl(Plugin blueMap) {
|
public BlueMapAPIImpl(Plugin plugin) {
|
||||||
this.blueMap = blueMap;
|
this.plugin = plugin;
|
||||||
|
|
||||||
this.renderer = new RenderAPIImpl(this, blueMap.getRenderManager());
|
this.renderer = new RenderAPIImpl(this, plugin.getRenderManager());
|
||||||
|
|
||||||
worlds = new HashMap<>();
|
worlds = new HashMap<>();
|
||||||
for (World world : blueMap.getWorlds()) {
|
for (World world : plugin.getWorlds()) {
|
||||||
BlueMapWorldImpl w = new BlueMapWorldImpl(this, world);
|
BlueMapWorldImpl w = new BlueMapWorldImpl(this, world);
|
||||||
worlds.put(w.getUuid(), w);
|
worlds.put(w.getUuid(), w);
|
||||||
}
|
}
|
||||||
|
|
||||||
maps = new HashMap<>();
|
maps = new HashMap<>();
|
||||||
for (MapType map : blueMap.getMapTypes()) {
|
for (MapType map : plugin.getMapTypes()) {
|
||||||
BlueMapMapImpl m = new BlueMapMapImpl(this, map);
|
BlueMapMapImpl m = new BlueMapMapImpl(this, map);
|
||||||
maps.put(m.getId(), m);
|
maps.put(m.getId(), m);
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ public RenderAPIImpl getRenderAPI() {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MarkerAPIImpl getMarkerAPI() throws IOException {
|
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
|
@Override
|
||||||
@ -104,15 +104,9 @@ public String createImage(BufferedImage image, String path) throws IOException {
|
|||||||
path = path.replaceAll("[^a-zA-Z_\\.\\-\\/]", "_");
|
path = path.replaceAll("[^a-zA-Z_\\.\\-\\/]", "_");
|
||||||
String separator = FileSystems.getDefault().getSeparator();
|
String separator = FileSystems.getDefault().getSeparator();
|
||||||
|
|
||||||
Path webRoot = blueMap.getMainConfig().getWebRoot().toAbsolutePath();
|
Path webRoot = plugin.getRenderConfig().getWebRoot().toPath().toAbsolutePath();
|
||||||
Path webDataRoot = blueMap.getMainConfig().getWebDataPath().toAbsolutePath();
|
Path webDataRoot = webRoot.resolve("data");
|
||||||
|
Path imagePath = webDataRoot.resolve(Paths.get(IMAGE_ROOT_PATH, path.replace("/", separator) + ".png")).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();
|
|
||||||
}
|
|
||||||
|
|
||||||
File imageFile = imagePath.toFile();
|
File imageFile = imagePath.toFile();
|
||||||
imageFile.getParentFile().mkdirs();
|
imageFile.getParentFile().mkdirs();
|
||||||
|
@ -31,9 +31,9 @@
|
|||||||
|
|
||||||
import com.google.gson.stream.JsonWriter;
|
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.Player;
|
||||||
import de.bluecolored.bluemap.common.plugin.serverinterface.ServerInterface;
|
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.HttpRequest;
|
||||||
import de.bluecolored.bluemap.core.webserver.HttpRequestHandler;
|
import de.bluecolored.bluemap.core.webserver.HttpRequestHandler;
|
||||||
import de.bluecolored.bluemap.core.webserver.HttpResponse;
|
import de.bluecolored.bluemap.core.webserver.HttpResponse;
|
||||||
@ -45,9 +45,9 @@ public class LiveAPIRequestHandler implements HttpRequestHandler {
|
|||||||
private Map<String, HttpRequestHandler> liveAPIRequests;
|
private Map<String, HttpRequestHandler> liveAPIRequests;
|
||||||
private ServerInterface server;
|
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.server = server;
|
||||||
this.notFoundHandler = notFoundHandler;
|
this.notFoundHandler = notFoundHandler;
|
||||||
|
|
||||||
@ -63,7 +63,13 @@ public LiveAPIRequestHandler(ServerInterface server, LiveAPISettings config, Htt
|
|||||||
public HttpResponse handle(HttpRequest request) {
|
public HttpResponse handle(HttpRequest request) {
|
||||||
if (!config.isLiveUpdatesEnabled()) return this.notFoundHandler.handle(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);
|
if (handler != null) return handler.handle(request);
|
||||||
|
|
||||||
return this.notFoundHandler.handle(request);
|
return this.notFoundHandler.handle(request);
|
||||||
|
@ -30,43 +30,32 @@
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import de.bluecolored.bluemap.common.BlueMapService;
|
||||||
|
|
||||||
import com.flowpowered.math.vector.Vector2i;
|
|
||||||
|
|
||||||
import de.bluecolored.bluemap.common.BlueMapWebServer;
|
|
||||||
import de.bluecolored.bluemap.common.MapType;
|
import de.bluecolored.bluemap.common.MapType;
|
||||||
|
import de.bluecolored.bluemap.common.MissingResourcesException;
|
||||||
import de.bluecolored.bluemap.common.RenderManager;
|
import de.bluecolored.bluemap.common.RenderManager;
|
||||||
import de.bluecolored.bluemap.common.api.BlueMapAPIImpl;
|
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.serverinterface.ServerInterface;
|
||||||
import de.bluecolored.bluemap.common.plugin.skins.PlayerSkinUpdater;
|
import de.bluecolored.bluemap.common.plugin.skins.PlayerSkinUpdater;
|
||||||
import de.bluecolored.bluemap.core.config.ConfigManager;
|
import de.bluecolored.bluemap.core.BlueMap;
|
||||||
import de.bluecolored.bluemap.core.config.MainConfig;
|
import de.bluecolored.bluemap.core.config.CoreConfig;
|
||||||
import de.bluecolored.bluemap.core.config.MainConfig.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.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.mca.MCAWorld;
|
|
||||||
import de.bluecolored.bluemap.core.metrics.Metrics;
|
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.ParseResourceException;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
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.webserver.HttpRequestHandler;
|
||||||
import de.bluecolored.bluemap.core.world.SlicedWorld;
|
import de.bluecolored.bluemap.core.webserver.WebServer;
|
||||||
import de.bluecolored.bluemap.core.world.World;
|
import de.bluecolored.bluemap.core.world.World;
|
||||||
|
|
||||||
public class Plugin {
|
public class Plugin {
|
||||||
@ -74,173 +63,80 @@ public class Plugin {
|
|||||||
public static final String PLUGIN_ID = "bluemap";
|
public static final String PLUGIN_ID = "bluemap";
|
||||||
public static final String PLUGIN_NAME = "BlueMap";
|
public static final String PLUGIN_NAME = "BlueMap";
|
||||||
|
|
||||||
private BlueMapAPIImpl api;
|
|
||||||
|
|
||||||
private String implementationType;
|
private String implementationType;
|
||||||
|
|
||||||
private ServerInterface serverInterface;
|
private ServerInterface serverInterface;
|
||||||
|
|
||||||
private MainConfig config;
|
private BlueMapService blueMap;
|
||||||
private ResourcePack resourcePack;
|
private BlueMapAPIImpl api;
|
||||||
|
|
||||||
private Map<UUID, World> worlds;
|
private Map<UUID, World> worlds;
|
||||||
private Map<String, MapType> maps;
|
private Map<String, MapType> maps;
|
||||||
|
|
||||||
private MapUpdateHandler updateHandler;
|
|
||||||
private PlayerSkinUpdater skinUpdater;
|
|
||||||
|
|
||||||
private RenderManager renderManager;
|
private RenderManager renderManager;
|
||||||
private BlueMapWebServer webServer;
|
private WebServer webServer;
|
||||||
|
|
||||||
private Thread periodicalSaveThread;
|
private Thread periodicalSaveThread;
|
||||||
private Thread metricsThread;
|
private Thread metricsThread;
|
||||||
|
|
||||||
|
private PluginConfig pluginConfig;
|
||||||
|
private MapUpdateHandler updateHandler;
|
||||||
|
private PlayerSkinUpdater skinUpdater;
|
||||||
|
|
||||||
private boolean loaded = false;
|
private boolean loaded = false;
|
||||||
|
|
||||||
public Plugin(String implementationType, ServerInterface serverInterface) {
|
public Plugin(String implementationType, ServerInterface serverInterface) {
|
||||||
this.implementationType = implementationType.toLowerCase();
|
this.implementationType = implementationType.toLowerCase();
|
||||||
|
|
||||||
this.serverInterface = serverInterface;
|
this.serverInterface = serverInterface;
|
||||||
|
|
||||||
this.maps = new HashMap<>();
|
|
||||||
this.worlds = new HashMap<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void load() throws IOException, ParseResourceException {
|
public synchronized void load() throws IOException, ParseResourceException {
|
||||||
if (loaded) return;
|
if (loaded) return;
|
||||||
unload(); //ensure nothing is left running (from a failed load or something)
|
unload(); //ensure nothing is left running (from a failed load or something)
|
||||||
|
|
||||||
|
blueMap = new BlueMapService(serverInterface);
|
||||||
|
|
||||||
//load configs
|
//load configs
|
||||||
URL defaultSpongeConfig = Plugin.class.getResource("/bluemap-" + implementationType + ".conf");
|
CoreConfig coreConfig = blueMap.getCoreConfig();
|
||||||
URL spongeConfigDefaults = Plugin.class.getResource("/bluemap-" + implementationType + "-defaults.conf");
|
RenderConfig renderConfig = blueMap.getRenderConfig();
|
||||||
ConfigManager configManager = new ConfigManager(serverInterface.getConfigFolder(), defaultSpongeConfig, spongeConfigDefaults);
|
WebServerConfig webServerConfig = blueMap.getWebServerConfig();
|
||||||
configManager.loadMainConfig();
|
|
||||||
config = configManager.getMainConfig();
|
|
||||||
|
|
||||||
//load resources
|
//load plugin config
|
||||||
File defaultResourceFile = config.getDataPath().resolve("minecraft-client-" + ResourcePack.MINECRAFT_CLIENT_VERSION + ".jar").toFile();
|
pluginConfig = new PluginConfig(blueMap.getConfigManager().loadOrCreate(
|
||||||
File resourceExtensionsFile = config.getDataPath().resolve("resourceExtensions.zip").toFile();
|
new File(serverInterface.getConfigFolder(), "plugin.conf"),
|
||||||
File textureExportFile = config.getWebDataPath().resolve("textures.json").toFile();
|
Plugin.class.getResource("/plugin.conf"),
|
||||||
|
Plugin.class.getResource("/plugin-defaults.conf"),
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
));
|
||||||
|
|
||||||
if (!defaultResourceFile.exists()) {
|
//try load resources
|
||||||
if (config.isDownloadAccepted()) {
|
|
||||||
|
|
||||||
//download file
|
|
||||||
try {
|
try {
|
||||||
Logger.global.logInfo("Downloading " + ResourcePack.MINECRAFT_CLIENT_URL + " to " + defaultResourceFile + " ...");
|
blueMap.getResourcePack();
|
||||||
ResourcePack.downloadDefaultResource(defaultResourceFile);
|
} catch (MissingResourcesException ex) {
|
||||||
} catch (IOException e) {
|
|
||||||
Logger.global.logError("Failed to download resources!", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Logger.global.logWarning("BlueMap is missing important resources!");
|
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("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) {}
|
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");
|
Logger.global.logInfo("If you have changed the config you can simply reload the plugin using: /bluemap reload");
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resourceExtensionsFile.delete();
|
|
||||||
FileUtils.copyURLToFile(Plugin.class.getResource("/resourceExtensions.zip"), resourceExtensionsFile, 10000, 10000);
|
|
||||||
|
|
||||||
//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<File> 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();
|
|
||||||
|
|
||||||
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();
|
unload();
|
||||||
return;
|
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
|
//initialize render manager
|
||||||
renderManager = new RenderManager(config.getRenderThreadCount());
|
renderManager = new RenderManager(coreConfig.getRenderThreadCount());
|
||||||
renderManager.start();
|
renderManager.start();
|
||||||
|
|
||||||
//load render-manager state
|
//load render-manager state
|
||||||
try {
|
try {
|
||||||
File saveFile = config.getDataPath().resolve("rmstate").toFile();
|
File saveFile = getRenderManagerSaveFile();
|
||||||
saveFile.getParentFile().mkdirs();
|
|
||||||
if (saveFile.exists()) {
|
if (saveFile.exists()) {
|
||||||
try (DataInputStream in = new DataInputStream(new GZIPInputStream(new FileInputStream(saveFile)))) {
|
try (DataInputStream in = new DataInputStream(new GZIPInputStream(new FileInputStream(saveFile)))) {
|
||||||
renderManager.readState(in, getMapTypes());
|
renderManager.readState(in, getMapTypes());
|
||||||
@ -272,38 +168,31 @@ public synchronized void load() throws IOException, ParseResourceException {
|
|||||||
this.updateHandler = new MapUpdateHandler(this);
|
this.updateHandler = new MapUpdateHandler(this);
|
||||||
serverInterface.registerListener(updateHandler);
|
serverInterface.registerListener(updateHandler);
|
||||||
|
|
||||||
|
//update webapp and settings
|
||||||
|
blueMap.createOrUpdateWebApp(false);
|
||||||
|
blueMap.updateWebAppSettings();
|
||||||
|
|
||||||
//start skin updater
|
//start skin updater
|
||||||
if (config.isLiveUpdatesEnabled()) {
|
if (pluginConfig.isLiveUpdatesEnabled()) {
|
||||||
this.skinUpdater = new PlayerSkinUpdater(config.getWebRoot().resolve("assets").resolve("playerheads").toFile());
|
this.skinUpdater = new PlayerSkinUpdater(new File(renderConfig.getWebRoot(), "assets" + File.separator + "playerheads"));
|
||||||
serverInterface.registerListener(skinUpdater);
|
serverInterface.registerListener(skinUpdater);
|
||||||
}
|
}
|
||||||
|
|
||||||
//create/update webfiles
|
//create and start webserver
|
||||||
WebFilesManager webFilesManager = new WebFilesManager(config.getWebRoot());
|
if (webServerConfig.isWebserverEnabled()) {
|
||||||
if (webFilesManager.needsUpdate()) {
|
HttpRequestHandler requestHandler = new FileRequestHandler(webServerConfig.getWebRoot().toPath(), "BlueMap v" + BlueMap.VERSION);
|
||||||
webFilesManager.updateFiles();
|
|
||||||
|
//inject live api if enabled
|
||||||
|
if (pluginConfig.isLiveUpdatesEnabled()) {
|
||||||
|
requestHandler = new LiveAPIRequestHandler(serverInterface, pluginConfig, requestHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSettings webSettings = new WebSettings(config.getWebDataPath().resolve("settings.json").toFile());
|
webServer = new WebServer(
|
||||||
webSettings.set(config.isUseCookies(), "useCookies");
|
webServerConfig.getWebserverPort(),
|
||||||
webSettings.setAllMapsEnabled(false);
|
webServerConfig.getWebserverMaxConnections(),
|
||||||
for (MapType map : maps.values()) {
|
webServerConfig.getWebserverBindAdress(),
|
||||||
webSettings.setMapEnabled(true, map.getId());
|
requestHandler
|
||||||
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();
|
|
||||||
webServer.start();
|
webServer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,7 +202,8 @@ public synchronized void load() throws IOException, ParseResourceException {
|
|||||||
Thread.sleep(TimeUnit.MINUTES.toMillis(1));
|
Thread.sleep(TimeUnit.MINUTES.toMillis(1));
|
||||||
|
|
||||||
while (true) {
|
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));
|
Thread.sleep(TimeUnit.MINUTES.toMillis(30));
|
||||||
}
|
}
|
||||||
} catch (InterruptedException ex){
|
} catch (InterruptedException ex){
|
||||||
@ -369,25 +259,27 @@ public synchronized void unload() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//save renders
|
//save renders
|
||||||
|
if (maps != null) {
|
||||||
for (MapType map : maps.values()) {
|
for (MapType map : maps.values()) {
|
||||||
map.getTileRenderer().save();
|
map.getTileRenderer().save();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//clear resources and configs
|
//clear resources and configs
|
||||||
|
blueMap = null;
|
||||||
|
worlds = null;
|
||||||
|
maps = null;
|
||||||
renderManager = null;
|
renderManager = null;
|
||||||
webServer = null;
|
webServer = null;
|
||||||
updateHandler = null;
|
updateHandler = null;
|
||||||
resourcePack = null;
|
pluginConfig = null;
|
||||||
config = null;
|
|
||||||
maps.clear();
|
|
||||||
worlds.clear();
|
|
||||||
|
|
||||||
loaded = false;
|
loaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveRenderManagerState() throws IOException {
|
public void saveRenderManagerState() throws IOException {
|
||||||
File saveFile = config.getDataPath().resolve("rmstate").toFile();
|
File saveFile = getRenderManagerSaveFile();
|
||||||
saveFile.getParentFile().mkdirs();
|
|
||||||
if (saveFile.exists()) saveFile.delete();
|
if (saveFile.exists()) saveFile.delete();
|
||||||
saveFile.createNewFile();
|
saveFile.createNewFile();
|
||||||
|
|
||||||
@ -405,12 +297,24 @@ public ServerInterface getServerInterface() {
|
|||||||
return serverInterface;
|
return serverInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MainConfig getMainConfig() {
|
public CoreConfig getCoreConfig() throws IOException {
|
||||||
return config;
|
return blueMap.getCoreConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourcePack getResourcePack() {
|
public RenderConfig getRenderConfig() throws IOException {
|
||||||
return resourcePack;
|
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){
|
public World getWorld(UUID uuid){
|
||||||
@ -429,11 +333,20 @@ public RenderManager getRenderManager() {
|
|||||||
return renderManager;
|
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() {
|
public MapUpdateHandler getUpdateHandler() {
|
||||||
return updateHandler;
|
return updateHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlueMapWebServer getWebServer() {
|
public WebServer getWebServer() {
|
||||||
return webServer;
|
return webServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* 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<String> 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<String> getHiddenGameModes() {
|
||||||
|
return this.hiddenGameModes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHideInvisible() {
|
||||||
|
return this.hideInvisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHideSneaking() {
|
||||||
|
return this.hideSneaking;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,7 +19,7 @@ dependencies {
|
|||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
from(sourceSets.main.resources.srcDirs) {
|
||||||
include 'core.json'
|
include 'de/bluecolored/bluemap/version.json'
|
||||||
|
|
||||||
expand (
|
expand (
|
||||||
version: project.version
|
version: project.version
|
||||||
@ -54,7 +54,7 @@ task webpackWebroot(type: NpmTask) {
|
|||||||
task zipWebroot(type: Zip) {
|
task zipWebroot(type: Zip) {
|
||||||
from fileTree('build/generated/webroot/')
|
from fileTree('build/generated/webroot/')
|
||||||
archiveName 'webroot.zip'
|
archiveName 'webroot.zip'
|
||||||
destinationDir(file('src/main/resources/'))
|
destinationDir(file('src/main/resources/de/bluecolored/bluemap/'))
|
||||||
outputs.upToDateWhen { false }
|
outputs.upToDateWhen { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ task buildWebroot {
|
|||||||
task zipResourceExtensions(type: Zip) {
|
task zipResourceExtensions(type: Zip) {
|
||||||
from fileTree('src/main/resourceExtensions')
|
from fileTree('src/main/resourceExtensions')
|
||||||
archiveName 'resourceExtensions.zip'
|
archiveName 'resourceExtensions.zip'
|
||||||
destinationDir(file('src/main/resources/'))
|
destinationDir(file('src/main/resources/de/bluecolored/bluemap/'))
|
||||||
outputs.upToDateWhen { false }
|
outputs.upToDateWhen { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,9 +35,9 @@ public class BlueMap {
|
|||||||
static {
|
static {
|
||||||
String version = "DEV";
|
String version = "DEV";
|
||||||
try {
|
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) {
|
} 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";
|
if (version.equals("${version}")) version = "DEV";
|
||||||
|
@ -37,6 +37,8 @@
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.BlueMap;
|
import de.bluecolored.bluemap.core.BlueMap;
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
|
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));
|
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 BlockIdConfig blockIdConfig;
|
||||||
private BlockPropertiesConfig blockPropertiesConfig;
|
private BlockPropertiesConfig blockPropertiesConfig;
|
||||||
private BiomeConfig biomeConfig;
|
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 configFile The config file to load
|
||||||
* @param defaultMainConfig The default main-configuration file, used if a new configuration is generated
|
* @param defaultConfig The default config that is used as a template if the config file does not exist (can be null)
|
||||||
* @param mainConfigDefaultValues The default values that are used for the main-configuration file (if they are undefined)
|
* @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) {
|
public ConfigurationNode loadOrCreate(File configFile, URL defaultConfig, URL defaultValues, boolean usePlaceholders, boolean generateEmptyConfig) throws IOException {
|
||||||
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 {
|
|
||||||
|
|
||||||
ConfigurationNode configNode;
|
ConfigurationNode configNode;
|
||||||
if (!configFile.exists()) {
|
if (!configFile.exists()) {
|
||||||
@ -255,6 +122,103 @@ private ConfigurationNode loadOrCreate(File configFile, URL defaultConfig, URL d
|
|||||||
return configNode;
|
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 {
|
private File makeAutogen(File file) throws IOException {
|
||||||
File autogenFile = file.getCanonicalFile().toPath().getParent().resolve("missing-configs").resolve(file.getName()).toFile();
|
File autogenFile = file.getCanonicalFile().toPath().getParent().resolve("missing-configs").resolve(file.getName()).toFile();
|
||||||
autogenFile.getParentFile().mkdirs();
|
autogenFile.getParentFile().mkdirs();
|
||||||
@ -281,4 +245,12 @@ private ConfigurationLoader<? extends ConfigurationNode> getLoader(File file){
|
|||||||
else return HoconConfigurationLoader.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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,389 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
||||||
*
|
|
||||||
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
||||||
* 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<MapConfig> mapConfigs = new ArrayList<>();
|
|
||||||
|
|
||||||
private boolean liveUpdatesEnabled = false;
|
|
||||||
private Collection<String> 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<MapConfig> getMapConfigs(){
|
|
||||||
return mapConfigs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLiveUpdatesEnabled() {
|
|
||||||
return this.liveUpdatesEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<String> 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!");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -24,19 +24,49 @@
|
|||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.core.config;
|
package de.bluecolored.bluemap.core.config;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class OutdatedConfigException extends IOException {
|
import ninja.leaping.configurate.ConfigurationNode;
|
||||||
private static final long serialVersionUID = -942567050110586060L;
|
|
||||||
|
|
||||||
public OutdatedConfigException() {}
|
public class RenderConfig {
|
||||||
|
|
||||||
public OutdatedConfigException(String message) {
|
private File webRoot = new File("web");
|
||||||
super(message);
|
private boolean useCookies;
|
||||||
|
private List<MapConfig> 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 OutdatedConfigException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public File getWebRoot() {
|
||||||
|
if (!webRoot.exists()) webRoot.mkdirs();
|
||||||
|
return webRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUseCookies() {
|
||||||
|
return useCookies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MapConfig> getMapConfigs(){
|
||||||
|
return mapConfigs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -84,6 +84,10 @@ public HttpResponse handle(HttpRequest request) {
|
|||||||
private HttpResponse generateResponse(HttpRequest request) {
|
private HttpResponse generateResponse(HttpRequest request) {
|
||||||
String path = 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);
|
||||||
|
|
||||||
Path filePath = webRoot;
|
Path filePath = webRoot;
|
||||||
try {
|
try {
|
||||||
filePath = webRoot.resolve(path);
|
filePath = webRoot.resolve(path);
|
||||||
@ -102,6 +106,13 @@ private HttpResponse generateResponse(HttpRequest request) {
|
|||||||
|
|
||||||
File file = filePath.toFile();
|
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()){
|
if (!file.exists() || file.isDirectory()){
|
||||||
file = new File(filePath.toString() + ".gz");
|
file = new File(filePath.toString() + ".gz");
|
||||||
isDeflated = true;
|
isDeflated = true;
|
||||||
@ -164,7 +175,7 @@ private HttpResponse generateResponse(HttpRequest request) {
|
|||||||
|
|
||||||
//add content type header
|
//add content type header
|
||||||
String filetype = file.getName().toString();
|
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('.');
|
int pointIndex = filetype.lastIndexOf('.');
|
||||||
if (pointIndex >= 0) filetype = filetype.substring(pointIndex + 1);
|
if (pointIndex >= 0) filetype = filetype.substring(pointIndex + 1);
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipFile;
|
import java.util.zip.ZipFile;
|
||||||
@ -36,20 +35,20 @@
|
|||||||
|
|
||||||
public class WebFilesManager {
|
public class WebFilesManager {
|
||||||
|
|
||||||
private Path webRoot;
|
private File webRoot;
|
||||||
|
|
||||||
public WebFilesManager(Path webRoot) {
|
public WebFilesManager(File webRoot) {
|
||||||
this.webRoot = webRoot;
|
this.webRoot = webRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean needsUpdate() {
|
public boolean needsUpdate() {
|
||||||
if (!webRoot.resolve("index.html").toFile().exists()) return true;
|
if (!new File(webRoot, "index.html").exists()) return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateFiles() throws IOException {
|
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);
|
File tempFile = File.createTempFile("bluemap_webroot_extraction", null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -58,9 +57,9 @@ public void updateFiles() throws IOException {
|
|||||||
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||||
while(entries.hasMoreElements()) {
|
while(entries.hasMoreElements()) {
|
||||||
ZipEntry zipEntry = entries.nextElement();
|
ZipEntry zipEntry = entries.nextElement();
|
||||||
if (zipEntry.isDirectory()) webRoot.resolve(zipEntry.getName()).toFile().mkdirs();
|
if (zipEntry.isDirectory()) new File(webRoot, zipEntry.getName()).mkdirs();
|
||||||
else {
|
else {
|
||||||
File target = webRoot.resolve(zipEntry.getName()).toFile();
|
File target = new File(webRoot, zipEntry.getName());
|
||||||
FileUtils.copyInputStreamToFile(zipFile.getInputStream(zipEntry), target);
|
FileUtils.copyInputStreamToFile(zipFile.getInputStream(zipEntry), target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
import com.flowpowered.math.vector.Vector2i;
|
import com.flowpowered.math.vector.Vector2i;
|
||||||
import com.flowpowered.math.vector.Vector3f;
|
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.render.TileRenderer;
|
||||||
import de.bluecolored.bluemap.core.util.MathUtils;
|
import de.bluecolored.bluemap.core.util.MathUtils;
|
||||||
import de.bluecolored.bluemap.core.world.World;
|
import de.bluecolored.bluemap.core.world.World;
|
||||||
|
@ -58,6 +58,7 @@ public class HttpRequest {
|
|||||||
|
|
||||||
private String path = null;
|
private String path = null;
|
||||||
private Map<String, String> getParams = null;
|
private Map<String, String> getParams = null;
|
||||||
|
private String getParamString = null;
|
||||||
|
|
||||||
public HttpRequest(String method, String adress, String version, Map<String, Set<String>> header) {
|
public HttpRequest(String method, String adress, String version, Map<String, Set<String>> header) {
|
||||||
this.method = method;
|
this.method = method;
|
||||||
@ -120,15 +121,20 @@ public Map<String, String> getGETParams() {
|
|||||||
return Collections.unmodifiableMap(getParams);
|
return Collections.unmodifiableMap(getParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getGETParamString() {
|
||||||
|
if (getParamString == null) parseAdress();
|
||||||
|
return getParamString;
|
||||||
|
}
|
||||||
|
|
||||||
private void parseAdress() {
|
private void parseAdress() {
|
||||||
String adress = this.adress;
|
String adress = this.adress;
|
||||||
if (adress.isEmpty()) adress = "/";
|
if (adress.isEmpty()) adress = "/";
|
||||||
String[] adressParts = adress.split("\\?", 2);
|
String[] adressParts = adress.split("\\?", 2);
|
||||||
String path = adressParts[0];
|
String path = adressParts[0];
|
||||||
String getParamString = adressParts.length > 1 ? adressParts[1] : "";
|
this.getParamString = adressParts.length > 1 ? adressParts[1] : "";
|
||||||
|
|
||||||
Map<String, String> getParams = new HashMap<>();
|
Map<String, String> getParams = new HashMap<>();
|
||||||
for (String getParam : getParamString.split("&")){
|
for (String getParam : this.getParamString.split("&")){
|
||||||
if (getParam.isEmpty()) continue;
|
if (getParam.isEmpty()) continue;
|
||||||
String[] kv = getParam.split("=", 2);
|
String[] kv = getParam.split("=", 2);
|
||||||
String key = kv[0];
|
String key = kv[0];
|
||||||
@ -136,10 +142,6 @@ private void parseAdress() {
|
|||||||
getParams.put(key, value);
|
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.path = path;
|
||||||
this.getParams = getParams;
|
this.getParams = getParams;
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
@ -0,0 +1,4 @@
|
|||||||
|
accept-download: false
|
||||||
|
renderThreadCount: -2
|
||||||
|
metrics: true
|
||||||
|
data: "bluemap"
|
@ -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: <data>/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"
|
@ -0,0 +1,5 @@
|
|||||||
|
liveUpdates: true
|
||||||
|
skinDownload: true
|
||||||
|
hiddenGameModes: []
|
||||||
|
hideInvisible: true
|
||||||
|
hideSneaking: false
|
@ -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
|
@ -0,0 +1,3 @@
|
|||||||
|
webroot: "bluemap/web"
|
||||||
|
useCookies: true
|
||||||
|
maps: []
|
@ -1,62 +1,16 @@
|
|||||||
## ##
|
## ##
|
||||||
## BlueMap ##
|
## BlueMap ##
|
||||||
## ##
|
## Render-Config ##
|
||||||
## by Blue (Lukas Rieger) ##
|
|
||||||
## http://bluecolored.de/ ##
|
|
||||||
## ##
|
## ##
|
||||||
|
|
||||||
# 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),
|
# The folder (webroot) where the map-data and web-application files will be saved.
|
||||||
# you confirm that you own a license to Minecraft (Java Edition)
|
# Default is "bluemap/web"
|
||||||
# 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: <data>/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.
|
|
||||||
webroot: "bluemap/web"
|
webroot: "bluemap/web"
|
||||||
|
|
||||||
# Unncomment this to override the path where bluemap stores the data-files.
|
|
||||||
# Default is "<webroot>/data"
|
|
||||||
#webdata: "path/to/data/folder"
|
|
||||||
|
|
||||||
# If the web-application should use cookies to save the configurations of a user.
|
# If the web-application should use cookies to save the configurations of a user.
|
||||||
|
# Default is true
|
||||||
useCookies: 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.
|
# This is an array with multiple configured maps.
|
||||||
# You can define multiple maps, for different worlds with different render-settings here
|
# You can define multiple maps, for different worlds with different render-settings here
|
||||||
maps: [
|
maps: [
|
||||||
@ -123,6 +77,16 @@ maps: [
|
|||||||
# Changing this value requires a re-render of the map.
|
# Changing this value requires a re-render of the map.
|
||||||
# Default is true
|
# Default is true
|
||||||
useCompression: 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
|
# 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
|
|
||||||
}
|
|
@ -0,0 +1,4 @@
|
|||||||
|
enabled: true
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
port: 8100
|
||||||
|
maxConnectionCount: 100
|
@ -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
|
@ -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
|
|
||||||
}
|
|
@ -0,0 +1,4 @@
|
|||||||
|
accept-download: false
|
||||||
|
renderThreadCount: -2
|
||||||
|
metrics: true
|
||||||
|
data: "bluemap"
|
@ -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: <data>/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"
|
@ -0,0 +1,5 @@
|
|||||||
|
liveUpdates: true
|
||||||
|
skinDownload: true
|
||||||
|
hiddenGameModes: []
|
||||||
|
hideInvisible: true
|
||||||
|
hideSneaking: false
|
@ -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
|
@ -0,0 +1,3 @@
|
|||||||
|
webroot: "bluemap/web"
|
||||||
|
useCookies: true
|
||||||
|
maps: []
|
@ -1,68 +1,16 @@
|
|||||||
## ##
|
## ##
|
||||||
## BlueMap ##
|
## BlueMap ##
|
||||||
## ##
|
## Render-Config ##
|
||||||
## by Blue (Lukas Rieger) ##
|
|
||||||
## http://bluecolored.de/ ##
|
|
||||||
## ##
|
## ##
|
||||||
|
|
||||||
# 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),
|
# The folder (webroot) where the map-data and web-application files will be saved.
|
||||||
# you confirm that you own a license to Minecraft (Java Edition)
|
# Default is "bluemap/web"
|
||||||
# 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: <data>/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.
|
|
||||||
webroot: "bluemap/web"
|
webroot: "bluemap/web"
|
||||||
|
|
||||||
# Unncomment this to override the path where bluemap stores the data-files.
|
|
||||||
# Default is "<webroot>/data"
|
|
||||||
#webdata: "path/to/data/folder"
|
|
||||||
|
|
||||||
# If the web-application should use cookies to save the configurations of a user.
|
# If the web-application should use cookies to save the configurations of a user.
|
||||||
# Default is true
|
# Default is true
|
||||||
useCookies: 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.
|
# This is an array with multiple configured maps.
|
||||||
# You can define multiple maps, for different worlds with different render-settings here
|
# You can define multiple maps, for different worlds with different render-settings here
|
||||||
maps: [
|
maps: [
|
||||||
@ -129,6 +77,16 @@ maps: [
|
|||||||
# Changing this value requires a re-render of the map.
|
# Changing this value requires a re-render of the map.
|
||||||
# Default is true
|
# Default is true
|
||||||
useCompression: 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
|
# 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
|
|
||||||
}
|
|
@ -0,0 +1,4 @@
|
|||||||
|
enabled: true
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
port: 8100
|
||||||
|
maxConnectionCount: 100
|
@ -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
|
@ -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
|
|
||||||
}
|
|
@ -0,0 +1,4 @@
|
|||||||
|
accept-download: false
|
||||||
|
renderThreadCount: -2
|
||||||
|
metrics: false
|
||||||
|
data: "bluemap"
|
@ -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: <data>/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"
|
@ -0,0 +1,5 @@
|
|||||||
|
liveUpdates: true
|
||||||
|
skinDownload: false
|
||||||
|
hiddenGameModes: []
|
||||||
|
hideInvisible: true
|
||||||
|
hideSneaking: false
|
@ -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
|
@ -0,0 +1,3 @@
|
|||||||
|
webroot: "bluemap/web"
|
||||||
|
useCookies: true
|
||||||
|
maps: []
|
@ -1,68 +1,16 @@
|
|||||||
## ##
|
## ##
|
||||||
## BlueMap ##
|
## BlueMap ##
|
||||||
## ##
|
## Render-Config ##
|
||||||
## by Blue (Lukas Rieger) ##
|
|
||||||
## http://bluecolored.de/ ##
|
|
||||||
## ##
|
## ##
|
||||||
|
|
||||||
# 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),
|
# The folder (webroot) where the map-data and web-application files will be saved.
|
||||||
# you confirm that you own a license to Minecraft (Java Edition)
|
# Default is "bluemap/web"
|
||||||
# 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: <data>/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.
|
|
||||||
webroot: "bluemap/web"
|
webroot: "bluemap/web"
|
||||||
|
|
||||||
# Unncomment this to override the path where bluemap stores the data-files.
|
|
||||||
# Default is "<webroot>/data"
|
|
||||||
#webdata: "path/to/data/folder"
|
|
||||||
|
|
||||||
# If the web-application should use cookies to save the configurations of a user.
|
# If the web-application should use cookies to save the configurations of a user.
|
||||||
# Default is true
|
# Default is true
|
||||||
useCookies: 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.
|
# This is an array with multiple configured maps.
|
||||||
# You can define multiple maps, for different worlds with different render-settings here
|
# You can define multiple maps, for different worlds with different render-settings here
|
||||||
maps: [
|
maps: [
|
||||||
@ -129,6 +77,16 @@ maps: [
|
|||||||
# Changing this value requires a re-render of the map.
|
# Changing this value requires a re-render of the map.
|
||||||
# Default is true
|
# Default is true
|
||||||
useCompression: 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
|
# 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
|
|
||||||
}
|
|
@ -0,0 +1,4 @@
|
|||||||
|
enabled: true
|
||||||
|
webroot: "bluemap/web"
|
||||||
|
port: 8100
|
||||||
|
maxConnectionCount: 100
|
@ -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
|
@ -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.
|
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.
|
See below for a list of what is planned for future releases.
|
||||||
|
|
||||||
|
![screenshot](https://bluecolored.de/paste/BlueMapScreenshot.jpg)
|
||||||
|
|
||||||
### Download
|
### Download
|
||||||
You can choose a version and download BlueMap from [here](https://github.com/BlueMap-Minecraft/BlueMap/releases).
|
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
|
### 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.)*
|
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 more tile-entities (banners, shulker-chests, etc..)
|
||||||
- render entities (armor-stands, item-frames, maybe even cows and such..)
|
- render entities (armor-stands, item-frames, maybe even cows and such..)
|
||||||
- free-flight-controls
|
- free-flight-controls
|
||||||
|
@ -47,10 +47,10 @@ allprojects {
|
|||||||
license {
|
license {
|
||||||
header rootProject.file('HEADER')
|
header rootProject.file('HEADER')
|
||||||
excludes([
|
excludes([
|
||||||
'*.conf',
|
'**/*.conf',
|
||||||
'*.yml',
|
'**/*.yml',
|
||||||
'*.zip',
|
'**/*.zip',
|
||||||
'*.json'
|
'**/*.json'
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user