export Util functions separately
This commit is contained in:
parent
f7b3c4d551
commit
df487ec364
@ -27,7 +27,7 @@ import Sidebar from './components/Sidebar.vue';
|
||||
import ChatBox from './components/ChatBox.vue';
|
||||
import {useStore} from "./store";
|
||||
import {ActionTypes} from "@/store/action-types";
|
||||
import Util from '@/util';
|
||||
import {parseUrl} from '@/util';
|
||||
import {MutationTypes} from "@/store/mutation-types";
|
||||
|
||||
export default defineComponent({
|
||||
@ -85,8 +85,8 @@ export default defineComponent({
|
||||
updateTimeout.value = 0;
|
||||
},
|
||||
|
||||
parseUrl = () => {
|
||||
const parsedUrl = Util.parseUrl();
|
||||
handleUrl = () => {
|
||||
const parsedUrl = parseUrl();
|
||||
|
||||
if(parsedUrl) {
|
||||
//Remove legacy url if one was parsed
|
||||
@ -115,7 +115,7 @@ export default defineComponent({
|
||||
onMounted(() => loadConfiguration());
|
||||
onBeforeUnmount(() => stopUpdates());
|
||||
|
||||
parseUrl();
|
||||
handleUrl();
|
||||
onResize();
|
||||
|
||||
onMounted(() => window.addEventListener('resize', onResize));
|
||||
|
@ -25,7 +25,7 @@
|
||||
<script lang="ts">
|
||||
import {defineComponent, ref, onMounted, computed} from "@vue/runtime-core";
|
||||
import {DynmapChat} from "@/dynmap";
|
||||
import Util from '@/util';
|
||||
import {getMinecraftHead} from '@/util';
|
||||
import {useStore} from "@/store";
|
||||
|
||||
const defaultImage = require('@/assets/images/player_face.png');
|
||||
@ -65,7 +65,7 @@
|
||||
|
||||
onMounted(() => {
|
||||
if(showFace.value) {
|
||||
Util.getMinecraftHead(props.message.playerAccount as string, '16')
|
||||
getMinecraftHead(props.message.playerAccount as string, '16')
|
||||
.then((result) => image.value = result.src).catch(() => {});
|
||||
}
|
||||
});
|
||||
|
@ -20,7 +20,7 @@ import {useStore} from "@/store";
|
||||
import {DynmapArea, DynmapMarkerSet} from "@/dynmap";
|
||||
import {ActionTypes} from "@/store/action-types";
|
||||
import {createArea, updateArea} from "@/util/areas";
|
||||
import Util from '@/util';
|
||||
import {getPointConverter} from '@/util';
|
||||
import DynmapLayerGroup from "@/leaflet/layer/DynmapLayerGroup";
|
||||
import DynmapPolygon from "@/leaflet/vector/DynmapPolygon";
|
||||
import DynmapPolyline from "@/leaflet/vector/DynmapPolyline";
|
||||
@ -50,7 +50,7 @@ export default defineComponent({
|
||||
layers = Object.freeze(new Map()) as Map<string, DynmapPolygon | DynmapPolyline>,
|
||||
|
||||
createAreas = () => {
|
||||
const converter = Util.getPointConverter();
|
||||
const converter = getPointConverter();
|
||||
|
||||
props.set.areas.forEach((area: DynmapArea, id: string) => {
|
||||
const layer = createArea(area, converter);
|
||||
@ -76,7 +76,7 @@ export default defineComponent({
|
||||
markerSet: props.set.id,
|
||||
amount: 10,
|
||||
}).then(updates => {
|
||||
const converter = Util.getPointConverter();
|
||||
const converter = getPointConverter();
|
||||
|
||||
for(const update of updates) {
|
||||
if(update.removed) {
|
||||
@ -103,7 +103,7 @@ export default defineComponent({
|
||||
|
||||
//FIXME: Prevent unnecessary repositioning when changing worlds
|
||||
watch(currentProjection, () => {
|
||||
const converter = Util.getPointConverter();
|
||||
const converter = getPointConverter();
|
||||
|
||||
for (const [id, area] of props.set.areas) {
|
||||
updateArea(layers.get(id), area, converter);
|
||||
|
@ -20,7 +20,7 @@ import {useStore} from "@/store";
|
||||
import {DynmapCircle, DynmapMarkerSet} from "@/dynmap";
|
||||
import {ActionTypes} from "@/store/action-types";
|
||||
import {createCircle, updateCircle} from "@/util/circles";
|
||||
import Util from '@/util';
|
||||
import {getPointConverter} from '@/util';
|
||||
import DynmapPolyline from "@/leaflet/vector/DynmapPolyline";
|
||||
import DynmapPolygon from "@/leaflet/vector/DynmapPolygon";
|
||||
import DynmapLayerGroup from "@/leaflet/layer/DynmapLayerGroup";
|
||||
@ -50,7 +50,7 @@ export default defineComponent({
|
||||
layers = Object.freeze(new Map<string, DynmapPolyline | DynmapPolygon>()),
|
||||
|
||||
createCircles = () => {
|
||||
const converter = Util.getPointConverter();
|
||||
const converter = getPointConverter();
|
||||
|
||||
props.set.circles.forEach((circle: DynmapCircle, id: string) => {
|
||||
const layer = createCircle(circle, converter);
|
||||
@ -76,7 +76,7 @@ export default defineComponent({
|
||||
markerSet: props.set.id,
|
||||
amount: 10,
|
||||
}).then(updates => {
|
||||
const converter = Util.getPointConverter();
|
||||
const converter = getPointConverter();
|
||||
|
||||
for(const update of updates) {
|
||||
if(update.removed) {
|
||||
@ -103,7 +103,7 @@ export default defineComponent({
|
||||
|
||||
//FIXME: Prevent unnecessary repositioning when changing worlds
|
||||
watch(currentProjection, () => {
|
||||
const converter = Util.getPointConverter();
|
||||
const converter = getPointConverter();
|
||||
|
||||
for (const [id, circle] of props.set.circles) {
|
||||
updateCircle(layers.get(id), circle, converter);
|
||||
|
@ -20,7 +20,7 @@ import {useStore} from "@/store";
|
||||
import {DynmapLine, DynmapMarkerSet} from "@/dynmap";
|
||||
import {ActionTypes} from "@/store/action-types";
|
||||
import {createLine, updateLine} from "@/util/lines";
|
||||
import Util from '@/util';
|
||||
import {getPointConverter} from '@/util';
|
||||
import DynmapPolyline from "@/leaflet/vector/DynmapPolyline";
|
||||
import DynmapLayerGroup from "@/leaflet/layer/DynmapLayerGroup";
|
||||
|
||||
@ -49,7 +49,7 @@ export default defineComponent({
|
||||
layers = Object.freeze(new Map<string, DynmapPolyline>()),
|
||||
|
||||
createLines = () => {
|
||||
const converter = Util.getPointConverter();
|
||||
const converter = getPointConverter();
|
||||
|
||||
props.set.lines.forEach((line: DynmapLine, id: string) => {
|
||||
const layer = createLine(line, converter);
|
||||
@ -75,7 +75,7 @@ export default defineComponent({
|
||||
markerSet: props.set.id,
|
||||
amount: 10,
|
||||
}).then(updates => {
|
||||
const converter = Util.getPointConverter();
|
||||
const converter = getPointConverter();
|
||||
|
||||
for(const update of updates) {
|
||||
if(update.removed) {
|
||||
@ -102,7 +102,7 @@ export default defineComponent({
|
||||
|
||||
//FIXME: Prevent unnecessary repositioning when changing worlds
|
||||
watch(currentProjection, () => {
|
||||
const converter = Util.getPointConverter();
|
||||
const converter = getPointConverter();
|
||||
|
||||
for (const [id, line] of props.set.lines) {
|
||||
updateLine(layers.get(id), line, converter);
|
||||
|
@ -36,7 +36,7 @@ import {DynmapPlayer} from "@/dynmap";
|
||||
import {useStore} from "@/store";
|
||||
import {MutationTypes} from "@/store/mutation-types";
|
||||
import {defineComponent, onMounted, ref, watch} from "@vue/runtime-core";
|
||||
import Util from '@/util';
|
||||
import {getMinecraftHead} from '@/util';
|
||||
|
||||
const defaultImage = require('@/assets/images/player_face.png');
|
||||
|
||||
@ -67,7 +67,7 @@ export default defineComponent({
|
||||
image.value = defaultImage;
|
||||
|
||||
if(store.state.components.playerMarkers && store.state.components.playerMarkers.showSkinFaces) {
|
||||
Util.getMinecraftHead(props.target, '16').then((result) => image.value = result.src).catch(() => {});
|
||||
getMinecraftHead(props.target, '16').then((result) => image.value = result.src).catch(() => {});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -30,7 +30,7 @@ import {defineComponent, computed, ref, onMounted} from 'vue';
|
||||
import {DynmapPlayer} from "@/dynmap";
|
||||
import {useStore} from "@/store";
|
||||
import {MutationTypes} from "@/store/mutation-types";
|
||||
import Util from '@/util';
|
||||
import {getMinecraftHead} from '@/util';
|
||||
|
||||
const defaultImage = require('@/assets/images/player_face.png');
|
||||
|
||||
@ -86,7 +86,7 @@ export default defineComponent({
|
||||
|
||||
onMounted(() => {
|
||||
if(store.state.components.playerMarkers && store.state.components.playerMarkers.showSkinFaces) {
|
||||
Util.getMinecraftHead(props.player, '16').then((result) => image.value = result.src).catch(() => {});
|
||||
getMinecraftHead(props.player, '16').then((result) => image.value = result.src).catch(() => {});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
import {ControlOptions, DomUtil, Util, Map, Control} from 'leaflet';
|
||||
import Utils from '@/util';
|
||||
import {getMinecraftTime} from '@/util';
|
||||
import {DynmapWorldState} from "@/dynmap";
|
||||
|
||||
import sun from '@/assets/icons/clock_sun.svg';
|
||||
@ -120,7 +120,7 @@ export class ClockControl extends Control {
|
||||
this._moon!.style.transform = 'translate(-150px, -150px)';
|
||||
}
|
||||
|
||||
const minecraftTime = Utils.getMinecraftTime(timeOfDay);
|
||||
const minecraftTime = getMinecraftTime(timeOfDay);
|
||||
|
||||
if (this.options.showDigitalClock) {
|
||||
if (timeOfDay >= 0) {
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
import {MarkerOptions, DivIcon, DomUtil} from 'leaflet';
|
||||
import {DynmapPlayer} from "@/dynmap";
|
||||
import Util from '@/util';
|
||||
import {getMinecraftHead} from '@/util';
|
||||
|
||||
const playerImage = require('@/assets/images/player_face.png');
|
||||
|
||||
@ -107,7 +107,7 @@ export class PlayerIcon extends DivIcon {
|
||||
offset = 16;
|
||||
}
|
||||
|
||||
Util.getMinecraftHead(player, size).then(head => {
|
||||
getMinecraftHead(player, size).then(head => {
|
||||
this._playerImage!.src = head.src;
|
||||
}).catch(() => {});
|
||||
} else {
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
import {GetterTree} from "vuex";
|
||||
import {State} from "@/store/state";
|
||||
import Util from "@/util";
|
||||
import {getMinecraftTime} from "@/util";
|
||||
|
||||
export type Getters = {
|
||||
playerMarkersEnabled(state: State): boolean;
|
||||
@ -41,7 +41,7 @@ export const getters: GetterTree<State, State> & Getters = {
|
||||
},
|
||||
|
||||
night(state: State): boolean {
|
||||
return Util.getMinecraftTime(state.currentWorldState.timeOfDay).night;
|
||||
return getMinecraftTime(state.currentWorldState.timeOfDay).night;
|
||||
},
|
||||
|
||||
mapBackground(state: State): string {
|
||||
@ -50,7 +50,7 @@ export const getters: GetterTree<State, State> & Getters = {
|
||||
}
|
||||
|
||||
if(state.currentMap.nightAndDay) {
|
||||
if(Util.getMinecraftTime(state.currentWorldState.timeOfDay).night) {
|
||||
if(getMinecraftTime(state.currentWorldState.timeOfDay).night) {
|
||||
return state.currentMap.backgroundNight || state.currentMap.background || 'transparent';
|
||||
}
|
||||
|
||||
|
274
src/util.ts
274
src/util.ts
@ -20,154 +20,152 @@ import {useStore} from "@/store";
|
||||
const headCache = new Map<string, HTMLImageElement>(),
|
||||
headUnresolvedCache = new Map<string, Promise<HTMLImageElement>>();
|
||||
|
||||
export default {
|
||||
getMinecraftTime(serverTime: number) {
|
||||
const day = serverTime >= 0 && serverTime < 13700;
|
||||
export const getMinecraftTime = (serverTime: number) => {
|
||||
const day = serverTime >= 0 && serverTime < 13700;
|
||||
|
||||
return {
|
||||
serverTime: serverTime,
|
||||
days: Math.floor((serverTime + 8000) / 24000),
|
||||
return {
|
||||
serverTime: serverTime,
|
||||
days: Math.floor((serverTime + 8000) / 24000),
|
||||
|
||||
// Assuming it is day at 6:00
|
||||
hours: (Math.floor(serverTime / 1000) + 6) % 24,
|
||||
minutes: Math.floor(((serverTime / 1000) % 1) * 60),
|
||||
seconds: Math.floor(((((serverTime / 1000) % 1) * 60) % 1) * 60),
|
||||
// Assuming it is day at 6:00
|
||||
hours: (Math.floor(serverTime / 1000) + 6) % 24,
|
||||
minutes: Math.floor(((serverTime / 1000) % 1) * 60),
|
||||
seconds: Math.floor(((((serverTime / 1000) % 1) * 60) % 1) * 60),
|
||||
|
||||
day: day,
|
||||
night: !day
|
||||
day: day,
|
||||
night: !day
|
||||
};
|
||||
}
|
||||
|
||||
export const getMinecraftHead = (player: DynmapPlayer | string, size: string): Promise<HTMLImageElement> => {
|
||||
const account = typeof player === 'string' ? player : player.account,
|
||||
cacheKey = `${account}-${size}`;
|
||||
|
||||
if(headCache.has(cacheKey)) {
|
||||
return Promise.resolve(headCache.get(cacheKey) as HTMLImageElement);
|
||||
}
|
||||
|
||||
if(headUnresolvedCache.has(cacheKey)) {
|
||||
return headUnresolvedCache.get(cacheKey) as Promise<HTMLImageElement>;
|
||||
}
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const faceImage = new Image();
|
||||
|
||||
faceImage.onload = function() {
|
||||
headCache.set(cacheKey, faceImage);
|
||||
resolve(faceImage);
|
||||
};
|
||||
},
|
||||
|
||||
getMinecraftHead(player: DynmapPlayer | string, size: string): Promise<HTMLImageElement> {
|
||||
const account = typeof player === 'string' ? player : player.account,
|
||||
cacheKey = `${account}-${size}`;
|
||||
|
||||
if(headCache.has(cacheKey)) {
|
||||
return Promise.resolve(headCache.get(cacheKey) as HTMLImageElement);
|
||||
}
|
||||
|
||||
if(headUnresolvedCache.has(cacheKey)) {
|
||||
return headUnresolvedCache.get(cacheKey) as Promise<HTMLImageElement>;
|
||||
}
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const faceImage = new Image();
|
||||
|
||||
faceImage.onload = function() {
|
||||
headCache.set(cacheKey, faceImage);
|
||||
resolve(faceImage);
|
||||
};
|
||||
|
||||
faceImage.onerror = function(e) {
|
||||
console.warn(`Failed to retrieve face of ${account} with size ${size}!`);
|
||||
reject(e);
|
||||
};
|
||||
|
||||
const src = (size === 'body') ? `faces/body/${account}.png` :`faces/${size}x${size}/${account}.png`;
|
||||
faceImage.src = this.concatURL(window.config.url.markers, src);
|
||||
}).finally(() => headUnresolvedCache.delete(cacheKey)) as Promise<HTMLImageElement>;
|
||||
|
||||
headUnresolvedCache.set(cacheKey, promise);
|
||||
|
||||
return promise;
|
||||
},
|
||||
|
||||
concatURL(base: string, addition: string) {
|
||||
if(base.indexOf('?') >= 0) {
|
||||
return base + escape(addition);
|
||||
}
|
||||
|
||||
return base + addition;
|
||||
},
|
||||
|
||||
getPointConverter() {
|
||||
const projection = useStore().state.currentProjection;
|
||||
|
||||
return (x: number, y: number, z: number) => {
|
||||
return projection.locationToLatLng({x, y, z});
|
||||
faceImage.onerror = function(e) {
|
||||
console.warn(`Failed to retrieve face of ${account} with size ${size}!`);
|
||||
reject(e);
|
||||
};
|
||||
},
|
||||
|
||||
parseUrl() {
|
||||
const query = new URLSearchParams(window.location.search),
|
||||
hash = window.location.hash.replace('#', '');
|
||||
const src = (size === 'body') ? `faces/body/${account}.png` :`faces/${size}x${size}/${account}.png`;
|
||||
faceImage.src = concatURL(window.config.url.markers, src);
|
||||
}).finally(() => headUnresolvedCache.delete(cacheKey)) as Promise<HTMLImageElement>;
|
||||
|
||||
if(hash) {
|
||||
try {
|
||||
return this.parseMapHash(hash);
|
||||
} catch (e) {
|
||||
console.warn('Ignoring invalid url ' + e);
|
||||
}
|
||||
}
|
||||
headUnresolvedCache.set(cacheKey, promise);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
export const concatURL = (base: string, addition: string) => {
|
||||
if(base.indexOf('?') >= 0) {
|
||||
return base + escape(addition);
|
||||
}
|
||||
|
||||
return base + addition;
|
||||
}
|
||||
|
||||
export const getPointConverter = () => {
|
||||
const projection = useStore().state.currentProjection;
|
||||
|
||||
return (x: number, y: number, z: number) => {
|
||||
return projection.locationToLatLng({x, y, z});
|
||||
};
|
||||
}
|
||||
|
||||
export const parseUrl = () => {
|
||||
const query = new URLSearchParams(window.location.search),
|
||||
hash = window.location.hash.replace('#', '');
|
||||
|
||||
if(hash) {
|
||||
try {
|
||||
return this.parseMapSearchParams(query);
|
||||
} catch(e) {
|
||||
console.warn('Ignoring invalid legacy url ' + e);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
parseMapHash(hash: string) {
|
||||
const parts = hash.replace('#', '').split(';');
|
||||
|
||||
const world = parts[0] || undefined,
|
||||
map = parts[1] || undefined,
|
||||
location = (parts[2] || '').split(',')
|
||||
.map(item => parseFloat(item))
|
||||
.filter(item => !isNaN(item) && isFinite(item)),
|
||||
zoom = typeof parts[3] !== 'undefined' ? parseInt(parts[3]) : undefined;
|
||||
|
||||
if(location.length && location.length !== 3) {
|
||||
throw new TypeError('Location should contain exactly 3 valid numbers');
|
||||
}
|
||||
|
||||
if(typeof zoom !== 'undefined' && (isNaN(zoom) || zoom < 0 || !isFinite(zoom))) {
|
||||
throw new TypeError('Invalid value for zoom');
|
||||
}
|
||||
|
||||
return {
|
||||
world,
|
||||
map,
|
||||
location: location.length ? {
|
||||
x: location[0],
|
||||
y: location[1],
|
||||
z: location[2],
|
||||
} : undefined,
|
||||
zoom,
|
||||
legacy: false,
|
||||
}
|
||||
},
|
||||
|
||||
parseMapSearchParams(query: URLSearchParams) {
|
||||
const world = query.get('worldname') || undefined,
|
||||
map = query.get('mapname') || undefined,
|
||||
location = [
|
||||
query.get('x') || '',
|
||||
query.get('y') || '',
|
||||
query.get('z') || ''
|
||||
].map(item => parseFloat(item)).filter(item => !isNaN(item) && isFinite(item)),
|
||||
zoom = query.has('zoom') ? parseInt(query.get('zoom') as string) : undefined;
|
||||
|
||||
if(location.length && location.length !== 3) {
|
||||
throw new TypeError('Location should contain exactly 3 valid numbers');
|
||||
}
|
||||
|
||||
if(typeof zoom !== 'undefined' && (isNaN(zoom) || zoom < 0 || !isFinite(zoom))) {
|
||||
throw new TypeError('Invalid value for zoom');
|
||||
}
|
||||
|
||||
return {
|
||||
world,
|
||||
map,
|
||||
location: location.length ? {
|
||||
x: location[0],
|
||||
y: location[1],
|
||||
z: location[2],
|
||||
} : undefined,
|
||||
zoom,
|
||||
legacy: true,
|
||||
return parseMapHash(hash);
|
||||
} catch (e) {
|
||||
console.warn('Ignoring invalid url ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return parseMapSearchParams(query);
|
||||
} catch(e) {
|
||||
console.warn('Ignoring invalid legacy url ' + e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export const parseMapHash = (hash: string) => {
|
||||
const parts = hash.replace('#', '').split(';');
|
||||
|
||||
const world = parts[0] || undefined,
|
||||
map = parts[1] || undefined,
|
||||
location = (parts[2] || '').split(',')
|
||||
.map(item => parseFloat(item))
|
||||
.filter(item => !isNaN(item) && isFinite(item)),
|
||||
zoom = typeof parts[3] !== 'undefined' ? parseInt(parts[3]) : undefined;
|
||||
|
||||
if(location.length && location.length !== 3) {
|
||||
throw new TypeError('Location should contain exactly 3 valid numbers');
|
||||
}
|
||||
|
||||
if(typeof zoom !== 'undefined' && (isNaN(zoom) || zoom < 0 || !isFinite(zoom))) {
|
||||
throw new TypeError('Invalid value for zoom');
|
||||
}
|
||||
|
||||
return {
|
||||
world,
|
||||
map,
|
||||
location: location.length ? {
|
||||
x: location[0],
|
||||
y: location[1],
|
||||
z: location[2],
|
||||
} : undefined,
|
||||
zoom,
|
||||
legacy: false,
|
||||
}
|
||||
}
|
||||
|
||||
export const parseMapSearchParams = (query: URLSearchParams) => {
|
||||
const world = query.get('worldname') || undefined,
|
||||
map = query.get('mapname') || undefined,
|
||||
location = [
|
||||
query.get('x') || '',
|
||||
query.get('y') || '',
|
||||
query.get('z') || ''
|
||||
].map(item => parseFloat(item)).filter(item => !isNaN(item) && isFinite(item)),
|
||||
zoom = query.has('zoom') ? parseInt(query.get('zoom') as string) : undefined;
|
||||
|
||||
if(location.length && location.length !== 3) {
|
||||
throw new TypeError('Location should contain exactly 3 valid numbers');
|
||||
}
|
||||
|
||||
if(typeof zoom !== 'undefined' && (isNaN(zoom) || zoom < 0 || !isFinite(zoom))) {
|
||||
throw new TypeError('Invalid value for zoom');
|
||||
}
|
||||
|
||||
return {
|
||||
world,
|
||||
map,
|
||||
location: location.length ? {
|
||||
x: location[0],
|
||||
y: location[1],
|
||||
z: location[2],
|
||||
} : undefined,
|
||||
zoom,
|
||||
legacy: true,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user