Implement update handling for map tiles

This commit is contained in:
James Lyne 2020-12-11 18:51:23 +00:00
parent b0e53b5fc9
commit 52bb6f5778
9 changed files with 102 additions and 19 deletions

View File

@ -11,7 +11,7 @@ import {
DynmapMarkerSetUpdates, DynmapMarkerSetUpdates,
DynmapMessageConfig, DynmapMessageConfig,
DynmapPlayer, DynmapPlayer,
DynmapServerConfig, DynmapUpdate, DynmapServerConfig, DynmapTileUpdate, DynmapUpdate,
DynmapUpdateResponse, DynmapUpdates, DynmapUpdateResponse, DynmapUpdates,
DynmapWorld DynmapWorld
} from "@/dynmap"; } from "@/dynmap";
@ -68,9 +68,9 @@ function buildWorlds(response: AxiosResponse): Array<DynmapWorld> {
background: '#121212', //map.background || '#000000', background: '#121212', //map.background || '#000000',
backgroundDay: map.backgroundday || '#000000', backgroundDay: map.backgroundday || '#000000',
backgroundNight: map.backgroundnight || '#000000', backgroundNight: map.backgroundnight || '#000000',
compassView: map.compassView || 'S', compassView: map.compassview || 'S',
icon: map.icon || undefined, icon: map.icon || undefined,
imageFormat: map.imageFormat || 'png', imageFormat: map['image-format'] || 'png',
name: map.name || '(Unnamed map)', name: map.name || '(Unnamed map)',
nightAndDay: map.nightandday || false, nightAndDay: map.nightandday || false,
prefix: map.prefix || '', prefix: map.prefix || '',
@ -303,7 +303,7 @@ function buildCircle(circle: any): DynmapCircle {
function buildUpdates(data: Array<any>): DynmapUpdates { function buildUpdates(data: Array<any>): DynmapUpdates {
const updates = { const updates = {
markerSets: new Map<string, DynmapMarkerSetUpdates>(), markerSets: new Map<string, DynmapMarkerSetUpdates>(),
tiles: new Map(), tiles: [] as DynmapTileUpdate[],
chat: [], chat: [],
} }
@ -370,7 +370,10 @@ function buildUpdates(data: Array<any>): DynmapUpdates {
break; break;
} }
updates.tiles.set(entry.name, entry.timestamp); updates.tiles.push({
name: entry.name,
timestamp: entry.timestamp,
});
break; break;
default: default:

View File

@ -5,6 +5,7 @@ import {Map} from 'leaflet';
import {useStore} from "@/store"; import {useStore} from "@/store";
import {HDMapType} from "@/leaflet/mapType/HDMapType"; import {HDMapType} from "@/leaflet/mapType/HDMapType";
import {MutationTypes} from "@/store/mutation-types"; import {MutationTypes} from "@/store/mutation-types";
import {ActionTypes} from "@/store/action-types";
export default defineComponent({ export default defineComponent({
props: { props: {
@ -23,11 +24,15 @@ export default defineComponent({
}, },
setup(props) { setup(props) {
let updateFrame = 0,
stopUpdateWatch: Function;
const store = useStore(), const store = useStore(),
layer = new HDMapType({ layer = new HDMapType({
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))),
}), }),
pendingUpdates = computed(() => !!store.state.pendingTileUpdates.length),
active = computed(() => props.map === store.state.currentMap), active = computed(() => props.map === store.state.currentMap),
enableLayer = () => { enableLayer = () => {
@ -37,9 +42,38 @@ export default defineComponent({
noMoveStart: true, noMoveStart: true,
animate: false, animate: false,
}); });
stopUpdateWatch = watch(pendingUpdates, (newValue, oldValue) => {
if(newValue && !oldValue && !updateFrame) {
handlePendingUpdates();
}
});
}, },
disableLayer = () => layer.remove(); disableLayer = () => {
layer.remove();
if(stopUpdateWatch) {
stopUpdateWatch();
}
},
handlePendingUpdates = () => {
useStore().dispatch(ActionTypes.POP_TILE_UPDATES, 10).then(updates => {
for(const update of updates) {
console.log('Updating tile ' + update.name);
layer.updateNamedTile(update.name, update.timestamp);
}
if(pendingUpdates.value) {
console.log('More updates left, scheduling frame');
// eslint-disable-next-line no-unused-vars
updateFrame = requestAnimationFrame(() => handlePendingUpdates());
} else {
updateFrame = 0;
}
});
};
watch(active, (newValue) => newValue ? enableLayer() : disableLayer()); watch(active, (newValue) => newValue ? enableLayer() : disableLayer());
@ -49,7 +83,13 @@ export default defineComponent({
} }
}); });
onUnmounted(() => disableLayer()); onUnmounted(() => {
disableLayer();
if(updateFrame) {
cancelAnimationFrame(updateFrame);
}
});
}, },
render() { render() {

9
src/dynmap.d.ts vendored
View File

@ -1,4 +1,4 @@
import {CircleMarkerOptions, PathOptions, PointTuple, PolylineOptions} from "leaflet"; import {PathOptions, PointTuple, PolylineOptions} from "leaflet";
import {CoordinatesControlOptions} from "@/leaflet/control/CoordinatesControl"; import {CoordinatesControlOptions} from "@/leaflet/control/CoordinatesControl";
import {LogoControlOptions} from "@/leaflet/control/LogoControl"; import {LogoControlOptions} from "@/leaflet/control/LogoControl";
import {ClockControlOptions} from "@/leaflet/control/ClockControl"; import {ClockControlOptions} from "@/leaflet/control/ClockControl";
@ -214,7 +214,7 @@ interface DynmapCircle {
interface DynmapUpdates { interface DynmapUpdates {
markerSets: Map<string, DynmapMarkerSetUpdates>, markerSets: Map<string, DynmapMarkerSetUpdates>,
tiles: Map<string, number>, tiles: Array<DynmapTileUpdate>,
chat: Array<any> //TODO chat: Array<any> //TODO
} }
@ -245,4 +245,9 @@ interface DynmapCircleUpdate extends DynmapUpdate {
interface DynmapLineUpdate extends DynmapUpdate { interface DynmapLineUpdate extends DynmapUpdate {
payload?: DynmapLine payload?: DynmapLine
}
interface DynmapTileUpdate {
name: string
timestamp: number
} }

View File

@ -83,24 +83,34 @@ export class DynmapTileLayer extends L.TileLayer {
} }
getTileUrl(coords: Coordinate) { getTileUrl(coords: Coordinate) {
const tileName = this.getTileName(coords); return this.getTileUrlFromName(this.getTileName(coords));
let url = this._cachedTileUrls.get(tileName); }
getTileUrlFromName(name: string, timestamp?: number) {
let url = this._cachedTileUrls.get(name);
if (!url) { if (!url) {
const path = escape(`${this._mapSettings.world.name}/${tileName}`); const path = escape(`${this._mapSettings.world.name}/${name}`);
url = `${window.config.url.tiles}${path}`; url = `${window.config.url.tiles}${path}`;
this._cachedTileUrls.set(tileName, url);
if(typeof timestamp !== 'undefined') {
url += `&timestamp=${timestamp}`;
}
this._cachedTileUrls.set(name, url);
} }
return url; return url;
} }
updateNamedTile(name: string) { updateNamedTile(name: string, timestamp: number) {
const tile = this._namedTiles.get(name); const tile = this._namedTiles.get(name);
this._cachedTileUrls.delete(name); this._cachedTileUrls.delete(name);
if (tile) { if (tile) {
//tile.src = this._cachedTileUrls[name] = this.getTileUrl(name); tile.dataset.src = this.getTileUrlFromName(name, timestamp);
this._loadQueue.push(tile);
this._tickLoadQueue();
} }
} }

View File

@ -7,4 +7,5 @@ export enum ActionTypes {
POP_AREA_UPDATES = "popAreaUpdates", POP_AREA_UPDATES = "popAreaUpdates",
POP_CIRCLE_UPDATES = "popCircleUpdates", POP_CIRCLE_UPDATES = "popCircleUpdates",
POP_LINE_UPDATES = "popLineUpdates", POP_LINE_UPDATES = "popLineUpdates",
POP_TILE_UPDATES = "popTileUpdates",
} }

View File

@ -9,7 +9,7 @@ import {
DynmapConfigurationResponse, DynmapLineUpdate, DynmapConfigurationResponse, DynmapLineUpdate,
DynmapMarkerSet, DynmapMarkerSet,
DynmapMarkerUpdate, DynmapMarkerUpdate,
DynmapPlayer, DynmapPlayer, DynmapTileUpdate,
DynmapUpdateResponse DynmapUpdateResponse
} from "@/dynmap"; } from "@/dynmap";
@ -50,6 +50,10 @@ export interface Actions {
{commit}: AugmentedActionContext, {commit}: AugmentedActionContext,
payload: {markerSet: string, amount: number} payload: {markerSet: string, amount: number}
): Promise<DynmapLineUpdate[]> ): Promise<DynmapLineUpdate[]>
[ActionTypes.POP_TILE_UPDATES](
{commit}: AugmentedActionContext,
payload: number
): Promise<DynmapTileUpdate[]>
} }
export const actions: ActionTree<State, State> & Actions = { export const actions: ActionTree<State, State> & Actions = {
@ -80,6 +84,7 @@ export const actions: ActionTree<State, State> & Actions = {
commit(MutationTypes.SET_UPDATE_TIMESTAMP, new Date(update.timestamp)); commit(MutationTypes.SET_UPDATE_TIMESTAMP, new Date(update.timestamp));
commit(MutationTypes.INCREMENT_REQUEST_ID, undefined); commit(MutationTypes.INCREMENT_REQUEST_ID, undefined);
commit(MutationTypes.ADD_MARKER_SET_UPDATES, update.updates.markerSets); commit(MutationTypes.ADD_MARKER_SET_UPDATES, update.updates.markerSets);
commit(MutationTypes.ADD_TILE_UPDATES, update.updates.tiles);
return dispatch(ActionTypes.SET_PLAYERS, update.players).then(() => { return dispatch(ActionTypes.SET_PLAYERS, update.players).then(() => {
return update; return update;
@ -175,4 +180,11 @@ export const actions: ActionTree<State, State> & Actions = {
return Promise.resolve(updates); return Promise.resolve(updates);
}, },
[ActionTypes.POP_TILE_UPDATES]({commit, state}, amount: number): Promise<Array<DynmapTileUpdate>> {
const updates = state.pendingTileUpdates.slice(0, amount);
commit(MutationTypes.POP_TILE_UPDATES, amount);
return Promise.resolve(updates);
},
} }

View File

@ -8,10 +8,12 @@ export enum MutationTypes {
SET_WORLD_STATE = 'setWorldState', SET_WORLD_STATE = 'setWorldState',
SET_UPDATE_TIMESTAMP = 'setUpdateTimestamp', SET_UPDATE_TIMESTAMP = 'setUpdateTimestamp',
ADD_MARKER_SET_UPDATES = 'addMarkerSetUpdates', ADD_MARKER_SET_UPDATES = 'addMarkerSetUpdates',
ADD_TILE_UPDATES = 'addTileUpdates',
POP_MARKER_UPDATES = 'popMarkerUpdates', POP_MARKER_UPDATES = 'popMarkerUpdates',
POP_AREA_UPDATES = 'popAreaUpdates', POP_AREA_UPDATES = 'popAreaUpdates',
POP_CIRCLE_UPDATES = 'popCircleUpdates', POP_CIRCLE_UPDATES = 'popCircleUpdates',
POP_LINE_UPDATES = 'popLineUpdates', POP_LINE_UPDATES = 'popLineUpdates',
POP_TILE_UPDATES = 'popTileUpdates',
INCREMENT_REQUEST_ID = 'incrementRequestId', INCREMENT_REQUEST_ID = 'incrementRequestId',
SET_PLAYERS = 'setPlayers', SET_PLAYERS = 'setPlayers',
SET_PLAYERS_ASYNC = 'setPlayersAsync', SET_PLAYERS_ASYNC = 'setPlayersAsync',

View File

@ -15,7 +15,7 @@ import {
DynmapMarkerUpdate, DynmapMarkerUpdate,
DynmapMessageConfig, DynmapMessageConfig,
DynmapPlayer, DynmapPlayer,
DynmapServerConfig, DynmapServerConfig, DynmapTileUpdate,
DynmapWorld, DynmapWorld,
DynmapWorldState DynmapWorldState
} from "@/dynmap"; } from "@/dynmap";
@ -36,11 +36,13 @@ export type Mutations<S = State> = {
[MutationTypes.SET_WORLD_STATE](state: S, worldState: DynmapWorldState): void [MutationTypes.SET_WORLD_STATE](state: S, worldState: DynmapWorldState): void
[MutationTypes.SET_UPDATE_TIMESTAMP](state: S, time: Date): void [MutationTypes.SET_UPDATE_TIMESTAMP](state: S, time: Date): 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.POP_MARKER_UPDATES](state: S, payload: {markerSet: string, amount: number}): Array<DynmapMarkerUpdate> [MutationTypes.POP_MARKER_UPDATES](state: S, payload: {markerSet: string, amount: number}): Array<DynmapMarkerUpdate>
[MutationTypes.POP_AREA_UPDATES](state: S, payload: {markerSet: string, amount: number}): Array<DynmapAreaUpdate> [MutationTypes.POP_AREA_UPDATES](state: S, payload: {markerSet: string, amount: number}): Array<DynmapAreaUpdate>
[MutationTypes.POP_CIRCLE_UPDATES](state: S, payload: {markerSet: string, amount: number}): Array<DynmapCircleUpdate> [MutationTypes.POP_CIRCLE_UPDATES](state: S, payload: {markerSet: string, amount: number}): Array<DynmapCircleUpdate>
[MutationTypes.POP_LINE_UPDATES](state: S, payload: {markerSet: string, amount: number}): Array<DynmapLineUpdate> [MutationTypes.POP_LINE_UPDATES](state: S, payload: {markerSet: string, amount: number}): Array<DynmapLineUpdate>
[MutationTypes.POP_TILE_UPDATES](state: S, amount: number): Array<DynmapTileUpdate>
[MutationTypes.INCREMENT_REQUEST_ID](state: S): void [MutationTypes.INCREMENT_REQUEST_ID](state: S): void
[MutationTypes.SET_PLAYERS_ASYNC](state: S, players: Set<DynmapPlayer>): Set<DynmapPlayer> [MutationTypes.SET_PLAYERS_ASYNC](state: S, players: Set<DynmapPlayer>): Set<DynmapPlayer>
@ -167,6 +169,10 @@ export const mutations: MutationTree<State> & Mutations = {
} }
}, },
[MutationTypes.ADD_TILE_UPDATES](state: State, updates: Array<DynmapTileUpdate>) {
state.pendingTileUpdates = state.pendingTileUpdates.concat(updates);
},
[MutationTypes.POP_MARKER_UPDATES](state: State, {markerSet, amount}): Array<DynmapMarkerUpdate> { [MutationTypes.POP_MARKER_UPDATES](state: State, {markerSet, amount}): Array<DynmapMarkerUpdate> {
if(!state.markerSets.has(markerSet)) { if(!state.markerSets.has(markerSet)) {
console.log(`Marker set ${markerSet} doesn't exist`); console.log(`Marker set ${markerSet} doesn't exist`);
@ -203,6 +209,10 @@ export const mutations: MutationTree<State> & Mutations = {
return state.pendingSetUpdates.get(markerSet)!.lineUpdates.splice(0, amount); return state.pendingSetUpdates.get(markerSet)!.lineUpdates.splice(0, amount);
}, },
[MutationTypes.POP_TILE_UPDATES](state: State, amount: number): Array<DynmapTileUpdate> {
return state.pendingTileUpdates.splice(0, amount);
},
//Increments the request id for the next update fetch //Increments the request id for the next update fetch
[MutationTypes.INCREMENT_REQUEST_ID](state: State) { [MutationTypes.INCREMENT_REQUEST_ID](state: State) {
state.updateRequestId++; state.updateRequestId++;

View File

@ -3,7 +3,7 @@ import {
DynmapMap, DynmapMarkerSet, DynmapMarkerSetUpdates, DynmapMap, DynmapMarkerSet, DynmapMarkerSetUpdates,
DynmapMessageConfig, DynmapMessageConfig,
DynmapPlayer, DynmapPlayer,
DynmapServerConfig, DynmapServerConfig, DynmapTileUpdate,
DynmapWorld, DynmapWorldState DynmapWorld, DynmapWorldState
} from "@/dynmap"; } from "@/dynmap";
import {DynmapProjection} from "@/leaflet/projection/DynmapProjection"; import {DynmapProjection} from "@/leaflet/projection/DynmapProjection";
@ -19,7 +19,7 @@ export type State = {
markerSets: Map<string, DynmapMarkerSet>; markerSets: Map<string, DynmapMarkerSet>;
pendingSetUpdates: Map<string, DynmapMarkerSetUpdates>; pendingSetUpdates: Map<string, DynmapMarkerSetUpdates>;
pendingTileUpdates: Array<string>; pendingTileUpdates: Array<DynmapTileUpdate>;
following?: DynmapPlayer; following?: DynmapPlayer;