mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-10-15 19:46:20 +00:00
Merge 'stable' into 'minor-next'
Automatic merge performed by: https://github.com/pmmp/RestrictedActions/actions/runs/18064897730
This commit is contained in:
@@ -102,3 +102,10 @@ Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if
|
||||
- `FastChunkSerializer` (used for transmitting chunks between threads)
|
||||
- GS4 Query
|
||||
- Auxiliary read-only data loading in the `pocketmine\data\bedrock` package
|
||||
|
||||
# 5.34.1
|
||||
Released 26th September 2025.
|
||||
|
||||
## Fixes
|
||||
- Player login JSON processing no longer bails out on unexpected extra properties. A warning will now be logged instead (@dktapps).
|
||||
- Fixed container drop issues when an ender crystal explosion causes another ender crystal nearby to explode (@dktapps, @kostamax27).
|
||||
|
@@ -31,7 +31,7 @@ use function str_repeat;
|
||||
|
||||
final class VersionInfo{
|
||||
public const NAME = "PocketMine-MP";
|
||||
public const BASE_VERSION = "5.34.1";
|
||||
public const BASE_VERSION = "5.34.2";
|
||||
public const IS_DEVELOPMENT_BUILD = true;
|
||||
public const BUILD_CHANNEL = "stable";
|
||||
|
||||
|
@@ -56,6 +56,7 @@ use function is_object;
|
||||
use function json_decode;
|
||||
use function md5;
|
||||
use function ord;
|
||||
use function var_export;
|
||||
use const JSON_THROW_ON_ERROR;
|
||||
|
||||
/**
|
||||
@@ -114,7 +115,7 @@ class LoginPacketHandler extends PacketHandler{
|
||||
throw new PacketHandlingException("Unexpected type for self-signed certificate chain: " . gettype($chainData) . ", expected object");
|
||||
}
|
||||
try{
|
||||
$chain = $this->defaultJsonMapper()->map($chainData, new LegacyAuthChain());
|
||||
$chain = $this->defaultJsonMapper("Self-signed auth chain JSON")->map($chainData, new LegacyAuthChain());
|
||||
}catch(\JsonMapper_Exception $e){
|
||||
throw PacketHandlingException::wrap($e, "Error mapping self-signed certificate chain");
|
||||
}
|
||||
@@ -132,7 +133,7 @@ class LoginPacketHandler extends PacketHandler{
|
||||
}
|
||||
|
||||
try{
|
||||
$claims = $this->defaultJsonMapper()->map($claimsArray["extraData"], new LegacyAuthIdentityData());
|
||||
$claims = $this->defaultJsonMapper("Self-signed auth JWT 'extraData'")->map($claimsArray["extraData"], new LegacyAuthIdentityData());
|
||||
}catch(\JsonMapper_Exception $e){
|
||||
throw PacketHandlingException::wrap($e, "Error mapping self-signed certificate extraData");
|
||||
}
|
||||
@@ -244,7 +245,7 @@ class LoginPacketHandler extends PacketHandler{
|
||||
throw new PacketHandlingException("Unexpected type for auth info data: " . gettype($authInfoJson) . ", expected object");
|
||||
}
|
||||
|
||||
$mapper = $this->defaultJsonMapper();
|
||||
$mapper = $this->defaultJsonMapper("Root authentication info JSON");
|
||||
try{
|
||||
$clientData = $mapper->map($authInfoJson, new AuthenticationInfo());
|
||||
}catch(\JsonMapper_Exception $e){
|
||||
@@ -258,7 +259,7 @@ class LoginPacketHandler extends PacketHandler{
|
||||
* @throws PacketHandlingException
|
||||
*/
|
||||
protected function mapXboxTokenHeader(array $headerArray) : XboxAuthJwtHeader{
|
||||
$mapper = $this->defaultJsonMapper();
|
||||
$mapper = $this->defaultJsonMapper("OpenID JWT header");
|
||||
try{
|
||||
$header = $mapper->map($headerArray, new XboxAuthJwtHeader());
|
||||
}catch(\JsonMapper_Exception $e){
|
||||
@@ -272,7 +273,7 @@ class LoginPacketHandler extends PacketHandler{
|
||||
* @throws PacketHandlingException
|
||||
*/
|
||||
protected function mapXboxTokenBody(array $bodyArray) : XboxAuthJwtBody{
|
||||
$mapper = $this->defaultJsonMapper();
|
||||
$mapper = $this->defaultJsonMapper("OpenID JWT body");
|
||||
try{
|
||||
$header = $mapper->map($bodyArray, new XboxAuthJwtBody());
|
||||
}catch(\JsonMapper_Exception $e){
|
||||
@@ -291,7 +292,7 @@ class LoginPacketHandler extends PacketHandler{
|
||||
throw PacketHandlingException::wrap($e);
|
||||
}
|
||||
|
||||
$mapper = $this->defaultJsonMapper();
|
||||
$mapper = $this->defaultJsonMapper("ClientData JWT body");
|
||||
try{
|
||||
$clientData = $mapper->map($clientDataClaims, new ClientData());
|
||||
}catch(\JsonMapper_Exception $e){
|
||||
@@ -329,12 +330,21 @@ class LoginPacketHandler extends PacketHandler{
|
||||
$this->server->getAsyncPool()->submitTask(new ProcessLegacyLoginTask($legacyCertificate, $clientDataJwt, rootAuthKeyDer: null, authRequired: $authRequired, onCompletion: $this->authCallback));
|
||||
}
|
||||
|
||||
private function defaultJsonMapper() : \JsonMapper{
|
||||
private function defaultJsonMapper(string $logContext) : \JsonMapper{
|
||||
$mapper = new \JsonMapper();
|
||||
$mapper->bExceptionOnMissingData = true;
|
||||
$mapper->bExceptionOnUndefinedProperty = true;
|
||||
$mapper->undefinedPropertyHandler = $this->warnUndefinedJsonPropertyHandler($logContext);
|
||||
$mapper->bStrictObjectTypeChecking = true;
|
||||
$mapper->bEnforceMapType = false;
|
||||
return $mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-return \Closure(object, string, mixed) : void
|
||||
*/
|
||||
private function warnUndefinedJsonPropertyHandler(string $context) : \Closure{
|
||||
return fn(object $object, string $name, mixed $value) => $this->session->getLogger()->warning(
|
||||
"$context: Unexpected JSON property for " . (new \ReflectionClass($object))->getShortName() . ": " . $name . " = " . var_export($value, return: true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -62,6 +62,20 @@ class ResourcePacksPacketHandler extends PacketHandler{
|
||||
*/
|
||||
private const MAX_CONCURRENT_CHUNK_REQUESTS = 1;
|
||||
|
||||
/**
|
||||
* All data/resource_packs/chemistry* packs need to be listed here to get chemistry blocks to render
|
||||
* correctly, unfortunately there doesn't seem to be a better way to do this
|
||||
*/
|
||||
private const CHEMISTRY_RESOURCE_PACKS = [
|
||||
["b41c2785-c512-4a49-af56-3a87afd47c57", "1.21.30"],
|
||||
["a4df0cb3-17be-4163-88d7-fcf7002b935d", "1.21.20"],
|
||||
["d19adffe-a2e1-4b02-8436-ca4583368c89", "1.21.10"],
|
||||
["85d5603d-2824-4b21-8044-34f441f4fce1", "1.21.0"],
|
||||
["e977cd13-0a11-4618-96fb-03dfe9c43608", "1.20.60"],
|
||||
["0674721c-a0aa-41a1-9ba8-1ed33ea3e7ed", "1.20.50"],
|
||||
["0fba4063-dba1-4281-9b89-ff9390653530", "1.0.0"],
|
||||
];
|
||||
|
||||
/**
|
||||
* @var ResourcePack[]
|
||||
* @phpstan-var array<string, ResourcePack>
|
||||
@@ -200,8 +214,10 @@ class ResourcePacksPacketHandler extends PacketHandler{
|
||||
return new ResourcePackStackEntry($pack->getPackId(), $pack->getPackVersion(), ""); //TODO: subpacks
|
||||
}, $this->resourcePackStack);
|
||||
|
||||
//we support chemistry blocks by default, the client should already have this installed
|
||||
$stack[] = new ResourcePackStackEntry("0fba4063-dba1-4281-9b89-ff9390653530", "1.0.0", "");
|
||||
//we support chemistry blocks by default, the client should already have these installed
|
||||
foreach(self::CHEMISTRY_RESOURCE_PACKS as [$uuid, $version]){
|
||||
$stack[] = new ResourcePackStackEntry($uuid, $version, "");
|
||||
}
|
||||
|
||||
//we don't force here, because it doesn't have user-facing effects
|
||||
//but it does have an annoying side-effect when true: it makes
|
||||
|
@@ -26,9 +26,11 @@ namespace pocketmine\utils;
|
||||
use function abs;
|
||||
use function date_default_timezone_set;
|
||||
use function date_parse;
|
||||
use function escapeshellarg;
|
||||
use function exec;
|
||||
use function file_get_contents;
|
||||
use function implode;
|
||||
use function floor;
|
||||
use function hexdec;
|
||||
use function ini_get;
|
||||
use function ini_set;
|
||||
use function is_array;
|
||||
@@ -37,6 +39,7 @@ use function json_decode;
|
||||
use function parse_ini_file;
|
||||
use function preg_match;
|
||||
use function readlink;
|
||||
use function sprintf;
|
||||
use function str_contains;
|
||||
use function str_replace;
|
||||
use function str_starts_with;
|
||||
@@ -105,40 +108,67 @@ abstract class Timezone{
|
||||
public static function detectSystemTimezone() : string|false{
|
||||
switch(Utils::getOS()){
|
||||
case Utils::OS_WINDOWS:
|
||||
$regex = '/(UTC)(\+*\-*\d*\d*\:*\d*\d*)/';
|
||||
$keyPath = 'HKLM\\SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation';
|
||||
|
||||
/*
|
||||
* wmic timezone get Caption
|
||||
* Get the timezone offset
|
||||
* Get the timezone offset through the registry
|
||||
*
|
||||
* Sample Output var_dump
|
||||
* array(3) {
|
||||
* [0] =>
|
||||
* string(7) "Caption"
|
||||
* [1] =>
|
||||
* string(20) "(UTC+09:30) Adelaide"
|
||||
* [2] =>
|
||||
* string(0) ""
|
||||
* }
|
||||
* array(13) {
|
||||
* [0]=>
|
||||
* string(0) ""
|
||||
* [1]=>
|
||||
* string(71) "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation"
|
||||
* [2]=>
|
||||
* string(35) " Bias REG_DWORD 0xfffffe20"
|
||||
* [3]=>
|
||||
* string(43) " DaylightBias REG_DWORD 0xffffffc4"
|
||||
* [4]=>
|
||||
* string(45) " DaylightName REG_SZ @tzres.dll,-571"
|
||||
* [5]=>
|
||||
* string(67) " DaylightStart REG_BINARY 00000000000000000000000000000000"
|
||||
* [6]=>
|
||||
* string(36) " StandardBias REG_DWORD 0x0"
|
||||
* [7]=>
|
||||
* string(45) " StandardName REG_SZ @tzres.dll,-572"
|
||||
* [8]=>
|
||||
* string(67) " StandardStart REG_BINARY 00000000000000000000000000000000"
|
||||
* [9]=>
|
||||
* string(52) " TimeZoneKeyName REG_SZ China Standard Time"
|
||||
* [10]=>
|
||||
* string(51) " DynamicDaylightTimeDisabled REG_DWORD 0x0"
|
||||
* [11]=>
|
||||
* string(45) " ActiveTimeBias REG_DWORD 0xfffffe20"
|
||||
* [12]=>
|
||||
* string(0) ""
|
||||
* }
|
||||
*/
|
||||
exec("wmic timezone get Caption", $output);
|
||||
exec("reg query " . escapeshellarg($keyPath), $output);
|
||||
|
||||
$string = trim(implode("\n", $output));
|
||||
foreach($output as $line){
|
||||
if(preg_match('/ActiveTimeBias\s+REG_DWORD\s+0x([0-9a-fA-F]+)/', $line, $matches) > 0){
|
||||
$offsetMinutes = Binary::signInt((int) hexdec(trim($matches[1])));
|
||||
|
||||
//Detect the Time Zone string
|
||||
preg_match($regex, $string, $matches);
|
||||
if($offsetMinutes === 0){
|
||||
return "UTC";
|
||||
}
|
||||
|
||||
if(!isset($matches[2])){
|
||||
return false;
|
||||
$sign = $offsetMinutes <= 0 ? '+' : '-'; //windows timezone + and - are opposite
|
||||
$absMinutes = abs($offsetMinutes);
|
||||
$hours = floor($absMinutes / 60);
|
||||
$minutes = $absMinutes % 60;
|
||||
|
||||
$offset = sprintf(
|
||||
"%s%02d:%02d",
|
||||
$sign,
|
||||
$hours,
|
||||
$minutes
|
||||
);
|
||||
|
||||
return self::parseOffset($offset);
|
||||
}
|
||||
}
|
||||
|
||||
$offset = $matches[2];
|
||||
|
||||
if($offset === ""){
|
||||
return "UTC";
|
||||
}
|
||||
|
||||
return self::parseOffset($offset);
|
||||
return false;
|
||||
case Utils::OS_LINUX:
|
||||
// Ubuntu / Debian.
|
||||
$data = @file_get_contents('/etc/timezone');
|
||||
|
@@ -5,6 +5,9 @@ class JsonMapper_Exception extends \Exception{}
|
||||
|
||||
class JsonMapper{
|
||||
|
||||
/** @var ?\Closure(object, string, mixed) : void */
|
||||
public $undefinedPropertyHandler = null;
|
||||
|
||||
/**
|
||||
* @template TModel of object
|
||||
*
|
||||
|
Reference in New Issue
Block a user