Skip to content

Commit c23939b

Browse files
committed
Implementing object option 4&5 packets +fixing custom map object actions
1 parent b2c1b43 commit c23939b

File tree

6 files changed

+150
-40
lines changed

6 files changed

+150
-40
lines changed

src/game-engine/net/inbound-packets.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,19 @@ export async function loadPackets(): Promise<Map<number, InboundPacket>> {
3939
export function handlePacket(player: Player, packetId: number, packetSize: number, buffer: ByteBuffer): boolean {
4040
const incomingPacket = incomingPackets.get(packetId);
4141

42-
if (!incomingPacket) {
42+
if(!incomingPacket) {
4343
logger.info(`Unknown packet ${packetId} with size ${packetSize} received.`);
4444
return false;
4545
}
4646

4747
new Promise<void>(resolve => {
48-
incomingPacket.handler(player, { packetId, packetSize, buffer });
48+
try {
49+
incomingPacket.handler(player, { packetId, packetSize, buffer });
50+
} catch(error) {
51+
logger.error(`Error handling inbound packet ${packetId} with size ${packetSize}`);
52+
logger.error(error);
53+
}
4954
resolve();
50-
}).catch(error => logger.error(`Error handling inbound packet ${packetId} with size ${packetSize}: ${error}`));
55+
});
5156
return true;
5257
}
Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,82 @@
1-
import { Position } from '../../world/position';
2-
import { filestore, world } from '../../game-server';
31
import { logger } from '@runejs/core';
4-
import { getVarbitMorphIndex } from "../../util/varbits";
5-
const option1 = packet => {
2+
3+
import { filestore, world } from '@engine/game-server';
4+
import { Position } from '@engine/world/position';
5+
import { getVarbitMorphIndex } from '@engine/util/varbits';
6+
import { PacketData } from '@engine/net/inbound-packets';
7+
import { Player, Rights } from '@engine/world/actor/player/player';
8+
9+
10+
interface ObjectInteractionData {
11+
objectId: number;
12+
x: number;
13+
y: number;
14+
}
15+
16+
type objectInteractionPacket = (packet: PacketData) => ObjectInteractionData;
17+
18+
19+
const option1: objectInteractionPacket = packet => {
620
const { buffer } = packet;
721
const objectId = buffer.get('short', 'u');
822
const y = buffer.get('short', 'u');
923
const x = buffer.get('short', 'u', 'le');
1024
return { objectId, x, y };
1125
};
1226

13-
const option2 = packet => {
27+
const option2: objectInteractionPacket = packet => {
1428
const { buffer } = packet;
1529
const x = buffer.get('short', 'u', 'le');
1630
const y = buffer.get('short', 'u', 'le');
1731
const objectId = buffer.get('short', 'u', 'le');
1832
return { objectId, x, y };
1933
};
2034

21-
const option3 = packet => {
35+
const option3: objectInteractionPacket = packet => {
2236
const { buffer } = packet;
2337
const y = buffer.get('short', 'u');
2438
const objectId = buffer.get('short', 'u');
2539
const x = buffer.get('short', 'u');
2640
return { objectId, x, y };
2741
};
2842

43+
const option4: objectInteractionPacket = packet => {
44+
const { buffer } = packet;
45+
const x = buffer.get('short', 'u', 'le');
46+
const objectId = buffer.get('short', 'u', 'le');
47+
const y = buffer.get('short', 'u', 'le');
48+
return { objectId, x, y };
49+
};
50+
51+
const option5: objectInteractionPacket = packet => {
52+
const { buffer } = packet;
53+
const objectId = buffer.get('short', 'u');
54+
const y = buffer.get('short', 'u', 'le');
55+
const x = buffer.get('short', 'u', 'le');
56+
return { objectId, x, y };
57+
};
58+
59+
60+
const objectInteractionPackets: { [key: number]: { packetDef: objectInteractionPacket, index: number } } = {
61+
30: { packetDef: option1, index: 0 },
62+
164: { packetDef: option2, index: 1 },
63+
183: { packetDef: option3, index: 2 },
64+
229: { packetDef: option4, index: 3 },
65+
62: { packetDef: option5, index: 4 },
66+
};
2967

3068

31-
const objectInteractionPacket = (player, packet) => {
69+
const objectInteractionPacket = (player: Player, packet: PacketData) => {
3270
const { packetId } = packet;
3371

34-
const options = {
35-
30: { packetDef: option1, index: 0 },
36-
164: { packetDef: option2, index: 1 },
37-
183: { packetDef: option3, index: 2 },
38-
/*136: { packetDef: option4, index: 3 },
39-
55: { packetDef: option5, index: 4 },*/
40-
};
41-
42-
const { objectId, x, y } = options[packetId].packetDef(packet);
72+
const { objectId, x, y } = objectInteractionPackets[packetId].packetDef(packet);
4373
const level = player.position.level;
4474
const objectPosition = new Position(x, y, level);
4575
let { object: landscapeObject, cacheOriginal } = world.findObjectAtLocation(player, objectId, objectPosition);
4676
if(!landscapeObject) {
77+
if(player.rights === Rights.ADMIN) {
78+
player.sendMessage(`Custom object ${objectId} @[${objectPosition.key}]`);
79+
}
4780
return;
4881
}
4982

@@ -52,9 +85,8 @@ const objectInteractionPacket = (player, packet) => {
5285
let morphIndex = -1;
5386
if(objectConfig.varbitId === -1) {
5487
if(objectConfig.configId !== -1) {
55-
const configValue = player.metadata['configs'] && player.metadata['configs'][objectConfig.configId] ? player.metadata['configs'][objectConfig.configId] : 0;
56-
morphIndex = configValue;
57-
88+
morphIndex = player.metadata['configs'] && player.metadata['configs'][objectConfig.configId] ?
89+
player.metadata['configs'][objectConfig.configId] : 0;
5890
}
5991
} else {
6092
morphIndex = getVarbitMorphIndex(objectConfig.varbitId, player.metadata['configs']);
@@ -64,7 +96,7 @@ const objectInteractionPacket = (player, packet) => {
6496
}
6597
}
6698

67-
const actionIdx = options[packetId].index;
99+
const actionIdx = objectInteractionPackets[packetId].index;
68100
let optionName = `action-${actionIdx + 1}`;
69101
if(objectConfig.options && objectConfig.options.length >= actionIdx) {
70102
if(!objectConfig.options[actionIdx]) {
@@ -83,16 +115,9 @@ const objectInteractionPacket = (player, packet) => {
83115
player.actionPipeline.call('object_interaction', player, landscapeObject, objectConfig, objectPosition, optionName.toLowerCase(), cacheOriginal);
84116
};
85117

86-
export default [{
87-
opcode: 30,
88-
size: 6,
89-
handler: objectInteractionPacket
90-
}, {
91-
opcode: 164,
92-
size: 6,
93-
handler: objectInteractionPacket
94-
}, {
95-
opcode: 183,
118+
119+
export default Object.keys(objectInteractionPackets).map(opcode => ({
120+
opcode: parseInt(opcode, 10),
96121
size: 6,
97122
handler: objectInteractionPacket
98-
}];
123+
}));

src/game-engine/net/outbound-packets.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -586,14 +586,14 @@ export class OutboundPackets {
586586
const offsetX = playerChunk.position.x - (topCornerMapChunk.position.x - 2);
587587
const offsetY = playerChunk.position.y - (topCornerMapChunk.position.y - 2);
588588

589-
const centerOffsetX = offsetX - 6; // 6 === center
590-
const centerOffsetY = offsetY - 6; // 6 === center
589+
mapData.centerOffsetX = offsetX - 6; // 6 === center
590+
mapData.centerOffsetY = offsetY - 6; // 6 === center
591591

592592
for(let level = 0; level < 4; level++) {
593593
for(let x = 0; x < 13; x++) {
594594
for(let y = 0; y < 13; y++) {
595-
let mapTileOffsetX = x + centerOffsetX;
596-
let mapTileOffsetY = y + centerOffsetY;
595+
let mapTileOffsetX = x + mapData.centerOffsetX;
596+
let mapTileOffsetY = y + mapData.centerOffsetY;
597597
if(mapTileOffsetX < 0) {
598598
mapTileOffsetX = 0;
599599
}

src/game-engine/world/action/item-on-npc.action.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { Position } from '@engine/world/position';
33
import { ActionHook, getActionHooks } from '@engine/world/action/hooks';
44
import { Item } from '@engine/world/items/item';
55
import { Npc } from '@engine/world/actor/npc/npc';
6-
import { playerWalkTo } from '@engine/game-server';
76
import { advancedNumberHookFilter, questHookFilter, stringHookFilter } from '@engine/world/action/hooks/hook-filters';
87
import { ActionPipe, RunnableHooks } from '@engine/world/action/index';
98

src/game-engine/world/index.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Quadtree from 'quadtree-lib';
33
import { Player } from './actor/player/player';
44
import { ChunkManager } from './map/chunk-manager';
55
import { ExamineCache } from './config/examine-data';
6-
import { loadPlugins } from '@engine/game-server';
6+
import { loadPlugins, world } from '@engine/game-server';
77
import { Position } from './position';
88
import { Npc } from './actor/npc/npc';
99
import TravelLocations from '@engine/world/config/travel-locations';
@@ -19,6 +19,8 @@ import { loadActionFiles } from '@engine/world/action';
1919
import { LandscapeObject } from '@runejs/filestore';
2020
import { lastValueFrom, Subject } from 'rxjs';
2121
import { take } from 'rxjs/operators';
22+
import { ConstructedMap, getRotatedObjectX, getRotatedObjectY } from '@engine/world/map/region';
23+
import { Chunk } from '@engine/world/map/chunk';
2224

2325

2426
export interface QuadtreeKey {
@@ -81,7 +83,18 @@ export class World {
8183
objectPosition: Position): { object: LandscapeObject, cacheOriginal: boolean } {
8284
const x = objectPosition.x;
8385
const y = objectPosition.y;
86+
8487
const objectChunk = this.chunkManager.getChunkForWorldPosition(objectPosition);
88+
89+
if(actor instanceof Player && actor.metadata.customMap) {
90+
const templateMapObject = this.findCustomMapObject(actor, objectId, objectPosition);
91+
if(templateMapObject) {
92+
return { object: templateMapObject, cacheOriginal: true };
93+
}
94+
95+
return null;
96+
}
97+
8598
let cacheOriginal = true;
8699

87100
let tileModifications;
@@ -129,6 +142,43 @@ export class World {
129142
};
130143
}
131144

145+
/**
146+
* Locates a map template object from the actor's active custom map (if applicable).
147+
* @param actor The actor to find the object for.
148+
* @param objectId The ID of the object to find.
149+
* @param objectPosition The position of the copied object to find the template of.
150+
*/
151+
public findCustomMapObject(actor: Actor, objectId: number, objectPosition: Position): LandscapeObject | null {
152+
const objectChunk = this.chunkManager.getChunkForWorldPosition(objectPosition);
153+
const map = actor.metadata.customMap as ConstructedMap;
154+
const mapChunk = world.chunkManager.getChunkForWorldPosition(map.position);
155+
156+
const chunkIndexX = objectChunk.position.x - (mapChunk.position.x - 2);
157+
const chunkIndexY = objectChunk.position.y - (mapChunk.position.y - 2);
158+
159+
const centerOffsetX = map.centerOffsetX || 0;
160+
const centerOffsetY = map.centerOffsetY || 0;
161+
162+
const objectTile = map.tileData[actor.position.level][chunkIndexX + centerOffsetX][chunkIndexY + centerOffsetY];
163+
164+
const tileX = objectTile >> 14 & 0x3ff;
165+
const tileY = objectTile >> 3 & 0x7ff;
166+
const tileOrientation = (0x6 & objectTile) >> 1;
167+
168+
const objectLocalX = objectPosition.x - (objectChunk.position.x + 6) * 8;
169+
const objectLocalY = objectPosition.y - (objectChunk.position.y + 6) * 8;
170+
171+
const mapTemplateWorldX = tileX * 8;
172+
const mapTemplateWorldY = tileY * 8;
173+
const mapTemplateChunk = world.chunkManager.getChunkForWorldPosition(new Position(mapTemplateWorldX, mapTemplateWorldY, objectPosition.level));
174+
175+
const templateObjectPosition = new Position(mapTemplateWorldX + getRotatedObjectX(tileOrientation, objectLocalX, objectLocalY),
176+
mapTemplateWorldY + getRotatedObjectY(tileOrientation, objectLocalX, objectLocalY), objectPosition.level);
177+
const realObject = mapTemplateChunk.getFilestoreLandscapeObject(objectId, templateObjectPosition);
178+
179+
return realObject || null;
180+
}
181+
132182
/**
133183
* Saves player data for every active player within the game world.
134184
*/

src/game-engine/world/map/region.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,35 @@ export interface ConstructedMap {
2727
position: Position;
2828
emptySpace?: number;
2929
tileData: number[][][];
30+
centerOffsetX?: number;
31+
centerOffsetY?: number;
3032
}
33+
34+
35+
export const getRotatedObjectX = (orientation: number, localX: number, localY: number): number => {
36+
orientation &= 0x3;
37+
if(orientation === 0) {
38+
return localX;
39+
}
40+
if(orientation === 1) {
41+
return localY;
42+
}
43+
if(orientation === 2) {
44+
return -localX + 7;
45+
}
46+
return 7 + -localY;
47+
};
48+
49+
export const getRotatedObjectY = (orientation: number, localX: number, localY: number): number => {
50+
orientation &= 0x3;
51+
if(orientation === 0) {
52+
return localY;
53+
}
54+
if(orientation === 1) {
55+
return 7 + -localX;
56+
}
57+
if(orientation === 2) {
58+
return -localY + 7;
59+
}
60+
return localX;
61+
};

0 commit comments

Comments
 (0)