mirror of
https://gitee.com/dgflash/oops-plugin-framework.git
synced 2026-05-08 03:16:49 +08:00
1.规范化框架业务模板的提示信息
2.废弃GameCollision.ts
This commit is contained in:
@@ -11,7 +11,26 @@ import type { CCEntity } from './CCEntity';
|
||||
|
||||
/** 业务逻辑 */
|
||||
export class CCBusiness<T extends CCEntity> {
|
||||
ent!: T;
|
||||
private _destroyed: boolean = false;
|
||||
|
||||
/** 当前业务逻辑是否有效(未销毁) */
|
||||
get isValid(): boolean {
|
||||
return !this._destroyed;
|
||||
}
|
||||
|
||||
private _ent: T | null = null;
|
||||
|
||||
/** 所属实体引用 */
|
||||
get ent(): T {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '尝试访问已销毁的业务逻辑的实体引用');
|
||||
}
|
||||
return this._ent!;
|
||||
}
|
||||
|
||||
set ent(value: T) {
|
||||
this._ent = value;
|
||||
}
|
||||
|
||||
/** 业务逻辑初始化(由 CCEntity.addBusiness 自动调用) */
|
||||
protected init() {
|
||||
@@ -19,6 +38,13 @@ export class CCBusiness<T extends CCEntity> {
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '业务逻辑已销毁,无需重复销毁');
|
||||
return;
|
||||
}
|
||||
|
||||
this._destroyed = true;
|
||||
|
||||
// 释放消息对象
|
||||
if (this._event) {
|
||||
this._event.clear();
|
||||
@@ -26,7 +52,7 @@ export class CCBusiness<T extends CCEntity> {
|
||||
}
|
||||
|
||||
// 清空实体引用,避免循环引用导致的内存泄漏
|
||||
this.ent = null!;
|
||||
this._ent = null;
|
||||
}
|
||||
|
||||
//#region 全局事件管理
|
||||
@@ -34,6 +60,9 @@ export class CCBusiness<T extends CCEntity> {
|
||||
private _event: EventDispatcher | null = null;
|
||||
/** 全局事件管理器 */
|
||||
private get event(): EventDispatcher {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '尝试访问已销毁的业务逻辑的事件管理器');
|
||||
}
|
||||
if (this._event == null) this._event = new EventDispatcher();
|
||||
return this._event;
|
||||
}
|
||||
@@ -47,6 +76,10 @@ export class CCBusiness<T extends CCEntity> {
|
||||
* @param object 侦听函数绑定的this对象
|
||||
*/
|
||||
watch<K extends keyof OopsFramework.TypedEventMap>(event: K, listener: ListenerFuncTyped<K, OopsFramework.TypedEventMap[K]>, object: any): void {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '尝试在已销毁的业务逻辑上注册事件');
|
||||
return;
|
||||
}
|
||||
this.event.on(event as string, listener as ListenerFunc, object);
|
||||
}
|
||||
|
||||
@@ -57,6 +90,10 @@ export class CCBusiness<T extends CCEntity> {
|
||||
* @param object 侦听函数绑定的this对象
|
||||
*/
|
||||
watchOnce<K extends keyof OopsFramework.TypedEventMap>(event: K, listener: ListenerFuncTyped<K, OopsFramework.TypedEventMap[K]>, object: any): void {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '尝试在已销毁的业务逻辑上注册一次性事件');
|
||||
return;
|
||||
}
|
||||
this.event.once(event as string, listener as ListenerFunc, object);
|
||||
}
|
||||
|
||||
@@ -67,6 +104,7 @@ export class CCBusiness<T extends CCEntity> {
|
||||
* @param object 侦听函数绑定的this对象(可选)
|
||||
*/
|
||||
unwatch<K extends keyof OopsFramework.TypedEventMap>(event: K, listener?: ListenerFuncTyped<K, OopsFramework.TypedEventMap[K]>, object?: any): void {
|
||||
if (this._destroyed) return;
|
||||
this.event.off(event as string, listener as ListenerFunc, object);
|
||||
}
|
||||
|
||||
@@ -76,6 +114,10 @@ export class CCBusiness<T extends CCEntity> {
|
||||
* @param data 事件数据
|
||||
*/
|
||||
emit<K extends keyof OopsFramework.TypedEventMap>(event: K, data: OopsFramework.TypedEventMap[K]): void {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '尝试在已销毁的业务逻辑上触发事件');
|
||||
return;
|
||||
}
|
||||
this.event.emit(event, data);
|
||||
}
|
||||
|
||||
@@ -85,6 +127,10 @@ export class CCBusiness<T extends CCEntity> {
|
||||
* @param data 事件数据(必须完全匹配类型定义)
|
||||
*/
|
||||
emitAsync<K extends keyof OopsFramework.TypedEventMap>(event: K, data: OopsFramework.TypedEventMap[K]): Promise<void> {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '尝试在已销毁的业务逻辑上触发异步事件');
|
||||
return Promise.resolve();
|
||||
}
|
||||
return this.event.emitAsync(event, data);
|
||||
}
|
||||
|
||||
@@ -99,6 +145,10 @@ export class CCBusiness<T extends CCEntity> {
|
||||
* @param object 侦听函数绑定的this对象
|
||||
*/
|
||||
on(event: string, listener: ListenerFunc, object: object) {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '尝试在已销毁的业务逻辑上注册事件');
|
||||
return;
|
||||
}
|
||||
this.event.on(event, listener, object);
|
||||
}
|
||||
|
||||
@@ -109,6 +159,10 @@ export class CCBusiness<T extends CCEntity> {
|
||||
* @param object 侦听函数绑定的this对象
|
||||
*/
|
||||
once(event: string, listener: ListenerFunc, object: object) {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '尝试在已销毁的业务逻辑上注册一次性事件');
|
||||
return;
|
||||
}
|
||||
this.event.once(event, listener, object);
|
||||
}
|
||||
|
||||
@@ -119,6 +173,7 @@ export class CCBusiness<T extends CCEntity> {
|
||||
* @param object 侦听函数绑定的this对象(可选)
|
||||
*/
|
||||
off(event: string, listener?: ListenerFunc, object?: object) {
|
||||
if (this._destroyed) return;
|
||||
this.event.off(event, listener, object);
|
||||
}
|
||||
|
||||
@@ -128,6 +183,10 @@ export class CCBusiness<T extends CCEntity> {
|
||||
* @param args 事件参数
|
||||
*/
|
||||
dispatchEvent(event: string, ...args: unknown[]) {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '尝试在已销毁的业务逻辑上触发事件');
|
||||
return;
|
||||
}
|
||||
this.event.dispatchEvent(event, ...args);
|
||||
}
|
||||
|
||||
@@ -137,6 +196,10 @@ export class CCBusiness<T extends CCEntity> {
|
||||
* @param args 事件参数
|
||||
*/
|
||||
dispatchEventAsync(event: string, ...args: unknown[]): Promise<void> {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '尝试在已销毁的业务逻辑上触发异步事件');
|
||||
return Promise.resolve();
|
||||
}
|
||||
return this.event.dispatchEventAsync(event, ...args);
|
||||
}
|
||||
|
||||
@@ -149,13 +212,17 @@ export class CCBusiness<T extends CCEntity> {
|
||||
* onGlobal(event: string, args: unknown) { console.log(args) };
|
||||
*/
|
||||
protected setEvent(...args: string[]) {
|
||||
if (this._destroyed) {
|
||||
console.warn('[OopsFramework]', '尝试在已销毁的业务逻辑上批量设置事件');
|
||||
return;
|
||||
}
|
||||
for (const name of args) {
|
||||
const func = (this as Record<string, unknown>)[name];
|
||||
if (typeof func === 'function') {
|
||||
this.on(name, func as ListenerFunc, this);
|
||||
}
|
||||
else {
|
||||
console.error(`名为【${name}】的全局事方法不存在`);
|
||||
console.error('[OopsFramework]', `名为【${name}】的全局事方法不存在`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export abstract class CCEntity extends ecs.Entity {
|
||||
addChildSingleton<T extends CCEntity>(cls: OopsFramework.EntityCtor<T>): T {
|
||||
if (this.singletons == null) this.singletons = new Map();
|
||||
if (this.singletons.has(cls)) {
|
||||
console.error(`${cls.name} 单例子实体已存在`);
|
||||
console.error('[OopsFramework]', `${cls.name} 单例子实体已存在`);
|
||||
return null!;
|
||||
}
|
||||
const entity = ecs.getEntity<T>(cls);
|
||||
@@ -105,7 +105,7 @@ export abstract class CCEntity extends ecs.Entity {
|
||||
|
||||
// 检查实体是否已销毁
|
||||
if (!this.isValid) {
|
||||
console.warn(`实体已销毁,取消添加预制体组件: ${(ctor as any).name}`);
|
||||
console.warn('[OopsFramework]', `实体已销毁,取消添加预制体组件: ${(ctor as any).name}`);
|
||||
node.destroy();
|
||||
return null;
|
||||
}
|
||||
@@ -120,7 +120,7 @@ export abstract class CCEntity extends ecs.Entity {
|
||||
|
||||
// 检查实体是否已销毁
|
||||
if (!this.isValid) {
|
||||
console.warn(`实体已销毁,取消添加预制体组件: ${(ctor as any).name}`);
|
||||
console.warn('[OopsFramework]', `实体已销毁,取消添加预制体组件: ${(ctor as any).name}`);
|
||||
node.destroy();
|
||||
return null;
|
||||
}
|
||||
@@ -166,7 +166,7 @@ export abstract class CCEntity extends ecs.Entity {
|
||||
}
|
||||
|
||||
if (oops.gui.has(key)) {
|
||||
console.warn(`${key} 界面已存在`);
|
||||
console.warn('[OopsFramework]', `${key} 界面已存在`);
|
||||
return oops.gui.get(key);
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ export abstract class CCEntity extends ecs.Entity {
|
||||
|
||||
// 检查实体是否已销毁
|
||||
if (!this.isValid) {
|
||||
console.warn(`实体已销毁,取消添加界面组件: ${key}`);
|
||||
console.warn('[OopsFramework]', `实体已销毁,取消添加界面组件: ${key}`);
|
||||
oops.gui.remove(key);
|
||||
return null;
|
||||
}
|
||||
@@ -196,7 +196,7 @@ export abstract class CCEntity extends ecs.Entity {
|
||||
if (key) {
|
||||
const node = oops.gui.get(key);
|
||||
if (node == null) {
|
||||
console.warn(`${key} 界面不存在或已关闭`);
|
||||
console.warn('[OopsFramework]', `${key} 界面不存在或已关闭`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ export abstract class CCEntity extends ecs.Entity {
|
||||
if (view) this.remove(ctor as unknown as CompType<ecs.IComp>);
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`移除界面组件失败: ${key}`, error);
|
||||
console.error('[OopsFramework]', `移除界面组件失败: ${key}`, error);
|
||||
}
|
||||
};
|
||||
oops.gui.remove(key);
|
||||
@@ -248,7 +248,7 @@ export abstract class CCEntity extends ecs.Entity {
|
||||
addBusiness<T extends CCBusiness<CCEntity>>(cls: OopsFramework.BusinessCtor<T>): T {
|
||||
if (this.businesss == null) this.businesss = new Map();
|
||||
if (this.businesss.has(cls)) {
|
||||
console.error(`${cls.name} 业务逻辑组件已存在`);
|
||||
console.error('[OopsFramework]', `${cls.name} 业务逻辑组件已存在`);
|
||||
return null!;
|
||||
}
|
||||
const business = new cls();
|
||||
|
||||
@@ -5,13 +5,11 @@
|
||||
* @LastEditTime: 2022-09-06 17:20:51
|
||||
*/
|
||||
|
||||
import type { Component } from 'cc';
|
||||
import type { ecs } from '../../libs/ecs/ECS';
|
||||
import { ECSModel } from '../../libs/ecs/ECSModel';
|
||||
import { VM } from '../../libs/model-view/ViewModel';
|
||||
import { VMBase } from '../../libs/model-view/VMBase';
|
||||
import type { CCEntity } from './CCEntity';
|
||||
import type { UICtor } from '../../types/Module';
|
||||
import { GameComponent } from './GameComponent';
|
||||
|
||||
/**
|
||||
@@ -90,15 +88,13 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
|
||||
* 注意:如果子类需要覆盖此方法,必须调用 super.onLoad()
|
||||
*/
|
||||
onLoad() {
|
||||
// 提前返回,避免不必要的检查
|
||||
if (!this.mvvm) return;
|
||||
|
||||
// onBind 语义为"绑定初始化",与 data 是否存在解耦,始终调用
|
||||
this.onBind();
|
||||
|
||||
const data = this.data;
|
||||
if (data === undefined || data === null) {
|
||||
console.warn(`[CCView] ${this.constructor.name}: mvvm=true 但 data 未定义,VM 绑定已跳过`);
|
||||
console.warn('[OopsFramework]', `${this.constructor.name}: mvvm=true 但 data 未定义,VM 绑定已跳过`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -110,7 +106,6 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
|
||||
* @private
|
||||
*/
|
||||
private initializeVM() {
|
||||
// 使用正则替换所有的点,避免 VM.add 内部校验失败
|
||||
const uuid = this.node.uuid.replace(/\./g, '');
|
||||
this.tag = `_temp<${uuid}>`;
|
||||
VM.add(this.data!, this.tag);
|
||||
@@ -161,35 +156,30 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
|
||||
private getVMComponents(): VMBase[] {
|
||||
const result: VMBase[] = [];
|
||||
const myUuid = this.uuid;
|
||||
|
||||
// 深度优先遍历,遇到嵌套的 MVVM CCView 时剪枝
|
||||
|
||||
const traverse = (node: any) => {
|
||||
// 检查当前节点的组件
|
||||
const vmComps = node.getComponents(VMBase);
|
||||
const vmLen = vmComps.length;
|
||||
for (let i = 0; i < vmLen; i++) {
|
||||
result.push(vmComps[i]);
|
||||
}
|
||||
|
||||
// 检查是否有嵌套的 MVVM CCView(排除自己)
|
||||
|
||||
const ccViews = node.getComponents(CCView);
|
||||
const ccLen = ccViews.length;
|
||||
for (let i = 0; i < ccLen; i++) {
|
||||
const view = ccViews[i];
|
||||
if (view.uuid !== myUuid && view.mvvm) {
|
||||
// 遇到嵌套的 MVVM CCView,剪枝,不再遍历其子节点
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 递归遍历子节点
|
||||
|
||||
const children = node.children;
|
||||
const childLen = children.length;
|
||||
for (let i = 0; i < childLen; i++) {
|
||||
traverse(children[i]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
traverse(this.node);
|
||||
return result;
|
||||
}
|
||||
@@ -199,24 +189,24 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
|
||||
remove() {
|
||||
const ent = this.ent;
|
||||
if (!ent) {
|
||||
console.error(`组件 ${this.name} 移除失败,实体不存在`);
|
||||
console.error('[OopsFramework]', `组件 ${this.name} 移除失败,实体不存在`);
|
||||
return;
|
||||
}
|
||||
|
||||
const tid = this.tid;
|
||||
if (tid < 0) {
|
||||
console.error(`组件 ${this.name} 移除失败,组件未注册 (tid=${tid})`);
|
||||
console.error('[OopsFramework]', `组件 ${this.name} 移除失败,组件未注册 (tid=${tid})`);
|
||||
return;
|
||||
}
|
||||
|
||||
const cct = ECSModel.compCtors[tid];
|
||||
if (!cct) {
|
||||
console.error(`组件 ${this.name} 移除失败,组件构造函数不存在 (tid=${tid})`);
|
||||
console.error('[OopsFramework]', `组件 ${this.name} 移除失败,组件构造函数不存在 (tid=${tid})`);
|
||||
return;
|
||||
}
|
||||
|
||||
ent.removeUi(cct as unknown as UICtor);
|
||||
this.ent = null!; // 清空引用,避免内存泄漏
|
||||
ent.removeUi(cct as unknown as OopsFramework.UICtor);
|
||||
this.ent = null!;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,11 +214,9 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
|
||||
* 注意:如果子类需要覆盖此方法,必须调用 super.onDestroy()
|
||||
*/
|
||||
protected onDestroy() {
|
||||
// 只有启用了 MVVM 时才执行清理
|
||||
if (this.mvvm) {
|
||||
this.onUnBind();
|
||||
|
||||
// 解除全部引用
|
||||
const tag = this.tag;
|
||||
if (tag) {
|
||||
VM.remove(tag);
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2022-03-29 17:08:08
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-09-02 09:45:41
|
||||
*/
|
||||
import type { ICollisionEvent, ITriggerEvent } from 'cc';
|
||||
import { _decorator, ccenum, Collider, Component } from 'cc';
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/** 碰撞物体类型 */
|
||||
export enum CollisionType {
|
||||
/** 角色类 */
|
||||
Role,
|
||||
/** 飞弹类体*/
|
||||
Ballistic,
|
||||
/** 墙体类 */
|
||||
Wall
|
||||
}
|
||||
ccenum(CollisionType);
|
||||
|
||||
const Event_TriggerEnter = 'onTriggerEnter';
|
||||
const Event_TriggerStay = 'onTriggerStay';
|
||||
const Event_TriggerExit = 'onTriggerExit';
|
||||
const Event_CollisionEnter = 'onCollisionEnter';
|
||||
const Event_CollisionStay = 'onCollisionStay';
|
||||
const Event_CollisionExit = 'onCollisionExit';
|
||||
|
||||
/** 碰撞器与触发器 */
|
||||
@ccclass('GameCollision')
|
||||
export class GameCollision extends Component {
|
||||
protected collider: Collider = null!;
|
||||
|
||||
@property({ type: CollisionType, tooltip: '碰撞物体类型' })
|
||||
type: CollisionType = CollisionType.Ballistic;
|
||||
|
||||
onLoad() {
|
||||
this.collider = this.getComponent(Collider)!;
|
||||
if (this.collider.isTrigger) {
|
||||
this.collider.on(Event_TriggerEnter, this.onTrigger, this);
|
||||
this.collider.on(Event_TriggerStay, this.onTrigger, this);
|
||||
this.collider.on(Event_TriggerExit, this.onTrigger, this);
|
||||
}
|
||||
else {
|
||||
this.collider.on(Event_CollisionEnter, this.onCollision, this);
|
||||
this.collider.on(Event_CollisionStay, this.onCollision, this);
|
||||
this.collider.on(Event_CollisionExit, this.onCollision, this);
|
||||
}
|
||||
}
|
||||
|
||||
private onTrigger(event: ITriggerEvent) {
|
||||
switch (event.type) {
|
||||
case Event_TriggerEnter:
|
||||
this.onTriggerEnter(event);
|
||||
break;
|
||||
case Event_TriggerStay:
|
||||
this.onTriggerStay(event);
|
||||
break;
|
||||
case Event_TriggerExit:
|
||||
this.onTriggerExit(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected onTriggerEnter(event: ITriggerEvent) { }
|
||||
protected onTriggerStay(event: ITriggerEvent) { }
|
||||
protected onTriggerExit(event: ITriggerEvent) { }
|
||||
|
||||
private onCollision(event: ICollisionEvent) {
|
||||
switch (event.type) {
|
||||
case Event_CollisionEnter:
|
||||
this.onCollisionEnter(event);
|
||||
break;
|
||||
case Event_CollisionStay:
|
||||
this.onCollisionStay(event);
|
||||
break;
|
||||
case Event_CollisionExit:
|
||||
this.onCollisionExit(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected onCollisionEnter(event: ICollisionEvent) { }
|
||||
protected onCollisionStay(event: ICollisionEvent) { }
|
||||
protected onCollisionExit(event: ICollisionEvent) { }
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "7fa3eab3-0e4a-4152-af0e-50daf4e55261",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
Reference in New Issue
Block a user