mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-07 04:17:07 +00:00
Merge commit '82d9e481d2a0a389fbbc6dfd3672fc366127febc'
This commit is contained in:
commit
c85c1c3c3f
20
changelogs/3.10.md
Normal file
20
changelogs/3.10.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
**For Minecraft: Bedrock Edition 1.13.0**
|
||||||
|
|
||||||
|
### 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.10.0
|
||||||
|
- Added support for Minecraft: Bedrock Edition 1.13.0
|
||||||
|
- Removed compatibility with 1.12.0
|
||||||
|
|
||||||
|
## Note about skins
|
||||||
|
PocketMine-MP **does not support skins made in the Charactor Creator** (known as Persona skins), due to technical changes which would require premature backwards compatibility breaks. The dev team has decided not to support Persona yet.
|
||||||
|
These skins will be **replaced with a random solid-colour skin. This is not a bug.**
|
||||||
|
Skins chosen from the Classic tab (classic skins) will continue to work as normal.
|
||||||
|
|
||||||
|
# 3.10.1
|
||||||
|
- Fixed custom plugin-created skins being invisible when no geometry name was specified.
|
||||||
|
- Updated RakLib to 0.12.6 to fix security bugs.
|
@ -1 +1 @@
|
|||||||
Subproject commit b5a8c68c4262e5d9d7f8280c1d07c252a5e8dbf8
|
Subproject commit 0df4e593af7eca16c9e9dd4c6cf2f206be267fd3
|
@ -48,6 +48,7 @@ use pocketmine\network\mcpe\protocol\PlayerSkinPacket;
|
|||||||
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty;
|
use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty;
|
||||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\SkinAdapterSingleton;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use pocketmine\utils\Limits;
|
use pocketmine\utils\Limits;
|
||||||
use pocketmine\utils\UUID;
|
use pocketmine\utils\UUID;
|
||||||
@ -153,7 +154,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
|
|||||||
public function sendSkin(?array $targets = null) : void{
|
public function sendSkin(?array $targets = null) : void{
|
||||||
$pk = new PlayerSkinPacket();
|
$pk = new PlayerSkinPacket();
|
||||||
$pk->uuid = $this->getUniqueId();
|
$pk->uuid = $this->getUniqueId();
|
||||||
$pk->skin = $this->skin;
|
$pk->skin = SkinAdapterSingleton::get()->toSkinData($this->skin);
|
||||||
$this->server->broadcastPackets($targets ?? $this->hasSpawned, [$pk]);
|
$this->server->broadcastPackets($targets ?? $this->hasSpawned, [$pk]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,7 +408,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
|
|||||||
|
|
||||||
protected function sendSpawnPacket(Player $player) : void{
|
protected function sendSpawnPacket(Player $player) : void{
|
||||||
if(!($this instanceof Player)){
|
if(!($this instanceof Player)){
|
||||||
$player->getNetworkSession()->sendDataPacket(PlayerListPacket::add([PlayerListEntry::createAdditionEntry($this->uuid, $this->id, $this->getName(), $this->skin)]));
|
$player->getNetworkSession()->sendDataPacket(PlayerListPacket::add([PlayerListEntry::createAdditionEntry($this->uuid, $this->id, $this->getName(), SkinAdapterSingleton::get()->toSkinData($this->skin))]));
|
||||||
}
|
}
|
||||||
|
|
||||||
$pk = new AddPlayerPacket();
|
$pk = new AddPlayerPacket();
|
||||||
|
@ -61,7 +61,7 @@ class InventoryManager{
|
|||||||
|
|
||||||
$this->windowMap[ContainerIds::INVENTORY] = $this->player->getInventory();
|
$this->windowMap[ContainerIds::INVENTORY] = $this->player->getInventory();
|
||||||
$this->windowMap[ContainerIds::ARMOR] = $this->player->getArmorInventory();
|
$this->windowMap[ContainerIds::ARMOR] = $this->player->getArmorInventory();
|
||||||
$this->windowMap[ContainerIds::CURSOR] = $this->player->getCursorInventory();
|
$this->windowMap[ContainerIds::UI] = $this->player->getCursorInventory();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getWindowId(Inventory $inventory) : ?int{
|
public function getWindowId(Inventory $inventory) : ?int{
|
||||||
|
@ -73,6 +73,7 @@ use pocketmine\network\mcpe\protocol\types\command\CommandParameter;
|
|||||||
use pocketmine\network\mcpe\protocol\types\inventory\ContainerIds;
|
use pocketmine\network\mcpe\protocol\types\inventory\ContainerIds;
|
||||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||||
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
|
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\SkinAdapterSingleton;
|
||||||
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
|
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
|
||||||
use pocketmine\network\NetworkSessionManager;
|
use pocketmine\network\NetworkSessionManager;
|
||||||
use pocketmine\player\GameMode;
|
use pocketmine\player\GameMode;
|
||||||
@ -726,7 +727,7 @@ class NetworkSession{
|
|||||||
0,
|
0,
|
||||||
$aliasObj,
|
$aliasObj,
|
||||||
[
|
[
|
||||||
[CommandParameter::standard("args", AvailableCommandsPacket::ARG_TYPE_RAWTEXT, true)]
|
[CommandParameter::standard("args", AvailableCommandsPacket::ARG_TYPE_RAWTEXT, 0, true)]
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -830,12 +831,12 @@ class NetworkSession{
|
|||||||
|
|
||||||
public function syncPlayerList() : void{
|
public function syncPlayerList() : void{
|
||||||
$this->sendDataPacket(PlayerListPacket::add(array_map(function(Player $player){
|
$this->sendDataPacket(PlayerListPacket::add(array_map(function(Player $player){
|
||||||
return PlayerListEntry::createAdditionEntry($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkin(), $player->getXuid());
|
return PlayerListEntry::createAdditionEntry($player->getUniqueId(), $player->getId(), $player->getDisplayName(), SkinAdapterSingleton::get()->toSkinData($player->getSkin()), $player->getXuid());
|
||||||
}, $this->server->getOnlinePlayers())));
|
}, $this->server->getOnlinePlayers())));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onPlayerAdded(Player $p) : void{
|
public function onPlayerAdded(Player $p) : void{
|
||||||
$this->sendDataPacket(PlayerListPacket::add([PlayerListEntry::createAdditionEntry($p->getUniqueId(), $p->getId(), $p->getDisplayName(), $p->getSkin(), $p->getXuid())]));
|
$this->sendDataPacket(PlayerListPacket::add([PlayerListEntry::createAdditionEntry($p->getUniqueId(), $p->getId(), $p->getDisplayName(), SkinAdapterSingleton::get()->toSkinData($p->getSkin()), $p->getXuid())]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onPlayerRemoved(Player $p) : void{
|
public function onPlayerRemoved(Player $p) : void{
|
||||||
|
@ -41,7 +41,11 @@ class DeathPacketHandler extends PacketHandler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function setUp() : void{
|
public function setUp() : void{
|
||||||
$this->session->sendDataPacket(RespawnPacket::create($this->player->getOffsetPosition($this->player->getSpawn())));
|
$this->session->sendDataPacket(RespawnPacket::create(
|
||||||
|
$this->player->getOffsetPosition($this->player->getSpawn()),
|
||||||
|
RespawnPacket::SEARCHING_FOR_SPAWN,
|
||||||
|
$this->player->getId()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handlePlayerAction(PlayerActionPacket $packet) : bool{
|
public function handlePlayerAction(PlayerActionPacket $packet) : bool{
|
||||||
@ -56,4 +60,16 @@ class DeathPacketHandler extends PacketHandler{
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function handleRespawn(RespawnPacket $packet) : bool{
|
||||||
|
if($packet->respawnState === RespawnPacket::CLIENT_READY_TO_SPAWN){
|
||||||
|
$this->session->sendDataPacket(RespawnPacket::create(
|
||||||
|
$this->player->getOffsetPosition($this->player->getSpawn()),
|
||||||
|
RespawnPacket::READY_TO_SPAWN,
|
||||||
|
$this->player->getId()
|
||||||
|
));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,10 @@ use pocketmine\network\mcpe\protocol\ShowCreditsPacket;
|
|||||||
use pocketmine\network\mcpe\protocol\SpawnExperienceOrbPacket;
|
use pocketmine\network\mcpe\protocol\SpawnExperienceOrbPacket;
|
||||||
use pocketmine\network\mcpe\protocol\SubClientLoginPacket;
|
use pocketmine\network\mcpe\protocol\SubClientLoginPacket;
|
||||||
use pocketmine\network\mcpe\protocol\TextPacket;
|
use pocketmine\network\mcpe\protocol\TextPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\SkinAdapterSingleton;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\inventory\ContainerIds;
|
||||||
use pocketmine\network\mcpe\protocol\types\inventory\MismatchTransactionData;
|
use pocketmine\network\mcpe\protocol\types\inventory\MismatchTransactionData;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\inventory\NetworkInventoryAction;
|
||||||
use pocketmine\network\mcpe\protocol\types\inventory\NormalTransactionData;
|
use pocketmine\network\mcpe\protocol\types\inventory\NormalTransactionData;
|
||||||
use pocketmine\network\mcpe\protocol\types\inventory\ReleaseItemTransactionData;
|
use pocketmine\network\mcpe\protocol\types\inventory\ReleaseItemTransactionData;
|
||||||
use pocketmine\network\mcpe\protocol\types\inventory\UseItemOnEntityTransactionData;
|
use pocketmine\network\mcpe\protocol\types\inventory\UseItemOnEntityTransactionData;
|
||||||
@ -197,8 +200,24 @@ class InGamePacketHandler extends PacketHandler{
|
|||||||
$isCrafting = false;
|
$isCrafting = false;
|
||||||
$isFinalCraftingPart = false;
|
$isFinalCraftingPart = false;
|
||||||
foreach($data->getActions() as $networkInventoryAction){
|
foreach($data->getActions() as $networkInventoryAction){
|
||||||
$isCrafting = $isCrafting || $networkInventoryAction->isCraftingPart();
|
if(
|
||||||
$isFinalCraftingPart = $isFinalCraftingPart || $networkInventoryAction->isFinalCraftingPart();
|
$networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_CONTAINER and
|
||||||
|
$networkInventoryAction->windowId === ContainerIds::UI and
|
||||||
|
$networkInventoryAction->inventorySlot === 50 and
|
||||||
|
!$networkInventoryAction->oldItem->equalsExact($networkInventoryAction->newItem)
|
||||||
|
){
|
||||||
|
$isCrafting = true;
|
||||||
|
if(!$networkInventoryAction->oldItem->isNull() and $networkInventoryAction->newItem->isNull()){
|
||||||
|
$isFinalCraftingPart = true;
|
||||||
|
}
|
||||||
|
}elseif(
|
||||||
|
$networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_TODO and (
|
||||||
|
$networkInventoryAction->windowId === NetworkInventoryAction::SOURCE_TYPE_CRAFTING_RESULT or
|
||||||
|
$networkInventoryAction->windowId === NetworkInventoryAction::SOURCE_TYPE_CRAFTING_USE_INGREDIENT
|
||||||
|
)
|
||||||
|
){
|
||||||
|
$isCrafting = true;
|
||||||
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
$action = $networkInventoryAction->createInventoryAction($this->player);
|
$action = $networkInventoryAction->createInventoryAction($this->player);
|
||||||
@ -285,6 +304,10 @@ class InGamePacketHandler extends PacketHandler{
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case UseItemTransactionData::ACTION_CLICK_AIR:
|
case UseItemTransactionData::ACTION_CLICK_AIR:
|
||||||
|
if($this->player->isUsingItem() and !$this->player->consumeHeldItem()){
|
||||||
|
$this->session->getInvManager()->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if(!$this->player->useHeldItem()){
|
if(!$this->player->useHeldItem()){
|
||||||
$this->session->getInvManager()->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
|
$this->session->getInvManager()->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
|
||||||
}
|
}
|
||||||
@ -347,11 +370,6 @@ class InGamePacketHandler extends PacketHandler{
|
|||||||
$this->session->getInvManager()->syncContents($this->player->getInventory());
|
$this->session->getInvManager()->syncContents($this->player->getInventory());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case ReleaseItemTransactionData::ACTION_CONSUME:
|
|
||||||
if(!$this->player->consumeHeldItem()){
|
|
||||||
$this->session->getInvManager()->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -603,7 +621,7 @@ class InGamePacketHandler extends PacketHandler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function handlePlayerSkin(PlayerSkinPacket $packet) : bool{
|
public function handlePlayerSkin(PlayerSkinPacket $packet) : bool{
|
||||||
return $this->player->changeSkin($packet->skin, $packet->newSkinName, $packet->oldSkinName);
|
return $this->player->changeSkin(SkinAdapterSingleton::get()->fromSkinData($packet->skin), $packet->newSkinName, $packet->oldSkinName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleSubClientLogin(SubClientLoginPacket $packet) : bool{
|
public function handleSubClientLogin(SubClientLoginPacket $packet) : bool{
|
||||||
|
@ -30,6 +30,10 @@ use pocketmine\network\mcpe\NetworkSession;
|
|||||||
use pocketmine\network\mcpe\protocol\LoginPacket;
|
use pocketmine\network\mcpe\protocol\LoginPacket;
|
||||||
use pocketmine\network\mcpe\protocol\PlayStatusPacket;
|
use pocketmine\network\mcpe\protocol\PlayStatusPacket;
|
||||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\SkinAdapterSingleton;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\SkinAnimation;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\SkinData;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\SkinImage;
|
||||||
use pocketmine\player\Player;
|
use pocketmine\player\Player;
|
||||||
use pocketmine\player\PlayerInfo;
|
use pocketmine\player\PlayerInfo;
|
||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
@ -72,13 +76,34 @@ class LoginPacketHandler extends PacketHandler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
$skin = new Skin(
|
/** @var SkinAnimation[] $animations */
|
||||||
$packet->clientData[LoginPacket::I_SKIN_ID],
|
$animations = [];
|
||||||
base64_decode($packet->clientData[LoginPacket::I_SKIN_DATA]),
|
foreach($packet->clientData[LoginPacket::I_ANIMATION_IMAGES] as $animation){
|
||||||
base64_decode($packet->clientData[LoginPacket::I_CAPE_DATA]),
|
$animations[] = new SkinAnimation(
|
||||||
$packet->clientData[LoginPacket::I_GEOMETRY_NAME],
|
new SkinImage(
|
||||||
base64_decode($packet->clientData[LoginPacket::I_GEOMETRY_DATA])
|
$animation[LoginPacket::I_ANIMATION_IMAGE_HEIGHT],
|
||||||
|
$animation[LoginPacket::I_ANIMATION_IMAGE_WIDTH],
|
||||||
|
base64_decode($animation[LoginPacket::I_ANIMATION_IMAGE_DATA])
|
||||||
|
),
|
||||||
|
$animation[LoginPacket::I_ANIMATION_IMAGE_TYPE],
|
||||||
|
$animation[LoginPacket::I_ANIMATION_IMAGE_FRAMES]
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
$skinData = new SkinData(
|
||||||
|
$packet->clientData[LoginPacket::I_SKIN_ID],
|
||||||
|
base64_decode($packet->clientData[LoginPacket::I_SKIN_RESOURCE_PATCH]),
|
||||||
|
new SkinImage($packet->clientData[LoginPacket::I_SKIN_HEIGHT], $packet->clientData[LoginPacket::I_SKIN_WIDTH], base64_decode($packet->clientData[LoginPacket::I_SKIN_DATA])),
|
||||||
|
$animations,
|
||||||
|
new SkinImage($packet->clientData[LoginPacket::I_CAPE_HEIGHT], $packet->clientData[LoginPacket::I_CAPE_WIDTH], base64_decode($packet->clientData[LoginPacket::I_CAPE_DATA])),
|
||||||
|
base64_decode($packet->clientData[LoginPacket::I_GEOMETRY_DATA]),
|
||||||
|
base64_decode($packet->clientData[LoginPacket::I_ANIMATION_DATA]),
|
||||||
|
$packet->clientData[LoginPacket::I_PREMIUM_SKIN],
|
||||||
|
$packet->clientData[LoginPacket::I_PERSONA_SKIN],
|
||||||
|
$packet->clientData[LoginPacket::I_PERSONA_CAPE_ON_CLASSIC_SKIN],
|
||||||
|
$packet->clientData[LoginPacket::I_CAPE_ID]
|
||||||
|
);
|
||||||
|
|
||||||
|
$skin = SkinAdapterSingleton::get()->fromSkinData($skinData);
|
||||||
}catch(\InvalidArgumentException $e){
|
}catch(\InvalidArgumentException $e){
|
||||||
$this->session->getLogger()->debug("Invalid skin: " . $e->getMessage());
|
$this->session->getLogger()->debug("Invalid skin: " . $e->getMessage());
|
||||||
$this->session->disconnect("disconnectionScreen.invalidSkin");
|
$this->session->disconnect("disconnectionScreen.invalidSkin");
|
||||||
|
@ -34,6 +34,7 @@ use pocketmine\network\mcpe\protocol\AddPaintingPacket;
|
|||||||
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
|
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
|
||||||
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
|
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
|
||||||
use pocketmine\network\mcpe\protocol\AnimatePacket;
|
use pocketmine\network\mcpe\protocol\AnimatePacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\AnvilDamagePacket;
|
||||||
use pocketmine\network\mcpe\protocol\AutomationClientConnectPacket;
|
use pocketmine\network\mcpe\protocol\AutomationClientConnectPacket;
|
||||||
use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket;
|
use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket;
|
||||||
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
|
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
|
||||||
@ -54,14 +55,16 @@ use pocketmine\network\mcpe\protocol\ClientToServerHandshakePacket;
|
|||||||
use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket;
|
use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket;
|
||||||
use pocketmine\network\mcpe\protocol\CommandOutputPacket;
|
use pocketmine\network\mcpe\protocol\CommandOutputPacket;
|
||||||
use pocketmine\network\mcpe\protocol\CommandRequestPacket;
|
use pocketmine\network\mcpe\protocol\CommandRequestPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\CompletedUsingItemPacket;
|
||||||
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
|
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
|
||||||
use pocketmine\network\mcpe\protocol\ContainerOpenPacket;
|
use pocketmine\network\mcpe\protocol\ContainerOpenPacket;
|
||||||
use pocketmine\network\mcpe\protocol\ContainerSetDataPacket;
|
use pocketmine\network\mcpe\protocol\ContainerSetDataPacket;
|
||||||
use pocketmine\network\mcpe\protocol\CraftingDataPacket;
|
use pocketmine\network\mcpe\protocol\CraftingDataPacket;
|
||||||
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
|
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
|
||||||
use pocketmine\network\mcpe\protocol\DisconnectPacket;
|
use pocketmine\network\mcpe\protocol\DisconnectPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\EducationSettingsPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\EmotePacket;
|
||||||
use pocketmine\network\mcpe\protocol\EventPacket;
|
use pocketmine\network\mcpe\protocol\EventPacket;
|
||||||
use pocketmine\network\mcpe\protocol\ExplodePacket;
|
|
||||||
use pocketmine\network\mcpe\protocol\GameRulesChangedPacket;
|
use pocketmine\network\mcpe\protocol\GameRulesChangedPacket;
|
||||||
use pocketmine\network\mcpe\protocol\GuiDataPickItemPacket;
|
use pocketmine\network\mcpe\protocol\GuiDataPickItemPacket;
|
||||||
use pocketmine\network\mcpe\protocol\HurtArmorPacket;
|
use pocketmine\network\mcpe\protocol\HurtArmorPacket;
|
||||||
@ -89,12 +92,15 @@ use pocketmine\network\mcpe\protocol\ModalFormResponsePacket;
|
|||||||
use pocketmine\network\mcpe\protocol\MoveActorAbsolutePacket;
|
use pocketmine\network\mcpe\protocol\MoveActorAbsolutePacket;
|
||||||
use pocketmine\network\mcpe\protocol\MoveActorDeltaPacket;
|
use pocketmine\network\mcpe\protocol\MoveActorDeltaPacket;
|
||||||
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
|
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\MultiplayerSettingsPacket;
|
||||||
use pocketmine\network\mcpe\protocol\NetworkChunkPublisherUpdatePacket;
|
use pocketmine\network\mcpe\protocol\NetworkChunkPublisherUpdatePacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\NetworkSettingsPacket;
|
||||||
use pocketmine\network\mcpe\protocol\NetworkStackLatencyPacket;
|
use pocketmine\network\mcpe\protocol\NetworkStackLatencyPacket;
|
||||||
use pocketmine\network\mcpe\protocol\NpcRequestPacket;
|
use pocketmine\network\mcpe\protocol\NpcRequestPacket;
|
||||||
use pocketmine\network\mcpe\protocol\OnScreenTextureAnimationPacket;
|
use pocketmine\network\mcpe\protocol\OnScreenTextureAnimationPacket;
|
||||||
use pocketmine\network\mcpe\protocol\PhotoTransferPacket;
|
use pocketmine\network\mcpe\protocol\PhotoTransferPacket;
|
||||||
use pocketmine\network\mcpe\protocol\PlayerActionPacket;
|
use pocketmine\network\mcpe\protocol\PlayerActionPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\PlayerAuthInputPacket;
|
||||||
use pocketmine\network\mcpe\protocol\PlayerHotbarPacket;
|
use pocketmine\network\mcpe\protocol\PlayerHotbarPacket;
|
||||||
use pocketmine\network\mcpe\protocol\PlayerInputPacket;
|
use pocketmine\network\mcpe\protocol\PlayerInputPacket;
|
||||||
use pocketmine\network\mcpe\protocol\PlayerListPacket;
|
use pocketmine\network\mcpe\protocol\PlayerListPacket;
|
||||||
@ -133,6 +139,7 @@ use pocketmine\network\mcpe\protocol\SetScoreboardIdentityPacket;
|
|||||||
use pocketmine\network\mcpe\protocol\SetScorePacket;
|
use pocketmine\network\mcpe\protocol\SetScorePacket;
|
||||||
use pocketmine\network\mcpe\protocol\SetSpawnPositionPacket;
|
use pocketmine\network\mcpe\protocol\SetSpawnPositionPacket;
|
||||||
use pocketmine\network\mcpe\protocol\SetTimePacket;
|
use pocketmine\network\mcpe\protocol\SetTimePacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\SettingsCommandPacket;
|
||||||
use pocketmine\network\mcpe\protocol\SetTitlePacket;
|
use pocketmine\network\mcpe\protocol\SetTitlePacket;
|
||||||
use pocketmine\network\mcpe\protocol\ShowCreditsPacket;
|
use pocketmine\network\mcpe\protocol\ShowCreditsPacket;
|
||||||
use pocketmine\network\mcpe\protocol\ShowProfilePacket;
|
use pocketmine\network\mcpe\protocol\ShowProfilePacket;
|
||||||
@ -143,11 +150,12 @@ use pocketmine\network\mcpe\protocol\SpawnParticleEffectPacket;
|
|||||||
use pocketmine\network\mcpe\protocol\StartGamePacket;
|
use pocketmine\network\mcpe\protocol\StartGamePacket;
|
||||||
use pocketmine\network\mcpe\protocol\StopSoundPacket;
|
use pocketmine\network\mcpe\protocol\StopSoundPacket;
|
||||||
use pocketmine\network\mcpe\protocol\StructureBlockUpdatePacket;
|
use pocketmine\network\mcpe\protocol\StructureBlockUpdatePacket;
|
||||||
use pocketmine\network\mcpe\protocol\StructureTemplateDataExportRequestPacket;
|
use pocketmine\network\mcpe\protocol\StructureTemplateDataRequestPacket;
|
||||||
use pocketmine\network\mcpe\protocol\StructureTemplateDataExportResponsePacket;
|
use pocketmine\network\mcpe\protocol\StructureTemplateDataResponsePacket;
|
||||||
use pocketmine\network\mcpe\protocol\SubClientLoginPacket;
|
use pocketmine\network\mcpe\protocol\SubClientLoginPacket;
|
||||||
use pocketmine\network\mcpe\protocol\TakeItemActorPacket;
|
use pocketmine\network\mcpe\protocol\TakeItemActorPacket;
|
||||||
use pocketmine\network\mcpe\protocol\TextPacket;
|
use pocketmine\network\mcpe\protocol\TextPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\TickSyncPacket;
|
||||||
use pocketmine\network\mcpe\protocol\TransferPacket;
|
use pocketmine\network\mcpe\protocol\TransferPacket;
|
||||||
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
|
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
|
||||||
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
|
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
|
||||||
@ -254,7 +262,7 @@ abstract class PacketHandler{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleExplode(ExplodePacket $packet) : bool{
|
public function handleTickSync(TickSyncPacket $packet) : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -686,11 +694,11 @@ abstract class PacketHandler{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleStructureTemplateDataExportRequest(StructureTemplateDataExportRequestPacket $packet) : bool{
|
public function handleStructureTemplateDataRequest(StructureTemplateDataRequestPacket $packet) : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleStructureTemplateDataExportResponse(StructureTemplateDataExportResponsePacket $packet) : bool{
|
public function handleStructureTemplateDataResponse(StructureTemplateDataResponsePacket $packet) : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,4 +713,36 @@ abstract class PacketHandler{
|
|||||||
public function handleClientCacheMissResponse(ClientCacheMissResponsePacket $packet) : bool{
|
public function handleClientCacheMissResponse(ClientCacheMissResponsePacket $packet) : bool{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function handleEducationSettings(EducationSettingsPacket $packet) : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleEmote(EmotePacket $packet) : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleMultiplayerSettings(MultiplayerSettingsPacket $packet) : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleSettingsCommand(SettingsCommandPacket $packet) : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleAnvilDamage(AnvilDamagePacket $packet) : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleCompletedUsingItem(CompletedUsingItemPacket $packet) : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleNetworkSettings(NetworkSettingsPacket $packet) : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handlePlayerAuthInput(PlayerAuthInputPacket $packet) : bool{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ class PreSpawnPacketHandler extends PacketHandler{
|
|||||||
$pk->spawnZ = $spawnPosition->getFloorZ();
|
$pk->spawnZ = $spawnPosition->getFloorZ();
|
||||||
$pk->hasAchievementsDisabled = true;
|
$pk->hasAchievementsDisabled = true;
|
||||||
$pk->time = $location->getWorld()->getTime();
|
$pk->time = $location->getWorld()->getTime();
|
||||||
$pk->eduMode = false;
|
$pk->eduEditionOffer = 0;
|
||||||
$pk->rainLevel = 0; //TODO: implement these properly
|
$pk->rainLevel = 0; //TODO: implement these properly
|
||||||
$pk->lightningLevel = 0;
|
$pk->lightningLevel = 0;
|
||||||
$pk->commandsEnabled = true;
|
$pk->commandsEnabled = true;
|
||||||
|
@ -75,6 +75,8 @@ class AddPlayerPacket extends DataPacket implements ClientboundPacket{
|
|||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $deviceId = ""; //TODO: fill player's device ID (???)
|
public $deviceId = ""; //TODO: fill player's device ID (???)
|
||||||
|
/** @var int */
|
||||||
|
public $buildPlatform = -1;
|
||||||
|
|
||||||
protected function decodePayload() : void{
|
protected function decodePayload() : void{
|
||||||
$this->uuid = $this->getUUID();
|
$this->uuid = $this->getUUID();
|
||||||
@ -104,6 +106,7 @@ class AddPlayerPacket extends DataPacket implements ClientboundPacket{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->deviceId = $this->getString();
|
$this->deviceId = $this->getString();
|
||||||
|
$this->buildPlatform = $this->getLInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function encodePayload() : void{
|
protected function encodePayload() : void{
|
||||||
@ -134,6 +137,7 @@ class AddPlayerPacket extends DataPacket implements ClientboundPacket{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->putString($this->deviceId);
|
$this->putString($this->deviceId);
|
||||||
|
$this->putLInt($this->buildPlatform);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(PacketHandler $handler) : bool{
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
78
src/network/mcpe/protocol/AnvilDamagePacket.php
Normal file
78
src/network/mcpe/protocol/AnvilDamagePacket.php
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?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\handler\PacketHandler;
|
||||||
|
|
||||||
|
class AnvilDamagePacket extends DataPacket implements ServerboundPacket{
|
||||||
|
public const NETWORK_ID = ProtocolInfo::ANVIL_DAMAGE_PACKET;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $x;
|
||||||
|
/** @var int */
|
||||||
|
private $y;
|
||||||
|
/** @var int */
|
||||||
|
private $z;
|
||||||
|
/** @var int */
|
||||||
|
private $damageAmount;
|
||||||
|
|
||||||
|
public static function create(int $x, int $y, int $z, int $damageAmount) : self{
|
||||||
|
$result = new self;
|
||||||
|
[$result->x, $result->y, $result->z] = [$x, $y, $z];
|
||||||
|
$result->damageAmount = $damageAmount;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDamageAmount() : int{
|
||||||
|
return $this->damageAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getX() : int{
|
||||||
|
return $this->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getY() : int{
|
||||||
|
return $this->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getZ() : int{
|
||||||
|
return $this->z;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function decodePayload() : void{
|
||||||
|
$this->damageAmount = $this->getByte();
|
||||||
|
$this->getBlockPosition($this->x, $this->y, $this->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function encodePayload() : void{
|
||||||
|
$this->putByte($this->damageAmount);
|
||||||
|
$this->putBlockPosition($this->x, $this->y, $this->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
return $handler->handleAnvilDamage($this);
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
@ -29,6 +29,7 @@ use pocketmine\network\BadPacketException;
|
|||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
use pocketmine\network\mcpe\protocol\types\command\CommandData;
|
use pocketmine\network\mcpe\protocol\types\command\CommandData;
|
||||||
use pocketmine\network\mcpe\protocol\types\command\CommandEnum;
|
use pocketmine\network\mcpe\protocol\types\command\CommandEnum;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\command\CommandEnumConstraint;
|
||||||
use pocketmine\network\mcpe\protocol\types\command\CommandParameter;
|
use pocketmine\network\mcpe\protocol\types\command\CommandParameter;
|
||||||
use pocketmine\utils\BinaryDataException;
|
use pocketmine\utils\BinaryDataException;
|
||||||
use function count;
|
use function count;
|
||||||
@ -57,17 +58,17 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
|
|||||||
|
|
||||||
public const ARG_TYPE_FILEPATH = 0x0e;
|
public const ARG_TYPE_FILEPATH = 0x0e;
|
||||||
|
|
||||||
public const ARG_TYPE_STRING = 0x1b;
|
public const ARG_TYPE_STRING = 0x1d;
|
||||||
|
|
||||||
public const ARG_TYPE_POSITION = 0x1d;
|
public const ARG_TYPE_POSITION = 0x25;
|
||||||
|
|
||||||
public const ARG_TYPE_MESSAGE = 0x20;
|
public const ARG_TYPE_MESSAGE = 0x29;
|
||||||
|
|
||||||
public const ARG_TYPE_RAWTEXT = 0x22;
|
public const ARG_TYPE_RAWTEXT = 0x2b;
|
||||||
|
|
||||||
public const ARG_TYPE_JSON = 0x25;
|
public const ARG_TYPE_JSON = 0x2f;
|
||||||
|
|
||||||
public const ARG_TYPE_COMMAND = 0x2c;
|
public const ARG_TYPE_COMMAND = 0x36;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enums are a little different: they are composed as follows:
|
* Enums are a little different: they are composed as follows:
|
||||||
@ -80,12 +81,23 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
|
|||||||
*/
|
*/
|
||||||
public const ARG_FLAG_POSTFIX = 0x1000000;
|
public const ARG_FLAG_POSTFIX = 0x1000000;
|
||||||
|
|
||||||
|
public const HARDCODED_ENUM_NAMES = [
|
||||||
|
"CommandName" => true
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var CommandData[]
|
* @var CommandData[]
|
||||||
* List of command data, including name, description, alias indexes and parameters.
|
* List of command data, including name, description, alias indexes and parameters.
|
||||||
*/
|
*/
|
||||||
public $commandData = [];
|
public $commandData = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var CommandEnum[]
|
||||||
|
* List of enums which aren't directly referenced by any vanilla command.
|
||||||
|
* This is used for the `CommandName` enum, which is a magic enum used by the `command` argument type.
|
||||||
|
*/
|
||||||
|
public $hardcodedEnums = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var CommandEnum[]
|
* @var CommandEnum[]
|
||||||
* List of dynamic command enums, also referred to as "soft" enums. These can by dynamically updated mid-game
|
* List of dynamic command enums, also referred to as "soft" enums. These can by dynamically updated mid-game
|
||||||
@ -93,6 +105,12 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
|
|||||||
*/
|
*/
|
||||||
public $softEnums = [];
|
public $softEnums = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var CommandEnumConstraint[]
|
||||||
|
* List of constraints for enum members. Used to constrain gamerules that can bechanged in nocheats mode and more.
|
||||||
|
*/
|
||||||
|
public $enumConstraints = [];
|
||||||
|
|
||||||
protected function decodePayload() : void{
|
protected function decodePayload() : void{
|
||||||
/** @var string[] $enumValues */
|
/** @var string[] $enumValues */
|
||||||
$enumValues = [];
|
$enumValues = [];
|
||||||
@ -109,7 +127,10 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
|
|||||||
/** @var CommandEnum[] $enums */
|
/** @var CommandEnum[] $enums */
|
||||||
$enums = [];
|
$enums = [];
|
||||||
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||||
$enums[] = $this->getEnum($enumValues);
|
$enums[] = $enum = $this->getEnum($enumValues);
|
||||||
|
if(isset(self::HARDCODED_ENUM_NAMES[$enum->getName()])){
|
||||||
|
$this->hardcodedEnums[] = $enum;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||||
@ -119,6 +140,10 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
|
|||||||
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||||
$this->softEnums[] = $this->getSoftEnum();
|
$this->softEnums[] = $this->getSoftEnum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||||
|
$this->enumConstraints[] = $this->getEnumConstraint($enums, $enumValues);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -217,6 +242,52 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param CommandEnum[] $enums
|
||||||
|
* @param string[] $enumValues
|
||||||
|
*
|
||||||
|
* @return CommandEnumConstraint
|
||||||
|
* @throws BadPacketException
|
||||||
|
* @throws BinaryDataException
|
||||||
|
*/
|
||||||
|
protected function getEnumConstraint(array $enums, array $enumValues) : CommandEnumConstraint{
|
||||||
|
//wtf, what was wrong with an offset inside the enum? :(
|
||||||
|
$valueIndex = $this->getLInt();
|
||||||
|
if(!isset($enumValues[$valueIndex])){
|
||||||
|
throw new BadPacketException("Enum constraint refers to unknown enum value index $valueIndex");
|
||||||
|
}
|
||||||
|
$enumIndex = $this->getLInt();
|
||||||
|
if(!isset($enums[$enumIndex])){
|
||||||
|
throw new BadPacketException("Enum constraint refers to unknown enum index $enumIndex");
|
||||||
|
}
|
||||||
|
$enum = $enums[$enumIndex];
|
||||||
|
$valueOffset = array_search($enumValues[$valueIndex], $enum->getValues(), true);
|
||||||
|
if($valueOffset === false){
|
||||||
|
throw new BadPacketException("Value \"" . $enumValues[$valueIndex] . "\" does not belong to enum \"" . $enum->getName() . "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
$constraintIds = [];
|
||||||
|
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||||
|
$constraintIds[] = $this->getByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommandEnumConstraint($enum, $valueOffset, $constraintIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param CommandEnumConstraint $constraint
|
||||||
|
* @param int[] $enumIndexes string enum name -> int index
|
||||||
|
* @param int[] $enumValueIndexes string value -> int index
|
||||||
|
*/
|
||||||
|
protected function putEnumConstraint(CommandEnumConstraint $constraint, array $enumIndexes, array $enumValueIndexes) : void{
|
||||||
|
$this->putLInt($enumValueIndexes[$constraint->getAffectedValue()]);
|
||||||
|
$this->putLInt($enumIndexes[$constraint->getEnum()->getName()]);
|
||||||
|
$this->putUnsignedVarInt(count($constraint->getConstraints()));
|
||||||
|
foreach($constraint->getConstraints() as $v){
|
||||||
|
$this->putByte($v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CommandEnum[] $enums
|
* @param CommandEnum[] $enums
|
||||||
* @param string[] $postfixes
|
* @param string[] $postfixes
|
||||||
@ -365,6 +436,9 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
|
|||||||
$enumValueIndexes[$str] = $enumValueIndexes[$str] ?? count($enumValueIndexes); //latest index
|
$enumValueIndexes[$str] = $enumValueIndexes[$str] ?? count($enumValueIndexes); //latest index
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
foreach($this->hardcodedEnums as $enum){
|
||||||
|
$addEnumFn($enum);
|
||||||
|
}
|
||||||
foreach($this->commandData as $commandData){
|
foreach($this->commandData as $commandData){
|
||||||
if($commandData->aliases !== null){
|
if($commandData->aliases !== null){
|
||||||
$addEnumFn($commandData->aliases);
|
$addEnumFn($commandData->aliases);
|
||||||
@ -408,6 +482,11 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
|
|||||||
foreach($this->softEnums as $enum){
|
foreach($this->softEnums as $enum){
|
||||||
$this->putSoftEnum($enum);
|
$this->putSoftEnum($enum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->putUnsignedVarInt(count($this->enumConstraints));
|
||||||
|
foreach($this->enumConstraints as $constraint){
|
||||||
|
$this->putEnumConstraint($constraint, $enumIndexes, $enumValueIndexes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(PacketHandler $handler) : bool{
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
@ -26,11 +26,14 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
#include <rules/DataPacket.h>
|
#include <rules/DataPacket.h>
|
||||||
|
|
||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
|
use function file_get_contents;
|
||||||
|
|
||||||
class BiomeDefinitionListPacket extends DataPacket implements ClientboundPacket{
|
class BiomeDefinitionListPacket extends DataPacket implements ClientboundPacket{
|
||||||
public const NETWORK_ID = ProtocolInfo::BIOME_DEFINITION_LIST_PACKET;
|
public const NETWORK_ID = ProtocolInfo::BIOME_DEFINITION_LIST_PACKET;
|
||||||
|
|
||||||
public const HARDCODED_NBT_BLOB = "CgAKDWJhbWJvb19qdW5nbGUFCGRvd25mYWxsZmZmPwULdGVtcGVyYXR1cmUzM3M/AAoTYmFtYm9vX2p1bmdsZV9oaWxscwUIZG93bmZhbGxmZmY/BQt0ZW1wZXJhdHVyZTMzcz8ACgViZWFjaAUIZG93bmZhbGzNzMw+BQt0ZW1wZXJhdHVyZc3MTD8ACgxiaXJjaF9mb3Jlc3QFCGRvd25mYWxsmpkZPwULdGVtcGVyYXR1cmWamRk/AAoSYmlyY2hfZm9yZXN0X2hpbGxzBQhkb3duZmFsbJqZGT8FC3RlbXBlcmF0dXJlmpkZPwAKGmJpcmNoX2ZvcmVzdF9oaWxsc19tdXRhdGVkBQhkb3duZmFsbM3MTD8FC3RlbXBlcmF0dXJlMzMzPwAKFGJpcmNoX2ZvcmVzdF9tdXRhdGVkBQhkb3duZmFsbM3MTD8FC3RlbXBlcmF0dXJlMzMzPwAKCmNvbGRfYmVhY2gFCGRvd25mYWxsmpmZPgULdGVtcGVyYXR1cmXNzEw9AAoKY29sZF9vY2VhbgUIZG93bmZhbGwAAAA/BQt0ZW1wZXJhdHVyZQAAAD8ACgpjb2xkX3RhaWdhBQhkb3duZmFsbM3MzD4FC3RlbXBlcmF0dXJlAAAAvwAKEGNvbGRfdGFpZ2FfaGlsbHMFCGRvd25mYWxszczMPgULdGVtcGVyYXR1cmUAAAC/AAoSY29sZF90YWlnYV9tdXRhdGVkBQhkb3duZmFsbM3MzD4FC3RlbXBlcmF0dXJlAAAAvwAKD2RlZXBfY29sZF9vY2VhbgUIZG93bmZhbGwAAAA/BQt0ZW1wZXJhdHVyZQAAAD8AChFkZWVwX2Zyb3plbl9vY2VhbgUIZG93bmZhbGwAAAA/BQt0ZW1wZXJhdHVyZQAAAAAAChNkZWVwX2x1a2V3YXJtX29jZWFuBQhkb3duZmFsbAAAAD8FC3RlbXBlcmF0dXJlAAAAPwAKCmRlZXBfb2NlYW4FCGRvd25mYWxsAAAAPwULdGVtcGVyYXR1cmUAAAA/AAoPZGVlcF93YXJtX29jZWFuBQhkb3duZmFsbAAAAD8FC3RlbXBlcmF0dXJlAAAAPwAKBmRlc2VydAUIZG93bmZhbGwAAAAABQt0ZW1wZXJhdHVyZQAAAEAACgxkZXNlcnRfaGlsbHMFCGRvd25mYWxsAAAAAAULdGVtcGVyYXR1cmUAAABAAAoOZGVzZXJ0X211dGF0ZWQFCGRvd25mYWxsAAAAAAULdGVtcGVyYXR1cmUAAABAAAoNZXh0cmVtZV9oaWxscwUIZG93bmZhbGyamZk+BQt0ZW1wZXJhdHVyZc3MTD4AChJleHRyZW1lX2hpbGxzX2VkZ2UFCGRvd25mYWxsmpmZPgULdGVtcGVyYXR1cmXNzEw+AAoVZXh0cmVtZV9oaWxsc19tdXRhdGVkBQhkb3duZmFsbJqZmT4FC3RlbXBlcmF0dXJlzcxMPgAKGGV4dHJlbWVfaGlsbHNfcGx1c190cmVlcwUIZG93bmZhbGyamZk+BQt0ZW1wZXJhdHVyZc3MTD4ACiBleHRyZW1lX2hpbGxzX3BsdXNfdHJlZXNfbXV0YXRlZAUIZG93bmZhbGyamZk+BQt0ZW1wZXJhdHVyZc3MTD4ACg1mbG93ZXJfZm9yZXN0BQhkb3duZmFsbM3MTD8FC3RlbXBlcmF0dXJlMzMzPwAKBmZvcmVzdAUIZG93bmZhbGzNzEw/BQt0ZW1wZXJhdHVyZTMzMz8ACgxmb3Jlc3RfaGlsbHMFCGRvd25mYWxszcxMPwULdGVtcGVyYXR1cmUzMzM/AAoMZnJvemVuX29jZWFuBQhkb3duZmFsbAAAAD8FC3RlbXBlcmF0dXJlAAAAAAAKDGZyb3plbl9yaXZlcgUIZG93bmZhbGwAAAA/BQt0ZW1wZXJhdHVyZQAAAAAACgRoZWxsBQhkb3duZmFsbAAAAAAFC3RlbXBlcmF0dXJlAAAAQAAKDWljZV9tb3VudGFpbnMFCGRvd25mYWxsAAAAPwULdGVtcGVyYXR1cmUAAAAAAAoKaWNlX3BsYWlucwUIZG93bmZhbGwAAAA/BQt0ZW1wZXJhdHVyZQAAAAAAChFpY2VfcGxhaW5zX3NwaWtlcwUIZG93bmZhbGwAAIA/BQt0ZW1wZXJhdHVyZQAAAAAACgZqdW5nbGUFCGRvd25mYWxsZmZmPwULdGVtcGVyYXR1cmUzM3M/AAoLanVuZ2xlX2VkZ2UFCGRvd25mYWxszcxMPwULdGVtcGVyYXR1cmUzM3M/AAoTanVuZ2xlX2VkZ2VfbXV0YXRlZAUIZG93bmZhbGzNzEw/BQt0ZW1wZXJhdHVyZTMzcz8ACgxqdW5nbGVfaGlsbHMFCGRvd25mYWxsZmZmPwULdGVtcGVyYXR1cmUzM3M/AAoOanVuZ2xlX211dGF0ZWQFCGRvd25mYWxsZmZmPwULdGVtcGVyYXR1cmUzM3M/AAoTbGVnYWN5X2Zyb3plbl9vY2VhbgUIZG93bmZhbGwAAAA/BQt0ZW1wZXJhdHVyZQAAAAAACg5sdWtld2FybV9vY2VhbgUIZG93bmZhbGwAAAA/BQt0ZW1wZXJhdHVyZQAAAD8ACgptZWdhX3RhaWdhBQhkb3duZmFsbM3MTD8FC3RlbXBlcmF0dXJlmpmZPgAKEG1lZ2FfdGFpZ2FfaGlsbHMFCGRvd25mYWxszcxMPwULdGVtcGVyYXR1cmWamZk+AAoEbWVzYQUIZG93bmZhbGwAAAAABQt0ZW1wZXJhdHVyZQAAAEAACgptZXNhX2JyeWNlBQhkb3duZmFsbAAAAAAFC3RlbXBlcmF0dXJlAAAAQAAKDG1lc2FfcGxhdGVhdQUIZG93bmZhbGwAAAAABQt0ZW1wZXJhdHVyZQAAAEAAChRtZXNhX3BsYXRlYXVfbXV0YXRlZAUIZG93bmZhbGwAAAAABQt0ZW1wZXJhdHVyZQAAAEAAChJtZXNhX3BsYXRlYXVfc3RvbmUFCGRvd25mYWxsAAAAAAULdGVtcGVyYXR1cmUAAABAAAoabWVzYV9wbGF0ZWF1X3N0b25lX211dGF0ZWQFCGRvd25mYWxsAAAAAAULdGVtcGVyYXR1cmUAAABAAAoPbXVzaHJvb21faXNsYW5kBQhkb3duZmFsbAAAgD8FC3RlbXBlcmF0dXJlZmZmPwAKFW11c2hyb29tX2lzbGFuZF9zaG9yZQUIZG93bmZhbGwAAIA/BQt0ZW1wZXJhdHVyZWZmZj8ACgVvY2VhbgUIZG93bmZhbGwAAAA/BQt0ZW1wZXJhdHVyZQAAAD8ACgZwbGFpbnMFCGRvd25mYWxszczMPgULdGVtcGVyYXR1cmXNzEw/AAobcmVkd29vZF90YWlnYV9oaWxsc19tdXRhdGVkBQhkb3duZmFsbM3MTD8FC3RlbXBlcmF0dXJlmpmZPgAKFXJlZHdvb2RfdGFpZ2FfbXV0YXRlZAUIZG93bmZhbGzNzEw/BQt0ZW1wZXJhdHVyZQAAgD4ACgVyaXZlcgUIZG93bmZhbGwAAAA/BQt0ZW1wZXJhdHVyZQAAAD8ACg1yb29mZWRfZm9yZXN0BQhkb3duZmFsbM3MTD8FC3RlbXBlcmF0dXJlMzMzPwAKFXJvb2ZlZF9mb3Jlc3RfbXV0YXRlZAUIZG93bmZhbGzNzEw/BQt0ZW1wZXJhdHVyZTMzMz8ACgdzYXZhbm5hBQhkb3duZmFsbAAAAAAFC3RlbXBlcmF0dXJlmpmZPwAKD3NhdmFubmFfbXV0YXRlZAUIZG93bmZhbGwAAAA/BQt0ZW1wZXJhdHVyZc3MjD8ACg9zYXZhbm5hX3BsYXRlYXUFCGRvd25mYWxsAAAAAAULdGVtcGVyYXR1cmUAAIA/AAoXc2F2YW5uYV9wbGF0ZWF1X211dGF0ZWQFCGRvd25mYWxsAAAAPwULdGVtcGVyYXR1cmUAAIA/AAoLc3RvbmVfYmVhY2gFCGRvd25mYWxsmpmZPgULdGVtcGVyYXR1cmXNzEw+AAoQc3VuZmxvd2VyX3BsYWlucwUIZG93bmZhbGzNzMw+BQt0ZW1wZXJhdHVyZc3MTD8ACglzd2FtcGxhbmQFCGRvd25mYWxsAAAAPwULdGVtcGVyYXR1cmXNzEw/AAoRc3dhbXBsYW5kX211dGF0ZWQFCGRvd25mYWxsAAAAPwULdGVtcGVyYXR1cmXNzEw/AAoFdGFpZ2EFCGRvd25mYWxszcxMPwULdGVtcGVyYXR1cmUAAIA+AAoLdGFpZ2FfaGlsbHMFCGRvd25mYWxszcxMPwULdGVtcGVyYXR1cmUAAIA+AAoNdGFpZ2FfbXV0YXRlZAUIZG93bmZhbGzNzEw/BQt0ZW1wZXJhdHVyZQAAgD4ACgd0aGVfZW5kBQhkb3duZmFsbAAAAD8FC3RlbXBlcmF0dXJlAAAAPwAKCndhcm1fb2NlYW4FCGRvd25mYWxsAAAAPwULdGVtcGVyYXR1cmUAAAA/AAA=";
|
/** @var string|null */
|
||||||
|
private static $DEFAULT_NBT_CACHE = null;
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $namedtag;
|
public $namedtag;
|
||||||
|
|
||||||
@ -39,7 +42,11 @@ class BiomeDefinitionListPacket extends DataPacket implements ClientboundPacket{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function encodePayload() : void{
|
protected function encodePayload() : void{
|
||||||
$this->put($this->namedtag ?? self::HARDCODED_NBT_BLOB);
|
$this->put(
|
||||||
|
$this->namedtag ??
|
||||||
|
self::$DEFAULT_NBT_CACHE ??
|
||||||
|
(self::$DEFAULT_NBT_CACHE = file_get_contents(\pocketmine\RESOURCE_PATH . '/vanilla/biome_definitions.nbt'))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(PacketHandler $handler) : bool{
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
66
src/network/mcpe/protocol/CompletedUsingItemPacket.php
Normal file
66
src/network/mcpe/protocol/CompletedUsingItemPacket.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
|
|
||||||
|
class CompletedUsingItemPacket extends DataPacket implements ClientboundPacket{
|
||||||
|
public const NETWORK_ID = ProtocolInfo::COMPLETED_USING_ITEM_PACKET;
|
||||||
|
|
||||||
|
public const ACTION_UNKNOWN = -1;
|
||||||
|
public const ACTION_EQUIP_ARMOR = 0;
|
||||||
|
public const ACTION_EAT = 1;
|
||||||
|
public const ACTION_ATTACK = 2;
|
||||||
|
public const ACTION_CONSUME = 3;
|
||||||
|
public const ACTION_THROW = 4;
|
||||||
|
public const ACTION_SHOOT = 5;
|
||||||
|
public const ACTION_PLACE = 6;
|
||||||
|
public const ACTION_FILL_BOTTLE = 7;
|
||||||
|
public const ACTION_FILL_BUCKET = 8;
|
||||||
|
public const ACTION_POUR_BUCKET = 9;
|
||||||
|
public const ACTION_USE_TOOL = 10;
|
||||||
|
public const ACTION_INTERACT = 11;
|
||||||
|
public const ACTION_RETRIEVED = 12;
|
||||||
|
public const ACTION_DYED = 13;
|
||||||
|
public const ACTION_TRADED = 14;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
public $itemId;
|
||||||
|
/** @var int */
|
||||||
|
public $action;
|
||||||
|
|
||||||
|
public function decodePayload() : void{
|
||||||
|
$this->itemId = $this->getShort();
|
||||||
|
$this->action = $this->getLInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encodePayload() : void{
|
||||||
|
$this->putShort($this->itemId);
|
||||||
|
$this->putLInt($this->action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
return $handler->handleCompletedUsingItem($this);
|
||||||
|
}
|
||||||
|
}
|
@ -33,6 +33,8 @@ use pocketmine\item\Item;
|
|||||||
use pocketmine\item\ItemFactory;
|
use pocketmine\item\ItemFactory;
|
||||||
use pocketmine\network\BadPacketException;
|
use pocketmine\network\BadPacketException;
|
||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\PotionContainerChangeRecipe;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\PotionTypeRecipe;
|
||||||
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
||||||
#ifndef COMPILE
|
#ifndef COMPILE
|
||||||
use pocketmine\utils\Binary;
|
use pocketmine\utils\Binary;
|
||||||
@ -54,6 +56,10 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{
|
|||||||
|
|
||||||
/** @var object[] */
|
/** @var object[] */
|
||||||
public $entries = [];
|
public $entries = [];
|
||||||
|
/** @var PotionTypeRecipe[] */
|
||||||
|
public $potionTypeRecipes = [];
|
||||||
|
/** @var PotionContainerChangeRecipe[] */
|
||||||
|
public $potionContainerRecipes = [];
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $cleanRecipes = false;
|
public $cleanRecipes = false;
|
||||||
|
|
||||||
@ -139,6 +145,18 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{
|
|||||||
}
|
}
|
||||||
$this->decodedEntries[] = $entry;
|
$this->decodedEntries[] = $entry;
|
||||||
}
|
}
|
||||||
|
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||||
|
$input = $this->getVarInt();
|
||||||
|
$ingredient = $this->getVarInt();
|
||||||
|
$output = $this->getVarInt();
|
||||||
|
$this->potionTypeRecipes[] = new PotionTypeRecipe($input, $ingredient, $output);
|
||||||
|
}
|
||||||
|
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||||
|
$input = $this->getVarInt();
|
||||||
|
$ingredient = $this->getVarInt();
|
||||||
|
$output = $this->getVarInt();
|
||||||
|
$this->potionContainerRecipes[] = new PotionContainerChangeRecipe($input, $ingredient, $output);
|
||||||
|
}
|
||||||
$this->cleanRecipes = $this->getBool();
|
$this->cleanRecipes = $this->getBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,6 +257,18 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{
|
|||||||
|
|
||||||
$writer->reset();
|
$writer->reset();
|
||||||
}
|
}
|
||||||
|
$this->putUnsignedVarInt(count($this->potionTypeRecipes));
|
||||||
|
foreach($this->potionTypeRecipes as $recipe){
|
||||||
|
$this->putVarInt($recipe->getInputPotionType());
|
||||||
|
$this->putVarInt($recipe->getIngredientItemId());
|
||||||
|
$this->putVarInt($recipe->getOutputPotionType());
|
||||||
|
}
|
||||||
|
$this->putUnsignedVarInt(count($this->potionContainerRecipes));
|
||||||
|
foreach($this->potionContainerRecipes as $recipe){
|
||||||
|
$this->putVarInt($recipe->getInputItemId());
|
||||||
|
$this->putVarInt($recipe->getIngredientItemId());
|
||||||
|
$this->putVarInt($recipe->getOutputItemId());
|
||||||
|
}
|
||||||
|
|
||||||
$this->putBool($this->cleanRecipes);
|
$this->putBool($this->cleanRecipes);
|
||||||
}
|
}
|
||||||
|
66
src/network/mcpe/protocol/EducationSettingsPacket.php
Normal file
66
src/network/mcpe/protocol/EducationSettingsPacket.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?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\handler\PacketHandler;
|
||||||
|
|
||||||
|
class EducationSettingsPacket extends DataPacket implements ClientboundPacket{
|
||||||
|
public const NETWORK_ID = ProtocolInfo::EDUCATION_SETTINGS_PACKET;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
private $codeBuilderDefaultUri;
|
||||||
|
/** @var bool */
|
||||||
|
private $hasQuiz;
|
||||||
|
|
||||||
|
public static function create(string $codeBuilderDefaultUri, bool $hasQuiz) : self{
|
||||||
|
$result = new self;
|
||||||
|
$result->codeBuilderDefaultUri = $codeBuilderDefaultUri;
|
||||||
|
$result->hasQuiz = $hasQuiz;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCodeBuilderDefaultUri() : string{
|
||||||
|
return $this->codeBuilderDefaultUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHasQuiz() : bool{
|
||||||
|
return $this->hasQuiz;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function decodePayload() : void{
|
||||||
|
$this->codeBuilderDefaultUri = $this->getString();
|
||||||
|
$this->hasQuiz = $this->getBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function encodePayload() : void{
|
||||||
|
$this->putString($this->codeBuilderDefaultUri);
|
||||||
|
$this->putBool($this->hasQuiz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
return $handler->handleEducationSettings($this);
|
||||||
|
}
|
||||||
|
}
|
81
src/network/mcpe/protocol/EmotePacket.php
Normal file
81
src/network/mcpe/protocol/EmotePacket.php
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<?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\handler\PacketHandler;
|
||||||
|
|
||||||
|
class EmotePacket extends DataPacket implements ClientboundPacket, ServerboundPacket{
|
||||||
|
public const NETWORK_ID = ProtocolInfo::EMOTE_PACKET;
|
||||||
|
|
||||||
|
private const FLAG_SERVER = 1 << 0;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $entityRuntimeId;
|
||||||
|
/** @var string */
|
||||||
|
private $emoteId;
|
||||||
|
/** @var int */
|
||||||
|
private $flags;
|
||||||
|
|
||||||
|
public static function create(int $entityRuntimeId, string $emoteId, int $flags) : self{
|
||||||
|
$result = new self;
|
||||||
|
$result->entityRuntimeId = $entityRuntimeId;
|
||||||
|
$result->emoteId = $emoteId;
|
||||||
|
$result->flags = $flags;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: we can't call this getEntityRuntimeId() because of base class collision (crap architecture, thanks Shoghi)
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getEntityRuntimeIdField() : int{
|
||||||
|
return $this->entityRuntimeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEmoteId() : string{
|
||||||
|
return $this->emoteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFlags() : int{
|
||||||
|
return $this->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function decodePayload() : void{
|
||||||
|
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
||||||
|
$this->emoteId = $this->getString();
|
||||||
|
$this->flags = $this->getByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function encodePayload() : void{
|
||||||
|
$this->putEntityRuntimeId($this->entityRuntimeId);
|
||||||
|
$this->putString($this->emoteId);
|
||||||
|
$this->putByte($this->flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
return $handler->handleEmote($this);
|
||||||
|
}
|
||||||
|
}
|
@ -1,83 +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;
|
|
||||||
|
|
||||||
#include <rules/DataPacket.h>
|
|
||||||
|
|
||||||
|
|
||||||
use pocketmine\math\Vector3;
|
|
||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
|
||||||
use function count;
|
|
||||||
|
|
||||||
class ExplodePacket extends DataPacket implements ClientboundPacket{
|
|
||||||
public const NETWORK_ID = ProtocolInfo::EXPLODE_PACKET;
|
|
||||||
|
|
||||||
/** @var Vector3 */
|
|
||||||
public $position;
|
|
||||||
/** @var float */
|
|
||||||
public $radius;
|
|
||||||
/** @var Vector3[] */
|
|
||||||
public $records = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Vector3 $center
|
|
||||||
* @param float $radius
|
|
||||||
* @param Vector3[] $records
|
|
||||||
*
|
|
||||||
* @return ExplodePacket
|
|
||||||
*/
|
|
||||||
public static function create(Vector3 $center, float $radius, array $records) : self{
|
|
||||||
$result = new self;
|
|
||||||
$result->position = $center;
|
|
||||||
$result->radius = $radius;
|
|
||||||
$result->records = $records;
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function decodePayload() : void{
|
|
||||||
$this->position = $this->getVector3();
|
|
||||||
$this->radius = (float) ($this->getVarInt() / 32);
|
|
||||||
$count = $this->getUnsignedVarInt();
|
|
||||||
for($i = 0; $i < $count; ++$i){
|
|
||||||
$x = $y = $z = null;
|
|
||||||
$this->getSignedBlockPosition($x, $y, $z);
|
|
||||||
$this->records[$i] = new Vector3($x, $y, $z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function encodePayload() : void{
|
|
||||||
$this->putVector3($this->position);
|
|
||||||
$this->putVarInt((int) ($this->radius * 32));
|
|
||||||
$this->putUnsignedVarInt(count($this->records));
|
|
||||||
if(count($this->records) > 0){
|
|
||||||
foreach($this->records as $record){
|
|
||||||
$this->putSignedBlockPosition((int) $record->x, (int) $record->y, (int) $record->z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(PacketHandler $handler) : bool{
|
|
||||||
return $handler->handleExplode($this);
|
|
||||||
}
|
|
||||||
}
|
|
@ -52,11 +52,32 @@ class LoginPacket extends DataPacket implements ServerboundPacket{
|
|||||||
public const I_SERVER_ADDRESS = 'ServerAddress';
|
public const I_SERVER_ADDRESS = 'ServerAddress';
|
||||||
public const I_LANGUAGE_CODE = 'LanguageCode';
|
public const I_LANGUAGE_CODE = 'LanguageCode';
|
||||||
|
|
||||||
|
public const I_SKIN_RESOURCE_PATCH = 'SkinResourcePatch';
|
||||||
|
|
||||||
public const I_SKIN_ID = 'SkinId';
|
public const I_SKIN_ID = 'SkinId';
|
||||||
|
public const I_SKIN_HEIGHT = 'SkinImageHeight';
|
||||||
|
public const I_SKIN_WIDTH = 'SkinImageWidth';
|
||||||
public const I_SKIN_DATA = 'SkinData';
|
public const I_SKIN_DATA = 'SkinData';
|
||||||
|
|
||||||
|
public const I_CAPE_ID = 'CapeId';
|
||||||
|
public const I_CAPE_HEIGHT = 'CapeImageHeight';
|
||||||
|
public const I_CAPE_WIDTH = 'CapeImageWidth';
|
||||||
public const I_CAPE_DATA = 'CapeData';
|
public const I_CAPE_DATA = 'CapeData';
|
||||||
public const I_GEOMETRY_NAME = 'SkinGeometryName';
|
|
||||||
public const I_GEOMETRY_DATA = 'SkinGeometry';
|
public const I_GEOMETRY_DATA = 'SkinGeometryData';
|
||||||
|
|
||||||
|
public const I_ANIMATION_DATA = 'SkinAnimationData';
|
||||||
|
public const I_ANIMATION_IMAGES = 'AnimatedImageData';
|
||||||
|
|
||||||
|
public const I_ANIMATION_IMAGE_HEIGHT = 'ImageHeight';
|
||||||
|
public const I_ANIMATION_IMAGE_WIDTH = 'ImageWidth';
|
||||||
|
public const I_ANIMATION_IMAGE_FRAMES = 'Frames';
|
||||||
|
public const I_ANIMATION_IMAGE_TYPE = 'Type';
|
||||||
|
public const I_ANIMATION_IMAGE_DATA = 'Image';
|
||||||
|
|
||||||
|
public const I_PREMIUM_SKIN = 'PremiumSkin';
|
||||||
|
public const I_PERSONA_SKIN = 'PersonaSkin';
|
||||||
|
public const I_PERSONA_CAPE_ON_CLASSIC_SKIN = 'CapeOnClassicSkin';
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public $protocol;
|
public $protocol;
|
||||||
@ -164,11 +185,32 @@ class LoginPacket extends DataPacket implements ServerboundPacket{
|
|||||||
$v->required(self::I_SERVER_ADDRESS)->string();
|
$v->required(self::I_SERVER_ADDRESS)->string();
|
||||||
$v->required(self::I_LANGUAGE_CODE)->string();
|
$v->required(self::I_LANGUAGE_CODE)->string();
|
||||||
|
|
||||||
|
$v->required(self::I_SKIN_RESOURCE_PATCH)->string();
|
||||||
|
|
||||||
$v->required(self::I_SKIN_ID)->string();
|
$v->required(self::I_SKIN_ID)->string();
|
||||||
$v->required(self::I_SKIN_DATA)->string();
|
$v->required(self::I_SKIN_DATA)->string();
|
||||||
|
$v->required(self::I_SKIN_HEIGHT)->integer(true);
|
||||||
|
$v->required(self::I_SKIN_WIDTH)->integer(true);
|
||||||
|
|
||||||
|
$v->required(self::I_CAPE_ID, null, true)->string();
|
||||||
$v->required(self::I_CAPE_DATA, null, true)->string();
|
$v->required(self::I_CAPE_DATA, null, true)->string();
|
||||||
$v->required(self::I_GEOMETRY_NAME)->string();
|
$v->required(self::I_CAPE_HEIGHT)->integer(true);
|
||||||
|
$v->required(self::I_CAPE_WIDTH)->integer(true);
|
||||||
|
|
||||||
$v->required(self::I_GEOMETRY_DATA, null, true)->string();
|
$v->required(self::I_GEOMETRY_DATA, null, true)->string();
|
||||||
|
|
||||||
|
$v->required(self::I_ANIMATION_DATA, null, true)->string();
|
||||||
|
$v->required(self::I_ANIMATION_IMAGES, null, true)->isArray()->each(function(Validator $vSub) : void{
|
||||||
|
$vSub->required(self::I_ANIMATION_IMAGE_HEIGHT)->integer(true);
|
||||||
|
$vSub->required(self::I_ANIMATION_IMAGE_WIDTH)->integer(true);
|
||||||
|
$vSub->required(self::I_ANIMATION_IMAGE_FRAMES)->numeric(); //float() doesn't accept ints ???
|
||||||
|
$vSub->required(self::I_ANIMATION_IMAGE_TYPE)->integer(true);
|
||||||
|
$vSub->required(self::I_ANIMATION_IMAGE_DATA)->string();
|
||||||
|
});
|
||||||
|
$v->required(self::I_PREMIUM_SKIN)->bool();
|
||||||
|
$v->required(self::I_PERSONA_SKIN)->bool();
|
||||||
|
$v->required(self::I_PERSONA_CAPE_ON_CLASSIC_SKIN)->bool();
|
||||||
|
|
||||||
self::validate($v, 'clientData', $clientData);
|
self::validate($v, 'clientData', $clientData);
|
||||||
|
|
||||||
$this->clientData = $clientData;
|
$this->clientData = $clientData;
|
||||||
|
@ -83,7 +83,7 @@ class MoveActorDeltaPacket extends DataPacket implements ClientboundPacket{
|
|||||||
|
|
||||||
protected function decodePayload() : void{
|
protected function decodePayload() : void{
|
||||||
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
||||||
$this->flags = $this->getByte();
|
$this->flags = $this->getLShort();
|
||||||
$this->xDiff = $this->maybeReadCoord(self::FLAG_HAS_X);
|
$this->xDiff = $this->maybeReadCoord(self::FLAG_HAS_X);
|
||||||
$this->yDiff = $this->maybeReadCoord(self::FLAG_HAS_Y);
|
$this->yDiff = $this->maybeReadCoord(self::FLAG_HAS_Y);
|
||||||
$this->zDiff = $this->maybeReadCoord(self::FLAG_HAS_Z);
|
$this->zDiff = $this->maybeReadCoord(self::FLAG_HAS_Z);
|
||||||
@ -106,7 +106,7 @@ class MoveActorDeltaPacket extends DataPacket implements ClientboundPacket{
|
|||||||
|
|
||||||
protected function encodePayload() : void{
|
protected function encodePayload() : void{
|
||||||
$this->putEntityRuntimeId($this->entityRuntimeId);
|
$this->putEntityRuntimeId($this->entityRuntimeId);
|
||||||
$this->putByte($this->flags);
|
$this->putLShort($this->flags);
|
||||||
$this->maybeWriteCoord(self::FLAG_HAS_X, $this->xDiff);
|
$this->maybeWriteCoord(self::FLAG_HAS_X, $this->xDiff);
|
||||||
$this->maybeWriteCoord(self::FLAG_HAS_Y, $this->yDiff);
|
$this->maybeWriteCoord(self::FLAG_HAS_Y, $this->yDiff);
|
||||||
$this->maybeWriteCoord(self::FLAG_HAS_Z, $this->zDiff);
|
$this->maybeWriteCoord(self::FLAG_HAS_Z, $this->zDiff);
|
||||||
|
61
src/network/mcpe/protocol/MultiplayerSettingsPacket.php
Normal file
61
src/network/mcpe/protocol/MultiplayerSettingsPacket.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?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\handler\PacketHandler;
|
||||||
|
|
||||||
|
class MultiplayerSettingsPacket extends DataPacket implements ServerboundPacket{ //TODO: this might be clientbound too, but unsure
|
||||||
|
public const NETWORK_ID = ProtocolInfo::MULTIPLAYER_SETTINGS_PACKET;
|
||||||
|
|
||||||
|
public const ACTION_ENABLE_MULTIPLAYER = 0;
|
||||||
|
public const ACTION_DISABLE_MULTIPLAYER = 1;
|
||||||
|
public const ACTION_REFRESH_JOIN_CODE = 2;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $action;
|
||||||
|
|
||||||
|
public static function create(int $action) : self{
|
||||||
|
$result = new self;
|
||||||
|
$result->action = $action;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAction() : int{
|
||||||
|
return $this->action;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function decodePayload() : void{
|
||||||
|
$this->action = $this->getVarInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function encodePayload() : void{
|
||||||
|
$this->putVarInt($this->action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
return $handler->handleMultiplayerSettings($this);
|
||||||
|
}
|
||||||
|
}
|
60
src/network/mcpe/protocol/NetworkSettingsPacket.php
Normal file
60
src/network/mcpe/protocol/NetworkSettingsPacket.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?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\handler\PacketHandler;
|
||||||
|
|
||||||
|
class NetworkSettingsPacket extends DataPacket implements ClientboundPacket{
|
||||||
|
public const NETWORK_ID = ProtocolInfo::NETWORK_SETTINGS_PACKET;
|
||||||
|
|
||||||
|
public const COMPRESS_NOTHING = 0;
|
||||||
|
public const COMPRESS_EVERYTHING = 1;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $compressionThreshold;
|
||||||
|
|
||||||
|
public static function create(int $compressionThreshold) : self{
|
||||||
|
$result = new self;
|
||||||
|
$result->compressionThreshold = $compressionThreshold;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCompressionThreshold() : int{
|
||||||
|
return $this->compressionThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function decodePayload() : void{
|
||||||
|
$this->compressionThreshold = $this->getLShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function encodePayload() : void{
|
||||||
|
$this->putLShort($this->compressionThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
return $handler->handleNetworkSettings($this);
|
||||||
|
}
|
||||||
|
}
|
@ -54,7 +54,7 @@ class PacketPool{
|
|||||||
static::registerPacket(new RiderJumpPacket());
|
static::registerPacket(new RiderJumpPacket());
|
||||||
static::registerPacket(new UpdateBlockPacket());
|
static::registerPacket(new UpdateBlockPacket());
|
||||||
static::registerPacket(new AddPaintingPacket());
|
static::registerPacket(new AddPaintingPacket());
|
||||||
static::registerPacket(new ExplodePacket());
|
static::registerPacket(new TickSyncPacket());
|
||||||
static::registerPacket(new LevelSoundEventPacketV1());
|
static::registerPacket(new LevelSoundEventPacketV1());
|
||||||
static::registerPacket(new LevelEventPacket());
|
static::registerPacket(new LevelEventPacket());
|
||||||
static::registerPacket(new BlockEventPacket());
|
static::registerPacket(new BlockEventPacket());
|
||||||
@ -162,11 +162,19 @@ class PacketPool{
|
|||||||
static::registerPacket(new ClientCacheStatusPacket());
|
static::registerPacket(new ClientCacheStatusPacket());
|
||||||
static::registerPacket(new OnScreenTextureAnimationPacket());
|
static::registerPacket(new OnScreenTextureAnimationPacket());
|
||||||
static::registerPacket(new MapCreateLockedCopyPacket());
|
static::registerPacket(new MapCreateLockedCopyPacket());
|
||||||
static::registerPacket(new StructureTemplateDataExportRequestPacket());
|
static::registerPacket(new StructureTemplateDataRequestPacket());
|
||||||
static::registerPacket(new StructureTemplateDataExportResponsePacket());
|
static::registerPacket(new StructureTemplateDataResponsePacket());
|
||||||
static::registerPacket(new UpdateBlockPropertiesPacket());
|
static::registerPacket(new UpdateBlockPropertiesPacket());
|
||||||
static::registerPacket(new ClientCacheBlobStatusPacket());
|
static::registerPacket(new ClientCacheBlobStatusPacket());
|
||||||
static::registerPacket(new ClientCacheMissResponsePacket());
|
static::registerPacket(new ClientCacheMissResponsePacket());
|
||||||
|
static::registerPacket(new EducationSettingsPacket());
|
||||||
|
static::registerPacket(new EmotePacket());
|
||||||
|
static::registerPacket(new MultiplayerSettingsPacket());
|
||||||
|
static::registerPacket(new SettingsCommandPacket());
|
||||||
|
static::registerPacket(new AnvilDamagePacket());
|
||||||
|
static::registerPacket(new CompletedUsingItemPacket());
|
||||||
|
static::registerPacket(new NetworkSettingsPacket());
|
||||||
|
static::registerPacket(new PlayerAuthInputPacket());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
175
src/network/mcpe/protocol/PlayerAuthInputPacket.php
Normal file
175
src/network/mcpe/protocol/PlayerAuthInputPacket.php
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
<?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\handler\PacketHandler;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\InputMode;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\PlayMode;
|
||||||
|
use function assert;
|
||||||
|
|
||||||
|
class PlayerAuthInputPacket extends DataPacket implements ServerboundPacket{
|
||||||
|
public const NETWORK_ID = ProtocolInfo::PLAYER_AUTH_INPUT_PACKET;
|
||||||
|
|
||||||
|
/** @var Vector3 */
|
||||||
|
private $position;
|
||||||
|
/** @var float */
|
||||||
|
private $pitch;
|
||||||
|
/** @var float */
|
||||||
|
private $yaw;
|
||||||
|
/** @var float */
|
||||||
|
private $headYaw;
|
||||||
|
/** @var float */
|
||||||
|
private $moveVecX;
|
||||||
|
/** @var float */
|
||||||
|
private $moveVecZ;
|
||||||
|
/** @var int */
|
||||||
|
private $inputFlags;
|
||||||
|
/** @var int */
|
||||||
|
private $inputMode;
|
||||||
|
/** @var int */
|
||||||
|
private $playMode;
|
||||||
|
/** @var Vector3|null */
|
||||||
|
private $vrGazeDirection = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Vector3 $position
|
||||||
|
* @param float $pitch
|
||||||
|
* @param float $yaw
|
||||||
|
* @param float $headYaw
|
||||||
|
* @param float $moveVecX
|
||||||
|
* @param float $moveVecZ
|
||||||
|
* @param int $inputFlags
|
||||||
|
* @param int $inputMode @see InputMode
|
||||||
|
* @param int $playMode @see PlayMode
|
||||||
|
* @param Vector3|null $vrGazeDirection only used when PlayMode::VR
|
||||||
|
*
|
||||||
|
* @return 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 = null) : 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");
|
||||||
|
}
|
||||||
|
$result = new self;
|
||||||
|
$result->position = $position->asVector3();
|
||||||
|
$result->pitch = $pitch;
|
||||||
|
$result->yaw = $yaw;
|
||||||
|
$result->headYaw = $headYaw;
|
||||||
|
$result->moveVecX = $moveVecX;
|
||||||
|
$result->moveVecZ = $moveVecZ;
|
||||||
|
$result->inputFlags = $inputFlags;
|
||||||
|
$result->inputMode = $inputMode;
|
||||||
|
$result->playMode = $playMode;
|
||||||
|
if($vrGazeDirection !== null){
|
||||||
|
$this->vrGazeDirection = $vrGazeDirection->asVector3();
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPosition() : Vector3{
|
||||||
|
return $this->position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPitch() : float{
|
||||||
|
return $this->pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getYaw() : float{
|
||||||
|
return $this->yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHeadYaw() : float{
|
||||||
|
return $this->headYaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMoveVecX() : float{
|
||||||
|
return $this->moveVecX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMoveVecZ() : float{
|
||||||
|
return $this->moveVecZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInputFlags() : int{
|
||||||
|
return $this->inputFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see InputMode
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getInputMode() : int{
|
||||||
|
return $this->inputMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see PlayMode
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getPlayMode() : int{
|
||||||
|
return $this->playMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVrGazeDirection() : ?Vector3{
|
||||||
|
return $this->vrGazeDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function decodePayload() : void{
|
||||||
|
$this->yaw = $this->getLFloat();
|
||||||
|
$this->pitch = $this->getLFloat();
|
||||||
|
$this->position = $this->getVector3();
|
||||||
|
$this->moveVecX = $this->getLFloat();
|
||||||
|
$this->moveVecZ = $this->getLFloat();
|
||||||
|
$this->headYaw = $this->getLFloat();
|
||||||
|
$this->inputFlags = $this->getUnsignedVarLong();
|
||||||
|
$this->inputMode = $this->getUnsignedVarInt();
|
||||||
|
$this->playMode = $this->getUnsignedVarInt();
|
||||||
|
if($this->playMode === PlayMode::VR){
|
||||||
|
$this->vrGazeDirection = $this->getVector3();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function encodePayload() : void{
|
||||||
|
$this->putLFloat($this->yaw);
|
||||||
|
$this->putLFloat($this->pitch);
|
||||||
|
$this->putVector3($this->position);
|
||||||
|
$this->putLFloat($this->moveVecX);
|
||||||
|
$this->putLFloat($this->moveVecZ);
|
||||||
|
$this->putLFloat($this->headYaw);
|
||||||
|
$this->putUnsignedVarLong($this->inputFlags);
|
||||||
|
$this->putUnsignedVarInt($this->inputMode);
|
||||||
|
$this->putUnsignedVarInt($this->playMode);
|
||||||
|
if($this->playMode === PlayMode::VR){
|
||||||
|
assert($this->vrGazeDirection !== null);
|
||||||
|
$this->putVector3($this->vrGazeDirection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
return $handler->handlePlayerAuthInput($this);
|
||||||
|
}
|
||||||
|
}
|
@ -26,8 +26,6 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
#include <rules/DataPacket.h>
|
#include <rules/DataPacket.h>
|
||||||
|
|
||||||
|
|
||||||
use pocketmine\entity\Skin;
|
|
||||||
use pocketmine\network\BadPacketException;
|
|
||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||||
use function count;
|
use function count;
|
||||||
@ -67,26 +65,12 @@ class PlayerListPacket extends DataPacket implements ClientboundPacket{
|
|||||||
$entry->uuid = $this->getUUID();
|
$entry->uuid = $this->getUUID();
|
||||||
$entry->entityUniqueId = $this->getEntityUniqueId();
|
$entry->entityUniqueId = $this->getEntityUniqueId();
|
||||||
$entry->username = $this->getString();
|
$entry->username = $this->getString();
|
||||||
|
|
||||||
$skinId = $this->getString();
|
|
||||||
$skinData = $this->getString();
|
|
||||||
$capeData = $this->getString();
|
|
||||||
$geometryName = $this->getString();
|
|
||||||
$geometryData = $this->getString();
|
|
||||||
|
|
||||||
try{
|
|
||||||
$entry->skin = new Skin(
|
|
||||||
$skinId,
|
|
||||||
$skinData,
|
|
||||||
$capeData,
|
|
||||||
$geometryName,
|
|
||||||
$geometryData
|
|
||||||
);
|
|
||||||
}catch(\InvalidArgumentException $e){
|
|
||||||
throw new BadPacketException($e->getMessage(), 0, $e);
|
|
||||||
}
|
|
||||||
$entry->xboxUserId = $this->getString();
|
$entry->xboxUserId = $this->getString();
|
||||||
$entry->platformChatId = $this->getString();
|
$entry->platformChatId = $this->getString();
|
||||||
|
$entry->buildPlatform = $this->getLInt();
|
||||||
|
$entry->skinData = $this->getSkin();
|
||||||
|
$entry->isTeacher = $this->getBool();
|
||||||
|
$entry->isHost = $this->getBool();
|
||||||
}else{
|
}else{
|
||||||
$entry->uuid = $this->getUUID();
|
$entry->uuid = $this->getUUID();
|
||||||
}
|
}
|
||||||
@ -103,13 +87,12 @@ class PlayerListPacket extends DataPacket implements ClientboundPacket{
|
|||||||
$this->putUUID($entry->uuid);
|
$this->putUUID($entry->uuid);
|
||||||
$this->putEntityUniqueId($entry->entityUniqueId);
|
$this->putEntityUniqueId($entry->entityUniqueId);
|
||||||
$this->putString($entry->username);
|
$this->putString($entry->username);
|
||||||
$this->putString($entry->skin->getSkinId());
|
|
||||||
$this->putString($entry->skin->getSkinData());
|
|
||||||
$this->putString($entry->skin->getCapeData());
|
|
||||||
$this->putString($entry->skin->getGeometryName());
|
|
||||||
$this->putString($entry->skin->getGeometryData());
|
|
||||||
$this->putString($entry->xboxUserId);
|
$this->putString($entry->xboxUserId);
|
||||||
$this->putString($entry->platformChatId);
|
$this->putString($entry->platformChatId);
|
||||||
|
$this->putLInt($entry->buildPlatform);
|
||||||
|
$this->putSkin($entry->skinData);
|
||||||
|
$this->putBool($entry->isTeacher);
|
||||||
|
$this->putBool($entry->isHost);
|
||||||
}else{
|
}else{
|
||||||
$this->putUUID($entry->uuid);
|
$this->putUUID($entry->uuid);
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,8 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
|
|
||||||
#include <rules/DataPacket.h>
|
#include <rules/DataPacket.h>
|
||||||
|
|
||||||
use pocketmine\entity\Skin;
|
|
||||||
use pocketmine\network\BadPacketException;
|
|
||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\SkinData;
|
||||||
use pocketmine\utils\UUID;
|
use pocketmine\utils\UUID;
|
||||||
|
|
||||||
class PlayerSkinPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{
|
class PlayerSkinPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{
|
||||||
@ -39,43 +38,21 @@ class PlayerSkinPacket extends DataPacket implements ClientboundPacket, Serverbo
|
|||||||
public $oldSkinName = "";
|
public $oldSkinName = "";
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $newSkinName = "";
|
public $newSkinName = "";
|
||||||
/** @var Skin */
|
/** @var SkinData */
|
||||||
public $skin;
|
public $skin;
|
||||||
/** @var bool */
|
|
||||||
public $premiumSkin = false;
|
|
||||||
|
|
||||||
protected function decodePayload() : void{
|
protected function decodePayload() : void{
|
||||||
$this->uuid = $this->getUUID();
|
$this->uuid = $this->getUUID();
|
||||||
|
$this->skin = $this->getSkin();
|
||||||
$skinId = $this->getString();
|
|
||||||
$this->newSkinName = $this->getString();
|
$this->newSkinName = $this->getString();
|
||||||
$this->oldSkinName = $this->getString();
|
$this->oldSkinName = $this->getString();
|
||||||
$skinData = $this->getString();
|
|
||||||
$capeData = $this->getString();
|
|
||||||
$geometryModel = $this->getString();
|
|
||||||
$geometryData = $this->getString();
|
|
||||||
|
|
||||||
try{
|
|
||||||
$this->skin = new Skin($skinId, $skinData, $capeData, $geometryModel, $geometryData);
|
|
||||||
}catch(\InvalidArgumentException $e){
|
|
||||||
throw new BadPacketException($e->getMessage(), 0, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->premiumSkin = $this->getBool();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function encodePayload() : void{
|
protected function encodePayload() : void{
|
||||||
$this->putUUID($this->uuid);
|
$this->putUUID($this->uuid);
|
||||||
|
$this->putSkin($this->skin);
|
||||||
$this->putString($this->skin->getSkinId());
|
|
||||||
$this->putString($this->newSkinName);
|
$this->putString($this->newSkinName);
|
||||||
$this->putString($this->oldSkinName);
|
$this->putString($this->oldSkinName);
|
||||||
$this->putString($this->skin->getSkinData());
|
|
||||||
$this->putString($this->skin->getCapeData());
|
|
||||||
$this->putString($this->skin->getGeometryName());
|
|
||||||
$this->putString($this->skin->getGeometryData());
|
|
||||||
|
|
||||||
$this->putBool($this->premiumSkin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(PacketHandler $handler) : bool{
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
@ -43,15 +43,15 @@ final class ProtocolInfo{
|
|||||||
/**
|
/**
|
||||||
* Actual Minecraft: PE protocol version
|
* Actual Minecraft: PE protocol version
|
||||||
*/
|
*/
|
||||||
public const CURRENT_PROTOCOL = 361;
|
public const CURRENT_PROTOCOL = 388;
|
||||||
/**
|
/**
|
||||||
* Current Minecraft PE version reported by the server. This is usually the earliest currently supported version.
|
* Current Minecraft PE version reported by the server. This is usually the earliest currently supported version.
|
||||||
*/
|
*/
|
||||||
public const MINECRAFT_VERSION = 'v1.12.0';
|
public const MINECRAFT_VERSION = 'v1.13.0';
|
||||||
/**
|
/**
|
||||||
* Version number sent to clients in ping responses.
|
* Version number sent to clients in ping responses.
|
||||||
*/
|
*/
|
||||||
public const MINECRAFT_VERSION_NETWORK = '1.12.0';
|
public const MINECRAFT_VERSION_NETWORK = '1.13.0';
|
||||||
|
|
||||||
public const LOGIN_PACKET = 0x01;
|
public const LOGIN_PACKET = 0x01;
|
||||||
public const PLAY_STATUS_PACKET = 0x02;
|
public const PLAY_STATUS_PACKET = 0x02;
|
||||||
@ -75,7 +75,7 @@ final class ProtocolInfo{
|
|||||||
public const RIDER_JUMP_PACKET = 0x14;
|
public const RIDER_JUMP_PACKET = 0x14;
|
||||||
public const UPDATE_BLOCK_PACKET = 0x15;
|
public const UPDATE_BLOCK_PACKET = 0x15;
|
||||||
public const ADD_PAINTING_PACKET = 0x16;
|
public const ADD_PAINTING_PACKET = 0x16;
|
||||||
public const EXPLODE_PACKET = 0x17;
|
public const TICK_SYNC_PACKET = 0x17;
|
||||||
public const LEVEL_SOUND_EVENT_PACKET_V1 = 0x18;
|
public const LEVEL_SOUND_EVENT_PACKET_V1 = 0x18;
|
||||||
public const LEVEL_EVENT_PACKET = 0x19;
|
public const LEVEL_EVENT_PACKET = 0x19;
|
||||||
public const BLOCK_EVENT_PACKET = 0x1a;
|
public const BLOCK_EVENT_PACKET = 0x1a;
|
||||||
@ -184,10 +184,18 @@ final class ProtocolInfo{
|
|||||||
public const CLIENT_CACHE_STATUS_PACKET = 0x81;
|
public const CLIENT_CACHE_STATUS_PACKET = 0x81;
|
||||||
public const ON_SCREEN_TEXTURE_ANIMATION_PACKET = 0x82;
|
public const ON_SCREEN_TEXTURE_ANIMATION_PACKET = 0x82;
|
||||||
public const MAP_CREATE_LOCKED_COPY_PACKET = 0x83;
|
public const MAP_CREATE_LOCKED_COPY_PACKET = 0x83;
|
||||||
public const STRUCTURE_TEMPLATE_DATA_EXPORT_REQUEST_PACKET = 0x84;
|
public const STRUCTURE_TEMPLATE_DATA_REQUEST_PACKET = 0x84;
|
||||||
public const STRUCTURE_TEMPLATE_DATA_EXPORT_RESPONSE_PACKET = 0x85;
|
public const STRUCTURE_TEMPLATE_DATA_RESPONSE_PACKET = 0x85;
|
||||||
public const UPDATE_BLOCK_PROPERTIES_PACKET = 0x86;
|
public const UPDATE_BLOCK_PROPERTIES_PACKET = 0x86;
|
||||||
public const CLIENT_CACHE_BLOB_STATUS_PACKET = 0x87;
|
public const CLIENT_CACHE_BLOB_STATUS_PACKET = 0x87;
|
||||||
public const CLIENT_CACHE_MISS_RESPONSE_PACKET = 0x88;
|
public const CLIENT_CACHE_MISS_RESPONSE_PACKET = 0x88;
|
||||||
|
public const EDUCATION_SETTINGS_PACKET = 0x89;
|
||||||
|
public const EMOTE_PACKET = 0x8a;
|
||||||
|
public const MULTIPLAYER_SETTINGS_PACKET = 0x8b;
|
||||||
|
public const SETTINGS_COMMAND_PACKET = 0x8c;
|
||||||
|
public const ANVIL_DAMAGE_PACKET = 0x8d;
|
||||||
|
public const COMPLETED_USING_ITEM_PACKET = 0x8e;
|
||||||
|
public const NETWORK_SETTINGS_PACKET = 0x8f;
|
||||||
|
public const PLAYER_AUTH_INPUT_PACKET = 0x90;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -55,15 +55,14 @@ class ResourcePackChunkDataPacket extends DataPacket implements ClientboundPacke
|
|||||||
$this->packId = $this->getString();
|
$this->packId = $this->getString();
|
||||||
$this->chunkIndex = $this->getLInt();
|
$this->chunkIndex = $this->getLInt();
|
||||||
$this->progress = $this->getLLong();
|
$this->progress = $this->getLLong();
|
||||||
$this->data = $this->get($this->getLInt());
|
$this->data = $this->getString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function encodePayload() : void{
|
protected function encodePayload() : void{
|
||||||
$this->putString($this->packId);
|
$this->putString($this->packId);
|
||||||
$this->putLInt($this->chunkIndex);
|
$this->putLInt($this->chunkIndex);
|
||||||
$this->putLLong($this->progress);
|
$this->putLLong($this->progress);
|
||||||
$this->putLInt(strlen($this->data));
|
$this->putString($this->data);
|
||||||
$this->put($this->data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(PacketHandler $handler) : bool{
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
@ -44,6 +44,8 @@ class ResourcePackStackPacket extends DataPacket implements ClientboundPacket{
|
|||||||
|
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $isExperimental = false;
|
public $isExperimental = false;
|
||||||
|
/** @var string */
|
||||||
|
public $baseGameVersion = ProtocolInfo::MINECRAFT_VERSION_NETWORK;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ResourcePackStackEntry[] $resourcePacks
|
* @param ResourcePackStackEntry[] $resourcePacks
|
||||||
@ -75,6 +77,7 @@ class ResourcePackStackPacket extends DataPacket implements ClientboundPacket{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->isExperimental = $this->getBool();
|
$this->isExperimental = $this->getBool();
|
||||||
|
$this->baseGameVersion = $this->getString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function encodePayload() : void{
|
protected function encodePayload() : void{
|
||||||
@ -91,6 +94,7 @@ class ResourcePackStackPacket extends DataPacket implements ClientboundPacket{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->putBool($this->isExperimental);
|
$this->putBool($this->isExperimental);
|
||||||
|
$this->putString($this->baseGameVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(PacketHandler $handler) : bool{
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
@ -29,24 +29,38 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
|
|
||||||
class RespawnPacket extends DataPacket implements ClientboundPacket{
|
class RespawnPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{
|
||||||
public const NETWORK_ID = ProtocolInfo::RESPAWN_PACKET;
|
public const NETWORK_ID = ProtocolInfo::RESPAWN_PACKET;
|
||||||
|
|
||||||
|
public const SEARCHING_FOR_SPAWN = 0;
|
||||||
|
public const READY_TO_SPAWN = 1;
|
||||||
|
public const CLIENT_READY_TO_SPAWN = 2;
|
||||||
|
|
||||||
/** @var Vector3 */
|
/** @var Vector3 */
|
||||||
public $position;
|
public $position;
|
||||||
|
/** @var int */
|
||||||
|
public $respawnState = self::SEARCHING_FOR_SPAWN;
|
||||||
|
/** @var int */
|
||||||
|
public $entityRuntimeId;
|
||||||
|
|
||||||
public static function create(Vector3 $position) : self{
|
public static function create(Vector3 $position, int $respawnStatus, int $entityRuntimeId) : self{
|
||||||
$result = new self;
|
$result = new self;
|
||||||
$result->position = $position->asVector3();
|
$result->position = $position->asVector3();
|
||||||
|
$result->respawnState = $respawnStatus;
|
||||||
|
$result->entityRuntimeId = $entityRuntimeId;
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function decodePayload() : void{
|
protected function decodePayload() : void{
|
||||||
$this->position = $this->getVector3();
|
$this->position = $this->getVector3();
|
||||||
|
$this->respawnState = $this->getByte();
|
||||||
|
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function encodePayload() : void{
|
protected function encodePayload() : void{
|
||||||
$this->putVector3($this->position);
|
$this->putVector3($this->position);
|
||||||
|
$this->putByte($this->respawnState);
|
||||||
|
$this->putEntityRuntimeId($this->entityRuntimeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(PacketHandler $handler) : bool{
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
@ -27,7 +27,7 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
|
|
||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
|
|
||||||
class ScriptCustomEventPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{
|
class ScriptCustomEventPacket extends DataPacket{ //TODO: this doesn't have handlers in either client or server in the game as of 1.8
|
||||||
public const NETWORK_ID = ProtocolInfo::SCRIPT_CUSTOM_EVENT_PACKET;
|
public const NETWORK_ID = ProtocolInfo::SCRIPT_CUSTOM_EVENT_PACKET;
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
|
66
src/network/mcpe/protocol/SettingsCommandPacket.php
Normal file
66
src/network/mcpe/protocol/SettingsCommandPacket.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?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\handler\PacketHandler;
|
||||||
|
|
||||||
|
class SettingsCommandPacket extends DataPacket implements ServerboundPacket{
|
||||||
|
public const NETWORK_ID = ProtocolInfo::SETTINGS_COMMAND_PACKET;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
private $command;
|
||||||
|
/** @var bool */
|
||||||
|
private $suppressOutput;
|
||||||
|
|
||||||
|
public static function create(string $command, bool $suppressOutput) : self{
|
||||||
|
$result = new self;
|
||||||
|
$result->command = $command;
|
||||||
|
$result->suppressOutput = $suppressOutput;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommand() : string{
|
||||||
|
return $this->command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSuppressOutput() : bool{
|
||||||
|
return $this->suppressOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function decodePayload() : void{
|
||||||
|
$this->command = $this->getString();
|
||||||
|
$this->suppressOutput = $this->getBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function encodePayload() : void{
|
||||||
|
$this->putString($this->command);
|
||||||
|
$this->putBool($this->suppressOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
return $handler->handleSettingsCommand($this);
|
||||||
|
}
|
||||||
|
}
|
@ -27,10 +27,13 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
|
|
||||||
|
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
|
use pocketmine\nbt\TreeRoot;
|
||||||
|
use pocketmine\nbt\tag\ListTag;
|
||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
|
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
|
||||||
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
|
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
|
||||||
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
|
||||||
|
use pocketmine\network\mcpe\serializer\NetworkNbtSerializer;
|
||||||
use function count;
|
use function count;
|
||||||
use function file_get_contents;
|
use function file_get_contents;
|
||||||
use function json_decode;
|
use function json_decode;
|
||||||
@ -79,8 +82,8 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
|
|||||||
public $hasAchievementsDisabled = true;
|
public $hasAchievementsDisabled = true;
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public $time = -1;
|
public $time = -1;
|
||||||
/** @var bool */
|
/** @var int */
|
||||||
public $eduMode = false;
|
public $eduEditionOffer = 0;
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $hasEduFeaturesEnabled = false;
|
public $hasEduFeaturesEnabled = false;
|
||||||
/** @var float */
|
/** @var float */
|
||||||
@ -130,6 +133,8 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
|
|||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $onlySpawnV1Villagers = false;
|
public $onlySpawnV1Villagers = false;
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
public $vanillaVersion = ProtocolInfo::MINECRAFT_VERSION_NETWORK;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $levelId = ""; //base64 string, usually the same as world folder name in vanilla
|
public $levelId = ""; //base64 string, usually the same as world folder name in vanilla
|
||||||
/** @var string */
|
/** @var string */
|
||||||
@ -138,6 +143,8 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
|
|||||||
public $premiumWorldTemplateId = "";
|
public $premiumWorldTemplateId = "";
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $isTrial = false;
|
public $isTrial = false;
|
||||||
|
/** @var bool */
|
||||||
|
public $isMovementServerAuthoritative = false;
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public $currentTick = 0; //only used if isTrial is true
|
public $currentTick = 0; //only used if isTrial is true
|
||||||
/** @var int */
|
/** @var int */
|
||||||
@ -145,7 +152,7 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
|
|||||||
/** @var string */
|
/** @var string */
|
||||||
public $multiplayerCorrelationId = ""; //TODO: this should be filled with a UUID of some sort
|
public $multiplayerCorrelationId = ""; //TODO: this should be filled with a UUID of some sort
|
||||||
|
|
||||||
/** @var array|null ["name" (string), "data" (int16), "legacy_id" (int16)] */
|
/** @var ListTag|null */
|
||||||
public $blockTable = null;
|
public $blockTable = null;
|
||||||
/** @var array|null string (name) => int16 (legacyID) */
|
/** @var array|null string (name) => int16 (legacyID) */
|
||||||
public $itemTable = null;
|
public $itemTable = null;
|
||||||
@ -169,7 +176,7 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
|
|||||||
$this->getBlockPosition($this->spawnX, $this->spawnY, $this->spawnZ);
|
$this->getBlockPosition($this->spawnX, $this->spawnY, $this->spawnZ);
|
||||||
$this->hasAchievementsDisabled = $this->getBool();
|
$this->hasAchievementsDisabled = $this->getBool();
|
||||||
$this->time = $this->getVarInt();
|
$this->time = $this->getVarInt();
|
||||||
$this->eduMode = $this->getBool();
|
$this->eduEditionOffer = $this->getVarInt();
|
||||||
$this->hasEduFeaturesEnabled = $this->getBool();
|
$this->hasEduFeaturesEnabled = $this->getBool();
|
||||||
$this->rainLevel = $this->getLFloat();
|
$this->rainLevel = $this->getLFloat();
|
||||||
$this->lightningLevel = $this->getLFloat();
|
$this->lightningLevel = $this->getLFloat();
|
||||||
@ -193,22 +200,22 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
|
|||||||
$this->isWorldTemplateOptionLocked = $this->getBool();
|
$this->isWorldTemplateOptionLocked = $this->getBool();
|
||||||
$this->onlySpawnV1Villagers = $this->getBool();
|
$this->onlySpawnV1Villagers = $this->getBool();
|
||||||
|
|
||||||
|
$this->vanillaVersion = $this->getString();
|
||||||
$this->levelId = $this->getString();
|
$this->levelId = $this->getString();
|
||||||
$this->worldName = $this->getString();
|
$this->worldName = $this->getString();
|
||||||
$this->premiumWorldTemplateId = $this->getString();
|
$this->premiumWorldTemplateId = $this->getString();
|
||||||
$this->isTrial = $this->getBool();
|
$this->isTrial = $this->getBool();
|
||||||
|
$this->isMovementServerAuthoritative = $this->getBool();
|
||||||
$this->currentTick = $this->getLLong();
|
$this->currentTick = $this->getLLong();
|
||||||
|
|
||||||
$this->enchantmentSeed = $this->getVarInt();
|
$this->enchantmentSeed = $this->getVarInt();
|
||||||
|
|
||||||
$this->blockTable = [];
|
$blockTable = (new NetworkNbtSerializer())->read($this->buffer, $this->offset, 512)->getTag();
|
||||||
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
if(!($blockTable instanceof ListTag)){
|
||||||
$id = $this->getString();
|
throw new \UnexpectedValueException("Wrong block table root NBT tag type");
|
||||||
$data = $this->getSignedLShort();
|
|
||||||
$unknown = $this->getSignedLShort();
|
|
||||||
|
|
||||||
$this->blockTable[$i] = ["name" => $id, "data" => $data, "legacy_id" => $unknown];
|
|
||||||
}
|
}
|
||||||
|
$this->blockTable = $blockTable;
|
||||||
|
|
||||||
$this->itemTable = [];
|
$this->itemTable = [];
|
||||||
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||||
$id = $this->getString();
|
$id = $this->getString();
|
||||||
@ -239,7 +246,7 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
|
|||||||
$this->putBlockPosition($this->spawnX, $this->spawnY, $this->spawnZ);
|
$this->putBlockPosition($this->spawnX, $this->spawnY, $this->spawnZ);
|
||||||
$this->putBool($this->hasAchievementsDisabled);
|
$this->putBool($this->hasAchievementsDisabled);
|
||||||
$this->putVarInt($this->time);
|
$this->putVarInt($this->time);
|
||||||
$this->putBool($this->eduMode);
|
$this->putVarInt($this->eduEditionOffer);
|
||||||
$this->putBool($this->hasEduFeaturesEnabled);
|
$this->putBool($this->hasEduFeaturesEnabled);
|
||||||
$this->putLFloat($this->rainLevel);
|
$this->putLFloat($this->rainLevel);
|
||||||
$this->putLFloat($this->lightningLevel);
|
$this->putLFloat($this->lightningLevel);
|
||||||
@ -263,10 +270,12 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
|
|||||||
$this->putBool($this->isWorldTemplateOptionLocked);
|
$this->putBool($this->isWorldTemplateOptionLocked);
|
||||||
$this->putBool($this->onlySpawnV1Villagers);
|
$this->putBool($this->onlySpawnV1Villagers);
|
||||||
|
|
||||||
|
$this->putString($this->vanillaVersion);
|
||||||
$this->putString($this->levelId);
|
$this->putString($this->levelId);
|
||||||
$this->putString($this->worldName);
|
$this->putString($this->worldName);
|
||||||
$this->putString($this->premiumWorldTemplateId);
|
$this->putString($this->premiumWorldTemplateId);
|
||||||
$this->putBool($this->isTrial);
|
$this->putBool($this->isTrial);
|
||||||
|
$this->putBool($this->isMovementServerAuthoritative);
|
||||||
$this->putLLong($this->currentTick);
|
$this->putLLong($this->currentTick);
|
||||||
|
|
||||||
$this->putVarInt($this->enchantmentSeed);
|
$this->putVarInt($this->enchantmentSeed);
|
||||||
@ -274,11 +283,11 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
|
|||||||
if($this->blockTable === null){
|
if($this->blockTable === null){
|
||||||
if(self::$blockTableCache === null){
|
if(self::$blockTableCache === null){
|
||||||
//this is a really nasty hack, but it'll do for now
|
//this is a really nasty hack, but it'll do for now
|
||||||
self::$blockTableCache = self::serializeBlockTable(RuntimeBlockMapping::getBedrockKnownStates());
|
self::$blockTableCache = (new NetworkNbtSerializer())->write(new TreeRoot(new ListTag(RuntimeBlockMapping::getBedrockKnownStates())));
|
||||||
}
|
}
|
||||||
$this->put(self::$blockTableCache);
|
$this->put(self::$blockTableCache);
|
||||||
}else{
|
}else{
|
||||||
$this->put(self::serializeBlockTable($this->blockTable));
|
$this->put((new NetworkNbtSerializer())->write(new TreeRoot($this->blockTable)));
|
||||||
}
|
}
|
||||||
if($this->itemTable === null){
|
if($this->itemTable === null){
|
||||||
if(self::$itemTableCache === null){
|
if(self::$itemTableCache === null){
|
||||||
@ -292,17 +301,6 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{
|
|||||||
$this->putString($this->multiplayerCorrelationId);
|
$this->putString($this->multiplayerCorrelationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function serializeBlockTable(array $table) : string{
|
|
||||||
$stream = new NetworkBinaryStream();
|
|
||||||
$stream->putUnsignedVarInt(count($table));
|
|
||||||
foreach($table as $v){
|
|
||||||
$stream->putString($v["name"]);
|
|
||||||
$stream->putLShort($v["data"]);
|
|
||||||
$stream->putLShort($v["legacy_id"]);
|
|
||||||
}
|
|
||||||
return $stream->getBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function serializeItemTable(array $table) : string{
|
private static function serializeItemTable(array $table) : string{
|
||||||
$stream = new NetworkBinaryStream();
|
$stream = new NetworkBinaryStream();
|
||||||
$stream->putUnsignedVarInt(count($table));
|
$stream->putUnsignedVarInt(count($table));
|
||||||
|
@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
use pocketmine\network\mcpe\protocol\types\StructureSettings;
|
use pocketmine\network\mcpe\protocol\types\StructureSettings;
|
||||||
|
|
||||||
class StructureTemplateDataExportRequestPacket extends DataPacket implements ServerboundPacket{
|
class StructureTemplateDataRequestPacket extends DataPacket implements ServerboundPacket{
|
||||||
public const NETWORK_ID = ProtocolInfo::STRUCTURE_TEMPLATE_DATA_EXPORT_REQUEST_PACKET;
|
public const NETWORK_ID = ProtocolInfo::STRUCTURE_TEMPLATE_DATA_REQUEST_PACKET;
|
||||||
|
|
||||||
public const TYPE_ALWAYS_LOAD = 1;
|
public const TYPE_ALWAYS_LOAD = 1;
|
||||||
public const TYPE_CREATE_AND_LOAD = 2;
|
public const TYPE_CREATE_AND_LOAD = 2;
|
||||||
@ -62,6 +62,6 @@ class StructureTemplateDataExportRequestPacket extends DataPacket implements Ser
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function handle(PacketHandler $handler) : bool{
|
public function handle(PacketHandler $handler) : bool{
|
||||||
return $handler->handleStructureTemplateDataExportRequest($this);
|
return $handler->handleStructureTemplateDataRequest($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,8 +27,8 @@ namespace pocketmine\network\mcpe\protocol;
|
|||||||
|
|
||||||
use pocketmine\network\mcpe\handler\PacketHandler;
|
use pocketmine\network\mcpe\handler\PacketHandler;
|
||||||
|
|
||||||
class StructureTemplateDataExportResponsePacket extends DataPacket implements ClientboundPacket{
|
class StructureTemplateDataResponsePacket extends DataPacket implements ClientboundPacket{
|
||||||
public const NETWORK_ID = ProtocolInfo::STRUCTURE_TEMPLATE_DATA_EXPORT_RESPONSE_PACKET;
|
public const NETWORK_ID = ProtocolInfo::STRUCTURE_TEMPLATE_DATA_RESPONSE_PACKET;
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $structureTemplateName;
|
public $structureTemplateName;
|
||||||
@ -51,6 +51,6 @@ class StructureTemplateDataExportResponsePacket extends DataPacket implements Cl
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function handle(PacketHandler $handler) : bool{
|
public function handle(PacketHandler $handler) : bool{
|
||||||
return $handler->handleStructureTemplateDataExportResponse($this);
|
return $handler->handleStructureTemplateDataResponse($this);
|
||||||
}
|
}
|
||||||
}
|
}
|
73
src/network/mcpe/protocol/TickSyncPacket.php
Normal file
73
src/network/mcpe/protocol/TickSyncPacket.php
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?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\handler\PacketHandler;
|
||||||
|
|
||||||
|
class TickSyncPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{
|
||||||
|
public const NETWORK_ID = ProtocolInfo::TICK_SYNC_PACKET;
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $clientSendTime;
|
||||||
|
/** @var int */
|
||||||
|
private $serverReceiveTime;
|
||||||
|
|
||||||
|
public static function request(int $clientTime) : self{
|
||||||
|
$result = new self;
|
||||||
|
$result->clientSendTime = $clientTime;
|
||||||
|
$result->serverReceiveTime = 0; //useless
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function response(int $clientSendTime, int $serverReceiveTime) : self{
|
||||||
|
$result = new self;
|
||||||
|
$result->clientSendTime = $clientSendTime;
|
||||||
|
$result->serverReceiveTime = $serverReceiveTime;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClientSendTime() : int{
|
||||||
|
return $this->clientSendTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getServerReceiveTime() : int{
|
||||||
|
return $this->serverReceiveTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function decodePayload() : void{
|
||||||
|
$this->clientSendTime = $this->getLLong();
|
||||||
|
$this->serverReceiveTime = $this->getLLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function encodePayload() : void{
|
||||||
|
$this->putLLong($this->clientSendTime);
|
||||||
|
$this->putLLong($this->serverReceiveTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(PacketHandler $handler) : bool{
|
||||||
|
return $handler->handleTickSync($this);
|
||||||
|
}
|
||||||
|
}
|
36
src/network/mcpe/protocol/types/InputMode.php
Normal file
36
src/network/mcpe/protocol/types/InputMode.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?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 InputMode{
|
||||||
|
|
||||||
|
private function __construct(){
|
||||||
|
//NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
public const MOUSE_KEYBOARD = 1;
|
||||||
|
public const TOUCHSCREEN = 2;
|
||||||
|
public const GAME_PAD = 3;
|
||||||
|
public const MOTION_CONTROLLER = 4;
|
||||||
|
}
|
67
src/network/mcpe/protocol/types/LegacySkinAdapter.php
Normal file
67
src/network/mcpe/protocol/types/LegacySkinAdapter.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?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\entity\Skin;
|
||||||
|
|
||||||
|
use function is_array;
|
||||||
|
use function is_string;
|
||||||
|
|
||||||
|
class LegacySkinAdapter implements SkinAdapter{
|
||||||
|
|
||||||
|
public function toSkinData(Skin $skin) : SkinData{
|
||||||
|
$capeData = new SkinImage(32, 64, $skin->getCapeData());
|
||||||
|
if($skin->getCapeData() === ""){
|
||||||
|
$capeData = new SkinImage(0, 0, $skin->getCapeData());
|
||||||
|
}
|
||||||
|
$geometryName = $skin->getGeometryName();
|
||||||
|
if($geometryName === ""){
|
||||||
|
$geometryName = "geometry.humanoid.custom";
|
||||||
|
}
|
||||||
|
return new SkinData(
|
||||||
|
$skin->getSkinId(),
|
||||||
|
json_encode(["geometry" => ["default" => $geometryName]]),
|
||||||
|
SkinImage::fromLegacy($skin->getSkinData()), [],
|
||||||
|
$capeData,
|
||||||
|
$skin->getGeometryData()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fromSkinData(SkinData $data) : Skin{
|
||||||
|
$capeData = $data->getCapeImage()->getData();
|
||||||
|
$geometryName = "";
|
||||||
|
$resourcePatch = json_decode($data->getResourcePatch(), true);
|
||||||
|
if(is_array($resourcePatch["geometry"]) && is_string($resourcePatch["geometry"]["default"])){
|
||||||
|
$geometryName = $resourcePatch["geometry"]["default"];
|
||||||
|
}else{
|
||||||
|
//TODO: Kick for invalid skin
|
||||||
|
}
|
||||||
|
if($data->isPersona()){
|
||||||
|
return new Skin("Standard_Custom", str_repeat(random_bytes(3) . "\xff", 2048));
|
||||||
|
}elseif($data->isPersonaCapeOnClassic()){
|
||||||
|
$capeData = "";
|
||||||
|
}
|
||||||
|
return new Skin($data->getSkinId(), $data->getSkinImage()->getData(), $capeData, $geometryName, $data->getGeometryData());
|
||||||
|
}
|
||||||
|
}
|
45
src/network/mcpe/protocol/types/PlayMode.php
Normal file
45
src/network/mcpe/protocol/types/PlayMode.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum used by PlayerAuthInputPacket. Most of these names don't make any sense, but that isn't surprising.
|
||||||
|
*/
|
||||||
|
final class PlayMode{
|
||||||
|
|
||||||
|
private function __construct(){
|
||||||
|
//NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
public const NORMAL = 0;
|
||||||
|
public const TEASER = 1;
|
||||||
|
public const SCREEN = 2;
|
||||||
|
public const VIEWER = 3;
|
||||||
|
public const VR = 4;
|
||||||
|
public const PLACEMENT = 5;
|
||||||
|
public const LIVING_ROOM = 6;
|
||||||
|
public const EXIT_LEVEL = 7;
|
||||||
|
public const EXIT_LEVEL_LIVING_ROOM = 8;
|
||||||
|
|
||||||
|
}
|
@ -34,12 +34,18 @@ class PlayerListEntry{
|
|||||||
public $entityUniqueId;
|
public $entityUniqueId;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $username;
|
public $username;
|
||||||
/** @var Skin */
|
/** @var SkinData */
|
||||||
public $skin;
|
public $skinData;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $xboxUserId;
|
public $xboxUserId;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $platformChatId = "";
|
public $platformChatId = "";
|
||||||
|
/** @var int */
|
||||||
|
public $buildPlatform = -1;
|
||||||
|
/** @var bool */
|
||||||
|
public $isTeacher = false;
|
||||||
|
/** @var bool */
|
||||||
|
public $isHost = false;
|
||||||
|
|
||||||
public static function createRemovalEntry(UUID $uuid) : PlayerListEntry{
|
public static function createRemovalEntry(UUID $uuid) : PlayerListEntry{
|
||||||
$entry = new PlayerListEntry();
|
$entry = new PlayerListEntry();
|
||||||
@ -48,14 +54,17 @@ class PlayerListEntry{
|
|||||||
return $entry;
|
return $entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function createAdditionEntry(UUID $uuid, int $entityUniqueId, string $username, Skin $skin, string $xboxUserId = "", string $platformChatId = "") : PlayerListEntry{
|
public static function createAdditionEntry(UUID $uuid, int $entityUniqueId, string $username, SkinData $skinData, string $xboxUserId = "", string $platformChatId = "", int $buildPlatform = -1, bool $isTeacher = false, bool $isHost = false) : PlayerListEntry{
|
||||||
$entry = new PlayerListEntry();
|
$entry = new PlayerListEntry();
|
||||||
$entry->uuid = $uuid;
|
$entry->uuid = $uuid;
|
||||||
$entry->entityUniqueId = $entityUniqueId;
|
$entry->entityUniqueId = $entityUniqueId;
|
||||||
$entry->username = $username;
|
$entry->username = $username;
|
||||||
$entry->skin = $skin;
|
$entry->skinData = $skinData;
|
||||||
$entry->xboxUserId = $xboxUserId;
|
$entry->xboxUserId = $xboxUserId;
|
||||||
$entry->platformChatId = $platformChatId;
|
$entry->platformChatId = $platformChatId;
|
||||||
|
$entry->buildPlatform = $buildPlatform;
|
||||||
|
$entry->isTeacher = $isTeacher;
|
||||||
|
$entry->isHost = $isHost;
|
||||||
|
|
||||||
return $entry;
|
return $entry;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
class PotionContainerChangeRecipe{
|
||||||
|
/** @var int */
|
||||||
|
private $inputItemId;
|
||||||
|
/** @var int */
|
||||||
|
private $ingredientItemId;
|
||||||
|
/** @var int */
|
||||||
|
private $outputItemId;
|
||||||
|
|
||||||
|
public function __construct(int $inputItemId, int $ingredientItemId, int $outputItemId){
|
||||||
|
$this->inputItemId = $inputItemId;
|
||||||
|
$this->ingredientItemId = $ingredientItemId;
|
||||||
|
$this->outputItemId = $outputItemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInputItemId() : int{
|
||||||
|
return $this->inputItemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIngredientItemId() : int{
|
||||||
|
return $this->ingredientItemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOutputItemId() : int{
|
||||||
|
return $this->outputItemId;
|
||||||
|
}
|
||||||
|
}
|
51
src/network/mcpe/protocol/types/PotionTypeRecipe.php
Normal file
51
src/network/mcpe/protocol/types/PotionTypeRecipe.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
class PotionTypeRecipe{
|
||||||
|
/** @var int */
|
||||||
|
private $inputPotionType;
|
||||||
|
/** @var int */
|
||||||
|
private $ingredientItemId;
|
||||||
|
/** @var int */
|
||||||
|
private $outputPotionType;
|
||||||
|
|
||||||
|
public function __construct(int $inputPotionType, int $ingredientItemId, int $outputPotionType){
|
||||||
|
$this->inputPotionType = $inputPotionType;
|
||||||
|
$this->ingredientItemId = $ingredientItemId;
|
||||||
|
$this->outputPotionType = $outputPotionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInputPotionType() : int{
|
||||||
|
return $this->inputPotionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIngredientItemId() : int{
|
||||||
|
return $this->ingredientItemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOutputPotionType() : int{
|
||||||
|
return $this->outputPotionType;
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,12 @@ declare(strict_types=1);
|
|||||||
namespace pocketmine\network\mcpe\protocol\types;
|
namespace pocketmine\network\mcpe\protocol\types;
|
||||||
|
|
||||||
use pocketmine\block\BlockLegacyIds;
|
use pocketmine\block\BlockLegacyIds;
|
||||||
|
use pocketmine\nbt\NBT;
|
||||||
|
use pocketmine\nbt\tag\CompoundTag;
|
||||||
|
use pocketmine\nbt\tag\ListTag;
|
||||||
|
use pocketmine\nbt\tag\StringTag;
|
||||||
|
use pocketmine\network\mcpe\serializer\NetworkNbtSerializer;
|
||||||
|
use pocketmine\utils\BinaryDataException;
|
||||||
use function file_get_contents;
|
use function file_get_contents;
|
||||||
use function getmypid;
|
use function getmypid;
|
||||||
use function json_decode;
|
use function json_decode;
|
||||||
@ -40,7 +46,7 @@ final class RuntimeBlockMapping{
|
|||||||
private static $legacyToRuntimeMap = [];
|
private static $legacyToRuntimeMap = [];
|
||||||
/** @var int[] */
|
/** @var int[] */
|
||||||
private static $runtimeToLegacyMap = [];
|
private static $runtimeToLegacyMap = [];
|
||||||
/** @var mixed[]|null */
|
/** @var CompoundTag[]|null */
|
||||||
private static $bedrockKnownStates = null;
|
private static $bedrockKnownStates = null;
|
||||||
|
|
||||||
private function __construct(){
|
private function __construct(){
|
||||||
@ -48,32 +54,54 @@ final class RuntimeBlockMapping{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static function init() : void{
|
public static function init() : void{
|
||||||
|
$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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var CompoundTag[] $list */
|
||||||
|
$list = $tag->getValue();
|
||||||
|
self::$bedrockKnownStates = self::randomizeTable($list);
|
||||||
|
|
||||||
|
self::setupLegacyMappings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function setupLegacyMappings() : void{
|
||||||
$legacyIdMap = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/block_id_map.json"), true);
|
$legacyIdMap = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/block_id_map.json"), true);
|
||||||
|
$legacyStateMap = (new NetworkNbtSerializer())->read(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/r12_to_current_block_map.nbt"))->getTag();
|
||||||
$compressedTable = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla/required_block_states.json"), true);
|
if(!($legacyStateMap instanceof ListTag) or $legacyStateMap->getTagType() !== NBT::TAG_Compound){
|
||||||
$decompressed = [];
|
throw new \RuntimeException("Invalid legacy states mapping table, expected TAG_List<TAG_Compound> root");
|
||||||
|
|
||||||
foreach($compressedTable as $prefix => $entries){
|
|
||||||
foreach($entries as $shortStringId => $states){
|
|
||||||
foreach($states as $state){
|
|
||||||
$name = "$prefix:$shortStringId";
|
|
||||||
$decompressed[] = [
|
|
||||||
"name" => $name,
|
|
||||||
"data" => $state,
|
|
||||||
"legacy_id" => $legacyIdMap[$name]
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
self::$bedrockKnownStates = self::randomizeTable($decompressed);
|
|
||||||
|
|
||||||
foreach(self::$bedrockKnownStates as $k => $obj){
|
/**
|
||||||
if($obj["data"] > 15){
|
* @var int[][] $idToStatesMap string id -> int[] list of candidate state indices
|
||||||
//TODO: in 1.12 they started using data values bigger than 4 bits which we can't handle right now
|
*/
|
||||||
|
$idToStatesMap = [];
|
||||||
|
foreach(self::$bedrockKnownStates as $k => $state){
|
||||||
|
$idToStatesMap[$state->getCompoundTag("block")->getString("name")][] = $k;
|
||||||
|
}
|
||||||
|
/** @var CompoundTag $pair */
|
||||||
|
foreach($legacyStateMap as $pair){
|
||||||
|
$oldState = $pair->getCompoundTag("old");
|
||||||
|
$id = $legacyIdMap[$oldState->getString("name")];
|
||||||
|
$data = $oldState->getShort("val");
|
||||||
|
if($data > 15){
|
||||||
|
//we can't handle metadata with more than 4 bits
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//this has to use the json offset to make sure the mapping is consistent with what we send over network, even though we aren't using all the entries
|
$mappedState = $pair->getCompoundTag("new");
|
||||||
self::registerMapping($k, $obj["legacy_id"], $obj["data"]);
|
$mappedName = $mappedState->getString("name");
|
||||||
|
if(!isset($idToStatesMap[$mappedName])){
|
||||||
|
throw new \RuntimeException("Mapped new state does not appear in network table");
|
||||||
|
}
|
||||||
|
foreach($idToStatesMap[$mappedName] as $k){
|
||||||
|
$networkState = self::$bedrockKnownStates[$k];
|
||||||
|
if($mappedState->equals($networkState->getCompoundTag("block"))){
|
||||||
|
self::registerMapping($k, $id, $data);
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new \RuntimeException("Mapped new state does not appear in network table");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,9 +116,9 @@ final class RuntimeBlockMapping{
|
|||||||
* Plugins shouldn't use this stuff anyway, but plugin devs have an irritating habit of ignoring what they
|
* 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.
|
* aren't supposed to do, so we have to deliberately break it to make them stop.
|
||||||
*
|
*
|
||||||
* @param array $table
|
* @param CompoundTag[] $table
|
||||||
*
|
*
|
||||||
* @return array
|
* @return CompoundTag[]
|
||||||
*/
|
*/
|
||||||
private static function randomizeTable(array $table) : array{
|
private static function randomizeTable(array $table) : array{
|
||||||
$postSeed = mt_rand(); //save a seed to set afterwards, to avoid poor quality randoms
|
$postSeed = mt_rand(); //save a seed to set afterwards, to avoid poor quality randoms
|
||||||
@ -133,7 +161,7 @@ final class RuntimeBlockMapping{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return CompoundTag[]
|
||||||
*/
|
*/
|
||||||
public static function getBedrockKnownStates() : array{
|
public static function getBedrockKnownStates() : array{
|
||||||
self::lazyInit();
|
self::lazyInit();
|
||||||
|
48
src/network/mcpe/protocol/types/SkinAdapter.php
Normal file
48
src/network/mcpe/protocol/types/SkinAdapter.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?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\entity\Skin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to convert new skin data to the skin entity or old skin entity to skin data.
|
||||||
|
*/
|
||||||
|
interface SkinAdapter{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows you to convert a skin entity to skin data.
|
||||||
|
*
|
||||||
|
* @param Skin $skin
|
||||||
|
* @return SkinData
|
||||||
|
*/
|
||||||
|
public function toSkinData(Skin $skin) : SkinData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows you to convert skin data to a skin entity.
|
||||||
|
*
|
||||||
|
* @param SkinData $data
|
||||||
|
* @return Skin
|
||||||
|
*/
|
||||||
|
public function fromSkinData(SkinData $data) : Skin;
|
||||||
|
}
|
43
src/network/mcpe/protocol/types/SkinAdapterSingleton.php
Normal file
43
src/network/mcpe/protocol/types/SkinAdapterSingleton.php
Normal 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessor for SkinAdapter
|
||||||
|
*/
|
||||||
|
class SkinAdapterSingleton{
|
||||||
|
/** @var SkinAdapter|null */
|
||||||
|
private static $skinAdapter = null;
|
||||||
|
|
||||||
|
public static function get() : SkinAdapter{
|
||||||
|
if(self::$skinAdapter === null){
|
||||||
|
self::$skinAdapter = new LegacySkinAdapter();
|
||||||
|
}
|
||||||
|
return self::$skinAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function set(SkinAdapter $adapter) : void{
|
||||||
|
self::$skinAdapter = $adapter;
|
||||||
|
}
|
||||||
|
}
|
71
src/network/mcpe/protocol/types/SkinAnimation.php
Normal file
71
src/network/mcpe/protocol/types/SkinAnimation.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
class SkinAnimation{
|
||||||
|
|
||||||
|
public const TYPE_HEAD = 1;
|
||||||
|
public const TYPE_BODY_32 = 2;
|
||||||
|
public const TYPE_BODY_64 = 3;
|
||||||
|
|
||||||
|
/** @var SkinImage */
|
||||||
|
private $image;
|
||||||
|
/** @var int */
|
||||||
|
private $type;
|
||||||
|
/** @var float */
|
||||||
|
private $frames;
|
||||||
|
|
||||||
|
public function __construct(SkinImage $image, int $type, float $frames){
|
||||||
|
$this->image = $image;
|
||||||
|
$this->type = $type;
|
||||||
|
$this->frames = $frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Image of the animation.
|
||||||
|
*
|
||||||
|
* @return SkinImage
|
||||||
|
*/
|
||||||
|
public function getImage() : SkinImage{
|
||||||
|
return $this->image;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of animation you are applying.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getType() : int{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total amount of frames in an animation.
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getFrames() : float{
|
||||||
|
return $this->frames;
|
||||||
|
}
|
||||||
|
}
|
155
src/network/mcpe/protocol/types/SkinData.php
Normal file
155
src/network/mcpe/protocol/types/SkinData.php
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
class SkinData{
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
private $skinId;
|
||||||
|
/** @var string */
|
||||||
|
private $resourcePatch;
|
||||||
|
/** @var SkinImage */
|
||||||
|
private $skinImage;
|
||||||
|
/** @var SkinAnimation[] */
|
||||||
|
private $animations;
|
||||||
|
/** @var SkinImage */
|
||||||
|
private $capeImage;
|
||||||
|
/** @var string */
|
||||||
|
private $geometryData;
|
||||||
|
/** @var string */
|
||||||
|
private $animationData;
|
||||||
|
/** @var bool */
|
||||||
|
private $persona;
|
||||||
|
/** @var bool */
|
||||||
|
private $premium;
|
||||||
|
/** @var bool */
|
||||||
|
private $personaCapeOnClassic;
|
||||||
|
/** @var string */
|
||||||
|
private $capeId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $skinId
|
||||||
|
* @param string $resourcePatch
|
||||||
|
* @param SkinImage $skinImage
|
||||||
|
* @param SkinAnimation[] $animations
|
||||||
|
* @param SkinImage|null $capeImage
|
||||||
|
* @param string $geometryData
|
||||||
|
* @param string $animationData
|
||||||
|
* @param bool $premium
|
||||||
|
* @param bool $persona
|
||||||
|
* @param bool $personaCapeOnClassic
|
||||||
|
* @param string $capeId
|
||||||
|
*/
|
||||||
|
public function __construct(string $skinId, string $resourcePatch, SkinImage $skinImage, array $animations = [], SkinImage $capeImage = null, string $geometryData = "", string $animationData = "", bool $premium = false, bool $persona = false, bool $personaCapeOnClassic = false, string $capeId = ""){
|
||||||
|
$this->skinId = $skinId;
|
||||||
|
$this->resourcePatch = $resourcePatch;
|
||||||
|
$this->skinImage = $skinImage;
|
||||||
|
$this->animations = $animations;
|
||||||
|
$this->capeImage = $capeImage;
|
||||||
|
$this->geometryData = $geometryData;
|
||||||
|
$this->animationData = $animationData;
|
||||||
|
$this->premium = $premium;
|
||||||
|
$this->persona = $persona;
|
||||||
|
$this->personaCapeOnClassic = $personaCapeOnClassic;
|
||||||
|
$this->capeId = $capeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSkinId() : string{
|
||||||
|
return $this->skinId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getResourcePatch() : string{
|
||||||
|
return $this->resourcePatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return SkinImage
|
||||||
|
*/
|
||||||
|
public function getSkinImage() : SkinImage{
|
||||||
|
return $this->skinImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return SkinAnimation[]
|
||||||
|
*/
|
||||||
|
public function getAnimations() : array{
|
||||||
|
return $this->animations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return SkinImage
|
||||||
|
*/
|
||||||
|
public function getCapeImage() : SkinImage{
|
||||||
|
return $this->capeImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getGeometryData() : string{
|
||||||
|
return $this->geometryData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getAnimationData() : string{
|
||||||
|
return $this->animationData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPersona() : bool{
|
||||||
|
return $this->persona;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPremium() : bool{
|
||||||
|
return $this->premium;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPersonaCapeOnClassic() : bool{
|
||||||
|
return $this->personaCapeOnClassic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCapeId() : string{
|
||||||
|
return $this->capeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
67
src/network/mcpe/protocol/types/SkinImage.php
Normal file
67
src/network/mcpe/protocol/types/SkinImage.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
class SkinImage{
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
private $height;
|
||||||
|
/** @var int */
|
||||||
|
private $width;
|
||||||
|
/** @var string */
|
||||||
|
private $data;
|
||||||
|
|
||||||
|
public function __construct(int $height, int $width, string $data){
|
||||||
|
$this->height = $height;
|
||||||
|
$this->width = $width;
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fromLegacy(string $data) : SkinImage{
|
||||||
|
switch(strlen($data)){
|
||||||
|
case 64 * 32 * 4:
|
||||||
|
return new self(64, 32, $data);
|
||||||
|
case 64 * 64 * 4:
|
||||||
|
return new self(64, 64, $data);
|
||||||
|
case 128 * 64 * 4:
|
||||||
|
return new self(128, 64, $data);
|
||||||
|
case 128 * 128 * 4:
|
||||||
|
return new self(128, 128, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \InvalidArgumentException("Unknown size");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHeight() : int{
|
||||||
|
return $this->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWidth() : int{
|
||||||
|
return $this->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getData() : string{
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
<?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\command;
|
||||||
|
|
||||||
|
class CommandEnumConstraint{
|
||||||
|
/** @var CommandEnum */
|
||||||
|
private $enum;
|
||||||
|
/** @var int */
|
||||||
|
private $valueOffset;
|
||||||
|
/** @var int[] */
|
||||||
|
private $constraints; //TODO: find constants
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param CommandEnum $enum
|
||||||
|
* @param int $valueOffset
|
||||||
|
* @param int[] $constraints
|
||||||
|
*/
|
||||||
|
public function __construct(CommandEnum $enum, int $valueOffset, array $constraints){
|
||||||
|
(static function(int ...$_){})(...$constraints);
|
||||||
|
if(!isset($enum->getValues()[$valueOffset])){
|
||||||
|
throw new \InvalidArgumentException("Invalid enum value offset $valueOffset");
|
||||||
|
}
|
||||||
|
$this->enum = $enum;
|
||||||
|
$this->valueOffset = $valueOffset;
|
||||||
|
$this->constraints = $constraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEnum() : CommandEnum{
|
||||||
|
return $this->enum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValueOffset() : int{
|
||||||
|
return $this->valueOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAffectedValue() : string{
|
||||||
|
return $this->enum->getValues()[$this->valueOffset];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int[]
|
||||||
|
*/
|
||||||
|
public function getConstraints() : array{
|
||||||
|
return $this->constraints;
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,9 @@ namespace pocketmine\network\mcpe\protocol\types\command;
|
|||||||
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
|
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
|
||||||
|
|
||||||
class CommandParameter{
|
class CommandParameter{
|
||||||
|
public const FLAG_FORCE_COLLAPSE_ENUM = 0x1;
|
||||||
|
public const FLAG_HAS_ENUM_CONSTRAINT = 0x2;
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public $paramName;
|
public $paramName;
|
||||||
/** @var int */
|
/** @var int */
|
||||||
@ -39,28 +42,28 @@ class CommandParameter{
|
|||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
public $postfix;
|
public $postfix;
|
||||||
|
|
||||||
private static function baseline(string $name, int $type, bool $optional) : self{
|
private static function baseline(string $name, int $type, int $flags, bool $optional) : self{
|
||||||
$result = new self;
|
$result = new self;
|
||||||
$result->paramName = $name;
|
$result->paramName = $name;
|
||||||
$result->paramType = $type;
|
$result->paramType = $type;
|
||||||
|
$result->flags = $flags;
|
||||||
$result->isOptional = $optional;
|
$result->isOptional = $optional;
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function standard(string $name, int $type, bool $optional = false) : self{
|
public static function standard(string $name, int $type, int $flags = 0, bool $optional = false) : self{
|
||||||
return self::baseline($name, AvailableCommandsPacket::ARG_FLAG_VALID | $type, $optional);
|
return self::baseline($name, AvailableCommandsPacket::ARG_FLAG_VALID | $type, $flags, $optional);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function postfixed(string $name, string $postfix, bool $optional = false) : self{
|
public static function postfixed(string $name, string $postfix, int $flags = 0, bool $optional = false) : self{
|
||||||
$result = self::baseline($name, AvailableCommandsPacket::ARG_FLAG_POSTFIX, $optional);
|
$result = self::baseline($name, AvailableCommandsPacket::ARG_FLAG_POSTFIX, $flags, $optional);
|
||||||
$result->postfix = $postfix;
|
$result->postfix = $postfix;
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function enum(string $name, CommandEnum $enum, int $flags, bool $optional = false) : self{
|
public static function enum(string $name, CommandEnum $enum, int $flags, bool $optional = false) : self{
|
||||||
$result = self::baseline($name, AvailableCommandsPacket::ARG_FLAG_ENUM | AvailableCommandsPacket::ARG_FLAG_VALID, $optional);
|
$result = self::baseline($name, AvailableCommandsPacket::ARG_FLAG_ENUM | AvailableCommandsPacket::ARG_FLAG_VALID, $flags, $optional);
|
||||||
$result->enum = $enum;
|
$result->enum = $enum;
|
||||||
$result->flags = $flags;
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,6 @@ final class ContainerIds{
|
|||||||
public const CREATIVE = 121;
|
public const CREATIVE = 121;
|
||||||
public const HOTBAR = 122;
|
public const HOTBAR = 122;
|
||||||
public const FIXED_INVENTORY = 123;
|
public const FIXED_INVENTORY = 123;
|
||||||
public const CURSOR = 124;
|
public const UI = 124;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace pocketmine\network\mcpe\protocol\types\inventory;
|
namespace pocketmine\network\mcpe\protocol\types\inventory;
|
||||||
|
|
||||||
|
use pocketmine\crafting\CraftingGrid;
|
||||||
use pocketmine\inventory\AnvilInventory;
|
use pocketmine\inventory\AnvilInventory;
|
||||||
use pocketmine\inventory\EnchantInventory;
|
use pocketmine\inventory\EnchantInventory;
|
||||||
use pocketmine\inventory\transaction\action\CreateItemAction;
|
use pocketmine\inventory\transaction\action\CreateItemAction;
|
||||||
@ -41,7 +42,6 @@ class NetworkInventoryAction{
|
|||||||
|
|
||||||
public const SOURCE_WORLD = 2; //drop/pickup item entity
|
public const SOURCE_WORLD = 2; //drop/pickup item entity
|
||||||
public const SOURCE_CREATIVE = 3;
|
public const SOURCE_CREATIVE = 3;
|
||||||
public const SOURCE_CRAFTING_GRID = 100;
|
|
||||||
public const SOURCE_TODO = 99999;
|
public const SOURCE_TODO = 99999;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,7 +116,6 @@ class NetworkInventoryAction{
|
|||||||
break;
|
break;
|
||||||
case self::SOURCE_CREATIVE:
|
case self::SOURCE_CREATIVE:
|
||||||
break;
|
break;
|
||||||
case self::SOURCE_CRAFTING_GRID:
|
|
||||||
case self::SOURCE_TODO:
|
case self::SOURCE_TODO:
|
||||||
$this->windowId = $packet->getVarInt();
|
$this->windowId = $packet->getVarInt();
|
||||||
break;
|
break;
|
||||||
@ -148,7 +147,6 @@ class NetworkInventoryAction{
|
|||||||
break;
|
break;
|
||||||
case self::SOURCE_CREATIVE:
|
case self::SOURCE_CREATIVE:
|
||||||
break;
|
break;
|
||||||
case self::SOURCE_CRAFTING_GRID:
|
|
||||||
case self::SOURCE_TODO:
|
case self::SOURCE_TODO:
|
||||||
$packet->putVarInt($this->windowId);
|
$packet->putVarInt($this->windowId);
|
||||||
break;
|
break;
|
||||||
@ -169,11 +167,37 @@ class NetworkInventoryAction{
|
|||||||
* @throws \UnexpectedValueException
|
* @throws \UnexpectedValueException
|
||||||
*/
|
*/
|
||||||
public function createInventoryAction(Player $player) : ?InventoryAction{
|
public function createInventoryAction(Player $player) : ?InventoryAction{
|
||||||
|
if($this->oldItem->equalsExact($this->newItem)){
|
||||||
|
//filter out useless noise in 1.13
|
||||||
|
return null;
|
||||||
|
}
|
||||||
switch($this->sourceType){
|
switch($this->sourceType){
|
||||||
case self::SOURCE_CONTAINER:
|
case self::SOURCE_CONTAINER:
|
||||||
|
if($this->windowId === ContainerIds::UI and $this->inventorySlot > 0){
|
||||||
|
if($this->inventorySlot === 50){
|
||||||
|
return null; //useless noise
|
||||||
|
}
|
||||||
|
if($this->inventorySlot >= 28 and $this->inventorySlot <= 31){
|
||||||
|
$window = $player->getCraftingGrid();
|
||||||
|
if($window->getGridWidth() !== CraftingGrid::SIZE_SMALL){
|
||||||
|
throw new \UnexpectedValueException("Expected small crafting grid");
|
||||||
|
}
|
||||||
|
$slot = $this->inventorySlot - 28;
|
||||||
|
}elseif($this->inventorySlot >= 32 and $this->inventorySlot <= 40){
|
||||||
|
$window = $player->getCraftingGrid();
|
||||||
|
if($window->getGridWidth() !== CraftingGrid::SIZE_BIG){
|
||||||
|
throw new \UnexpectedValueException("Expected big crafting grid");
|
||||||
|
}
|
||||||
|
$slot = $this->inventorySlot - 32;
|
||||||
|
}else{
|
||||||
|
throw new \UnexpectedValueException("Unhandled magic UI slot offset $this->inventorySlot");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
$window = $player->getNetworkSession()->getInvManager()->getWindow($this->windowId);
|
$window = $player->getNetworkSession()->getInvManager()->getWindow($this->windowId);
|
||||||
|
$slot = $this->inventorySlot;
|
||||||
|
}
|
||||||
if($window !== null){
|
if($window !== null){
|
||||||
return new SlotChangeAction($window, $this->inventorySlot, $this->oldItem, $this->newItem);
|
return new SlotChangeAction($window, $slot, $this->oldItem, $this->newItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \UnexpectedValueException("No open container with window ID $this->windowId");
|
throw new \UnexpectedValueException("No open container with window ID $this->windowId");
|
||||||
@ -193,7 +217,6 @@ class NetworkInventoryAction{
|
|||||||
throw new \UnexpectedValueException("Unexpected creative action type $this->inventorySlot");
|
throw new \UnexpectedValueException("Unexpected creative action type $this->inventorySlot");
|
||||||
|
|
||||||
}
|
}
|
||||||
case self::SOURCE_CRAFTING_GRID:
|
|
||||||
case self::SOURCE_TODO:
|
case self::SOURCE_TODO:
|
||||||
//These types need special handling.
|
//These types need special handling.
|
||||||
switch($this->windowId){
|
switch($this->windowId){
|
||||||
@ -226,18 +249,4 @@ class NetworkInventoryAction{
|
|||||||
throw new \UnexpectedValueException("Unknown inventory source type $this->sourceType");
|
throw new \UnexpectedValueException("Unknown inventory source type $this->sourceType");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Hack to allow identifying crafting transaction parts.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isCraftingPart() : bool{
|
|
||||||
return ($this->sourceType === self::SOURCE_TODO or $this->sourceType === self::SOURCE_CRAFTING_GRID) and
|
|
||||||
($this->windowId === self::SOURCE_TYPE_CRAFTING_RESULT or $this->windowId === self::SOURCE_TYPE_CRAFTING_USE_INGREDIENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isFinalCraftingPart() : bool{
|
|
||||||
return $this->isCraftingPart() and $this->windowId === self::SOURCE_TYPE_CRAFTING_RESULT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,12 @@ final class ResourcePackType{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public const INVALID = 0;
|
public const INVALID = 0;
|
||||||
public const RESOURCES = 1;
|
public const ADDON = 1;
|
||||||
public const BEHAVIORS = 2;
|
public const CACHED = 2;
|
||||||
public const WORLD_TEMPLATE = 3;
|
public const COPY_PROTECTED = 3;
|
||||||
public const ADDON = 4; //scripts?
|
public const BEHAVIORS = 4;
|
||||||
public const SKINS = 5;
|
public const PERSONA_PIECE = 5;
|
||||||
|
public const RESOURCES = 6;
|
||||||
|
public const SKINS = 7;
|
||||||
|
public const WORLD_TEMPLATE = 8;
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,9 @@ use pocketmine\network\mcpe\protocol\types\entity\MetadataProperty;
|
|||||||
use pocketmine\network\mcpe\protocol\types\entity\ShortMetadataProperty;
|
use pocketmine\network\mcpe\protocol\types\entity\ShortMetadataProperty;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty;
|
use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\Vec3MetadataProperty;
|
use pocketmine\network\mcpe\protocol\types\entity\Vec3MetadataProperty;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\SkinData;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\SkinImage;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\SkinAnimation;
|
||||||
use pocketmine\network\mcpe\protocol\types\StructureSettings;
|
use pocketmine\network\mcpe\protocol\types\StructureSettings;
|
||||||
use pocketmine\utils\BinaryDataException;
|
use pocketmine\utils\BinaryDataException;
|
||||||
use pocketmine\utils\BinaryStream;
|
use pocketmine\utils\BinaryStream;
|
||||||
@ -94,6 +97,66 @@ class NetworkBinaryStream extends BinaryStream{
|
|||||||
$this->putLInt($uuid->getPart(2));
|
$this->putLInt($uuid->getPart(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSkin() : SkinData{
|
||||||
|
$skinId = $this->getString();
|
||||||
|
$skinResourcePatch = $this->getString();
|
||||||
|
$skinData = $this->getSkinImage();
|
||||||
|
$animationCount = $this->getLInt();
|
||||||
|
$animations = [];
|
||||||
|
for($i = 0; $i < $animationCount; ++$i){
|
||||||
|
$animations[] = new SkinAnimation(
|
||||||
|
$skinImage = $this->getSkinImage(),
|
||||||
|
$animationType = $this->getLInt(),
|
||||||
|
$animationFrames = $this->getLFloat()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$capeData = $this->getSkinImage();
|
||||||
|
$geometryData = $this->getString();
|
||||||
|
$animationData = $this->getString();
|
||||||
|
$premium = $this->getBool();
|
||||||
|
$persona = $this->getBool();
|
||||||
|
$capeOnClassic = $this->getBool();
|
||||||
|
$capeId = $this->getString();
|
||||||
|
$fullSkinId = $this->getString();
|
||||||
|
|
||||||
|
return new SkinData($skinId, $skinResourcePatch, $skinData, $animations, $capeData, $geometryData, $animationData, $premium, $persona, $capeOnClassic, $capeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function putSkin(SkinData $skin){
|
||||||
|
$this->putString($skin->getSkinId());
|
||||||
|
$this->putString($skin->getResourcePatch());
|
||||||
|
$this->putSkinImage($skin->getSkinImage());
|
||||||
|
$this->putLInt(count($skin->getAnimations()));
|
||||||
|
foreach($skin->getAnimations() as $animation){
|
||||||
|
$this->putSkinImage($animation->getImage());
|
||||||
|
$this->putLInt($animation->getType());
|
||||||
|
$this->putLFloat($animation->getFrames());
|
||||||
|
}
|
||||||
|
$this->putSkinImage($skin->getCapeImage());
|
||||||
|
$this->putString($skin->getGeometryData());
|
||||||
|
$this->putString($skin->getAnimationData());
|
||||||
|
$this->putBool($skin->isPremium());
|
||||||
|
$this->putBool($skin->isPersona());
|
||||||
|
$this->putBool($skin->isPersonaCapeOnClassic());
|
||||||
|
$this->putString($skin->getCapeId());
|
||||||
|
|
||||||
|
//this has to be unique or the client will do stupid things
|
||||||
|
$this->putString(UUID::fromRandom()->toString()); //full skin ID
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getSkinImage() : SkinImage{
|
||||||
|
$width = $this->getLInt();
|
||||||
|
$height = $this->getLInt();
|
||||||
|
$data = $this->getString();
|
||||||
|
return new SkinImage($height, $width, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function putSkinImage(SkinImage $image) : void{
|
||||||
|
$this->putLInt($image->getWidth());
|
||||||
|
$this->putLInt($image->getHeight());
|
||||||
|
$this->putString($image->getData());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Item
|
* @return Item
|
||||||
*
|
*
|
||||||
|
@ -37,7 +37,6 @@ use pocketmine\item\ItemFactory;
|
|||||||
use pocketmine\math\AxisAlignedBB;
|
use pocketmine\math\AxisAlignedBB;
|
||||||
use pocketmine\math\Facing;
|
use pocketmine\math\Facing;
|
||||||
use pocketmine\math\Vector3;
|
use pocketmine\math\Vector3;
|
||||||
use pocketmine\network\mcpe\protocol\ExplodePacket;
|
|
||||||
use pocketmine\world\particle\HugeExplodeSeedParticle;
|
use pocketmine\world\particle\HugeExplodeSeedParticle;
|
||||||
use pocketmine\world\sound\ExplodeSound;
|
use pocketmine\world\sound\ExplodeSound;
|
||||||
use pocketmine\world\utils\SubChunkIteratorManager;
|
use pocketmine\world\utils\SubChunkIteratorManager;
|
||||||
@ -251,8 +250,6 @@ class Explosion{
|
|||||||
$send[] = $pos->subtract($source);
|
$send[] = $pos->subtract($source);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->world->broadcastPacketToViewers($source, ExplodePacket::create($this->source->asVector3(), $this->size, $send));
|
|
||||||
|
|
||||||
$this->world->addParticle($source, new HugeExplodeSeedParticle());
|
$this->world->addParticle($source, new HugeExplodeSeedParticle());
|
||||||
$this->world->addSound($source, new ExplodeSound());
|
$this->world->addSound($source, new ExplodeSound());
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
|
|||||||
use pocketmine\network\mcpe\protocol\types\entity\FloatMetadataProperty;
|
use pocketmine\network\mcpe\protocol\types\entity\FloatMetadataProperty;
|
||||||
use pocketmine\network\mcpe\protocol\types\entity\LongMetadataProperty;
|
use pocketmine\network\mcpe\protocol\types\entity\LongMetadataProperty;
|
||||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\SkinAdapterSingleton;
|
||||||
use pocketmine\utils\UUID;
|
use pocketmine\utils\UUID;
|
||||||
use function str_repeat;
|
use function str_repeat;
|
||||||
|
|
||||||
@ -92,7 +93,7 @@ class FloatingTextParticle implements Particle{
|
|||||||
$uuid = UUID::fromRandom();
|
$uuid = UUID::fromRandom();
|
||||||
$name = $this->title . ($this->text !== "" ? "\n" . $this->text : "");
|
$name = $this->title . ($this->text !== "" ? "\n" . $this->text : "");
|
||||||
|
|
||||||
$p[] = PlayerListPacket::add([PlayerListEntry::createAdditionEntry($uuid, $this->entityId, $name, new Skin("Standard_Custom", str_repeat("\x00", 8192)))]);
|
$p[] = PlayerListPacket::add([PlayerListEntry::createAdditionEntry($uuid, $this->entityId, $name, SkinAdapterSingleton::get()->toSkinData(new Skin("Standard_Custom", str_repeat("\x00", 8192))))]);
|
||||||
|
|
||||||
$pk = new AddPlayerPacket();
|
$pk = new AddPlayerPacket();
|
||||||
$pk->uuid = $uuid;
|
$pk->uuid = $uuid;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user