Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protocol changes for 1.21.50 #279

Merged
merged 9 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions src/serializer/BitSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@

namespace pocketmine\network\mcpe\protocol\serializer;

use pocketmine\utils\BinaryDataException;
use function array_pad;
use function array_slice;
use function array_values;
use function chr;
use function count;
use function intdiv;
use function ord;

class BitSet{
private const INT_BITS = PHP_INT_SIZE * 8;
Expand All @@ -33,7 +31,7 @@ public function __construct(
private readonly int $length,
private array $parts = []
){
$expectedPartsCount = intdiv($length + self::INT_BITS - 1, self::INT_BITS);
$expectedPartsCount = self::getExpectedPartsCount($length);
$partsCount = count($parts);

if($partsCount > $expectedPartsCount){
Expand Down Expand Up @@ -77,14 +75,25 @@ private function getPartIndex(int $index) : array{
];
}

/**
* @internal
*/
public function getPartsCount() : int{
return count($this->parts);
}

private static function getExpectedPartsCount(int $length) : int{
return intdiv($length + self::INT_BITS - 1, self::INT_BITS);
}

public static function read(PacketSerializer $in, int $length) : self{
$result = [0];

$currentIndex = 0;
$currentShift = 0;

for($i = 0; $i < $length; $i += self::SHIFT){
$b = ord($in->get(1));
$b = $in->getByte();
$bits = $b & 0x7f;

$result[$currentIndex] |= $bits << $currentShift; //extra bits will be discarded
Expand All @@ -97,16 +106,14 @@ public static function read(PacketSerializer $in, int $length) : self{
$currentShift = $nextShift;

if(($b & 0x80) === 0){
return new self($length, $result);
return new self($length, array_slice($result, 0, self::getExpectedPartsCount($length)));
}
}

throw new BinaryDataException("Didn't terminate after reading $length bits");
return new self($length, array_slice($result, 0, self::getExpectedPartsCount($length)));
}

public function write(PacketSerializer $out) : void{
$buf = "";

$parts = $this->parts;
$length = $this->length;

Expand All @@ -118,20 +125,18 @@ public function write(PacketSerializer $out) : void{
$nextShift = $currentShift + self::SHIFT;
if($nextShift >= self::INT_BITS){
$nextShift -= self::INT_BITS;
$bits |= $parts[++$currentIndex] << (self::SHIFT - $nextShift);
$bits |= ($parts[++$currentIndex] ?? 0) << (self::SHIFT - $nextShift);
dries-c marked this conversation as resolved.
Show resolved Hide resolved
}
$currentShift = $nextShift;

$last = $i + self::SHIFT >= $length;
$bits |= $last ? 0 : 0x80;

$buf .= chr($bits);
$out->putByte($bits);
if($last){
break;
}
}

$out->put($buf);
}

public function getLength() : int{
Expand Down
6 changes: 6 additions & 0 deletions src/types/PlayerAuthInputFlags.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,11 @@ final class PlayerAuthInputFlags{
public const IS_ROT_CONTROLLED_BY_MOVE_DIRECTION = 55;
public const START_SPIN_ATTACK = 56;
public const STOP_SPIN_ATTACK = 57;
public const JUMP_RELEASED_RAW = 58;
public const JUMP_PRESSED_RAW = 59;
public const JUMP_CURRENT_RAW = 60;
public const SNEAK_RELEASED_RAW = 61;
public const SNEAK_PRESSED_RAW = 62;
public const SNEAK_CURRENT_RAW = 63;

}
72 changes: 64 additions & 8 deletions tests/phpunit/BitSetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,81 @@
use PHPUnit\Framework\TestCase;
use pocketmine\network\mcpe\protocol\serializer\BitSet;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
use function PHPUnit\Framework\assertTrue;
use function var_dump;

class BitSetTest extends TestCase{

public function testBitSet() : void{
$test = new BitSet(65);
$writeTest = new BitSet(65);

$test->set(0, true);
$test->set(64, true);
$writeTest->set(0, true);
$writeTest->set(64, true);

$packetSerializer = PacketSerializer::encoder();
$writeTest->write($packetSerializer);

$packetSerializer = PacketSerializer::decoder($packetSerializer->getBuffer(), 0);
$readTest = BitSet::read($packetSerializer, 65);

assertTrue($this->setsEqual($writeTest, $readTest));
}

public function testBitSetConstructor() : void{
$test = new BitSet(65, [-9223372036854775808, 1]);

Check failure on line 41 in tests/phpunit/BitSetTest.php

View workflow job for this annotation

GitHub Actions / Tests (PHP 8.1)

Parameter #2 $parts of class pocketmine\network\mcpe\protocol\serializer\BitSet constructor expects array<int>, array<int, float|int> given.

Check failure on line 41 in tests/phpunit/BitSetTest.php

View workflow job for this annotation

GitHub Actions / Tests (PHP 8.2)

Parameter #2 $parts of class pocketmine\network\mcpe\protocol\serializer\BitSet constructor expects array<int>, array<int, float|int> given.

Check failure on line 41 in tests/phpunit/BitSetTest.php

View workflow job for this annotation

GitHub Actions / Tests (PHP 8.3)

Parameter #2 $parts of class pocketmine\network\mcpe\protocol\serializer\BitSet constructor expects array<int>, array<int, float|int> given.

Check failure on line 41 in tests/phpunit/BitSetTest.php

View workflow job for this annotation

GitHub Actions / Tests (PHP 8.1)

Parameter #2 $parts of class pocketmine\network\mcpe\protocol\serializer\BitSet constructor expects array<int>, array<int, float|int> given.

Check failure on line 41 in tests/phpunit/BitSetTest.php

View workflow job for this annotation

GitHub Actions / Tests (PHP 8.2)

Parameter #2 $parts of class pocketmine\network\mcpe\protocol\serializer\BitSet constructor expects array<int>, array<int, float|int> given.

Check failure on line 41 in tests/phpunit/BitSetTest.php

View workflow job for this annotation

GitHub Actions / Tests (PHP 8.3)

Parameter #2 $parts of class pocketmine\network\mcpe\protocol\serializer\BitSet constructor expects array<int>, array<int, float|int> given.
dries-c marked this conversation as resolved.
Show resolved Hide resolved
$test2 = new BitSet(65, [-9223372036854775808]);

Check failure on line 42 in tests/phpunit/BitSetTest.php

View workflow job for this annotation

GitHub Actions / Tests (PHP 8.1)

Parameter #2 $parts of class pocketmine\network\mcpe\protocol\serializer\BitSet constructor expects array<int>, array<int, float> given.

Check failure on line 42 in tests/phpunit/BitSetTest.php

View workflow job for this annotation

GitHub Actions / Tests (PHP 8.2)

Parameter #2 $parts of class pocketmine\network\mcpe\protocol\serializer\BitSet constructor expects array<int>, array<int, float> given.

Check failure on line 42 in tests/phpunit/BitSetTest.php

View workflow job for this annotation

GitHub Actions / Tests (PHP 8.3)

Parameter #2 $parts of class pocketmine\network\mcpe\protocol\serializer\BitSet constructor expects array<int>, array<int, float> given.

Check failure on line 42 in tests/phpunit/BitSetTest.php

View workflow job for this annotation

GitHub Actions / Tests (PHP 8.1)

Parameter #2 $parts of class pocketmine\network\mcpe\protocol\serializer\BitSet constructor expects array<int>, array<int, float> given.

Check failure on line 42 in tests/phpunit/BitSetTest.php

View workflow job for this annotation

GitHub Actions / Tests (PHP 8.2)

Parameter #2 $parts of class pocketmine\network\mcpe\protocol\serializer\BitSet constructor expects array<int>, array<int, float> given.

Check failure on line 42 in tests/phpunit/BitSetTest.php

View workflow job for this annotation

GitHub Actions / Tests (PHP 8.3)

Parameter #2 $parts of class pocketmine\network\mcpe\protocol\serializer\BitSet constructor expects array<int>, array<int, float> given.
dries-c marked this conversation as resolved.
Show resolved Hide resolved

$test2->set(64, true);

$packetSerializer = PacketSerializer::encoder();
$test->write($packetSerializer);

$packetSerializer2 = PacketSerializer::encoder();
$test2->write($packetSerializer2);

self::assertEquals($packetSerializer->getBuffer(), $packetSerializer2->getBuffer());
}

public function testBitSetParts() : void{
$writeTest = new BitSet(128);
$writeTest->set(127, true);

$packetSerializer = PacketSerializer::encoder();
$writeTest->write($packetSerializer);

$packetSerializer = PacketSerializer::decoder($packetSerializer->getBuffer(), 0);
$readTest = BitSet::read($packetSerializer, 128);

assertTrue($this->setsEqual($writeTest, $readTest));
}

public function testVarUnsignedLongCompatibility() : void{
$packetSerializer = PacketSerializer::encoder();
$packetSerializer->putUnsignedVarLong(0 | 1 << 63);

$packetSerializer = PacketSerializer::decoder($packetSerializer->getBuffer(), 0);
$test = BitSet::read($packetSerializer, 65);
$readTest = BitSet::read($packetSerializer, 64);

self::assertTrue($test->get(0));
for($i = 1; $i < 64; ++$i){
self::assertFalse($test->get($i));
$expectedResult = new BitSet(64);
$expectedResult->set(63, true);

assertTrue($this->setsEqual($expectedResult, $readTest));
dries-c marked this conversation as resolved.
Show resolved Hide resolved
}

private function setsEqual(BitSet $a, BitSet $b) : bool{
$length = $a->getLength();
if($length !== $b->getLength()){
var_dump($length, $b->getLength());
return false;
dries-c marked this conversation as resolved.
Show resolved Hide resolved
}
self::assertTrue($test->get(64));

for($i = 0; $i < $length; ++$i){
if($a->get($i) !== $b->get($i)){
var_dump($i, $a->get($i), $b->get($i));
return false;
dries-c marked this conversation as resolved.
Show resolved Hide resolved
}
}
dries-c marked this conversation as resolved.
Show resolved Hide resolved

return $a->getPartsCount() === $b->getPartsCount();
}
}
dries-c marked this conversation as resolved.
Show resolved Hide resolved
Loading