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
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));
|
|
}
|
|
} |