@minecraft/creator-tools
Version:
Minecraft Creator Tools command line and libraries.
723 lines (721 loc) • 28.8 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.EntityPropertyType = exports.AttributeComponents = exports.EntityTypeComponentExtendedCategory = exports.EntityTypeComponentCategory = void 0;
const Log_1 = require("../core/Log");
const ste_events_1 = require("ste-events");
const ScriptGen_1 = require("../script/ScriptGen");
const ManagedComponentGroup_1 = require("./ManagedComponentGroup");
const ManagedComponent_1 = require("./ManagedComponent");
const StorageUtilities_1 = require("../storage/StorageUtilities");
const Database_1 = require("./Database");
const MinecraftUtilities_1 = require("./MinecraftUtilities");
const IProjectItemData_1 = require("../app/IProjectItemData");
const EntityTypeResourceDefinition_1 = require("./EntityTypeResourceDefinition");
const SpawnRulesBehaviorDefinition_1 = require("./SpawnRulesBehaviorDefinition");
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 || (exports.EntityTypeComponentCategory = {}));
var EntityTypeComponentExtendedCategory;
(function (EntityTypeComponentExtendedCategory) {
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["attribute"] = 0] = "attribute";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["complex"] = 1] = "complex";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["behavior"] = 2] = "behavior";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["trigger"] = 3] = "trigger";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["movementBehavior"] = 4] = "movementBehavior";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["mobSpecificBehavior"] = 5] = "mobSpecificBehavior";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["movementComplex"] = 6] = "movementComplex";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["combatAndHealthComplex"] = 7] = "combatAndHealthComplex";
EntityTypeComponentExtendedCategory[EntityTypeComponentExtendedCategory["sensorComponents"] = 8] = "sensorComponents";
})(EntityTypeComponentExtendedCategory = exports.EntityTypeComponentExtendedCategory || (exports.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["string"] = 0] = "string";
EntityPropertyType[EntityPropertyType["boolean"] = 1] = "boolean";
EntityPropertyType[EntityPropertyType["number"] = 2] = "number";
})(EntityPropertyType = exports.EntityPropertyType || (exports.EntityPropertyType = {}));
class EntityTypeDefinition {
constructor() {
this._isLoaded = false;
this._managedComponents = {};
this._componentGroups = {};
this._events = {};
this._onLoaded = new ste_events_1.EventDispatcher();
this._onComponentAdded = new ste_events_1.EventDispatcher();
this._onComponentRemoved = new ste_events_1.EventDispatcher();
this._onComponentChanged = new ste_events_1.EventDispatcher();
}
get data() {
return this._data;
}
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;
}
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._behaviorPackFile;
}
get onLoaded() {
return this._onLoaded.asEvent();
}
set behaviorPackFile(newFile) {
this._behaviorPackFile = newFile;
}
get id() {
return this._id;
}
set id(newId) {
this._id = 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;
}
async getFormatVersionIsCurrent() {
const fv = this.getFormatVersion();
if (fv === undefined || fv.length !== 3) {
return false;
}
return await Database_1.default.isRecentVersionFromVersionArray(fv);
}
getFormatVersion() {
if (!this.behaviorPackWrapper) {
return undefined;
}
return MinecraftUtilities_1.default.getVersionArrayFrom(this.behaviorPackWrapper.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 (!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;
}
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.behaviorPackWrapper || !this.behaviorPackWrapper.format_version) {
return undefined;
}
return this.behaviorPackWrapper.format_version;
}
setBehaviorPackFormatVersion(versionStr) {
this._ensureBehaviorPackDataInitialized();
if (this.behaviorPackWrapper) {
this.behaviorPackWrapper.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;
}
getComponentGroup(componentGroupName) {
if (this._data !== undefined) {
if (!this._componentGroups[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) {
if (this._data !== undefined) {
if (!this._events[eventName]) {
const eventData = this._data.events[eventName];
this._events[eventName] = eventData;
}
return this._events[eventName];
}
return undefined;
}
getEvents() {
const events = [];
if (this._data !== undefined) {
for (const eventName in this._data.events) {
if (!this._events[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;
}
removeComponent(id) {
if (this._data === undefined) {
return;
}
const newBehaviorPacks = {};
const newManagedComponents = {};
for (const name in this._data.components) {
if (name !== id) {
const componentData = this._data.components[name];
newBehaviorPacks[name] = componentData;
}
}
for (const name in this._managedComponents) {
if (name !== id && this._managedComponents[name]) {
newManagedComponents[name] = this._managedComponents[name];
}
}
this._data.components = newBehaviorPacks;
this._managedComponents = newManagedComponents;
}
_ensureBehaviorPackDataInitialized() {
if (!this.behaviorPackWrapper) {
this.behaviorPackWrapper = {
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.behaviorPackWrapper) {
//@ts-ignore
this.behaviorPackWrapper["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;
}
addProperty(propertyName, stateType) {
if (!this._data || !this._data.description) {
return;
}
let dataArr = [];
if (stateType === EntityPropertyType.boolean) {
dataArr = [false, true];
}
else if (stateType === EntityPropertyType.number) {
dataArr = [0, 1, 2];
}
else if (stateType === EntityPropertyType.string) {
dataArr = ["value1", "value2"];
}
if (!this._data.description.properties) {
this._data.description.properties = {};
}
this._data.description.properties[propertyName] = dataArr;
}
addEvent(eventName) {
if (!this._data) {
return;
}
if (!this._data.events) {
this._data.events = {};
}
this._data.events[eventName] = {};
}
async addChildItems(project, item) {
let lootTablePaths = [];
const comps = this.getComponentsInBaseAndGroups("minecraft:loot");
for (const comp of comps) {
let lootTablePath = comp.getProperty("table");
if (lootTablePath) {
lootTablePaths.push(lootTablePath);
}
}
const itemsCopy = project.getItemsCopy();
for (const candItem of itemsCopy) {
if (candItem.itemType === IProjectItemData_1.ProjectItemType.entityTypeResource) {
await candItem.ensureStorage();
if (candItem.file) {
const etrd = await EntityTypeResourceDefinition_1.default.ensureOnFile(candItem.file);
if (etrd) {
const id = etrd.id;
if (id === this.id) {
item.addChildItem(candItem);
}
}
}
}
else if (candItem.itemType === IProjectItemData_1.ProjectItemType.spawnRuleBehavior) {
await candItem.ensureStorage();
if (candItem.file) {
const srb = await SpawnRulesBehaviorDefinition_1.default.ensureOnFile(candItem.file);
if (srb) {
const id = srb.id;
if (id === this.id) {
item.addChildItem(candItem);
}
}
}
}
else if (candItem.itemType === IProjectItemData_1.ProjectItemType.lootTableBehavior) {
for (const lootTablePath of lootTablePaths) {
if (candItem.projectPath?.endsWith(lootTablePath)) {
item.addChildItem(candItem);
}
}
}
}
}
static async ensureOnFile(behaviorPackFile, loadHandler) {
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 && loadHandler) {
et.onLoaded.subscribe(loadHandler);
}
await et.load();
}
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;\r\n");
results.push(" constructor(entity) {");
}
results.push(" this._entity = entity;");
results.push(" }\r\n\r\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(" }\r\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(" }\r\n");
if (isTypeScript) {
results.push(" setHealth(newValue : number) {");
}
else {
results.push(" setHealth(newValue) {");
}
results.push(' this._entity.getComponent("minecraft:health").setCurrent(newValue);');
results.push(" }\r\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(" }\r\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(" }\r\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(" }\r\n");
}
}
results.push("}");
return results.join("\r\n");
}
persist() {
if (this._behaviorPackFile === undefined) {
return;
}
const bpString = JSON.stringify(this.behaviorPackWrapper, null, 2);
this._behaviorPackFile.setContent(bpString);
}
async load() {
if (this._isLoaded) {
return;
}
if (this._behaviorPackFile === undefined) {
Log_1.default.unexpectedUndefined("ETBPF");
return;
}
await this._behaviorPackFile.loadContent();
if (!this._behaviorPackFile.content || this._behaviorPackFile.content instanceof Uint8Array) {
return;
}
let data = {};
let result = StorageUtilities_1.default.getJsonObject(this._behaviorPackFile);
if (result) {
data = result;
}
this.behaviorPackWrapper = 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._onLoaded.dispatch(this, this);
}
}
exports.default = EntityTypeDefinition;
//# sourceMappingURL=../maps/minecraft/EntityTypeDefinition.js.map