import { isEqual } from 'lodash-es'; import { SaveCompression } from '../common'; import { ISpecial, SpecialCreation } from './types'; // TODO: 颜色参数 export interface ICommonSpecialConfig { /** 获取特殊属性的名称 */ getSpecialName: (special: ISpecial) => string; /** 获取特殊属性的描述 */ getDescription: (special: ISpecial) => string; /** 从旧样板怪物对象获取此特殊属性对应的属性值 */ fromLegacyEnemy: (enemy: Enemy) => T; } export class CommonSerializableSpecial implements ISpecial { constructor( readonly code: number, public value: T, readonly config: ICommonSpecialConfig ) {} setValue(value: T): void { this.value = value; } getValue(): T { return this.value; } getSpecialName(): string { return this.config.getSpecialName(this); } getDescription(): string { return this.config.getDescription(this); } fromLegacyEnemy(enemy: Enemy): void { this.value = this.config.fromLegacyEnemy(enemy); } clone(): ISpecial { return new CommonSerializableSpecial( this.code, structuredClone(this.value), this.config ); } saveState(_compression: SaveCompression): T { return structuredClone(this.value); } loadState(state: T, _compression: SaveCompression): void { this.setValue(state); } deepEqualsTo(other: ISpecial): boolean { if (this.code !== other.code) return false; return isEqual(this.value, other.getValue()); } } export class NonePropertySpecial implements ISpecial { value: void = undefined; constructor( readonly code: number, readonly config: ICommonSpecialConfig ) {} setValue(_value: void): void { // unneeded } getValue(): void { return void 0; } getSpecialName(): string { return this.config.getSpecialName(this); } getDescription(): string { return this.config.getDescription(this); } fromLegacyEnemy(_enemy: Enemy): void { // unneeded } clone(): ISpecial { return new NonePropertySpecial(this.code, this.config); } saveState(_compression: SaveCompression): void { return undefined; } loadState(_state: void, _compression: SaveCompression): void { // 无属性,无需操作 } deepEqualsTo(other: ISpecial): boolean { return this.code === other.code; } } export function defineCommonSerializableSpecial( code: number, value: T, config: ICommonSpecialConfig ): SpecialCreation { return () => new CommonSerializableSpecial(code, structuredClone(value), config); } export function defineNonePropertySpecial( code: number, config: ICommonSpecialConfig ): SpecialCreation { return () => new NonePropertySpecial(code, config); }