export Util functions separately

This commit is contained in:
James Lyne 2021-01-26 20:37:29 +00:00
parent f7b3c4d551
commit df487ec364
11 changed files with 165 additions and 167 deletions

View File

@ -27,7 +27,7 @@ import Sidebar from './components/Sidebar.vue';
import ChatBox from './components/ChatBox.vue'; import ChatBox from './components/ChatBox.vue';
import {useStore} from "./store"; import {useStore} from "./store";
import {ActionTypes} from "@/store/action-types"; import {ActionTypes} from "@/store/action-types";
import Util from '@/util'; import {parseUrl} from '@/util';
import {MutationTypes} from "@/store/mutation-types"; import {MutationTypes} from "@/store/mutation-types";
export default defineComponent({ export default defineComponent({
@ -85,8 +85,8 @@ export default defineComponent({
updateTimeout.value = 0; updateTimeout.value = 0;
}, },
parseUrl = () => { handleUrl = () => {
const parsedUrl = Util.parseUrl(); const parsedUrl = parseUrl();
if(parsedUrl) { if(parsedUrl) {
//Remove legacy url if one was parsed //Remove legacy url if one was parsed
@ -115,7 +115,7 @@ export default defineComponent({
onMounted(() => loadConfiguration()); onMounted(() => loadConfiguration());
onBeforeUnmount(() => stopUpdates()); onBeforeUnmount(() => stopUpdates());
parseUrl(); handleUrl();
onResize(); onResize();
onMounted(() => window.addEventListener('resize', onResize)); onMounted(() => window.addEventListener('resize', onResize));

View File

@ -25,7 +25,7 @@
<script lang="ts"> <script lang="ts">
import {defineComponent, ref, onMounted, computed} from "@vue/runtime-core"; import {defineComponent, ref, onMounted, computed} from "@vue/runtime-core";
import {DynmapChat} from "@/dynmap"; import {DynmapChat} from "@/dynmap";
import Util from '@/util'; import {getMinecraftHead} from '@/util';
import {useStore} from "@/store"; import {useStore} from "@/store";
const defaultImage = require('@/assets/images/player_face.png'); const defaultImage = require('@/assets/images/player_face.png');
@ -65,7 +65,7 @@
onMounted(() => { onMounted(() => {
if(showFace.value) { 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(() => {}); .then((result) => image.value = result.src).catch(() => {});
} }
}); });

View File

@ -20,7 +20,7 @@ import {useStore} from "@/store";
import {DynmapArea, DynmapMarkerSet} from "@/dynmap"; import {DynmapArea, DynmapMarkerSet} from "@/dynmap";
import {ActionTypes} from "@/store/action-types"; import {ActionTypes} from "@/store/action-types";
import {createArea, updateArea} from "@/util/areas"; import {createArea, updateArea} from "@/util/areas";
import Util from '@/util'; import {getPointConverter} from '@/util';
import DynmapLayerGroup from "@/leaflet/layer/DynmapLayerGroup"; import DynmapLayerGroup from "@/leaflet/layer/DynmapLayerGroup";
import DynmapPolygon from "@/leaflet/vector/DynmapPolygon"; import DynmapPolygon from "@/leaflet/vector/DynmapPolygon";
import DynmapPolyline from "@/leaflet/vector/DynmapPolyline"; import DynmapPolyline from "@/leaflet/vector/DynmapPolyline";
@ -50,7 +50,7 @@ export default defineComponent({
layers = Object.freeze(new Map()) as Map<string, DynmapPolygon | DynmapPolyline>, layers = Object.freeze(new Map()) as Map<string, DynmapPolygon | DynmapPolyline>,
createAreas = () => { createAreas = () => {
const converter = Util.getPointConverter(); const converter = getPointConverter();
props.set.areas.forEach((area: DynmapArea, id: string) => { props.set.areas.forEach((area: DynmapArea, id: string) => {
const layer = createArea(area, converter); const layer = createArea(area, converter);
@ -76,7 +76,7 @@ export default defineComponent({
markerSet: props.set.id, markerSet: props.set.id,
amount: 10, amount: 10,
}).then(updates => { }).then(updates => {
const converter = Util.getPointConverter(); const converter = getPointConverter();
for(const update of updates) { for(const update of updates) {
if(update.removed) { if(update.removed) {
@ -103,7 +103,7 @@ export default defineComponent({
//FIXME: Prevent unnecessary repositioning when changing worlds //FIXME: Prevent unnecessary repositioning when changing worlds
watch(currentProjection, () => { watch(currentProjection, () => {
const converter = Util.getPointConverter(); const converter = getPointConverter();
for (const [id, area] of props.set.areas) { for (const [id, area] of props.set.areas) {
updateArea(layers.get(id), area, converter); updateArea(layers.get(id), area, converter);

View File

@ -20,7 +20,7 @@ import {useStore} from "@/store";
import {DynmapCircle, DynmapMarkerSet} from "@/dynmap"; import {DynmapCircle, DynmapMarkerSet} from "@/dynmap";
import {ActionTypes} from "@/store/action-types"; import {ActionTypes} from "@/store/action-types";
import {createCircle, updateCircle} from "@/util/circles"; import {createCircle, updateCircle} from "@/util/circles";
import Util from '@/util'; import {getPointConverter} from '@/util';
import DynmapPolyline from "@/leaflet/vector/DynmapPolyline"; import DynmapPolyline from "@/leaflet/vector/DynmapPolyline";
import DynmapPolygon from "@/leaflet/vector/DynmapPolygon"; import DynmapPolygon from "@/leaflet/vector/DynmapPolygon";
import DynmapLayerGroup from "@/leaflet/layer/DynmapLayerGroup"; import DynmapLayerGroup from "@/leaflet/layer/DynmapLayerGroup";
@ -50,7 +50,7 @@ export default defineComponent({
layers = Object.freeze(new Map<string, DynmapPolyline | DynmapPolygon>()), layers = Object.freeze(new Map<string, DynmapPolyline | DynmapPolygon>()),
createCircles = () => { createCircles = () => {
const converter = Util.getPointConverter(); const converter = getPointConverter();
props.set.circles.forEach((circle: DynmapCircle, id: string) => { props.set.circles.forEach((circle: DynmapCircle, id: string) => {
const layer = createCircle(circle, converter); const layer = createCircle(circle, converter);
@ -76,7 +76,7 @@ export default defineComponent({
markerSet: props.set.id, markerSet: props.set.id,
amount: 10, amount: 10,
}).then(updates => { }).then(updates => {
const converter = Util.getPointConverter(); const converter = getPointConverter();
for(const update of updates) { for(const update of updates) {
if(update.removed) { if(update.removed) {
@ -103,7 +103,7 @@ export default defineComponent({
//FIXME: Prevent unnecessary repositioning when changing worlds //FIXME: Prevent unnecessary repositioning when changing worlds
watch(currentProjection, () => { watch(currentProjection, () => {
const converter = Util.getPointConverter(); const converter = getPointConverter();
for (const [id, circle] of props.set.circles) { for (const [id, circle] of props.set.circles) {
updateCircle(layers.get(id), circle, converter); updateCircle(layers.get(id), circle, converter);

View File

@ -20,7 +20,7 @@ import {useStore} from "@/store";
import {DynmapLine, DynmapMarkerSet} from "@/dynmap"; import {DynmapLine, DynmapMarkerSet} from "@/dynmap";
import {ActionTypes} from "@/store/action-types"; import {ActionTypes} from "@/store/action-types";
import {createLine, updateLine} from "@/util/lines"; import {createLine, updateLine} from "@/util/lines";
import Util from '@/util'; import {getPointConverter} from '@/util';
import DynmapPolyline from "@/leaflet/vector/DynmapPolyline"; import DynmapPolyline from "@/leaflet/vector/DynmapPolyline";
import DynmapLayerGroup from "@/leaflet/layer/DynmapLayerGroup"; import DynmapLayerGroup from "@/leaflet/layer/DynmapLayerGroup";
@ -49,7 +49,7 @@ export default defineComponent({
layers = Object.freeze(new Map<string, DynmapPolyline>()), layers = Object.freeze(new Map<string, DynmapPolyline>()),
createLines = () => { createLines = () => {
const converter = Util.getPointConverter(); const converter = getPointConverter();
props.set.lines.forEach((line: DynmapLine, id: string) => { props.set.lines.forEach((line: DynmapLine, id: string) => {
const layer = createLine(line, converter); const layer = createLine(line, converter);
@ -75,7 +75,7 @@ export default defineComponent({
markerSet: props.set.id, markerSet: props.set.id,
amount: 10, amount: 10,
}).then(updates => { }).then(updates => {
const converter = Util.getPointConverter(); const converter = getPointConverter();
for(const update of updates) { for(const update of updates) {
if(update.removed) { if(update.removed) {
@ -102,7 +102,7 @@ export default defineComponent({
//FIXME: Prevent unnecessary repositioning when changing worlds //FIXME: Prevent unnecessary repositioning when changing worlds
watch(currentProjection, () => { watch(currentProjection, () => {
const converter = Util.getPointConverter(); const converter = getPointConverter();
for (const [id, line] of props.set.lines) { for (const [id, line] of props.set.lines) {
updateLine(layers.get(id), line, converter); updateLine(layers.get(id), line, converter);

View File

@ -36,7 +36,7 @@ import {DynmapPlayer} from "@/dynmap";
import {useStore} from "@/store"; import {useStore} from "@/store";
import {MutationTypes} from "@/store/mutation-types"; import {MutationTypes} from "@/store/mutation-types";
import {defineComponent, onMounted, ref, watch} from "@vue/runtime-core"; 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'); const defaultImage = require('@/assets/images/player_face.png');
@ -67,7 +67,7 @@ export default defineComponent({
image.value = defaultImage; image.value = defaultImage;
if(store.state.components.playerMarkers && store.state.components.playerMarkers.showSkinFaces) { 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(() => {});
} }
}; };

View File

@ -30,7 +30,7 @@ import {defineComponent, computed, ref, onMounted} from 'vue';
import {DynmapPlayer} from "@/dynmap"; import {DynmapPlayer} from "@/dynmap";
import {useStore} from "@/store"; import {useStore} from "@/store";
import {MutationTypes} from "@/store/mutation-types"; import {MutationTypes} from "@/store/mutation-types";
import Util from '@/util'; import {getMinecraftHead} from '@/util';
const defaultImage = require('@/assets/images/player_face.png'); const defaultImage = require('@/assets/images/player_face.png');
@ -86,7 +86,7 @@ export default defineComponent({
onMounted(() => { onMounted(() => {
if(store.state.components.playerMarkers && store.state.components.playerMarkers.showSkinFaces) { 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(() => {});
} }
}); });

View File

@ -18,7 +18,7 @@
*/ */
import {ControlOptions, DomUtil, Util, Map, Control} from 'leaflet'; import {ControlOptions, DomUtil, Util, Map, Control} from 'leaflet';
import Utils from '@/util'; import {getMinecraftTime} from '@/util';
import {DynmapWorldState} from "@/dynmap"; import {DynmapWorldState} from "@/dynmap";
import sun from '@/assets/icons/clock_sun.svg'; import sun from '@/assets/icons/clock_sun.svg';
@ -120,7 +120,7 @@ export class ClockControl extends Control {
this._moon!.style.transform = 'translate(-150px, -150px)'; this._moon!.style.transform = 'translate(-150px, -150px)';
} }
const minecraftTime = Utils.getMinecraftTime(timeOfDay); const minecraftTime = getMinecraftTime(timeOfDay);
if (this.options.showDigitalClock) { if (this.options.showDigitalClock) {
if (timeOfDay >= 0) { if (timeOfDay >= 0) {

View File

@ -19,7 +19,7 @@
import {MarkerOptions, DivIcon, DomUtil} from 'leaflet'; import {MarkerOptions, DivIcon, DomUtil} from 'leaflet';
import {DynmapPlayer} from "@/dynmap"; import {DynmapPlayer} from "@/dynmap";
import Util from '@/util'; import {getMinecraftHead} from '@/util';
const playerImage = require('@/assets/images/player_face.png'); const playerImage = require('@/assets/images/player_face.png');
@ -107,7 +107,7 @@ export class PlayerIcon extends DivIcon {
offset = 16; offset = 16;
} }
Util.getMinecraftHead(player, size).then(head => { getMinecraftHead(player, size).then(head => {
this._playerImage!.src = head.src; this._playerImage!.src = head.src;
}).catch(() => {}); }).catch(() => {});
} else { } else {

View File

@ -16,7 +16,7 @@
import {GetterTree} from "vuex"; import {GetterTree} from "vuex";
import {State} from "@/store/state"; import {State} from "@/store/state";
import Util from "@/util"; import {getMinecraftTime} from "@/util";
export type Getters = { export type Getters = {
playerMarkersEnabled(state: State): boolean; playerMarkersEnabled(state: State): boolean;
@ -41,7 +41,7 @@ export const getters: GetterTree<State, State> & Getters = {
}, },
night(state: State): boolean { night(state: State): boolean {
return Util.getMinecraftTime(state.currentWorldState.timeOfDay).night; return getMinecraftTime(state.currentWorldState.timeOfDay).night;
}, },
mapBackground(state: State): string { mapBackground(state: State): string {
@ -50,7 +50,7 @@ export const getters: GetterTree<State, State> & Getters = {
} }
if(state.currentMap.nightAndDay) { 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'; return state.currentMap.backgroundNight || state.currentMap.background || 'transparent';
} }

View File

@ -20,154 +20,152 @@ import {useStore} from "@/store";
const headCache = new Map<string, HTMLImageElement>(), const headCache = new Map<string, HTMLImageElement>(),
headUnresolvedCache = new Map<string, Promise<HTMLImageElement>>(); headUnresolvedCache = new Map<string, Promise<HTMLImageElement>>();
export default { export const getMinecraftTime = (serverTime: number) => {
getMinecraftTime(serverTime: number) { const day = serverTime >= 0 && serverTime < 13700;
const day = serverTime >= 0 && serverTime < 13700;
return { return {
serverTime: serverTime, serverTime: serverTime,
days: Math.floor((serverTime + 8000) / 24000), days: Math.floor((serverTime + 8000) / 24000),
// Assuming it is day at 6:00 // Assuming it is day at 6:00
hours: (Math.floor(serverTime / 1000) + 6) % 24, hours: (Math.floor(serverTime / 1000) + 6) % 24,
minutes: Math.floor(((serverTime / 1000) % 1) * 60), minutes: Math.floor(((serverTime / 1000) % 1) * 60),
seconds: Math.floor(((((serverTime / 1000) % 1) * 60) % 1) * 60), seconds: Math.floor(((((serverTime / 1000) % 1) * 60) % 1) * 60),
day: day, day: day,
night: !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> { faceImage.onerror = function(e) {
const account = typeof player === 'string' ? player : player.account, console.warn(`Failed to retrieve face of ${account} with size ${size}!`);
cacheKey = `${account}-${size}`; reject(e);
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});
}; };
},
parseUrl() { const src = (size === 'body') ? `faces/body/${account}.png` :`faces/${size}x${size}/${account}.png`;
const query = new URLSearchParams(window.location.search), faceImage.src = concatURL(window.config.url.markers, src);
hash = window.location.hash.replace('#', ''); }).finally(() => headUnresolvedCache.delete(cacheKey)) as Promise<HTMLImageElement>;
if(hash) { headUnresolvedCache.set(cacheKey, promise);
try {
return this.parseMapHash(hash);
} catch (e) {
console.warn('Ignoring invalid url ' + e);
}
}
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 { try {
return this.parseMapSearchParams(query); return parseMapHash(hash);
} catch(e) { } catch (e) {
console.warn('Ignoring invalid legacy url ' + e); console.warn('Ignoring invalid 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,
} }
} }
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,
}
} }