Replace serverConfig getter with MapProvider url methods

This commit is contained in:
James Lyne 2021-07-25 01:57:59 +01:00
parent e7945b3f9a
commit e61d0def04
7 changed files with 72 additions and 50 deletions

14
src/index.d.ts vendored
View File

@ -151,11 +151,15 @@ interface LiveAtlasParsedUrl {
interface LiveAtlasMapProvider { interface LiveAtlasMapProvider {
loadServerConfiguration(): Promise<void>; loadServerConfiguration(): Promise<void>;
loadWorldConfiguration(world: LiveAtlasWorldDefinition): Promise<void>; populateWorld(world: LiveAtlasWorldDefinition): Promise<void>;
startUpdates(): void; startUpdates(): void;
stopUpdates(): void; stopUpdates(): void;
sendChatMessage(message: string): void; sendChatMessage(message: string): void;
destroy(): void; destroy(): void;
getPlayerHeadUrl(entry: HeadQueueEntry): string;
getTilesUrl(): string;
getMarkerIconUrl(icon: string): string;
} }
interface LiveAtlasMarkerSet { interface LiveAtlasMarkerSet {
@ -217,3 +221,11 @@ interface LiveAtlasCircle {
maxZoom?: number; maxZoom?: number;
popupContent?: string; popupContent?: string;
} }
interface HeadQueueEntry {
cacheKey: string;
name: string;
uuid?: string;
size: string;
image: HTMLImageElement;
}

View File

@ -60,7 +60,7 @@ export class GenericIcon extends DivIcon {
} }
const div = markerContainer.cloneNode(false) as HTMLDivElement, const div = markerContainer.cloneNode(false) as HTMLDivElement,
url = `${useStore().getters.serverConfig.dynmap.markers}_markers_/${this.options.icon}.png`, url = useStore().state.currentMapProvider!.getMarkerIconUrl(this.options.icon),
size = point(this.options.iconSize as PointExpression); size = point(this.options.iconSize as PointExpression);
this._image = markerIcon.cloneNode(false) as HTMLImageElement; this._image = markerIcon.cloneNode(false) as HTMLImageElement;
@ -96,7 +96,7 @@ export class GenericIcon extends DivIcon {
update(options: GenericIconOptions) { update(options: GenericIconOptions) {
if(this._image && options.icon !== this.options.icon) { if(this._image && options.icon !== this.options.icon) {
this._image!.src = `${useStore().getters.serverConfig.dynmap.markers}_markers_/${options.icon}.png`; this._image!.src = useStore().state.currentMapProvider!.getMarkerIconUrl(this.options.icon);
this.options.icon = options.icon; this.options.icon = options.icon;
} }

View File

@ -62,6 +62,7 @@ export class DynmapTileLayer extends TileLayer {
private readonly _loadQueue: DynmapTileElement[] = []; private readonly _loadQueue: DynmapTileElement[] = [];
private readonly _loadingTiles: Set<DynmapTileElement> = Object.seal(new Set()); private readonly _loadingTiles: Set<DynmapTileElement> = Object.seal(new Set());
private readonly _tileTemplate: DynmapTileElement; private readonly _tileTemplate: DynmapTileElement;
private readonly _baseUrl: string;
declare readonly options: DynmapTileLayerOptions; declare readonly options: DynmapTileLayerOptions;
constructor(options: DynmapTileLayerOptions) { constructor(options: DynmapTileLayerOptions) {
@ -85,6 +86,7 @@ export class DynmapTileLayer extends TileLayer {
this._tileTemplate.alt = ''; this._tileTemplate.alt = '';
this._tileTemplate.tileName = ''; this._tileTemplate.tileName = '';
this._tileTemplate.setAttribute('role', 'presentation'); this._tileTemplate.setAttribute('role', 'presentation');
this._baseUrl = store.state.currentMapProvider!.getTilesUrl();
Object.seal(this._tileTemplate); Object.seal(this._tileTemplate);
@ -110,7 +112,7 @@ export class DynmapTileLayer extends TileLayer {
if (!url) { if (!url) {
const path = escape(`${this._mapSettings.world.name}/${name}`); const path = escape(`${this._mapSettings.world.name}/${name}`);
url = `${store.getters.serverConfig.dynmap.tiles}${path}`; url = `${this._baseUrl}${path}`;
if(typeof timestamp !== 'undefined') { if(typeof timestamp !== 'undefined') {
url += (url.indexOf('?') === -1 ? `?timestamp=${timestamp}` : `&timestamp=${timestamp}`); url += (url.indexOf('?') === -1 ? `?timestamp=${timestamp}` : `&timestamp=${timestamp}`);

View File

@ -15,6 +15,7 @@
*/ */
import { import {
HeadQueueEntry,
LiveAtlasArea, LiveAtlasArea,
LiveAtlasCircle, LiveAtlasCircle,
LiveAtlasDimension, LiveAtlasDimension,
@ -582,8 +583,8 @@ export default class DynmapMapProvider extends MapProvider {
return updates; return updates;
} }
private async getMarkerSets(world: string): Promise<Map<string, LiveAtlasMarkerSet>> { private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise<Map<string, LiveAtlasMarkerSet>> {
const url = `${useStore().getters.serverConfig.dynmap.markers}_markers_/marker_${world}.json`; const url = `${this.config.dynmap!.markers}_markers_/marker_${world.name}.json`;
if(this.markersAbort) { if(this.markersAbort) {
this.markersAbort.abort(); this.markersAbort.abort();
@ -619,7 +620,6 @@ export default class DynmapMapProvider extends MapProvider {
return sets; return sets;
} }
async loadServerConfiguration(): Promise<void> { async loadServerConfiguration(): Promise<void> {
if(this.configurationAbort) { if(this.configurationAbort) {
this.configurationAbort.abort(); this.configurationAbort.abort();
@ -627,7 +627,7 @@ export default class DynmapMapProvider extends MapProvider {
this.configurationAbort = new AbortController(); this.configurationAbort = new AbortController();
const response = await DynmapMapProvider.fetchJSON(useStore().getters.serverConfig.dynmap.configuration, this.configurationAbort.signal); const response = await DynmapMapProvider.fetchJSON(this.config.dynmap!.configuration, this.configurationAbort.signal);
if (response.error === 'login-required') { if (response.error === 'login-required') {
throw new Error("Login required"); throw new Error("Login required");
@ -647,14 +647,14 @@ export default class DynmapMapProvider extends MapProvider {
this.store.commit(MutationTypes.SET_LOGGED_IN, response.loggedin || false); this.store.commit(MutationTypes.SET_LOGGED_IN, response.loggedin || false);
} }
async loadWorldConfiguration(): Promise<void> { async populateWorld(world: LiveAtlasWorldDefinition): Promise<void> {
const markerSets = await this.getMarkerSets(this.store.state.currentWorld!.name); const markerSets = await this.getMarkerSets(world);
useStore().commit(MutationTypes.SET_MARKER_SETS, markerSets); useStore().commit(MutationTypes.SET_MARKER_SETS, markerSets);
} }
private async getUpdate(): Promise<void> { private async getUpdate(): Promise<void> {
let url = useStore().getters.serverConfig.dynmap.update; let url = this.config.dynmap!.update;
url = url.replace('{world}', this.store.state.currentWorld!.name); url = url.replace('{world}', this.store.state.currentWorld!.name);
url = url.replace('{timestamp}', this.updateTimestamp.getTime().toString()); url = url.replace('{timestamp}', this.updateTimestamp.getTime().toString());
@ -729,7 +729,7 @@ export default class DynmapMapProvider extends MapProvider {
return Promise.reject(store.state.messages.chatErrorDisabled); return Promise.reject(store.state.messages.chatErrorDisabled);
} }
return fetch(useStore().getters.serverConfig.dynmap.sendmessage, { return fetch(this.config.dynmap!.sendmessage, {
method: 'POST', method: 'POST',
body: JSON.stringify({ body: JSON.stringify({
name: null, name: null,
@ -789,7 +789,23 @@ export default class DynmapMapProvider extends MapProvider {
this.updateTimeout = 0; this.updateTimeout = 0;
} }
getTilesUrl(): string {
return this.config.dynmap!.tiles;
}
getPlayerHeadUrl(head: HeadQueueEntry): string {
const icon = (head.size === 'body') ? `faces/body/${head.name}.png` :`faces/${head.size}x${head.size}/${head.name}.png`
return this.getMarkerIconUrl(icon);
}
getMarkerIconUrl(icon: string): string {
return `${this.config.dynmap!.markers}_markers_/${icon}.png`;
}
destroy() { destroy() {
super.destroy();
if(this.configurationAbort) { if(this.configurationAbort) {
this.configurationAbort.abort(); this.configurationAbort.abort();
} }

View File

@ -1,27 +1,43 @@
import {LiveAtlasMapProvider, LiveAtlasServerDefinition, LiveAtlasWorldDefinition} from "@/index"; import {
HeadQueueEntry,
LiveAtlasMapProvider,
LiveAtlasServerDefinition,
LiveAtlasWorldDefinition
} from "@/index";
import {useStore} from "@/store"; import {useStore} from "@/store";
import {watch} from "vue"; import {computed, watch} from "@vue/runtime-core";
import {computed} from "@vue/runtime-core"; import {WatchStopHandle} from "vue";
export default abstract class MapProvider implements LiveAtlasMapProvider { export default abstract class MapProvider implements LiveAtlasMapProvider {
protected readonly store = useStore(); protected readonly store = useStore();
protected readonly config: LiveAtlasServerDefinition;
private readonly currentWorldUnwatch: WatchStopHandle;
protected constructor(config: LiveAtlasServerDefinition) { protected constructor(config: LiveAtlasServerDefinition) {
this.config = config;
const currentWorld = computed(() => this.store.state.currentWorld); const currentWorld = computed(() => this.store.state.currentWorld);
watch(currentWorld, (newValue) => { this.currentWorldUnwatch = watch(currentWorld, (newValue) => {
if (newValue) { if (newValue) {
this.loadWorldConfiguration(newValue); this.populateWorld(newValue);
} }
}); });
} }
abstract loadServerConfiguration(): Promise<void>; abstract loadServerConfiguration(): Promise<void>;
abstract loadWorldConfiguration(world: LiveAtlasWorldDefinition): Promise<void>; abstract populateWorld(world: LiveAtlasWorldDefinition): Promise<void>;
abstract sendChatMessage(message: string): void; abstract sendChatMessage(message: string): void;
abstract startUpdates(): void; abstract startUpdates(): void;
abstract stopUpdates(): void; abstract stopUpdates(): void;
abstract destroy(): void;
abstract getPlayerHeadUrl(head: HeadQueueEntry): string;
abstract getTilesUrl(): string;
abstract getMarkerIconUrl(icon: string): string;
destroy() {
this.currentWorldUnwatch();
}
protected static async fetchJSON(url: string, signal: AbortSignal) { protected static async fetchJSON(url: string, signal: AbortSignal) {
let response, json; let response, json;

View File

@ -17,7 +17,6 @@
import {GetterTree} from "vuex"; import {GetterTree} from "vuex";
import {State} from "@/store/state"; import {State} from "@/store/state";
import {getMinecraftTime, getUrlForLocation} from "@/util"; import {getMinecraftTime, getUrlForLocation} from "@/util";
import {LiveAtlasDynmapServerDefinition} from "@/index";
export type Getters = { export type Getters = {
playerMarkersEnabled(state: State): boolean; playerMarkersEnabled(state: State): boolean;
@ -26,7 +25,6 @@ export type Getters = {
night(state: State): boolean; night(state: State): boolean;
mapBackground(state: State, getters: GetterTree<State, State> & Getters): string; mapBackground(state: State, getters: GetterTree<State, State> & Getters): string;
url(state: State, getters: GetterTree<State, State> & Getters): string; url(state: State, getters: GetterTree<State, State> & Getters): string;
serverConfig(state: State, getters: GetterTree<State, State> & Getters): LiveAtlasDynmapServerDefinition;
} }
export const getters: GetterTree<State, State> & Getters = { export const getters: GetterTree<State, State> & Getters = {
@ -74,12 +72,4 @@ export const getters: GetterTree<State, State> & Getters = {
return getUrlForLocation(state.currentMap, {x,y,z}, zoom); return getUrlForLocation(state.currentMap, {x,y,z}, zoom);
}, },
serverConfig(state: State): LiveAtlasDynmapServerDefinition {
if(!state.currentServer) {
throw RangeError("No current server");
}
return state.currentServer as LiveAtlasDynmapServerDefinition;
},
} }

View File

@ -16,14 +16,7 @@
import {useStore} from "@/store"; import {useStore} from "@/store";
import LiveAtlasMapDefinition from "@/model/LiveAtlasMapDefinition"; import LiveAtlasMapDefinition from "@/model/LiveAtlasMapDefinition";
import {LiveAtlasPlayer} from "@/index"; import {HeadQueueEntry, LiveAtlasPlayer} from "@/index";
interface HeadQueueEntry {
cacheKey: string;
account: string;
size: string;
image: HTMLImageElement;
}
const headCache = new Map<string, HTMLImageElement>(), const headCache = new Map<string, HTMLImageElement>(),
headUnresolvedCache = new Map<string, Promise<HTMLImageElement>>(), headUnresolvedCache = new Map<string, Promise<HTMLImageElement>>(),
@ -54,6 +47,7 @@ export const getMinecraftTime = (serverTime: number) => {
export const getMinecraftHead = (player: LiveAtlasPlayer | string, size: string): Promise<HTMLImageElement> => { export const getMinecraftHead = (player: LiveAtlasPlayer | string, size: string): Promise<HTMLImageElement> => {
const account = typeof player === 'string' ? player : player.name, const account = typeof player === 'string' ? player : player.name,
uuid = typeof player === 'string' ? undefined : player.uuid,
cacheKey = `${account}-${size}`; cacheKey = `${account}-${size}`;
if(headCache.has(cacheKey)) { if(headCache.has(cacheKey)) {
@ -82,7 +76,8 @@ export const getMinecraftHead = (player: LiveAtlasPlayer | string, size: string)
}; };
headQueue.push({ headQueue.push({
account, name: account,
uuid,
size, size,
cacheKey, cacheKey,
image: faceImage, image: faceImage,
@ -100,23 +95,14 @@ const tickHeadQueue = () => {
return; return;
} }
const head = headQueue.pop() as HeadQueueEntry, const head = headQueue.pop() as HeadQueueEntry;
src = (head.size === 'body') ? `faces/body/${head.account}.png` :`faces/${head.size}x${head.size}/${head.account}.png`;
headsLoading.add(head.cacheKey); headsLoading.add(head.cacheKey);
head.image.src = concatURL(useStore().getters.serverConfig.dynmap.markers, src); head.image.src = useStore().state.currentMapProvider!.getPlayerHeadUrl(head);
tickHeadQueue(); tickHeadQueue();
} }
export const concatURL = (base: string, addition: string) => {
if(base.indexOf('?') >= 0) {
return base + escape(addition);
}
return base + addition;
}
export const getPointConverter = () => { export const getPointConverter = () => {
const map = useStore().state.currentMap; const map = useStore().state.currentMap;