Skip to content

Commit 1dc347b

Browse files
committed
feat: Reconnect logic, move to UIDs, new info logic
1 parent eb08605 commit 1dc347b

File tree

17 files changed

+645
-347
lines changed

17 files changed

+645
-347
lines changed

.vscode/launch.json

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
{
2-
// Use IntelliSense to learn about possible attributes.
3-
// Hover to view descriptions of existing attributes.
4-
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
52
"version": "0.2.0",
63
"configurations": [
74
{
@@ -33,7 +30,14 @@
3330
"skipFiles": [
3431
"<node_internals>/**"
3532
],
36-
"console": "internalConsole",
33+
"console": "internalConsole"
34+
},
35+
{
36+
"type": "node-terminal",
37+
"name": "Start Server",
38+
"request": "launch",
39+
"command": "node --no-warnings --loader ts-node/esm src/lostcity/app.ts",
40+
"cwd": "${workspaceFolder}"
3741
}
3842
]
3943
}
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,35 @@
1-
[debugproc,forcemove_walk]
1+
[debugproc,walk_1]
22
p_walk(movecoord(coord, 0, 0, 1));
33

4-
[debugproc,forcemove_walk5]
5-
p_walk(movecoord(coord, 0, 0, 5));
4+
[debugproc,walk_2]
5+
p_walk(movecoord(coord, 0, 0, 2));
66

7-
[debugproc,forcemove_run]
8-
p_walk(movecoord(coord, 0, 0, 1));
9-
p_walk(movecoord(coord, 0, 0, 1));
7+
[debugproc,walk_3]
8+
p_walk(movecoord(coord, 0, 0, 3));
109

11-
[debugproc,forcemove_tele]
12-
p_walk(movecoord(coord, 0, 0, 1));
13-
p_walk(movecoord(coord, 0, 0, 1));
14-
p_walk(movecoord(coord, 0, 0, 1));
10+
// ----
11+
12+
[debugproc,telejump_1]
13+
p_telejump(movecoord(coord, 0, 0, 1));
14+
15+
[debugproc,telejump_2]
16+
p_telejump(movecoord(coord, 0, 0, 2));
17+
18+
[debugproc,telejump_3]
19+
p_telejump(movecoord(coord, 0, 0, 3));
20+
21+
// ----
22+
23+
[debugproc,teleport_1]
24+
p_teleport(movecoord(coord, 0, 0, 1));
25+
26+
[debugproc,teleport_2]
27+
p_teleport(movecoord(coord, 0, 0, 2));
28+
29+
[debugproc,teleport_3]
30+
p_teleport(movecoord(coord, 0, 0, 3));
31+
32+
// ----
1533

1634
[debugproc,exactmove]
17-
p_exactmove(coord, movecoord(coord, 0, 0, 5), 30, 64, ^exact_south);
35+
p_exactmove(coord, movecoord(coord, 0, 0, 3), 0, 100, ^exact_north);

src/jagex2/io/Packet.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,10 @@ export default class Packet {
154154
this.p4(Number(value & 0xFFFFFFFFn));
155155
}
156156

