earthmc
Version:
An unofficial EarthMC library providing handy methods and extensive info.
1,247 lines (1,226 loc) • 76.1 kB
JavaScript
'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(/((")|(&\w[a-z0-9].|&[0-9kmnola-z]));/g, "").replace(/"|'/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