Skip to content

Commit

Permalink
DexTypes: CoW init for TypeInfo
Browse files Browse the repository at this point in the history
When possible, DexTypes will re-use objects from the parent.
To achieve this, inheritance is integrated with construction.
dataCache.Typechart reflects the data from the file.
Because dataCache.Typechart no longer has the same information, it is
deleted after DexTypes is constructed.
In short, it became a temporary intermediate representation.
This lowers the long-term memory usage.
  • Loading branch information
larry-the-table-guy committed Oct 5, 2024
1 parent a790ed0 commit 419ac34
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 8 deletions.
58 changes: 54 additions & 4 deletions sim/dex-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
*/
import {Utils} from '../lib';

/** Unfortunately we do for..in too much to want to deal with the casts */
export interface DexTable<T> {[id: string]: T}

/**
* Converts anything to an ID. An ID must have only lowercase alphanumeric
* characters.
Expand Down Expand Up @@ -210,6 +213,7 @@ export interface TypeData {
HPivs?: SparseStatsTable;
isNonstandard?: Nonstandard | null;
}
const TYPE_DATA_KEYS: readonly (keyof TypeData)[] = Object.freeze(['damageTaken', 'HPivs', 'HPdvs', 'isNonstandard']);

export type ModdedTypeData = TypeData | Partial<Omit<TypeData, 'name'>> & {inherit: true};
export interface TypeDataTable {[typeid: IDEntry]: TypeData}
Expand Down Expand Up @@ -285,15 +289,61 @@ export class DexTypes {
allCache: readonly TypeInfo[];
namesCache: readonly string[];

constructor(dex: ModdedDex) {
constructor(dex: ModdedDex, patches: ModdedTypeDataTable, parent?: DexTypes) {
this.dex = dex;

let patchesEmpty = true;
for (const k in patches) { // eslint-disable-line @typescript-eslint/no-unused-vars
patchesEmpty = false;
break;
}
if (parent && patchesEmpty) {
this.allCache = parent.allCache;
this.namesCache = parent.namesCache;
this.typeCache = parent.typeCache;
return;
}
const allCache = [];
const namesCache = [];
for (const _id in this.dex.data.TypeChart) {
if (parent) {
for (const parentType of parent.all()) {
const id = parentType.id;
const patchEntry = patches[id];
// null means don't inherit
if (patchEntry === null) {
delete patches[id];
continue;
}
let type;
// if patchEntry present, construct
// else re-use parent's object
if (patchEntry) {
// if inherit, copy fields from parent into child
if ('inherit' in patchEntry && patchEntry.inherit === true) {
delete (patchEntry as any).inherit;
for (const field of TYPE_DATA_KEYS) {
if (field in patchEntry) continue;
// nonsense to appease tsc.
(patchEntry as any)[field] = parentType[field];
}
// patchEntry is now a complete TypeData
}
type = new TypeInfo({name: parentType.name, id, ...patchEntry});
type = dex.deepFreeze(type);
delete patches[id];
} else {
type = parentType;
}
this.typeCache.set(id, type);
allCache.push(type);
if (!type.isNonstandard) namesCache.push(type.name);
}
}
for (const _id in patches) {
const id = _id as ID;
const typeName = id.charAt(0).toUpperCase() + id.substr(1);
const type = new TypeInfo({name: typeName, id, ...this.dex.data.TypeChart[id]});
this.typeCache.set(id, this.dex.deepFreeze(type));
const type = new TypeInfo({name: typeName, id, ...patches[id]});
this.typeCache.set(id, dex.deepFreeze(type));
allCache.push(type);
if (!type.isNonstandard) namesCache.push(type.name);
}
Expand Down
11 changes: 7 additions & 4 deletions sim/dex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import * as fs from 'fs';
import * as path from 'path';

import * as Data from './dex-data';
import {DexTable} from './dex-data';
export {DexTable} from './dex-data';
import {Condition, DexConditions} from './dex-conditions';
import {DataMove, DexMoves} from './dex-moves';
import {Item, DexItems} from './dex-items';
Expand Down Expand Up @@ -78,8 +80,6 @@ const DATA_FILES = {
TypeChart: 'typechart',
};

/** Unfortunately we do for..in too much to want to deal with the casts */
export interface DexTable<T> {[id: string]: T}
export interface AliasesTable {[id: IDEntry]: string}

interface DexTableData {
Expand All @@ -95,7 +95,7 @@ interface DexTableData {
PokemonGoData: DexTable<import('./dex-species').PokemonGoData>;
Scripts: DexTable<AnyObject>;
Conditions: DexTable<import('./dex-conditions').ConditionData>;
TypeChart: DexTable<import('./dex-data').TypeData>;
TypeChart: import('./dex-data').ModdedTypeDataTable;
}
interface TextTableData {
Abilities: DexTable<AbilityText>;
Expand Down Expand Up @@ -185,6 +185,7 @@ export class ModdedDex {
if (parentDex) {
dataCache['Aliases'] = parentDex.data['Aliases'];
for (const dataType of DATA_TYPES) {
if (dataType === 'TypeChart') continue; // ported to CoW
const parentTypedData: DexTable<any> = parentDex.data[dataType];
const childTypedData: DexTable<any> = dataCache[dataType] || (dataCache[dataType] = {});
for (const entryId in parentTypedData) {
Expand Down Expand Up @@ -225,7 +226,8 @@ export class ModdedDex {
this.species = new DexSpecies(this);
this.conditions = new DexConditions(this);
this.natures = new Data.DexNatures(this);
this.types = new Data.DexTypes(this);
this.types = new Data.DexTypes(this, dataCache.TypeChart, parentDex?.types);
delete dataCache.TypeChart;
this.stats = new Data.DexStats(this);
}

Expand Down Expand Up @@ -258,6 +260,7 @@ export class ModdedDex {
}

modData(dataType: DataType, id: string) {
if (dataType === 'TypeChart') throw new Error("todo: modify modData");
if (this.isBase) return this.data[dataType][id];
if (this.data[dataType][id] !== this.mod(this.parentMod).data[dataType][id]) return this.data[dataType][id];
return (this.data[dataType][id] = Utils.deepClone(this.data[dataType][id]));
Expand Down

0 comments on commit 419ac34

Please sign in to comment.