Skip to content

Commit

Permalink
feat(clientdb): add initial clientdb implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
fallenoak committed Jan 10, 2024
1 parent 7815b46 commit d005f26
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 0 deletions.
Binary file added fixture/clientdb/Light.dbc
Binary file not shown.
74 changes: 74 additions & 0 deletions src/lib/clientdb/ClientDb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { IoSource, openStream } from '@wowserhq/io';
import ClientDbRecord from './ClientDbRecord.js';
import * as dbIo from './io.js';

interface Constructor<T> {
new (...args: any[]): T;
}

class ClientDb<T extends ClientDbRecord> {
#RecordClass: Constructor<T>;

#minId = 0xfffffff;
#maxId = 0;

#recordCount = 0;

#records: T[];
#recordsById: Record<number, T>;

constructor(RecordClass: Constructor<T>) {
this.#RecordClass = RecordClass;
}

get records() {
return this.#records;
}

load(source: IoSource): ClientDb<T> {
const stream = openStream(source);

const header = dbIo.header.read(stream);

this.#recordCount = header.recordCount;

const records = new Array(this.#recordCount);
const recordsById = {};

for (let i = 0; i < this.#recordCount; i++) {
const record = new this.#RecordClass().load(stream);

this.#minId = record.id < this.#minId ? record.id : this.#minId;
this.#maxId = record.id > this.#maxId ? record.id : this.#maxId;

records[i] = record;
recordsById[record.id] = record;
}

this.#records = records;
this.#recordsById = recordsById;

stream.close();

return this;
}

getRecord(id: number): T {
if (id < this.#minId || id > this.#maxId) {
return null;
}

return this.#recordsById[id];
}

getRecordByIndex(index: number) {
if (index < 0 || index >= this.#recordCount) {
return null;
}

return this.#records[index];
}
}

export default ClientDb;
export { ClientDb };
25 changes: 25 additions & 0 deletions src/lib/clientdb/ClientDbRecord.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { IoSource, IoType, openStream } from '@wowserhq/io';

class ClientDbRecord {
id: number;

#recordIo: IoType;

constructor(recordIo: IoType) {
this.#recordIo = recordIo;
}

load(source: IoSource) {
const stream = openStream(source);

const record = this.#recordIo.read(stream);

for (const [key, value] of Object.entries(record)) {
this[key] = value;
}

return this;
}
}

export default ClientDbRecord;
12 changes: 12 additions & 0 deletions src/lib/clientdb/io.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as io from '@wowserhq/io';
import { IoType } from '@wowserhq/io';

const header: IoType = io.struct({
magic: io.string({ size: 4, terminate: false }),
recordCount: io.uint32le,
fieldCount: io.uint32le,
recordSize: io.uint32le,
stringBlockSize: io.uint32le,
});

export { header };
22 changes: 22 additions & 0 deletions src/lib/clientdb/record/LightFloatBandRecord.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as io from '@wowserhq/io';
import ClientDbRecord from '../ClientDbRecord.js';

const recordIo = io.struct({
id: io.int32le,
num: io.int32le,
time: io.array(io.int32le, { size: 16 }),
data: io.array(io.float32le, { size: 16 }),
});

class LightFloatBandRecord extends ClientDbRecord {
num: number;
time: number[];
data: number[];

constructor() {
super(recordIo);
}
}

export default LightFloatBandRecord;
export { LightFloatBandRecord };
22 changes: 22 additions & 0 deletions src/lib/clientdb/record/LightIntBandRecord.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as io from '@wowserhq/io';
import ClientDbRecord from '../ClientDbRecord.js';

const recordIo = io.struct({
id: io.int32le,
num: io.int32le,
time: io.array(io.int32le, { size: 16 }),
data: io.array(io.int32le, { size: 16 }),
});

class LightIntBandRecord extends ClientDbRecord {
num: number;
time: number[];
data: number[];

constructor() {
super(recordIo);
}
}

export default LightIntBandRecord;
export { LightIntBandRecord };
32 changes: 32 additions & 0 deletions src/lib/clientdb/record/LightParamsRecord.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as io from '@wowserhq/io';
import ClientDbRecord from '../ClientDbRecord.js';

const recordIo = io.struct({
id: io.int32le,
highlightSky: io.int32le,
lightSkyboxId: io.int32le,
glow: io.float32le,
waterShallowAlpha: io.float32le,
waterDeepAlpha: io.float32le,
oceanShallowAlpha: io.float32le,
oceanDeepAlpha: io.float32le,
flags: io.int32le,
});

class LightParamsRecord extends ClientDbRecord {
highlightSky: number;
lightSkyboxId: number;
glow: number;
waterShallowAlpha: number;
waterDeepAlpha: number;
oceanShallowAlpha: number;
oceanDeepAlpha: number;
flags: number;

constructor() {
super(recordIo);
}
}

export default LightParamsRecord;
export { LightParamsRecord };
26 changes: 26 additions & 0 deletions src/lib/clientdb/record/LightRecord.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as io from '@wowserhq/io';
import ClientDbRecord from '../ClientDbRecord.js';

const recordIo = io.struct({
id: io.int32le,
continentId: io.int32le,
gameCoords: io.array(io.float32le, { size: 3 }),
gameFalloffStart: io.float32le,
gameFalloffEnd: io.float32le,
lightParamsId: io.array(io.int32le, { size: 8 }),
});

class LightRecord extends ClientDbRecord {
continentId: number;
gameCoords: number[];
gameFalloffStart: number;
gameFalloffEnd: number;
lightParamsId: number[];

constructor() {
super(recordIo);
}
}

export default LightRecord;
export { LightRecord };
4 changes: 4 additions & 0 deletions src/lib/clientdb/records.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './record/LightRecord.js';
export * from './record/LightFloatBandRecord.js';
export * from './record/LightIntBandRecord.js';
export * from './record/LightParamsRecord.js';
3 changes: 3 additions & 0 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import Blp, { BlpImage, BLP_COLOR_FORMAT, BLP_IMAGE_FORMAT } from './blp/Blp.js';
export { Blp, BlpImage, BLP_COLOR_FORMAT, BLP_IMAGE_FORMAT };

export * from './clientdb/ClientDb.js';
export * from './clientdb/records.js';

export * from './map/Map.js';
export * from './map/MapArea.js';
export * from './map/MapChunk.js';
Expand Down
15 changes: 15 additions & 0 deletions src/spec/clientdb/ClientDb.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, expect, test } from 'vitest';
import ClientDb from '../../lib/clientdb/ClientDb.js';
import LightRecord from '../../lib/clientdb/record/LightRecord.js';

describe('ClientDb', () => {
describe('load', () => {
test('should load blp from valid file', () => {
const dbc = new ClientDb(LightRecord).load('./fixture/clientdb/Light.dbc');
const record = dbc.getRecordByIndex(1);

expect(record.id).toBe(2);
expect(record.lightParamsId).toEqual([14, 15, 494, 15, 4, 0, 0, 0]);
});
});
});

0 comments on commit d005f26

Please sign in to comment.