mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-07-23 11:26:37 +00:00
Merge branch 'next-minor' into next-major
This commit is contained in:
commit
b39eaaf91f
14
changelogs/4.9.md
Normal file
14
changelogs/4.9.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.19.30**
|
||||||
|
|
||||||
|
### Note about API versions
|
||||||
|
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
|
||||||
|
Plugin developers should **only** update their required API to this version if you need the changes in this build.
|
||||||
|
|
||||||
|
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
|
||||||
|
|
||||||
|
# 4.9.0
|
||||||
|
Released 20th September 2022.
|
||||||
|
|
||||||
|
## General
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.19.30.
|
||||||
|
- Removed support for older versions.
|
@ -37,7 +37,7 @@
|
|||||||
"pocketmine/bedrock-block-upgrade-schema": "dev-master@dev",
|
"pocketmine/bedrock-block-upgrade-schema": "dev-master@dev",
|
||||||
"pocketmine/bedrock-data": "dev-modern-world-support@dev",
|
"pocketmine/bedrock-data": "dev-modern-world-support@dev",
|
||||||
"pocketmine/bedrock-item-upgrade-schema": "dev-master",
|
"pocketmine/bedrock-item-upgrade-schema": "dev-master",
|
||||||
"pocketmine/bedrock-protocol": "~12.2.0+bedrock-1.19.20",
|
"pocketmine/bedrock-protocol": "~13.0.0+bedrock-1.19.30",
|
||||||
"pocketmine/binaryutils": "^0.2.1",
|
"pocketmine/binaryutils": "^0.2.1",
|
||||||
"pocketmine/callback-validator": "^1.0.2",
|
"pocketmine/callback-validator": "^1.0.2",
|
||||||
"pocketmine/classloader": "^0.2.0",
|
"pocketmine/classloader": "^0.2.0",
|
||||||
|
34
composer.lock
generated
34
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "ab34faed0ca4120106748663b00e9604",
|
"content-hash": "284e89a86c5b7fdb4d97ec5516666b36",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "adhocore/json-comment",
|
"name": "adhocore/json-comment",
|
||||||
@ -276,12 +276,12 @@
|
|||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pmmp/BedrockData.git",
|
"url": "https://github.com/pmmp/BedrockData.git",
|
||||||
"reference": "6f480c67ed03abb1b2641802879f5c1aeda11cc2"
|
"reference": "1ca9241ce66358cdfb2dbde65d609eb9c185c515"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/6f480c67ed03abb1b2641802879f5c1aeda11cc2",
|
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/1ca9241ce66358cdfb2dbde65d609eb9c185c515",
|
||||||
"reference": "6f480c67ed03abb1b2641802879f5c1aeda11cc2",
|
"reference": "1ca9241ce66358cdfb2dbde65d609eb9c185c515",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
@ -294,7 +294,7 @@
|
|||||||
"issues": "https://github.com/pmmp/BedrockData/issues",
|
"issues": "https://github.com/pmmp/BedrockData/issues",
|
||||||
"source": "https://github.com/pmmp/BedrockData/tree/modern-world-support"
|
"source": "https://github.com/pmmp/BedrockData/tree/modern-world-support"
|
||||||
},
|
},
|
||||||
"time": "2022-08-09T17:47:56+00:00"
|
"time": "2022-09-21T13:59:15+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pocketmine/bedrock-item-upgrade-schema",
|
"name": "pocketmine/bedrock-item-upgrade-schema",
|
||||||
@ -325,16 +325,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pocketmine/bedrock-protocol",
|
"name": "pocketmine/bedrock-protocol",
|
||||||
"version": "12.2.0+bedrock-1.19.21",
|
"version": "13.0.0+bedrock-1.19.30",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/pmmp/BedrockProtocol.git",
|
"url": "https://github.com/pmmp/BedrockProtocol.git",
|
||||||
"reference": "d1b3e83f77e2c6628b64793485260cddc55d92e3"
|
"reference": "94de2221676ca717587e1ff4e45445c24ada1749"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/d1b3e83f77e2c6628b64793485260cddc55d92e3",
|
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/94de2221676ca717587e1ff4e45445c24ada1749",
|
||||||
"reference": "d1b3e83f77e2c6628b64793485260cddc55d92e3",
|
"reference": "94de2221676ca717587e1ff4e45445c24ada1749",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -366,9 +366,9 @@
|
|||||||
"description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP",
|
"description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/pmmp/BedrockProtocol/issues",
|
"issues": "https://github.com/pmmp/BedrockProtocol/issues",
|
||||||
"source": "https://github.com/pmmp/BedrockProtocol/tree/12.2.0+bedrock-1.19.21"
|
"source": "https://github.com/pmmp/BedrockProtocol/tree/bedrock-1.19.30"
|
||||||
},
|
},
|
||||||
"time": "2022-08-24T18:47:37+00:00"
|
"time": "2022-09-20T18:35:00+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pocketmine/binaryutils",
|
"name": "pocketmine/binaryutils",
|
||||||
@ -980,16 +980,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ramsey/uuid",
|
"name": "ramsey/uuid",
|
||||||
"version": "4.5.0",
|
"version": "4.5.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ramsey/uuid.git",
|
"url": "https://github.com/ramsey/uuid.git",
|
||||||
"reference": "ef842484ba57f163c6d465ab744bfecb872a11d4"
|
"reference": "a161a26d917604dc6d3aa25100fddf2556e9f35d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/ef842484ba57f163c6d465ab744bfecb872a11d4",
|
"url": "https://api.github.com/repos/ramsey/uuid/zipball/a161a26d917604dc6d3aa25100fddf2556e9f35d",
|
||||||
"reference": "ef842484ba57f163c6d465ab744bfecb872a11d4",
|
"reference": "a161a26d917604dc6d3aa25100fddf2556e9f35d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -1058,7 +1058,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/ramsey/uuid/issues",
|
"issues": "https://github.com/ramsey/uuid/issues",
|
||||||
"source": "https://github.com/ramsey/uuid/tree/4.5.0"
|
"source": "https://github.com/ramsey/uuid/tree/4.5.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -1070,7 +1070,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-09-15T01:44:53+00:00"
|
"time": "2022-09-16T03:22:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-php81",
|
"name": "symfony/polyfill-php81",
|
||||||
|
@ -177,10 +177,10 @@ namespace pocketmine {
|
|||||||
|
|
||||||
|
|
||||||
--------------------------------------- ! WARNING ! ---------------------------------------
|
--------------------------------------- ! WARNING ! ---------------------------------------
|
||||||
You're using PHP 8.0 with JIT enabled. This provides significant performance improvements.
|
You're using PHP with JIT enabled. This provides significant performance improvements.
|
||||||
HOWEVER, it is EXPERIMENTAL, and has already been seen to cause weird and unexpected bugs.
|
HOWEVER, it is EXPERIMENTAL, and has already been seen to cause weird and unexpected bugs.
|
||||||
Proceed with caution.
|
Proceed with caution.
|
||||||
If you want to report any bugs, make sure to mention that you are using PHP 8.0 with JIT.
|
If you want to report any bugs, make sure to mention that you have enabled PHP JIT.
|
||||||
To turn off JIT, change `opcache.jit` to `0` in your php.ini file.
|
To turn off JIT, change `opcache.jit` to `0` in your php.ini file.
|
||||||
-------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -26,13 +26,14 @@ namespace pocketmine\crafting\json;
|
|||||||
final class RecipeIngredientData{
|
final class RecipeIngredientData{
|
||||||
public const WILDCARD_META_VALUE = 32767;
|
public const WILDCARD_META_VALUE = 32767;
|
||||||
|
|
||||||
/** @required */
|
|
||||||
public string $name;
|
public string $name;
|
||||||
public int $meta;
|
public int $meta;
|
||||||
public string $block_states;
|
public string $block_states;
|
||||||
public int $count;
|
|
||||||
|
|
||||||
public function __construct(string $name){
|
public string $tag;
|
||||||
$this->name = $name;
|
|
||||||
}
|
public string $molang_expression;
|
||||||
|
public int $molang_version;
|
||||||
|
|
||||||
|
public int $count;
|
||||||
}
|
}
|
||||||
|
@ -227,7 +227,7 @@ final class EntityFactory{
|
|||||||
*/
|
*/
|
||||||
public function createFromData(World $world, CompoundTag $nbt) : ?Entity{
|
public function createFromData(World $world, CompoundTag $nbt) : ?Entity{
|
||||||
try{
|
try{
|
||||||
$saveId = $nbt->getTag("id") ?? $nbt->getTag("identifier");
|
$saveId = $nbt->getTag("identifier") ?? $nbt->getTag("id");
|
||||||
$func = null;
|
$func = null;
|
||||||
if($saveId instanceof StringTag){
|
if($saveId instanceof StringTag){
|
||||||
$func = $this->creationFuncs[$saveId->getValue()] ?? null;
|
$func = $this->creationFuncs[$saveId->getValue()] ?? null;
|
||||||
@ -248,7 +248,7 @@ final class EntityFactory{
|
|||||||
|
|
||||||
public function injectSaveId(string $class, CompoundTag $saveData) : void{
|
public function injectSaveId(string $class, CompoundTag $saveData) : void{
|
||||||
if(isset($this->saveNames[$class])){
|
if(isset($this->saveNames[$class])){
|
||||||
$saveData->setTag("id", new StringTag($this->saveNames[$class]));
|
$saveData->setTag("identifier", new StringTag($this->saveNames[$class]));
|
||||||
}else{
|
}else{
|
||||||
throw new \InvalidArgumentException("Entity $class is not registered");
|
throw new \InvalidArgumentException("Entity $class is not registered");
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ class InstantDamageEffect extends InstantEffect{
|
|||||||
|
|
||||||
public function applyEffect(Living $entity, EffectInstance $instance, float $potency = 1.0, ?Entity $source = null) : void{
|
public function applyEffect(Living $entity, EffectInstance $instance, float $potency = 1.0, ?Entity $source = null) : void{
|
||||||
//TODO: add particles (witch spell)
|
//TODO: add particles (witch spell)
|
||||||
$damage = (4 << $instance->getAmplifier()) * $potency;
|
$damage = (6 << $instance->getAmplifier()) * $potency;
|
||||||
if($source !== null){
|
if($source !== null){
|
||||||
$sourceOwner = $source->getOwningEntity();
|
$sourceOwner = $source->getOwningEntity();
|
||||||
if($sourceOwner !== null){
|
if($sourceOwner !== null){
|
||||||
|
@ -30,7 +30,7 @@ use pocketmine\event\entity\EntityRegainHealthEvent;
|
|||||||
class RegenerationEffect extends Effect{
|
class RegenerationEffect extends Effect{
|
||||||
|
|
||||||
public function canTick(EffectInstance $instance) : bool{
|
public function canTick(EffectInstance $instance) : bool{
|
||||||
if(($interval = (40 >> $instance->getAmplifier())) > 0){
|
if(($interval = (50 >> $instance->getAmplifier())) > 0){
|
||||||
return ($instance->getDuration() % $interval) === 0;
|
return ($instance->getDuration() % $interval) === 0;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -179,6 +179,10 @@ class ItemEntity extends Entity{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function canSaveWithChunk() : bool{
|
||||||
|
return !$this->item->isNull() && parent::canSaveWithChunk();
|
||||||
|
}
|
||||||
|
|
||||||
public function saveNBT() : CompoundTag{
|
public function saveNBT() : CompoundTag{
|
||||||
$nbt = parent::saveNBT();
|
$nbt = parent::saveNBT();
|
||||||
$nbt->setTag("Item", $this->item->nbtSerialize());
|
$nbt->setTag("Item", $this->item->nbtSerialize());
|
||||||
|
@ -56,6 +56,7 @@ use pocketmine\network\mcpe\handler\LoginPacketHandler;
|
|||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
use pocketmine\network\mcpe\handler\PreSpawnPacketHandler;
|
use pocketmine\network\mcpe\handler\PreSpawnPacketHandler;
|
||||||
use pocketmine\network\mcpe\handler\ResourcePacksPacketHandler;
|
use pocketmine\network\mcpe\handler\ResourcePacksPacketHandler;
|
||||||
|
use pocketmine\network\mcpe\handler\SessionStartPacketHandler;
|
||||||
use pocketmine\network\mcpe\handler\SpawnResponsePacketHandler;
|
use pocketmine\network\mcpe\handler\SpawnResponsePacketHandler;
|
||||||
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
|
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
|
||||||
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
|
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
|
||||||
@ -164,6 +165,7 @@ class NetworkSession{
|
|||||||
*/
|
*/
|
||||||
private \SplQueue $compressedQueue;
|
private \SplQueue $compressedQueue;
|
||||||
private bool $forceAsyncCompression = true;
|
private bool $forceAsyncCompression = true;
|
||||||
|
private bool $enableCompression = false; //disabled until handshake completed
|
||||||
|
|
||||||
private PacketSerializerContext $packetSerializerContext;
|
private PacketSerializerContext $packetSerializerContext;
|
||||||
|
|
||||||
@ -196,17 +198,10 @@ class NetworkSession{
|
|||||||
|
|
||||||
$this->connectTime = time();
|
$this->connectTime = time();
|
||||||
|
|
||||||
$this->setHandler(new LoginPacketHandler(
|
$this->setHandler(new SessionStartPacketHandler(
|
||||||
$this->server,
|
$this->server,
|
||||||
$this,
|
$this,
|
||||||
function(PlayerInfo $info) : void{
|
fn() => $this->onSessionStartSuccess()
|
||||||
$this->info = $info;
|
|
||||||
$this->logger->info("Player: " . TextFormat::AQUA . $info->getUsername() . TextFormat::RESET);
|
|
||||||
$this->logger->setPrefix($this->getLogPrefix());
|
|
||||||
},
|
|
||||||
function(bool $isAuthenticated, bool $authRequired, ?string $error, ?string $clientPubKey) : void{
|
|
||||||
$this->setAuthenticationStatus($isAuthenticated, $authRequired, $error, $clientPubKey);
|
|
||||||
}
|
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->manager->add($this);
|
$this->manager->add($this);
|
||||||
@ -221,6 +216,24 @@ class NetworkSession{
|
|||||||
return $this->logger;
|
return $this->logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function onSessionStartSuccess() : void{
|
||||||
|
$this->logger->debug("Session start handshake completed, awaiting login packet");
|
||||||
|
$this->flushSendBuffer(true);
|
||||||
|
$this->enableCompression = true;
|
||||||
|
$this->setHandler(new LoginPacketHandler(
|
||||||
|
$this->server,
|
||||||
|
$this,
|
||||||
|
function(PlayerInfo $info) : void{
|
||||||
|
$this->info = $info;
|
||||||
|
$this->logger->info("Player: " . TextFormat::AQUA . $info->getUsername() . TextFormat::RESET);
|
||||||
|
$this->logger->setPrefix($this->getLogPrefix());
|
||||||
|
},
|
||||||
|
function(bool $isAuthenticated, bool $authRequired, ?string $error, ?string $clientPubKey) : void{
|
||||||
|
$this->setAuthenticationStatus($isAuthenticated, $authRequired, $error, $clientPubKey);
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
protected function createPlayer() : void{
|
protected function createPlayer() : void{
|
||||||
$this->server->createPlayer($this, $this->info, $this->authenticated, $this->cachedOfflinePlayerData)->onCompletion(
|
$this->server->createPlayer($this, $this->info, $this->authenticated, $this->cachedOfflinePlayerData)->onCompletion(
|
||||||
\Closure::fromCallable([$this, 'onPlayerCreated']),
|
\Closure::fromCallable([$this, 'onPlayerCreated']),
|
||||||
@ -335,18 +348,22 @@ class NetworkSession{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timings::$playerNetworkReceiveDecompress->startTiming();
|
if($this->enableCompression){
|
||||||
try{
|
Timings::$playerNetworkReceiveDecompress->startTiming();
|
||||||
$stream = new PacketBatch($this->compressor->decompress($payload));
|
try{
|
||||||
}catch(DecompressionException $e){
|
$decompressed = $this->compressor->decompress($payload);
|
||||||
$this->logger->debug("Failed to decompress packet: " . base64_encode($payload));
|
}catch(DecompressionException $e){
|
||||||
throw PacketHandlingException::wrap($e, "Compressed packet batch decode error");
|
$this->logger->debug("Failed to decompress packet: " . base64_encode($payload));
|
||||||
}finally{
|
throw PacketHandlingException::wrap($e, "Compressed packet batch decode error");
|
||||||
Timings::$playerNetworkReceiveDecompress->stopTiming();
|
}finally{
|
||||||
|
Timings::$playerNetworkReceiveDecompress->stopTiming();
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
$decompressed = $payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
foreach($stream->getPackets($this->packetPool, $this->packetSerializerContext, 500) as [$packet, $buffer]){
|
foreach((new PacketBatch($decompressed))->getPackets($this->packetPool, $this->packetSerializerContext, 500) as [$packet, $buffer]){
|
||||||
if($packet === null){
|
if($packet === null){
|
||||||
$this->logger->debug("Unknown packet: " . base64_encode($buffer));
|
$this->logger->debug("Unknown packet: " . base64_encode($buffer));
|
||||||
throw new PacketHandlingException("Unknown packet received");
|
throw new PacketHandlingException("Unknown packet received");
|
||||||
@ -451,7 +468,14 @@ class NetworkSession{
|
|||||||
}elseif($this->forceAsyncCompression){
|
}elseif($this->forceAsyncCompression){
|
||||||
$syncMode = false;
|
$syncMode = false;
|
||||||
}
|
}
|
||||||
$promise = $this->server->prepareBatch(PacketBatch::fromPackets($this->packetSerializerContext, ...$this->sendBuffer), $this->compressor, $syncMode);
|
|
||||||
|
$batch = PacketBatch::fromPackets($this->packetSerializerContext, ...$this->sendBuffer);
|
||||||
|
if($this->enableCompression){
|
||||||
|
$promise = $this->server->prepareBatch($batch, $this->compressor, $syncMode);
|
||||||
|
}else{
|
||||||
|
$promise = new CompressBatchPromise();
|
||||||
|
$promise->resolve($batch->getBuffer());
|
||||||
|
}
|
||||||
$this->sendBuffer = [];
|
$this->sendBuffer = [];
|
||||||
$this->queueCompressedNoBufferFlush($promise, $immediate);
|
$this->queueCompressedNoBufferFlush($promise, $immediate);
|
||||||
}
|
}
|
||||||
|
18
src/network/mcpe/cache/CraftingDataCache.php
vendored
18
src/network/mcpe/cache/CraftingDataCache.php
vendored
@ -35,6 +35,7 @@ use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
|
|||||||
use pocketmine\network\mcpe\protocol\types\recipe\CraftingRecipeBlockName;
|
use pocketmine\network\mcpe\protocol\types\recipe\CraftingRecipeBlockName;
|
||||||
use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipe as ProtocolFurnaceRecipe;
|
use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipe as ProtocolFurnaceRecipe;
|
||||||
use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipeBlockName;
|
use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipeBlockName;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\recipe\IntIdMetaItemDescriptor;
|
||||||
use pocketmine\network\mcpe\protocol\types\recipe\PotionContainerChangeRecipe as ProtocolPotionContainerChangeRecipe;
|
use pocketmine\network\mcpe\protocol\types\recipe\PotionContainerChangeRecipe as ProtocolPotionContainerChangeRecipe;
|
||||||
use pocketmine\network\mcpe\protocol\types\recipe\PotionTypeRecipe as ProtocolPotionTypeRecipe;
|
use pocketmine\network\mcpe\protocol\types\recipe\PotionTypeRecipe as ProtocolPotionTypeRecipe;
|
||||||
use pocketmine\network\mcpe\protocol\types\recipe\RecipeIngredient as ProtocolRecipeIngredient;
|
use pocketmine\network\mcpe\protocol\types\recipe\RecipeIngredient as ProtocolRecipeIngredient;
|
||||||
@ -138,7 +139,10 @@ final class CraftingDataCache{
|
|||||||
default => throw new AssumptionFailedError("Unreachable"),
|
default => throw new AssumptionFailedError("Unreachable"),
|
||||||
};
|
};
|
||||||
foreach($manager->getFurnaceRecipeManager($furnaceType)->getAll() as $recipe){
|
foreach($manager->getFurnaceRecipeManager($furnaceType)->getAll() as $recipe){
|
||||||
$input = $converter->coreRecipeIngredientToNet($recipe->getInput());
|
$input = $converter->coreRecipeIngredientToNet($recipe->getInput())->getDescriptor();
|
||||||
|
if(!$input instanceof IntIdMetaItemDescriptor){
|
||||||
|
throw new AssumptionFailedError();
|
||||||
|
}
|
||||||
$recipesWithTypeIds[] = new ProtocolFurnaceRecipe(
|
$recipesWithTypeIds[] = new ProtocolFurnaceRecipe(
|
||||||
CraftingDataPacket::ENTRY_FURNACE_DATA,
|
CraftingDataPacket::ENTRY_FURNACE_DATA,
|
||||||
$input->getId(),
|
$input->getId(),
|
||||||
@ -151,8 +155,11 @@ final class CraftingDataCache{
|
|||||||
|
|
||||||
$potionTypeRecipes = [];
|
$potionTypeRecipes = [];
|
||||||
foreach($manager->getPotionTypeRecipes() as $recipe){
|
foreach($manager->getPotionTypeRecipes() as $recipe){
|
||||||
$input = $converter->coreRecipeIngredientToNet($recipe->getInput());
|
$input = $converter->coreRecipeIngredientToNet($recipe->getInput())->getDescriptor();
|
||||||
$ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient());
|
$ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient())->getDescriptor();
|
||||||
|
if(!$input instanceof IntIdMetaItemDescriptor || !$ingredient instanceof IntIdMetaItemDescriptor){
|
||||||
|
throw new AssumptionFailedError();
|
||||||
|
}
|
||||||
$output = $converter->coreItemStackToNet($recipe->getOutput());
|
$output = $converter->coreItemStackToNet($recipe->getOutput());
|
||||||
$potionTypeRecipes[] = new ProtocolPotionTypeRecipe(
|
$potionTypeRecipes[] = new ProtocolPotionTypeRecipe(
|
||||||
$input->getId(),
|
$input->getId(),
|
||||||
@ -168,7 +175,10 @@ final class CraftingDataCache{
|
|||||||
$itemTypeDictionary = GlobalItemTypeDictionary::getInstance()->getDictionary();
|
$itemTypeDictionary = GlobalItemTypeDictionary::getInstance()->getDictionary();
|
||||||
foreach($manager->getPotionContainerChangeRecipes() as $recipe){
|
foreach($manager->getPotionContainerChangeRecipes() as $recipe){
|
||||||
$input = $itemTypeDictionary->fromStringId($recipe->getInputItemId());
|
$input = $itemTypeDictionary->fromStringId($recipe->getInputItemId());
|
||||||
$ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient());
|
$ingredient = $converter->coreRecipeIngredientToNet($recipe->getIngredient())->getDescriptor();
|
||||||
|
if(!$ingredient instanceof IntIdMetaItemDescriptor){
|
||||||
|
throw new AssumptionFailedError();
|
||||||
|
}
|
||||||
$output = $itemTypeDictionary->fromStringId($recipe->getOutputItemId());
|
$output = $itemTypeDictionary->fromStringId($recipe->getOutputItemId());
|
||||||
$potionContainerChangeRecipes[] = new ProtocolPotionContainerChangeRecipe(
|
$potionContainerChangeRecipes[] = new ProtocolPotionContainerChangeRecipe(
|
||||||
$input,
|
$input,
|
||||||
|
@ -43,7 +43,9 @@ use pocketmine\network\mcpe\protocol\types\inventory\ContainerIds;
|
|||||||
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
|
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
|
||||||
use pocketmine\network\mcpe\protocol\types\inventory\NetworkInventoryAction;
|
use pocketmine\network\mcpe\protocol\types\inventory\NetworkInventoryAction;
|
||||||
use pocketmine\network\mcpe\protocol\types\inventory\UIInventorySlotOffset;
|
use pocketmine\network\mcpe\protocol\types\inventory\UIInventorySlotOffset;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\recipe\IntIdMetaItemDescriptor;
|
||||||
use pocketmine\network\mcpe\protocol\types\recipe\RecipeIngredient as ProtocolRecipeIngredient;
|
use pocketmine\network\mcpe\protocol\types\recipe\RecipeIngredient as ProtocolRecipeIngredient;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\recipe\StringIdMetaItemDescriptor;
|
||||||
use pocketmine\player\GameMode;
|
use pocketmine\player\GameMode;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use pocketmine\utils\AssumptionFailedError;
|
use pocketmine\utils\AssumptionFailedError;
|
||||||
@ -111,7 +113,7 @@ class TypeConverter{
|
|||||||
|
|
||||||
public function coreRecipeIngredientToNet(?RecipeIngredient $ingredient) : ProtocolRecipeIngredient{
|
public function coreRecipeIngredientToNet(?RecipeIngredient $ingredient) : ProtocolRecipeIngredient{
|
||||||
if($ingredient === null){
|
if($ingredient === null){
|
||||||
return new ProtocolRecipeIngredient(0, 0, 0);
|
return new ProtocolRecipeIngredient(null, 0);
|
||||||
}
|
}
|
||||||
if($ingredient instanceof MetaWildcardRecipeIngredient){
|
if($ingredient instanceof MetaWildcardRecipeIngredient){
|
||||||
$id = GlobalItemTypeDictionary::getInstance()->getDictionary()->fromStringId($ingredient->getItemId());
|
$id = GlobalItemTypeDictionary::getInstance()->getDictionary()->fromStringId($ingredient->getItemId());
|
||||||
@ -128,29 +130,42 @@ class TypeConverter{
|
|||||||
}else{
|
}else{
|
||||||
throw new \LogicException("Unsupported recipe ingredient type " . get_class($ingredient) . ", only " . ExactRecipeIngredient::class . " and " . MetaWildcardRecipeIngredient::class . " are supported");
|
throw new \LogicException("Unsupported recipe ingredient type " . get_class($ingredient) . ", only " . ExactRecipeIngredient::class . " and " . MetaWildcardRecipeIngredient::class . " are supported");
|
||||||
}
|
}
|
||||||
return new ProtocolRecipeIngredient($id, $meta, 1);
|
|
||||||
|
return new ProtocolRecipeIngredient(new IntIdMetaItemDescriptor($id, $meta), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function netRecipeIngredientToCore(ProtocolRecipeIngredient $ingredient) : ?RecipeIngredient{
|
public function netRecipeIngredientToCore(ProtocolRecipeIngredient $ingredient) : ?RecipeIngredient{
|
||||||
if($ingredient->getId() === 0){
|
$descriptor = $ingredient->getDescriptor();
|
||||||
|
if($descriptor === null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$itemId = GlobalItemTypeDictionary::getInstance()->getDictionary()->fromIntId($ingredient->getId());
|
if($descriptor instanceof IntIdMetaItemDescriptor){
|
||||||
|
$stringId = GlobalItemTypeDictionary::getInstance()->getDictionary()->fromIntId($descriptor->getId());
|
||||||
if($ingredient->getMeta() === self::RECIPE_INPUT_WILDCARD_META){
|
$meta = $descriptor->getMeta();
|
||||||
return new MetaWildcardRecipeIngredient($itemId);
|
}elseif($descriptor instanceof StringIdMetaItemDescriptor){
|
||||||
|
$stringId = $descriptor->getId();
|
||||||
|
$meta = $descriptor->getMeta();
|
||||||
|
}else{
|
||||||
|
throw new \LogicException("Unsupported conversion of recipe ingredient to core item stack");
|
||||||
|
}
|
||||||
|
|
||||||
|
if($meta === self::RECIPE_INPUT_WILDCARD_META){
|
||||||
|
return new MetaWildcardRecipeIngredient($stringId);
|
||||||
}
|
}
|
||||||
|
|
||||||
$meta = $ingredient->getMeta();
|
|
||||||
$blockRuntimeId = null;
|
$blockRuntimeId = null;
|
||||||
if(($blockId = BlockItemIdMap::getInstance()->lookupBlockId($itemId)) !== null){
|
if(($blockId = BlockItemIdMap::getInstance()->lookupBlockId($stringId)) !== null){
|
||||||
$blockRuntimeId = RuntimeBlockMapping::getInstance()->getBlockStateDictionary()->lookupStateIdFromIdMeta($blockId, $meta);
|
$blockRuntimeId = RuntimeBlockMapping::getInstance()->getBlockStateDictionary()->lookupStateIdFromIdMeta($blockId, $meta);
|
||||||
if($blockRuntimeId !== null){
|
if($blockRuntimeId !== null){
|
||||||
$meta = 0;
|
$meta = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$result = ItemTranslator::getInstance()->fromNetworkId($ingredient->getId(), $meta, $blockRuntimeId ?? ItemTranslator::NO_BLOCK_RUNTIME_ID);
|
$result = ItemTranslator::getInstance()->fromNetworkId(
|
||||||
|
GlobalItemTypeDictionary::getInstance()->getDictionary()->fromStringId($stringId),
|
||||||
|
$meta,
|
||||||
|
$blockRuntimeId ?? ItemTranslator::NO_BLOCK_RUNTIME_ID
|
||||||
|
);
|
||||||
return new ExactRecipeIngredient($result);
|
return new ExactRecipeIngredient($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,6 @@ use pocketmine\network\mcpe\InventoryManager;
|
|||||||
use pocketmine\network\mcpe\NetworkSession;
|
use pocketmine\network\mcpe\NetworkSession;
|
||||||
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||||
use pocketmine\network\mcpe\protocol\ActorPickRequestPacket;
|
use pocketmine\network\mcpe\protocol\ActorPickRequestPacket;
|
||||||
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
|
|
||||||
use pocketmine\network\mcpe\protocol\AnimatePacket;
|
use pocketmine\network\mcpe\protocol\AnimatePacket;
|
||||||
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
|
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
|
||||||
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
|
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
|
||||||
@ -660,10 +659,6 @@ class InGamePacketHandler extends PacketHandler{
|
|||||||
return true; //this is a broken useless packet, so we don't use it
|
return true; //this is a broken useless packet, so we don't use it
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleAdventureSettings(AdventureSettingsPacket $packet) : bool{
|
|
||||||
return true; //no longer used, but the client still sends it for flight changes
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handleBlockActorData(BlockActorDataPacket $packet) : bool{
|
public function handleBlockActorData(BlockActorDataPacket $packet) : bool{
|
||||||
$pos = new Vector3($packet->blockPosition->getX(), $packet->blockPosition->getY(), $packet->blockPosition->getZ());
|
$pos = new Vector3($packet->blockPosition->getX(), $packet->blockPosition->getY(), $packet->blockPosition->getZ());
|
||||||
if($pos->distanceSquared($this->player->getLocation()) > 10000){
|
if($pos->distanceSquared($this->player->getLocation()) > 10000){
|
||||||
|
76
src/network/mcpe/handler/SessionStartPacketHandler.php
Normal file
76
src/network/mcpe/handler/SessionStartPacketHandler.php
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* @author PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\network\mcpe\handler;
|
||||||
|
|
||||||
|
use pocketmine\lang\KnownTranslationFactory;
|
||||||
|
use pocketmine\network\mcpe\NetworkSession;
|
||||||
|
use pocketmine\network\mcpe\protocol\NetworkSettingsPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\PlayStatusPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||||
|
use pocketmine\network\mcpe\protocol\RequestNetworkSettingsPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\CompressionAlgorithm;
|
||||||
|
use pocketmine\Server;
|
||||||
|
|
||||||
|
final class SessionStartPacketHandler extends PacketHandler{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phpstan-param \Closure() : void $onSuccess
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
private Server $server,
|
||||||
|
private NetworkSession $session,
|
||||||
|
private \Closure $onSuccess
|
||||||
|
){}
|
||||||
|
|
||||||
|
public function handleRequestNetworkSettings(RequestNetworkSettingsPacket $packet) : bool{
|
||||||
|
$protocolVersion = $packet->getProtocolVersion();
|
||||||
|
if(!$this->isCompatibleProtocol($protocolVersion)){
|
||||||
|
$this->session->sendDataPacket(PlayStatusPacket::create($protocolVersion < ProtocolInfo::CURRENT_PROTOCOL ? PlayStatusPacket::LOGIN_FAILED_CLIENT : PlayStatusPacket::LOGIN_FAILED_SERVER), true);
|
||||||
|
|
||||||
|
//This pocketmine disconnect message will only be seen by the console (PlayStatusPacket causes the messages to be shown for the client)
|
||||||
|
$this->session->disconnect(
|
||||||
|
$this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_disconnect_incompatibleProtocol((string) $protocolVersion)),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: we're filling in the defaults to get pre-1.19.30 behaviour back for now, but we should explore the new options in the future
|
||||||
|
$this->session->sendDataPacket(NetworkSettingsPacket::create(
|
||||||
|
NetworkSettingsPacket::COMPRESS_EVERYTHING,
|
||||||
|
CompressionAlgorithm::ZLIB,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
));
|
||||||
|
($this->onSuccess)();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isCompatibleProtocol(int $protocolVersion) : bool{
|
||||||
|
return $protocolVersion === ProtocolInfo::CURRENT_PROTOCOL;
|
||||||
|
}
|
||||||
|
}
|
@ -58,7 +58,7 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{
|
|||||||
* Sometimes this gets changed when the MCPE-layer protocol gets broken to the point where old and new can't
|
* Sometimes this gets changed when the MCPE-layer protocol gets broken to the point where old and new can't
|
||||||
* communicate. It's important that we check this to avoid catastrophes.
|
* communicate. It's important that we check this to avoid catastrophes.
|
||||||
*/
|
*/
|
||||||
private const MCPE_RAKNET_PROTOCOL_VERSION = 10;
|
private const MCPE_RAKNET_PROTOCOL_VERSION = 11;
|
||||||
|
|
||||||
private const MCPE_RAKNET_PACKET_ID = "\xfe";
|
private const MCPE_RAKNET_PACKET_ID = "\xfe";
|
||||||
|
|
||||||
|
@ -2502,7 +2502,7 @@ class World implements ChunkManager{
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if($entity === null){
|
if($entity === null){
|
||||||
$saveIdTag = $nbt->getTag("id") ?? $nbt->getTag("identifier");
|
$saveIdTag = $nbt->getTag("identifier") ?? $nbt->getTag("id");
|
||||||
$saveId = "<unknown>";
|
$saveId = "<unknown>";
|
||||||
if($saveIdTag instanceof StringTag){
|
if($saveIdTag instanceof StringTag){
|
||||||
$saveId = $saveIdTag->getValue();
|
$saveId = $saveIdTag->getValue();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user