UNPKG

@bedrock-oss/bedrock-boost

Version:

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

1,777 lines (1,771 loc) 162 kB
// src/math/Vec3.ts import { Direction as Direction2, StructureRotation as StructureRotation2 } from "@minecraft/server"; // src/math/MutVec3.ts import { Direction, StructureRotation } from "@minecraft/server"; var MutVec3 = class _MutVec3 { x; y; z; constructor(x, y, z) { if (x === Direction.Down) { this.x = 0; this.y = -1; this.z = 0; } else if (x === Direction.Up) { this.x = 0; this.y = 1; this.z = 0; } else if (x === Direction.North) { this.x = 0; this.y = 0; this.z = -1; } else if (x === Direction.South) { this.x = 0; this.y = 0; this.z = 1; } else if (x === Direction.East) { this.x = 1; this.y = 0; this.z = 0; } else if (x === 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 _MutVec3 || 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) { 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 _MutVec3) return new _MutVec3(x); if (typeof x === "number" && y !== void 0 && z !== void 0) return new _MutVec3(x, y, z); if (Array.isArray(x)) return new _MutVec3(x); if (x === Direction.Down) return new _MutVec3(Direction.Down); if (x === Direction.Up) return new _MutVec3(Direction.Up); if (x === Direction.North) return new _MutVec3(Direction.North); if (x === Direction.South) return new _MutVec3(Direction.South); if (x === Direction.East) return new _MutVec3(Direction.East); if (x === Direction.West) return new _MutVec3(Direction.West); if (!x || !x.x && x.x !== 0 || !x.y && x.y !== 0 || !x.z && x.z !== 0) { throw new Error("Invalid arguments"); } return new _MutVec3( x.x, x.y, x.z ); } static _from(x, y, z) { if (typeof x === "number" && y === void 0 && z === void 0) { return new _MutVec3(x, x, x); } if (x instanceof _MutVec3) return x; if (typeof x === "number" && y !== void 0 && z !== void 0) return new _MutVec3(x, y, z); if (Array.isArray(x)) return new _MutVec3(x); if (x === Direction.Down) return new _MutVec3(Direction.Down); if (x === Direction.Up) return new _MutVec3(Direction.Up); if (x === Direction.North) return new _MutVec3(Direction.North); if (x === Direction.South) return new _MutVec3(Direction.South); if (x === Direction.East) return new _MutVec3(Direction.East); if (x === Direction.West) return new _MutVec3(Direction.West); if (!x || !x.x && x.x !== 0 || !x.y && x.y !== 0 || !x.z && x.z !== 0) { throw new Error("Invalid arguments"); } return new _MutVec3( x.x, x.y, x.z ); } copy() { return new _MutVec3(this.x, this.y, this.z); } toImmutable() { return new Vec3(this.x, this.y, this.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 yv = -Math.sin(theta); const z = Math.cos(theta) * Math.cos(psi); return new _MutVec3(x, yv, z); } toRotation() { if (this.isZero()) throw new Error("Cannot convert zero-length vector to direction"); const dir = this.copy().normalize(); const yaw = -Math.atan2(dir.x, dir.z) * (180 / Math.PI); const pitch = Math.asin(-dir.y) * (180 / Math.PI); return { x: pitch, y: yaw }; } add(x, y, z) { const v = _MutVec3._from(x, y, z); this.x += v.x; this.y += v.y; this.z += v.z; return this; } directionTo(x, y, z) { const v = _MutVec3._from(x, y, z); this.subtract(v).multiply(-1).normalize(); return this; } subtract(x, y, z) { const v = _MutVec3._from(x, y, z); this.x -= v.x; this.y -= v.y; this.z -= v.z; return this; } multiply(x, y, z) { const v = _MutVec3._from(x, y, z); this.x *= v.x; this.y *= v.y; this.z *= v.z; return this; } scale(scalar) { this.x *= scalar; this.y *= scalar; this.z *= scalar; return this; } divide(x, y, z) { if (typeof x === "number" && y === void 0 && z === void 0) { if (x === 0) throw new Error("Cannot divide by zero"); this.x /= x; this.y /= x; this.z /= x; return this; } const v = _MutVec3._from(x, y, z); if (v.x === 0 || v.y === 0 || v.z === 0) throw new Error("Cannot divide by zero"); this.x /= v.x; this.y /= v.y; this.z /= v.z; return this; } normalize() { if (this.isZero()) throw new Error("Cannot normalize zero-length vector"); const len = this.length(); this.x /= len; this.y /= len; this.z /= len; return this; } length() { return Math.hypot(this.x, this.y, this.z); } lengthSquared() { return this.x * this.x + this.y * this.y + this.z * this.z; } cross(x, y, z) { const v = _MutVec3._from(x, y, z); const cx = this.y * v.z - this.z * v.y; const cy = this.z * v.x - this.x * v.z; const cz = this.x * v.y - this.y * v.x; this.x = cx; this.y = cy; this.z = cz; return this; } distance(x, y, z) { const v = _MutVec3._from(x, y, z); return this.copy().subtract(v).length(); } distanceSquared(x, y, z) { const v = _MutVec3._from(x, y, z); return this.copy().subtract(v).lengthSquared(); } lerp(v, t) { if (!v || t === void 0) return this; if (t === 1) { this.x = v.x; this.y = v.y; this.z = v.z; return this; } if (t === 0) return this; this.x = this.x + (v.x - this.x) * t; this.y = this.y + (v.y - this.y) * t; this.z = this.z + (v.z - this.z) * t; return this; } slerp(v, t) { if (!v || t === void 0) return this; if (t === 1) { this.x = v.x; this.y = v.y; this.z = v.z; return this; } if (t === 0) return this; const dot = this.dot(v); const theta = Math.acos(dot) * t; const relative = _MutVec3.from(v).subtract(this.copy().multiply(dot)).normalize(); const cosT = Math.cos(theta); const sinT = Math.sin(theta); this.multiply(cosT); this.x += relative.x * sinT; this.y += relative.y * sinT; this.z += relative.z * sinT; return this; } dot(x, y, z) { const v = _MutVec3._from(x, y, z); return this.x * v.x + this.y * v.y + this.z * v.z; } angleBetween(x, y, z) { const v = _MutVec3._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 = _MutVec3._from(x, y, z); if (v.isZero()) { this.x = 0; this.y = 0; this.z = 0; return this; } const denom = v.dot(v); if (denom === 0) { this.x = 0; this.y = 0; this.z = 0; return this; } const scale = this.dot(v) / denom; this.x = v.x * scale; this.y = v.y * scale; this.z = v.z * scale; return this; } reflect(x, y, z) { const normal = _MutVec3._from(x, y, z); const tmp = this.copy(); const proj = tmp.projectOnto(normal); return this.subtract(proj.multiply(2)); } 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 vx = this.x, vy = this.y, vz = this.z; const qv_x = w * w * vx + 2 * y * w * vz - 2 * z * w * vy + x * x * vx + 2 * y * x * vy + 2 * z * x * vz - z * z * vx - y * y * vx; const qv_y = 2 * x * y * vx + y * y * vy + 2 * z * y * vz + 2 * w * z * vx - z * z * vy + w * w * vy - 2 * x * w * vz - x * x * vy; const qv_z = 2 * x * z * vx + 2 * y * z * vy + z * z * vz - 2 * w * y * vx - y * y * vz + 2 * w * x * vy - x * x * vz + w * w * vz; this.x = qv_x; this.y = qv_y; this.z = qv_z; return this; } update(x, y, z) { if (!x) x = (v) => v; if (!y) y = (v) => v; if (!z) z = (v) => v; this.x = x(this.x); this.y = y(this.y); this.z = z(this.z); return this; } setX(value) { if (typeof value === "number") this.x = value; else this.x = value(this.x); return this; } setY(value) { if (typeof value === "number") this.y = value; else this.y = value(this.y); return this; } setZ(value) { if (typeof value === "number") this.z = value; else this.z = value(this.z); return this; } floor() { return this.update(Math.floor, Math.floor, Math.floor); } floorX() { return this.setX(Math.floor); } floorY() { return this.setY(Math.floor); } floorZ() { return this.setZ(Math.floor); } ceil() { return this.update(Math.ceil, Math.ceil, Math.ceil); } ceilX() { return this.setX(Math.ceil); } ceilY() { return this.setY(Math.ceil); } ceilZ() { return this.setZ(Math.ceil); } round() { return this.update(Math.round, Math.round, Math.round); } roundX() { return this.setX(Math.round); } roundY() { return this.setY(Math.round); } roundZ() { return this.setZ(Math.round); } up() { return this.add(Direction.Up); } down() { return this.add(Direction.Down); } north() { return this.add(Direction.North); } south() { return this.add(Direction.South); } east() { return this.add(Direction.East); } west() { return this.add(Direction.West); } isZero() { return this.x === 0 && this.y === 0 && this.z === 0; } toArray() { return [this.x, this.y, this.z]; } toDirection() { if (this.isZero()) throw new Error("Cannot convert zero-length vector to direction"); const normalized = this.copy().normalize(); const maxValue = Math.max( Math.abs(normalized.x), Math.abs(normalized.y), Math.abs(normalized.z) ); if (maxValue === normalized.x) return Direction.East; if (maxValue === -normalized.x) return Direction.West; if (maxValue === normalized.y) return Direction.Up; if (maxValue === -normalized.y) return Direction.Down; if (maxValue === normalized.z) return Direction.South; if (maxValue === -normalized.z) return Direction.North; throw new Error("Cannot convert vector to direction"); } toStructureRotation() { const rotation = this.toRotation(); let aligned = Math.round(rotation.y / 90) * 90; if (aligned < 0) aligned += 360; if (aligned >= 360) aligned -= 360; if (aligned === 0) return StructureRotation.None; if (aligned === 90) return StructureRotation.Rotate90; if (aligned === 180) return StructureRotation.Rotate180; if (aligned === 270) return StructureRotation.Rotate270; throw new Error("Cannot convert vector to structure rotation"); } toBlockLocation() { this.x = (this.x << 0) - (this.x < 0 && this.x !== this.x << 0 ? 1 : 0); this.y = (this.y << 0) - (this.y < 0 && this.y !== this.y << 0 ? 1 : 0); this.z = (this.z << 0) - (this.z < 0 && this.z !== this.z << 0 ? 1 : 0); return this; } almostEqual(x, y, z, delta) { try { let other; if (typeof x !== "number" && z === void 0) { other = _MutVec3._from(x, void 0, void 0); delta = y; } else { other = _MutVec3._from(x, y, z); } return Math.abs(this.x - other.x) <= delta && Math.abs(this.y - other.y) <= delta && Math.abs(this.z - other.z) <= delta; } catch (e) { return false; } } equals(x, y, z) { try { const other = _MutVec3._from(x, y, z); return this.x === other.x && this.y === other.y && this.z === other.z; } catch (e) { return false; } } toString(format = "long", separator = ", ") { const result = `${this.x + separator + this.y + separator + this.z}`; return format === "long" ? `MutVec3(${result})` : result; } static fromString(str, format = "long", separator = ", ") { if (format === "long") { const match = str.match(/^MutVec3\((.*)\)$/); if (!match) throw new Error("Invalid string format"); const components = match[1].split(separator); if (components.length !== 3) throw new Error("Invalid string format"); return new _MutVec3( Number(components[0]), Number(components[1]), Number(components[2]) ); } else { const components = str.split(separator); if (components.length !== 3) throw new Error("Invalid string format"); return new _MutVec3( Number(components[0]), Number(components[1]), Number(components[2]) ); } } }; // src/Logging.ts import { system, world } from "@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, timestampFormatter: (timestamp) => { return ""; }, formatFunction: (level, logger, message, timestamp, tags = void 0) => { const _tags = tags !== void 0 ? `\xA77${tags.map((tag) => `[${tag}]`).join("")}\xA7r` : ""; const time = timestamp ? `[${timestamp}]` : ""; return `${time}[${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; system.beforeEvents.startup.subscribe(() => { system.afterEvents.scriptEventReceive.subscribe((ev) => { if (ev.id === "logging:level" || ev.id === "log:level") { if (!ev.message) { loggingSettings.level = LogLevel.Info; world.sendMessage( `${ChatColor.AQUA}Logging level set to ${ChatColor.BOLD}${loggingSettings.level}` ); } else { const level = LogLevel.parse(ev.message); if (level) { loggingSettings.level = level; world.sendMessage( `${ChatColor.AQUA}Logging level set to ${ChatColor.BOLD}${loggingSettings.level}` ); } else { 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(","); } 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 timestamp formatter for the logger. * @param formatter - The function used to format the timestamp. */ static setTimestampFormatter(formatter) { loggingSettings.timestampFormatter = formatter; } /** * Set the basic timestamp formatter for the logger in HH:mm:ss.SS format. */ static setBasicTimestampFormatter() { loggingSettings.timestampFormatter = (timestamp) => { const hours = timestamp.getHours().toString().padStart(2, "0"); const minutes = timestamp.getMinutes().toString().padStart(2, "0"); const seconds = timestamp.getSeconds().toString().padStart(2, "0"); const centiseconds = Math.floor(timestamp.getMilliseconds() / 10).toString().padStart(2, "0"); return `${hours}:${minutes}:${seconds}.${centiseconds}`; }; } /** * 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 now = /* @__PURE__ */ new Date(); const formattedTimestamp = loggingSettings.timestampFormatter(now); const formatted = loggingSettings.formatFunction( level, this, loggingSettings.messagesJoinFunction(msgs), formattedTimestamp, loggingSettings.outputTags ? this.tags : void 0 ); const outputs = loggingSettings.outputConfig[level.level] || [ 0 /* Chat */, 1 /* ConsoleInfo */ ]; if (outputs.includes(0 /* Chat */)) { try { world.sendMessage(formatted); } catch (_) { system.run(() => { 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/math/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(Direction2.Down); /** * Up vector, positive towards Y */ static Up = new _Vec3(Direction2.Up); /** * North vector, negative towards Z */ static North = new _Vec3(Direction2.North); /** * South vector, positive towards Z */ static South = new _Vec3(Direction2.South); /** * East vector, positive towards X */ static East = new _Vec3(Direction2.East); /** * West vector, negative towards X */ static West = new _Vec3(Direction2.West); x; y; z; constructor(x, y, z) { if (x === Direction2.Down) { this.x = 0; this.y = -1; this.z = 0; } else if (x === Direction2.Up) { this.x = 0; this.y = 1; this.z = 0; } else if (x === Direction2.North) { this.x = 0; this.y = 0; this.z = -1; } else if (x === Direction2.South) { this.x = 0; this.y = 0; this.z = 1; } else if (x === Direction2.East) { this.x = 1; this.y = 0; this.z = 0; } else if (x === Direction2.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 === Direction2.Down) return _Vec3.Down; if (x === Direction2.Up) return _Vec3.Up; if (x === Direction2.North) return _Vec3.North; if (x === Direction2.South) return _Vec3.South; if (x === Direction2.East) return _Vec3.East; if (x === Direction2.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 (typeof x === "number" && y === void 0 && z === void 0) { return new _Vec3(x, x, x); } 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 === Direction2.Down) return _Vec3.Down; if (x === Direction2.Up) return _Vec3.Up; if (x === Direction2.North) return _Vec3.North; if (x === Direction2.South) return _Vec3.South; if (x === Direction2.East) return _Vec3.East; if (x === Direction2.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); } /** * Converts this immutable vector to a new mutable vector. */ toMutable() { return new MutVec3(this.x, this.y, this.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. */ 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