You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
3.9 KiB
JavaScript

import {CRS, LatLng, LatLngBounds, map, tileLayer} from 'leaflet'
import {NwahIcons} from "./NwahIcons";
import {NwahPlayer} from "./NwahPlayer";
import {Component} from "preact";
import PlayerList from "./components/PlayerList";
export class NwahMap {
constructor({mapUrl, settings, icons, websocketUrl, playerList} = {}) {
this.players = {};
this.mapUrl = mapUrl;
this.playerList = playerList;
this.settings = settings || {
cellSize: 2048,
cellOffsetY: -20,
cellOffsetX: 8,
};
this.map = null;
this.follow = false;
this.icons = icons || NwahIcons;
this.websocketUrl = websocketUrl;
}
setFollow(follow) {
this.follow = follow;
}
init(element, component) {
this.map = map(element, {
zoom: 3,
center: this.gameCoordsToLatLng(0, 0),
crs: CRS.Simple
});
window.nwahMap = this;
this.map.setMaxBounds(new LatLngBounds(new LatLng(-255, 255), new LatLng(0, 0)));
this.map.invalidateSize();
this.tileLayer = tileLayer('/tileset/mwmap/zoom{z}/vvardenfell-{x}-{y}-{z}.jpg', {
attribution: 'uesp.net',
minZoom: 0,
maxZoom: 7,
zoomOffset: 10,
});
this.tileLayer.addTo(this.map);
if (this.websocketUrl) {
this.websocket = new WebSocket(this.websocketUrl);
this.websocket.onmessage = (message) => {
let event = JSON.parse(message.data);
if (event.type === "playerPosition") {
this.updatePositions(event.positions);
}
if (event.type === "fullPlayer") {
this.updatePlayers(event.players);
component.setState({players: event.players});
window.players = event.players;
}
if (this.follow) {
this.zoomOnPlayers();
}
}
}
}
zoomOnPlayers() {
let locations = Object.values(this.players)
.filter(x => x.isOutside)
.map(x => this.gameCoordsToLatLng(x.x, x.y));
if (locations.length === 0) {
return;
}
let bounds = new LatLngBounds(locations);
this.map.fitBounds(bounds);
}
updatePositions(positions) {
let knownPlayers = new Set(Object.keys(this.players));
for (let pos of positions) {
const name = pos.name;
knownPlayers.delete(name);
if (!(name in this.players)) {
this.players[name] = new NwahPlayer(name);
this.players[name].addTo(this);
}
let [x, y] = pos.position;
this.players[name].update(x, y, pos.rotation, false, pos.isOutside, pos.cell);
}
for (let name of knownPlayers) {
this.players[name].remove();
delete this.players[name];
}
}
updatePlayers(players) {
let knownPlayers = new Set(Object.keys(this.players));
for (let player of players) {
const name = player.name;
knownPlayers.delete(name);
if (!(name in this.players)) {
this.players[name] = new NwahPlayer(name);
this.players[name].addTo(this);
}
let {x, y} = player.position;
this.players[name].update(x, y, player.rotation.z, true, player.isOutside, player.cell);
}
for (let name of knownPlayers) {
this.players[name].remove();
delete this.players[name];
}
}
gameCoordsToLatLng(x, y) {
return new LatLng(
(y / this.settings.cellSize) - 128 + this.settings.cellOffsetY,
128 + ((x / this.settings.cellSize) + this.settings.cellOffsetX),
);
}
show({x, y}) {
this.map.panTo(this.gameCoordsToLatLng(x, y));
}
}