diff --git a/src/components/map/vector/Areas.vue b/src/components/map/vector/Areas.vue index 1becc7a..99b12cc 100644 --- a/src/components/map/vector/Areas.vue +++ b/src/components/map/vector/Areas.vue @@ -23,6 +23,7 @@ import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup"; import LiveAtlasPolygon from "@/leaflet/vector/LiveAtlasPolygon"; import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline"; import {LiveAtlasArea, LiveAtlasMarkerSet} from "@/index"; +import {nonReactiveState} from "@/store/state"; export default defineComponent({ props: { @@ -51,7 +52,7 @@ export default defineComponent({ createAreas = () => { const converter = currentMap.value!.locationToLatLng.bind(currentMap.value); - props.set.areas.forEach((area: LiveAtlasArea, id: string) => { + nonReactiveState.markers.get(props.set.id)!.areas.forEach((area: LiveAtlasArea, id: string) => { const layer = createArea(area, converter); layers.set(id, layer); @@ -103,7 +104,7 @@ export default defineComponent({ if(newValue && (!oldValue || oldValue.world === newValue.world)) { const converter = newValue.locationToLatLng.bind(newValue); - for (const [id, area] of props.set.areas) { + for (const [id, area] of nonReactiveState.markers.get(props.set.id)!.areas) { updateArea(layers.get(id), area, converter); } } diff --git a/src/components/map/vector/Circles.vue b/src/components/map/vector/Circles.vue index b25dd17..e6893ca 100644 --- a/src/components/map/vector/Circles.vue +++ b/src/components/map/vector/Circles.vue @@ -23,6 +23,7 @@ import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline"; import LiveAtlasPolygon from "@/leaflet/vector/LiveAtlasPolygon"; import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup"; import {LiveAtlasCircle, LiveAtlasMarkerSet} from "@/index"; +import {nonReactiveState} from "@/store/state"; export default defineComponent({ props: { @@ -51,7 +52,7 @@ export default defineComponent({ createCircles = () => { const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap); - props.set.circles.forEach((circle: LiveAtlasCircle, id: string) => { + nonReactiveState.markers.get(props.set.id)!.circles.forEach((circle: LiveAtlasCircle, id: string) => { const layer = createCircle(circle, converter); layers.set(id, layer); @@ -103,7 +104,7 @@ export default defineComponent({ if(newValue && (!oldValue || oldValue.world === newValue.world)) { const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap); - for (const [id, circle] of props.set.circles) { + for (const [id, circle] of nonReactiveState.markers.get(props.set.id)!.circles) { updateCircle(layers.get(id), circle, converter); } } diff --git a/src/components/map/vector/Lines.vue b/src/components/map/vector/Lines.vue index fc22aff..dfdfc41 100644 --- a/src/components/map/vector/Lines.vue +++ b/src/components/map/vector/Lines.vue @@ -22,6 +22,7 @@ import {createLine, updateLine} from "@/util/lines"; import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline"; import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup"; import {LiveAtlasLine, LiveAtlasMarkerSet} from "@/index"; +import {nonReactiveState} from "@/store/state"; export default defineComponent({ props: { @@ -50,7 +51,7 @@ export default defineComponent({ createLines = () => { const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap); - props.set.lines.forEach((line: LiveAtlasLine, id: string) => { + nonReactiveState.markers.get(props.set.id)!.lines.forEach((line: LiveAtlasLine, id: string) => { const layer = createLine(line, converter); layers.set(id, layer); @@ -102,7 +103,7 @@ export default defineComponent({ if(newValue && (!oldValue || oldValue.world === newValue.world)) { const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap); - for (const [id, line] of props.set.lines) { + for (const [id, line] of nonReactiveState.markers.get(props.set.id)!.lines) { updateLine(layers.get(id), line, converter); } } diff --git a/src/components/map/vector/Markers.vue b/src/components/map/vector/Markers.vue index cd9b0a4..01de292 100644 --- a/src/components/map/vector/Markers.vue +++ b/src/components/map/vector/Markers.vue @@ -22,6 +22,7 @@ import {ActionTypes} from "@/store/action-types"; import {createMarker, updateMarker} from "@/util/markers"; import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup"; import {LiveAtlasMarker, LiveAtlasMarkerSet} from "@/index"; +import {nonReactiveState} from "@/store/state"; export default defineComponent({ props: { @@ -50,7 +51,7 @@ export default defineComponent({ createMarkers = () => { const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap); - props.set.markers.forEach((marker: LiveAtlasMarker, id: string) => { + nonReactiveState.markers.get(props.set.id)!.markers.forEach((marker: LiveAtlasMarker, id: string) => { const layer = createMarker(marker, converter); layers.set(id, layer); @@ -102,7 +103,7 @@ export default defineComponent({ if(newValue && (!oldValue || oldValue.world === newValue.world)) { const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap); - for (const [id, marker] of props.set.markers) { + for (const [id, marker] of nonReactiveState.markers.get(props.set.id)!.markers) { updateMarker(layers.get(id), marker, converter); } } diff --git a/src/index.d.ts b/src/index.d.ts index a3559a1..206c968 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -228,7 +228,10 @@ interface LiveAtlasMarkerSet { minZoom?: number; maxZoom?: number; showLabels?: boolean; - markers: Map; +} + +interface LiveAtlasMarkerSetContents { + markers: Map, areas: Map; lines: Map; circles: Map; diff --git a/src/providers/DynmapMapProvider.ts b/src/providers/DynmapMapProvider.ts index 1d634b3..7a48780 100644 --- a/src/providers/DynmapMapProvider.ts +++ b/src/providers/DynmapMapProvider.ts @@ -16,7 +16,7 @@ import { HeadQueueEntry, - LiveAtlasMarkerSet, + LiveAtlasMarkerSet, LiveAtlasMarkerSetContents, LiveAtlasPlayer, LiveAtlasServerDefinition, LiveAtlasWorldDefinition @@ -47,11 +47,14 @@ export default class DynmapMapProvider extends MapProvider { private updateTimestamp: Date = new Date(); private updateInterval: number = 3000; + private markerSets: Map = new Map(); + private markers = new Map(); + constructor(config: LiveAtlasServerDefinition) { super(config); } - private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise> { + private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise { const url = `${this.config.dynmap!.markers}_markers_/marker_${world.name}.json`; if(this.markersAbort) { @@ -61,7 +64,6 @@ export default class DynmapMapProvider extends MapProvider { this.markersAbort = new AbortController(); const response = await this.getJSON(url, this.markersAbort.signal); - const sets: Map = new Map(); response.sets = response.sets || {}; @@ -71,21 +73,16 @@ export default class DynmapMapProvider extends MapProvider { } const set: MarkerSet = response.sets[key], - markers = buildMarkers(set.markers || {}), - circles = buildCircles(set.circles || {}), - areas = buildAreas(set.areas || {}), - lines = buildLines(set.lines || {}); + markerSet = buildMarkerSet(key, set); - sets.set(key, { - ...buildMarkerSet(key, set), - markers, - circles, - areas, - lines, - }); + this.markerSets.set(key, markerSet); + this.markers.set(key, Object.seal({ + markers: buildMarkers(set.markers || {}), + areas: buildAreas(set.areas || {}), + lines: buildLines(set.lines || {}), + circles: buildCircles(set.circles || {}), + })); } - - return sets; } async loadServerConfiguration(): Promise { @@ -115,9 +112,13 @@ export default class DynmapMapProvider extends MapProvider { } async populateWorld(world: LiveAtlasWorldDefinition): Promise { - const markerSets = await this.getMarkerSets(world); + await this.getMarkerSets(world); - this.store.commit(MutationTypes.SET_MARKER_SETS, markerSets); + this.store.commit(MutationTypes.SET_MARKER_SETS, this.markerSets); + this.store.commit(MutationTypes.SET_MARKERS, this.markers); + + this.markerSets.clear(); + this.markers.clear(); } private async getUpdate(): Promise { diff --git a/src/providers/Pl3xmapMapProvider.ts b/src/providers/Pl3xmapMapProvider.ts index 1276fe0..f063ef6 100644 --- a/src/providers/Pl3xmapMapProvider.ts +++ b/src/providers/Pl3xmapMapProvider.ts @@ -22,7 +22,7 @@ import { LiveAtlasDimension, LiveAtlasLine, LiveAtlasMarker, - LiveAtlasMarkerSet, + LiveAtlasMarkerSet, LiveAtlasMarkerSetContents, LiveAtlasPartialComponentConfig, LiveAtlasPlayer, LiveAtlasServerConfig, @@ -56,6 +56,9 @@ export default class Pl3xmapMapProvider extends MapProvider { components: LiveAtlasPartialComponentConfig, }> = new Map(); + private markerSets: Map = new Map(); + private markers = new Map(); + constructor(config: LiveAtlasServerDefinition) { super(config); } @@ -220,7 +223,7 @@ export default class Pl3xmapMapProvider extends MapProvider { return components; } - private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise> { + private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise { const url = `${this.config.pl3xmap}tiles/${world.name}/markers.json`; if(this.markersAbort) { @@ -230,10 +233,9 @@ export default class Pl3xmapMapProvider extends MapProvider { this.markersAbort = new AbortController(); const response = await Pl3xmapMapProvider.getJSON(url, this.markersAbort.signal); - const sets: Map = new Map(); if(!Array.isArray(response)) { - return sets; + return; } response.forEach(set => { @@ -277,27 +279,19 @@ export default class Pl3xmapMapProvider extends MapProvider { } }); - - const e = { + this.markerSets.set(id, { id, label: set.name || "Unnamed set", hidden: set.hide || false, priority: set.order || 0, - showLabels: false, - markers, - circles, - areas, - lines, - }; - - sets.set(id, e); + showLabels: false + }); + this.markers.set(id, Object.seal({markers, circles, areas, lines})); }); - - return sets; } private static buildMarker(marker: any): LiveAtlasMarker { - return Object.seal({ + return { location: { x: marker.point?.x || 0, y: 0, @@ -308,11 +302,11 @@ export default class Pl3xmapMapProvider extends MapProvider { label: (marker.tooltip || '').trim(), isLabelHTML: true - }); + }; } private static buildRectangle(area: any): LiveAtlasArea { - return Object.seal({ + return { style: { stroke: typeof area.stroke !== 'undefined' ? !!area.stroke : true, color: area.color || '#3388ff', @@ -334,11 +328,11 @@ export default class Pl3xmapMapProvider extends MapProvider { tooltipContent: area.tooltip, popupContent: area.popup, isPopupHTML: true, - }); + }; } private static buildArea(area: any): LiveAtlasArea { - return Object.seal({ + return { style: { stroke: typeof area.stroke !== 'undefined' ? !!area.stroke : true, color: area.color || '#3388ff', @@ -355,11 +349,11 @@ export default class Pl3xmapMapProvider extends MapProvider { tooltipContent: area.tooltip, popupContent: area.popup, isPopupHTML: true, - }); + }; } private static buildLine(line: any): LiveAtlasLine { - return Object.seal({ + return { style: { stroke: typeof line.stroke !== 'undefined' ? !!line.stroke : true, color: line.color || '#3388ff', @@ -371,11 +365,11 @@ export default class Pl3xmapMapProvider extends MapProvider { tooltipContent: line.tooltip, popupContent: line.popup, isPopupHTML: true, - }); + }; } private static buildCircle(circle: any): LiveAtlasCircle { - return Object.seal({ + return { location: { x: circle.center?.x || 0, y: 0, @@ -396,7 +390,7 @@ export default class Pl3xmapMapProvider extends MapProvider { tooltipContent: circle.tooltip, popupContent: circle.popup, isPopupHTML: true - }); + }; } async loadServerConfiguration(): Promise { @@ -427,14 +421,18 @@ export default class Pl3xmapMapProvider extends MapProvider { } async populateWorld(world: LiveAtlasWorldDefinition) { - const markerSets = await this.getMarkerSets(world), - worldConfig = this.worldComponents.get(world.name); + const worldConfig = this.worldComponents.get(world.name); + await this.getMarkerSets(world); this.playerUpdateInterval = this.worldPlayerUpdateIntervals.get(world.name) || 3000; this.markerUpdateInterval = this.worldMarkerUpdateIntervals.get(world.name) || 3000; - this.store.commit(MutationTypes.SET_MARKER_SETS, markerSets); + this.store.commit(MutationTypes.SET_MARKER_SETS, this.markerSets); + this.store.commit(MutationTypes.SET_MARKERS, this.markers); this.store.commit(MutationTypes.SET_COMPONENTS, worldConfig!.components); + + this.markerSets.clear(); + this.markers.clear(); } private async getPlayers(): Promise> { @@ -453,7 +451,7 @@ export default class Pl3xmapMapProvider extends MapProvider { players.add({ name: (player.name || '').toLowerCase(), uuid: player.uuid, - displayName: player.name || "", + displayName: player.display_name || player.name || "", health: player.health || 0, armor: player.armor || 0, sort: 0, diff --git a/src/store/mutation-types.ts b/src/store/mutation-types.ts index b3de3b2..17e6227 100644 --- a/src/store/mutation-types.ts +++ b/src/store/mutation-types.ts @@ -23,6 +23,7 @@ export enum MutationTypes { SET_WORLDS = 'setWorlds', SET_COMPONENTS = 'setComponents', SET_MARKER_SETS = 'setMarkerSets', + SET_MARKERS = 'setMarkers', SET_WORLD_STATE = 'setWorldState', ADD_MARKER_SET_UPDATES = 'addMarkerSetUpdates', ADD_TILE_UPDATES = 'addTileUpdates', diff --git a/src/store/mutations.ts b/src/store/mutations.ts index 176067f..21f0396 100644 --- a/src/store/mutations.ts +++ b/src/store/mutations.ts @@ -16,7 +16,7 @@ import {MutationTree} from "vuex"; import {MutationTypes} from "@/store/mutation-types"; -import {State} from "@/store/state"; +import {nonReactiveState, State} from "@/store/state"; import { DynmapMarkerSetUpdates, DynmapTileUpdate @@ -44,7 +44,7 @@ import { LiveAtlasPartialComponentConfig, LiveAtlasComponentConfig, LiveAtlasUIModal, - LiveAtlasSidebarSectionState + LiveAtlasSidebarSectionState, LiveAtlasMarkerSetContents } from "@/index"; import DynmapMapProvider from "@/providers/DynmapMapProvider"; import Pl3xmapMapProvider from "@/providers/Pl3xmapMapProvider"; @@ -61,7 +61,8 @@ export type Mutations = { [MutationTypes.SET_SERVER_MESSAGES](state: S, messages: LiveAtlasServerMessageConfig): void [MutationTypes.SET_WORLDS](state: S, worlds: Array): void [MutationTypes.SET_COMPONENTS](state: S, components: LiveAtlasPartialComponentConfig | LiveAtlasComponentConfig): void - [MutationTypes.SET_MARKER_SETS](state: S, worlds: Map): void + [MutationTypes.SET_MARKER_SETS](state: S, markerSets: Map): void + [MutationTypes.SET_MARKERS](state: S, markers: Map): void [MutationTypes.SET_WORLD_STATE](state: S, worldState: LiveAtlasWorldState): void [MutationTypes.ADD_MARKER_SET_UPDATES](state: S, updates: Map): void [MutationTypes.ADD_TILE_UPDATES](state: S, updates: Array): void @@ -259,6 +260,7 @@ export const mutations: MutationTree & Mutations = { [MutationTypes.SET_MARKER_SETS](state: State, markerSets: Map) { state.markerSets.clear(); state.pendingSetUpdates.clear(); + nonReactiveState.markers.clear(); for(const entry of markerSets) { state.markerSets.set(entry[0], entry[1]); @@ -268,6 +270,21 @@ export const mutations: MutationTree & Mutations = { circleUpdates: [], lineUpdates: [], }); + nonReactiveState.markers.set(entry[0], { + markers: new Map(), + areas: new Map(), + lines: new Map(), + circles: new Map(), + }); + } + }, + + //Sets the existing marker sets from the last marker fetch + [MutationTypes.SET_MARKERS](state: State, markers: Map) { + nonReactiveState.markers.clear(); + + for(const entry of markers) { + nonReactiveState.markers.set(entry[0], entry[1]); } }, @@ -291,10 +308,6 @@ export const mutations: MutationTree & Mutations = { priority: entry[1].payload.priority, label: entry[1].payload.label, hidden: entry[1].payload.hidden, - markers: Object.freeze(new Map()) as Map, - areas: Object.freeze(new Map()) as Map, - circles: Object.freeze(new Map()) as Map, - lines: Object.freeze(new Map()) as Map, }); state.pendingSetUpdates.set(entry[0], { @@ -310,6 +323,7 @@ export const mutations: MutationTree & Mutations = { } const set = state.markerSets.get(entry[0]) as LiveAtlasMarkerSet, + setContents = nonReactiveState.markers.get(entry[0]) as LiveAtlasMarkerSetContents, setUpdates = state.pendingSetUpdates.get(entry[0]) as DynmapMarkerSetUpdates; //Delete the set if it has been deleted @@ -332,33 +346,33 @@ export const mutations: MutationTree & Mutations = { //Update non-reactive lists for(const update of entry[1].markerUpdates) { if(update.removed) { - set.markers.delete(update.id); + setContents.markers.delete(update.id); } else { - set.markers.set(update.id, update.payload as LiveAtlasMarker); + setContents.markers.set(update.id, update.payload as LiveAtlasMarker); } } for(const update of entry[1].areaUpdates) { if(update.removed) { - set.areas.delete(update.id); + setContents.areas.delete(update.id); } else { - set.areas.set(update.id, update.payload as LiveAtlasArea); + setContents.areas.set(update.id, update.payload as LiveAtlasArea); } } for(const update of entry[1].circleUpdates) { if(update.removed) { - set.circles.delete(update.id); + setContents.circles.delete(update.id); } else { - set.circles.set(update.id, update.payload as LiveAtlasCircle); + setContents.circles.set(update.id, update.payload as LiveAtlasCircle); } } for(const update of entry[1].lineUpdates) { if(update.removed) { - set.lines.delete(update.id); + setContents.lines.delete(update.id); } else { - set.lines.set(update.id, update.payload as LiveAtlasLine); + setContents.lines.set(update.id, update.payload as LiveAtlasLine); } } diff --git a/src/store/state.ts b/src/store/state.ts index 4fe5f1b..682f180 100644 --- a/src/store/state.ts +++ b/src/store/state.ts @@ -35,7 +35,8 @@ import { LiveAtlasServerConfig, LiveAtlasChat, LiveAtlasUIModal, - LiveAtlasSidebarSectionState + LiveAtlasSidebarSectionState, + LiveAtlasMarkerSetContents } from "@/index"; import LiveAtlasMapDefinition from "@/model/LiveAtlasMapDefinition"; @@ -189,7 +190,8 @@ export const state: State = { messages: [], }, - markerSets: new Map(), //Markers from world_markers.json. Contents of each set isn't reactive for performance reasons. + markerSets: new Map(), //Markers sets from world_markers.json, doesn't include the markers themselves for performance reasons + pendingSetUpdates: new Map(), //Pending updates to markers/areas/etc for each marker set pendingTileUpdates: [], //Pending updates to map tiles @@ -274,3 +276,7 @@ export const state: State = { }, } }; + +export const nonReactiveState = Object.freeze({ + markers: new Map(), +}); diff --git a/src/util/dynmap.ts b/src/util/dynmap.ts index b933d24..e996d5e 100644 --- a/src/util/dynmap.ts +++ b/src/util/dynmap.ts @@ -285,14 +285,14 @@ export function buildMarker(data: Marker): LiveAtlasMarker { let dimensions; if(data.dim) { - dimensions = data.dim.split('x').slice(0, 2).map(value => parseInt(value)); + dimensions = data.dim.split('x').filter(value => !isNaN(Number(value))); if(dimensions.length !== 2) { dimensions = undefined; } } - return Object.seal({ + return { label: data.label || '', //Dynmap#2288 currently means markup:false markers are still encoded //The planned solution for this is to always treat everything as HTML, so we'll do that here @@ -307,7 +307,7 @@ export function buildMarker(data: Marker): LiveAtlasMarker { minZoom: typeof data.minzoom !== 'undefined' && data.minzoom > -1 ? data.minzoom : undefined, maxZoom: typeof data.maxzoom !== 'undefined' && data.maxzoom > -1 ? data.maxzoom : undefined, popupContent: data.desc || undefined, - }); + }; } export function buildAreas(data: any): Map { @@ -325,12 +325,7 @@ export function buildAreas(data: any): Map { } export function buildArea(area: MarkerArea): LiveAtlasArea { - const opacity = area.fillopacity || 0, - x = area.x || [0, 0], - y: [number, number] = [area.ybottom || 0, area.ytop || 0], - z = area.z || [0, 0]; - - return Object.seal({ + return { style: { color: area.color || '#ff0000', opacity: area.opacity || 1, @@ -338,8 +333,12 @@ export function buildArea(area: MarkerArea): LiveAtlasArea { fillColor: area.fillcolor || '#ff0000', fillOpacity: area.fillopacity || 0, }, - outline: !opacity, - points: getPoints(x, y, z, !opacity), + outline: !area.fillopacity, + points: getPoints( + area.x || [0, 0], + [area.ybottom || 0, area.ytop || 0], + area.z || [0, 0], + !area.fillopacity), minZoom: typeof area.minzoom !== 'undefined' && area.minzoom > -1 ? area.minzoom : undefined, maxZoom: typeof area.maxzoom !== 'undefined' && area.maxzoom > -1 ? area.maxzoom : undefined, @@ -347,7 +346,7 @@ export function buildArea(area: MarkerArea): LiveAtlasArea { //The planned solution for this is to always treat everything as HTML, so we'll do that here isPopupHTML: true, //area.desc ? true : area.markup || false, popupContent: area.desc || area.label || undefined, - }); + }; } export function buildLines(data: any): Map { @@ -365,7 +364,7 @@ export function buildLines(data: any): Map { } export function buildLine(line: MarkerLine): LiveAtlasLine { - return Object.seal({ + return { style: { color: line.color || '#ff0000', opacity: line.opacity || 1, @@ -379,7 +378,7 @@ export function buildLine(line: MarkerLine): LiveAtlasLine { //The planned solution for this is to always treat everything as HTML, so we'll do that here isPopupHTML: true, popupContent: line.desc || line.label || undefined, - }); + }; } export function buildCircles(data: any): Map { @@ -397,7 +396,7 @@ export function buildCircles(data: any): Map { } export function buildCircle(circle: MarkerCircle): LiveAtlasCircle { - return Object.seal({ + return { location: { x: circle.x || 0, y: circle.y || 0, @@ -418,7 +417,7 @@ export function buildCircle(circle: MarkerCircle): LiveAtlasCircle { //The planned solution for this is to always treat everything as HTML, so we'll do that here isPopupHTML: true, popupContent: circle.desc || circle.label || undefined, - }); + }; } export function buildUpdates(data: Array, lastUpdate: Date) {