Skip to content

Commit 9f79ba4

Browse files
committed
feat: add paintKit field to Sticker for sticker slab identification
Proto field 12 inside the Sticker sub-message encodes the actual sticker slab variant ID. Previously this field was silently ignored, causing all Sticker Slabs to decode identically (stickerId=37 for all variants). paintKit maps to the sticker catalog ID (stickers.json) and uniquely identifies which Sticker Slab variant an item is. Add decode/encode support and two test vectors: - NaVi (Holo) | Copenhagen 2024: defIndex=1355, rarity=5, paintKit=7256 - Eco Rush: defIndex=1355, rarity=3, paintKit=275
1 parent 3f2491d commit 9f79ba4

3 files changed

Lines changed: 88 additions & 0 deletions

File tree

src/InspectLink.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ private static function encodeSticker(Sticker $s): string
220220
$w->writeUint32(11, $s->highlightReel);
221221
}
222222

223+
if ($s->paintKit !== null) {
224+
$w->writeUint32(12, $s->paintKit);
225+
}
226+
223227
return $w->toBytes();
224228
}
225229

@@ -241,6 +245,7 @@ private static function decodeSticker(string $data): Sticker
241245
9 => $s->offsetZ = (float) unpack('f', $f['value'])[1],
242246
10 => $s->pattern = $f['value'],
243247
11 => $s->highlightReel = $f['value'],
248+
12 => $s->paintKit = $f['value'],
244249
default => null,
245250
};
246251
}

src/Sticker.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ public function __construct(
2424
public ?float $offsetZ = null,
2525
public int $pattern = 0,
2626
public ?int $highlightReel = null,
27+
public ?int $paintKit = null,
2728
) {}
2829
}

tests/InspectLinkTest.php

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,4 +570,86 @@ public function testSerialize_NullPaintwearProducesFewerBytes(): void
570570
$withFloat = InspectLink::serialize(new ItemPreviewData(defindex: 7, paintwear: 0.5));
571571
$this->assertLessThan(strlen($withFloat), strlen($withNull));
572572
}
573+
574+
// -----------------------------------------------------------------------
575+
// Sticker Slab test vectors (defIndex=1355, quality=8, sticker slab variant via paintKit)
576+
// -----------------------------------------------------------------------
577+
578+
/** Sticker Slab URL A — rarity=5, keychains[0].stickerId=37, keychains[0].paintKit=7256 */
579+
private const SLAB_URL_A = 'steam://run/730//+csgo_econ_action_preview%20918191895A9BB191B994A199F991E191339096999181B4F149A98D5C0889';
580+
581+
/** Sticker Slab URL B — rarity=3, keychains[0].stickerId=37, keychains[0].paintKit=275 */
582+
private const SLAB_URL_B = 'steam://run/730//+csgo_econ_action_preview%20CBDBCBD300C1EBCBE3C8FBC3A3CBBBCB69CACCC3CBDBEEAB58C9B8B67C83';
583+
584+
public function testSlabA_Defindex(): void
585+
{
586+
$this->assertSame(1355, InspectLink::deserialize(self::SLAB_URL_A)->defindex);
587+
}
588+
589+
public function testSlabA_Quality(): void
590+
{
591+
$this->assertSame(8, InspectLink::deserialize(self::SLAB_URL_A)->quality);
592+
}
593+
594+
public function testSlabA_Rarity(): void
595+
{
596+
$this->assertSame(5, InspectLink::deserialize(self::SLAB_URL_A)->rarity);
597+
}
598+
599+
public function testSlabA_KeychainStickerId(): void
600+
{
601+
$keychains = InspectLink::deserialize(self::SLAB_URL_A)->keychains;
602+
$this->assertCount(1, $keychains);
603+
$this->assertSame(37, $keychains[0]->stickerId);
604+
}
605+
606+
public function testSlabA_KeychainPaintKit(): void
607+
{
608+
$keychains = InspectLink::deserialize(self::SLAB_URL_A)->keychains;
609+
$this->assertCount(1, $keychains);
610+
$this->assertSame(7256, $keychains[0]->paintKit);
611+
}
612+
613+
public function testSlabB_Defindex(): void
614+
{
615+
$this->assertSame(1355, InspectLink::deserialize(self::SLAB_URL_B)->defindex);
616+
}
617+
618+
public function testSlabB_Quality(): void
619+
{
620+
$this->assertSame(8, InspectLink::deserialize(self::SLAB_URL_B)->quality);
621+
}
622+
623+
public function testSlabB_Rarity(): void
624+
{
625+
$this->assertSame(3, InspectLink::deserialize(self::SLAB_URL_B)->rarity);
626+
}
627+
628+
public function testSlabB_KeychainStickerId(): void
629+
{
630+
$keychains = InspectLink::deserialize(self::SLAB_URL_B)->keychains;
631+
$this->assertCount(1, $keychains);
632+
$this->assertSame(37, $keychains[0]->stickerId);
633+
}
634+
635+
public function testSlabB_KeychainPaintKit(): void
636+
{
637+
$keychains = InspectLink::deserialize(self::SLAB_URL_B)->keychains;
638+
$this->assertCount(1, $keychains);
639+
$this->assertSame(275, $keychains[0]->paintKit);
640+
}
641+
642+
public function testRoundtrip_PaintKit(): void
643+
{
644+
$data = new ItemPreviewData(
645+
defindex: 1355,
646+
quality: 8,
647+
rarity: 5,
648+
keychains: [new Sticker(slot: 0, stickerId: 37, paintKit: 7256)],
649+
);
650+
$result = InspectLink::deserialize(InspectLink::serialize($data));
651+
$this->assertCount(1, $result->keychains);
652+
$this->assertSame(37, $result->keychains[0]->stickerId);
653+
$this->assertSame(7256, $result->keychains[0]->paintKit);
654+
}
573655
}

0 commit comments

Comments
 (0)