mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-11-24 03:25:17 +01:00
Merge branch 'master' into mc/1.12
This commit is contained in:
commit
eac678669b
2
.github/workflows/gradle.yml
vendored
2
.github/workflows/gradle.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
|||||||
- name: Test with Gradle
|
- name: Test with Gradle
|
||||||
run: ./gradlew test
|
run: ./gradlew test
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew shadowJar
|
run: ./gradlew build
|
||||||
- uses: actions/upload-artifact@v1
|
- uses: actions/upload-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: artifact
|
name: artifact
|
||||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -20,6 +20,9 @@ bin/*
|
|||||||
.project
|
.project
|
||||||
*/.project
|
*/.project
|
||||||
|
|
||||||
|
node_modules/
|
||||||
|
package-lock.json
|
||||||
|
|
||||||
# exclude generated resource
|
# exclude generated resource
|
||||||
BlueMapCore/src/main/resources/webroot.zip
|
BlueMapCore/src/main/resources/webroot.zip
|
||||||
BlueMapCore/src/main/resources/resourceExtensions.zip
|
BlueMapCore/src/main/resources/resourceExtensions.zip
|
||||||
|
@ -1,24 +1,57 @@
|
|||||||
|
plugins {
|
||||||
|
id 'com.moowork.node' version '1.3.1'
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.google.guava:guava:21.0'
|
compile 'com.google.guava:guava:21.0'
|
||||||
compile 'com.google.code.gson:gson:2.8.0'
|
compile 'com.google.code.gson:gson:2.8.0'
|
||||||
compile 'org.apache.commons:commons-lang3:3.5'
|
compile 'org.apache.commons:commons-lang3:3.5'
|
||||||
compile group: 'commons-io', name: 'commons-io', version: '2.6'
|
compile group: 'commons-io', name: 'commons-io', version: '2.6'
|
||||||
compile 'com.flowpowered:flow-math:1.0.3'
|
compile 'com.flowpowered:flow-math:1.0.3'
|
||||||
compile 'ninja.leaping.configurate:configurate-hocon:3.3'
|
compile 'ninja.leaping.configurate:configurate-hocon:3.3'
|
||||||
compile 'ninja.leaping.configurate:configurate-gson:3.3'
|
compile 'ninja.leaping.configurate:configurate-gson:3.3'
|
||||||
compile 'ninja.leaping.configurate:configurate-yaml:3.3'
|
compile 'ninja.leaping.configurate:configurate-yaml:3.3'
|
||||||
compile 'com.github.Querz:NBT:4.0'
|
compile 'com.github.Querz:NBT:4.0'
|
||||||
|
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
|
}
|
||||||
|
|
||||||
|
node {
|
||||||
|
version = '12.14.1'
|
||||||
|
download = true
|
||||||
|
}
|
||||||
|
|
||||||
|
task fixPackageLock() {
|
||||||
|
if (!file("./package-lock.json").exists()) {
|
||||||
|
file("./package-lock.json").text = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanWebroot(type: Delete) {
|
||||||
|
delete 'build/generated/webroot/'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run WebPack build to generate resources into the generated resources
|
||||||
|
task webpackWebroot(type: NpmTask) {
|
||||||
|
args = ['run', 'build']
|
||||||
}
|
}
|
||||||
|
|
||||||
task zipWebroot(type: Zip) {
|
task zipWebroot(type: Zip) {
|
||||||
from fileTree('src/main/webroot')
|
from fileTree('build/generated/webroot/')
|
||||||
archiveName 'webroot.zip'
|
archiveName 'webroot.zip'
|
||||||
destinationDir(file('src/main/resources/'))
|
destinationDir(file('src/main/resources/'))
|
||||||
outputs.upToDateWhen { false }
|
outputs.upToDateWhen { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// removes tmp build directory, build project with webpack, zip contents for the shaded jar
|
||||||
|
task buildWebroot {
|
||||||
|
dependsOn 'fixPackageLock'
|
||||||
|
dependsOn 'npmInstall'
|
||||||
|
dependsOn 'cleanWebroot'
|
||||||
|
dependsOn 'webpackWebroot'
|
||||||
|
dependsOn 'zipWebroot'
|
||||||
|
}
|
||||||
|
|
||||||
task zipResourceExtensions(type: Zip) {
|
task zipResourceExtensions(type: Zip) {
|
||||||
from fileTree('src/main/resourceExtensions')
|
from fileTree('src/main/resourceExtensions')
|
||||||
archiveName 'resourceExtensions.zip'
|
archiveName 'resourceExtensions.zip'
|
||||||
@ -27,5 +60,5 @@ task zipResourceExtensions(type: Zip) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//always update the zip before build
|
//always update the zip before build
|
||||||
compileJava.dependsOn(zipWebroot)
|
processResources.dependsOn(buildWebroot)
|
||||||
compileJava.dependsOn(zipResourceExtensions)
|
processResources.dependsOn(zipResourceExtensions)
|
||||||
|
42
BlueMapCore/package.json
Normal file
42
BlueMapCore/package.json
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"name": "bluemap",
|
||||||
|
"description": "BlueMap is a tool that generates 3d-maps of your Minecraft worlds and displays them in your browser.",
|
||||||
|
"private": true,
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/BlueMap-Minecraft/BlueMap.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"minecraft"
|
||||||
|
],
|
||||||
|
"author": "Blue",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/BlueMap-Minecraft/BlueMap/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/BlueMap-Minecraft/BlueMap#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"jquery": "^3.4.1",
|
||||||
|
"three": "^0.94.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"css-loader": "^3.4.2",
|
||||||
|
"fibers": "^4.0.2",
|
||||||
|
"file-loader": "^5.0.2",
|
||||||
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
"mini-css-extract-plugin": "^0.9.0",
|
||||||
|
"node-sass": "^4.13.0",
|
||||||
|
"sass": "^1.24.4",
|
||||||
|
"sass-loader": "^8.0.2",
|
||||||
|
"ts-loader": "^6.2.1",
|
||||||
|
"typescript": "^3.7.4",
|
||||||
|
"webpack": "^4.41.5",
|
||||||
|
"webpack-cli": "^3.3.10",
|
||||||
|
"webpack-dev-server": "^3.10.1"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "webpack --mode production",
|
||||||
|
"start": "webpack-dev-server --watch --mode development"
|
||||||
|
}
|
||||||
|
}
|
@ -34,38 +34,38 @@
|
|||||||
public class TileRenderer {
|
public class TileRenderer {
|
||||||
private HiresModelManager hiresModelManager;
|
private HiresModelManager hiresModelManager;
|
||||||
private LowresModelManager lowresModelManager;
|
private LowresModelManager lowresModelManager;
|
||||||
|
|
||||||
public TileRenderer(HiresModelManager hiresModelManager, LowresModelManager lowresModelManager) {
|
public TileRenderer(HiresModelManager hiresModelManager, LowresModelManager lowresModelManager) {
|
||||||
this.hiresModelManager = hiresModelManager;
|
this.hiresModelManager = hiresModelManager;
|
||||||
this.lowresModelManager = lowresModelManager;
|
this.lowresModelManager = lowresModelManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the provided WorldTile (only) if the world is generated
|
* Renders the provided WorldTile (only) if the world is generated
|
||||||
* @throws IOException If an IO-Exception occurs during the render
|
* @throws IOException If an IO-Exception occurs during the render
|
||||||
*/
|
*/
|
||||||
public void render(WorldTile tile) throws IOException {
|
public void render(WorldTile tile) throws IOException {
|
||||||
//check if the region is generated before rendering, don't render if it's not generated
|
//check if the region is generated before rendering, don't render if it's not generated
|
||||||
AABB area = hiresModelManager.getTileRegion(tile);
|
AABB area = hiresModelManager.getTileRegion(tile);
|
||||||
if (!tile.getWorld().isAreaGenerated(area)) return;
|
if (!tile.getWorld().isAreaGenerated(area)) return;
|
||||||
|
|
||||||
HiresModel hiresModel = hiresModelManager.render(tile);
|
HiresModel hiresModel = hiresModelManager.render(tile);
|
||||||
lowresModelManager.render(hiresModel);
|
lowresModelManager.render(hiresModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves changes to disk
|
* Saves changes to disk
|
||||||
*/
|
*/
|
||||||
public void save(){
|
public void save(){
|
||||||
lowresModelManager.save();
|
lowresModelManager.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public HiresModelManager getHiresModelManager() {
|
public HiresModelManager getHiresModelManager() {
|
||||||
return hiresModelManager;
|
return hiresModelManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LowresModelManager getLowresModelManager() {
|
public LowresModelManager getLowresModelManager() {
|
||||||
return lowresModelManager;
|
return lowresModelManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,10 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
<head>
|
||||||
<head>
|
<meta charset="utf-8">
|
||||||
<meta charset=utf-8>
|
<title>BlueMap</title>
|
||||||
<title>BlueMap</title>
|
</head>
|
||||||
|
<body>
|
||||||
<link rel="stylesheet" type="text/css" href="style/style.css?v=2">
|
<div id="map-container"></div>
|
||||||
|
</body>
|
||||||
<script src="js/libs/jquery.min.js"></script>
|
|
||||||
<script type="text/javascript" src="js/libs/three.min.js"></script>
|
|
||||||
<script type="text/javascript" src="js/libs/bluemap.js"></script>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="map-container"></div>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="js/site.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
483
BlueMapCore/src/main/webroot/js/libs/BlueMap.js
Normal file
483
BlueMapCore/src/main/webroot/js/libs/BlueMap.js
Normal file
@ -0,0 +1,483 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
import $ from 'jquery';
|
||||||
|
import {
|
||||||
|
AmbientLight,
|
||||||
|
BackSide,
|
||||||
|
BufferGeometryLoader,
|
||||||
|
ClampToEdgeWrapping,
|
||||||
|
CubeGeometry,
|
||||||
|
DirectionalLight,
|
||||||
|
FileLoader,
|
||||||
|
FrontSide,
|
||||||
|
Mesh,
|
||||||
|
MeshBasicMaterial,
|
||||||
|
MeshLambertMaterial,
|
||||||
|
NormalBlending,
|
||||||
|
NearestFilter,
|
||||||
|
PerspectiveCamera,
|
||||||
|
Scene,
|
||||||
|
Texture,
|
||||||
|
TextureLoader,
|
||||||
|
VertexColors,
|
||||||
|
WebGLRenderer,
|
||||||
|
} from 'three';
|
||||||
|
|
||||||
|
import Compass from './modules/Compass.js';
|
||||||
|
import Info from './modules/Info.js';
|
||||||
|
import MapMenu from './modules/MapMenu.js';
|
||||||
|
import Position from './modules/Position.js';
|
||||||
|
import Settings from './modules/Settings.js';
|
||||||
|
|
||||||
|
import Controls from './Controls.js';
|
||||||
|
import TileManager from './TileManager.js';
|
||||||
|
|
||||||
|
import { stringToImage, pathFromCoords } from './utils.js';
|
||||||
|
|
||||||
|
import SKYBOX_NORTH from '../../assets/skybox/north.png';
|
||||||
|
import SKYBOX_SOUTH from '../../assets/skybox/south.png';
|
||||||
|
import SKYBOX_EAST from '../../assets/skybox/east.png';
|
||||||
|
import SKYBOX_WEST from '../../assets/skybox/west.png';
|
||||||
|
import SKYBOX_UP from '../../assets/skybox/up.png';
|
||||||
|
import SKYBOX_DOWN from '../../assets/skybox/down.png';
|
||||||
|
|
||||||
|
export default class BlueMap {
|
||||||
|
constructor(element, dataRoot) {
|
||||||
|
this.element = element;
|
||||||
|
this.dataRoot = dataRoot;
|
||||||
|
|
||||||
|
this.loadingNoticeElement = $('<div id="bluemap-loading" class="box">loading...</div>').appendTo($(this.element));
|
||||||
|
|
||||||
|
this.fileLoader = new FileLoader();
|
||||||
|
this.blobLoader = new FileLoader();
|
||||||
|
this.blobLoader.setResponseType('blob');
|
||||||
|
this.bufferGeometryLoader = new BufferGeometryLoader();
|
||||||
|
|
||||||
|
this.initStage();
|
||||||
|
this.locationHash = '';
|
||||||
|
this.controls = new Controls(this.camera, this.element, this.hiresScene);
|
||||||
|
|
||||||
|
this.loadSettings().then(async () => {
|
||||||
|
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.initModules();
|
||||||
|
this.start();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initModules() {
|
||||||
|
this.modules = {};
|
||||||
|
this.modules.compass = new Compass(this);
|
||||||
|
this.modules.position = new Position(this);
|
||||||
|
this.modules.mapMenu = new MapMenu(this);
|
||||||
|
this.modules.info = new Info(this);
|
||||||
|
this.modules.settings = new Settings(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
changeMap(map) {
|
||||||
|
this.hiresTileManager.close();
|
||||||
|
this.lowresTileManager.close();
|
||||||
|
|
||||||
|
this.map = map;
|
||||||
|
this.controls.resetPosition();
|
||||||
|
|
||||||
|
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}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.lowresTileManager.update();
|
||||||
|
this.hiresTileManager.update();
|
||||||
|
|
||||||
|
document.dispatchEvent(new Event('bluemap-map-change'));
|
||||||
|
}
|
||||||
|
|
||||||
|
loadLocationHash() {
|
||||||
|
let hashVars = window.location.hash.substring(1).split(':');
|
||||||
|
if (hashVars.length >= 1){
|
||||||
|
if (this.settings[hashVars[0]] !== undefined && this.map !== hashVars[0]){
|
||||||
|
this.changeMap(hashVars[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hashVars.length >= 3){
|
||||||
|
let x = parseInt(hashVars[1]);
|
||||||
|
let z = parseInt(hashVars[2]);
|
||||||
|
if (!isNaN(x) && !isNaN(z)){
|
||||||
|
this.controls.targetPosition.x = x + 0.5;
|
||||||
|
this.controls.targetPosition.z = z + 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hashVars.length >= 6){
|
||||||
|
let dir = parseFloat(hashVars[3]);
|
||||||
|
let dist = parseFloat(hashVars[4]);
|
||||||
|
let angle = parseFloat(hashVars[5]);
|
||||||
|
if (!isNaN(dir)) this.controls.targetDirection = dir;
|
||||||
|
if (!isNaN(dist)) this.controls.targetDistance = dist;
|
||||||
|
if (!isNaN(angle)) this.controls.targetAngle = angle;
|
||||||
|
this.controls.direction = this.controls.targetDirection;
|
||||||
|
this.controls.distance = this.controls.targetDistance;
|
||||||
|
this.controls.angle = this.controls.targetAngle;
|
||||||
|
this.controls.targetPosition.y = this.controls.minHeight;
|
||||||
|
this.controls.position.copy(this.controls.targetPosition);
|
||||||
|
}
|
||||||
|
if (hashVars.length >= 7){
|
||||||
|
let height = parseInt(hashVars[6]);
|
||||||
|
if (!isNaN(height)){
|
||||||
|
this.controls.minHeight = height;
|
||||||
|
this.controls.targetPosition.y = height;
|
||||||
|
this.controls.position.copy(this.controls.targetPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
this.loadingNoticeElement.remove();
|
||||||
|
|
||||||
|
this.loadLocationHash();
|
||||||
|
|
||||||
|
$(window).on('hashchange', () => {
|
||||||
|
if (this.locationHash === window.location.hash) return;
|
||||||
|
this.loadLocationHash();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.update();
|
||||||
|
this.render();
|
||||||
|
|
||||||
|
this.lowresTileManager.update();
|
||||||
|
this.hiresTileManager.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
update = () => {
|
||||||
|
setTimeout(this.update, 1000);
|
||||||
|
|
||||||
|
this.lowresTileManager.setPosition(this.controls.targetPosition);
|
||||||
|
this.hiresTileManager.setPosition(this.controls.targetPosition);
|
||||||
|
|
||||||
|
this.locationHash =
|
||||||
|
'#' + this.map
|
||||||
|
+ ':' + Math.floor(this.controls.targetPosition.x)
|
||||||
|
+ ':' + Math.floor(this.controls.targetPosition.z)
|
||||||
|
+ ':' + Math.round(this.controls.targetDirection * 100) / 100
|
||||||
|
+ ':' + Math.round(this.controls.targetDistance * 100) / 100
|
||||||
|
+ ':' + Math.ceil(this.controls.targetAngle * 100) / 100
|
||||||
|
+ ':' + Math.floor(this.controls.targetPosition.y);
|
||||||
|
history.replaceState(undefined, undefined, this.locationHash);
|
||||||
|
};
|
||||||
|
|
||||||
|
render = () => {
|
||||||
|
requestAnimationFrame(this.render);
|
||||||
|
|
||||||
|
if (this.controls.update()) this.updateFrame = true;
|
||||||
|
|
||||||
|
if (!this.updateFrame) return;
|
||||||
|
this.updateFrame = false;
|
||||||
|
|
||||||
|
document.dispatchEvent(new Event('bluemap-update-frame'));
|
||||||
|
|
||||||
|
this.skyboxCamera.rotation.copy(this.camera.rotation);
|
||||||
|
this.skyboxCamera.updateProjectionMatrix();
|
||||||
|
|
||||||
|
this.renderer.clear();
|
||||||
|
this.renderer.render(this.skyboxScene, this.skyboxCamera, this.renderer.getRenderTarget(), false);
|
||||||
|
this.renderer.clearDepth();
|
||||||
|
this.renderer.render(this.lowresScene, this.camera, this.renderer.getRenderTarget(), false);
|
||||||
|
if (this.camera.position.y < 400) {
|
||||||
|
this.renderer.clearDepth();
|
||||||
|
this.renderer.render(this.hiresScene, this.camera, this.renderer.getRenderTarget(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleContainerResize = () => {
|
||||||
|
this.camera.aspect = this.element.clientWidth / this.element.clientHeight;
|
||||||
|
this.camera.updateProjectionMatrix();
|
||||||
|
|
||||||
|
this.skyboxCamera.aspect = this.element.clientWidth / this.element.clientHeight;
|
||||||
|
this.skyboxCamera.updateProjectionMatrix();
|
||||||
|
|
||||||
|
this.renderer.setSize(this.element.clientWidth * this.quality, this.element.clientHeight * this.quality);
|
||||||
|
$(this.renderer.domElement)
|
||||||
|
.css('width', this.element.clientWidth)
|
||||||
|
.css('height', this.element.clientHeight);
|
||||||
|
|
||||||
|
this.updateFrame = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadSettings() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
this.fileLoader.load(this.dataRoot + 'settings.json', settings => {
|
||||||
|
this.settings = JSON.parse(settings);
|
||||||
|
this.maps = [];
|
||||||
|
for (let map in this.settings) {
|
||||||
|
if (this.settings.hasOwnProperty(map) && this.settings[map].enabled){
|
||||||
|
this.maps.push(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.maps.sort((map1, map2) => {
|
||||||
|
var sort = this.settings[map1].ordinal - this.settings[map2].ordinal;
|
||||||
|
if (isNaN(sort)) return 0;
|
||||||
|
return sort;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.map = this.maps[0];
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initStage() {
|
||||||
|
this.updateFrame = true;
|
||||||
|
this.quality = 1;
|
||||||
|
|
||||||
|
this.renderer = new WebGLRenderer({
|
||||||
|
alpha: true,
|
||||||
|
antialias: true,
|
||||||
|
sortObjects: false,
|
||||||
|
preserveDrawingBuffer: true,
|
||||||
|
logarithmicDepthBuffer: true,
|
||||||
|
});
|
||||||
|
this.renderer.autoClear = false;
|
||||||
|
|
||||||
|
this.camera = new PerspectiveCamera(75, this.element.scrollWidth / this.element.scrollHeight, 0.1, 10000);
|
||||||
|
this.camera.updateProjectionMatrix();
|
||||||
|
|
||||||
|
this.skyboxCamera = this.camera.clone();
|
||||||
|
this.skyboxCamera.updateProjectionMatrix();
|
||||||
|
|
||||||
|
this.skyboxScene = new Scene();
|
||||||
|
this.skyboxScene.ambient = new AmbientLight(0xffffff, 1);
|
||||||
|
this.skyboxScene.add(this.skyboxScene.ambient);
|
||||||
|
this.skyboxScene.add(this.createSkybox());
|
||||||
|
|
||||||
|
this.lowresScene = new Scene();
|
||||||
|
this.lowresScene.ambient = new AmbientLight(0xffffff, 0.6);
|
||||||
|
this.lowresScene.add(this.lowresScene.ambient);
|
||||||
|
this.lowresScene.sunLight = new DirectionalLight(0xccccbb, 0.7);
|
||||||
|
this.lowresScene.sunLight.position.set(1, 5, 3);
|
||||||
|
this.lowresScene.add(this.lowresScene.sunLight);
|
||||||
|
|
||||||
|
this.hiresScene = new Scene();
|
||||||
|
this.hiresScene.ambient = new AmbientLight(0xffffff, 1);
|
||||||
|
this.hiresScene.add(this.hiresScene.ambient);
|
||||||
|
this.hiresScene.sunLight = new DirectionalLight(0xccccbb, 0.2);
|
||||||
|
this.hiresScene.sunLight.position.set(1, 5, 3);
|
||||||
|
this.hiresScene.add(this.hiresScene.sunLight);
|
||||||
|
|
||||||
|
this.element.append(this.renderer.domElement);
|
||||||
|
this.handleContainerResize();
|
||||||
|
|
||||||
|
$(window).resize(this.handleContainerResize);
|
||||||
|
}
|
||||||
|
|
||||||
|
createSkybox() {
|
||||||
|
let geometry = new CubeGeometry(10, 10, 10);
|
||||||
|
let material = [
|
||||||
|
new MeshBasicMaterial({
|
||||||
|
map: new TextureLoader().load(SKYBOX_SOUTH),
|
||||||
|
side: BackSide
|
||||||
|
}),
|
||||||
|
new MeshBasicMaterial({
|
||||||
|
map: new TextureLoader().load(SKYBOX_NORTH),
|
||||||
|
side: BackSide
|
||||||
|
}),
|
||||||
|
new MeshBasicMaterial({
|
||||||
|
map: new TextureLoader().load(SKYBOX_UP),
|
||||||
|
side: BackSide
|
||||||
|
}),
|
||||||
|
new MeshBasicMaterial({
|
||||||
|
map: new TextureLoader().load(SKYBOX_DOWN),
|
||||||
|
side: BackSide
|
||||||
|
}),
|
||||||
|
new MeshBasicMaterial({
|
||||||
|
map: new TextureLoader().load(SKYBOX_EAST),
|
||||||
|
side: BackSide
|
||||||
|
}),
|
||||||
|
new MeshBasicMaterial({
|
||||||
|
map: new TextureLoader().load(SKYBOX_WEST),
|
||||||
|
side: BackSide
|
||||||
|
})
|
||||||
|
];
|
||||||
|
return new Mesh(geometry, material);
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadHiresMaterial() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
this.fileLoader.load(this.dataRoot + 'textures.json', textures => {
|
||||||
|
textures = JSON.parse(textures);
|
||||||
|
|
||||||
|
let materials = [];
|
||||||
|
for (let i = 0; i < textures['textures'].length; i++) {
|
||||||
|
let t = textures['textures'][i];
|
||||||
|
|
||||||
|
let material = new MeshLambertMaterial({
|
||||||
|
transparent: t['transparent'],
|
||||||
|
alphaTest: 0.01,
|
||||||
|
depthWrite: true,
|
||||||
|
depthTest: true,
|
||||||
|
blending: NormalBlending,
|
||||||
|
vertexColors: VertexColors,
|
||||||
|
side: FrontSide,
|
||||||
|
wireframe: false
|
||||||
|
});
|
||||||
|
|
||||||
|
let texture = new Texture();
|
||||||
|
texture.image = stringToImage(t['texture']);
|
||||||
|
|
||||||
|
texture.premultiplyAlpha = false;
|
||||||
|
texture.generateMipmaps = false;
|
||||||
|
texture.magFilter = NearestFilter;
|
||||||
|
texture.minFilter = NearestFilter;
|
||||||
|
texture.wrapS = ClampToEdgeWrapping;
|
||||||
|
texture.wrapT = ClampToEdgeWrapping;
|
||||||
|
texture.flipY = false;
|
||||||
|
texture.needsUpdate = true;
|
||||||
|
texture.flatShading = true;
|
||||||
|
|
||||||
|
material.map = texture;
|
||||||
|
material.needsUpdate = true;
|
||||||
|
|
||||||
|
materials[i] = material;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hiresMaterial = materials;
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadLowresMaterial() {
|
||||||
|
this.lowresMaterial = new MeshLambertMaterial({
|
||||||
|
transparent: false,
|
||||||
|
depthWrite: true,
|
||||||
|
depthTest: true,
|
||||||
|
vertexColors: VertexColors,
|
||||||
|
side: FrontSide,
|
||||||
|
wireframe: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadHiresTile(tileX, tileZ) {
|
||||||
|
let path = this.dataRoot + this.map + '/hires/';
|
||||||
|
path += pathFromCoords(tileX, tileZ);
|
||||||
|
path += '.json';
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.bufferGeometryLoader.load(path, geometry => {
|
||||||
|
let object = new Mesh(geometry, this.hiresMaterial);
|
||||||
|
|
||||||
|
let tileSize = this.settings[this.map]['hires']['tileSize'];
|
||||||
|
let translate = this.settings[this.map]['hires']['translate'];
|
||||||
|
let scale = this.settings[this.map]['hires']['scale'];
|
||||||
|
object.position.set(tileX * tileSize.x + translate.x, 0, tileZ * tileSize.z + translate.z);
|
||||||
|
object.scale.set(scale.x, 1, scale.z);
|
||||||
|
|
||||||
|
resolve(object);
|
||||||
|
}, () => {
|
||||||
|
}, reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadLowresTile(tileX, tileZ) {
|
||||||
|
let path = this.dataRoot + this.map + '/lowres/';
|
||||||
|
path += pathFromCoords(tileX, tileZ);
|
||||||
|
path += '.json';
|
||||||
|
|
||||||
|
return new Promise((reslove, reject) => {
|
||||||
|
this.bufferGeometryLoader.load(path, geometry => {
|
||||||
|
let object = new Mesh(geometry, this.lowresMaterial);
|
||||||
|
|
||||||
|
let tileSize = this.settings[this.map]['lowres']['tileSize'];
|
||||||
|
let translate = this.settings[this.map]['lowres']['translate'];
|
||||||
|
let scale = this.settings[this.map]['lowres']['scale'];
|
||||||
|
object.position.set(tileX * tileSize.x + translate.x, 0, tileZ * tileSize.z + translate.z);
|
||||||
|
object.scale.set(scale.x, 1, scale.z);
|
||||||
|
|
||||||
|
reslove(object);
|
||||||
|
}, () => {
|
||||||
|
}, reject);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ###### UI ######
|
||||||
|
|
||||||
|
alert(content) {
|
||||||
|
let alertBox = $('#alert-box');
|
||||||
|
if (alertBox.length === 0){
|
||||||
|
alertBox = $('<div id="alert-box"></div>').appendTo(this.element);
|
||||||
|
}
|
||||||
|
|
||||||
|
let displayAlert = () => {
|
||||||
|
let alert = $(`<div class="alert box" style="display: none;"><div class="alert-close-button"></div>${content}</div>`).appendTo(alertBox);
|
||||||
|
alert.find('.alert-close-button').click(() => {
|
||||||
|
alert.fadeOut(200, () => alert.remove());
|
||||||
|
});
|
||||||
|
alert.fadeIn(200);
|
||||||
|
};
|
||||||
|
|
||||||
|
let oldAlerts = alertBox.find('.alert');
|
||||||
|
if (oldAlerts.length > 0){
|
||||||
|
alertBox.fadeOut(200, () => {
|
||||||
|
alertBox.html('');
|
||||||
|
alertBox.show();
|
||||||
|
displayAlert();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
displayAlert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
297
BlueMapCore/src/main/webroot/js/libs/Controls.js
Normal file
297
BlueMapCore/src/main/webroot/js/libs/Controls.js
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
/*
|
||||||
|
* 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 Softwarevent.
|
||||||
|
*
|
||||||
|
* 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 SOFTWARevent.
|
||||||
|
*/
|
||||||
|
import $ from 'jquery';
|
||||||
|
import {
|
||||||
|
Euler,
|
||||||
|
Raycaster,
|
||||||
|
Vector2,
|
||||||
|
Vector3,
|
||||||
|
MOUSE
|
||||||
|
} from 'three';
|
||||||
|
|
||||||
|
import { Vector2_ZERO } from './utils.js';
|
||||||
|
|
||||||
|
export default class Controls {
|
||||||
|
static KEYS = {
|
||||||
|
LEFT: 37,
|
||||||
|
UP: 38,
|
||||||
|
RIGHT: 39,
|
||||||
|
DOWN: 40,
|
||||||
|
ORBIT: MOUSE.RIGHT,
|
||||||
|
MOVE: MOUSE.LEFT
|
||||||
|
};
|
||||||
|
static STATES = {
|
||||||
|
NONE: -1,
|
||||||
|
ORBIT: 0,
|
||||||
|
MOVE: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* targetHeightScene and cameraHeightScene are scenes of objects that are checked via raycasting for a height for the target and the camera
|
||||||
|
*/
|
||||||
|
constructor(camera, element, heightScene) {
|
||||||
|
this.settings = {
|
||||||
|
zoom: {
|
||||||
|
min: 10,
|
||||||
|
max: 2000,
|
||||||
|
speed: 1.5,
|
||||||
|
smooth: 0.2,
|
||||||
|
},
|
||||||
|
move: {
|
||||||
|
speed: 1.75,
|
||||||
|
smooth: 0.3,
|
||||||
|
smoothY: 0.075,
|
||||||
|
},
|
||||||
|
tilt: {
|
||||||
|
max: Math.PI / 2.1,
|
||||||
|
speed: 1.5,
|
||||||
|
smooth: 0.3,
|
||||||
|
},
|
||||||
|
rotate: {
|
||||||
|
speed: 1.5,
|
||||||
|
smooth: 0.3,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.camera = camera;
|
||||||
|
this.element = element;
|
||||||
|
this.heightScene = heightScene;
|
||||||
|
this.minHeight = 0;
|
||||||
|
|
||||||
|
this.raycaster = new Raycaster();
|
||||||
|
this.rayDirection = new Vector3(0, -1, 0);
|
||||||
|
|
||||||
|
this.resetPosition();
|
||||||
|
|
||||||
|
this.mouse = new Vector2(0, 0);
|
||||||
|
this.lastMouse = new Vector2(0, 0);
|
||||||
|
this.deltaMouse = new Vector2(0, 0);
|
||||||
|
|
||||||
|
//variables used to calculate with (to prevent object creation every update)
|
||||||
|
this.orbitRot = new Euler(0, 0, 0, 'YXZ');
|
||||||
|
this.cameraPosDelta = new Vector3(0, 0, 0);
|
||||||
|
this.moveDelta = new Vector2(0, 0);
|
||||||
|
|
||||||
|
this.keyStates = {}
|
||||||
|
this.state = Controls.STATES.NONE;
|
||||||
|
|
||||||
|
let canvas = $(this.element).find('canvas').get(0);
|
||||||
|
window.addEventListener('contextmenu', event => {
|
||||||
|
event.preventDefault();
|
||||||
|
}, false);
|
||||||
|
canvas.addEventListener('mousedown', this.onMouseDown, false);
|
||||||
|
window.addEventListener('mousemove', this.onMouseMove, false);
|
||||||
|
window.addEventListener('mouseup', this.onMouseUp, false);
|
||||||
|
canvas.addEventListener('wheel', this.onMouseWheel, false);
|
||||||
|
window.addEventListener('keydown', this.onKeyDown, false);
|
||||||
|
window.addEventListener('keyup', this.onKeyUp, false);
|
||||||
|
|
||||||
|
this.camera.position.set(0, 1000, 0);
|
||||||
|
this.camera.lookAt(this.position);
|
||||||
|
this.camera.updateProjectionMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
resetPosition() {
|
||||||
|
this.position = new Vector3(0, 70, 0);
|
||||||
|
this.targetPosition = new Vector3(0, 70, 0);
|
||||||
|
|
||||||
|
this.distance = 5000;
|
||||||
|
this.targetDistance = 1000;
|
||||||
|
|
||||||
|
this.direction = 0;
|
||||||
|
this.targetDirection = 0;
|
||||||
|
|
||||||
|
this.angle = 0;
|
||||||
|
this.targetAngle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.updateMouseMoves();
|
||||||
|
|
||||||
|
let changed = false;
|
||||||
|
|
||||||
|
let zoomLerp = (this.distance - 100) / 200;
|
||||||
|
if (zoomLerp < 0) zoomLerp = 0;
|
||||||
|
if (zoomLerp > 1) zoomLerp = 1;
|
||||||
|
this.targetPosition.y = 300 * zoomLerp + this.minHeight * (1 - zoomLerp);
|
||||||
|
|
||||||
|
this.position.x += (this.targetPosition.x - this.position.x) * this.settings.move.smooth;
|
||||||
|
this.position.y += (this.targetPosition.y - this.position.y) * this.settings.move.smoothY;
|
||||||
|
this.position.z += (this.targetPosition.z - this.position.z) * this.settings.move.smooth;
|
||||||
|
|
||||||
|
this.distance += (this.targetDistance - this.distance) * this.settings.zoom.smooth;
|
||||||
|
|
||||||
|
let deltaDir = (this.targetDirection - this.direction) * this.settings.rotate.smooth;
|
||||||
|
this.direction += deltaDir;
|
||||||
|
changed = changed || Math.abs(deltaDir) > 0.001;
|
||||||
|
|
||||||
|
let max = Math.min(this.settings.tilt.max, this.settings.tilt.max - Math.pow(((this.distance - this.settings.zoom.min) / (this.settings.zoom.max - this.settings.zoom.min)) * Math.pow(this.settings.tilt.max, 4), 1/4));
|
||||||
|
if (this.targetAngle > max) this.targetAngle = max;
|
||||||
|
if (this.targetAngle < 0.01) this.targetAngle = 0.001;
|
||||||
|
let deltaAngle = (this.targetAngle - this.angle) * this.settings.tilt.smooth;
|
||||||
|
this.angle += deltaAngle;
|
||||||
|
changed = changed || Math.abs(deltaAngle) > 0.001;
|
||||||
|
|
||||||
|
let last = this.camera.position.x + this.camera.position.y + this.camera.position.z;
|
||||||
|
this.orbitRot.set(this.angle, this.direction, 0);
|
||||||
|
this.cameraPosDelta.set(0, this.distance, 0).applyEuler(this.orbitRot);
|
||||||
|
|
||||||
|
this.camera.position.set(this.position.x + this.cameraPosDelta.x, this.position.y + this.cameraPosDelta.y, this.position.z + this.cameraPosDelta.z);
|
||||||
|
let move = last - (this.camera.position.x + this.camera.position.y + this.camera.position.z);
|
||||||
|
|
||||||
|
changed = changed || Math.abs(move) > 0.001;
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
this.camera.lookAt(this.position);
|
||||||
|
this.camera.updateProjectionMatrix();
|
||||||
|
|
||||||
|
this.updateHeights();
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateHeights() {
|
||||||
|
//TODO: this can be performance-improved by only intersecting the correct tile?
|
||||||
|
|
||||||
|
let rayStart = new Vector3(this.targetPosition.x, 300, this.targetPosition.z);
|
||||||
|
this.raycaster.set(rayStart, this.rayDirection);
|
||||||
|
this.raycaster.near = 1;
|
||||||
|
this.raycaster.far = 300;
|
||||||
|
let intersects = this.raycaster.intersectObjects(this.heightScene.children);
|
||||||
|
if (intersects.length > 0){
|
||||||
|
this.minHeight = intersects[0].point.y;
|
||||||
|
//this.targetPosition.y = this.minHeight;
|
||||||
|
} else {
|
||||||
|
//this.targetPosition.y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rayStart.set(this.camera.position.x, 300, this.camera.position.z);
|
||||||
|
this.raycaster.set(rayStart, this.rayDirection);
|
||||||
|
intersects.length = 0;
|
||||||
|
intersects = this.raycaster.intersectObjects(this.heightScene.children);
|
||||||
|
if (intersects.length > 0){
|
||||||
|
if (intersects[0].point.y > this.minHeight){
|
||||||
|
this.minHeight = intersects[0].point.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
updateMouseMoves = () => {
|
||||||
|
this.deltaMouse.set(this.lastMouse.x - this.mouse.x, this.lastMouse.y - this.mouse.y);
|
||||||
|
|
||||||
|
this.moveDelta.x = 0;
|
||||||
|
this.moveDelta.y = 0;
|
||||||
|
|
||||||
|
if (this.keyStates[Controls.KEYS.UP]){
|
||||||
|
this.moveDelta.y -= 20;
|
||||||
|
}
|
||||||
|
if (this.keyStates[Controls.KEYS.DOWN]){
|
||||||
|
this.moveDelta.y += 20;
|
||||||
|
}
|
||||||
|
if (this.keyStates[Controls.KEYS.LEFT]){
|
||||||
|
this.moveDelta.x -= 20;
|
||||||
|
}
|
||||||
|
if (this.keyStates[Controls.KEYS.RIGHT]){
|
||||||
|
this.moveDelta.x += 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state === Controls.STATES.MOVE) {
|
||||||
|
if (this.deltaMouse.x === 0 && this.deltaMouse.y === 0) return;
|
||||||
|
this.moveDelta.copy(this.deltaMouse);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.moveDelta.x !== 0 || this.moveDelta.y !== 0) {
|
||||||
|
this.moveDelta.rotateAround(Vector2_ZERO, -this.direction);
|
||||||
|
this.targetPosition.set(
|
||||||
|
this.targetPosition.x + (this.moveDelta.x * this.distance / this.element.clientHeight * this.settings.move.speed),
|
||||||
|
this.targetPosition.y,
|
||||||
|
this.targetPosition.z + (this.moveDelta.y * this.distance / this.element.clientHeight * this.settings.move.speed)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state === Controls.STATES.ORBIT) {
|
||||||
|
this.targetDirection += (this.deltaMouse.x / this.element.clientHeight * Math.PI);
|
||||||
|
this.targetAngle += (this.deltaMouse.y / this.element.clientHeight * Math.PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastMouse.copy(this.mouse);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMouseWheel = event => {
|
||||||
|
if (event.deltaY > 0) {
|
||||||
|
this.targetDistance *= this.settings.zoom.speed;
|
||||||
|
} else if (event.deltaY < 0) {
|
||||||
|
this.targetDistance /= this.settings.zoom.speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.targetDistance < this.settings.zoom.min) this.targetDistance = this.settings.zoom.min;
|
||||||
|
if (this.targetDistance > this.settings.zoom.max) this.targetDistance = this.settings.zoom.max;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseMove = event => {
|
||||||
|
this.mouse.set(event.clientX, event.clientY);
|
||||||
|
|
||||||
|
if (this.state !== Controls.STATES.NONE){
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseDown = event => {
|
||||||
|
if (this.state !== Controls.STATES.NONE) return;
|
||||||
|
|
||||||
|
switch (event.button) {
|
||||||
|
case Controls.KEYS.MOVE :
|
||||||
|
this.state = Controls.STATES.MOVE;
|
||||||
|
event.preventDefault();
|
||||||
|
break;
|
||||||
|
case Controls.KEYS.ORBIT :
|
||||||
|
this.state = Controls.STATES.ORBIT;
|
||||||
|
event.preventDefault();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseUp = event => {
|
||||||
|
if (this.state === Controls.STATES.NONE) return;
|
||||||
|
|
||||||
|
switch (event.button) {
|
||||||
|
case Controls.KEYS.MOVE :
|
||||||
|
if (this.state === Controls.STATES.MOVE) this.state = Controls.STATES.NONE;
|
||||||
|
break;
|
||||||
|
case Controls.KEYS.ORBIT :
|
||||||
|
if (this.state === Controls.STATES.ORBIT) this.state = Controls.STATES.NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onKeyDown = event => {
|
||||||
|
this.keyStates[event.keyCode] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
onKeyUp = e => {
|
||||||
|
this.keyStates[event.keyCode] = false;
|
||||||
|
}
|
||||||
|
}
|
59
BlueMapCore/src/main/webroot/js/libs/Tile.js
Normal file
59
BlueMapCore/src/main/webroot/js/libs/Tile.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default class Tile {
|
||||||
|
isLoading = false;
|
||||||
|
disposed = false;
|
||||||
|
model = null;
|
||||||
|
|
||||||
|
constructor(scene, x, z) {
|
||||||
|
this.scene = scene;
|
||||||
|
this.x = x;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
setModel(model) {
|
||||||
|
this.disposeModel();
|
||||||
|
|
||||||
|
if (model) {
|
||||||
|
this.model = model;
|
||||||
|
this.scene.add(model);
|
||||||
|
|
||||||
|
//console.log('Added tile:', this.x, this.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disposeModel() {
|
||||||
|
this.disposed = true;
|
||||||
|
|
||||||
|
if (this.model) {
|
||||||
|
this.scene.remove(this.model);
|
||||||
|
this.model.geometry.dispose();
|
||||||
|
delete this.model;
|
||||||
|
|
||||||
|
//console.log('Removed tile:', this.x, this.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
184
BlueMapCore/src/main/webroot/js/libs/TileManager.js
Normal file
184
BlueMapCore/src/main/webroot/js/libs/TileManager.js
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Vector2 } from 'three';
|
||||||
|
|
||||||
|
import Tile from './Tile.js';
|
||||||
|
|
||||||
|
import { hashTile } from './utils.js';
|
||||||
|
|
||||||
|
export default class TileManager {
|
||||||
|
constructor(blueMap, viewDistance, tileLoader, scene, tileSize, position) {
|
||||||
|
this.blueMap = blueMap;
|
||||||
|
this.viewDistance = viewDistance;
|
||||||
|
this.tileLoader = tileLoader;
|
||||||
|
this.scene = scene;
|
||||||
|
this.tileSize = new Vector2(tileSize.x, tileSize.z);
|
||||||
|
|
||||||
|
this.tile = new Vector2(position.x, position.z);
|
||||||
|
this.lastTile = this.tile.clone();
|
||||||
|
|
||||||
|
this.closed = false;
|
||||||
|
this.currentlyLoading = 0;
|
||||||
|
this.updateTimeout = null;
|
||||||
|
|
||||||
|
this.tiles = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
setPosition(center) {
|
||||||
|
this.tile.set(center.x, center.z).divide(this.tileSize).floor();
|
||||||
|
|
||||||
|
if (!this.tile.equals(this.lastTile) && !this.closed) {
|
||||||
|
this.update();
|
||||||
|
this.lastTile.copy(this.tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
if (this.closed) return;
|
||||||
|
|
||||||
|
// free a loader so if there was an error loading a tile we don't get stuck forever with the blocked loading process
|
||||||
|
this.currentlyLoading--;
|
||||||
|
if (this.currentlyLoading < 0) this.currentlyLoading = 0;
|
||||||
|
|
||||||
|
this.removeFarTiles();
|
||||||
|
this.loadCloseTiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFarTiles() {
|
||||||
|
let keys = Object.keys(this.tiles);
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
if (!this.tiles.hasOwnProperty(keys[i])) continue;
|
||||||
|
|
||||||
|
let tile = this.tiles[keys[i]];
|
||||||
|
|
||||||
|
let vd = this.viewDistance;
|
||||||
|
|
||||||
|
if (
|
||||||
|
tile.x + vd < this.tile.x ||
|
||||||
|
tile.x - vd > this.tile.x ||
|
||||||
|
tile.z + vd < this.tile.y ||
|
||||||
|
tile.z - vd > this.tile.y
|
||||||
|
) {
|
||||||
|
tile.disposeModel();
|
||||||
|
delete this.tiles[keys[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeAllTiles() {
|
||||||
|
let keys = Object.keys(this.tiles);
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
if (!this.tiles.hasOwnProperty(keys[i])) continue;
|
||||||
|
|
||||||
|
let tile = this.tiles[keys[i]];
|
||||||
|
tile.disposeModel();
|
||||||
|
delete this.tiles[keys[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.closed = true;
|
||||||
|
this.removeAllTiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCloseTiles() {
|
||||||
|
if (this.closed) return;
|
||||||
|
|
||||||
|
if (this.currentlyLoading < 8) {
|
||||||
|
if (!this.loadNextTile()) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.updateTimeout) clearTimeout(this.updateTimeout);
|
||||||
|
this.updateTimeout = setTimeout(() => this.loadCloseTiles(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadNextTile() {
|
||||||
|
let x = 0;
|
||||||
|
let z = 0;
|
||||||
|
let d = 1;
|
||||||
|
let m = 1;
|
||||||
|
|
||||||
|
while (m < this.viewDistance * 2) {
|
||||||
|
while (2 * x * d < m) {
|
||||||
|
if (this.tryLoadTile(this.tile.x + x, this.tile.y + z)) return true;
|
||||||
|
x = x + d;
|
||||||
|
}
|
||||||
|
while (2 * z * d < m) {
|
||||||
|
if (this.tryLoadTile(this.tile.x + x, this.tile.y + z)) return true;
|
||||||
|
z = z + d;
|
||||||
|
}
|
||||||
|
d = -1 * d;
|
||||||
|
m = m + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tryLoadTile(x, z) {
|
||||||
|
if (this.closed) return false;
|
||||||
|
|
||||||
|
let tileHash = hashTile(x, z);
|
||||||
|
|
||||||
|
let tile = this.tiles[tileHash];
|
||||||
|
if (tile !== undefined) return false;
|
||||||
|
|
||||||
|
tile = new Tile(this.scene, x, z);
|
||||||
|
tile.isLoading = true;
|
||||||
|
|
||||||
|
this.currentlyLoading++;
|
||||||
|
|
||||||
|
this.tiles[tileHash] = tile;
|
||||||
|
|
||||||
|
this.tileLoader.call(this.blueMap, x, z)
|
||||||
|
.then(model => {
|
||||||
|
tile.isLoading = false;
|
||||||
|
|
||||||
|
if (tile.disposed || this.closed) {
|
||||||
|
model.geometry.dispose();
|
||||||
|
tile.disposeModel();
|
||||||
|
delete this.tiles[tileHash];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tiles[tileHash] = tile;
|
||||||
|
tile.setModel(model);
|
||||||
|
|
||||||
|
this.blueMap.updateFrame = true;
|
||||||
|
|
||||||
|
this.currentlyLoading--;
|
||||||
|
if (this.currentlyLoading < 0) this.currentlyLoading = 0;
|
||||||
|
}).catch(error => {
|
||||||
|
tile.isLoading = false;
|
||||||
|
tile.disposeModel();
|
||||||
|
|
||||||
|
this.currentlyLoading--;
|
||||||
|
|
||||||
|
//console.log("Failed to load tile: ", x, z);
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
53
BlueMapCore/src/main/webroot/js/libs/modules/Compass.js
Normal file
53
BlueMapCore/src/main/webroot/js/libs/modules/Compass.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
import { getTopLeftElement } from './Module.js';
|
||||||
|
|
||||||
|
import COMPASS from '../../../assets/compass.svg';
|
||||||
|
|
||||||
|
export default class Compass {
|
||||||
|
constructor(blueMap) {
|
||||||
|
this.blueMap = blueMap;
|
||||||
|
|
||||||
|
$('#bluemap-compass').remove();
|
||||||
|
this.element = $(`<div id="bluemap-compass" class="button"><img id="bluemap-compass-needle" src="${COMPASS}" /></div>`).appendTo(getTopLeftElement(blueMap));
|
||||||
|
this.needle = $('#bluemap-compass-needle');
|
||||||
|
|
||||||
|
$(document).on('bluemap-update-frame', this.onBlueMapUpdateFrame);
|
||||||
|
$(this.element).click(this.onClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
onBlueMapUpdateFrame = () => {
|
||||||
|
this.needle.css('transform', `rotate(${this.blueMap.controls.direction}rad)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick = () => {
|
||||||
|
this.blueMap.controls.targetDirection = 0;
|
||||||
|
this.blueMap.controls.direction = this.blueMap.controls.direction % (Math.PI * 2);
|
||||||
|
if (this.blueMap.controls.direction < -Math.PI) this.blueMap.controls.direction += Math.PI * 2;
|
||||||
|
if (this.blueMap.controls.direction > Math.PI) this.blueMap.controls.direction -= Math.PI * 2;
|
||||||
|
}
|
||||||
|
}
|
49
BlueMapCore/src/main/webroot/js/libs/modules/Info.js
Normal file
49
BlueMapCore/src/main/webroot/js/libs/modules/Info.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
import { getTopRightElement } from './Module.js';
|
||||||
|
|
||||||
|
export default class Info {
|
||||||
|
constructor(blueMap) {
|
||||||
|
this.blueMap = blueMap;
|
||||||
|
const parent = getTopRightElement(blueMap);
|
||||||
|
$('#bluemap-info').remove();
|
||||||
|
this.elementInfo = $('<div id="bluemap-info" class="button"></div>').appendTo(parent);
|
||||||
|
this.elementInfo.click(this.onClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick = () => {
|
||||||
|
this.blueMap.alert(
|
||||||
|
'<h1>Info</h1>' +
|
||||||
|
'Visit BlueMap on <a href="https://github.com/BlueMap-Minecraft">GitHub</a>!<br>' +
|
||||||
|
'BlueMap works best with <a href="https://www.google.com/chrome/">Chrome</a>.<br>' +
|
||||||
|
'<h2>Controls</h2>' +
|
||||||
|
'Leftclick-drag with your mouse or use the arrow-keys to navigate.<br>' +
|
||||||
|
'Rightclick-drag with your mouse to rotate your view.<br>' +
|
||||||
|
'Scroll to zoom.<br>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
63
BlueMapCore/src/main/webroot/js/libs/modules/MapMenu.js
Normal file
63
BlueMapCore/src/main/webroot/js/libs/modules/MapMenu.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
import { getTopLeftElement } from './Module.js';
|
||||||
|
|
||||||
|
export default class MapMenu {
|
||||||
|
constructor(blueMap) {
|
||||||
|
this.bluemap = blueMap;
|
||||||
|
const maps = this.bluemap.settings;
|
||||||
|
|
||||||
|
$('#bluemap-mapmenu').remove();
|
||||||
|
this.element = $(`<div id="bluemap-mapmenu" class="dropdown-container"><span class="selection">${maps[this.bluemap.map].name}</span></div>`).appendTo(getTopLeftElement(blueMap));
|
||||||
|
|
||||||
|
const dropdown = $('<div class="dropdown"></div>').appendTo(this.element);
|
||||||
|
this.maplist = $('<ul></ul>').appendTo(dropdown);
|
||||||
|
|
||||||
|
for (let mapId in maps) {
|
||||||
|
if (!maps.hasOwnProperty(mapId)) continue;
|
||||||
|
const map = maps[mapId];
|
||||||
|
if (!map.enabled) continue;
|
||||||
|
|
||||||
|
$(`<li map="${mapId}">${map.name}</li>`).appendTo(this.maplist);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.maplist.find('li[map=' + this.bluemap.map + ']').hide();
|
||||||
|
this.maplist.find('li[map]').click(this.onMapClick);
|
||||||
|
$(document).on('bluemap-map-change', this.onBlueMapMapChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMapClick = event => {
|
||||||
|
const map = $(event.target).attr('map');
|
||||||
|
this.bluemap.changeMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
onBlueMapMapChange = () => {
|
||||||
|
this.maplist.find('li').show();
|
||||||
|
this.maplist.find('li[map=' + this.bluemap.map + ']').hide();
|
||||||
|
this.element.find('.selection').html(this.bluemap.settings[this.bluemap.map].name);
|
||||||
|
}
|
||||||
|
}
|
47
BlueMapCore/src/main/webroot/js/libs/modules/Module.js
Normal file
47
BlueMapCore/src/main/webroot/js/libs/modules/Module.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
// ###### Modules ######
|
||||||
|
|
||||||
|
export const getTopRightElement = blueMap => {
|
||||||
|
let element = $('#bluemap-topright');
|
||||||
|
|
||||||
|
if (element.length === 0){
|
||||||
|
element = $('<div id="bluemap-topright" class="box"></div>').appendTo(blueMap.element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getTopLeftElement = blueMap => {
|
||||||
|
let element = $('#bluemap-topleft');
|
||||||
|
|
||||||
|
if (element.length === 0){
|
||||||
|
element = $('<div id="bluemap-topleft" class="box"></div>').appendTo(blueMap.element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
};
|
47
BlueMapCore/src/main/webroot/js/libs/modules/Position.js
Normal file
47
BlueMapCore/src/main/webroot/js/libs/modules/Position.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
import { getTopLeftElement } from './Module.js';
|
||||||
|
|
||||||
|
export default class Position {
|
||||||
|
constructor(blueMap) {
|
||||||
|
this.blueMap = blueMap;
|
||||||
|
const parent = getTopLeftElement(blueMap);
|
||||||
|
|
||||||
|
$('.bluemap-position').remove();
|
||||||
|
this.elementX = $('<div class="bluemap-position pos-x">0</div>').appendTo(parent);
|
||||||
|
//this.elementY = $('<div class="bluemap-position pos-y">0</div>').appendTo(parent);
|
||||||
|
this.elementZ = $('<div class="bluemap-position pos-z">0</div>').appendTo(parent);
|
||||||
|
|
||||||
|
$(document).on('bluemap-update-frame', this.onBlueMapUpdateFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
onBlueMapUpdateFrame = () => {
|
||||||
|
this.elementX.html(Math.floor(this.blueMap.controls.targetPosition.x));
|
||||||
|
//this.elementY.html(this.blueMap.controls.targetPosition.y === 0 ? '-' : Math.floor(this.blueMap.controls.targetPosition.y));
|
||||||
|
this.elementZ.html(Math.floor(this.blueMap.controls.targetPosition.z));
|
||||||
|
}
|
||||||
|
}
|
122
BlueMapCore/src/main/webroot/js/libs/modules/Settings.js
Normal file
122
BlueMapCore/src/main/webroot/js/libs/modules/Settings.js
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
import $ from 'jquery';
|
||||||
|
import { Math as Math3 } from 'three';
|
||||||
|
|
||||||
|
import { getTopRightElement } from './Module.js';
|
||||||
|
|
||||||
|
import GEAR from '../../../assets/gear.svg';
|
||||||
|
|
||||||
|
export default class Settings {
|
||||||
|
constructor(blueMap) {
|
||||||
|
this.blueMap = blueMap;
|
||||||
|
const parent = getTopRightElement(blueMap);
|
||||||
|
|
||||||
|
$('#bluemap-settings').remove();
|
||||||
|
this.elementMenu = $('<div id="bluemap-settings-container" style="display: none"></div>').appendTo(parent);
|
||||||
|
this.elementSettings = $(`<div id="bluemap-settings" class="button"><img src="${GEAR}" /></div>`).appendTo(parent);
|
||||||
|
this.elementSettings.click(this.onSettingsClick);
|
||||||
|
|
||||||
|
/* Quality */
|
||||||
|
|
||||||
|
this.elementQuality = $(
|
||||||
|
'<div id="bluemap-settings-quality" class="dropdown-container"><span class="selection">Quality: <span>Normal</span></span><div class="dropdown"><ul>' +
|
||||||
|
'<li quality="2">High</li>' +
|
||||||
|
'<li quality="1" style="display: none">Normal</li>' +
|
||||||
|
'<li quality="0.75">Fast</li>' +
|
||||||
|
'</ul></div></div>'
|
||||||
|
).prependTo(this.elementMenu);
|
||||||
|
|
||||||
|
this.elementQuality.find('li[quality]').click(this.onQualityClick);
|
||||||
|
this.elementRenderDistance = $('<div id="bluemap-settings-render-distance" class="dropdown-container"></div>').prependTo(this.elementMenu);
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
|
||||||
|
$(document).on('bluemap-map-change', this.init);
|
||||||
|
}
|
||||||
|
|
||||||
|
init = () => {
|
||||||
|
this.defaultHighRes = this.blueMap.hiresTileManager.viewDistance;
|
||||||
|
this.defaultLowRes = this.blueMap.lowresTileManager.viewDistance;
|
||||||
|
|
||||||
|
this.elementRenderDistance.html(
|
||||||
|
'<span class="selection">View Distance: <span>' + this.blueMap.hiresTileManager.viewDistance + '</span></span>' +
|
||||||
|
'<div class="dropdown">' +
|
||||||
|
'<input type="range" min="0" max="100" step="1" value="' + this.renderDistanceToPct(this.blueMap.hiresTileManager.viewDistance, this.defaultHighRes) + '" />' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
this.slider = this.elementRenderDistance.find('input');
|
||||||
|
this.slider.on('change input', this.onViewDistanceSlider);
|
||||||
|
};
|
||||||
|
|
||||||
|
onViewDistanceSlider = () => {
|
||||||
|
this.blueMap.hiresTileManager.viewDistance = this.pctToRenderDistance(parseFloat(this.slider.val()), this.defaultHighRes);
|
||||||
|
this.blueMap.lowresTileManager.viewDistance = this.pctToRenderDistance(parseFloat(this.slider.val()), this.defaultLowRes);
|
||||||
|
this.elementRenderDistance.find('.selection > span').html(Math.round(this.blueMap.hiresTileManager.viewDistance * 10) / 10);
|
||||||
|
|
||||||
|
this.blueMap.lowresTileManager.update();
|
||||||
|
this.blueMap.hiresTileManager.update();
|
||||||
|
};
|
||||||
|
|
||||||
|
onQualityClick = (event) => {
|
||||||
|
const target = event.target
|
||||||
|
const desc = $(target).html();
|
||||||
|
this.blueMap.quality = parseFloat($(target).attr('quality'));
|
||||||
|
|
||||||
|
this.elementQuality.find('li').show();
|
||||||
|
this.elementQuality.find(`li[quality="${this.blueMap.quality}"]`).hide();
|
||||||
|
|
||||||
|
this.elementQuality.find('.selection > span').html(desc);
|
||||||
|
|
||||||
|
this.blueMap.handleContainerResize();
|
||||||
|
};
|
||||||
|
|
||||||
|
onSettingsClick = () => {
|
||||||
|
if (this.elementMenu.css('display') === 'none'){
|
||||||
|
this.elementSettings.addClass('active');
|
||||||
|
} else {
|
||||||
|
this.elementSettings.removeClass('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.elementMenu.animate({
|
||||||
|
width: 'toggle'
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
pctToRenderDistance(value, defaultValue) {
|
||||||
|
let max = defaultValue * 5;
|
||||||
|
if (max > 20) max = 20;
|
||||||
|
|
||||||
|
return Math3.mapLinear(value, 0, 100, 1, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDistanceToPct(value, defaultValue) {
|
||||||
|
let max = defaultValue * 5;
|
||||||
|
if (max > 20) max = 20;
|
||||||
|
|
||||||
|
return Math3.mapLinear(value, 1, max, 0, 100);
|
||||||
|
}
|
||||||
|
}
|
946
BlueMapCore/src/main/webroot/js/libs/three.min.js
vendored
946
BlueMapCore/src/main/webroot/js/libs/three.min.js
vendored
File diff suppressed because one or more lines are too long
66
BlueMapCore/src/main/webroot/js/libs/utils.js
Normal file
66
BlueMapCore/src/main/webroot/js/libs/utils.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Vector2, Vector3 } from 'three';
|
||||||
|
|
||||||
|
export const stringToImage = string => {
|
||||||
|
let image = document.createElementNS('http://www.w3.org/1999/xhtml', 'img');
|
||||||
|
image.src = string;
|
||||||
|
return image;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const pathFromCoords = (x, z) => {
|
||||||
|
let path = 'x';
|
||||||
|
path += splitNumberToPath(x);
|
||||||
|
|
||||||
|
path += 'z';
|
||||||
|
path += splitNumberToPath(z);
|
||||||
|
|
||||||
|
path = path.substring(0, path.length - 1);
|
||||||
|
|
||||||
|
return path;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const splitNumberToPath = num => {
|
||||||
|
let path = '';
|
||||||
|
|
||||||
|
if (num < 0) {
|
||||||
|
num = -num;
|
||||||
|
path += '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
let s = num.toString();
|
||||||
|
|
||||||
|
for (let i = 0; i < s.length; i++) {
|
||||||
|
path += s.charAt(i) + '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hashTile = (x, z) => `x${x}z${z}`;
|
||||||
|
|
||||||
|
export const Vector2_ZERO = new Vector2(0, 0);
|
||||||
|
export const Vector3_ZERO = new Vector3(0, 0, 0);
|
@ -1,6 +1,8 @@
|
|||||||
// global variable to enable access through browser console
|
import $ from 'jquery';
|
||||||
var blueMap;
|
import BlueMap from './libs/BlueMap.js';
|
||||||
|
|
||||||
$(document).ready(function () {
|
import '../style/style.scss';
|
||||||
blueMap = new BlueMap($("#map-container")[0], "data/");
|
|
||||||
|
$(document).ready(() => {
|
||||||
|
window.blueMap = new BlueMap($('#map-container')[0], 'data/');
|
||||||
});
|
});
|
||||||
|
71
BlueMapCore/src/main/webroot/style/modules/alertbox.scss
Normal file
71
BlueMapCore/src/main/webroot/style/modules/alertbox.scss
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#alert-box {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-content: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: column;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
padding: 15px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
padding: 15px 0 5px 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #333333;
|
||||||
|
text-decoration: underline;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #888888;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
position: relative;
|
||||||
|
pointer-events: all;
|
||||||
|
margin: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
.alert-close-button {
|
||||||
|
/*position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
right: 5px;
|
||||||
|
*/
|
||||||
|
margin: -10px -10px 0px 0px;
|
||||||
|
padding: 0 0 5px 5px;
|
||||||
|
float: right;
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
line-height: 15px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #333333;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: 'x';
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #dd3333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
BlueMapCore/src/main/webroot/style/modules/compass.scss
Normal file
8
BlueMapCore/src/main/webroot/style/modules/compass.scss
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#bluemap-compass {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
|
||||||
|
&:hover #bluemap-compass-needle {
|
||||||
|
filter: invert(1);
|
||||||
|
}
|
||||||
|
}
|
10
BlueMapCore/src/main/webroot/style/modules/info.scss
Normal file
10
BlueMapCore/src/main/webroot/style/modules/info.scss
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#bluemap-info {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: 'i';
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
7
BlueMapCore/src/main/webroot/style/modules/mapmenu.scss
Normal file
7
BlueMapCore/src/main/webroot/style/modules/mapmenu.scss
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#bluemap-mapmenu {
|
||||||
|
width: 200px;
|
||||||
|
|
||||||
|
.selection, .dropdown li {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
41
BlueMapCore/src/main/webroot/style/modules/settings.scss
Normal file
41
BlueMapCore/src/main/webroot/style/modules/settings.scss
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#bluemap-settings {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-settings.active:not(:hover) {
|
||||||
|
background-color: #dddddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-settings:hover > img {
|
||||||
|
filter: invert(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-settings-container {
|
||||||
|
display: flex;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-settings-quality {
|
||||||
|
width: 150px;
|
||||||
|
height: 30px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-settings-quality .selection, #bluemap-settings-quality .dropdown li {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-settings-render-distance {
|
||||||
|
width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-settings-render-distance .selection {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-settings-render-distance input {
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
margin: 10px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
@ -1,290 +0,0 @@
|
|||||||
html, body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 15px;
|
|
||||||
font-family: Verdana,Helvetica,Arial,sans-serif;
|
|
||||||
|
|
||||||
color: #333333;
|
|
||||||
background-color: #dddddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.box {
|
|
||||||
color: #333333;
|
|
||||||
background-color: white;
|
|
||||||
box-shadow: 0px 1px 4px 0px rgba(50, 50, 50, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
background-color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:hover {
|
|
||||||
background-color: #333333;
|
|
||||||
color: #dddddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-container {
|
|
||||||
background-color: white;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
transition: all 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-container:hover {
|
|
||||||
background-color: #dddddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-container > .dropdown {
|
|
||||||
position: absolute;
|
|
||||||
background-color: white;
|
|
||||||
color: #333333;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
transition: all 0.3s;
|
|
||||||
max-height: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-container:hover > .dropdown {
|
|
||||||
max-height: 200px;
|
|
||||||
border-color: #ddddddFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-container > .dropdown > ul {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-container > .dropdown > ul > li {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-container > .dropdown > ul > li:hover {
|
|
||||||
color: #dddddd;
|
|
||||||
background-color: #333333;
|
|
||||||
}
|
|
||||||
|
|
||||||
#alert-box {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-content: center;
|
|
||||||
justify-content: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
flex-direction: column;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#alert-box h1 {
|
|
||||||
font-size: 1.4rem;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
margin: 0;
|
|
||||||
padding: 15px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#alert-box h2 {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
margin: 0;
|
|
||||||
padding: 15px 0 5px 0;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
#alert-box a {
|
|
||||||
color: #333333;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
#alert-box a:hover {
|
|
||||||
color: #888888;
|
|
||||||
}
|
|
||||||
|
|
||||||
#alert-box .alert {
|
|
||||||
position: relative;
|
|
||||||
pointer-events: all;
|
|
||||||
margin: 10px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#alert-box .alert .alert-close-button {
|
|
||||||
/*position: absolute;
|
|
||||||
top: 5px;
|
|
||||||
right: 5px;
|
|
||||||
*/
|
|
||||||
margin: -10px -10px 0px 0px;
|
|
||||||
padding: 0 0 5px 5px;
|
|
||||||
float: right;
|
|
||||||
width: 15px;
|
|
||||||
height: 15px;
|
|
||||||
line-height: 15px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 15px;
|
|
||||||
color: #333333;
|
|
||||||
}
|
|
||||||
|
|
||||||
#alert-box .alert .alert-close-button::after {
|
|
||||||
content: 'x';
|
|
||||||
}
|
|
||||||
|
|
||||||
#alert-box .alert .alert-close-button:hover {
|
|
||||||
color: #dd3333;
|
|
||||||
}
|
|
||||||
|
|
||||||
#map-container {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: black;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
#map-container canvas {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-loading {
|
|
||||||
position: absolute;
|
|
||||||
width: 200px;
|
|
||||||
line-height: 20px;
|
|
||||||
padding: 20px 0;
|
|
||||||
top: calc(50% - 31px);
|
|
||||||
left: calc(50% - 101px);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-topright {
|
|
||||||
position: absolute;
|
|
||||||
top: 10px;
|
|
||||||
right: 10px;
|
|
||||||
|
|
||||||
line-height: 30px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-topright > *:not(:last-child) {
|
|
||||||
border-right: solid 1px #dddddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-topleft {
|
|
||||||
position: absolute;
|
|
||||||
top: 10px;
|
|
||||||
left: 10px;
|
|
||||||
|
|
||||||
line-height: 30px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-topleft > *:not(:last-child) {
|
|
||||||
border-right: solid 1px #dddddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-mapmenu {
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-mapmenu .selection, #bluemap-mapmenu .dropdown li {
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-compass {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-compass:hover #bluemap-compass-needle {
|
|
||||||
filter: invert(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bluemap-position {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
width: 60px;
|
|
||||||
height: 30px;
|
|
||||||
padding: 0 5px 0 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bluemap-position::before {
|
|
||||||
position: absolute;
|
|
||||||
left: 7px;
|
|
||||||
color: #888888;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bluemap-position.pos-x::before {
|
|
||||||
content: "x:";
|
|
||||||
}
|
|
||||||
|
|
||||||
.bluemap-position.pos-y::before {
|
|
||||||
content: "y:";
|
|
||||||
}
|
|
||||||
|
|
||||||
.bluemap-position.pos-z::before {
|
|
||||||
content: "z:";
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-settings {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-settings.active:not(:hover) {
|
|
||||||
background-color: #dddddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-settings:hover > img {
|
|
||||||
filter: invert(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-settings-container {
|
|
||||||
display: flex;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-settings-quality {
|
|
||||||
width: 150px;
|
|
||||||
height: 30px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-settings-quality .selection, #bluemap-settings-quality .dropdown li {
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-settings-render-distance {
|
|
||||||
width: 180px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-settings-render-distance .selection {
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-settings-render-distance input {
|
|
||||||
width: calc(100% - 20px);
|
|
||||||
margin: 10px;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-info {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#bluemap-info::after {
|
|
||||||
content: 'i';
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
153
BlueMapCore/src/main/webroot/style/style.scss
Normal file
153
BlueMapCore/src/main/webroot/style/style.scss
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
@import "./modules/alertbox.scss";
|
||||||
|
@import "./modules/compass.scss";
|
||||||
|
@import "./modules/info.scss";
|
||||||
|
@import "./modules/mapmenu.scss";
|
||||||
|
@import "./modules/settings.scss";
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 15px;
|
||||||
|
font-family: Verdana,Helvetica,Arial,sans-serif;
|
||||||
|
|
||||||
|
color: #333333;
|
||||||
|
background-color: #dddddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
color: #333333;
|
||||||
|
background-color: white;
|
||||||
|
box-shadow: 0px 1px 4px 0px rgba(50, 50, 50, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
background-color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
background-color: #333333;
|
||||||
|
color: #dddddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-container {
|
||||||
|
background-color: white;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-container:hover {
|
||||||
|
background-color: #dddddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-container > .dropdown {
|
||||||
|
position: absolute;
|
||||||
|
background-color: white;
|
||||||
|
color: #333333;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
transition: all 0.3s;
|
||||||
|
max-height: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-container:hover > .dropdown {
|
||||||
|
max-height: 200px;
|
||||||
|
border-color: #ddddddFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-container > .dropdown > ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-container > .dropdown > ul > li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-container > .dropdown > ul > li:hover {
|
||||||
|
color: #dddddd;
|
||||||
|
background-color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#map-container {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: black;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#map-container canvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-loading {
|
||||||
|
position: absolute;
|
||||||
|
width: 200px;
|
||||||
|
line-height: 20px;
|
||||||
|
padding: 20px 0;
|
||||||
|
top: calc(50% - 31px);
|
||||||
|
left: calc(50% - 101px);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-topright {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
|
||||||
|
line-height: 30px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-topright > *:not(:last-child) {
|
||||||
|
border-right: solid 1px #dddddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-topleft {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
|
||||||
|
line-height: 30px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bluemap-topleft > *:not(:last-child) {
|
||||||
|
border-right: solid 1px #dddddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bluemap-position {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
width: 60px;
|
||||||
|
height: 30px;
|
||||||
|
padding: 0 5px 0 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bluemap-position::before {
|
||||||
|
position: absolute;
|
||||||
|
left: 7px;
|
||||||
|
color: #888888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bluemap-position.pos-x::before {
|
||||||
|
content: "x:";
|
||||||
|
}
|
||||||
|
|
||||||
|
.bluemap-position.pos-y::before {
|
||||||
|
content: "y:";
|
||||||
|
}
|
||||||
|
|
||||||
|
.bluemap-position.pos-z::before {
|
||||||
|
content: "z:";
|
||||||
|
}
|
14
BlueMapCore/tsconfig.json
Normal file
14
BlueMapCore/tsconfig.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"sourceMap": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"target": "es6",
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowJs": true
|
||||||
|
},
|
||||||
|
"include": [ "src" ]
|
||||||
|
}
|
79
BlueMapCore/webpack.config.js
Normal file
79
BlueMapCore/webpack.config.js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
const path = require('path')
|
||||||
|
const fs = require('fs')
|
||||||
|
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
|
|
||||||
|
const WEBROOT_PATH = path.resolve(__dirname, 'src/main/webroot')
|
||||||
|
const BUILD_PATH = path.resolve(__dirname, 'build/generated/webroot')
|
||||||
|
// folder with a generated world to render in the dev server
|
||||||
|
const WORLD_DATA_PATH = path.resolve(__dirname, 'build/generated/world')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: 'production',
|
||||||
|
devtool: 'source-map',
|
||||||
|
entry: {
|
||||||
|
'bluemap': path.resolve(WEBROOT_PATH, 'js/site.js'),
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: BUILD_PATH,
|
||||||
|
filename: 'js/[name].js',
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
contentBase: WORLD_DATA_PATH,
|
||||||
|
compress: true,
|
||||||
|
port: 8080,
|
||||||
|
hot: true,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new MiniCssExtractPlugin({
|
||||||
|
filename: 'style/[name].css?[hash]',
|
||||||
|
}),
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: path.resolve(WEBROOT_PATH, 'index.html'),
|
||||||
|
hash: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.css', '.scss'],
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
// Transpile JavaScript source files using TypeScript engine
|
||||||
|
{
|
||||||
|
test: /\.(js|ts)$/,
|
||||||
|
include: /src/,
|
||||||
|
use: 'ts-loader',
|
||||||
|
},
|
||||||
|
// Just import normal css files
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
include: /src/,
|
||||||
|
use: [
|
||||||
|
{ loader: MiniCssExtractPlugin.loader },
|
||||||
|
{ loader: 'css-loader' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Converts scss files into css to use within custom elements
|
||||||
|
{
|
||||||
|
test: /\.scss$/,
|
||||||
|
include: /src/,
|
||||||
|
use: [
|
||||||
|
{ loader: MiniCssExtractPlugin.loader },
|
||||||
|
{ loader: 'css-loader' },
|
||||||
|
{ loader: 'sass-loader' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Load additional files
|
||||||
|
{
|
||||||
|
test: /\.(png|svg)(\?.*$|$)/,
|
||||||
|
include: /src/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'file-loader',
|
||||||
|
options: { name: 'assets/[name].[ext]?[hash]' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
10
README.md
10
README.md
@ -1,6 +1,6 @@
|
|||||||
![title-banner](https://bluecolored.de/paste/bluemap-title.jpg)
|
![title-banner](https://bluecolored.de/paste/bluemap-title.jpg)
|
||||||
|
|
||||||
BlueMap is a tool that generates 3d-maps of your Minecraft worlds and displays them in your browser. Take a look at [this demo](https://bluecolored.de/bluemap). It is really easy to set up - almost plug-and-play - if you use the integrated web-server (optional).
|
BlueMap is a tool that generates 3d-maps of your Minecraft worlds and displays them in your browser. Take a look at [this demo](https://bluecolored.de/bluemap). It is really easy to set up - almost plug-and-play - if you use the integrated web-server (optional).
|
||||||
|
|
||||||
The Sponge-Plugin automatically updates your map as soon as something changes in your world, as well as rendering newly generated terrain and managing the render-tasks.
|
The Sponge-Plugin automatically updates your map as soon as something changes in your world, as well as rendering newly generated terrain and managing the render-tasks.
|
||||||
|
|
||||||
@ -15,21 +15,21 @@ Easy:
|
|||||||
`git clone https://github.com/BlueMap-Minecraft/BlueMap.git`
|
`git clone https://github.com/BlueMap-Minecraft/BlueMap.git`
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
In order to build BlueMap you simply need to run the `./gradlew shadowJar` command.
|
In order to build BlueMap you simply need to run the `./gradlew build` command.
|
||||||
You can find the compiled JAR file in `./build/libs`
|
You can find the compiled JAR file in `./build/libs`
|
||||||
|
|
||||||
### Issues / Suggestions
|
### Issues / Suggestions
|
||||||
You found a bug, have another issue or a suggestion? Please create an issue [here](https://github.com/BlueMap-Minecraft/BlueMap/issues)!
|
You found a bug, have another issue or a suggestion? Please create an issue [here](https://github.com/BlueMap-Minecraft/BlueMap/issues)!
|
||||||
|
|
||||||
### Contributing
|
### Contributing
|
||||||
You are welcome to contribute!
|
You are welcome to contribute!
|
||||||
Just create a pull request with your changes :)
|
Just create a pull request with your changes :)
|
||||||
|
|
||||||
## Using the CLI
|
## Using the CLI
|
||||||
BlueMap can be used on the command-line, to render your Minecraft-Worlds *(Currently supported versions: 1.12 - 1.14)*.
|
BlueMap can be used on the command-line, to render your Minecraft-Worlds *(Currently supported versions: 1.12 - 1.14)*.
|
||||||
|
|
||||||
Use `java -jar bluemap.jar` and BlueMap will generate a default config in the current working directory. You then can configure your maps and even the webserver as you wish. Then, re-run the command and BlueMap will render all the configured maps for you and start the webserver if you turned it on in the config.
|
Use `java -jar bluemap.jar` and BlueMap will generate a default config in the current working directory. You then can configure your maps and even the webserver as you wish. Then, re-run the command and BlueMap will render all the configured maps for you and start the webserver if you turned it on in the config.
|
||||||
To only run the webserver, just don't define any maps in the config.
|
To only run the webserver, just don't define any maps in the config.
|
||||||
|
|
||||||
You can use `-c <config-file>` on the command-line to define a different configuration-file.
|
You can use `-c <config-file>` on the command-line to define a different configuration-file.
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ BlueMap is mostly plug-and-play. Just install it like every other Sponge-Plugin
|
|||||||
|
|
||||||
**Before BlueMap can render anything,** it needs one more thing: resources! To render all the block-models, BlueMap makes use of the default minecraft-resources. Since they are property of mojang i can not include them in the plugin. Fortunately BlueMap can download them from mojangs servers for you, but you need to explicitly agree to this in the config! Simply change the `accept-download: false` setting to `accept-download: true`, and run the `/bluemap reload` command.
|
**Before BlueMap can render anything,** it needs one more thing: resources! To render all the block-models, BlueMap makes use of the default minecraft-resources. Since they are property of mojang i can not include them in the plugin. Fortunately BlueMap can download them from mojangs servers for you, but you need to explicitly agree to this in the config! Simply change the `accept-download: false` setting to `accept-download: true`, and run the `/bluemap reload` command.
|
||||||
|
|
||||||
After downloading the resources, BlueMap will start updating the configured worlds. To render the whole world for a start, you can use this command `/bluemap render [world]`.
|
After downloading the resources, BlueMap will start updating the configured worlds. To render the whole world for a start, you can use this command `/bluemap render [world]`.
|
||||||
|
|
||||||
Then, head over to `http://<your-server-ip>:8100/` and you should see your map! *(If there is only black, you might have to wait a little until BlueMap has rendered enough of the map. You can also try to zoom in: the hires-models are saved first)*
|
Then, head over to `http://<your-server-ip>:8100/` and you should see your map! *(If there is only black, you might have to wait a little until BlueMap has rendered enough of the map. You can also try to zoom in: the hires-models are saved first)*
|
||||||
|
|
||||||
|
10
build.gradle
10
build.gradle
@ -6,7 +6,7 @@ plugins {
|
|||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven {
|
maven {
|
||||||
url 'https://jitpack.io'
|
url 'https://jitpack.io'
|
||||||
}
|
}
|
||||||
maven {
|
maven {
|
||||||
@ -21,7 +21,7 @@ allprojects {
|
|||||||
|
|
||||||
compileJava.options.compilerArgs.add '-parameters'
|
compileJava.options.compilerArgs.add '-parameters'
|
||||||
compileTestJava.options.compilerArgs.add '-parameters'
|
compileTestJava.options.compilerArgs.add '-parameters'
|
||||||
|
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
apply plugin: 'com.github.johnrengelman.shadow'
|
apply plugin: 'com.github.johnrengelman.shadow'
|
||||||
}
|
}
|
||||||
@ -31,14 +31,14 @@ dependencies {
|
|||||||
compile project(':BlueMapSponge')
|
compile project(':BlueMapSponge')
|
||||||
}
|
}
|
||||||
|
|
||||||
shadowJar {
|
assemble.dependsOn shadowJar {
|
||||||
baseName = 'BlueMap'
|
baseName = 'BlueMap'
|
||||||
version = null
|
version = null
|
||||||
classifier = null
|
classifier = null
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
manifest {
|
manifest {
|
||||||
attributes 'Main-Class' : "de.bluecolored.bluemap.cli.BlueMapCLI"
|
attributes 'Main-Class' : "de.bluecolored.bluemap.cli.BlueMapCLI"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user