Skip to content

Commit

Permalink
feat(map): emit area:change events when appropriate
Browse files Browse the repository at this point in the history
  • Loading branch information
fallenoak committed Jan 14, 2024
1 parent d5008d9 commit 9dfffb2
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 8 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"three.js"
],
"dependencies": {
"@wowserhq/format": "^0.13.1"
"@wowserhq/format": "^0.15.0"
},
"peerDependencies": {
"three": "^0.160.0"
Expand Down
64 changes: 62 additions & 2 deletions src/lib/map/MapManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import * as THREE from 'three';
import { Map, MAP_CHUNK_HEIGHT, MAP_AREA_COUNT_Y } from '@wowserhq/format';
import {
AreaTableRecord,
ClientDb,
Map,
MAP_AREA_COUNT_Y,
MAP_CHUNK_COUNT_Y,
MAP_CHUNK_COUNT_X,
MAP_CHUNK_HEIGHT,
} from '@wowserhq/format';
import TerrainManager from './terrain/TerrainManager.js';
import TextureManager from '../texture/TextureManager.js';
import DoodadManager from './DoodadManager.js';
Expand All @@ -19,7 +27,7 @@ type MapManagerOptions = {
viewDistance?: number;
};

class MapManager {
class MapManager extends EventTarget {
#mapName: string;
#mapDir: string;
#map: MapSpec;
Expand All @@ -39,11 +47,15 @@ class MapManager {

#mapLight: MapLight;

#areaTableDb: ClientDb<AreaTableRecord>;

#target = new THREE.Vector2();
#targetAreaX: number;
#targetAreaY: number;
#targetChunkX: number;
#targetChunkY: number;
#targetArea: MapAreaSpec;
#targetAreaTableId: number;

#viewDistance = DEFAULT_VIEW_DISTANCE;
#detailDistance = this.#viewDistance;
Expand All @@ -54,6 +66,8 @@ class MapManager {
#desiredAreas = new Set<number>();

constructor(options: MapManagerOptions) {
super();

if (options.viewDistance) {
this.#viewDistance = options.viewDistance;
this.#detailDistance = this.#viewDistance;
Expand Down Expand Up @@ -105,6 +119,7 @@ class MapManager {

this.#root.name = `map:${mapName}`;

this.#loadDbs().catch((error) => console.error(error));
this.#loadMap().catch((error) => console.error(error));
this.#syncAreas().catch((error) => console.error(error));

Expand All @@ -118,16 +133,35 @@ class MapManager {
const previousAreaY = this.#targetAreaY;
const previousChunkX = this.#targetChunkX;
const previousChunkY = this.#targetChunkY;
const previousAreaTableId = this.#targetAreaTableId;

const { areaX, areaY, chunkX, chunkY } = Map.getIndicesFromPosition(x, y);
this.#targetAreaX = areaX;
this.#targetAreaY = areaY;
this.#targetChunkX = chunkX;
this.#targetChunkY = chunkY;

const targetArea = this.#loadedAreas.get(this.#getAreaId(areaX, areaY));
if (targetArea) {
this.#targetArea = targetArea;

const localChunkX = chunkX % MAP_CHUNK_COUNT_X;
const localChunkY = chunkY % MAP_CHUNK_COUNT_Y;
const localChunkIndex = localChunkX * MAP_CHUNK_COUNT_Y + localChunkY;
const targetAreaTableId = targetArea.areaTableIds[localChunkIndex];

if (targetAreaTableId) {
this.#targetAreaTableId = targetAreaTableId;
}
}

if (previousChunkX !== chunkX || previousChunkY !== chunkY) {
this.#calculateDesiredAreas();
}

if (previousAreaTableId !== this.#targetAreaTableId) {
this.#handleAreaTableIdChange();
}
}

update(deltaTime: number, camera: THREE.Camera) {
Expand Down Expand Up @@ -164,6 +198,28 @@ class MapManager {
}
}

#handleAreaTableIdChange() {
if (!this.#areaTableDb || !this.#targetAreaTableId) {
return;
}

const areaTableRecord = this.#areaTableDb.getRecord(this.#targetAreaTableId);
if (!areaTableRecord) {
return;
}

const parentAreaTableRecord = this.#areaTableDb.getRecord(areaTableRecord.parentAreaId);

const detail = {
areaName: areaTableRecord.areaName[0],
areaId: areaTableRecord.id,
parentAreaName: parentAreaTableRecord?.areaName[0],
parentAreaId: parentAreaTableRecord?.id,
};

this.dispatchEvent(new CustomEvent('area:change', { detail }));
}

async #syncAreas() {
if (!this.#map) {
requestAnimationFrame(() => this.#syncAreas().catch((error) => console.error(error)));
Expand Down Expand Up @@ -284,6 +340,10 @@ class MapManager {
this.#desiredAreas = desiredAreas;
}

async #loadDbs() {
this.#areaTableDb = await this.#dbManager.get('AreaTable.dbc', AreaTableRecord);
}

async #loadMap() {
const mapPath = `${this.#mapDir}/${this.#mapName}.wdt`;
this.#map = await this.#loader.loadMapSpec(mapPath);
Expand Down
10 changes: 9 additions & 1 deletion src/lib/map/loader/MapLoaderWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,15 @@ class MapLoaderWorker extends SceneWorker {

const buffers = new Set<ArrayBuffer>();

const areaTableIds = new Uint32Array(area.chunks.length);
buffers.add(areaTableIds.buffer);

const terrainSpecs: TerrainSpec[] = [];
for (const chunk of area.chunks) {
for (let i = 0; i < area.chunks.length; i++) {
const chunk = area.chunks[i];

areaTableIds[i] = chunk.areaId;

if (chunk.layers.length === 0) {
continue;
}
Expand All @@ -70,6 +77,7 @@ class MapLoaderWorker extends SceneWorker {

const spec: MapAreaSpec = {
terrain: terrainSpecs,
areaTableIds,
doodadDefs: area.doodadDefs.map((def) => ({
id: def.id,
name: def.name,
Expand Down
1 change: 1 addition & 0 deletions src/lib/map/loader/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type TerrainSpec = {

type MapAreaSpec = {
terrain: TerrainSpec[];
areaTableIds: Uint32Array;
doodadDefs: MapDoodadDefSpec[];
};

Expand Down

0 comments on commit 9dfffb2

Please sign in to comment.