@@ -7,6 +7,7 @@ import { Position } from '@server/world/position';
7
7
import { LocationObject } from '@runejs/cache-parser' ;
8
8
import { Chunk , ChunkUpdateItem } from '@server/world/map/chunk' ;
9
9
import { WorldItem } from '@server/world/items/world-item' ;
10
+ import { ByteBuffer } from '@runejs/byte-buffer' ;
10
11
11
12
/**
12
13
* A helper class for sending various network packets back to the game client.
@@ -303,32 +304,73 @@ export class OutgoingPackets {
303
304
this . queue ( packet ) ;
304
305
}
305
306
306
- public sendUpdateAllWidgetItems ( widget : { widgetId : number , containerId : number } , container : ItemContainer ) : void {
307
- const packet = new Packet ( 12 , PacketType . DYNAMIC_LARGE ) ;
308
- packet . put ( widget . widgetId << 16 | widget . containerId , 'INT' ) ;
309
- packet . put ( container . size , 'SHORT' ) ;
307
+ public update ( packet : Packet , widget : { widgetId : number , containerId : number } , container : ItemContainer ) : void {
308
+ const packed = widget . widgetId << 16 | widget . containerId ;
309
+ packet . put ( packed , 'INT' ) ;
310
310
311
- const items = container . items ;
312
- items . forEach ( item => {
313
- if ( ! item ) {
314
- // Empty slot
315
- packet . put ( 0 ) ;
316
- packet . put ( 0 , 'SHORT' ) ;
317
- } else {
318
- if ( item . amount >= 255 ) {
319
- packet . put ( 255 ) ;
320
- packet . put ( item . amount , 'INT' ) ;
321
- } else {
322
- packet . put ( item . amount ) ;
323
- }
311
+ const size = container . size ;
312
+ packet . put ( size , 'SHORT' ) ;
313
+
314
+ const bound = container . items . length * 7 ;
315
+ const payload = new Packet ( - 1 , PacketType . FIXED , bound ) ; //TODO: change default value of allocatedSize from 5000 to something reasonable (64 - 256 as most RS packets are quite small)
324
316
325
- packet . put ( item . itemId + 1 , 'SHORT' ) ; // +1 because 0 means an empty slot
317
+ for ( let index = 0 ; index < size ; index += 8 ) {
318
+ const { bitset, buffer } = this . segment ( container , index ) ;
319
+
320
+ payload . put ( bitset , 'BYTE' ) ;
321
+
322
+ if ( bitset == 0 ) {
323
+ continue ;
326
324
}
327
- } ) ;
325
+
326
+ payload . putBytes ( buffer ) ;
327
+ }
328
+
329
+ packet . putBytes ( this . strip ( payload ) ) ;
328
330
329
331
this . queue ( packet ) ;
330
332
}
331
333
334
+ private strip ( packet : Packet ) : Buffer {
335
+ const size = packet . writerIndex ;
336
+ const buffer = new ByteBuffer ( size ) ;
337
+ packet . copy ( buffer , 0 , 0 , size ) ;
338
+ return Buffer . from ( buffer ) ;
339
+ }
340
+
341
+ private segment ( container : ItemContainer , start : number ) : { bitset : number , buffer : Buffer } {
342
+ const bound = 7 * 8 ;
343
+ const payload = new Packet ( - 1 , PacketType . FIXED , bound ) ;
344
+
345
+ let bitset : number = 0 ;
346
+
347
+ for ( let offset = 0 ; offset < 8 ; offset ++ ) {
348
+ const item = container . items [ start + offset ] ;
349
+
350
+ if ( ! item ) {
351
+ continue ;
352
+ }
353
+
354
+ bitset |= 1 << offset ;
355
+
356
+ const large = item . amount >= 255 ;
357
+
358
+ if ( large ) {
359
+ payload . put ( 255 , 'BYTE' ) ;
360
+ }
361
+
362
+ payload . put ( item . amount , large ? 'INT' : 'BYTE' ) ;
363
+ payload . put ( item . itemId + 1 , 'SHORT' ) ;
364
+ }
365
+
366
+ return { bitset, buffer : this . strip ( payload ) } ;
367
+ }
368
+
369
+ public sendUpdateAllWidgetItems ( widget : { widgetId : number , containerId : number } , container : ItemContainer ) : void {
370
+ const packet = new Packet ( 12 , PacketType . DYNAMIC_LARGE ) ;
371
+ this . update ( packet , widget , container ) ;
372
+ }
373
+
332
374
public sendUpdateAllWidgetItemsById ( widget : { widgetId : number , containerId : number } , itemIds : number [ ] ) : void {
333
375
const packet = new Packet ( 12 , PacketType . DYNAMIC_LARGE ) ;
334
376
packet . put ( widget . widgetId << 16 | widget . containerId , 'INT' ) ;
0 commit comments