@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
643 lines (641 loc) • 25.7 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _ContentIndex_data, _ContentIndex_iteration;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnnotationCategory = void 0;
const Log_1 = require("./Log");
const Utilities_1 = require("./Utilities");
const esprima_next_1 = require("esprima-next");
var AnnotationCategory;
(function (AnnotationCategory) {
AnnotationCategory["blockTextureReferenceSource"] = "a";
AnnotationCategory["blockTypeDependent"] = "b";
AnnotationCategory["entityComponentDependent"] = "c";
AnnotationCategory["blockComponentDependent"] = "d";
AnnotationCategory["entityTypeDependent"] = "e";
AnnotationCategory["entityFilter"] = "f";
AnnotationCategory["entityComponentDependentInGroup"] = "g";
AnnotationCategory["blockTextureReferenceDependent"] = "h";
AnnotationCategory["itemTypeDependent"] = "i";
AnnotationCategory["itemComponentDependent"] = "j";
AnnotationCategory["itemTextureReferenceSource"] = "k";
AnnotationCategory["featureSource"] = "l";
AnnotationCategory["featureDependent"] = "m";
AnnotationCategory["featureRuleSource"] = "n";
AnnotationCategory["blockComponentDependentInPermutation"] = "p";
AnnotationCategory["storagePathDependent"] = "s";
AnnotationCategory["textureFile"] = "t";
AnnotationCategory["entityEvent"] = "v";
AnnotationCategory["blockTypeSource"] = "B";
AnnotationCategory["entityTypeSource"] = "E";
AnnotationCategory["itemTypeSource"] = "I";
AnnotationCategory["itemTextureSource"] = "J";
AnnotationCategory["blockSounds"] = "L";
AnnotationCategory["musicDefinitionSource"] = "M";
AnnotationCategory["entitySounds"] = "N";
AnnotationCategory["interactiveSounds"] = "R";
AnnotationCategory["jsSource"] = "S";
AnnotationCategory["terrainTextureSource"] = "T";
AnnotationCategory["soundDefinitionSource"] = "U";
AnnotationCategory["individualEventSoundsSource"] = "V";
AnnotationCategory["worldProperty"] = "W";
AnnotationCategory["experiment"] = "X";
})(AnnotationCategory = exports.AnnotationCategory || (exports.AnnotationCategory = {}));
const AvoidTermList = ["__proto__", "prototype", "[[Prototype]]"];
class ContentIndex {
constructor() {
_ContentIndex_data.set(this, {
items: [],
trie: {},
});
_ContentIndex_iteration.set(this, Math.floor(Math.random() * 1000000));
}
get iteration() {
return __classPrivateFieldGet(this, _ContentIndex_iteration, "f");
}
set iteration(newIteration) {
__classPrivateFieldSet(this, _ContentIndex_iteration, newIteration, "f");
}
static getAnnotationCategoryKeys() {
const keys = [];
for (const key in AnnotationCategory) {
keys.push(key.toLowerCase());
}
return keys;
}
static getAnnotationCategoryFromLongString(longStr) {
longStr = longStr.toLowerCase();
for (const key in AnnotationCategory) {
if (key.toLowerCase() === longStr) {
return AnnotationCategory[key];
}
}
return undefined;
}
get data() {
return __classPrivateFieldGet(this, _ContentIndex_data, "f");
}
get startLength() {
return 4;
}
setItems(items) {
__classPrivateFieldGet(this, _ContentIndex_data, "f").items = items;
}
setTrie(trie) {
__classPrivateFieldGet(this, _ContentIndex_data, "f").trie = trie;
}
getAll(withAnnotation) {
const results = {};
this._appendToResults("", __classPrivateFieldGet(this, _ContentIndex_data, "f").trie, results, withAnnotation);
return results;
}
_isTermToAvoid(term) {
return AvoidTermList.includes(term);
}
_appendToResults(prefix, node, results, withAnnotation) {
for (const token in node) {
const subNode = node[token];
if (subNode) {
if (token === "±" || token === "$") {
const arr = subNode;
if (arr.constructor === Array) {
if (!this._isTermToAvoid(prefix)) {
let res = this.getValuesFromIndexArray(arr, withAnnotation);
if (res) {
results[prefix] = res;
}
}
}
}
else if (subNode.constructor === Array) {
if (!this._isTermToAvoid(prefix + token)) {
let res = this.getValuesFromIndexArray(subNode, withAnnotation);
if (res) {
results[prefix + token] = res;
}
}
}
else {
this._appendToResults(prefix + token, subNode, results, withAnnotation);
}
}
}
}
mergeFrom(index, newItem) {
const all = index.getAll();
for (const fullKey in all) {
const annVals = all[fullKey];
let annVal;
for (const subVal of annVals) {
if (subVal.annotation) {
if (!annVal) {
annVal = subVal.annotation;
}
else if (annVal.indexOf(subVal.annotation) < 0) {
annVal += subVal.annotation;
}
}
}
this.insert(fullKey, newItem, annVal);
}
}
static processResultValues(annotatedValues, withAnyAnnotation) {
if (!annotatedValues) {
return undefined;
}
if (withAnyAnnotation) {
let newAnnotatedValues = [];
for (const annV of annotatedValues) {
if (annV.annotation && withAnyAnnotation.includes(annV.annotation)) {
newAnnotatedValues.push(annV);
}
}
annotatedValues = newAnnotatedValues;
}
return annotatedValues;
}
getValuesFromIndexArray(indices, withAnnotation) {
let results = [];
if (!indices) {
return undefined;
}
if (Utilities_1.default.arrayHasNegativeAndIsNumeric(indices)) {
indices = Utilities_1.default.decodeSequentialRunLengthUsingNegative(indices);
}
for (const index of indices) {
if (typeof index === "object") {
const indexN = index.n;
if (indexN >= 0 && indexN < __classPrivateFieldGet(this, _ContentIndex_data, "f").items.length) {
const annotate = index.a;
if (!withAnnotation || withAnnotation.includes(annotate)) {
results.push({ value: __classPrivateFieldGet(this, _ContentIndex_data, "f").items[indexN], annotation: index.a });
}
}
}
else if (index >= 0 && index < __classPrivateFieldGet(this, _ContentIndex_data, "f").items.length && !withAnnotation) {
results.push({ value: __classPrivateFieldGet(this, _ContentIndex_data, "f").items[index], annotation: undefined });
}
}
if (results.length === 0) {
return undefined;
}
return results;
}
loadFromData(data) {
__classPrivateFieldSet(this, _ContentIndex_data, data, "f");
}
hasPathMatches(pathEnd) {
pathEnd = pathEnd.toLowerCase();
const lastPeriodEnd = pathEnd.lastIndexOf(".");
if (lastPeriodEnd >= 0) {
pathEnd = pathEnd.substring(0, lastPeriodEnd);
}
for (let path of this.data.items) {
if (path.startsWith("/")) {
const lastPeriod = path.lastIndexOf(".");
if (lastPeriod >= 0) {
path = path.substring(0, lastPeriod);
}
if (path.endsWith(pathEnd)) {
return true;
}
}
}
return false;
}
async getMatches(searchString, wholeTermSearch, withAnyAnnotation) {
searchString = searchString.trim().toLowerCase();
let terms = [searchString];
if (!wholeTermSearch) {
terms = searchString.split(" ");
}
let termWasSearched = false;
let andResults;
for (const term of terms) {
if (term.length > 1) {
const results = this.getTermMatch(term);
termWasSearched = true;
if (results && results.length) {
if (andResults === undefined) {
andResults = results;
}
else {
const newArr = [];
for (let num of results) {
if (andResults.includes(num)) {
newArr.push(num);
}
}
}
}
}
}
if (andResults === undefined || andResults.length === 0) {
if (termWasSearched) {
return [];
}
return undefined;
}
let annotatedValues = ContentIndex.processResultValues(this.getValuesFromIndexArray(andResults), withAnyAnnotation);
if (!annotatedValues) {
return undefined;
}
return annotatedValues.sort((a, b) => {
let aTermMatches = 0;
let bTermMatches = 0;
const aVal = a.value.toLowerCase();
const bVal = b.value.toLowerCase();
for (const term of terms) {
if (aVal.startsWith(term)) {
aTermMatches += 5;
}
else if (aVal.includes(term)) {
aTermMatches++;
}
if (bVal.startsWith(term)) {
bTermMatches += 5;
}
else if (bVal.includes(term)) {
bTermMatches++;
}
}
if (aTermMatches === bTermMatches) {
return a.value.localeCompare(b.value);
}
return bTermMatches - aTermMatches;
});
}
getTermMatchStrings(term) {
const results = this.getTermMatch(term);
if (results === undefined) {
return results;
}
return this.getValuesFromIndexArray(results);
}
async getDescendentStrings(term) {
let termIndex = 0;
let curNode = __classPrivateFieldGet(this, _ContentIndex_data, "f").trie;
const results = {};
let hasAdvanced = true;
let termSubstr = "";
while (termIndex < term.length && hasAdvanced) {
hasAdvanced = false;
if (curNode.constructor === Array) {
return undefined;
}
let nextNode = curNode[term[termIndex]];
if (nextNode) {
curNode = nextNode;
termIndex++;
termSubstr = term.substring(0, termIndex);
hasAdvanced = true;
}
else {
let nextStart = term[termIndex];
for (const item in curNode) {
// we've found part of our string in this node
if (item.startsWith(nextStart) && curNode[item] !== undefined) {
let itemIndex = 0;
hasAdvanced = true;
curNode = curNode[item];
termSubstr = term.substring(0, termIndex) + item;
while (termIndex < term.length && itemIndex < item.length && item[itemIndex] === term[termIndex]) {
itemIndex++;
termIndex++;
}
break;
}
}
}
}
if (termIndex < term.length) {
const termStub = term.substring(termIndex);
for (const childNodeName in curNode) {
if (childNodeName.startsWith(termStub) && curNode[childNodeName]) {
this._appendToResults(term.substring(0, termIndex) + childNodeName, curNode[childNodeName], results);
}
}
}
else {
if (curNode.constructor === Array) {
results[termSubstr] = this.getValuesFromIndexArray(curNode);
}
else if (curNode["±"] !== undefined) {
this._appendToResults(termSubstr, curNode, results);
}
}
return results;
}
getTermMatch(term) {
let termIndex = 0;
let curNode = __classPrivateFieldGet(this, _ContentIndex_data, "f").trie;
let hasAdvanced = true;
while (termIndex < term.length && hasAdvanced) {
hasAdvanced = false;
if (curNode.constructor === Array) {
return undefined;
}
let nextNode = curNode[term[termIndex]];
if (nextNode) {
curNode = nextNode;
termIndex++;
hasAdvanced = true;
}
else {
let nextStart = term[termIndex];
if (termIndex < term.length - 1) {
nextStart += term[termIndex + 1];
}
for (const item in curNode) {
// we've found part of our string in this node
if (item.startsWith(nextStart) && curNode[item] !== undefined && !hasAdvanced) {
let itemIndex = 0;
hasAdvanced = true;
curNode = curNode[item];
while (termIndex < term.length && itemIndex < item.length && item[itemIndex] === term[termIndex]) {
itemIndex++;
termIndex++;
}
}
}
}
}
if (termIndex < term.length) {
return undefined;
}
if (curNode.constructor === Array) {
return curNode;
}
else if (curNode["±"] !== undefined) {
return curNode["±"];
}
else {
const arr = [];
this.aggregateIndices(curNode, arr);
return arr;
}
}
aggregateIndices(curNode, arr) {
for (const childNodeName in curNode) {
const childNode = curNode[childNodeName];
if (childNode) {
if (childNode.constructor === Array) {
for (const num of childNode) {
if (!arr.includes(num)) {
arr.push(num);
}
}
}
else if (childNode["±"] !== undefined) {
for (const num of childNode["±"]) {
if (!arr.includes(num)) {
arr.push(num);
}
}
}
else {
this.aggregateIndices(childNode, arr);
}
}
}
}
insertArray(key, items) {
for (const item of items) {
this.insert(key, item.value, item.annotation);
}
}
insert(key, item, annotationChar) {
if (Utilities_1.default.isNumericIsh(key) || key.length > 70) {
return;
}
// since we treat ± as special, ban usage of ± in strings.
key = key.replace(/±/gi, "").toLowerCase().trim();
let keyIndex = 0;
let curNode = __classPrivateFieldGet(this, _ContentIndex_data, "f").trie;
let parentNode = curNode;
let curNodeIndex;
let dataIndex = -1;
let curIndex = 0;
for (const itemCand of __classPrivateFieldGet(this, _ContentIndex_data, "f").items) {
if (itemCand === item) {
dataIndex = curIndex;
break;
}
curIndex++;
}
if (dataIndex < 0) {
dataIndex = __classPrivateFieldGet(this, _ContentIndex_data, "f").items.length;
__classPrivateFieldGet(this, _ContentIndex_data, "f").items.push(item);
}
let hasAdvanced = true;
while (keyIndex < key.length && hasAdvanced) {
hasAdvanced = false;
if (curNode.constructor !== Array) {
for (const item in curNode) {
// we've found part of our string in this node
if (item.startsWith(key[keyIndex]) && curNode[item] !== undefined) {
// && curNode[item].constructor !== Array) {
let itemIndex = 0;
hasAdvanced = true;
curNodeIndex = item;
parentNode = curNode;
curNode = curNode[item];
while (keyIndex < key.length && itemIndex < item.length && item[itemIndex] === key[keyIndex]) {
itemIndex++;
keyIndex++;
}
// if we're in the middle of a string like "subset", and we're trying add the word "subpar",
// create a new node called "sub" and place "set" underneath it.
// also support the case where we're adding "sub" but "subset" already exists (keyIndex === key.length)
if (item[itemIndex] !== key[keyIndex] && itemIndex < item.length && keyIndex <= key.length) {
parentNode[curNodeIndex] = undefined;
curNodeIndex = item.substring(0, itemIndex);
let newNode = {};
parentNode[curNodeIndex] = newNode;
const term = item.substring(itemIndex);
if (!this._isTermToAvoid(term)) {
newNode[term] = curNode;
}
curNode = newNode;
}
break;
}
}
}
}
// we've reached the end of the trie; we need to add a new node
if (keyIndex < key.length) {
// if parent node was a leaf array, switch to an object
if (curNode.constructor === Array && curNodeIndex) {
parentNode[curNodeIndex] = {};
parentNode[curNodeIndex]["±"] = curNode;
curNode = parentNode[curNodeIndex];
}
const substr = key.substring(keyIndex);
if (substr !== "±") {
if (!this._isTermToAvoid(substr)) {
// create a new leaf array
curNode[substr] = this.ensureAnnotatedContentInArray([], dataIndex, annotationChar);
}
}
}
else {
if (curNode.constructor === Array && curNodeIndex) {
if (!this._isTermToAvoid(curNodeIndex)) {
parentNode[curNodeIndex] = this.ensureAnnotatedContentInArray(curNode, dataIndex, annotationChar);
}
}
else {
if (curNode["±"] === undefined) {
curNode["±"] = [];
}
curNode["±"] = this.ensureAnnotatedContentInArray(curNode["±"], dataIndex, annotationChar);
}
}
}
ensureAnnotatedContentInArray(arr, dataIndex, annotationChar) {
try {
for (const item of arr) {
if (typeof item === "object") {
if (item.n === dataIndex) {
if (annotationChar) {
if (!item.a) {
item.a = annotationChar;
}
else {
if (item.a.indexOf(annotationChar) < 0) {
item.a += annotationChar;
}
}
}
return arr;
}
}
else if (item === dataIndex) {
if (!annotationChar) {
return arr;
}
// convert simple number to annotated object
const newArr = [];
for (const existItem of arr) {
if (existItem !== dataIndex) {
newArr.push(existItem);
}
}
newArr.push({ n: dataIndex, a: annotationChar });
return newArr;
}
}
if (annotationChar) {
arr.push({ n: dataIndex, a: annotationChar });
}
else {
arr.push(dataIndex);
}
}
catch (e) {
console.warn("Error ensuring annotated content: " + e + "|" + arr + "|" + JSON.stringify(arr));
}
return arr;
}
parseJsContent(sourcePath, content) {
try {
const results = esprima_next_1.default.tokenize(content);
if (results) {
for (const token of results) {
if (token.type === "Identifier" && token.value && token.value.length > 3) {
if (token.value !== "from") {
this.insert(token.value.toLowerCase(), sourcePath, "S");
}
}
}
}
}
catch (e) {
Log_1.default.debugAlert("JS parsing error:" + e);
}
}
parseTextContent(sourcePath, content) {
const dictionaryOfTerms = {};
let curWord = "";
content = content.toLowerCase();
for (let i = 0; i < content.length; i++) {
const curChar = content[i];
if (curChar === "{" ||
curChar === "}" ||
curChar === " " ||
curChar === "\r" ||
curChar === "\n" ||
curChar === "\t" ||
curChar === "(" ||
curChar === ")" ||
curChar === "[" ||
curChar === "]" ||
curChar === ":" ||
curChar === '"' ||
curChar === "'") {
if (curWord.length > 0) {
if (curWord.length > 3 && !Utilities_1.default.isNumericIsh(curWord)) {
dictionaryOfTerms[curWord] = true;
}
curWord = "";
}
}
else {
curWord += content[i];
}
}
for (const term in dictionaryOfTerms) {
this.insert(term, sourcePath);
}
}
parseJsonContent(sourcePath, content) {
const dictionaryOfTerms = {};
let curWord = "";
content = content.toLowerCase();
for (let i = 0; i < content.length; i++) {
const curChar = content[i];
if (curChar === "{" ||
curChar === "}" ||
curChar === " " ||
curChar === "\r" ||
curChar === "\n" ||
curChar === "\t" ||
curChar === "(" ||
curChar === ")" ||
curChar === "[" ||
curChar === "]" ||
curChar === ":" ||
curChar === '"' ||
curChar === "'") {
if (curWord.length > 0) {
if (curWord.length > 3 && !Utilities_1.default.isNumericIsh(curWord)) {
dictionaryOfTerms[curWord] = true;
}
curWord = "";
}
}
else {
curWord += content[i];
}
}
for (const term in dictionaryOfTerms) {
this.insert(term, sourcePath);
}
}
}
exports.default = ContentIndex;
_ContentIndex_data = new WeakMap(), _ContentIndex_iteration = new WeakMap();
//# sourceMappingURL=../maps/core/ContentIndex.js.map