Skip to content

Commit 59d739b

Browse files
author
src
authored
Merge branch 'develop' into development
2 parents f5f16e4 + 5cfeecc commit 59d739b

31 files changed

+810
-163
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ yarn-error.log*
2222
*.njsproj
2323
*.sln
2424
*.sw?
25+
/.vs

data/config/xteas/468.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[
2+
{
3+
"archive": 5,
4+
"group": 33,
5+
"name_hash": -1155051794,
6+
"name": "l29_79",
7+
"mapsquare": 7503,
8+
"key": [
9+
-205505693,
10+
-1069477933,
11+
-1042446848,
12+
-93348110
13+
]
14+
},
15+
{
16+
"archive": 5,
17+
"group": 35,
18+
"name_hash": -1154396392,
19+
"name": "l30_79",
20+
"mapsquare": 7759,
21+
"key": [
22+
-1255219039,
23+
-277284099,
24+
1886972034,
25+
-723091074
26+
]
27+
}
28+
]

src/game-engine/config/index.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,21 @@ import { Quest } from '@engine/world/actor/player/quest';
1919
import { ItemSpawn, loadItemSpawnConfigurations } from '@engine/config/item-spawn-config';
2020
import { loadSkillGuideConfigurations, SkillGuide } from '@engine/config/skill-guide-config';
2121
import { loadMusicRegionConfigurations, MusicTrack } from '@engine/config/music-regions-config';
22-
import { loadXteaRegionFiles, XteaRegion } from '@runejs/filestore';
22+
2323
import {
2424
loadStrongholdOfSecurityQuizData,
2525
StrongholdOfSecurityQuiz,
2626
StrongholdOfSecurityQuizQuestion
2727
} from '@engine/config/stronghold-of-security-quiz-config';
2828
import { BookData, loadStrongholdOfSecurityBookData } from '@engine/config/sectioned-book-config';
29+
import { LandscapeObject, loadXteaRegionFiles, ObjectConfig, XteaRegion } from '@runejs/filestore';
2930

3031
require('json5/lib/register');
3132

3233

3334
export let itemMap: { [key: string]: ItemDetails };
3435
export let itemIdMap: { [key: number]: string };
36+
export let objectMap: { [key: number]: ObjectConfig };
3537
export let itemPresetMap: ItemPresetConfiguration;
3638
export let npcMap: { [key: string]: NpcDetails };
3739
export let npcIdMap: { [key: number]: string };
@@ -75,6 +77,8 @@ export async function loadGameConfigurations(): Promise<void> {
7577
shopMap = await loadShopConfigurations('data/config/shops/');
7678
skillGuides = await loadSkillGuideConfigurations('data/config/skill-guides/');
7779
logger.info(`Loaded ${strongholdOfSecurityQuizData.questions.length} Stronghold of Security questions.`);
80+
81+
objectMap = {};
7882
logger.info(`Loaded ${musicRegions.length} music regions, ${Object.keys(itemMap).length} items, ${itemSpawns.length} item spawns, ` +
7983
`${Object.keys(npcMap).length} npcs, ${npcSpawns.length} npc spawns, ${Object.keys(shopMap).length} shops and ${skillGuides.length} skill guides.`);
8084
}
@@ -180,6 +184,21 @@ export const findNpc = (npcKey: number | string): NpcDetails | null => {
180184
};
181185

182186

