Merge branch 'stable'

This commit is contained in:
Dylan K. Taylor 2020-11-21 21:13:48 +00:00
commit af1fe7c293
42 changed files with 1192 additions and 1075 deletions

18
changelogs/3.16.md Normal file
View File

@ -0,0 +1,18 @@
**For Minecraft: Bedrock Edition 1.16.100**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 3.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.
# 3.16.0
- Added support for Minecraft: Bedrock Edition 1.16.100.
- Removed compatibility with earlier versions.
- Added new custom composer commands `make-server` and `make-devtools` to ease setting up a development environment and building the server.
## Known issues (please don't open issues for these)
- Walls don't connect to each other
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
- New blocks, items & mobs aren't implemented
- Nether doesn't exist

View File

@ -153,7 +153,7 @@ class InventoryManager{
public function onCurrentWindowRemove() : void{
if(isset($this->windowMap[$this->lastInventoryNetworkId])){
$this->remove($this->lastInventoryNetworkId);
$this->session->sendDataPacket(ContainerClosePacket::create($this->lastInventoryNetworkId));
$this->session->sendDataPacket(ContainerClosePacket::create($this->lastInventoryNetworkId, true));
}
}

View File

@ -727,7 +727,7 @@ class NetworkSession{
if(count($attributes) > 0){
$this->sendDataPacket(UpdateAttributesPacket::create($entity->getId(), array_map(function(Attribute $attr) : NetworkAttribute{
return new NetworkAttribute($attr->getId(), $attr->getMinValue(), $attr->getMaxValue(), $attr->getValue(), $attr->getDefaultValue());
}, $attributes)));
}, $attributes), 0));
}
}
@ -736,7 +736,7 @@ class NetworkSession{
* @phpstan-param array<int, MetadataProperty> $properties
*/
public function syncActorData(Entity $entity, array $properties) : void{
$this->sendDataPacket(SetActorDataPacket::create($entity->getId(), $properties));
$this->sendDataPacket(SetActorDataPacket::create($entity->getId(), $properties, 0));
}
public function onEntityEffectAdded(Living $entity, EffectInstance $effect, bool $replacesOldEffect) : void{

View File

@ -0,0 +1,183 @@
<?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\convert;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\SingletonTrait;
use function array_key_exists;
use function file_get_contents;
use function is_array;
use function is_numeric;
use function is_string;
use function json_decode;
/**
* This class handles translation between network item ID+metadata to PocketMine-MP internal ID+metadata and vice versa.
*/
final class ItemTranslator{
use SingletonTrait;
/**
* @var int[]
* @phpstan-var array<int, int>
*/
private $simpleCoreToNetMapping = [];
/**
* @var int[]
* @phpstan-var array<int, int>
*/
private $simpleNetToCoreMapping = [];
/**
* runtimeId = array[internalId][metadata]
* @var int[][]
* @phpstan-var array<int, array<int, int>>
*/
private $complexCoreToNetMapping = [];
/**
* [internalId, metadata] = array[runtimeId]
* @var int[][]
* @phpstan-var array<int, array{int, int}>
*/
private $complexNetToCoreMapping = [];
private static function make() : self{
$data = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/r16_to_current_item_map.json');
if($data === false) throw new AssumptionFailedError("Missing required resource file");
$json = json_decode($data, true);
if(!is_array($json) or !isset($json["simple"], $json["complex"]) || !is_array($json["simple"]) || !is_array($json["complex"])){
throw new AssumptionFailedError("Invalid item table format");
}
$legacyStringToIntMapRaw = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/item_id_map.json');
if($legacyStringToIntMapRaw === false){
throw new AssumptionFailedError("Missing required resource file");
}
$legacyStringToIntMap = json_decode($legacyStringToIntMapRaw, true);
if(!is_array($legacyStringToIntMap)){
throw new AssumptionFailedError("Invalid mapping table format");
}
/** @phpstan-var array<string, int> $simpleMappings */
$simpleMappings = [];
foreach($json["simple"] as $oldId => $newId){
if(!is_string($oldId) || !is_string($newId)){
throw new AssumptionFailedError("Invalid item table format");
}
$simpleMappings[$newId] = $legacyStringToIntMap[$oldId];
}
foreach($legacyStringToIntMap as $stringId => $intId){
if(isset($simpleMappings[$stringId])){
throw new \UnexpectedValueException("Old ID $stringId collides with new ID");
}
$simpleMappings[$stringId] = $intId;
}
/** @phpstan-var array<string, array{int, int}> $complexMappings */
$complexMappings = [];
foreach($json["complex"] as $oldId => $map){
if(!is_string($oldId) || !is_array($map)){
throw new AssumptionFailedError("Invalid item table format");
}
foreach($map as $meta => $newId){
if(!is_numeric($meta) || !is_string($newId)){
throw new AssumptionFailedError("Invalid item table format");
}
$complexMappings[$newId] = [$legacyStringToIntMap[$oldId], (int) $meta];
}
}
return new self(ItemTypeDictionary::getInstance(), $simpleMappings, $complexMappings);
}
/**
* @param int[] $simpleMappings
* @param int[][] $complexMappings
* @phpstan-param array<string, int> $simpleMappings
* @phpstan-param array<string, array<int, int>> $complexMappings
*/
public function __construct(ItemTypeDictionary $dictionary, array $simpleMappings, array $complexMappings){
foreach($dictionary->getEntries() as $entry){
$stringId = $entry->getStringId();
$netId = $entry->getNumericId();
if(isset($complexMappings[$stringId])){
[$id, $meta] = $complexMappings[$stringId];
$this->complexCoreToNetMapping[$id][$meta] = $netId;
$this->complexNetToCoreMapping[$netId] = [$id, $meta];
}elseif(isset($simpleMappings[$stringId])){
$this->simpleCoreToNetMapping[$simpleMappings[$stringId]] = $netId;
$this->simpleNetToCoreMapping[$netId] = $simpleMappings[$stringId];
}elseif($stringId !== "minecraft:unknown"){
throw new \InvalidArgumentException("Unmapped entry " . $stringId);
}
}
}
/**
* @return int[]
* @phpstan-return array{int, int}
*/
public function toNetworkId(int $internalId, int $internalMeta) : array{
if(isset($this->complexCoreToNetMapping[$internalId][$internalMeta])){
return [$this->complexCoreToNetMapping[$internalId][$internalMeta], 0];
}
if(array_key_exists($internalId, $this->simpleCoreToNetMapping)){
return [$this->simpleCoreToNetMapping[$internalId], $internalMeta];
}
throw new \InvalidArgumentException("Unmapped ID/metadata combination $internalId:$internalMeta");
}
/**
* @return int[]
* @phpstan-return array{int, int}
*/
public function fromNetworkId(int $networkId, int $networkMeta, ?bool &$isComplexMapping = null) : array{
if(isset($this->complexNetToCoreMapping[$networkId])){
if($networkMeta !== 0){
throw new \UnexpectedValueException("Unexpected non-zero network meta on complex item mapping");
}
$isComplexMapping = true;
return $this->complexNetToCoreMapping[$networkId];
}
$isComplexMapping = false;
if(isset($this->simpleNetToCoreMapping[$networkId])){
return [$this->simpleNetToCoreMapping[$networkId], $networkMeta];
}
throw new \UnexpectedValueException("Unmapped network ID/metadata combination $networkId:$networkMeta");
}
/**
* @return int[]
* @phpstan-return array{int, int}
*/
public function fromNetworkIdWithWildcardHandling(int $networkId, int $networkMeta) : array{
$isComplexMapping = false;
if($networkMeta !== 0x7fff){
return $this->fromNetworkId($networkId, $networkMeta);
}
[$id, $meta] = $this->fromNetworkId($networkId, 0, $isComplexMapping);
return [$id, $isComplexMapping ? $meta : -1];
}
}

View File

@ -0,0 +1,106 @@
<?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\convert;
use pocketmine\network\mcpe\protocol\types\ItemTypeEntry;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\SingletonTrait;
use function array_key_exists;
use function file_get_contents;
use function is_array;
use function is_bool;
use function is_int;
use function is_string;
use function json_decode;
final class ItemTypeDictionary{
use SingletonTrait;
/**
* @var ItemTypeEntry[]
* @phpstan-var list<ItemTypeEntry>
*/
private $itemTypes;
/**
* @var string[]
* @phpstan-var array<int, string>
*/
private $intToStringIdMap = [];
/**
* @var int[]
* @phpstan-var array<string, int>
*/
private $stringToIntMap = [];
private static function make() : self{
$data = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/required_item_list.json');
if($data === false) throw new AssumptionFailedError("Missing required resource file");
$table = json_decode($data, true);
if(!is_array($table)){
throw new AssumptionFailedError("Invalid item list format");
}
$params = [];
foreach($table as $name => $entry){
if(!is_array($entry) || !is_string($name) || !isset($entry["component_based"], $entry["runtime_id"]) || !is_bool($entry["component_based"]) || !is_int($entry["runtime_id"])){
throw new AssumptionFailedError("Invalid item list format");
}
$params[] = new ItemTypeEntry($name, $entry["runtime_id"], $entry["component_based"]);
}
return new self($params);
}
/**
* @param ItemTypeEntry[] $itemTypes
*/
public function __construct(array $itemTypes){
$this->itemTypes = $itemTypes;
foreach($this->itemTypes as $type){
$this->stringToIntMap[$type->getStringId()] = $type->getNumericId();
$this->intToStringIdMap[$type->getNumericId()] = $type->getStringId();
}
}
/**
* @return ItemTypeEntry[]
* @phpstan-return list<ItemTypeEntry>
*/
public function getEntries() : array{
return $this->itemTypes;
}
public function fromStringId(string $stringId) : int{
if(!array_key_exists($stringId, $this->stringToIntMap)){
throw new \InvalidArgumentException("Unmapped string ID \"$stringId\"");
}
return $this->stringToIntMap[$stringId];
}
public function fromIntId(int $intId) : string{
if(!array_key_exists($intId, $this->intToStringIdMap)){
throw new \InvalidArgumentException("Unmapped int ID $intId");
}
return $this->intToStringIdMap[$intId];
}
}

View File

@ -25,18 +25,12 @@ namespace pocketmine\network\mcpe\convert;
use pocketmine\block\BlockLegacyIds;
use pocketmine\data\bedrock\LegacyBlockIdToStringIdMap;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
use pocketmine\network\mcpe\protocol\types\CacheableNbt;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\SingletonTrait;
use function file_get_contents;
use function getmypid;
use function mt_rand;
use function mt_srand;
use function shuffle;
/**
* @internal
@ -50,21 +44,18 @@ final class RuntimeBlockMapping{
private $runtimeToLegacyMap = [];
/** @var CompoundTag[] */
private $bedrockKnownStates;
/**
* @var CacheableNbt|null
* @phpstan-var CacheableNbt<\pocketmine\nbt\tag\ListTag>|null
*/
private $startGamePaletteCache = null;
private function __construct(){
$tag = (new NetworkNbtSerializer())->read(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/required_block_states.nbt"))->getTag();
if(!($tag instanceof ListTag) or $tag->getTagType() !== NBT::TAG_Compound){ //this is a little redundant currently, but good for auto complete and makes phpstan happy
throw new \RuntimeException("Invalid blockstates table, expected TAG_List<TAG_Compound> root");
$canonicalBlockStatesFile = file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/canonical_block_states.nbt");
if($canonicalBlockStatesFile === false){
throw new AssumptionFailedError("Missing required resource file");
}
/** @var CompoundTag[] $list */
$list = $tag->getValue();
$this->bedrockKnownStates = self::randomizeTable($list);
$stream = new PacketSerializer($canonicalBlockStatesFile);
$list = [];
while(!$stream->feof()){
$list[] = $stream->getNbtCompoundRoot();
}
$this->bedrockKnownStates = $list;
$this->setupLegacyMappings();
}
@ -90,7 +81,7 @@ final class RuntimeBlockMapping{
*/
$idToStatesMap = [];
foreach($this->bedrockKnownStates as $k => $state){
$idToStatesMap[$state->getCompoundTag("block")->getString("name")][] = $k;
$idToStatesMap[$state->getString("name")][] = $k;
}
foreach($legacyStateMap as $pair){
$id = $legacyIdMap->stringToLegacy($pair->getId()) ?? null;
@ -109,7 +100,7 @@ final class RuntimeBlockMapping{
}
foreach($idToStatesMap[$mappedName] as $k){
$networkState = $this->bedrockKnownStates[$k];
if($mappedState->equals($networkState->getCompoundTag("block"))){
if($mappedState->equals($networkState)){
$this->registerMapping($k, $id, $data);
continue 2;
}
@ -118,23 +109,6 @@ final class RuntimeBlockMapping{
}
}
/**
* Randomizes the order of the runtimeID table to prevent plugins relying on them.
* Plugins shouldn't use this stuff anyway, but plugin devs have an irritating habit of ignoring what they
* aren't supposed to do, so we have to deliberately break it to make them stop.
*
* @param CompoundTag[] $table
*
* @return CompoundTag[]
*/
private static function randomizeTable(array $table) : array{
$postSeed = mt_rand(); //save a seed to set afterwards, to avoid poor quality randoms
mt_srand(getmypid()); //Use a seed which is the same on all threads. This isn't a secure seed, but we don't care.
shuffle($table);
mt_srand($postSeed); //restore a good quality seed that isn't dependent on PID
return $table;
}
public function toRuntimeId(int $internalStateId) : int{
return $this->legacyToRuntimeMap[$internalStateId] ?? $this->legacyToRuntimeMap[BlockLegacyIds::INFO_UPDATE << 4];
}
@ -146,7 +120,6 @@ final class RuntimeBlockMapping{
private function registerMapping(int $staticRuntimeId, int $legacyId, int $legacyMeta) : void{
$this->legacyToRuntimeMap[($legacyId << 4) | $legacyMeta] = $staticRuntimeId;
$this->runtimeToLegacyMap[$staticRuntimeId] = ($legacyId << 4) | $legacyMeta;
$this->startGamePaletteCache = null;
}
/**
@ -155,11 +128,4 @@ final class RuntimeBlockMapping{
public function getBedrockKnownStates() : array{
return $this->bedrockKnownStates;
}
/**
* @phpstan-return CacheableNbt<\pocketmine\nbt\tag\ListTag>
*/
public function getStartGamePaletteCache() : CacheableNbt{
return $this->startGamePaletteCache ?? ($this->startGamePaletteCache = new CacheableNbt(new ListTag($this->bedrockKnownStates)));
}
}

View File

@ -55,6 +55,14 @@ class TypeConverter{
private const DAMAGE_TAG = "Damage"; //TAG_Int
private const DAMAGE_TAG_CONFLICT_RESOLUTION = "___Damage_ProtocolCollisionResolution___";
/** @var int */
private $shieldRuntimeId;
public function __construct(){
//TODO: inject stuff via constructor
$this->shieldRuntimeId = ItemTypeDictionary::getInstance()->fromStringId("minecraft:shield");
}
/**
* Returns a client-friendly gamemode of the specified real gamemode
* This function takes care of handling gamemodes known to MCPE (as of 1.1.0.3, that includes Survival, Creative and Adventure)
@ -92,16 +100,30 @@ class TypeConverter{
}
public function coreItemStackToRecipeIngredient(Item $itemStack) : RecipeIngredient{
$meta = $itemStack->getMeta();
return new RecipeIngredient($itemStack->getId(), $meta === -1 ? 0x7fff : $meta, $itemStack->getCount());
if($itemStack->isNull()){
return new RecipeIngredient(0, 0, 0);
}
if($itemStack->hasAnyDamageValue()){
[$id, ] = ItemTranslator::getInstance()->toNetworkId($itemStack->getId(), 0);
$meta = 0x7fff;
}else{
[$id, $meta] = ItemTranslator::getInstance()->toNetworkId($itemStack->getId(), $itemStack->getMeta());
}
return new RecipeIngredient($id, $meta, $itemStack->getCount());
}
public function recipeIngredientToCoreItemStack(RecipeIngredient $ingredient) : Item{
$meta = $ingredient->getMeta();
return ItemFactory::getInstance()->get($ingredient->getId(), $meta === 0x7fff ? -1 : $meta, $ingredient->getCount());
if($ingredient->getId() === 0){
return ItemFactory::getInstance()->get(ItemIds::AIR, 0, 0);
}
[$id, $meta] = ItemTranslator::getInstance()->fromNetworkIdWithWildcardHandling($ingredient->getId(), $ingredient->getMeta());
return ItemFactory::getInstance()->get($id, $meta, $ingredient->getCount());
}
public function coreItemStackToNet(Item $itemStack) : ItemStack{
if($itemStack->isNull()){
return ItemStack::null();
}
$nbt = null;
if($itemStack->hasNamedTag()){
$nbt = clone $itemStack->getNamedTag();
@ -117,23 +139,26 @@ class TypeConverter{
}
$nbt->setInt(self::DAMAGE_TAG, $itemStack->getDamage());
}
$id = $itemStack->getId();
$meta = $itemStack->getMeta();
[$id, $meta] = ItemTranslator::getInstance()->toNetworkId($itemStack->getId(), $itemStack->getMeta());
return new ItemStack(
$id,
$meta === -1 ? 0x7fff : $meta,
$meta,
$itemStack->getCount(),
$nbt,
[],
[],
$id === ItemIds::SHIELD ? 0 : null
$id === $this->shieldRuntimeId ? 0 : null
);
}
public function netItemStackToCore(ItemStack $itemStack) : Item{
if($itemStack->getId() === 0){
return ItemFactory::getInstance()->get(ItemIds::AIR, 0, 0);
}
$compound = $itemStack->getNbt();
$meta = $itemStack->getMeta();
[$id, $meta] = ItemTranslator::getInstance()->fromNetworkId($itemStack->getId(), $itemStack->getMeta());
if($compound !== null){
$compound = clone $compound;
@ -153,8 +178,8 @@ class TypeConverter{
end:
return ItemFactory::getInstance()->get(
$itemStack->getId(),
$meta !== 0x7fff ? $meta : -1,
$id,
$meta,
$itemStack->getCount(),
$compound
);

View File

@ -49,13 +49,9 @@ class DeathPacketHandler extends PacketHandler{
}
public function handlePlayerAction(PlayerActionPacket $packet) : bool{
switch($packet->action){
case PlayerActionPacket::ACTION_RESPAWN:
$this->player->respawn();
return true;
case PlayerActionPacket::ACTION_DIMENSION_CHANGE_REQUEST:
//TODO: players send this when they die in another dimension
break;
if($packet->action === PlayerActionPacket::ACTION_RESPAWN){
$this->player->respawn();
return true;
}
return false;

View File

@ -47,7 +47,6 @@ use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\network\mcpe\InventoryManager;
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\ActorFallPacket;
use pocketmine\network\mcpe\protocol\ActorPickRequestPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket;
@ -279,7 +278,7 @@ class InGamePacketHandler extends PacketHandler{
* So people don't whine about messy desync issues when someone cancels CraftItemEvent, or when a crafting
* transaction goes wrong.
*/
$this->session->sendDataPacket(ContainerClosePacket::create(InventoryManager::HARDCODED_CRAFTING_GRID_WINDOW_ID));
$this->session->sendDataPacket(ContainerClosePacket::create(InventoryManager::HARDCODED_CRAFTING_GRID_WINDOW_ID, true));
return false;
}finally{
@ -536,7 +535,10 @@ class InGamePacketHandler extends PacketHandler{
case PlayerActionPacket::ACTION_STOP_SWIMMING:
//TODO: handle this when it doesn't spam every damn tick (yet another spam bug!!)
break;
case PlayerActionPacket::ACTION_INTERACT_BLOCK: //ignored (for now)
case PlayerActionPacket::ACTION_INTERACT_BLOCK: //TODO: ignored (for now)
break;
case PlayerActionPacket::ACTION_CREATIVE_PLAYER_DESTROY_BLOCK:
//TODO: do we need to handle this?
break;
default:
$this->session->getLogger()->debug("Unhandled/unknown player action type " . $packet->action);
@ -548,10 +550,6 @@ class InGamePacketHandler extends PacketHandler{
return true;
}
public function handleActorFall(ActorFallPacket $packet) : bool{
return true; //Not used
}
public function handleAnimate(AnimatePacket $packet) : bool{
return true; //Not used
}
@ -565,7 +563,7 @@ class InGamePacketHandler extends PacketHandler{
$this->session->getInvManager()->onClientRemoveWindow($packet->windowId);
}
$this->session->sendDataPacket(ContainerClosePacket::create($packet->windowId));
$this->session->sendDataPacket(ContainerClosePacket::create($packet->windowId, false));
return true;
}

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\handler;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\ActorFallPacket;
use pocketmine\network\mcpe\protocol\ActorPickRequestPacket;
use pocketmine\network\mcpe\protocol\AddActorPacket;
use pocketmine\network\mcpe\protocol\AddBehaviorTreePacket;
@ -33,6 +32,7 @@ use pocketmine\network\mcpe\protocol\AddItemActorPacket;
use pocketmine\network\mcpe\protocol\AddPaintingPacket;
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimateEntityPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\AnvilDamagePacket;
use pocketmine\network\mcpe\protocol\AutomationClientConnectPacket;
@ -45,6 +45,7 @@ use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
use pocketmine\network\mcpe\protocol\BookEditPacket;
use pocketmine\network\mcpe\protocol\BossEventPacket;
use pocketmine\network\mcpe\protocol\CameraPacket;
use pocketmine\network\mcpe\protocol\CameraShakePacket;
use pocketmine\network\mcpe\protocol\ChangeDimensionPacket;
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
use pocketmine\network\mcpe\protocol\ClientboundMapItemDataPacket;
@ -60,6 +61,7 @@ use pocketmine\network\mcpe\protocol\CompletedUsingItemPacket;
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
use pocketmine\network\mcpe\protocol\ContainerOpenPacket;
use pocketmine\network\mcpe\protocol\ContainerSetDataPacket;
use pocketmine\network\mcpe\protocol\CorrectPlayerMovePredictionPacket;
use pocketmine\network\mcpe\protocol\CraftingDataPacket;
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
use pocketmine\network\mcpe\protocol\CreativeContentPacket;
@ -76,6 +78,7 @@ use pocketmine\network\mcpe\protocol\InteractPacket;
use pocketmine\network\mcpe\protocol\InventoryContentPacket;
use pocketmine\network\mcpe\protocol\InventorySlotPacket;
use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
use pocketmine\network\mcpe\protocol\ItemComponentPacket;
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
use pocketmine\network\mcpe\protocol\ItemStackRequestPacket;
use pocketmine\network\mcpe\protocol\ItemStackResponsePacket;
@ -95,6 +98,7 @@ use pocketmine\network\mcpe\protocol\MobEffectPacket;
use pocketmine\network\mcpe\protocol\MobEquipmentPacket;
use pocketmine\network\mcpe\protocol\ModalFormRequestPacket;
use pocketmine\network\mcpe\protocol\ModalFormResponsePacket;
use pocketmine\network\mcpe\protocol\MotionPredictionHintsPacket;
use pocketmine\network\mcpe\protocol\MoveActorAbsolutePacket;
use pocketmine\network\mcpe\protocol\MoveActorDeltaPacket;
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
@ -111,6 +115,7 @@ use pocketmine\network\mcpe\protocol\PlayerActionPacket;
use pocketmine\network\mcpe\protocol\PlayerArmorDamagePacket;
use pocketmine\network\mcpe\protocol\PlayerAuthInputPacket;
use pocketmine\network\mcpe\protocol\PlayerEnchantOptionsPacket;
use pocketmine\network\mcpe\protocol\PlayerFogPacket;
use pocketmine\network\mcpe\protocol\PlayerHotbarPacket;
use pocketmine\network\mcpe\protocol\PlayerInputPacket;
use pocketmine\network\mcpe\protocol\PlayerListPacket;
@ -171,7 +176,6 @@ use pocketmine\network\mcpe\protocol\TickSyncPacket;
use pocketmine\network\mcpe\protocol\TransferPacket;
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPropertiesPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockSyncedPacket;
use pocketmine\network\mcpe\protocol\UpdateEquipPacket;
use pocketmine\network\mcpe\protocol\UpdatePlayerGameTypePacket;
@ -330,10 +334,6 @@ abstract class PacketHandler implements PacketHandlerInterface{
return false;
}
public function handleActorFall(ActorFallPacket $packet) : bool{
return false;
}
public function handleHurtArmor(HurtArmorPacket $packet) : bool{
return false;
}
@ -710,10 +710,6 @@ abstract class PacketHandler implements PacketHandlerInterface{
return false;
}
public function handleUpdateBlockProperties(UpdateBlockPropertiesPacket $packet) : bool{
return false;
}
public function handleClientCacheBlobStatus(ClientCacheBlobStatusPacket $packet) : bool{
return false;
}
@ -801,4 +797,28 @@ abstract class PacketHandler implements PacketHandlerInterface{
public function handlePacketViolationWarning(PacketViolationWarningPacket $packet) : bool{
return false;
}
public function handleMotionPredictionHints(MotionPredictionHintsPacket $packet) : bool{
return false;
}
public function handleAnimateEntity(AnimateEntityPacket $packet) : bool{
return false;
}
public function handleCameraShake(CameraShakePacket $packet) : bool{
return false;
}
public function handlePlayerFog(PlayerFogPacket $packet) : bool{
return false;
}
public function handleCorrectPlayerMovePrediction(CorrectPlayerMovePredictionPacket $packet) : bool{
return false;
}
public function handleItemComponent(ItemComponentPacket $packet) : bool{
return false;
}
}

View File

@ -23,16 +23,16 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\handler;
use pocketmine\data\bedrock\LegacyItemIdToStringIdMap;
use pocketmine\network\mcpe\cache\CraftingDataCache;
use pocketmine\network\mcpe\cache\StaticPacketCache;
use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
use pocketmine\network\mcpe\convert\ItemTypeDictionary;
use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket;
use pocketmine\network\mcpe\protocol\StartGamePacket;
use pocketmine\network\mcpe\protocol\types\BoolGameRule;
use pocketmine\network\mcpe\protocol\types\DimensionIds;
use pocketmine\network\mcpe\protocol\types\Experiments;
use pocketmine\network\mcpe\protocol\types\SpawnSettings;
use pocketmine\player\Player;
use pocketmine\Server;
@ -82,10 +82,10 @@ class PreSpawnPacketHandler extends PacketHandler{
$pk->gameRules = [
"naturalregeneration" => new BoolGameRule(false) //Hack for client side regeneration
];
$pk->experiments = new Experiments([], false);
$pk->levelId = "";
$pk->worldName = $this->server->getMotd();
$pk->blockTable = RuntimeBlockMapping::getInstance()->getStartGamePaletteCache();
$pk->itemTable = LegacyItemIdToStringIdMap::getInstance()->getStringToLegacyMap(); //TODO: check if this is actually needed
$pk->itemTable = ItemTypeDictionary::getInstance()->getEntries(); //TODO: check if this is actually needed
$this->session->sendDataPacket($pk);
$this->session->sendDataPacket(StaticPacketCache::getInstance()->getAvailableActorIdentifiers());

View File

@ -30,6 +30,7 @@ use pocketmine\network\mcpe\protocol\ResourcePackClientResponsePacket;
use pocketmine\network\mcpe\protocol\ResourcePackDataInfoPacket;
use pocketmine\network\mcpe\protocol\ResourcePacksInfoPacket;
use pocketmine\network\mcpe\protocol\ResourcePackStackPacket;
use pocketmine\network\mcpe\protocol\types\Experiments;
use pocketmine\network\mcpe\protocol\types\resourcepacks\ResourcePackInfoEntry;
use pocketmine\network\mcpe\protocol\types\resourcepacks\ResourcePackStackEntry;
use pocketmine\resourcepacks\ResourcePack;
@ -127,7 +128,7 @@ class ResourcePacksPacketHandler extends PacketHandler{
//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
//the client remove its own non-server-supplied resource packs.
$this->session->sendDataPacket(ResourcePackStackPacket::create($stack, [], false, false));
$this->session->sendDataPacket(ResourcePackStackPacket::create($stack, [], false, new Experiments([], false)));
$this->session->getLogger()->debug("Applying resource pack stack");
break;
case ResourcePackClientResponsePacket::STATUS_COMPLETED:

View File

@ -0,0 +1,108 @@
<?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\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
use function count;
class AnimateEntityPacket extends DataPacket implements ClientboundPacket{
public const NETWORK_ID = ProtocolInfo::ANIMATE_ENTITY_PACKET;
/** @var string */
private $animation;
/** @var string */
private $nextState;
/** @var string */
private $stopExpression;
/** @var string */
private $controller;
/** @var float */
private $blendOutTime;
/**
* @var int[]
* @phpstan-var list<int>
*/
private $actorRuntimeIds;
/**
* @param int[] $actorRuntimeIds
* @phpstan-param list<int> $actorRuntimeIds
*/
public static function create(string $animation, string $nextState, string $stopExpression, string $controller, float $blendOutTime, array $actorRuntimeIds) : self{
$result = new self;
$result->animation = $animation;
$result->nextState = $nextState;
$result->stopExpression = $stopExpression;
$result->controller = $controller;
$result->blendOutTime = $blendOutTime;
$result->actorRuntimeIds = $actorRuntimeIds;
return $result;
}
public function getAnimation() : string{ return $this->animation; }
public function getNextState() : string{ return $this->nextState; }
public function getStopExpression() : string{ return $this->stopExpression; }
public function getController() : string{ return $this->controller; }
public function getBlendOutTime() : float{ return $this->blendOutTime; }
/**
* @return int[]
* @phpstan-return list<int>
*/
public function getActorRuntimeIds() : array{ return $this->actorRuntimeIds; }
protected function decodePayload(PacketSerializer $in) : void{
$this->animation = $in->getString();
$this->nextState = $in->getString();
$this->stopExpression = $in->getString();
$this->controller = $in->getString();
$this->blendOutTime = $in->getLFloat();
$this->actorRuntimeIds = [];
for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){
$this->actorRuntimeIds[] = $in->getEntityRuntimeId();
}
}
protected function encodePayload(PacketSerializer $out) : void{
$out->putString($this->animation);
$out->putString($this->nextState);
$out->putString($this->stopExpression);
$out->putString($this->controller);
$out->putLFloat($this->blendOutTime);
$out->putUnsignedVarInt(count($this->actorRuntimeIds));
foreach($this->actorRuntimeIds as $id){
$out->putEntityRuntimeId($id);
}
}
public function handle(PacketHandlerInterface $handler) : bool{
return $handler->handleAnimateEntity($this);
}
}

View File

@ -0,0 +1,72 @@
<?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\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
class CameraShakePacket extends DataPacket implements ClientboundPacket{
public const NETWORK_ID = ProtocolInfo::CAMERA_SHAKE_PACKET;
public const TYPE_POSITIONAL = 0;
public const TYPE_ROTATIONAL = 1;
/** @var float */
private $intensity;
/** @var float */
private $duration;
/** @var int */
private $shakeType;
public static function create(float $intensity, float $duration, int $shakeType) : self{
$result = new self;
$result->intensity = $intensity;
$result->duration = $duration;
$result->shakeType = $shakeType;
return $result;
}
public function getIntensity() : float{ return $this->intensity; }
public function getDuration() : float{ return $this->duration; }
public function getShakeType() : int{ return $this->shakeType; }
protected function decodePayload(PacketSerializer $in) : void{
$this->intensity = $in->getLFloat();
$this->duration = $in->getLFloat();
$this->shakeType = $in->getByte();
}
protected function encodePayload(PacketSerializer $out) : void{
$out->putLFloat($this->intensity);
$out->putLFloat($this->duration);
$out->putByte($this->shakeType);
}
public function handle(PacketHandlerInterface $handler) : bool{
return $handler->handleCameraShake($this);
}
}

View File

@ -32,19 +32,24 @@ class ContainerClosePacket extends DataPacket implements ClientboundPacket, Serv
/** @var int */
public $windowId;
/** @var bool */
public $server = false;
public static function create(int $windowId) : self{
public static function create(int $windowId, bool $server) : self{
$result = new self;
$result->windowId = $windowId;
$result->server = $server;
return $result;
}
protected function decodePayload(PacketSerializer $in) : void{
$this->windowId = $in->getByte();
$this->server = $in->getBool();
}
protected function encodePayload(PacketSerializer $out) : void{
$out->putByte($this->windowId);
$out->putBool($this->server);
}
public function handle(PacketHandlerInterface $handler) : bool{

View File

@ -0,0 +1,77 @@
<?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\protocol;
#include <rules/DataPacket.h>
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
class CorrectPlayerMovePredictionPacket extends DataPacket implements ClientboundPacket{
public const NETWORK_ID = ProtocolInfo::CORRECT_PLAYER_MOVE_PREDICTION_PACKET;
/** @var Vector3 */
private $position;
/** @var Vector3 */
private $delta;
/** @var bool */
private $onGround;
/** @var int */
private $tick;
public static function create(Vector3 $position, Vector3 $delta, bool $onGround, int $tick) : self{
$result = new self;
$result->position = $position;
$result->delta = $delta;
$result->onGround = $onGround;
$result->tick = $tick;
return $result;
}
public function getPosition() : Vector3{ return $this->position; }
public function getDelta() : Vector3{ return $this->delta; }
public function isOnGround() : bool{ return $this->onGround; }
public function getTick() : int{ return $this->tick; }
protected function decodePayload(PacketSerializer $in) : void{
$this->position = $in->getVector3();
$this->delta = $in->getVector3();
$this->onGround = $in->getBool();
$this->tick = $in->getUnsignedVarLong();
}
protected function encodePayload(PacketSerializer $out) : void{
$out->putVector3($this->position);
$out->putVector3($this->delta);
$out->putBool($this->onGround);
$out->putUnsignedVarLong($this->tick);
}
public function handle(PacketHandlerInterface $handler) : bool{
return $handler->handleCorrectPlayerMovePrediction($this);
}
}

View File

@ -0,0 +1,79 @@
<?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\protocol;
#include <rules/DataPacket.h>
use pocketmine\nbt\TreeRoot;
use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
use pocketmine\network\mcpe\protocol\types\ItemComponentPacketEntry;
use function count;
class ItemComponentPacket extends DataPacket implements ClientboundPacket{
public const NETWORK_ID = ProtocolInfo::ITEM_COMPONENT_PACKET;
/**
* @var ItemComponentPacketEntry[]
* @phpstan-var list<ItemComponentPacketEntry>
*/
private $entries;
/**
* @param ItemComponentPacketEntry[] $entries
* @phpstan-param list<ItemComponentPacketEntry> $entries
*/
public static function create(array $entries) : self{
$result = new self;
$result->entries = $entries;
return $result;
}
/**
* @return ItemComponentPacketEntry[]
* @phpstan-return list<ItemComponentPacketEntry>
*/
public function getEntries() : array{ return $this->entries; }
protected function decodePayload(PacketSerializer $in) : void{
$this->entries = [];
for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){
$name = $in->getString();
$nbt = $in->getNbtCompoundRoot();
$this->entries[] = new ItemComponentPacketEntry($name, $nbt);
}
}
protected function encodePayload(PacketSerializer $out) : void{
$out->putUnsignedVarInt(count($this->entries));
foreach($this->entries as $entry){
$out->putString($entry->getName());
$out->put((new NetworkNbtSerializer())->write(new TreeRoot($entry->getComponentNbt())));
}
}
public function handle(PacketHandlerInterface $handler) : bool{
return $handler->handleItemComponent($this);
}
}

View File

@ -25,31 +25,46 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
class ActorFallPacket extends DataPacket implements ServerboundPacket{
public const NETWORK_ID = ProtocolInfo::ACTOR_FALL_PACKET;
class MotionPredictionHintsPacket extends DataPacket implements ClientboundPacket{
public const NETWORK_ID = ProtocolInfo::MOTION_PREDICTION_HINTS_PACKET;
/** @var int */
public $entityRuntimeId;
/** @var float */
public $fallDistance;
private $entityRuntimeId;
/** @var Vector3 */
private $motion;
/** @var bool */
public $isInVoid;
private $onGround;
public static function create(int $entityRuntimeId, Vector3 $motion, bool $onGround) : self{
$result = new self;
$result->entityRuntimeId = $entityRuntimeId;
$result->motion = $motion;
$result->onGround = $onGround;
return $result;
}
public function getEntityRuntimeId() : int{ return $this->entityRuntimeId; }
public function getMotion() : Vector3{ return $this->motion; }
public function isOnGround() : bool{ return $this->onGround; }
protected function decodePayload(PacketSerializer $in) : void{
$this->entityRuntimeId = $in->getEntityRuntimeId();
$this->fallDistance = $in->getLFloat();
$this->isInVoid = $in->getBool();
$this->motion = $in->getVector3();
$this->onGround = $in->getBool();
}
protected function encodePayload(PacketSerializer $out) : void{
$out->putEntityRuntimeId($this->entityRuntimeId);
$out->putLFloat($this->fallDistance);
$out->putBool($this->isInVoid);
$out->putVector3($this->motion);
$out->putBool($this->onGround);
}
public function handle(PacketHandlerInterface $handler) : bool{
return $handler->handleActorFall($this);
return $handler->handleMotionPredictionHints($this);
}
}

View File

@ -45,12 +45,12 @@ class MoveActorDeltaPacket extends DataPacket implements ClientboundPacket{
public $entityRuntimeId;
/** @var int */
public $flags;
/** @var int */
public $xDiff = 0;
/** @var int */
public $yDiff = 0;
/** @var int */
public $zDiff = 0;
/** @var float */
public $xPos = 0;
/** @var float */
public $yPos = 0;
/** @var float */
public $zPos = 0;
/** @var float */
public $xRot = 0.0;
/** @var float */
@ -61,9 +61,9 @@ class MoveActorDeltaPacket extends DataPacket implements ClientboundPacket{
/**
* @throws BinaryDataException
*/
private function maybeReadCoord(int $flag, PacketSerializer $in) : int{
private function maybeReadCoord(int $flag, PacketSerializer $in) : float{
if(($this->flags & $flag) !== 0){
return $in->getVarInt();
return $in->getLFloat();
}
return 0;
}
@ -81,17 +81,17 @@ class MoveActorDeltaPacket extends DataPacket implements ClientboundPacket{
protected function decodePayload(PacketSerializer $in) : void{
$this->entityRuntimeId = $in->getEntityRuntimeId();
$this->flags = $in->getLShort();
$this->xDiff = $this->maybeReadCoord(self::FLAG_HAS_X, $in);
$this->yDiff = $this->maybeReadCoord(self::FLAG_HAS_Y, $in);
$this->zDiff = $this->maybeReadCoord(self::FLAG_HAS_Z, $in);
$this->xPos = $this->maybeReadCoord(self::FLAG_HAS_X, $in);
$this->yPos = $this->maybeReadCoord(self::FLAG_HAS_Y, $in);
$this->zPos = $this->maybeReadCoord(self::FLAG_HAS_Z, $in);
$this->xRot = $this->maybeReadRotation(self::FLAG_HAS_ROT_X, $in);
$this->yRot = $this->maybeReadRotation(self::FLAG_HAS_ROT_Y, $in);
$this->zRot = $this->maybeReadRotation(self::FLAG_HAS_ROT_Z, $in);
}
private function maybeWriteCoord(int $flag, int $val, PacketSerializer $out) : void{
private function maybeWriteCoord(int $flag, float $val, PacketSerializer $out) : void{
if(($this->flags & $flag) !== 0){
$out->putVarInt($val);
$out->putLFloat($val);
}
}
@ -104,15 +104,15 @@ class MoveActorDeltaPacket extends DataPacket implements ClientboundPacket{
protected function encodePayload(PacketSerializer $out) : void{
$out->putEntityRuntimeId($this->entityRuntimeId);
$out->putLShort($this->flags);
$this->maybeWriteCoord(self::FLAG_HAS_X, $this->xDiff, $out);
$this->maybeWriteCoord(self::FLAG_HAS_Y, $this->yDiff, $out);
$this->maybeWriteCoord(self::FLAG_HAS_Z, $this->zDiff, $out);
$this->maybeWriteCoord(self::FLAG_HAS_X, $this->xPos, $out);
$this->maybeWriteCoord(self::FLAG_HAS_Y, $this->yPos, $out);
$this->maybeWriteCoord(self::FLAG_HAS_Z, $this->zPos, $out);
$this->maybeWriteRotation(self::FLAG_HAS_ROT_X, $this->xRot, $out);
$this->maybeWriteRotation(self::FLAG_HAS_ROT_Y, $this->yRot, $out);
$this->maybeWriteRotation(self::FLAG_HAS_ROT_Z, $this->zRot, $out);
}
public function handle(PacketHandlerInterface $handler) : bool{
return $handler->handleMoveActorDelta($this);
public function handle(PacketHandlerInterface $session) : bool{
return $session->handleMoveActorDelta($this);
}
}

View File

@ -56,6 +56,8 @@ class MovePlayerPacket extends DataPacket implements ClientboundPacket, Serverbo
public $teleportCause = 0;
/** @var int */
public $teleportItem = 0;
/** @var int */
public $tick = 0;
protected function decodePayload(PacketSerializer $in) : void{
$this->entityRuntimeId = $in->getEntityRuntimeId();
@ -70,6 +72,7 @@ class MovePlayerPacket extends DataPacket implements ClientboundPacket, Serverbo
$this->teleportCause = $in->getLInt();
$this->teleportItem = $in->getLInt();
}
$this->tick = $in->getUnsignedVarLong();
}
protected function encodePayload(PacketSerializer $out) : void{
@ -85,6 +88,7 @@ class MovePlayerPacket extends DataPacket implements ClientboundPacket, Serverbo
$out->putLInt($this->teleportCause);
$out->putLInt($this->teleportItem);
}
$out->putUnsignedVarLong($this->tick);
}
public function handle(PacketHandlerInterface $handler) : bool{

View File

@ -97,8 +97,6 @@ interface PacketHandlerInterface{
public function handlePlayerAction(PlayerActionPacket $packet) : bool;
public function handleActorFall(ActorFallPacket $packet) : bool;
public function handleHurtArmor(HurtArmorPacket $packet) : bool;
public function handleSetActorData(SetActorDataPacket $packet) : bool;
@ -287,8 +285,6 @@ interface PacketHandlerInterface{
public function handleStructureTemplateDataResponse(StructureTemplateDataResponsePacket $packet) : bool;
public function handleUpdateBlockProperties(UpdateBlockPropertiesPacket $packet) : bool;
public function handleClientCacheBlobStatus(ClientCacheBlobStatusPacket $packet) : bool;
public function handleClientCacheMissResponse(ClientCacheMissResponsePacket $packet) : bool;
@ -332,4 +328,16 @@ interface PacketHandlerInterface{
public function handleDebugInfo(DebugInfoPacket $packet) : bool;
public function handlePacketViolationWarning(PacketViolationWarningPacket $packet) : bool;
public function handleMotionPredictionHints(MotionPredictionHintsPacket $packet) : bool;
public function handleAnimateEntity(AnimateEntityPacket $packet) : bool;
public function handleCameraShake(CameraShakePacket $packet) : bool;
public function handlePlayerFog(PlayerFogPacket $packet) : bool;
public function handleCorrectPlayerMovePrediction(CorrectPlayerMovePredictionPacket $packet) : bool;
public function handleItemComponent(ItemComponentPacket $packet) : bool;
}

View File

@ -78,7 +78,6 @@ class PacketPool{
$this->registerPacket(new BlockPickRequestPacket());
$this->registerPacket(new ActorPickRequestPacket());
$this->registerPacket(new PlayerActionPacket());
$this->registerPacket(new ActorFallPacket());
$this->registerPacket(new HurtArmorPacket());
$this->registerPacket(new SetActorDataPacket());
$this->registerPacket(new SetActorMotionPacket());
@ -173,7 +172,6 @@ class PacketPool{
$this->registerPacket(new MapCreateLockedCopyPacket());
$this->registerPacket(new StructureTemplateDataRequestPacket());
$this->registerPacket(new StructureTemplateDataResponsePacket());
$this->registerPacket(new UpdateBlockPropertiesPacket());
$this->registerPacket(new ClientCacheBlobStatusPacket());
$this->registerPacket(new ClientCacheMissResponsePacket());
$this->registerPacket(new EducationSettingsPacket());
@ -196,6 +194,12 @@ class PacketPool{
$this->registerPacket(new PositionTrackingDBClientRequestPacket());
$this->registerPacket(new DebugInfoPacket());
$this->registerPacket(new PacketViolationWarningPacket());
$this->registerPacket(new MotionPredictionHintsPacket());
$this->registerPacket(new AnimateEntityPacket());
$this->registerPacket(new CameraShakePacket());
$this->registerPacket(new PlayerFogPacket());
$this->registerPacket(new CorrectPlayerMovePredictionPacket());
$this->registerPacket(new ItemComponentPacket());
}
public function registerPacket(Packet $packet) : void{

View File

@ -43,7 +43,7 @@ class PlayerActionPacket extends DataPacket implements ServerboundPacket{
public const ACTION_STOP_SPRINT = 10;
public const ACTION_START_SNEAK = 11;
public const ACTION_STOP_SNEAK = 12;
public const ACTION_DIMENSION_CHANGE_REQUEST = 13; //sent when dying in different dimension
public const ACTION_CREATIVE_PLAYER_DESTROY_BLOCK = 13;
public const ACTION_DIMENSION_CHANGE_ACK = 14; //sent when spawning in a different dimension to tell the server we spawned
public const ACTION_START_GLIDE = 15;
public const ACTION_STOP_GLIDE = 16;

View File

@ -54,13 +54,17 @@ class PlayerAuthInputPacket extends DataPacket implements ServerboundPacket{
private $playMode;
/** @var Vector3|null */
private $vrGazeDirection = null;
/** @var int */
private $tick;
/** @var Vector3 */
private $delta;
/**
* @param int $inputMode @see InputMode
* @param int $playMode @see PlayMode
* @param Vector3|null $vrGazeDirection only used when PlayMode::VR
*/
public static function create(Vector3 $position, float $pitch, float $yaw, float $headYaw, float $moveVecX, float $moveVecZ, int $inputFlags, int $inputMode, int $playMode, ?Vector3 $vrGazeDirection = null) : self{
public static function create(Vector3 $position, float $pitch, float $yaw, float $headYaw, float $moveVecX, float $moveVecZ, int $inputFlags, int $inputMode, int $playMode, ?Vector3 $vrGazeDirection, int $tick, Vector3 $delta) : self{
if($playMode === PlayMode::VR and $vrGazeDirection === null){
//yuck, can we get a properly written packet just once? ...
throw new \InvalidArgumentException("Gaze direction must be provided for VR play mode");
@ -78,6 +82,8 @@ class PlayerAuthInputPacket extends DataPacket implements ServerboundPacket{
if($vrGazeDirection !== null){
$result->vrGazeDirection = $vrGazeDirection->asVector3();
}
$result->tick = $tick;
$result->delta = $delta;
return $result;
}
@ -140,6 +146,8 @@ class PlayerAuthInputPacket extends DataPacket implements ServerboundPacket{
if($this->playMode === PlayMode::VR){
$this->vrGazeDirection = $in->getVector3();
}
$this->tick = $in->getUnsignedVarLong();
$this->delta = $in->getVector3();
}
protected function encodePayload(PacketSerializer $out) : void{
@ -156,6 +164,8 @@ class PlayerAuthInputPacket extends DataPacket implements ServerboundPacket{
assert($this->vrGazeDirection !== null);
$out->putVector3($this->vrGazeDirection);
}
$out->putUnsignedVarLong($this->tick);
$out->putVector3($this->delta);
}
public function handle(PacketHandlerInterface $handler) : bool{

View File

@ -25,41 +25,49 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
use pocketmine\network\mcpe\protocol\types\CacheableNbt;
use function count;
class UpdateBlockPropertiesPacket extends DataPacket implements ClientboundPacket{
public const NETWORK_ID = ProtocolInfo::UPDATE_BLOCK_PROPERTIES_PACKET;
class PlayerFogPacket extends DataPacket implements ClientboundPacket{
public const NETWORK_ID = ProtocolInfo::PLAYER_FOG_PACKET;
/**
* @var CacheableNbt
* @phpstan-var CacheableNbt<\pocketmine\nbt\tag\CompoundTag>
* @var string[]
* @phpstan-var list<string>
*/
private $blockProperties;
private $fogLayers;
public static function create(CompoundTag $data) : self{
/**
* @param string[] $fogLayers
* @phpstan-param list<string> $fogLayers
*/
public static function create(array $fogLayers) : self{
$result = new self;
$result->blockProperties = new CacheableNbt($data);
$result->fogLayers = $fogLayers;
return $result;
}
/**
* @phpstan-return CacheableNbt<\pocketmine\nbt\tag\CompoundTag>
* @return string[]
* @phpstan-return list<string>
*/
public function getBlockProperties() : CacheableNbt{
return $this->blockProperties;
}
public function getFogLayers() : array{ return $this->fogLayers; }
protected function decodePayload(PacketSerializer $in) : void{
$this->blockProperties = new CacheableNbt($in->getNbtCompoundRoot());
$this->fogLayers = [];
for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){
$this->fogLayers[] = $in->getString();
}
}
protected function encodePayload(PacketSerializer $out) : void{
$out->put($this->blockProperties->getEncodedNbt());
$out->putUnsignedVarInt(count($this->fogLayers));
foreach($this->fogLayers as $fogLayer){
$out->putString($fogLayer);
}
}
public function handle(PacketHandlerInterface $handler) : bool{
return $handler->handleUpdateBlockProperties($this);
return $handler->handlePlayerFog($this);
}
}

View File

@ -41,11 +41,11 @@ final class ProtocolInfo{
*/
/** Actual Minecraft: PE protocol version */
public const CURRENT_PROTOCOL = 408;
public const CURRENT_PROTOCOL = 419;
/** Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */
public const MINECRAFT_VERSION = 'v1.16.20';
public const MINECRAFT_VERSION = 'v1.16.100';
/** Version number sent to clients in ping responses. */
public const MINECRAFT_VERSION_NETWORK = '1.16.20';
public const MINECRAFT_VERSION_NETWORK = '1.16.100';
public const LOGIN_PACKET = 0x01;
public const PLAY_STATUS_PACKET = 0x02;
@ -83,7 +83,7 @@ final class ProtocolInfo{
public const BLOCK_PICK_REQUEST_PACKET = 0x22;
public const ACTOR_PICK_REQUEST_PACKET = 0x23;
public const PLAYER_ACTION_PACKET = 0x24;
public const ACTOR_FALL_PACKET = 0x25;
public const HURT_ARMOR_PACKET = 0x26;
public const SET_ACTOR_DATA_PACKET = 0x27;
public const SET_ACTOR_MOTION_PACKET = 0x28;
@ -180,7 +180,7 @@ final class ProtocolInfo{
public const MAP_CREATE_LOCKED_COPY_PACKET = 0x83;
public const STRUCTURE_TEMPLATE_DATA_REQUEST_PACKET = 0x84;
public const STRUCTURE_TEMPLATE_DATA_RESPONSE_PACKET = 0x85;
public const UPDATE_BLOCK_PROPERTIES_PACKET = 0x86;
public const CLIENT_CACHE_BLOB_STATUS_PACKET = 0x87;
public const CLIENT_CACHE_MISS_RESPONSE_PACKET = 0x88;
public const EDUCATION_SETTINGS_PACKET = 0x89;
@ -203,5 +203,11 @@ final class ProtocolInfo{
public const POSITION_TRACKING_D_B_CLIENT_REQUEST_PACKET = 0x9a;
public const DEBUG_INFO_PACKET = 0x9b;
public const PACKET_VIOLATION_WARNING_PACKET = 0x9c;
public const MOTION_PREDICTION_HINTS_PACKET = 0x9d;
public const ANIMATE_ENTITY_PACKET = 0x9e;
public const CAMERA_SHAKE_PACKET = 0x9f;
public const PLAYER_FOG_PACKET = 0xa0;
public const CORRECT_PLAYER_MOVE_PREDICTION_PACKET = 0xa1;
public const ITEM_COMPONENT_PACKET = 0xa2;
}

View File

@ -26,6 +26,7 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
use pocketmine\network\mcpe\protocol\types\Experiments;
use pocketmine\network\mcpe\protocol\types\resourcepacks\ResourcePackStackEntry;
use function count;
@ -40,23 +41,24 @@ class ResourcePackStackPacket extends DataPacket implements ClientboundPacket{
/** @var ResourcePackStackEntry[] */
public $resourcePackStack = [];
/** @var bool */
public $isExperimental = false;
/** @var string */
public $baseGameVersion = ProtocolInfo::MINECRAFT_VERSION_NETWORK;
/** @var Experiments */
public $experiments;
/**
* @param ResourcePackStackEntry[] $resourcePacks
* @param ResourcePackStackEntry[] $behaviorPacks
*
* @return ResourcePackStackPacket
*/
public static function create(array $resourcePacks, array $behaviorPacks, bool $mustAccept, bool $isExperimental = false) : self{
public static function create(array $resourcePacks, array $behaviorPacks, bool $mustAccept, Experiments $experiments) : self{
$result = new self;
$result->mustAccept = $mustAccept;
$result->resourcePackStack = $resourcePacks;
$result->behaviorPackStack = $behaviorPacks;
$result->isExperimental = $isExperimental;
$result->experiments = $experiments;
return $result;
}
@ -72,8 +74,8 @@ class ResourcePackStackPacket extends DataPacket implements ClientboundPacket{
$this->resourcePackStack[] = ResourcePackStackEntry::read($in);
}
$this->isExperimental = $in->getBool();
$this->baseGameVersion = $in->getString();
$this->experiments = Experiments::read($in);
}
protected function encodePayload(PacketSerializer $out) : void{
@ -89,8 +91,8 @@ class ResourcePackStackPacket extends DataPacket implements ClientboundPacket{
$entry->write($out);
}
$out->putBool($this->isExperimental);
$out->putString($this->baseGameVersion);
$this->experiments->write($out);
}
public function handle(PacketHandlerInterface $handler) : bool{

View File

@ -39,26 +39,32 @@ class SetActorDataPacket extends DataPacket implements ClientboundPacket, Server
*/
public $metadata;
/** @var int */
public $tick = 0;
/**
* @param MetadataProperty[] $metadata
* @phpstan-param array<int, MetadataProperty> $metadata
*/
public static function create(int $entityRuntimeId, array $metadata) : self{
public static function create(int $entityRuntimeId, array $metadata, int $tick) : self{
$result = new self;
$result->entityRuntimeId = $entityRuntimeId;
$result->metadata = $metadata;
$result->tick = $tick;
return $result;
}
protected function decodePayload(PacketSerializer $in) : void{
$this->entityRuntimeId = $in->getEntityRuntimeId();
$this->metadata = $in->getEntityMetadata();
$this->tick = $in->getUnsignedVarLong();
}
protected function encodePayload(PacketSerializer $out) : void{
$out->putEntityRuntimeId($this->entityRuntimeId);
$out->putEntityMetadata($this->metadata);
$out->putUnsignedVarLong($this->tick);
}
public function handle(PacketHandlerInterface $handler) : bool{

View File

@ -26,13 +26,17 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
use pocketmine\network\mcpe\protocol\types\CacheableNbt;
use pocketmine\network\mcpe\protocol\types\BlockPaletteEntry;
use pocketmine\network\mcpe\protocol\types\EducationEditionOffer;
use pocketmine\network\mcpe\protocol\types\Experiments;
use pocketmine\network\mcpe\protocol\types\GameRule;
use pocketmine\network\mcpe\protocol\types\GeneratorType;
use pocketmine\network\mcpe\protocol\types\ItemTypeEntry;
use pocketmine\network\mcpe\protocol\types\MultiplayerGameVisibility;
use pocketmine\network\mcpe\protocol\types\PlayerMovementType;
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
use pocketmine\network\mcpe\protocol\types\SpawnSettings;
use function count;
@ -104,6 +108,8 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
* @phpstan-var array<string, GameRule>
*/
public $gameRules = [];
/** @var Experiments */
public $experiments;
/** @var bool */
public $hasBonusChestEnabled = false;
/** @var bool */
@ -147,8 +153,8 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
public $premiumWorldTemplateId = "";
/** @var bool */
public $isTrial = false;
/** @var bool */
public $isMovementServerAuthoritative = false;
/** @var int */
public $playerMovementType = PlayerMovementType::LEGACY;
/** @var int */
public $currentTick = 0; //only used if isTrial is true
/** @var int */
@ -159,15 +165,15 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
public $enableNewInventorySystem = false; //TODO
/**
* @var CacheableNbt
* @phpstan-var CacheableNbt<\pocketmine\nbt\tag\ListTag>
* @var BlockPaletteEntry[]
* @phpstan-var list<BlockPaletteEntry>
*/
public $blockTable;
public $blockPalette = [];
/**
* @var int[] string (name) => int16 (legacyID)
* @phpstan-var array<string, int>
* @var ItemTypeEntry[]
* @phpstan-var list<ItemTypeEntry>
*/
public $itemTable = [];
public $itemTable;
protected function decodePayload(PacketSerializer $in) : void{
$this->entityUniqueId = $in->getEntityUniqueId();
@ -201,6 +207,7 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
$this->commandsEnabled = $in->getBool();
$this->isTexturePacksRequired = $in->getBool();
$this->gameRules = $in->getGameRules();
$this->experiments = Experiments::read($in);
$this->hasBonusChestEnabled = $in->getBool();
$this->hasStartWithMapEnabled = $in->getBool();
$this->defaultPlayerPermission = $in->getVarInt();
@ -226,23 +233,25 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
$this->worldName = $in->getString();
$this->premiumWorldTemplateId = $in->getString();
$this->isTrial = $in->getBool();
$this->isMovementServerAuthoritative = $in->getBool();
$this->playerMovementType = $in->getVarInt();
$this->currentTick = $in->getLLong();
$this->enchantmentSeed = $in->getVarInt();
$blockTable = $in->getNbtRoot()->getTag();
if(!($blockTable instanceof ListTag)){
throw new \UnexpectedValueException("Wrong block table root NBT tag type");
$this->blockPalette = [];
for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){
$blockName = $in->getString();
$state = $in->getNbtCompoundRoot();
$this->blockPalette[] = new BlockPaletteEntry($blockName, $state);
}
$this->blockTable = new CacheableNbt($blockTable);
$this->itemTable = [];
for($i = 0, $count = $in->getUnsignedVarInt(); $i < $count; ++$i){
$id = $in->getString();
$legacyId = $in->getSignedLShort();
$stringId = $in->getString();
$numericId = $in->getSignedLShort();
$isComponentBased = $in->getBool();
$this->itemTable[$id] = $legacyId;
$this->itemTable[] = new ItemTypeEntry($stringId, $numericId, $isComponentBased);
}
$this->multiplayerCorrelationId = $in->getString();
@ -281,6 +290,7 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
$out->putBool($this->commandsEnabled);
$out->putBool($this->isTexturePacksRequired);
$out->putGameRules($this->gameRules);
$this->experiments->write($out);
$out->putBool($this->hasBonusChestEnabled);
$out->putBool($this->hasStartWithMapEnabled);
$out->putVarInt($this->defaultPlayerPermission);
@ -305,33 +315,29 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
$out->putString($this->worldName);
$out->putString($this->premiumWorldTemplateId);
$out->putBool($this->isTrial);
$out->putBool($this->isMovementServerAuthoritative);
$out->putVarInt($this->playerMovementType);
$out->putLLong($this->currentTick);
$out->putVarInt($this->enchantmentSeed);
$out->put($this->blockTable->getEncodedNbt());
$out->putUnsignedVarInt(count($this->blockPalette));
$nbtWriter = new NetworkNbtSerializer();
foreach($this->blockPalette as $entry){
$out->putString($entry->getName());
$out->put($nbtWriter->write(new TreeRoot($entry->getStates())));
}
$out->put(self::serializeItemTable($this->itemTable));
$out->putUnsignedVarInt(count($this->itemTable));
foreach($this->itemTable as $entry){
$out->putString($entry->getStringId());
$out->putLShort($entry->getNumericId());
$out->putBool($entry->isComponentBased());
}
$out->putString($this->multiplayerCorrelationId);
$out->putBool($this->enableNewInventorySystem);
}
/**
* @param int[] $table
* @phpstan-param array<string, int> $table
*/
private static function serializeItemTable(array $table) : string{
$stream = new PacketSerializer();
$stream->putUnsignedVarInt(count($table));
foreach($table as $name => $legacyId){
$stream->putString($name);
$stream->putLShort($legacyId);
}
return $stream->getBuffer();
}
public function handle(PacketHandlerInterface $handler) : bool{
return $handler->handleStartGame($this);
}

View File

@ -36,27 +36,32 @@ class UpdateAttributesPacket extends DataPacket implements ClientboundPacket{
public $entityRuntimeId;
/** @var Attribute[] */
public $entries = [];
/** @var int */
public $tick = 0;
/**
* @param Attribute[] $attributes
*
* @return UpdateAttributesPacket
*/
public static function create(int $entityRuntimeId, array $attributes) : self{
public static function create(int $entityRuntimeId, array $attributes, int $tick) : self{
$result = new self;
$result->entityRuntimeId = $entityRuntimeId;
$result->entries = $attributes;
$result->tick = $tick;
return $result;
}
protected function decodePayload(PacketSerializer $in) : void{
$this->entityRuntimeId = $in->getEntityRuntimeId();
$this->entries = $in->getAttributeList();
$this->tick = $in->getUnsignedVarLong();
}
protected function encodePayload(PacketSerializer $out) : void{
$out->putEntityRuntimeId($this->entityRuntimeId);
$out->putAttributeList(...array_values($this->entries));
$out->putUnsignedVarLong($this->tick);
}
public function handle(PacketHandlerInterface $handler) : bool{

View File

@ -29,6 +29,7 @@ use pocketmine\math\Vector3;
use pocketmine\nbt\NbtDataException;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\network\mcpe\convert\ItemTypeDictionary;
use pocketmine\network\mcpe\protocol\PacketDecodeException;
use pocketmine\network\mcpe\protocol\types\BoolGameRule;
use pocketmine\network\mcpe\protocol\types\command\CommandOriginData;
@ -44,7 +45,6 @@ use pocketmine\network\mcpe\protocol\types\entity\MetadataProperty;
use pocketmine\network\mcpe\protocol\types\entity\ShortMetadataProperty;
use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty;
use pocketmine\network\mcpe\protocol\types\entity\Vec3MetadataProperty;
use pocketmine\network\mcpe\protocol\types\FixedItemIds;
use pocketmine\network\mcpe\protocol\types\FloatGameRule;
use pocketmine\network\mcpe\protocol\types\GameRule;
use pocketmine\network\mcpe\protocol\types\GameRuleType;
@ -108,7 +108,8 @@ class PacketSerializer extends BinaryStream{
$skinImage = $this->getSkinImage();
$animationType = $this->getLInt();
$animationFrames = $this->getLFloat();
$animations[] = new SkinAnimation($skinImage, $animationType, $animationFrames);
$expressionType = $this->getLInt();
$animations[] = new SkinAnimation($skinImage, $animationType, $animationFrames, $expressionType);
}
$capeData = $this->getSkinImage();
$geometryData = $this->getString();
@ -157,6 +158,7 @@ class PacketSerializer extends BinaryStream{
$this->putSkinImage($animation->getImage());
$this->putLInt($animation->getType());
$this->putLFloat($animation->getFrames());
$this->putLInt($animation->getExpressionType());
}
$this->putSkinImage($skin->getCapeImage());
$this->putString($skin->getGeometryData());
@ -242,7 +244,7 @@ class PacketSerializer extends BinaryStream{
}
$shieldBlockingTick = null;
if($id === FixedItemIds::SHIELD){
if($id === ItemTypeDictionary::getInstance()->fromStringId("minecraft:shield")){
$shieldBlockingTick = $this->getVarLong();
}
@ -279,8 +281,8 @@ class PacketSerializer extends BinaryStream{
}
$blockingTick = $item->getShieldBlockingTick();
if($blockingTick !== null){
$this->putVarLong($blockingTick);
if($item->getId() === ItemTypeDictionary::getInstance()->fromStringId("minecraft:shield")){
$this->putVarLong($blockingTick ?? 0);
}
}

View File

@ -0,0 +1,43 @@
<?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\protocol\types;
use pocketmine\nbt\tag\CompoundTag;
final class BlockPaletteEntry{
/** @var string */
private $name;
/** @var CompoundTag */
private $states;
public function __construct(string $name, CompoundTag $states){
$this->name = $name;
$this->states = $states;
}
public function getName() : string{ return $this->name; }
public function getStates() : CompoundTag{ return $this->states; }
}

View File

@ -0,0 +1,72 @@
<?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\protocol\types;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
use function count;
final class Experiments{
/**
* @var bool[]
* @phpstan-var array<string, bool>
*/
private $experiments;
/** @var bool */
private $hasPreviouslyUsedExperiments;
/**
* @param bool[] $experiments
* @phpstan-param array<string, bool> $experiments
*/
public function __construct(array $experiments, bool $hasPreviouslyUsedExperiments){
$this->experiments = $experiments;
$this->hasPreviouslyUsedExperiments = $hasPreviouslyUsedExperiments;
}
/** @return bool[] */
public function getExperiments() : array{ return $this->experiments; }
public function hasPreviouslyUsedExperiments() : bool{ return $this->hasPreviouslyUsedExperiments; }
public static function read(PacketSerializer $in) : self{
$experiments = [];
for($i = 0, $len = $in->getLInt(); $i < $len; ++$i){
$experimentName = $in->getString();
$enabled = $in->getBool();
$experiments[$experimentName] = $enabled;
}
$hasPreviouslyUsedExperiments = $in->getBool();
return new self($experiments, $hasPreviouslyUsedExperiments);
}
public function write(PacketSerializer $out) : void{
$out->putLInt(count($this->experiments));
foreach($this->experiments as $experimentName => $enabled){
$out->putString($experimentName);
$out->putBool($enabled);
}
$out->putBool($this->hasPreviouslyUsedExperiments);
}
}

View File

@ -1,864 +0,0 @@
<?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\protocol\types;
/**
* This file is directly generated from the item ID mappings provided by the client. The items listed in this file are
* expected to always have the same IDs.
*
* The constants in this file may change or disappear at any time.
*
* This file is automatically generated; do NOT edit it by hand or your changes may be lost.
*/
final class FixedItemIds{
private function __construct(){
//NOOP
}
public const QUARTZ_BRICKS = -304;
public const CRACKED_NETHER_BRICKS = -303;
public const CHISELED_NETHER_BRICKS = -302;
public const STRIPPED_WARPED_HYPHAE = -301;
public const STRIPPED_CRIMSON_HYPHAE = -300;
public const CRIMSON_HYPHAE = -299;
public const WARPED_HYPHAE = -298;
public const POLISHED_BLACKSTONE_WALL = -297;
public const POLISHED_BLACKSTONE_BUTTON = -296;
public const POLISHED_BLACKSTONE_PRESSURE_PLATE = -295;
public const POLISHED_BLACKSTONE_DOUBLE_SLAB = -294;
public const POLISHED_BLACKSTONE_SLAB = -293;
public const POLISHED_BLACKSTONE_STAIRS = -292;
public const POLISHED_BLACKSTONE = -291;
public const ITEM_SOUL_CAMPFIRE = -290;
public const CRYING_OBSIDIAN = -289;
public const NETHER_GOLD_ORE = -288;
public const TWISTING_VINES = -287;
public const ITEM_CHAIN = -286;
public const POLISHED_BLACKSTONE_BRICK_DOUBLE_SLAB = -285;
public const POLISHED_BLACKSTONE_BRICK_SLAB = -284;
public const BLACKSTONE_DOUBLE_SLAB = -283;
public const BLACKSTONE_SLAB = -282;
public const GILDED_BLACKSTONE = -281;
public const CRACKED_POLISHED_BLACKSTONE_BRICKS = -280;
public const CHISELED_POLISHED_BLACKSTONE = -279;
public const POLISHED_BLACKSTONE_BRICK_WALL = -278;
public const BLACKSTONE_WALL = -277;
public const BLACKSTONE_STAIRS = -276;
public const POLISHED_BLACKSTONE_BRICK_STAIRS = -275;
public const POLISHED_BLACKSTONE_BRICKS = -274;
public const BLACKSTONE = -273;
public const RESPAWN_ANCHOR = -272;
public const ANCIENT_DEBRIS = -271;
public const NETHERITE_BLOCK = -270;
public const SOUL_LANTERN = -269;
public const SOUL_TORCH = -268;
public const WARPED_DOUBLE_SLAB = -267;
public const CRIMSON_DOUBLE_SLAB = -266;
public const WARPED_SLAB = -265;
public const CRIMSON_SLAB = -264;
public const WARPED_PRESSURE_PLATE = -263;
public const CRIMSON_PRESSURE_PLATE = -262;
public const WARPED_BUTTON = -261;
public const CRIMSON_BUTTON = -260;
public const WARPED_FENCE_GATE = -259;
public const CRIMSON_FENCE_GATE = -258;
public const WARPED_FENCE = -257;
public const CRIMSON_FENCE = -256;
public const WARPED_STAIRS = -255;
public const CRIMSON_STAIRS = -254;
public const WARPED_WALL_SIGN = -253;
public const CRIMSON_WALL_SIGN = -252;
public const WARPED_STANDING_SIGN = -251;
public const CRIMSON_STANDING_SIGN = -250;
public const WARPED_TRAPDOOR = -247;
public const CRIMSON_TRAPDOOR = -246;
public const ITEM_WARPED_DOOR = -245;
public const ITEM_CRIMSON_DOOR = -244;
public const WARPED_PLANKS = -243;
public const CRIMSON_PLANKS = -242;
public const STRIPPED_WARPED_STEM = -241;
public const STRIPPED_CRIMSON_STEM = -240;
public const TARGET = -239;
public const ITEM_NETHER_SPROUTS = -238;
public const SOUL_FIRE = -237;
public const SOUL_SOIL = -236;
public const POLISHED_BASALT = -235;
public const BASALT = -234;
public const WARPED_NYLIUM = -233;
public const CRIMSON_NYLIUM = -232;
public const WEEPING_VINES = -231;
public const SHROOMLIGHT = -230;
public const WARPED_FUNGUS = -229;
public const CRIMSON_FUNGUS = -228;
public const WARPED_WART_BLOCK = -227;
public const WARPED_STEM = -226;
public const CRIMSON_STEM = -225;
public const WARPED_ROOTS = -224;
public const CRIMSON_ROOTS = -223;
public const LODESTONE = -222;
public const HONEYCOMB_BLOCK = -221;
public const HONEY_BLOCK = -220;
public const BEEHIVE = -219;
public const BEE_NEST = -218;
public const STICKYPISTONARMCOLLISION = -217;
public const WITHER_ROSE = -216;
public const LIGHT_BLOCK = -215;
public const LIT_BLAST_FURNACE = -214;
public const COMPOSTER = -213;
public const WOOD = -212;
public const JIGSAW = -211;
public const LAVA_CAULDRON = -210;
public const ITEM_CAMPFIRE = -209;
public const LANTERN = -208;
public const SWEET_BERRY_BUSH = -207;
public const BELL = -206;
public const LOOM = -204;
public const BARREL = -203;
public const SMITHING_TABLE = -202;
public const FLETCHING_TABLE = -201;
public const CARTOGRAPHY_TABLE = -200;
public const LIT_SMOKER = -199;
public const SMOKER = -198;
public const STONECUTTER_BLOCK = -197;
public const BLAST_FURNACE = -196;
public const GRINDSTONE = -195;
public const LECTERN = -194;
public const DARKOAK_WALL_SIGN = -193;
public const DARKOAK_STANDING_SIGN = -192;
public const ACACIA_WALL_SIGN = -191;
public const ACACIA_STANDING_SIGN = -190;
public const JUNGLE_WALL_SIGN = -189;
public const JUNGLE_STANDING_SIGN = -188;
public const BIRCH_WALL_SIGN = -187;
public const BIRCH_STANDING_SIGN = -186;
public const SMOOTH_QUARTZ_STAIRS = -185;
public const RED_NETHER_BRICK_STAIRS = -184;
public const SMOOTH_STONE = -183;
public const SPRUCE_WALL_SIGN = -182;
public const SPRUCE_STANDING_SIGN = -181;
public const NORMAL_STONE_STAIRS = -180;
public const MOSSY_COBBLESTONE_STAIRS = -179;
public const END_BRICK_STAIRS = -178;
public const SMOOTH_SANDSTONE_STAIRS = -177;
public const SMOOTH_RED_SANDSTONE_STAIRS = -176;
public const MOSSY_STONE_BRICK_STAIRS = -175;
public const POLISHED_ANDESITE_STAIRS = -174;
public const POLISHED_DIORITE_STAIRS = -173;
public const POLISHED_GRANITE_STAIRS = -172;
public const ANDESITE_STAIRS = -171;
public const DIORITE_STAIRS = -170;
public const GRANITE_STAIRS = -169;
public const REAL_DOUBLE_STONE_SLAB4 = -168;
public const REAL_DOUBLE_STONE_SLAB3 = -167;
public const DOUBLE_STONE_SLAB4 = -166;
public const SCAFFOLDING = -165;
public const BAMBOO_SAPLING = -164;
public const BAMBOO = -163;
public const DOUBLE_STONE_SLAB3 = -162;
public const BARRIER = -161;
public const BUBBLE_COLUMN = -160;
public const TURTLE_EGG = -159;
public const AIR = -158;
public const CONDUIT = -157;
public const SEA_PICKLE = -156;
public const CARVED_PUMPKIN = -155;
public const SPRUCE_PRESSURE_PLATE = -154;
public const JUNGLE_PRESSURE_PLATE = -153;
public const DARK_OAK_PRESSURE_PLATE = -152;
public const BIRCH_PRESSURE_PLATE = -151;
public const ACACIA_PRESSURE_PLATE = -150;
public const SPRUCE_TRAPDOOR = -149;
public const JUNGLE_TRAPDOOR = -148;
public const DARK_OAK_TRAPDOOR = -147;
public const BIRCH_TRAPDOOR = -146;
public const ACACIA_TRAPDOOR = -145;
public const SPRUCE_BUTTON = -144;
public const JUNGLE_BUTTON = -143;
public const DARK_OAK_BUTTON = -142;
public const BIRCH_BUTTON = -141;
public const ACACIA_BUTTON = -140;
public const DRIED_KELP_BLOCK = -139;
public const ITEM_KELP = -138;
public const CORAL_FAN_HANG3 = -137;
public const CORAL_FAN_HANG2 = -136;
public const CORAL_FAN_HANG = -135;
public const CORAL_FAN_DEAD = -134;
public const CORAL_FAN = -133;
public const CORAL_BLOCK = -132;
public const CORAL = -131;
public const SEAGRASS = -130;
public const ELEMENT_118 = -129;
public const ELEMENT_117 = -128;
public const ELEMENT_116 = -127;
public const ELEMENT_115 = -126;
public const ELEMENT_114 = -125;
public const ELEMENT_113 = -124;
public const ELEMENT_112 = -123;
public const ELEMENT_111 = -122;
public const ELEMENT_110 = -121;
public const ELEMENT_109 = -120;
public const ELEMENT_108 = -119;
public const ELEMENT_107 = -118;
public const ELEMENT_106 = -117;
public const ELEMENT_105 = -116;
public const ELEMENT_104 = -115;
public const ELEMENT_103 = -114;
public const ELEMENT_102 = -113;
public const ELEMENT_101 = -112;
public const ELEMENT_100 = -111;
public const ELEMENT_99 = -110;
public const ELEMENT_98 = -109;
public const ELEMENT_97 = -108;
public const ELEMENT_96 = -107;
public const ELEMENT_95 = -106;
public const ELEMENT_94 = -105;
public const ELEMENT_93 = -104;
public const ELEMENT_92 = -103;
public const ELEMENT_91 = -102;
public const ELEMENT_90 = -101;
public const ELEMENT_89 = -100;
public const ELEMENT_88 = -99;
public const ELEMENT_87 = -98;
public const ELEMENT_86 = -97;
public const ELEMENT_85 = -96;
public const ELEMENT_84 = -95;
public const ELEMENT_83 = -94;
public const ELEMENT_82 = -93;
public const ELEMENT_81 = -92;
public const ELEMENT_80 = -91;
public const ELEMENT_79 = -90;
public const ELEMENT_78 = -89;
public const ELEMENT_77 = -88;
public const ELEMENT_76 = -87;
public const ELEMENT_75 = -86;
public const ELEMENT_74 = -85;
public const ELEMENT_73 = -84;
public const ELEMENT_72 = -83;
public const ELEMENT_71 = -82;
public const ELEMENT_70 = -81;
public const ELEMENT_69 = -80;
public const ELEMENT_68 = -79;
public const ELEMENT_67 = -78;
public const ELEMENT_66 = -77;
public const ELEMENT_65 = -76;
public const ELEMENT_64 = -75;
public const ELEMENT_63 = -74;
public const ELEMENT_62 = -73;
public const ELEMENT_61 = -72;
public const ELEMENT_60 = -71;
public const ELEMENT_59 = -70;
public const ELEMENT_58 = -69;
public const ELEMENT_57 = -68;
public const ELEMENT_56 = -67;
public const ELEMENT_55 = -66;
public const ELEMENT_54 = -65;
public const ELEMENT_53 = -64;
public const ELEMENT_52 = -63;
public const ELEMENT_51 = -62;
public const ELEMENT_50 = -61;
public const ELEMENT_49 = -60;
public const ELEMENT_48 = -59;
public const ELEMENT_47 = -58;
public const ELEMENT_46 = -57;
public const ELEMENT_45 = -56;
public const ELEMENT_44 = -55;
public const ELEMENT_43 = -54;
public const ELEMENT_42 = -53;
public const ELEMENT_41 = -52;
public const ELEMENT_40 = -51;
public const ELEMENT_39 = -50;
public const ELEMENT_38 = -49;
public const ELEMENT_37 = -48;
public const ELEMENT_36 = -47;
public const ELEMENT_35 = -46;
public const ELEMENT_34 = -45;
public const ELEMENT_33 = -44;
public const ELEMENT_32 = -43;
public const ELEMENT_31 = -42;
public const ELEMENT_30 = -41;
public const ELEMENT_29 = -40;
public const ELEMENT_28 = -39;
public const ELEMENT_27 = -38;
public const ELEMENT_26 = -37;
public const ELEMENT_25 = -36;
public const ELEMENT_24 = -35;
public const ELEMENT_23 = -34;
public const ELEMENT_22 = -33;
public const ELEMENT_21 = -32;
public const ELEMENT_20 = -31;
public const ELEMENT_19 = -30;
public const ELEMENT_18 = -29;
public const ELEMENT_17 = -28;
public const ELEMENT_16 = -27;
public const ELEMENT_15 = -26;
public const ELEMENT_14 = -25;
public const ELEMENT_13 = -24;
public const ELEMENT_12 = -23;
public const ELEMENT_11 = -22;
public const ELEMENT_10 = -21;
public const ELEMENT_9 = -20;
public const ELEMENT_8 = -19;
public const ELEMENT_7 = -18;
public const ELEMENT_6 = -17;
public const ELEMENT_5 = -16;
public const ELEMENT_4 = -15;
public const ELEMENT_3 = -14;
public const ELEMENT_2 = -13;
public const ELEMENT_1 = -12;
public const BLUE_ICE = -11;
public const STRIPPED_OAK_LOG = -10;
public const STRIPPED_DARK_OAK_LOG = -9;
public const STRIPPED_ACACIA_LOG = -8;
public const STRIPPED_JUNGLE_LOG = -7;
public const STRIPPED_BIRCH_LOG = -6;
public const STRIPPED_SPRUCE_LOG = -5;
public const PRISMARINE_BRICKS_STAIRS = -4;
public const DARK_PRISMARINE_STAIRS = -3;
public const PRISMARINE_STAIRS = -2;
public const STONE = 1;
public const GRASS = 2;
public const DIRT = 3;
public const COBBLESTONE = 4;
public const PLANKS = 5;
public const SAPLING = 6;
public const BEDROCK = 7;
public const FLOWING_WATER = 8;
public const WATER = 9;
public const FLOWING_LAVA = 10;
public const LAVA = 11;
public const SAND = 12;
public const GRAVEL = 13;
public const GOLD_ORE = 14;
public const IRON_ORE = 15;
public const COAL_ORE = 16;
public const LOG = 17;
public const LEAVES = 18;
public const SPONGE = 19;
public const GLASS = 20;
public const LAPIS_ORE = 21;
public const LAPIS_BLOCK = 22;
public const DISPENSER = 23;
public const SANDSTONE = 24;
public const NOTEBLOCK = 25;
public const ITEM_BED = 26;
public const GOLDEN_RAIL = 27;
public const DETECTOR_RAIL = 28;
public const STICKY_PISTON = 29;
public const WEB = 30;
public const TALLGRASS = 31;
public const DEADBUSH = 32;
public const PISTON = 33;
public const PISTONARMCOLLISION = 34;
public const WOOL = 35;
public const ELEMENT_0 = 36;
public const YELLOW_FLOWER = 37;
public const RED_FLOWER = 38;
public const BROWN_MUSHROOM = 39;
public const RED_MUSHROOM = 40;
public const GOLD_BLOCK = 41;
public const IRON_BLOCK = 42;
public const REAL_DOUBLE_STONE_SLAB = 43;
public const DOUBLE_STONE_SLAB = 44;
public const BRICK_BLOCK = 45;
public const TNT = 46;
public const BOOKSHELF = 47;
public const MOSSY_COBBLESTONE = 48;
public const OBSIDIAN = 49;
public const TORCH = 50;
public const FIRE = 51;
public const MOB_SPAWNER = 52;
public const OAK_STAIRS = 53;
public const CHEST = 54;
public const REDSTONE_WIRE = 55;
public const DIAMOND_ORE = 56;
public const DIAMOND_BLOCK = 57;
public const CRAFTING_TABLE = 58;
public const ITEM_WHEAT = 59;
public const FARMLAND = 60;
public const FURNACE = 61;
public const LIT_FURNACE = 62;
public const STANDING_SIGN = 63;
public const ITEM_WOODEN_DOOR = 64;
public const LADDER = 65;
public const RAIL = 66;
public const STONE_STAIRS = 67;
public const WALL_SIGN = 68;
public const LEVER = 69;
public const STONE_PRESSURE_PLATE = 70;
public const ITEM_IRON_DOOR = 71;
public const WOODEN_PRESSURE_PLATE = 72;
public const REDSTONE_ORE = 73;
public const LIT_REDSTONE_ORE = 74;
public const UNLIT_REDSTONE_TORCH = 75;
public const REDSTONE_TORCH = 76;
public const STONE_BUTTON = 77;
public const SNOW_LAYER = 78;
public const ICE = 79;
public const SNOW = 80;
public const CACTUS = 81;
public const CLAY = 82;
public const ITEM_REEDS = 83;
public const JUKEBOX = 84;
public const FENCE = 85;
public const PUMPKIN = 86;
public const NETHERRACK = 87;
public const SOUL_SAND = 88;
public const GLOWSTONE = 89;
public const PORTAL = 90;
public const LIT_PUMPKIN = 91;
public const ITEM_CAKE = 92;
public const UNPOWERED_REPEATER = 93;
public const POWERED_REPEATER = 94;
public const INVISIBLEBEDROCK = 95;
public const TRAPDOOR = 96;
public const MONSTER_EGG = 97;
public const STONEBRICK = 98;
public const BROWN_MUSHROOM_BLOCK = 99;
public const RED_MUSHROOM_BLOCK = 100;
public const IRON_BARS = 101;
public const GLASS_PANE = 102;
public const MELON_BLOCK = 103;
public const PUMPKIN_STEM = 104;
public const MELON_STEM = 105;
public const VINE = 106;
public const FENCE_GATE = 107;
public const BRICK_STAIRS = 108;
public const STONE_BRICK_STAIRS = 109;
public const MYCELIUM = 110;
public const WATERLILY = 111;
public const NETHER_BRICK = 112;
public const NETHER_BRICK_FENCE = 113;
public const NETHER_BRICK_STAIRS = 114;
public const ITEM_NETHER_WART = 115;
public const ENCHANTING_TABLE = 116;
public const BREWINGSTANDBLOCK = 117;
public const ITEM_CAULDRON = 118;
public const END_PORTAL = 119;
public const END_PORTAL_FRAME = 120;
public const END_STONE = 121;
public const DRAGON_EGG = 122;
public const REDSTONE_LAMP = 123;
public const LIT_REDSTONE_LAMP = 124;
public const DROPPER = 125;
public const ACTIVATOR_RAIL = 126;
public const COCOA = 127;
public const SANDSTONE_STAIRS = 128;
public const EMERALD_ORE = 129;
public const ENDER_CHEST = 130;
public const TRIPWIRE_HOOK = 131;
public const TRIPWIRE = 132;
public const EMERALD_BLOCK = 133;
public const SPRUCE_STAIRS = 134;
public const BIRCH_STAIRS = 135;
public const JUNGLE_STAIRS = 136;
public const COMMAND_BLOCK = 137;
public const BEACON = 138;
public const COBBLESTONE_WALL = 139;
public const ITEM_FLOWER_POT = 140;
public const CARROTS = 141;
public const POTATOES = 142;
public const WOODEN_BUTTON = 143;
public const ITEM_SKULL = 144;
public const ANVIL = 145;
public const TRAPPED_CHEST = 146;
public const LIGHT_WEIGHTED_PRESSURE_PLATE = 147;
public const HEAVY_WEIGHTED_PRESSURE_PLATE = 148;
public const UNPOWERED_COMPARATOR = 149;
public const POWERED_COMPARATOR = 150;
public const DAYLIGHT_DETECTOR = 151;
public const REDSTONE_BLOCK = 152;
public const QUARTZ_ORE = 153;
public const ITEM_HOPPER = 154;
public const QUARTZ_BLOCK = 155;
public const QUARTZ_STAIRS = 156;
public const DOUBLE_WOODEN_SLAB = 157;
public const WOODEN_SLAB = 158;
public const STAINED_HARDENED_CLAY = 159;
public const STAINED_GLASS_PANE = 160;
public const LEAVES2 = 161;
public const LOG2 = 162;
public const ACACIA_STAIRS = 163;
public const DARK_OAK_STAIRS = 164;
public const SLIME = 165;
public const GLOW_STICK = 166;
public const IRON_TRAPDOOR = 167;
public const PRISMARINE = 168;
public const SEALANTERN = 169;
public const HAY_BLOCK = 170;
public const CARPET = 171;
public const HARDENED_CLAY = 172;
public const COAL_BLOCK = 173;
public const PACKED_ICE = 174;
public const DOUBLE_PLANT = 175;
public const STANDING_BANNER = 176;
public const WALL_BANNER = 177;
public const DAYLIGHT_DETECTOR_INVERTED = 178;
public const RED_SANDSTONE = 179;
public const RED_SANDSTONE_STAIRS = 180;
public const REAL_DOUBLE_STONE_SLAB2 = 181;
public const DOUBLE_STONE_SLAB2 = 182;
public const SPRUCE_FENCE_GATE = 183;
public const BIRCH_FENCE_GATE = 184;
public const JUNGLE_FENCE_GATE = 185;
public const DARK_OAK_FENCE_GATE = 186;
public const ACACIA_FENCE_GATE = 187;
public const REPEATING_COMMAND_BLOCK = 188;
public const CHAIN_COMMAND_BLOCK = 189;
public const HARD_GLASS_PANE = 190;
public const HARD_STAINED_GLASS_PANE = 191;
public const CHEMICAL_HEAT = 192;
public const ITEM_SPRUCE_DOOR = 193;
public const ITEM_BIRCH_DOOR = 194;
public const ITEM_JUNGLE_DOOR = 195;
public const ITEM_ACACIA_DOOR = 196;
public const ITEM_DARK_OAK_DOOR = 197;
public const GRASS_PATH = 198;
public const ITEM_FRAME = 199;
public const CHORUS_FLOWER = 200;
public const PURPUR_BLOCK = 201;
public const COLORED_TORCH_RG = 202;
public const PURPUR_STAIRS = 203;
public const COLORED_TORCH_BP = 204;
public const UNDYED_SHULKER_BOX = 205;
public const END_BRICKS = 206;
public const FROSTED_ICE = 207;
public const END_ROD = 208;
public const END_GATEWAY = 209;
public const ALLOW = 210;
public const DENY = 211;
public const BORDER_BLOCK = 212;
public const MAGMA = 213;
public const NETHER_WART_BLOCK = 214;
public const RED_NETHER_BRICK = 215;
public const BONE_BLOCK = 216;
public const STRUCTURE_VOID = 217;
public const SHULKER_BOX = 218;
public const PURPLE_GLAZED_TERRACOTTA = 219;
public const WHITE_GLAZED_TERRACOTTA = 220;
public const ORANGE_GLAZED_TERRACOTTA = 221;
public const MAGENTA_GLAZED_TERRACOTTA = 222;
public const LIGHT_BLUE_GLAZED_TERRACOTTA = 223;
public const YELLOW_GLAZED_TERRACOTTA = 224;
public const LIME_GLAZED_TERRACOTTA = 225;
public const PINK_GLAZED_TERRACOTTA = 226;
public const GRAY_GLAZED_TERRACOTTA = 227;
public const SILVER_GLAZED_TERRACOTTA = 228;
public const CYAN_GLAZED_TERRACOTTA = 229;
public const BLUE_GLAZED_TERRACOTTA = 231;
public const BROWN_GLAZED_TERRACOTTA = 232;
public const GREEN_GLAZED_TERRACOTTA = 233;
public const RED_GLAZED_TERRACOTTA = 234;
public const BLACK_GLAZED_TERRACOTTA = 235;
public const CONCRETE = 236;
public const CONCRETE_POWDER = 237;
public const CHEMISTRY_TABLE = 238;
public const UNDERWATER_TORCH = 239;
public const CHORUS_PLANT = 240;
public const STAINED_GLASS = 241;
public const ITEM_CAMERA = 242;
public const PODZOL = 243;
public const ITEM_BEETROOT = 244;
public const STONECUTTER = 245;
public const GLOWINGOBSIDIAN = 246;
public const NETHERREACTOR = 247;
public const INFO_UPDATE = 248;
public const INFO_UPDATE2 = 249;
public const MOVINGBLOCK = 250;
public const OBSERVER = 251;
public const STRUCTURE_BLOCK = 252;
public const HARD_GLASS = 253;
public const HARD_STAINED_GLASS = 254;
public const RESERVED6 = 255;
public const IRON_SHOVEL = 256;
public const IRON_PICKAXE = 257;
public const IRON_AXE = 258;
public const FLINT_AND_STEEL = 259;
public const APPLE = 260;
public const BOW = 261;
public const ARROW = 262;
public const COAL = 263;
public const DIAMOND = 264;
public const IRON_INGOT = 265;
public const GOLD_INGOT = 266;
public const IRON_SWORD = 267;
public const WOODEN_SWORD = 268;
public const WOODEN_SHOVEL = 269;
public const WOODEN_PICKAXE = 270;
public const WOODEN_AXE = 271;
public const STONE_SWORD = 272;
public const STONE_SHOVEL = 273;
public const STONE_PICKAXE = 274;
public const STONE_AXE = 275;
public const DIAMOND_SWORD = 276;
public const DIAMOND_SHOVEL = 277;
public const DIAMOND_PICKAXE = 278;
public const DIAMOND_AXE = 279;
public const STICK = 280;
public const BOWL = 281;
public const MUSHROOM_STEW = 282;
public const GOLDEN_SWORD = 283;
public const GOLDEN_SHOVEL = 284;
public const GOLDEN_PICKAXE = 285;
public const GOLDEN_AXE = 286;
public const STRING = 287;
public const FEATHER = 288;
public const GUNPOWDER = 289;
public const WOODEN_HOE = 290;
public const STONE_HOE = 291;
public const IRON_HOE = 292;
public const DIAMOND_HOE = 293;
public const GOLDEN_HOE = 294;
public const WHEAT_SEEDS = 295;
public const WHEAT = 296;
public const BREAD = 297;
public const LEATHER_HELMET = 298;
public const LEATHER_CHESTPLATE = 299;
public const LEATHER_LEGGINGS = 300;
public const LEATHER_BOOTS = 301;
public const CHAINMAIL_HELMET = 302;
public const CHAINMAIL_CHESTPLATE = 303;
public const CHAINMAIL_LEGGINGS = 304;
public const CHAINMAIL_BOOTS = 305;
public const IRON_HELMET = 306;
public const IRON_CHESTPLATE = 307;
public const IRON_LEGGINGS = 308;
public const IRON_BOOTS = 309;
public const DIAMOND_HELMET = 310;
public const DIAMOND_CHESTPLATE = 311;
public const DIAMOND_LEGGINGS = 312;
public const DIAMOND_BOOTS = 313;
public const GOLDEN_HELMET = 314;
public const GOLDEN_CHESTPLATE = 315;
public const GOLDEN_LEGGINGS = 316;
public const GOLDEN_BOOTS = 317;
public const FLINT = 318;
public const PORKCHOP = 319;
public const COOKED_PORKCHOP = 320;
public const PAINTING = 321;
public const GOLDEN_APPLE = 322;
public const SIGN = 323;
public const WOODEN_DOOR = 324;
public const BUCKET = 325;
public const MINECART = 328;
public const SADDLE = 329;
public const IRON_DOOR = 330;
public const REDSTONE = 331;
public const SNOWBALL = 332;
public const BOAT = 333;
public const LEATHER = 334;
public const KELP = 335;
public const BRICK = 336;
public const CLAY_BALL = 337;
public const REEDS = 338;
public const PAPER = 339;
public const BOOK = 340;
public const SLIME_BALL = 341;
public const CHEST_MINECART = 342;
public const EGG = 344;
public const COMPASS = 345;
public const FISHING_ROD = 346;
public const CLOCK = 347;
public const GLOWSTONE_DUST = 348;
public const FISH = 349;
public const COOKED_FISH = 350;
public const DYE = 351;
public const BONE = 352;
public const SUGAR = 353;
public const CAKE = 354;
public const BED = 355;
public const REPEATER = 356;
public const COOKIE = 357;
public const MAP = 358;
public const SHEARS = 359;
public const MELON = 360;
public const PUMPKIN_SEEDS = 361;
public const MELON_SEEDS = 362;
public const BEEF = 363;
public const COOKED_BEEF = 364;
public const CHICKEN = 365;
public const COOKED_CHICKEN = 366;
public const ROTTEN_FLESH = 367;
public const ENDER_PEARL = 368;
public const BLAZE_ROD = 369;
public const GHAST_TEAR = 370;
public const GOLD_NUGGET = 371;
public const NETHER_WART = 372;
public const POTION = 373;
public const GLASS_BOTTLE = 374;
public const SPIDER_EYE = 375;
public const FERMENTED_SPIDER_EYE = 376;
public const BLAZE_POWDER = 377;
public const MAGMA_CREAM = 378;
public const BREWING_STAND = 379;
public const CAULDRON = 380;
public const ENDER_EYE = 381;
public const SPECKLED_MELON = 382;
public const SPAWN_EGG = 383;
public const EXPERIENCE_BOTTLE = 384;
public const FIREBALL = 385;
public const WRITABLE_BOOK = 386;
public const WRITTEN_BOOK = 387;
public const EMERALD = 388;
public const FRAME = 389;
public const FLOWER_POT = 390;
public const CARROT = 391;
public const POTATO = 392;
public const BAKED_POTATO = 393;
public const POISONOUS_POTATO = 394;
public const EMPTYMAP = 395;
public const GOLDEN_CARROT = 396;
public const SKULL = 397;
public const CARROTONASTICK = 398;
public const NETHERSTAR = 399;
public const PUMPKIN_PIE = 400;
public const FIREWORKS = 401;
public const FIREWORKSCHARGE = 402;
public const ENCHANTED_BOOK = 403;
public const COMPARATOR = 404;
public const NETHERBRICK = 405;
public const QUARTZ = 406;
public const TNT_MINECART = 407;
public const HOPPER_MINECART = 408;
public const PRISMARINE_SHARD = 409;
public const HOPPER = 410;
public const RABBIT = 411;
public const COOKED_RABBIT = 412;
public const RABBIT_STEW = 413;
public const RABBIT_FOOT = 414;
public const RABBIT_HIDE = 415;
public const HORSEARMORLEATHER = 416;
public const HORSEARMORIRON = 417;
public const HORSEARMORGOLD = 418;
public const HORSEARMORDIAMOND = 419;
public const LEAD = 420;
public const NAME_TAG = 421;
public const PRISMARINE_CRYSTALS = 422;
public const MUTTONRAW = 423;
public const MUTTONCOOKED = 424;
public const ARMOR_STAND = 425;
public const END_CRYSTAL = 426;
public const SPRUCE_DOOR = 427;
public const BIRCH_DOOR = 428;
public const JUNGLE_DOOR = 429;
public const ACACIA_DOOR = 430;
public const DARK_OAK_DOOR = 431;
public const CHORUS_FRUIT = 432;
public const CHORUS_FRUIT_POPPED = 433;
public const BANNER_PATTERN = 434;
public const DRAGON_BREATH = 437;
public const SPLASH_POTION = 438;
public const LINGERING_POTION = 441;
public const SPARKLER = 442;
public const COMMAND_BLOCK_MINECART = 443;
public const ELYTRA = 444;
public const SHULKER_SHELL = 445;
public const BANNER = 446;
public const MEDICINE = 447;
public const BALLOON = 448;
public const RAPID_FERTILIZER = 449;
public const TOTEM = 450;
public const BLEACH = 451;
public const IRON_NUGGET = 452;
public const ICE_BOMB = 453;
public const TRIDENT = 455;
public const BEETROOT = 457;
public const BEETROOT_SEEDS = 458;
public const BEETROOT_SOUP = 459;
public const SALMON = 460;
public const CLOWNFISH = 461;
public const PUFFERFISH = 462;
public const COOKED_SALMON = 463;
public const DRIED_KELP = 464;
public const NAUTILUS_SHELL = 465;
public const APPLEENCHANTED = 466;
public const HEART_OF_THE_SEA = 467;
public const TURTLE_SHELL_PIECE = 468;
public const TURTLE_HELMET = 469;
public const PHANTOM_MEMBRANE = 470;
public const CROSSBOW = 471;
public const SPRUCE_SIGN = 472;
public const BIRCH_SIGN = 473;
public const JUNGLE_SIGN = 474;
public const ACACIA_SIGN = 475;
public const DARKOAK_SIGN = 476;
public const SWEET_BERRIES = 477;
public const CAMERA = 498;
public const COMPOUND = 499;
public const RECORD_13 = 500;
public const RECORD_CAT = 501;
public const RECORD_BLOCKS = 502;
public const RECORD_CHIRP = 503;
public const RECORD_FAR = 504;
public const RECORD_MALL = 505;
public const RECORD_MELLOHI = 506;
public const RECORD_STAL = 507;
public const RECORD_STRAD = 508;
public const RECORD_WARD = 509;
public const RECORD_11 = 510;
public const RECORD_WAIT = 511;
public const SHIELD = 513;
public const CAMPFIRE = 720;
public const SUSPICIOUS_STEW = 734;
public const HONEYCOMB = 736;
public const HONEY_BOTTLE = 737;
public const LODESTONECOMPASS = 741;
public const NETHERITE_INGOT = 742;
public const NETHERITE_SWORD = 743;
public const NETHERITE_SHOVEL = 744;
public const NETHERITE_PICKAXE = 745;
public const NETHERITE_AXE = 746;
public const NETHERITE_HOE = 747;
public const NETHERITE_HELMET = 748;
public const NETHERITE_CHESTPLATE = 749;
public const NETHERITE_LEGGINGS = 750;
public const NETHERITE_BOOTS = 751;
public const NETHERITE_SCRAP = 752;
public const CRIMSON_SIGN = 753;
public const WARPED_SIGN = 754;
public const CRIMSON_DOOR = 755;
public const WARPED_DOOR = 756;
public const WARPED_FUNGUS_ON_A_STICK = 757;
public const CHAIN = 758;
public const RECORD_PIGSTEP = 759;
public const NETHER_SPROUTS = 760;
public const SOUL_CAMPFIRE = 801;
}

View File

@ -0,0 +1,43 @@
<?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\protocol\types;
use pocketmine\nbt\tag\CompoundTag;
final class ItemComponentPacketEntry{
/** @var string */
private $name;
/** @var CompoundTag */
private $componentNbt;
public function __construct(string $name, CompoundTag $componentNbt){
$this->name = $name;
$this->componentNbt = $componentNbt;
}
public function getName() : string{ return $this->name; }
public function getComponentNbt() : CompoundTag{ return $this->componentNbt; }
}

View File

@ -0,0 +1,46 @@
<?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\protocol\types;
final class ItemTypeEntry{
/** @var string */
private $stringId;
/** @var int */
private $numericId;
/** @var bool */
private $componentBased;
public function __construct(string $stringId, int $numericId, bool $componentBased){
$this->stringId = $stringId;
$this->numericId = $numericId;
$this->componentBased = $componentBased;
}
public function getStringId() : string{ return $this->stringId; }
public function getNumericId() : int{ return $this->numericId; }
public function isComponentBased() : bool{ return $this->componentBased; }
}

View File

@ -0,0 +1,31 @@
<?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\protocol\types;
final class PlayerMovementType{
public const LEGACY = 0; //MovePlayerPacket
public const SERVER_AUTHORITATIVE_V1 = 1; //PlayerAuthInputPacket
public const SERVER_AUTHORITATIVE_V2_REWIND = 2; //PlayerAuthInputPacket + a bunch of junk that solves a nonexisting problem
}

View File

@ -26,7 +26,6 @@ namespace pocketmine\network\mcpe\protocol\types\inventory;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
use pocketmine\network\mcpe\protocol\types\FixedItemIds;
use function base64_encode;
use function count;
@ -52,9 +51,6 @@ final class ItemStack implements \JsonSerializable{
* @param string[] $canDestroy
*/
public function __construct(int $id, int $meta, int $count, ?CompoundTag $nbt, array $canPlaceOn, array $canDestroy, ?int $shieldBlockingTick = null){
if(($shieldBlockingTick !== null) !== ($id === FixedItemIds::SHIELD)){
throw new \InvalidArgumentException("Blocking tick must only be provided for shield items");
}
$this->id = $id;
$this->meta = $meta;
$this->count = $count;

View File

@ -28,8 +28,13 @@ use function count;
final class ItemStackResponse{
/** @var bool */
private $ok;
public const RESULT_OK = 0;
public const RESULT_ERROR = 1;
//TODO: there are a ton more possible result types but we don't need them yet and they are wayyyyyy too many for me
//to waste my time on right now...
/** @var int */
private $result;
/** @var int */
private $requestId;
/** @var ItemStackResponseContainerInfo[] */
@ -38,13 +43,13 @@ final class ItemStackResponse{
/**
* @param ItemStackResponseContainerInfo[] $containerInfos
*/
public function __construct(bool $ok, int $requestId, array $containerInfos){
$this->ok = $ok;
public function __construct(int $result, int $requestId, array $containerInfos){
$this->result = $result;
$this->requestId = $requestId;
$this->containerInfos = $containerInfos;
}
public function isOk() : bool{ return $this->ok; }
public function getResult() : int{ return $this->result; }
public function getRequestId() : int{ return $this->requestId; }
@ -52,17 +57,17 @@ final class ItemStackResponse{
public function getContainerInfos() : array{ return $this->containerInfos; }
public static function read(PacketSerializer $in) : self{
$ok = $in->getBool();
$result = $in->getByte();
$requestId = $in->readGenericTypeNetworkId();
$containerInfos = [];
for($i = 0, $len = $in->getUnsignedVarInt(); $i < $len; ++$i){
$containerInfos[] = ItemStackResponseContainerInfo::read($in);
}
return new self($ok, $requestId, $containerInfos);
return new self($result, $requestId, $containerInfos);
}
public function write(PacketSerializer $out) : void{
$out->putBool($this->ok);
$out->putByte($this->result);
$out->writeGenericTypeNetworkId($this->requestId);
$out->putUnsignedVarInt(count($this->containerInfos));
foreach($this->containerInfos as $containerInfo){

View File

@ -57,4 +57,10 @@ final class ClientDataAnimationFrame{
* @required
*/
public $Image;
/**
* @var int
* @required
*/
public $AnimationExpression;
}

View File

@ -60,7 +60,8 @@ final class ClientDataToSkinDataHelper{
self::safeB64Decode($animation->Image, "AnimatedImageData.$k.Image")
),
$animation->Type,
$animation->Frames
$animation->Frames,
$animation->AnimationExpression
);
}
return new SkinData(

View File

@ -29,17 +29,23 @@ class SkinAnimation{
public const TYPE_BODY_32 = 2;
public const TYPE_BODY_64 = 3;
public const EXPRESSION_LINEAR = 0; //???
public const EXPRESSION_BLINKING = 1;
/** @var SkinImage */
private $image;
/** @var int */
private $type;
/** @var float */
private $frames;
/** @var int */
private $expressionType;
public function __construct(SkinImage $image, int $type, float $frames){
public function __construct(SkinImage $image, int $type, float $frames, int $expressionType){
$this->image = $image;
$this->type = $type;
$this->frames = $frames;
$this->expressionType = $expressionType;
}
/**
@ -62,4 +68,6 @@ class SkinAnimation{
public function getFrames() : float{
return $this->frames;
}
public function getExpressionType() : int{ return $this->expressionType; }
}