@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
935 lines (934 loc) • 37.6 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EntityPropertyType = exports.AttributeComponents = exports.EntityTypeComponentExtendedCategory = exports.EntityTypeComponentCategory = void 0;
const Log_1 = __importDefault(require("../core/Log"));
const ste_events_1 = require("ste-events");
const ScriptGen_1 = __importDefault(require("../script/ScriptGen"));
const ManagedComponentGroup_1 = __importDefault(require("./ManagedComponentGroup"));
const ManagedComponent_1 = require("./ManagedComponent");
const StorageUtilities_1 = __importDefault(require("../storage/StorageUtilities"));
const Database_1 = __importDefault(require("./Database"));
const MinecraftUtilities_1 = __importDefault(require("./MinecraftUtilities"));
const IProjectItemData_1 = require("../app/IProjectItemData");
const EntityTypeResourceDefinition_1 = __importDefault(require("./EntityTypeResourceDefinition"));
const SpawnRulesBehaviorDefinition_1 = __importDefault(require("./SpawnRulesBehaviorDefinition"));
const Utilities_1 = __importDefault(require("../core/Utilities"));
var EntityTypeComponentCategory;
(function (EntityTypeComponentCategory) {
EntityTypeComponentCategory[EntityTypeComponentCategory["attribute"] = 0] = "attribute";
EntityTypeComponentCategory[EntityTypeComponentCategory["complex"] = 1] = "complex";
EntityTypeComponentCategory[EntityTypeComponentCategory["behavior"] = 2] = "behavior";
EntityTypeComponentCategory[EntityTypeComponentCategory["trigger"] = 3] = "trigger";
})(EntityTypeComponentCategory || (exports.EntityTypeComponentCategory = EntityTypeComponentCategory = {}));
var EntityTypeComponentExtendedCategory;
(function (EntityTypeComponentExtendedCategory) {
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["attribute"] = 0] = "attribute";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["complex"] = 1] = "complex";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["movementComplex"] = 2] = "movementComplex";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["combatAndHealthComplex"] = 3] = "combatAndHealthComplex";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["sensorComponents"] = 4] = "sensorComponents";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["trigger"] = 5] = "trigger";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["behavior"] = 6] = "behavior";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["movementBehavior"] = 7] = "movementBehavior";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["mobSpecificBehavior"] = 8] = "mobSpecificBehavior";
})(EntityTypeComponentExtendedCategory || (exports.EntityTypeComponentExtendedCategory = EntityTypeComponentExtendedCategory = {}));
exports.AttributeComponents = {
"minecraft:body_rotation_blocked": "b",
"minecraft:can_climb": "b",
"minecraft:can_fly": "b",
"minecraft:can_power_jump": "b",
"minecraft:cannot_be_attacked": "b",
"minecraft:color": "s",
"minecraft:color2": "s",
"minecraft:default_look_angle": "f",
"minecraft:fire_immune": "b",
"minecraft:floats_in_liquid": "b",
"minecraft:flying_speed": "f",
"minecraft:friction_modifier": "f",
"minecraft:ground_offset": "f",
"minecraft:ignore_cannot_be_attacked": "b",
"minecraft:input_ground_controlled": "b",
"minecraft:is_baby": "b",
"minecraft:is_charged": "b",
"minecraft:is_chested": "b",
"minecraft:is_dyeable": "b",
"minecraft:is_hidden_when_invisible": "b",
"minecraft:is_ignited": "b",
"minecraft:is_illager_captain": "b",
"minecraft:is_pregnant": "b",
"minecraft:is_saddled": "b",
"minecraft:is_sheared": "b",
"minecraft:is_stackable": "b",
"minecraft:is_stunned": "b",
"minecraft:is_tamed": "b",
"minecraft:mark_variant": "i",
"minecraft:movement_sound_distance_offset": "f",
"minecraft:push_through": "f",
"minecraft:renders_when_invisible": "b",
"minecraft:scale": "f",
"minecraft:skin_id": "i",
"minecraft:sound_volume": "f",
"minecraft:type_family": "family",
"minecraft:variant": "i",
"minecraft:walk_animation_speed": "f",
"minecraft:wants_jockey": "b",
};
var EntityPropertyType;
(function (EntityPropertyType) {
EntityPropertyType[EntityPropertyType["enum"] = 0] = "enum";
EntityPropertyType[EntityPropertyType["boolean"] = 1] = "boolean";
EntityPropertyType[EntityPropertyType["float"] = 2] = "float";
EntityPropertyType[EntityPropertyType["int"] = 3] = "int";
})(EntityPropertyType || (exports.EntityPropertyType = EntityPropertyType = {}));
class EntityTypeDefinition {
_wrapper;
_file;
_id;
_isLoaded = false;
_loadedWithComments = false;
/** Set during persist() so the resulting onFileContentUpdated event doesn't wipe our already-current in-memory state. */
_isSelfPersisting = false;
_managedComponents = {};
_data;
_componentGroups = {};
_events = {};
_onLoaded = new ste_events_1.EventDispatcher();
_onComponentAdded = new ste_events_1.EventDispatcher();
_onComponentRemoved = new ste_events_1.EventDispatcher();
_onComponentChanged = new ste_events_1.EventDispatcher();
get data() {
return this._data;
}
get componentGroups() {
return this._componentGroups;
}
static getFormIdFromComponentId(componentId) {
return componentId.replace(/:/gi, "_").replace(/\./gi, "_");
}
static getComponentCategory(id) {
if (id.startsWith("minecraft:behavior")) {
return EntityTypeComponentCategory.behavior;
}
else if (id.startsWith("minecraft:on_")) {
return EntityTypeComponentCategory.trigger;
}
else if (exports.AttributeComponents[id] !== undefined) {
return EntityTypeComponentCategory.attribute;
}
return EntityTypeComponentCategory.complex;
}
static getExtendedComponentCategory(id) {
if (id.startsWith("minecraft:behavior.move") ||
id.startsWith("minecraft:behavior.jump") ||
id.startsWith("minecraft:behavior.go") ||
id.startsWith("minecraft:behavior.follow") ||
id.startsWith("minecraft:behavior.circle")) {
return EntityTypeComponentExtendedCategory.movementBehavior;
}
else if (id.startsWith("minecraft:behavior.dragon") ||
id.startsWith("minecraft:behavior.enderman") ||
id.startsWith("minecraft:behavior.guardian") ||
id.startsWith("minecraft:behavior.ocelot") ||
id.startsWith("minecraft:behavior.silverfish") ||
id.startsWith("minecraft:behavior.skeleton") ||
id.startsWith("minecraft:behavior.slime") ||
id.startsWith("minecraft:behavior.squid") ||
id.startsWith("minecraft:behavior.vex") ||
id.startsWith("minecraft:behavior.wither")) {
return EntityTypeComponentExtendedCategory.mobSpecificBehavior;
}
else if (id.startsWith("minecraft:behavior")) {
return EntityTypeComponentExtendedCategory.behavior;
}
else if (id.startsWith("minecraft:on_")) {
return EntityTypeComponentExtendedCategory.trigger;
}
else if (exports.AttributeComponents[id] !== undefined) {
return EntityTypeComponentExtendedCategory.attribute;
}
else if (id.indexOf("sensor") >= 0) {
return EntityTypeComponentExtendedCategory.sensorComponents;
}
else if (id.indexOf("jump") >= 0 ||
id.indexOf("climb") >= 0 ||
id.indexOf("move") >= 0 ||
id.startsWith("minecraft:navigation") ||
id.startsWith("minecraft:flying") ||
id.startsWith("minecraft:friction") ||
id.startsWith("minecraft:walk_animation")) {
return EntityTypeComponentExtendedCategory.movementComplex;
}
else if (id.indexOf("attack") >= 0 ||
id.indexOf("combat") >= 0 ||
id.indexOf("damage") >= 0 ||
id.startsWith("minecraft:health") ||
id.startsWith("minecraft:healable") ||
id.startsWith("minecraft:hurt_on")) {
return EntityTypeComponentExtendedCategory.combatAndHealthComplex;
}
return EntityTypeComponentExtendedCategory.complex;
}
get formatVersion() {
return this._wrapper?.format_version;
}
static getComponentFromBaseFileName(name) {
let canonName = name;
if (canonName.startsWith("minecraft_")) {
canonName = canonName.substring(10);
if (canonName.startsWith("behavior_")) {
canonName = "behavior." + canonName.substring(9);
}
if (canonName.startsWith("movement_")) {
canonName = "movement." + canonName.substring(9);
}
if (canonName.startsWith("navigation_")) {
canonName = "navigation." + canonName.substring(11);
}
if (canonName.startsWith("player_")) {
canonName = "player." + canonName.substring(7);
}
if (canonName.startsWith("jump_")) {
canonName = "jump." + canonName.substring(5);
}
if (canonName.startsWith("horse_")) {
canonName = "horse." + canonName.substring(6);
}
if (canonName.startsWith("annotation_")) {
canonName = "annotation." + canonName.substring(11);
}
}
return canonName;
}
static getComponentCategoryDescription(category) {
switch (category) {
case EntityTypeComponentCategory.behavior:
return "Behavior";
case EntityTypeComponentCategory.attribute:
return "Attribute";
case EntityTypeComponentCategory.trigger:
return "Trigger";
default:
return "Component";
}
}
static getPluralComponentCategoryDescription(category) {
switch (category) {
case EntityTypeComponentCategory.behavior:
return "Behaviors (AI)";
case EntityTypeComponentCategory.attribute:
return "Attributes";
case EntityTypeComponentCategory.trigger:
return "Triggers";
default:
return "Components";
}
}
get onComponentAdded() {
return this._onComponentAdded.asEvent();
}
get onComponentRemoved() {
return this._onComponentRemoved.asEvent();
}
get onComponentChanged() {
return this._onComponentChanged.asEvent();
}
get isLoaded() {
return this._isLoaded;
}
get behaviorPackFile() {
return this._file;
}
get onLoaded() {
return this._onLoaded.asEvent();
}
set behaviorPackFile(newFile) {
if (this._file) {
this._file.onFileContentUpdated.unsubscribe(this._handleFileUpdated);
}
this._file = newFile;
if (this._file) {
this._file.onFileContentUpdated.subscribe(this._handleFileUpdated);
}
}
_handleFileUpdated(file, fileB) {
// Skip when this update came from our own persist() call — the in-memory
// state already matches what we just wrote, so resetting it (and forcing a
// re-parse) would leave the editor stuck on "Loading mob definition..."
// until the next prop change.
if (this._isSelfPersisting) {
return;
}
this._data = undefined;
this._isLoaded = false;
this._wrapper = undefined;
this._managedComponents = {};
}
get id() {
if (this._id === undefined) {
return "";
}
return this._id;
}
set id(newId) {
this._id = newId;
if (this._data && this._data.description) {
this._data.description.identifier = newId;
}
}
get runtimeIdentifier() {
if (this._data && this._data.description) {
return this._data.description.runtime_identifier;
}
return undefined;
}
set runtimeIdentifier(newId) {
if (this._data && this._data.description) {
this._data.description.runtime_identifier = newId;
}
}
get aliases() {
if (!this._data || !this._data.description) {
return undefined;
}
return this._data.description.aliases;
}
get properties() {
if (!this._data || !this._data.description) {
return undefined;
}
return this._data.description.properties;
}
constructor() {
this._handleFileUpdated = this._handleFileUpdated.bind(this);
}
async getFormatVersionIsCurrent() {
const fv = this.getFormatVersionAsNumberArray();
if (fv === undefined || fv.length !== 3) {
return false;
}
return await Database_1.default.isRecentVersionFromVersionArray(fv);
}
getFormatVersionAsNumberArray() {
if (!this._wrapper) {
return undefined;
}
return MinecraftUtilities_1.default.getVersionArrayFrom(this._wrapper.format_version);
}
removeProperty(propertyName) {
if (this._data?.description?.properties) {
this._data.description.properties[propertyName] = undefined;
}
}
get shortId() {
if (this._id !== undefined) {
let val = this._id;
if (val.startsWith("minecraft:")) {
return val.substring(10, this._id.length);
}
const firstColon = val.indexOf(":");
if (firstColon >= 0) {
val = val.substring(firstColon + 1);
}
return val;
}
return undefined;
}
getComponent(id) {
if (this._data === undefined || this._data.components === undefined) {
return undefined;
}
if (!Utilities_1.default.isUsableAsObjectKey(id)) {
Log_1.default.unsupportedToken(id);
throw new Error();
}
if (!this._managedComponents[id]) {
const comp = this._data.components[id];
if (comp) {
this._managedComponents[id] = new ManagedComponent_1.ManagedComponent(this._data.components, id, comp);
}
}
return this._managedComponents[id];
}
getComponentsInBaseAndGroups(id) {
if (this._data === undefined) {
return [];
}
let results = [];
let comp = this.getComponent(id);
if (comp) {
results.push(comp);
}
for (const componentGroupName in this._componentGroups) {
const group = this._componentGroups[componentGroupName];
if (group) {
comp = group.getComponent(id);
if (comp) {
results.push(comp);
}
}
}
return results;
}
getCoreAndComponentGroupList() {
const componentSets = [this];
const cgs = this.getComponentGroups();
componentSets.push(...cgs);
return componentSets;
}
getAllComponents() {
if (this._data === undefined) {
return [];
}
let results = this.getComponents();
for (const componentGroupName in this._componentGroups) {
const group = this._componentGroups[componentGroupName];
if (group) {
for (const comp of group.getComponents()) {
if (comp) {
results.push(comp);
}
}
}
}
return results;
}
get behaviorPackFormatVersion() {
if (!this._wrapper || !this._wrapper.format_version) {
return undefined;
}
return this._wrapper.format_version;
}
setBehaviorPackFormatVersion(versionStr) {
this._ensureBehaviorPackDataInitialized();
if (this._wrapper) {
this._wrapper.format_version = versionStr;
}
}
notifyComponentUpdated(id) {
const component = this.getComponent(id);
if (component === undefined) {
Log_1.default.unexpectedUndefined("ETNCU");
}
else {
this._onComponentChanged.dispatch(this, component);
}
}
getComponents() {
const componentSet = [];
if (this._data !== undefined) {
for (const componentName in this._data.components) {
const component = this.getComponent(componentName);
if (component !== undefined) {
componentSet.push(component);
}
}
}
return componentSet;
}
getComponentGroupsComponentUsedIn(componentName) {
const componentGroups = this.getComponentGroups();
const cgsUsedIn = [];
for (const cg of componentGroups) {
if (cg && cg.getComponent(componentName)) {
cgsUsedIn.push(cg);
}
}
return cgsUsedIn;
}
getComponentGroup(componentGroupName) {
if (this._data && this._data.component_groups) {
if (!this._componentGroups[componentGroupName] && this._data.component_groups[componentGroupName]) {
const componentGroupData = this._data.component_groups[componentGroupName];
const cg = new ManagedComponentGroup_1.default(componentGroupData, componentGroupName);
this._componentGroups[componentGroupName] = cg;
}
return this._componentGroups[componentGroupName];
}
return undefined;
}
getComponentGroups() {
const componentGroups = [];
if (this._data !== undefined) {
for (const componentGroupName in this._data.component_groups) {
if (!this._componentGroups[componentGroupName]) {
const componentGroupData = this._data.component_groups[componentGroupName];
const cg = new ManagedComponentGroup_1.default(componentGroupData, componentGroupName);
this._componentGroups[componentGroupName] = cg;
componentGroups.push(cg);
}
else {
componentGroups.push(this._componentGroups[componentGroupName]);
}
}
}
return componentGroups;
}
getEvent(eventName) {
try {
if (this._data !== undefined && Utilities_1.default.isUsableAsObjectKey(eventName)) {
if (!this._events[eventName]) {
const eventData = this._data.events[eventName];
this._events[eventName] = eventData;
}
return this._events[eventName];
}
}
catch (e) {
Log_1.default.verbose("Error getting event " + eventName + ": " + e);
}
return undefined;
}
getEffectiveComponents(componentGroupAddRemoveList) {
const componentState = JSON.parse(JSON.stringify(this._data?.components)); // clone
for (let componentGroupId of componentGroupAddRemoveList) {
let isAdd = true;
if (componentGroupId.startsWith("-")) {
componentGroupId = componentGroupId.substring(1);
isAdd = false;
}
else if (componentGroupId.startsWith("+")) {
componentGroupId = componentGroupId.substring(1);
}
const componentGroup = this.getComponentGroup(componentGroupId);
if (componentGroup) {
const cgComps = componentGroup.getComponents();
if (isAdd) {
for (const cgComp of cgComps) {
componentState[cgComp.id] = cgComp.getData();
}
}
else if (!isAdd) {
for (const cgComp of cgComps) {
componentState[cgComp.id] = undefined;
}
}
}
}
return new ManagedComponentGroup_1.default(componentState, this.id);
}
getEvents() {
const events = [];
if (this._data !== undefined) {
for (const eventName in this._data.events) {
if (!this._events[eventName] && Utilities_1.default.isUsableAsObjectKey(eventName)) {
const eventData = this._data.events[eventName];
this._events[eventName] = eventData;
events.push({ id: eventName, event: eventData });
}
else {
events.push({ id: eventName, event: this._events[eventName] });
}
}
}
return events;
}
addComponent(id, componentOrData) {
this._ensureBehaviorPackDataInitialized();
const bpData = this._data;
const mc = componentOrData instanceof ManagedComponent_1.ManagedComponent
? componentOrData
: new ManagedComponent_1.ManagedComponent(bpData.components, id, componentOrData);
bpData.components[id] = mc.getData();
this._managedComponents[id] = mc;
this._onComponentAdded.dispatch(this, mc);
return mc;
}
addComponentGroup(id, componentOrData) {
this._ensureBehaviorPackDataInitialized();
if (id === undefined) {
id = "group";
let increment = 0;
let cg = this.getComponentGroup(id);
while (cg !== undefined && increment < 100) {
increment++;
id = "group" + increment;
cg = this.getComponentGroup(id);
}
}
if (componentOrData === undefined) {
componentOrData = {};
}
const bpData = this._data;
const mcg = componentOrData instanceof ManagedComponentGroup_1.default
? componentOrData
: new ManagedComponentGroup_1.default(componentOrData, id);
const cgData = mcg.getData();
if (cgData) {
bpData.component_groups[id] = cgData;
}
this._componentGroups[id] = mcg;
return mcg;
}
removeComponent(id) {
if (this._data === undefined) {
return;
}
const newBehaviorPacks = {};
const newManagedComponents = {};
for (const name in this._data.components) {
if (name !== id && Utilities_1.default.isUsableAsObjectKey(name)) {
const componentData = this._data.components[name];
newBehaviorPacks[name] = componentData;
}
}
for (const name in this._managedComponents) {
if (name !== id && this._managedComponents[name] && Utilities_1.default.isUsableAsObjectKey(name)) {
newManagedComponents[name] = this._managedComponents[name];
}
}
this._data.components = newBehaviorPacks;
this._managedComponents = newManagedComponents;
}
_ensureBehaviorPackDataInitialized() {
if (!this._wrapper) {
this._wrapper = {
format_version: "1.20.0",
};
}
if (this._data === undefined) {
this._data = {
description: {
identifier: "unknown",
is_experimental: false,
is_spawnable: false,
is_summonable: false,
},
components: {},
component_groups: {},
events: {},
};
if (this._wrapper) {
//@ts-ignore
this._wrapper["minecraft:entity"] = this._data;
}
}
}
getProperties() {
if (!this._data || !this._data?.description) {
return undefined;
}
return this._data.description.properties;
}
getPropertyList() {
const props = this.getProperties();
if (!props) {
return [];
}
const propertyList = [];
for (const propName in props) {
if (props[propName] !== undefined) {
propertyList.push(propName);
}
}
return propertyList;
}
static getPropertyTypeString(stateType) {
switch (stateType) {
case EntityPropertyType.boolean:
return "bool";
case EntityPropertyType.float:
return "float";
case EntityPropertyType.enum:
return "enum";
}
return "int";
}
addProperty(propertyName, propertyType) {
if (!this._data || !this._data.description) {
return;
}
let dataArr = undefined;
let typeStr = EntityTypeDefinition.getPropertyTypeString(propertyType);
let defaultValue = false;
if (propertyType === EntityPropertyType.float) {
dataArr = [0, 1, 2];
defaultValue = 0;
}
else if (propertyType === EntityPropertyType.enum) {
dataArr = ["value1", "value2"];
defaultValue = "value1";
}
if (!this._data.description.properties) {
this._data.description.properties = {};
}
this._data.description.properties[propertyName] = {
type: typeStr,
values: dataArr,
default: defaultValue,
};
}
addEvent(eventName) {
if (!this._data) {
return;
}
if (!this._data.events) {
this._data.events = {};
}
if (eventName === undefined) {
eventName = "eventName";
let increment = 0;
let eve = this.getEvent(eventName);
while (eve !== undefined && increment < 100) {
increment++;
eventName = "eventName" + increment;
eve = this.getEvent(eventName);
}
}
this._data.events[eventName] = {};
}
async addChildItems(project, item, index) {
let lootTablePaths = [];
const comps = this.getComponentsInBaseAndGroups("minecraft:loot");
for (const comp of comps) {
let lootTablePath = comp.getProperty("table");
if (lootTablePath) {
lootTablePaths.push(lootTablePath);
}
}
// Use pre-built index for O(1) lookups when available
if (index && this.id) {
// Entity resources matching this entity's ID
const matchingResources = index.getItemsById(index.entityResourcesById, this.id);
for (const candItem of matchingResources) {
item.addChildItem(candItem);
}
// Spawn rules matching this entity's ID
const matchingSpawnRules = index.getItemsById(index.spawnRulesById, this.id);
for (const candItem of matchingSpawnRules) {
item.addChildItem(candItem);
}
// Loot tables by path suffix match
if (lootTablePaths.length > 0) {
const lootTableItems = project.getItemsByType(IProjectItemData_1.ProjectItemType.lootTableBehavior);
for (const candItem of lootTableItems) {
for (const lootTablePath of lootTablePaths) {
if (candItem.projectPath?.endsWith(lootTablePath)) {
item.addChildItem(candItem);
}
}
}
}
}
else {
// Fallback: scan items when index is not available
const entityResourceItems = project.getItemsByType(IProjectItemData_1.ProjectItemType.entityTypeResource);
for (const candItem of entityResourceItems) {
if (!candItem.isContentLoaded) {
await candItem.loadContent();
}
if (candItem.primaryFile) {
const etrd = await EntityTypeResourceDefinition_1.default.ensureOnFile(candItem.primaryFile);
if (etrd) {
const id = etrd.id;
if (id === this.id) {
item.addChildItem(candItem);
}
}
}
}
const spawnRuleItems = project.getItemsByType(IProjectItemData_1.ProjectItemType.spawnRuleBehavior);
for (const candItem of spawnRuleItems) {
if (!candItem.isContentLoaded) {
await candItem.loadContent();
}
if (candItem.primaryFile) {
const srb = await SpawnRulesBehaviorDefinition_1.default.ensureOnFile(candItem.primaryFile);
if (srb) {
const id = srb.id;
if (id === this.id) {
item.addChildItem(candItem);
}
}
}
}
if (lootTablePaths.length > 0) {
const lootTableItems = project.getItemsByType(IProjectItemData_1.ProjectItemType.lootTableBehavior);
for (const candItem of lootTableItems) {
for (const lootTablePath of lootTablePaths) {
if (candItem.projectPath?.endsWith(lootTablePath)) {
item.addChildItem(candItem);
}
}
}
}
}
}
static async ensureOnFile(behaviorPackFile, loadHandler, preserveComments) {
let et;
if (behaviorPackFile.manager === undefined) {
et = new EntityTypeDefinition();
et.behaviorPackFile = behaviorPackFile;
behaviorPackFile.manager = et;
}
if (behaviorPackFile.manager !== undefined && behaviorPackFile.manager instanceof EntityTypeDefinition) {
et = behaviorPackFile.manager;
if (!et.isLoaded || (preserveComments && !et._loadedWithComments)) {
if (loadHandler) {
et.onLoaded.subscribe(loadHandler);
}
await et.load(preserveComments);
}
}
return et;
}
getScript(isTypeScript) {
if (this.shortId === undefined) {
return;
}
const className = ScriptGen_1.default.getClassName(this.shortId);
const results = [];
results.push("import * as mc from '@minecraft/server';");
results.push("export default class " + className + "Base");
results.push("{");
if (isTypeScript) {
results.push(" _entity : mc.Entity;");
results.push(" constructor(entity : mc.Entity) {");
}
else {
results.push(" _entity;\n");
results.push(" constructor(entity) {");
}
results.push(" this._entity = entity;");
results.push(" }\n\n");
if (isTypeScript) {
results.push(" static spawn(location : mc.Vector3) {");
}
else {
results.push(" static spawn(location) {");
}
results.push(' const entity = world.getDimension("overworld").spawnEntity("' + this.id + '", location);');
results.push(" const " + ScriptGen_1.default.getInstanceName(this.shortId) + " = new " + className + "(entity);");
results.push(" return " + ScriptGen_1.default.getInstanceName(this.shortId) + ";");
results.push(" }\n");
if (this._data !== undefined) {
const healthC = this._data.components["minecraft:health"];
if (healthC !== undefined) {
results.push(" fullyHeal() {");
results.push(' this._entity.getComponent("minecraft:health").resetToMaxValue();');
results.push(" }\n");
if (isTypeScript) {
results.push(" setHealth(newValue : number) {");
}
else {
results.push(" setHealth(newValue) {");
}
results.push(' this._entity.getComponent("minecraft:health").setCurrent(newValue);');
results.push(" }\n");
}
const rideableC = this._data.components["minecraft:rideable"];
if (rideableC !== undefined) {
if (isTypeScript) {
results.push(" addRider(newRider : mc.Entity) {");
}
else {
results.push(" addRider(newRider) {");
}
results.push(' this._entity.getComponent("minecraft:rideable").addRider(newRider);');
results.push(" }\n");
if (isTypeScript) {
results.push(" ejectRider(rider : mc.Entity) {");
}
else {
results.push(" ejectRider(rider) {");
}
results.push(' this._entity.getComponent("minecraft:rideable").addRider(rider);');
results.push(" }\n");
}
const tameableC = this._data.components["minecraft:tameable"];
if (tameableC !== undefined) {
results.push(" tame() {");
results.push(' return this._entity.getComponent("minecraft:tameable").tame();');
results.push(" }\n");
}
}
results.push("}");
return results.join("\n");
}
persist() {
if (this._file === undefined) {
return false;
}
Log_1.default.assert(!this._isLoaded || this._wrapper !== null, "ETDP");
if (!this._wrapper) {
return false;
}
this._isSelfPersisting = true;
try {
return this._file.setObjectContentIfSemanticallyDifferent(this._wrapper);
}
finally {
this._isSelfPersisting = false;
}
}
/**
* Loads the entity type definition from the file.
* @param preserveComments If true, uses comment-preserving JSON parsing for edit/save cycles.
* If false (default), uses efficient standard JSON parsing.
* Can be called again with true to "upgrade" a read-only load to read/write.
*/
async load(preserveComments = false) {
// If already loaded with comments, we have the "best" version - nothing more to do
if (this._isLoaded && this._loadedWithComments) {
return;
}
// If already loaded without comments and caller doesn't need comments, we're done
if (this._isLoaded && !preserveComments) {
return;
}
// If we get here and _isLoaded is true, we need to "upgrade" from read-only to read/write
// by re-parsing with comment preservation
if (this._file === undefined) {
Log_1.default.unexpectedUndefined("ETBPF");
return;
}
if (!this._file.isContentLoaded) {
await this._file.loadContent();
}
if (!this._file.content || this._file.content instanceof Uint8Array) {
this._isLoaded = true;
this._onLoaded.dispatch(this, this);
return;
}
let data = {};
// Use comment-preserving parser only when needed for editing
let result = preserveComments
? StorageUtilities_1.default.getJsonObjectWithComments(this._file)
: StorageUtilities_1.default.getJsonObject(this._file);
if (result) {
data = result;
}
this._wrapper = data;
const entity = data["minecraft:entity"];
if (entity && entity.description) {
this.id = entity.description.identifier;
}
this._data = entity;
if (this._data) {
if (this._data.components) {
for (const compName in this._data.components) {
const comp = this._data.components[compName];
if (comp) {
this._managedComponents[compName] = new ManagedComponent_1.ManagedComponent(this._data.components, compName, comp);
}
}
}
if (this._data.component_groups) {
for (const compGroupName in this._data.component_groups) {
const compGroup = this._data.component_groups[compGroupName];
if (compGroup) {
this._componentGroups[compGroupName] = new ManagedComponentGroup_1.default(compGroup, compGroupName);
}
}
}
}
this._isLoaded = true;
this._loadedWithComments = preserveComments;
this._onLoaded.dispatch(this, this);
}
}
exports.default = EntityTypeDefinition;