UNPKG

bc-minecraft-bedrock-project

Version:

The typescript library responsible for reading/parsing minecraft bedrock data

298 lines 10.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.process = process; exports.parseCustomCommands = parseCustomCommands; const bc_minecraft_bedrock_command_1 = require("bc-minecraft-bedrock-command"); const ts = __importStar(require("typescript")); const custom_command_1 = require("./custom-command"); /** * Parses script files and returns script-defined custom commands. */ function process(doc) { const data = parseCustomCommands(doc); const out = []; Object.keys(data).forEach((key) => out.push(custom_command_1.CustomCommand.create(key, doc.uri, data[key]))); return out; } function parseCustomCommands(doc) { const text = doc.getText(); const language = doc.uri.endsWith('.ts') ? 'typescript' : 'javascript'; const scriptKind = doc.uri.endsWith('.ts') ? ts.ScriptKind.TS : ts.ScriptKind.JS; const source = ts.createSourceFile(doc.uri, text, ts.ScriptTarget.Latest, true, scriptKind); const variables = new Map(); const output = {}; visit(source); return output; function visit(node) { if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) { variables.set(node.name.text, node.initializer); } if (ts.isCallExpression(node)) { const call = node; if (isCustomCommandRegisterCall(call)) { const info = parseRegisterCall(call, source, variables, doc.uri, language); if (info) { const list = output[info.name] ?? []; list.push(info); output[info.name] = list; } } } ts.forEachChild(node, visit); } } function isCustomCommandRegisterCall(node) { if (!ts.isPropertyAccessExpression(node.expression)) return false; if (node.expression.name.text !== 'registerCommand') return false; const object = node.expression.expression; if (ts.isIdentifier(object) && object.text === 'CustomCommandRegistry') { return true; } if (ts.isPropertyAccessExpression(object) && ts.isIdentifier(object.name)) { return object.name.text === 'CustomCommandRegistry'; } return false; } function parseRegisterCall(call, source, variables, uri, language) { const args = call.arguments; if (args.length <= 0) return undefined; const first = resolveValue(args[0], variables); const second = args.length > 1 ? resolveValue(args[1], variables) : undefined; const object = getDefinitionObject(first, second); if (!object) return undefined; const nameRaw = getString(object['name']) ?? getString(first); if (!nameRaw) return undefined; const name = nameRaw.replace(/^\//, ''); const description = getString(object['description']) ?? 'Script-defined custom command.'; const permission = getPermissionLevel(object['permission']); const parameters = getParameters(name, object); const line = ts.getLineAndCharacterOfPosition(source, call.getStart(source)).line + 1; return { name, documentation: description, permission_level: permission, parameters, source: { uri, line, language, }, }; } function getDefinitionObject(first, second) { if (isObject(first)) return first; if (isObject(second)) return second; return undefined; } function getParameters(commandName, object) { const out = [{ text: commandName, type: bc_minecraft_bedrock_command_1.ParameterType.keyword, required: true }]; const mandatory = getArray(object['mandatoryParameters']); const optional = getArray(object['optionalParameters']); const mixed = getArray(object['parameters']); addParameterArray(out, mandatory, true); addParameterArray(out, optional, false); addParameterArray(out, mixed, undefined); return out; } function addParameterArray(receiver, input, required) { if (!input) return; for (let i = 0; i < input.length; i++) { const item = input[i]; if (!isObject(item)) continue; const name = getString(item['name']) ?? getString(item['id']) ?? `parameter_${i + 1}`; const typeValue = getString(item['type']); const optional = item['optional'] === true; const parameterRequired = typeof required === 'boolean' ? required : !optional; const type = toParameterType(typeValue); const parameter = { text: name, type, required: parameterRequired }; const acceptedValues = getStringArray(item['enum']) ?? getStringArray(item['acceptedValues']) ?? getStringArray(item['values']); if (acceptedValues && acceptedValues.length > 0) { parameter.options = { acceptedValues }; if (type === bc_minecraft_bedrock_command_1.ParameterType.unknown) { parameter.type = bc_minecraft_bedrock_command_1.ParameterType.keyword; } } receiver.push(parameter); } } function toParameterType(type) { if (!type) return bc_minecraft_bedrock_command_1.ParameterType.unknown; switch (type.toLowerCase()) { case 'bool': case 'boolean': return bc_minecraft_bedrock_command_1.ParameterType.boolean; case 'int': case 'integer': case 'long': return bc_minecraft_bedrock_command_1.ParameterType.integer; case 'float': case 'number': case 'double': return bc_minecraft_bedrock_command_1.ParameterType.float; case 'coordinate': case 'coordinates': case 'position': case 'vector3': case 'location': return bc_minecraft_bedrock_command_1.ParameterType.coordinate; case 'target': case 'entity': case 'selector': case 'entityselector': case 'playerselector': return bc_minecraft_bedrock_command_1.ParameterType.selector; case 'message': return bc_minecraft_bedrock_command_1.ParameterType.message; case 'string': case 'text': return bc_minecraft_bedrock_command_1.ParameterType.string; case 'json': return bc_minecraft_bedrock_command_1.ParameterType.jsonRawText; default: return bc_minecraft_bedrock_command_1.ParameterType.unknown; } } function getPermissionLevel(value) { if (typeof value === 'number') return value; const text = getString(value); if (!text) return 0; switch (text.toLowerCase()) { case 'any': return 0; case 'host': case 'gamedirectors': return 1; case 'admin': return 2; } return 0; } function resolveValue(value, variables, depth = 0) { if (depth > 20) return undefined; if (ts.isParenthesizedExpression(value)) { return resolveValue(value.expression, variables, depth + 1); } if (ts.isAsExpression(value) || ts.isTypeAssertionExpression(value)) { return resolveValue(value.expression, variables, depth + 1); } if (ts.isIdentifier(value)) { const resolved = variables.get(value.text); if (resolved) return resolveValue(resolved, variables, depth + 1); return value.text; } if (ts.isPropertyAccessExpression(value)) { return value.name.text; } if (ts.isStringLiteral(value) || ts.isNoSubstitutionTemplateLiteral(value)) { return value.text; } if (ts.isNumericLiteral(value)) { return Number(value.text); } if (value.kind === ts.SyntaxKind.TrueKeyword) return true; if (value.kind === ts.SyntaxKind.FalseKeyword) return false; if (ts.isArrayLiteralExpression(value)) { return value.elements.map((element) => resolveValue(element, variables, depth + 1)); } if (ts.isObjectLiteralExpression(value)) { const out = {}; for (let i = 0; i < value.properties.length; i++) { const property = value.properties[i]; if (ts.isPropertyAssignment(property)) { const key = getPropertyName(property.name); if (!key) continue; out[key] = resolveValue(property.initializer, variables, depth + 1); } else if (ts.isShorthandPropertyAssignment(property)) { const name = property.name.text; out[name] = resolveValue(property.name, variables, depth + 1); } } return out; } return undefined; } function getPropertyName(name) { if (ts.isIdentifier(name)) return name.text; if (ts.isStringLiteral(name)) return name.text; if (ts.isNumericLiteral(name)) return name.text; return undefined; } function isObject(value) { return !!value && typeof value === 'object' && !Array.isArray(value); } function getArray(value) { if (Array.isArray(value)) return value; return undefined; } function getString(value) { if (typeof value === 'string') return value; return undefined; } function getStringArray(value) { if (!Array.isArray(value)) return undefined; const out = []; for (let i = 0; i < value.length; i++) { const item = value[i]; if (typeof item === 'string') out.push(item); } return out; } //# sourceMappingURL=process.js.map