157-
pjstr(str: string) {
157+
pjstr(str: string | null) {
158+
if (str === null) {
159+
str = 'null';
160+
}
158161
this.ensure(str.length + 1);
159162
for (let i = 0; i < str.length; i++) {
160163
this.data[this.pos++] = str.charCodeAt(i);
@@ -289,7 +292,7 @@ export default class Packet {
289292

290293
gjstr(): string {
291294
let str = '';
292-
while (this.data[this.pos] != 10) {
295+
while (this.data[this.pos] != 10 && this.pos < this.data.length) {
293296
str += String.fromCharCode(this.data[this.pos++]);
294297
}
295298
this.pos++;
@@ -328,11 +331,13 @@ export default class Packet {
328331
// ----
329332

330333
bits() {
331-
this.bitPos = this.pos << 3;
334+
this.bitPos = this.pos * 8;
335+
// this.bitPos = this.pos << 3;
332336
}
333337

334338
bytes() {
335-
this.pos = (this.bitPos + 7) >>> 3;
339+
this.pos = ((this.bitPos + 7) / 8) >>> 0;
340+
// this.pos = (this.bitPos + 7) >>> 3;
336341
}
337342

338343
gBit(n: number) {

src/lostcity/engine/Login.ts

+27-10
Original file line numberDiff line numberDiff line change
@@ -74,30 +74,47 @@ class Login {
7474
return;
7575
}
7676

77-
if (World.getPlayerByUsername(username)) {
77+
let player = World.getPlayerByUsername(username);
78+
if ((opcode === 16 && player) || (opcode === 18 && !player && process.env.LOCAL_DEV !== 'true')) {
7879
socket.send(Uint8Array.from([5]));
7980
socket.close();
8081
return;
8182
}
8283

83-
const player = Player.load(username);
84-
player.client = socket;
85-
player.lowMemory = (info & 0x1) === 1;
86-
player.webClient = socket.isWebSocket();
84+
if (opcode === 18 && player && player.client !== null) {
85+
socket.send(Uint8Array.from([5]));
86+
socket.close();
87+
return;
88+
}
89+
90+
socket.state = 1;
8791
socket.decryptor = new Isaac(seed);
8892
for (let i = 0; i < 4; i++) {
8993
seed[i] += 50;
9094
}
9195
socket.encryptor = new Isaac(seed);
9296

93-
World.addPlayer(player, socket);
97+
if (!player) {
98+
player = Player.load(username);
99+
World.addPlayer(player, socket);
94100

95-
socket.state = 1;
96-
if (opcode === 18) {
97-
socket.send(Uint8Array.from([15]));
98-
} else {
99101
socket.send(Uint8Array.from([2]));
102+
} else {
103+
player.logoutRequested = false;
104+
player.netOut = []; // clear old packets
105+
player.playerIds = []; // clear old observed players
106+
player.npcIds = []; // clear old observed npcs
107+
player.loadedX = -1; // reload area
108+
player.loadedZ = -1;
109+
player.tele = true;
110+
player.jump = true;
111+
112+
socket.send(Uint8Array.from([15]));
100113
}
114+
115+
player.client = socket;
116+
player.lowMemory = (info & 0x1) === 1;
117+
player.webClient = socket.isWebSocket();
101118
} else {
102119
socket.close();
103120
}

src/lostcity/engine/World.ts

+48-50
Original file line numberDiff line numberDiff line change
@@ -255,13 +255,13 @@ class World {
255255
// client input
256256
// - decode packets
257257
for (let i = 0; i < this.playerIds.length; i++) {
258+
// iterate on playerIds so pid order matters
258259
if (this.playerIds[i] === -1) {
259260
continue;
260261
}
261262

262263
const player = this.players[this.playerIds[i]];
263264
if (!player) {
264-
this.playerIds[i] = -1;
265265
continue;
266266
}
267267

@@ -322,13 +322,13 @@ class World {
322322
// - player/npc interactions
323323
// - close interface if attempting to logout
324324
for (let i = 0; i < this.playerIds.length; i++) {
325+
// iterate on playerIds so pid order matters
325326
if (this.playerIds[i] === -1) {
326327
continue;
327328
}
328329

329330
const player = this.players[this.playerIds[i]];
330331
if (!player) {
331-
this.playerIds[i] = -1;
332332
continue;
333333
}
334334

@@ -377,10 +377,12 @@ class World {
377377

378378
if (this.shutdownTick < this.currentTick) {
379379
if (this.currentTick - player.lastResponse >= 25) {
380+
// request logout after 15 seconds (this may be 16 ticks in osrs!)
380381
player.logoutRequested = true;
381382
}
382383

383-
if (this.currentTick - player.lastResponse >= 100) {
384+
if (process.env.LOCAL_DEV === 'true' && this.currentTick - player.lastResponse >= 100) {
385+
// remove after 60 seconds
384386
player.queue = [];
385387
player.weakQueue = [];
386388
player.engineQueue = [];
@@ -484,6 +486,8 @@ class World {
484486
this.futureUpdates.delete(this.currentTick);
485487
}
486488

489+
this.computeSharedEvents();
490+
487491
// client output
488492
// - map update
489493
// - player info
@@ -492,43 +496,9 @@ class World {
492496
// - inv changes
493497
// - stat changes
494498
// - flush packets
495-
this.computeSharedEvents();
496-
497-
/// we're doing a pass to convert p_tele to walk/run if needed, todo refactor
498-
for (let i = 0; i < this.playerIds.length; i++) {
499-
if (this.playerIds[i] === -1) {
500-
continue;
501-
}
502-
503-
const player = this.players[this.playerIds[i]];
504-
if (!player) {
505-
this.playerIds[i] = -1;
506-
continue;
507-
}
508-
509-
try {
510-
if (player.tele && !player.jump && Math.abs(player.x - player.lastX) < 2 && Math.abs(player.z - player.lastZ) < 2) {
511-
// convert teleport to a walk/run op
512-
player.walkDir = Position.face(player.lastX, player.lastZ, player.x, player.z);
513-
player.runDir = -1; // TODO support run <= 2 tiles
514-
player.tele = false;
515-
}
516-
} catch (err) {
517-
console.error(err);
518-
player.logout();
519-
this.removePlayer(player);
520-
}
521-
}
522-
523-
// client output
524-
for (let i = 0; i < this.playerIds.length; i++) {
525-
if (this.playerIds[i] === -1) {
526-
continue;
527-
}
528-
529-
const player = this.players[this.playerIds[i]];
499+
for (let i = 0; i < this.players.length; i++) {
500+
const player = this.players[i];
530501
if (!player) {
531-
this.playerIds[i] = -1;
532502
continue;
533503
}
534504

@@ -552,14 +522,9 @@ class World {
552522
}
553523

554524
// reset entity masks
555-
for (let i = 0; i < this.playerIds.length; i++) {
556-
if (this.playerIds[i] === -1) {
557-
continue;
558-
}
559-
560-
const player = this.players[this.playerIds[i]];
525+
for (let i = 0; i < this.players.length; i++) {
526+
const player = this.players[i];
561527
if (!player) {
562-
this.playerIds[i] = -1;
563528
continue;
564529
}
565530

@@ -594,7 +559,7 @@ class World {
594559
}
595560

596561
const end = Date.now();
597-
// console.log(`tick ${this.currentTick} took ${end - start}ms`);
562+
// console.log(`tick ${this.currentTick} took ${end - start}ms: ${this.getTotalPlayers()} players`);
598563

599564
this.currentTick++;
600565

@@ -944,7 +909,7 @@ class World {
944909
stream.pos += length;
945910

946911
socket.inCount[opcode]++;
947-
if (socket.inCount[opcode] > 10) {
912+
if (socket.inCount[opcode] > 5) {
948913
continue;
949914
}
950915

@@ -975,6 +940,7 @@ class World {
975940
this.players[index] = player;
976941
this.playerIds[pid] = index;
977942
player.pid = pid;
943+
player.uid = ((Number(player.username37 & 0x1FFFFFn) << 11) | player.pid) >>> 0;
978944

979945
this.getZone(player.x, player.z, player.level).addPlayer(player);
980946

@@ -1010,7 +976,27 @@ class World {
1010976

1011977
const player = this.players[slot];
1012978
if (!player) {
1013-
this.playerIds[pid] = -1;
979+
return null;
980+
}
981+
982+
return player;
983+
}
984+
985+
getPlayerByUid(uid: number) {
986+
const pid = uid & 0x7FF;
987+
const name37 = (uid >> 11) & 0x1FFFFF;
988+
989+
const slot = this.playerIds[pid];
990+
if (slot === -1) {
991+
return null;
992+
}
993+
994+
const player = this.players[slot];
995+
if (!player) {
996+
return null;
997+
}
998+
999+
if (Number(player.username37 & 0x1FFFFFn) !== name37) {
10141000
return null;
10151001
}
10161002

@@ -1023,13 +1009,25 @@ class World {
10231009
}
10241010

10251011
getTotalPlayers() {
1026-
return this.players.length;
1012+
return this.players.filter(p => p).length;
10271013
}
10281014

10291015
getNpc(nid: number) {
10301016
return this.npcs[nid];
10311017
}
10321018

1019+
getNpcByUid(uid: number) {
1020+
const slot = uid & 0xFFFF;
1021+
const type = (uid >> 16) & 0xFFFF;
1022+
1023+
const npc = this.npcs[slot];
1024+
if (!npc || npc.type !== type) {
1025+
return null;
1026+
}
1027+
1028+
return npc;
1029+
}
1030+
10331031
getNextNid() {
10341032
return this.npcs.indexOf(null, 1);
10351033
}

src/lostcity/engine/script/ScriptRunner.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import path from 'path';
22

33
import Script from '#lostcity/engine/script/Script.js';
4+
import ScriptOpcode from '#lostcity/engine/script/ScriptOpcode.js';
45
import ScriptPointer from '#lostcity/engine/script/ScriptPointer.js';
56
import ScriptState from '#lostcity/engine/script/ScriptState.js';
67

@@ -185,6 +186,7 @@ export default class ScriptRunner {
185186

186187
static executeInner(state: ScriptState, opcode: number) {
187188
const handler = ScriptRunner.HANDLERS[opcode];
189+
// console.log('Executing', ScriptOpcode[opcode]);
188190
if (!handler) {
189191
throw new Error(`Unknown opcode ${opcode}`);
190192
}

0 commit comments

Comments
 (0)