mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-12-17 22:47:38 +01:00
Merge branch 'master' into mc/1.12
This commit is contained in:
commit
9f79488e75
@ -104,7 +104,7 @@ private UUID getUUIDForWorldSync (File worldFolder) throws IOException {
|
||||
if (worldFolder.equals(world.getWorldFolder().getCanonicalFile())) return world.getUID();
|
||||
}
|
||||
|
||||
throw new IOException("There is no world with this folder loaded: " + worldFolder.getCanonicalPath());
|
||||
throw new IOException("There is no world with this folder loaded: " + worldFolder.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -24,7 +24,7 @@ renderThreadCount: -2
|
||||
|
||||
# If this is true, BlueMap might send really basic metrics reports containg only the implementation-type and the version that is being used to https://metrics.bluecolored.de/bluemap/
|
||||
# This allows me to track the basic usage of BlueMap and helps me stay motivated to further develop this tool! Please leave it on :)
|
||||
# An example report looks like this: {"implementation":"CLI","version":"%version%"}
|
||||
# An example report looks like this: {"implementation":"bukkit","version":"%version%"}
|
||||
metrics: true
|
||||
|
||||
# The folder where bluemap saves data-files it needs during runtime or to save e.g. the render-progress to resume it later.
|
||||
@ -75,6 +75,10 @@ maps: [
|
||||
# The path to the save-folder of the world to render
|
||||
world: "world"
|
||||
|
||||
# The position on the world where the map will be centered if you open it.
|
||||
# This defaults to the world-spawn if you don't set it.
|
||||
#startPos: [500, -820]
|
||||
|
||||
# If this is false, BlueMap tries to omit all blocks that are not visible from above-ground.
|
||||
# More specific: Block-Faces that have a sunlight/skylight value of 0 are removed.
|
||||
# This improves the performance of the map on slower devices by a lot, but might cause some blocks to disappear that should normally be visible.
|
||||
|
@ -24,8 +24,14 @@
|
||||
*/
|
||||
package de.bluecolored.bluemap.cli;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -36,6 +42,8 @@
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.CommandLineParser;
|
||||
@ -136,15 +144,14 @@ public void renderMaps() throws IOException {
|
||||
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());
|
||||
webSettings.setFrom(map.getWorld(), map.getId());
|
||||
}
|
||||
int ordinal = 0;
|
||||
for (MapConfig map : config.getMapConfigs()) {
|
||||
if (!maps.containsKey(map.getId())) continue; //don't add not loaded maps
|
||||
webSettings.setOrdinal(ordinal++, map.getId());
|
||||
webSettings.setHiresViewDistance(map.getHiresViewDistance(), map.getId());
|
||||
webSettings.setLowresViewDistance(map.getLowresViewDistance(), map.getId());
|
||||
webSettings.setFrom(map, map.getId());
|
||||
}
|
||||
webSettings.save();
|
||||
|
||||
@ -153,11 +160,22 @@ public void renderMaps() throws IOException {
|
||||
resourcePack.saveTextureFile(textureExportFile);
|
||||
|
||||
RenderManager renderManager = new RenderManager(config.getRenderThreadCount());
|
||||
renderManager.start();
|
||||
File rmstate = new File(configFolder, "rmstate");
|
||||
|
||||
if (rmstate.exists()) {
|
||||
try (
|
||||
InputStream in = new GZIPInputStream(new FileInputStream(rmstate));
|
||||
DataInputStream din = new DataInputStream(in);
|
||||
){
|
||||
renderManager.readState(din, maps.values());
|
||||
Logger.global.logInfo("Found unfinished render, continuing ... (If you want to start a new render, delete the this file: " + rmstate.getCanonicalPath());
|
||||
} catch (IOException ex) {
|
||||
Logger.global.logError("Failed to read saved render-state! Remove the file " + rmstate.getCanonicalPath() + " to start a new render.", ex);
|
||||
}
|
||||
} else {
|
||||
for (MapType map : maps.values()) {
|
||||
Logger.global.logInfo("Rendering map '" + map.getId() + "' ...");
|
||||
Logger.global.logInfo("Collecting tiles to render...");
|
||||
Logger.global.logInfo("Creating render-task for map '" + map.getId() + "' ...");
|
||||
Logger.global.logInfo("Collecting tiles ...");
|
||||
|
||||
Collection<Vector2i> chunks;
|
||||
if (!forceRender) {
|
||||
@ -178,60 +196,81 @@ public void renderMaps() throws IOException {
|
||||
continue;
|
||||
}
|
||||
|
||||
Logger.global.logInfo("Starting Render...");
|
||||
long starttime = System.currentTimeMillis();
|
||||
|
||||
RenderTask task = new RenderTask("Map-Render: " + map.getName(), map);
|
||||
RenderTask task = new RenderTask(map.getName(), map);
|
||||
task.addTiles(tiles);
|
||||
task.optimizeQueue();
|
||||
|
||||
renderManager.addRenderTask(task);
|
||||
}
|
||||
}
|
||||
|
||||
long lastLogUpdate = System.currentTimeMillis();
|
||||
long lastSave = lastLogUpdate;
|
||||
Logger.global.logInfo("Starting render ...");
|
||||
renderManager.start();
|
||||
|
||||
while(!task.isFinished()) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
long lastLogUpdate = startTime;
|
||||
long lastSave = startTime;
|
||||
|
||||
while(renderManager.getRenderTaskCount() != 0) {
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
} catch (InterruptedException e) {}
|
||||
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (lastLogUpdate < now - 10000) { // print update all 10 seconds
|
||||
RenderTask currentTask = renderManager.getCurrentRenderTask();
|
||||
lastLogUpdate = now;
|
||||
long time = task.getActiveTime();
|
||||
long time = currentTask.getActiveTime();
|
||||
|
||||
String durationString = DurationFormatUtils.formatDurationWords(time, true, true);
|
||||
int tileCount = task.getRemainingTileCount() + task.getRenderedTileCount();
|
||||
double pct = (double)task.getRenderedTileCount() / (double) tileCount;
|
||||
int tileCount = currentTask.getRemainingTileCount() + currentTask.getRenderedTileCount();
|
||||
double pct = (double)currentTask.getRenderedTileCount() / (double) tileCount;
|
||||
|
||||
long ert = (long)((time / pct) * (1d - pct));
|
||||
String ertDurationString = DurationFormatUtils.formatDurationWords(ert, true, true);
|
||||
|
||||
double tps = task.getRenderedTileCount() / (time / 1000.0);
|
||||
double tps = currentTask.getRenderedTileCount() / (time / 1000.0);
|
||||
|
||||
Logger.global.logInfo("Rendered " + task.getRenderedTileCount() + " of " + tileCount + " tiles in " + durationString + " | " + GenericMath.round(tps, 3) + " tiles/s");
|
||||
Logger.global.logInfo("Rendering map '" + currentTask.getName() + "':");
|
||||
Logger.global.logInfo("Rendered " + currentTask.getRenderedTileCount() + " of " + tileCount + " tiles in " + durationString + " | " + GenericMath.round(tps, 3) + " tiles/s");
|
||||
Logger.global.logInfo(GenericMath.round(pct * 100, 3) + "% | Estimated remaining time: " + ertDurationString);
|
||||
}
|
||||
|
||||
if (lastSave < now - 5 * 60000) { // save every 5 minutes
|
||||
if (lastSave < now - 1 * 60000) { // save every minute
|
||||
RenderTask currentTask = renderManager.getCurrentRenderTask();
|
||||
|
||||
lastSave = now;
|
||||
map.getTileRenderer().save();
|
||||
}
|
||||
}
|
||||
currentTask.getMapType().getTileRenderer().save();
|
||||
|
||||
map.getTileRenderer().save();
|
||||
|
||||
try {
|
||||
webSettings.set(starttime, map.getId(), "last-render");
|
||||
webSettings.save();
|
||||
} catch (IOException e) {
|
||||
Logger.global.logError("Failed to update web-settings!", e);
|
||||
try (
|
||||
OutputStream os = new GZIPOutputStream(new FileOutputStream(rmstate));
|
||||
DataOutputStream dos = new DataOutputStream(os);
|
||||
){
|
||||
renderManager.writeState(dos);
|
||||
} catch (IOException ex) {
|
||||
Logger.global.logError("Failed to save render-state!", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderManager.stop();
|
||||
|
||||
//render finished, so remove render state file
|
||||
rmstate.delete();
|
||||
|
||||
for (MapType map : maps.values()) {
|
||||
webSettings.set(startTime, map.getId(), "last-render");
|
||||
}
|
||||
|
||||
try {
|
||||
webSettings.save();
|
||||
} catch (IOException e) {
|
||||
Logger.global.logError("Failed to update web-settings!", e);
|
||||
}
|
||||
|
||||
Logger.global.logInfo("Waiting for all threads to quit ...");
|
||||
if (!ForkJoinPool.commonPool().awaitQuiescence(30, TimeUnit.SECONDS)) {
|
||||
Logger.global.logWarning("Some save-threads are taking very long to exit (>30s), they will be ignored.");
|
||||
|
@ -24,7 +24,7 @@ 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%"}
|
||||
# An example report looks like this: {"implementation":"cli","version":"%version%"}
|
||||
metrics: true
|
||||
|
||||
# The folder where bluemap saves data-files it needs during runtime
|
||||
@ -74,6 +74,10 @@ maps: [
|
||||
# The path to the save-folder of the world to render
|
||||
world: "world"
|
||||
|
||||
# The position on the world where the map will be centered if you open it.
|
||||
# This defaults to the world-spawn if you don't set it.
|
||||
#startPos: [500, -820]
|
||||
|
||||
# If this is false, BlueMap tries to omit all blocks that are not visible from above-ground.
|
||||
# More specific: Block-Faces that have a sunlight/skylight value of 0 are removed.
|
||||
# This improves the performance of the map on slower devices by a lot, but might cause some blocks to disappear that should normally be visible.
|
||||
|
@ -127,11 +127,13 @@ private void renderThread() {
|
||||
RenderTask task = renderTasks.peek();
|
||||
if (task != null) {
|
||||
ticket = task.poll();
|
||||
if (task.isFinished()) renderTasks.poll();
|
||||
if (task.isFinished()) {
|
||||
renderTasks.poll();
|
||||
task.getMapType().getTileRenderer().save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ticket != null) {
|
||||
try {
|
||||
@ -155,8 +157,18 @@ public int getQueueSize() {
|
||||
* Returns a copy of the deque with the render tasks in order as array
|
||||
*/
|
||||
public RenderTask[] getRenderTasks(){
|
||||
synchronized (renderTasks) {
|
||||
return renderTasks.toArray(new RenderTask[renderTasks.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
public int getRenderTaskCount(){
|
||||
return renderTasks.size();
|
||||
}
|
||||
|
||||
public RenderTask getCurrentRenderTask() {
|
||||
return renderTasks.peek();
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
|
@ -69,6 +69,7 @@ public class Plugin {
|
||||
private RenderManager renderManager;
|
||||
private BlueMapWebServer webServer;
|
||||
|
||||
private Thread periodicalSaveThread;
|
||||
private Thread metricsThread;
|
||||
|
||||
private boolean loaded = false;
|
||||
@ -218,6 +219,23 @@ public synchronized void load() throws IOException, ParseResourceException {
|
||||
Logger.global.logError("Failed to load render-manager state!", ex);
|
||||
}
|
||||
|
||||
//create periodical-save thread
|
||||
periodicalSaveThread = new Thread(() -> {
|
||||
try {
|
||||
while (true) {
|
||||
Thread.sleep(TimeUnit.MINUTES.toMillis(5));
|
||||
try {
|
||||
saveRenderManagerState();
|
||||
} catch (IOException ex) {
|
||||
Logger.global.logError("Failed to save render-manager state!", ex);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException ex){
|
||||
return;
|
||||
}
|
||||
});
|
||||
periodicalSaveThread.start();
|
||||
|
||||
//start map updater
|
||||
this.updateHandler = new MapUpdateHandler();
|
||||
serverInterface.registerListener(updateHandler);
|
||||
@ -232,15 +250,14 @@ public synchronized void load() throws IOException, ParseResourceException {
|
||||
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());
|
||||
webSettings.setFrom(map.getWorld(), map.getId());
|
||||
}
|
||||
int ordinal = 0;
|
||||
for (MapConfig map : config.getMapConfigs()) {
|
||||
if (!maps.containsKey(map.getId())) continue; //don't add not loaded maps
|
||||
webSettings.setOrdinal(ordinal++, map.getId());
|
||||
webSettings.setHiresViewDistance(map.getHiresViewDistance(), map.getId());
|
||||
webSettings.setLowresViewDistance(map.getLowresViewDistance(), map.getId());
|
||||
webSettings.setFrom(map, map.getId());
|
||||
}
|
||||
webSettings.save();
|
||||
|
||||
@ -278,6 +295,9 @@ public synchronized void unload() {
|
||||
if (metricsThread != null) metricsThread.interrupt();
|
||||
metricsThread = null;
|
||||
|
||||
if (periodicalSaveThread != null) periodicalSaveThread.interrupt();
|
||||
periodicalSaveThread = null;
|
||||
|
||||
//stop services
|
||||
if (renderManager != null) renderManager.stop();
|
||||
if (webServer != null) webServer.close();
|
||||
@ -286,14 +306,7 @@ public synchronized void unload() {
|
||||
if (updateHandler != null) updateHandler.flushTileBuffer(); //first write all buffered tiles to the render manager to save them too
|
||||
if (renderManager != null) {
|
||||
try {
|
||||
File saveFile = config.getDataPath().resolve("rmstate").toFile();
|
||||
saveFile.getParentFile().mkdirs();
|
||||
if (saveFile.exists()) saveFile.delete();
|
||||
saveFile.createNewFile();
|
||||
|
||||
try (DataOutputStream out = new DataOutputStream(new GZIPOutputStream(new FileOutputStream(saveFile)))) {
|
||||
renderManager.writeState(out);
|
||||
}
|
||||
saveRenderManagerState();
|
||||
} catch (IOException ex) {
|
||||
Logger.global.logError("Failed to save render-manager state!", ex);
|
||||
}
|
||||
@ -316,6 +329,17 @@ public synchronized void unload() {
|
||||
loaded = false;
|
||||
}
|
||||
|
||||
public void saveRenderManagerState() throws IOException {
|
||||
File saveFile = config.getDataPath().resolve("rmstate").toFile();
|
||||
saveFile.getParentFile().mkdirs();
|
||||
if (saveFile.exists()) saveFile.delete();
|
||||
saveFile.createNewFile();
|
||||
|
||||
try (DataOutputStream out = new DataOutputStream(new GZIPOutputStream(new FileOutputStream(saveFile)))) {
|
||||
renderManager.writeState(out);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void reload() throws IOException, ParseResourceException {
|
||||
unload();
|
||||
load();
|
||||
|
@ -32,6 +32,7 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.flowpowered.math.vector.Vector2i;
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
@ -194,6 +195,8 @@ public class MapConfig implements RenderSettings {
|
||||
private String name;
|
||||
private String world;
|
||||
|
||||
private Vector2i startPos;
|
||||
|
||||
private boolean renderCaves;
|
||||
private float ambientOcclusion;
|
||||
private float lighting;
|
||||
@ -219,6 +222,8 @@ private MapConfig(ConfigurationNode node) throws IOException {
|
||||
this.world = node.getNode("world").getString("");
|
||||
if (world.isEmpty()) throw new IOException("Invalid configuration: Node maps[?].world is not defined");
|
||||
|
||||
if (!node.getNode("startPos").isVirtual()) this.startPos = ConfigUtils.readVector2i(node.getNode("startPos"));
|
||||
|
||||
this.renderCaves = node.getNode("renderCaves").getBoolean(false);
|
||||
this.ambientOcclusion = node.getNode("ambientOcclusion").getFloat(0.25f);
|
||||
this.lighting = node.getNode("lighting").getFloat(0.8f);
|
||||
@ -234,7 +239,7 @@ private MapConfig(ConfigurationNode node) throws IOException {
|
||||
|
||||
this.renderEdges = node.getNode("renderEdges").getBoolean(true);
|
||||
|
||||
this.renderEdges = node.getNode("useCompression").getBoolean(true);
|
||||
this.useGzip = node.getNode("useCompression").getBoolean(true);
|
||||
|
||||
this.hiresTileSize = node.getNode("hires", "tileSize").getInt(32);
|
||||
this.hiresViewDistance = node.getNode("hires", "viewDistance").getFloat(4.5f);
|
||||
@ -260,6 +265,10 @@ public String getWorldPath() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public Vector2i getStartPos() {
|
||||
return startPos;
|
||||
}
|
||||
|
||||
public boolean isRenderCaves() {
|
||||
return renderCaves;
|
||||
}
|
||||
|
@ -84,8 +84,7 @@ public HiresModel render(WorldTile tile, AABB region) {
|
||||
e.addSuppressed(e2);
|
||||
blockModel = new BlockStateModel();
|
||||
}
|
||||
|
||||
Logger.global.noFloodDebug(block.getBlockState().getFullId() + "-hiresModelRenderer-blockmodelerr", "Failed to create BlockModel for BlockState: " + block.getBlockState() + " (" + 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(modelMin.toFloat()));
|
||||
|
@ -66,7 +66,7 @@ public Collection<TransformedBlockModelResource> getModels(BlockState blockState
|
||||
Variant allMatch = null;
|
||||
for (Variant variant : variants) {
|
||||
if (variant.condition.matches(blockState)) {
|
||||
if (variant.condition instanceof All) { //only use "all" conditioned if nothing else matched
|
||||
if (variant.condition instanceof All) { //only use "all" condition if nothing else matched
|
||||
if (allMatch == null) allMatch = variant;
|
||||
continue;
|
||||
}
|
||||
@ -106,16 +106,21 @@ private Variant() {
|
||||
}
|
||||
|
||||
public TransformedBlockModelResource getModel(Vector3i pos) {
|
||||
if (models.isEmpty()) throw new IllegalStateException("A variant must have at least one model!");
|
||||
|
||||
double selection = MathUtils.hashToFloat(pos, 827364) * totalWeight; // random based on position
|
||||
for (Weighted<TransformedBlockModelResource> w : models) {
|
||||
selection -= w.weight;
|
||||
if (selection < 0)
|
||||
return w.value;
|
||||
if (selection <= 0) return w.value;
|
||||
}
|
||||
|
||||
throw new RuntimeException("This line should never be reached!");
|
||||
}
|
||||
|
||||
public void checkValid() throws ParseResourceException {
|
||||
if (models.isEmpty()) throw new ParseResourceException("A variant must have at least one model!");
|
||||
}
|
||||
|
||||
public void updateTotalWeight() {
|
||||
totalWeight = 0d;
|
||||
for (Weighted<?> w : models) {
|
||||
@ -181,10 +186,11 @@ public BlockStateResource build(String blockstateFile) throws IOException {
|
||||
variant.models = loadModels(transformedModelNode, blockstateFile, null);
|
||||
|
||||
variant.updateTotalWeight();
|
||||
variant.checkValid();
|
||||
|
||||
blockState.variants.add(variant);
|
||||
} catch (Exception ex) {
|
||||
Logger.global.logWarning("Failed to parse a variant of " + blockstateFile + ": " + ex);
|
||||
} catch (Throwable t) {
|
||||
Logger.global.logWarning("Failed to parse a variant of " + blockstateFile + ": " + t);
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,10 +205,11 @@ public BlockStateResource build(String blockstateFile) throws IOException {
|
||||
variant.models = loadModels(partNode.getNode("apply"), blockstateFile, null);
|
||||
|
||||
variant.updateTotalWeight();
|
||||
variant.checkValid();
|
||||
|
||||
blockState.multipart.add(variant);
|
||||
} catch (Exception ex) {
|
||||
Logger.global.logWarning("Failed to parse a multipart-part of " + blockstateFile + ": " + ex);
|
||||
} catch (Throwable t) {
|
||||
Logger.global.logWarning("Failed to parse a multipart-part of " + blockstateFile + ": " + t);
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,7 +371,14 @@ private BlockStateResource buildForge(ConfigurationNode config, String blockstat
|
||||
}
|
||||
|
||||
variant.updateTotalWeight();
|
||||
|
||||
try {
|
||||
variant.checkValid();
|
||||
blockState.variants.add(variant);
|
||||
} catch (ParseResourceException ex) {
|
||||
Logger.global.logWarning("Failed to parse a variant (forge/property) of " + blockstateFile + ": " + ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//create default straight variant
|
||||
@ -390,7 +404,14 @@ private BlockStateResource buildForge(ConfigurationNode config, String blockstat
|
||||
}
|
||||
|
||||
variant.updateTotalWeight();
|
||||
|
||||
try {
|
||||
variant.checkValid();
|
||||
blockState.variants.add(variant);
|
||||
} catch (ParseResourceException ex) {
|
||||
Logger.global.logWarning("Failed to parse a variant (forge/straight) of " + blockstateFile + ": " + ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return blockState;
|
||||
|
@ -31,7 +31,9 @@
|
||||
|
||||
import com.flowpowered.math.vector.Vector2i;
|
||||
|
||||
import de.bluecolored.bluemap.core.config.MainConfig.MapConfig;
|
||||
import de.bluecolored.bluemap.core.render.TileRenderer;
|
||||
import de.bluecolored.bluemap.core.world.World;
|
||||
import ninja.leaping.configurate.ConfigurationNode;
|
||||
import ninja.leaping.configurate.gson.GsonConfigurationLoader;
|
||||
import ninja.leaping.configurate.loader.ConfigurationLoader;
|
||||
@ -129,12 +131,22 @@ public void setFrom(TileRenderer tileRenderer, String mapId) {
|
||||
set(pointSize.getY() / 2, mapId, "lowres", "translate", "z");
|
||||
}
|
||||
|
||||
public void setHiresViewDistance(float hiresViewDistance, String mapId) {
|
||||
set(hiresViewDistance, mapId, "hires", "viewDistance");
|
||||
public void setFrom(World world, String mapId) {
|
||||
set(world.getSpawnPoint().getX(), mapId, "startPos", "x");
|
||||
set(world.getSpawnPoint().getZ(), mapId, "startPos", "z");
|
||||
}
|
||||
|
||||
public void setLowresViewDistance(float lowresViewDistance, String mapId) {
|
||||
set(lowresViewDistance, mapId, "lowres", "viewDistance");
|
||||
public void setFrom(MapConfig mapConfig, String mapId) {
|
||||
Vector2i startPos = mapConfig.getStartPos();
|
||||
if (startPos != null) {
|
||||
set(startPos.getX(), mapId, "startPos", "x");
|
||||
set(startPos.getY(), mapId, "startPos", "z");
|
||||
}
|
||||
|
||||
set(mapConfig.getLowresViewDistance(), mapId, "lowres", "viewDistance");
|
||||
set(mapConfig.getHiresViewDistance(), mapId, "hires", "viewDistance");
|
||||
|
||||
setName(mapConfig.getName(), mapId);
|
||||
}
|
||||
|
||||
public void setOrdinal(int ordinal, String mapId) {
|
||||
|
@ -81,32 +81,17 @@ export default class BlueMap {
|
||||
this.controls = new Controls(this.camera, this.element, this.hiresScene);
|
||||
|
||||
this.loadSettings().then(async () => {
|
||||
this.controls.setTileSize(this.settings[this.map]['hires']['tileSize']);
|
||||
|
||||
this.lowresTileManager = new TileManager(
|
||||
this,
|
||||
this.settings[this.map]['lowres']['viewDistance'],
|
||||
this.loadLowresTile,
|
||||
this.lowresScene,
|
||||
this.settings[this.map]['lowres']['tileSize'],
|
||||
{x: 0, z: 0}
|
||||
);
|
||||
|
||||
this.hiresTileManager = new TileManager(
|
||||
this,
|
||||
this.settings[this.map]['hires']['viewDistance'],
|
||||
this.loadHiresTile,
|
||||
this.hiresScene,
|
||||
this.settings[this.map]['hires']['tileSize'],
|
||||
{x: 0, z: 0}
|
||||
);
|
||||
|
||||
await this.loadHiresMaterial();
|
||||
await this.loadLowresMaterial();
|
||||
|
||||
this.changeMap(this.map);
|
||||
|
||||
this.initModules();
|
||||
this.start();
|
||||
}).catch(error => this.onLoadError(error.toString()));
|
||||
}).catch(error => {
|
||||
this.onLoadError(error.toString())
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
initModules() {
|
||||
@ -119,12 +104,20 @@ export default class BlueMap {
|
||||
}
|
||||
|
||||
changeMap(map) {
|
||||
this.hiresTileManager.close();
|
||||
this.lowresTileManager.close();
|
||||
if (this.hiresTileManager !== undefined) this.hiresTileManager.close();
|
||||
if (this.lowresTileManager !== undefined) this.lowresTileManager.close();
|
||||
|
||||
this.map = map;
|
||||
|
||||
let startPos = {
|
||||
x: this.settings[this.map]["startPos"]["x"],
|
||||
z: this.settings[this.map]["startPos"]["z"]
|
||||
};
|
||||
|
||||
this.controls.setTileSize(this.settings[this.map]['hires']['tileSize']);
|
||||
this.controls.resetPosition();
|
||||
this.controls.targetPosition.set(startPos.x, this.controls.targetPosition.y, startPos.z);
|
||||
this.controls.position.copy(this.controls.targetPosition);
|
||||
|
||||
this.lowresTileManager = new TileManager(
|
||||
this,
|
||||
@ -132,7 +125,7 @@ export default class BlueMap {
|
||||
this.loadLowresTile,
|
||||
this.lowresScene,
|
||||
this.settings[this.map]['lowres']['tileSize'],
|
||||
{x: 0, z: 0}
|
||||
startPos
|
||||
);
|
||||
|
||||
this.hiresTileManager = new TileManager(
|
||||
@ -141,7 +134,7 @@ export default class BlueMap {
|
||||
this.loadHiresTile,
|
||||
this.hiresScene,
|
||||
this.settings[this.map]['hires']['tileSize'],
|
||||
{x: 0, z: 0}
|
||||
startPos
|
||||
);
|
||||
|
||||
this.lowresTileManager.update();
|
||||
@ -221,7 +214,10 @@ export default class BlueMap {
|
||||
+ ':' + Math.round(this.controls.targetDistance * 100) / 100
|
||||
+ ':' + Math.ceil(this.controls.targetAngle * 100) / 100
|
||||
+ ':' + Math.floor(this.controls.targetPosition.y);
|
||||
// only update hash when changed
|
||||
if (window.location.hash !== this.locationHash) {
|
||||
history.replaceState(undefined, undefined, this.locationHash);
|
||||
}
|
||||
};
|
||||
|
||||
render = () => {
|
||||
|
@ -37,7 +37,8 @@ export default class TileManager {
|
||||
this.scene = scene;
|
||||
this.tileSize = new Vector2(tileSize.x, tileSize.z);
|
||||
|
||||
this.tile = new Vector2(position.x, position.z);
|
||||
this.tile = new Vector2(0, 0);
|
||||
this.tile.set(position.x, position.z).divide(this.tileSize).floor();
|
||||
this.lastTile = this.tile.clone();
|
||||
|
||||
this.closed = false;
|
||||
|
@ -70,6 +70,10 @@ maps: [
|
||||
# The path to the save-folder of the world to render
|
||||
world: "world"
|
||||
|
||||
# The position on the world where the map will be centered if you open it.
|
||||
# This defaults to the world-spawn if you don't set it.
|
||||
#startPos: [500, -820]
|
||||
|
||||
# If this is false, BlueMap tries to omit all blocks that are not visible from above-ground.
|
||||
# More specific: Block-Faces that have a sunlight/skylight value of 0 are removed.
|
||||
# This improves the performance of the map on slower devices by a lot, but might cause some blocks to disappear that should normally be visible.
|
||||
|
Loading…
Reference in New Issue
Block a user