UNPKG

earthmc

Version:

An unofficial EarthMC library providing handy methods and extensive info.

1,247 lines (1,226 loc) 76.1 kB
'use strict'; const undici = require('undici'); const asyncMutex = require('async-mutex'); const TTLCache = require('@isaacs/ttlcache'); const striptags = require('striptags'); const modernDiacritics = require('modern-diacritics'); const mitt = require('mitt'); const MCAPI = require('mojang-lib'); var map = { nova: "https://earthmc.net/map/nova/standalone/MySQL_markers.php?marker=_markers_/marker_earth.json", aurora: "https://earthmc.net/map/aurora/standalone/MySQL_markers.php?marker=_markers_/marker_earth.json" }; var players = { nova: "https://earthmc.net/map/nova/standalone/MySQL_update.php?world=earth", aurora: "https://earthmc.net/map/aurora/standalone/MySQL_update.php?world=earth" }; var config = { nova: "https://earthmc.net/map/nova/standalone/MySQL_configuration.php", aurora: "https://earthmc.net/map/aurora/standalone/MySQL_configuration.php" }; var squaremap = { map: "https://map.earthmc.net/tiles/minecraft_overworld/markers.json", players: "https://map.earthmc.net/tiles/players.json" }; var towny = { "v2/aurora": "https://api.earthmc.net/v2/aurora", "v3/aurora": "https://api.earthmc.net/v3/aurora" }; const endpoints = { map: map, players: players, config: config, squaremap: squaremap, towny: towny }; const getEndpointUrl = (dataType, map) => { return endpoints[dataType][map.toLowerCase()]; }; const asJSON = async (url, options = null, retries = 3) => { const res = await undici.request(url, options).then((res2) => { var _a; return (_a = res2.body) == null ? void 0 : _a.json(); }).catch(async (err) => await retry(err, url, retries)); return res != null ? res : await retry(null, url, retries); }; const retry = (val, url, amt) => amt === 1 ? val : asJSON(url, null, amt - 1); let archiveTs = 0; const useArchive = (ts) => archiveTs = ts; const getArchive = async (url, unixTs = Date.now()) => { const formattedTs = new Date(unixTs * 1e3).toISOString().replace(/[^0-9]/g, "").slice(0, -3); return await asJSON(`https://web.archive.org/web/${formattedTs}id_/${decodeURIComponent(url)}`); }; const configData = async (mapName) => asJSON(getEndpointUrl("config", mapName)); const playerData = async (mapName) => { const url = mapName.toLowerCase() == "aurora" ? getEndpointUrl("squaremap", "players") : getEndpointUrl("players", mapName); return asJSON(url); }; const mapData = async (mapName) => { const url = mapName.toLowerCase() == "aurora" ? getEndpointUrl("squaremap", "map") : getEndpointUrl("map", mapName); return !archiveTs ? asJSON(url) : getArchive(url, archiveTs); }; const oapiDataV3 = async (endpoint = "", body) => { if (!endpoint) endpoint = ""; const url = getEndpointUrl("towny", "v3/aurora"); return body ? asJSON(`${url}${endpoint}`, { method: "POST", body: JSON.stringify(body) }) : asJSON(`${url}${endpoint}`); }; const endpoint = /*#__PURE__*/Object.freeze({ __proto__: null, asJSON, configData, getArchive, getEndpointUrl, mapData, oapiDataV3, playerData, useArchive }); class NotFoundError extends Error { constructor(message) { super(message); this.name = "NotFoundError"; this.message = message; } } class FetchError extends Error { constructor(message) { super(message); this.name = "FetchError"; this.message = message; } } class InvalidError extends Error { constructor(message) { super(message); this.name = "InvalidError"; this.message = message; } } const NotFound = (input) => new NotFoundError(`${input} does not exist.`); var __defProp$f = Object.defineProperty; var __typeError$b = (msg) => { throw TypeError(msg); }; var __defNormalProp$f = (obj, key, value) => key in obj ? __defProp$f(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$f = (obj, key, value) => __defNormalProp$f(obj, typeof key !== "symbol" ? key + "" : key, value); var __accessCheck$b = (obj, member, msg) => member.has(obj) || __typeError$b("Cannot " + msg); var __privateGet$b = (obj, member, getter) => (__accessCheck$b(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd$b = (obj, member, value) => member.has(obj) ? __typeError$b("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet$a = (obj, member, value, setter) => (__accessCheck$b(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); var _map$a, _cache, _cacheTTL, _cacheLock; class DataHandler { //#isNode = true constructor(mapName, cacheTTL) { __privateAdd$b(this, _map$a); __privateAdd$b(this, _cache); __privateAdd$b(this, _cacheTTL); __privateAdd$b(this, _cacheLock); __publicField$f(this, "createCache", async () => { const release = await __privateGet$b(this, _cacheLock).acquire(); let cacheInstance = null; try { cacheInstance = new TTLCache({ ttl: __privateGet$b(this, _cacheTTL) }); } catch (e) { console.error(e); } finally { release(); } return cacheInstance; }); __publicField$f(this, "getFromCache", (key) => { var _a; return (_a = __privateGet$b(this, _cache)) == null ? void 0 : _a.get(key); }); __publicField$f(this, "putInCache", (key, value) => { var _a; return (_a = __privateGet$b(this, _cache)) == null ? void 0 : _a.set(key, value); }); __publicField$f(this, "setKeyTTL", (key, ttl) => { var _a; return (_a = __privateGet$b(this, _cache)) == null ? void 0 : _a.setTTL(key, ttl); }); __publicField$f(this, "playerData", () => playerData(this.map)); __publicField$f(this, "configData", () => configData(this.map)); __publicField$f(this, "mapData", async () => { if (!__privateGet$b(this, _cache)) { __privateSet$a(this, _cache, await this.createCache()); } const cached = this.getFromCache("mapData"); if (!cached) { const data = await mapData(__privateGet$b(this, _map$a)); this.putInCache("mapData", data); return data; } return cached; }); __privateSet$a(this, _map$a, mapName); __privateSet$a(this, _cacheLock, new asyncMutex.Mutex()); __privateSet$a(this, _cacheTTL, cacheTTL < 1e3 ? 1e3 : cacheTTL); } get map() { return __privateGet$b(this, _map$a); } } _map$a = new WeakMap(); _cache = new WeakMap(); _cacheTTL = new WeakMap(); _cacheLock = new WeakMap(); const fastMerge = (original, args) => { original.push.apply(original, args); return original; }; const fastMergeUnique = (original, args) => { fastMerge(original, args); return [...new Set(original)]; }; const stripInvalidChars = (str) => { return str.replace(/((&#34)|(&\w[a-z0-9].|&[0-9kmnola-z]));/g, "").replace(/&quot;|&#039;/g, '"'); }; function formatString(str, removeAccents = false) { str = stripInvalidChars(str); return removeAccents ? modernDiacritics.removeDiacritics(str) : str; } function editPlayerProps$1(props) { if (!props) throw new ReferenceError("Can't edit player props! The parameter is null or undefined."); if (props instanceof Array) return props.length > 0 ? props.map((p) => editPlayerProp(p)) : []; throw new TypeError("Can't edit player props! Type isn't of object or array."); } const editPlayerProp = (player) => ({ name: player.account, nickname: striptags(player.name), x: player.x, y: player.y, z: player.z, underground: player.world != "earth", world: player.world }); const roundToNearest16 = (num) => Math.round(num / 16) * 16; function calcArea(X, Z, numPoints, divisor = 256) { let i = 0, j = numPoints - 1, area = 0; for (; i < numPoints; i++) { area += (X[j] + X[i]) * (Z[j] - Z[i]); j = i; } return Math.abs(area / 2) / divisor; } function calcAreaPoints(points, divisor = 256) { let area = 0; const NUM_POINTS = points.length; for (let i = 0; i < NUM_POINTS; i++) { const cur = points[i]; const next = points[(i + 1) % NUM_POINTS]; area += cur.x * next.z; area -= cur.z * next.x; } return Math.abs(area / 2) / divisor; } function averageNationPos(name, towns) { const nationTowns = towns.filter((t) => { var _a; return ((_a = t.nation) == null ? void 0 : _a.toLowerCase()) == name.toLowerCase(); }); return getAveragePos(nationTowns); } function getAveragePos(arr) { if (!arr) return "Error getting average position: 'towns' parameter not defined!"; return { x: average(arr, "x"), z: average(arr, "z") }; } const safeParseInt = (num) => typeof num === "number" ? num : parseInt(num); const asBool = (str) => str == "true"; const midrange = (args) => Math.round((Math.max(...args) + Math.min(...args)) / 2); const sqr = (a, b, range) => Math.hypot( safeParseInt(a.x) - safeParseInt(b.x), safeParseInt(a.z) - safeParseInt(b.z) ) <= range; const average = (nums, key) => { const sum = nums.map((obj) => obj[key]).reduce((a, b) => safeParseInt(a) + safeParseInt(b)); return safeParseInt(sum) / nums.length; }; const getExisting = (a1, a2, key) => { return a2.flat().map((x) => { var _a; return (_a = a1.find( (e) => { var _a2; return (x == null ? void 0 : x.toLowerCase()) == ((_a2 = String(e[key])) == null ? void 0 : _a2.toLowerCase()); } )) != null ? _a : NotFound(x); }); }; const hypot = (num, args) => { const [input, radius] = args; return num <= input + radius && num >= input - radius; }; const manhattan = (x1, z1, x2, z2) => Math.abs(x2 - x1) + Math.abs(z2 - z1); const euclidean = (x1, z1, x2, z2) => Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(z2 - z1, 2)); const strictFalsy = (val) => val === void 0 || val === null; const isInvitable = (town, nation, range, belonging) => { const val = sqr(town, nation.capital, range) && town.nation != nation.name; return belonging ? val : val && town.nation == "No Nation"; }; const getNearest = async (location, radius, arr, fallback, disallowCenter = false) => { if (!arr) { arr = await fallback(); if (!arr) return null; } if (disallowCenter) return arr.filter((el) => { var _a, _b; if (el.x == 0 && el.z == 0) return; return hypot(safeParseInt((_a = el.x) != null ? _a : el.capital.x), [location.x, radius.x]) && hypot(safeParseInt((_b = el.z) != null ? _b : el.capital.z), [location.z, radius.z]); }); return arr.filter( (el) => { var _a, _b; return hypot(safeParseInt((_a = el.x) != null ? _a : el.capital.x), [location.x, radius.x]) && hypot(safeParseInt((_b = el.z) != null ? _b : el.capital.z), [location.z, radius.z]); } ); }; const checkWithinBounds = (location, bounds) => { if (strictFalsy(location.x) || strictFalsy(location.z)) { const obj = JSON.stringify(location); throw new ReferenceError(`(withinBounds) - Invalid location: ${obj}`); } const locX = safeParseInt(location.x); const locZ = safeParseInt(location.z); const withinX = locX >= Math.min(...bounds.x) && locX <= Math.max(...bounds.x); const withinZ = locZ >= Math.min(...bounds.z) && locZ <= Math.max(...bounds.z); return withinX && withinZ; }; const checkWithinTown = async (location, towns) => { const len = towns.length; let inBounds = false; for (let i = 0; i < len; i++) { const cur = towns[i]; if (checkWithinBounds(location, cur.bounds)) { inBounds = true; break; } } return inBounds; }; var __defProp$e = Object.defineProperty; var __typeError$a = (msg) => { throw TypeError(msg); }; var __defNormalProp$e = (obj, key, value) => key in obj ? __defProp$e(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$e = (obj, key, value) => __defNormalProp$e(obj, typeof key !== "symbol" ? key + "" : key, value); var __accessCheck$a = (obj, member, msg) => member.has(obj) || __typeError$a("Cannot " + msg); var __privateGet$a = (obj, member, getter) => (__accessCheck$a(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd$a = (obj, member, value) => member.has(obj) ? __typeError$a("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet$9 = (obj, member, value, setter) => (__accessCheck$a(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); var _map$9; let Towns$1 = class Towns { constructor(map) { __privateAdd$a(this, _map$9); __publicField$e(this, "fromNation", async (nationName) => { if (!nationName) throw new InvalidError(`Parameter 'nation' is ${nationName}`); const nation = await this.map.Nations.get(nationName); if (nation instanceof Error) throw nation; return await this.get(...nation.towns); }); __publicField$e(this, "get", async (...townList) => { const towns = await this.all(); if (!towns) throw new FetchError("Error fetching towns! Please try again."); const existing = getExisting(towns, townList, "name"); return existing.length > 1 ? Promise.all(existing) : Promise.resolve(existing[0]); }); __publicField$e(this, "all", async (removeAccents = false) => { var _a, _b, _c, _d, _e, _f, _g, _h, _i; let cachedTowns = this.map.getFromCache("towns"); if (cachedTowns) return cachedTowns; const markerset = await this.map.markerset(); if (!(markerset == null ? void 0 : markerset.areas)) { throw new ReferenceError("No areas found on markerset!"); } const townsArray = []; 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((i2) => striptags(i2, ["a"])); const firstEl = info[0]; if (firstEl.includes("(Shop)")) continue; const mayor = info[1].slice(7); if (mayor == "") continue; let split = firstEl.split(" ("); split = ((_a = split[2]) != null ? _a : split[1]).slice(0, -1); const residents = info[2].slice(9).split(", "); const capital = asBool((_b = info[9]) == null ? void 0 : _b.slice(9)); let nationName = split; let wikiPage = null; if (split.includes("href")) { nationName = split.slice(split.indexOf(">") + 1).replace("</a>", ""); split = split.replace('<a href="', ""); if (capital) wikiPage = split.substring(0, split.indexOf('"')); } const home = nationName != "" ? markerset.markers[`${town.label}__home`] : null; const [townX, townZ] = [town.x, town.z]; const area = calcArea(townX, townZ, townX.length); const currentTown = { name: formatString(town.label, removeAccents), nation: nationName == "" ? "No Nation" : formatString(nationName.trim(), removeAccents), mayor, area, x: (_c = home == null ? void 0 : home.x) != null ? _c : midrange(townX), z: (_d = home == null ? void 0 : home.z) != null ? _d : midrange(townZ), bounds: { x: townX.map((num) => Math.round(num)), z: townZ.map((num) => Math.round(num)) }, residents, flags: { pvp: asBool((_e = info[4]) == null ? void 0 : _e.slice(5)), mobs: asBool((_f = info[5]) == null ? void 0 : _f.slice(6)), public: asBool((_g = info[6]) == null ? void 0 : _g.slice(8)), explosion: asBool((_h = info[7]) == null ? void 0 : _h.slice(11)), fire: asBool((_i = info[8]) == null ? void 0 : _i.slice(6)), capital }, colours: { fill: town.fillcolor, outline: town.color }, opacities: { fill: town.fillopacity, outline: town.opacity } }; if (wikiPage) { currentTown["wiki"] = wikiPage; } townsArray.push(currentTown); } const temp = {}; cachedTowns = []; const townsArrLen = townsArray.length; for (let i = 0; i < townsArrLen; i++) { const town = townsArray[i]; const name = town.name; if (temp[name]) temp[name].area += town.area; else { temp[name] = town; cachedTowns.push(town); } } if (cachedTowns.length > 0) { this.map.putInCache("towns", cachedTowns); } return cachedTowns; }); __publicField$e(this, "nearby", async (location, radius, towns) => getNearest(location, radius, towns, this.all)); __publicField$e(this, "invitable", async (nationName, includeBelonging = false) => { const nation = await this.map.Nations.get(nationName); if (nation instanceof NotFoundError) throw new Error("Error checking invitable: Nation does not exist!"); if (!nation) throw new Error("Error checking invitable: Could not fetch the nation!"); const towns = await this.all(); if (!towns) throw new FetchError("An error occurred fetching towns!"); return towns.filter((t) => isInvitable(t, nation, this.map.inviteRange, includeBelonging)); }); __privateSet$9(this, _map$9, map); } get map() { return __privateGet$a(this, _map$9); } }; _map$9 = new WeakMap(); var __defProp$d = Object.defineProperty; var __typeError$9 = (msg) => { throw TypeError(msg); }; var __defNormalProp$d = (obj, key, value) => key in obj ? __defProp$d(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$d = (obj, key, value) => __defNormalProp$d(obj, typeof key !== "symbol" ? key + "" : key, value); var __accessCheck$9 = (obj, member, msg) => member.has(obj) || __typeError$9("Cannot " + msg); var __privateGet$9 = (obj, member, getter) => (__accessCheck$9(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd$9 = (obj, member, value) => member.has(obj) ? __typeError$9("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet$8 = (obj, member, value, setter) => (__accessCheck$9(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); var _map$8; let Nations$1 = class Nations { constructor(map) { __privateAdd$9(this, _map$8); __publicField$d(this, "get", async (...nationList) => { const nations = await this.all(); if (!nations) throw new FetchError("Error fetching nations! Please try again."); const existing = getExisting(nations, nationList, "name"); return existing.length > 1 ? Promise.all(existing) : Promise.resolve(existing[0]); }); __publicField$d(this, "all", async (towns) => { var _a; if (!towns) { towns = await this.map.Towns.all(); if (!towns) throw new Error("Error getting nations: Could not fetch towns."); } const raw = {}; const nations = []; const len = towns.length; for (let i = 0; i < len; i++) { const town = towns[i]; const nationName = town.nation; if (nationName == "No Nation") continue; if (!raw[nationName]) { raw[nationName] = { name: nationName, residents: town.residents, towns: [], area: 0, king: void 0, capital: void 0 }; nations.push(raw[nationName]); } const resNames = raw[nationName].residents; raw[nationName].residents = fastMergeUnique(resNames, town.residents); raw[nationName].area += town.area; if (raw[nationName].name == nationName) (_a = raw[nationName].towns) == null ? void 0 : _a.push(town.name); if (town.flags.capital) { if (town.wiki) raw[nationName].wiki = town.wiki; raw[nationName].king = town.mayor; raw[nationName].capital = { name: town.name, x: town.x, z: town.z }; } } return nations; }); __publicField$d(this, "nearby", async (location, radius, nations) => getNearest(location, radius, nations, this.all)); __publicField$d(this, "joinable", async (townName, nationless = true) => { const town = await this.map.Towns.get(townName).then((obj) => obj instanceof NotFoundError ? null : obj).catch(() => { throw new FetchError("Error fetching town ${}! Please try again."); }); const nations = await this.all(this.map.getFromCache("towns")); if (!nations) throw new FetchError("Error fetching nations! Please try again."); return nations.filter((n) => { const joinable = sqr(n.capital, town, this.map.inviteRange); return nationless ? joinable && town.nation == "No Nation" : joinable; }); }); __privateSet$8(this, _map$8, map); } get map() { return __privateGet$9(this, _map$8); } }; _map$8 = new WeakMap(); var __defProp$c = Object.defineProperty; var __defProps$2 = Object.defineProperties; var __getOwnPropDescs$2 = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols; var __hasOwnProp$2 = Object.prototype.hasOwnProperty; var __propIsEnum$2 = Object.prototype.propertyIsEnumerable; var __typeError$8 = (msg) => { throw TypeError(msg); }; var __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$2 = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$2.call(b, prop)) __defNormalProp$c(a, prop, b[prop]); if (__getOwnPropSymbols$2) for (var prop of __getOwnPropSymbols$2(b)) { if (__propIsEnum$2.call(b, prop)) __defNormalProp$c(a, prop, b[prop]); } return a; }; var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b)); var __publicField$c = (obj, key, value) => __defNormalProp$c(obj, typeof key !== "symbol" ? key + "" : key, value); var __accessCheck$8 = (obj, member, msg) => member.has(obj) || __typeError$8("Cannot " + msg); var __privateGet$8 = (obj, member, getter) => (__accessCheck$8(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd$8 = (obj, member, value) => member.has(obj) ? __typeError$8("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet$7 = (obj, member, value, setter) => (__accessCheck$8(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); var _map$7; let Players$1 = class Players { constructor(map) { __privateAdd$8(this, _map$7); __publicField$c(this, "get", async (...playerList) => { const players = await this.all(); if (!players) throw new FetchError("Error fetching players! Please try again."); const existing = getExisting(players, playerList, "name"); return existing.length > 1 ? Promise.all(existing) : Promise.resolve(existing[0]); }); __publicField$c(this, "all", async () => { const onlinePlayers = await this.map.onlinePlayerData(); if (!onlinePlayers) return; const residents = await this.map.Residents.all(); if (!residents) return; const merged = residents.map((res) => { const op = onlinePlayers.find((op2) => op2.name === res.name); return !op ? __spreadProps$2(__spreadValues$2({}, res), { online: false }) : __spreadProps$2(__spreadValues$2(__spreadValues$2({}, res), op), { online: true }); }); return merged; }); __publicField$c(this, "townless", async () => { const onlinePlayers = await this.online(); if (!onlinePlayers) return null; const mapData$1 = await mapData("aurora"); if (!mapData$1) throw new FetchError("Error fetching townless! Please try again."); const allResidents = []; const markerset = mapData$1.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); } 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; }); }); __publicField$c(this, "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 = []; 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(__spreadValues$2(__spreadValues$2({ online: true }, curOp), foundRes)); } return merged; }); __publicField$c(this, "nearby", async (location, radius, players) => getNearest(location, radius, players, this.online, true)); __privateSet$7(this, _map$7, map); } get map() { return __privateGet$8(this, _map$7); } }; _map$7 = new WeakMap(); var __defProp$b = Object.defineProperty; var __typeError$7 = (msg) => { throw TypeError(msg); }; var __defNormalProp$b = (obj, key, value) => key in obj ? __defProp$b(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$b = (obj, key, value) => __defNormalProp$b(obj, typeof key !== "symbol" ? key + "" : key, value); var __accessCheck$7 = (obj, member, msg) => member.has(obj) || __typeError$7("Cannot " + msg); var __privateGet$7 = (obj, member, getter) => (__accessCheck$7(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd$7 = (obj, member, value) => member.has(obj) ? __typeError$7("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet$6 = (obj, member, value, setter) => (__accessCheck$7(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); var _map$6; let Residents$1 = class Residents { constructor(map) { __privateAdd$7(this, _map$6); __publicField$b(this, "fromTown", async (townName) => { if (!townName) throw new InvalidError(`Parameter 'town' is ${townName}`); const town = await this.map.Towns.get(townName); if (town instanceof Error) throw town; return await this.get(...town.residents); }); __publicField$b(this, "get", async (...names) => { const residents = await this.all(); if (!residents) throw new FetchError("Error fetching residents! Please try again."); const existing = getExisting(residents, names, "name"); return existing.length > 1 ? Promise.all(existing) : Promise.resolve(existing[0]); }); __publicField$b(this, "all", async (towns) => { if (!towns) { towns = await this.map.Towns.all(); if (!towns) return null; } return towns.reduce((acc, town) => { acc.push.apply(acc, town.residents.map((res) => ({ name: res, town: town.name, nation: town.nation, rank: town.mayor == res ? town.flags.capital ? "Nation Leader" : "Mayor" : "Resident" }))); return acc; }, []); }); __privateSet$6(this, _map$6, map); } get map() { return __privateGet$7(this, _map$6); } }; _map$6 = new WeakMap(); const createRoute = (avoidPvp, avoidPrivate) => ({ avoidPvp, avoidPrivate }); const Routes = { SAFEST: createRoute(true, true), FASTEST: createRoute(false, false), AVOID_PRIVATE: createRoute(false, true), AVOID_PVP: createRoute(true, false) }; const BASE_DIRECTIONS = [ "North", "East", "South", "West" ]; const DIRECTIONS = [ "North", "North-East", "East", "South-East", "South", "South-West", "West", "North-West" ]; const rawPlayerStatsTemplate = { // PVP / PVE player_kills: 0, mob_kills: 0, deaths: 0, // Damage damage_taken: 0, damage_dealt: 0, damage_resisted: 0, damage_absorbed: 0, damage_dealt_resisted: 0, damage_dealt_absorbed: 0, damage_blocked_by_shield: 0, // Interact interact_with_crafting_table: 0, interact_with_smithing_table: 0, interact_with_cartography_table: 0, interact_with_furnace: 0, interact_with_blast_furnace: 0, interact_with_smoker: 0, interact_with_stonecutter: 0, interact_with_grindstone: 0, interact_with_anvil: 0, interact_with_loom: 0, interact_with_lectern: 0, interact_with_beacon: 0, interact_with_campfire: 0, interact_with_brewingstand: 0, // Inspect inspect_dispenser: 0, inspect_dropper: 0, inspect_hopper: 0, // Open open_enderchest: 0, open_chest: 0, open_barrel: 0, open_shulker_box: 0, // Villager traded_with_villager: 0, talked_to_villager: 0, // Times total_world_time: 0, play_time: 0, sneak_time: 0, time_since_rest: 0, time_since_death: 0, // Raid raid_win: 0, raid_trigger: 0, // Movement walk_one_cm: 0, sprint_one_cm: 0, boat_one_cm: 0, swim_one_cm: 0, fall_one_cm: 0, walk_on_water_one_cm: 0, walk_under_water_one_cm: 0, horse_one_cm: 0, minecart_one_cm: 0, aviate_one_cm: 0, crouch_one_cm: 0, climb_one_cm: 0, pig_one_cm: 0, fly_one_cm: 0, strider_one_cm: 0, // Clean clean_banner: 0, clean_shulker_box: 0, clean_armor: 0, // Mobs animals_bred: 0, fish_caught: 0, // Music/Play play_record: 0, play_noteblock: 0, tune_noteblock: 0, // Misc jump: 0, bell_ring: 0, eat_cake_slice: 0, sleep_in_bed: 0, trigger_trapped_chest: 0, fill_cauldron: 0, use_cauldron: 0, target_hit: 0, drop_count: 0, pot_flower: 0, leave_game: 0, enchant_item: 0 }; const SQUAREMAP_MAPS = ["aurora"]; const DYNMAP_MAPS = ["nova"]; var __defProp$a = Object.defineProperty; var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$a = (obj, key, value) => __defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value); class Emitter { constructor() { __publicField$a(this, "_on"); __publicField$a(this, "_off"); __publicField$a(this, "emit"); const emitter = mitt(); this._on = emitter.on; this._off = emitter.off; this.emit = emitter.emit; } get on() { return this._on; } get off() { return this._off; } } var __defProp$9 = Object.defineProperty; var __typeError$6 = (msg) => { throw TypeError(msg); }; var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$9 = (obj, key, value) => __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value); var __accessCheck$6 = (obj, member, msg) => member.has(obj) || __typeError$6("Cannot " + msg); var __privateGet$6 = (obj, member, getter) => (__accessCheck$6(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd$6 = (obj, member, value) => member.has(obj) ? __typeError$6("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet$5 = (obj, member, value, setter) => (__accessCheck$6(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); var _map$5, _emittedUnderground, _lastLoc$1; const _GPS$1 = class _GPS extends Emitter { constructor(map) { super(); __privateAdd$6(this, _map$5); __privateAdd$6(this, _emittedUnderground, false); __privateAdd$6(this, _lastLoc$1); __publicField$9(this, "playerIsOnline", (player) => { if (!player.online) { this.emit("error", { err: "INVALID_PLAYER", msg: "Player is offline or does not exist!" }); } return player.online; }); __publicField$9(this, "track", async (playerName, interval = 3e3, route = Routes.FASTEST) => { setInterval(async () => { const player = await this.map.Players.get(playerName).catch((e) => { this.emit("error", { err: "FETCH_ERROR", msg: e.message }); return null; }); if (!player) return; if (!this.playerIsOnline(player)) return; if (player.underground) { if (!this.emittedUnderground) { this.emittedUnderground = true; if (!this.lastLoc) { this.emit("underground", "No last location. Waiting for this player to show."); return; } try { const routeInfo = await this.findRoute(this.lastLoc, route); this.emit("underground", { lastLocation: this.lastLoc, routeInfo }); } catch (e) { this.emit("error", { err: "INVALID_LAST_LOC", msg: e.message }); } } } else { this.lastLoc = { x: safeParseInt(player.x), z: safeParseInt(player.z) }; try { const routeInfo = await this.findRoute({ x: player.x, z: player.z }, route); this.emit("locationUpdate", routeInfo); } catch (e) { this.emit("error", { err: "INVALID_LOC", msg: e.message }); } } }, interval); return this; }); __publicField$9(this, "safestRoute", (loc) => this.findRoute(loc, Routes.SAFEST)); __publicField$9(this, "fastestRoute", (loc) => this.findRoute(loc, Routes.FASTEST)); __publicField$9(this, "findRoute", async (loc, options) => { if (strictFalsy(loc.x) || strictFalsy(loc.z)) { const obj = JSON.stringify(loc); throw new Error(`Cannot calculate route! One or more inputs are invalid: ${obj}`); } const [towns, nations] = await Promise.all([this.map.Towns.all(), this.map.Nations.all()]); const townsMap = new Map(towns.map((t) => [t.name, t])); const len = nations.length; const filtered = []; for (let i = 0; i < len; i++) { const nation2 = nations[i]; const capitalName = nation2.capital.name; const capital = townsMap.get(capitalName); if (!capital) continue; const flags = capital.flags; const PVP = options.avoidPvp && flags.pvp; const PRIVATE = options.avoidPrivate && !flags.public; if (PVP || PRIVATE) continue; filtered.push(nation2); } const { distance, nation } = filtered.reduce((acc, nation2) => { const dist = manhattan( safeParseInt(nation2.capital.x), safeParseInt(nation2.capital.z), safeParseInt(loc.x), safeParseInt(loc.z) ); const closer = !acc.distance || dist < acc.distance; return !closer ? acc : { distance: Math.round(dist), nation: { name: nation2.name, capital: nation2.capital } }; }, { distance: null, nation: null }); const direction = _GPS.cardinalDirection(nation.capital, loc); return { nation, distance, direction }; }); __privateSet$5(this, _map$5, map); } get map() { return __privateGet$6(this, _map$5); } get emittedUnderground() { return __privateGet$6(this, _emittedUnderground); } set emittedUnderground(val) { __privateSet$5(this, _emittedUnderground, val); } get lastLoc() { return __privateGet$6(this, _lastLoc$1); } set lastLoc(val) { __privateSet$5(this, _lastLoc$1, val); } /** * Determines the direction to the destination from the origin. * * Only one of the main four directions (N, S, W, E) can be returned, no intermediates. * @param origin The location where something is currently at. * @param destination The location we wish to arrive at. */ static cardinalDirection(origin, destination) { const deltaX = safeParseInt(origin.x) - safeParseInt(destination.x); const deltaZ = safeParseInt(origin.z) - safeParseInt(destination.z); const angle = Math.atan2(deltaZ, deltaX) * 180 / Math.PI; if (angle >= -45 && angle < 45) return "east"; if (angle >= 45 && angle < 135) return "north"; if (angle >= 135 || angle < -135) return "west"; return "south"; } }; _map$5 = new WeakMap(); _emittedUnderground = new WeakMap(); _lastLoc$1 = new WeakMap(); __publicField$9(_GPS$1, "Routes", Routes); let GPS$1 = _GPS$1; var __defProp$8 = Object.defineProperty; var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value); class Dynmap extends DataHandler { //#endregion constructor(mapName, cacheTimeoutMs = 120 * 1e3) { super(mapName, cacheTimeoutMs); //#region Data classes __publicField$8(this, "Towns"); __publicField$8(this, "Nations"); __publicField$8(this, "Residents"); __publicField$8(this, "Players"); __publicField$8(this, "GPS"); //#endregion //#region Map-specific properties __publicField$8(this, "name"); __publicField$8(this, "inviteRange"); __publicField$8(this, "withinTown", async (location) => { const towns = await this.Towns.all(); return checkWithinTown(location, towns); }); __publicField$8(this, "isWilderness", async (location) => !await this.withinTown(location)); __publicField$8(this, "withinBounds", (location, bounds) => checkWithinBounds(location, bounds)); __publicField$8(this, "onlinePlayerData", async () => { const pData = await this.playerData(); return (pData == null ? void 0 : pData.players) ? editPlayerProps$1(pData.players) : null; }); __publicField$8(this, "markerset", async () => { const mapData = await this.mapData(); return mapData == null ? void 0 : mapData.sets["townyPlugin.markerset"]; }); this.name = mapName; this.inviteRange = mapName == "nova" ? 3e3 : 3500; this.Towns = new Towns$1(this); this.Nations = new Nations$1(this); this.Residents = new Residents$1(this); this.Players = new Players$1(this); this.GPS = new GPS$1(this); } } const extractText = (text) => { const anchorMatch = text.match(/<a[^>]*>([^<]+)<\/a>/); return anchorMatch ? anchorMatch[1] : text; }; const parsePopup = (popup) => { var _a, _b; const spanMatch = popup.match(/<span[^>]*>(.*?)<\/span>/); const spanContent = spanMatch ? spanMatch[1] : null; const updatedPopup = popup.replace(/<span[^>]*>.*?<\/span>/, "<b>"); const cleaned = striptags(updatedPopup.replaceAll("\n", ""), ["a"]).trim(); const townWiki = spanContent.match(/<a href="(.*)">(.*)<\/a> /); const nationWiki = spanContent.match(/\(<a href="(.*)">(.*)<\/a>\)/); const sectioned = cleaned.replace(/\s{2,}/g, " // "); const councillorsStr = extractSection(sectioned, "Councillors"); const residentsMatch = sectioned.match(/Residents: .*?\/\/(.*?)(?=\/\/|$)/); const residentsDetails = residentsMatch ? residentsMatch[1].trim() : null; const bracketMatch = spanContent.match(/^(.*)\s\((.*)\)\s*$/); const townStr = bracketMatch ? bracketMatch[1].trim() : spanContent.trim(); const nationStr = bracketMatch ? bracketMatch[2].trim() : null; const town = extractText(townStr); const nation = nationStr ? extractText(nationStr) : null; const board = ((_a = updatedPopup.match(/<i\b[^>]*>(.*?)<\/i>/)) == null ? void 0 : _a[1]) || null; return { town, nation, board, mayor: extractSection(sectioned, "Mayor"), councillors: !councillorsStr || councillorsStr == "None" ? [] : councillorsStr.split(", "), founded: extractSection(sectioned, "Founded"), //wealth: extractSection(sectioned, 'Wealth'), residents: (_b = residentsDetails == null ? void 0 : residentsDetails.split(", ")) != null ? _b : [], flags: { pvp: extractSection(sectioned, "PVP"), public: extractSection(sectioned, "Public") }, wikis: { town: townWiki ? townWiki[1] : null, nation: nationWiki ? nationWiki[1] : null } }; }; const extractSection = (input, section) => { const match = input.match(`${section}:\\s*([^\\/]*)(?:\\s*\\/\\/)?`); return match ? match[1].trim() : null; }; const isCapital = (marker) => { var _a; const desc = striptags(marker.tooltip.replaceAll("\n", "")).trim(); const bracketMatch = desc.replace(/^[^\s]*\s*/, "").match(/\(([^()]+)\)/); const tooltipBracketContent = bracketMatch ? bracketMatch[1].trim() : null; return (_a = tooltipBracketContent == null ? void 0 : tooltipBracketContent.startsWith("Capital of")) != null ? _a : false; }; const parseTowns = (res, removeAccents = false) => { if (res.id == "chunky") throw new Error("Error parsing towns: Chunky markerset detected, pass a towny markerset instead."); if (!(res == null ? void 0 : res.markers)) throw new ReferenceError("Error parsing towns: Missing or invalid markers!"); const len = res.markers.length; const towns = []; for (let i = 0; i < len; i++) { const curMarker = res.markers[i]; if (curMarker.type == "icon") continue; const points = curMarker.points.flat(2); const { townX, townZ } = points.reduce((acc, p) => { acc.townX.push(roundToNearest16(p.x)); acc.townZ.push(roundToNearest16(p.z)); return acc; }, { townX: [], townZ: [] }); const parsedPopup = parsePopup(curMarker.popup); const townName = parsedPopup.town || ""; const nationName = parsedPopup.nation ? formatString(parsedPopup.nation, removeAccents) : "No Nation"; const town = { name: formatString(townName, removeAccents), nation: nationName, foundedTimestamp: parsedPopup.founded ? Math.floor(new Date(parsedPopup.founded).getTime() / 1e3) : null, mayor: parsedPopup.mayor, councillors: parsedPopup.councillors, residents: parsedPopup.residents, x: midrange(townX), z: midrange(townZ), area: calcAreaPoints(points), points, bounds: { x: townX, z: townZ }, flags: { pvp: asBool(parsedPopup.flags.pvp), public: asBool(parsedPopup.flags.public), capital: nationName == "No Nation" ? false : isCapital(curMarker) }, colours: { fill: curMarker.fillColor || curMarker.color, outline: curMarker.color }, opacities: { fill: curMarker.fillOpacity || curMarker.opacity, outline: curMarker.opacity } }; if (parsedPopup.board && parsedPopup.board != "/town set board [msg]") { town.board = parsedPopup.board; } if (parsedPopup.wikis.town || parsedPopup.wikis.nation) { town.wikis = {}; } if (parsedPopup.wikis.town) { town.wikis.town = parsedPopup.wikis.town; } if (parsedPopup.wikis.nation) { town.wikis.nation = parsedPopup.wikis.nation; } towns.push(town); } return towns; }; const parseNations = (towns) => { var _a, _b; const raw = {}; const nations = []; const len = towns.length; for (let i = 0; i < len; i++) { const town = towns[i]; const nationName = town.nation; if (nationName == "No Nation") continue; if (!raw[nationName]) { raw[nationName] = { name: nationName, residents: [], councillors: [], towns: [], area: 0, king: void 0, capital: void 0 }; nations.push(raw[nationName]); } raw[nationName].residents = fastMergeUnique(raw[nationName].residents, town.residents); raw[nationName].councillors = fastMergeUnique(raw[nationName].councillors, town.councillors); raw[nationName].area += town.area; if (raw[nationName].name == nationName) { (_a = raw[nationName].towns) == null ? void 0 : _a.push(town.name); } if (town.flags.capital) { if ((_b = town.wikis) == null ? void 0 : _b.nation) raw[nationName].wiki = town.wikis.nation; raw[nationName].king = town.mayor; raw[nationName].capital = { name: town.name, x: town.x, z: town.z }; } } return nations; }; const parseResidents = (towns) => towns.reduce((acc, town) => { acc.push.apply(acc, town.residents.map((res) => ({ name: res, town: town.name, nation: town.nation, rank: town.mayor == res ? town.flags.capital ? "Nation Leader" : "Mayor" : "Resident" }))); return acc; }, []); const editPlayerProps = (player) => ({ uuid: player.uuid, name: player.name, nickname: player.display_name ? striptags(formatString(player.display_name)) : null, x: player.x, y: player.y, z: player.z, yaw: player.yaw, world: player.world }); const parsePlayers = (players) => { if (!players) throw new Error("Error parsing players: Input was null or undefined!"); if (!(players instanceof Array)) throw new TypeError("Error parsing players: Input type must be `Object` or `Array`."); return players.length > 0 ? players.map((p) => editPlayerProps(p)) : []; }; var __defProp$7 = Object.defineProperty; var __typeError$5 = (msg) => { throw TypeError(msg); }; var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value); var __accessCheck$5 = (obj, member, msg) => member.has(obj) || __typeError$5("Cannot " + msg); var __privateGet$5 = (obj, member, getter) => (__accessCheck$5(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd$5 = (obj, member, value) => member.has(obj) ? __typeError$5("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet$4 = (obj, member, value, setter) => (__accessCheck$5(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); var _map$4; class Towns { constructor(map) { __privateAdd$5(this, _map$4); __publicField$7(this, "fromNation", async (nationName) => { if (!nationName) throw new InvalidError(`Parameter 'nation' is ${nationName}`); const nation = await this.map.Nations.get(nationName); if (nation instanceof Error) throw nation; return await this.get(...nation.towns); }); __publicField$7(this, "get", async (...names) => { const towns = await this.all(); if (!towns) throw new FetchError("Error fetching towns! Please try again."); const existing = getExisting(towns, names, "name"); return existing.length > 1 ? Promise.all(existing) : Promise.resolve(existing[0]); }); __publicField$7(this, "all", async (_removeAccents = false) => { const cachedTowns = this.map.getFromCache("towns"); if (cachedTowns) return cachedTowns; const markerset = await this.map.markerset(); const towns = parseTowns(markerset); if (towns.length > 0) { this.map.putInCache("towns", towns); } return towns; }); __publicField$7(this, "nearby", async (location, radius, towns) => getNearest(location, radius, towns, this.all)); // TODO: Maybe put this into common.ts ? __publicField$7(this, "invitable", async (nationName, includeBelonging = false) => { const nation = await this.map.Nations.get(nationName); if (nation instanceof NotFoundError) throw new Error("Error checking invitable: Nation does not exist!"); if (!nation) throw new Error("Error checking invitable: Could not fetch the nation!"); const towns = await this.all(); if (!towns) throw new FetchError("An error occurred fetching towns!"); return towns.filter((t) => isInvitable(t, nation, this.map.inviteRange, includeBelonging)); }); __privateSet$4(this, _map$4, map); } get map() { return __privateGet$5(this, _map$4); } // readonly totalWealth = async() => { // // Could do this with nations instead, but towns is likely to be more reliable. // const towns = await this.all() // return towns.reduce((acc, town) => acc + town.wealth || 0, 0) // } } _map$4 = new WeakMap(); var __defProp$6 = Object.defineProperty; var __typeError$4 = (msg) => { throw TypeError(msg); }; var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value); var __accessCheck$4 = (obj, member, msg) => member.has(obj) || __typeError$4("Cannot " + msg); var __privateGet$4 = (obj, member, getter) => (__accessCheck$4(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd$4 = (obj, memb