Reorganize config, add render-bounds and make some optimizations

This commit is contained in:
Blue (Lukas Rieger) 2020-01-10 17:54:36 +01:00
parent dfbbf7d690
commit 1af2a8c86d
25 changed files with 639 additions and 324 deletions

View File

@ -58,6 +58,7 @@ import de.bluecolored.bluemap.core.config.MainConfig.MapConfig;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.mca.MCAWorld;
import de.bluecolored.bluemap.core.metrics.Metrics;
import de.bluecolored.bluemap.core.render.RenderSettings;
import de.bluecolored.bluemap.core.render.TileRenderer;
import de.bluecolored.bluemap.core.render.hires.HiresModelManager;
import de.bluecolored.bluemap.core.render.lowres.LowresModelManager;
@ -66,6 +67,7 @@ import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
import de.bluecolored.bluemap.core.web.BlueMapWebServer;
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;
public class BlueMapCLI {
@ -93,13 +95,18 @@ public class BlueMapCLI {
Map<String, MapType> maps = new HashMap<>();
for (MapConfig mapConfig : config.getMapConfigs()) {
File mapPath = new File(mapConfig.getWorldPath());
if (!mapPath.exists() || !mapPath.isDirectory()) {
throw new IOException("Save folder '" + mapPath + "' does not exist or is not a directory!");
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(mapPath.toPath(), UUID.randomUUID(), configManager.getBlockIdConfig(), configManager.getBlockPropertiesConfig(), configManager.getBiomeConfig());
World world = MCAWorld.load(worldFolder.toPath(), UUID.randomUUID(), configManager.getBlockIdConfig(), configManager.getBlockPropertiesConfig(), configManager.getBiomeConfig());
//slice world to render edges if configured
if (mapConfig.isRenderEdges() && !(mapConfig.getMin().equals(RenderSettings.DEFAULT_MIN) && mapConfig.getMax().equals(RenderSettings.DEFAULT_MAX))) {
world = new SlicedWorld(world, mapConfig.getMin(), mapConfig.getMax());
}
HiresModelManager hiresModelManager = new HiresModelManager(
config.getWebDataPath().resolve("hires").resolve(mapConfig.getId()),
@ -123,12 +130,16 @@ public class BlueMapCLI {
Logger.global.logInfo("Writing settings.json ...");
WebSettings webSettings = new WebSettings(config.getWebDataPath().resolve("settings.json").toFile());
webSettings.setAllEnabled(false);
for (MapType map : maps.values()) {
webSettings.setEnabled(true, map.getId());
webSettings.setName(map.getName(), map.getId());
webSettings.setFrom(map.getTileRenderer(), 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.setHiresViewDistance(map.getHiresViewDistance(), map.getId());
webSettings.setLowresViewDistance(map.getLowresViewDistance(), map.getId());
}
@ -233,7 +244,7 @@ public class BlueMapCLI {
return true;
}
private boolean handleMissingResources(File resourceFile) {
private boolean handleMissingResources(File resourceFile) throws IOException {
if (configManager.getMainConfig().isDownloadAccepted()) {
try {
Logger.global.logInfo("Downloading " + ResourcePack.MINECRAFT_CLIENT_URL + " to " + resourceFile.getCanonicalPath() + " ...");
@ -246,7 +257,7 @@ public class BlueMapCLI {
} 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() + " and try again!");
Logger.global.logWarning("Please check " + configManager.getMainConfigFile().getCanonicalPath() + " and try again!");
return false;
}
}
@ -278,7 +289,7 @@ public class BlueMapCLI {
config.loadMainConfig();
if (configCreated) {
Logger.global.logInfo("No config file found! Created default configs here: " + configFolder);
Logger.global.logInfo("No config file found! Created default configs here: " + config.getMainConfigFile().getCanonicalPath());
return;
}

View File

@ -1,10 +1,10 @@
accept-download: false
metrics: true
renderThreadCount: 0
data: "."
web {
webroot: "web"
webserver {
enabled: false
webroot: "web"
port: 8100
maxConnectionCount: 100
}
renderThreadCount: 0

View File

@ -5,20 +5,23 @@
## http://bluecolored.de/ ##
## ##
# !! Don't change this !!
# This is used to detect version-changes in the configuration
# and update configuration correctly.
version: "%version%"
# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula),
# you confirm that you own a license to Minecraft (Java Edition)
# and you agree that BlueMap will download and use this file for you: %minecraft-client-url%
# (Alternatively you can download the file yourself and store it here: <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 compilant with mojang's EULA.
# 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%"}
@ -27,40 +30,33 @@ metrics: true
# The folder where bluemap saves data-files it needs during runtime
data: "."
web {
# The webroot of the website that displays the map.
webroot: "web"
# Unncomment this to override the path where bluemap stores the data-files.
# Default is "<webroot>/data"
#webdata: "path/to/data/folder"
webserver {
# With this setting you can enable the integrated web-server.
# Default is disabled
enabled: false
# The webroot of the website that displays the map.
webroot: "web"
# The IP-Adress that the webserver binds to.
# If this setting is commented out, bluemap tries to find the default ip-adress of your system.
# If you only want to access it locally use "localhost".
#ip: "localhost"
#ip: "127.0.0.1"
# The port that the webserver listenes to.
# Default is 8100
port: 8100
# Max number of simultaneous connections that the webserver allows
# Default is 100
maxConnectionCount: 100
# Unncomment this to override the path where bluemap stores the data-files.
# Default is "<webroot>/data"
#web-data: "path/to/data/folder"
}
# This changes the amount of threads that BlueMap will use to render the maps.
# A higher value can improve render-speed but could impact performance on the host machine.
# This should be always below or equal to the number of available processor-cores.
# 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
# This is an array with multiple configured maps.
# You can define multiple maps, for different worlds with different render-settings here
maps: [
@ -96,15 +92,21 @@ maps: [
# Default is 0.8
lighting: 0.8
# Using this, BlueMap pretends that every Block above the defined value is AIR.
# Default is disabled
#sliceY: 90
# With the below values you can just not render blocks at certain heights.
# This can be used to ignore the nethers ceiling.
# Default is no min or max y value
# With the below values you can limit the map-render.
# This can be used to ignore the nethers ceiling or render only a certain part of a world.
# Default is no min or max value (= infinite bounds)
#minX: -4000
#maxX: 4000
#minZ: -4000
#maxZ: 4000
#minY: 50
#maxY: 126
# Using this, BlueMap pretends that every Block out of the defined render-bounds is AIR,
# this means you can see the blocks where the world is cut (instead of having a see-through/xray view).
# This has only an effect if you set some render-bounds above.
# Default is enabled
renderEdges: true
# HIRES is the high-resolution render of the map. Where you see every block.
hires {
@ -118,7 +120,7 @@ maps: [
viewDistance: 4.5
}
# LOWRES is the low-resolution render of the map. THats the model that you see if you zoom far out to get an overview.
# LOWRES is the low-resolution render of the map. Thats the model that you see if you zoom far out to get an overview.
lowres {
# Defines resolution of the lowres model. E.g. If the hires.tileSize is 32, a value of 4 means that every 8*8 blocks will be summarized by one point on the lowres map.
# Calculation: 32 / 4 = 8
@ -137,13 +139,13 @@ maps: [
}
# Here another example for the End-Map
# Things we dont want to change from default we can just omit
# Things we don't want to change from default we can just omit
{
id: "end"
name: "End"
world: "world/DIM1"
# In the end is no light, so we need to enable this or we don't see anything.
# In the end is no sky-light, so we need to enable this or we won't see anything.
renderCaves: true
# Same here, we don't want a dark map. But not completely disabled, so we see the effect of e.g torches.
@ -159,12 +161,10 @@ maps: [
renderCaves: true
lighting: 0.6
# We slice the whole world at y:90 so evrery block above 90 will be air.
# This way we dont render the nethers ceiling.
sliceY: 90
# Instead of slicing we also could do this, that would look like an x-ray view through the ceiling.
#maxY: 126
# We slice the whole world at y:90 so every block above 90 will be air.
# This way we don't render the nethers ceiling.
maxY: 90
renderEdges: true
}
]

View File

@ -51,7 +51,7 @@ public class BiomeConfig implements BiomeMapper {
for (Entry<Object, ? extends ConfigurationNode> e : node.getChildrenMap().entrySet()){
String id = e.getKey().toString();
Biome biome = Biome.create(id, e.getValue());
biomes.put(biome.getOrdinal(), biome);
biomes.put(biome.getNumeralId(), biome);
}
}

View File

@ -30,11 +30,13 @@ import java.net.InetAddress;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
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;
@ -57,51 +59,65 @@ public class MainConfig implements WebServerConfig {
private int renderThreadCount = 0;
private Collection<MapConfig> mapConfigs = new ArrayList<>();
private List<MapConfig> mapConfigs = new ArrayList<>();
public MainConfig(ConfigurationNode node) throws IOException {
version = node.getNode("version").getString();
public MainConfig(ConfigurationNode node) throws OutdatedConfigException, IOException {
checkOutdated(node);
//acceppt-download
downloadAccepted = node.getNode("accept-download").getBoolean(false);
metricsEnabled = node.getNode("metrics").getBoolean(false);
dataPath = toFolder(node.getNode("data").getString("data"));
loadWebConfig(node.getNode("web"));
//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");
//webserver
loadWebConfig(node.getNode("webserver"));
//maps
loadMapConfigs(node.getNode("maps"));
}
private void loadWebConfig(ConfigurationNode node) throws IOException {
//enabled
webserverEnabled = node.getNode("enabled").getBoolean(false);
String webRootString = node.getNode("webroot").getString();
if (webserverEnabled && webRootString == null) throw new IOException("Invalid configuration: Node web.webroot is not defined");
webRoot = toFolder(webRootString);
if (webserverEnabled) {
webserverPort = node.getNode("port").getInt(8100);
webserverMaxConnections = node.getNode("maxConnectionCount").getInt(100);
//ip
String webserverBindAdressString = node.getNode("ip").getString("");
if (webserverBindAdressString.isEmpty()) {
webserverBindAdress = InetAddress.getLocalHost();
} else {
webserverBindAdress = InetAddress.getByName(webserverBindAdressString);
}
//port
webserverPort = node.getNode("port").getInt(8100);
//maxConnectionCount
webserverMaxConnections = node.getNode("maxConnectionCount").getInt(100);
}
String webDataString = node.getNode("web-data").getString(node.getNode("data").getString());
if (webDataString != null)
webDataPath = toFolder(webDataString);
else if (webRoot != null)
webDataPath = webRoot.resolve("data");
else
throw new IOException("Invalid configuration: Node web.data is not defined in config");
}
private void loadMapConfigs(ConfigurationNode node) throws IOException {
@ -168,7 +184,7 @@ public class MainConfig implements WebServerConfig {
return renderThreadCount;
}
public Collection<MapConfig> getMapConfigs(){
public List<MapConfig> getMapConfigs(){
return mapConfigs;
}
@ -182,7 +198,8 @@ public class MainConfig implements WebServerConfig {
private float ambientOcclusion;
private float lighting;
private int maxY, minY, sliceY;
private Vector3i min, max;
private boolean renderEdges;
private int hiresTileSize;
private float hiresViewDistance;
@ -203,17 +220,24 @@ public class MainConfig implements WebServerConfig {
this.renderCaves = node.getNode("renderCaves").getBoolean(false);
this.ambientOcclusion = node.getNode("ambientOcclusion").getFloat(0.25f);
this.lighting = node.getNode("lighting").getFloat(0.8f);
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.maxY = node.getNode("maxY").getInt(RenderSettings.super.getMaxY());
this.minY = node.getNode("minY").getInt(RenderSettings.super.getMinY());
this.sliceY = node.getNode("sliceY").getInt(RenderSettings.super.getSliceY());
this.renderEdges = node.getNode("renderEdges").getBoolean(true);
this.hiresTileSize = node.getNode("hires", "tileSize").getInt(32);
this.hiresViewDistance = node.getNode("hires", "viewDistance").getFloat(3.5f);
this.hiresViewDistance = node.getNode("hires", "viewDistance").getFloat(4.5f);
this.lowresPointsPerHiresTile = node.getNode("lowres", "pointsPerHiresTile").getInt(4);
this.lowresPointsPerLowresTile = node.getNode("lowres", "pointsPerLowresTile").getInt(50);
this.lowresViewDistance = node.getNode("lowres", "viewDistance").getFloat(4f);
this.lowresViewDistance = node.getNode("lowres", "viewDistance").getFloat(7f);
//check valid configuration values
double blocksPerPoint = (double) this.hiresTileSize / (double) this.lowresPointsPerHiresTile;
@ -272,20 +296,33 @@ public class MainConfig implements WebServerConfig {
}
@Override
public int getMaxY() {
return maxY;
public Vector3i getMin() {
return min;
}
@Override
public int getMinY() {
return minY;
public Vector3i getMax() {
return max;
}
@Override
public int getSliceY() {
return sliceY;
public boolean isRenderEdges() {
return renderEdges;
}
}
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!");
}
}

View File

@ -0,0 +1,42 @@
/*
* 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;
public class OutdatedConfigException extends IOException {
private static final long serialVersionUID = -942567050110586060L;
public OutdatedConfigException() {}
public OutdatedConfigException(String message) {
super(message);
}
public OutdatedConfigException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,98 +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.mca;
import com.flowpowered.math.vector.Vector3i;
import de.bluecolored.bluemap.core.world.Biome;
import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.BlockProperties;
import de.bluecolored.bluemap.core.world.BlockState;
import de.bluecolored.bluemap.core.world.LightData;
public class MCABlock extends Block {
private MCAWorld world;
private BlockState blockState;
private LightData lightData;
private Biome biome;
private BlockProperties properties;
private Vector3i pos;
public MCABlock(MCAWorld world, BlockState blockState, LightData lightData, Biome biome, BlockProperties properties, Vector3i pos) {
this.world = world;
this.blockState = blockState;
this.lightData = lightData;
this.biome = biome;
this.properties = properties;
this.pos = pos;
}
@Override
public BlockState getBlock() {
return blockState;
}
@Override
public MCAWorld getWorld() {
return world;
}
@Override
public Vector3i getPosition() {
return pos;
}
@Override
public double getSunLightLevel() {
return lightData.getSkyLight();
}
@Override
public double getBlockLightLevel() {
return lightData.getBlockLight();
}
@Override
public boolean isCullingNeighborFaces() {
return properties.isCulling();
}
@Override
public boolean isOccludingNeighborFaces() {
return properties.isOccluding();
}
@Override
public boolean isFlammable() {
return properties.isFlammable();
}
@Override
public Biome getBiome() {
return biome;
}
}

View File

@ -149,11 +149,11 @@ public class MCAWorld implements World {
@Override
public Block getBlock(Vector3i pos) {
if (pos.getY() < getMinY()) {
return new MCABlock(this, BlockState.AIR, LightData.ZERO, Biome.DEFAULT, BlockProperties.SOLID, pos);
return new Block(this, BlockState.AIR, LightData.ZERO, Biome.DEFAULT, BlockProperties.TRANSPARENT, pos);
}
if (pos.getY() > getMaxY()) {
return new MCABlock(this, BlockState.AIR, LightData.FULL, Biome.DEFAULT, BlockProperties.TRANSPARENT, pos);
return new Block(this, BlockState.AIR, LightData.FULL, Biome.DEFAULT, BlockProperties.TRANSPARENT, pos);
}
try {
@ -164,7 +164,7 @@ public class MCAWorld implements World {
LightData lightData = chunk.getLightData(pos);
Biome biome = chunk.getBiome(pos);
BlockProperties properties = blockPropertiesMapper.get(blockState);
return new MCABlock(this, blockState, lightData, biome, properties, pos);
return new Block(this, blockState, lightData, biome, properties, pos);
} catch (IOException ex) {
throw new RuntimeException("Unexpected IO-Exception trying to read world-data!", ex);

View File

@ -24,8 +24,13 @@
*/
package de.bluecolored.bluemap.core.render;
import com.flowpowered.math.vector.Vector3i;
public interface RenderSettings {
static final Vector3i DEFAULT_MIN = Vector3i.from(Integer.MIN_VALUE);
static final Vector3i DEFAULT_MAX = Vector3i.from(Integer.MAX_VALUE);
/**
* The strenght of ao-shading calculated for each vertex.<br>
* A value of 0 turns off ao.<br>
@ -49,39 +54,38 @@ public interface RenderSettings {
default float getLightShadeMultiplier() {
return 0.8f;
}
/**
* The maximum height of rendered blocks
*/
default int getMaxY() {
return Integer.MAX_VALUE;
}
/**
* The minimum height of rendered blocks
* The minimum position of blocks to render
*/
default int getMinY() {
return 0;
default Vector3i getMin() {
return DEFAULT_MIN;
}
/**
* The maximum position of blocks to render
*/
default Vector3i getMax() {
return DEFAULT_MAX;
}
/**
* The same as the maximum height, but blocks that are above this value are treated as AIR.<br>
* This leads to the top-faces being rendered instead of them being culled.
*/
default int getSliceY() {
return Integer.MAX_VALUE;
default boolean isRenderEdges() {
return true;
}
default RenderSettings copy() {
return new StaticRenderSettings(
getAmbientOcclusionStrenght(),
isExcludeFacesWithoutSunlight(),
getLightShadeMultiplier(),
getMaxY(),
getMinY(),
getSliceY()
getMin(),
getMax(),
isRenderEdges()
);
}

View File

@ -24,27 +24,30 @@
*/
package de.bluecolored.bluemap.core.render;
import com.flowpowered.math.vector.Vector3i;
public class StaticRenderSettings implements RenderSettings {
private float ambientOcclusion;
private boolean excludeFacesWithoutSunlight;
private float lightShade;
private int maxY, minY, sliceY;
private Vector3i min, max;
private boolean renderEdges;
public StaticRenderSettings(
float ambientOcclusion,
boolean excludeFacesWithoutSunlight,
float ligheShade,
int maxY,
int minY,
int sliceY
Vector3i min,
Vector3i max,
boolean renderEdges
) {
this.ambientOcclusion = ambientOcclusion;
this.excludeFacesWithoutSunlight = excludeFacesWithoutSunlight;
this.lightShade = ligheShade;
this.maxY = maxY;
this.minY = minY;
this.sliceY = sliceY;
this.min = min;
this.max = max;
this.renderEdges = renderEdges;
}
@Override
@ -61,20 +64,20 @@ public class StaticRenderSettings implements RenderSettings {
public float getLightShadeMultiplier() {
return lightShade;
}
@Override
public int getMaxY() {
return maxY;
public Vector3i getMin() {
return min;
}
@Override
public int getMinY() {
return minY;
public Vector3i getMax() {
return max;
}
@Override
public int getSliceY() {
return sliceY;
public boolean isRenderEdges() {
return renderEdges;
}
}

View File

@ -60,7 +60,9 @@ public class HiresModel extends Model {
}
public Vector4f getColor(int x, int z){
return colors[x - blockMin.getX()][z - blockMin.getZ()];
Vector4f color = colors[x - blockMin.getX()][z - blockMin.getZ()];
if (color == null) return Vector4f.ZERO;
return color;
}
public void setHeight(int x, int z, int height){

View File

@ -52,15 +52,15 @@ public class HiresModelRenderer {
}
public HiresModel render(WorldTile tile, AABB region) {
Vector3i min = region.getMin().toInt();
Vector3i max = region.getMax().toInt();
Vector3i modelMin = region.getMin().toInt();
Vector3i modelMax = region.getMax().toInt();
min = new Vector3i(min.getX(), Math.max(min.getY(), renderSettings.getMinY()), min.getZ());
max = new Vector3i(max.getX(), Math.min(max.getY(), Math.min(renderSettings.getMaxY(), renderSettings.getSliceY())), max.getZ());
Vector3i min = modelMin.max(renderSettings.getMin());
Vector3i max = modelMax.min(renderSettings.getMax());
World world = tile.getWorld();
HiresModel model = new HiresModel(tile.getWorld().getUUID(), tile.getTile(), min, max);
HiresModel model = new HiresModel(tile.getWorld().getUUID(), tile.getTile(), modelMin, modelMax);
for (int x = min.getX(); x <= max.getX(); x++){
for (int z = min.getZ(); z <= max.getZ(); z++){
@ -70,9 +70,9 @@ public class HiresModelRenderer {
for (int y = min.getY(); y <= max.getY(); y++){
Block block = world.getBlock(x, y, z);
if (block.getBlock().getId().equals("air")) continue;
if (block.getBlockState().equals(BlockState.AIR)) continue;
if (!block.getBlock().equals(BlockState.AIR)) maxHeight = y;
maxHeight = y;
BlockStateModel blockModel;
try {
@ -85,15 +85,15 @@ public class HiresModelRenderer {
blockModel = new BlockStateModel();
}
Logger.global.noFloodDebug(block.getBlock().getFullId() + "-hiresModelRenderer-blockmodelerr", "Failed to create BlockModel for BlockState: " + block.getBlock() + " (" + e.toString() + ")");
Logger.global.noFloodDebug(block.getBlockState().getFullId() + "-hiresModelRenderer-blockmodelerr", "Failed to create BlockModel for BlockState: " + block.getBlockState() + " (" + e.toString() + ")");
}
blockModel.translate(new Vector3f(x, y, z).sub(min.toFloat()));
blockModel.translate(new Vector3f(x, y, z).sub(modelMin.toFloat()));
color = MathUtils.overlayColors(blockModel.getMapColor(), color);
//TODO: quick hack to random offset grass
if (block.getBlock().getId().equals("grass")){
if (block.getBlockState().getFullId().equals("minecraft:grass")){
float dx = (MathUtils.hashToFloat(x, y, z, 123984) - 0.5f) * 0.75f;
float dz = (MathUtils.hashToFloat(x, y, z, 345542) - 0.5f) * 0.75f;
blockModel.translate(new Vector3f(dx, 0, dz));

View File

@ -44,7 +44,7 @@ public class BlockStateModelFactory {
}
public BlockStateModel createFrom(Block block) throws NoSuchResourceException {
return createFrom(block, block.getBlock());
return createFrom(block, block.getBlockState());
}
public BlockStateModel createFrom(Block block, BlockState blockState) throws NoSuchResourceException {

View File

@ -52,6 +52,7 @@ public class LiquidModelBuilder {
"minecraft:seagrass",
"minecraft:tall_seagrass",
"minecraft:kelp",
"minecraft:kelp_plant",
"minecraft:bubble_column"
);
@ -74,7 +75,7 @@ public class LiquidModelBuilder {
public BlockStateModel build(BlockModelResource bmr) {
if (this.renderSettings.isExcludeFacesWithoutSunlight() && block.getSunLightLevel() == 0) return new BlockStateModel();
int level = getLiquidLevel(block.getBlock());
int level = getLiquidLevel(block.getBlockState());
float[] heights = new float[]{16f, 16f, 16f, 16f};
float coloralpha = 0.2f;
@ -143,9 +144,9 @@ public class LiquidModelBuilder {
for (int iz = z; iz<= z+1; iz++){
Block b = block.getRelativeBlock(ix, y, iz);
if (isLiquid(b)){
if (getLiquidLevel(b.getBlock()) == 0) return 14f;
if (getLiquidLevel(b.getBlockState()) == 0) return 14f;
sumHeight += getLiquidBaseHeight(b.getBlock());
sumHeight += getLiquidBaseHeight(b.getBlockState());
count++;
}
@ -163,12 +164,12 @@ public class LiquidModelBuilder {
}
private boolean isLiquidBlockingBlock(Block block){
if (block.getBlock().equals(BlockState.AIR)) return false;
if (block.getBlockState().equals(BlockState.AIR)) return false;
return true;
}
private boolean isLiquid(Block block){
return isLiquid(block.getBlock());
return isLiquid(block.getBlockState());
}
private boolean isLiquid(BlockState blockState){

View File

@ -86,7 +86,7 @@ public class BlockColorCalculator {
}
public Vector3f getBlockColor(Block block){
String blockId = block.getBlock().getFullId();
String blockId = block.getBlockState().getFullId();
Function<Block, Vector3f> colorFunction = blockColorMap.get(blockId);
if (colorFunction == null) colorFunction = blockColorMap.get("default");

View File

@ -160,4 +160,13 @@ public class ConfigUtils {
return Integer.parseInt(val);
}
public static String nodePathToString(ConfigurationNode node) {
Object[] keys = node.getPath();
String[] stringKeys = new String[keys.length];
for (int i = 0; i < keys.length; i++) {
stringKeys[i] = keys[i].toString();
}
return String.join(".", stringKeys);
}
}

View File

@ -26,6 +26,8 @@ package de.bluecolored.bluemap.core.web;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.stream.Collectors;
import com.flowpowered.math.vector.Vector2i;
@ -50,7 +52,7 @@ public class WebSettings {
.setFile(settingsFile)
.build();
rootNode = configLoader.createEmptyNode();
load();
}
public void load() throws IOException {
@ -73,7 +75,7 @@ public class WebSettings {
return rootNode.getNode(path).getString();
}
public long getInt(Object... path) {
public int getInt(Object... path) {
return rootNode.getNode(path).getInt();
}
@ -81,7 +83,7 @@ public class WebSettings {
return rootNode.getNode(path).getLong();
}
public double getFloat(Object... path) {
public float getFloat(Object... path) {
return rootNode.getNode(path).getFloat();
}
@ -89,6 +91,20 @@ public class WebSettings {
return rootNode.getNode(path).getDouble();
}
public Collection<String> getMapIds() {
return rootNode.getChildrenMap().keySet().stream().map(o -> o.toString()).collect(Collectors.toSet());
}
public void setAllEnabled(boolean enabled) {
for (ConfigurationNode mapNode : rootNode.getChildrenMap().values()) {
mapNode.getNode("enabled").setValue(enabled);
}
}
public void setEnabled(boolean enabled, String mapId) {
set(enabled, mapId, "enabled");
}
public void setFrom(TileRenderer tileRenderer, String mapId) {
Vector2i hiresTileSize = tileRenderer.getHiresModelManager().getTileSize();
Vector2i gridOrigin = tileRenderer.getHiresModelManager().getGridOrigin();
@ -121,6 +137,14 @@ public class WebSettings {
set(lowresViewDistance, mapId, "lowres", "viewDistance");
}
public void setOrdinal(int ordinal, String mapId) {
set(ordinal, mapId, "ordinal");
}
public int getOrdinal(String mapId) {
return getInt(mapId, "ordinal");
}
public void setName(String name, String mapId) {
set(name, mapId, "name");
}

View File

@ -37,7 +37,7 @@ public class Biome {
public static final Biome DEFAULT = new Biome();
private String id = "ocean";
private int ordinal = 0;
private int numeralId = 0;
private float humidity = 0.5f;
private float temp = 0.5f;
private Vector3f waterColor = MathUtils.color3FromInt(4159204);
@ -47,16 +47,16 @@ public class Biome {
private Biome() {}
public Biome(String id, int ordinal, float humidity, float temp, Vector3f waterColor) {
public Biome(String id, int numeralId, float humidity, float temp, Vector3f waterColor) {
this.id = id;
this.ordinal = ordinal;
this.numeralId = numeralId;
this.humidity = humidity;
this.temp = temp;
this.waterColor = waterColor;
}
public Biome(String id, int ordinal, float humidity, float temp, Vector3f waterColor, Vector4f overlayFoliageColor, Vector4f overlayGrassColor) {
this (id, ordinal, humidity, temp, waterColor);
public Biome(String id, int numeralId, float humidity, float temp, Vector3f waterColor, Vector4f overlayFoliageColor, Vector4f overlayGrassColor) {
this (id, numeralId, humidity, temp, waterColor);
this.overlayFoliageColor = overlayFoliageColor;
this.overlayGrassColor = overlayGrassColor;
@ -66,8 +66,8 @@ public class Biome {
return id;
}
public int getOrdinal() {
return ordinal;
public int getNumeralId() {
return numeralId;
}
public float getHumidity() {
@ -94,7 +94,7 @@ public class Biome {
Biome biome = new Biome();
biome.id = id;
biome.ordinal = node.getNode("id").getInt(biome.ordinal);
biome.numeralId = node.getNode("id").getInt(biome.numeralId);
biome.humidity = node.getNode("humidity").getFloat(biome.humidity);
biome.temp = node.getNode("temp").getFloat(biome.temp);
try { biome.waterColor = MathUtils.color3FromInt(ConfigUtils.readColorInt(node.getNode("watercolor"))); } catch (NumberFormatException ignored) {}
@ -108,7 +108,7 @@ public class Biome {
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", getId())
.add("ordinal", getOrdinal())
.add("numeralId", getNumeralId())
.add("humidity", getHumidity())
.add("temp", getTemp())
.add("waterColor", getWaterColor())

View File

@ -29,35 +29,65 @@ import com.google.common.base.MoreObjects;
import de.bluecolored.bluemap.core.util.Direction;
public abstract class Block {
public class Block {
private World world;
private BlockState blockState;
private LightData lightData;
private Biome biome;
private BlockProperties properties;
private Vector3i pos;
private float sunLight;
private float blockLight;
public Block() {
sunLight = -1;
blockLight = -1;
public Block(World world, BlockState blockState, LightData lightData, Biome biome, BlockProperties properties, Vector3i pos) {
this.world = world;
this.blockState = blockState;
this.lightData = lightData;
this.biome = biome;
this.properties = properties;
this.pos = pos;
this.sunLight = -1;
this.blockLight = -1;
}
public abstract BlockState getBlock();
public BlockState getBlockState() {
return blockState;
}
public abstract World getWorld();
public World getWorld() {
return world;
}
public abstract Vector3i getPosition();
public Vector3i getPosition() {
return pos;
}
public abstract double getSunLightLevel();
public double getSunLightLevel() {
return lightData.getSkyLight();
}
public abstract double getBlockLightLevel();
public double getBlockLightLevel() {
return lightData.getBlockLight();
}
public abstract boolean isCullingNeighborFaces();
public boolean isCullingNeighborFaces() {
return properties.isCulling();
}
public abstract boolean isFlammable();
public boolean isFlammable() {
return properties.isFlammable();
}
public boolean isOccludingNeighborFaces(){
return isCullingNeighborFaces();
return properties.isOccluding();
}
public abstract Biome getBiome();
public Biome getBiome() {
return biome;
}
/**
* This is internally used for light rendering
@ -104,6 +134,33 @@ public abstract class Block {
return getRelativeBlock(direction.toVector());
}
public void setWorld(World world) {
this.world = world;
}
public void setBlockState(BlockState blockState) {
this.blockState = blockState;
}
public void setLightData(LightData lightData) {
this.lightData = lightData;
this.blockLight = -1f;
this.sunLight = -1f;
}
public void setBiome(Biome biome) {
this.biome = biome;
}
public void setProperties(BlockProperties properties) {
this.properties = properties;
}
public void setPos(Vector3i pos) {
this.pos = pos;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
@ -111,7 +168,7 @@ public abstract class Block {
.add("biome", getBiome())
.add("blocklight", getBlockLightLevel())
.add("sunlight", getSunLightLevel())
.add("state", getBlock())
.add("state", getBlockState())
.toString();
}

View File

@ -0,0 +1,206 @@
/*
* 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.world;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.UUID;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3i;
import de.bluecolored.bluemap.core.util.AABB;
/**
* A sliced view of a world. Everything outside the defined bounds is seen as "not generated" and "air".
*/
public class SlicedWorld implements World {
private World world;
private Vector3i min;
private Vector3i max;
public SlicedWorld(World world, Vector3i min, Vector3i max) {
this.world = world;
this.min = min;
this.max = max;
}
@Override
public String getName() {
return world.getName();
}
@Override
public UUID getUUID() {
return world.getUUID();
}
@Override
public int getSeaLevel() {
return world.getSeaLevel();
}
@Override
public Vector3i getSpawnPoint() {
return world.getSpawnPoint();
}
@Override
public int getMaxY() {
return world.getMaxY();
}
@Override
public int getMinY() {
return world.getMinY();
}
@Override
public Block getBlock(Vector3i pos) {
if (!isInside(pos)) return createAirBlock(pos);
Block block = world.getBlock(pos);
block.setWorld(this);
return block;
}
@Override
public Block getBlock(int x, int y, int z) {
if (!isInside(x, y, z)) return createAirBlock(new Vector3i(x, y, z));
Block block = world.getBlock(x, y, z);
block.setWorld(this);
return block;
}
@Override
public Collection<Vector2i> getChunkList(){
Collection<Vector2i> chunkList = world.getChunkList();
ArrayList<Vector2i> filteredChunkList = new ArrayList<>(chunkList.size());
for (Vector2i chunk : chunkList) {
if (isInside(chunk)) filteredChunkList.add(chunk);
}
filteredChunkList.trimToSize();
return filteredChunkList;
}
@Override
public Collection<Vector2i> getChunkList(long modifiedSince) {
Collection<Vector2i> chunkList = world.getChunkList(modifiedSince);
ArrayList<Vector2i> filteredChunkList = new ArrayList<>(chunkList.size());
for (Vector2i chunk : chunkList) {
if (isInside(chunk)) filteredChunkList.add(chunk);
}
filteredChunkList.trimToSize();
return filteredChunkList;
}
@Override
public boolean isChunkGenerated(Vector2i chunkPos) throws IOException {
if (!isInside(chunkPos)) return false;
return world.isChunkGenerated(chunkPos);
}
@Override
public boolean isAreaGenerated(AABB area) throws IOException {
if (!isInside(blockPosToChunkPos(area.getMin().toInt())) && !isInside(blockPosToChunkPos(area.getMax().toInt()))) return false;
return world.isAreaGenerated(area);
}
@Override
public boolean isAreaGenerated(Vector3i blockMin, Vector3i blockMax) throws IOException {
if (!isInside(blockPosToChunkPos(blockMin)) && !isInside(blockPosToChunkPos(blockMax))) return false;
return world.isAreaGenerated(blockMin, blockMax);
}
@Override
public boolean isAreaGenerated(Vector2i chunkMin, Vector2i chunkMax) throws IOException {
if (!isInside(chunkMin) && !isInside(chunkMax)) return false;
return world.isAreaGenerated(chunkMin, chunkMax);
}
@Override
public void invalidateChunkCache() {
world.invalidateChunkCache();
}
@Override
public void invalidateChunkCache(Vector2i chunk) {
world.invalidateChunkCache(chunk);
}
@Override
public Vector2i blockPosToChunkPos(Vector3i block) {
return world.blockPosToChunkPos(block);
}
private boolean isInside(Vector3i blockPos) {
return isInside(blockPos.getX(), blockPos.getY(), blockPos.getZ());
}
private boolean isInside(int x, int y, int z) {
return
x >= min.getX() &&
x <= max.getX() &&
z >= min.getZ() &&
z <= max.getZ() &&
y >= min.getY() &&
y <= max.getY();
}
private boolean isInside(Vector2i chunkPos) {
return isInside(chunkPos.getX(), chunkPos.getY());
}
private boolean isInside(int chunkX, int chunkZ) {
return
chunkX * 16 >= min.getX() &&
chunkX * 16 + 15 <= max.getX() &&
chunkZ * 16 >= min.getZ() &&
chunkZ * 16 + 15 <= max.getZ();
}
private Block createAirBlock(Vector3i pos) {
return new Block(
this,
BlockState.AIR,
pos.getY() < this.min.getY() ? LightData.ZERO : LightData.FULL,
Biome.DEFAULT,
BlockProperties.TRANSPARENT,
pos
);
}
}

View File

@ -233,11 +233,17 @@ BlueMap.prototype.loadSettings = function (callback) {
scope.maps = [];
for (map in scope.settings){
if (scope.settings.hasOwnProperty(map)){
if (scope.settings.hasOwnProperty(map) && scope.settings[map].enabled){
scope.maps.push(map);
}
}
scope.maps.sort(function (map1, map2) {
var sort = scope.settings[map1].ordinal - scope.settings[map2].ordinal;
if (isNaN(sort)) return 0;
return sort;
});
scope.map = scope.maps[0];
callback.call(scope);

View File

@ -67,6 +67,7 @@ import de.bluecolored.bluemap.core.config.MainConfig.MapConfig;
import de.bluecolored.bluemap.core.logger.Logger;
import de.bluecolored.bluemap.core.mca.MCAWorld;
import de.bluecolored.bluemap.core.metrics.Metrics;
import de.bluecolored.bluemap.core.render.RenderSettings;
import de.bluecolored.bluemap.core.render.TileRenderer;
import de.bluecolored.bluemap.core.render.hires.HiresModelManager;
import de.bluecolored.bluemap.core.render.lowres.LowresModelManager;
@ -75,6 +76,7 @@ import de.bluecolored.bluemap.core.resourcepack.ResourcePack;
import de.bluecolored.bluemap.core.web.BlueMapWebServer;
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;
import net.querz.nbt.CompoundTag;
import net.querz.nbt.NBTUtil;
@ -209,6 +211,11 @@ public class SpongePlugin {
}
}
//slice world to render edges if configured
if (mapConfig.isRenderEdges() && !(mapConfig.getMin().equals(RenderSettings.DEFAULT_MIN) && mapConfig.getMax().equals(RenderSettings.DEFAULT_MAX))) {
world = new SlicedWorld(world, mapConfig.getMin(), mapConfig.getMax());
}
HiresModelManager hiresModelManager = new HiresModelManager(
config.getWebDataPath().resolve("hires").resolve(id),
resourcePack,
@ -257,12 +264,16 @@ public class SpongePlugin {
}
WebSettings webSettings = new WebSettings(config.getWebDataPath().resolve("settings.json").toFile());
webSettings.setAllEnabled(false);
for (MapType map : maps.values()) {
webSettings.setEnabled(true, map.getId());
webSettings.setName(map.getName(), map.getId());
webSettings.setFrom(map.getTileRenderer(), 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.setHiresViewDistance(map.getHiresViewDistance(), map.getId());
webSettings.setLowresViewDistance(map.getLowresViewDistance(), map.getId());
}

View File

@ -1,10 +1,10 @@
accept-download: false
metrics: false
renderThreadCount: -2
data: "bluemap"
web {
webroot: "bluemap/web"
webserver {
enabled: true
webroot: "bluemap/web"
port: 8100
maxConnectionCount: 100
}
renderThreadCount: -2

View File

@ -5,50 +5,15 @@
## http://bluecolored.de/ ##
## ##
# !! Don't change this !!
# This is used to detect version-changes in the configuration
# and update configuration correctly.
version: "%version%"
# By changing the setting (accept-download) below to TRUE you are indicating that you have accepted mojang's EULA (https://account.mojang.com/documents/minecraft_eula),
# you confirm that you own a license to Minecraft (Java Edition)
# and you agree that BlueMap will download and use this file for you: %minecraft-client-url%
# (Alternatively you can download the file yourself and store it here: <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 compilant with mojang's EULA.
# 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
# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later.
data: "bluemap"
web {
# With this setting you can disable the 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.
enabled: true
# The webroot of the website that displays the map.
webroot: "bluemap/web"
# The IP-Adress that the webserver binds to.
# If this setting is commented out, bluemap tries to find the default ip-adress of your system.
# If you only want to access it locally use "localhost".
#ip: "localhost"
#ip: "127.0.0.1"
# The port that the webserver listenes to.
# Default is 8100
port: 8100
# Max number of simultaneous connections that the webserver allows
# Default is 100
maxConnectionCount: 100
# Unncomment this to override the path where bluemap stores the data-files.
# Default is "<webroot>/data"
#web-data: "path/to/data/folder"
}
# This changes the amount of threads that BlueMap will use to render the maps.
# A higher value can improve render-speed but could impact performance on the host machine.
# This should be always below or equal to the number of available processor-cores.
@ -57,6 +22,37 @@ web {
# 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"
# Unncomment this to override the path where bluemap stores the data-files.
# Default is "<webroot>/data"
#webdata: "path/to/data/folder"
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.
# If this setting is commented out, bluemap tries to find the default ip-adress of your system.
# If you only want to access it locally use "localhost".
#ip: "localhost"
#ip: "127.0.0.1"
# The port that the webserver listenes to.
# Default is 8100
port: 8100
# Max number of simultaneous connections that the webserver allows
# Default is 100
maxConnectionCount: 100
}
# This is an array with multiple configured maps.
# You can define multiple maps, for different worlds with different render-settings here
maps: [
@ -92,15 +88,21 @@ maps: [
# Default is 0.8
lighting: 0.8
# Using this, BlueMap pretends that every Block above the defined value is AIR.
# Default is disabled
#sliceY: 90
# With the below values you can just not render blocks at certain heights.
# This can be used to ignore the nethers ceiling.
# Default is no min or max y value
# With the below values you can limit the map-render.
# This can be used to ignore the nethers ceiling or render only a certain part of a world.
# Default is no min or max value (= infinite bounds)
#minX: -4000
#maxX: 4000
#minZ: -4000
#maxZ: 4000
#minY: 50
#maxY: 126
# Using this, BlueMap pretends that every Block out of the defined render-bounds is AIR,
# this means you can see the blocks where the world is cut (instead of having a see-through/xray view).
# This has only an effect if you set some render-bounds above.
# Default is enabled
renderEdges: true
# HIRES is the high-resolution render of the map. Where you see every block.
hires {
@ -114,7 +116,7 @@ maps: [
viewDistance: 4.5
}
# LOWRES is the low-resolution render of the map. THats the model that you see if you zoom far out to get an overview.
# LOWRES is the low-resolution render of the map. Thats the model that you see if you zoom far out to get an overview.
lowres {
# Defines resolution of the lowres model. E.g. If the hires.tileSize is 32, a value of 4 means that every 8*8 blocks will be summarized by one point on the lowres map.
# Calculation: 32 / 4 = 8
@ -133,13 +135,13 @@ maps: [
}
# Here another example for the End-Map
# Things we dont want to change from default we can just omit
# Things we don't want to change from default we can just omit
{
id: "end"
name: "End"
world: "world/DIM1"
# In the end is no light, so we need to enable this or we don't see anything.
# In the end is no sky-light, so we need to enable this or we won't see anything.
renderCaves: true
# Same here, we don't want a dark map. But not completely disabled, so we see the effect of e.g torches.
@ -155,12 +157,10 @@ maps: [
renderCaves: true
lighting: 0.6
# We slice the whole world at y:90 so evrery block above 90 will be air.
# This way we dont render the nethers ceiling.
sliceY: 90
# Instead of slicing we also could do this, that would look like an x-ray view through the ceiling.
#maxY: 126
# We slice the whole world at y:90 so every block above 90 will be air.
# This way we don't render the nethers ceiling.
maxY: 90
renderEdges: true
}
]

View File

@ -1,8 +1,8 @@
rootProject.name = 'BlueMap'
include ':BlueMapCore'
include ':BlueMapCLI'
//include ':BlueMapSponge'
include ':BlueMapSponge'
project(':BlueMapCore').projectDir = "$rootDir/BlueMapCore" as File
project(':BlueMapCLI').projectDir = "$rootDir/BlueMapCLI" as File
//project(':BlueMapSponge').projectDir = "$rootDir/BlueMapSponge" as File
project(':BlueMapSponge').projectDir = "$rootDir/BlueMapSponge" as File