Move BlueMapVue and BlueMapWeb into the main repo

This commit is contained in:
Lukas Rieger (Blue) 2022-12-18 16:58:37 +01:00
parent 7918035abd
commit 6642c11742
No known key found for this signature in database
GPG Key ID: 2D09EC5ED2687FF2
79 changed files with 20674 additions and 4 deletions

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "BlueMapAPI"]
path = BlueMapAPI
url = https://github.com/BlueMap-Minecraft/BlueMapAPI
[submodule "BlueMapVue"]
path = BlueMapCommon/BlueMapVue
url = https://github.com/BlueMap-Minecraft/BlueMapVue

@ -1 +0,0 @@
Subproject commit ad27cb4211c515bb0ea6228ba4025f07580f3b8c

View File

@ -0,0 +1,27 @@
name: Node.js CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v2
with:
name: distribution
path: dist/*

23
BlueMapCommon/BlueMapVue/.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

@ -0,0 +1 @@
Subproject commit b5cd8989340198464e10af891afa8e4a13565dc5

View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) Blue <https://www.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.

View File

@ -0,0 +1,24 @@
# bluemapvue
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View File

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

12954
BlueMapCommon/BlueMapVue/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
{
"name": "bluemapvue",
"version": "0.1.0",
"description": "A vue based frontend to load and display Minecraft maps generated by BlueMap.",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/BlueMap-Minecraft/BlueMapWeb.git"
},
"keywords": [
"minecraft",
"minecraft-mod",
"minecraft-plugin",
"threejs",
"webgl",
"bluemap"
],
"author": "Lukas Rieger <contact@bluecolored.de> (https://bluecolored.de/)",
"license": "MIT",
"bugs": {
"url": "https://github.com/BlueMap-Minecraft/BlueMap/issues"
},
"homepage": "https://bluecolo.red/bluemap",
"dependencies": {
"bluemap": "file:./BlueMapWeb",
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vue-i18n": "^8.24.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"node-sass": "^5.0.0",
"sass-loader": "^10.1.1",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {
"no-unused-vars": "off",
"no-prototype-builtins": "off"
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
],
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
}
}

View File

@ -0,0 +1,192 @@
<?php
// !!! SET YOUR SQL-CONNECTION SETTINGS HERE: !!!
$hostname = "127.0.0.1";
$port = 3306;
$username = "root";
$password = "";
$database = "bluemap";
// set this to "none" if you disabled compression on your maps
$hiresCompression = "gzip";
// !!! END - DONT CHANGE ANYTHING AFTER THIS LINE !!!
// some helper functions
function error($code, $message = null) {
global $path;
http_response_code($code);
header("Content-Type: text/plain");
echo "BlueMap php-script - $code\n";
if ($message != null) echo $message."\n";
echo "Requested Path: $path";
exit;
}
function startsWith($haystack, $needle) {
return substr($haystack, 0, strlen($needle)) === $needle;
}
// mime-types for meta-files
$mimeDefault = "application/octet-stream";
$mimeTypes = [
"txt" => "text/plain",
"css" => "text/css",
"csv" => "text/csv",
"htm" => "text/html",
"html" => "text/html",
"js" => "text/javascript",
"xml" => "text/xml",
"png" => "image/png",
"jpg" => "image/jpeg",
"jpeg" => "image/jpeg",
"gif" => "image/gif",
"webp" => "image/webp",
"tif" => "image/tiff",
"tiff" => "image/tiff",
"svg" => "image/svg+xml",
"json" => "application/json",
"mp3" => "audio/mpeg",
"oga" => "audio/ogg",
"wav" => "audio/wav",
"weba" => "audio/webm",
"mp4" => "video/mp4",
"mpeg" => "video/mpeg",
"webm" => "video/webm",
"ttf" => "font/ttf",
"woff" => "font/woff",
"woff2" => "font/woff2"
];
function getMimeType($path) {
global $mimeDefault, $mimeTypes;
$i = strrpos($path, ".");
if ($i === false) return $mimeDefault;
$s = strrpos($path, "/");
if ($s !== false && $i < $s) return $mimeDefault;
$suffix = substr($path, $i + 1);
if (isset($mimeTypes[$suffix]))
return $mimeTypes[$suffix];
return $mimeDefault;
}
// determine relative request-path
$root = dirname($_SERVER['PHP_SELF']);
if ($root === "/" || $root === "\\") $root = "";
$uriPath = $_SERVER['REQUEST_URI'];
$path = substr($uriPath, strlen($root));
// add /
if ($path === "") {
header("Location: $uriPath/");
exit;
}
// root => index.html
if ($path === "/") {
header("Content-Type: text/html");
echo file_get_contents("index.html");
exit;
}
if (startsWith($path, "/maps/")) {
// determine map-path
$pathParts = explode("/", substr($path, strlen("/maps/")), 2);
$mapId = $pathParts[0];
$mapPath = $pathParts[1];
// get sql-connection
$sql = new mysqli($hostname, $username, $password, $database, $port);
if ($sql->errno) error(500, "Failed to connect to Database!");
// provide map-tiles
if (startsWith($mapPath, "tiles/")) {
// parse tile-coordinates
preg_match_all("/tiles\/([\d\/]+)\/x(-?[\d\/]+)z(-?[\d\/]+).*/", $mapPath, $matches);
$lod = intval($matches[1][0]);
$tileX = intval(str_replace("/", "", $matches[2][0]));
$tileZ = intval(str_replace("/", "", $matches[3][0]));
$compression = $lod === 0 ? $hiresCompression : "none";
// query for tile
$statement = $sql->prepare("
SELECT t.`data`
FROM `bluemap_map_tile` t
INNER JOIN `bluemap_map` m
ON t.`map` = m.`id`
INNER JOIN `bluemap_map_tile_compression` c
ON t.`compression` = c.`id`
WHERE m.`map_id` = ?
AND t.`lod` = ?
AND t.`x` = ?
AND t.`z` = ?
AND c.`compression` = ?
");
$statement->bind_param("siiis", $mapId, $lod, $tileX, $tileZ, $compression);
$statement->execute();
if ($statement->errno) error(500, "Database query failed!");
// return result
$result = $statement->get_result();
if ($result && $line = $result->fetch_assoc()) {
if ($compression !== "none")
header("Content-Encoding: $compression");
if ($lod === 0) {
header("Content-Type: application/json");
} else {
header("Content-Type: image/png");
}
echo $line["data"];
exit;
}
// empty json response if nothing found
header("Content-Type: application/json");
echo "{}";
exit;
}
// provide meta-files
$statement = $sql->prepare("
SELECT t.`value`
FROM `bluemap_map_meta` t
INNER JOIN `bluemap_map` m
ON t.`map` = m.`id`
WHERE m.`map_id` = ?
AND t.`key` = ?
");
$statement->bind_param("ss", $mapId, $mapPath);
$statement->execute();
if ($statement->errno) error(500, "Database query failed!");
$result = $statement->get_result();
if ($result && $line = $result->fetch_assoc()) {
header("Content-Type: ".getMimeType($mapPath));
echo $line["value"];
exit;
}
}
// no match => 404
error(404);

View File

@ -0,0 +1 @@
{}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -0,0 +1,19 @@
{
"$schema": "https://json.schemastore.org/web-manifest-combined.json",
"name": "BlueMap",
"short_name": "BlueMap",
"start_url": "..",
"display": "standalone",
"background_color": "#181818",
"theme_color": "#006EDE",
"description": "BlueMap is a tool that generates 3D maps of your Minecraft worlds and displays them in your browser.",
"icons": [{
"src": "logoCircle512.png",
"sizes": "512x512",
"type": "image/png"
},{
"src": "logoCircle64.png",
"sizes": "64x64",
"type": "image/png"
}]
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
<g>
<path fill="#FFFFFF" d="M37.468,17.123C37.468,29.596,25,45.346,25,45.346s-12.468-14.93-12.468-28.223
c0-6.885,5.581-12.468,12.468-12.468C31.885,4.655,37.468,10.237,37.468,17.123z"/>
</g>
<g>
<path fill="#333333" d="M26.901,12.559c0.034,1.046-0.732,1.885-1.954,1.885c-1.083,0-1.85-0.838-1.85-1.885
c0-1.082,0.804-1.92,1.918-1.92C26.169,10.639,26.901,11.478,26.901,12.559z M23.464,29.063l0.017-11.757h3.072l-0.018,11.757
H23.464z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 919 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description"
content="BlueMap is a tool that generates 3D maps of your Minecraft worlds and displays them in your browser">
<meta name="version" content="%version%">
<meta name="keywords" content="bluemap, map, minecraft, minecraft map">
<meta name="theme-color" content="#006EDE">
<meta name="og:site_name" content="BlueMap">
<meta name="og:title" content="BlueMap">
<meta name="og:description"
content="BlueMap is a tool that generates 3D maps of your Minecraft worlds and displays them in your browser">
<meta name="og:type" content="website">
<meta name="og:image" content="https://avatars.githubusercontent.com/u/42522657?s=200&v=4">
<meta name="robots" content="index,nofollow">
<link rel="icon" href="assets/favicon.png">
<link rel="manifest" href="assets/manifest.webmanifest">
<title>BlueMap</title>
</head>
<body>
<noscript>
<strong>Sorry but BlueMap doesn't work without JavaScript enabled.
Please <a href="https://www.enable-javascript.com/">enable</a> it to continue.</strong>
</noscript>
<div id="map-container"></div>
<div id="app"></div>
</body>
</html>

View File

@ -0,0 +1,144 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menu",
tooltip: "Menu"
},
maps: {
title: "Mapy",
button: "Mapy",
tooltip: "Seznam map"
},
markers: {
title: "Značky",
button: "Značky",
tooltip: "Seznam značek",
marker: "značka | značky",
markerSet: "sada značek | sady značek"
},
settings: {
title: "Nastavení",
button: "Nastavení"
},
goFullscreen: {
button: "Celá obrazovka"
},
resetCamera: {
button: "Obnovit kameru",
tooltip: "Obnovit kameru a pozici"
},
updateMap: {
button: "Aktualizovat mapu",
tooltip: "Vymazat mezipaměť dlaždic"
},
lighting: {
title: "Osvětlení",
dayNightSwitch: {
tooltip: "Den/noc"
},
sunlight: "Sluneční světlo",
ambientLight: "Ambientní osvětlení"
},
resolution: {
title: "Rozlišení",
high: "Vysoké (SSAA, x2)",
normal: "Normální (Native, x1)",
low: "Nízké (Upscaling, x0.5)"
},
freeFlightControls: {
title: "Ovládání volného létání",
mouseSensitivity: "Citlivost myši",
invertMouseY: "Invertovat Y myši"
},
renderDistance: {
title: "Dohled",
hiresLayer: "Vrstva vysokého rozlišení",
lowersLayer: "Vrstva nízkého rozlišení"
},
theme: {
title: "Téma",
default: "Výchozí (systém/prohlížeč)",
dark: "Tmavé",
light: "Světlé"
},
debug: {
button: "Ladění"
},
resetAllSettings: {
button: "Obnovit všechna nastavení"
},
players: {
title: "Hráči",
tooltip: "Seznam hráčů"
},
compass: {
tooltip: "Kompas / sever"
},
controls: {
title: "Zobrazení / ovládání",
perspective: {
button: "Perspektiva",
tooltip: "Zobrazení perspektivy"
},
flatView: {
button: "Plochý",
tooltip: "Ortografické / ploché zobrazení",
},
freeFlight: {
button: "Volné létání",
tooltip: "Volné létání / režim pozorovatele"
}
},
language: {
title: "Jazyk",
},
blockTooltip: {
block: "Blok",
position: "Pozice",
chunk: "Chunk",
region: {
region: "Oblast",
file: "Soubor"
},
light: {
light: "Světlo",
sun: "Slunce",
block: "Blok",
}
},
info: {
title: "Informace",
button: "Informace",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Ovládání myší:</h2>
<table>
<tr><th>pohyb</th><td><kbd>levé tlačítko</kbd> + táhnutí</td></tr>
<tr><th>přiblížení</th><td><kbd>kolečko myši</kbd> (otáčení)</td></tr>
<tr><th>rotace / naklonění</th><td><kbd>pravé tlačítko</kbd> + táhnutí</td></tr>
</table>
</p>
<p>
<h2>Ovládání klávesnicí:</h2>
<table>
<tr><th>pohyb</th><td><kbd>wasd</kbd> / <kbd>šipky</kbd></td></tr>
<tr><th>přiblížení</th><td>Num. klávesnice: <kbd>+</kbd>/<kbd>-</kbd> nebo <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>rotace / naklonění</th><td><kbd>Levý Alt</kbd> + <kbd>wasd</kbd> / <kbd>šipky</kbd> nebo <kbd>Del</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Ovládání dotykem:</h2>
<table>
<tr><th>pohyb</th><td>dotyk + táhnutí</td></tr>
<tr><th>přiblížení</th><td>dotyk dvěma prsty + roztáhnutí</td></tr>
<tr><th>rotace / naklonění</th><td>dotyk dvěma prsty + rotace / pohyb nahoru/dolů</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Mapa byla vygenerována s &#9829; pomocí <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
}

View File

@ -0,0 +1,149 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menü",
tooltip: "Menü"
},
maps: {
title: "Karten",
button: "Karten",
tooltip: "Kartenliste"
},
markers: {
title: "Marker",
button: "Marker",
tooltip: "Markerliste",
marker: "Marker | Marker",
markerSet: "Markerset | Markersets",
searchPlaceholder: "Suche...",
followPlayerTitle: "Spieler folgen"
},
settings: {
title: "Einstellungen",
button: "Einstellungen"
},
goFullscreen: {
button: "Vollbildmodus"
},
resetCamera: {
button: "Kamera zurücksetzen",
tooltip: "Kamera & Position zurücksetzen"
},
updateMap: {
button: "Karte aktualisieren",
tooltip: "Leere den Karten-Cache"
},
lighting: {
title: "Beleuchtung",
dayNightSwitch: {
tooltip: "Tag/Nacht"
},
sunlight: "Sonnenlicht",
ambientLight: "Umgebungslicht"
},
resolution: {
title: "Auflösung",
high: "Hoch (SSAA, x2)",
normal: "Normal (Nativ, x1)",
low: "Niedrig (Hochskalieren, x0.5)"
},
freeFlightControls: {
title: "Freie Kamera",
mouseSensitivity: "Maus-Sensitivität",
invertMouseY: "Maus Y umkehren"
},
renderDistance: {
title: "Renderdistanz",
hiresLayer: "Hires-Schicht",
lowersLayer: "Lowres-Schicht",
loadHiresWhileMoving: "Lade Hires während Bewegung",
off: "Off"
},
theme: {
title: "Farbmodus",
default: "Standard (System/Browser)",
dark: "Dunkel",
light: "Hell",
contrast: "Kontrast"
},
debug: {
button: "Debug"
},
resetAllSettings: {
button: "Einstellungen zurücksetzen"
},
players: {
title: "Spieler",
tooltip: "Spielerliste"
},
compass: {
tooltip: "Kompass / nach Norden ausrichten"
},
controls: {
title: "Ansicht / Steuerung",
perspective: {
button: "Perspektiv-Sicht",
tooltip: "Perspektivische Sicht"
},
flatView: {
button: "Flache Sicht",
tooltip: "Orthographisch / Flache Sicht",
},
freeFlight: {
button: "Freie Kamera",
tooltip: "Freie Kamera / Zuschauermodus"
}
},
language: {
title: "Sprache",
},
blockTooltip: {
block: "Block",
position: "Position",
chunk: "Chunk",
region: {
region: "Region",
file: "Datei"
},
light: {
light: "Licht",
sun: "Sonne",
block: "Block",
}
},
info: {
title: "Info",
button: "Info",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Maussteuerung:</h2>
<table>
<tr><th>Bewegen</th><td><kbd>Linksklick</kbd> + ziehen</td></tr>
<tr><th>Zoomen</th><td><kbd>Mausrad</kbd> (scrollen)</td></tr>
<tr><th>Drehen / Schwenken</th><td><kbd>Rechtsklick</kbd> + ziehen</td></tr>
</table>
</p>
<p>
<h2>Tastatursteuerung:</h2>
<table>
<tr><th>Bewegen</th><td><kbd>wasd</kbd> / <kbd>Pfeiltasten</kbd></td></tr>
<tr><th>Zoomen</th><td>Nummernblock: <kbd>+</kbd>/<kbd>-</kbd> oder <kbd>Einfg</kbd>/<kbd>Pos 1</kbd></td></tr>
<tr><th>Drehen / Schwenken</th><td><kbd>Alt</kbd> + <kbd>wasd</kbd> / <kbd>Pfeiltasten</kbd> oder <kbd>Entf</kbd>/<kbd>Ende</kbd>/<kbd>Bild &uarr;</kbd>/<kbd>Bild &darr;</kbd></td></tr>
</table>
</p>
<p>
<h2>Touchsteuerung:</h2>
<table>
<tr><th>Bewegen</th><td>berühren + ziehen</td></tr>
<tr><th>Zoomen</th><td>mit zwei Fingern berühren + zusammen/auseinander ziehen</td></tr>
<tr><th>Drehen / Schwenken</th><td>mit zwei Fingern berühren + drehen / hoch/runter ziehen</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Diese Map wurde mit &#9829; von <a href="https://bluecolo.red/bluemap">BlueMap</a> {version} generiert
</p>
`
}
};

View File

@ -0,0 +1,154 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menu",
tooltip: "Menu"
},
maps: {
title: "Maps",
button: "Maps",
tooltip: "Map-List"
},
markers: {
title: "Markers",
button: "Markers",
tooltip: "Marker-List",
marker: "marker | markers",
markerSet: "marker-set | marker-sets",
searchPlaceholder: "Search...",
followPlayerTitle: "Follow Player"
},
settings: {
title: "Settings",
button: "Settings"
},
goFullscreen: {
button: "Go Fullscreen"
},
resetCamera: {
button: "Reset Camera",
tooltip: "Reset Camera & Position"
},
updateMap: {
button: "Update Map",
tooltip: "Clear Tile Cache"
},
lighting: {
title: "Lighting",
dayNightSwitch: {
tooltip: "Day/Night"
},
sunlight: "Sunlight",
ambientLight: "Ambient-Light"
},
resolution: {
title: "Resolution",
high: "High (SSAA, x2)",
normal: "Normal (Native, x1)",
low: "Low (Upscaling, x0.5)"
},
freeFlightControls: {
title: "Free-Flight Controls",
mouseSensitivity: "Mouse-Sensitivity",
invertMouseY: "Invert Mouse Y"
},
renderDistance: {
title: "Render Distance",
hiresLayer: "Hires layer",
lowersLayer: "Lowres layer",
loadHiresWhileMoving: "Load hires while moving",
off: "Off"
},
theme: {
title: "Theme",
default: "Default (System/Browser)",
dark: "Dark",
light: "Light",
contrast: "Contrast"
},
debug: {
button: "Debug"
},
resetAllSettings: {
button: "Reset All Settings"
},
players: {
title: "Players",
tooltip: "Player-List"
},
compass: {
tooltip: "Compass / Face North"
},
screenshot: {
title: "Screenshot",
button: "Take Screenshot",
clipboard: "Copy to Clipboard"
},
controls: {
title: "View / Controls",
perspective: {
button: "Perspective",
tooltip: "Perspective-View"
},
flatView: {
button: "Flat",
tooltip: "Orthographic / Flat-View",
},
freeFlight: {
button: "Free-Flight",
tooltip: "Free-Flight / Spectator Mode"
}
},
language: {
title: "Language",
},
blockTooltip: {
block: "Block",
position: "Position",
chunk: "Chunk",
region: {
region: "Region",
file: "File"
},
light: {
light: "Light",
sun: "Sun",
block: "Block",
}
},
info: {
title: "Info",
button: "Info",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Mouse-Controls:</h2>
<table>
<tr><th>move</th><td><kbd>left-click</kbd> + drag</td></tr>
<tr><th>zoom</th><td><kbd>mousewheel</kbd> (scroll)</td></tr>
<tr><th>rotate / tilt</th><td><kbd>right-click</kbd> + drag</td></tr>
</table>
</p>
<p>
<h2>Keyboard-Controls:</h2>
<table>
<tr><th>move</th><td><kbd>wasd</kbd> / <kbd>arrow-keys</kbd></td></tr>
<tr><th>zoom</th><td>Numpad: <kbd>+</kbd>/<kbd>-</kbd> or <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>rotate / tilt</th><td><kbd>Left-Alt</kbd> + <kbd>wasd</kbd> / <kbd>arrow-keys</kbd> or <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Touch-Controls:</h2>
<table>
<tr><th>move</th><td>touch + drag</td></tr>
<tr><th>zoom</th><td>touch with two fingers + pinch</td></tr>
<tr><th>rotate / tilt</th><td>touch with two fingers + rotate / move up/down</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
This map has been generated with &#9829; using <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
};

View File

@ -0,0 +1,151 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menú",
tooltip: "Menú"
},
maps: {
title: "Mapas",
button: "Mapas",
tooltip: "Lista de mapas"
},
markers: {
title: "Marcadores",
button: "Marcadores",
tooltip: "Lista de marcadores",
marker: "marcador | marcadores",
markerSet: "Conjunto de Marcadores | Conjuntos de Marcadores",
searchPlaceholder: "Buscar...",
followPlayerTitle: "Seguir Jugador"
},
settings: {
title: "Ajustes",
button: "Ajustes"
},
goFullscreen: {
button: "Pantalla Completa"
},
resetCamera: {
button: "Restablecer Cámara",
tooltip: "Restablecer Cámara y Posición"
},
updateMap: {
button: "Actualizar Mapa",
tooltip: "Limpiar Cache"
},
lighting: {
title: "Iluminación",
dayNightSwitch: {
tooltip: "Día/Noche"
},
sunlight: "Luz de Día",
ambientLight: "Luz Ambiental"
},
resolution: {
title: "Resolución",
high: "Alta (SSAA, x2)",
normal: "Normal (Nativa, x1)",
low: "Baja (Ampliada, x0.5)"
},
freeFlightControls: {
title: "Controles de Vuelo Libre",
mouseSensitivity: "Sensibilidad de Ratón",
invertMouseY: "Invertir Eje Y del Ratón"
},
renderDistance: {
title: "Distancia de Renderizado",
hiresLayer: "Capa de Alta Resolución",
lowersLayer: "Capa de Baja Resolución"
},
theme: {
title: "Tema",
default: "Predeterminado (Sistema/Navegador)",
dark: "Oscuro",
light: "Claro"
},
debug: {
button: "Debug"
},
resetAllSettings: {
button: "Restaurar todo los ajustes"
},
players: {
title: "Jugadores",
tooltip: "Lista de Jugadores"
},
compass: {
tooltip: "Brújula / Norte"
},
screenshot: {
title: "Captura de Pantalla",
button: "Tomar Captura de Pantalla",
clipboard: "Copiar al Portapapeles",
},
controls: {
title: "Vista / Controles",
perspective: {
button: "Perspectiva",
tooltip: "Vista en perspectiva"
},
flatView: {
button: "Plano",
tooltip: "Ortogonal / Visualización Plana",
},
freeFlight: {
button: "Vuelo libre",
tooltip: "Vuelo libre / Modo espectador"
}
},
language: {
title: "Idioma",
},
blockTooltip: {
block: "Bloque",
position: "Posición",
chunk: "Chunk",
region: {
region: "Región",
file: "Archivo"
},
light: {
light: "Iluminación",
sun: "Sol",
block: "Bloque",
}
},
info: {
title: "Información",
button: "Información",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Control con ratón:</h2>
<table>
<tr><th>movimiento</th><td><kbd>clic izquierdo</kbd> + arrastrar</td></tr>
<tr><th>zoom</th><td><kbd>rueda del ratón</kbd> (desplazar)</td></tr>
<tr><th>rotar / inclinar</th><td><kbd>clic derecho</kbd> + arrastrar</td></tr>
</table>
</p>
<p>
<h2>Control con teclado:</h2>
<table>
<tr><th>movimiento</th><td><kbd>wasd</kbd> / <kbd>flechas de desplazamiento</kbd></td></tr>
<tr><th>zoom</th><td>Pad numérico: <kbd>+</kbd>/<kbd>-</kbd> ó <kbd>Insertar</kbd>/<kbd>Inicio</kbd></td></tr>
<tr><th>rotar / inclinar</th><td><kbd>Alt izquierdo</kbd> + <kbd>wasd</kbd> / <kbd>flechas de desplazamiento</kbd> ó <kbd>Supr</kbd>/<kbd>Fin</kbd>/<kbd>Re pág</kbd>/<kbd>Av Pág</kbd></td></tr>
</table>
</p>
<p>
<h2>Control con panel táctil:</h2>
<table>
<tr><th>movimiento</th><td>pulsa + arrastrar</td></tr>
<tr><th>zoom</th><td>pulsa con dos dedos + junta</td></tr>
<tr><th>rotar / inclinar</th><td>pulsa con dos dedos + rotar / desliza arriba/abajo</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Este mapa ha sido generado con &#9829; usando <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
};

View File

@ -0,0 +1,146 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Valikko",
tooltip: "Valikko"
},
maps: {
title: "Kartat",
button: "Kartat",
tooltip: "Karttalista"
},
markers: {
title: "Merkit",
button: "Merkit",
tooltip: "Merkkilista",
marker: "merkki | merkkiä",
markerSet: "merkkisetti | merkkisettiä",
searchPlaceholder: "Etsi...",
followPlayerTitle: "Seuraa pelaajaa"
},
settings: {
title: "Asetukset",
button: "Asetukset"
},
goFullscreen: {
button: "Mene kokoruudun tilaan"
},
resetCamera: {
button: "Nollaa kamera",
tooltip: "Nolla kamera ja sijainti"
},
updateMap: {
button: "Päivitä kartta",
tooltip: "Tyhjennä välimuisti"
},
lighting: {
title: "Valaistus",
dayNightSwitch: {
tooltip: "Päivä/Yö"
},
sunlight: "Auringonvalo",
ambientLight: "Ympäristön valo"
},
resolution: {
title: "Resoluutio",
high: "Korkea (SSAA, x2)",
normal: "Normaali (Natiivi, x1)",
low: "Alhainen (Skaalaus, x0.5)"
},
freeFlightControls: {
title: "Vapaan Lennon Ohjaimet",
mouseSensitivity: "Hiiren Herkkyys",
invertMouseY: "Käännä Hiiren Y"
},
renderDistance: {
title: "Näköetäisyys",
hiresLayer: "Korkea laatuinen kerros",
lowersLayer: "Matala laatuinen kerros"
},
theme: {
title: "Teema",
default: "Oletus (Järjestelmä/Selain)",
dark: "Tumma",
light: "Vaalea"
},
debug: {
button: "Debug"
},
resetAllSettings: {
button: "Nollaa Kaikki Asetukset"
},
players: {
title: "Pelaajat",
tooltip: "Pelaajalista"
},
compass: {
tooltip: "Kompassi / Katso Pohjoiseen"
},
controls: {
title: "Näkymä / Ohjaus",
perspective: {
button: "Perspektiivi",
tooltip: "Perspektiivi näkymä"
},
flatView: {
button: "Tasainen",
tooltip: "Ortografinen / Tasainen näkymä",
},
freeFlight: {
button: "Vapaa lento",
tooltip: "Vapaa lento / Katsojatila"
}
},
language: {
title: "Kieli",
},
blockTooltip: {
block: "Kuutio",
position: "Sijainti",
chunk: "Lohko",
region: {
region: "Alue",
file: "Tiedosto"
},
light: {
light: "Valo",
sun: "Aurinko",
block: "Kuutio",
}
},
info: {
title: "Tiedot",
button: "Tiedot",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Hiiriasetukset:</h2>
<table>
<tr><th>liiku</th><td><kbd>vasen painallus</kbd> + vedä</td></tr>
<tr><th>zoomaa</th><td><kbd>hiiren rulla</kbd> (rullaa)</td></tr>
<tr><th>käänny / kallista</th><td><kbd>oikea painallus</kbd> + vedä</td></tr>
</table>
</p>
<p>
<h2>Näppäimistöasetukset:</h2>
<table>
<tr><th>liiku</th><td><kbd>wasd</kbd> / <kbd>nuolinäppäimet</kbd></td></tr>
<tr><th>zoomaa</th><td>Numero näppäimistö: <kbd>+</kbd>/<kbd>-</kbd> tai <kbd>Ins-näppäin</kbd>/<kbd>Home-näppäin</kbd></td></tr>
<tr><th>käänny / kallista</th><td><kbd>Vasen-Alt</kbd> + <kbd>wasd</kbd> / <kbd>nuolinäppäimet</kbd> tai <kbd>Delete-näppäin</kbd>/<kbd>End-näppäin</kbd>/<kbd>Page Up -näppäin</kbd>/<kbd>Page Down -näppäin</kbd></td></tr>
</table>
</p>
<p>
<h2>Kosketusasetukset:</h2>
<table>
<tr><th>liiku</th><td>kosketa + vedä</td></tr>
<tr><th>zoomaa</th><td>kosketa kahdella sormella + nipistä</td></tr>
<tr><th>käänny / kallista</th><td>kosketa kahdella sormella + käännä / liiku ylös/alas</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Tämä kartta on tehty rakkaudella &#9829; käyttäen <a href="https://bluecolo.red/bluemap">BlueMap</a> {version} -ohjelmaa
</p>
`
}
};

