Skip to content

Commit e8f41bc

Browse files
authored
Merge pull request #376 from Jameskmonger/actor-typed-metadaata
refactor: create strongly typed `metadata` property on `Actor` and `Player`
2 parents 2f30be1 + cdce42d commit e8f41bc

18 files changed

+245
-61
lines changed

src/engine/action/pipe/button.action.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,6 @@ const buttonActionPipe = (player: Player, widgetId: number, buttonId: number): R
6161
matchingHooks = questActions;
6262
}
6363

64-
if(player.metadata.buttonListener) {
65-
if(widgetId === player.metadata.buttonListener.widgetId) {
66-
player.metadata.buttonListener.event.next(buttonId);
67-
}
68-
}
69-
7064
if(matchingHooks.length === 0) {
7165
player.outgoingPackets.chatboxMessage(`Unhandled button interaction: ${widgetId}:${buttonId}`);
7266
return null;

src/engine/config/shop-config.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ export class Shop {
9797
}
9898

9999
public open(player: Player): void {
100-
player.metadata['lastOpenedShop'] = this;
101-
player.metadata['shopCloseListener'] = player.interfaceState.closed.subscribe((whatClosed: WidgetClosedEvent) => {
100+
player.metadata.lastOpenedShop = this;
101+
player.metadata.shopCloseListener = player.interfaceState.closed.subscribe((whatClosed: WidgetClosedEvent) => {
102102
if(whatClosed && whatClosed.widget && whatClosed.widget.widgetId === widgets.shop.widgetId) {
103103
this.removePlayerFromShop(player);
104104
}
@@ -121,7 +121,7 @@ export class Shop {
121121

122122
private updateCustomers() {
123123
for (const player of this.customers) {
124-
if(player.metadata['lastOpenedShop'] === this) {
124+
if(player.metadata.lastOpenedShop === this) {
125125
player.outgoingPackets.sendUpdateAllWidgetItems(widgets.shop, this.container);
126126
} else {
127127
this.removePlayerFromShop(player);
@@ -130,9 +130,9 @@ export class Shop {
130130
}
131131

132132
private removePlayerFromShop(player: Player) {
133-
if(player.metadata['lastOpenedShop'] === this) {
134-
player.metadata['lastOpenedShop'] = undefined;
135-
player.metadata['shopCloseListener'].unsubscribe();
133+
if(player.metadata.lastOpenedShop === this) {
134+
player.metadata.lastOpenedShop = undefined;
135+
player.metadata.shopCloseListener.unsubscribe();
136136
}
137137
this.customers = this.customers.filter((c) => c !== player);
138138
}

src/engine/net/inbound-packets/item-on-object.packet.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ const itemOnObjectPacket = (player: Player, packet: PacketData) => {
4747
let morphIndex = -1;
4848
if(objectConfig.varbitId === -1) {
4949
if(objectConfig.configId !== -1) {
50-
const configValue = player.metadata['configs'] && player.metadata['configs'][objectConfig.configId] ? player.metadata['configs'][objectConfig.configId] : 0;
50+
const configValue = player.metadata.configs && player.metadata.configs[objectConfig.configId] ? player.metadata.configs[objectConfig.configId] : 0;
5151
morphIndex = configValue;
5252

5353
}
5454
} else {
55-
morphIndex = getVarbitMorphIndex(objectConfig.varbitId, player.metadata['configs']);
55+
morphIndex = getVarbitMorphIndex(objectConfig.varbitId, player.metadata.configs);
5656
}
5757
if(morphIndex !== -1) {
5858
objectConfig = filestore.configStore.objectStore.getObject(objectConfig.configChangeDest[morphIndex]);

src/engine/net/inbound-packets/object-interaction.packet.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,11 @@ const objectInteractionPacket = (player: Player, packet: PacketData) => {
8585
let morphIndex = -1;
8686
if(objectConfig.varbitId === -1) {
8787
if(objectConfig.configId !== -1) {
88-
morphIndex = player.metadata['configs'] && player.metadata['configs'][objectConfig.configId] ?
89-
player.metadata['configs'][objectConfig.configId] : 0;
88+
morphIndex = player.metadata.configs && player.metadata.configs[objectConfig.configId] ?
89+
player.metadata.configs[objectConfig.configId] : 0;
9090
}
9191
} else {
92-
morphIndex = getVarbitMorphIndex(objectConfig.varbitId, player.metadata['configs']);
92+
morphIndex = getVarbitMorphIndex(objectConfig.varbitId, player.metadata.configs);
9393
}
9494
if(morphIndex !== -1) {
9595
objectConfig = filestore.configStore.objectStore.getObject(objectConfig.configChangeDest[morphIndex]);

src/engine/net/outbound-packet-handler.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export class OutboundPacketHandler {
7171

7272
public sendProjectile(position: Position, offsetX: number, offsetY: number, id: number, startHeight: number, endHeight: number, speed: number, lockon: number, delay: number) {
7373
this.updateReferencePosition(position);
74-
74+
7575
const packet = new Packet(1);
7676
packet.put(0);
7777
packet.put(offsetY, 'byte');
@@ -85,7 +85,8 @@ export class OutboundPacketHandler {
8585
packet.put(16);
8686
packet.put(64);
8787
this.queue(packet);
88-
}
88+
}
89+
8990
public updateFriendStatus(friendName: string, worldId: number): void {
9091
const packet = new Packet(156);
9192
packet.put(stringToLong(friendName.toLowerCase()), 'LONG');
@@ -278,8 +279,8 @@ export class OutboundPacketHandler {
278279
public updateClientConfig(configId: number, value: number): void {
279280
let packet: Packet;
280281
const metadata = this.player.metadata;
281-
if(!metadata['configs']) {
282-
metadata['configs'] = []
282+
if(!metadata.configs) {
283+
metadata.configs = []
283284
}
284285
metadata.configs[configId] = value;
285286

src/engine/world/actor/actor.ts

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Pathfinding } from './pathfinding';
1616
import { Attack, AttackDamageType } from './player/attack';
1717
import { Behavior } from './behaviors';
1818
import { Effect, EffectType } from './effect';
19+
import { ActorMetadata } from './metadata';
1920

2021

2122
export type ActorType = 'player' | 'npc';
@@ -33,7 +34,16 @@ export abstract class Actor {
3334
public readonly inventory: ItemContainer = new ItemContainer(28);
3435
public readonly bank: ItemContainer = new ItemContainer(376);
3536
public readonly actionPipeline = new ActionPipeline(this);
36-
public readonly metadata: { [key: string]: any } = {};
37+
38+
/**
39+
* The map of available metadata for this actor.
40+
*
41+
* You cannot guarantee that this will be populated with data, so you should always check for the existence of the
42+
* metadata you are looking for before using it.
43+
*
44+
* @author jameskmonger
45+
*/
46+
public readonly metadata: Partial<ActorMetadata> = {};
3747

3848
/**
3949
* @deprecated - use new action system instead
@@ -109,13 +119,13 @@ export abstract class Actor {
109119
// https://oldschool.runescape.wiki/w/Combat_level#:~:text=Calculating%20combat%20level,-Simply&text=Add%20your%20Strength%20and%20Attack,have%20your%20melee%20combat%20level.&text=Multiply%20this%20by%200.325%20and,have%20your%20magic%20combat%20level
110120
// https://oldschool.runescape.wiki/w/Damage_per_second/Melee#:~:text=1%20Step%20one%3A%20Calculate%20the%20effective%20strength%20level%3B,1.7%20Step%20seven%3A%20Calculate%20the%20melee%20damage%20output
111121
public getAttackRoll(defender): Attack {
112-
122+
113123
//the amount of damage is random from 0 to Max
114124
//stance modifiers
115125
const _stance_defense = 3;
116126
const _stance_accurate = 0;
117127
const _stance_controlled = 1;
118-
128+
119129
// base level
120130
// ToDo: calculate prayer effects
121131
// round decimal result calulcation up
@@ -131,7 +141,7 @@ export abstract class Actor {
131141
132142
Effective strength level
133143
Multiply by(Equipment Melee Strength + 64)
134-
Add 320
144+
Add 320
135145
Divide by 640
136146
Round down to nearest integer
137147
Multiply by gear bonus
@@ -211,7 +221,7 @@ export abstract class Actor {
211221
return attack;
212222
//+ stance modifier
213223
}
214-
// #endregion
224+
// #endregion
215225

216226
public damage(amount: number, damageType: DamageType = DamageType.DAMAGE) {
217227
const armorReduction = 0;
@@ -347,7 +357,7 @@ export abstract class Actor {
347357

348358
public follow(target: Actor): void {
349359
this.face(target, false, false, false);
350-
this.metadata['following'] = target;
360+
this.metadata.following = target;
351361

352362
this.moveBehind(target);
353363
const subscription = target.walkingQueue.movementEvent.subscribe(() => {
@@ -362,7 +372,7 @@ export abstract class Actor {
362372
).subscribe(() => {
363373
subscription.unsubscribe();
364374
this.face(null);
365-
delete this.metadata['following'];
375+
delete this.metadata.following;
366376
});
367377
}
368378

@@ -376,7 +386,7 @@ export abstract class Actor {
376386
if(distance <= 1) {
377387
return false;
378388
}
379-
389+
380390
if(distance > 16) {
381391
this.clearFaceActor();
382392
this.metadata.faceActorClearedByWalking = true;
@@ -398,7 +408,7 @@ export abstract class Actor {
398408
return;
399409
}
400410

401-
this.metadata['tailing'] = target;
411+
this.metadata.tailing = target;
402412

403413
this.moveTo(target);
404414
const subscription = target.walkingQueue.movementEvent.subscribe(async () => this.moveTo(target));
@@ -409,7 +419,7 @@ export abstract class Actor {
409419
).subscribe(() => {
410420
subscription.unsubscribe();
411421
this.face(null);
412-
delete this.metadata['tailing'];
422+
delete this.metadata.tailing;
413423
});
414424
}
415425

@@ -424,8 +434,8 @@ export abstract class Actor {
424434
this.updateFlags.facePosition = face;
425435
} else if(face instanceof Actor) {
426436
this.updateFlags.faceActor = face;
427-
this.metadata['faceActor'] = face;
428-
this.metadata['faceActorClearedByWalking'] = clearedByWalking;
437+
this.metadata.faceActor = face;
438+
this.metadata.faceActorClearedByWalking = clearedByWalking;
429439

430440
if(autoClear) {
431441
setTimeout(() => {
@@ -441,9 +451,9 @@ export abstract class Actor {
441451
}
442452

443453
public clearFaceActor(): void {
444-
if(this.metadata['faceActor']) {
454+
if(this.metadata.faceActor) {
445455
this.updateFlags.faceActor = null;
446-
this.metadata['faceActor'] = undefined;
456+
this.metadata.faceActor = undefined;
447457
}
448458
}
449459

src/engine/world/actor/metadata.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { ConstructedRegion } from '../map';
2+
import { Position } from '../position';
3+
import { Actor } from './actor';
4+
5+
/**
6+
* The definition of the metadata available on an {@link Actor}.
7+
*
8+
* You cannot guarantee that all of these properties will be present on an actor,
9+
* so you should always check for their existence before using them.
10+
*
11+
* @author jameskmonger
12+
*/
13+
export type ActorMetadata = {
14+
/**
15+
* The custom constructed map region for this actor.
16+
*
17+
* TODO (jameskmonger) Should this live on Actor rather than on {@link Player}? I don't think NPCs can have a custom map.
18+
*/
19+
customMap: ConstructedRegion;
20+
21+
/**
22+
* The player's current target position.
23+
*
24+
* Used within the action pipeline.
25+
*/
26+
walkingTo: Position;
27+
28+
/**
29+
* The actor currently being `tailed` by this actor.
30+
*
31+
* TODO (jameskmonger) we should delete this - only used by deleted code in the old combat plugin
32+
*/
33+
tailing: Actor;
34+
35+
/**
36+
* The actor currently being followed by this actor.
37+
*/
38+
following: Actor;
39+
40+
/**
41+
* The actor which the local actor is facing towards.
42+
*/
43+
faceActor: Actor;
44+
45+
/**
46+
* Whether a walk action has cleared the actor which the local actor is facing towards.
47+
*
48+
* TODO (jameskmonger) does this belong on this metadata?
49+
*/
50+
faceActorClearedByWalking: boolean;
51+
52+
/**
53+
* Set to true if the actor is currently teleporting.
54+
*/
55+
teleporting: boolean;
56+
};

0 commit comments

Comments
 (0)