Skip to content

Commit 21ccca1

Browse files
committed
Merge remote-tracking branch 'upstream/stable' into stable
2 parents c806bfe + 8843b1b commit 21ccca1

File tree

6 files changed

+113
-14
lines changed

6 files changed

+113
-14
lines changed

changelogs/5.29.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# 5.29.0
2+
Released 18th June 2025.
3+
4+
This is a support release for Minecraft: Bedrock Edition 1.21.90.
5+
6+
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
7+
Do not update plugin minimum API versions unless you need new features added in this release.
8+
9+
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
10+
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
11+
12+
## General
13+
- Added support for Minecraft: Bedrock Edition 1.21.90.
14+
- Removed support for earlier versions.
15+
16+
## Fixes
17+
- Fixed thread crashes sometimes not reporting proper cause information in crashdumps.
18+
- Fixed crash when a plugin replaced a player's held tool with a different tool with a damage exceeding the old tool's max damage during an action.
19+
- Fixed performance issue of `PlayerAuthInputPacket` input flags handling (broken change detection).
20+
- Fixed `BaseInventory->addItem()` triggering updates on empty slots when no items were added.
21+
- Fixed slow check in `SubChunk` block layer garbage collection.
22+
23+
## Internals
24+
- `LoginPacketHandler->processLogin()` signature has changed. This will break any plugins overriding `LoginPacketHandler`. As noted above, this is _not_ covered by the API version guarantee.
25+
- Automated branch sync for `minor-next` and `major-next` is now triggered by `repository_dispatch` from a cron job in this repository instead of `RestrictedActions`. The `RestrictedActions` cron job was getting automatically disabled by GitHub due to repo inactivity.

