Reorganize config, add render-bounds and make some optimizations
This commit is contained in:
parent
dfbbf7d690
commit
1af2a8c86d
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
]
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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){
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
]
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue