mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2025-02-02 13:41:21 +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 {
|
||||
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.ParseException;
|
||||
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.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.MainConfig;
|
||||
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();
|
||||
resourcePack.saveTextureFile(textureExportFile);
|
||||
|
||||
RenderManager renderManager = new RenderManager(config.getRenderThreadCount());
|
||||
renderManager.start();
|
||||
|
||||
for (MapType map : maps.values()) {
|
||||
Logger.global.logInfo("Rendering map '" + map.getId() + "' ...");
|
||||
Logger.global.logInfo("Collecting tiles to render...");
|
||||
@ -173,8 +181,46 @@ public void renderMaps() throws IOException {
|
||||
Logger.global.logInfo("Starting Render...");
|
||||
long starttime = System.currentTimeMillis();
|
||||
|
||||
RenderTask task = new RenderTask(map, tiles, config.getRenderThreadCount());
|
||||
task.render();
|
||||
RenderTask task = new RenderTask("Map-Render: " + map.getName(), map);
|
||||
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 {
|
||||
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...");
|
||||
if (!ForkJoinPool.commonPool().awaitQuiescence(30, TimeUnit.SECONDS)) {
|
||||
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