Move marker set contents outside the store, other small optimisations.

Improves marker set creation performance by avoiding traversal of all markers when watching the marker set.

Various other small changes to reduce allocations when creating markers
This commit is contained in:
James Lyne 2022-01-11 16:08:30 +00:00
parent 6717cab096
commit ff77f09025
11 changed files with 116 additions and 90 deletions

View File

@ -23,6 +23,7 @@ import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
import LiveAtlasPolygon from "@/leaflet/vector/LiveAtlasPolygon"; import LiveAtlasPolygon from "@/leaflet/vector/LiveAtlasPolygon";
import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline"; import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline";
import {LiveAtlasArea, LiveAtlasMarkerSet} from "@/index"; import {LiveAtlasArea, LiveAtlasMarkerSet} from "@/index";
import {nonReactiveState} from "@/store/state";
export default defineComponent({ export default defineComponent({
props: { props: {
@ -51,7 +52,7 @@ export default defineComponent({
createAreas = () => { createAreas = () => {
const converter = currentMap.value!.locationToLatLng.bind(currentMap.value); 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); const layer = createArea(area, converter);
layers.set(id, layer); layers.set(id, layer);
@ -103,7 +104,7 @@ export default defineComponent({
if(newValue && (!oldValue || oldValue.world === newValue.world)) { if(newValue && (!oldValue || oldValue.world === newValue.world)) {
const converter = newValue.locationToLatLng.bind(newValue); 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); updateArea(layers.get(id), area, converter);
} }
} }

View File

@ -23,6 +23,7 @@ import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline";
import LiveAtlasPolygon from "@/leaflet/vector/LiveAtlasPolygon"; import LiveAtlasPolygon from "@/leaflet/vector/LiveAtlasPolygon";
import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup"; import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
import {LiveAtlasCircle, LiveAtlasMarkerSet} from "@/index"; import {LiveAtlasCircle, LiveAtlasMarkerSet} from "@/index";
import {nonReactiveState} from "@/store/state";
export default defineComponent({ export default defineComponent({
props: { props: {
@ -51,7 +52,7 @@ export default defineComponent({
createCircles = () => { createCircles = () => {
const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap); 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); const layer = createCircle(circle, converter);
layers.set(id, layer); layers.set(id, layer);
@ -103,7 +104,7 @@ export default defineComponent({
if(newValue && (!oldValue || oldValue.world === newValue.world)) { if(newValue && (!oldValue || oldValue.world === newValue.world)) {
const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap); 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); updateCircle(layers.get(id), circle, converter);
} }
} }

View File

@ -22,6 +22,7 @@ import {createLine, updateLine} from "@/util/lines";
import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline"; import LiveAtlasPolyline from "@/leaflet/vector/LiveAtlasPolyline";
import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup"; import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
import {LiveAtlasLine, LiveAtlasMarkerSet} from "@/index"; import {LiveAtlasLine, LiveAtlasMarkerSet} from "@/index";
import {nonReactiveState} from "@/store/state";
export default defineComponent({ export default defineComponent({
props: { props: {
@ -50,7 +51,7 @@ export default defineComponent({
createLines = () => { createLines = () => {
const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap); 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); const layer = createLine(line, converter);
layers.set(id, layer); layers.set(id, layer);
@ -102,7 +103,7 @@ export default defineComponent({
if(newValue && (!oldValue || oldValue.world === newValue.world)) { if(newValue && (!oldValue || oldValue.world === newValue.world)) {
const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap); 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); updateLine(layers.get(id), line, converter);
} }
} }

View File

@ -22,6 +22,7 @@ import {ActionTypes} from "@/store/action-types";
import {createMarker, updateMarker} from "@/util/markers"; import {createMarker, updateMarker} from "@/util/markers";
import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup"; import LiveAtlasLayerGroup from "@/leaflet/layer/LiveAtlasLayerGroup";
import {LiveAtlasMarker, LiveAtlasMarkerSet} from "@/index"; import {LiveAtlasMarker, LiveAtlasMarkerSet} from "@/index";
import {nonReactiveState} from "@/store/state";
export default defineComponent({ export default defineComponent({
props: { props: {
@ -50,7 +51,7 @@ export default defineComponent({
createMarkers = () => { createMarkers = () => {
const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap); 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); const layer = createMarker(marker, converter);
layers.set(id, layer); layers.set(id, layer);
@ -102,7 +103,7 @@ export default defineComponent({
if(newValue && (!oldValue || oldValue.world === newValue.world)) { if(newValue && (!oldValue || oldValue.world === newValue.world)) {
const converter = currentMap.value!.locationToLatLng.bind(store.state.currentMap); 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); updateMarker(layers.get(id), marker, converter);
} }
} }

5
src/index.d.ts vendored
View File

@ -228,7 +228,10 @@ interface LiveAtlasMarkerSet {
minZoom?: number; minZoom?: number;
maxZoom?: number; maxZoom?: number;
showLabels?: boolean; showLabels?: boolean;
markers: Map<string, LiveAtlasMarker>; }
interface LiveAtlasMarkerSetContents {
markers: Map<string, LiveAtlasMarker>,
areas: Map<string, LiveAtlasArea>; areas: Map<string, LiveAtlasArea>;
lines: Map<string, LiveAtlasLine>; lines: Map<string, LiveAtlasLine>;
circles: Map<string, LiveAtlasCircle>; circles: Map<string, LiveAtlasCircle>;

View File

@ -16,7 +16,7 @@
import { import {
HeadQueueEntry, HeadQueueEntry,
LiveAtlasMarkerSet, LiveAtlasMarkerSet, LiveAtlasMarkerSetContents,
LiveAtlasPlayer, LiveAtlasPlayer,
LiveAtlasServerDefinition, LiveAtlasServerDefinition,
LiveAtlasWorldDefinition LiveAtlasWorldDefinition
@ -47,11 +47,14 @@ export default class DynmapMapProvider extends MapProvider {
private updateTimestamp: Date = new Date(); private updateTimestamp: Date = new Date();
private updateInterval: number = 3000; private updateInterval: number = 3000;
private markerSets: Map<string, LiveAtlasMarkerSet> = new Map();
private markers = new Map<string, LiveAtlasMarkerSetContents>();
constructor(config: LiveAtlasServerDefinition) { constructor(config: LiveAtlasServerDefinition) {
super(config); super(config);
} }
private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise<Map<string, LiveAtlasMarkerSet>> { private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise<void> {
const url = `${this.config.dynmap!.markers}_markers_/marker_${world.name}.json`; const url = `${this.config.dynmap!.markers}_markers_/marker_${world.name}.json`;
if(this.markersAbort) { if(this.markersAbort) {
@ -61,7 +64,6 @@ export default class DynmapMapProvider extends MapProvider {
this.markersAbort = new AbortController(); this.markersAbort = new AbortController();
const response = await this.getJSON(url, this.markersAbort.signal); const response = await this.getJSON(url, this.markersAbort.signal);
const sets: Map<string, LiveAtlasMarkerSet> = new Map();
response.sets = response.sets || {}; response.sets = response.sets || {};
@ -71,21 +73,16 @@ export default class DynmapMapProvider extends MapProvider {
} }
const set: MarkerSet = response.sets[key], const set: MarkerSet = response.sets[key],
markers = buildMarkers(set.markers || {}), markerSet = buildMarkerSet(key, set);
circles = buildCircles(set.circles || {}),
areas = buildAreas(set.areas || {}),
lines = buildLines(set.lines || {});
sets.set(key, { this.markerSets.set(key, markerSet);
...buildMarkerSet(key, set), this.markers.set(key, Object.seal({
markers, markers: buildMarkers(set.markers || {}),
circles, areas: buildAreas(set.areas || {}),
areas, lines: buildLines(set.lines || {}),
lines, circles: buildCircles(set.circles || {}),
}); }));
} }
return sets;
} }
async loadServerConfiguration(): Promise<void> { async loadServerConfiguration(): Promise<void> {
@ -115,9 +112,13 @@ export default class DynmapMapProvider extends MapProvider {
} }
async populateWorld(world: LiveAtlasWorldDefinition): Promise<void> { async populateWorld(world: LiveAtlasWorldDefinition): Promise<void> {
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<void> { private async getUpdate(): Promise<void> {

View File

@ -22,7 +22,7 @@ import {
LiveAtlasDimension, LiveAtlasDimension,
LiveAtlasLine, LiveAtlasLine,
LiveAtlasMarker, LiveAtlasMarker,
LiveAtlasMarkerSet, LiveAtlasMarkerSet, LiveAtlasMarkerSetContents,
LiveAtlasPartialComponentConfig, LiveAtlasPartialComponentConfig,
LiveAtlasPlayer, LiveAtlasPlayer,
LiveAtlasServerConfig, LiveAtlasServerConfig,
@ -56,6 +56,9 @@ export default class Pl3xmapMapProvider extends MapProvider {
components: LiveAtlasPartialComponentConfig, components: LiveAtlasPartialComponentConfig,
}> = new Map(); }> = new Map();
private markerSets: Map<string, LiveAtlasMarkerSet> = new Map();
private markers = new Map<string, LiveAtlasMarkerSetContents>();
constructor(config: LiveAtlasServerDefinition) { constructor(config: LiveAtlasServerDefinition) {
super(config); super(config);
} }
@ -220,7 +223,7 @@ export default class Pl3xmapMapProvider extends MapProvider {
return components; return components;
} }
private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise<Map<string, LiveAtlasMarkerSet>> { private async getMarkerSets(world: LiveAtlasWorldDefinition): Promise<void> {
const url = `${this.config.pl3xmap}tiles/${world.name}/markers.json`; const url = `${this.config.pl3xmap}tiles/${world.name}/markers.json`;
if(this.markersAbort) { if(this.markersAbort) {
@ -230,10 +233,9 @@ export default class Pl3xmapMapProvider extends MapProvider {
this.markersAbort = new AbortController(); this.markersAbort = new AbortController();
const response = await Pl3xmapMapProvider.getJSON(url, this.markersAbort.signal); const response = await Pl3xmapMapProvider.getJSON(url, this.markersAbort.signal);
const sets: Map<string, LiveAtlasMarkerSet> = new Map();
if(!Array.isArray(response)) { if(!Array.isArray(response)) {
return sets; return;
} }
response.forEach(set => { response.forEach(set => {
@ -277,27 +279,19 @@ export default class Pl3xmapMapProvider extends MapProvider {
} }
}); });
this.markerSets.set(id, {
const e = {
id, id,
label: set.name || "Unnamed set", label: set.name || "Unnamed set",
hidden: set.hide || false, hidden: set.hide || false,
priority: set.order || 0, priority: set.order || 0,
showLabels: false, showLabels: false
markers, });
circles, this.markers.set(id, Object.seal({markers, circles, areas, lines}));
areas,
lines,
};
sets.set(id, e);
}); });
return sets;
} }
private static buildMarker(marker: any): LiveAtlasMarker { private static buildMarker(marker: any): LiveAtlasMarker {
return Object.seal({ return {
location: { location: {
x: marker.point?.x || 0, x: marker.point?.x || 0,
y: 0, y: 0,
@ -308,11 +302,11 @@ export default class Pl3xmapMapProvider extends MapProvider {
label: (marker.tooltip || '').trim(), label: (marker.tooltip || '').trim(),
isLabelHTML: true isLabelHTML: true
}); };
} }
private static buildRectangle(area: any): LiveAtlasArea { private static buildRectangle(area: any): LiveAtlasArea {
return Object.seal({ return {
style: { style: {
stroke: typeof area.stroke !== 'undefined' ? !!area.stroke : true, stroke: typeof area.stroke !== 'undefined' ? !!area.stroke : true,
color: area.color || '#3388ff', color: area.color || '#3388ff',
@ -334,11 +328,11 @@ export default class Pl3xmapMapProvider extends MapProvider {
tooltipContent: area.tooltip, tooltipContent: area.tooltip,
popupContent: area.popup, popupContent: area.popup,
isPopupHTML: true, isPopupHTML: true,
}); };
} }
private static buildArea(area: any): LiveAtlasArea { private static buildArea(area: any): LiveAtlasArea {
return Object.seal({ return {
style: { style: {
stroke: typeof area.stroke !== 'undefined' ? !!area.stroke : true, stroke: typeof area.stroke !== 'undefined' ? !!area.stroke : true,
color: area.color || '#3388ff', color: area.color || '#3388ff',
@ -355,11 +349,11 @@ export default class Pl3xmapMapProvider extends MapProvider {
tooltipContent: area.tooltip, tooltipContent: area.tooltip,
popupContent: area.popup, popupContent: area.popup,
isPopupHTML: true, isPopupHTML: true,
}); };
} }
private static buildLine(line: any): LiveAtlasLine { private static buildLine(line: any): LiveAtlasLine {
return Object.seal({ return {
style: { style: {
stroke: typeof line.stroke !== 'undefined' ? !!line.stroke : true, stroke: typeof line.stroke !== 'undefined' ? !!line.stroke : true,
color: line.color || '#3388ff', color: line.color || '#3388ff',
@ -371,11 +365,11 @@ export default class Pl3xmapMapProvider extends MapProvider {
tooltipContent: line.tooltip, tooltipContent: line.tooltip,
popupContent: line.popup, popupContent: line.popup,
isPopupHTML: true, isPopupHTML: true,
}); };
} }
private static buildCircle(circle: any): LiveAtlasCircle { private static buildCircle(circle: any): LiveAtlasCircle {
return Object.seal({ return {
location: { location: {
x: circle.center?.x || 0, x: circle.center?.x || 0,
y: 0, y: 0,
@ -396,7 +390,7 @@ export default class Pl3xmapMapProvider extends MapProvider {
tooltipContent: circle.tooltip, tooltipContent: circle.tooltip,
popupContent: circle.popup, popupContent: circle.popup,
isPopupHTML: true isPopupHTML: true
}); };
} }
async loadServerConfiguration(): Promise<void> { async loadServerConfiguration(): Promise<void> {
@ -427,14 +421,18 @@ export default class Pl3xmapMapProvider extends MapProvider {
} }
async populateWorld(world: LiveAtlasWorldDefinition) { async populateWorld(world: LiveAtlasWorldDefinition) {
const markerSets = await this.getMarkerSets(world), const worldConfig = this.worldComponents.get(world.name);
worldConfig = this.worldComponents.get(world.name); await this.getMarkerSets(world);
this.playerUpdateInterval = this.worldPlayerUpdateIntervals.get(world.name) || 3000; this.playerUpdateInterval = this.worldPlayerUpdateIntervals.get(world.name) || 3000;
this.markerUpdateInterval = this.worldMarkerUpdateIntervals.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.store.commit(MutationTypes.SET_COMPONENTS, worldConfig!.components);
this.markerSets.clear();
this.markers.clear();
} }
private async getPlayers(): Promise<Set<LiveAtlasPlayer>> { private async getPlayers(): Promise<Set<LiveAtlasPlayer>> {
@ -453,7 +451,7 @@ export default class Pl3xmapMapProvider extends MapProvider {
players.add({ players.add({
name: (player.name || '').toLowerCase(), name: (player.name || '').toLowerCase(),
uuid: player.uuid, uuid: player.uuid,
displayName: player.name || "", displayName: player.display_name || player.name || "",
health: player.health || 0, health: player.health || 0,
armor: player.armor || 0, armor: player.armor || 0,
sort: 0, sort: 0,

View File

@ -23,6 +23,7 @@ export enum MutationTypes {
SET_WORLDS = 'setWorlds', SET_WORLDS = 'setWorlds',
SET_COMPONENTS = 'setComponents', SET_COMPONENTS = 'setComponents',
SET_MARKER_SETS = 'setMarkerSets', SET_MARKER_SETS = 'setMarkerSets',
SET_MARKERS = 'setMarkers',
SET_WORLD_STATE = 'setWorldState', SET_WORLD_STATE = 'setWorldState',
ADD_MARKER_SET_UPDATES = 'addMarkerSetUpdates', ADD_MARKER_SET_UPDATES = 'addMarkerSetUpdates',
ADD_TILE_UPDATES = 'addTileUpdates', ADD_TILE_UPDATES = 'addTileUpdates',

View File

@ -16,7 +16,7 @@
import {MutationTree} from "vuex"; import {MutationTree} from "vuex";
import {MutationTypes} from "@/store/mutation-types"; import {MutationTypes} from "@/store/mutation-types";
import {State} from "@/store/state"; import {nonReactiveState, State} from "@/store/state";
import { import {
DynmapMarkerSetUpdates, DynmapMarkerSetUpdates,
DynmapTileUpdate DynmapTileUpdate
@ -44,7 +44,7 @@ import {
LiveAtlasPartialComponentConfig, LiveAtlasPartialComponentConfig,
LiveAtlasComponentConfig, LiveAtlasComponentConfig,
LiveAtlasUIModal, LiveAtlasUIModal,
LiveAtlasSidebarSectionState LiveAtlasSidebarSectionState, LiveAtlasMarkerSetContents
} from "@/index"; } from "@/index";
import DynmapMapProvider from "@/providers/DynmapMapProvider"; import DynmapMapProvider from "@/providers/DynmapMapProvider";
import Pl3xmapMapProvider from "@/providers/Pl3xmapMapProvider"; import Pl3xmapMapProvider from "@/providers/Pl3xmapMapProvider";
@ -61,7 +61,8 @@ export type Mutations<S = State> = {
[MutationTypes.SET_SERVER_MESSAGES](state: S, messages: LiveAtlasServerMessageConfig): void [MutationTypes.SET_SERVER_MESSAGES](state: S, messages: LiveAtlasServerMessageConfig): void
[MutationTypes.SET_WORLDS](state: S, worlds: Array<LiveAtlasWorldDefinition>): void [MutationTypes.SET_WORLDS](state: S, worlds: Array<LiveAtlasWorldDefinition>): void
[MutationTypes.SET_COMPONENTS](state: S, components: LiveAtlasPartialComponentConfig | LiveAtlasComponentConfig): void [MutationTypes.SET_COMPONENTS](state: S, components: LiveAtlasPartialComponentConfig | LiveAtlasComponentConfig): void
[MutationTypes.SET_MARKER_SETS](state: S, worlds: Map<string, LiveAtlasMarkerSet>): void [MutationTypes.SET_MARKER_SETS](state: S, markerSets: Map<string, LiveAtlasMarkerSet>): void
[MutationTypes.SET_MARKERS](state: S, markers: Map<string, LiveAtlasMarkerSetContents>): void
[MutationTypes.SET_WORLD_STATE](state: S, worldState: LiveAtlasWorldState): void [MutationTypes.SET_WORLD_STATE](state: S, worldState: LiveAtlasWorldState): void
[MutationTypes.ADD_MARKER_SET_UPDATES](state: S, updates: Map<string, DynmapMarkerSetUpdates>): void [MutationTypes.ADD_MARKER_SET_UPDATES](state: S, updates: Map<string, DynmapMarkerSetUpdates>): void
[MutationTypes.ADD_TILE_UPDATES](state: S, updates: Array<DynmapTileUpdate>): void [MutationTypes.ADD_TILE_UPDATES](state: S, updates: Array<DynmapTileUpdate>): void
@ -259,6 +260,7 @@ export const mutations: MutationTree<State> & Mutations = {
[MutationTypes.SET_MARKER_SETS](state: State, markerSets: Map<string, LiveAtlasMarkerSet>) { [MutationTypes.SET_MARKER_SETS](state: State, markerSets: Map<string, LiveAtlasMarkerSet>) {
state.markerSets.clear(); state.markerSets.clear();
state.pendingSetUpdates.clear(); state.pendingSetUpdates.clear();
nonReactiveState.markers.clear();
for(const entry of markerSets) { for(const entry of markerSets) {
state.markerSets.set(entry[0], entry[1]); state.markerSets.set(entry[0], entry[1]);
@ -268,6 +270,21 @@ export const mutations: MutationTree<State> & Mutations = {
circleUpdates: [], circleUpdates: [],
lineUpdates: [], lineUpdates: [],
}); });
nonReactiveState.markers.set(entry[0], {
markers: new Map<string, LiveAtlasMarker>(),
areas: new Map<string, LiveAtlasArea>(),
lines: new Map<string, LiveAtlasLine>(),
circles: new Map<string, LiveAtlasCircle>(),
});
}
},
//Sets the existing marker sets from the last marker fetch
[MutationTypes.SET_MARKERS](state: State, markers: Map<string, LiveAtlasMarkerSetContents>) {
nonReactiveState.markers.clear();
for(const entry of markers) {
nonReactiveState.markers.set(entry[0], entry[1]);
} }
}, },
@ -291,10 +308,6 @@ export const mutations: MutationTree<State> & Mutations = {
priority: entry[1].payload.priority, priority: entry[1].payload.priority,
label: entry[1].payload.label, label: entry[1].payload.label,
hidden: entry[1].payload.hidden, hidden: entry[1].payload.hidden,
markers: Object.freeze(new Map()) as Map<string, LiveAtlasMarker>,
areas: Object.freeze(new Map()) as Map<string, LiveAtlasArea>,
circles: Object.freeze(new Map()) as Map<string, LiveAtlasCircle>,
lines: Object.freeze(new Map()) as Map<string, LiveAtlasLine>,
}); });
state.pendingSetUpdates.set(entry[0], { state.pendingSetUpdates.set(entry[0], {
@ -310,6 +323,7 @@ export const mutations: MutationTree<State> & Mutations = {
} }
const set = state.markerSets.get(entry[0]) as LiveAtlasMarkerSet, 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; setUpdates = state.pendingSetUpdates.get(entry[0]) as DynmapMarkerSetUpdates;
//Delete the set if it has been deleted //Delete the set if it has been deleted
@ -332,33 +346,33 @@ export const mutations: MutationTree<State> & Mutations = {
//Update non-reactive lists //Update non-reactive lists
for(const update of entry[1].markerUpdates) { for(const update of entry[1].markerUpdates) {
if(update.removed) { if(update.removed) {
set.markers.delete(update.id); setContents.markers.delete(update.id);
} else { } 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) { for(const update of entry[1].areaUpdates) {
if(update.removed) { if(update.removed) {
set.areas.delete(update.id); setContents.areas.delete(update.id);
} else { } 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) { for(const update of entry[1].circleUpdates) {
if(update.removed) { if(update.removed) {
set.circles.delete(update.id); setContents.circles.delete(update.id);
} else { } 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) { for(const update of entry[1].lineUpdates) {
if(update.removed) { if(update.removed) {
set.lines.delete(update.id); setContents.lines.delete(update.id);
} else { } else {
set.lines.set(update.id, update.payload as LiveAtlasLine); setContents.lines.set(update.id, update.payload as LiveAtlasLine);
} }
} }

View File

@ -35,7 +35,8 @@ import {
LiveAtlasServerConfig, LiveAtlasServerConfig,
LiveAtlasChat, LiveAtlasChat,
LiveAtlasUIModal, LiveAtlasUIModal,
LiveAtlasSidebarSectionState LiveAtlasSidebarSectionState,
LiveAtlasMarkerSetContents
} from "@/index"; } from "@/index";
import LiveAtlasMapDefinition from "@/model/LiveAtlasMapDefinition"; import LiveAtlasMapDefinition from "@/model/LiveAtlasMapDefinition";
@ -189,7 +190,8 @@ export const state: State = {
messages: [], 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 pendingSetUpdates: new Map(), //Pending updates to markers/areas/etc for each marker set
pendingTileUpdates: [], //Pending updates to map tiles pendingTileUpdates: [], //Pending updates to map tiles
@ -274,3 +276,7 @@ export const state: State = {
}, },
} }
}; };
export const nonReactiveState = Object.freeze({
markers: new Map<string, LiveAtlasMarkerSetContents>(),
});

View File

@ -285,14 +285,14 @@ export function buildMarker(data: Marker): LiveAtlasMarker {
let dimensions; let dimensions;
if(data.dim) { 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) { if(dimensions.length !== 2) {
dimensions = undefined; dimensions = undefined;
} }
} }
return Object.seal({ return {
label: data.label || '', label: data.label || '',
//Dynmap#2288 currently means markup:false markers are still encoded //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 //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, minZoom: typeof data.minzoom !== 'undefined' && data.minzoom > -1 ? data.minzoom : undefined,
maxZoom: typeof data.maxzoom !== 'undefined' && data.maxzoom > -1 ? data.maxzoom : undefined, maxZoom: typeof data.maxzoom !== 'undefined' && data.maxzoom > -1 ? data.maxzoom : undefined,
popupContent: data.desc || undefined, popupContent: data.desc || undefined,
}); };
} }
export function buildAreas(data: any): Map<string, LiveAtlasArea> { export function buildAreas(data: any): Map<string, LiveAtlasArea> {
@ -325,12 +325,7 @@ export function buildAreas(data: any): Map<string, LiveAtlasArea> {
} }
export function buildArea(area: MarkerArea): LiveAtlasArea { export function buildArea(area: MarkerArea): LiveAtlasArea {
const opacity = area.fillopacity || 0, return {
x = area.x || [0, 0],
y: [number, number] = [area.ybottom || 0, area.ytop || 0],
z = area.z || [0, 0];
return Object.seal({
style: { style: {
color: area.color || '#ff0000', color: area.color || '#ff0000',
opacity: area.opacity || 1, opacity: area.opacity || 1,
@ -338,8 +333,12 @@ export function buildArea(area: MarkerArea): LiveAtlasArea {
fillColor: area.fillcolor || '#ff0000', fillColor: area.fillcolor || '#ff0000',
fillOpacity: area.fillopacity || 0, fillOpacity: area.fillopacity || 0,
}, },
outline: !opacity, outline: !area.fillopacity,
points: getPoints(x, y, z, !opacity), 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, minZoom: typeof area.minzoom !== 'undefined' && area.minzoom > -1 ? area.minzoom : undefined,
maxZoom: typeof area.maxzoom !== 'undefined' && area.maxzoom > -1 ? area.maxzoom : 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 //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, isPopupHTML: true, //area.desc ? true : area.markup || false,
popupContent: area.desc || area.label || undefined, popupContent: area.desc || area.label || undefined,
}); };
} }
export function buildLines(data: any): Map<string, LiveAtlasLine> { export function buildLines(data: any): Map<string, LiveAtlasLine> {
@ -365,7 +364,7 @@ export function buildLines(data: any): Map<string, LiveAtlasLine> {
} }
export function buildLine(line: MarkerLine): LiveAtlasLine { export function buildLine(line: MarkerLine): LiveAtlasLine {
return Object.seal({ return {
style: { style: {
color: line.color || '#ff0000', color: line.color || '#ff0000',
opacity: line.opacity || 1, 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 //The planned solution for this is to always treat everything as HTML, so we'll do that here
isPopupHTML: true, isPopupHTML: true,
popupContent: line.desc || line.label || undefined, popupContent: line.desc || line.label || undefined,
}); };
} }
export function buildCircles(data: any): Map<string, LiveAtlasCircle> { export function buildCircles(data: any): Map<string, LiveAtlasCircle> {
@ -397,7 +396,7 @@ export function buildCircles(data: any): Map<string, LiveAtlasCircle> {
} }
export function buildCircle(circle: MarkerCircle): LiveAtlasCircle { export function buildCircle(circle: MarkerCircle): LiveAtlasCircle {
return Object.seal({ return {
location: { location: {
x: circle.x || 0, x: circle.x || 0,
y: circle.y || 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 //The planned solution for this is to always treat everything as HTML, so we'll do that here
isPopupHTML: true, isPopupHTML: true,
popupContent: circle.desc || circle.label || undefined, popupContent: circle.desc || circle.label || undefined,
}); };
} }
export function buildUpdates(data: Array<any>, lastUpdate: Date) { export function buildUpdates(data: Array<any>, lastUpdate: Date) {