View File

@ -0,0 +1,146 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menu",
tooltip: "Menu"
},
maps: {
title: "Cartes",
button: "Cartes",
tooltip: "Liste des cartes"
},
markers: {
title: "Balises",
button: "Balises",
tooltip: "Liste des balises",
marker: "balises | balises",
markerSet: "Collection de balises | Collections de balises",
searchPlaceholder: "Rechercher...",
followPlayerTitle: "Suivre ce Joueur"
},
settings: {
title: "Paramètres",
button: "Paramètres"
},
goFullscreen: {
button: "Plein Écran"
},
resetCamera: {
button: "Réinitialiser la Caméra",
tooltip: "Réinitialiser la Caméra et la Position"
},
updateMap: {
button: "Mettre à jour la Carte",
tooltip: "Nettoyer le Cache des Tuiles"
},
lighting: {
title: "Lumière",
dayNightSwitch: {
tooltip: "Jour/Nuit"
},
sunlight: "Soleil",
ambientLight: "Lumière Ambiante"
},
resolution: {
title: "Résolution",
high: "Haute (SSAA, x2)",
normal: "Normale (Native, x1)",
low: "Basse (Upscaling, x0.5)"
},
freeFlightControls: {
title: "Contrôles du Vol Libre",
mouseSensitivity: "Sensibilité de la Souris",
invertMouseY: "Inverser l'Y de la Souris"
},
renderDistance: {
title: "Distance de rendu",
hiresLayer: "Couche haute définition",
lowersLayer: "Couche basse définition"
},
theme: {
title: "Thème",
default: "Par Défaut (Système/Navigateur)",
dark: "Sombre",
light: "Clair"
},
debug: {
button: "Debug"
},
resetAllSettings: {
button: "Réinitialiser tous les Paramètres"
},
players: {
title: "Joueurs",
tooltip: "Liste des Joueurs"
},
compass: {
tooltip: "Boussole / Pointe le Nord"
},
controls: {
title: "Vue / Contrôles",
perspective: {
button: "Perspective",
tooltip: "Vue en Perspective"
},
flatView: {
button: "Plate",
tooltip: "Orthographique / Vue Plate",
},
freeFlight: {
button: "Vol Libre",
tooltip: "Vol Libre / Mode Spectateur"
}
},
language: {
title: "Langue",
},
blockTooltip: {
block: "Bloc",
position: "Position",
chunk: "Chunk",
region: {
region: "Région",
file: "Fichier"
},
light: {
light: "Lumière",
sun: "Soleil",
block: "Bloc",
}
},
info: {
title: "Info",
button: "Info",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Contrôles de la Souris :</h2>
<table>
<tr><th>déplacement</th><td><kbd>clic-gauche</kbd> + mouvement</td></tr>
<tr><th>zoom</th><td><kbd>molette</kbd> (scroll)</td></tr>
<tr><th>rotation / inclinaison</th><td><kbd>clic-droit</kbd> + mouvement</td></tr>
</table>
</p>
<p>
<h2>Contrôles du Clavier :</h2>
<table>
<tr><th>déplacement</th><td><kbd>zqsd</kbd> / <kbd>flèches</kbd></td></tr>
<tr><th>zoom</th><td>Pavé Numérique : <kbd>+</kbd>/<kbd>-</kbd> ou <kbd>Inser</kbd>/<kbd>Début</kbd></td></tr>
<tr><th>rotation / inclinaison</th><td><kbd>Alt-Gauche</kbd> + <kbd>zqsd</kbd> / <kbd>flèches</kbd> ou <kbd>Suppr</kbd>/<kbd>Fin</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Contrôles du Toucher :</h2>
<table>
<tr><th>déplacement</th><td>toucher + mouvement</td></tr>
<tr><th>zoom</th><td>toucher avec 2 doigts + pincement</td></tr>
<tr><th>rotation / inclinaison</th><td>toucher avec 2 doigts + rotation / haut/bas</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Cette carte a été générée avec &#9829; par <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
}

View File

@ -0,0 +1,146 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "मेन्यू",
tooltip: "मेन्यू"
},
maps: {
title: "नक्शे",
button: "नक्शे",
tooltip: "मानचित्र-सूची"
},
markers: {
title: "मार्करों",
button: "मार्करों",
tooltip: "मार्कर-सूची",
marker: "मार्कर | मार्करों",
markerSet: "मार्कर-सेट | मार्कर-सेट",
searchPlaceholder: "खोज...",
followPlayerTitle: "प्लेयर को फॉलो करें"
},
settings: {
title: "सेटिंग्स",
button: "सेटिंग्स"
},
goFullscreen: {
button: "पूर्णस्क्रीन मोड"
},
resetCamera: {
button: "कैमरा रीसेट करें",
tooltip: "कैमरा और स्थिति रीसेट करें"
},
updateMap: {
button: "नक्शा अपडेट करें",
tooltip: "टाइल कैश साफ़ करें"
},
lighting: {
title: "प्रकाश",
dayNightSwitch: {
tooltip: "दिन हो या रात"
},
sunlight: "सूरज की रोशनी",
ambientLight: "परिवेश प्रकाश"
},
resolution: {
title: "संकल्प",
high: "उच्च (SSAA, x2)",
normal: "सामान्य (देशी, x1)",
low: "कम (अप स्केलिंग, x0.5)"
},
freeFlightControls: {
title: "मुक्त उड़ान नियंत्रण",
mouseSensitivity: "माउस-संवेदनशीलता",
invertMouseY: "माउस-संवेदनशीलता"
},
renderDistance: {
title: "रेंडर दूरी",
hiresLayer: "परत काम देता है",
lowersLayer: "निचली परत"
},
theme: {
title: "थीम",
default: "डिफ़ॉल्ट (सिस्टम / ब्राउज़र)",
dark: "डार्क",
light: "प्रकाश"
},
debug: {
button: "डिबग"
},
resetAllSettings: {
button: "सभी सेटिंग्स रीसेट करें"
},
players: {
title: "खिलाड़ी",
tooltip: "प्लेयर-सूची"
},
compass: {
tooltip: "कम्पास / फेस नॉर्थ"
},
controls: {
title: "देखें / नियंत्रण",
perspective: {
button: "परिप्रेक्ष्य",
tooltip: "परिप्रेक्ष्य-दृश्य"
},
flatView: {
button: "फ्लैट",
tooltip: "ऑर्थोग्राफिक / फ्लैट-व्यू",
},
freeFlight: {
button: "फ्री-फ्लाइट",
tooltip: "फ्री-फ्लाइट / दर्शक मोड"
}
},
language: {
title: "भाषा",
},
blockTooltip: {
block: "ब्लॉक",
position: "स्थिति",
chunk: "चंक",
region: {
region: "क्षेत्र",
file: "फ़ाइल"
},
light: {
light: "प्रकाश",
sun: "सूर्य",
block: "ब्लॉक",
}
},
info: {
title: "जानकारी",
button: "जानकारी",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>उस-िरण:</h2>
<table>
<tr><th>कदम</th><td><kbd> ि </kbd> + </td></tr>
<tr><th></th><td><kbd></kbd> ()</td></tr>
<tr><th> / </th><td><kbd>-ि </kbd> + </td></tr>
</table>
</p>
<p>
<h2> पर िरण:</h2>
<table>
<tr><th>कदम</th><td><kbd>wasd</kbd> / <kbd> </kbd></td></tr>
<tr><th></th><td>Numpad: <kbd></kbd>/<kbd></kbd> <kbd></kbd>/<kbd></kbd></td></tr>
<tr><th> / </th><td><kbd>-Alt</kbd> + <kbd>wasd</kbd> / <kbd> </kbd> <kbd></kbd>/<kbd></kbd>/<kbd></kbd>/<kbd> </kbd></td></tr>
</table>
</p>
<p>
<h2>पर िरण:</h2>
<table>
<tr><th>कदम</th><td> + </td></tr>
<tr><th></th><td> ि + </td></tr>
<tr><th> / </th><td> ि + / / </td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
उपय कर उतपन <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
};

View File

@ -0,0 +1,146 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menü",
tooltip: "Menü"
},
maps: {
title: "Térképek",
button: "Térképek",
tooltip: "Térképlista"
},
markers: {
title: "Jelölők",
button: "Jelölők",
tooltip: "Jelölőlista",
marker: "jelölő | jelölők",
markerSet: "jelölőkészlet | jelölőkészletek",
searchPlaceholder: "Keresés...",
followPlayerTitle: "Játékos követése"
},
settings: {
title: "Beállítások",
button: "Beállítások"
},
goFullscreen: {
button: "Teljes képernyős mód bekapcsolása"
},
resetCamera: {
button: "Kamera visszaállítása",
tooltip: "Kamera & pozíció visszaállítása"
},
updateMap: {
button: "Térkép frissítése",
tooltip: "Csempe gyorsítótárának törlése"
},
lighting: {
title: "Villámlás",
dayNightSwitch: {
tooltip: "Reggel/Éjszaka"
},
sunlight: "Napfény",
ambientLight: "Háttérvilágítás"
},
resolution: {
title: "Felbontás",
high: "Magas (SSAA, x2)",
normal: "Normál (Native, x1)",
low: "Alacsony (Upscaling, x0.5)"
},
freeFlightControls: {
title: "Szabadrepülési vezérlők",
mouseSensitivity: "Egér érzékenység",
invertMouseY: "Egér Y tengelyének invertálása"
},
renderDistance: {
title: "Látótávolság",
hiresLayer: "Hires réteg",
lowersLayer: "Lowres réteg"
},
theme: {
title: "Téma",
default: "Alapértelmezett (Rendszer/Böngésző)",
dark: "Sötét",
light: "Világos"
},
debug: {
button: "Hibakeresés"
},
resetAllSettings: {
button: "Minden beállítás alaphelyzetbe állítása"
},
players: {
title: "Játékosok",
tooltip: "Játékos lista"
},
compass: {
tooltip: "Iránytű / Északra fordulás"
},
controls: {
title: "Nézet / Vezérlés",
perspective: {
button: "Perspektivikus",
tooltip: "Perspektivikus nézet"
},
flatView: {
button: "Lapos",
tooltip: "Orthographic / Lapos nézet",
},
freeFlight: {
button: "Szabadrepülés",
tooltip: "Szabadrepülési / Szemlélő mód"
}
},
language: {
title: "Nyelv",
},
blockTooltip: {
block: "Blokk",
position: "Pozíció",
chunk: "Chunk",
region: {
region: "Régió",
file: "Fájl"
},
light: {
light: "Fény",
sun: "Nap",
block: "Blokk",
}
},
info: {
title: "Infó",
button: "Infó",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Egeres vezérlés:</h2>
<table>
<tr><th>mozgatás</th><td><kbd>bal klikk</kbd> + húzás</td></tr>
<tr><th>zoomolás</th><td><kbd>görgő</kbd> (görgetés)</td></tr>
<tr><th>elforgatás / döntés</th><td><kbd>jobb klikk</kbd> + húzás</td></tr>
</table>
</p>
<p>
<h2>Billentyűzetes vezérlés:</h2>
<table>
<tr><th>mozgatás</th><td><kbd>wasd</kbd> / <kbd>nyilak</kbd></td></tr>
<tr><th>zoomolás</th><td>Numpad: <kbd>+</kbd>/<kbd>-</kbd> or <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>elforgatás / döntés</th><td><kbd>Bal alt</kbd> + <kbd>wasd</kbd> / <kbd>arrow-keys</kbd> vagy <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Érintéses vezérlés:</h2>
<table>
<tr><th>mozgatás</th><td>érintés + húzás</td></tr>
<tr><th>zoomolás</th><td>két ujjal érintés + csípés</td></tr>
<tr><th>elforgatás / döntés</th><td>két ujjal érintés + forgatás / felfele/lefele mozgatás</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Ez a térkép &#9829; a <a href="https://bluecolo.red/bluemap">BlueMap</a> {version} segítségével lett generálva
</p>
`
}
};

View File

@ -0,0 +1,144 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menu",
tooltip: "Menu"
},
maps: {
title: "Mappe",
button: "Mappe",
tooltip: "Map-List"
},
markers: {
title: "Marcatori",
button: "Marcatori",
tooltip: "Lista-Marcatori",
marker: "marcatore | marcatori",
markerSet: "set-di-marcatori | sets-di-marcatori"
},
settings: {
title: "Impostazioni",
button: "Impostazioni"
},
goFullscreen: {
button: "Metti Lo Schermo Pieno"
},
resetCamera: {
button: "Resetta La Telecamera",
tooltip: "Resetta La Telecamera E La Posizione"
},
updateMap: {
button: "Aggiorna Mappa",
tooltip: "Pulisci La Chace Delle Caselle"
},
lighting: {
title: "Illuminazione",
dayNightSwitch: {
tooltip: "Giorno/Notte"
},
sunlight: "Luce",
ambientLight: "Luce-Ambientale"
},
resolution: {
title: "Risoluzione",
high: "Alta (SSAA, x2)",
normal: "Normale (Nativa, x1)",
low: "Bassa (Upscaling, x0.5)"
},
freeFlightControls: {
title: "Controlli Free-Flight",
mouseSensitivity: "Sensitivita-Mouse",
invertMouseY: "Inverti Y Del Mouse"
},
renderDistance: {
title: "Distanza Rendering",
hiresLayer: "Layer Alta Risoluzione",
lowersLayer: "Layer Bassa Risoluzione"
},
theme: {
title: "Tema",
default: "Default (Sistema/Browser)",
dark: "Scuro",
light: "Chiaro"
},
debug: {
button: "Debug"
},
resetAllSettings: {
button: "Ripristina Impostazioni"
},
players: {
title: "Giocatori",
tooltip: "Lista-Giocatori"
},
compass: {
tooltip: "Compasso / Verso Nord"
},
controls: {
title: "Visuale / Controlli",
perspective: {
button: "Prospettiva",
tooltip: "Visuale-Prospettiva"
},
flatView: {
button: "Piatta",
tooltip: "Ortografica / Visuale-Piatta",
},
freeFlight: {
button: "Free-Flight",
tooltip: "Free-Flight / Modalita Spettatore"
}
},
language: {
title: "Lingua",
},
blockTooltip: {
block: "Blocco",
position: "Posizione",
chunk: "Chunk",
region: {
region: "Regione",
file: "File"
},
light: {
light: "Luminosita",
sun: "Sole",
block: "Blocco",
}
},
info: {
title: "Informazioni",
button: "Informazioni",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Controlli-Mouse:</h2>
<table>
<tr><th>movimento</th><td><kbd>tasto-sinistro</kbd> + scorrimento</td></tr>
<tr><th>zoom</th><td><kbd>rotellina</kbd> (scroll)</td></tr>
<tr><th>rotazione / inclinazione</th><td><kbd>tasto-destro</kbd> + scorrimento</td></tr>
</table>
</p>
<p>
<h2>Controlli-Tastiera:</h2>
<table>
<tr><th>movimento</th><td><kbd>wasd</kbd> / <kbd>tasti-direzionali</kbd></td></tr>
<tr><th>zoom</th><td>Numpad: <kbd>+</kbd>/<kbd>-</kbd> or <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>rotazione / inclinazione</th><td><kbd>Alt-Sinistro</kbd> + <kbd>wasd</kbd> / <kbd>tasti-direzionali</kbd> or <kbd>Rimuovi</kbd>/<kbd>End</kbd>/<kbd>Pagina Su</kbd>/<kbd>Pagina Giu</kbd></td></tr>
</table>
</p>
<p>
<h2>Touch-Controls:</h2>
<table>
<tr><th>movimento</th><td>tocco + scorrimento</td></tr>
<tr><th>zoom</th><td>tocco con due dita + pizzico</td></tr>
<tr><th>rotazione / inclinazione</th><td>tocco con due dita + rotazione / muovi in alto/basso</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Questa mappa e' stata generata con &#9829; usando <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
}

View File

@ -0,0 +1,146 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "メニュー",
tooltip: "メニューを表示"
},
maps: {
title: "ワールド",
button: "ワールド",
tooltip: "ワールド一覧"
},
markers: {
title: "マーカー",
button: "マーカー",
tooltip: "マーカー一覧",
marker: "マーカー | マーカー",
markerSet: "マーカーグループ | マーカーグループ",
searchPlaceholder: "検索...",
followPlayerTitle: "プレイヤーを追跡"
},
settings: {
title: "設定",
button: "設定"
},
goFullscreen: {
button: "フルスクリーン"
},
resetCamera: {
button: "カメラ位置をリセット",
tooltip: "カメラ位置をリセット"
},
updateMap: {
button: "地形情報を更新",
tooltip: "キャッシュを削除して最新情報に更新する"
},
lighting: {
title: "明るさ",
dayNightSwitch: {
tooltip: "夜/朝を切り替え"
},
sunlight: "時間帯",
ambientLight: "明るさ"
},
resolution: {
title: "グラフィック品質",
high: "最高設定! (SSAA, x2)",
normal: "描画優先 (Native, x1)",
low: "処理優先 (Upscaling, x0.5)"
},
freeFlightControls: {
title: "マウス設定",
mouseSensitivity: "マウス感度",
invertMouseY: "Y軸の反転"
},
renderDistance: {
title: "描画距離",
hiresLayer: "高品質の距離",
lowersLayer: "低品質の距離"
},
theme: {
title: "テーマ",
default: "デフォルト (システム / ブラウザー の設定)",
dark: "ダーク",
light: "ライト"
},
debug: {
button: "デバッグ情報の表示"
},
resetAllSettings: {
button: "設定をリセット"
},
players: {
title: "プレイヤー",
tooltip: "プレイヤー一覧"
},
compass: {
tooltip: "方角 / クリックで方角をリセット"
},
controls: {
title: "視点",
perspective: {
button: "立体",
tooltip: "立体表示"
},
flatView: {
button: "平面",
tooltip: "平面表示",
},
freeFlight: {
button: "スペクテイター",
tooltip: "スペクテイターモード"
}
},
language: {
title: "言語",
},
blockTooltip: {
block: "ブロック",
position: "座標",
chunk: "チャンク",
region: {
region: "リージョン",
file: "ファイル"
},
light: {
light: "明るさ",
sun: "太陽光",
block: "光源"
}
},
info: {
title: "情報",
button: "情報",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>マウス操作:</h2>
<table>
<tr><th>移動</th><td><kbd></kbd> + </td></tr>
<tr><th>ズーム</th><td><kbd></kbd> (scroll)</td></tr>
<tr><th>回転 / 傾き</th><td><kbd></kbd> + </td></tr>
</table>
</p>
<p>
<h2>キーボード操作:</h2>
<table>
<tr><th>移動</th><td><kbd>wasd</kbd> / <kbd></kbd></td></tr>
<tr><th>ズーム</th><td>Numpad: <kbd>+</kbd>/<kbd>-</kbd> or <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>回転 / 傾き</th><td><kbd>Left-Alt</kbd> + <kbd>wasd</kbd> / <kbd>arrow-keys</kbd> or <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>タッチ操作:</h2>
<table>
<tr><th>移動</th><td></td></tr>
<tr><th>ズーム</th><td> /</td></tr>
<tr><th>回転 / 傾き</th><td>二本指でドラッグ + 回転 / 昇降</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
このマップは<a href="https://bluecolo.red/bluemap">BlueMap</a> {version}&#9829;
</p>
`
}
}

View File

