yolkbot 0.1.0-alpha.5 → 0.1.0-alpha.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/browser.js +6 -6
- package/package.json +27 -8
- package/src/api.js +97 -23
- package/src/bot/GamePlayer.js +3 -3
- package/src/bot.js +778 -404
- package/src/constants/index.js +23 -1
- package/src/constants/items.js +372 -173
- package/src/constants/maps.js +51 -12
- package/src/dispatches/BootPlayerDispatch.js +1 -1
- package/src/dispatches/ChatDispatch.js +1 -1
- package/src/dispatches/GameOptionsDispatch.js +1 -1
- package/src/dispatches/GoToAmmoDispatch.js +44 -0
- package/src/dispatches/GoToCoopDispatch.js +44 -0
- package/src/dispatches/GoToGrenadeDispatch.js +44 -0
- package/src/dispatches/GoToPlayerDispatch.js +5 -1
- package/src/dispatches/GoToSpatulaDispatch.js +5 -1
- package/src/dispatches/MeleeDispatch.js +1 -1
- package/src/dispatches/PauseDispatch.js +1 -1
- package/src/dispatches/ReloadDispatch.js +1 -1
- package/src/dispatches/ReportPlayerDispatch.js +1 -1
- package/src/dispatches/SaveLoadoutDispatch.js +11 -34
- package/src/dispatches/SpawnDispatch.js +1 -1
- package/src/dispatches/SwapWeaponDispatch.js +1 -1
- package/src/dispatches/SwitchTeamDispatch.js +1 -1
- package/src/dispatches/ThrowGrenadeDispatch.js +1 -1
- package/src/dispatches/index.js +14 -2
- package/src/matchmaker.js +11 -2
- package/src/pathing/mapnode.js +33 -4
- package/src/socket.js +1 -1
- package/src/types/api.d.ts +2 -16
- package/src/types/bot/GamePlayer.d.ts +87 -0
- package/src/types/bot.d.ts +118 -35
- package/src/types/constants/guns.d.ts +240 -0
- package/src/types/constants/index.d.ts +100 -0
- package/src/types/constants/items.d.ts +21 -0
- package/src/types/constants/maps.d.ts +15 -0
- package/src/types/dispatches/BootPlayerDispatch.d.ts +12 -0
- package/src/types/dispatches/ChatDispatch.d.ts +10 -0
- package/src/types/dispatches/FireDispatch.d.ts +10 -0
- package/src/types/dispatches/GameOptionsDispatch.d.ts +8 -0
- package/src/types/dispatches/GoToAmmoDispatch.d.ts +8 -0
- package/src/types/dispatches/GoToCoopDispatch.d.ts +8 -0
- package/src/types/dispatches/GoToGrenadeDispatch.d.ts +8 -0
- package/src/types/dispatches/GoToPlayerDispatch.d.ts +11 -0
- package/src/types/dispatches/GoToSpatulaDispatch.d.ts +8 -0
- package/src/types/dispatches/LookAtDispatch.d.ts +14 -0
- package/src/types/dispatches/LookAtPosDispatch.d.ts +19 -0
- package/src/types/dispatches/MeleeDispatch.d.ts +8 -0
- package/src/types/dispatches/MovementDispatch.d.ts +12 -0
- package/src/types/dispatches/PauseDispatch.d.ts +8 -0
- package/src/types/dispatches/ReloadDispatch.d.ts +8 -0
- package/src/types/dispatches/ReportPlayerDispatch.d.ts +22 -0
- package/src/types/dispatches/SaveLoadoutDispatch.d.ts +34 -0
- package/src/types/dispatches/SpawnDispatch.d.ts +8 -0
- package/src/types/dispatches/SwapWeaponDispatch.d.ts +8 -0
- package/src/types/dispatches/SwitchTeamDispatch.d.ts +8 -0
- package/src/types/dispatches/ThrowGrenadeDispatch.d.ts +10 -0
- package/src/types/dispatches/index.d.ts +174 -0
- package/src/types/matchmaker.d.ts +19 -14
- package/src/types/socket.d.ts +7 -0
package/src/bot.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { loginAnonymously, loginWithCredentials } from '#api';
|
|
1
|
+
import { createAccount, loginAnonymously, loginWithCredentials, loginWithRefreshToken, queryServices } from '#api';
|
|
2
2
|
|
|
3
3
|
import CommIn from './comm/CommIn.js';
|
|
4
4
|
import CommOut from './comm/CommOut.js';
|
|
@@ -9,6 +9,7 @@ import Matchmaker from './matchmaker.js';
|
|
|
9
9
|
import yolkws from './socket.js';
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
|
+
ChiknWinnerDailyLimit,
|
|
12
13
|
CollectTypes,
|
|
13
14
|
CoopStates,
|
|
14
15
|
findItemById,
|
|
@@ -17,6 +18,7 @@ import {
|
|
|
17
18
|
GameOptionFlags,
|
|
18
19
|
GunList,
|
|
19
20
|
IsBrowser,
|
|
21
|
+
ItemTypes,
|
|
20
22
|
Movements,
|
|
21
23
|
PlayTypes,
|
|
22
24
|
ShellStreaks
|
|
@@ -32,30 +34,31 @@ import { Maps } from './constants/maps.js';
|
|
|
32
34
|
const CoopStagesById = Object.fromEntries(Object.entries(CoopStates).map(([key, value]) => [value, key]));
|
|
33
35
|
const GameModesById = Object.fromEntries(Object.entries(GameModes).map(([key, value]) => [value, key]));
|
|
34
36
|
|
|
37
|
+
const intents = {
|
|
38
|
+
CHALLENGES: 1,
|
|
39
|
+
STATS: 2,
|
|
40
|
+
PATHFINDING: 3,
|
|
41
|
+
BUFFERS: 4,
|
|
42
|
+
PING: 5,
|
|
43
|
+
COSMETIC_DATA: 6,
|
|
44
|
+
PLAYER_HEALTH: 7
|
|
45
|
+
}
|
|
46
|
+
|
|
35
47
|
export class Bot {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// params.updateInterval - the auto update interval
|
|
40
|
-
// params.doPing - whether to auto ping (for bot.<ping>)
|
|
41
|
-
// params.pingInterval - the ping interval
|
|
42
|
-
// params.doPathing - whether to run pathfinding logic
|
|
43
|
-
// params.instance - a custom shell URL to run requests through
|
|
48
|
+
static Intents = intents;
|
|
49
|
+
Intents = intents;
|
|
50
|
+
|
|
44
51
|
constructor(params = {}) {
|
|
45
52
|
if (params.proxy && IsBrowser)
|
|
46
53
|
throw new Error('proxies do not work and hence are not supported in the browser');
|
|
47
54
|
|
|
55
|
+
this.intents = params.intents || [];
|
|
56
|
+
|
|
57
|
+
this.instance = params.instance || 'shellshock.io';
|
|
48
58
|
this.proxy = params.proxy || '';
|
|
49
|
-
this.name = params.name || Math.random().toString(36).substring(8);
|
|
50
59
|
|
|
51
|
-
this.autoPing = params.doPing || true;
|
|
52
60
|
this.autoUpdate = params.doUpdate || true;
|
|
53
|
-
this.
|
|
54
|
-
|
|
55
|
-
this.pingInterval = params.pingInterval || 1000;
|
|
56
|
-
this.updateInterval = params.updateInterval || 5;
|
|
57
|
-
|
|
58
|
-
this.instance = params.instance || 'shellshock.io';
|
|
61
|
+
this.updateInterval = params.updateInterval || 11;
|
|
59
62
|
|
|
60
63
|
this._hooks = {};
|
|
61
64
|
this._globalHooks = [];
|
|
@@ -63,10 +66,10 @@ export class Bot {
|
|
|
63
66
|
|
|
64
67
|
// private information NOT FOR OTHER PLAYERS!!
|
|
65
68
|
this.state = {
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
// kept for specifying socket open sequence
|
|
70
|
+
name: '',
|
|
68
71
|
|
|
69
|
-
//
|
|
72
|
+
// tracking for dispatch checks
|
|
70
73
|
reloading: false,
|
|
71
74
|
swappingGun: false,
|
|
72
75
|
usingMelee: false,
|
|
@@ -81,6 +84,7 @@ export class Bot {
|
|
|
81
84
|
this.game = {
|
|
82
85
|
raw: {}, // matchmaker response
|
|
83
86
|
code: '',
|
|
87
|
+
socket: null,
|
|
84
88
|
|
|
85
89
|
// data given on sign in
|
|
86
90
|
gameModeId: 0, // assume ffa
|
|
@@ -98,8 +102,10 @@ export class Bot {
|
|
|
98
102
|
},
|
|
99
103
|
availability: 'both',
|
|
100
104
|
numPlayers: '18',
|
|
105
|
+
|
|
101
106
|
raw: {},
|
|
102
|
-
nodes: {}
|
|
107
|
+
nodes: {},
|
|
108
|
+
zones: []
|
|
103
109
|
},
|
|
104
110
|
playerLimit: 0,
|
|
105
111
|
isGameOwner: false,
|
|
@@ -135,7 +141,8 @@ export class Bot {
|
|
|
135
141
|
|
|
136
142
|
// data from kotc
|
|
137
143
|
stage: CoopStates.capturing,
|
|
138
|
-
|
|
144
|
+
zoneNumber: 0,
|
|
145
|
+
activeZone: [],
|
|
139
146
|
capturing: 0,
|
|
140
147
|
captureProgress: 0,
|
|
141
148
|
numCapturing: 0,
|
|
@@ -145,10 +152,23 @@ export class Bot {
|
|
|
145
152
|
|
|
146
153
|
this.account = {
|
|
147
154
|
// used for auth
|
|
155
|
+
id: 0,
|
|
148
156
|
firebaseId: '',
|
|
149
157
|
sessionId: '',
|
|
150
158
|
session: '',
|
|
151
159
|
|
|
160
|
+
// raw login params
|
|
161
|
+
email: '',
|
|
162
|
+
password: '',
|
|
163
|
+
|
|
164
|
+
// chikn winner related info
|
|
165
|
+
cw: {
|
|
166
|
+
atLimit: false,
|
|
167
|
+
limit: 0,
|
|
168
|
+
secondsUntilPlay: 0, // short cooldown, in seconds
|
|
169
|
+
canPlayAgain: Date.now()
|
|
170
|
+
},
|
|
171
|
+
|
|
152
172
|
// used for skin changing
|
|
153
173
|
loadout: {
|
|
154
174
|
hatId: null,
|
|
@@ -184,21 +204,17 @@ export class Bot {
|
|
|
184
204
|
this._dispatches = [];
|
|
185
205
|
this._packetQueue = [];
|
|
186
206
|
|
|
187
|
-
this.
|
|
207
|
+
this.matchmaker = null;
|
|
188
208
|
|
|
189
209
|
this.ping = 0;
|
|
190
210
|
this.lastPingTime = -1;
|
|
191
211
|
|
|
192
212
|
this.lastDeathTime = -1;
|
|
193
213
|
this.lastChatTime = -1;
|
|
194
|
-
|
|
195
214
|
this.lastUpdateTime = -1;
|
|
196
|
-
this.nUpdates = 0;
|
|
197
215
|
|
|
198
216
|
this.controlKeys = 0;
|
|
199
217
|
|
|
200
|
-
this.initTime = Date.now();
|
|
201
|
-
|
|
202
218
|
this.pathing = {
|
|
203
219
|
nodeList: null,
|
|
204
220
|
followingPath: false,
|
|
@@ -208,47 +224,11 @@ export class Bot {
|
|
|
208
224
|
}
|
|
209
225
|
}
|
|
210
226
|
|
|
211
|
-
async login(email, pass) {
|
|
212
|
-
// const time = Date.now();
|
|
213
|
-
|
|
214
|
-
this.email = email;
|
|
215
|
-
this.pass = pass;
|
|
216
|
-
|
|
217
|
-
const loginData = await loginWithCredentials(email, pass, this.proxy, this.instance);
|
|
218
|
-
|
|
219
|
-
if (typeof loginData == 'string') {
|
|
220
|
-
this.#emit('authFail', loginData);
|
|
221
|
-
return false;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
if (loginData.banRemaining) {
|
|
225
|
-
this.#emit('banned', loginData.banRemaining);
|
|
226
|
-
return false;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
this.state.loggedIn = true;
|
|
230
|
-
|
|
231
|
-
this.account.rawLoginData = loginData;
|
|
232
|
-
|
|
233
|
-
this.account.accountAge = loginData.accountAge;
|
|
234
|
-
this.account.eggBalance = loginData.currentBalance;
|
|
235
|
-
this.account.emailVerified = loginData.emailVerified;
|
|
236
|
-
this.account.firebaseId = loginData.firebaseId;
|
|
237
|
-
this.account.loadout = loginData.loadout;
|
|
238
|
-
this.account.ownedItemIds = loginData.ownedItemIds;
|
|
239
|
-
this.account.sessionId = loginData.sessionId;
|
|
240
|
-
this.account.vip = loginData.upgradeProductId && !loginData.upgradeIsExpired;
|
|
241
|
-
|
|
242
|
-
// console.log('Logged in successfully. Time:', Date.now() - time, 'ms');
|
|
243
|
-
|
|
244
|
-
return this.account;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
227
|
dispatch(disp) {
|
|
248
228
|
this._dispatches.push(disp);
|
|
249
229
|
}
|
|
250
230
|
|
|
251
|
-
drain() {
|
|
231
|
+
#drain() {
|
|
252
232
|
for (let i = 0; i < this._dispatches.length; i++) {
|
|
253
233
|
const disp = this._dispatches[i];
|
|
254
234
|
if (disp.check(this)) {
|
|
@@ -261,15 +241,45 @@ export class Bot {
|
|
|
261
241
|
}
|
|
262
242
|
}
|
|
263
243
|
|
|
264
|
-
async
|
|
244
|
+
async createAccount(email, pass) {
|
|
245
|
+
this.account.email = email;
|
|
246
|
+
this.account.password = pass;
|
|
247
|
+
|
|
248
|
+
const loginData = await createAccount(email, pass, this.proxy, this.instance);
|
|
249
|
+
return this.#processLoginData(loginData);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async login(email, pass) {
|
|
253
|
+
this.account.email = email;
|
|
254
|
+
this.account.password = pass;
|
|
255
|
+
|
|
256
|
+
const loginData = await loginWithCredentials(email, pass, this.proxy, this.instance);
|
|
257
|
+
return this.#processLoginData(loginData);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async loginWithRefreshToken(refreshToken) {
|
|
261
|
+
const loginData = await loginWithRefreshToken(refreshToken, this.proxy, this.instance);
|
|
262
|
+
return this.#processLoginData(loginData);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async loginAnonymously() {
|
|
266
|
+
delete this.account.email;
|
|
267
|
+
delete this.account.password;
|
|
268
|
+
|
|
265
269
|
const loginData = await loginAnonymously(this.proxy, this.instance);
|
|
270
|
+
return this.#processLoginData(loginData);
|
|
271
|
+
}
|
|
266
272
|
|
|
273
|
+
#processLoginData(loginData) {
|
|
267
274
|
if (typeof loginData == 'string') {
|
|
268
275
|
this.#emit('authFail', loginData);
|
|
269
276
|
return false;
|
|
270
277
|
}
|
|
271
278
|
|
|
272
|
-
|
|
279
|
+
if (loginData.banRemaining) {
|
|
280
|
+
this.#emit('banned', loginData.banRemaining);
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
273
283
|
|
|
274
284
|
this.account.rawLoginData = loginData;
|
|
275
285
|
|
|
@@ -277,19 +287,20 @@ export class Bot {
|
|
|
277
287
|
this.account.eggBalance = loginData.currentBalance;
|
|
278
288
|
this.account.emailVerified = loginData.emailVerified;
|
|
279
289
|
this.account.firebaseId = loginData.firebaseId;
|
|
290
|
+
this.account.id = loginData.id;
|
|
280
291
|
this.account.loadout = loginData.loadout;
|
|
281
292
|
this.account.ownedItemIds = loginData.ownedItemIds;
|
|
282
293
|
this.account.session = loginData.session;
|
|
283
294
|
this.account.sessionId = loginData.sessionId;
|
|
284
|
-
this.account.vip =
|
|
295
|
+
this.account.vip = loginData.upgradeProductId && !loginData.upgradeIsExpired;
|
|
285
296
|
|
|
286
297
|
return this.account;
|
|
287
298
|
}
|
|
288
299
|
|
|
289
300
|
async initMatchmaker() {
|
|
290
|
-
if (
|
|
301
|
+
if (this.account.id == 0) {
|
|
291
302
|
// console.log('Not logged in, attempting to create anonymous user...');
|
|
292
|
-
const anonLogin = await this
|
|
303
|
+
const anonLogin = await this.loginAnonymously();
|
|
293
304
|
if (!anonLogin) return false;
|
|
294
305
|
}
|
|
295
306
|
|
|
@@ -312,34 +323,33 @@ export class Bot {
|
|
|
312
323
|
async #joinGameWithCode(code) {
|
|
313
324
|
if (!await this.initMatchmaker()) return false;
|
|
314
325
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
delete this.game.raw.command; // pissed me off
|
|
326
|
+
return await new Promise((resolve) => {
|
|
327
|
+
const listener = (mes) => {
|
|
328
|
+
if (mes.command == 'gameFound') {
|
|
329
|
+
this.matchmaker.off('msg', listener);
|
|
320
330
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
if (mes.error && mes.error == 'gameNotFound')
|
|
325
|
-
throw new Error(`Game ${code} not found (likely expired).`)
|
|
326
|
-
};
|
|
331
|
+
this.game.raw = mes;
|
|
332
|
+
this.game.code = code;
|
|
327
333
|
|
|
328
|
-
|
|
334
|
+
resolve();
|
|
335
|
+
}
|
|
329
336
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
observe: false,
|
|
334
|
-
sessionId: this.account.sessionId
|
|
335
|
-
})
|
|
337
|
+
if (mes.error && mes.error == 'gameNotFound')
|
|
338
|
+
throw new Error(`Game ${code} not found (likely expired).`)
|
|
339
|
+
};
|
|
336
340
|
|
|
337
|
-
|
|
341
|
+
this.matchmaker.on('msg', listener);
|
|
338
342
|
|
|
339
|
-
|
|
343
|
+
this.matchmaker.send({
|
|
344
|
+
command: 'joinGame',
|
|
345
|
+
id: code,
|
|
346
|
+
observe: false,
|
|
347
|
+
sessionId: this.account.sessionId
|
|
348
|
+
})
|
|
349
|
+
});
|
|
340
350
|
}
|
|
341
351
|
|
|
342
|
-
async #onGameMesssage(msg) {
|
|
352
|
+
async #onGameMesssage(msg) {
|
|
343
353
|
CommIn.init(msg.data);
|
|
344
354
|
|
|
345
355
|
let out;
|
|
@@ -350,7 +360,7 @@ export class Bot {
|
|
|
350
360
|
out = CommOut.getBuffer();
|
|
351
361
|
out.packInt8(CommCode.joinGame);
|
|
352
362
|
|
|
353
|
-
out.packString(this.name); // name
|
|
363
|
+
out.packString(this.state.name); // name
|
|
354
364
|
out.packString(this.game.raw.uuid); // game id
|
|
355
365
|
|
|
356
366
|
out.packInt8(0); // hidebadge
|
|
@@ -360,10 +370,10 @@ export class Bot {
|
|
|
360
370
|
out.packString(this.account.firebaseId); // firebase id
|
|
361
371
|
out.packString(this.account.sessionId); // session id
|
|
362
372
|
|
|
363
|
-
out.send(this.
|
|
373
|
+
out.send(this.game.socket);
|
|
364
374
|
break;
|
|
365
375
|
|
|
366
|
-
case CommCode.gameJoined:
|
|
376
|
+
case CommCode.gameJoined: {
|
|
367
377
|
this.me.id = CommIn.unPackInt8U();
|
|
368
378
|
// console.log("My id is:", this.me.id);
|
|
369
379
|
this.me.team = CommIn.unPackInt8U();
|
|
@@ -373,9 +383,10 @@ export class Bot {
|
|
|
373
383
|
// console.log("Gametype:", this.game.gameMode, this.game.gameModeId);
|
|
374
384
|
this.game.mapIdx = CommIn.unPackInt8U();
|
|
375
385
|
this.game.map = Maps[this.game.mapIdx];
|
|
376
|
-
if (
|
|
386
|
+
if (this.intents.includes(this.Intents.PATHFINDING)) {
|
|
377
387
|
this.game.map.raw = await this.#fetchMap(this.game.map.filename, this.game.map.hash);
|
|
378
388
|
this.pathing.nodeList = new NodeList(this.game.map.raw);
|
|
389
|
+
if (this.game.gameModeId === GameModes.kotc) this.#initKotcZones();
|
|
379
390
|
}
|
|
380
391
|
// console.log("Map:", this.game.map);
|
|
381
392
|
this.game.playerLimit = CommIn.unPackInt8U();
|
|
@@ -389,34 +400,34 @@ export class Bot {
|
|
|
389
400
|
this.state.joinedGame = true;
|
|
390
401
|
this.lastDeathTime = Date.now();
|
|
391
402
|
|
|
403
|
+
const out = CommOut.getBuffer();
|
|
404
|
+
out.packInt8(CommCode.clientReady);
|
|
405
|
+
out.send(this.game.socket);
|
|
406
|
+
|
|
407
|
+
this.game.socket.onmessage = (msg) => this._packetQueue.push(msg.data);
|
|
408
|
+
|
|
409
|
+
if (this.autoUpdate)
|
|
410
|
+
setInterval(() => this.update(), this.updateInterval);
|
|
411
|
+
|
|
412
|
+
if (this.intents.includes(this.Intents.PING)) {
|
|
413
|
+
const out = CommOut.getBuffer();
|
|
414
|
+
out.packInt8(CommCode.ping);
|
|
415
|
+
out.send(this.game.socket);
|
|
416
|
+
this.lastPingTime = Date.now();
|
|
417
|
+
}
|
|
392
418
|
break;
|
|
419
|
+
}
|
|
393
420
|
|
|
394
421
|
case CommCode.eventModifier:
|
|
395
422
|
// console.log("Echoed eventModifier"); // why the fuck do you need to do this
|
|
396
423
|
out = CommOut.getBuffer();
|
|
397
424
|
out.packInt8(CommCode.eventModifier);
|
|
398
|
-
out.send(this.
|
|
425
|
+
out.send(this.game.socket);
|
|
399
426
|
break;
|
|
400
427
|
|
|
401
|
-
case CommCode.requestGameOptions:
|
|
402
|
-
|
|
403
|
-
out.packInt8(CommCode.gameOptions);
|
|
404
|
-
out.packInt8(this.game.options.gravity * 4);
|
|
405
|
-
out.packInt8(this.game.options.damage * 4);
|
|
406
|
-
out.packInt8(this.game.options.healthRegen * 4);
|
|
407
|
-
|
|
408
|
-
const flags =
|
|
409
|
-
(this.game.options.locked ? 1 : 0) |
|
|
410
|
-
(this.game.options.noTeamChange ? 2 : 0) |
|
|
411
|
-
(this.game.options.noTeamShuffle ? 4 : 0);
|
|
412
|
-
|
|
413
|
-
out.packInt8(flags);
|
|
414
|
-
|
|
415
|
-
this.game.options.weaponsDisabled.forEach((v) => {
|
|
416
|
-
out.packInt8(v ? 1 : 0);
|
|
417
|
-
});
|
|
428
|
+
case CommCode.requestGameOptions:
|
|
429
|
+
this.#processGameRequestOptionsPacket();
|
|
418
430
|
break;
|
|
419
|
-
}
|
|
420
431
|
|
|
421
432
|
default:
|
|
422
433
|
try {
|
|
@@ -449,52 +460,50 @@ export class Bot {
|
|
|
449
460
|
|
|
450
461
|
if (mapIdx == -1) throw new Error('invalid map, see the Maps constant for a list')
|
|
451
462
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
delete this.game.raw.command;
|
|
457
|
-
|
|
458
|
-
this.gameFound = true;
|
|
459
|
-
}
|
|
460
|
-
};
|
|
463
|
+
await new Promise((resolve) => {
|
|
464
|
+
const listener = (msg) => {
|
|
465
|
+
if (msg.command == 'gameFound') {
|
|
466
|
+
this.matchmaker.off('msg', listener);
|
|
461
467
|
|
|
462
|
-
|
|
468
|
+
this.game.raw = msg;
|
|
469
|
+
this.game.code = this.game.raw.id;
|
|
463
470
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
playType: PlayTypes.createPrivate,
|
|
468
|
-
gameType: GameModes[opts.mode],
|
|
469
|
-
sessionId: this.account.sessionId,
|
|
470
|
-
noobLobby: false,
|
|
471
|
-
map: mapIdx
|
|
472
|
-
});
|
|
471
|
+
resolve();
|
|
472
|
+
}
|
|
473
|
+
};
|
|
473
474
|
|
|
474
|
-
|
|
475
|
+
this.matchmaker.on('msg', listener);
|
|
475
476
|
|
|
476
|
-
|
|
477
|
+
this.matchmaker.send({
|
|
478
|
+
command: 'findGame',
|
|
479
|
+
region: opts.region,
|
|
480
|
+
playType: PlayTypes.createPrivate,
|
|
481
|
+
gameType: GameModes[opts.mode],
|
|
482
|
+
sessionId: this.account.sessionId,
|
|
483
|
+
noobLobby: false,
|
|
484
|
+
map: mapIdx
|
|
485
|
+
});
|
|
486
|
+
});
|
|
477
487
|
|
|
478
488
|
return this.game.raw;
|
|
479
489
|
}
|
|
480
490
|
|
|
481
|
-
async join(data) {
|
|
491
|
+
async join(name, data) {
|
|
492
|
+
this.state.name = name || 'yolkbot';
|
|
493
|
+
|
|
482
494
|
if (typeof data == 'string') {
|
|
483
495
|
if (data.includes('#')) data = data.split('#')[1]; // stupid shell kids put in full links
|
|
484
496
|
// this is a string code that we can pass and get the needed info from
|
|
485
497
|
await this.#joinGameWithCode(data);
|
|
486
498
|
} else if (typeof data == 'object') {
|
|
487
|
-
if (
|
|
499
|
+
if (this.account.id == 0) {
|
|
488
500
|
// console.log('passed an object but you still need to be logged in!!')
|
|
489
|
-
await this
|
|
501
|
+
await this.loginAnonymously();
|
|
490
502
|
}
|
|
491
503
|
|
|
492
504
|
// this is a game object that we can pass and get the needed info from
|
|
493
505
|
this.game.raw = data;
|
|
494
506
|
this.game.code = this.game.raw.id;
|
|
495
|
-
delete this.game.raw.command;
|
|
496
|
-
|
|
497
|
-
this.gameFound = true;
|
|
498
507
|
}
|
|
499
508
|
|
|
500
509
|
if (!this.game.raw.id || !this.game.raw.subdomain)
|
|
@@ -502,113 +511,103 @@ export class Bot {
|
|
|
502
511
|
|
|
503
512
|
// console.log(`Joining ${this.game.raw.id} using proxy ${this.proxy || 'none'}`);
|
|
504
513
|
|
|
505
|
-
|
|
514
|
+
const attempt = async () => {
|
|
515
|
+
try {
|
|
516
|
+
this.game.socket = new yolkws(`wss://${this.game.raw.subdomain}.${this.instance}/game/${this.game.raw.id}`, this.proxy);
|
|
517
|
+
} catch {
|
|
518
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
519
|
+
await attempt();
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
await attempt();
|
|
506
524
|
|
|
507
|
-
this.
|
|
525
|
+
this.game.socket.binaryType = 'arraybuffer';
|
|
508
526
|
|
|
509
|
-
this.
|
|
527
|
+
this.game.socket.onopen = () => {
|
|
510
528
|
// console.log('Successfully connected to game server.');
|
|
511
529
|
}
|
|
512
530
|
|
|
513
|
-
this.
|
|
531
|
+
this.game.socket.onmessage = this.#onGameMesssage.bind(this);
|
|
514
532
|
|
|
515
|
-
this.
|
|
533
|
+
this.game.socket.onclose = (e) => {
|
|
516
534
|
// console.log('Game socket closed:', e.code, Object.entries(CloseCode).filter(([, v]) => v == e.code));
|
|
517
535
|
this.#emit('close', e.code);
|
|
518
536
|
}
|
|
519
|
-
|
|
520
|
-
while (!this.state.joinedGame) await new Promise(r => setTimeout(r, 5));
|
|
521
|
-
|
|
522
|
-
const out = CommOut.getBuffer();
|
|
523
|
-
out.packInt8(CommCode.clientReady);
|
|
524
|
-
out.send(this.gameSocket);
|
|
525
|
-
|
|
526
|
-
this.gameSocket.onmessage = (msg) => this._packetQueue.push(msg.data);
|
|
527
|
-
|
|
528
|
-
// console.log(`Successfully joined ${this.game.code}. Startup to join time: ${Date.now() - this.initTime} ms`);
|
|
529
|
-
|
|
530
|
-
if (this.autoUpdate)
|
|
531
|
-
setInterval(() => this.update(), this.updateInterval);
|
|
532
|
-
|
|
533
|
-
if (this.autoPing) {
|
|
534
|
-
const out = CommOut.getBuffer();
|
|
535
|
-
out.packInt8(CommCode.ping);
|
|
536
|
-
out.send(this.gameSocket);
|
|
537
|
-
this.lastPingTime = Date.now();
|
|
538
|
-
}
|
|
539
537
|
}
|
|
540
538
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
this.nUpdates++;
|
|
545
|
-
|
|
546
|
-
if (this._packetQueue.length === 0 && this._dispatches.length === 0) return;
|
|
547
|
-
|
|
548
|
-
let packet;
|
|
549
|
-
while ((packet = this._packetQueue.shift()) !== undefined) { this.#handlePacket(packet); }
|
|
550
|
-
|
|
551
|
-
this.drain();
|
|
552
|
-
|
|
553
|
-
if (this.pathing.followingPath && !this.disablePathing) {
|
|
554
|
-
const myPositionStr = Object.entries(this.me.position).map(entry => Math.floor(entry[1])).join(',');
|
|
539
|
+
#processPathfinding() {
|
|
540
|
+
const myPositionStr = Object.entries(this.me.position).map(entry => Math.floor(entry[1])).join(',');
|
|
555
541
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
542
|
+
if (myPositionStr == this.pathing.activePath[this.pathing.activePath.length - 1].positionStr()) {
|
|
543
|
+
// console.log('Completed path to', this.pathing.activePath[this.pathing.activePath.length - 1].position);
|
|
544
|
+
this.pathing.followingPath = false;
|
|
545
|
+
this.pathing.activePath = null;
|
|
546
|
+
this.pathing.activeNode = null;
|
|
547
|
+
this.pathing.activeNodeIdx = 0;
|
|
562
548
|
|
|
563
|
-
|
|
549
|
+
this.dispatch(new MovementDispatch(0));
|
|
550
|
+
} else {
|
|
551
|
+
let positionTarget;
|
|
552
|
+
if (this.pathing.activeNodeIdx < this.pathing.activePath.length - 1) {
|
|
553
|
+
positionTarget = this.pathing.activePath[this.pathing.activeNodeIdx + 1].flatCenter();
|
|
554
|
+
this.dispatch(new LookAtPosDispatch(positionTarget));
|
|
564
555
|
} else {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
this.dispatch(new LookAtPosDispatch(positionTarget));
|
|
569
|
-
} else {
|
|
570
|
-
positionTarget = this.pathing.activePath[this.pathing.activeNodeIdx].flatCenter();
|
|
571
|
-
this.dispatch(new LookAtPosDispatch(positionTarget));
|
|
572
|
-
}
|
|
556
|
+
positionTarget = this.pathing.activePath[this.pathing.activeNodeIdx].flatCenter();
|
|
557
|
+
this.dispatch(new LookAtPosDispatch(positionTarget));
|
|
558
|
+
}
|
|
573
559
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
} else {
|
|
581
|
-
// console.log('Close to node that\'s before, idx:',
|
|
582
|
-
// this.pathing.activePath.indexOf(node), 'current:', this.pathing.activeNodeIdx);
|
|
583
|
-
}
|
|
560
|
+
for (const node of this.pathing.activePath) {
|
|
561
|
+
if (node.flatRadialDistance(this.me.position) < 0.1 && node.position.y == Math.floor(this.me.position.y)) {
|
|
562
|
+
if (this.pathing.activePath.indexOf(node) >= this.pathing.activeNodeIdx) {
|
|
563
|
+
this.pathing.activeNodeIdx = this.pathing.activePath.indexOf(node) + 1;
|
|
564
|
+
this.pathing.activeNode = this.pathing.activePath[this.pathing.activeNodeIdx];
|
|
565
|
+
break;
|
|
584
566
|
} else {
|
|
585
|
-
// console.log('
|
|
567
|
+
// console.log('Close to node that\'s before, idx:',
|
|
568
|
+
// this.pathing.activePath.indexOf(node), 'current:', this.pathing.activeNodeIdx);
|
|
586
569
|
}
|
|
587
|
-
|
|
570
|
+
} else {
|
|
571
|
+
// console.log('Node at', node.position, 'is', node.flatRadialDistance(this.me.position), 'away.')
|
|
588
572
|
}
|
|
573
|
+
// console.log('activeNode is ', this.pathing.activeNode.flatRadialDistance(this.me.position), 'away');
|
|
574
|
+
}
|
|
589
575
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
}
|
|
576
|
+
if (!(this.controlKeys & Movements.FORWARD)) {
|
|
577
|
+
this.dispatch(new MovementDispatch(Movements.FORWARD));
|
|
593
578
|
}
|
|
579
|
+
}
|
|
594
580
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
}
|
|
581
|
+
/*let onPath = false;
|
|
582
|
+
for (const node of this.pathing.activePath) {
|
|
583
|
+
if (node.positionStr() == myPositionStr) {
|
|
584
|
+
onPath = true;
|
|
585
|
+
break;
|
|
601
586
|
}
|
|
602
|
-
if (!onPath) {
|
|
603
|
-
console.log('Got off-path somehow');
|
|
604
|
-
this.dispatch(new PathfindDispatch(this.pathing.activePath[this.pathing.activePath.length - 1]));
|
|
605
|
-
this.pathing.followingPath = false;
|
|
606
|
-
this.pathing.activePath = null;
|
|
607
|
-
this.pathing.activeNode = null;
|
|
608
|
-
this.pathing.activeNodeIdx = 0;
|
|
609
|
-
}*/
|
|
610
587
|
}
|
|
588
|
+
if (!onPath) {
|
|
589
|
+
console.log('Got off-path somehow');
|
|
590
|
+
this.dispatch(new PathfindDispatch(this.pathing.activePath[this.pathing.activePath.length - 1]));
|
|
591
|
+
this.pathing.followingPath = false;
|
|
592
|
+
this.pathing.activePath = null;
|
|
593
|
+
this.pathing.activeNode = null;
|
|
594
|
+
this.pathing.activeNodeIdx = 0;
|
|
595
|
+
}*/
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
update() {
|
|
599
|
+
if (!this.state.joinedGame) throw new Error('Not playing, can\'t update. ');
|
|
600
|
+
|
|
601
|
+
// process pathfinding
|
|
602
|
+
if (this.pathing.followingPath && this.intents.includes(this.Intents.PATHFINDING)) this.#processPathfinding();
|
|
611
603
|
|
|
604
|
+
// process incoming packets
|
|
605
|
+
while (this._packetQueue.length > 0) this.#handlePacket(this._packetQueue.shift());
|
|
606
|
+
|
|
607
|
+
// process dispatches
|
|
608
|
+
if (this._dispatches.length > 0) this.#drain();
|
|
609
|
+
|
|
610
|
+
// process syncMe
|
|
612
611
|
if (Date.now() - this.lastUpdateTime >= 50) {
|
|
613
612
|
this.#emit('tick');
|
|
614
613
|
|
|
@@ -624,14 +623,16 @@ export class Bot {
|
|
|
624
623
|
out.packRad(this.me.view.pitch); // pitch
|
|
625
624
|
out.packInt8(100); // fixes commcode issues, does nothing
|
|
626
625
|
}
|
|
627
|
-
out.send(this.
|
|
626
|
+
out.send(this.game.socket);
|
|
628
627
|
|
|
629
628
|
this.lastUpdateTime = Date.now();
|
|
630
629
|
this.state.shotsFired = 0;
|
|
631
630
|
}
|
|
632
631
|
|
|
633
|
-
|
|
634
|
-
|
|
632
|
+
while (this._liveCallbacks.length > 0) {
|
|
633
|
+
const cb = this._liveCallbacks.shift();
|
|
634
|
+
cb();
|
|
635
|
+
}
|
|
635
636
|
}
|
|
636
637
|
|
|
637
638
|
on(event, cb) {
|
|
@@ -688,6 +689,64 @@ export class Bot {
|
|
|
688
689
|
}
|
|
689
690
|
}
|
|
690
691
|
|
|
692
|
+
#initKotcZones() {
|
|
693
|
+
const meshData = this.game.map.raw.data['DYNAMIC.capture-zone.none'];
|
|
694
|
+
if (!meshData) return delete this.game.map.zones;
|
|
695
|
+
|
|
696
|
+
let numCaptureZones = 0;
|
|
697
|
+
const mapData = {};
|
|
698
|
+
const zones = [];
|
|
699
|
+
|
|
700
|
+
for (const cell of meshData) {
|
|
701
|
+
if (!mapData[cell.x]) mapData[cell.x] = {};
|
|
702
|
+
if (!mapData[cell.x][cell.y]) mapData[cell.x][cell.y] = {};
|
|
703
|
+
mapData[cell.x][cell.y][cell.z] = { zone: null };
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
const offsets = [
|
|
707
|
+
{ x: -1, z: 0 },
|
|
708
|
+
{ x: 1, z: 0 },
|
|
709
|
+
{ x: 0, z: -1 },
|
|
710
|
+
{ x: 0, z: 1 }
|
|
711
|
+
];
|
|
712
|
+
|
|
713
|
+
function getMapCellAt(x, y, z) {
|
|
714
|
+
return mapData[x] && mapData[x][y] && mapData[x][y][z] ? mapData[x][y][z] : null;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
for (const cellA of meshData) {
|
|
718
|
+
if (!mapData[cellA.x][cellA.y][cellA.z].zone) {
|
|
719
|
+
cellA.zone = ++numCaptureZones;
|
|
720
|
+
mapData[cellA.x][cellA.y][cellA.z].zone = cellA.zone;
|
|
721
|
+
|
|
722
|
+
const currentZone = [cellA];
|
|
723
|
+
let hits;
|
|
724
|
+
|
|
725
|
+
do {
|
|
726
|
+
hits = 0;
|
|
727
|
+
for (const cellB of meshData) {
|
|
728
|
+
if (!mapData[cellB.x][cellB.y][cellB.z].zone) {
|
|
729
|
+
for (const o of offsets) {
|
|
730
|
+
const cell = getMapCellAt(cellB.x + o.x, cellB.y, cellB.z + o.z);
|
|
731
|
+
if (cell && cell.zone == cellA.zone) {
|
|
732
|
+
hits++;
|
|
733
|
+
cellB.zone = cellA.zone;
|
|
734
|
+
mapData[cellB.x][cellB.y][cellB.z].zone = cellA.zone;
|
|
735
|
+
currentZone.push(cellB);
|
|
736
|
+
break;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
} while (hits > 0);
|
|
742
|
+
|
|
743
|
+
zones.push(currentZone);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
this.game.map.zones = zones;
|
|
748
|
+
}
|
|
749
|
+
|
|
691
750
|
#processChatPacket() {
|
|
692
751
|
const id = CommIn.unPackInt8U();
|
|
693
752
|
const msgFlags = CommIn.unPackInt8U();
|
|
@@ -704,6 +763,7 @@ export class Bot {
|
|
|
704
763
|
const name = CommIn.unPackString();
|
|
705
764
|
const safename = CommIn.unPackString(); // ??? (a)
|
|
706
765
|
const charClass = CommIn.unPackInt8U();
|
|
766
|
+
const findCosmetics = this.intents.includes(this.Intents.COSMETIC_DATA);
|
|
707
767
|
const playerData = {
|
|
708
768
|
id_: id_,
|
|
709
769
|
uniqueId_: uniqueId,
|
|
@@ -712,14 +772,14 @@ export class Bot {
|
|
|
712
772
|
charClass_: charClass,
|
|
713
773
|
team_: CommIn.unPackInt8U(),
|
|
714
774
|
primaryWeaponItem_: findItemById(CommIn.unPackInt16U()),
|
|
715
|
-
secondaryWeaponItem_: findItemById(CommIn.unPackInt16U())
|
|
775
|
+
secondaryWeaponItem_: findCosmetics ? findItemById(CommIn.unPackInt16U()) : CommIn.unPackInt16U(),
|
|
716
776
|
shellColor_: CommIn.unPackInt8U(),
|
|
717
|
-
hatItem_: findItemById(CommIn.unPackInt16U()),
|
|
718
|
-
stampItem_: findItemById(CommIn.unPackInt16U()),
|
|
777
|
+
hatItem_: findCosmetics ? findItemById(CommIn.unPackInt16U()) : CommIn.unPackInt16U(),
|
|
778
|
+
stampItem_: findCosmetics ? findItemById(CommIn.unPackInt16U()) : CommIn.unPackInt16U(),
|
|
719
779
|
unknownInt8: CommIn.unPackInt8(), // c
|
|
720
780
|
otherUnknownInt8: CommIn.unPackInt8(),
|
|
721
|
-
grenadeItem_: findItemById(CommIn.unPackInt16U()),
|
|
722
|
-
meleeItem_: findItemById(CommIn.unPackInt16U()),
|
|
781
|
+
grenadeItem_: findCosmetics ? findItemById(CommIn.unPackInt16U()) : CommIn.unPackInt16U(),
|
|
782
|
+
meleeItem_: findCosmetics ? findItemById(CommIn.unPackInt16U()) : CommIn.unPackInt16U(),
|
|
723
783
|
x_: CommIn.unPackFloat(),
|
|
724
784
|
y_: CommIn.unPackFloat(),
|
|
725
785
|
z_: CommIn.unPackFloat(),
|
|
@@ -757,7 +817,7 @@ export class Bot {
|
|
|
757
817
|
|
|
758
818
|
const player = this.players[playerData.id_];
|
|
759
819
|
|
|
760
|
-
if (player.playing) {
|
|
820
|
+
if (player.playing && this.intents.includes(this.Intents.PLAYER_HEALTH)) {
|
|
761
821
|
player.healthInterval = setInterval(() => {
|
|
762
822
|
if (player.hp < 1) return;
|
|
763
823
|
|
|
@@ -777,11 +837,6 @@ export class Bot {
|
|
|
777
837
|
}
|
|
778
838
|
|
|
779
839
|
this.#emit('playerJoin', this.players[playerData.id_]);
|
|
780
|
-
|
|
781
|
-
const unp = CommIn.unPackInt8U();
|
|
782
|
-
if (unp == CommCode.addPlayer) { // there is another player stacked
|
|
783
|
-
this.#processAddPlayerPacket();
|
|
784
|
-
}
|
|
785
840
|
}
|
|
786
841
|
|
|
787
842
|
#processRespawnPacket() {
|
|
@@ -810,21 +865,22 @@ export class Bot {
|
|
|
810
865
|
// console.log(`Player ${player.name} respawned at ${x}, ${y}, ${z}`);
|
|
811
866
|
this.#emit('playerRespawn', player);
|
|
812
867
|
|
|
813
|
-
if (
|
|
814
|
-
|
|
815
|
-
|
|
868
|
+
if (this.intents.includes(this.Intents.PLAYER_HEALTH)) {
|
|
869
|
+
if (player.healthInterval)
|
|
870
|
+
clearInterval(player.healthInterval);
|
|
816
871
|
|
|
817
|
-
|
|
818
|
-
|
|
872
|
+
player.healthInterval = setInterval(() => {
|
|
873
|
+
if (player.hp < 1) return;
|
|
819
874
|
|
|
820
|
-
|
|
875
|
+
const regenSpeed = 0.1 * (this.game.isPrivate ? this.game.options[GameOptionFlags.healthRegen] : 1);
|
|
821
876
|
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
877
|
+
if (player.streakRewards.includes(ShellStreaks.OverHeal)) {
|
|
878
|
+
player.hp = Math.max(100, player.hp - regenSpeed);
|
|
879
|
+
} else {
|
|
880
|
+
player.hp = Math.min(100, player.hp + regenSpeed);
|
|
881
|
+
}
|
|
882
|
+
}, 33);
|
|
883
|
+
}
|
|
828
884
|
} else {
|
|
829
885
|
// console.log(`Player ${id} not found. (me: ${this.me.id}) (respawn)`);
|
|
830
886
|
}
|
|
@@ -838,37 +894,53 @@ export class Bot {
|
|
|
838
894
|
const climbing = CommIn.unPackInt8U();
|
|
839
895
|
|
|
840
896
|
const player = this.players[id];
|
|
841
|
-
if (!player
|
|
897
|
+
if (!player) return;
|
|
842
898
|
|
|
843
|
-
if (player.
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
899
|
+
if (player.position.x !== x) player.position.x = x;
|
|
900
|
+
if (player.position.z !== z) player.position.z = z;
|
|
901
|
+
|
|
902
|
+
if (!player.jumping || Math.abs(player.position.y - y) > 0.5 && player.position.y !== y)
|
|
903
|
+
player.position.y = y;
|
|
904
|
+
|
|
905
|
+
if (player.climbing !== climbing) player.climbing = climbing;
|
|
906
|
+
|
|
907
|
+
if (this.intents.includes(this.Intents.BUFFERS)) {
|
|
908
|
+
if (!player.buffer) return;
|
|
909
|
+
|
|
910
|
+
if (player.id == this.me.id) {
|
|
911
|
+
for (let i2 = 0; i2 < 3 /* FramesBetweenSyncs */; i2++) {
|
|
912
|
+
CommIn.unPackInt8U();
|
|
913
|
+
CommIn.unPackRadU();
|
|
914
|
+
CommIn.unPackRad();
|
|
915
|
+
CommIn.unPackInt8U();
|
|
916
|
+
}
|
|
917
|
+
return;
|
|
848
918
|
}
|
|
849
|
-
}
|
|
850
919
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
yaw = CommIn.unPackRadU();
|
|
855
|
-
if (!isNaN(yaw)) { player.buffer[i2].yaw_ = yaw }
|
|
856
|
-
pitch = CommIn.unPackRad();
|
|
857
|
-
if (!isNaN(pitch)) { player.buffer[i2].pitch_ = pitch }
|
|
858
|
-
}
|
|
920
|
+
let yaw, pitch;
|
|
921
|
+
for (let i2 = 0; i2 < 3; i2++) {
|
|
922
|
+
player.buffer[i2].controlKeys = CommIn.unPackInt8U();
|
|
859
923
|
|
|
860
|
-
|
|
924
|
+
yaw = CommIn.unPackRadU();
|
|
925
|
+
if (!isNaN(yaw)) player.buffer[i2].yaw_ = yaw
|
|
861
926
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
927
|
+
pitch = CommIn.unPackRad();
|
|
928
|
+
if (!isNaN(pitch)) player.buffer[i2].pitch_ = pitch
|
|
929
|
+
|
|
930
|
+
CommIn.unPackInt8U();
|
|
931
|
+
}
|
|
865
932
|
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
933
|
+
player.buffer[0].x = x;
|
|
934
|
+
player.buffer[0].y = y;
|
|
935
|
+
player.buffer[0].z = z;
|
|
936
|
+
} else {
|
|
937
|
+
for (let i2 = 0; i2 < 3; i2++) {
|
|
938
|
+
CommIn.unPackInt8U();
|
|
939
|
+
CommIn.unPackRadU();
|
|
940
|
+
CommIn.unPackRad();
|
|
941
|
+
CommIn.unPackInt8U();
|
|
942
|
+
}
|
|
943
|
+
}
|
|
872
944
|
}
|
|
873
945
|
|
|
874
946
|
#processPausePacket() {
|
|
@@ -894,16 +966,14 @@ export class Bot {
|
|
|
894
966
|
#processDeathPacket() {
|
|
895
967
|
const killedId = CommIn.unPackInt8U();
|
|
896
968
|
const byId = CommIn.unPackInt8U();
|
|
897
|
-
|
|
969
|
+
|
|
970
|
+
CommIn.unPackInt8U();
|
|
971
|
+
CommIn.unPackInt8U();
|
|
972
|
+
CommIn.unPackInt8U();
|
|
898
973
|
|
|
899
974
|
const killed = this.players[killedId];
|
|
900
975
|
const killer = this.players[byId];
|
|
901
976
|
|
|
902
|
-
/*
|
|
903
|
-
const killerLastDmg = CommIn.unPackInt8U();
|
|
904
|
-
const killedLastDmg = CommIn.unPackInt8U();
|
|
905
|
-
*/
|
|
906
|
-
|
|
907
977
|
if (killed) {
|
|
908
978
|
killed.playing = false;
|
|
909
979
|
killed.kills = 0;
|
|
@@ -920,6 +990,9 @@ export class Bot {
|
|
|
920
990
|
#processFirePacket() {
|
|
921
991
|
const id = CommIn.unPackInt8U();
|
|
922
992
|
|
|
993
|
+
for (let i = 0; i < 6; i++)
|
|
994
|
+
CommIn.unPackFloat();
|
|
995
|
+
|
|
923
996
|
const player = this.players[id];
|
|
924
997
|
const playerWeapon = player.weapons[player.activeGun];
|
|
925
998
|
|
|
@@ -960,7 +1033,9 @@ export class Bot {
|
|
|
960
1033
|
}
|
|
961
1034
|
|
|
962
1035
|
if (type == CollectTypes.GRENADE) {
|
|
963
|
-
player.grenades
|
|
1036
|
+
player.grenades++;
|
|
1037
|
+
if (player.grenades > 3) player.grenades = 3
|
|
1038
|
+
|
|
964
1039
|
this.#emit('collectGrenade', player);
|
|
965
1040
|
}
|
|
966
1041
|
}
|
|
@@ -980,8 +1055,11 @@ export class Bot {
|
|
|
980
1055
|
|
|
981
1056
|
#processHitMePacket() {
|
|
982
1057
|
const hp = CommIn.unPackInt8U();
|
|
983
|
-
const oldHp = this.me.hp;
|
|
984
1058
|
|
|
1059
|
+
CommIn.unPackFloat();
|
|
1060
|
+
CommIn.unPackFloat();
|
|
1061
|
+
|
|
1062
|
+
const oldHp = this.me.hp;
|
|
985
1063
|
this.me.hp = hp;
|
|
986
1064
|
|
|
987
1065
|
this.#emit('selfDamaged', oldHp, this.me.hp);
|
|
@@ -1001,6 +1079,10 @@ export class Bot {
|
|
|
1001
1079
|
const newY = CommIn.unPackFloat();
|
|
1002
1080
|
const newZ = CommIn.unPackFloat();
|
|
1003
1081
|
|
|
1082
|
+
CommIn.unPackInt8U();
|
|
1083
|
+
CommIn.unPackInt8U();
|
|
1084
|
+
CommIn.unPackInt8U();
|
|
1085
|
+
|
|
1004
1086
|
const oldX = player.position.x;
|
|
1005
1087
|
const oldY = player.position.y;
|
|
1006
1088
|
const oldZ = player.position.z;
|
|
@@ -1017,7 +1099,7 @@ export class Bot {
|
|
|
1017
1099
|
#processEventModifierPacket() {
|
|
1018
1100
|
const out = CommOut.getBuffer();
|
|
1019
1101
|
out.packInt8(CommCode.eventModifier);
|
|
1020
|
-
out.send(this.
|
|
1102
|
+
out.send(this.game.socket);
|
|
1021
1103
|
}
|
|
1022
1104
|
|
|
1023
1105
|
#processRemovePlayerPacket() {
|
|
@@ -1052,7 +1134,7 @@ export class Bot {
|
|
|
1052
1134
|
this.#emit('gameStateChange', this.game);
|
|
1053
1135
|
} else if (this.game.gameModeId == GameModes.kotc) {
|
|
1054
1136
|
this.game.stage = CommIn.unPackInt8U(); // constants.CoopStates
|
|
1055
|
-
this.game.
|
|
1137
|
+
this.game.zoneNumber = CommIn.unPackInt8U(); // a number to represent which 'active zone' kotc is using
|
|
1056
1138
|
this.game.capturing = CommIn.unPackInt8U(); // the team capturing, named "teams" in shell src
|
|
1057
1139
|
this.game.captureProgress = CommIn.unPackInt16U(); // progress of the coop capture
|
|
1058
1140
|
this.game.numCapturing = CommIn.unPackInt8U(); // number of players capturing - number/1000
|
|
@@ -1062,8 +1144,12 @@ export class Bot {
|
|
|
1062
1144
|
// not in shell, for utility purposes =D
|
|
1063
1145
|
this.game.stageName = CoopStagesById[this.game.stage]; // name of the stage ('start' / 'capturing' / 'etc')
|
|
1064
1146
|
this.game.capturePercent = this.game.captureProgress / 1000; // progress of the capture as a percentage
|
|
1147
|
+
this.game.activeZone = this.game.map.zones ? this.game.map.zones[this.game.zoneNumber - 1] : null;
|
|
1065
1148
|
|
|
1066
1149
|
this.#emit('gameStateChange', this.game);
|
|
1150
|
+
} else if (this.game.gameModeId == GameModes.team) {
|
|
1151
|
+
this.game.teamScore[1] = CommIn.unPackInt16U();
|
|
1152
|
+
this.game.teamScore[2] = CommIn.unPackInt16U();
|
|
1067
1153
|
}
|
|
1068
1154
|
|
|
1069
1155
|
if (this.game.gameModeId !== GameModes.spatula) {
|
|
@@ -1072,13 +1158,16 @@ export class Bot {
|
|
|
1072
1158
|
|
|
1073
1159
|
if (this.game.gameModeId !== GameModes.kotc) {
|
|
1074
1160
|
delete this.game.stage;
|
|
1075
|
-
delete this.game.
|
|
1161
|
+
delete this.game.zoneNumber;
|
|
1076
1162
|
delete this.game.capturing;
|
|
1077
1163
|
delete this.game.captureProgress;
|
|
1078
|
-
delete this.game.numCapturing
|
|
1164
|
+
delete this.game.numCapturing;
|
|
1165
|
+
delete this.game.stageName;
|
|
1166
|
+
delete this.game.numCapturing;
|
|
1167
|
+
delete this.game.activeZone;
|
|
1079
1168
|
}
|
|
1080
1169
|
|
|
1081
|
-
if (this.game.gameModeId
|
|
1170
|
+
if (this.game.gameModeId == GameModes.ffa) {
|
|
1082
1171
|
delete this.game.teamScore;
|
|
1083
1172
|
}
|
|
1084
1173
|
}
|
|
@@ -1155,6 +1244,9 @@ export class Bot {
|
|
|
1155
1244
|
const hb = CommIn.unPackInt8U();
|
|
1156
1245
|
const hp = CommIn.unPackInt8U();
|
|
1157
1246
|
|
|
1247
|
+
CommIn.unPackFloat();
|
|
1248
|
+
CommIn.unPackFloat();
|
|
1249
|
+
|
|
1158
1250
|
this.me.hpShield = hb;
|
|
1159
1251
|
this.me.hp = hp;
|
|
1160
1252
|
|
|
@@ -1208,25 +1300,33 @@ export class Bot {
|
|
|
1208
1300
|
// console.log('owner reset game');
|
|
1209
1301
|
|
|
1210
1302
|
this.me.kills = 0;
|
|
1211
|
-
this.game.teamScore = [0, 0, 0];
|
|
1212
1303
|
|
|
1213
|
-
this.game.
|
|
1214
|
-
|
|
1215
|
-
this.game.spatula
|
|
1304
|
+
if (this.game.gameModeId !== GameModes.ffa) this.game.teamScore = [0, 0, 0];
|
|
1305
|
+
|
|
1306
|
+
if (this.game.gameModeId === GameModes.spatula) {
|
|
1307
|
+
this.game.spatula.controlledBy = 0;
|
|
1308
|
+
this.game.spatula.controlledByTeam = 0;
|
|
1309
|
+
this.game.spatula.coords = { x: 0, y: 0, z: 0 };
|
|
1310
|
+
}
|
|
1216
1311
|
|
|
1217
|
-
this.game.
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1312
|
+
if (this.game.gameModeId === GameModes.kotc) {
|
|
1313
|
+
this.game.stage = CoopStates.capturing;
|
|
1314
|
+
this.game.zoneNumber = 0;
|
|
1315
|
+
this.game.activeZone = null;
|
|
1316
|
+
this.game.capturing = 0;
|
|
1317
|
+
this.game.captureProgress = 0;
|
|
1318
|
+
this.game.numCapturing = 0;
|
|
1319
|
+
this.game.stageName = CoopStagesById[CoopStates.capturing];
|
|
1320
|
+
this.game.capturePercent = 0.0;
|
|
1321
|
+
}
|
|
1224
1322
|
|
|
1225
1323
|
this.#emit('gameReset');
|
|
1226
1324
|
}
|
|
1227
1325
|
}
|
|
1228
1326
|
|
|
1229
1327
|
#processPingPacket() {
|
|
1328
|
+
if (!this.intents.includes(this.Intents.PING)) return;
|
|
1329
|
+
|
|
1230
1330
|
const oldPing = this.ping;
|
|
1231
1331
|
|
|
1232
1332
|
this.ping = Date.now() - this.lastPingTime;
|
|
@@ -1236,7 +1336,7 @@ export class Bot {
|
|
|
1236
1336
|
setTimeout(() => {
|
|
1237
1337
|
const out = CommOut.getBuffer();
|
|
1238
1338
|
out.packInt8(CommCode.ping);
|
|
1239
|
-
out.send(this.
|
|
1339
|
+
out.send(this.game.socket);
|
|
1240
1340
|
this.lastPingTime = Date.now();
|
|
1241
1341
|
}, this.pingInterval);
|
|
1242
1342
|
}
|
|
@@ -1268,12 +1368,18 @@ export class Bot {
|
|
|
1268
1368
|
const grenadeIdx = CommIn.unPackInt16U();
|
|
1269
1369
|
const meleeIdx = CommIn.unPackInt16U();
|
|
1270
1370
|
|
|
1371
|
+
CommIn.unPackInt8();
|
|
1372
|
+
CommIn.unPackInt8();
|
|
1373
|
+
|
|
1374
|
+
const findCosmetics = this.intents.includes(this.Intents.COSMETIC_DATA);
|
|
1375
|
+
|
|
1271
1376
|
const primaryWeaponItem = findItemById(primaryWeaponIdx);
|
|
1272
|
-
|
|
1273
|
-
const
|
|
1274
|
-
const
|
|
1275
|
-
const
|
|
1276
|
-
const
|
|
1377
|
+
|
|
1378
|
+
const secondaryWeaponItem = findCosmetics ? findItemById(secondaryWeaponIdx) : secondaryWeaponIdx;
|
|
1379
|
+
const hatItem = findCosmetics ? findItemById(hatIdx) : hatIdx;
|
|
1380
|
+
const stampItem = findCosmetics ? findItemById(stampIdx) : stampIdx;
|
|
1381
|
+
const grenadeItem = findCosmetics ? findItemById(grenadeIdx) : grenadeIdx;
|
|
1382
|
+
const meleeItem = findCosmetics ? findItemById(meleeIdx) : meleeIdx;
|
|
1277
1383
|
|
|
1278
1384
|
const player = this.players[id];
|
|
1279
1385
|
if (player) {
|
|
@@ -1316,7 +1422,8 @@ export class Bot {
|
|
|
1316
1422
|
if (player) this.#emit('playerMelee', player);
|
|
1317
1423
|
}
|
|
1318
1424
|
|
|
1319
|
-
// we do this since reload doesn't get emitted
|
|
1425
|
+
// we do this since reload doesn't get emitted for the bot itself
|
|
1426
|
+
// so we simulate it when calling a reload dispatch
|
|
1320
1427
|
processReloadPacket(customPlayer, iUnderstandThisIsForInternalUseOnlyAndIShouldNotBeCallingThis) {
|
|
1321
1428
|
if (!iUnderstandThisIsForInternalUseOnlyAndIShouldNotBeCallingThis)
|
|
1322
1429
|
throw new Error('processReloadPacket is exposed for internal use only. do not call it.');
|
|
@@ -1341,141 +1448,408 @@ export class Bot {
|
|
|
1341
1448
|
this.#emit('playerReload', player, playerActiveWeapon);
|
|
1342
1449
|
}
|
|
1343
1450
|
|
|
1451
|
+
#processGameRequestOptionsPacket() {
|
|
1452
|
+
const out = CommOut.getBuffer();
|
|
1453
|
+
out.packInt8(CommCode.gameOptions);
|
|
1454
|
+
out.packInt8(this.game.options.gravity * 4);
|
|
1455
|
+
out.packInt8(this.game.options.damage * 4);
|
|
1456
|
+
out.packInt8(this.game.options.healthRegen * 4);
|
|
1457
|
+
|
|
1458
|
+
const flags =
|
|
1459
|
+
(this.game.options.locked ? 1 : 0) |
|
|
1460
|
+
(this.game.options.noTeamChange ? 2 : 0) |
|
|
1461
|
+
(this.game.options.noTeamShuffle ? 4 : 0);
|
|
1462
|
+
|
|
1463
|
+
out.packInt8(flags);
|
|
1464
|
+
|
|
1465
|
+
this.game.options.weaponsDisabled.forEach((v) => {
|
|
1466
|
+
out.packInt8(v ? 1 : 0);
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
#processExplodePacket() {
|
|
1471
|
+
const itemType = CommIn.unPackInt8U();
|
|
1472
|
+
let item = CommIn.unPackInt16U();
|
|
1473
|
+
const x = CommIn.unPackFloat();
|
|
1474
|
+
const y = CommIn.unPackFloat();
|
|
1475
|
+
const z = CommIn.unPackFloat();
|
|
1476
|
+
const damage = CommIn.unPackInt8U();
|
|
1477
|
+
const radius = CommIn.unPackFloat();
|
|
1478
|
+
|
|
1479
|
+
if (this.intents.includes(this.Intents.COSMETIC_DATA))
|
|
1480
|
+
item = findItemById(item);
|
|
1481
|
+
|
|
1482
|
+
if (itemType == ItemTypes.Grenade) this.#emit('grenadeExploded', item, { x, y, z }, damage, radius);
|
|
1483
|
+
else this.#emit('rocketHit', { x, y, z }, damage, radius);
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
#processThrowGrenadePacket() {
|
|
1487
|
+
const id = CommIn.unPackInt8U();
|
|
1488
|
+
const x = CommIn.unPackFloat();
|
|
1489
|
+
const y = CommIn.unPackFloat();
|
|
1490
|
+
const z = CommIn.unPackFloat();
|
|
1491
|
+
const dx = CommIn.unPackFloat();
|
|
1492
|
+
const dy = CommIn.unPackFloat();
|
|
1493
|
+
const dz = CommIn.unPackFloat();
|
|
1494
|
+
|
|
1495
|
+
const player = this.players[id];
|
|
1496
|
+
|
|
1497
|
+
if (player) {
|
|
1498
|
+
player.grenades--;
|
|
1499
|
+
this.#emit('playerThrowGrenade', player, { x, y, z }, { x: dx, y: dy, z: dz });
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1344
1503
|
#handlePacket(packet) {
|
|
1345
1504
|
CommIn.init(packet);
|
|
1346
|
-
this.#emit('packet', packet);
|
|
1347
|
-
const cmd = CommIn.unPackInt8U();
|
|
1348
|
-
switch (cmd) {
|
|
1349
|
-
case CommCode.chat:
|
|
1350
|
-
this.#processChatPacket(packet);
|
|
1351
|
-
break;
|
|
1352
1505
|
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
break;
|
|
1506
|
+
let lastCommand = 0;
|
|
1507
|
+
let abort = false;
|
|
1356
1508
|
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
break;
|
|
1509
|
+
while (CommIn.isMoreDataAvailable() && !abort) {
|
|
1510
|
+
const cmd = CommIn.unPackInt8U();
|
|
1360
1511
|
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1512
|
+
switch (cmd) {
|
|
1513
|
+
case CommCode.syncThem:
|
|
1514
|
+
this.#processExternalSyncPacket(packet);
|
|
1515
|
+
break;
|
|
1364
1516
|
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1517
|
+
case CommCode.fire:
|
|
1518
|
+
this.#processFirePacket(packet);
|
|
1519
|
+
break;
|
|
1368
1520
|
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1521
|
+
case CommCode.hitThem:
|
|
1522
|
+
this.#processHitThemPacket(packet);
|
|
1523
|
+
break;
|
|
1372
1524
|
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1525
|
+
case CommCode.syncMe:
|
|
1526
|
+
this.#processSyncMePacket(packet);
|
|
1527
|
+
break;
|
|
1376
1528
|
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1529
|
+
case CommCode.hitMe:
|
|
1530
|
+
this.#processHitMePacket(packet);
|
|
1531
|
+
break;
|
|
1380
1532
|
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1533
|
+
case CommCode.swapWeapon:
|
|
1534
|
+
this.#processSwapWeaponPacket(packet);
|
|
1535
|
+
break;
|
|
1384
1536
|
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1537
|
+
case CommCode.collectItem:
|
|
1538
|
+
this.#processCollectPacket(packet);
|
|
1539
|
+
break;
|
|
1388
1540
|
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1541
|
+
case CommCode.respawn:
|
|
1542
|
+
this.#processRespawnPacket(packet);
|
|
1543
|
+
break;
|
|
1392
1544
|
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1545
|
+
case CommCode.die:
|
|
1546
|
+
this.#processDeathPacket(packet);
|
|
1547
|
+
break;
|
|
1396
1548
|
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1549
|
+
case CommCode.pause:
|
|
1550
|
+
this.#processPausePacket(packet);
|
|
1551
|
+
break;
|
|
1400
1552
|
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1553
|
+
case CommCode.chat:
|
|
1554
|
+
this.#processChatPacket(packet);
|
|
1555
|
+
break;
|
|
1404
1556
|
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1557
|
+
case CommCode.addPlayer:
|
|
1558
|
+
this.#processAddPlayerPacket(packet);
|
|
1559
|
+
break;
|
|
1408
1560
|
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1561
|
+
case CommCode.removePlayer:
|
|
1562
|
+
this.#processRemovePlayerPacket(packet);
|
|
1563
|
+
break;
|
|
1412
1564
|
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1565
|
+
case CommCode.eventModifier:
|
|
1566
|
+
this.#processEventModifierPacket(packet);
|
|
1567
|
+
break;
|
|
1416
1568
|
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1569
|
+
case CommCode.metaGameState:
|
|
1570
|
+
this.#processGameStatePacket(packet);
|
|
1571
|
+
break;
|
|
1420
1572
|
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1573
|
+
case CommCode.beginShellStreak:
|
|
1574
|
+
this.#processBeginStreakPacket(packet);
|
|
1575
|
+
break;
|
|
1424
1576
|
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1577
|
+
case CommCode.endShellStreak:
|
|
1578
|
+
this.#processEndStreakPacket(packet);
|
|
1579
|
+
break;
|
|
1428
1580
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1581
|
+
case CommCode.hitMeHardBoiled:
|
|
1582
|
+
this.#processHitShieldPacket(packet);
|
|
1583
|
+
break;
|
|
1432
1584
|
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1585
|
+
case CommCode.gameOptions:
|
|
1586
|
+
this.#processGameOptionsPacket(packet);
|
|
1587
|
+
break;
|
|
1436
1588
|
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1589
|
+
case CommCode.ping:
|
|
1590
|
+
this.#processPingPacket(packet);
|
|
1591
|
+
break;
|
|
1440
1592
|
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1593
|
+
case CommCode.switchTeam:
|
|
1594
|
+
this.#processSwitchTeamPacket(packet);
|
|
1595
|
+
break;
|
|
1444
1596
|
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1597
|
+
case CommCode.changeCharacter:
|
|
1598
|
+
this.#processChangeCharacterPacket(packet);
|
|
1599
|
+
break;
|
|
1448
1600
|
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1601
|
+
case CommCode.reload:
|
|
1602
|
+
this.processReloadPacket(null, true);
|
|
1603
|
+
break;
|
|
1452
1604
|
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1605
|
+
case CommCode.explode:
|
|
1606
|
+
this.#processExplodePacket();
|
|
1607
|
+
break;
|
|
1456
1608
|
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1609
|
+
case CommCode.throwGrenade:
|
|
1610
|
+
this.#processThrowGrenadePacket();
|
|
1611
|
+
break;
|
|
1612
|
+
|
|
1613
|
+
case CommCode.spawnItem:
|
|
1614
|
+
this.#processSpawnItemPacket();
|
|
1615
|
+
break;
|
|
1616
|
+
|
|
1617
|
+
case CommCode.melee:
|
|
1618
|
+
this.#processMeleePacket();
|
|
1619
|
+
break;
|
|
1620
|
+
|
|
1621
|
+
case CommCode.updateBalance:
|
|
1622
|
+
this.#processUpdateBalancePacket(packet);
|
|
1623
|
+
break;
|
|
1624
|
+
|
|
1625
|
+
case CommCode.gameAction:
|
|
1626
|
+
this.#processGameActionPacket(packet);
|
|
1627
|
+
break;
|
|
1628
|
+
|
|
1629
|
+
case CommCode.requestGameOptions:
|
|
1630
|
+
this.#processGameRequestOptionsPacket();
|
|
1631
|
+
break;
|
|
1632
|
+
|
|
1633
|
+
case CommCode.respawnDenied:
|
|
1634
|
+
this.#processRespawnDeniedPacket(packet);
|
|
1635
|
+
break;
|
|
1460
1636
|
|
|
1461
|
-
case CommCode.clientReady:
|
|
1462
|
-
case CommCode.expireUpgrade:
|
|
1463
|
-
case CommCode.musicInfo:
|
|
1464
|
-
case CommCode.challengeCompleted:
|
|
1465
1637
|
// we do not plan to implement these
|
|
1466
1638
|
// for more info, see comm/codes.js
|
|
1467
|
-
|
|
1639
|
+
case CommCode.clientReady:
|
|
1640
|
+
case CommCode.expireUpgrade:
|
|
1641
|
+
break;
|
|
1468
1642
|
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
break;
|
|
1643
|
+
case CommCode.musicInfo:
|
|
1644
|
+
CommIn.unPackLongString();
|
|
1645
|
+
break;
|
|
1473
1646
|
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1647
|
+
case CommCode.challengeCompleted:
|
|
1648
|
+
CommIn.unPackInt8U();
|
|
1649
|
+
CommIn.unPackInt8U();
|
|
1650
|
+
break;
|
|
1651
|
+
|
|
1652
|
+
default:
|
|
1653
|
+
console.error(`handlePacket: I got but did not handle a: ${Object.keys(CommCode).find(k => CommCode[k] === cmd)}`);
|
|
1654
|
+
if (lastCommand) console.error(`handlePacket: It may be a result of the ${lastCommand} command.`);
|
|
1655
|
+
abort = true
|
|
1656
|
+
break;
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
lastCommand = Object.keys(CommCode).find(k => CommCode[k] === cmd);
|
|
1477
1660
|
}
|
|
1478
1661
|
}
|
|
1662
|
+
|
|
1663
|
+
async checkChiknWinner() {
|
|
1664
|
+
const response = await queryServices({
|
|
1665
|
+
cmd: 'chicknWinnerReady',
|
|
1666
|
+
id: this.account.id,
|
|
1667
|
+
sessionId: this.account.sessionId
|
|
1668
|
+
});
|
|
1669
|
+
|
|
1670
|
+
this.account.cw.limit = response.limit;
|
|
1671
|
+
this.account.cw.atLimit = response.limit > 3;
|
|
1672
|
+
|
|
1673
|
+
// if there is a "span", that means that it's under the daily limit and you can play again soon
|
|
1674
|
+
// if there is a "period", that means that the account is done for the day and must wait a long time
|
|
1675
|
+
this.account.cw.secondsUntilPlay = response.span || response.period || 0;
|
|
1676
|
+
this.account.cw.canPlayAgain = Date.now() + (this.account.cw.secondsUntilPlay * 1000);
|
|
1677
|
+
|
|
1678
|
+
return this.account.cw;
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
async playChiknWinner() {
|
|
1682
|
+
if (this.account.cw.atLimit || this.account.cw.limit > ChiknWinnerDailyLimit) return 'hit_daily_limit';
|
|
1683
|
+
if (this.account.cw.canPlayAgain > Date.now()) return 'on_cooldown';
|
|
1684
|
+
|
|
1685
|
+
const response = await queryServices({
|
|
1686
|
+
cmd: 'incentivizedVideoReward',
|
|
1687
|
+
firebaseId: this.account.firebaseId,
|
|
1688
|
+
id: this.account.id,
|
|
1689
|
+
sessionId: this.account.sessionId,
|
|
1690
|
+
token: null
|
|
1691
|
+
}, this.proxy, this.instance);
|
|
1692
|
+
|
|
1693
|
+
if (response.error) {
|
|
1694
|
+
if (response.error == 'RATELIMITED') {
|
|
1695
|
+
await this.checkChiknWinner();
|
|
1696
|
+
return 'on_cooldown';
|
|
1697
|
+
} else if (response.error == 'SESSION_EXPIRED') {
|
|
1698
|
+
return 'session_expired';
|
|
1699
|
+
} else {
|
|
1700
|
+
console.error('Unknown Chikn Winner response', response);
|
|
1701
|
+
return 'unknown_error';
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
if (response.reward) {
|
|
1706
|
+
this.account.eggBalance += response.reward.eggsGiven;
|
|
1707
|
+
response.reward.itemIds.forEach((id) => this.account.ownedItemIds.push(id));
|
|
1708
|
+
|
|
1709
|
+
await this.checkChiknWinner();
|
|
1710
|
+
|
|
1711
|
+
return response.reward;
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
console.error('Unknown Chikn Winner response', response);
|
|
1715
|
+
return 'unknown_error';
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
async resetChiknWinner() {
|
|
1719
|
+
if (this.account.eggBalance < 200) return 'not_enough_eggs';
|
|
1720
|
+
if (!this.account.cw.atLimit) return 'not_at_limit';
|
|
1721
|
+
|
|
1722
|
+
const response = await queryServices({
|
|
1723
|
+
cmd: 'chwReset',
|
|
1724
|
+
sessionId: this.account.sessionId
|
|
1725
|
+
});
|
|
1726
|
+
|
|
1727
|
+
if (response.result !== 'SUCCESS') {
|
|
1728
|
+
console.error('Unknown Chikn Winner reset response', response);
|
|
1729
|
+
return 'unknown_error';
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
this.account.eggBalance -= 200;
|
|
1733
|
+
await this.checkChiknWinner();
|
|
1734
|
+
|
|
1735
|
+
return this.account.cw;
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
canSee(target) {
|
|
1739
|
+
if (!this.intents.includes(this.Intents.PATHFINDING)) throw new Error('You must have the PATHFINDING intent to use this method.');
|
|
1740
|
+
return this.pathing.nodeList.hasLineOfSight(this.me.position, target.position);
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
getBestTarget() {
|
|
1744
|
+
const options = Object.values(this.players)
|
|
1745
|
+
.filter((player) => player)
|
|
1746
|
+
.filter((player) => player !== this.me)
|
|
1747
|
+
.filter((player) => player.playing)
|
|
1748
|
+
.filter((player) => player.hp > 0)
|
|
1749
|
+
.filter((player) => player.name !== this.me.name)
|
|
1750
|
+
.filter((player) => this.me.team === 0 || player.team !== this.me.team)
|
|
1751
|
+
.filter((player) => this.canSee(player));
|
|
1752
|
+
|
|
1753
|
+
let minDistance = 200;
|
|
1754
|
+
let targetPlayer = null;
|
|
1755
|
+
|
|
1756
|
+
for (const player of options) {
|
|
1757
|
+
const dx = player.position.x - this.me.position.x;
|
|
1758
|
+
const dy = player.position.y - this.me.position.y;
|
|
1759
|
+
const dz = player.position.z - this.me.position.z;
|
|
1760
|
+
|
|
1761
|
+
const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
1762
|
+
|
|
1763
|
+
if (distance < minDistance) {
|
|
1764
|
+
minDistance = distance;
|
|
1765
|
+
targetPlayer = player;
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
return targetPlayer;
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
async refreshBalance() {
|
|
1773
|
+
const result = await queryServices({
|
|
1774
|
+
cmd: 'checkBalance',
|
|
1775
|
+
firebaseId: this.account.firebaseId,
|
|
1776
|
+
sessionId: this.account.sessionId
|
|
1777
|
+
}, this.proxy, this.instance);
|
|
1778
|
+
|
|
1779
|
+
this.account.eggBalance = result.currentBalance;
|
|
1780
|
+
|
|
1781
|
+
return result.currentBalance;
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
async redeemCode(code) {
|
|
1785
|
+
const result = await queryServices({
|
|
1786
|
+
cmd: 'redeem',
|
|
1787
|
+
firebaseId: this.account.firebaseId,
|
|
1788
|
+
sessionId: this.account.sessionId,
|
|
1789
|
+
id: this.account.id,
|
|
1790
|
+
code
|
|
1791
|
+
}, this.proxy, this.instance);
|
|
1792
|
+
|
|
1793
|
+
if (result.result === 'SUCCESS') {
|
|
1794
|
+
this.account.eggBalance = result.eggs_given;
|
|
1795
|
+
result.item_ids.forEach((id) => this.account.ownedItemIds.push(id));
|
|
1796
|
+
|
|
1797
|
+
return {
|
|
1798
|
+
result,
|
|
1799
|
+
eggsGiven: result.eggs_given,
|
|
1800
|
+
itemIds: result.item_ids
|
|
1801
|
+
};
|
|
1802
|
+
} else return result;
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
async claimURLReward(reward) {
|
|
1806
|
+
const result = await queryServices({
|
|
1807
|
+
cmd: 'urlRewardParams',
|
|
1808
|
+
firebaseId: this.account.firebaseId,
|
|
1809
|
+
sessionId: this.account.sessionId,
|
|
1810
|
+
reward
|
|
1811
|
+
}, this.proxy, this.instance);
|
|
1812
|
+
|
|
1813
|
+
if (result.result === 'SUCCESS') {
|
|
1814
|
+
this.account.eggBalance += result.eggsGiven;
|
|
1815
|
+
result.itemIds.forEach((id) => this.account.ownedItemIds.push(id));
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
return result;
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
async claimSocialReward(rewardTag) {
|
|
1822
|
+
const result = await queryServices({
|
|
1823
|
+
cmd: 'reward',
|
|
1824
|
+
firebaseId: this.account.firebaseId,
|
|
1825
|
+
sessionId: this.account.sessionId,
|
|
1826
|
+
rewardTag
|
|
1827
|
+
}, this.proxy, this.instance);
|
|
1828
|
+
|
|
1829
|
+
if (result.result === 'SUCCESS') {
|
|
1830
|
+
this.account.eggBalance += result.eggsGiven;
|
|
1831
|
+
result.itemIds.forEach((id) => this.account.ownedItemIds.push(id));
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
return result;
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
async buyItem(itemId) {
|
|
1838
|
+
const result = await queryServices({
|
|
1839
|
+
cmd: 'buy',
|
|
1840
|
+
firebaseId: this.account.firebaseId,
|
|
1841
|
+
sessionId: this.account.sessionId,
|
|
1842
|
+
itemId,
|
|
1843
|
+
save: true
|
|
1844
|
+
}, this.proxy, this.instance);
|
|
1845
|
+
|
|
1846
|
+
if (result.result === 'SUCCESS') {
|
|
1847
|
+
this.account.eggBalance = result.currentBalance;
|
|
1848
|
+
this.account.ownedItemIds.push(result.itemId);
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
return result;
|
|
1852
|
+
}
|
|
1479
1853
|
}
|
|
1480
1854
|
|
|
1481
1855
|
export default Bot;
|