UNPKG

@bedrock-oss/bedrock-boost

Version:

A utility package with helper functions for developing add-ons with Script API in Minecraft Bedrock Edition

1,649 lines (1,642 loc) 96.8 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { CameraShakeType: () => CameraShakeType, ChatColor: () => ChatColor, ColorJSON: () => ColorJSON, ColorUtils: () => ColorUtils, CommandUtils: () => CommandUtils, DirectionUtils: () => DirectionUtils, EntityPulseScheduler: () => EntityPulseScheduler, EntitySaver: () => EntitySaver, EntityUtils: () => EntityUtils, InputPermission: () => InputPermission, ItemUtils: () => ItemUtils, LogLevel: () => LogLevel, Logger: () => Logger, OutputType: () => OutputType, PlayerPulseScheduler: () => PlayerPulseScheduler, Polyfill: () => Polyfill, PulseScheduler: () => PulseScheduler, SlotLocation: () => SlotLocation, TaskPulseScheduler: () => TaskPulseScheduler, TimeOfDay: () => TimeOfDay, Timings: () => Timings, UniquePulseScheduler: () => UniquePulseScheduler, VanillaBlockTags: () => VanillaBlockTags, VanillaItemTags: () => VanillaItemTags, Vec3: () => Vec3, addIdleDummy: () => addIdleDummy, clearIdleDummy: () => clearIdleDummy, consumeDurability: () => consumeDurability, getBlockPermutation: () => getBlockPermutation, getDimension: () => getDimension, getDimensionHeightRange: () => getDimensionHeightRange, isValidLocation: () => isValidLocation, jobProgressPromise: () => jobProgressPromise, jobPromise: () => jobPromise, sendMolangData: () => sendMolangData }); module.exports = __toCommonJS(src_exports); // src/Vec3.ts var import_server2 = require("@minecraft/server"); // src/Logging.ts var import_server = require("@minecraft/server"); // src/ChatColor.ts var ChatColor = class _ChatColor { /** * Class ChatColor Constructor. * @param code - The color code as a string. * @param color - The color code as a hexadecimal number. Can be undefined. */ constructor(code, color) { this.code = code; this.color = color; if (color) { this.r = color >> 16 & 255; this.g = color >> 8 & 255; this.b = color & 255; } } /** * Black color code. (0) */ static BLACK = new _ChatColor("0", 0); /** * Dark blue color code. (1) */ static DARK_BLUE = new _ChatColor("1", 170); /** * Dark green color code. (2) */ static DARK_GREEN = new _ChatColor("2", 43520); /** * Dark aqua color code. (3) */ static DARK_AQUA = new _ChatColor("3", 43690); /** * Dark red color code. (4) */ static DARK_RED = new _ChatColor("4", 11141120); /** * Dark purple color code. (5) */ static DARK_PURPLE = new _ChatColor("5", 11141290); /** * Gold color code. (6) */ static GOLD = new _ChatColor("6", 16755200); /** * Gray color code. (7) */ static GRAY = new _ChatColor("7", 11184810); /** * Dark gray color code. (8) */ static DARK_GRAY = new _ChatColor("8", 5592405); /** * Blue color code. (9) */ static BLUE = new _ChatColor("9", 5592575); /** * Green color code. (a) */ static GREEN = new _ChatColor("a", 5635925); /** * Aqua color code. (b) */ static AQUA = new _ChatColor("b", 5636095); /** * Red color code. (c) */ static RED = new _ChatColor("c", 16733525); /** * Light purple color code. (d) */ static LIGHT_PURPLE = new _ChatColor("d", 16733695); /** * Yellow color code. (e) */ static YELLOW = new _ChatColor("e", 16777045); /** * White color code. (f) */ static WHITE = new _ChatColor("f", 16777215); /** * MineCoin gold color code. (g) */ static MINECOIN_GOLD = new _ChatColor("g", 14603781); /** * Material quartz color code. (h) */ static MATERIAL_QUARTZ = new _ChatColor("h", 14931153); /** * Material iron color code. (i) */ static MATERIAL_IRON = new _ChatColor("i", 13552330); /** * Material netherite color code. (j) */ static MATERIAL_NETHERITE = new _ChatColor("j", 4471355); /** * Material redstone color code. (m) */ static MATERIAL_REDSTONE = new _ChatColor("m", 9901575); /** * Material copper color code. (n) */ static MATERIAL_COPPER = new _ChatColor("n", 11823181); /** * Material gold color code. (p) */ static MATERIAL_GOLD = new _ChatColor("p", 14594349); /** * Material emerald color code. (q) */ static MATERIAL_EMERALD = new _ChatColor("q", 1155126); /** * Material diamond color code. (s) */ static MATERIAL_DIAMOND = new _ChatColor("s", 2931368); /** * Material lapis color code. (t) */ static MATERIAL_LAPIS = new _ChatColor("t", 2181499); /** * Material amethyst color code. (u) */ static MATERIAL_AMETHYST = new _ChatColor("u", 10116294); /** * Obfuscated color code. (k) */ static OBFUSCATED = new _ChatColor("k"); /** * Bold color code. (l) */ static BOLD = new _ChatColor("l"); /** * Italic color code. (o) */ static ITALIC = new _ChatColor("o"); /** * Reset color code. (r) */ static RESET = new _ChatColor("r"); /** * All available color codes. */ static VALUES = [ _ChatColor.BLACK, _ChatColor.DARK_BLUE, _ChatColor.DARK_GREEN, _ChatColor.DARK_AQUA, _ChatColor.DARK_RED, _ChatColor.DARK_PURPLE, _ChatColor.GOLD, _ChatColor.GRAY, _ChatColor.DARK_GRAY, _ChatColor.BLUE, _ChatColor.GREEN, _ChatColor.AQUA, _ChatColor.RED, _ChatColor.LIGHT_PURPLE, _ChatColor.YELLOW, _ChatColor.WHITE, _ChatColor.MINECOIN_GOLD, _ChatColor.MATERIAL_QUARTZ, _ChatColor.MATERIAL_IRON, _ChatColor.MATERIAL_NETHERITE, _ChatColor.MATERIAL_REDSTONE, _ChatColor.MATERIAL_COPPER, _ChatColor.MATERIAL_GOLD, _ChatColor.MATERIAL_EMERALD, _ChatColor.MATERIAL_DIAMOND, _ChatColor.MATERIAL_LAPIS, _ChatColor.MATERIAL_AMETHYST, _ChatColor.OBFUSCATED, _ChatColor.BOLD, _ChatColor.ITALIC, _ChatColor.RESET ]; /** * All available color codes excluding the formatting codes. */ static ALL_COLORS = [ _ChatColor.BLACK, _ChatColor.DARK_BLUE, _ChatColor.DARK_GREEN, _ChatColor.DARK_AQUA, _ChatColor.DARK_RED, _ChatColor.DARK_PURPLE, _ChatColor.GOLD, _ChatColor.GRAY, _ChatColor.DARK_GRAY, _ChatColor.BLUE, _ChatColor.GREEN, _ChatColor.AQUA, _ChatColor.RED, _ChatColor.LIGHT_PURPLE, _ChatColor.YELLOW, _ChatColor.WHITE, _ChatColor.MINECOIN_GOLD, _ChatColor.MATERIAL_QUARTZ, _ChatColor.MATERIAL_IRON, _ChatColor.MATERIAL_NETHERITE, _ChatColor.MATERIAL_REDSTONE, _ChatColor.MATERIAL_COPPER, _ChatColor.MATERIAL_GOLD, _ChatColor.MATERIAL_EMERALD, _ChatColor.MATERIAL_DIAMOND, _ChatColor.MATERIAL_LAPIS, _ChatColor.MATERIAL_AMETHYST ]; r; g; b; /** * PREFIX is the section sign (§) used in Minecraft color codes. */ static PREFIX = "\xA7"; /** * Returns the string representation of the ChatColor instance, * which includes the PREFIX followed by the color code. * @returns A string representing the ChatColor instance */ toString() { return _ChatColor.PREFIX + this.code; } /** * Returns the color code of the ChatColor instance. * @returns The color code of this ChatColor instance. */ toRGB() { return this.color; } /** * Returns the hexadecimal string representation of the color code * @returns {string | undefined} The hexadecimal representation of the color. */ toHex() { return this.color?.toString(16); } /** * Retrieve the value of the red component. * * @returns {number | undefined} The value of the red component, or undefined if it is not set. */ getRed() { return this.r; } /** * Retrieves the green value of the current color. * * @returns {number | undefined} The green value of the color, or undefined if it is not set. */ getGreen() { return this.g; } /** * Retrieves the blue value of a color. * * @returns The blue value of the color. * @type {number | undefined} */ getBlue() { return this.b; } /** * Retrieves the format code associated with the chat color. * * @returns {string} The format code of the chat color. */ getCode() { return this.code; } /** * Removes color codes from the specified string * @param str - The string from which color codes will be removed. * @returns The string cleared from color codes. */ static stripColor(str) { return str.replace(/§[0-9a-u]/g, ""); } /** * Finds the closest ChatColor code for the given RGB values * @param r - Red part of the color. * @param g - Green part of the color. * @param b - Blue part of the color. * @returns The closest ChatColor for the given RGB values. */ static findClosestColor(r, g, b) { let minDistance = Number.MAX_VALUE; let closestColor = _ChatColor.WHITE; for (const color of _ChatColor.ALL_COLORS) { if (color.r && color.g && color.b) { const distance = Math.sqrt(Math.pow(color.r - r, 2) + Math.pow(color.g - g, 2) + Math.pow(color.b - b, 2)); if (distance < minDistance) { minDistance = distance; closestColor = color; } } } return closestColor; } }; // src/ColorJSON.ts var ColorJSON = class _ColorJSON { // Tokens OpenObject = "{"; CloseObject = "}"; OpenArray = "["; CloseArray = "]"; Comma = ","; KeyValueSeparator = ":"; StringDelimiter = '"'; KeyDelimiter = ""; Indent = " "; NewLine = "\n"; Space = " "; // Threshold for inline representation InlineThreshold = 60; // Maximum depth to which objects will be traversed MaxDepth = 1; // Whether to include class names IncludeClassNames = true; // Values FunctionValue = "\u0192"; NullValue = "null"; UndefinedValue = "undefined"; TrueValue = "true"; FalseValue = "false"; CycleValue = "[...cycle...]"; TruncatedObjectValue = "{...}"; // Colors OpenCloseObjectColor = ChatColor.YELLOW; OpenCloseArrayColor = ChatColor.AQUA; NumberColor = ChatColor.DARK_AQUA; StringColor = ChatColor.DARK_GREEN; BooleanColor = ChatColor.GOLD; NullColor = ChatColor.GOLD; KeyColor = ChatColor.GRAY; EscapeColor = ChatColor.GOLD; FunctionColor = ChatColor.GRAY; ClassColor = ChatColor.GRAY; ClassStyle = ChatColor.BOLD; CycleColor = ChatColor.DARK_RED; /** * The default ColorJSON instance */ static DEFAULT = new _ColorJSON(); static createPlain() { const plain = new _ColorJSON(); plain.OpenCloseObjectColor = ""; plain.OpenCloseArrayColor = ""; plain.NumberColor = ""; plain.StringColor = ""; plain.BooleanColor = ""; plain.NullColor = ""; plain.KeyColor = ""; plain.EscapeColor = ""; plain.FunctionColor = ""; plain.ClassColor = ""; plain.ClassStyle = ""; plain.CycleColor = ""; return plain; } /** * A ColorJSON instance that does not colorize anything. */ static PLAIN = this.createPlain(); /** * Transforms a value into a chat-friendly, colored JSON representation. * @param value - The value to transform. */ stringify(value) { return this.stringifyValue(value, { indentLevel: 0, visited: /* @__PURE__ */ new WeakSet() }); } /** * Transforms a string into a JSON representation. * @param value - The string to transform. */ stringifyString(value) { return this.StringColor + this.StringDelimiter + this.escapeString(value) + this.StringDelimiter + ChatColor.RESET; } /** * Transforms a number into a JSON representation. * @param value - The number to transform. */ stringifyNumber(value) { return this.NumberColor + value.toString() + ChatColor.RESET; } /** * Transforms a boolean into a JSON representation. * @param value - The boolean to transform. */ stringifyBoolean(value) { return this.BooleanColor + (value ? this.TrueValue : this.FalseValue) + ChatColor.RESET; } /** * Transforms a function into a JSON representation. * @param value - The function to transform. */ // eslint-disable-next-line @typescript-eslint/ban-types stringifyFunction(value) { return this.FunctionColor + this.FunctionValue + ChatColor.RESET; } /** * Returns a null JSON representation. */ stringifyNull() { return this.NullColor + this.NullValue + ChatColor.RESET; } /** * Returns an undefined JSON representation. */ stringifyUndefined() { return this.NullColor + this.UndefinedValue + ChatColor.RESET; } /** * Returns a cycle JSON representation. */ stringifyCycle() { return this.CycleColor + this.CycleValue + ChatColor.RESET; } /** * Transforms an array into a JSON representation. * @param value - The array to transform. * @param indentLevel - The indentation level for pretty-printing. */ stringifyArray(value, ctx) { const indentSpace = this.Indent.repeat(ctx.indentLevel); if (value.length === 0) { return this.OpenCloseArrayColor + this.OpenArray + this.CloseArray + ChatColor.RESET; } let result = this.OpenCloseArrayColor + this.OpenArray + ChatColor.RESET + this.NewLine; let compactResult = this.OpenCloseArrayColor + this.OpenArray + ChatColor.RESET; value.forEach((item, index) => { result += indentSpace + this.Indent + this.stringifyValue(item, this.indent(ctx)); result += index < value.length - 1 ? this.Comma + this.NewLine : this.NewLine; compactResult += this.stringifyValue(item, this.indent(ctx)); compactResult += index < value.length - 1 ? this.Comma + this.Space : ""; }); result += indentSpace + this.OpenCloseArrayColor + this.CloseArray + ChatColor.RESET; compactResult += this.OpenCloseArrayColor + this.CloseArray + ChatColor.RESET; if (compactResult.length < this.InlineThreshold) { return compactResult; } return result; } /** * Transforms an object into a truncated JSON representation. * @param value - The object to transform. * @param className - Class Name of the object. * @param indentLevel - The indentation level for pretty-printing. */ stringifyTruncatedObject(value, className, ctx) { return (this.IncludeClassNames ? this.ClassColor + "" + this.ClassStyle + className + ChatColor.RESET + this.Space : "") + this.TruncatedObjectValue; } /** * Transforms an object into a JSON representation. * @param value - The object to transform. * @param className - Class Name of the object. * @param entries - Entries of the object to transform. * @param indentLevel - The indentation level for pretty-printing. */ stringifyObject(value, className, entries, ctx) { const indentSpace = this.Indent.repeat(ctx.indentLevel); const prefix = this.IncludeClassNames && className !== "Object" ? this.ClassColor + "" + this.ClassStyle + className + ChatColor.RESET + this.Space : ""; if (entries.length === 0) { return prefix + this.OpenCloseObjectColor + this.OpenObject + this.CloseObject + ChatColor.RESET; } let result = prefix + this.OpenCloseObjectColor + this.OpenObject + ChatColor.RESET + this.NewLine; let compactResult = prefix + this.OpenCloseObjectColor + this.OpenObject + ChatColor.RESET; entries.forEach(([key, val], index) => { const compactVal = this.stringifyValue(val, this.indent(ctx)); result += indentSpace + this.Indent + this.KeyColor + this.KeyDelimiter + key + this.KeyDelimiter + ChatColor.RESET + this.KeyValueSeparator + this.Space + compactVal; result += index < entries.length - 1 ? this.Comma + this.NewLine : this.NewLine; compactResult += this.KeyColor + key + ChatColor.RESET + this.KeyValueSeparator + this.Space + compactVal; compactResult += index < entries.length - 1 ? this.Comma + this.Space : ""; }); result += indentSpace + this.OpenCloseObjectColor + this.CloseObject + ChatColor.RESET; compactResult += this.OpenCloseObjectColor + this.CloseObject + ChatColor.RESET; if (compactResult.length < this.InlineThreshold) { return compactResult; } return result; } shouldTruncateObject(value, className, ctx) { return !(className === "Object" || ctx.indentLevel <= this.MaxDepth || this.MaxDepth <= 0); } /** * Transforms a value of any type into a JSON representation. This function is not meant to be overridden. * @param value - The value to transform. * @param indentLevel - The indentation level for pretty-printing. */ stringifyValue(value, ctx) { if (value === null) return this.stringifyNull(); if (value === void 0) return this.stringifyUndefined(); if (typeof value === "number") return this.stringifyNumber(value); if (typeof value === "string") return this.stringifyString(value); if (typeof value === "boolean") return this.stringifyBoolean(value); if (typeof value === "function") return this.stringifyFunction(value); if (this.isCycle(value, ctx)) { return this.stringifyCycle(); } this.markCycle(value, ctx); if (Array.isArray(value)) { const result = this.stringifyArray(value, ctx.indentLevel ? this.indent(ctx) : ctx); this.clearCycle(value, ctx); return result; } if (typeof value === "object") { const name = value.constructor.name; if (!this.shouldTruncateObject(value, name, ctx)) { const keySet = /* @__PURE__ */ new Set(); let prototype = Object.getPrototypeOf(value); let keys = Object.keys(prototype); while (keys.length > 0) { keys.forEach((key) => keySet.add(key)); prototype = Object.getPrototypeOf(prototype); keys = Object.keys(prototype); } Object.keys(value).forEach((key) => keySet.add(key)); keySet.delete("__cycleDetection__"); const allKeys = [...keySet].sort(); const entries = allKeys.map((key) => { try { return [key, value[key] ?? void 0]; } catch (e) { return [key, void 0]; } }).filter(([, val]) => typeof val !== "function" && val !== void 0); const result = this.stringifyObject(value, name, entries, ctx); this.clearCycle(value, ctx); return result; } else { const result = this.stringifyTruncatedObject(value, name, ctx); this.clearCycle(value, ctx); return result; } } this.clearCycle(value, ctx); return ChatColor.RESET + value.toString(); } /** * Escapes a string for JSON. * @param str - The string to escape. */ escapeString(str) { return str.replace(/\\/g, this.EscapeColor + "\\\\" + this.StringColor).replace(/"/g, this.EscapeColor + '\\"' + this.StringColor).replace(/\n/g, this.EscapeColor + "\\n" + this.StringColor).replace(/\r/g, this.EscapeColor + "\\r" + this.StringColor).replace(/\t/g, this.EscapeColor + "\\t" + this.StringColor); } markCycle(value, ctx) { ctx.visited.add(value); } isCycle(value, ctx) { return ctx.visited.has(value); } clearCycle(value, ctx) { ctx.visited.delete(value); } indent(ctx) { return { ...ctx, indentLevel: ctx.indentLevel + 1 }; } }; // src/Logging.ts var sourceMapping = void 0; try { sourceMapping = globalSourceMapping; } catch (e) { } var OutputType = /* @__PURE__ */ ((OutputType2) => { OutputType2[OutputType2["Chat"] = 0] = "Chat"; OutputType2[OutputType2["ConsoleInfo"] = 1] = "ConsoleInfo"; OutputType2[OutputType2["ConsoleWarn"] = 2] = "ConsoleWarn"; OutputType2[OutputType2["ConsoleError"] = 3] = "ConsoleError"; return OutputType2; })(OutputType || {}); var LogLevel = class _LogLevel { /** * The constructor for each log level. * * @param {number} level - The numerical level for this logger. * @param {string} name - The string name for this logger. * @param {ChatColor} color - The color to use for this logger. Defaults to `ChatColor.RESET`. */ constructor(level, name, color = ChatColor.RESET) { this.level = level; this.name = name; this.color = color; } static All = new _LogLevel(-2, "all"); static Trace = new _LogLevel(-2, "trace", ChatColor.DARK_AQUA); static Debug = new _LogLevel(-1, "debug", ChatColor.AQUA); static Info = new _LogLevel(0, "info", ChatColor.GREEN); static Warn = new _LogLevel(1, "warn", ChatColor.GOLD); static Error = new _LogLevel(2, "error", ChatColor.RED); static Fatal = new _LogLevel(3, "fatal", ChatColor.DARK_RED); static Off = new _LogLevel(100, "off"); /** * The list of all available log levels. */ static values = [ _LogLevel.All, _LogLevel.Trace, _LogLevel.Debug, _LogLevel.Info, _LogLevel.Warn, _LogLevel.Error, _LogLevel.Fatal, _LogLevel.Off ]; /** * Return the logging level as a string. * * @returns {string} The string representation of the logging level. */ toString() { return this.color + this.name.toUpperCase() + ChatColor.RESET; } /** * Parse a string to get the corresponding `LogLevel`. * * @param {string} str - The string to parse. * @returns {LogLevel} The corresponding `LogLevel`, or `undefined` if none was found. */ static parse(str) { str = str.toLowerCase(); for (const level of _LogLevel.values) { if (level.name === str) return level; } const num = parseInt(str); if (!isNaN(num)) { for (const level of _LogLevel.values) { if (level.level === num) return level; } } return void 0; } }; function starMatch(pattern, str) { if (pattern === "*") return true; if (pattern.includes("*")) { if (pattern.startsWith("*")) { return str.endsWith(pattern.substring(1)); } if (pattern.endsWith("*")) { return str.startsWith(pattern.substring(0, pattern.length - 1)); } const regex = new RegExp(pattern.replace(/\*/g, ".*")); return regex.test(str); } return pattern === str; } var loggingSettings = { level: LogLevel.Info, filter: ["*"], outputTags: false, formatFunction: (level, logger, message, tags = void 0) => { const _tags = tags !== void 0 ? `\xA77${tags.map((tag) => `[${tag}]`).join("")}\xA7r` : ""; return `[${level}][${ChatColor.MATERIAL_EMERALD}${logger.name}${ChatColor.RESET}]${_tags} ${message}`; }, messagesJoinFunction: (messages) => { return messages.join(" "); }, jsonFormatter: ColorJSON.DEFAULT, outputConfig: { [LogLevel.Trace.level]: [0 /* Chat */, 1 /* ConsoleInfo */], [LogLevel.Debug.level]: [0 /* Chat */, 1 /* ConsoleInfo */], [LogLevel.Info.level]: [0 /* Chat */, 1 /* ConsoleInfo */], [LogLevel.Warn.level]: [ 0 /* Chat */, 1 /* ConsoleInfo */, 2 /* ConsoleWarn */ ], [LogLevel.Error.level]: [ 0 /* Chat */, 1 /* ConsoleInfo */, 3 /* ConsoleError */ ], [LogLevel.Fatal.level]: [ 0 /* Chat */, 1 /* ConsoleInfo */, 3 /* ConsoleError */ ] } }; var Logger = class _Logger { /** * Construct a new Logger * * @param {string} name - The name of the Logger. * @param {string[]} tags - The tags for the logger as strings. */ constructor(name, tags = []) { this.name = name; this.tags = tags; } static initialized = false; /** * Initialize logger class */ static init() { LOGGING: { if (_Logger.initialized) return; _Logger.initialized = true; import_server.system.afterEvents.scriptEventReceive.subscribe((ev) => { if (ev.id === "logging:level" || ev.id === "log:level") { if (!ev.message) { loggingSettings.level = LogLevel.Info; import_server.world.sendMessage( `${ChatColor.AQUA}Logging level set to ${ChatColor.BOLD}${loggingSettings.level}` ); } else { const level = LogLevel.parse(ev.message); if (level) { loggingSettings.level = level; import_server.world.sendMessage( `${ChatColor.AQUA}Logging level set to ${ChatColor.BOLD}${loggingSettings.level}` ); } else { import_server.world.sendMessage( `${ChatColor.DARK_RED}Invalid logging level: ${ev.message}` ); } } } else if (ev.id === "logging:filter" || ev.id === "log:filter") { if (!ev.message) { loggingSettings.filter = ["*"]; } else { loggingSettings.filter = ev.message.split(","); } import_server.world.sendMessage( `${ChatColor.AQUA}Logging filter set to ${ChatColor.BOLD}${loggingSettings.filter.join(", ")}` ); } }); } } /** * @param {LogLevel} level - The level to set. */ static setLevel(level) { loggingSettings.level = level; } /** * Filter the loggers by the given tags. Tags can use the `*` wildcard. * @param {'*' | string[]} filter - The filter to set. */ static setFilter(filter) { loggingSettings.filter = filter; } /** * Set the format function for the logger. * @param {function} func - The function to set. */ static setFormatFunction(func) { loggingSettings.formatFunction = func; } /** * Set the function, that joins multiple messages into one for the logger. * @param {function} func - The function to set. */ static setMessagesJoinFunction(func) { loggingSettings.messagesJoinFunction = func; } /** * Set the tag visibility for the logger. When true, tags will be printed in the log. Disabled by default. * @param visible */ static setTagsOutputVisibility(visible) { loggingSettings.outputTags = visible; } /** * Set the JSON formatter for the logger. * @param {ColorJSON} formatter - The json formatter to set. */ static setJsonFormatter(formatter) { loggingSettings.jsonFormatter = formatter; } /** * Get the output configuration for the logger. * @returns {OutputConfig} The output configuration. */ static getOutputConfig() { return loggingSettings.outputConfig; } /** * Returns a new Logger. * * @param {string} name - The name of the Logger. * @param {string[]} tags - The tags for the Logger as strings. * * @returns {Logger} A new Logger. */ static getLogger(name, ...tags) { LOGGING: { if (!_Logger.initialized) { _Logger.init(); } } return new _Logger(name, tags); } /** * Log messages with the level set. * * @param {LogLevel} level - The LogLevel to log the messages at. * @param {array} message - An array of the messages to log. */ log(level, ...message) { LOGGING: { if (level.level < loggingSettings.level.level) return; if (loggingSettings.filter.length === 0 || this.tags.length === 0) { this.logRaw(level, ...message); return; } for (const filter of loggingSettings.filter) { if (filter.startsWith("!")) { if (starMatch(filter.substring(1), this.name) || this.tags.some((tag) => starMatch(filter.substring(1), tag))) { return; } } if (starMatch(filter, this.name) || this.tags.some((tag) => starMatch(filter, tag))) { this.logRaw(level, ...message); return; } } } } stringifyError(x) { let stack = x.stack ?? ""; if (sourceMapping) { const stackLineRegex = /\(([^)]+\.js):(\d+)(?::(\d+))?\)/; stack = stack.split("\n").map((line) => { const match = stackLineRegex.exec(line); if (match) { const filePath = match[1]; const lineNumber = parseInt(match[2], 10) - sourceMapping.metadata.offset; if (filePath.includes(sourceMapping.metadata.filePath)) { const mappingEntry = globalSourceMapping[lineNumber]; if (mappingEntry) { const replacement = `(${mappingEntry.source}:${mappingEntry.originalLine})`; return line.replace(stackLineRegex, replacement); } } } return line; }).join("\n"); } return `${ChatColor.DARK_RED}${ChatColor.BOLD}${x.message} ${ChatColor.RESET}${ChatColor.GRAY}${ChatColor.ITALIC}${stack}${ChatColor.RESET}`; } /** * Internal function to log messages with the level set, that bypasses the filters. * * @param {LogLevel} level - The LogLevel to log the messages at. * @param {array} message - An array of the messages to log. */ logRaw(level, ...message) { LOGGING: { const msgs = message.map((x) => { if (x === void 0) { return ChatColor.GOLD + "undefined" + ChatColor.RESET; } if (x === null) { return ChatColor.GOLD + "null" + ChatColor.RESET; } if (x && x instanceof Error) { return this.stringifyError(x); } if (typeof x === "object" || Array.isArray(x)) { return loggingSettings.jsonFormatter.stringify(x) + ChatColor.RESET; } return x.toString() + ChatColor.RESET; }); const formatted = loggingSettings.formatFunction( level, this, loggingSettings.messagesJoinFunction(msgs), loggingSettings.outputTags ? this.tags : void 0 ); const outputs = loggingSettings.outputConfig[level.level] || [ 0 /* Chat */, 1 /* ConsoleInfo */ ]; if (outputs.includes(0 /* Chat */)) { try { import_server.world.sendMessage(formatted); } catch (_) { import_server.system.run(() => { import_server.world.sendMessage(formatted); }); } } if (outputs.includes(1 /* ConsoleInfo */)) { if (console.originalLog) { console.originalLog(ChatColor.stripColor(formatted)); } else { console.log(ChatColor.stripColor(formatted)); } } if (outputs.includes(2 /* ConsoleWarn */)) { console.warn(formatted); } if (outputs.includes(3 /* ConsoleError */)) { console.error(formatted); } } } /** * Logs a trace message. * * @param {...unknown} message - The message(s) to be logged. */ trace(...message) { LOGGING: this.log(LogLevel.Trace, ...message); } /** * Logs debug message. * * @param {...unknown[]} message - The message(s) to be logged. */ debug(...message) { LOGGING: this.log(LogLevel.Debug, ...message); } /** * Logs an informational message. * * @param {...unknown[]} message - The message(s) to be logged. */ info(...message) { LOGGING: this.log(LogLevel.Info, ...message); } /** * Logs a warning message. * * @param {...unknown[]} message - The warning message or messages to be logged. */ warn(...message) { LOGGING: this.log(LogLevel.Warn, ...message); } /** * Logs an error message. * * @param {...unknown[]} message - The error message(s) to log. */ error(...message) { LOGGING: this.log(LogLevel.Error, ...message); } /** * Logs a fatal error. * * @param {unknown[]} message - The error message to log. */ fatal(...message) { LOGGING: this.log(LogLevel.Fatal, ...message); } }; // src/Vec3.ts var Vec3 = class _Vec3 { static log = Logger.getLogger( "vec3", "vec3", "bedrock-boost" ); /** * Zero vector */ static Zero = new _Vec3(0, 0, 0); /** * Down vector, negative towards Y */ static Down = new _Vec3(import_server2.Direction.Down); /** * Up vector, positive towards Y */ static Up = new _Vec3(import_server2.Direction.Up); /** * North vector, negative towards Z */ static North = new _Vec3(import_server2.Direction.North); /** * South vector, positive towards Z */ static South = new _Vec3(import_server2.Direction.South); /** * East vector, positive towards X */ static East = new _Vec3(import_server2.Direction.East); /** * West vector, negative towards X */ static West = new _Vec3(import_server2.Direction.West); x; y; z; constructor(x, y, z) { if (x === import_server2.Direction.Down) { this.x = 0; this.y = -1; this.z = 0; } else if (x === import_server2.Direction.Up) { this.x = 0; this.y = 1; this.z = 0; } else if (x === import_server2.Direction.North) { this.x = 0; this.y = 0; this.z = -1; } else if (x === import_server2.Direction.South) { this.x = 0; this.y = 0; this.z = 1; } else if (x === import_server2.Direction.East) { this.x = 1; this.y = 0; this.z = 0; } else if (x === import_server2.Direction.West) { this.x = -1; this.y = 0; this.z = 0; } else if (typeof x === "number") { this.x = x; this.y = y; this.z = z; } else if (Array.isArray(x)) { this.x = x[0]; this.y = x[1]; this.z = x[2]; } else if (x instanceof _Vec3) { this.x = x.x; this.y = x.y; this.z = x.z; } else { if (!x || !x.x && x.x !== 0 || !x.y && x.y !== 0 || !x.z && x.z !== 0) { _Vec3.log.error(new Error("Invalid vector"), x); throw new Error("Invalid vector"); } this.x = x.x; this.y = x.y; this.z = x.z; } } static from(x, y, z) { if (x instanceof _Vec3) return x; if (typeof x === "number" && y !== void 0 && z !== void 0) { return new _Vec3(x, y, z); } if (Array.isArray(x)) { return new _Vec3(x); } if (x === import_server2.Direction.Down) return _Vec3.Down; if (x === import_server2.Direction.Up) return _Vec3.Up; if (x === import_server2.Direction.North) return _Vec3.North; if (x === import_server2.Direction.South) return _Vec3.South; if (x === import_server2.Direction.East) return _Vec3.East; if (x === import_server2.Direction.West) return _Vec3.West; if (!x || !x.x && x.x !== 0 || !x.y && x.y !== 0 || !x.z && x.z !== 0) { _Vec3.log.error(new Error("Invalid arguments"), x, y, z); throw new Error("Invalid arguments"); } return new _Vec3( x.x, x.y, x.z ); } static _from(x, y, z) { if (x instanceof _Vec3) return x; if (typeof x === "number" && y !== void 0 && z !== void 0) { return new _Vec3(x, y, z); } if (Array.isArray(x)) { return new _Vec3(x); } if (x === import_server2.Direction.Down) return _Vec3.Down; if (x === import_server2.Direction.Up) return _Vec3.Up; if (x === import_server2.Direction.North) return _Vec3.North; if (x === import_server2.Direction.South) return _Vec3.South; if (x === import_server2.Direction.East) return _Vec3.East; if (x === import_server2.Direction.West) return _Vec3.West; if (!x || !x.x && x.x !== 0 || !x.y && x.y !== 0 || !x.z && x.z !== 0) { _Vec3.log.error(new Error("Invalid arguments"), x, y, z); throw new Error("Invalid arguments"); } return new _Vec3( x.x, x.y, x.z ); } /** * Creates a copy of the current vector. * * @returns A new vector with the same values as the current vector. */ copy() { return new _Vec3(this.x, this.y, this.z); } static fromYawPitch(yawOrRotation, pitch) { let yaw; if (typeof yawOrRotation === "number") { yaw = yawOrRotation; pitch = pitch; } else { yaw = yawOrRotation.y; pitch = yawOrRotation.x; } const psi = yaw * (Math.PI / 180); const theta = pitch * (Math.PI / 180); const x = Math.cos(theta) * Math.sin(psi); const y = Math.sin(theta); const z = Math.cos(theta) * Math.cos(psi); return new _Vec3(x, y, z); } static fromRotation(yawOrRotation, pitch) { let yaw; if (typeof yawOrRotation === "number") { yaw = yawOrRotation; pitch = pitch; } else { yaw = yawOrRotation.y; pitch = yawOrRotation.x; } const psi = yaw * (Math.PI / 180); const theta = pitch * (Math.PI / 180); const x = -Math.cos(theta) * Math.sin(psi); const y = -Math.sin(theta); const z = Math.cos(theta) * Math.cos(psi); return new _Vec3(x, y, z); } /** * Converts the normal vector to yaw and pitch values. * * @returns A Vector2 containing the yaw and pitch values. * @deprecated Use toRotation() instead. This method returns inverted values and will be removed in the future. */ toYawPitch() { if (this.isZero()) { _Vec3.log.error( new Error("Cannot convert zero-length vector to direction") ); throw new Error("Cannot convert zero-length vector to direction"); } const direction = this.normalize(); const yaw = Math.atan2(direction.x, direction.z) * (180 / Math.PI); const pitch = Math.asin(direction.y) * (180 / Math.PI); return { x: pitch, y: yaw }; } /** * Converts the normal vector to yaw and pitch values. * * @returns A Vector2 containing the yaw and pitch values. */ toRotation() { if (this.isZero()) { _Vec3.log.error( new Error("Cannot convert zero-length vector to direction") ); throw new Error("Cannot convert zero-length vector to direction"); } const direction = this.normalize(); const yaw = -Math.atan2(direction.x, direction.z) * (180 / Math.PI); const pitch = Math.asin(-direction.y) * (180 / Math.PI); return { x: pitch, y: yaw }; } add(x, y, z) { const v = _Vec3._from(x, y, z); return _Vec3.from(v.x + this.x, v.y + this.y, v.z + this.z); } subtract(x, y, z) { const v = _Vec3._from(x, y, z); return _Vec3.from(this.x - v.x, this.y - v.y, this.z - v.z); } multiply(x, y, z) { if (typeof x === "number" && y === void 0 && z === void 0) { return _Vec3.from(this.x * x, this.y * x, this.z * x); } const v = _Vec3._from(x, y, z); return _Vec3.from(v.x * this.x, v.y * this.y, v.z * this.z); } /** * Scales the current vector by a scalar. * * @param scalar - The scalar to scale the vector by. * @returns The updated vector after scaling. */ scale(scalar) { return _Vec3.from(this.x * scalar, this.y * scalar, this.z * scalar); } divide(x, y, z) { if (typeof x === "number" && y === void 0 && z === void 0) { if (x === 0) throw new Error("Cannot divide by zero"); return _Vec3.from(this.x / x, this.y / x, this.z / x); } const v = _Vec3._from(x, y, z); if (v.x === 0 || v.y === 0 || v.z === 0) throw new Error("Cannot divide by zero"); return _Vec3.from(this.x / v.x, this.y / v.y, this.z / v.z); } /** * Normalizes the vector to have a length (magnitude) of 1. * Normalized vectors are often used as a direction vectors. * * @returns The normalized vector. */ normalize() { if (this.isZero()) { _Vec3.log.error(new Error("Cannot normalize zero-length vector")); throw new Error("Cannot normalize zero-length vector"); } const len = this.length(); return _Vec3.from(this.x / len, this.y / len, this.z / len); } /** * Computes the length (magnitude) of the vector. * * @returns The length of the vector. */ length() { return Math.hypot(this.x, this.y, this.z); } /** * Computes the squared length of the vector. * This is faster than computing the actual length and can be useful for comparison purposes. * * @returns The squared length of the vector. */ lengthSquared() { return this.x * this.x + this.y * this.y + this.z * this.z; } cross(x, y, z) { const v = _Vec3._from(x, y, z); return _Vec3.from( this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x ); } distance(x, y, z) { const v = _Vec3._from(x, y, z); return this.subtract(v).length(); } distanceSquared(x, y, z) { const v = _Vec3._from(x, y, z); return this.subtract(v).lengthSquared(); } /** * Computes the linear interpolation between the current vector and another vector, when t is in the range [0, 1]. * Computes the extrapolation when t is outside this range. * * @param v - The other vector. * @param t - The interpolation factor. * @returns A new vector after performing the lerp operation. */ lerp(v, t) { if (!v || !t) return _Vec3.from(this); if (t === 1) return _Vec3.from(v); if (t === 0) return _Vec3.from(this); return _Vec3.from( this.x + (v.x - this.x) * t, this.y + (v.y - this.y) * t, this.z + (v.z - this.z) * t ); } /** * Computes the spherical linear interpolation between the current vector and another vector, when t is in the range [0, 1]. * Computes the extrapolation when t is outside this range. * * @param v - The other vector. * @param t - The interpolation factor. * @returns A new vector after performing the slerp operation. */ slerp(v, t) { if (!v || !t) return _Vec3.from(this); if (t === 1) return _Vec3.from(v); if (t === 0) return _Vec3.from(this); const dot = this.dot(v); const theta = Math.acos(dot) * t; const relative = _Vec3.from(v).subtract(this.multiply(dot)).normalize(); return this.multiply(Math.cos(theta)).add( relative.multiply(Math.sin(theta)) ); } dot(x, y, z) { const v = _Vec3._from(x, y, z); return this.x * v.x + this.y * v.y + this.z * v.z; } angleBetween(x, y, z) { const v = _Vec3._from(x, y, z); const dotProduct = this.dot(v); const lenSq1 = this.lengthSquared(); if (lenSq1 === 0) { return 0; } const lenSq2 = v.lengthSquared(); if (lenSq2 === 0) { return 0; } const denom = Math.sqrt(lenSq1 * lenSq2); const cosAngle = Math.min(1, Math.max(-1, dotProduct / denom)); return Math.acos(cosAngle); } projectOnto(x, y, z) { const v = _Vec3._from(x, y, z); if (v.isZero()) { return _Vec3.Zero; } const denom = v.dot(v); if (denom === 0) { return _Vec3.Zero; } const scale = this.dot(v) / denom; return _Vec3.from(v.x * scale, v.y * scale, v.z * scale); } reflect(x, y, z) { const normal = _Vec3._from(x, y, z); const proj = this.projectOnto(normal); return this.subtract(proj.multiply(2)); } /** * Rotates the current normalized vector by a given angle around a given axis. * * @param axis - The axis of rotation. * @param angle - The angle of rotation in degrees. * @returns The rotated vector. */ rotate(axis, angle) { const halfAngle = angle * Math.PI / 180 / 2; const w = Math.cos(halfAngle); const x = axis.x * Math.sin(halfAngle); const y = axis.y * Math.sin(halfAngle); const z = axis.z * Math.sin(halfAngle); const v = this; const qv_x = w * w * v.x + 2 * y * w * v.z - 2 * z * w * v.y + x * x * v.x + 2 * y * x * v.y + 2 * z * x * v.z - z * z * v.x - y * y * v.x; const qv_y = 2 * x * y * v.x + y * y * v.y + 2 * z * y * v.z + 2 * w * z * v.x - z * z * v.y + w * w * v.y - 2 * x * w * v.z - x * x * v.y; const qv_z = 2 * x * z * v.x + 2 * y * z * v.y + z * z * v.z - 2 * w * y * v.x - y * y * v.z + 2 * w * x * v.y - x * x * v.z + w * w * v.z; return new _Vec3(qv_x, qv_y, qv_z); } /** * Updates the X, Y, and Z components of the vector. * * @param x - The function to use to update the X value. * @param y - The function to use to update the Y value. * @param z - The function to use to update the Z value. * @returns The updated vector with the new values. */ update(x, y, z) { if (!x) { x = (value) => value; } if (!y) { y = (value) => value; } if (!z) { z = (value) => value; } return new _Vec3(x(this.x), y(this.y), z(this.z)); } setX(value) { if (typeof value === "number") { return new _Vec3(value, this.y, this.z); } return new _Vec3(value(this.x), this.y, this.z); } setY(value) { if (typeof value === "number") { return new _Vec3(this.x, value, this.z); } return new _Vec3(this.x, value(this.y), this.z); } setZ(value) { if (typeof value === "number") { return new _Vec3(this.x, this.y, value); } return new _Vec3(this.x, this.y, value(this.z)); } /** * Calculates the shortest distance between a point (represented by this Vector3 instance) and a line segment. * * This method finds the perpendicular projection of the point onto the line defined by the segment. If this * projection lies outside the line segment, then the method calculates the distance from the point to the * nearest segment endpoint. * * @param start - The starting point of the line segment. * @param end - The ending point of the line segment. * @returns The shortest distance between the point and the line segment. */ distanceToLineSegment(start, end) { const lineDirection = _Vec3.from(end).subtract(start); if (lineDirection.lengthSquared() === 0) { return this.subtract(start).length(); } const t = Math.max( 0, Math.min( 1, this.subtract(start).dot(lineDirection) / lineDirection.dot(lineDirection) ) ); const projection = _Vec3.from(start).add(lineDirection.multiply(t)); return this.subtract(projection).length(); } /** * Floors the X, Y, and Z components of the vector. * @returns A new vector with the floored components. */ floor() { return this.update(Math.floor, Math.floor, Math.floor); } /** * Floors the X component of the vector. * @returns A new vector with the floored X component. */ floorX() { return this.setX(Math.floor); } /** * Floors the Y component of the vector. * @returns A new vector with the floored Y component. */ floorY() { return this.setY(Math.floor); } /** * Floors the Z component of the vector. * @returns A new vector with the floored Z component. */ floorZ() { return this.setZ(Math.floor); } /** * Ceils the X, Y, and Z components of the vector. * @returns A new vector with the ceiled components. */ ceil() { return new _Vec3(Math.ceil(this.x), Math.ceil(this.y), Math.ceil(this.z)); } /** * Ceils the X component of the vector. * @returns A new vector with the ceiled X component. */ ceilX() { return this.setX(Math.ceil); } /** * Ceils the Y component of the vector. * @returns A new vector with the ceiled Y component. */ ceilY() { return this.setY(Math.ceil); } /** * Ceils the Z component of the vector. * @returns A new vector with the ceiled Z component. */ ceilZ() { return this.setZ(Math.ceil); } /** * Rounds the X, Y, and Z components of the vector. * @returns A new vector with the rounded components. */ round() { return this.update(Math.round, Math.round, Math.round); } /** * Rounds the X component of the vector. * @returns A new vector with the rounded X component. */ roundX() { return this.setX(Math.round); } /** * Rounds the Y component of the vector. * @returns A new vector with the rounded Y component. */ roundY() { return this.setY(Math.round); } /** * Rounds the Z component of the vector. * @returns A new vector with the rounded Z component. */ roundZ() { return this.setZ(Math.round); } /** * Returns a new vector offset from the current vector up by 1 block. * @returns A new vector offset from the current vector up by 1 block. */ up() { return this.add(_Vec3.Up); } /** * Returns a new vector offset from the current vector down by 1 block. * @returns A new vector offset from the current vector down by 1 block. */ down() { return this.add(_Vec3.Down); } /** * Returns a new vector offset from the current vector north by 1 block. * @returns A new vector offset from the current vector north by 1 block. */ north() { return this.add(_Vec3.North); } /** * Returns a new vector offset from the current vector south by 1 block. * @returns A new vector offset from the current vector south by 1 block. */ south() { return this.add(_Vec3.South); } /** * Returns a new vector offset from the current vector east by 1 block. * @returns A new vector offset from the current vector east by 1 block. */ east() { return this.add(_Vec3.East); } /** * Returns a new vector offset from the current vector west by 1 block. * @returns A new vector offset from the current vector west by 1 block. */ west() { return this.add(_Vec3.West); } /** * Checks if the current vector is equal to the zero vector. * @returns true if the vector is equal to the zero vector, else returns false. */ isZero() { return this.x === 0 && this.y === 0 && this.z === 0; } /** * Converts the vector to an array containing the X, Y, and Z components of the vector. * @returns An array containing t