187+
export const findObject = (objectId: number): ObjectConfig | null => {
188+
if(!objectMap[objectId]) {
189+
const object = filestore.objectStore.getObject(objectId);
190+
if(!object) {
191+
return null;
192+
}
193+
194+
objectMap[objectId] = object;
195+
return object;
196+
} else {
197+
return objectMap[objectId];
198+
}
199+
};
200+
201+
183202
export const findShop = (shopKey: string): Shop | null => {
184203
if (!shopKey) {
185204
return null;

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
}

src/game-engine/net/inbound-packets/object-interaction-packet.js

Lines changed: 0 additions & 98 deletions
This file was deleted.
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { logger } from '@runejs/core';
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 => {
20+
const { buffer } = packet;
21+
const objectId = buffer.get('short', 'u');
22+
const y = buffer.get('short', 'u');
23+
const x = buffer.get('short', 'u', 'le');
24+
return { objectId, x, y };
25+
};
26+
27+
const option2: objectInteractionPacket = packet => {
28+
const { buffer } = packet;
29+
const x = buffer.get('short', 'u', 'le');
30+
const y = buffer.get('short', 'u', 'le');
31+
const objectId = buffer.get('short', 'u', 'le');
32+
return { objectId, x, y };
33+
};
34+
35+
const option3: objectInteractionPacket = packet => {
36+
const { buffer } = packet;
37+
const y = buffer.get('short', 'u');
38+
const objectId = buffer.get('short', 'u');
39+
const x = buffer.get('short', 'u');
40+
return { objectId, x, y };
41+
};
42+
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+
};
67+
68+
69+
const objectInteractionPacket = (player: Player, packet: PacketData) => {
70+
const { packetId } = packet;
71+
72+
const { objectId, x, y } = objectInteractionPackets[packetId].packetDef(packet);
73+
const level = player.position.level;
74+
const objectPosition = new Position(x, y, level);
75+
const { object: landscapeObject, cacheOriginal } = world.findObjectAtLocation(player, objectId, objectPosition);
76+
if(!landscapeObject) {
77+
if(player.rights === Rights.ADMIN) {
78+
player.sendMessage(`Custom object ${objectId} @[${objectPosition.key}]`);
79+
}
80+
return;
81+
}
82+
83+
let objectConfig = filestore.configStore.objectStore.getObject(objectId);
84+
if (objectConfig.configChangeDest) {
85+
let morphIndex = -1;
86+
if(objectConfig.varbitId === -1) {
87+
if(objectConfig.configId !== -1) {
88+
morphIndex = player.metadata['configs'] && player.metadata['configs'][objectConfig.configId] ?
89+
player.metadata['configs'][objectConfig.configId] : 0;
90+
}
91+
} else {
92+
morphIndex = getVarbitMorphIndex(objectConfig.varbitId, player.metadata['configs']);
93+
}
94+
if(morphIndex !== -1) {
95+
objectConfig = filestore.configStore.objectStore.getObject(objectConfig.configChangeDest[morphIndex]);
96+
}
97+
}
98+
99+
const actionIdx = objectInteractionPackets[packetId].index;
100+
let optionName = `action-${actionIdx + 1}`;
101+
if(objectConfig.options && objectConfig.options.length >= actionIdx) {
102+
if(!objectConfig.options[actionIdx]) {
103+
// Invalid action
104+
logger.error(`1: Invalid object ${objectId} option ${actionIdx + 1}, options: ${JSON.stringify(objectConfig.options)}`);
105+
return;
106+
}
107+
108+
optionName = objectConfig.options[actionIdx];
109+
} else {
110+
// Invalid action
111+
logger.error(`2: Invalid object ${objectId} option ${actionIdx + 1}, options: ${JSON.stringify(objectConfig.options)}`);
112+
return;
113+
}
114+
115+
player.actionPipeline.call('object_interaction', player, landscapeObject, objectConfig, objectPosition, optionName.toLowerCase(), cacheOriginal);
116+
};
117+
118+
119+
export default Object.keys(objectInteractionPackets).map(opcode => ({
120+
opcode: parseInt(opcode, 10),
121+
size: 6,
122+
handler: objectInteractionPacket
123+
}));

src/game-engine/net/inbound-packets/widget-interaction-packet.js renamed to src/game-engine/net/inbound-packets/widget-interaction-packet.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
const widgetInteractionPacket = (player, packet) => {
1+
import { Player } from '@engine/world/actor/player/player';
2+
import { PacketData } from '@engine/net/inbound-packets';
3+
4+
5+
const widgetInteractionPacket = (player: Player, packet: PacketData) => {
26
const { buffer } = packet;
37
const childId = buffer.get('short');
48
const widgetId = buffer.get('short');

0 commit comments

Comments
 (0)