@ -0,0 +1,146 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "메뉴",
tooltip: "메뉴"
},
maps: {
title: "월드",
button: "월드",
tooltip: "월드 목록"
},
markers: {
title: "마커",
button: "마커",
tooltip: "마커 목록",
marker: "개의 마커",
markerSet: "마커 목록 | 마커 목록",
searchPlaceholder: "검색...",
followPlayerTitle: "플레이어 따라가기"
},
settings: {
title: "설정",
button: "설정"
},
goFullscreen: {
button: "전체화면"
},
resetCamera: {
button: "카메라 위치 초기화",
tooltip: "카메라의 위치를 초기화합니다."
},
updateMap: {
button: "맵 정보 갱신",
tooltip: "맵 타일 캐시를 삭제합니다."
},
lighting: {
title: "광원",
dayNightSwitch: {
tooltip: "밤/낮 전환"
},
sunlight: "자연광",
ambientLight: "주변광"
},
resolution: {
title: "해상도",
high: "높음 (SSAA, x2)",
normal: "보통 (Native, x1)",
low: "낮음 (Upscaling, x0.5)"
},
freeFlightControls: {
title: "자유 이동 조작",
mouseSensitivity: "마우스 감도",
invertMouseY: "마우스 Y축 반전"
},
renderDistance: {
title: "렌더 거리",
hiresLayer: "고해상도 레이어",
lowersLayer: "저해상도 레이어"
},
theme: {
title: "테마",
default: "기본값 (시스템/브라우저)",
dark: "Dark",
light: "Light"
},
debug: {
button: "디버그"
},
resetAllSettings: {
button: "설정값 재설정"
},
players: {
title: "플레이어",
tooltip: "플레이어 목록"
},
compass: {
tooltip: "나침반 / 북쪽 보기"
},
controls: {
title: "시점 / 컨트롤",
perspective: {
button: "투시",
tooltip: "투시로 보기"
},
flatView: {
button: "평면",
tooltip: "직각투영 / 평면으로 보기",
},
freeFlight: {
button: "자유 이동",
tooltip: "자유 이동 / 관전모드로 보기"
}
},
language: {
title: "언어",
},
blockTooltip: {
block: "블록",
position: "위치",
chunk: "청크",
region: {
region: "지역",
file: "파일"
},
light: {
light: "광원",
sun: "자연",
block: "블럭",
}
},
info: {
title: "정보",
button: "정보",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>마우스 조작:</h2>
<table>
<tr><th>이동</th><td><kbd></kbd> + </td></tr>
<tr><th>확대</th><td><kbd> </kbd> ()</td></tr>
<tr><th>회전 / 기울이기</th><td><kbd></kbd> + </td></tr>
</table>
</p>
<p>
<h2>키보드 조작:</h2>
<table>
<tr><th>이동</th><td><kbd>wasd</kbd> / <kbd> </kbd></td></tr>
<tr><th>확대</th><td>: <kbd>+</kbd>/<kbd>-</kbd> <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>회전 / 기울이기</th><td><kbd> Alt</kbd> + <kbd>wasd</kbd> / <kbd> </kbd> <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>터치 조작:</h2>
<table>
<tr><th>이동</th><td> + </td></tr>
<tr><th>확대</th><td> + </td></tr>
<tr><th>회전 / 기울이기</th><td>두 손가락으로 터치 + 회전 / /아래로 끌기</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
지도는 &#9829; <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
};

View File

@ -0,0 +1,145 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Izvēlne",
tooltip: "Izvēlne"
},
maps: {
title: "Kartes",
button: "Kartes",
tooltip: "Karšu Saraksts"
},
markers: {
title: "Marķieri",
button: "Marķieri",
tooltip: "Marķieru Saraksts",
marker: "Marķieris | Marķieri",
markerSet: "Marķieru Kopa | Marķieru Kopas",
searchPlaceholder: "Meklēt..."
},
settings: {
title: "Iestatījumi",
button: "Iestatījumi"
},
goFullscreen: {
button: "Pilnekrāna Režīms"
},
resetCamera: {
button: "Atiestatīt Kameru",
tooltip: "Atiestatīt Kameru & Pozīciju"
},
updateMap: {
button: "Atjaunot Karti",
tooltip: "Notīrīt Kartes Kešatmiņu"
},
lighting: {
title: "Apgaismojums",
dayNightSwitch: {
tooltip: "Diena/Nakts"
},
sunlight: "Saules Gaisma",
ambientLight: "Gaisma No Blokiem"
},
resolution: {
title: "Ižšķirtspēja",
high: "Augsta (SSAA, x2)",
normal: "Vidēja (Iebūvētā, x1)",
low: "Zema (Palielināšana, x0.5)"
},
freeFlightControls: {
title: "Brīvā Lidojuma Vadība",
mouseSensitivity: "Peles Jūtība",
invertMouseY: "Izvērst Peli Y Asī"
},
renderDistance: {
title: "Renderēšanas Attālums",
hiresLayer: "Augstās Kval. Slānis",
lowersLayer: "Zemās Kval. Slānis"
},
theme: {
title: "Motīvs",
default: "Noklusētais (Sistēma/Pārlūks)",
dark: "Tumšs",
light: "Gaišs"
},
debug: {
button: "Atķļūdošana"
},
resetAllSettings: {
button: "Atjaunot Iestatījumus"
},
players: {
title: "Spēlētāji",
tooltip: "Spēlētāju Saraksts"
},
compass: {
tooltip: "Kompass / Pagriezt Uz Ziemeļiem"
},
controls: {
title: "Skats / Vadība",
perspective: {
button: "Perspektīvā Projekcija",
tooltip: "3D / Perspektīvā Projekcija"
},
flatView: {
button: "Plakans",
tooltip: "Ortogrāfiskais / Plakanais Skats",
},
freeFlight: {
button: "Brīvais Lidojums",
tooltip: "Brīvais Lidojums / Skatītāja Režīms"
}
},
language: {
title: "Valoda",
},
blockTooltip: {
block: "Bloks",
position: "Pozīcija",
chunk: "Gabals",
region: {
region: "Reģions",
file: "Fails"
},
light: {
light: "Gaisma",
sun: "Saule",
block: "Bloks",
}
},
info: {
title: "Informācija",
button: "Informācija",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Peles Vadība:</h2>
<table>
<tr><th>Pārvietošana</th><td><kbd>Kreisais Peles Klikšķis</kbd> + drag</td></tr>
<tr><th>Pietuvināšana</th><td><kbd>Peles Rullītis</kbd> (scroll)</td></tr>
<tr><th>Rotācija / Sašķiebšana</th><td><kbd>Labais Peles Klikšķis</kbd> + drag</td></tr>
</table>
</p>
<p>
<h2>Klaviatūras Vadība::</h2>
<table>
<tr><th>Pārvietošana</th><td><kbd>WASD</kbd> / <kbd>Bultiņu Taustiņi</kbd></td></tr>
<tr><th>Pietuvināšana</th><td>Numurtaustiņi <kbd>+</kbd>/<kbd>-</kbd> vai <kbd>Insert</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>Rotācija / Sašķiebšana</th><td><kbd>Kreisais-Alt</kbd> + <kbd>WASD</kbd> / <kbd>Bultiņu Taustiņi</kbd> vai <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Pieskārienu Vadība:</h2>
<table>
<tr><th>Pārvietošana</th><td>Pieskāriens + Vilkšana</td></tr>
<tr><th>Pietuvināšana</th><td>Pieskarieties Ar Diviem Pirkstiem + Satvert</td></tr>
<tr><th>Rotācija / Sašķiebšana</th><td>Pieskarieties Ar Diviem Pirkstiem + Rotācija / Uz Augšu/Leju</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Šī karte veidota ar &#9829; <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
}

View File

@ -0,0 +1,146 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menu",
tooltip: "Menu"
},
maps: {
title: "Kaarten",
button: "Kaarten",
tooltip: "Kaartenlijst"
},
markers: {
title: "Markers",
button: "Markers",
tooltip: "Markerlijst",
marker: "marker | markers",
markerSet: "Markerset | Markersets",
searchPlaceholder: "Zoek...",
followPlayerTitle: "Volg Speler"
},
settings: {
title: "Instellingen",
button: "Instellingen"
},
goFullscreen: {
button: "Volledig scherm modus"
},
resetCamera: {
button: "Camera terugzetten",
tooltip: "Camera & Positie terugzetten"
},
updateMap: {
button: "Kaart verversen",
tooltip: "Leeg de kaarten-cache"
},
lighting: {
title: "Belichting",
dayNightSwitch: {
tooltip: "Dag/Nacht"
},
sunlight: "Zonlicht",
ambientLight: "Omgevingslicht"
},
resolution: {
title: "Resolutie",
high: "Hoog (SSAA, x2)",
normal: "Normaal (Standaard, x1)",
low: "Laag (Opgeschaald, x0.5)"
},
freeFlightControls: {
title: "Vrije camera",
mouseSensitivity: "Muis gevoeligheid",
invertMouseY: "Muis Y omdraaien"
},
renderDistance: {
title: "Renderafstand",
hiresLayer: "Hires-Laag",
lowersLayer: "Lowres-Laag"
},
theme: {
title: "Kleurmodus",
default: "Standaard (Systeem/Browser)",
dark: "Donker",
light: "Licht"
},
debug: {
button: "Debug"
},
resetAllSettings: {
button: "Instellingen terugzetten"
},
players: {
title: "Spelers",
tooltip: "Spelerlijst"
},
compass: {
tooltip: "Kompas / Naar het noorden richten"
},
controls: {
title: "Aanzicht / Besturing",
perspective: {
button: "Perspectief",
tooltip: "Perspectief aanzicht"
},
flatView: {
button: "Plat",
tooltip: "Orthografisch / Plat aanzicht",
},
freeFlight: {
button: "Vrije vlucht",
tooltip: "Vrije vlucht / Toeschouwersmodus"
}
},
language: {
title: "Taal",
},
blockTooltip: {
block: "Blok",
position: "Positie",
chunk: "Chunk",
region: {
region: "Regio",
file: "Datum"
},
light: {
light: "Licht",
sun: "Zon",
block: "Blok",
}
},
info: {
title: "Info",
button: "Info",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Muisbediening:</h2>
<table>
<tr><th>Bewegen</th><td><kbd>Linkerklik</kbd> + slepen</td></tr>
<tr><th>Zoomen</th><td><kbd>Muiswiel</kbd> (scrollen)</td></tr>
<tr><th>Draaien / Kantelen</th><td><kbd>Rechterklik</kbd> + slepen</td></tr>
</table>
</p>
<p>
<h2>Toetsenbordbediening:</h2>
<table>
<tr><th>Bewegen</th><td><kbd>wasd</kbd> / <kbd>Pijltjestoetsen</kbd></td></tr>
<tr><th>Zoomen</th><td>Numeriek toetsenbord: <kbd>+</kbd>/<kbd>-</kbd> of <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>Draaien / Kantelen</th><td><kbd>Alt</kbd> + <kbd>wasd</kbd> / <kbd>Pijltjestoetsen</kbd> of <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Aanraakbediening:</h2>
<table>
<tr><th>Bewegen</th><td>Aanraken + vegen</td></tr>
<tr><th>Zoomen</th><td>Met twee vingers aanraken + knijpen</td></tr>
<tr><th>Draaien / Kantelen</th><td>Met twee vingers aanraken + draaien / naar boven/onder slepen</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Deze kaart is met &#9829; door <a href="https://bluecolo.red/bluemap">BlueMap</a> {version} gegenereerd
</p>
`
}
};

View File

@ -0,0 +1,153 @@
export default {
pageTitle: "BlueMap - {Kart}",
menu: {
title: "Meny",
tooltip: "Meny"
},
maps: {
title: "Kart",
button: "Kart",
tooltip: "Kartliste"
},
markers: {
title: "Markører",
button: "Markører",
tooltip: "Markørliste",
marker: "markør | markører",
markerSet: "markørsett | markørsett",
searchPlaceholder: "Søk...",
followPlayerTitle: "Følg spiller"
},
settings: {
title: "Innstillinger",
button: "Innstillinger"
},
goFullscreen: {
button: "Fullskjerm"
},
resetCamera: {
button: "Tilbakestill kamera",
tooltip: "Tilbakestill kamera og posisjon"
},
updateMap: {
button: "Oppdater kart",
tooltip: "Slett rutebuffer"
},
lighting: {
title: "Belysning",
dayNightSwitch: {
tooltip: "Dag/natt"
},
sunlight: "Sollys",
ambientLight: "Bakgrunnsbelysning"
},
resolution: {
title: "Oppløsning",
high: "Høy (SSAA, x2)",
normal: "Normal (Opprinnelig oppløsning, x1)",
low: "Lav (Oppskalert, x0.5)"
},
freeFlightControls: {
title: "Friflyvningskontroller",
mouseSensitivity: "Mussensitivitet",
invertMouseY: "Snu mus Y"
},
renderDistance: {
title: "Innlastningsavstand",
hiresLayer: "Høyoppløsningslag",
lowersLayer: "Lavoppløsningslag",
loadHiresWhileMoving: "Last inn høyoppløsning under bevegelse",
off: "Av"
},
theme: {
title: "Tema",
default: "Standard (System/Nettleser)",
dark: "Mørk",
light: "Lys"
},
debug: {
button: "Feilsøk"
},
resetAllSettings: {
button: "Tilbakestill alle innstillinger"
},
players: {
title: "Spillere",
tooltip: "Spillerliste"
},
compass: {
tooltip: "Kompass / Pek nord"
},
screenshot: {
title: "Skjermbilde",
button: "Ta skjermbilde",
clipboard: "Kopier til utklippstavle"
},
controls: {
title: "Visning / Kontroller",
perspective: {
button: "Perspektiv",
tooltip: "Perpektivvisning"
},
flatView: {
button: "Flat",
tooltip: "Ortografisk / Flatvisning",
},
freeFlight: {
button: "Friflyvning",
tooltip: "Friflyvning / Tilskuermodus"
}
},
language: {
title: "Språk",
},
blockTooltip: {
block: "Blokk",
position: "Posisjon",
chunk: "Bit",
region: {
region: "Region",
file: "Fil"
},
light: {
light: "Lys",
sun: "Sol",
block: "Blokk",
}
},
info: {
title: "Informasjon",
button: "Informasjon",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Mouse-Controls:</h2>
<table>
<tr><th>move</th><td><kbd>left-click</kbd> + drag</td></tr>
<tr><th>zoom</th><td><kbd>mousewheel</kbd> (scroll)</td></tr>
<tr><th>rotate / tilt</th><td><kbd>right-click</kbd> + drag</td></tr>
</table>
</p>
<p>
<h2>Keyboard-Controls:</h2>
<table>
<tr><th>move</th><td><kbd>wasd</kbd> / <kbd>arrow-keys</kbd></td></tr>
<tr><th>zoom</th><td>Numpad: <kbd>+</kbd>/<kbd>-</kbd> or <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>rotate / tilt</th><td><kbd>Left-Alt</kbd> + <kbd>wasd</kbd> / <kbd>arrow-keys</kbd> or <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Touch-Controls:</h2>
<table>
<tr><th>move</th><td>touch + drag</td></tr>
<tr><th>zoom</th><td>touch with two fingers + pinch</td></tr>
<tr><th>rotate / tilt</th><td>touch with two fingers + rotate / move up/down</td></tr>
</table>
</p>
<br><hr>
<p>
This map has been generated with &#9829; using <a href="https://bluecolo.red/bluemap">BlueMap</a>.
</p>
`
}
}

View File