composer.lock

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/VersionInfo.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
final class VersionInfo{
3333
public const NAME = "NG-PocketMine-MP";
34-
public const BASE_VERSION = "5.28.3";
34+
public const BASE_VERSION = "5.29.1";
3535
public const IS_DEVELOPMENT_BUILD = true;
3636
public const BUILD_CHANNEL = "stable";
3737

src/data/bedrock/item/ItemTypeNames.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ final class ItemTypeNames{
380380
public const MUSIC_DISC_RELIC = "minecraft:music_disc_relic";
381381
public const MUSIC_DISC_STAL = "minecraft:music_disc_stal";
382382
public const MUSIC_DISC_STRAD = "minecraft:music_disc_strad";
383+
public const MUSIC_DISC_TEARS = "minecraft:music_disc_tears";
383384
public const MUSIC_DISC_WAIT = "minecraft:music_disc_wait";
384385
public const MUSIC_DISC_WARD = "minecraft:music_disc_ward";
385386
public const MUTTON = "minecraft:mutton";

src/network/mcpe/handler/LoginPacketHandler.php

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
use pocketmine\network\mcpe\protocol\LoginPacket;
3535
use pocketmine\network\mcpe\protocol\ProtocolInfo;
3636
use pocketmine\network\mcpe\protocol\types\login\AuthenticationData;
37+
use pocketmine\network\mcpe\protocol\types\login\AuthenticationInfo;
38+
use pocketmine\network\mcpe\protocol\types\login\AuthenticationType;
3739
use pocketmine\network\mcpe\protocol\types\login\ClientData;
3840
use pocketmine\network\mcpe\protocol\types\login\ClientDataToSkinDataHelper;
3941
use pocketmine\network\mcpe\protocol\types\login\JwtChain;
@@ -43,8 +45,12 @@
4345
use pocketmine\player\XboxLivePlayerInfo;
4446
use pocketmine\Server;
4547
use Ramsey\Uuid\Uuid;
48+
use function gettype;
4649
use function in_array;
4750
use function is_array;
51+
use function is_object;
52+
use function json_decode;
53+
use const JSON_THROW_ON_ERROR;
4854

4955
/**
5056
* Handles the initial login phase of the session. This handler is used as the initial state.
@@ -70,7 +76,14 @@ public function handleLogin(LoginPacket $packet) : bool{
7076
}
7177
$this->session->setProtocolId($protocolVersion);
7278

73-
$extraData = $this->fetchAuthData($packet->chainDataJwt);
79+
if($protocolVersion >= ProtocolInfo::PROTOCOL_1_21_90){
80+
$authInfo = $this->parseAuthInfo($packet->authInfoJson);
81+
$jwtChain = $this->parseJwtChain($authInfo->Certificate);
82+
}else{
83+
$jwtChain = $this->parseJwtChain($packet->authInfoJson);
84+
}
85+
86+
$extraData = $this->fetchAuthData($jwtChain);
7487

7588
if(!Player::isValidUserName($extraData->displayName)){
7689
$this->session->disconnectWithError(KnownTranslationFactory::disconnectionScreen_invalidName());
@@ -148,11 +161,65 @@ public function handleLogin(LoginPacket $packet) : bool{
148161
return true;
149162
}
150163

151-
$this->processLogin($packet, $ev->isAuthRequired());
164+
if(isset($authInfo)){
165+
$this->processLogin($authInfo->Token, AuthenticationType::from($authInfo->AuthenticationType), $jwtChain->chain, $packet->clientDataJwt, $ev->isAuthRequired());
166+
}else{
167+
$this->processLogin(null, null, $jwtChain->chain, $packet->clientDataJwt, $ev->isAuthRequired());
168+
}
152169

153170
return true;
154171
}
155172

173+
/**
174+
* @throws PacketHandlingException
175+
*/
176+
protected function parseAuthInfo(string $authInfo) : AuthenticationInfo{
177+
try{
178+
$authInfoJson = json_decode($authInfo, associative: false, flags: JSON_THROW_ON_ERROR);
179+
}catch(\JsonException $e){
180+
throw PacketHandlingException::wrap($e);
181+
}
182+
if(!is_object($authInfoJson)){
183+
throw new \RuntimeException("Unexpected type for auth info data: " . gettype($authInfoJson) . ", expected object");
184+
}
185+
186+
$mapper = new \JsonMapper();
187+
$mapper->bExceptionOnMissingData = true;
188+
$mapper->bExceptionOnUndefinedProperty = true;
189+
$mapper->bStrictObjectTypeChecking = true;
190+
try{
191+
$clientData = $mapper->map($authInfoJson, new AuthenticationInfo());
192+
}catch(\JsonMapper_Exception $e){
193+
throw PacketHandlingException::wrap($e);
194+
}
195+
return $clientData;
196+
}
197+
198+
/**
199+
* @throws PacketHandlingException
200+
*/
201+
protected function parseJwtChain(string $chainDataJwt) : JwtChain{
202+
try{
203+
$jwtChainJson = json_decode($chainDataJwt, associative: false, flags: JSON_THROW_ON_ERROR);
204+
}catch(\JsonException $e){
205+
throw PacketHandlingException::wrap($e);
206+
}
207+
if(!is_object($jwtChainJson)){
208+
throw new \RuntimeException("Unexpected type for JWT chain data: " . gettype($jwtChainJson) . ", expected object");
209+
}
210+
211+
$mapper = new \JsonMapper();
212+
$mapper->bExceptionOnMissingData = true;
213+
$mapper->bExceptionOnUndefinedProperty = true;
214+
$mapper->bStrictObjectTypeChecking = true;
215+
try{
216+
$clientData = $mapper->map($jwtChainJson, new JwtChain());
217+
}catch(\JsonMapper_Exception $e){
218+
throw PacketHandlingException::wrap($e);
219+
}
220+
return $clientData;
221+
}
222+
156223
/**
157224
* @throws PacketHandlingException
158225
*/
@@ -220,10 +287,15 @@ protected function parseClientData(string $clientDataJwt) : ClientData{
220287
* TODO: This is separated for the purposes of allowing plugins (like Specter) to hack it and bypass authentication.
221288
* In the future this won't be necessary.
222289
*
290+
* @param null|string[] $legacyCertificate
291+
*
223292
* @throws \InvalidArgumentException
224293
*/
225-
protected function processLogin(LoginPacket $packet, bool $authRequired) : void{
226-
$this->server->getAsyncPool()->submitTask(new ProcessLoginTask($packet->chainDataJwt->chain, $packet->clientDataJwt, $authRequired, $this->authCallback));
294+
protected function processLogin(?string $token, ?AuthenticationType $authType, ?array $legacyCertificate, string $clientData, bool $authRequired) : void{
295+
if($legacyCertificate === null){
296+
throw new PacketHandlingException("Legacy certificate cannot be null");
297+
}
298+
$this->server->getAsyncPool()->submitTask(new ProcessLoginTask($legacyCertificate, $clientData, $authRequired, $this->authCallback));
227299
$this->session->setHandler(null); //drop packets received during login verification
228300
}
229301

src/network/mcpe/handler/ResourcePacksPacketHandler.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ public function setUp() : void{
123123
forceServerPacks: false,
124124
cdnUrls: [],
125125
worldTemplateId: Uuid::fromString(Uuid::NIL),
126-
worldTemplateVersion: ""
126+
worldTemplateVersion: "",
127+
forceDisableVibrantVisuals: true,
127128
));
128129
$this->session->getLogger()->debug("Waiting for client to accept resource packs");
129130
}

0 commit comments

Comments
 (0)