mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2025-02-09 00:51:30 +01:00
Make CLI use some classes from common and remove the obsolete ones
This commit is contained in:
parent
5dc59b454b
commit
0b8624d54e
@ -1,4 +1,4 @@
|
|||||||
dependencies {
|
dependencies {
|
||||||
compile group: 'commons-cli', name: 'commons-cli', version: '1.4'
|
compile group: 'commons-cli', name: 'commons-cli', version: '1.4'
|
||||||
compile project(':BlueMapCore')
|
compile project(':BlueMapCommon')
|
||||||
}
|
}
|
||||||
|
@ -45,10 +45,15 @@
|
|||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.commons.lang3.time.DurationFormatUtils;
|
||||||
|
|
||||||
|
import com.flowpowered.math.GenericMath;
|
||||||
import com.flowpowered.math.vector.Vector2i;
|
import com.flowpowered.math.vector.Vector2i;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.common.MapType;
|
||||||
|
import de.bluecolored.bluemap.common.RenderManager;
|
||||||
|
import de.bluecolored.bluemap.common.RenderTask;
|
||||||
import de.bluecolored.bluemap.core.config.ConfigManager;
|
import de.bluecolored.bluemap.core.config.ConfigManager;
|
||||||
import de.bluecolored.bluemap.core.config.MainConfig;
|
import de.bluecolored.bluemap.core.config.MainConfig;
|
||||||
import de.bluecolored.bluemap.core.config.MainConfig.MapConfig;
|
import de.bluecolored.bluemap.core.config.MainConfig.MapConfig;
|
||||||
@ -147,6 +152,9 @@ public void renderMaps() throws IOException {
|
|||||||
File textureExportFile = config.getWebDataPath().resolve("textures.json").toFile();
|
File textureExportFile = config.getWebDataPath().resolve("textures.json").toFile();
|
||||||
resourcePack.saveTextureFile(textureExportFile);
|
resourcePack.saveTextureFile(textureExportFile);
|
||||||
|
|
||||||
|
RenderManager renderManager = new RenderManager(config.getRenderThreadCount());
|
||||||
|
renderManager.start();
|
||||||
|
|
||||||
for (MapType map : maps.values()) {
|
for (MapType map : maps.values()) {
|
||||||
Logger.global.logInfo("Rendering map '" + map.getId() + "' ...");
|
Logger.global.logInfo("Rendering map '" + map.getId() + "' ...");
|
||||||
Logger.global.logInfo("Collecting tiles to render...");
|
Logger.global.logInfo("Collecting tiles to render...");
|
||||||
@ -173,8 +181,46 @@ public void renderMaps() throws IOException {
|
|||||||
Logger.global.logInfo("Starting Render...");
|
Logger.global.logInfo("Starting Render...");
|
||||||
long starttime = System.currentTimeMillis();
|
long starttime = System.currentTimeMillis();
|
||||||
|
|
||||||
RenderTask task = new RenderTask(map, tiles, config.getRenderThreadCount());
|
RenderTask task = new RenderTask("Map-Render: " + map.getName(), map);
|
||||||
task.render();
|
task.addTiles(tiles);
|
||||||
|
task.optimizeQueue();
|
||||||
|
|
||||||
|
renderManager.addRenderTask(task);
|
||||||
|
|
||||||
|
long lastLogUpdate = System.currentTimeMillis();
|
||||||
|
long lastSave = lastLogUpdate;
|
||||||
|
|
||||||
|
while(!task.isFinished()) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(200);
|
||||||
|
} catch (InterruptedException e) {}
|
||||||
|
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
|
if (lastLogUpdate < now - 10000) { // print update all 10 seconds
|
||||||
|
lastLogUpdate = now;
|
||||||
|
long time = task.getActiveTime();
|
||||||
|
|
||||||
|
String durationString = DurationFormatUtils.formatDurationWords(time, true, true);
|
||||||
|
int tileCount = task.getRemainingTileCount() + task.getRenderedTileCount();
|
||||||
|
double pct = (double)task.getRenderedTileCount() / (double) tileCount;
|
||||||
|
|
||||||
|
long ert = (long)((time / pct) * (1d - pct));
|
||||||
|
String ertDurationString = DurationFormatUtils.formatDurationWords(ert, true, true);
|
||||||
|
|
||||||
|
double tps = task.getRenderedTileCount() / (time / 1000.0);
|
||||||
|
|
||||||
|
Logger.global.logInfo("Rendered " + task.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
|
||||||
|
lastSave = now;
|
||||||
|
map.getTileRenderer().save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
map.getTileRenderer().save();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
webSettings.set(starttime, map.getId(), "last-render");
|
webSettings.set(starttime, map.getId(), "last-render");
|
||||||
@ -184,6 +230,8 @@ public void renderMaps() throws IOException {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderManager.stop();
|
||||||
|
|
||||||
Logger.global.logInfo("Waiting for all threads to quit...");
|
Logger.global.logInfo("Waiting for all threads to quit...");
|
||||||
if (!ForkJoinPool.commonPool().awaitQuiescence(30, TimeUnit.SECONDS)) {
|
if (!ForkJoinPool.commonPool().awaitQuiescence(30, TimeUnit.SECONDS)) {
|
||||||
Logger.global.logWarning("Some save-threads are taking very long to exit (>30s), they will be ignored.");
|
Logger.global.logWarning("Some save-threads are taking very long to exit (>30s), they will be ignored.");
|
||||||
|
@ -1,91 +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.cli;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import com.flowpowered.math.vector.Vector2i;
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.render.TileRenderer;
|
|
||||||
import de.bluecolored.bluemap.core.render.WorldTile;
|
|
||||||
import de.bluecolored.bluemap.core.world.World;
|
|
||||||
|
|
||||||
public class MapType {
|
|
||||||
|
|
||||||
private final String id;
|
|
||||||
private String name;
|
|
||||||
private World world;
|
|
||||||
private TileRenderer tileRenderer;
|
|
||||||
|
|
||||||
public MapType(String id, String name, World world, TileRenderer tileRenderer) {
|
|
||||||
Preconditions.checkNotNull(id);
|
|
||||||
Preconditions.checkNotNull(name);
|
|
||||||
Preconditions.checkNotNull(world);
|
|
||||||
Preconditions.checkNotNull(tileRenderer);
|
|
||||||
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this.world = world;
|
|
||||||
this.tileRenderer = tileRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public World getWorld() {
|
|
||||||
return world;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TileRenderer getTileRenderer() {
|
|
||||||
return tileRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void renderTile(Vector2i tile) throws IOException {
|
|
||||||
getTileRenderer().render(new WorldTile(getWorld(), tile));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return id.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (obj != null && obj instanceof MapType) {
|
|
||||||
MapType that = (MapType) obj;
|
|
||||||
|
|
||||||
return this.id.equals(that.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,171 +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.cli;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayDeque;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Deque;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.time.DurationFormatUtils;
|
|
||||||
|
|
||||||
import com.flowpowered.math.GenericMath;
|
|
||||||
import com.flowpowered.math.vector.Vector2d;
|
|
||||||
import com.flowpowered.math.vector.Vector2i;
|
|
||||||
|
|
||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
|
||||||
import de.bluecolored.bluemap.core.render.TileRenderer;
|
|
||||||
import de.bluecolored.bluemap.core.render.WorldTile;
|
|
||||||
import de.bluecolored.bluemap.core.world.World;
|
|
||||||
|
|
||||||
public class RenderTask {
|
|
||||||
|
|
||||||
private World world;
|
|
||||||
private TileRenderer tileRenderer;
|
|
||||||
private Deque<Vector2i> tilesToRender;
|
|
||||||
|
|
||||||
private int tileCount;
|
|
||||||
private long startTime = -1;
|
|
||||||
private int renderedTiles = 0;
|
|
||||||
|
|
||||||
private Thread[] threads;
|
|
||||||
|
|
||||||
public RenderTask(MapType map, Collection<Vector2i> tilesToRender, int threadCount) {
|
|
||||||
this.world = map.getWorld();
|
|
||||||
this.tileRenderer = map.getTileRenderer();
|
|
||||||
|
|
||||||
//Sort the chunks to opimize the chunk-cache usage of MCAWorld and generate the world in a nicer order, so you can see the first results early in the web-map during render
|
|
||||||
Vector2d sortGridSize = new Vector2d(20, 20).div(tileRenderer.getHiresModelManager().getTileSize().toDouble().div(16)).ceil().max(1, 1); //Find a good grid size to match the MCAWorlds chunk-cache size of 500
|
|
||||||
ArrayList<Vector2i> sortedTiles = new ArrayList<>(tilesToRender);
|
|
||||||
sortedTiles.sort((v1, v2) -> {
|
|
||||||
Vector2i v1SortGridPos = v1.toDouble().div(sortGridSize).floor().toInt();
|
|
||||||
Vector2i v2SortGridPos = v2.toDouble().div(sortGridSize).floor().toInt();
|
|
||||||
|
|
||||||
if (v1SortGridPos != v2SortGridPos){
|
|
||||||
int v1Dist = v1SortGridPos.distanceSquared(Vector2i.ZERO);
|
|
||||||
int v2Dist = v2SortGridPos.distanceSquared(Vector2i.ZERO);
|
|
||||||
|
|
||||||
if (v1Dist < v2Dist) return -1;
|
|
||||||
if (v1Dist > v2Dist) return 1;
|
|
||||||
|
|
||||||
if (v1SortGridPos.getY() < v2SortGridPos.getY()) return -1;
|
|
||||||
if (v1SortGridPos.getY() > v2SortGridPos.getY()) return 1;
|
|
||||||
if (v1SortGridPos.getX() < v2SortGridPos.getX()) return -1;
|
|
||||||
if (v1SortGridPos.getX() > v2SortGridPos.getX()) return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v1.getY() < v2.getY()) return -1;
|
|
||||||
if (v1.getY() > v2.getY()) return 1;
|
|
||||||
if (v1.getX() < v2.getX()) return -1;
|
|
||||||
if (v1.getX() > v2.getX()) return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.tilesToRender = new ArrayDeque<>(sortedTiles);
|
|
||||||
|
|
||||||
this.tileCount = this.tilesToRender.size();
|
|
||||||
this.threads = new Thread[threadCount];
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void render() {
|
|
||||||
this.startTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
for (int i = 0; i < threads.length; i++) {
|
|
||||||
if (threads[i] != null) threads[i].interrupt();
|
|
||||||
|
|
||||||
threads[i] = new Thread(this::renderThread);
|
|
||||||
threads[i].start();
|
|
||||||
}
|
|
||||||
|
|
||||||
long lastLogUpdate = startTime;
|
|
||||||
long lastSave = startTime;
|
|
||||||
|
|
||||||
while (!Thread.interrupted()) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean stillRendering = false;
|
|
||||||
for (Thread t : threads) {
|
|
||||||
if (t.isAlive()) {
|
|
||||||
stillRendering = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!stillRendering) break;
|
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
if (lastLogUpdate < now - 10000) { // print update all 10 seconds
|
|
||||||
lastLogUpdate = now;
|
|
||||||
|
|
||||||
long time = now - startTime;
|
|
||||||
String durationString = DurationFormatUtils.formatDurationWords(time, true, true);
|
|
||||||
double pct = (double)renderedTiles / (double)tileCount;
|
|
||||||
|
|
||||||
long ert = (long)((time / pct) * (1d - pct));
|
|
||||||
String ertDurationString = DurationFormatUtils.formatDurationWords(ert, true, true);
|
|
||||||
|
|
||||||
double tps = renderedTiles / (time / 1000.0);
|
|
||||||
|
|
||||||
Logger.global.logInfo("Rendered " + renderedTiles + " 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
|
|
||||||
lastSave = now;
|
|
||||||
tileRenderer.save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tileRenderer.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderThread() {
|
|
||||||
Vector2i tilePos;
|
|
||||||
|
|
||||||
while (!Thread.interrupted()) {
|
|
||||||
synchronized (tilesToRender) {
|
|
||||||
if (tilesToRender.isEmpty()) break;
|
|
||||||
tilePos = tilesToRender.poll();
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldTile tile = new WorldTile(world, tilePos);
|
|
||||||
try {
|
|
||||||
tileRenderer.render(tile);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Logger.global.logError("Failed to render tile " + tilePos, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderedTiles++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user