@ -0,0 +1,177 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menu",
tooltip: "Menu"
},
maps: {
title: "Mapy",
button: "Mapy",
tooltip: "Lista map"
},
markers: {
title: "Znaczniki",
button: "Znaczniki",
tooltip: "Lista znaczników",
marker: "znacznik | znaczniki",
markerSet: "zbiór znaczników | zbiory znaczników",
searchPlaceholder: "Wyszukaj...",
followPlayerTitle: "Śledzenie gracza"
},
settings: {
title: "Ustawienia",
button: "Ustawienia"
},
goFullscreen: {
button: "Tryb pełnoekranowy"
},
resetCamera: {
button: "Wyśrodkuj kamerę",
tooltip: "Zresetuj pozycję kamery"
},
updateMap: {
button: "Załaduj mapę ponownie",
tooltip: "Wyczyść pamięć podręczną mapy"
},
lighting: {
title: "Oświetlenie",
dayNightSwitch: {
tooltip: "Dzień/Noc"
},
sunlight: "Światło słoneczne",
ambientLight: "Światło otoczenia"
},
resolution: {
title: "Rozdzielczość",
high: "Wysoka (SSAA, x2)",
normal: "Normalna (Natywna, x1)",
low: "Niska (Skalowanie, x0.5)"
},
freeFlightControls: {
title: "Sterowanie w locie swobodnym",
mouseSensitivity: "Czułość myszy",
invertMouseY: "Odwróć oś pionową myszy"
},
renderDistance: {
title: "Odległość renderowania",
hiresLayer: "Warstwa wysokiej rozdzielczości",
lowersLayer: "Warstwa niskiej rozdzielczości"
},
theme: {
title: "Motyw",
default: "Domyślny (według ustawień systemowych)",
dark: "Tryb ciemny",
light: "Tryb jasny",
contrast: "Wysoki kontrast"
},
debug: {
button: "Debugowanie"
},
resetAllSettings: {
button: "Przywróć ustawienia domyślne"
},
players: {
title: "Gracze",
tooltip: "Lista graczy"
},
compass: {
tooltip: "Kompas / zwroć na północ"
},
screenshot: {
title: "Zrzut ekranu",
button: "Wykonaj zrzut ekranu",
clipboard: "Skopiuj do schowka"
},
controls: {
title: "Widok",
perspective: {
button: "Perspektywa",
tooltip: "Widok z perspektywy"
},
flatView: {
button: "Płaski",
tooltip: "Widok płaski",
},
freeFlight: {
button: "Lot swobodny",
tooltip: "Tryb widza"
}
},
language: {
title: "Język",
},
blockTooltip: {
block: "Blok",
position: "Pozycja",
chunk: "Chunk",
region: {
region: "Region",
file: "Plik"
},
light: {
light: "Oświetlenie",
sun: "Słońce",
block: "Blok",
}
},
info: {
title: "Informacje",
button: "Informacje i skróty klawiszowe",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Sterowanie myszką</h2>
<table>
<tr><th>Poruszanie się</th><td><kbd>lewy przycisk</kbd> + przeciągnięcie</td></tr>
<tr><th>Zbliżenie i oddalenie</th><td><kbd>kółko myszy</kbd> (przewijanie)</td></tr>
<tr><th>Obrót i pochylenie</th><td><kbd>prawy przycisk</kbd> + przeciągnięcie</td></tr>
</table>
</p>
<br />
<p>
<h2>Sterowanie klawiaturą</h2>
<table>
<tr>
<th>Poruszanie się</th>
<td>
<kbd>Klawisze WASD</kbd>
<br />
albo <kbd>Strzałki</kbd>
</td>
</tr>
<tr>
<th>Zbliżenie i oddalenie</th>
<td>
Klawiatura numeryczna: <kbd>+</kbd> / <kbd>-</kbd>
<br />
lub <kbd>Insert (Ins)</kbd> / <kbd>Home</kbd>
</td>
</tr>
<tr>
<th>Obrót i pochylenie</th>
<td>
<kbd>Lewy ALT</kbd> + <kbd>WASD</kbd>,
<br />
<kbd>Lewy ALT</kbd> + <kbd>Strzałki</kbd>,
<br /><br />
Alternatywnie: <kbd>Delete</kbd> / <kbd>End</kbd> / <kbd>Page Up</kbd> / <kbd>Page Down</kbd>
</td>
</tr>
</table>
</p>
<br />
<p>
<h2>Sterowanie dotykowe (telefon)</h2>
<table>
<tr><th>Poruszanie się</th><td>Przeciąganie jednym palcem po ekranie</td></tr>
<tr><th>Zbliżenie i oddalenie</th><td>Uszczypnięcie dwoma palcami</td></tr>
<tr><th>Obrót</th><td>Przeciąganie palca po ekranie, jednocześnie trzymając mapę drugim palcem</td></tr>
<tr><th>Pochylenie</th><td>Przeciąganie dwoma palcami po ekranie w pionie</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Ta mapa została wygenerowana z &#9829; za pomocą <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}</p>
`
}
}

View File

@ -0,0 +1,145 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menu",
tooltip: "Menu"
},
maps: {
title: "Mapas",
button: "Mapas",
tooltip: "Lista de mapas"
},
markers: {
title: "Marcadores",
button: "Marcadores",
tooltip: "Lista de marcadores",
marker: "marcador | marcadores",
markerSet: "colocar marcador | colocar marcadores",
searchPlaceholder: "Procurar..."
},
settings: {
title: "Definições",
button: "Definições"
},
goFullscreen: {
button: "Tela Cheia"
},
resetCamera: {
button: "Redefinir Câmara",
tooltip: "Redefinir Câmara e Posição"
},
updateMap: {
button: "Atualizar mapa",
tooltip: "Limpar cache de tiles"
},
lighting: {
title: "Luminosidade",
dayNightSwitch: {
tooltip: "Dia/Noite"
},
sunlight: "Luz do dia",
ambientLight: "Luz ambiental"
},
resolution: {
title: "Resolução",
high: "Alta (SSAA, x2)",
normal: "Normal (Nativo, x1)",
low: "Baixa (Upscaling, x0.5)"
},
freeFlightControls: {
title: "Controlos de voo-livre",
mouseSensitivity: "Sensibilidade do rato",
invertMouseY: "Inverter rato Y"
},
renderDistance: {
title: "Distância de renderização",
hiresLayer: "Camada de alta resolução",
lowersLayer: "Camada de baixa resolução"
},
theme: {
title: "Tema",
default: "Padrão (Sistema/Browser)",
dark: "Escuro",
light: "Claro"
},
debug: {
button: "Debug"
},
resetAllSettings: {
button: "Redefinir todas as configurações"
},
players: {
title: "Jogadores",
tooltip: "Lista de jogadores"
},
compass: {
tooltip: "Compasso / Apontar para norte"
},
controls: {
title: "Visão / Controlos",
perspective: {
button: "Perspetiva",
tooltip: "Visão de perspetiva"
},
flatView: {
button: "Plano",
tooltip: "Visão plana",
},
freeFlight: {
button: "Voo-livre",
tooltip: "Voo-livre / Modo espectador"
}
},
language: {
title: "Língua",
},
blockTooltip: {
block: "Bloco",
position: "Posição",
chunk: "Chunk",
region: {
region: "Região",
file: "Ficheiro"
},
light: {
light: "Luz",
sun: "Sol",
block: "Bloco",
}
},
info: {
title: "Informação",
button: "Informação",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Controlos do rato:</h2>
<table>
<tr><th>mover</th><td><kbd>click-esquerdo</kbd> + arrastar</td></tr>
<tr><th>zoom</th><td><kbd>botão do meio</kbd> (scroll)</td></tr>
<tr><th>rodar / inclinar</th><td><kbd>click-direito</kbd> + arrastar</td></tr>
</table>
</p>
<p>
<h2>Controlos do teclado:</h2>
<table>
<tr><th>mover</th><td><kbd>wasd</kbd> / <kbd>setas</kbd></td></tr>
<tr><th>zoom</th><td>Numpad: <kbd>+</kbd>/<kbd>-</kbd> ou <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>rodar / inclinar</th><td><kbd>Alt-esquerdo</kbd> + <kbd>wasd</kbd> / <kbd>setas</kbd> ou <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Controlos táteis:</h2>
<table>
<tr><th>mover</th><td>tocar + arrastar</td></tr>
<tr><th>zoom</th><td>tocar com 2 dedos + afastar / aproximar os dedos</td></tr>
<tr><th>rodar / inclinar</th><td>tocar com 2 dedos + rodar / mover para cima / baixo</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Este mapa foi gerado com &#9829; usando o <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
}

View File

@ -0,0 +1,154 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Меню",
tooltip: "Меню"
},
maps: {
title: "Карта",
button: "Карта",
tooltip: "Список карт"
},
markers: {
title: "Маркеры",
button: "Маркеры",
tooltip: "Список маркеров",
marker: "маркер | маркеры",
markerSet: "набор маркеров | наборы маркеров",
searchPlaceholder: "Поиск...",
followPlayerTitle: "Следовать за игроком"
},
settings: {
title: "Настройки",
button: "Настройки"
},
goFullscreen: {
button: "Полноэкранный режим"
},
resetCamera: {
button: "Сброс настроек камеры",
tooltip: "Сбросить настройки и положение камеры"
},
updateMap: {
button: "Обновить карту",
tooltip: "Очистить кэш карты"
},
lighting: {
title: "Освещение",
dayNightSwitch: {
tooltip: "День/Ночь"
},
sunlight: "Солнечный свет",
ambientLight: "Свет от блоков"
},
resolution: {
title: "Разрешение",
high: "Высокое (SSAA, x2)",
normal: "Нормальное (Нативное, x1)",
low: "Низкое (Апскейл, x0.5)"
},
freeFlightControls: {
title: "Управление свободным полётом",
mouseSensitivity: "Чувствительность мыши",
invertMouseY: "Инвертировать мышь по Y"
},
renderDistance: {
title: "Дальность прорисовки",
hiresLayer: "Высокой чёткости",
lowersLayer: "Низкой чёткости",
loadHiresWhileMoving: "Выс. чёткость при движении",
off: "Откл"
},
theme: {
title: "Тема",
default: "По умолчанию (Системная/Браузера)",
dark: "Тёмная",
light: "Светлая",
contrast: "Контрастная"
},
debug: {
button: "Отладка"
},
resetAllSettings: {
button: "Сбросить все настройки"
},
players: {
title: "Игроки",
tooltip: "Список игроков"
},
compass: {
tooltip: "Компас / Указать на север"
},
screenshot: {
title: "Скриншот",
button: "Сделать Скриншот",
clipboard: "Скопировать в буфер обмена"
},
controls: {
title: "Вид / Управление",
perspective: {
button: "Перспективная проекция",
tooltip: "3D / Перспективная проекция"
},
flatView: {
button: "Ортографическая проекция",
tooltip: "Плоская / Ортографическая проекция",
},
freeFlight: {
button: "Свободный полёт",
tooltip: "Свободный полёт / Режим наблюдателя"
}
},
language: {
title: "Язык",
},
blockTooltip: {
block: "Блок",
position: "Координаты",
chunk: "Чанк",
region: {
region: "Регион",
file: "Файл"
},
light: {
light: "Освещение",
sun: "Неба",
block: "Блоками",
}
},
info: {
title: "Информация",
button: "Информация",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Управление мышью:</h2>
<table>
<tr><th>перемещение</th><td>зажать <kbd>ЛКМ</kbd></td></tr>
<tr><th>приближение</th><td>прокрутить <kbd>колесо</kbd></td></tr>
<tr><th>поворот / наклон</th><td>зажать <kbd>ПКМ</kbd></td></tr>
</table>
</p>
<p>
<h2>Управление клавиатурой:</h2>
<table>
<tr><th>перемещение</th><td><kbd>WASD</kbd> / <kbd>стрелки</kbd></td></tr>
<tr><th>приближение</th><td>Нампад: <kbd>+</kbd>/<kbd>-</kbd> или <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>поворот / наклон</th><td><kbd>Левый Alt</kbd> + <kbd>WASD</kbd> / <kbd>стрелки</kbd> или <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Управление сенсором:</h2>
<table>
<tr><th>перемещение</th><td>коснуться и переместить</td></tr>
<tr><th>приближение</th><td>коснуться двумя пальцами и ущипнуть</td></tr>
<tr><th>поворот / наклон</th><td>коснуться двумя пальцами и повернуть / переместить вверх/вниз</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Эта карта сгенерирована с &#9829; <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
}

View File

@ -0,0 +1,94 @@
export default {
default: "en",
languages: [
// remove the languages you don't need, reorder them, or add your own
{
locale: "cs",
name: "Czech"
},
{
locale: "de",
name: "Deutsch"
},
{
locale: "en",
name: "English"
},
{
locale: "fr",
name: "French"
},
{
locale: "hi",
name: "हिन्दी"
},
{
locale: "it",
name: "Italiano"
},
{
locale: "lv",
name: "Latviešu"
},
{
locale: "hu",
name: "Magyar"
},
{
locale: "nl",
name: "Nederlands"
},
{
locale: "no_nb",
name: "Norsk bokmål"
},
{
locale: "pl",
name: "Polski"
},
{
locale: "pt_PT",
name: "Português (Portugal)"
},
{
locale: "ru",
name: "Русский"
},
{
locale: "fi",
name: "Suomi"
},
{
locale: "es",
name: "Spanish"
},
{
locale: "sv",
name: "Svenska"
},
{
locale: "ua",
name: "Українська"
},
{
locale: "ja",
name: "日本語"
},
{
locale: "zh_CN",
name: "简体中文"
},
{
locale: "zh_TW",
name: "中文(台灣)"
},
{
locale: "zh_HK",
name: "中文(香港)"
},
{
locale: "ko",
name: "한국어"
}
]
}

View File

@ -0,0 +1,146 @@
export default {
pageTitle: "Bluemap - {map}",
menu: {
title: "Meny",
tooltip: "Meny"
},
maps: {
title: "Kartor",
button: "Kartor",
tooltip: "Kart lista"
},
markers: {
title: "Markörer",
button: "Markörer",
tooltip: "Markör lista",
marker: "Markör | Markörer",
markerSet: "Placera markör | Palcera markör",
searchPlaceholder: "Sök...",
followPlayerTitle: "Följ spelare"
},
settings: {
title: "Inställningar",
button: "Inställningar"
},
goFullscreen: {
button: "Sätt på helskärm"
},
resetCamera: {
button: "Återställ kamera",
tooltip: "Återställ kamera och position"
},
updateMap: {
button: "Uppdatera karta",
tooltip: "Rensa cacheminne"
},
lighting: {
title: "Ljus",
dayNightSwitch: {
tooltip: "Dag/Natt"
},
sunlight: "Solljus",
ambientLight: "Ljussättning"
},
resolution: {
title: "Upplösning",
high: "Hög (SSAA, x2)",
normal: "Normal (Ursprunglig, x1)",
low: "låg (Uppskalning, x0.5)"
},
freeFlightControls: {
title: "Kontroller för fritt flyg",
mouseSensitivity: "Muskänslighet",
invertMouseY: "Invertera mus Y"
},
renderDistance: {
title: "Renderings avstånd",
hiresLayer: "Hög upplösnings lager",
lowersLayer: "Låg upplösnings lager"
},
theme: {
title: "Teman",
default: "Standard (System/Webläsare)",
dark: "Mörkt",
light: "Ljust"
},
debug: {
button: "Felsökning"
},
resetAllSettings: {
button: "Återställ alla inställningar"
},
players: {
title: "Spelare",
tooltip: "Spelare lista"
},
compass: {
tooltip: "Kompass / Vänd mot norr"
},
controls: {
title: "Visa / kontroller",
perspective: {
button: "Perspective",
tooltip: "Perspektiv-vy"
},
flatView: {
button: "Platt",
tooltip: "Ortografisk / platt vy",
},
freeFlight: {
button: "Fritt flyg",
tooltip: "Fritt flyg / Åskådarläge"
}
},
language: {
title: "Språk",
},
blockTooltip: {
block: "Block",
position: "Placera",
chunk: "Chunk",
region: {
region: "Område",
file: "Fil"
},
light: {
light: "Ljus",
sun: "Sol",
block: "Block",
}
},
info: {
title: "Info",
button: "Info",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Muskontroller:</h2>
<table>
<tr><th>Styra</th><td><kbd>vänster klick</kbd> + dra</td></tr>
<tr><th>zoom</th><td><kbd>mushjul</kbd> (scroll)</td></tr>
<tr><th>rotera / luta</th><td><kbd>Höger klick</kbd> + dra</td></tr>
</table>
</p>
<p>
<h2>Tangentbordskontroller:</h2>
<table>
<tr><th>Styra</th><td><kbd>wasd</kbd> / <kbd>piltangenter</kbd></td></tr>
<tr><th>zoom</th><td><kbd>+</kbd>/<kbd>-</kbd> eller <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>rotera / luta</th><td><kbd>Vänster-Alt</kbd> + <kbd>wasd</kbd> / <kbd>piltangenter</kbd> eller <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Pekkontroller:</h2>
<table>
<tr><th>Styra</th><td>rör + dra</td></tr>
<tr><th>zoom</th><td>rör med två fingrar + nypa</td></tr>
<tr><th>rotera / luta</th><td>rör med två fingrar + rotera / flytta upp / ner</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Denna karta har blivit genererad med &#9829; med hjälp av <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
};

View File

@ -0,0 +1,155 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Меню",
tooltip: "Меню"
},
maps: {
title: "Карти",
button: "Карти",
tooltip: "Список карт"
},
markers: {
title: "Мітки",
button: "Мітки",
tooltip: "Список міток",
marker: "маркер | маркери",
markerSet: "набір маркерів | набори маркерів",
searchPlaceholder: "Пошук...",
followPlayerTitle: "Слідкувати за гравцем"
},
settings: {
title: "Налаштування",
button: "Налаштування"
},
goFullscreen: {
button: "Перейти в повноекранний режим"
},
resetCamera: {
button: "Скинути камеру",
tooltip: "Скинути камеру та позицію"
},
updateMap: {
button: "Оновити карту",
tooltip: "Очистити кеш тайлів"
},
lighting: {
title: "Освітлення",
dayNightSwitch: {
tooltip: "День/Ніч"
},
sunlight: "Сонячне світло",
ambientLight: "Навколишнє світло"
},
resolution: {
title: "Роздільна здатність",
high: "Висока (SSAA, x2)",
normal: "Нормальна (Системна, x1)",
low: "Низька (Апскейл, x0.5)"
},
freeFlightControls: {
title: "Налаштування вільного польоту",
mouseSensitivity: "Чутливість миші",
invertMouseY: "Вертикальне інвертування миші"
},
renderDistance: {
title: "Відстань промальовки",
hiresLayer: "Високодеталізований шар",
lowersLayer: "Низькодеталізований шар",
loadHiresWhileMoving: "Вис. шар під час руху",
off: "Вимк"
},
theme: {
title: "Тема",
default: "За замовчуванням (Браузерна)",
dark: "Темна",
light: "Світла",
contrast: "Контрастна"
},
debug: {
button: "Відлагоджувальний режим"
},
resetAllSettings: {
button: "Скинути всі налаштування"
},
players: {
title: "Гравці",
tooltip: "Список гравців"
},
compass: {
tooltip: "Компас / Повернути на північ"
},
screenshot: {
title: "Скріншот",
button: "Зробити Скріншот",
clipboard: "Скопіювати в буфер обміну"
},
controls: {
title: "Налаштування відображення",
perspective: {
button: "Перспектива",
tooltip: "Перспективна проекція"
},
flatView: {
button: "Пласка карта",
tooltip: "Ортографічна / Пласка проекція",
},
freeFlight: {
button: "Вільний політ",
tooltip: "Вільний політ / \"Spectator mode\""
}
},
language: {
title: "Мова",
},
blockTooltip: {
block: "Блок",
position: "Позиція",
chunk: "Чанк",
region: {
region: "Регіон",
file: "Файл"
},
light: {
light: "Освітлення",
sun: "Сонце",
block: "Блок",
}
},
info: {
title: "Інформація",
button: "Інформація",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Керування-мишею:</h2>
<table>
<tr><th>рух</th><td><kbd>лівий-клік</kbd> + пересування</td></tr>
<tr><th>приближення</th><td><kbd>колесико-миші</kbd> (прокрутити)</td></tr>
<tr><th>повернути / повернути</th><td><kbd>правий-клік</kbd> + пересування</td></tr>
</table>
</p>
<p>
<h2>Керування-клавіатурою:</h2>
<table>
<tr><th>рух</th><td><kbd>wasd</kbd> / <kbd>стрілки-клавіатури</kbd></td></tr>
<tr><th>приблизити</th><td>Цифроблок: <kbd>+</kbd>/<kbd>-</kbd> або <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>повернути / нахилити</th><td><kbd>Лівий-Alt</kbd> + <kbd>wasd</kbd> / <kbd>стрілки-клавіатури</kbd> або <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Сенсорна-панель:</h2>
<table>
<tr><th>рух</th><td>дотик + перетягування</td></tr>
<tr><th>приблизити</th><td>дотик двома пальцями + зсув доверху</td></tr>
<tr><th>поворот / нахил</th><td>дотик двома пальцями + поворот / зсув доверху / донизу</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
Цю карту було згенеровано з &#9829; використовуючи <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
}
//Переклав Y0shioSato, оновив KaRiLaA

View File

@ -0,0 +1,145 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "菜单",
tooltip: "打开菜单"
},
maps: {
title: "地图",
button: "地图",
tooltip: "地图列表"
},
markers: {
title: "标记",
button: "标记",
tooltip: "标记列表",
marker: "标记 | 标记列表",
markerSet: "标记集 | 标记集",
searchPlaceholder: "搜寻中..."
},
settings: {
title: "设置",
button: "打开设置"
},
goFullscreen: {
button: "全屏"
},
resetCamera: {
button: "重置镜头",
tooltip: "重置镜头 & 位置"
},
updateMap: {
button: "更新地图",
tooltip: "清除方块缓存"
},
lighting: {
title: "光照",
dayNightSwitch: {
tooltip: "昼/夜"
},
sunlight: "日光",
ambientLight: "环境光"
},
resolution: {
title: "抗锯齿",
high: "高 (SSAA, x2)",
normal: "普通 (默认, x1)",
low: "低 (粗糙, x0.5)"
},
freeFlightControls: {
title: "自由飞行控制",
mouseSensitivity: "鼠标灵敏度",
invertMouseY: "反转鼠标 Y"
},
renderDistance: {
title: "渲染距离",
hiresLayer: "高分辨率",
lowersLayer: "低分辨率"
},
theme: {
title: "主题",
default: "默认 (系统/浏览器)",
dark: "暗夜主题",
light: "白亮主题"
},
debug: {
button: "调试"
},
resetAllSettings: {
button: "重置所有设置"
},
players: {
title: "玩家",
tooltip: "玩家列表"
},
compass: {
tooltip: "罗盘 / 朝北"
},
controls: {
title: "视野 / 控制",
perspective: {
button: "透视",
tooltip: "透视视野"
},
flatView: {
button: "平视",
tooltip: "正交视图 / 平坦视图",
},
freeFlight: {
button: "自由视野",
tooltip: "自由视野 / 观察者模式"
}
},
language: {
title: "语言",
},
blockTooltip: {
block: "方块",
position: "坐标",
chunk: "区块",
region: {
region: "区域",
file: "文件"
},
light: {
light: "光源",
sun: "太阳",
block: "方块",
}
},
info: {
title: "信息",
button: "信息",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>鼠标控制:</h2>
<table>
<tr><th>移动</th><td><kbd></kbd> + </td></tr>
<tr><th>缩放</th><td><kbd></kbd> ()</td></tr>
<tr><th>旋转 / 倾斜</th><td><kbd></kbd> + </td></tr>
</table>
</p>
<p>
<h2>键盘控制:</h2>
<table>
<tr><th>移动</th><td><kbd>wasd</kbd> / <kbd></kbd></td></tr>
<tr><th>缩放</th><td>: <kbd>+</kbd>/<kbd>-</kbd> <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>旋转 / 倾斜</th><td><kbd>-Alt</kbd> + <kbd>wasd</kbd> / <kbd></kbd> <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>触屏控制:</h2>
<table>
<tr><th>移动</th><td> + </td></tr>
<tr><th>缩放</th><td> + </td></tr>
<tr><th>旋转 / 倾斜</th><td>双指触屏 + 旋转 / 向上滑动 / 向下滑动</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
本地图由 &#9829 生成; 正在使用 <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
}

View File

@ -0,0 +1,144 @@
export default {
pageTitle: "Bluemap網絡地圖 - {map}世界",
menu: {
title: "菜單",
tooltip: "菜單"
},
maps: {
title: "地圖",
button: "地圖",
tooltip: "地圖列表"
},
markers: {
title: "標記",
button: "標記",
tooltip: "標記列表",
marker: "標記 | 標記",
markerSet: "標記設定 | 標記設定"
},
settings: {
title: "設定",
button: "設定"
},
goFullscreen: {
button: "開啟全螢幕模式"
},
resetCamera: {
button: "重設鏡頭視角",
tooltip: "重設鏡頭視角及位置"
},
updateMap: {
button: "重新讀取地圖",
tooltip: "移除地圖快取"
},
lighting: {
title: "光影",
dayNightSwitch: {
tooltip: "日/夜"
},
sunlight: "日光",
ambientLight: "環境亮度"
},
resolution: {
title: "解像度",
high: "高 (SSAA反鋸齒, x2)",
normal: "普通 (預設, x1)",
low: "低 (倍率, x0.5)"
},
freeFlightControls: {
title: "自由瀏覽飛行模式",
mouseSensitivity: "滑鼠靈敏度",
invertMouseY: "反轉Y軸"
},
renderDistance: {
title: "渲染距離",
hiresLayer: "高解像度層",
lowersLayer: "低解像度層"
},
theme: {
title: "顯示距離",
default: "預設 (系統/瀏覽器)",
dark: "黑暗",
light: "光亮"
},
debug: {
button: "除錯"
},
resetAllSettings: {
button: "重設所有設定"
},
players: {
title: "玩家",
tooltip: "玩家列表"
},
compass: {
tooltip: "指南針/朝北"
},
controls: {
title: "觀賞模式/控制",
perspective: {
button: "3D透視",
tooltip: "3D透視-觀賞模式"
},
flatView: {
button: "平面",
tooltip: "平面投射 / 平面-觀賞模式",
},
freeFlight: {
button: "自由瀏覽飛行模式",
tooltip: "自由瀏覽 / 觀察者模式"
}
},
language: {
title: "語言",
},
blockTooltip: {
block: "方塊",
position: "位置",
chunk: "區塊",
region: {
region: "區域",
file: "檔案"
},
light: {
light: "光亮度",
sun: "太陽",
block: "方塊",
}
},
info: {
title: "資訊",
button: "資訊",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>滑鼠控制:</h2>
<table>
<tr><th>移動</th><td><kbd></kbd> + </td></tr>
<tr><th>放大縮小</th><td><kbd></kbd> ()</td></tr>
<tr><th>旋轉 / 傾斜</th><td><kbd></kbd> + </td></tr>
</table>
</p>
<p>
<h2>鍵盤控制:</h2>
<table>
<tr><th>移動</th><td><kbd>wasd</kbd> / <kbd></kbd></td></tr>
<tr><th>放大縮小</th><td>: <kbd>+</kbd>/<kbd>-</kbd> <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>旋轉 / 傾斜</th><td><kbd> Alt</kbd> + <kbd>wasd</kbd> / <kbd>arrow-keys</kbd> <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>觸碰控制:</h2>
<table>
<tr><th>移動</th><td> + </td></tr>
<tr><th>放大縮小</th><td> </td></tr>
<tr><th>旋轉 / 傾斜</th><td> + </td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
此地圖是用 &#9829; 製作地圖插件名稱是 <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
}

View File

@ -0,0 +1,144 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "選單",
tooltip: "選單"
},
maps: {
title: "地圖",
button: "地圖",
tooltip: "地圖列表"
},
markers: {
title: "圖釘",
button: "圖釘",
tooltip: "圖釘列表",
marker: "圖釘 | 圖釘",
markerSet: "圖釘設定 | 圖釘設定"
},
settings: {
title: "設定",
button: "設定"
},
goFullscreen: {
button: "全螢幕模式"
},
resetCamera: {
button: "重置視角",
tooltip: "重置視角 & 位置"
},
updateMap: {
button: "更新地圖",
tooltip: "清除暫存"
},
lighting: {
title: "亮度",
dayNightSwitch: {
tooltip: "白天/夜晚"
},
sunlight: "時間",
ambientLight: "環境光"
},
resolution: {
title: "解析度",
high: "高 (最高畫質,SSAA, x2)",
normal: "預設 (畫質優先,Native, x1)",
low: "低 (效能優先,Upscaling, x0.5)"
},
freeFlightControls: {
title: "滑鼠設定",
mouseSensitivity: "滑鼠靈敏度",
invertMouseY: "反轉Y軸"
},
renderDistance: {
title: "顯示範圍",
hiresLayer: "高畫質的距離",
lowersLayer: "低畫質的距離"
},
theme: {
title: "主題",
default: "預設 (系統/瀏覽器)",
dark: "黑暗",
light: "明亮"
},
debug: {
button: "除錯"
},
resetAllSettings: {
button: "重設所有設定"
},
players: {
title: "玩家",
tooltip: "玩家列表"
},
compass: {
tooltip: "指北針"
},
controls: {
title: "顯示/控制",
perspective: {
button: "立體",
tooltip: "立體顯示"
},
flatView: {
button: "平面",
tooltip: "正射/平面顯示",
},
freeFlight: {
button: "觀察者",
tooltip: "觀察者模式"
}
},
language: {
title: "語言",
},
blockTooltip: {
block: "方塊",
position: "座標",
chunk: "區塊",
region: {
region: "區域",
file: "檔案"
},
light: {
light: "亮度",
sun: "日光",
block: "光源",
}
},
info: {
title: "資訊",
button: "資訊",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>滑鼠控制:</h2>
<table>
<tr><th>移動:</th><td><kbd></kbd></td></tr>
<tr><th>縮放:</th><td><kbd></kbd> ()</td></tr>
<tr><th>旋轉/傾斜:</th><td><kbd></kbd></td></tr>
</table>
</p>
<p>
<h2>鍵盤控制:</h2>
<table>
<tr><th>移動:</th><td><kbd></kbd> / <kbd></kbd></td></tr>
<tr><th>縮放:</th><td>Numpad: <kbd>+</kbd>/<kbd>-</kbd> or <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>旋轉/傾斜:</th><td><kbd>Alt</kbd> + <kbd></kbd> / <kbd></kbd> <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>觸控:</h2>
<table>
<tr><th>移動:</th><td></td></tr>
<tr><th>縮放:</th><td></td></tr>
<tr><th>旋轉/傾斜:</th><td></td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
This map has been generated with &#9829; using <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
}

View File

@ -0,0 +1,52 @@
<template>
<div id="app" :class="{'theme-light': appState.theme === 'light', 'theme-dark': appState.theme === 'dark', 'theme-contrast': appState.theme === 'contrast'}">
<FreeFlightMobileControls v-if="appState.controls.state === 'free'" />
<ControlBar />
<MainMenu :menu="appState.menu" />
</div>
</template>
<script>
import ControlBar from "@/components/ControlBar/ControlBar";
import MainMenu from "@/components/Menu/MainMenu";
import FreeFlightMobileControls from "@/components/Controls/FreeFlightMobileControls";
export default {
name: 'App',
components: {
FreeFlightMobileControls,
MainMenu,
ControlBar
},
data() {
return {
appState: this.$bluemap.appState,
}
}
}
</script>
<style lang="scss">
@import "~@/scss/global.scss";
#map-container {
position: absolute;
width: 100%;
height: 100%;
}
#app {
position: absolute;
width: 100%;
height: 100%;
z-index: 100; // put over bluemap markers
pointer-events: none;
font-size: 1rem;
@media (max-width: $mobile-break) {
font-size: 1.5rem;
}
}
</style>

View File

@ -0,0 +1,72 @@
<template>
<SvgButton class="compass" @action="action">
<svg viewBox="0 0 30 30" :style="style">
<path class="north" d="M14.792,1.04c0.114-0.354,0.299-0.354,0.412,0l4.089,12.729c0.114,0.353-0.097,0.642-0.468,0.642
l-7.651,0.001c-0.371,0-0.581-0.288-0.468-0.642L14.792,1.04z"/>
<path class="south" d="M10.707,16.23c-0.114-0.353,0.097-0.642,0.468-0.642l7.651-0.001c0.371,0,0.581,0.289,0.468,0.642
l-4.086,12.73c-0.113,0.353-0.299,0.353-0.412,0L10.707,16.23z"/>
</svg>
</SvgButton>
</template>
<script>
import {animate, EasingFunctions} from "bluemap/src/util/Utils";
import SvgButton from "@/components/ControlBar/SvgButton";
let animation;
export default {
name: "Compass",
components: {SvgButton},
data() {
return {
controls: this.$bluemap.mapViewer.controlsManager.data
}
},
computed: {
style() {
return {transform: "translate(-50%, -50%) rotate(" + (-this.controls.rotation) + "rad)"}
}
},
methods: {
action(evt) {
evt.preventDefault();
if (animation) animation.cancel();
let startRotation = this.controls.rotation;
animation = animate(t => {
this.controls.rotation = startRotation * (1-EasingFunctions.easeOutQuad(t));
}, 300);
}
}
}
</script>
<style lang="scss">
.compass {
svg {
height: 1.8em;
.north {
fill: var(--theme-fg);
}
.south {
fill: var(--theme-fg-light);
}
}
&:active {
svg {
.north {
fill: var(--theme-bg);
}
.south {
fill: var(--theme-bg-light);
}
}
}
}
</style>

View File

@ -0,0 +1,169 @@
<template>
<div class="control-bar">
<MenuButton :close="appState.menu.isOpen" :back="false" @action="appState.menu.reOpenPage()" :title="$t('menu.tooltip')" />
<div class="space thin-hide"></div>
<SvgButton v-if="appState.maps.length > 0" class="thin-hide" :title="$t('maps.tooltip')"
@action="appState.menu.openPage('maps', $t('maps.title'))">
<svg viewBox="0 0 30 30">
<polygon points="26.708,22.841 19.049,25.186 11.311,20.718 3.292,22.841 7.725,5.96 13.475,4.814 19.314,7.409 25.018,6.037 "/>
</svg>
</SvgButton>
<SvgButton v-if="markers.markerSets.length > 0 || markers.markers.length > 0" class="thin-hide" :title="$t('markers.tooltip')"
@action="appState.menu.openPage('markers', $t('markers.title'), {markerSet: markers})">
<svg viewBox="0 0 30 30">
<path d="M15,3.563c-4.459,0-8.073,3.615-8.073,8.073c0,6.483,8.196,14.802,8.196,14.802s7.951-8.013,7.951-14.802
C23.073,7.177,19.459,3.563,15,3.563z M15,15.734c-2.263,0-4.098-1.835-4.098-4.099c0-2.263,1.835-4.098,4.098-4.098
c2.263,0,4.098,1.835,4.098,4.098C19.098,13.899,17.263,15.734,15,15.734z"/>
</svg>
</SvgButton>
<SvgButton v-if="!playerMarkerSet.fake" class="thin-hide" :title="$t('players.tooltip')" @action="openPlayerList">
<svg viewBox="0 0 30 30">
<g>
<path d="M8.95,14.477c0.409-0.77,1.298-1.307,2.164-1.309h0.026c-0.053-0.234-0.087-0.488-0.087-0.755
c0-1.381,0.715-2.595,1.791-3.301c-0.01,0-0.021-0.006-0.03-0.006h-1.427c-0.39,0-0.514-0.251-0.276-0.563
c0,0,0.497-0.645,0.497-1.452c0-1.48-1.2-2.681-2.679-2.681c-1.481,0-2.679,1.2-2.679,2.681c0,0.807,0.496,1.452,0.496,1.452
c0.24,0.311,0.114,0.565-0.275,0.565L5.042,9.118C4.649,9.119,4.182,9.405,3.998,9.75l-2.601,4.927
c-0.184,0.347-0.062,0.802,0.265,1.015l1.297,0.83c0.332,0.213,0.794,0.135,1.034-0.18l0.598-0.775
c0.238-0.31,0.471-0.245,0.516,0.141l0.454,3.854c0.035,0.311,0.272,0.566,0.564,0.66c0.018-0.279,0.087-0.561,0.225-0.82
L8.95,14.477z"/>
<path d="M28.604,14.677l-2.597-4.94c-0.185-0.346-0.65-0.631-1.042-0.631h-1.428c-0.39,0-0.514-0.251-0.274-0.563
c0,0,0.496-0.645,0.496-1.452c0-1.48-1.2-2.681-2.68-2.681c-1.481,0-2.679,1.2-2.679,2.681c0,0.807,0.496,1.452,0.496,1.452
c0.239,0.311,0.114,0.565-0.275,0.565l-1.428,0.009c-0.005,0-0.009,0.002-0.015,0.002c1.067,0.708,1.774,1.917,1.774,3.292
c0,0.263-0.031,0.513-0.084,0.744h0.02c0.868,0,1.758,0.537,2.166,1.305l2.598,4.944c0.137,0.262,0.205,0.539,0.222,0.818
c0.296-0.092,0.538-0.35,0.574-0.664l0.451-3.842c0.044-0.389,0.28-0.452,0.519-0.143l0.588,0.768
c0.239,0.313,0.702,0.391,1.033,0.182l1.297-0.833C28.667,15.479,28.787,15.026,28.604,14.677z"/>
</g>
<path d="M19.932,15.058c-0.184-0.346-0.651-0.63-1.043-0.63h-1.427c-0.39,0-0.515-0.252-0.275-0.564c0,0,0.496-0.645,0.496-1.451
c0-1.479-1.199-2.68-2.679-2.68c-1.482,0-2.679,1.201-2.679,2.68c0,0.806,0.496,1.451,0.496,1.451
c0.24,0.312,0.114,0.566-0.275,0.566l-1.427,0.009c-0.393,0.001-0.861,0.287-1.045,0.632l-2.602,4.925
c-0.185,0.348-0.062,0.803,0.266,1.016l1.297,0.832c0.332,0.213,0.794,0.133,1.034-0.18l0.598-0.775
c0.239-0.311,0.472-0.246,0.517,0.141l0.454,3.854c0.043,0.389,0.403,0.705,0.794,0.705h5.148c0.392,0,0.749-0.316,0.794-0.705
l0.45-3.844c0.045-0.389,0.282-0.451,0.52-0.143l0.587,0.768c0.239,0.313,0.703,0.393,1.033,0.182l1.297-0.832
c0.331-0.213,0.451-0.666,0.269-1.016L19.932,15.058z"/>
</svg>
</SvgButton>
<div class="space thin-hide greedy"></div>
<DayNightSwitch class="thin-hide" :title="$t('lighting.dayNightSwitch.tooltip')" />
<div class="space thin-hide"></div>
<ControlsSwitch class="thin-hide"></ControlsSwitch>
<div class="space thin-hide"></div>
<SvgButton class="thin-hide" :title="$t('resetCamera.tooltip')" @action="$bluemap.resetCamera()">
<svg viewBox="0 0 30 30">
<rect x="7.085" y="4.341" transform="matrix(0.9774 0.2116 -0.2116 0.9774 3.2046 -1.394)" width="2.063" height="19.875"/>
<path d="M12.528,5.088c0,0,3.416-0.382,4.479-0.031c1.005,0.332,2.375,2.219,3.382,2.545c1.096,0.354,4.607-0.089,4.607-0.089
l-2.738,8.488c0,0-3.285,0.641-4.344,0.381c-1.049-0.257-2.607-2.015-3.642-2.324c-0.881-0.264-3.678-0.052-3.678-0.052
L12.528,5.088z"/>
</svg>
</SvgButton>
<PositionInput class="pos-input" />
<Compass :title="$t('compass.tooltip')" />
</div>
</template>
<script>
import PositionInput from "@/components/ControlBar/PositionInput";
import Compass from "@/components/ControlBar/Compass";
import DayNightSwitch from "@/components/ControlBar/DayNightSwitch";
import ControlsSwitch from "@/components/ControlBar/ControlsSwitch";
import MenuButton from "@/components/ControlBar/MenuButton";
import SvgButton from "@/components/ControlBar/SvgButton";
export default {
name: "ControlBar",
components: {
SvgButton,
MenuButton,
ControlsSwitch,
DayNightSwitch,
PositionInput,
Compass
},
data() {
return {
appState: this.$bluemap.appState,
markers: this.$bluemap.mapViewer.markers.data,
}
},
computed: {
playerMarkerSet() {
for (let set of this.markers.markerSets) {
if (set.id === "bm-players") return set;
}
return {
id: "bm-players",
label: "Players",
markerSets: [],
markers: [],
fake: true,
}
}
},
methods: {
openPlayerList() {
let playerList = this.playerMarkerSet;
this.appState.menu.openPage('markers', this.$t("players.title"), {markerSet: playerList});
}
}
}
</script>
<style lang="scss">
@import "~@/scss/variables.scss";
.control-bar {
position: fixed;
top: 0;
left: 0;
display: flex;
filter: drop-shadow(1px 1px 3px rgba(0, 0, 0, 0.53));
height: 2em;
margin: 0.5em;
width: calc(100% - 1em);
.pos-input {
max-width: 20em;
width: 100%;
}
> :not(:first-child) {
border-left: solid 1px var(--theme-bg-light);
}
.space {
width: 0.5em;
flex-shrink: 0;
&.greedy {
flex-grow: 1;
}
}
.space, .space + * {
border-left: none;
}
@media (max-width: $mobile-break) {
margin: 0;
width: 100%;
background-color: var(--theme-bg-light);
.pos-input {
max-width: unset;
}
.thin-hide {
display: none;
}
.space {
width: 1px;
}
}
}
</style>

View File

@ -0,0 +1,74 @@
<template>
<div class="controls-switch">
<SvgButton :active="isPerspectiveView" @action="setPerspectiveView" :title="$t('controls.perspective.tooltip')">
<svg viewBox="0 0 30 30">
<path d="M19.475,10.574c-0.166-0.021-0.337-0.036-0.51-0.045c-0.174-0.009-0.35-0.013-0.525-0.011
c-0.176,0.002-0.353,0.01-0.526,0.024c-0.175,0.015-0.347,0.036-0.515,0.063l-13.39,2.189
c-0.372,0.061-0.7,0.146-0.975,0.247c-0.276,0.102-0.5,0.221-0.66,0.349c-0.161,0.129-0.259,0.268-0.282,0.408
c-0.024,0.141,0.028,0.285,0.165,0.421l5.431,5.511c0.086,0.087,0.191,0.167,0.314,0.241s0.263,0.142,0.417,0.202
c0.155,0.062,0.323,0.115,0.502,0.162c0.18,0.046,0.371,0.085,0.569,0.116s0.405,0.054,0.616,0.068
c0.211,0.015,0.427,0.021,0.645,0.017c0.217-0.003,0.436-0.016,0.652-0.037c0.217-0.022,0.431-0.054,0.641-0.095L27.12,17.43
c0.371-0.073,0.679-0.175,0.917-0.296c0.236-0.12,0.404-0.259,0.497-0.407c0.093-0.147,0.111-0.305,0.052-0.461
c-0.059-0.156-0.195-0.313-0.415-0.46l-7.089-4.742c-0.089-0.06-0.192-0.115-0.308-0.166
c-0.116-0.051-0.243-0.097-0.381-0.138c-0.137-0.041-0.283-0.078-0.438-0.108C19.803,10.621,19.641,10.595,19.475,10.574"/>
</svg>
</SvgButton>
<SvgButton :active="isFlatView" @action="setFlatView" :title="$t('controls.flatView.tooltip')">
<svg viewBox="0 0 30 30">
<path d="M22.371,4.158c1.65,0,3,1.35,3,3v15.684c0,1.65-1.35,3-3,3H7.629c-1.65,0-3-1.35-3-3V7.158c0-1.65,1.35-3,3-3H22.371z"/>
</svg>
</SvgButton>
<SvgButton v-if="controls.enableFreeFlight" :active="isFreeFlight" @action="setFreeFlight" :title="$t('controls.freeFlight.tooltip')">
<svg viewBox="0 0 30 30">
<path d="M21.927,11.253c-0.256-0.487-0.915-0.885-1.465-0.885h-2.004c-0.55,0-0.726-0.356-0.39-0.792c0,0,0.698-0.905,0.698-2.041
c0-2.08-1.687-3.767-3.767-3.767s-3.767,1.687-3.767,3.767c0,1.136,0.698,2.041,0.698,2.041c0.336,0.436,0.161,0.794-0.389,0.797
l-2.005,0.01c-0.55,0.002-1.21,0.403-1.467,0.889l-3.656,6.924c-0.257,0.487-0.088,1.128,0.375,1.425l1.824,1.171
c0.462,0.297,1.116,0.184,1.451-0.253l0.839-1.092c0.335-0.437,0.662-0.346,0.726,0.2l0.637,5.415
c0.064,0.546,0.567,0.993,1.117,0.993h7.234c0.55,0,1.053-0.447,1.117-0.993l0.635-5.401c0.064-0.546,0.392-0.637,0.727-0.2
l0.828,1.078c0.335,0.437,0.988,0.55,1.451,0.253l1.823-1.171c0.463-0.297,0.633-0.938,0.377-1.425L21.927,11.253z"/>
</svg>
</SvgButton>
</div>
</template>
<script>
import SvgButton from "@/components/ControlBar/SvgButton";
export default {
name: "ControlsSwitch",
components: {SvgButton},
data() {
return {
controls: this.$bluemap.appState.controls,
}
},
computed: {
isPerspectiveView() {
return this.controls.state === "perspective";
},
isFlatView() {
return this.controls.state === "flat";
},
isFreeFlight() {
return this.controls.state === "free";
}
},
methods: {
setPerspectiveView() {
this.$bluemap.setPerspectiveView(500, this.isFreeFlight ? 100 : 0);
},
setFlatView() {
this.$bluemap.setFlatView(500, this.isFreeFlight ? 100 : 0);
},
setFreeFlight() {
this.$bluemap.setFreeFlight(500);
}
}
}
</script>
<style lang="scss">
.controls-switch {
display: flex;
}
</style>

View File

@ -0,0 +1,70 @@
<template>
<SvgButton class="day-night-switch" :active="!isDay" @action="action">
<svg viewBox="0 0 30 30">
<path d="M17.011,19.722c-3.778-1.613-5.533-5.982-3.921-9.76c0.576-1.348,1.505-2.432,2.631-3.204
c-3.418-0.243-6.765,1.664-8.186,4.992c-1.792,4.197,0.159,9.053,4.356,10.844c3.504,1.496,7.462,0.377,9.717-2.476
C20.123,20.465,18.521,20.365,17.011,19.722z"/>
<circle cx="5.123" cy="7.64" r="1.196"/>
<circle cx="23.178" cy="5.249" r="1.195"/>
<circle cx="20.412" cy="13.805" r="1.195"/>
<circle cx="25.878" cy="23.654" r="1.195"/>
</svg>
</SvgButton>
</template>
<script>
import {animate, EasingFunctions} from "bluemap/src/util/Utils";
import SvgButton from "@/components/ControlBar/SvgButton";
let animation;
export default {
name: "DayNightSwitch",
components: {SvgButton},
data() {
return {
mapViewer: this.$bluemap.mapViewer.data
}
},
computed: {
isDay() {
return this.mapViewer.uniforms.sunlightStrength.value > 0.6;
}
},
methods: {
action(evt) {
evt.preventDefault();
if (animation) animation.cancel();
let startValue = this.mapViewer.uniforms.sunlightStrength.value;
let targetValue = this.isDay ? 0.25 : 1;
animation = animate(t => {
let u = EasingFunctions.easeOutQuad(t);
this.mapViewer.uniforms.sunlightStrength.value = startValue * (1-u) + targetValue * u;
}, 300);
}
}
}
</script>
<style lang="scss">
.day-night-switch {
svg {
fill: var(--theme-moon-day);
circle {
fill: var(--theme-stars-day);
}
}
&:active {
svg {
fill: var(--theme-moon-night);
circle {
fill: var(--theme-stars-night);
}
}
}
}
</style>

View File

@ -0,0 +1,85 @@
<template>
<SvgButton class="menu-button" :class="{close: close, back: back}" @action="$emit('action', $event)">
<svg viewBox="0 0 30 30">
<g>
<path d="M25.004,9.294c0,0.806-0.75,1.46-1.676,1.46H6.671c-0.925,0-1.674-0.654-1.674-1.46l0,0
c0-0.807,0.749-1.461,1.674-1.461h16.657C24.254,7.833,25.004,8.487,25.004,9.294L25.004,9.294z"/>
<path d="M25.004,15c0,0.807-0.75,1.461-1.676,1.461H6.671c-0.925,0-1.674-0.654-1.674-1.461l0,0
c0-0.807,0.749-1.461,1.674-1.461h16.657C24.254,13.539,25.004,14.193,25.004,15L25.004,15z"/>
<path d="M25.004,20.706c0,0.807-0.75,1.461-1.676,1.461H6.671c-0.925,0-1.674-0.654-1.674-1.461l0,0
c0-0.807,0.749-1.461,1.674-1.461h16.657C24.254,19.245,25.004,19.899,25.004,20.706L25.004,20.706z"/>
</g>
</svg>
</SvgButton>
</template>
<script>
import SvgButton from "@/components/ControlBar/SvgButton";
export default {
name: "MenuButton",
components: {SvgButton},
props: {
close: Boolean,
back: Boolean,
}
}
</script>
<style lang="scss">
.menu-button {
svg {
g {
transform-origin: center;
transition: transform 0.3s;
}
path {
transition: transform 0.3s, fill 0.3s;
transform: translate(0 0) rotate(0);
&:nth-child(1) {
transform-origin: 15px 9px;
}
&:nth-child(2) {
transform-origin: 15px 15px;
}
&:nth-child(3) {
transform-origin: 15px 21px;
}
}
}
&.close {
svg {
path:nth-child(1) {
transform: translate(0, 5.75px) rotate(45deg);
}
path:nth-child(2) {
transform: translate(-100%, 0) rotate(0);
}
path:nth-child(3) {
transform: translate(0, -5.75px) rotate(-45deg);
}
}
&.back {
svg {
g {
transform: scale(0.75);
}
path:nth-child(1) {
transform: translate(0, 10px) rotate(30deg);
}
path:nth-child(2) {
transform: translate(-150%, 0) rotate(0);
}
path:nth-child(3) {
transform: translate(0, -10px) rotate(-30deg);
}
}
}
}
}
</style>

View File

@ -0,0 +1,65 @@
<template>
<div class="number-input">
<label>
<span class="label">{{label}}:</span>
<input type="number"
v-bind:value="value | format"
v-on:input="$emit('input', $event)"
v-on:keydown="$event.stopPropagation()"
>
</label>
</div>
</template>
<script>
export default {
name: "NumberInput",
props: {
label: String,
value: Number
},
filters: {
format(value) {
return Math.floor(value);
}
}
}
</script>
<style lang="scss">
.number-input {
pointer-events: auto;
background-color: var(--theme-bg);
color: var(--theme-fg);
min-height: 2em;
.label {
display: inline-block;
width: 1em;
padding: 0 0.5em 0 0.5em;
color: var(--theme-fg-light);
}
input {
height: 100%;
line-height: 100%;
width: calc(100% - 2em);
background-color: inherit;
color: inherit;
// remove number spinner firefox
-moz-appearance: textfield;
// remove number spinner webkit
&::-webkit-inner-spin-button,
&::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
}
}
</style>

View File

@ -0,0 +1,39 @@
<template>
<div class="position-input">
<NumberInput label="x" :value="controls.position.x" v-on:input="controls.position.x = parseFloat($event.target.value);" />
<NumberInput label="y" :value="controls.position.y" v-on:input="controls.position.y = parseFloat($event.target.value);" v-if="appState.controls.state === 'free'" />
<NumberInput label="z" :value="controls.position.z" v-on:input="controls.position.z = parseFloat($event.target.value);" />
</div>
</template>
<script>
import NumberInput from "@/components/ControlBar/NumberInput";
export default {
name: "PositionInput",
components: {
NumberInput
},
data() {
return {
controls: this.$bluemap.mapViewer.controlsManager.data,
appState: this.$bluemap.appState
}
}
}
</script>
<style lang="scss">
.position-input {
display: flex;
user-select: none;
> * {
width: 100%;
&:not(:first-child) {
border-left: solid 1px var(--theme-bg-light);
}
}
}
</style>

View File

@ -0,0 +1,59 @@
<template>
<div class="svg-button" :class="{active: active}" @click="$emit('action', $event)">
<slot />
</div>
</template>
<script>
export default {
name: "SvgButton",
props: {
active: Boolean,
}
}
</script>
<style lang="scss">
.svg-button {
position: relative;
pointer-events: auto;
overflow: hidden;
cursor: pointer;
min-width: 2em;
min-height: 2em;
background-color: var(--theme-bg);
color: var(--theme-fg);
&:hover {
background-color: var(--theme-bg-hover);
}
&.active {
background-color: var(--theme-bg-light);
}
&:active {
background-color: var(--theme-fg-light);
color: var(--theme-bg);
}
svg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
height: 1.8em;
fill: var(--theme-fg-light);
}
&:active {
svg {
fill: var(--theme-bg-light);
}
}
}
</style>

View File

@ -0,0 +1,131 @@
<template>
<div id="ff-mobile-controls" :class="{disabled: !enabled}">
<div class="move-fields">
<div class="button up-button" @touchstart="forward = 1; forwardPointer = $event.changedTouches[0].identifier; $event.preventDefault();">
<svg viewBox="0 0 100 50">
<path d="M6.75,48.375c-2.75,0-3.384-1.565-1.409-3.479L46.41,5.104c1.975-1.914,5.207-1.913,7.182,0l41.067,39.792
c1.975,1.914,1.341,3.479-1.409,3.479H6.75z"/>
</svg>
</div>
<div class="button down-button" @touchstart="forward = -1; forwardPointer = $event.changedTouches[0].identifier; $event.preventDefault();">
<svg viewBox="0 0 100 50" class="down">
<path d="M6.75,48.375c-2.75,0-3.384-1.565-1.409-3.479L46.41,5.104c1.975-1.914,5.207-1.913,7.182,0l41.067,39.792
c1.975,1.914,1.341,3.479-1.409,3.479H6.75z"/>
</svg>
</div>
</div>
<div class="height-fields">
<div class="button up-button" @touchstart="up = 1; upPointer = $event.changedTouches[0].identifier; $event.preventDefault();">
<svg viewBox="0 0 100 50">
<path d="M6.75,48.375c-2.75,0-3.384-1.565-1.409-3.479L46.41,5.104c1.975-1.914,5.207-1.913,7.182,0l41.067,39.792
c1.975,1.914,1.341,3.479-1.409,3.479H6.75z"/>
</svg>
</div>
<div class="button down-button" @touchstart="up = -1; upPointer = $event.changedTouches[0].identifier; $event.preventDefault();">
<svg viewBox="0 0 100 50" class="down">
<path d="M6.75,48.375c-2.75,0-3.384-1.565-1.409-3.479L46.41,5.104c1.975-1.914,5.207-1.913,7.182,0l41.067,39.792
c1.975,1.914,1.341,3.479-1.409,3.479H6.75z"/>
</svg>
</div>
</div>
</div>
</template>
<script>
export default {
name: "FreeFlightMobileControls",
data() {
return {
enabled: false,
forward: 0,
forwardPointer: -1,
up: 0,
upPointer: -1,
}
},
methods: {
onTouchStop(evt) {
console.log("Stop: ", evt);
if (evt.changedTouches[0].identifier === this.forwardPointer) this.forward = 0;
if (evt.changedTouches[0].identifier === this.upPointer) this.up = 0;
},
onFrame(evt) {
let cm = this.$bluemap.mapViewer.controlsManager;
cm.position.x += this.forward * Math.sin(cm.rotation) * evt.detail.delta * 0.02;
cm.position.z += this.forward * -Math.cos(cm.rotation) * evt.detail.delta * 0.02;
cm.position.y += this.up * evt.detail.delta * 0.01;
},
enable(evt) {
this.enabled = true;
},
},
mounted() {
window.addEventListener("touchstart", this.enable);
window.addEventListener("touchend", this.onTouchStop);
window.addEventListener("touchcancel", this.onTouchStop);
this.$bluemap.events.addEventListener("bluemapRenderFrame", this.onFrame);
},
beforeDestroy() {
window.removeEventListener("touchstart", this.enable);
window.removeEventListener("touchend", this.onTouchStop);
window.removeEventListener("touchcancel", this.onTouchStop);
this.$bluemap.events.removeEventListener("bluemapRenderFrame", this.onFrame);
}
}
</script>
<style lang="scss">
#ff-mobile-controls {
font-size: 15vw;
&.disabled {
display: none;
}
@media (orientation: portrait) {
font-size: 15vh;
}
.button {
width: 1em;
margin: 0.1em;
opacity: 0.5;
pointer-events: auto;
svg {
fill: var(--theme-bg);
&:active {
fill: var(--theme-bg-light);
opacity: 0.8;
}
&.down {
transform: scaleY(-1);
}
}
}
.move-fields {
position: fixed;
bottom: 0.2em;
left: 0.2em;
}
.height-fields {
position: fixed;
bottom: 0.2em;
right: 0.2em;
}
}
</style>

View File

@ -0,0 +1,44 @@
<template>
<div class="group">
<span class="title">{{ title }}</span>
<div class="content">
<slot/>
</div>
</div>
</template>
<script>
export default {
name: "Group",
props: {
title: String
}
}
</script>
<style lang="scss">
.side-menu .group {
position: relative;
margin: 2em 0 1em;
padding-top: 1em;
border: solid 2px var(--theme-bg-hover);
> .title {
position: absolute;
top: calc(-0.5em - 1px);
right: 0.5em;
padding: 0 0.5em;
background-color: var(--theme-bg);
}
&:first-child {
margin-top: 1em;
}
> .content {
max-height: 15em;
overflow-y: auto;
}
}
</style>

View File

@ -0,0 +1,88 @@
<template>
<SideMenu :open="menu.isOpen"
:title="menu.currentPage().title"
:back="menu.pageStack.length > 1"
@back="menu.closePage()"
@close="menu.closeAll()">
<div v-if="menu.currentPage().id === 'root'">
<SimpleButton @action="menu.openPage('maps', () => $t('maps.title'))" :submenu="true">{{ $t("maps.button") }}</SimpleButton>
<SimpleButton @action="menu.openPage('markers', () => $t('markers.title'), {markerSet: markers})" :submenu="true">{{ $t("markers.button") }}</SimpleButton>
<SimpleButton @action="menu.openPage('settings', () => $t('settings.title'))" :submenu="true">{{ $t("settings.button") }}</SimpleButton>
<SimpleButton @action="menu.openPage('info', () => $t('info.title'))" :submenu="true">{{ $t("info.button") }}</SimpleButton>
<hr>
<SimpleButton @action="goFullscreen">{{ $t("goFullscreen.button") }}</SimpleButton>
<SimpleButton @action="$bluemap.resetCamera()">{{ $t("resetCamera.button") }}</SimpleButton>
<SimpleButton @action="$bluemap.takeScreenshot()">{{ $t("screenshot.button") }}</SimpleButton>
<SimpleButton @action="$bluemap.updateMap()" :title="$t('updateMap.tooltip')">{{ $t("updateMap.button") }}</SimpleButton>
</div>
<div v-if="menu.currentPage().id === 'maps'">
<MapButton v-for="map of appState.maps" :key="map.id" :map="map" />
</div>
<MarkerSetMenu v-if="menu.currentPage().id === 'markers'" :menu="menu" />
<SettingsMenu v-if="menu.currentPage().id === 'settings'" />
<div class="info-content" v-if="menu.currentPage().id === 'info'" v-html="$t('info.content', {
version: $bluemap.settings.version
})"></div>
</SideMenu>
</template>
<script>
import SideMenu from "@/components/Menu/SideMenu";
import SimpleButton from "@/components/Menu/SimpleButton";
import SettingsMenu from "@/components/Menu/SettingsMenu";
import {MainMenu} from "@/js/MainMenu";
import MarkerSetMenu from "@/components/Menu/MarkerSetMenu";
import MapButton from "@/components/Menu/MapButton";
export default {
name: "MainMenu",
components: {MapButton, MarkerSetMenu, SettingsMenu, SimpleButton, SideMenu},
props: {
menu: MainMenu
},
data() {
return {
appState: this.$bluemap.appState,
markers: this.$bluemap.mapViewer.markers.data,
}
},
methods: {
goFullscreen() {
document.body.requestFullscreen();
}
}
}
</script>
<style lang="scss">
.info-content {
font-size: 0.8em;
table {
border-collapse: collapse;
width: 100%;
tr {
th, td {
padding: 0.2em 0.5em;
border: solid 1px var(--theme-bg-light);
}
th {
font-weight: inherit;
text-align: inherit;
}
}
}
.info-footer {
text-align: center;
}
}
</style>

View File

@ -0,0 +1,71 @@
<template>
<div class="map-button" :class="{selected: map.id === selectedMapId}" @click="switchMap(map.id)" :title="map.id">
<span class="sky" :style="{color: 'rgb(' + map.skyColor.r * 255 + ',' + map.skyColor.g * 255 + ',' + map.skyColor.b * 255 + ')'}">&bull;</span>
<span class="name">{{map.name}}</span>
</div>
</template>
<script>
export default {
name: "MapButton",
props: {
map: Object,
},
data() {
return {
mapViewer: this.$bluemap.mapViewer.data,
appState: this.$bluemap.appState,
}
},
computed: {
selectedMapId() {
return this.mapViewer.map ? this.mapViewer.map.id : null;
}
},
methods: {
switchMap(mapId) {
this.$bluemap.switchMap(mapId);
}
}
}
</script>
<style lang="scss">
.side-menu .map-button {
position: relative;
cursor: pointer;
user-select: none;
height: 2em;
line-height: 2em;
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
&.selected {
background-color: var(--theme-bg-light);
}
&:hover {
background-color: var(--theme-bg-hover);
}
.sky {
float: left;
border-radius: 100%;
width: 0.5em;
height: 0.5em;
margin: 0 0.25em 0 0.5em;
}
.id {
font-style: italic;
color: var(--theme-fg-light);
margin: 0 0.5em;
}
}
</style>

View File

@ -0,0 +1,209 @@
<template>
<div class="marker-item" :class="{'marker-hidden': !marker.visible}">
<div class="marker-button" :title="marker.id" @click="click(false)">
<div class="icon" v-if="marker.type === 'player'">
<img :src="'maps/' + mapId + '/live/assets/playerheads/' + marker.playerUuid + '.png'" alt="playerhead" @error="steve">
</div>
<div class="info">
<div class="label">{{markerLabel}}</div>
<div class="stats">
<div v-if="appState.debug">
{{marker.type}}-marker
</div>
<div>
({{marker.position.x | position}} | {{marker.position.y | position}} | {{marker.position.z | position}})
</div>
</div>
</div>
</div>
<div class="follow-player-button" :class="{active: controls.controls.followingPlayer && controls.controls.followingPlayer.id === marker.id}"
v-if="marker.type === 'player'" @click="click(true)" :title="$t('markers.followPlayerTitle')">
<svg viewBox="0 0 30 30">
<circle fill="none" stroke-width="3" stroke-miterlimit="10" cx="15" cy="15" r="10.375"/>
<line fill="none" stroke-width="3" stroke-miterlimit="10" x1="3.25" y1="15" x2="1.063" y2="15"/>
<line fill="none" stroke-width="3" stroke-miterlimit="10" x1="15" y1="26.75" x2="15" y2="28.938"/>
<line fill="none" stroke-width="3" stroke-miterlimit="10" x1="26.75" y1="15" x2="28.938" y2="15"/>
<line fill="none" stroke-width="3" stroke-miterlimit="10" x1="15" y1="3.25" x2="15" y2="1.063"/>
<circle stroke="none" cx="15" cy="15" r="6.042"/>
</svg>
</div>
</div>
</template>
<script>
export default {
name: "MarkerItem",
props: {
marker: Object,
},
data() {
return {
appState: this.$bluemap.appState,
controls: this.$bluemap.mapViewer.controlsManager.data,
mapId: this.$bluemap.mapViewer.data.map.id
}
},
computed: {
markerLabel() {
switch (this.marker.type) {
case "player" : return this.marker.name;
default : break;
}
if (this.marker.label){
let strippedLabel = /^(?:<[^>]*>\s*)*([^<>]*\S[^<>]*)(?:<|$)/gi.exec(this.marker.label);
if (strippedLabel && strippedLabel.length > 1) {
return strippedLabel[1];
}
}
return this.marker.id;
}
},
filters: {
position(v) {
return Math.floor(v);
}
},
methods: {
async click(follow) {
let cm = this.$bluemap.mapViewer.controlsManager;
if (cm.controls && cm.controls.stopFollowingPlayerMarker) {
cm.controls.stopFollowingPlayerMarker();
}
if (this.marker.type === "player") {
if (this.marker.foreign) {
let matchingMap = await this.$bluemap.findPlayerMap(this.marker.playerUuid);
if (!matchingMap) return;
//this.$bluemap.appState.menu.closeAll();
await this.$bluemap.switchMap(matchingMap.data.id);
}
if (follow && cm.controls && cm.controls.followPlayerMarker && this.marker.visible) {
cm.controls.followPlayerMarker(this.marker);
}
} else if (!this.marker.visible) {
return;
}
cm.position.copy(this.marker.position);
},
steve(event) {
event.target.src = "assets/steve.png";
}
}
}
</script>
<style lang="scss">
@import "~@/scss/variables.scss";
.side-menu .marker-item {
display: flex;
margin: 0.5em 0;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
white-space: nowrap;
user-select: none;
&.marker-hidden {
opacity: 0.5;
filter: grayscale(1);
}
.marker-button {
display: flex;
flex-grow: 1;
cursor: pointer;
&:hover {
background-color: var(--theme-bg-hover);
}
> .info {
position: relative;
flex-grow: 1;
overflow-x: hidden;
text-overflow: ellipsis;
.label {
line-height: 2em;
overflow-x: hidden;
text-overflow: ellipsis;
margin: 0 0.5em 1.5em 0.5em;
}
.stats {
display: flex;
margin: 0 0.5em;
position: absolute;
bottom: 0;
font-size: 0.8em;
line-height: 2em;
color: var(--theme-fg-light);
> div {
&:not(:first-child) {
margin-left: 0.5em;
padding-left: 0.5em;
border-left: solid 1px var(--theme-bg-hover);
}
}
}
}
> .icon {
height: 2.5em;
margin: 0.5em;
flex-shrink: 0;
img {
image-rendering: pixelated;
height: 100%;
}
}
}
> .follow-player-button {
width: 2em;
cursor: pointer;
background-color: var(--theme-bg);
&:hover, &.active {
background-color: var(--theme-bg-light);
}
> svg {
position: relative;
fill: var(--theme-fg-light);
stroke: var(--theme-fg-light);
top: 50%;
transform: translate(0, -50%) scale(0.75);
}
&:active {
background-color: var(--theme-fg-light);
color: var(--theme-bg);
> svg {
fill: var(--theme-bg-light);
stroke: var(--theme-bg-light);
}
}
}
}
</style>

View File

@ -0,0 +1,154 @@
<template>
<div class="marker-set" :title="markerSet.id">
<div class="info" @click="toggle">
<div class="marker-set-switch">
<div class="label">{{ label }}</div>
<SwitchHandle :on="markerSet.visible" v-if="markerSet.toggleable"/>
</div>
<div class="stats">
<div>
{{ markerSet.markers.length }}
{{ $tc('markers.marker', markerSet.markers.length) }}
</div>
<div v-if="filteredMarkerSets.length > 0">
{{ filteredMarkerSets.length }}
{{ $tc('markers.markerSet', filteredMarkerSets.length) }}
</div>
</div>
</div>
<div class="open-menu-button" @click="$emit('more', $event)">
<svg viewBox="0 0 30 30">
<path d="M25.004,9.294c0,0.806-0.75,1.46-1.676,1.46H6.671c-0.925,0-1.674-0.654-1.674-1.46l0,0
c0-0.807,0.749-1.461,1.674-1.461h16.657C24.254,7.833,25.004,8.487,25.004,9.294L25.004,9.294z"/>
<path d="M25.004,20.706c0,0.807-0.75,1.461-1.676,1.461H6.671c-0.925,0-1.674-0.654-1.674-1.461l0,0
c0-0.807,0.749-1.461,1.674-1.461h16.657C24.254,19.245,25.004,19.899,25.004,20.706L25.004,20.706z"/>
</svg>
</div>
</div>
</template>
<script>
import SwitchHandle from "@/components/Menu/SwitchHandle";
export default {
name: "MarkerSet",
components: {SwitchHandle},
props: {
markerSet: Object,
},
computed: {
filteredMarkerSets() {
return this.markerSet.markerSets.filter(markerSet => {
return (markerSet.id !== "bm-popup-set");
});
},
label() {
if (this.markerSet.id === "bm-players") return this.$t("players.title");
return this.markerSet.label;
}
},
methods: {
toggle() {
if (this.markerSet.toggleable) {
this.markerSet.visible = !this.markerSet.visible
}
}
}
}
</script>
<style lang="scss">
.side-menu .marker-set {
display: flex;
user-select: none;
line-height: 2em;
margin: 0.5em 0;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
> .info {
flex-grow: 1;
cursor: pointer;
&:hover {
background-color: var(--theme-bg-hover);
}
> .marker-set-switch {
position: relative;
.label {
margin: 0 3em 0 0.5em;
}
> .switch {
position: absolute;
top: 0.5em;
right: 0.5em;
}
}
> .stats {
display: flex;
margin: 0 0.5em;
font-size: 0.8em;
line-height: 2em;
color: var(--theme-fg-light);
> div {
&:not(:first-child) {
margin-left: 0.5em;
padding-left: 0.5em;
border-left: solid 1px var(--theme-bg-light);
}
}
}
}
> .open-menu-button {
width: 2em;
cursor: pointer;
&:hover {
background-color: var(--theme-bg-hover);
}
> svg {
position: relative;
fill: var(--theme-fg-light);
top: 50%;
transform: translate(0, -50%) scale(0.75);
path:nth-child(1) {
transform-origin: 15px 9px;
transform: translate(0, 10px) rotate(-30deg);
}
path:nth-child(2) {
transform-origin: 15px 21px;
transform: translate(0, -10px) rotate(30deg);
}
}
&:active {
background-color: var(--theme-fg-light);
color: var(--theme-bg);
> svg {
fill: var(--theme-bg-light);
}
}
}
}
</style>

View File

@ -0,0 +1,69 @@
<template>
<div>
<div class="marker-sets">
<MarkerSet v-for="markerSet of filteredMarkerSets" :key="markerSet.id" :marker-set="markerSet" @more="openMore(markerSet)" />
</div>
<hr v-if="filteredMarkerSets.length > 0 & thisMarkerSet.markers.length > 0">
<div class="markers" v-if="thisMarkerSet.markers.length > 0">
<TextInput :value="filter.search" @input="filter.search = $event.target.value" :placeholder="$t('markers.searchPlaceholder')" />
<MarkerItem v-for="marker of filteredMarkers" :key="marker.id" :marker="marker" />
</div>
</div>
</template>
<script>
import MarkerItem from "@/components/Menu/MarkerItem";
import TextInput from "@/components/Menu/TextInput";
import MarkerSet from "@/components/Menu/MarkerSet";
import {MainMenu} from "@/js/MainMenu";
export default {
name: "MarkerSetMenu",
components: {MarkerSet, TextInput, MarkerItem},
props: {
menu: MainMenu
},
data() {
return {
filter: {
search: "",
}
}
},
computed: {
thisMarkerSet() {
return this.menu.currentPage().markerSet;
},
filteredMarkers() {
return [...this.thisMarkerSet.markers].sort((a, b) => {
if (a.id < b.id) return -1;
if (a.id > b.id) return 1;
return 0;
}).filter(marker => {
if (!this.filter.search) return true;
if (marker.id.includesCI(this.filter.search)) return true;
if (marker.label && marker.label.includesCI(this.filter.search)) return true;
if (marker.type === "player" && (marker.name.includesCI(this.filter.search) || marker.playerUuid.includesCI(this.filter.search))) return true;
return false;
});
},
filteredMarkerSets() {
return this.thisMarkerSet.markerSets.filter(markerSet => {
return (markerSet.id !== "bm-popup-set");
});
}
},
methods: {
openMore(markerSet) {
this.menu.openPage(
this.menu.currentPage().id,
this.menu.currentPage().title + " > " + markerSet.label,
{markerSet: markerSet}
)
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,116 @@
<template>
<div>
<Group :title="$t('controls.title')">
<SimpleButton :active="appState.controls.state === 'perspective'" @action="$bluemap.setPerspectiveView(500, appState.controls.state === 'free' ? 100 : 0)">{{$t('controls.perspective.button')}}</SimpleButton>
<SimpleButton :active="appState.controls.state === 'flat'" @action="$bluemap.setFlatView(500, appState.controls.state === 'free' ? 100 : 0)">{{$t('controls.flatView.button')}}</SimpleButton>
<SimpleButton :active="appState.controls.state === 'free'" @action="$bluemap.setFreeFlight(500)">{{$t('controls.freeFlight.button')}}</SimpleButton>
</Group>
<Group :title="$t('lighting.title')">
<Slider :value="mapViewer.uniforms.sunlightStrength.value" :min="0" :max="1" :step="0.01"
@update="mapViewer.uniforms.sunlightStrength.value = $event">{{$t('lighting.sunlight')}}</Slider>
<Slider :value="mapViewer.uniforms.ambientLight.value" :min="0" :max="1" :step="0.01"
@update="mapViewer.uniforms.ambientLight.value = $event">{{$t('lighting.ambientLight')}}</Slider>
</Group>
<Group :title="$t('resolution.title')">
<SimpleButton v-for="stage of qualityStages" :key="stage.name"
:active="mapViewer.superSampling === stage.value"
@action="$bluemap.mapViewer.superSampling = stage.value; $bluemap.saveUserSettings();"
>{{stage.name}}</SimpleButton>
</Group>
<Group :title="$t('renderDistance.title')">
<Slider :value="mapViewer.loadedHiresViewDistance" :min="settings.hiresSliderMin" :max="settings.hiresSliderMax" :step="10" :formatter="renderDistanceFormatter"
@update="mapViewer.loadedHiresViewDistance = $event; $bluemap.mapViewer.updateLoadedMapArea()" @lazy="$bluemap.saveUserSettings()">{{ $t("renderDistance.hiresLayer") }}</Slider>
<Slider :value="mapViewer.loadedLowresViewDistance" :min="settings.lowresSliderMin" :max="settings.lowresSliderMax" :step="100"
@update="mapViewer.loadedLowresViewDistance = $event; $bluemap.mapViewer.updateLoadedMapArea()" @lazy="$bluemap.saveUserSettings()">{{ $t("renderDistance.lowersLayer") }}</Slider>
<SwitchButton :on="!appState.controls.pauseTileLoading" @action="appState.controls.pauseTileLoading = !appState.controls.pauseTileLoading; $bluemap.saveUserSettings()">{{ $t("renderDistance.loadHiresWhileMoving") }}</SwitchButton>
</Group>
<Group :title="$t('freeFlightControls.title')">
<Slider :value="appState.controls.mouseSensitivity" :min="0.1" :max="5" :step="0.05"
@update="appState.controls.mouseSensitivity = $event; $bluemap.updateControlsSettings();" @lazy="$bluemap.saveUserSettings()">{{ $t("freeFlightControls.mouseSensitivity") }}</Slider>
<SwitchButton :on="appState.controls.invertMouse" @action="appState.controls.invertMouse = !appState.controls.invertMouse; $bluemap.updateControlsSettings(); $bluemap.saveUserSettings()">{{ $t("freeFlightControls.invertMouseY") }}</SwitchButton>
</Group>
<Group :title="$t('theme.title')">
<SimpleButton v-for="theme of themes" :key="theme.name"
:active="appState.theme === theme.value"
@action="$bluemap.setTheme(theme.value); $bluemap.saveUserSettings();"
>{{theme.name}}</SimpleButton>
</Group>
<Group :title="$t('screenshot.title')">
<SwitchButton :on="appState.screenshot.clipboard" @action="appState.screenshot.clipboard = !appState.screenshot.clipboard; $bluemap.saveUserSettings()">{{ $t("screenshot.clipboard") }}</SwitchButton>
</Group>
<Group v-if="$i18n.languages.length > 1" :title="$t('language.title')">
<SimpleButton v-for="lang of $i18n.languages" :key="lang.locale"
:active="lang.locale === $i18n.locale"
@action="$i18n.setLanguage(lang.locale); $bluemap.saveUserSettings();"
>{{lang.name}}</SimpleButton>
</Group>
<SwitchButton :on="appState.debug" @action="switchDebug(); $bluemap.saveUserSettings();">{{ $t("debug.button") }}</SwitchButton>
<SimpleButton @action="$bluemap.resetSettings()">{{ $t("resetAllSettings.button") }}</SimpleButton>
</div>
</template>
<script>
import Group from "@/components/Menu/Group";
import SimpleButton from "@/components/Menu/SimpleButton";
import Slider from "@/components/Menu/Slider";
import SwitchButton from "@/components/Menu/SwitchButton";
import i18n from "../../i18n";
const themes = [
{get name(){ return i18n.t("theme.default")}, value: null},
{get name(){ return i18n.t("theme.dark")}, value: 'dark'},
{get name(){ return i18n.t("theme.light")}, value: 'light'},
{get name(){ return i18n.t("theme.contrast")}, value: 'contrast'},
];
const qualityStages = [
{get name(){ return i18n.t("resolution.high")}, value: 2},
{get name(){ return i18n.t("resolution.normal")}, value: 1},
{get name(){ return i18n.t("resolution.low")}, value: 0.5},
];
export default {
name: "SettingsMenu",
components: {SwitchButton, Slider, SimpleButton, Group},
data() {
return {
appState: this.$bluemap.appState,
mapViewer: this.$bluemap.mapViewer.data,
settings: {
...{
hiresSliderMax: 500,
hiresSliderMin: 50,
lowresSliderMax: 10000,
lowresSliderMin: 500
},
...this.$bluemap.settings
},
qualityStages: qualityStages,
themes: themes,
}
},
methods: {
switchDebug() {
this.$bluemap.setDebug(!this.appState.debug);
},
renderDistanceFormatter(value) {
let f = parseFloat(value);
return f === 0 ? this.$t("renderDistance.off") : f.toFixed(0);
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,131 @@
<template>
<Transition name="side-menu" @enter="buttonEnterAnimation(); $emit('enter', $event)">
<div class="side-menu" v-if="open">
<MenuButton :close="open && rendered" :back="back" @action="$emit('back', $event)" />
<MenuButton class="full-close" v-if="open && back" :close="true" @action="$emit('close', $event)" />
<div class="title">{{ title }}</div>
<div class="content">
<slot />
</div>
</div>
</Transition>
</template>
<script>
import MenuButton from "@/components/ControlBar/MenuButton";
export default {
name: "SideMenu",
components: {MenuButton},
props: {
title: {
type: String,
default: "Menu"
},
open: {
type: Boolean,
default: true
},
back: Boolean
},
data() {
return {
rendered: false
}
},
methods: {
async buttonEnterAnimation() {
this.rendered = false;
await this.$nextTick();
await this.$nextTick();
this.rendered = true;
}
}
}
</script>
<style lang="scss">
@import "~@/scss/variables.scss";
.side-menu {
position: fixed;
top: 0;
left: 0;
overflow: hidden;
pointer-events: auto;
width: 100%;
max-width: 20em;
height: 100%;
filter: drop-shadow(1px 1px 3px #0008);
background-color: var(--theme-bg);
color: var(--theme-fg);
&-enter-active, &-leave-active {
transition: opacity 0.3s;
}
&-enter, &-leave-to {
opacity: 0;
pointer-events: none;
* {
pointer-events: none !important;
}
}
> .menu-button {
position: absolute;
top: 0;
left: 0;
margin: 0.5em;
@media (max-width: $mobile-break) {
margin: 0;
}
&.full-close {
right: 0;
left: unset;
}
}
> .title {
line-height: 2em;
text-align: center;
background-color: inherit;
border-bottom: solid 1px var(--theme-bg-hover);
padding: 0.5em;
@media (max-width: $mobile-break) {
padding: 0;
}
}
> .content {
position: relative;
overflow-y: auto;
overflow-x: hidden;
padding: 0.5em;
height: calc(100% - 4em - 1px);
@media (max-width: $mobile-break) {
height: calc(100% - 3em - 1px);
}
hr {
border: none;
border-bottom: solid 2px var(--theme-bg-hover);
margin: 0.5em 0;
}
}
}
</style>

View File

@ -0,0 +1,89 @@
<template>
<div class="simple-button" :class="{active: active}" @click="$emit('action')">
<div class="label"><slot /></div>
<div class="submenu-icon" v-if="submenu">
<svg viewBox="0 0 30 30">
<path d="M25.004,9.294c0,0.806-0.75,1.46-1.676,1.46H6.671c-0.925,0-1.674-0.654-1.674-1.46l0,0
c0-0.807,0.749-1.461,1.674-1.461h16.657C24.254,7.833,25.004,8.487,25.004,9.294L25.004,9.294z"/>
<path d="M25.004,20.706c0,0.807-0.75,1.461-1.676,1.461H6.671c-0.925,0-1.674-0.654-1.674-1.461l0,0
c0-0.807,0.749-1.461,1.674-1.461h16.657C24.254,19.245,25.004,19.899,25.004,20.706L25.004,20.706z"/>
</svg>
</div>
</div>
</template>
<script>
export default {
name: "SimpleButton",
props: {
submenu: Boolean,
active: {
type: Boolean,
default: false,
}
}
}
</script>
<style lang="scss">
.side-menu .simple-button {
cursor: pointer;
user-select: none;
display: flex;
line-height: 2em;
padding: 0 0.5em;
> .label {
flex-grow: 1;
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
}
&:hover {
background-color: var(--theme-bg-hover);
}
&.active {
background-color: var(--theme-bg-light);
}
> .submenu-icon {
width: 2em;
height: 2em;
flex-shrink: 0;
margin-right: -0.5em;
> svg {
fill: var(--theme-fg-light);
path:nth-child(1) {
transform-origin: 15px 9px;
transform: translate(0, 10px) rotate(-30deg);
}
path:nth-child(2) {
transform-origin: 15px 21px;
transform: translate(0, -10px) rotate(30deg);
}
transform: scale(0.75);
}
}
&:active {
background-color: var(--theme-fg-light);
color: var(--theme-bg);
> .submenu-icon > svg {
fill: var(--theme-bg-light);
}
}
}
</style>

View File

@ -0,0 +1,94 @@
<template>
<div class="slider">
<div class="label"><slot />: <span class="value">{{formatter(value)}}</span></div>
<label>
<input type="range" :min="min" :max="max" :step="step" :value="value" @input="$emit('update', parseFloat($event.target.value))" @change="$emit('lazy', parseFloat($event.target.value))">
</label>
</div>
</template>
<script>
function countDecimals(value) {
if(Math.floor(value) === value) return 0;
return value.toString().split(".")[1].length || 0;
}
export default {
name: "Slider",
props: {
value: Number,
min: Number,
max: Number,
step: Number,
formatter: {
type: Function,
default: function(value) {
return parseFloat(value).toFixed(countDecimals(this.step));
}
}
}
}
</script>
<style lang="scss">
.side-menu .slider {
line-height: 2em;
padding: 0 0.5em;
&:hover {
background-color: var(--theme-bg-hover);
}
> .label {
> .value {
float: right;
}
}
> label {
> input {
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
outline: none;
width: 100%;
height: 1em;
border-radius: 1em;
//border: solid 0.125em var(--theme-fg-light);
overflow: hidden;
background-color: var(--theme-bg-light);
&::-webkit-slider-thumb {
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
outline: none;
width: 1em;
height: 1em;
border-radius: 1em;
border: solid 0.125em var(--theme-bg-light);
background-color: var(--theme-bg);
//box-shadow: calc(-100vw - 0.375em) 0 0 100vw var(--theme-switch-button-on);
}
&::-moz-range-thumb {
width: 0.75em;
height: 0.75em;
border-radius: 0.75em;
border: solid 0.125em var(--theme-bg-light);
background-color: var(--theme-bg);
}
}
}
}
</style>

View File

@ -0,0 +1,46 @@
<template>
<div class="switch-button" @click="$emit('action')">
<div class="label"><slot /></div>
<SwitchHandle :on="on" />
</div>
</template>
<script>
import SwitchHandle from "@/components/Menu/SwitchHandle";
export default {
name: "SwitchButton",
components: {SwitchHandle},
props: {
on: Boolean
}
}
</script>
<style lang="scss">
.side-menu .switch-button {
cursor: pointer;
user-select: none;
display: flex;
line-height: 2em;
padding: 0 0.5em;
> .label {
flex-grow: 1;
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
}
> .switch {
margin: 0.5em 0;
}
&:hover {
background-color: var(--theme-bg-hover);
}
}
</style>

View File

@ -0,0 +1,48 @@
<template>
<div class="switch" :class="{on: on}"></div>
</template>
<script>
export default {
name: "SwitchHandle",
props: {
on: Boolean
}
}
</script>
<style lang="scss">
.side-menu .switch {
height: 1em;
width: 2em;
border-radius: 1em;
background-color: var(--theme-bg-light);
transition: background-color 0.3s;
&::after {
content: "";
display: block;
width: 0.75em;
height: 0.75em;
border-radius: 100%;
background-color: var(--theme-bg);
position: relative;
top: 0.125em;
left: 0.125em;
transition: left 0.3s;
}
&.on {
background-color: var(--theme-switch-button-on);
&::after {
left: 1.125em;
}
}
}
</style>

View File

@ -0,0 +1,20 @@
<template>
<input class="text-input" type="text" :value="value" @input="$emit('input', $event)" @keydown="$event.stopPropagation()">
</template>
<script>
export default {
name: "TextInput",
props: {
value: String
}
}
</script>
<style lang="scss">
.side-menu .text-input {
background-color: var(--theme-bg-hover);
width: calc(100% - 1em);
padding: 0.5em;
}
</style>

View File

@ -0,0 +1,93 @@
Copyright 2011 The Quicksand Project Authors (https://github.com/andrew-paglinawan/QuicksandFamily), with Reserved Font Name “Quicksand”.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

View File

@ -0,0 +1,154 @@
export default {
pageTitle: "BlueMap - {map}",
menu: {
title: "Menu",
tooltip: "Menu"
},
maps: {
title: "Maps",
button: "Maps",
tooltip: "Map-List"
},
markers: {
title: "Markers",
button: "Markers",
tooltip: "Marker-List",
marker: "marker | markers",
markerSet: "marker-set | marker-sets",
searchPlaceholder: "Search...",
followPlayerTitle: "Follow Player"
},
settings: {
title: "Settings",
button: "Settings"
},
goFullscreen: {
button: "Go Fullscreen"
},
resetCamera: {
button: "Reset Camera",
tooltip: "Reset Camera & Position"
},
updateMap: {
button: "Update Map",
tooltip: "Clear Tile Cache"
},
lighting: {
title: "Lighting",
dayNightSwitch: {
tooltip: "Day/Night"
},
sunlight: "Sunlight",
ambientLight: "Ambient-Light"
},
resolution: {
title: "Resolution",
high: "High (SSAA, x2)",
normal: "Normal (Native, x1)",
low: "Low (Upscaling, x0.5)"
},
freeFlightControls: {
title: "Free-Flight Controls",
mouseSensitivity: "Mouse-Sensitivity",
invertMouseY: "Invert Mouse Y"
},
renderDistance: {
title: "Render Distance",
hiresLayer: "Hires layer",
lowersLayer: "Lowres layer",
loadHiresWhileMoving: "Load hires-tiles while moving",
off: "Off"
},
theme: {
title: "Theme",
default: "Default (System/Browser)",
dark: "Dark",
light: "Light",
contrast: "Contrast"
},
debug: {
button: "Debug"
},
resetAllSettings: {
button: "Reset All Settings"
},
players: {
title: "Players",
tooltip: "Player-List"
},
compass: {
tooltip: "Compass / Face North"
},
screenshot: {
title: "Screenshot",
button: "Take Screenshot",
clipboard: "Copy to Clipboard"
},
controls: {
title: "View / Controls",
perspective: {
button: "Perspective",
tooltip: "Perspective-View"
},
flatView: {
button: "Flat",
tooltip: "Orthographic / Flat-View",
},
freeFlight: {
button: "Free-Flight",
tooltip: "Free-Flight / Spectator Mode"
}
},
language: {
title: "Language",
},
blockTooltip: {
block: "Block",
position: "Position",
chunk: "Chunk",
region: {
region: "Region",
file: "File"
},
light: {
light: "Light",
sun: "Sun",
block: "Block",
}
},
info: {
title: "Info",
button: "Info",
content: `
<img src="assets/logo.png" style="display: block; width: 40%; margin: 3em auto; border-radius: 50%">
<p>
<h2>Mouse-Controls:</h2>
<table>
<tr><th>move</th><td><kbd>left-click</kbd> + drag</td></tr>
<tr><th>zoom</th><td><kbd>mousewheel</kbd> (scroll)</td></tr>
<tr><th>rotate / tilt</th><td><kbd>right-click</kbd> + drag</td></tr>
</table>
</p>
<p>
<h2>Keyboard-Controls:</h2>
<table>
<tr><th>move</th><td><kbd>wasd</kbd> / <kbd>arrow-keys</kbd></td></tr>
<tr><th>zoom</th><td>Numpad: <kbd>+</kbd>/<kbd>-</kbd> or <kbd>Ins</kbd>/<kbd>Home</kbd></td></tr>
<tr><th>rotate / tilt</th><td><kbd>Left-Alt</kbd> + <kbd>wasd</kbd> / <kbd>arrow-keys</kbd> or <kbd>Delete</kbd>/<kbd>End</kbd>/<kbd>Page Up</kbd>/<kbd>Page Down</kbd></td></tr>
</table>
</p>
<p>
<h2>Touch-Controls:</h2>
<table>
<tr><th>move</th><td>touch + drag</td></tr>
<tr><th>zoom</th><td>touch with two fingers + pinch</td></tr>
<tr><th>rotate / tilt</th><td>touch with two fingers + rotate / move up/down</td></tr>
</table>
</p>
<br><hr>
<p class="info-footer">
This map has been generated with &#9829; using <a href="https://bluecolo.red/bluemap">BlueMap</a> {version}
</p>
`
}
};

View File

@ -0,0 +1,36 @@
import VueI18n from 'vue-i18n';
import Vue from 'vue';
import fallback from './fallback';
VueI18n.prototype.setLanguage = async function(lang) {
try {
if (!this.messages[lang]){
let messages = {};
messages = (await import(/* webpackIgnore: true */ `../lang/${lang}.js`)).default;
this.setLocaleMessage(lang, messages);
}
this.locale = lang;
document.querySelector('html').setAttribute('lang', lang);
} catch (e) {
console.error(`Failed to load language '${lang}'!`, e);
}
}
VueI18n.prototype.loadLanguageSettings = async function() {
let settings = (await import(/* webpackIgnore: true */ "../lang/settings.js")).default;
this.languages = settings.languages;
this.setLanguage(settings.default);
};
Vue.use(VueI18n);
const i18n = new VueI18n({
locale: 'fallback',
fallbackLocale: 'fallback',
silentFallbackWarn: true,
messages: { fallback }
});
export default i18n;

View File

@ -0,0 +1,759 @@
/*
* 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 "bluemap/src/BlueMap";
import {MapViewer} from "bluemap/src/MapViewer";
import {MapControls} from "bluemap/src/controls/map/MapControls";
import {FreeFlightControls} from "bluemap/src/controls/freeflight/FreeFlightControls";
import {FileLoader, MathUtils, Vector3} from "three";
import {Map as BlueMapMap} from "bluemap/src/map/Map";
import {alert, animate, EasingFunctions, generateCacheHash} from "bluemap/src/util/Utils";
import {MainMenu} from "@/js/MainMenu";
import {PopupMarker} from "@/js/PopupMarker";
import {MarkerSet} from "bluemap/src/markers/MarkerSet";
import {getLocalStorage, round, setLocalStorage} from "@/js/Utils";
import i18n from "../i18n";
import {PlayerMarkerManager} from "bluemap/src/markers/PlayerMarkerManager";
import {NormalMarkerManager} from "bluemap/src/markers/NormalMarkerManager";
export class BlueMapApp {
/**
* @param rootElement {Element}
*/
constructor(rootElement) {
this.events = rootElement;
this.mapViewer = new MapViewer(rootElement, this.events);
this.mapControls = new MapControls(this.mapViewer.renderer.domElement);
this.freeFlightControls = new FreeFlightControls(this.mapViewer.renderer.domElement);
/** @type {PlayerMarkerManager} */
this.playerMarkerManager = null;
/** @type {NormalMarkerManager} */
this.markerFileManager = null;
/** @type {{
* version: string,
* useCookies: boolean,
* enableFreeFlight: boolean,
* resolutionDefault: number,
* minZoomDistance: number,
* maxZoomDistance: number,
* hiresSliderMax: number,
* hiresSliderDefault: number,
* hiresSliderMin: number,
* lowresSliderMax: number,
* lowresSliderDefault: number,
* lowresSliderMin: number,
* startLocation: string,
* maps: string[],
* scripts: string[],
* styles: string[]
* }}
**/
this.settings = null;
this.savedUserSettings = new Map();
/** @type BlueMapMap[] */
this.maps = [];
/** @type Map<BlueMapMap> */
this.mapsMap = new Map();
this.lastCameraMove = 0;
this.dataUrl = "maps/";
this.mainMenu = new MainMenu();
this.appState = {
controls: {
state: "perspective",
mouseSensitivity: 1,
invertMouse: false,
enableFreeFlight: false,
pauseTileLoading: false
},
menu: this.mainMenu,
maps: [],
theme: null,
screenshot: {
clipboard: true
},
debug: false
};
// init
this.updateControlsSettings();
this.initGeneralEvents();
// popup on click
this.popupMarkerSet = new MarkerSet("bm-popup-set");
this.popupMarker = new PopupMarker("bm-popup", this.appState, this.events);
this.popupMarkerSet.add(this.popupMarker);
this.mapViewer.markers.add(this.popupMarkerSet);
this.updateLoop = null;
this.hashUpdateTimeout = null;
this.viewAnimation = null;
}
/**
* @returns {Promise<void|never>}
*/
async load() {
let oldMaps = this.maps;
this.maps = [];
this.appState.maps.splice(0, this.appState.maps.length);
this.mapsMap.clear();
// load settings
await this.getSettings();
this.mapControls.minDistance = this.settings.minZoomDistance;
this.mapControls.maxDistance = this.settings.maxZoomDistance;
this.appState.controls.enableFreeFlight = this.settings.enableFreeFlight;
// load settings-styles
if (this.settings.styles) for (let styleUrl of this.settings.styles) {
let styleElement = document.createElement("link");
styleElement.rel = "stylesheet";
styleElement.href = styleUrl;
document.head.appendChild(styleElement);
}
// unload loaded maps
await this.mapViewer.switchMap(null);
oldMaps.forEach(map => map.dispose());
// load maps
this.maps = await this.loadMaps();
for (let map of this.maps) {
this.mapsMap.set(map.data.id, map);
this.appState.maps.push(map.data);
}
// switch to map
if (!await this.loadPageAddress()) {
if (this.maps.length > 0) await this.switchMap(this.maps[0].data.id);
this.resetCamera();
}
// map position address
window.addEventListener("hashchange", this.loadPageAddress);
this.events.addEventListener("bluemapCameraMoved", this.cameraMoved);
this.events.addEventListener("bluemapMapInteraction", this.mapInteraction);
// start app update loop
if(this.updateLoop) clearTimeout(this.updateLoop);
this.updateLoop = setTimeout(this.update, 1000);
// load user settings
await this.loadUserSettings();
// save user settings
this.saveUserSettings();
// load settings-scripts
if (this.settings.scripts) for (let scriptUrl of this.settings.scripts) {
let scriptElement = document.createElement("script");
scriptElement.src = scriptUrl;
document.body.appendChild(scriptElement);
}
}
update = async () => {
await this.followPlayerMarkerWorld();
this.updateLoop = setTimeout(this.update, 1000);
}
async followPlayerMarkerWorld() {
/** @type {PlayerLike} */
let player = this.mapViewer.controlsManager.controls?.data.followingPlayer;
if (this.mapViewer.map && player) {
if (player.foreign){
let matchingMap = await this.findPlayerMap(player.playerUuid)
if (matchingMap) {
this.mainMenu.closeAll();
await this.switchMap(matchingMap.data.id, false);
let playerMarker = this.playerMarkerManager.getPlayerMarker(player.playerUuid);
if (playerMarker && this.mapViewer.controlsManager.controls.followPlayerMarker)
this.mapViewer.controlsManager.controls.followPlayerMarker(playerMarker);
} else {
if (this.mapViewer.controlsManager.controls.stopFollowingPlayerMarker)
this.mapViewer.controlsManager.controls.stopFollowingPlayerMarker();
}
}
}
}
async findPlayerMap(playerUuid) {
/** @type BlueMapMap */
let matchingMap = null;
// search for the map that contains the player
if (this.maps.length < 20) {
for (let map of this.maps) {
let playerData = await this.loadPlayerData(map);
if (!Array.isArray(playerData.players)) continue;
for (let p of playerData.players) {
if (p.uuid === playerUuid && !p.foreign) {
matchingMap = map;
break;
}
}
if (matchingMap) break;
}
}
return matchingMap;
}
/**
* @param mapId {String}
* @param resetCamera {boolean}
* @returns {Promise<void>}
*/
async switchMap(mapId, resetCamera = true) {
let map = this.mapsMap.get(mapId);
if (!map) return Promise.reject(`There is no map with the id "${mapId}" loaded!`);
await this.mapViewer.switchMap(map)
if (resetCamera) this.resetCamera();
this.updatePageAddress();
await Promise.all([
this.initPlayerMarkerManager(),
this.initMarkerFileManager()
]);
}
resetCamera() {
let map = this.mapViewer.map;
let controls = this.mapViewer.controlsManager;
if (map) {
controls.position.set(map.data.startPos.x, 0, map.data.startPos.z);
controls.distance = 1500;
controls.angle = 0;
controls.rotation = 0;
controls.tilt = 0;
controls.ortho = 0;
}
controls.controls = this.mapControls;
this.appState.controls.state = "perspective";
this.updatePageAddress();
}
/**
* @returns Promise<BlueMapMap[]>
*/
async loadMaps() {
let settings = this.settings;
let maps = [];
// create maps
if (settings.maps !== undefined){
for (let mapId of settings.maps) {
let map = new BlueMapMap(mapId, this.dataUrl + mapId + "/", this.loadBlocker, this.mapViewer.events);
maps.push(map);
await map.loadSettings()
.catch(error => {
alert(this.events, `Failed to load settings for map '${map.data.id}':` + error, "warning");
});
}
}
// sort maps
maps.sort((map1, map2) => {
let sort = map1.data.sorting - map2.data.sorting;
if (isNaN(sort)) return 0;
return sort;
});
return maps;
}
async getSettings() {
if (!this.settings){
this.settings = await this.loadSettings();
}
return this.settings;
}
/**
* @returns {Promise<Object>}
*/
loadSettings() {
return new Promise((resolve, reject) => {
let loader = new FileLoader();
loader.setResponseType("json");
loader.load("settings.json?" + generateCacheHash(),
resolve,
() => {},
() => reject("Failed to load the settings.json!")
);
});
}
/**
* @param map {BlueMapMap}
* @returns {Promise<Object>}
*/
loadPlayerData(map) {
return new Promise((resolve, reject) => {
let loader = new FileLoader();
loader.setResponseType("json");
loader.load(map.data.dataUrl + "live/players?" + generateCacheHash(),
fileData => {
if (!fileData) reject(`Failed to parse '${this.fileUrl}'!`);
else resolve(fileData);
},
() => {},
() => reject(`Failed to load '${this.fileUrl}'!`)
)
});
}
initPlayerMarkerManager() {
if (this.playerMarkerManager){
this.playerMarkerManager.clear();
this.playerMarkerManager.dispose()
}
const map = this.mapViewer.map;
if (!map) return;
this.playerMarkerManager = new PlayerMarkerManager(this.mapViewer.markers, map.data.dataUrl + "live/players.json", map.data.dataUrl + "live/assets/playerheads/", this.events);
this.playerMarkerManager.setAutoUpdateInterval(0);
return this.playerMarkerManager.update()
.then(() => {
this.playerMarkerManager.setAutoUpdateInterval(1000);
})
.catch(e => {
alert(this.events, e, "warning");
this.playerMarkerManager.clear();
this.playerMarkerManager.dispose();
});
}
initMarkerFileManager() {
if (this.markerFileManager) {
this.markerFileManager.clear();
this.markerFileManager.dispose();
}
const map = this.mapViewer.map;
if (!map) return;
this.markerFileManager = new NormalMarkerManager(this.mapViewer.markers, map.data.dataUrl + "live/markers.json", this.events);
return this.markerFileManager.update()
.then(() => {
this.markerFileManager.setAutoUpdateInterval(1000 * 10);
})
.catch(e => {
alert(this.events, e, "warning");
this.markerFileManager.clear();
this.markerFileManager.dispose();
});
}
updateControlsSettings() {
let mouseInvert = this.appState.controls.invertMouse ? -1 : 1;
this.freeFlightControls.mouseRotate.speedCapture = -1.5 * this.appState.controls.mouseSensitivity;
this.freeFlightControls.mouseAngle.speedCapture = -1.5 * this.appState.controls.mouseSensitivity * mouseInvert;
this.freeFlightControls.mouseRotate.speedRight = -2 * this.appState.controls.mouseSensitivity;
this.freeFlightControls.mouseAngle.speedRight = -2 * this.appState.controls.mouseSensitivity * mouseInvert;
}
initGeneralEvents() {
//close menu on fullscreen
document.addEventListener("fullscreenchange", evt => {
if (document.fullscreen) {
this.mainMenu.closeAll();
}
});
}
setPerspectiveView(transition = 0, minDistance = 5) {
if (!this.mapViewer.map) return;
if (this.viewAnimation) this.viewAnimation.cancel();
let cm = this.mapViewer.controlsManager;
cm.controls = null;
let startDistance = cm.distance;
let targetDistance = Math.max(5, minDistance, startDistance);
let startY = cm.position.y;
let targetY = MathUtils.lerp(this.mapViewer.map.terrainHeightAt(cm.position.x, cm.position.z) + 3, 0, targetDistance / 500);
let startAngle = cm.angle;
let targetAngle = Math.min(Math.PI / 2, startAngle, this.mapControls.getMaxPerspectiveAngleForDistance(targetDistance));
let startOrtho = cm.ortho;
let startTilt = cm.tilt;
this.viewAnimation = animate(p => {
let ep = EasingFunctions.easeInOutQuad(p);
cm.position.y = MathUtils.lerp(startY, targetY, ep);
cm.distance = MathUtils.lerp(startDistance, targetDistance, ep);
cm.angle = MathUtils.lerp(startAngle, targetAngle, ep);
cm.ortho = MathUtils.lerp(startOrtho, 0, p);
cm.tilt = MathUtils.lerp(startTilt, 0, ep);
}, transition, finished => {
this.mapControls.reset();
if (finished){
cm.controls = this.mapControls;
this.updatePageAddress();
}
});
this.appState.controls.state = "perspective";
}
setFlatView(transition = 0, minDistance = 5) {
if (!this.mapViewer.map) return;
if (this.viewAnimation) this.viewAnimation.cancel();
let cm = this.mapViewer.controlsManager;
cm.controls = null;
let startDistance = cm.distance;
let targetDistance = Math.max(5, minDistance, startDistance);
let startRotation = cm.rotation;
let startAngle = cm.angle;
let startOrtho = cm.ortho;
let startTilt = cm.tilt;
this.viewAnimation = animate(p => {
let ep = EasingFunctions.easeInOutQuad(p);
cm.distance = MathUtils.lerp(startDistance, targetDistance, ep);
cm.rotation = MathUtils.lerp(startRotation, 0, ep);
cm.angle = MathUtils.lerp(startAngle, 0, ep);
cm.ortho = MathUtils.lerp(startOrtho, 1, p);
cm.tilt = MathUtils.lerp(startTilt, 0, ep);
}, transition, finished => {
this.mapControls.reset();
if (finished){
cm.controls = this.mapControls;
this.updatePageAddress();
}
});
this.appState.controls.state = "flat";
}
setFreeFlight(transition = 0, targetY = undefined) {
if (!this.mapViewer.map) return;
if (!this.settings.enableFreeFlight) return this.setPerspectiveView(transition);
if (this.viewAnimation) this.viewAnimation.cancel();
let cm = this.mapViewer.controlsManager;
cm.controls = null;
let startDistance = cm.distance;
let startY = cm.position.y;
if (!targetY) targetY = this.mapViewer.map.terrainHeightAt(cm.position.x, cm.position.z) + 3 || startY;
let startAngle = cm.angle;
let targetAngle = Math.PI / 2;
let startOrtho = cm.ortho;
let startTilt = cm.tilt;
this.viewAnimation = animate(p => {
let ep = EasingFunctions.easeInOutQuad(p);
cm.position.y = MathUtils.lerp(startY, targetY, ep);
cm.distance = MathUtils.lerp(startDistance, 0, ep);
cm.angle = MathUtils.lerp(startAngle, targetAngle, ep);
cm.ortho = MathUtils.lerp(startOrtho, 0, Math.min(p * 2, 1));
cm.tilt = MathUtils.lerp(startTilt, 0, ep);
}, transition, finished => {
if (finished){
cm.controls = this.freeFlightControls;
this.updatePageAddress();
}
});
this.appState.controls.state = "free";
}
setDebug(debug) {
this.appState.debug = debug;
if (debug){
this.mapViewer.stats.showPanel(0);
} else {
this.mapViewer.stats.showPanel(-1);
}
}
setTheme(theme) {
this.appState.theme = theme;
if (theme === "light") {
this.mapViewer.rootElement.classList.remove("theme-dark");
this.mapViewer.rootElement.classList.remove("theme-contrast");
this.mapViewer.rootElement.classList.add("theme-light");
}
else if (theme === "dark") {
this.mapViewer.rootElement.classList.remove("theme-light");
this.mapViewer.rootElement.classList.remove("theme-contrast");
this.mapViewer.rootElement.classList.add("theme-dark");
}
else if (theme === "contrast") {
this.mapViewer.rootElement.classList.remove("theme-light");
this.mapViewer.rootElement.classList.remove("theme-dark");
this.mapViewer.rootElement.classList.add("theme-contrast");
}
else {
this.mapViewer.rootElement.classList.remove("theme-light");
this.mapViewer.rootElement.classList.remove("theme-dark");
this.mapViewer.rootElement.classList.remove("theme-contrast");
}
}
setScreenshotClipboard(clipboard) {
this.appState.screenshot.clipboard = clipboard;
}
async updateMap() {
try {
this.mapViewer.clearTileCache();
if (this.mapViewer.map) {
await this.switchMap(this.mapViewer.map.data.id);
}
this.saveUserSettings();
} catch (e) {
alert(this.events, e, "error");
}
}
resetSettings() {
this.saveUserSetting("resetSettings", true);
location.reload();
}
async loadUserSettings(){
if (!isNaN(this.settings.resolutionDefault)) this.mapViewer.data.superSampling = this.settings.resolutionDefault;
if (!isNaN(this.settings.hiresSliderDefault)) this.mapViewer.data.loadedHiresViewDistance = this.settings.hiresSliderDefault;
if (!isNaN(this.settings.lowresSliderDefault)) this.mapViewer.data.loadedLowresViewDistance = this.settings.lowresSliderDefault;
if (!this.settings.useCookies) return;
if (this.loadUserSetting("resetSettings", false)) {
alert(this.events, "Settings reset!", "info");
this.saveUserSettings();
return;
}
this.mapViewer.clearTileCache(this.loadUserSetting("tileCacheHash", this.mapViewer.tileCacheHash));
this.mapViewer.superSampling = this.loadUserSetting("superSampling", this.mapViewer.data.superSampling);
this.mapViewer.data.loadedHiresViewDistance = this.loadUserSetting("hiresViewDistance", this.mapViewer.data.loadedHiresViewDistance);
this.mapViewer.data.loadedLowresViewDistance = this.loadUserSetting("lowresViewDistance", this.mapViewer.data.loadedLowresViewDistance);
this.mapViewer.updateLoadedMapArea();
this.appState.controls.mouseSensitivity = this.loadUserSetting("mouseSensitivity", this.appState.controls.mouseSensitivity);
this.appState.controls.invertMouse = this.loadUserSetting("invertMouse", this.appState.controls.invertMouse);
this.appState.controls.pauseTileLoading = this.loadUserSetting("pauseTileLoading", this.appState.controls.pauseTileLoading);
this.updateControlsSettings();
this.setTheme(this.loadUserSetting("theme", this.appState.theme));
this.setScreenshotClipboard(this.loadUserSetting("screenshotClipboard", this.appState.screenshot.clipboard));
await i18n.setLanguage(this.loadUserSetting("lang", i18n.locale));
this.setDebug(this.loadUserSetting("debug", this.appState.debug));
alert(this.events, "Settings loaded!", "info");
}
saveUserSettings() {
if (!this.settings.useCookies) return;
this.saveUserSetting("resetSettings", false);
this.saveUserSetting("tileCacheHash", this.mapViewer.tileCacheHash);
this.saveUserSetting("superSampling", this.mapViewer.data.superSampling);
this.saveUserSetting("hiresViewDistance", this.mapViewer.data.loadedHiresViewDistance);
this.saveUserSetting("lowresViewDistance", this.mapViewer.data.loadedLowresViewDistance);
this.saveUserSetting("mouseSensitivity", this.appState.controls.mouseSensitivity);
this.saveUserSetting("invertMouse", this.appState.controls.invertMouse);
this.saveUserSetting("pauseTileLoading", this.appState.controls.pauseTileLoading);
this.saveUserSetting("theme", this.appState.theme);
this.saveUserSetting("screenshotClipboard", this.appState.screenshot.clipboard);
this.saveUserSetting("lang", i18n.locale);
this.saveUserSetting("debug", this.appState.debug);
alert(this.events, "Settings saved!", "info");
}
loadUserSetting(key, defaultValue){
let value = getLocalStorage("bluemap-" + key);
if (value === undefined) return defaultValue;
return value;
}
saveUserSetting(key, value){
if (this.savedUserSettings.get(key) !== value){
this.savedUserSettings.set(key, value);
setLocalStorage("bluemap-" + key, value);
}
}
cameraMoved = () => {
if (this.hashUpdateTimeout) clearTimeout(this.hashUpdateTimeout);
this.hashUpdateTimeout = setTimeout(this.updatePageAddress, 1500);
this.lastCameraMove = Date.now();
}
loadBlocker = async () => {
if (!this.appState.controls.pauseTileLoading) return;
let timeToWait;
do {
let timeSinceLastMove = Date.now() - this.lastCameraMove;
timeToWait = 250 - timeSinceLastMove;
if (timeToWait > 0) await this.sleep(timeToWait);
} while (timeToWait > 0);
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
updatePageAddress = () => {
let hash = "#";
if (this.mapViewer.map) {
hash += this.mapViewer.map.data.id;
let controls = this.mapViewer.controlsManager;
hash += ":" + round(controls.position.x, 0);
hash += ":" + round(controls.position.y, 0);
hash += ":" + round(controls.position.z, 0);
hash += ":" + round(controls.distance, 0);
hash += ":" + round(controls.rotation, 2);
hash += ":" + round(controls.angle, 2);
hash += ":" + round(controls.tilt, 2);
hash += ":" + round(controls.ortho, 0);
hash += ":" + this.appState.controls.state;
}
history.replaceState(undefined, undefined, hash);
document.title = i18n.t("pageTitle", {
map: this.mapViewer.map ? this.mapViewer.map.data.name : "?",
version: this.settings.version
});
}
loadPageAddress = async () => {
let hash = window.location.hash?.substring(1) || this.settings.startLocation || "";
let values = hash.split(":");
if (values.length !== 10) return false;
let controls = this.mapViewer.controlsManager;
controls.controls = null;
if (!this.mapViewer.map || this.mapViewer.map.data.id !== values[0]) {
try {
await this.switchMap(values[0]);
} catch (e) {
return false;
}
}
controls.position.x = parseFloat(values[1]);
controls.position.y = parseFloat(values[2]);
controls.position.z = parseFloat(values[3]);
controls.distance = parseFloat(values[4]);
controls.rotation = parseFloat(values[5]);
controls.angle = parseFloat(values[6]);
controls.tilt = parseFloat(values[7]);
controls.ortho = parseFloat(values[8]);
switch (values[9]) {
case "flat" : this.setFlatView(0); break;
case "free" : this.setFreeFlight(0, controls.position.y); break;
default : this.setPerspectiveView(0); break;
}
return true;
}
mapInteraction = event => {
if (event.detail.data.doubleTap) {
let cm = this.mapViewer.controlsManager;
let pos = event.detail.hit?.point || event.detail.object?.getWorldPosition(new Vector3());
if (!pos) return;
let startDistance = cm.distance;
let targetDistance = Math.max(startDistance * 0.25, 5);
let startX = cm.position.x;
let targetX = pos.x;
let startZ = cm.position.z;
let targetZ = pos.z;
this.viewAnimation = animate(p => {
let ep = EasingFunctions.easeInOutQuad(p);
cm.distance = MathUtils.lerp(startDistance, targetDistance, ep);
cm.position.x = MathUtils.lerp(startX, targetX, ep);
cm.position.z = MathUtils.lerp(startZ, targetZ, ep);
}, 500);
}
}
takeScreenshot = () => {
let link = document.createElement("a");
link.download = "bluemap-screenshot.png";
link.href = this.mapViewer.renderer.domElement.toDataURL('image/png');
link.click();
if (this.appState.screenshot.clipboard) {
this.mapViewer.renderer.domElement.toBlob(blob => {
// eslint-disable-next-line no-undef
navigator.clipboard.write([new ClipboardItem({ ['image/png']: blob })]).catch(e => {
alert(this.events, "Failed to copy screenshot to clipboard: " + e, "error");
});
});
}
}
}

View File

@ -0,0 +1,89 @@
/*
* 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 i18n from "../i18n";
export class MainMenu {
static NULL_PAGE = {
id: "-",
title: "-"
}
constructor() {
this.isOpen = false;
this.pageStack = [];
}
currentPage() {
if (this.pageStack.length === 0) return MainMenu.NULL_PAGE;
return this.pageStack[this.pageStack.length - 1];
}
openPage(id = "root", title = () => i18n.t("menu.title"), data = {}) {
if (!this.isOpen){
this.pageStack.splice(0, this.pageStack.length);
this.isOpen = true;
}
if (typeof title === "function"){
this.pageStack.push({
id: id,
get title(){ return title() },
...data
});
} else {
this.pageStack.push({
id: id,
title: title,
...data
});
}
}
closePage() {
this.pageStack.splice(this.pageStack.length - 1, 1);
if (this.pageStack.length < 1) {
this.isOpen = false
}
}
reOpenPage() {
if (this.pageStack.length === 0){
this.openPage();
} else if (this.pageStack[0].id !== 'root') {
this.pageStack.splice(0, this.pageStack.length);
this.openPage();
} else {
this.isOpen = true;
}
}
closeAll() {
this.isOpen = false;
}
}

View File

@ -0,0 +1,242 @@
/*
* 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 {Marker} from "bluemap/src/markers/Marker";
import {CSS2DObject} from "bluemap/src/util/CSS2DRenderer";
import {animate, htmlToElement} from "bluemap/src/util/Utils";
import {BoxGeometry, MeshBasicMaterial, Mesh, Vector2} from "three";
import i18n from "../i18n";
export class PopupMarker extends Marker {
constructor(id, appState, events) {
super(id);
this.data.type = "popup";
this.data.label = "Last Map Interaction";
this.appState = appState;
this.events = events;
this.visible = false;
this.elementObject = new CSS2DObject(htmlToElement(`<div id="bm-marker-${this.data.id}" class="bm-marker-${this.data.type}">Test</div>`));
this.elementObject.position.set(0.5, 1, 0.5);
this.addEventListener( 'removed', () => {
if (this.element.parentNode) this.element.parentNode.removeChild(this.element);
});
let cubeGeo = new BoxGeometry(1.01, 1.01, 1.01).translate(0.5, 0.5, 0.5);
let cubeMaterial = new MeshBasicMaterial( {color: 0xffffff, opacity: 0.5, transparent: true} );
this.cube = new Mesh(cubeGeo, cubeMaterial);
this.cube.onClick = evt => this.onClick(evt);
this.add(this.elementObject);
this.add(this.cube);
this.animation = null;
this.events.addEventListener('bluemapMapInteraction', this.onMapInteraction);
window.addEventListener("mousedown", this.removeHandler);
window.addEventListener("touchstart", this.removeHandler);
window.addEventListener("keydown", this.removeHandler);
window.addEventListener("mousewheel", this.removeHandler);
}
onClick(event) {
return true;
}
onMapInteraction = evt => {
let isHires = true;
let int = evt.detail.hiresHit;
if (evt.detail.lowresHits) {
for (let i = 0; i < evt.detail.lowresHits.length; i++) {
if (!int) {
isHires = false;
int = evt.detail.lowresHits[i];
} else break;
}
}
if (!int) return;
this.position
.copy(int.pointOnLine || int.point)
.add(evt.detail.ray.direction.clone().multiplyScalar(0.05))
.floor();
//this.elementObject.position
//.copy(evt.detail.intersection.pointOnLine || evt.detail.intersection.point)
//.sub(this.position);
if (isHires) {
this.element.innerHTML = `
<div class="group">
<div class="label">${i18n.t("blockTooltip.block")}:</div>
<div class="content">
<div class="entry"><span class="label">x: </span><span class="value">${this.position.x}</span></div>
<div class="entry"><span class="label">y: </span><span class="value">${this.position.y}</span></div>
<div class="entry"><span class="label">z: </span><span class="value">${this.position.z}</span></div>
</div>
</div>
`;
} else {
this.element.innerHTML = `
<div class="group">
<div class="label">${i18n.t("blockTooltip.position")}:</div>
<div class="content">
<div class="entry"><span class="label">x: </span><span class="value">${this.position.x}</span></div>
<div class="entry"><span class="label">z: </span><span class="value">${this.position.z}</span></div>
</div>
</div>
`;
}
if (this.appState.debug) {
let chunkCoords = this.position.clone().divideScalar(16).floor();
let regionCoords = new Vector2(this.position.x, this.position.z).divideScalar(512).floor();
let regionFile = `r.${regionCoords.x}.${regionCoords.y}.mca`;
this.element.innerHTML += `
<hr>
<div class="group">
<div class="label">${i18n.t("blockTooltip.chunk")}:</div>
<div class="content">
<div class="entry"><span class="label">x: </span><span class="value">${chunkCoords.x}</span></div>
<div class="entry"><span class="label">y: </span><span class="value">${chunkCoords.y}</span></div>
<div class="entry"><span class="label">z: </span><span class="value">${chunkCoords.z}</span></div>
</div>
</div>
<hr>
<div class="group">
<div class="label">${i18n.t("blockTooltip.region.region")}:</div>
<div class="content">
<div class="entry"><span class="label">x: </span><span class="value">${regionCoords.x}</span></div>
<div class="entry"><span class="label">z: </span><span class="value">${regionCoords.y}</span></div>
</div>
<div class="content">
<div class="entry"><span class="label">${i18n.t("blockTooltip.region.file")}: </span><span class="value">${regionFile}</span></div>
</div>
</div>
`;
}
if (this.appState.debug) {
let faceIndex = int.faceIndex;
let attributes = int.object.geometry.attributes;
if (attributes.sunlight && attributes.blocklight) {
let sunlight = attributes.sunlight.array[faceIndex * 3];
let blocklight = attributes.blocklight.array[faceIndex * 3];
this.element.innerHTML += `
<hr>
<div class="group">
<div class="label">${i18n.t("blockTooltip.light.light")}:</div>
<div class="content">
<div class="entry"><span class="label">${i18n.t("blockTooltip.light.sun")}: </span><span class="value">${sunlight}</span></div>
<div class="entry"><span class="label">${i18n.t("blockTooltip.light.block")}: </span><span class="value">${blocklight}</span></div>
</div>
</div>
`;
}
}
if (this.appState.debug) {
let info = "";
if (isHires) {
let hrPath = evt.detail.hiresHit?.object?.userData?.tileUrl;
info += `<div>${hrPath}</div>`;
}
if (evt.detail.lowresHits) {
for (let i = 0; i < evt.detail.lowresHits.length; i++) {
let lrPath = evt.detail.lowresHits[i]?.object?.userData?.tileUrl;
if (lrPath) info += `<div>${lrPath}</div>`;
}
}
this.element.innerHTML += `
<hr>
<div class="files">
${info}
</div>
`;
}
if (this.appState.debug){
console.debug("Clicked Position Data:", evt.detail);
}
this.open();
};
open() {
if (this.animation) this.animation.cancel();
this.visible = true;
this.cube.visible = true;
let targetOpacity = 1;
this.element.style.opacity = "0";
this.animation = animate(progress => {
this.element.style.opacity = (progress * targetOpacity).toString();
}, 300);
}
removeHandler = evt => {
if (evt.composedPath().includes(this.element)) return;
this.close();
}
close() {
if (this.animation) this.animation.cancel();
this.cube.visible = false;
let startOpacity = parseFloat(this.element.style.opacity);
this.animation = animate(progress => {
this.element.style.opacity = (startOpacity - progress * startOpacity).toString();
}, 300, finished => {
if (finished) this.visible = false;
});
}
/**
* @returns {Element}
*/
get element() {
return this.elementObject.element.getElementsByTagName("div")[0];
}
dispose() {
super.dispose();
if (this.element.parentNode) this.element.parentNode.removeChild(this.element);
}
}

View File

@ -0,0 +1,30 @@
/**
* Converts a given value to JSON and writes it to the given key in
* localStorage.
*/
export const setLocalStorage = (key, value) => {
localStorage.setItem(key, JSON.stringify(value));
};
/**
* Fetches the value from a given key from localStorage. If the stored value is
* in JSON format, the parsed value will be returned.
*/
export const getLocalStorage = key => {
const value = localStorage.getItem(key);
// return undefined for not defined values
// because "null" might be ambiguous if there is actually "null" stored for that key
if (value == null) return undefined;
try {
return JSON.parse(value);
} catch(e) {
return value;
}
};
export const round = (value, precision) => {
let f = Math.pow(10, precision);
return Math.round(value * f) / f;
}

View File

@ -0,0 +1,72 @@
/*
* 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 Vue from 'vue'
import App from './App.vue'
import {BlueMapApp} from "@/js/BlueMapApp";
import i18n from './i18n';
// utils
String.prototype.includesCI = function (val) {
return this.toLowerCase().includes(val.toLowerCase());
}
// bluemap app
try {
const bluemap = new BlueMapApp(document.getElementById("map-container"));
window.bluemap = bluemap;
// init vue
Vue.config.productionTip = false;
Object.defineProperty(Vue.prototype, '$bluemap', {
get() {
return bluemap;
}
});
const vue = new Vue({
i18n,
render: h => h(App)
}).$mount('#app');
// load languages
i18n.loadLanguageSettings().catch(error => console.error(error));
// load bluemap next tick (to let the assets load first)
vue.$nextTick(() => {
bluemap.load().catch(error => console.error(error));
});
} catch (e) {
console.error("Failed to load BlueMap webapp!", e);
document.body.innerHTML = `
<div id="bm-app-err">
<div>
<img src="assets/logo.png" alt="bluemap logo">
<div class="bm-app-err-main">Failed to load BlueMap webapp!</div>
<div class="bm-app-err-hint">Make sure you have <a href="https://get.webgl.org/">WebGL</a> enabled on your browser.</div>
</div>
</div>
`;
}

View File

@ -0,0 +1,189 @@
/*
* 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.
*/
@font-face {
font-family: 'Quicksand';
font-style: normal;
font-display: swap;
font-weight: 100 900;
src: local("Quicksand"), url("./fonts/Quicksand.ttf") format('truetype-variations');
}
@import "variables.scss";
// ### global rules ###
:root {
line-height: 1rem;
@include dark-theme;
.theme-light {
@include light-theme;
}
.theme-contrast {
@include contrast-theme;
}
}
@media (prefers-color-scheme: light) {
:root {
@include light-theme;
.theme-dark {
@include dark-theme;
}
}
}
body {
margin: 0;
padding: 0;
overscroll-behavior: none;
overflow: hidden;
}
h1, h2, h3, h4, h5, h6 {
font-weight: inherit;
font-size: inherit;
text-align: left;
margin: 1em 0 0.5em 0;
padding: 0;
}
h1, h2 {
position: relative;
font-size: 1.2em;
margin-left: 0;
margin-right: 0;
padding-left: 0.5em;
padding-bottom: 0.5em;
width: calc(100% - 0.5em);
overflow: hidden;
&:after {
position: absolute;
left: 0;
bottom: 0;
content: '';
width: 100%;
height: 1px;
background-color: var(--theme-bg-light);
}
}
h1 {
width: 100%;
text-align: center;
padding-left: 0;
}
p {
margin: 0.5em;
padding: 0;
}
a {
color: inherit;
text-decoration: underline;
}
kbd {
background-color: var(--theme-bg-light);
border-radius: 0.2em;
margin: 0;
padding: 0 0.2em;
}
// normalize input fields
input {
display: inline-block;
box-sizing: content-box;
border: none;
outline: none;
margin: 0;
padding: 0;
font: inherit;
color: inherit;
}
// scrollbar
::-webkit-scrollbar {
width: 0.5em;
}
::-webkit-scrollbar-track {
background: var(--theme-bg);
}
::-webkit-scrollbar-thumb {
background: var(--theme-bg-light);
border-radius: 0.5em;
border: solid var(--theme-bg) 0.1em;
}
::-webkit-scrollbar-thumb:hover {
background: var(--theme-fg-light);
}
//app-error
#bm-app-err {
position: relative;
width: 100vw;
height: 100vh;
background-color: var(--theme-bg);
color: var(--theme-fg);
> div {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
img {
max-width: 10em;
min-width: 5em;
width: 90%;
border-radius: 50%;
margin: 0 0 3em 0;
}
.bm-app-err-hint {
color: var(--theme-fg-light);
}
}
}
@import "markers.scss";

View File

@ -0,0 +1,157 @@
/*
* 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.
*/
#map-container {
.bm-marker-html {
position: relative;
.bm-marker-poi-label {
position: absolute;
top: 0;
left: 0;
opacity: 0;
transition: opacity 0.3s;
}
.bm-marker-poi-icon {
opacity: 1;
transition: opacity 0.3s;
filter: drop-shadow(1px 1px 3px #0008);
}
&.bm-marker-highlight {
.bm-marker-poi-label {
opacity: 1;
}
.bm-marker-poi-icon {
opacity: 0;
}
}
}
.bm-marker-html .bm-marker-poi-label,
.bm-marker-labelpopup,
.bm-marker-popup {
transform: translate(-50%, -100%) translate(0, -0.5em);
max-width: 15em;
color: var(--theme-fg);
background-color: var(--theme-bg);
filter: drop-shadow(1px 1px 3px #0008);
padding: 0.5em;
> hr {
border: none;
border-bottom: solid 1px var(--theme-bg-light);
margin: 0.5em -0.5em;
}
&:after {
position: absolute;
bottom: calc(-1em + 1px);
left: 50%;
transform: translate(-50%, 0);
content: '';
border: solid 0.5em transparent;
border-top-color: var(--theme-bg);
}
}
.bm-marker-popup {
line-height: 1.2em;
.group {
> .label {
position: relative;
top: 0;
left: 0.5em;
margin: 0 0.5em;
font-size: 0.8em;
color: var(--theme-fg-light);
}
> .content {
display: flex;
justify-content: center;
> .entry {
margin: 0 0.5em;
> .label {
color: var(--theme-fg-light);
}
}
}
}
.files {
font-size: 0.8em;
color: var(--theme-fg-light);
}
}
.bm-marker-player {
position: relative;
transform: translate(-50%, -50%);
filter: drop-shadow(1px 1px 3px #0008);
img {
width: 32px;
image-rendering: pixelated;
transition: width 0.3s;
}
.bm-player-name {
position: absolute;
top: -0.5em;
left: 50%;
transform: translate(-50%, -100%);
padding: 0.25em;
background-color: #0008;
color: #fff;
transition: opacity 0.3s;
}
&[distance-data="med"],
&[distance-data="far"] {
img {
width: 16px;
}
.bm-player-name {
opacity: 0;
}
}
}
}

View File

@ -0,0 +1,91 @@
/*
* 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.
*/
// responsive breaks
$mobile-break: 575.98px;
// themes
@mixin dark-theme {
font-family: 'Quicksand', sans-serif;
font-size: 16px;
font-weight: 400;
--theme-bg: #181818;
--theme-bg-hover: #222;
--theme-bg-light: #444;
--theme-fg: #fff;
--theme-fg-light: #aaa;
//SwitchButton
--theme-switch-button-on: #00489d;
//DayNightSwitch
--theme-stars-day: #fff;
--theme-moon-day: #ff0;
--theme-stars-night: #444;
--theme-moon-night: #000;
}
@mixin light-theme {
font-family: 'Quicksand', sans-serif;
font-size: 16px;
font-weight: 500;
--theme-bg: #eee;
--theme-bg-hover: #ddd;
--theme-bg-light: #999;
--theme-fg: #000;
--theme-fg-light: #333;
//SwitchButton
--theme-switch-button-on: #6593dc;
//DayNightSwitch
--theme-stars-day: #444;
--theme-moon-day: #000;
--theme-stars-night: #fff;
--theme-moon-night: #ff0;
}
@mixin contrast-theme {
font-family: 'Quicksand', sans-serif;
font-size: 16px;
font-weight: 400;
--theme-bg: #000;
--theme-bg-hover: #222;
--theme-bg-light: #666;
--theme-fg: #fff;
--theme-fg-light: #aaa;
//SwitchButton
--theme-switch-button-on: #006fff;
//DayNightSwitch
--theme-stars-day: #fff;
--theme-moon-day: #ff0;
--theme-stars-night: #444;
--theme-moon-night: #000;
}

View File

@ -0,0 +1,20 @@
/**
* @type {import('@vue/cli-service').ProjectOptions}
*/
module.exports = {
publicPath: './',
devServer: {
proxy: {
'/settings.json': {
//target: 'http://localhost:8100',
target: 'https://bluecolored.de/bluemap',
changeOrigin: true,
},
'/maps': {
//target: 'http://localhost:8100',
target: 'https://bluecolored.de/bluemap',
changeOrigin: true,
}
}
}
}