[开发者心得] 模块管理-数据

[复制链接]
811 |1
alphaAE 发表于 2023-7-13 11:03:54 | 显示全部楼层 |阅读模式
本帖最后由 alphaAE 于 2023-7-13 11:15 编辑

1. 概述
    编辑器的数据存储是一个json文件,被所有地方共用,对于模块开发不太方便,操作数据也比较危险,所以引入了数据中心。
数据中心可以对数据进行统一的管理,包括对模块之间的数据分离、读取数据、修改数据,存储数据,以及前后端的数据自动同步。这样每个模块只需要关心自己的数据,感觉不到json文件的存在,也不会对其他数据造成误操作。

    结构图


2. DataCenterS(客户端数据中心)
    服务端的数据中心,运行在服务端,其中管理着所有玩家的各个模块数据
成员方法
    1. getData<T extends Subdata>(player: Gameplay.Player | number, SubdataType: Type.TypeName<T>): T;
        功能:获取一个玩家的某个模块数据
        参数: player 玩家
        参数: SubdataType 模块数据类
        返回: 模块数据对象
    2. getReadyPlayerIds(): Array<number>;
        功能:获取在线且数据就绪的所有玩家ID
        返回:玩家id数组

3. DataCenterC(客户端数据中心)
    客户端的数据中心,运行在客户端,其中管理着本玩家的各个模块数据,DataCenterC在游戏初始化的时候会自动从服务器拉取当前玩家的数据。
成员方法
    1. getData<T extends Subdata>(SubdataType: Type.TypeName<T>): T;
        功能:获取当前玩家的一个数据
        参数: 模块数据类
        返回: 模块数据对象
    2. ready(): Promise<void>;
        功能:判断数据是否就绪
        返回: true-就绪 false-未就绪

4. Subdata
  装饰器
    1. Decorator.SaveProperty()
          功能:让一个全局变量成为存储数据,模块数据中打了这个标记的变量将被存储
  成员属性
    1. get version(): number;
          功能:数据版本号,数据有变化需要重写,和currentVersion配合使用,可实现数据升级
    2. get currentVersion(): number;
          功能:当前数据版本号,和version配合使用,可实现数据升级
    3. set currentVersion(value: number);
          功能:当前数据版本号,和version配合使用,可实现数据升级
  成员方法
1. initDefaultData(): void;
          功能:初始化默认数据
    2. onDataInit(): void;
          功能:数据就绪后调用(可复写这个方法,根据version和targetVersion比较,进行数据升级)
    3. getSavedProperty<T>(propertyName: string): T;
          功能:通过属性名获取存储的属性值(用作数据升级,读取之前已经存储的数据)
    4. save(syncToClient: boolean): this
          功能:保存数据
    5. syncToClient(): this;
          功能:向客户端同步数据
  事件
  • onDataChange: Type.Action;
          功能:数据变化的委托

5. 模块中关于数据的API
  ModuleC
      get data(): ModuleData
          功能:当前玩家的本模块数据(注册模块时,填写的数据类的对象)
  ModuleS
      get currentData(): S
          功能:获取当前请求玩家的本模块数据控制


  • 使用示例
  • 一个模块数据
//角色模块数据

export class RoleModuleData extends Subdata {

    @Decorator.saveProperty

    public lv: number;

    @Decorator.saveProperty

    public score: number;

    @Decorator.saveProperty

    public gold: number;

    @Decorator.saveProperty

    public kill: number;

    //初始化默认数据

    protected override initDefaultData(): void {

        this.lv = 1;

        this.score = 0;

        this.gold = 0;

        this.kill = 0;

    }

}


  • 数据在模块中的应用


@Core.Class

export default class GameStart extends Core.Script {

    protected onStart() {

        // 初始化模块

        this.onRegisterModule();

    }

    protected onRegisterModule(): void {

        ModuleManager.getInstance().registerModule(RoleModuleS, RoleModuleC, RoleModuleData);

    }

}

export class RoleModuleC extends ModuleC<RoleModuleS, RoleModuleData> {

    onStart() {

        console.log(`进入游戏 playerLv = ${this.data.lv}`);

        InputUtil.onKeyDown(Keys.Q, async () => {

            await this.server.net_DataTest_lvUp();

            console.log(`升级 playerLv = ${this.data.lv}`);

        })

    }

}

export class RoleModuleS extends ModuleS<RoleModuleC, RoleModuleData> {

    /** 升级 */

    net_DataTest_lvUp(): boolean {

        this.currentData.lv += 1;

        this.currentData.save(true);

        return true;

    }

}



  • 数据升级


export class RoleModuleData extends Subdata {

    @Decorator.saveProperty

    public lv: number;

    @Decorator.saveProperty

    public score: number;

    @Decorator.saveProperty

    public gold: number;

    @Decorator.saveProperty

    public kill: number;

    /** 初始化默认数据 */

    protected override initDefaultData(): void {

        this.lv = 1;

        this.score = 0;

        this.gold = 0;

        this.kill = 0;

    }

    /** 数据初始化,在这里判断数据版本号,如果和当前版本号不同则修改数据,然后设置新的版本号  */

    protected override onDataInit(): void {

        while (this.version != this.currentVersion) {

            switch (this.currentVersion) {

                case 1:

                    // 设置当前版本

                    this.currentVersion = 2;

                    // 赋值新的数据

                    this.gold = 0;

                    break;

                case 2:

                    // 设置当前版本

                    this.currentVersion = 3;

                    // 赋值新的数据

                    this.kill = 0;

                    break;

                default:

                    console.log("未处理的数据版本~");

            }

        }

    }

    /** 当前最新的版本号(默认是1,升级数据需要重写) */

    protected override get version() {

        return 3;

    }

}


  • 事件的应用

export class RoleModuleData extends Subdata {

    public onLvChange: Action1<number> = new Action1();

    @Decorator.saveProperty

    public lv: number;

    @Decorator.saveProperty

    public score: number;

    /** 初始化默认数据 */

    protected override initDefaultData(): void {

        this.lv = 1;

        this.score = 0;

    }

}

export class RoleModuleC extends ModuleC<RoleModuleS, RoleModuleData> {

    onStart() {

        this.data.onDataChange.add(() => {

            console.log("数据发生了变化");

        });

        this.data.onLvChange.add((lv: number) => {

            console.log("等级变化 lv=" + lv);

        });

        InputUtil.onKeyDown(Keys.Q, async () => {

            await this.server.net_DataTest_lvUp();

            console.log(`升级 playerLv = ${this.data.lv}`);

        })

    }

}

export class RoleModuleS extends ModuleS<RoleModuleC, RoleModuleData> {

    /** 升级 */

    net_DataTest_lvUp(): boolean {

        this.currentData.lv += 1;

        this.currentData.save(true);

        this.currentData.onLvChange.call(this.currentData.lv);

        return true;

    }

}

/** 其他模块 */

export class OtherModuleC extends ModuleC<..., ...> {

    onStart(): void {

        DataCenterC.getInstance().getData(RoleModuleData).onLvChange.add((lv: number) => {

            //等级变化

        });

    }

}













回复

使用道具 举报

大当家 发表于 2023-7-13 13:52:54 | 显示全部楼层
假如我想每个模块的数据分别存在一个存档文件中呢?
回复

使用道具 举报

热门版块
快速回复 返回顶部 返回列表