feat: LazyEntityUpdater
This commit is contained in:
@@ -1,8 +1,22 @@
|
|||||||
|
import type { ICityEntity } from "./CityEntity.js";
|
||||||
|
import { LazyEntityUpdater } from "./LazyEntityUpdater.js";
|
||||||
|
import type { IResourceController } from "./ResourceController.js";
|
||||||
import type { CityID } from "./defs.js";
|
import type { CityID } from "./defs.js";
|
||||||
|
|
||||||
export class City{
|
export class City extends LazyEntityUpdater<ICityEntity>{
|
||||||
|
protected readonly _indirectNames: (keyof ICityEntity)[] = ["id", "nationID"];
|
||||||
|
protected readonly _entityType = "City";
|
||||||
|
protected readonly _raw: ICityEntity;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly id: CityID
|
raw: ICityEntity,
|
||||||
|
protected readonly resourceController: IResourceController
|
||||||
){
|
){
|
||||||
|
super();
|
||||||
|
this._raw = raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
get id(): CityID {
|
||||||
|
return this._raw.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import type { CityID, CityName, NationID } from "./defs.js";
|
||||||
|
|
||||||
|
export interface ICityEntity{
|
||||||
|
id: CityID;
|
||||||
|
name: CityName;
|
||||||
|
nationID: NationID;
|
||||||
|
}
|
||||||
@@ -6,21 +6,22 @@ import { DiplomaticPermission, type CityID, type GeneralID, type GeneralName, ty
|
|||||||
import { must } from "@sammo/util";
|
import { must } from "@sammo/util";
|
||||||
import { Nation } from "./Nation.js";
|
import { Nation } from "./Nation.js";
|
||||||
import { Troop } from "./Troop.js";
|
import { Troop } from "./Troop.js";
|
||||||
|
import { LazyEntityUpdater } from "./LazyEntityUpdater.js";
|
||||||
|
|
||||||
export class General {
|
export class General extends LazyEntityUpdater<IGeneralEntity> {
|
||||||
private _raw: IGeneralEntity;
|
protected readonly _indirectNames: (keyof IGeneralEntity)[] = ["id", "nationID", "troopID", "nationID"];
|
||||||
private _city: WeakRef<City>;
|
protected readonly _entityType = "General";
|
||||||
private _troop: WeakRef<Troop> | undefined;
|
protected readonly _raw: IGeneralEntity;
|
||||||
private _nation: WeakRef<Nation>;
|
|
||||||
|
|
||||||
public get raw(): Readonly<IGeneralEntity> {
|
protected _city: WeakRef<City>;
|
||||||
return this._raw;
|
protected _troop: WeakRef<Troop> | undefined;
|
||||||
}
|
protected _nation: WeakRef<Nation>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
raw: IGeneralEntity,
|
raw: IGeneralEntity,
|
||||||
private resourceController: IResourceController
|
protected readonly resourceController: IResourceController
|
||||||
){
|
){
|
||||||
|
super();
|
||||||
this._raw = raw;
|
this._raw = raw;
|
||||||
this._city = new WeakRef(must(resourceController.getCity(raw.cityID)));
|
this._city = new WeakRef(must(resourceController.getCity(raw.cityID)));
|
||||||
this._nation = new WeakRef(must(resourceController.getNation(raw.nationID)));
|
this._nation = new WeakRef(must(resourceController.getNation(raw.nationID)));
|
||||||
@@ -38,26 +39,16 @@ export class General {
|
|||||||
return this._raw.name;
|
return this._raw.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(callback: (oldRaw: IGeneralEntity) => void, force = false) {
|
public get city(): City {
|
||||||
|
return must(this._city.deref());
|
||||||
|
}
|
||||||
|
|
||||||
const oldCityID = this._raw.cityID;
|
public get troop(): Troop | undefined {
|
||||||
const oldTroopID = this._raw.troopID;
|
return this._troop?.deref();
|
||||||
const oldNationID = this._raw.nationID;
|
}
|
||||||
|
|
||||||
callback(this._raw);
|
public get nation(): Nation {
|
||||||
|
return must(this._nation.deref());
|
||||||
if(!force){
|
|
||||||
if(oldCityID !== this._raw.cityID){
|
|
||||||
throw new Error("City change by update() is not allowed");
|
|
||||||
}
|
|
||||||
if(oldTroopID !== this._raw.troopID){
|
|
||||||
throw new Error("Troop change by update() is not allowed");
|
|
||||||
}
|
|
||||||
if(oldNationID !== this._raw.nationID){
|
|
||||||
throw new Error("Nation change by update() is not allowed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.resourceController.setDirtyGeneral(this._raw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public changeCity(city: CityID | City){
|
public changeCity(city: CityID | City){
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import type { IResourceController, ValidEntity, ValidEntityType } from "./ResourceController.js";
|
||||||
|
|
||||||
|
export abstract class LazyEntityUpdater<Entity extends ValidEntity>{
|
||||||
|
protected abstract readonly _indirectNames: (keyof Entity)[];
|
||||||
|
protected abstract readonly _entityType: ValidEntityType<Entity>;
|
||||||
|
|
||||||
|
protected abstract readonly _raw: Entity;
|
||||||
|
|
||||||
|
protected abstract readonly resourceController: IResourceController;
|
||||||
|
|
||||||
|
public get raw(): Readonly<Entity> {
|
||||||
|
return this._raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get entityType(): ValidEntityType<Entity> {
|
||||||
|
return this._entityType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(callback: (oldRaw: Entity) => void, force = false) {
|
||||||
|
const oldRaw = { ...this._raw };
|
||||||
|
callback(this._raw);
|
||||||
|
if (!force) {
|
||||||
|
for (const indirectName of this._indirectNames) {
|
||||||
|
if (oldRaw[indirectName] !== this._raw[indirectName]) {
|
||||||
|
throw new Error(`${String(indirectName)} change by update() is not allowed`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.resourceController.setDirty(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,26 @@
|
|||||||
import type { NationID, NationName, NationType } from "./defs.js";
|
import { LazyEntityUpdater } from "./LazyEntityUpdater.js";
|
||||||
|
import type { INationEntity } from "./NationEntity.js";
|
||||||
|
import type { IResourceController } from "./ResourceController.js";
|
||||||
|
import type { NationID, NationName } from "./defs.js";
|
||||||
|
|
||||||
|
export class Nation extends LazyEntityUpdater<INationEntity> {
|
||||||
|
protected readonly _indirectNames: (keyof INationEntity)[] = ["id"];
|
||||||
|
protected readonly _entityType = "Nation";
|
||||||
|
protected readonly _raw: INationEntity;
|
||||||
|
|
||||||
export class Nation {
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly id: NationID,
|
raw: INationEntity,
|
||||||
public readonly name: NationName,
|
protected readonly resourceController: IResourceController
|
||||||
public readonly type: NationType,
|
){
|
||||||
) { }
|
super();
|
||||||
|
this._raw = raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get id(): NationID {
|
||||||
|
return this._raw.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get name(): NationName {
|
||||||
|
return this._raw.name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import type { CityID, NationID, NationName, NationType } from "./defs.js";
|
||||||
|
|
||||||
|
export interface INationEntity{
|
||||||
|
id: NationID;
|
||||||
|
name: NationName;
|
||||||
|
type: NationType;
|
||||||
|
|
||||||
|
capitalID: CityID;
|
||||||
|
}
|
||||||
@@ -6,6 +6,19 @@ import type { GameEnv } from "./GameEnv.js";
|
|||||||
import type { IGeneralEntity } from "./GeneralEntity.js";
|
import type { IGeneralEntity } from "./GeneralEntity.js";
|
||||||
import type { Troop } from "./Troop.js";
|
import type { Troop } from "./Troop.js";
|
||||||
import type { ITroopEntity } from "./TroopEntity.js";
|
import type { ITroopEntity } from "./TroopEntity.js";
|
||||||
|
import type { LazyEntityUpdater } from "./LazyEntityUpdater.js";
|
||||||
|
import type { ICityEntity } from "./CityEntity.js";
|
||||||
|
import type { INationEntity } from "./NationEntity.js";
|
||||||
|
|
||||||
|
export type ValidEntityList = {
|
||||||
|
'General': IGeneralEntity;
|
||||||
|
'City': ICityEntity;
|
||||||
|
'Nation': INationEntity;
|
||||||
|
'Troop': ITroopEntity;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ValidEntity = ValidEntityList[keyof ValidEntityList];
|
||||||
|
export type ValidEntityType<Entity> = Entity extends ValidEntityList[infer T extends keyof ValidEntityList] ? T : never;
|
||||||
|
|
||||||
export interface IResourceController{
|
export interface IResourceController{
|
||||||
addCity(city: City): boolean;
|
addCity(city: City): boolean;
|
||||||
@@ -38,6 +51,8 @@ export interface IResourceController{
|
|||||||
setDirtyTroop(troop: Troop | TroopID): void;
|
setDirtyTroop(troop: Troop | TroopID): void;
|
||||||
setDirtyNation(nation: Nation): void;
|
setDirtyNation(nation: Nation): void;
|
||||||
|
|
||||||
|
setDirty(entity: LazyEntityUpdater<any>): void;
|
||||||
|
|
||||||
createGeneral(raw: IGeneralEntity): General;
|
createGeneral(raw: IGeneralEntity): General;
|
||||||
createTroop(raw: ITroopEntity): Troop;
|
createTroop(raw: ITroopEntity): Troop;
|
||||||
//createNation
|
//createNation
|
||||||
|
|||||||
@@ -3,20 +3,20 @@ import type { General } from "./General.js";
|
|||||||
import type { IResourceController } from "./ResourceController.js";
|
import type { IResourceController } from "./ResourceController.js";
|
||||||
import type { ITroopEntity } from "./TroopEntity.js";
|
import type { ITroopEntity } from "./TroopEntity.js";
|
||||||
import type { GeneralID } from "./defs.js";
|
import type { GeneralID } from "./defs.js";
|
||||||
|
import { LazyEntityUpdater } from "./LazyEntityUpdater.js";
|
||||||
|
|
||||||
export class Troop {
|
export class Troop extends LazyEntityUpdater<ITroopEntity> {
|
||||||
private _raw: ITroopEntity
|
protected readonly _indirectNames: (keyof ITroopEntity)[] = ["id"];
|
||||||
|
protected readonly _entityType = "Troop";
|
||||||
|
protected readonly _raw: ITroopEntity;
|
||||||
private _leader: WeakRef<General>;
|
private _leader: WeakRef<General>;
|
||||||
private _members: Map<GeneralID, WeakRef<General>>;
|
private _members: Map<GeneralID, WeakRef<General>>;
|
||||||
|
|
||||||
public get raw(): Readonly<ITroopEntity> {
|
|
||||||
return this._raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
raw: ITroopEntity,
|
raw: ITroopEntity,
|
||||||
private resourceController: IResourceController
|
protected resourceController: IResourceController
|
||||||
){
|
){
|
||||||
|
super();
|
||||||
this._raw = raw;
|
this._raw = raw;
|
||||||
|
|
||||||
const members = resourceController.findGeneralByTroop(raw.id);
|
const members = resourceController.findGeneralByTroop(raw.id);
|
||||||
|
|||||||
Reference in New Issue
Block a user