mm_os
Version:
MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。
275 lines (249 loc) • 6.73 kB
JavaScript
/**
* 实体类
* 纯粹的实体标识符,不包含任何业务逻辑
* 只负责管理组件引用和实体生命周期
*/
const { idGen } = require('../../ulits/id_gen.js');
class Entity {
#is_dirty = false;
/**
* 构造函数
* @param {string} entity_id 实体ID
* @param {string} player_id 玩家ID
* @param {string} type 实体类型, 例如:玩家player、怪物monster、道具prop等
*/
constructor(entity_id, player_id, type) {
// 实体名称
this.name = '';
// 实体ID
this.entity_id = entity_id || this.genId();
// 实体类型
this.type = type || '';
// 玩家ID - 如果是玩家就有此ID
this.player_id = player_id || '';
// 是否活跃
this.is_active = true;
// 实体组件
this._component = new Map();
// 创建属性代理
this._createProperty();
}
/**
* 检查实体是否脏数据
* @param {boolean} is_dirty 是否脏数据
* @returns {boolean} 是否脏数据
*/
isDirty(is_dirty) {
if (is_dirty !== undefined) {
this.#is_dirty = is_dirty;
}
return this.#is_dirty;
};
}
/**
* 创建属性代理
* 使组件属性可以通过点语法直接访问
* 例如:entity.attr.hp 可以访问 attr 组件中的 hp 属性
*/
Entity.prototype._createProperty = function () {
var self = this;
// 为每个已存在的组件创建属性访问器
var keys = Array.from(self._component.keys());
for (var i = 0; i < keys.length; i++) {
(function (name) {
Object.defineProperty(self, name, {
get: function () {
return self._component.get(name);
},
set: function (value) {
if (typeof value === 'object' && value !== null) {
self._component.set(name, value);
// 标记为脏数据
self.isDirty(true);
}
},
enumerable: true,
configurable: true
});
})(keys[i]);
}
// 重写 addComponent 方法,使其在添加组件时自动创建属性访问器
let comp = self.addComponent;
self.addComponent = function (name, component) {
// 调用原始方法
comp.call(self, name, component);
// 创建属性访问器
Object.defineProperty(self, name, {
get: function () {
return self._component.get(name);
},
set: function (value) {
if (typeof value === 'object' && value !== null) {
self._component.set(name, value);
// 标记为脏数据
self.isDirty(true);
}
},
enumerable: true,
configurable: true
});
};
};
/**
* 获取实体ID
* @returns {string} 实体ID
*/
Entity.prototype.getId = function () {
return this.entity_id;
};
/**
* 检查实体是否活跃
* @returns {boolean} 是否活跃
*/
Entity.prototype.isActive = function () {
return this.is_active;
};
/**
* 激活实体
*/
Entity.prototype.activate = function () {
this.is_active = true;
};
/**
* 停用实体
*/
Entity.prototype.deactivate = function () {
this.is_active = false;
};
/**
* 添加组件
* @param {string} name 组件类型
* @param {object} component 组件数据
*/
Entity.prototype.addComponent = function (name, component) {
// 参数校验
if (typeof name !== 'string') {
throw new TypeError('组件类型必须是字符串');
}
if (typeof component !== 'object') {
throw new TypeError('组件数据必须是对象');
}
this._component.set(name, component);
};
/**
* 获取组件
* @param {string} name 组件类型
* @returns {object|null} 组件数据
*/
Entity.prototype.getComponent = function (name) {
// 参数校验
if (typeof name !== 'string') {
throw new TypeError('组件类型必须是字符串');
}
return this._component.get(name) || null;
};
/**
* 检查是否包含组件
* @param {string} name 组件类型
* @returns {boolean} 是否包含组件
*/
Entity.prototype.hasComponent = function (name) {
// 参数校验
if (typeof name !== 'string') {
throw new TypeError('组件类型必须是字符串');
}
return this._component.has(name);
};
/**
* 移除组件
* @param {string} name 组件类型
* @returns {boolean} 是否移除成功
*/
Entity.prototype.delComponent = function (name) {
// 参数校验
if (typeof name !== 'string') {
throw new TypeError('组件类型必须是字符串');
}
return this._component.delete(name);
};
/**
* 获取所有组件类型
* @returns {Array} 组件类型数组
*/
Entity.prototype.getComponentTypes = function () {
return Array.from(this._component.keys());
};
/**
* 转换为JSON字符串
* @returns {string} JSON字符串
*/
Entity.prototype.toJson = function () {
let data = {
entity_id: this.entity_id,
player_id: this.player_id,
is_active: this.is_active,
name: this.name,
type: this.type,
components: Object.fromEntries(this._component)
};
return JSON.stringify(data);
};
/**
* 从JSON字符串解析实体
* @param {string} json_str JSON字符串
* @returns {Entity} 实体对象
*/
Entity.prototype.fromJson = function (json_str) {
// 参数校验
if (typeof json_str !== 'string') {
throw new TypeError('JSON字符串必须是字符串');
}
let data = JSON.parse(json_str);
if (!data.entity_id) {
throw new Error('JSON字符串缺少实体ID');
}
// 设置基本属性
this.entity_id = data.entity_id;
this.player_id = data.player_id || '';
this.is_active = data.is_active !== undefined ? data.is_active : true;
this.name = data.name || '';
this.type = data.type || '';
// 恢复组件
if (data.components && typeof data.components === 'object') {
for (var k in data.components) {
this.addComponent(k, data.components[k]);
}
// 创建属性访问器
this._createProperty();
}
return this;
};
/**
* 生成唯一实体ID
* @returns {string} 唯一实体ID
*/
Entity.prototype.genId = function () {
return idGen.genId('entity');
};
/**
* 设置实体模型
* @param {object} model 实体模型
*/
Entity.prototype.setModel = function (model) {
for (var k in model) {
let value = model[k];
if (typeof value === 'object') {
var component = this.getComponent(k);
if (component) {
$.push(component, value);
this.addComponent(k, component);
}
}
else if (this.hasOwnProperty(k)) {
this[k] = value;
}
}
};
module.exports = {
Entity
};