specprotocol 1.2.0 → 1.4.0
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/dist/bot.d.ts +88 -0
- package/dist/bot.d.ts.map +1 -1
- package/dist/bot.js +280 -8
- package/dist/bot.js.map +1 -1
- package/dist/protocol/states/play.d.ts +259 -17
- package/dist/protocol/states/play.d.ts.map +1 -1
- package/dist/protocol/states/play.js +442 -24
- package/dist/protocol/states/play.js.map +1 -1
- package/dist/protocol/types.d.ts +15 -1
- package/dist/protocol/types.d.ts.map +1 -1
- package/dist/protocol/types.js +64 -34
- package/dist/protocol/types.js.map +1 -1
- package/package.json +1 -1
package/dist/bot.d.ts
CHANGED
|
@@ -36,8 +36,26 @@ export interface BotEvents {
|
|
|
36
36
|
'entitySpawn': (entity: Entity) => void;
|
|
37
37
|
/** Entity removed */
|
|
38
38
|
'entityRemove': (entityId: number) => void;
|
|
39
|
+
/** Entity moved */
|
|
40
|
+
'entityMove': (entityId: number, position: Vec3) => void;
|
|
41
|
+
/** Entity velocity changed */
|
|
42
|
+
'entityVelocity': (entityId: number, velocity: Vec3) => void;
|
|
39
43
|
/** Block updated */
|
|
40
44
|
'blockUpdate': (x: number, y: number, z: number, stateId: number) => void;
|
|
45
|
+
/** Experience updated */
|
|
46
|
+
'experience': (level: number, progress: number, total: number) => void;
|
|
47
|
+
/** Game event (weather, gamemode change, etc.) */
|
|
48
|
+
'gameEvent': (event: number, value: number) => void;
|
|
49
|
+
/** Respawned in a new dimension */
|
|
50
|
+
'respawn': (dimension: string, gameMode: number) => void;
|
|
51
|
+
/** Time updated */
|
|
52
|
+
'time': (worldAge: bigint, timeOfDay: bigint) => void;
|
|
53
|
+
/** Spawn position set */
|
|
54
|
+
'spawnPosition': (x: number, y: number, z: number) => void;
|
|
55
|
+
/** Title text displayed */
|
|
56
|
+
'title': (text: string) => void;
|
|
57
|
+
/** Subtitle text displayed */
|
|
58
|
+
'subtitle': (text: string) => void;
|
|
41
59
|
/** Raw packet received (for advanced use) */
|
|
42
60
|
'rawPacket': (packet: RawPacket) => void;
|
|
43
61
|
/** Connection error */
|
|
@@ -73,6 +91,15 @@ export declare class Bot extends TypedEventEmitter<BotEvents> {
|
|
|
73
91
|
private _saturation;
|
|
74
92
|
private _gameMode;
|
|
75
93
|
private _isAlive;
|
|
94
|
+
private _experience;
|
|
95
|
+
private _level;
|
|
96
|
+
private _isSprinting;
|
|
97
|
+
private _isSneaking;
|
|
98
|
+
private _worldAge;
|
|
99
|
+
private _timeOfDay;
|
|
100
|
+
private _spawnPosition;
|
|
101
|
+
private _actionSequence;
|
|
102
|
+
private physicsInterval;
|
|
76
103
|
private authMode;
|
|
77
104
|
private accessToken?;
|
|
78
105
|
readonly world: World;
|
|
@@ -121,6 +148,8 @@ export declare class Bot extends TypedEventEmitter<BotEvents> {
|
|
|
121
148
|
private handleConfigurationState;
|
|
122
149
|
private setupPlayStateHandlers;
|
|
123
150
|
private handlePlayPacket;
|
|
151
|
+
private startPhysicsTick;
|
|
152
|
+
private stopPhysicsTick;
|
|
124
153
|
/**
|
|
125
154
|
* Register a handler for a specific play-state packet ID.
|
|
126
155
|
* Used by plugins to listen for specific packets.
|
|
@@ -130,14 +159,33 @@ export declare class Bot extends TypedEventEmitter<BotEvents> {
|
|
|
130
159
|
* Send a raw packet to the server.
|
|
131
160
|
*/
|
|
132
161
|
sendPacket(packetId: number, data: Buffer): void;
|
|
162
|
+
get experience(): number;
|
|
163
|
+
get level(): number;
|
|
164
|
+
get isSprinting(): boolean;
|
|
165
|
+
get isSneaking(): boolean;
|
|
166
|
+
get worldAge(): bigint;
|
|
167
|
+
get timeOfDay(): bigint;
|
|
168
|
+
get spawnPosition(): Vec3;
|
|
133
169
|
/**
|
|
134
170
|
* Send a chat message.
|
|
135
171
|
*/
|
|
136
172
|
chat(message: string): void;
|
|
173
|
+
/**
|
|
174
|
+
* Send a / command (e.g. bot.command('gamemode creative')).
|
|
175
|
+
*/
|
|
176
|
+
command(cmd: string): void;
|
|
137
177
|
/**
|
|
138
178
|
* Attack an entity.
|
|
139
179
|
*/
|
|
140
180
|
attack(entity: Entity): void;
|
|
181
|
+
/**
|
|
182
|
+
* Attack entity by ID (raw packet).
|
|
183
|
+
*/
|
|
184
|
+
attackEntity(entityId: number): void;
|
|
185
|
+
/**
|
|
186
|
+
* Right-click / use an entity (villager trade, mount, etc.).
|
|
187
|
+
*/
|
|
188
|
+
useEntity(entityId: number, hand?: number): void;
|
|
141
189
|
/**
|
|
142
190
|
* Set the bot's position (sends position packet to server).
|
|
143
191
|
*/
|
|
@@ -150,14 +198,54 @@ export declare class Bot extends TypedEventEmitter<BotEvents> {
|
|
|
150
198
|
* Look at a position.
|
|
151
199
|
*/
|
|
152
200
|
lookAt(target: Vec3): void;
|
|
201
|
+
/**
|
|
202
|
+
* Start/stop sprinting.
|
|
203
|
+
*/
|
|
204
|
+
sprint(enabled: boolean): void;
|
|
205
|
+
/**
|
|
206
|
+
* Start/stop sneaking.
|
|
207
|
+
*/
|
|
208
|
+
sneak(enabled: boolean): void;
|
|
153
209
|
/**
|
|
154
210
|
* Start digging a block.
|
|
155
211
|
*/
|
|
156
212
|
dig(x: number, y: number, z: number, face?: number): void;
|
|
213
|
+
/**
|
|
214
|
+
* Place a block on a target block face.
|
|
215
|
+
*/
|
|
216
|
+
placeBlock(x: number, y: number, z: number, face?: number, hand?: number): void;
|
|
217
|
+
/**
|
|
218
|
+
* Use the item in hand (eat, throw, shoot bow, etc.).
|
|
219
|
+
*/
|
|
220
|
+
useItem(hand?: number): void;
|
|
157
221
|
/**
|
|
158
222
|
* Select a hotbar slot (0-8).
|
|
159
223
|
*/
|
|
160
224
|
setHeldItem(slot: number): void;
|
|
225
|
+
/**
|
|
226
|
+
* Swing arm animation.
|
|
227
|
+
*/
|
|
228
|
+
swingArm(hand?: number): void;
|
|
229
|
+
/**
|
|
230
|
+
* Drop the held item.
|
|
231
|
+
*/
|
|
232
|
+
dropItem(dropStack?: boolean): void;
|
|
233
|
+
/**
|
|
234
|
+
* Swap items between main and off hand.
|
|
235
|
+
*/
|
|
236
|
+
swapHands(): void;
|
|
237
|
+
/**
|
|
238
|
+
* Toggle flying (creative/spectator mode).
|
|
239
|
+
*/
|
|
240
|
+
fly(enabled: boolean): void;
|
|
241
|
+
/**
|
|
242
|
+
* Respawn after death.
|
|
243
|
+
*/
|
|
244
|
+
respawn(): void;
|
|
245
|
+
/**
|
|
246
|
+
* Close the currently open container.
|
|
247
|
+
*/
|
|
248
|
+
closeContainer(windowId?: number): void;
|
|
161
249
|
/**
|
|
162
250
|
* Disconnect from the server.
|
|
163
251
|
*/
|
package/dist/bot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAU,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"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"}
|
package/dist/bot.js
CHANGED
|
@@ -48,6 +48,15 @@ class Bot extends events_js_1.TypedEventEmitter {
|
|
|
48
48
|
_saturation = 5;
|
|
49
49
|
_gameMode = 0;
|
|
50
50
|
_isAlive = true;
|
|
51
|
+
_experience = 0;
|
|
52
|
+
_level = 0;
|
|
53
|
+
_isSprinting = false;
|
|
54
|
+
_isSneaking = false;
|
|
55
|
+
_worldAge = 0n;
|
|
56
|
+
_timeOfDay = 0n;
|
|
57
|
+
_spawnPosition = new vec3_js_1.Vec3(0, 0, 0);
|
|
58
|
+
_actionSequence = 0;
|
|
59
|
+
physicsInterval = null;
|
|
51
60
|
// Auth
|
|
52
61
|
authMode;
|
|
53
62
|
accessToken;
|
|
@@ -389,6 +398,13 @@ class Bot extends events_js_1.TypedEventEmitter {
|
|
|
389
398
|
this.connection.sendPacket(play_js_1.PlayServerboundPackets.KEEP_ALIVE, (0, play_js_1.buildKeepAlivePacket)(keepAliveId));
|
|
390
399
|
break;
|
|
391
400
|
}
|
|
401
|
+
case play_js_1.PlayClientboundPackets.CHUNK_BATCH_FINISHED: {
|
|
402
|
+
// Must respond with chunk_batch_received or server kicks
|
|
403
|
+
const writer = new types_js_1.BufferWriter();
|
|
404
|
+
writer.writeFloat(20.0); // chunks per tick
|
|
405
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.CHUNK_BATCH_RECEIVED, writer.toBuffer());
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
392
408
|
case play_js_1.PlayClientboundPackets.LOGIN: {
|
|
393
409
|
try {
|
|
394
410
|
const login = (0, play_js_1.parseLoginPlay)(packet.data);
|
|
@@ -398,6 +414,8 @@ class Bot extends events_js_1.TypedEventEmitter {
|
|
|
398
414
|
this.world.dimension = login.dimensionName;
|
|
399
415
|
this.world.seaLevel = login.seaLevel;
|
|
400
416
|
this.logger.info(`Spawned in ${login.dimensionName} (Entity ID: ${login.entityId})`);
|
|
417
|
+
// Start physics tick (50ms = 20 ticks/sec like vanilla)
|
|
418
|
+
this.startPhysicsTick();
|
|
401
419
|
this.emit('spawn');
|
|
402
420
|
}
|
|
403
421
|
catch (err) {
|
|
@@ -431,11 +449,17 @@ class Bot extends events_js_1.TypedEventEmitter {
|
|
|
431
449
|
this._food = food;
|
|
432
450
|
this._saturation = saturation;
|
|
433
451
|
this.emit('health', health, food, saturation);
|
|
434
|
-
if (health <= 0) {
|
|
452
|
+
if (health <= 0 && this._isAlive) {
|
|
435
453
|
this._isAlive = false;
|
|
436
454
|
this.emit('death');
|
|
455
|
+
// Auto-respawn after short delay
|
|
456
|
+
setTimeout(() => {
|
|
457
|
+
if (!this._isAlive && this.connection.connected) {
|
|
458
|
+
this.respawn();
|
|
459
|
+
}
|
|
460
|
+
}, 1000);
|
|
437
461
|
}
|
|
438
|
-
else {
|
|
462
|
+
else if (health > 0) {
|
|
439
463
|
this._isAlive = true;
|
|
440
464
|
}
|
|
441
465
|
break;
|
|
@@ -467,10 +491,8 @@ class Bot extends events_js_1.TypedEventEmitter {
|
|
|
467
491
|
}
|
|
468
492
|
case play_js_1.PlayClientboundPackets.REMOVE_ENTITIES: {
|
|
469
493
|
try {
|
|
470
|
-
const
|
|
471
|
-
const
|
|
472
|
-
for (let i = 0; i < count; i++) {
|
|
473
|
-
const entityId = reader.readVarInt();
|
|
494
|
+
const { entityIds } = (0, play_js_1.parseRemoveEntities)(packet.data);
|
|
495
|
+
for (const entityId of entityIds) {
|
|
474
496
|
this.entities.remove(entityId);
|
|
475
497
|
this.emit('entityRemove', entityId);
|
|
476
498
|
}
|
|
@@ -480,9 +502,129 @@ class Bot extends events_js_1.TypedEventEmitter {
|
|
|
480
502
|
}
|
|
481
503
|
break;
|
|
482
504
|
}
|
|
505
|
+
case play_js_1.PlayClientboundPackets.ENTITY_POSITION: {
|
|
506
|
+
try {
|
|
507
|
+
const pos = (0, play_js_1.parseEntityPosition)(packet.data);
|
|
508
|
+
const entity = this.entities.get(pos.entityId);
|
|
509
|
+
if (entity) {
|
|
510
|
+
entity.position = new vec3_js_1.Vec3(entity.position.x + pos.deltaX, entity.position.y + pos.deltaY, entity.position.z + pos.deltaZ);
|
|
511
|
+
this.emit('entityMove', pos.entityId, entity.position);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
catch (_) { /* ignore */ }
|
|
515
|
+
break;
|
|
516
|
+
}
|
|
517
|
+
case play_js_1.PlayClientboundPackets.ENTITY_POSITION_AND_ROTATION: {
|
|
518
|
+
try {
|
|
519
|
+
const pos = (0, play_js_1.parseEntityPositionAndRotation)(packet.data);
|
|
520
|
+
const entity = this.entities.get(pos.entityId);
|
|
521
|
+
if (entity) {
|
|
522
|
+
entity.position = new vec3_js_1.Vec3(entity.position.x + pos.deltaX, entity.position.y + pos.deltaY, entity.position.z + pos.deltaZ);
|
|
523
|
+
entity.yaw = pos.yaw;
|
|
524
|
+
entity.pitch = pos.pitch;
|
|
525
|
+
this.emit('entityMove', pos.entityId, entity.position);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
catch (_) { /* ignore */ }
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
531
|
+
case play_js_1.PlayClientboundPackets.SET_ENTITY_VELOCITY: {
|
|
532
|
+
try {
|
|
533
|
+
const vel = (0, play_js_1.parseEntityVelocity)(packet.data);
|
|
534
|
+
this.emit('entityVelocity', vel.entityId, new vec3_js_1.Vec3(vel.velocityX, vel.velocityY, vel.velocityZ));
|
|
535
|
+
}
|
|
536
|
+
catch (_) { /* ignore */ }
|
|
537
|
+
break;
|
|
538
|
+
}
|
|
539
|
+
case play_js_1.PlayClientboundPackets.ENTITY_HEAD_ROTATION: {
|
|
540
|
+
try {
|
|
541
|
+
const rot = (0, play_js_1.parseEntityHeadRotation)(packet.data);
|
|
542
|
+
const entity = this.entities.get(rot.entityId);
|
|
543
|
+
if (entity) {
|
|
544
|
+
entity.yaw = rot.headYaw;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
catch (_) { /* ignore */ }
|
|
548
|
+
break;
|
|
549
|
+
}
|
|
550
|
+
case play_js_1.PlayClientboundPackets.GAME_EVENT: {
|
|
551
|
+
try {
|
|
552
|
+
const ev = (0, play_js_1.parseGameEvent)(packet.data);
|
|
553
|
+
if (ev.event === play_js_1.GameEventType.CHANGE_GAME_MODE) {
|
|
554
|
+
this._gameMode = ev.value;
|
|
555
|
+
}
|
|
556
|
+
if (ev.event === play_js_1.GameEventType.START_WAITING_FOR_LEVEL_CHUNKS) {
|
|
557
|
+
// Send position confirmation after chunks start loading
|
|
558
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.SET_PLAYER_POSITION_AND_ROTATION, (0, play_js_1.buildSetPlayerPositionAndRotationPacket)(this.entity.position.x, this.entity.position.y, this.entity.position.z, this.entity.yaw, this.entity.pitch, true));
|
|
559
|
+
}
|
|
560
|
+
this.emit('gameEvent', ev.event, ev.value);
|
|
561
|
+
}
|
|
562
|
+
catch (_) { /* ignore */ }
|
|
563
|
+
break;
|
|
564
|
+
}
|
|
565
|
+
case play_js_1.PlayClientboundPackets.RESPAWN: {
|
|
566
|
+
try {
|
|
567
|
+
const resp = (0, play_js_1.parseRespawn)(packet.data);
|
|
568
|
+
this._gameMode = resp.gameMode;
|
|
569
|
+
this._isAlive = true;
|
|
570
|
+
this.world.dimension = resp.dimensionName;
|
|
571
|
+
this.emit('respawn', resp.dimensionName, resp.gameMode);
|
|
572
|
+
this.logger.info(`Respawned in ${resp.dimensionName}`);
|
|
573
|
+
}
|
|
574
|
+
catch (err) {
|
|
575
|
+
this.logger.error('Failed to parse respawn:', err);
|
|
576
|
+
}
|
|
577
|
+
break;
|
|
578
|
+
}
|
|
579
|
+
case play_js_1.PlayClientboundPackets.SET_EXPERIENCE: {
|
|
580
|
+
try {
|
|
581
|
+
const exp = (0, play_js_1.parseSetExperience)(packet.data);
|
|
582
|
+
this._experience = exp.totalExperience;
|
|
583
|
+
this._level = exp.level;
|
|
584
|
+
this.emit('experience', exp.level, exp.experienceBar, exp.totalExperience);
|
|
585
|
+
}
|
|
586
|
+
catch (_) { /* ignore */ }
|
|
587
|
+
break;
|
|
588
|
+
}
|
|
589
|
+
case play_js_1.PlayClientboundPackets.UPDATE_TIME: {
|
|
590
|
+
try {
|
|
591
|
+
const time = (0, play_js_1.parseUpdateTime)(packet.data);
|
|
592
|
+
this._worldAge = time.worldAge;
|
|
593
|
+
this._timeOfDay = time.timeOfDay;
|
|
594
|
+
this.emit('time', time.worldAge, time.timeOfDay);
|
|
595
|
+
}
|
|
596
|
+
catch (_) { /* ignore */ }
|
|
597
|
+
break;
|
|
598
|
+
}
|
|
599
|
+
case play_js_1.PlayClientboundPackets.SET_DEFAULT_SPAWN_POSITION: {
|
|
600
|
+
try {
|
|
601
|
+
const sp = (0, play_js_1.parseSetDefaultSpawnPosition)(packet.data);
|
|
602
|
+
this._spawnPosition = new vec3_js_1.Vec3(sp.x, sp.y, sp.z);
|
|
603
|
+
this.emit('spawnPosition', sp.x, sp.y, sp.z);
|
|
604
|
+
}
|
|
605
|
+
catch (_) { /* ignore */ }
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
case play_js_1.PlayClientboundPackets.PING: {
|
|
609
|
+
try {
|
|
610
|
+
const reader = new types_js_1.BufferReader(packet.data);
|
|
611
|
+
const pingId = reader.readInt();
|
|
612
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.PONG, (0, play_js_1.buildPongPacket)(pingId));
|
|
613
|
+
}
|
|
614
|
+
catch (_) { /* ignore */ }
|
|
615
|
+
break;
|
|
616
|
+
}
|
|
617
|
+
case play_js_1.PlayClientboundPackets.ACKNOWLEDGE_BLOCK_CHANGE: {
|
|
618
|
+
try {
|
|
619
|
+
(0, play_js_1.parseAcknowledgeBlockChange)(packet.data);
|
|
620
|
+
}
|
|
621
|
+
catch (_) { /* ignore */ }
|
|
622
|
+
break;
|
|
623
|
+
}
|
|
483
624
|
case play_js_1.PlayClientboundPackets.DISCONNECT: {
|
|
484
625
|
const { reason } = (0, play_js_1.parseDisconnectPlay)(packet.data);
|
|
485
626
|
this.logger.warn(`Kicked: ${reason}`);
|
|
627
|
+
this.stopPhysicsTick();
|
|
486
628
|
this.emit('kicked', reason);
|
|
487
629
|
break;
|
|
488
630
|
}
|
|
@@ -496,6 +638,36 @@ class Bot extends events_js_1.TypedEventEmitter {
|
|
|
496
638
|
}
|
|
497
639
|
break;
|
|
498
640
|
}
|
|
641
|
+
case play_js_1.PlayClientboundPackets.SYSTEM_CHAT: {
|
|
642
|
+
try {
|
|
643
|
+
const chat = (0, play_js_1.parseSystemChat)(packet.data);
|
|
644
|
+
this.emit('chat', chat.content, chat.isOverlay);
|
|
645
|
+
}
|
|
646
|
+
catch (_) { /* ignore */ }
|
|
647
|
+
break;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
// ─── Physics Tick ────────────────────────────────────
|
|
652
|
+
startPhysicsTick() {
|
|
653
|
+
if (this.physicsInterval)
|
|
654
|
+
return;
|
|
655
|
+
this.physicsInterval = setInterval(() => {
|
|
656
|
+
if (!this._isAlive || !this.connection.connected)
|
|
657
|
+
return;
|
|
658
|
+
// Send position to server every tick to stay "alive"
|
|
659
|
+
try {
|
|
660
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.SET_PLAYER_POSITION_AND_ROTATION, (0, play_js_1.buildSetPlayerPositionAndRotationPacket)(this.entity.position.x, this.entity.position.y, this.entity.position.z, this.entity.yaw, this.entity.pitch, true));
|
|
661
|
+
}
|
|
662
|
+
catch (_) {
|
|
663
|
+
this.stopPhysicsTick();
|
|
664
|
+
}
|
|
665
|
+
}, 50);
|
|
666
|
+
}
|
|
667
|
+
stopPhysicsTick() {
|
|
668
|
+
if (this.physicsInterval) {
|
|
669
|
+
clearInterval(this.physicsInterval);
|
|
670
|
+
this.physicsInterval = null;
|
|
499
671
|
}
|
|
500
672
|
}
|
|
501
673
|
// ─── Packet API ─────────────────────────────────────
|
|
@@ -514,6 +686,14 @@ class Bot extends events_js_1.TypedEventEmitter {
|
|
|
514
686
|
sendPacket(packetId, data) {
|
|
515
687
|
this.connection.sendPacket(packetId, data);
|
|
516
688
|
}
|
|
689
|
+
// ─── Property Getters ─────────────────────────────────
|
|
690
|
+
get experience() { return this._experience; }
|
|
691
|
+
get level() { return this._level; }
|
|
692
|
+
get isSprinting() { return this._isSprinting; }
|
|
693
|
+
get isSneaking() { return this._isSneaking; }
|
|
694
|
+
get worldAge() { return this._worldAge; }
|
|
695
|
+
get timeOfDay() { return this._timeOfDay; }
|
|
696
|
+
get spawnPosition() { return this._spawnPosition; }
|
|
517
697
|
// ─── High-Level API ─────────────────────────────────
|
|
518
698
|
/**
|
|
519
699
|
* Send a chat message.
|
|
@@ -524,6 +704,12 @@ class Bot extends events_js_1.TypedEventEmitter {
|
|
|
524
704
|
chatPlugin.chat(message);
|
|
525
705
|
}
|
|
526
706
|
}
|
|
707
|
+
/**
|
|
708
|
+
* Send a / command (e.g. bot.command('gamemode creative')).
|
|
709
|
+
*/
|
|
710
|
+
command(cmd) {
|
|
711
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.CHAT_COMMAND, (0, play_js_1.buildChatCommandPacket)(cmd));
|
|
712
|
+
}
|
|
527
713
|
/**
|
|
528
714
|
* Attack an entity.
|
|
529
715
|
*/
|
|
@@ -533,6 +719,19 @@ class Bot extends events_js_1.TypedEventEmitter {
|
|
|
533
719
|
combatPlugin.attack(entity);
|
|
534
720
|
}
|
|
535
721
|
}
|
|
722
|
+
/**
|
|
723
|
+
* Attack entity by ID (raw packet).
|
|
724
|
+
*/
|
|
725
|
+
attackEntity(entityId) {
|
|
726
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.INTERACT, (0, play_js_1.buildInteractEntityPacket)(entityId, play_js_1.InteractEntityType.ATTACK, this._isSneaking));
|
|
727
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.SWING_ARM, (0, play_js_1.buildSwingArmPacket)(0));
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* Right-click / use an entity (villager trade, mount, etc.).
|
|
731
|
+
*/
|
|
732
|
+
useEntity(entityId, hand = 0) {
|
|
733
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.INTERACT, (0, play_js_1.buildInteractEntityPacket)(entityId, play_js_1.InteractEntityType.INTERACT, this._isSneaking, undefined, undefined, undefined, hand));
|
|
734
|
+
}
|
|
536
735
|
/**
|
|
537
736
|
* Set the bot's position (sends position packet to server).
|
|
538
737
|
*/
|
|
@@ -563,17 +762,50 @@ class Bot extends events_js_1.TypedEventEmitter {
|
|
|
563
762
|
this.entity.pitch = pitch;
|
|
564
763
|
this.connection.sendPacket(play_js_1.PlayServerboundPackets.SET_PLAYER_POSITION_AND_ROTATION, (0, play_js_1.buildSetPlayerPositionAndRotationPacket)(this.entity.position.x, this.entity.position.y, this.entity.position.z, yaw, pitch, this.entity.onGround));
|
|
565
764
|
}
|
|
765
|
+
/**
|
|
766
|
+
* Start/stop sprinting.
|
|
767
|
+
*/
|
|
768
|
+
sprint(enabled) {
|
|
769
|
+
this._isSprinting = enabled;
|
|
770
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_COMMAND, (0, play_js_1.buildPlayerCommandPacket)(this._entityId, enabled ? play_js_1.PlayerCommandAction.START_SPRINTING : play_js_1.PlayerCommandAction.STOP_SPRINTING));
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* Start/stop sneaking.
|
|
774
|
+
*/
|
|
775
|
+
sneak(enabled) {
|
|
776
|
+
this._isSneaking = enabled;
|
|
777
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_COMMAND, (0, play_js_1.buildPlayerCommandPacket)(this._entityId, enabled ? play_js_1.PlayerCommandAction.START_SNEAKING : play_js_1.PlayerCommandAction.STOP_SNEAKING));
|
|
778
|
+
}
|
|
566
779
|
/**
|
|
567
780
|
* Start digging a block.
|
|
568
781
|
*/
|
|
569
782
|
dig(x, y, z, face = 1) {
|
|
783
|
+
this._actionSequence++;
|
|
570
784
|
// Start digging
|
|
571
|
-
this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_ACTION, (0, play_js_1.buildPlayerActionPacket)(play_js_1.PlayerActionStatus.STARTED_DIGGING, x, y, z, face,
|
|
785
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_ACTION, (0, play_js_1.buildPlayerActionPacket)(play_js_1.PlayerActionStatus.STARTED_DIGGING, x, y, z, face, this._actionSequence));
|
|
786
|
+
// Swing arm animation
|
|
787
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.SWING_ARM, (0, play_js_1.buildSwingArmPacket)(0));
|
|
572
788
|
// For creative mode, finish immediately
|
|
573
789
|
if (this._gameMode === 1) {
|
|
574
|
-
this.
|
|
790
|
+
this._actionSequence++;
|
|
791
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_ACTION, (0, play_js_1.buildPlayerActionPacket)(play_js_1.PlayerActionStatus.FINISHED_DIGGING, x, y, z, face, this._actionSequence));
|
|
575
792
|
}
|
|
576
793
|
}
|
|
794
|
+
/**
|
|
795
|
+
* Place a block on a target block face.
|
|
796
|
+
*/
|
|
797
|
+
placeBlock(x, y, z, face = 1, hand = 0) {
|
|
798
|
+
this._actionSequence++;
|
|
799
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.USE_ITEM_ON, (0, play_js_1.buildUseItemOnPacket)(hand, x, y, z, face, 0.5, 0.5, 0.5, false, false, this._actionSequence));
|
|
800
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.SWING_ARM, (0, play_js_1.buildSwingArmPacket)(hand));
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Use the item in hand (eat, throw, shoot bow, etc.).
|
|
804
|
+
*/
|
|
805
|
+
useItem(hand = 0) {
|
|
806
|
+
this._actionSequence++;
|
|
807
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.USE_ITEM, (0, play_js_1.buildUseItemPacket)(hand, this._actionSequence, this.entity.yaw, this.entity.pitch));
|
|
808
|
+
}
|
|
577
809
|
/**
|
|
578
810
|
* Select a hotbar slot (0-8).
|
|
579
811
|
*/
|
|
@@ -582,10 +814,50 @@ class Bot extends events_js_1.TypedEventEmitter {
|
|
|
582
814
|
throw new Error('Slot must be 0-8');
|
|
583
815
|
this.connection.sendPacket(play_js_1.PlayServerboundPackets.SET_HELD_ITEM, (0, play_js_1.buildSetHeldItemPacket)(slot));
|
|
584
816
|
}
|
|
817
|
+
/**
|
|
818
|
+
* Swing arm animation.
|
|
819
|
+
*/
|
|
820
|
+
swingArm(hand = 0) {
|
|
821
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.SWING_ARM, (0, play_js_1.buildSwingArmPacket)(hand));
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Drop the held item.
|
|
825
|
+
*/
|
|
826
|
+
dropItem(dropStack = false) {
|
|
827
|
+
this._actionSequence++;
|
|
828
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_ACTION, (0, play_js_1.buildPlayerActionPacket)(dropStack ? play_js_1.PlayerActionStatus.DROP_ITEM_STACK : play_js_1.PlayerActionStatus.DROP_ITEM, 0, 0, 0, 0, this._actionSequence));
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Swap items between main and off hand.
|
|
832
|
+
*/
|
|
833
|
+
swapHands() {
|
|
834
|
+
this._actionSequence++;
|
|
835
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_ACTION, (0, play_js_1.buildPlayerActionPacket)(play_js_1.PlayerActionStatus.SWAP_ITEM_IN_HAND, 0, 0, 0, 0, this._actionSequence));
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* Toggle flying (creative/spectator mode).
|
|
839
|
+
*/
|
|
840
|
+
fly(enabled) {
|
|
841
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_ABILITIES, (0, play_js_1.buildPlayerAbilitiesServerboundPacket)(enabled));
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Respawn after death.
|
|
845
|
+
*/
|
|
846
|
+
respawn() {
|
|
847
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.CLIENT_STATUS, (0, play_js_1.buildClientStatusPacket)(play_js_1.ClientStatusAction.PERFORM_RESPAWN));
|
|
848
|
+
this._isAlive = true;
|
|
849
|
+
}
|
|
850
|
+
/**
|
|
851
|
+
* Close the currently open container.
|
|
852
|
+
*/
|
|
853
|
+
closeContainer(windowId = 0) {
|
|
854
|
+
this.connection.sendPacket(play_js_1.PlayServerboundPackets.CLOSE_CONTAINER, (0, play_js_1.buildCloseContainerPacket)(windowId));
|
|
855
|
+
}
|
|
585
856
|
/**
|
|
586
857
|
* Disconnect from the server.
|
|
587
858
|
*/
|
|
588
859
|
disconnect() {
|
|
860
|
+
this.stopPhysicsTick();
|
|
589
861
|
this.plugins.destroyAll();
|
|
590
862
|
this.connection.disconnect();
|
|
591
863
|
this.logger.info('Disconnected');
|