Skip to content

Commit 2ed2fa3

Browse files
committed
Add click menu and debug option to web-app and fix two render-saving bugs that caused corrupted files sometimes
1 parent dde30e9 commit 2ed2fa3

File tree

20 files changed

+287
-34
lines changed

20 files changed

+287
-34
lines changed

BlueMapCLI/src/main/java/de/bluecolored/bluemap/cli/BlueMapCLI.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@
4040
import java.util.List;
4141
import java.util.Map;
4242
import java.util.UUID;
43-
import java.util.concurrent.ForkJoinPool;
44-
import java.util.concurrent.TimeUnit;
4543
import java.util.zip.GZIPInputStream;
4644
import java.util.zip.GZIPOutputStream;
4745

@@ -122,8 +120,7 @@ public void renderMaps() throws IOException {
122120
config.getWebDataPath().resolve(mapConfig.getId()).resolve("hires"),
123121
resourcePack,
124122
mapConfig,
125-
new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize()),
126-
ForkJoinPool.commonPool()
123+
new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize())
127124
);
128125

129126
LowresModelManager lowresModelManager = new LowresModelManager(
@@ -224,6 +221,8 @@ public void renderMaps() throws IOException {
224221

225222
if (lastLogUpdate < now - 10000) { // print update all 10 seconds
226223
RenderTask currentTask = renderManager.getCurrentRenderTask();
224+
if (currentTask == null) continue;
225+
227226
lastLogUpdate = now;
228227
long time = currentTask.getActiveTime();
229228

@@ -243,6 +242,7 @@ public void renderMaps() throws IOException {
243242

244243
if (lastSave < now - 1 * 60000) { // save every minute
245244
RenderTask currentTask = renderManager.getCurrentRenderTask();
245+
if (currentTask == null) continue;
246246

247247
lastSave = now;
248248
currentTask.getMapType().getTileRenderer().save();
@@ -272,11 +272,6 @@ public void renderMaps() throws IOException {
272272
} catch (IOException e) {
273273
Logger.global.logError("Failed to update web-settings!", e);
274274
}
275-
276-
Logger.global.logInfo("Waiting for all threads to quit ...");
277-
if (!ForkJoinPool.commonPool().awaitQuiescence(30, TimeUnit.SECONDS)) {
278-
Logger.global.logWarning("Some save-threads are taking very long to exit (>30s), they will be ignored.");
279-
}
280275

281276
Logger.global.logInfo("Render finished!");
282277
}

BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/RenderManager.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ public synchronized void start() {
4141

4242
for (int i = 0; i < renderThreads.length; i++) {
4343
renderThreads[i] = new Thread(this::renderThread);
44-
renderThreads[i].setDaemon(true);
4544
renderThreads[i].setPriority(Thread.MIN_PRIORITY);
4645
renderThreads[i].start();
4746
}

BlueMapCommon/src/main/java/de/bluecolored/bluemap/common/plugin/Plugin.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import java.util.List;
1515
import java.util.Map;
1616
import java.util.UUID;
17-
import java.util.concurrent.ForkJoinPool;
1817
import java.util.concurrent.TimeUnit;
1918
import java.util.zip.GZIPInputStream;
2019
import java.util.zip.GZIPOutputStream;
@@ -184,8 +183,7 @@ public synchronized void load() throws IOException, ParseResourceException {
184183
config.getWebDataPath().resolve(id).resolve("hires"),
185184
resourcePack,
186185
mapConfig,
187-
new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize()),
188-
ForkJoinPool.commonPool()
186+
new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize())
189187
);
190188

191189
LowresModelManager lowresModelManager = new LowresModelManager(

BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/hires/HiresModelManager.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import java.util.Collection;
3636
import java.util.HashSet;
3737
import java.util.Set;
38-
import java.util.concurrent.ExecutorService;
3938
import java.util.zip.GZIPOutputStream;
4039

4140
import com.flowpowered.math.vector.Vector2i;
@@ -57,22 +56,19 @@ public class HiresModelManager {
5756
private Vector2i tileSize;
5857
private Vector2i gridOrigin;
5958

60-
private ExecutorService savingExecutor;
61-
6259
private boolean useGzip;
6360

64-
public HiresModelManager(Path fileRoot, ResourcePack resourcePack, RenderSettings renderSettings, Vector2i tileSize, ExecutorService savingExecutor) {
65-
this(fileRoot, new HiresModelRenderer(resourcePack, renderSettings), tileSize, new Vector2i(2, 2), savingExecutor, renderSettings.useGzipCompression());
61+
public HiresModelManager(Path fileRoot, ResourcePack resourcePack, RenderSettings renderSettings, Vector2i tileSize) {
62+
this(fileRoot, new HiresModelRenderer(resourcePack, renderSettings), tileSize, new Vector2i(2, 2), renderSettings.useGzipCompression());
6663
}
6764

68-
public HiresModelManager(Path fileRoot, HiresModelRenderer renderer, Vector2i tileSize, Vector2i gridOrigin, ExecutorService savingExecutor, boolean useGzip) {
65+
public HiresModelManager(Path fileRoot, HiresModelRenderer renderer, Vector2i tileSize, Vector2i gridOrigin, boolean useGzip) {
6966
this.fileRoot = fileRoot;
7067
this.renderer = renderer;
7168

7269
this.tileSize = tileSize;
7370
this.gridOrigin = gridOrigin;
7471

75-
this.savingExecutor = savingExecutor;
7672
this.useGzip = useGzip;
7773
}
7874

@@ -87,7 +83,7 @@ public HiresModel render(WorldTile tile) {
8783

8884
private void save(final HiresModel model) {
8985
final String modelJson = model.toBufferGeometry().toJson();
90-
savingExecutor.submit(() -> save(model, modelJson));
86+
save(model, modelJson);
9187
}
9288

9389
private void save(HiresModel model, String modelJson){

BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/lowres/LowresModel.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ public void save(File file, boolean force, boolean useGzip) throws IOException {
126126
PrintWriter pw = new PrintWriter(osw);
127127
){
128128
pw.print(json);
129+
pw.flush();
129130
}
130131

131132
}

BlueMapCore/src/main/java/de/bluecolored/bluemap/core/render/lowres/LowresModelManager.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,16 @@ private LowresModel getModel(UUID world, Vector2i tile) {
195195
model = new CachedModel(world, tile, BufferGeometry.fromJson(json));
196196
} catch (IllegalArgumentException | IOException ex){
197197
Logger.global.logError("Failed to load lowres model: " + modelFile, ex);
198+
198199
modelFile.delete();
200+
201+
/*
202+
File brokenFile = modelFile.toPath().getParent().resolve(modelFile.getName() + ".broken").toFile();
203+
if (brokenFile.exists()) brokenFile.delete();
204+
if (!modelFile.renameTo(brokenFile)) {
205+
modelFile.delete();
206+
}
207+
*/
199208
}
200209
}
201210

BlueMapCore/src/main/webroot/js/libs/BlueMap.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export default class BlueMap {
7777
this.skyColor = {
7878
value: new Vector3(0, 0, 0)
7979
};
80+
this.debugInfo = false;
8081

8182
this.ui = new UI(this);
8283

@@ -139,6 +140,7 @@ export default class BlueMap {
139140
this.loadLowresTile,
140141
this.lowresScene,
141142
this.settings.maps[this.map]['lowres']['tileSize'],
143+
this.settings.maps[this.map]['lowres']['translate'],
142144
startPos
143145
);
144146

@@ -148,6 +150,7 @@ export default class BlueMap {
148150
this.loadHiresTile,
149151
this.hiresScene,
150152
this.settings.maps[this.map]['hires']['tileSize'],
153+
this.settings.maps[this.map]['hires']['translate'],
151154
startPos
152155
);
153156

@@ -349,6 +352,7 @@ export default class BlueMap {
349352
this.quality = this.loadUserSetting("renderQuality", this.quality);
350353
this.hiresViewDistance = this.loadUserSetting("hiresViewDistance", this.hiresViewDistance);
351354
this.lowresViewDistance = this.loadUserSetting("lowresViewDistance", this.lowresViewDistance);
355+
this.debugInfo = this.loadUserSetting("debugInfo", this.debugInfo);
352356
}
353357

354358
saveUserSettings(){
@@ -361,6 +365,7 @@ export default class BlueMap {
361365
this.saveUserSetting("renderQuality", this.quality);
362366
this.saveUserSetting("hiresViewDistance", this.hiresViewDistance);
363367
this.saveUserSetting("lowresViewDistance", this.lowresViewDistance);
368+
this.saveUserSetting("debugInfo", this.debugInfo);
364369
}
365370

366371
loadUserSetting(key, defaultValue){

BlueMapCore/src/main/webroot/js/libs/Controls.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export default class Controls {
100100

101101
this.keyStates = {};
102102
this.state = Controls.STATES.NONE;
103+
this.mouseMoved = false;
103104

104105
let canvas = $(this.element).find('canvas').get(0);
105106

@@ -116,6 +117,7 @@ export default class Controls {
116117

117118
// touch events
118119
this.hammer = new Hammer.Manager(canvas);
120+
let touchTap = new Hammer.Tap({ event: 'tap', pointers: 1, taps: 1, threshold: 2 });
119121
let touchMove = new Hammer.Pan({ event: 'move', direction: Hammer.DIRECTION_ALL, threshold: 0 });
120122
let touchTilt = new Hammer.Pan({ event: 'tilt', direction: Hammer.DIRECTION_VERTICAL, pointers: 2, threshold: 0 });
121123
let touchRotate = new Hammer.Rotate({ event: 'rotate', pointers: 2, threshold: 10 });
@@ -125,6 +127,7 @@ export default class Controls {
125127
touchTilt.recognizeWith(touchZoom);
126128
touchRotate.recognizeWith(touchZoom);
127129

130+
this.hammer.add( touchTap );
128131
this.hammer.add( touchMove );
129132
this.hammer.add( touchTilt );
130133
this.hammer.add( touchRotate );
@@ -144,6 +147,7 @@ export default class Controls {
144147
this.hammer.on('rotatecancel', this.onTouchRotateUp);
145148
this.hammer.on('zoomstart', this.onTouchZoomDown);
146149
this.hammer.on('zoommove', this.onTouchZoomMove);
150+
this.hammer.on('tap', this.onInfoClick);
147151

148152
this.camera.position.set(0, 1000, 0);
149153
this.camera.lookAt(this.position);
@@ -429,4 +433,11 @@ export default class Controls {
429433
onKeyUp = event => {
430434
this.keyStates[event.keyCode] = false;
431435
};
436+
437+
onInfoClick = event => {
438+
$(document).trigger({
439+
type: 'bluemap-info-click',
440+
pos: event.center
441+
});
442+
}
432443
}

BlueMapCore/src/main/webroot/js/libs/TileManager.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ import Tile from './Tile.js';
3030
import { hashTile } from './utils.js';
3131

3232
export default class TileManager {
33-
constructor(blueMap, viewDistance, tileLoader, scene, tileSize, position) {
33+
constructor(blueMap, viewDistance, tileLoader, scene, tileSize, tileOffset, position) {
3434
this.blueMap = blueMap;
3535
this.tileSize = new Vector2(tileSize.x, tileSize.z);
36+
this.tileOffset = new Vector2(tileOffset.x, tileOffset.z);
3637
this.setViewDistance(viewDistance);
3738
this.tileLoader = tileLoader;
3839
this.scene = scene;
@@ -54,7 +55,7 @@ export default class TileManager {
5455
}
5556

5657
setPosition(center) {
57-
this.tile.set(center.x, center.z).divide(this.tileSize).floor();
58+
this.tile.set(center.x, center.z).sub(this.tileOffset).divide(this.tileSize).floor();
5859

5960
if (!this.tile.equals(this.lastTile) && !this.closed) {
6061
this.update();
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import $ from 'jquery';
2+
import {
3+
Raycaster,
4+
Vector2
5+
} from 'three';
6+
import {pathFromCoords} from "../utils";
7+
8+
export default class HudInfo {
9+
10+
constructor(blueMap, container){
11+
this.blueMap = blueMap;
12+
this.container = container;
13+
14+
this.rayPosition = new Vector2();
15+
this.raycaster = new Raycaster();
16+
17+
this.element = $(`
18+
<div class="hud-info" style="display: none">
19+
<div class="content"></div>
20+
</div>
21+
`).appendTo(this.container);
22+
23+
$(document).on('bluemap-info-click', this.onShowInfo);
24+
$(window).on('mousedown wheel', this.onHideInfo);
25+
}
26+
27+
onShowInfo = event => {
28+
this.rayPosition.x = ( event.pos.x / this.blueMap.element.offsetWidth ) * 2 - 1;
29+
this.rayPosition.y = - ( event.pos.y / this.blueMap.element.offsetHeight ) * 2 + 1;
30+
31+
this.raycaster.setFromCamera(this.rayPosition, this.blueMap.camera);
32+
let hiresData = true;
33+
let intersects = this.raycaster.intersectObjects( this.blueMap.hiresScene.children );
34+
if (intersects.length === 0){
35+
hiresData = false;
36+
intersects = this.raycaster.intersectObjects( this.blueMap.lowresScene.children );
37+
}
38+
39+
if (intersects.length > 0) {
40+
this.element.hide();
41+
let content = this.element.find(".content");
42+
content.html("");
43+
44+
if (this.blueMap.debugInfo){
45+
console.debug("Tapped position data: ", intersects[0]);
46+
}
47+
48+
//clicked position
49+
let point = intersects[0].point;
50+
let normal = intersects[0].face.normal;
51+
let block = {
52+
x: Math.floor(point.x - normal.x * 0.001),
53+
y: Math.floor(point.y - normal.y * 0.001),
54+
z: Math.floor(point.z - normal.z * 0.001),
55+
};
56+
if (hiresData) {
57+
$(`
58+
<div class="label">block:</div>
59+
<div class="coords block">
60+
<div class="coord"><span class="label">x</span><span class="value">${block.x}</span></div>
61+
<div class="coord"><span class="label">y</span><span class="value">${block.y}</span></div>
62+
<div class="coord"><span class="label">z</span><span class="value">${block.z}</span></div>
63+
</div>
64+
`).appendTo(content);
65+
} else {
66+
$(`
67+
<div class="label">position:</div>
68+
<div class="coords block">
69+
<div class="coord"><span class="label">x</span><span class="value">${block.x}</span></div>
70+
<div class="coord"><span class="label">z</span><span class="value">${block.z}</span></div>
71+
</div>
72+
`).appendTo(content);
73+
}
74+
75+
//find light-data
76+
if (hiresData) {
77+
let vecIndex = intersects[0].face.a;
78+
let attributes = intersects[0].object.geometry.attributes;
79+
let sunlight = attributes.sunlight.array[vecIndex * attributes.sunlight.itemSize];
80+
let blocklight = attributes.blocklight.array[vecIndex * attributes.blocklight.itemSize];
81+
82+
$(`
83+
<div class="label" data-show="light">light:</div>
84+
<div class="coords block">
85+
<div class="coord"><span class="label">sun</span><span class="value">${sunlight}</span></div>
86+
<div class="coord"><span class="label">block</span><span class="value">${blocklight}</span></div>
87+
</div>
88+
`).appendTo(content);
89+
}
90+
91+
if (this.blueMap.debugInfo) {
92+
//hires tile path
93+
let hiresTileSize = this.blueMap.settings.maps[this.blueMap.map]['hires']['tileSize'];
94+
hiresTileSize.y = hiresTileSize.z;
95+
let hiresTileOffset = this.blueMap.settings.maps[this.blueMap.map]['hires']['translate'];
96+
hiresTileOffset.y = hiresTileOffset.z;
97+
let hiresTile = new Vector2(block.x, block.z).sub(hiresTileOffset).divide(hiresTileSize).floor();
98+
let hrpath = this.blueMap.dataRoot + this.blueMap.map + '/hires/';
99+
hrpath += pathFromCoords(hiresTile.x, hiresTile.y);
100+
hrpath += '.json';
101+
102+
//lowres tile path
103+
let lowresTileSize = this.blueMap.settings.maps[this.blueMap.map]['lowres']['tileSize'];
104+
lowresTileSize.y = lowresTileSize.z;
105+
let lowresTileOffset = this.blueMap.settings.maps[this.blueMap.map]['lowres']['translate'];
106+
lowresTileOffset.y = lowresTileOffset.z;
107+
let lowresTile = new Vector2(block.x, block.z).sub(lowresTileOffset).divide(lowresTileSize).floor();
108+
let lrpath = this.blueMap.dataRoot + this.blueMap.map + '/lowres/';
109+
lrpath += pathFromCoords(lowresTile.x, lowresTile.y);
110+
lrpath += '.json';
111+
$(`
112+
<div class="files">
113+
<span class="value">${hrpath}</span><br>
114+
<span class="value">${lrpath}</span>
115+
</div>
116+
`).appendTo(content);
117+
}
118+
119+
//display the element
120+
this.element.css('left', `${event.pos.x}px`);
121+
this.element.css('top', `${event.pos.y}px`);
122+
if (event.pos.y < this.blueMap.element.offsetHeight / 3){
123+
this.element.addClass("below");
124+
} else {
125+
this.element.removeClass("below");
126+
}
127+
this.element.fadeIn(200);
128+
}
129+
130+
};
131+
132+
onHideInfo = event => {
133+
if (!this.element.is(':animated')) {
134+
this.element.fadeOut(200);
135+
}
136+
};
137+
138+
};

0 commit comments

Comments
 (0)