UNPKG

earthmc

Version:

An unofficial EarthMC library providing handy methods and extensive info.

111 lines (85 loc) 3.84 kB
import striptags from 'striptags' import type Dynmap from './Dynmap.js' import type { MapResponse, OnlinePlayer, Player, StrictPoint2D } from '../../types/index.js' import * as fn from '../../utils/functions.js' import * as endpoint from '../../utils/endpoint.js' import { FetchError, type NotFoundError } from "../../utils/errors.js" import type { EntityApi } from '../../helpers/EntityApi.js' import { getNearest } from '../common.js' class Players implements EntityApi<Player | NotFoundError> { #map: Dynmap get map() { return this.#map } constructor(map: Dynmap) { this.#map = map } readonly get = async(...playerList: string[]) => { const players = await this.all() if (!players) throw new FetchError('Error fetching players! Please try again.') const existing = fn.getExisting(players, playerList, 'name') return existing.length > 1 ? Promise.all(existing) : Promise.resolve(existing[0]) } readonly all = async() => { const onlinePlayers = await this.map.onlinePlayerData() if (!onlinePlayers) return const residents = await this.map.Residents.all() if (!residents) return // Loop over residents and merge data for any online players const merged: Player[] = residents.map(res => { const op = onlinePlayers.find(op => op.name === res.name) return !op ? { ...res, online: false } : { ...res, ...op, online: true } }) return merged } readonly townless = async() => { const onlinePlayers = await this.online() if (!onlinePlayers) return null const mapData = await endpoint.mapData<MapResponse>("aurora") if (!mapData) throw new FetchError('Error fetching townless! Please try again.') const allResidents: string[] = [] const markerset = mapData.sets["townyPlugin.markerset"] const areas = Object.values(markerset.areas) const len = areas.length for (let i = 0; i < len; i++) { const town = areas[i] const rawinfo = town.desc.split("<br />") const info = rawinfo.map(x => striptags(x)) if (info[0].endsWith("(Shop)")) continue const mayor = info[1].slice(7) if (mayor == "") continue const residents = info[2].slice(9).split(", ") allResidents.push(...residents) } // Filter out residents & sort alphabetically const residentSet = new Set(allResidents) return onlinePlayers.filter(op => !residentSet.has(op.name)).sort((a, b) => { const [aName, bName] = [a.name.toLowerCase(), b.name.toLowerCase()] return bName < aName ? 1 : bName > aName ? -1 : 0 }) } readonly online = async(includeResidentInfo = false) => { const onlinePlayers = await this.map.onlinePlayerData() if (!onlinePlayers) return null if (!includeResidentInfo) return onlinePlayers const residents = await this.map.Residents.all() if (!residents) return null const merged: Player[] = [] const len = onlinePlayers.length for (let i = 0; i < len; i++) { const curOp = onlinePlayers[i] const foundRes = residents.find(res => res.name === curOp.name) merged.push({ online: true, ...curOp, ...foundRes }) } return merged } readonly nearby = async(location: StrictPoint2D, radius: StrictPoint2D, players?: OnlinePlayer[]) => getNearest<Partial<Player>>(location, radius, players, this.online, true) } export { Players, Players as default }