Refactor config loading
- Move config validation into map providers - Move TileLayer creation into map providers - Simplify config loading logic
This commit is contained in:
parent
52e512e316
commit
80fe8916f3
@ -169,6 +169,7 @@ export default defineComponent({
|
|||||||
const store = useStore();
|
const store = useStore();
|
||||||
|
|
||||||
if(newValue) {
|
if(newValue) {
|
||||||
|
store.state.currentMapProvider!.populateWorld(newValue);
|
||||||
let viewTarget = this.scheduledView || {} as LiveAtlasMapViewTarget;
|
let viewTarget = this.scheduledView || {} as LiveAtlasMapViewTarget;
|
||||||
|
|
||||||
// Abort if follow target is present, to avoid panning twice
|
// Abort if follow target is present, to avoid panning twice
|
||||||
|
@ -18,10 +18,8 @@
|
|||||||
import {defineComponent, onUnmounted, computed, watch} from "@vue/runtime-core";
|
import {defineComponent, onUnmounted, computed, watch} from "@vue/runtime-core";
|
||||||
import {Map} from 'leaflet';
|
import {Map} from 'leaflet';
|
||||||
import {useStore} from "@/store";
|
import {useStore} from "@/store";
|
||||||
import {DynmapTileLayer} from "@/leaflet/tileLayer/DynmapTileLayer";
|
|
||||||
import LiveAtlasMapDefinition from "@/model/LiveAtlasMapDefinition";
|
import LiveAtlasMapDefinition from "@/model/LiveAtlasMapDefinition";
|
||||||
import {LiveAtlasTileLayer} from "@/leaflet/tileLayer/LiveAtlasTileLayer";
|
import {LiveAtlasTileLayer} from "@/leaflet/tileLayer/LiveAtlasTileLayer";
|
||||||
import {Pl3xmapTileLayer} from "@/leaflet/tileLayer/Pl3xmapTileLayer";
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
@ -54,17 +52,10 @@ export default defineComponent({
|
|||||||
refreshTimeout = setTimeout(refresh, props.map.tileUpdateInterval);
|
refreshTimeout = setTimeout(refresh, props.map.tileUpdateInterval);
|
||||||
};
|
};
|
||||||
|
|
||||||
if(store.state.currentServer?.type === 'dynmap') {
|
layer = store.state.currentMapProvider!.createTileLayer({
|
||||||
layer = new DynmapTileLayer({
|
errorTileUrl: 'images/blank.png',
|
||||||
errorTileUrl: 'images/blank.png',
|
mapSettings: Object.freeze(JSON.parse(JSON.stringify(props.map))),
|
||||||
mapSettings: Object.freeze(JSON.parse(JSON.stringify(props.map))),
|
});
|
||||||
});
|
|
||||||
} else {
|
|
||||||
layer = new Pl3xmapTileLayer({
|
|
||||||
errorTileUrl: 'images/blank.png',
|
|
||||||
mapSettings: Object.freeze(JSON.parse(JSON.stringify(props.map)))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const enableLayer = () => {
|
const enableLayer = () => {
|
||||||
props.leaflet.addLayer(layer);
|
props.leaflet.addLayer(layer);
|
||||||
|
4
src/index.d.ts
vendored
4
src/index.d.ts
vendored
@ -30,6 +30,7 @@ import {ClockControlOptions} from "@/leaflet/control/ClockControl";
|
|||||||
import {LogoControlOptions} from "@/leaflet/control/LogoControl";
|
import {LogoControlOptions} from "@/leaflet/control/LogoControl";
|
||||||
import {globalMessages, serverMessages} from "../messages";
|
import {globalMessages, serverMessages} from "../messages";
|
||||||
import {LiveAtlasMarkerType} from "@/util/markers";
|
import {LiveAtlasMarkerType} from "@/util/markers";
|
||||||
|
import {LiveAtlasTileLayerOptions} from "@/leaflet/tileLayer/LiveAtlasTileLayer";
|
||||||
|
|
||||||
declare module "*.png" {
|
declare module "*.png" {
|
||||||
const value: any;
|
const value: any;
|
||||||
@ -100,7 +101,6 @@ interface LiveAtlasGlobalConfig {
|
|||||||
interface LiveAtlasServerDefinition {
|
interface LiveAtlasServerDefinition {
|
||||||
id: string;
|
id: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
type: 'dynmap' | 'pl3xmap';
|
|
||||||
dynmap?: DynmapUrlConfig;
|
dynmap?: DynmapUrlConfig;
|
||||||
pl3xmap?: string;
|
pl3xmap?: string;
|
||||||
squaremap?: string;
|
squaremap?: string;
|
||||||
@ -178,11 +178,11 @@ interface LiveAtlasMapProvider {
|
|||||||
populateWorld(world: LiveAtlasWorldDefinition): Promise<void>;
|
populateWorld(world: LiveAtlasWorldDefinition): Promise<void>;
|
||||||
startUpdates(): void;
|
startUpdates(): void;
|
||||||
stopUpdates(): void;
|
stopUpdates(): void;
|
||||||
|
createTileLayer(options: LiveAtlasTileLayerOptions): LiveAtlasTileLayer;
|
||||||
sendChatMessage(message: string): void;
|
sendChatMessage(message: string): void;
|
||||||
login(formData: FormData): void;
|
login(formData: FormData): void;
|
||||||
logout(): void;
|
logout(): void;
|
||||||
register(formData: FormData): void;
|
register(formData: FormData): void;
|
||||||
destroy(): void;
|
|
||||||
|
|
||||||
getPlayerHeadUrl(entry: HeadQueueEntry): string;
|
getPlayerHeadUrl(entry: HeadQueueEntry): string;
|
||||||
getTilesUrl(): string;
|
getTilesUrl(): string;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Map as LeafletMap, Coords, DoneCallback} from 'leaflet';
|
import {Map as LeafletMap, Coords, DoneCallback} from 'leaflet';
|
||||||
import {useStore} from "@/store";
|
import {Store, useStore} from "@/store";
|
||||||
import {Coordinate, Coordinate2D} from "@/index";
|
import {Coordinate, Coordinate2D} from "@/index";
|
||||||
import {LiveAtlasTileLayer, LiveAtlasTileLayerOptions} from "@/leaflet/tileLayer/LiveAtlasTileLayer";
|
import {LiveAtlasTileLayer, LiveAtlasTileLayerOptions} from "@/leaflet/tileLayer/LiveAtlasTileLayer";
|
||||||
import {computed, watch} from "@vue/runtime-core";
|
import {computed, watch} from "@vue/runtime-core";
|
||||||
@ -27,12 +27,12 @@ import {WatchStopHandle} from "vue";
|
|||||||
import {ActionTypes} from "@/store/action-types";
|
import {ActionTypes} from "@/store/action-types";
|
||||||
import {TileInformation} from "dynmap";
|
import {TileInformation} from "dynmap";
|
||||||
|
|
||||||
const store = useStore();
|
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
export class DynmapTileLayer extends LiveAtlasTileLayer {
|
export class DynmapTileLayer extends LiveAtlasTileLayer {
|
||||||
private readonly _namedTiles: Map<any, any>;
|
private readonly _namedTiles: Map<any, any>;
|
||||||
private readonly _baseUrl: string;
|
private readonly _baseUrl: string;
|
||||||
|
private readonly _store: Store = useStore();
|
||||||
|
|
||||||
private readonly _night: ComputedRef<boolean>;
|
private readonly _night: ComputedRef<boolean>;
|
||||||
private readonly _pendingUpdates: ComputedRef<boolean>;
|
private readonly _pendingUpdates: ComputedRef<boolean>;
|
||||||
@ -44,11 +44,11 @@ export class DynmapTileLayer extends LiveAtlasTileLayer {
|
|||||||
super('', options);
|
super('', options);
|
||||||
|
|
||||||
this._mapSettings = options.mapSettings;
|
this._mapSettings = options.mapSettings;
|
||||||
this._baseUrl = store.state.currentMapProvider!.getTilesUrl();
|
this._baseUrl = this._store.state.currentMapProvider!.getTilesUrl();
|
||||||
this._namedTiles = Object.seal(new Map());
|
this._namedTiles = Object.seal(new Map());
|
||||||
|
|
||||||
this._pendingUpdates = computed(() => !!store.state.pendingTileUpdates.length);
|
this._pendingUpdates = computed(() => !!this._store.state.pendingTileUpdates.length);
|
||||||
this._night = computed(() => store.getters.night);
|
this._night = computed(() => this._store.getters.night);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(map: LeafletMap) {
|
onAdd(map: LeafletMap) {
|
||||||
@ -183,7 +183,7 @@ export class DynmapTileLayer extends LiveAtlasTileLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async handlePendingUpdates() {
|
private async handlePendingUpdates() {
|
||||||
const updates = await store.dispatch(ActionTypes.POP_TILE_UPDATES, 10);
|
const updates = await this._store.dispatch(ActionTypes.POP_TILE_UPDATES, 10);
|
||||||
|
|
||||||
for(const update of updates) {
|
for(const update of updates) {
|
||||||
this.updateNamedTile(update.name, update.timestamp);
|
this.updateNamedTile(update.name, update.timestamp);
|
||||||
|
28
src/main.ts
28
src/main.ts
@ -23,10 +23,13 @@ import 'leaflet/dist/leaflet.css';
|
|||||||
import '@/scss/style.scss';
|
import '@/scss/style.scss';
|
||||||
|
|
||||||
import {MutationTypes} from "@/store/mutation-types";
|
import {MutationTypes} from "@/store/mutation-types";
|
||||||
import {showSplashError} from "@/util/splash";
|
|
||||||
import { VueClipboard } from '@soerenmartius/vue3-clipboard';
|
import { VueClipboard } from '@soerenmartius/vue3-clipboard';
|
||||||
import Notifications from '@kyvg/vue3-notification'
|
import Notifications from '@kyvg/vue3-notification'
|
||||||
import {getServerDefinitions} from "@/util/config";
|
import {loadConfig, registerMapProvider} from "@/util/config";
|
||||||
|
import DynmapMapProvider from "@/providers/DynmapMapProvider";
|
||||||
|
import Pl3xmapMapProvider from "@/providers/Pl3xmapMapProvider";
|
||||||
|
import {showSplashError} from "@/util/splash";
|
||||||
|
import ConfigurationError from "@/errors/ConfigurationError";
|
||||||
|
|
||||||
const splash = document.getElementById('splash'),
|
const splash = document.getElementById('splash'),
|
||||||
svgs = import.meta.globEager('/assets/icons/*.svg');
|
svgs = import.meta.globEager('/assets/icons/*.svg');
|
||||||
@ -49,10 +52,14 @@ store.subscribe((mutation, state) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
registerMapProvider('dynmap', DynmapMapProvider);
|
||||||
const config = window.liveAtlasConfig;
|
registerMapProvider('pl3xmap', Pl3xmapMapProvider);
|
||||||
config.servers = getServerDefinitions(config);
|
registerMapProvider('squaremap', Pl3xmapMapProvider);
|
||||||
|
|
||||||
|
const config = window.liveAtlasConfig;
|
||||||
|
|
||||||
|
try {
|
||||||
|
config.servers = loadConfig(config);
|
||||||
store.commit(MutationTypes.INIT, config);
|
store.commit(MutationTypes.INIT, config);
|
||||||
|
|
||||||
if(store.state.servers.size > 1) {
|
if(store.state.servers.size > 1) {
|
||||||
@ -76,7 +83,12 @@ try {
|
|||||||
|
|
||||||
// app.config.performance = true;
|
// app.config.performance = true;
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
console.error('LiveAtlas configuration is invalid: ', e);
|
if(e instanceof ConfigurationError) {
|
||||||
showSplashError('LiveAtlas configuration is invalid:\n' + e, true);
|
console.error('LiveAtlas configuration is invalid:', e);
|
||||||
|
showSplashError('LiveAtlas configuration is invalid:\n' + e, true);
|
||||||
|
} else {
|
||||||
|
console.error('LiveAtlas failed to load:', e);
|
||||||
|
showSplashError('LiveAtlas failed to load:\n' + e, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ import {
|
|||||||
HeadQueueEntry, LiveAtlasMarker,
|
HeadQueueEntry, LiveAtlasMarker,
|
||||||
LiveAtlasMarkerSet,
|
LiveAtlasMarkerSet,
|
||||||
LiveAtlasPlayer,
|
LiveAtlasPlayer,
|
||||||
LiveAtlasServerDefinition,
|
|
||||||
LiveAtlasWorldDefinition
|
LiveAtlasWorldDefinition
|
||||||
} from "@/index";
|
} from "@/index";
|
||||||
import ChatError from "@/errors/ChatError";
|
import ChatError from "@/errors/ChatError";
|
||||||
@ -36,6 +35,10 @@ import {
|
|||||||
} from "@/util/dynmap";
|
} from "@/util/dynmap";
|
||||||
import {getImagePixelSize} from "@/util";
|
import {getImagePixelSize} from "@/util";
|
||||||
import {MarkerSet} from "dynmap";
|
import {MarkerSet} from "dynmap";
|
||||||
|
import {DynmapUrlConfig} from "@/dynmap";
|
||||||
|
import ConfigurationError from "@/errors/ConfigurationError";
|
||||||
|
import {DynmapTileLayer} from "@/leaflet/tileLayer/DynmapTileLayer";
|
||||||
|
import {LiveAtlasTileLayer, LiveAtlasTileLayerOptions} from "@/leaflet/tileLayer/LiveAtlasTileLayer";
|
||||||
|
|
||||||
export default class DynmapMapProvider extends MapProvider {
|
export default class DynmapMapProvider extends MapProvider {
|
||||||
private configurationAbort?: AbortController = undefined;
|
private configurationAbort?: AbortController = undefined;
|
||||||
@ -50,12 +53,41 @@ export default class DynmapMapProvider extends MapProvider {
|
|||||||
private markerSets: Map<string, LiveAtlasMarkerSet> = new Map();
|
private markerSets: Map<string, LiveAtlasMarkerSet> = new Map();
|
||||||
private markers = new Map<string, Map<string, LiveAtlasMarker>>();
|
private markers = new Map<string, Map<string, LiveAtlasMarker>>();
|
||||||
|
|
||||||
constructor(config: LiveAtlasServerDefinition) {
|
constructor(config: DynmapUrlConfig) {
|
||||||
super(config);
|
super(config);
|
||||||
|
this.validateConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
private validateConfig() {
|
||||||
|
if(typeof this.config !== 'undefined') {
|
||||||
|
if (!this.config || this.config.constructor !== Object) {
|
||||||
|
throw new ConfigurationError(`Dynmap configuration object missing`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.config.configuration) {
|
||||||
|
throw new ConfigurationError(`Dynmap configuration URL missing`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.config.update) {
|
||||||
|
throw new ConfigurationError(`Dynmap update URL missing`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.config.markers) {
|
||||||
|
throw new ConfigurationError(`Dynmap markers URL missing`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.config.tiles) {
|
||||||
|
throw new ConfigurationError(`Dynmap tiles URL missing`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.config.sendmessage) {
|
||||||
|
throw new ConfigurationError(`Dynmap sendmessage URL missing`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise<void> {
|
private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise<void> {
|
||||||
const url = `${this.config.dynmap!.markers}_markers_/marker_${world.name}.json`;
|
const url = `${this.config.markers}_markers_/marker_${world.name}.json`;
|
||||||
|
|
||||||
if(this.markersAbort) {
|
if(this.markersAbort) {
|
||||||
this.markersAbort.abort();
|
this.markersAbort.abort();
|
||||||
@ -93,7 +125,7 @@ export default class DynmapMapProvider extends MapProvider {
|
|||||||
|
|
||||||
this.configurationAbort = new AbortController();
|
this.configurationAbort = new AbortController();
|
||||||
|
|
||||||
const response = await this.getJSON(this.config.dynmap!.configuration, this.configurationAbort.signal);
|
const response = await this.getJSON(this.config.configuration, this.configurationAbort.signal);
|
||||||
|
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
throw new Error(response.error);
|
throw new Error(response.error);
|
||||||
@ -122,8 +154,12 @@ export default class DynmapMapProvider extends MapProvider {
|
|||||||
this.markers.clear();
|
this.markers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createTileLayer(options: LiveAtlasTileLayerOptions): LiveAtlasTileLayer {
|
||||||
|
return new DynmapTileLayer(options);
|
||||||
|
}
|
||||||
|
|
||||||
private async getUpdate(): Promise<void> {
|
private async getUpdate(): Promise<void> {
|
||||||
let url = this.config.dynmap!.update;
|
let url = this.config.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());
|
||||||
|
|
||||||
@ -200,7 +236,7 @@ export default class DynmapMapProvider extends MapProvider {
|
|||||||
return Promise.reject(this.store.state.messages.chatErrorDisabled);
|
return Promise.reject(this.store.state.messages.chatErrorDisabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fetch(this.config.dynmap!.sendmessage, {
|
return fetch(this.config.sendmessage, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
@ -259,14 +295,26 @@ export default class DynmapMapProvider extends MapProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.updateTimeout = null;
|
this.updateTimeout = null;
|
||||||
|
|
||||||
|
if(this.configurationAbort) {
|
||||||
|
this.configurationAbort.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.updateAbort) {
|
||||||
|
this.updateAbort.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.markersAbort) {
|
||||||
|
this.markersAbort.abort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getTilesUrl(): string {
|
getTilesUrl(): string {
|
||||||
return this.config.dynmap!.tiles;
|
return this.config.tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlayerHeadUrl(head: HeadQueueEntry): string {
|
getPlayerHeadUrl(head: HeadQueueEntry): string {
|
||||||
const baseUrl = `${this.config.dynmap!.markers}faces/`;
|
const baseUrl = `${this.config.markers}faces/`;
|
||||||
|
|
||||||
if(head.size === 'body') {
|
if(head.size === 'body') {
|
||||||
return `${baseUrl}body/${head.name}.png`;
|
return `${baseUrl}body/${head.name}.png`;
|
||||||
@ -277,7 +325,7 @@ export default class DynmapMapProvider extends MapProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getMarkerIconUrl(icon: string): string {
|
getMarkerIconUrl(icon: string): string {
|
||||||
return `${this.config.dynmap!.markers}_markers_/${icon}.png`;
|
return `${this.config.markers}_markers_/${icon}.png`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async login(data: any) {
|
async login(data: any) {
|
||||||
@ -294,7 +342,7 @@ export default class DynmapMapProvider extends MapProvider {
|
|||||||
body.append('j_password', data.password || '');
|
body.append('j_password', data.password || '');
|
||||||
|
|
||||||
|
|
||||||
const response = await DynmapMapProvider.fetchJSON(this.config.dynmap!.login, {
|
const response = await DynmapMapProvider.fetchJSON(this.config.login, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body,
|
body,
|
||||||
});
|
});
|
||||||
@ -323,7 +371,7 @@ export default class DynmapMapProvider extends MapProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await DynmapMapProvider.fetchJSON(this.config.dynmap!.login, {
|
await DynmapMapProvider.fetchJSON(this.config.login, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -348,7 +396,7 @@ export default class DynmapMapProvider extends MapProvider {
|
|||||||
body.append('j_verify_password', data.password || '');
|
body.append('j_verify_password', data.password || '');
|
||||||
body.append('j_passcode', data.code || '');
|
body.append('j_passcode', data.code || '');
|
||||||
|
|
||||||
const response = await DynmapMapProvider.fetchJSON(this.config.dynmap!.register, {
|
const response = await DynmapMapProvider.fetchJSON(this.config.register, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body,
|
body,
|
||||||
});
|
});
|
||||||
@ -374,22 +422,6 @@ export default class DynmapMapProvider extends MapProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
|
||||||
super.destroy();
|
|
||||||
|
|
||||||
if(this.configurationAbort) {
|
|
||||||
this.configurationAbort.abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.updateAbort) {
|
|
||||||
this.updateAbort.abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.markersAbort) {
|
|
||||||
this.markersAbort.abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async getJSON(url: string, signal: AbortSignal) {
|
protected async getJSON(url: string, signal: AbortSignal) {
|
||||||
return MapProvider.fetchJSON(url, {signal, credentials: 'include'}).then(response => {
|
return MapProvider.fetchJSON(url, {signal, credentials: 'include'}).then(response => {
|
||||||
if(response.error === 'login-required') {
|
if(response.error === 'login-required') {
|
||||||
|
@ -17,31 +17,22 @@
|
|||||||
import {
|
import {
|
||||||
HeadQueueEntry,
|
HeadQueueEntry,
|
||||||
LiveAtlasMapProvider,
|
LiveAtlasMapProvider,
|
||||||
LiveAtlasServerDefinition,
|
|
||||||
LiveAtlasWorldDefinition
|
LiveAtlasWorldDefinition
|
||||||
} from "@/index";
|
} from "@/index";
|
||||||
import {useStore} from "@/store";
|
import {useStore} from "@/store";
|
||||||
import {computed, watch} from "@vue/runtime-core";
|
import {LiveAtlasTileLayer, LiveAtlasTileLayerOptions} from "@/leaflet/tileLayer/LiveAtlasTileLayer";
|
||||||
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;
|
protected config: any;
|
||||||
private readonly currentWorldUnwatch: WatchStopHandle;
|
|
||||||
|
|
||||||
protected constructor(config: LiveAtlasServerDefinition) {
|
protected constructor(config: any) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
const currentWorld = computed(() => this.store.state.currentWorld);
|
|
||||||
|
|
||||||
this.currentWorldUnwatch = watch(currentWorld, (newValue) => {
|
|
||||||
if (newValue) {
|
|
||||||
this.populateWorld(newValue);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract loadServerConfiguration(): Promise<void>;
|
abstract loadServerConfiguration(): Promise<void>;
|
||||||
abstract populateWorld(world: LiveAtlasWorldDefinition): Promise<void>;
|
abstract populateWorld(world: LiveAtlasWorldDefinition): Promise<void>;
|
||||||
|
abstract createTileLayer(options: LiveAtlasTileLayerOptions): LiveAtlasTileLayer;
|
||||||
|
|
||||||
abstract startUpdates(): void;
|
abstract startUpdates(): void;
|
||||||
abstract stopUpdates(): void;
|
abstract stopUpdates(): void;
|
||||||
@ -50,7 +41,7 @@ export default abstract class MapProvider implements LiveAtlasMapProvider {
|
|||||||
abstract getTilesUrl(): string;
|
abstract getTilesUrl(): string;
|
||||||
abstract getMarkerIconUrl(icon: string): string;
|
abstract getMarkerIconUrl(icon: string): string;
|
||||||
|
|
||||||
sendChatMessage(message: string) {
|
sendChatMessage(message: string) {
|
||||||
throw new Error('Provider does not support chat');
|
throw new Error('Provider does not support chat');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,10 +57,6 @@ export default abstract class MapProvider implements LiveAtlasMapProvider {
|
|||||||
throw new Error('Provider does not support registration');
|
throw new Error('Provider does not support registration');
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
|
||||||
this.currentWorldUnwatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static async fetchJSON(url: string, options: any) {
|
protected static async fetchJSON(url: string, options: any) {
|
||||||
let response, json;
|
let response, json;
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ import {
|
|||||||
LiveAtlasPlayer,
|
LiveAtlasPlayer,
|
||||||
LiveAtlasPointMarker,
|
LiveAtlasPointMarker,
|
||||||
LiveAtlasServerConfig,
|
LiveAtlasServerConfig,
|
||||||
LiveAtlasServerDefinition,
|
|
||||||
LiveAtlasServerMessageConfig,
|
LiveAtlasServerMessageConfig,
|
||||||
LiveAtlasWorldDefinition
|
LiveAtlasWorldDefinition
|
||||||
} from "@/index";
|
} from "@/index";
|
||||||
@ -37,6 +36,9 @@ import {ActionTypes} from "@/store/action-types";
|
|||||||
import {getBoundsFromPoints, getMiddle, stripHTML, titleColoursRegex} from "@/util";
|
import {getBoundsFromPoints, getMiddle, stripHTML, titleColoursRegex} from "@/util";
|
||||||
import {LiveAtlasMarkerType} from "@/util/markers";
|
import {LiveAtlasMarkerType} from "@/util/markers";
|
||||||
import {PointTuple} from "leaflet";
|
import {PointTuple} from "leaflet";
|
||||||
|
import ConfigurationError from "@/errors/ConfigurationError";
|
||||||
|
import {Pl3xmapTileLayer} from "@/leaflet/tileLayer/Pl3xmapTileLayer";
|
||||||
|
import {LiveAtlasTileLayer, LiveAtlasTileLayerOptions} from "@/leaflet/tileLayer/LiveAtlasTileLayer";
|
||||||
|
|
||||||
export default class Pl3xmapMapProvider extends MapProvider {
|
export default class Pl3xmapMapProvider extends MapProvider {
|
||||||
private configurationAbort?: AbortController = undefined;
|
private configurationAbort?: AbortController = undefined;
|
||||||
@ -61,8 +63,16 @@ export default class Pl3xmapMapProvider extends MapProvider {
|
|||||||
private markerSets: Map<string, LiveAtlasMarkerSet> = new Map();
|
private markerSets: Map<string, LiveAtlasMarkerSet> = new Map();
|
||||||
private markers = new Map<string, Map<string, LiveAtlasMarker>>();
|
private markers = new Map<string, Map<string, LiveAtlasMarker>>();
|
||||||
|
|
||||||
constructor(config: LiveAtlasServerDefinition) {
|
constructor(config: string) {
|
||||||
super(config);
|
super(config);
|
||||||
|
|
||||||
|
if(!this.config) {
|
||||||
|
throw new ConfigurationError("URL missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.config.slice(-1) !== '/') {
|
||||||
|
this.config = `${config}/`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static buildServerConfig(response: any): LiveAtlasServerConfig {
|
private static buildServerConfig(response: any): LiveAtlasServerConfig {
|
||||||
@ -168,7 +178,7 @@ export default class Pl3xmapMapProvider extends MapProvider {
|
|||||||
background: 'transparent',
|
background: 'transparent',
|
||||||
backgroundDay: 'transparent',
|
backgroundDay: 'transparent',
|
||||||
backgroundNight: 'transparent',
|
backgroundNight: 'transparent',
|
||||||
icon: world.icon ? `${this.config.pl3xmap}images/icon/${world.icon}.png` : undefined,
|
icon: world.icon ? `${this.config}images/icon/${world.icon}.png` : undefined,
|
||||||
imageFormat: 'png',
|
imageFormat: 'png',
|
||||||
name: 'flat',
|
name: 'flat',
|
||||||
displayName: 'Flat',
|
displayName: 'Flat',
|
||||||
@ -226,7 +236,7 @@ export default class Pl3xmapMapProvider extends MapProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise<void> {
|
private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise<void> {
|
||||||
const url = `${this.config.pl3xmap}tiles/${world.name}/markers.json`;
|
const url = `${this.config}tiles/${world.name}/markers.json`;
|
||||||
|
|
||||||
if(this.markersAbort) {
|
if(this.markersAbort) {
|
||||||
this.markersAbort.abort();
|
this.markersAbort.abort();
|
||||||
@ -424,7 +434,7 @@ export default class Pl3xmapMapProvider extends MapProvider {
|
|||||||
|
|
||||||
this.configurationAbort = new AbortController();
|
this.configurationAbort = new AbortController();
|
||||||
|
|
||||||
const baseUrl = this.config.pl3xmap,
|
const baseUrl = this.config,
|
||||||
response = await Pl3xmapMapProvider.getJSON(`${baseUrl}tiles/settings.json`, this.configurationAbort.signal);
|
response = await Pl3xmapMapProvider.getJSON(`${baseUrl}tiles/settings.json`, this.configurationAbort.signal);
|
||||||
|
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
@ -459,8 +469,12 @@ export default class Pl3xmapMapProvider extends MapProvider {
|
|||||||
this.markers.clear();
|
this.markers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createTileLayer(options: LiveAtlasTileLayerOptions): LiveAtlasTileLayer {
|
||||||
|
return new Pl3xmapTileLayer(options);
|
||||||
|
}
|
||||||
|
|
||||||
private async getPlayers(): Promise<Set<LiveAtlasPlayer>> {
|
private async getPlayers(): Promise<Set<LiveAtlasPlayer>> {
|
||||||
const url = `${this.config.pl3xmap}tiles/players.json`;
|
const url = `${this.config}tiles/players.json`;
|
||||||
|
|
||||||
if(this.playersAbort) {
|
if(this.playersAbort) {
|
||||||
this.playersAbort.abort();
|
this.playersAbort.abort();
|
||||||
@ -557,23 +571,6 @@ export default class Pl3xmapMapProvider extends MapProvider {
|
|||||||
|
|
||||||
this.markerUpdateTimeout = null;
|
this.markerUpdateTimeout = null;
|
||||||
this.playerUpdateTimeout = null;
|
this.playerUpdateTimeout = null;
|
||||||
}
|
|
||||||
|
|
||||||
getTilesUrl(): string {
|
|
||||||
return `${this.config.pl3xmap}tiles/`;
|
|
||||||
}
|
|
||||||
|
|
||||||
getPlayerHeadUrl(head: HeadQueueEntry): string {
|
|
||||||
//TODO: Listen to config
|
|
||||||
return 'https://mc-heads.net/avatar/{uuid}/16'.replace('{uuid}', head.uuid || '');
|
|
||||||
}
|
|
||||||
|
|
||||||
getMarkerIconUrl(icon: string): string {
|
|
||||||
return `${this.config.pl3xmap}images/icon/registered/${icon}.png`;
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy() {
|
|
||||||
super.destroy();
|
|
||||||
|
|
||||||
if(this.configurationAbort) {
|
if(this.configurationAbort) {
|
||||||
this.configurationAbort.abort();
|
this.configurationAbort.abort();
|
||||||
@ -587,4 +584,17 @@ export default class Pl3xmapMapProvider extends MapProvider {
|
|||||||
this.markersAbort.abort();
|
this.markersAbort.abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTilesUrl(): string {
|
||||||
|
return `${this.config}tiles/`;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPlayerHeadUrl(head: HeadQueueEntry): string {
|
||||||
|
//TODO: Listen to config
|
||||||
|
return 'https://mc-heads.net/avatar/{uuid}/16'.replace('{uuid}', head.uuid || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
getMarkerIconUrl(icon: string): string {
|
||||||
|
return `${this.config}images/icon/registered/${icon}.png`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@ import {
|
|||||||
LiveAtlasServerMessageConfig,
|
LiveAtlasServerMessageConfig,
|
||||||
LiveAtlasPlayer,
|
LiveAtlasPlayer,
|
||||||
LiveAtlasMarkerSet,
|
LiveAtlasMarkerSet,
|
||||||
LiveAtlasServerDefinition,
|
|
||||||
LiveAtlasServerConfig,
|
LiveAtlasServerConfig,
|
||||||
LiveAtlasChat,
|
LiveAtlasChat,
|
||||||
LiveAtlasPartialComponentConfig,
|
LiveAtlasPartialComponentConfig,
|
||||||
@ -41,9 +40,8 @@ import {
|
|||||||
LiveAtlasUIModal,
|
LiveAtlasUIModal,
|
||||||
LiveAtlasSidebarSectionState, LiveAtlasMarker, LiveAtlasMapViewTarget
|
LiveAtlasSidebarSectionState, LiveAtlasMarker, LiveAtlasMapViewTarget
|
||||||
} from "@/index";
|
} from "@/index";
|
||||||
import DynmapMapProvider from "@/providers/DynmapMapProvider";
|
|
||||||
import Pl3xmapMapProvider from "@/providers/Pl3xmapMapProvider";
|
|
||||||
import {getGlobalMessages} from "@/util";
|
import {getGlobalMessages} from "@/util";
|
||||||
|
import {getServerMapProvider} from "@/util/config";
|
||||||
|
|
||||||
export type CurrentMapPayload = {
|
export type CurrentMapPayload = {
|
||||||
worldName: string;
|
worldName: string;
|
||||||
@ -383,19 +381,9 @@ export const mutations: MutationTree<State> & Mutations = {
|
|||||||
|
|
||||||
if(state.currentMapProvider) {
|
if(state.currentMapProvider) {
|
||||||
state.currentMapProvider.stopUpdates();
|
state.currentMapProvider.stopUpdates();
|
||||||
state.currentMapProvider.destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(state.currentServer!.type) {
|
state.currentMapProvider = getServerMapProvider(serverName);
|
||||||
case 'pl3xmap':
|
|
||||||
state.currentMapProvider = Object.seal(
|
|
||||||
new Pl3xmapMapProvider(state.servers.get(serverName) as LiveAtlasServerDefinition));
|
|
||||||
break;
|
|
||||||
case 'dynmap':
|
|
||||||
state.currentMapProvider = Object.seal(
|
|
||||||
new DynmapMapProvider(state.servers.get(serverName) as LiveAtlasServerDefinition));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//Sets the currently active map/world
|
//Sets the currently active map/world
|
||||||
|
@ -18,10 +18,27 @@ import {LiveAtlasGlobalConfig, LiveAtlasServerDefinition} from "@/index";
|
|||||||
import ConfigurationError from "@/errors/ConfigurationError";
|
import ConfigurationError from "@/errors/ConfigurationError";
|
||||||
import {DynmapUrlConfig} from "@/dynmap";
|
import {DynmapUrlConfig} from "@/dynmap";
|
||||||
import {useStore} from "@/store";
|
import {useStore} from "@/store";
|
||||||
|
import MapProvider from "@/providers/MapProvider";
|
||||||
|
import DynmapMapProvider from "@/providers/DynmapMapProvider";
|
||||||
|
|
||||||
const expectedConfigVersion = 1;
|
const expectedConfigVersion = 1;
|
||||||
|
|
||||||
const validateLiveAtlasConfiguration = (config: any): Map<string, LiveAtlasServerDefinition> => {
|
const registeredProviders: Map<string, new (config: any) => MapProvider> = new Map();
|
||||||
|
const serverProviders: Map<string, MapProvider> = new Map();
|
||||||
|
|
||||||
|
export const registerMapProvider = (id: string, provider: new (config: any) => MapProvider) => {
|
||||||
|
if(registeredProviders.has(id)) {
|
||||||
|
throw new TypeError(`${id} is already registered`);
|
||||||
|
}
|
||||||
|
|
||||||
|
registeredProviders.set(id, provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getServerMapProvider = (server: string): MapProvider | undefined => {
|
||||||
|
return serverProviders.get(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadLiveAtlasConfig = (config: any): Map<string, LiveAtlasServerDefinition> => {
|
||||||
const check = '\nCheck your server configuration in index.html is correct.',
|
const check = '\nCheck your server configuration in index.html is correct.',
|
||||||
result = new Map<string, LiveAtlasServerDefinition>();
|
result = new Map<string, LiveAtlasServerDefinition>();
|
||||||
|
|
||||||
@ -35,100 +52,52 @@ const validateLiveAtlasConfiguration = (config: any): Map<string, LiveAtlasServe
|
|||||||
}
|
}
|
||||||
|
|
||||||
const serverConfig = config[server];
|
const serverConfig = config[server];
|
||||||
|
let foundProvider = false;
|
||||||
|
|
||||||
if (!serverConfig || serverConfig.constructor !== Object || !Object.keys(serverConfig).length) {
|
for (const mapProvider of registeredProviders) {
|
||||||
throw new ConfigurationError(`Server '${server}': Configuration missing. ${check}`);
|
if(serverConfig && Object.hasOwnProperty.call(serverConfig, mapProvider[0])) {
|
||||||
|
try {
|
||||||
|
serverProviders.set(server, new mapProvider[1](serverConfig[mapProvider[0]]));
|
||||||
|
} catch(e: any) {
|
||||||
|
e.message = `Server "${server}": ${e.message}. ${check}`;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.set(server, serverConfig);
|
||||||
|
foundProvider = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!foundProvider) {
|
||||||
|
throw new ConfigurationError(`Server "${server}": No configuration found for any supported map type. ${check}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
serverConfig.id = server;
|
serverConfig.id = server;
|
||||||
|
|
||||||
//Squaremap and Pl3xmap are currently interchangeable
|
|
||||||
if(typeof serverConfig.squaremap !== 'undefined') {
|
|
||||||
serverConfig.pl3xmap = serverConfig.squaremap;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(typeof serverConfig.pl3xmap !== 'undefined') {
|
|
||||||
serverConfig.type = 'pl3xmap';
|
|
||||||
|
|
||||||
// Ensure trailing /
|
|
||||||
if(serverConfig.pl3xmap.slice(-1) !== '/') {
|
|
||||||
serverConfig.pl3xmap = `${serverConfig.pl3xmap}/`;
|
|
||||||
}
|
|
||||||
} else if(typeof serverConfig.dynmap !== 'undefined') {
|
|
||||||
if (!serverConfig.dynmap || serverConfig.dynmap.constructor !== Object) {
|
|
||||||
throw new ConfigurationError(`Server '${server}': Dynmap configuration object missing. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!serverConfig.dynmap.configuration) {
|
|
||||||
throw new ConfigurationError(`Server '${server}': Dynmap configuration URL missing. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!serverConfig.dynmap.update) {
|
|
||||||
throw new ConfigurationError(`Server '${server}': Dynmap update URL missing. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!serverConfig.dynmap.markers) {
|
|
||||||
throw new ConfigurationError(`Server '${server}': Dynmap markers URL missing. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!serverConfig.dynmap.tiles) {
|
|
||||||
throw new ConfigurationError(`Server '${server}': Dynmap tiles URL missing. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!serverConfig.dynmap.sendmessage) {
|
|
||||||
throw new ConfigurationError(`Server '${server}': Dynmap sendmessage URL missing. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
serverConfig.type = 'dynmap';
|
|
||||||
} else {
|
|
||||||
throw new ConfigurationError(`Server '${server}': No Dynmap or Pl3xmap configuration defined. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.set(server, serverConfig);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateDynmapConfiguration = (config: DynmapUrlConfig): Map<string, LiveAtlasServerDefinition> => {
|
const loadDefaultConfig = (config: DynmapUrlConfig): Map<string, LiveAtlasServerDefinition> => {
|
||||||
const check = '\nCheck your standalone/config.js file exists and is being loaded correctly.';
|
const check = '\nCheck your standalone/config.js file exists and is being loaded correctly.';
|
||||||
|
|
||||||
if (!config) {
|
|
||||||
throw new ConfigurationError(`Dynmap configuration is missing. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config.configuration) {
|
|
||||||
throw new ConfigurationError(`Dynmap configuration URL is missing. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config.update) {
|
|
||||||
throw new ConfigurationError(`Dynmap update URL is missing. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config.markers) {
|
|
||||||
throw new ConfigurationError(`Dynmap markers URL is missing. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config.tiles) {
|
|
||||||
throw new ConfigurationError(`Dynmap tiles URL is missing. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config.sendmessage) {
|
|
||||||
throw new ConfigurationError(`Dynmap sendmessage URL is missing. ${check}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = new Map<string, LiveAtlasServerDefinition>();
|
const result = new Map<string, LiveAtlasServerDefinition>();
|
||||||
result.set('dynmap', {
|
result.set('dynmap', {
|
||||||
id: 'dynmap',
|
id: 'dynmap',
|
||||||
label: 'dynmap',
|
label: 'dynmap',
|
||||||
type: 'dynmap',
|
|
||||||
dynmap: config
|
dynmap: config
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
serverProviders.set('dynmap', new DynmapMapProvider(config));
|
||||||
|
} catch (e: any) {
|
||||||
|
e.message = `${e.message}. ${check}`;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getServerDefinitions = (config: LiveAtlasGlobalConfig): Map<string, LiveAtlasServerDefinition> => {
|
export const loadConfig = (config: LiveAtlasGlobalConfig): Map<string, LiveAtlasServerDefinition> => {
|
||||||
if (!config) {
|
if (!config) {
|
||||||
throw new ConfigurationError(`No configuration found.\nCheck for any syntax errors in your configuration in index.html. Your browser console may contain additional information.`);
|
throw new ConfigurationError(`No configuration found.\nCheck for any syntax errors in your configuration in index.html. Your browser console may contain additional information.`);
|
||||||
}
|
}
|
||||||
@ -138,9 +107,9 @@ export const getServerDefinitions = (config: LiveAtlasGlobalConfig): Map<string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof config.servers !== 'undefined') {
|
if (typeof config.servers !== 'undefined') {
|
||||||
return validateLiveAtlasConfiguration(config.servers);
|
return loadLiveAtlasConfig(config.servers);
|
||||||
}
|
}
|
||||||
|
|
||||||
return validateDynmapConfiguration(window.config?.url || null);
|
return loadDefaultConfig(window.config?.url || null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user