Compare commits

...

19 Commits
3.8.6 ... 3.9.1

Author SHA1 Message Date
aaa01bb6f8 Release 3.9.1 2019-07-14 19:10:29 +01:00
50d71809e1 Entity: fixed onfire flag being set when setting fire ticks to zero, closes #3031 2019-07-14 19:03:06 +01:00
6839712394 added new PlayerActionPacket constant, silence debug noise every time a player clicks a block 2019-07-14 17:30:37 +01:00
9b5ae7ec75 regenerate LevelSoundEventPacket sound IDs 2019-07-14 17:28:29 +01:00
94eb64c2be 1.12: fix resource packs, closes #3023 2019-07-14 17:22:44 +01:00
3fae57508b update particle ids 2019-07-13 20:08:17 +01:00
a883c35fd0 clean up yesterday's mess 2019-07-13 18:15:14 +01:00
740398282f [ci skip] added some detail about packet changes in 3.9.0 release 2019-07-13 15:35:00 +01:00
9d14bc54d6 3.9.1 is next 2019-07-12 19:03:24 +01:00
bd69c66d03 Release 3.9.0 2019-07-12 19:03:23 +01:00
c58a1bf9b7 Protocol changes for 1.12.0.28 2019-07-12 19:00:15 +01:00
59c310b914 unfuck the make-release script 2019-07-12 18:59:54 +01:00
790fcc4ebb Release 3.8.7 2019-07-12 18:20:47 +01:00
5430f19e7a make-release: allow specifying a version number explicitly 2019-07-12 18:18:26 +01:00
1cf4cf8614 Fixed decoding entries in SetScorePacket
closes #3000
2019-07-09 15:49:24 +01:00
55cccff850 Player: fixed documentation of isValidUserName()
[ci skip]
2019-07-07 23:50:59 +01:00
03e70e68f4 Player: fixed documentation of getDisplayName()
[ci skip]
2019-07-07 23:49:11 +01:00
7c52b4c93d make-release: added a missing newline 2019-07-07 18:02:25 +01:00
3f31dbde57 3.8.7 is next 2019-07-07 17:49:37 +01:00
61 changed files with 1668 additions and 639 deletions

View File

@ -39,7 +39,11 @@ use const STDIN;
require_once dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
require_once dirname(__DIR__) . '/vendor/autoload.php';
$currentVer = new VersionString(BASE_VERSION);
if(isset($argv[1])){
$currentVer = new VersionString($argv[1]);
}else{
$currentVer = new VersionString(BASE_VERSION);
}
$nextVer = new VersionString(sprintf(
"%u.%u.%u",
$currentVer->getMajor(),
@ -47,27 +51,31 @@ $nextVer = new VersionString(sprintf(
$currentVer->getPatch() + 1
));
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev) : void{
$versionInfo = file_get_contents($versionInfoPath);
$versionInfo = preg_replace(
$pattern = '/^const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
'const BASE_VERSION = "' . $newVersion . '";',
$versionInfo
);
$versionInfo = preg_replace(
'/^const IS_DEVELOPMENT_BUILD = (?:true|false);$/m',
'const IS_DEVELOPMENT_BUILD = ' . ($isDev ? 'true' : 'false'). ';',
$versionInfo
);
file_put_contents($versionInfoPath, $versionInfo);
}
$versionInfoPath = dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
$versionInfo = file_get_contents($versionInfoPath);
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false);
file_put_contents($versionInfoPath, preg_replace(
'/^const IS_DEVELOPMENT_BUILD = true;$/m',
'const IS_DEVELOPMENT_BUILD = false;',
$versionInfo
));
echo "please add appropriate notes to the changelog and press enter...";
fgets(STDIN);
system('git add "' . dirname(__DIR__) . '/changelogs"');
system('git commit -m "Release ' . BASE_VERSION . '" --include "' . $versionInfoPath . '"');
system('git tag ' . BASE_VERSION);
file_put_contents($versionInfoPath, $mod = preg_replace(
$pattern = '/^const BASE_VERSION = "' . preg_quote(BASE_VERSION, '/') . '";$/m',
'const BASE_VERSION = "' . $nextVer->getBaseVersion() . '";',
$versionInfo
));
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
system('git tag ' . $currentVer->getBaseVersion());
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true);
system('git add "' . $versionInfoPath . '"');
system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"');
echo "pushing changes in 10 seconds";
echo "pushing changes in 10 seconds\n";
sleep(10);
system('git push origin HEAD ' . BASE_VERSION);
system('git push origin HEAD ' . $currentVer->getBaseVersion());

View File

@ -63,3 +63,7 @@ This changelog **does not account for protocol changes**. If your plugin uses th
- Fixed out-of-bounds access on invalid inventory data in player data saves.
- Fixed crash when custom liquids have flow decays which aren't factors of 4.
- Fixed `Entity->noDamageTicks` not working when the entity had no previous damage cause.
# 3.8.7
- Improved documentation of `Player->getDisplayName()` and `Player::isValidUserName()`.
- Fixed a bug in `SetScorePacket` decoding causing the entry list to always be empty.

46
changelogs/3.9.md Normal file
View File

@ -0,0 +1,46 @@
**For Minecraft: Bedrock Edition 1.12.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.9.0
- Added support for Minecraft: Bedrock Edition 1.12.0
- Removed compatibility with 1.11.0
## Protocol
- The following classes in the `\pocketmine\network\mcpe\protocol` namespace have been renamed:
- `AddEntityPacket` -> `AddActorPacket`
- `AddItemEntityPacket` -> `AddItemActorPacket`
- `AvailableEntityIdentifiersPacket` -> `AvailableActorIdentifiersPacket`
- `BlockEntityDataPacket` -> `BlockActorDataPacket`
- `EntityEventPacket` -> `ActorEventPacket`
- `EntityFallPacket` -> `ActorFallPacket`
- `EntityPickRequestPacket` -> `ActorPickRequestPacket`
- `MoveEntityAbsolutePacket` -> `MoveActorAbsolutePacket`
- `MoveEntityDeltaPacket` -> `MoveActorDeltaPacket`
- `RemoveEntityPacket` -> `RemoveActorPacket`
- `SetEntityDataPacket` -> `SetActorDataPacket`
- `SetEntityLinkPacket` -> `SetActorLinkPacket`
- `SetEntityMotionPacket` -> `SetActorMotionPacket`
- `TakeItemEntityPacket` -> `TakeItemActorPacket`
- The following classes in the `\pocketmine\network\mcpe\protocol` namespace have been removed:
- `FullChunkDataPacket`
- The following classes in the `\pocketmine\network\mcpe\protocol` namespace have been added:
- `AddEntityPacket` (not to be confused with the old one)
- `ClientCacheBlobStatusPacket`
- `ClientCacheMissResponsePacket`
- `ClientCacheStatusPacket`
- `LevelChunkPacket`
- `RemoveEntityPacket` (not to be confused with the old one)
- `StructureTemplateDataExportRequestPacket`
- `StructureTemplateDataExportResponsePacket`
# 3.9.1
- Fixed resource packs not working on 1.12 clients.
- Fixed some particles displaying incorrectly (some still don't render at all).
- Fixed `Entity->setFireTicks()` with a value of `0` setting the on-fire flag.
- Silenced a debug message which appeared every time a player right-clicked a block.
- Updated constants for `LevelSoundEventPacket`.

View File

@ -99,20 +99,20 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\network\mcpe\PlayerNetworkSessionAdapter;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket;
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
use pocketmine\network\mcpe\protocol\AvailableEntityIdentifiersPacket;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket;
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
use pocketmine\network\mcpe\protocol\BookEditPacket;
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\DisconnectPacket;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\InteractPacket;
use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
@ -211,7 +211,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
public const VIEW = Player::SPECTATOR;
/**
* Checks a supplied username and checks it is valid.
* Validates the given username.
*
* @param string $name
*
@ -800,7 +800,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
/**
* Gets the "friendly" name to display of this player to use in the chat.
* Returns the "friendly" display name of this player to use in the chat.
*
* @return string
*/
@ -2157,7 +2157,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$pk->worldName = $this->server->getMotd();
$this->dataPacket($pk);
$this->sendDataPacket(new AvailableEntityIdentifiersPacket());
$this->sendDataPacket(new AvailableActorIdentifiersPacket());
$this->sendDataPacket(new BiomeDefinitionListPacket());
$this->level->sendTime($this);
@ -2279,14 +2279,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return true;
}
public function handleEntityEvent(EntityEventPacket $packet) : bool{
public function handleEntityEvent(ActorEventPacket $packet) : bool{
if(!$this->spawned or !$this->isAlive()){
return true;
}
$this->doCloseInventory();
switch($packet->event){
case EntityEventPacket::EATING_ITEM:
case ActorEventPacket::EATING_ITEM:
if($packet->data === 0){
return false;
}
@ -2855,6 +2855,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
case PlayerActionPacket::ACTION_STOP_SWIMMING:
//TODO: handle this when it doesn't spam every damn tick (yet another spam bug!!)
break;
case PlayerActionPacket::ACTION_INTERACT_BLOCK: //ignored (for now)
break;
default:
$this->server->getLogger()->debug("Unhandled/unknown player action type " . $packet->action . " from " . $this->getName());
return false;
@ -2981,7 +2983,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return $handled;
}
public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{
public function handleBlockEntityData(BlockActorDataPacket $packet) : bool{
if(!$this->spawned or !$this->isAlive()){
return true;
}

View File

@ -22,6 +22,6 @@
namespace pocketmine;
const NAME = "PocketMine-MP";
const BASE_VERSION = "3.8.6";
const BASE_VERSION = "3.9.1";
const IS_DEVELOPMENT_BUILD = false;
const BUILD_NUMBER = 0;

View File

@ -62,12 +62,12 @@ use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\protocol\AddEntityPacket;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\MoveEntityAbsolutePacket;
use pocketmine\network\mcpe\protocol\RemoveEntityPacket;
use pocketmine\network\mcpe\protocol\SetEntityDataPacket;
use pocketmine\network\mcpe\protocol\SetEntityMotionPacket;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\AddActorPacket;
use pocketmine\network\mcpe\protocol\MoveActorAbsolutePacket;
use pocketmine\network\mcpe\protocol\RemoveActorPacket;
use pocketmine\network\mcpe\protocol\SetActorDataPacket;
use pocketmine\network\mcpe\protocol\SetActorMotionPacket;
use pocketmine\Player;
use pocketmine\plugin\Plugin;
use pocketmine\Server;
@ -154,70 +154,76 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
public const DATA_LEAD_HOLDER_EID = 37; //long
public const DATA_SCALE = 38; //float
public const DATA_HAS_NPC_COMPONENT = 39; //byte (???)
public const DATA_SKIN_ID = 40; //string
public const DATA_NPC_SKIN_ID = 41; //string
public const DATA_URL_TAG = 42; //string
public const DATA_MAX_AIR = 43; //short
public const DATA_MARK_VARIANT = 44; //int
public const DATA_CONTAINER_TYPE = 45; //byte (ContainerComponent)
public const DATA_CONTAINER_BASE_SIZE = 46; //int (ContainerComponent)
public const DATA_CONTAINER_EXTRA_SLOTS_PER_STRENGTH = 47; //int (used for llamas, inventory size is baseSize + thisProp * strength)
public const DATA_BLOCK_TARGET = 48; //block coords (ender crystal)
public const DATA_WITHER_INVULNERABLE_TICKS = 49; //int
public const DATA_WITHER_TARGET_1 = 50; //long
public const DATA_WITHER_TARGET_2 = 51; //long
public const DATA_WITHER_TARGET_3 = 52; //long
/* 53 (short) */
public const DATA_BOUNDING_BOX_WIDTH = 54; //float
public const DATA_BOUNDING_BOX_HEIGHT = 55; //float
public const DATA_FUSE_LENGTH = 56; //int
public const DATA_RIDER_SEAT_POSITION = 57; //vector3f
public const DATA_RIDER_ROTATION_LOCKED = 58; //byte
public const DATA_RIDER_MAX_ROTATION = 59; //float
public const DATA_RIDER_MIN_ROTATION = 60; //float
public const DATA_AREA_EFFECT_CLOUD_RADIUS = 61; //float
public const DATA_AREA_EFFECT_CLOUD_WAITING = 62; //int
public const DATA_AREA_EFFECT_CLOUD_PARTICLE_ID = 63; //int
/* 64 (int) shulker-related */
public const DATA_SHULKER_ATTACH_FACE = 65; //byte
/* 66 (short) shulker-related */
public const DATA_SHULKER_ATTACH_POS = 67; //block coords
public const DATA_TRADING_PLAYER_EID = 68; //long
public const DATA_NPC_SKIN_INDEX = 40; //string
public const DATA_NPC_ACTIONS = 41; //string (maybe JSON blob?)
public const DATA_MAX_AIR = 42; //short
public const DATA_MARK_VARIANT = 43; //int
public const DATA_CONTAINER_TYPE = 44; //byte (ContainerComponent)
public const DATA_CONTAINER_BASE_SIZE = 45; //int (ContainerComponent)
public const DATA_CONTAINER_EXTRA_SLOTS_PER_STRENGTH = 46; //int (used for llamas, inventory size is baseSize + thisProp * strength)
public const DATA_BLOCK_TARGET = 47; //block coords (ender crystal)
public const DATA_WITHER_INVULNERABLE_TICKS = 48; //int
public const DATA_WITHER_TARGET_1 = 49; //long
public const DATA_WITHER_TARGET_2 = 50; //long
public const DATA_WITHER_TARGET_3 = 51; //long
/* 52 (short) */
public const DATA_BOUNDING_BOX_WIDTH = 53; //float
public const DATA_BOUNDING_BOX_HEIGHT = 54; //float
public const DATA_FUSE_LENGTH = 55; //int
public const DATA_RIDER_SEAT_POSITION = 56; //vector3f
public const DATA_RIDER_ROTATION_LOCKED = 57; //byte
public const DATA_RIDER_MAX_ROTATION = 58; //float
public const DATA_RIDER_MIN_ROTATION = 59; //float
public const DATA_AREA_EFFECT_CLOUD_RADIUS = 60; //float
public const DATA_AREA_EFFECT_CLOUD_WAITING = 61; //int
public const DATA_AREA_EFFECT_CLOUD_PARTICLE_ID = 62; //int
/* 63 (int) shulker-related */
public const DATA_SHULKER_ATTACH_FACE = 64; //byte
/* 65 (short) shulker-related */
public const DATA_SHULKER_ATTACH_POS = 66; //block coords
public const DATA_TRADING_PLAYER_EID = 67; //long
/* 70 (byte) command-block */
public const DATA_COMMAND_BLOCK_COMMAND = 71; //string
public const DATA_COMMAND_BLOCK_LAST_OUTPUT = 72; //string
public const DATA_COMMAND_BLOCK_TRACK_OUTPUT = 73; //byte
public const DATA_CONTROLLING_RIDER_SEAT_NUMBER = 74; //byte
public const DATA_STRENGTH = 75; //int
public const DATA_MAX_STRENGTH = 76; //int
/* 77 (int) */
public const DATA_LIMITED_LIFE = 78;
public const DATA_ARMOR_STAND_POSE_INDEX = 79; //int
public const DATA_ENDER_CRYSTAL_TIME_OFFSET = 80; //int
public const DATA_ALWAYS_SHOW_NAMETAG = 81; //byte: -1 = default, 0 = only when looked at, 1 = always
public const DATA_COLOR_2 = 82; //byte
/* 83 (unknown) */
public const DATA_SCORE_TAG = 84; //string
public const DATA_BALLOON_ATTACHED_ENTITY = 85; //int64, entity unique ID of owner
public const DATA_PUFFERFISH_SIZE = 86; //byte
public const DATA_BOAT_BUBBLE_TIME = 87; //int (time in bubble column)
public const DATA_PLAYER_AGENT_EID = 88; //long
/* 89 (float) related to panda sitting
* 90 (float) related to panda sitting */
public const DATA_EAT_COUNTER = 91; //int (used by pandas)
public const DATA_FLAGS2 = 92; //long (extended data flags)
/* 93 (float) related to panda lying down
* 94 (float) related to panda lying down */
public const DATA_AREA_EFFECT_CLOUD_DURATION = 95; //int
public const DATA_AREA_EFFECT_CLOUD_SPAWN_TIME = 96; //int
public const DATA_AREA_EFFECT_CLOUD_RADIUS_PER_TICK = 97; //float, usually negative
public const DATA_AREA_EFFECT_CLOUD_RADIUS_CHANGE_ON_PICKUP = 98; //float
public const DATA_AREA_EFFECT_CLOUD_PICKUP_COUNT = 99; //int
public const DATA_INTERACTIVE_TAG = 100; //string (button text)
public const DATA_TRADE_TIER = 101; //int
public const DATA_MAX_TRADE_TIER = 102; //int
public const DATA_TRADE_XP = 103; //int
/* 69 (byte) command-block */
public const DATA_COMMAND_BLOCK_COMMAND = 70; //string
public const DATA_COMMAND_BLOCK_LAST_OUTPUT = 71; //string
public const DATA_COMMAND_BLOCK_TRACK_OUTPUT = 72; //byte
public const DATA_CONTROLLING_RIDER_SEAT_NUMBER = 73; //byte
public const DATA_STRENGTH = 74; //int
public const DATA_MAX_STRENGTH = 75; //int
/* 76 (int) */
public const DATA_LIMITED_LIFE = 77;
public const DATA_ARMOR_STAND_POSE_INDEX = 78; //int
public const DATA_ENDER_CRYSTAL_TIME_OFFSET = 79; //int
public const DATA_ALWAYS_SHOW_NAMETAG = 80; //byte: -1 = default, 0 = only when looked at, 1 = always
public const DATA_COLOR_2 = 81; //byte
/* 82 (unknown) */
public const DATA_SCORE_TAG = 83; //string
public const DATA_BALLOON_ATTACHED_ENTITY = 84; //int64, entity unique ID of owner
public const DATA_PUFFERFISH_SIZE = 85; //byte
public const DATA_BOAT_BUBBLE_TIME = 86; //int (time in bubble column)
public const DATA_PLAYER_AGENT_EID = 87; //long
/* 88 (float) related to panda sitting
* 89 (float) related to panda sitting */
public const DATA_EAT_COUNTER = 90; //int (used by pandas)
public const DATA_FLAGS2 = 91; //long (extended data flags)
/* 92 (float) related to panda lying down
* 93 (float) related to panda lying down */
public const DATA_AREA_EFFECT_CLOUD_DURATION = 94; //int
public const DATA_AREA_EFFECT_CLOUD_SPAWN_TIME = 95; //int
public const DATA_AREA_EFFECT_CLOUD_RADIUS_PER_TICK = 96; //float, usually negative
public const DATA_AREA_EFFECT_CLOUD_RADIUS_CHANGE_ON_PICKUP = 97; //float
public const DATA_AREA_EFFECT_CLOUD_PICKUP_COUNT = 98; //int
public const DATA_INTERACTIVE_TAG = 99; //string (button text)
public const DATA_TRADE_TIER = 100; //int
public const DATA_MAX_TRADE_TIER = 101; //int
public const DATA_TRADE_XP = 102; //int
public const DATA_SKIN_ID = 103; //int ???
/* 104 (int) related to wither */
public const DATA_COMMAND_BLOCK_TICK_DELAY = 105; //int
public const DATA_COMMAND_BLOCK_EXECUTE_ON_FIRST_TICK = 106; //byte
public const DATA_AMBIENT_SOUND_INTERVAL_MIN = 107; //float
public const DATA_AMBIENT_SOUND_INTERVAL_RANGE = 108; //float
public const DATA_AMBIENT_SOUND_EVENT = 109; //string
public const DATA_FLAG_ONFIRE = 0;
public const DATA_FLAG_SNEAKING = 1;
@ -1137,7 +1143,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$this->setFireTicks($ticks);
}
$this->setGenericFlag(self::DATA_FLAG_ONFIRE, true);
$this->setGenericFlag(self::DATA_FLAG_ONFIRE, $this->isOnFire());
}
/**
@ -1235,7 +1241,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
protected function broadcastMovement(bool $teleport = false) : void{
$pk = new MoveEntityAbsolutePacket();
$pk = new MoveActorAbsolutePacket();
$pk->entityRuntimeId = $this->id;
$pk->position = $this->getOffsetPosition($this);
@ -1247,14 +1253,14 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$pk->zRot = $this->yaw;
if($teleport){
$pk->flags |= MoveEntityAbsolutePacket::FLAG_TELEPORT;
$pk->flags |= MoveActorAbsolutePacket::FLAG_TELEPORT;
}
$this->level->broadcastPacketToViewers($this, $pk);
}
protected function broadcastMotion() : void{
$pk = new SetEntityMotionPacket();
$pk = new SetActorMotionPacket();
$pk->entityRuntimeId = $this->id;
$pk->motion = $this->getMotion();
@ -2021,7 +2027,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
* @param Player $player
*/
protected function sendSpawnPacket(Player $player) : void{
$pk = new AddEntityPacket();
$pk = new AddActorPacket();
$pk->entityRuntimeId = $this->getId();
$pk->type = static::NETWORK_ID;
$pk->position = $this->asVector3();
@ -2071,7 +2077,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
public function despawnFrom(Player $player, bool $send = true) : void{
if(isset($this->hasSpawned[$player->getLoaderId()])){
if($send){
$pk = new RemoveEntityPacket();
$pk = new RemoveActorPacket();
$pk->entityUniqueId = $this->id;
$player->dataPacket($pk);
}
@ -2193,7 +2199,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$player = [$player];
}
$pk = new SetEntityDataPacket();
$pk = new SetActorDataPacket();
$pk->entityRuntimeId = $this->getId();
$pk->metadata = $data ?? $this->propertyManager->getAll();
@ -2210,7 +2216,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
public function broadcastEntityEvent(int $eventId, ?int $eventData = null, ?array $players = null) : void{
$pk = new EntityEventPacket();
$pk = new ActorEventPacket();
$pk->entityRuntimeId = $this->id;
$pk->event = $eventId;
$pk->data = $eventData ?? 0;

View File

@ -46,8 +46,8 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\LevelEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\PlayerListPacket;
@ -754,7 +754,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$this->addEffect(new EffectInstance(Effect::getEffect(Effect::FIRE_RESISTANCE), 40 * 20, 1));
$this->addEffect(new EffectInstance(Effect::getEffect(Effect::ABSORPTION), 5 * 20, 1));
$this->broadcastEntityEvent(EntityEventPacket::CONSUME_TOTEM);
$this->broadcastEntityEvent(ActorEventPacket::CONSUME_TOTEM);
$this->level->broadcastLevelEvent($this->add(0, $this->eyeHeight, 0), LevelEventPacket::EVENT_SOUND_TOTEM);
$hand = $this->inventory->getItemInHand();

View File

@ -44,7 +44,7 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\MobEffectPacket;
use pocketmine\Player;
@ -143,7 +143,7 @@ abstract class Living extends Entity implements Damageable{
parent::setHealth($amount);
$this->attributeMap->getAttribute(Attribute::HEALTH)->setValue(ceil($this->getHealth()), true);
if($this->isAlive() and !$wasAlive){
$this->broadcastEntityEvent(EntityEventPacket::RESPAWN);
$this->broadcastEntityEvent(ActorEventPacket::RESPAWN);
}
}
@ -606,7 +606,7 @@ abstract class Living extends Entity implements Damageable{
}
protected function doHitAnimation() : void{
$this->broadcastEntityEvent(EntityEventPacket::HURT_ANIMATION);
$this->broadcastEntityEvent(ActorEventPacket::HURT_ANIMATION);
}
public function knockBack(Entity $attacker, float $damage, float $x, float $z, float $base = 0.4) : void{
@ -664,7 +664,7 @@ abstract class Living extends Entity implements Damageable{
}
protected function startDeathAnimation() : void{
$this->broadcastEntityEvent(EntityEventPacket::DEATH_ANIMATION);
$this->broadcastEntityEvent(ActorEventPacket::DEATH_ANIMATION);
}
protected function endDeathAnimation() : void{

View File

@ -28,7 +28,7 @@ use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use function atan2;
use function mt_rand;
use function sqrt;
@ -68,7 +68,7 @@ class Squid extends WaterAnimal{
$this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize();
}
$this->broadcastEntityEvent(EntityEventPacket::SQUID_INK_CLOUD);
$this->broadcastEntityEvent(ActorEventPacket::SQUID_INK_CLOUD);
}
}

View File

@ -28,8 +28,8 @@ use pocketmine\event\entity\ItemDespawnEvent;
use pocketmine\event\entity\ItemSpawnEvent;
use pocketmine\event\inventory\InventoryPickupItemEvent;
use pocketmine\item\Item;
use pocketmine\network\mcpe\protocol\AddItemEntityPacket;
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
use pocketmine\network\mcpe\protocol\AddItemActorPacket;
use pocketmine\network\mcpe\protocol\TakeItemActorPacket;
use pocketmine\Player;
use function get_class;
@ -192,7 +192,7 @@ class ItemEntity extends Entity{
}
protected function sendSpawnPacket(Player $player) : void{
$pk = new AddItemEntityPacket();
$pk = new AddItemActorPacket();
$pk->entityRuntimeId = $this->getId();
$pk->position = $this->asVector3();
$pk->motion = $this->getMotion();
@ -229,7 +229,7 @@ class ItemEntity extends Entity{
break;
}
$pk = new TakeItemEntityPacket();
$pk = new TakeItemActorPacket();
$pk->eid = $player->getId();
$pk->target = $this->getId();
$this->server->broadcastPacket($this->getViewers(), $pk);

View File

@ -152,9 +152,11 @@ class Painting extends Entity{
protected function sendSpawnPacket(Player $player) : void{
$pk = new AddPaintingPacket();
$pk->entityRuntimeId = $this->getId();
$pk->x = $this->blockIn->x;
$pk->y = $this->blockIn->y;
$pk->z = $this->blockIn->z;
$pk->position = new Vector3(
($this->boundingBox->minX + $this->boundingBox->maxX) / 2,
($this->boundingBox->minY + $this->boundingBox->maxY) / 2,
($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2
);
$pk->direction = $this->direction;
$pk->title = $this->motive;

View File

@ -32,9 +32,9 @@ use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\RayTraceResult;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
use pocketmine\network\mcpe\protocol\TakeItemActorPacket;
use pocketmine\Player;
use function mt_rand;
use function sqrt;
@ -143,7 +143,7 @@ class Arrow extends Projectile{
protected function onHitBlock(Block $blockHit, RayTraceResult $hitResult) : void{
parent::onHitBlock($blockHit, $hitResult);
$this->broadcastEntityEvent(EntityEventPacket::ARROW_SHAKE, 7); //7 ticks
$this->broadcastEntityEvent(ActorEventPacket::ARROW_SHAKE, 7); //7 ticks
}
protected function onHitEntity(Entity $entityHit, RayTraceResult $hitResult) : void{
@ -193,7 +193,7 @@ class Arrow extends Projectile{
return;
}
$pk = new TakeItemEntityPacket();
$pk = new TakeItemActorPacket();
$pk->eid = $player->getId();
$pk->target = $this->getId();
$this->server->broadcastPacket($this->getViewers(), $pk);

View File

@ -72,7 +72,7 @@ use pocketmine\metadata\Metadatable;
use pocketmine\metadata\MetadataValue;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\protocol\AddEntityPacket;
use pocketmine\network\mcpe\protocol\AddActorPacket;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\LevelEventPacket;
@ -564,7 +564,7 @@ class Level implements ChunkManager, Metadatable{
$pk = new LevelSoundEventPacket();
$pk->sound = $soundId;
$pk->extraData = $extraData;
$pk->entityType = AddEntityPacket::LEGACY_ID_MAP_BC[$entityTypeId] ?? ":";
$pk->entityType = AddActorPacket::LEGACY_ID_MAP_BC[$entityTypeId] ?? ":";
$pk->isBabyMob = $isBabyMob;
$pk->disableRelativeVolume = $disableRelativeVolume;
$pk->position = $pos->asVector3();

View File

@ -869,13 +869,10 @@ class Chunk{
public function networkSerialize() : string{
$result = "";
$subChunkCount = $this->getSubChunkSendCount();
$result .= chr($subChunkCount);
for($y = 0; $y < $subChunkCount; ++$y){
$result .= $this->subChunks[$y]->networkSerialize();
}
$result .= pack("v*", ...$this->heightMap)
. $this->biomeIds
. chr(0); //border block array count
$result .= $this->biomeIds . chr(0); //border block array count
//Border block entry format: 1 byte (4 bits X, 4 bits Z). These are however useless since they crash the regular client.
foreach($this->tiles as $tile){

View File

@ -26,7 +26,7 @@ namespace pocketmine\level\format\io;
use pocketmine\level\format\Chunk;
use pocketmine\level\Level;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\FullChunkDataPacket;
use pocketmine\network\mcpe\protocol\LevelChunkPacket;
use pocketmine\scheduler\AsyncTask;
use pocketmine\Server;
use function assert;
@ -42,6 +42,9 @@ class ChunkRequestTask extends AsyncTask{
protected $compressionLevel;
/** @var int */
private $subChunkCount;
public function __construct(Level $level, int $chunkX, int $chunkZ, Chunk $chunk){
$this->levelId = $level->getId();
$this->compressionLevel = $level->getServer()->networkCompressionLevel;
@ -49,13 +52,11 @@ class ChunkRequestTask extends AsyncTask{
$this->chunk = $chunk->networkSerialize();
$this->chunkX = $chunkX;
$this->chunkZ = $chunkZ;
$this->subChunkCount = $chunk->getSubChunkSendCount();
}
public function onRun(){
$pk = new FullChunkDataPacket();
$pk->chunkX = $this->chunkX;
$pk->chunkZ = $this->chunkZ;
$pk->data = $this->chunk;
$pk = LevelChunkPacket::withoutCache($this->chunkX, $this->chunkZ, $this->subChunkCount, $this->chunk);
$batch = new BatchPacket();
$batch->addPacket($pk);

View File

@ -30,7 +30,7 @@ use pocketmine\item\ItemFactory;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\PlayerListPacket;
use pocketmine\network\mcpe\protocol\RemoveEntityPacket;
use pocketmine\network\mcpe\protocol\RemoveActorPacket;
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
use pocketmine\utils\UUID;
use function str_repeat;
@ -84,7 +84,7 @@ class FloatingTextParticle extends Particle{
if($this->entityId === null){
$this->entityId = Entity::$entityCount++;
}else{
$pk0 = new RemoveEntityPacket();
$pk0 = new RemoveActorPacket();
$pk0->entityUniqueId = $this->entityId;
$p[] = $pk0;

View File

@ -29,59 +29,67 @@ use pocketmine\network\mcpe\protocol\DataPacket;
abstract class Particle extends Vector3{
public const TYPE_BUBBLE = 1;
public const TYPE_CRITICAL = 2;
public const TYPE_BLOCK_FORCE_FIELD = 3;
public const TYPE_SMOKE = 4;
public const TYPE_EXPLODE = 5;
public const TYPE_EVAPORATION = 6;
public const TYPE_FLAME = 7;
public const TYPE_LAVA = 8;
public const TYPE_LARGE_SMOKE = 9;
public const TYPE_REDSTONE = 10;
public const TYPE_RISING_RED_DUST = 11;
public const TYPE_ITEM_BREAK = 12;
public const TYPE_SNOWBALL_POOF = 13;
public const TYPE_HUGE_EXPLODE = 14;
public const TYPE_HUGE_EXPLODE_SEED = 15;
public const TYPE_MOB_FLAME = 16;
public const TYPE_HEART = 17;
public const TYPE_TERRAIN = 18;
public const TYPE_SUSPENDED_TOWN = 19, TYPE_TOWN_AURA = 19;
public const TYPE_PORTAL = 20;
public const TYPE_SPLASH = 21, TYPE_WATER_SPLASH = 21;
public const TYPE_WATER_WAKE = 22;
public const TYPE_DRIP_WATER = 23;
public const TYPE_DRIP_LAVA = 24;
public const TYPE_FALLING_DUST = 25, TYPE_DUST = 25;
public const TYPE_MOB_SPELL = 26;
public const TYPE_MOB_SPELL_AMBIENT = 27;
public const TYPE_MOB_SPELL_INSTANTANEOUS = 28;
public const TYPE_INK = 29;
public const TYPE_SLIME = 30;
public const TYPE_RAIN_SPLASH = 31;
public const TYPE_VILLAGER_ANGRY = 32;
public const TYPE_VILLAGER_HAPPY = 33;
public const TYPE_ENCHANTMENT_TABLE = 34;
public const TYPE_TRACKING_EMITTER = 35;
public const TYPE_NOTE = 36;
public const TYPE_WITCH_SPELL = 37;
public const TYPE_CARROT = 38;
//39 unknown
public const TYPE_END_ROD = 40;
public const TYPE_DRAGONS_BREATH = 41;
public const TYPE_SPIT = 42;
public const TYPE_TOTEM = 43;
public const TYPE_FOOD = 44;
public const TYPE_FIREWORKS_STARTER = 45;
public const TYPE_FIREWORKS_SPARK = 46;
public const TYPE_FIREWORKS_OVERLAY = 47;
public const TYPE_BALLOON_GAS = 48;
public const TYPE_COLORED_FLAME = 49;
public const TYPE_SPARKLER = 50;
public const TYPE_CONDUIT = 51;
public const TYPE_BUBBLE_COLUMN_UP = 52;
public const TYPE_BUBBLE_COLUMN_DOWN = 53;
public const TYPE_SNEEZE = 54;
//2 same as 1
public const TYPE_CRITICAL = 3;
public const TYPE_BLOCK_FORCE_FIELD = 4;
public const TYPE_SMOKE = 5;
public const TYPE_EXPLODE = 6;
public const TYPE_EVAPORATION = 7;
public const TYPE_FLAME = 8;
public const TYPE_LAVA = 9;
public const TYPE_LARGE_SMOKE = 10;
public const TYPE_REDSTONE = 11;
public const TYPE_RISING_RED_DUST = 12;
//62 same as 12
public const TYPE_ITEM_BREAK = 13;
public const TYPE_SNOWBALL_POOF = 14;
public const TYPE_HUGE_EXPLODE = 15;
//60 same as 15
public const TYPE_HUGE_EXPLODE_SEED = 16;
public const TYPE_MOB_FLAME = 17;
public const TYPE_HEART = 18;
public const TYPE_TERRAIN = 19;
public const TYPE_SUSPENDED_TOWN = 20, TYPE_TOWN_AURA = 20;
//61 same as 20
public const TYPE_PORTAL = 21;
//22 same as 21
public const TYPE_SPLASH = 23, TYPE_WATER_SPLASH = 23;
//24 same as 23
public const TYPE_WATER_WAKE = 25;
public const TYPE_DRIP_WATER = 26;
public const TYPE_DRIP_LAVA = 27;
public const TYPE_FALLING_DUST = 28, TYPE_DUST = 28;
public const TYPE_MOB_SPELL = 29;
public const TYPE_MOB_SPELL_AMBIENT = 30;
public const TYPE_MOB_SPELL_INSTANTANEOUS = 31;
public const TYPE_INK = 32;
public const TYPE_SLIME = 33;
public const TYPE_RAIN_SPLASH = 34;
public const TYPE_VILLAGER_ANGRY = 35;
//59 same as 35
public const TYPE_VILLAGER_HAPPY = 36;
public const TYPE_ENCHANTMENT_TABLE = 37;
public const TYPE_TRACKING_EMITTER = 38;
public const TYPE_NOTE = 39;
public const TYPE_WITCH_SPELL = 40;
public const TYPE_CARROT = 41;
//42 unknown
public const TYPE_END_ROD = 43;
//58 same as 43
public const TYPE_DRAGONS_BREATH = 44;
public const TYPE_SPIT = 45;
public const TYPE_TOTEM = 46;
public const TYPE_FOOD = 47;
public const TYPE_FIREWORKS_STARTER = 48;
public const TYPE_FIREWORKS_SPARK = 49;
public const TYPE_FIREWORKS_OVERLAY = 50;
public const TYPE_BALLOON_GAS = 51;
public const TYPE_COLORED_FLAME = 52;
public const TYPE_SPARKLER = 53;
public const TYPE_CONDUIT = 54;
public const TYPE_BUBBLE_COLUMN_UP = 55;
public const TYPE_BUBBLE_COLUMN_DOWN = 56;
public const TYPE_SNEEZE = 57;
/**
* @return DataPacket|DataPacket[]

View File

@ -27,12 +27,14 @@ namespace pocketmine\network\mcpe;
use pocketmine\entity\Attribute;
use pocketmine\entity\Entity;
use pocketmine\item\Durable;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\ItemIds;
use pocketmine\math\Vector3;
use pocketmine\nbt\NetworkLittleEndianNBTStream;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\network\mcpe\protocol\types\CommandOriginData;
use pocketmine\network\mcpe\protocol\types\EntityLink;
use pocketmine\utils\BinaryStream;
@ -42,6 +44,9 @@ use function strlen;
class NetworkBinaryStream extends BinaryStream{
private const DAMAGE_TAG = "Damage"; //TAG_Int
private const DAMAGE_TAG_CONFLICT_RESOLUTION = "___Damage_ProtocolCollisionResolution___";
public function getString() : string{
return $this->get($this->getUnsignedVarInt());
}
@ -76,15 +81,12 @@ class NetworkBinaryStream extends BinaryStream{
$auxValue = $this->getVarInt();
$data = $auxValue >> 8;
if($data === 0x7fff){
$data = -1;
}
$cnt = $auxValue & 0xff;
$nbtLen = $this->getLShort();
/** @var CompoundTag|string $nbt */
$nbt = "";
/** @var CompoundTag|null $nbt */
$nbt = null;
if($nbtLen === 0xffff){
$c = $this->getByte();
if($c !== 1){
@ -108,7 +110,22 @@ class NetworkBinaryStream extends BinaryStream{
if($id === ItemIds::SHIELD){
$this->getVarLong(); //"blocking tick" (ffs mojang)
}
if($nbt !== null){
if($nbt->hasTag(self::DAMAGE_TAG, IntTag::class)){
$data = $nbt->getInt(self::DAMAGE_TAG);
$nbt->removeTag(self::DAMAGE_TAG);
if($nbt->count() === 0){
$nbt = null;
goto end;
}
}
if(($conflicted = $nbt->getTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION)) !== null){
$nbt->removeTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION);
$conflicted->setName(self::DAMAGE_TAG);
$nbt->setTag($conflicted);
}
}
end:
return ItemFactory::get($id, $data, $cnt, $nbt);
}
@ -124,10 +141,27 @@ class NetworkBinaryStream extends BinaryStream{
$auxValue = (($item->getDamage() & 0x7fff) << 8) | $item->getCount();
$this->putVarInt($auxValue);
$nbt = null;
if($item->hasCompoundTag()){
$nbt = clone $item->getNamedTag();
}
if($item instanceof Durable and $item->getDamage() > 0){
if($nbt !== null){
if(($existing = $nbt->getTag(self::DAMAGE_TAG)) !== null){
$nbt->removeTag(self::DAMAGE_TAG);
$existing->setName(self::DAMAGE_TAG_CONFLICT_RESOLUTION);
$nbt->setTag($existing);
}
}else{
$nbt = new CompoundTag();
}
$nbt->setInt(self::DAMAGE_TAG, $item->getDamage());
}
if($nbt !== null){
$this->putLShort(0xffff);
$this->putByte(1); //TODO: some kind of count field? always 1 as of 1.9.0
$this->put((new NetworkLittleEndianNBTStream())->write($item->getNamedTag()));
$this->put((new NetworkLittleEndianNBTStream())->write($nbt));
}else{
$this->putLShort(0);
}
@ -140,6 +174,29 @@ class NetworkBinaryStream extends BinaryStream{
}
}
public function getRecipeIngredient() : Item{
$id = $this->getVarInt();
if($id === 0){
return ItemFactory::get(ItemIds::AIR, 0, 0);
}
$meta = $this->getVarInt();
if($meta === 0x7fff){
$meta = -1;
}
$count = $this->getVarInt();
return ItemFactory::get($id, $meta, $count);
}
public function putRecipeIngredient(Item $item) : void{
if($item->isNull()){
$this->putVarInt(0);
}else{
$this->putVarInt($item->getId());
$this->putVarInt($item->getDamage() & 0x7fff);
$this->putVarInt($item->getCount());
}
}
/**
* Decodes entity metadata from the stream.
*

View File

@ -23,18 +23,22 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\ActorFallPacket;
use pocketmine\network\mcpe\protocol\ActorPickRequestPacket;
use pocketmine\network\mcpe\protocol\AddActorPacket;
use pocketmine\network\mcpe\protocol\AddBehaviorTreePacket;
use pocketmine\network\mcpe\protocol\AddEntityPacket;
use pocketmine\network\mcpe\protocol\AddItemEntityPacket;
use pocketmine\network\mcpe\protocol\AddItemActorPacket;
use pocketmine\network\mcpe\protocol\AddPaintingPacket;
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\AutomationClientConnectPacket;
use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket;
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
use pocketmine\network\mcpe\protocol\AvailableEntityIdentifiersPacket;
use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket;
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
use pocketmine\network\mcpe\protocol\BlockEventPacket;
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
use pocketmine\network\mcpe\protocol\BookEditPacket;
@ -43,6 +47,9 @@ use pocketmine\network\mcpe\protocol\CameraPacket;
use pocketmine\network\mcpe\protocol\ChangeDimensionPacket;
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
use pocketmine\network\mcpe\protocol\ClientboundMapItemDataPacket;
use pocketmine\network\mcpe\protocol\ClientCacheBlobStatusPacket;
use pocketmine\network\mcpe\protocol\ClientCacheMissResponsePacket;
use pocketmine\network\mcpe\protocol\ClientCacheStatusPacket;
use pocketmine\network\mcpe\protocol\ClientToServerHandshakePacket;
use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket;
use pocketmine\network\mcpe\protocol\CommandOutputPacket;
@ -54,12 +61,8 @@ use pocketmine\network\mcpe\protocol\CraftingDataPacket;
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\DisconnectPacket;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\EntityFallPacket;
use pocketmine\network\mcpe\protocol\EntityPickRequestPacket;
use pocketmine\network\mcpe\protocol\EventPacket;
use pocketmine\network\mcpe\protocol\ExplodePacket;
use pocketmine\network\mcpe\protocol\FullChunkDataPacket;
use pocketmine\network\mcpe\protocol\GameRulesChangedPacket;
use pocketmine\network\mcpe\protocol\GuiDataPickItemPacket;
use pocketmine\network\mcpe\protocol\HurtArmorPacket;
@ -70,6 +73,8 @@ use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
use pocketmine\network\mcpe\protocol\LabTablePacket;
use pocketmine\network\mcpe\protocol\LecternUpdatePacket;
use pocketmine\network\mcpe\protocol\LevelChunkPacket;
use pocketmine\network\mcpe\protocol\LevelEventGenericPacket;
use pocketmine\network\mcpe\protocol\LevelEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacketV1;
@ -82,8 +87,8 @@ use pocketmine\network\mcpe\protocol\MobEffectPacket;
use pocketmine\network\mcpe\protocol\MobEquipmentPacket;
use pocketmine\network\mcpe\protocol\ModalFormRequestPacket;
use pocketmine\network\mcpe\protocol\ModalFormResponsePacket;
use pocketmine\network\mcpe\protocol\MoveEntityAbsolutePacket;
use pocketmine\network\mcpe\protocol\MoveEntityDeltaPacket;
use pocketmine\network\mcpe\protocol\MoveActorAbsolutePacket;
use pocketmine\network\mcpe\protocol\MoveActorDeltaPacket;
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
use pocketmine\network\mcpe\protocol\NetworkChunkPublisherUpdatePacket;
use pocketmine\network\mcpe\protocol\NetworkStackLatencyPacket;
@ -98,6 +103,7 @@ use pocketmine\network\mcpe\protocol\PlayerSkinPacket;
use pocketmine\network\mcpe\protocol\PlaySoundPacket;
use pocketmine\network\mcpe\protocol\PlayStatusPacket;
use pocketmine\network\mcpe\protocol\PurchaseReceiptPacket;
use pocketmine\network\mcpe\protocol\RemoveActorPacket;
use pocketmine\network\mcpe\protocol\RemoveEntityPacket;
use pocketmine\network\mcpe\protocol\RemoveObjectivePacket;
use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket;
@ -113,13 +119,13 @@ use pocketmine\network\mcpe\protocol\ScriptCustomEventPacket;
use pocketmine\network\mcpe\protocol\ServerSettingsRequestPacket;
use pocketmine\network\mcpe\protocol\ServerSettingsResponsePacket;
use pocketmine\network\mcpe\protocol\ServerToClientHandshakePacket;
use pocketmine\network\mcpe\protocol\SetActorDataPacket;
use pocketmine\network\mcpe\protocol\SetActorLinkPacket;
use pocketmine\network\mcpe\protocol\SetActorMotionPacket;
use pocketmine\network\mcpe\protocol\SetCommandsEnabledPacket;
use pocketmine\network\mcpe\protocol\SetDefaultGameTypePacket;
use pocketmine\network\mcpe\protocol\SetDifficultyPacket;
use pocketmine\network\mcpe\protocol\SetDisplayObjectivePacket;
use pocketmine\network\mcpe\protocol\SetEntityDataPacket;
use pocketmine\network\mcpe\protocol\SetEntityLinkPacket;
use pocketmine\network\mcpe\protocol\SetEntityMotionPacket;
use pocketmine\network\mcpe\protocol\SetHealthPacket;
use pocketmine\network\mcpe\protocol\SetLastHurtByPacket;
use pocketmine\network\mcpe\protocol\SetLocalPlayerAsInitializedPacket;
@ -138,12 +144,15 @@ use pocketmine\network\mcpe\protocol\SpawnParticleEffectPacket;
use pocketmine\network\mcpe\protocol\StartGamePacket;
use pocketmine\network\mcpe\protocol\StopSoundPacket;
use pocketmine\network\mcpe\protocol\StructureBlockUpdatePacket;
use pocketmine\network\mcpe\protocol\StructureTemplateDataExportRequestPacket;
use pocketmine\network\mcpe\protocol\StructureTemplateDataExportResponsePacket;
use pocketmine\network\mcpe\protocol\SubClientLoginPacket;
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
use pocketmine\network\mcpe\protocol\TakeItemActorPacket;
use pocketmine\network\mcpe\protocol\TextPacket;
use pocketmine\network\mcpe\protocol\TransferPacket;
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPropertiesPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockSyncedPacket;
use pocketmine\network\mcpe\protocol\UpdateEquipPacket;
use pocketmine\network\mcpe\protocol\UpdateSoftEnumPacket;
@ -202,23 +211,23 @@ abstract class NetworkSession{
return false;
}
public function handleAddEntity(AddEntityPacket $packet) : bool{
public function handleAddActor(AddActorPacket $packet) : bool{
return false;
}
public function handleRemoveEntity(RemoveEntityPacket $packet) : bool{
public function handleRemoveActor(RemoveActorPacket $packet) : bool{
return false;
}
public function handleAddItemEntity(AddItemEntityPacket $packet) : bool{
public function handleAddItemActor(AddItemActorPacket $packet) : bool{
return false;
}
public function handleTakeItemEntity(TakeItemEntityPacket $packet) : bool{
public function handleTakeItemActor(TakeItemActorPacket $packet) : bool{
return false;
}
public function handleMoveEntityAbsolute(MoveEntityAbsolutePacket $packet) : bool{
public function handleMoveActorAbsolute(MoveActorAbsolutePacket $packet) : bool{
return false;
}
@ -254,7 +263,7 @@ abstract class NetworkSession{
return false;
}
public function handleEntityEvent(EntityEventPacket $packet) : bool{
public function handleActorEvent(ActorEventPacket $packet) : bool{
return false;
}
@ -286,7 +295,7 @@ abstract class NetworkSession{
return false;
}
public function handleEntityPickRequest(EntityPickRequestPacket $packet) : bool{
public function handleActorPickRequest(ActorPickRequestPacket $packet) : bool{
return false;
}
@ -294,7 +303,7 @@ abstract class NetworkSession{
return false;
}
public function handleEntityFall(EntityFallPacket $packet) : bool{
public function handleActorFall(ActorFallPacket $packet) : bool{
return false;
}
@ -302,15 +311,15 @@ abstract class NetworkSession{
return false;
}
public function handleSetEntityData(SetEntityDataPacket $packet) : bool{
public function handleSetActorData(SetActorDataPacket $packet) : bool{
return false;
}
public function handleSetEntityMotion(SetEntityMotionPacket $packet) : bool{
public function handleSetActorMotion(SetActorMotionPacket $packet) : bool{
return false;
}
public function handleSetEntityLink(SetEntityLinkPacket $packet) : bool{
public function handleSetActorLink(SetActorLinkPacket $packet) : bool{
return false;
}
@ -370,7 +379,7 @@ abstract class NetworkSession{
return false;
}
public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{
public function handleBlockActorData(BlockActorDataPacket $packet) : bool{
return false;
}
@ -378,7 +387,7 @@ abstract class NetworkSession{
return false;
}
public function handleFullChunkData(FullChunkDataPacket $packet) : bool{
public function handleLevelChunk(LevelChunkPacket $packet) : bool{
return false;
}
@ -590,7 +599,7 @@ abstract class NetworkSession{
return false;
}
public function handleMoveEntityDelta(MoveEntityDeltaPacket $packet) : bool{
public function handleMoveActorDelta(MoveActorDeltaPacket $packet) : bool{
return false;
}
@ -618,7 +627,7 @@ abstract class NetworkSession{
return false;
}
public function handleAvailableEntityIdentifiers(AvailableEntityIdentifiersPacket $packet) : bool{
public function handleAvailableActorIdentifiers(AvailableActorIdentifiersPacket $packet) : bool{
return false;
}
@ -638,6 +647,10 @@ abstract class NetworkSession{
return false;
}
public function handleLevelEventGeneric(LevelEventGenericPacket $packet) : bool{
return false;
}
public function handleLecternUpdate(LecternUpdatePacket $packet) : bool{
return false;
}
@ -646,11 +659,43 @@ abstract class NetworkSession{
return false;
}
public function handleMapCreateLockedCopy(MapCreateLockedCopyPacket $packet) : bool{
public function handleAddEntity(AddEntityPacket $packet) : bool{
return false;
}
public function handleRemoveEntity(RemoveEntityPacket $packet) : bool{
return false;
}
public function handleClientCacheStatus(ClientCacheStatusPacket $packet) : bool{
return false;
}
public function handleOnScreenTextureAnimation(OnScreenTextureAnimationPacket $packet) : bool{
return false;
}
public function handleMapCreateLockedCopy(MapCreateLockedCopyPacket $packet) : bool{
return false;
}
public function handleStructureTemplateDataExportRequest(StructureTemplateDataExportRequestPacket $packet) : bool{
return false;
}
public function handleStructureTemplateDataExportResponse(StructureTemplateDataExportResponsePacket $packet) : bool{
return false;
}
public function handleUpdateBlockProperties(UpdateBlockPropertiesPacket $packet) : bool{
return false;
}
public function handleClientCacheBlobStatus(ClientCacheBlobStatusPacket $packet) : bool{
return false;
}
public function handleClientCacheMissResponse(ClientCacheMissResponsePacket $packet) : bool{
return false;
}
}

View File

@ -25,9 +25,12 @@ namespace pocketmine\network\mcpe;
use pocketmine\event\server\DataPacketReceiveEvent;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\ActorFallPacket;
use pocketmine\network\mcpe\protocol\ActorPickRequestPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
use pocketmine\network\mcpe\protocol\BookEditPacket;
use pocketmine\network\mcpe\protocol\BossEventPacket;
@ -37,9 +40,6 @@ use pocketmine\network\mcpe\protocol\CommandRequestPacket;
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\EntityFallPacket;
use pocketmine\network\mcpe\protocol\EntityPickRequestPacket;
use pocketmine\network\mcpe\protocol\InteractPacket;
use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
@ -142,7 +142,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
return true; //useless leftover from 1.8
}
public function handleEntityEvent(EntityEventPacket $packet) : bool{
public function handleActorEvent(ActorEventPacket $packet) : bool{
return $this->player->handleEntityEvent($packet);
}
@ -166,7 +166,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
return $this->player->handleBlockPickRequest($packet);
}
public function handleEntityPickRequest(EntityPickRequestPacket $packet) : bool{
public function handleActorPickRequest(ActorPickRequestPacket $packet) : bool{
return false; //TODO
}
@ -174,7 +174,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
return $this->player->handlePlayerAction($packet);
}
public function handleEntityFall(EntityFallPacket $packet) : bool{
public function handleActorFall(ActorFallPacket $packet) : bool{
return true; //Not used
}
@ -198,7 +198,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
return $this->player->handleAdventureSettings($packet);
}
public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{
public function handleBlockActorData(BlockActorDataPacket $packet) : bool{
return $this->player->handleBlockEntityData($packet);
}

View File

@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\mcpe\NetworkSession;
class EntityEventPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ENTITY_EVENT_PACKET;
class ActorEventPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ACTOR_EVENT_PACKET;
public const HURT_ANIMATION = 2;
public const DEATH_ANIMATION = 3;
@ -103,6 +103,6 @@ class EntityEventPacket extends DataPacket{
}
public function handle(NetworkSession $session) : bool{
return $session->handleEntityEvent($this);
return $session->handleActorEvent($this);
}
}

View File

@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\mcpe\NetworkSession;
class EntityFallPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ENTITY_FALL_PACKET;
class ActorFallPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ACTOR_FALL_PACKET;
/** @var int */
public $entityRuntimeId;
@ -51,6 +51,6 @@ class EntityFallPacket extends DataPacket{
}
public function handle(NetworkSession $session) : bool{
return $session->handleEntityFall($this);
return $session->handleActorFall($this);
}
}

View File

@ -27,8 +27,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\mcpe\NetworkSession;
class EntityPickRequestPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ENTITY_PICK_REQUEST_PACKET;
class ActorPickRequestPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ACTOR_PICK_REQUEST_PACKET;
/** @var int */
public $entityUniqueId;
@ -46,6 +46,6 @@ class EntityPickRequestPacket extends DataPacket{
}
public function handle(NetworkSession $session) : bool{
return $session->handleEntityPickRequest($this);
return $session->handleActorPickRequest($this);
}
}

View File

@ -0,0 +1,240 @@
<?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\entity\Attribute;
use pocketmine\entity\EntityIds;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\types\EntityLink;
use function array_search;
use function count;
class AddActorPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ADD_ACTOR_PACKET;
/*
* Really really really really really nasty hack, to preserve backwards compatibility.
* We can't transition to string IDs within 3.x because the network IDs (the integer ones) are exposed
* to the API in some places (for god's sake shoghi).
*
* TODO: remove this on 4.0
*/
public const LEGACY_ID_MAP_BC = [
EntityIds::NPC => "minecraft:npc",
EntityIds::PLAYER => "minecraft:player",
EntityIds::WITHER_SKELETON => "minecraft:wither_skeleton",
EntityIds::HUSK => "minecraft:husk",
EntityIds::STRAY => "minecraft:stray",
EntityIds::WITCH => "minecraft:witch",
EntityIds::ZOMBIE_VILLAGER => "minecraft:zombie_villager",
EntityIds::BLAZE => "minecraft:blaze",
EntityIds::MAGMA_CUBE => "minecraft:magma_cube",
EntityIds::GHAST => "minecraft:ghast",
EntityIds::CAVE_SPIDER => "minecraft:cave_spider",
EntityIds::SILVERFISH => "minecraft:silverfish",
EntityIds::ENDERMAN => "minecraft:enderman",
EntityIds::SLIME => "minecraft:slime",
EntityIds::ZOMBIE_PIGMAN => "minecraft:zombie_pigman",
EntityIds::SPIDER => "minecraft:spider",
EntityIds::SKELETON => "minecraft:skeleton",
EntityIds::CREEPER => "minecraft:creeper",
EntityIds::ZOMBIE => "minecraft:zombie",
EntityIds::SKELETON_HORSE => "minecraft:skeleton_horse",
EntityIds::MULE => "minecraft:mule",
EntityIds::DONKEY => "minecraft:donkey",
EntityIds::DOLPHIN => "minecraft:dolphin",
EntityIds::TROPICALFISH => "minecraft:tropicalfish",
EntityIds::WOLF => "minecraft:wolf",
EntityIds::SQUID => "minecraft:squid",
EntityIds::DROWNED => "minecraft:drowned",
EntityIds::SHEEP => "minecraft:sheep",
EntityIds::MOOSHROOM => "minecraft:mooshroom",
EntityIds::PANDA => "minecraft:panda",
EntityIds::SALMON => "minecraft:salmon",
EntityIds::PIG => "minecraft:pig",
EntityIds::VILLAGER => "minecraft:villager",
EntityIds::COD => "minecraft:cod",
EntityIds::PUFFERFISH => "minecraft:pufferfish",
EntityIds::COW => "minecraft:cow",
EntityIds::CHICKEN => "minecraft:chicken",
EntityIds::BALLOON => "minecraft:balloon",
EntityIds::LLAMA => "minecraft:llama",
EntityIds::IRON_GOLEM => "minecraft:iron_golem",
EntityIds::RABBIT => "minecraft:rabbit",
EntityIds::SNOW_GOLEM => "minecraft:snow_golem",
EntityIds::BAT => "minecraft:bat",
EntityIds::OCELOT => "minecraft:ocelot",
EntityIds::HORSE => "minecraft:horse",
EntityIds::CAT => "minecraft:cat",
EntityIds::POLAR_BEAR => "minecraft:polar_bear",
EntityIds::ZOMBIE_HORSE => "minecraft:zombie_horse",
EntityIds::TURTLE => "minecraft:turtle",
EntityIds::PARROT => "minecraft:parrot",
EntityIds::GUARDIAN => "minecraft:guardian",
EntityIds::ELDER_GUARDIAN => "minecraft:elder_guardian",
EntityIds::VINDICATOR => "minecraft:vindicator",
EntityIds::WITHER => "minecraft:wither",
EntityIds::ENDER_DRAGON => "minecraft:ender_dragon",
EntityIds::SHULKER => "minecraft:shulker",
EntityIds::ENDERMITE => "minecraft:endermite",
EntityIds::MINECART => "minecraft:minecart",
EntityIds::HOPPER_MINECART => "minecraft:hopper_minecart",
EntityIds::TNT_MINECART => "minecraft:tnt_minecart",
EntityIds::CHEST_MINECART => "minecraft:chest_minecart",
EntityIds::COMMAND_BLOCK_MINECART => "minecraft:command_block_minecart",
EntityIds::ARMOR_STAND => "minecraft:armor_stand",
EntityIds::ITEM => "minecraft:item",
EntityIds::TNT => "minecraft:tnt",
EntityIds::FALLING_BLOCK => "minecraft:falling_block",
EntityIds::XP_BOTTLE => "minecraft:xp_bottle",
EntityIds::XP_ORB => "minecraft:xp_orb",
EntityIds::EYE_OF_ENDER_SIGNAL => "minecraft:eye_of_ender_signal",
EntityIds::ENDER_CRYSTAL => "minecraft:ender_crystal",
EntityIds::SHULKER_BULLET => "minecraft:shulker_bullet",
EntityIds::FISHING_HOOK => "minecraft:fishing_hook",
EntityIds::DRAGON_FIREBALL => "minecraft:dragon_fireball",
EntityIds::ARROW => "minecraft:arrow",
EntityIds::SNOWBALL => "minecraft:snowball",
EntityIds::EGG => "minecraft:egg",
EntityIds::PAINTING => "minecraft:painting",
EntityIds::THROWN_TRIDENT => "minecraft:thrown_trident",
EntityIds::FIREBALL => "minecraft:fireball",
EntityIds::SPLASH_POTION => "minecraft:splash_potion",
EntityIds::ENDER_PEARL => "minecraft:ender_pearl",
EntityIds::LEASH_KNOT => "minecraft:leash_knot",
EntityIds::WITHER_SKULL => "minecraft:wither_skull",
EntityIds::WITHER_SKULL_DANGEROUS => "minecraft:wither_skull_dangerous",
EntityIds::BOAT => "minecraft:boat",
EntityIds::LIGHTNING_BOLT => "minecraft:lightning_bolt",
EntityIds::SMALL_FIREBALL => "minecraft:small_fireball",
EntityIds::LLAMA_SPIT => "minecraft:llama_spit",
EntityIds::AREA_EFFECT_CLOUD => "minecraft:area_effect_cloud",
EntityIds::LINGERING_POTION => "minecraft:lingering_potion",
EntityIds::FIREWORKS_ROCKET => "minecraft:fireworks_rocket",
EntityIds::EVOCATION_FANG => "minecraft:evocation_fang",
EntityIds::EVOCATION_ILLAGER => "minecraft:evocation_illager",
EntityIds::VEX => "minecraft:vex",
EntityIds::AGENT => "minecraft:agent",
EntityIds::ICE_BOMB => "minecraft:ice_bomb",
EntityIds::PHANTOM => "minecraft:phantom",
EntityIds::TRIPOD_CAMERA => "minecraft:tripod_camera"
];
/** @var int|null */
public $entityUniqueId = null; //TODO
/** @var int */
public $entityRuntimeId;
/** @var int */
public $type;
/** @var Vector3 */
public $position;
/** @var Vector3|null */
public $motion;
/** @var float */
public $pitch = 0.0;
/** @var float */
public $yaw = 0.0;
/** @var float */
public $headYaw = 0.0;
/** @var Attribute[] */
public $attributes = [];
/** @var array */
public $metadata = [];
/** @var EntityLink[] */
public $links = [];
protected function decodePayload(){
$this->entityUniqueId = $this->getEntityUniqueId();
$this->entityRuntimeId = $this->getEntityRuntimeId();
$this->type = array_search($t = $this->getString(), self::LEGACY_ID_MAP_BC, true);
if($this->type === false){
throw new \UnexpectedValueException("Can't map ID $t to legacy ID");
}
$this->position = $this->getVector3();
$this->motion = $this->getVector3();
$this->pitch = $this->getLFloat();
$this->yaw = $this->getLFloat();
$this->headYaw = $this->getLFloat();
$attrCount = $this->getUnsignedVarInt();
for($i = 0; $i < $attrCount; ++$i){
$name = $this->getString();
$min = $this->getLFloat();
$current = $this->getLFloat();
$max = $this->getLFloat();
$attr = Attribute::getAttributeByName($name);
if($attr !== null){
$attr->setMinValue($min);
$attr->setMaxValue($max);
$attr->setValue($current);
$this->attributes[] = $attr;
}else{
throw new \UnexpectedValueException("Unknown attribute type \"$name\"");
}
}
$this->metadata = $this->getEntityMetadata();
$linkCount = $this->getUnsignedVarInt();
for($i = 0; $i < $linkCount; ++$i){
$this->links[] = $this->getEntityLink();
}
}
protected function encodePayload(){
$this->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId);
$this->putEntityRuntimeId($this->entityRuntimeId);
if(!isset(self::LEGACY_ID_MAP_BC[$this->type])){
throw new \InvalidArgumentException("Unknown entity numeric ID $this->type");
}
$this->putString(self::LEGACY_ID_MAP_BC[$this->type]);
$this->putVector3($this->position);
$this->putVector3Nullable($this->motion);
$this->putLFloat($this->pitch);
$this->putLFloat($this->yaw);
$this->putLFloat($this->headYaw);
$this->putUnsignedVarInt(count($this->attributes));
foreach($this->attributes as $attribute){
$this->putString($attribute->getName());
$this->putLFloat($attribute->getMinValue());
$this->putLFloat($attribute->getValue());
$this->putLFloat($attribute->getMaxValue());
}
$this->putEntityMetadata($this->metadata);
$this->putUnsignedVarInt(count($this->links));
foreach($this->links as $link){
$this->putEntityLink($link);
}
}
public function handle(NetworkSession $session) : bool{
return $session->handleAddActor($this);
}
}

View File

@ -25,216 +25,36 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\entity\Attribute;
use pocketmine\entity\EntityIds;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\types\EntityLink;
use function array_search;
use function count;
class AddEntityPacket extends DataPacket{
class AddEntityPacket extends DataPacket/* implements ClientboundPacket*/{
public const NETWORK_ID = ProtocolInfo::ADD_ENTITY_PACKET;
/*
* Really really really really really nasty hack, to preserve backwards compatibility.
* We can't transition to string IDs within 3.x because the network IDs (the integer ones) are exposed
* to the API in some places (for god's sake shoghi).
*
* TODO: remove this on 4.0
/** @var int */
private $uvarint1;
public static function create(int $uvarint1) : self{
$result = new self;
$result->uvarint1 = $uvarint1;
return $result;
}
/**
* @return int
*/
public const LEGACY_ID_MAP_BC = [
EntityIds::NPC => "minecraft:npc",
EntityIds::PLAYER => "minecraft:player",
EntityIds::WITHER_SKELETON => "minecraft:wither_skeleton",
EntityIds::HUSK => "minecraft:husk",
EntityIds::STRAY => "minecraft:stray",
EntityIds::WITCH => "minecraft:witch",
EntityIds::ZOMBIE_VILLAGER => "minecraft:zombie_villager",
EntityIds::BLAZE => "minecraft:blaze",
EntityIds::MAGMA_CUBE => "minecraft:magma_cube",
EntityIds::GHAST => "minecraft:ghast",
EntityIds::CAVE_SPIDER => "minecraft:cave_spider",
EntityIds::SILVERFISH => "minecraft:silverfish",
EntityIds::ENDERMAN => "minecraft:enderman",
EntityIds::SLIME => "minecraft:slime",
EntityIds::ZOMBIE_PIGMAN => "minecraft:zombie_pigman",
EntityIds::SPIDER => "minecraft:spider",
EntityIds::SKELETON => "minecraft:skeleton",
EntityIds::CREEPER => "minecraft:creeper",
EntityIds::ZOMBIE => "minecraft:zombie",
EntityIds::SKELETON_HORSE => "minecraft:skeleton_horse",
EntityIds::MULE => "minecraft:mule",
EntityIds::DONKEY => "minecraft:donkey",
EntityIds::DOLPHIN => "minecraft:dolphin",
EntityIds::TROPICALFISH => "minecraft:tropicalfish",
EntityIds::WOLF => "minecraft:wolf",
EntityIds::SQUID => "minecraft:squid",
EntityIds::DROWNED => "minecraft:drowned",
EntityIds::SHEEP => "minecraft:sheep",
EntityIds::MOOSHROOM => "minecraft:mooshroom",
EntityIds::PANDA => "minecraft:panda",
EntityIds::SALMON => "minecraft:salmon",
EntityIds::PIG => "minecraft:pig",
EntityIds::VILLAGER => "minecraft:villager",
EntityIds::COD => "minecraft:cod",
EntityIds::PUFFERFISH => "minecraft:pufferfish",
EntityIds::COW => "minecraft:cow",
EntityIds::CHICKEN => "minecraft:chicken",
EntityIds::BALLOON => "minecraft:balloon",
EntityIds::LLAMA => "minecraft:llama",
EntityIds::IRON_GOLEM => "minecraft:iron_golem",
EntityIds::RABBIT => "minecraft:rabbit",
EntityIds::SNOW_GOLEM => "minecraft:snow_golem",
EntityIds::BAT => "minecraft:bat",
EntityIds::OCELOT => "minecraft:ocelot",
EntityIds::HORSE => "minecraft:horse",
EntityIds::CAT => "minecraft:cat",
EntityIds::POLAR_BEAR => "minecraft:polar_bear",
EntityIds::ZOMBIE_HORSE => "minecraft:zombie_horse",
EntityIds::TURTLE => "minecraft:turtle",
EntityIds::PARROT => "minecraft:parrot",
EntityIds::GUARDIAN => "minecraft:guardian",
EntityIds::ELDER_GUARDIAN => "minecraft:elder_guardian",
EntityIds::VINDICATOR => "minecraft:vindicator",
EntityIds::WITHER => "minecraft:wither",
EntityIds::ENDER_DRAGON => "minecraft:ender_dragon",
EntityIds::SHULKER => "minecraft:shulker",
EntityIds::ENDERMITE => "minecraft:endermite",
EntityIds::MINECART => "minecraft:minecart",
EntityIds::HOPPER_MINECART => "minecraft:hopper_minecart",
EntityIds::TNT_MINECART => "minecraft:tnt_minecart",
EntityIds::CHEST_MINECART => "minecraft:chest_minecart",
EntityIds::COMMAND_BLOCK_MINECART => "minecraft:command_block_minecart",
EntityIds::ARMOR_STAND => "minecraft:armor_stand",
EntityIds::ITEM => "minecraft:item",
EntityIds::TNT => "minecraft:tnt",
EntityIds::FALLING_BLOCK => "minecraft:falling_block",
EntityIds::XP_BOTTLE => "minecraft:xp_bottle",
EntityIds::XP_ORB => "minecraft:xp_orb",
EntityIds::EYE_OF_ENDER_SIGNAL => "minecraft:eye_of_ender_signal",
EntityIds::ENDER_CRYSTAL => "minecraft:ender_crystal",
EntityIds::SHULKER_BULLET => "minecraft:shulker_bullet",
EntityIds::FISHING_HOOK => "minecraft:fishing_hook",
EntityIds::DRAGON_FIREBALL => "minecraft:dragon_fireball",
EntityIds::ARROW => "minecraft:arrow",
EntityIds::SNOWBALL => "minecraft:snowball",
EntityIds::EGG => "minecraft:egg",
EntityIds::PAINTING => "minecraft:painting",
EntityIds::THROWN_TRIDENT => "minecraft:thrown_trident",
EntityIds::FIREBALL => "minecraft:fireball",
EntityIds::SPLASH_POTION => "minecraft:splash_potion",
EntityIds::ENDER_PEARL => "minecraft:ender_pearl",
EntityIds::LEASH_KNOT => "minecraft:leash_knot",
EntityIds::WITHER_SKULL => "minecraft:wither_skull",
EntityIds::WITHER_SKULL_DANGEROUS => "minecraft:wither_skull_dangerous",
EntityIds::BOAT => "minecraft:boat",
EntityIds::LIGHTNING_BOLT => "minecraft:lightning_bolt",
EntityIds::SMALL_FIREBALL => "minecraft:small_fireball",
EntityIds::LLAMA_SPIT => "minecraft:llama_spit",
EntityIds::AREA_EFFECT_CLOUD => "minecraft:area_effect_cloud",
EntityIds::LINGERING_POTION => "minecraft:lingering_potion",
EntityIds::FIREWORKS_ROCKET => "minecraft:fireworks_rocket",
EntityIds::EVOCATION_FANG => "minecraft:evocation_fang",
EntityIds::EVOCATION_ILLAGER => "minecraft:evocation_illager",
EntityIds::VEX => "minecraft:vex",
EntityIds::AGENT => "minecraft:agent",
EntityIds::ICE_BOMB => "minecraft:ice_bomb",
EntityIds::PHANTOM => "minecraft:phantom",
EntityIds::TRIPOD_CAMERA => "minecraft:tripod_camera"
];
/** @var int|null */
public $entityUniqueId = null; //TODO
/** @var int */
public $entityRuntimeId;
/** @var int */
public $type;
/** @var Vector3 */
public $position;
/** @var Vector3|null */
public $motion;
/** @var float */
public $pitch = 0.0;
/** @var float */
public $yaw = 0.0;
/** @var float */
public $headYaw = 0.0;
/** @var Attribute[] */
public $attributes = [];
/** @var array */
public $metadata = [];
/** @var EntityLink[] */
public $links = [];
protected function decodePayload(){
$this->entityUniqueId = $this->getEntityUniqueId();
$this->entityRuntimeId = $this->getEntityRuntimeId();
$this->type = array_search($t = $this->getString(), self::LEGACY_ID_MAP_BC, true);
if($this->type === false){
throw new \UnexpectedValueException("Can't map ID $t to legacy ID");
}
$this->position = $this->getVector3();
$this->motion = $this->getVector3();
$this->pitch = $this->getLFloat();
$this->yaw = $this->getLFloat();
$this->headYaw = $this->getLFloat();
$attrCount = $this->getUnsignedVarInt();
for($i = 0; $i < $attrCount; ++$i){
$name = $this->getString();
$min = $this->getLFloat();
$current = $this->getLFloat();
$max = $this->getLFloat();
$attr = Attribute::getAttributeByName($name);
if($attr !== null){
$attr->setMinValue($min);
$attr->setMaxValue($max);
$attr->setValue($current);
$this->attributes[] = $attr;
}else{
throw new \UnexpectedValueException("Unknown attribute type \"$name\"");
}
}
$this->metadata = $this->getEntityMetadata();
$linkCount = $this->getUnsignedVarInt();
for($i = 0; $i < $linkCount; ++$i){
$this->links[] = $this->getEntityLink();
}
public function getUvarint1() : int{
return $this->uvarint1;
}
protected function encodePayload(){
$this->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId);
$this->putEntityRuntimeId($this->entityRuntimeId);
if(!isset(self::LEGACY_ID_MAP_BC[$this->type])){
throw new \InvalidArgumentException("Unknown entity numeric ID $this->type");
}
$this->putString(self::LEGACY_ID_MAP_BC[$this->type]);
$this->putVector3($this->position);
$this->putVector3Nullable($this->motion);
$this->putLFloat($this->pitch);
$this->putLFloat($this->yaw);
$this->putLFloat($this->headYaw);
$this->putUnsignedVarInt(count($this->attributes));
foreach($this->attributes as $attribute){
$this->putString($attribute->getName());
$this->putLFloat($attribute->getMinValue());
$this->putLFloat($attribute->getValue());
$this->putLFloat($attribute->getMaxValue());
}
$this->putEntityMetadata($this->metadata);
$this->putUnsignedVarInt(count($this->links));
foreach($this->links as $link){
$this->putEntityLink($link);
}
protected function decodePayload() : void{
$this->uvarint1 = $this->getUnsignedVarInt();
}
public function handle(NetworkSession $session) : bool{
return $session->handleAddEntity($this);
protected function encodePayload() : void{
$this->putUnsignedVarInt($this->uvarint1);
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleAddEntity($this);
}
}

View File

@ -29,8 +29,8 @@ use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\NetworkSession;
class AddItemEntityPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ENTITY_PACKET;
class AddItemActorPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ACTOR_PACKET;
/** @var int|null */
public $entityUniqueId = null; //TODO
@ -68,6 +68,6 @@ class AddItemEntityPacket extends DataPacket{
}
public function handle(NetworkSession $session) : bool{
return $session->handleAddItemEntity($this);
return $session->handleAddItemActor($this);
}
}

View File

@ -26,30 +26,27 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\NetworkSession;
class AddPaintingPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ADD_PAINTING_PACKET;
/** @var string */
public $title;
/** @var int */
public $entityRuntimeId;
/** @var int */
public $x;
/** @var int|null */
public $entityUniqueId = null;
/** @var int */
public $y;
/** @var int */
public $z;
public $entityRuntimeId;
/** @var Vector3 */
public $position;
/** @var int */
public $direction;
/** @var string */
public $title;
protected function decodePayload(){
$this->entityUniqueId = $this->getEntityUniqueId();
$this->entityRuntimeId = $this->getEntityRuntimeId();
$this->getBlockPosition($this->x, $this->y, $this->z);
$this->position = $this->getVector3();
$this->direction = $this->getVarInt();
$this->title = $this->getString();
}
@ -57,7 +54,7 @@ class AddPaintingPacket extends DataPacket{
protected function encodePayload(){
$this->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId);
$this->putEntityRuntimeId($this->entityRuntimeId);
$this->putBlockPosition($this->x, $this->y, $this->z);
$this->putVector3($this->position);
$this->putVarInt($this->direction);
$this->putString($this->title);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\mcpe\NetworkSession;
class BlockEntityDataPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::BLOCK_ENTITY_DATA_PACKET;
class BlockActorDataPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::BLOCK_ACTOR_DATA_PACKET;
/** @var int */
public $x;
@ -51,6 +51,6 @@ class BlockEntityDataPacket extends DataPacket{
}
public function handle(NetworkSession $session) : bool{
return $session->handleBlockEntityData($this);
return $session->handleBlockActorData($this);
}
}

View File

@ -0,0 +1,95 @@
<?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\NetworkSession;
use function count;
class ClientCacheBlobStatusPacket extends DataPacket/* implements ServerboundPacket*/{
public const NETWORK_ID = ProtocolInfo::CLIENT_CACHE_BLOB_STATUS_PACKET;
/** @var int[] xxHash64 subchunk data hashes */
private $hitHashes = [];
/** @var int[] xxHash64 subchunk data hashes */
private $missHashes = [];
/**
* @param int[] $hitHashes
* @param int[] $missHashes
*
* @return self
*/
public static function create(array $hitHashes, array $missHashes) : self{
//type checks
(static function(int ...$hashes){})(...$hitHashes);
(static function(int ...$hashes){})(...$missHashes);
$result = new self;
$result->hitHashes = $hitHashes;
$result->missHashes = $missHashes;
return $result;
}
/**
* @return int[]
*/
public function getHitHashes() : array{
return $this->hitHashes;
}
/**
* @return int[]
*/
public function getMissHashes() : array{
return $this->missHashes;
}
protected function decodePayload() : void{
$hitCount = $this->getUnsignedVarInt();
$missCount = $this->getUnsignedVarInt();
for($i = 0; $i < $hitCount; ++$i){
$this->hitHashes[] = $this->getLLong();
}
for($i = 0; $i < $missCount; ++$i){
$this->missHashes[] = $this->getLLong();
}
}
protected function encodePayload() : void{
$this->putUnsignedVarInt(count($this->hitHashes));
$this->putUnsignedVarInt(count($this->missHashes));
foreach($this->hitHashes as $hash){
$this->putLLong($hash);
}
foreach($this->missHashes as $hash){
$this->putLLong($hash);
}
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleClientCacheBlobStatus($this);
}
}

View 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\NetworkSession;
use pocketmine\network\mcpe\protocol\types\ChunkCacheBlob;
use function count;
class ClientCacheMissResponsePacket extends DataPacket/* implements ClientboundPacket*/{
public const NETWORK_ID = ProtocolInfo::CLIENT_CACHE_MISS_RESPONSE_PACKET;
/** @var ChunkCacheBlob[] */
private $blobs = [];
/**
* @param ChunkCacheBlob[] $blobs
*
* @return self
*/
public static function create(array $blobs) : self{
//type check
(static function(ChunkCacheBlob ...$blobs){})($blobs);
$result = new self;
$result->blobs = $blobs;
return $result;
}
/**
* @return ChunkCacheBlob[]
*/
public function getBlobs() : array{
return $this->blobs;
}
protected function decodePayload() : void{
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
$hash = $this->getLLong();
$payload = $this->getString();
$this->blobs[] = new ChunkCacheBlob($hash, $payload);
}
}
protected function encodePayload() : void{
$this->putUnsignedVarInt(count($this->blobs));
foreach($this->blobs as $blob){
$this->putLLong($blob->getHash());
$this->putString($blob->getPayload());
}
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleClientCacheMissResponse($this);
}
}

View 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\NetworkSession;
class ClientCacheStatusPacket extends DataPacket/* implements ServerboundPacket*/{
public const NETWORK_ID = ProtocolInfo::CLIENT_CACHE_STATUS_PACKET;
/** @var bool */
private $enabled;
public static function create(bool $enabled) : self{
$result = new self;
$result->enabled = $enabled;
return $result;
}
/**
* @return bool
*/
public function isEnabled() : bool{
return $this->enabled;
}
protected function decodePayload() : void{
$this->enabled = $this->getBool();
}
protected function encodePayload() : void{
$this->putBool($this->enabled);
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleClientCacheStatus($this);
}
}

View File

@ -59,6 +59,10 @@ class CommandBlockUpdatePacket extends DataPacket{
public $name;
/** @var bool */
public $shouldTrackOutput;
/** @var int */
public $tickDelay;
/** @var bool */
public $executeOnFirstTick;
protected function decodePayload(){
$this->isBlock = $this->getBool();
@ -78,6 +82,8 @@ class CommandBlockUpdatePacket extends DataPacket{
$this->name = $this->getString();
$this->shouldTrackOutput = $this->getBool();
$this->tickDelay = $this->getLInt();
$this->executeOnFirstTick = $this->getBool();
}
protected function encodePayload(){
@ -97,6 +103,8 @@ class CommandBlockUpdatePacket extends DataPacket{
$this->putString($this->name);
$this->putBool($this->shouldTrackOutput);
$this->putLInt($this->tickDelay);
$this->putBool($this->executeOnFirstTick);
}
public function handle(NetworkSession $session) : bool{

View File

@ -33,6 +33,9 @@ use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\network\mcpe\NetworkBinaryStream;
use pocketmine\network\mcpe\NetworkSession;
#ifndef COMPILE
use pocketmine\utils\Binary;
#endif
use function count;
use function str_repeat;
@ -72,11 +75,13 @@ class CraftingDataPacket extends DataPacket{
case self::ENTRY_SHAPELESS:
case self::ENTRY_SHULKER_BOX:
case self::ENTRY_SHAPELESS_CHEMISTRY:
$entry["recipe_id"] = $this->getString();
$ingredientCount = $this->getUnsignedVarInt();
/** @var Item */
$entry["input"] = [];
for($j = 0; $j < $ingredientCount; ++$j){
$entry["input"][] = $this->getSlot();
$entry["input"][] = $in = $this->getRecipeIngredient();
$in->setCount(1); //TODO HACK: they send a useless count field which breaks the PM crafting system because it isn't always 1
}
$resultCount = $this->getUnsignedVarInt();
$entry["output"] = [];
@ -85,16 +90,19 @@ class CraftingDataPacket extends DataPacket{
}
$entry["uuid"] = $this->getUUID()->toString();
$entry["block"] = $this->getString();
$entry["priority"] = $this->getVarInt();
break;
case self::ENTRY_SHAPED:
case self::ENTRY_SHAPED_CHEMISTRY:
$entry["recipe_id"] = $this->getString();
$entry["width"] = $this->getVarInt();
$entry["height"] = $this->getVarInt();
$count = $entry["width"] * $entry["height"];
$entry["input"] = [];
for($j = 0; $j < $count; ++$j){
$entry["input"][] = $this->getSlot();
$entry["input"][] = $in = $this->getRecipeIngredient();
$in->setCount(1); //TODO HACK: they send a useless count field which breaks the PM crafting system
}
$resultCount = $this->getUnsignedVarInt();
$entry["output"] = [];
@ -103,6 +111,7 @@ class CraftingDataPacket extends DataPacket{
}
$entry["uuid"] = $this->getUUID()->toString();
$entry["block"] = $this->getString();
$entry["priority"] = $this->getVarInt();
break;
case self::ENTRY_FURNACE:
@ -116,7 +125,10 @@ class CraftingDataPacket extends DataPacket{
}
}
$entry["input"] = ItemFactory::get($inputId, $inputData);
$entry["output"] = $this->getSlot();
$entry["output"] = $out = $this->getSlot();
if($out->getDamage() === 0x7fff){
$out->setDamage(0); //TODO HACK: some 1.12 furnace recipe outputs have wildcard damage values
}
$entry["block"] = $this->getString();
break;
@ -131,11 +143,11 @@ class CraftingDataPacket extends DataPacket{
$this->getBool(); //cleanRecipes
}
private static function writeEntry($entry, NetworkBinaryStream $stream){
private static function writeEntry($entry, NetworkBinaryStream $stream, int $pos){
if($entry instanceof ShapelessRecipe){
return self::writeShapelessRecipe($entry, $stream);
return self::writeShapelessRecipe($entry, $stream, $pos);
}elseif($entry instanceof ShapedRecipe){
return self::writeShapedRecipe($entry, $stream);
return self::writeShapedRecipe($entry, $stream, $pos);
}elseif($entry instanceof FurnaceRecipe){
return self::writeFurnaceRecipe($entry, $stream);
}
@ -144,10 +156,11 @@ class CraftingDataPacket extends DataPacket{
return -1;
}
private static function writeShapelessRecipe(ShapelessRecipe $recipe, NetworkBinaryStream $stream){
private static function writeShapelessRecipe(ShapelessRecipe $recipe, NetworkBinaryStream $stream, int $pos){
$stream->putString(Binary::writeInt($pos)); //some kind of recipe ID, doesn't matter what it is as long as it's unique
$stream->putUnsignedVarInt($recipe->getIngredientCount());
foreach($recipe->getIngredientList() as $item){
$stream->putSlot($item);
$stream->putRecipeIngredient($item);
}
$results = $recipe->getResults();
@ -158,17 +171,19 @@ class CraftingDataPacket extends DataPacket{
$stream->put(str_repeat("\x00", 16)); //Null UUID
$stream->putString("crafting_table"); //TODO: blocktype (no prefix) (this might require internal API breaks)
$stream->putVarInt(50); //TODO: priority
return CraftingDataPacket::ENTRY_SHAPELESS;
}
private static function writeShapedRecipe(ShapedRecipe $recipe, NetworkBinaryStream $stream){
private static function writeShapedRecipe(ShapedRecipe $recipe, NetworkBinaryStream $stream, int $pos){
$stream->putString(Binary::writeInt($pos)); //some kind of recipe ID, doesn't matter what it is as long as it's unique
$stream->putVarInt($recipe->getWidth());
$stream->putVarInt($recipe->getHeight());
for($z = 0; $z < $recipe->getHeight(); ++$z){
for($x = 0; $x < $recipe->getWidth(); ++$x){
$stream->putSlot($recipe->getIngredient($x, $z));
$stream->putRecipeIngredient($recipe->getIngredient($x, $z));
}
}
@ -180,6 +195,7 @@ class CraftingDataPacket extends DataPacket{
$stream->put(str_repeat("\x00", 16)); //Null UUID
$stream->putString("crafting_table"); //TODO: blocktype (no prefix) (this might require internal API breaks)
$stream->putVarInt(50); //TODO: priority
return CraftingDataPacket::ENTRY_SHAPED;
}
@ -212,8 +228,9 @@ class CraftingDataPacket extends DataPacket{
$this->putUnsignedVarInt(count($this->entries));
$writer = new NetworkBinaryStream();
$counter = 0;
foreach($this->entries as $d){
$entryType = self::writeEntry($d, $writer);
$entryType = self::writeEntry($d, $writer, $counter++);
if($entryType >= 0){
$this->putVarInt($entryType);
$this->put($writer->getBuffer());

View File

@ -0,0 +1,145 @@
<?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\NetworkSession;
use function count;
class LevelChunkPacket extends DataPacket/* implements ClientboundPacket*/{
public const NETWORK_ID = ProtocolInfo::LEVEL_CHUNK_PACKET;
/** @var int */
private $chunkX;
/** @var int */
private $chunkZ;
/** @var int */
private $subChunkCount;
/** @var bool */
private $cacheEnabled;
/** @var int[] */
private $usedBlobHashes = [];
/** @var string */
private $extraPayload;
public static function withoutCache(int $chunkX, int $chunkZ, int $subChunkCount, string $payload) : self{
$result = new self;
$result->chunkX = $chunkX;
$result->chunkZ = $chunkZ;
$result->subChunkCount = $subChunkCount;
$result->extraPayload = $payload;
$result->cacheEnabled = false;
return $result;
}
public static function withCache(int $chunkX, int $chunkZ, int $subChunkCount, array $usedBlobHashes, string $extraPayload) : self{
(static function(int ...$hashes){})($usedBlobHashes);
$result = new self;
$result->chunkX = $chunkX;
$result->chunkZ = $chunkZ;
$result->subChunkCount = $subChunkCount;
$result->extraPayload = $extraPayload;
$result->cacheEnabled = true;
$result->usedBlobHashes = $usedBlobHashes;
return $result;
}
/**
* @return int
*/
public function getChunkX() : int{
return $this->chunkX;
}
/**
* @return int
*/
public function getChunkZ() : int{
return $this->chunkZ;
}
/**
* @return int
*/
public function getSubChunkCount() : int{
return $this->subChunkCount;
}
/**
* @return bool
*/
public function isCacheEnabled() : bool{
return $this->cacheEnabled;
}
/**
* @return int[]
*/
public function getUsedBlobHashes() : array{
return $this->usedBlobHashes;
}
/**
* @return string
*/
public function getExtraPayload() : string{
return $this->extraPayload;
}
protected function decodePayload() : void{
$this->chunkX = $this->getVarInt();
$this->chunkZ = $this->getVarInt();
$this->subChunkCount = $this->getUnsignedVarInt();
$this->cacheEnabled = $this->getBool();
if($this->cacheEnabled){
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
$this->usedBlobHashes[] = $this->getLLong();
}
}
$this->extraPayload = $this->getString();
}
protected function encodePayload() : void{
$this->putVarInt($this->chunkX);
$this->putVarInt($this->chunkZ);
$this->putUnsignedVarInt($this->subChunkCount);
$this->putBool($this->cacheEnabled);
if($this->cacheEnabled){
$this->putUnsignedVarInt(count($this->usedBlobHashes));
foreach($this->usedBlobHashes as $hash){
$this->putLLong($hash);
}
}
$this->putString($this->extraPayload);
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleLevelChunk($this);
}
}

View File

@ -0,0 +1,74 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\nbt\NetworkLittleEndianNBTStream;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\NetworkSession;
class LevelEventGenericPacket extends DataPacket/* implements ClientboundPacket*/{
public const NETWORK_ID = ProtocolInfo::LEVEL_EVENT_GENERIC_PACKET;
/** @var int */
private $eventId;
/** @var string network-format NBT */
private $eventData;
public static function create(int $eventId, CompoundTag $data) : self{
$result = new self;
$result->eventId = $eventId;
$result->eventData = (new NetworkLittleEndianNBTStream())->write($data);
return $result;
}
/**
* @return int
*/
public function getEventId() : int{
return $this->eventId;
}
/**
* @return string
*/
public function getEventData() : string{
return $this->eventData;
}
protected function decodePayload() : void{
$this->eventId = $this->getVarInt();
$this->eventData = $this->getRemaining();
}
protected function encodePayload() : void{
$this->putVarInt($this->eventId);
$this->put($this->eventData);
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleLevelEventGeneric($this);
}
}

View File

@ -292,8 +292,8 @@ class LevelSoundEventPacket extends DataPacket{
public const SOUND_STUN = 261;
public const SOUND_BLOCK_SWEET_BERRY_BUSH_HURT = 262;
public const SOUND_BLOCK_SWEET_BERRY_BUSH_PICK = 263;
public const SOUND_UI_CARTOGRAPHY_TABLE_TAKE_RESULT = 264;
public const SOUND_UI_STONECUTTER_TAKE_RESULT = 265;
public const SOUND_BLOCK_CARTOGRAPHY_TABLE_USE = 264;
public const SOUND_BLOCK_STONECUTTER_USE = 265;
public const SOUND_BLOCK_COMPOSTER_EMPTY = 266;
public const SOUND_BLOCK_COMPOSTER_FILL = 267;
public const SOUND_BLOCK_COMPOSTER_FILL_SUCCESS = 268;
@ -302,7 +302,14 @@ class LevelSoundEventPacket extends DataPacket{
public const SOUND_BLOCK_BARREL_CLOSE = 271;
public const SOUND_RAID_HORN = 272;
public const SOUND_BLOCK_LOOM_USE = 273;
public const SOUND_UNDEFINED = 274;
public const SOUND_AMBIENT_IN_RAID = 274;
public const SOUND_UI_CARTOGRAPHY_TABLE_TAKE_RESULT = 275;
public const SOUND_UI_STONECUTTER_TAKE_RESULT = 276;
public const SOUND_UI_LOOM_TAKE_RESULT = 277;
public const SOUND_BLOCK_SMOKER_SMOKE = 278;
public const SOUND_BLOCK_BLASTFURNACE_FIRE_CRACKLE = 279;
public const SOUND_BLOCK_SMITHING_TABLE_USE = 280;
public const SOUND_UNDEFINED = 281;
/** @var int */
public $sound;

View File

@ -29,8 +29,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\NetworkSession;
class MoveEntityAbsolutePacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::MOVE_ENTITY_ABSOLUTE_PACKET;
class MoveActorAbsolutePacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::MOVE_ACTOR_ABSOLUTE_PACKET;
public const FLAG_GROUND = 0x01;
public const FLAG_TELEPORT = 0x02;
@ -67,6 +67,6 @@ class MoveEntityAbsolutePacket extends DataPacket{
}
public function handle(NetworkSession $session) : bool{
return $session->handleMoveEntityAbsolute($this);
return $session->handleMoveActorAbsolute($this);
}
}

View File

@ -27,8 +27,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\mcpe\NetworkSession;
class MoveEntityDeltaPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::MOVE_ENTITY_DELTA_PACKET;
class MoveActorDeltaPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::MOVE_ACTOR_DELTA_PACKET;
public const FLAG_HAS_X = 0x01;
public const FLAG_HAS_Y = 0x02;
@ -103,6 +103,6 @@ class MoveEntityDeltaPacket extends DataPacket{
}
public function handle(NetworkSession $session) : bool{
return $session->handleMoveEntityDelta($this);
return $session->handleMoveActorDelta($this);
}
}

View File

@ -45,11 +45,11 @@ class PacketPool{
static::registerPacket(new SetTimePacket());
static::registerPacket(new StartGamePacket());
static::registerPacket(new AddPlayerPacket());
static::registerPacket(new AddEntityPacket());
static::registerPacket(new RemoveEntityPacket());
static::registerPacket(new AddItemEntityPacket());
static::registerPacket(new TakeItemEntityPacket());
static::registerPacket(new MoveEntityAbsolutePacket());
static::registerPacket(new AddActorPacket());
static::registerPacket(new RemoveActorPacket());
static::registerPacket(new AddItemActorPacket());
static::registerPacket(new TakeItemActorPacket());
static::registerPacket(new MoveActorAbsolutePacket());
static::registerPacket(new MovePlayerPacket());
static::registerPacket(new RiderJumpPacket());
static::registerPacket(new UpdateBlockPacket());
@ -58,7 +58,7 @@ class PacketPool{
static::registerPacket(new LevelSoundEventPacketV1());
static::registerPacket(new LevelEventPacket());
static::registerPacket(new BlockEventPacket());
static::registerPacket(new EntityEventPacket());
static::registerPacket(new ActorEventPacket());
static::registerPacket(new MobEffectPacket());
static::registerPacket(new UpdateAttributesPacket());
static::registerPacket(new InventoryTransactionPacket());
@ -66,13 +66,13 @@ class PacketPool{
static::registerPacket(new MobArmorEquipmentPacket());
static::registerPacket(new InteractPacket());
static::registerPacket(new BlockPickRequestPacket());
static::registerPacket(new EntityPickRequestPacket());
static::registerPacket(new ActorPickRequestPacket());
static::registerPacket(new PlayerActionPacket());
static::registerPacket(new EntityFallPacket());
static::registerPacket(new ActorFallPacket());
static::registerPacket(new HurtArmorPacket());
static::registerPacket(new SetEntityDataPacket());
static::registerPacket(new SetEntityMotionPacket());
static::registerPacket(new SetEntityLinkPacket());
static::registerPacket(new SetActorDataPacket());
static::registerPacket(new SetActorMotionPacket());
static::registerPacket(new SetActorLinkPacket());
static::registerPacket(new SetHealthPacket());
static::registerPacket(new SetSpawnPositionPacket());
static::registerPacket(new AnimatePacket());
@ -87,9 +87,9 @@ class PacketPool{
static::registerPacket(new CraftingEventPacket());
static::registerPacket(new GuiDataPickItemPacket());
static::registerPacket(new AdventureSettingsPacket());
static::registerPacket(new BlockEntityDataPacket());
static::registerPacket(new BlockActorDataPacket());
static::registerPacket(new PlayerInputPacket());
static::registerPacket(new FullChunkDataPacket());
static::registerPacket(new LevelChunkPacket());
static::registerPacket(new SetCommandsEnabledPacket());
static::registerPacket(new SetDifficultyPacket());
static::registerPacket(new ChangeDimensionPacket());
@ -142,22 +142,31 @@ class PacketPool{
static::registerPacket(new SetScorePacket());
static::registerPacket(new LabTablePacket());
static::registerPacket(new UpdateBlockSyncedPacket());
static::registerPacket(new MoveEntityDeltaPacket());
static::registerPacket(new MoveActorDeltaPacket());
static::registerPacket(new SetScoreboardIdentityPacket());
static::registerPacket(new SetLocalPlayerAsInitializedPacket());
static::registerPacket(new UpdateSoftEnumPacket());
static::registerPacket(new NetworkStackLatencyPacket());
static::registerPacket(new ScriptCustomEventPacket());
static::registerPacket(new SpawnParticleEffectPacket());
static::registerPacket(new AvailableEntityIdentifiersPacket());
static::registerPacket(new AvailableActorIdentifiersPacket());
static::registerPacket(new LevelSoundEventPacketV2());
static::registerPacket(new NetworkChunkPublisherUpdatePacket());
static::registerPacket(new BiomeDefinitionListPacket());
static::registerPacket(new LevelSoundEventPacket());
static::registerPacket(new LevelEventGenericPacket());
static::registerPacket(new LecternUpdatePacket());
static::registerPacket(new VideoStreamConnectPacket());
static::registerPacket(new MapCreateLockedCopyPacket());
static::registerPacket(new AddEntityPacket());
static::registerPacket(new RemoveEntityPacket());
static::registerPacket(new ClientCacheStatusPacket());
static::registerPacket(new OnScreenTextureAnimationPacket());
static::registerPacket(new MapCreateLockedCopyPacket());
static::registerPacket(new StructureTemplateDataExportRequestPacket());
static::registerPacket(new StructureTemplateDataExportResponsePacket());
static::registerPacket(new UpdateBlockPropertiesPacket());
static::registerPacket(new ClientCacheBlobStatusPacket());
static::registerPacket(new ClientCacheMissResponsePacket());
}
/**

View File

@ -56,6 +56,7 @@ class PlayerActionPacket extends DataPacket{
public const ACTION_STOP_SWIMMING = 22;
public const ACTION_START_SPIN_ATTACK = 23;
public const ACTION_STOP_SPIN_ATTACK = 24;
public const ACTION_INTERACT_BLOCK = 25;
/** @var int */
public $entityRuntimeId;

View File

@ -39,15 +39,15 @@ interface ProtocolInfo{
/**
* Actual Minecraft: PE protocol version
*/
public const CURRENT_PROTOCOL = 354;
public const CURRENT_PROTOCOL = 361;
/**
* Current Minecraft PE version reported by the server. This is usually the earliest currently supported version.
*/
public const MINECRAFT_VERSION = 'v1.11.0';
public const MINECRAFT_VERSION = 'v1.12.0';
/**
* Version number sent to clients in ping responses.
*/
public const MINECRAFT_VERSION_NETWORK = '1.11.0';
public const MINECRAFT_VERSION_NETWORK = '1.12.0';
public const LOGIN_PACKET = 0x01;
public const PLAY_STATUS_PACKET = 0x02;
@ -61,12 +61,12 @@ interface ProtocolInfo{
public const SET_TIME_PACKET = 0x0a;
public const START_GAME_PACKET = 0x0b;
public const ADD_PLAYER_PACKET = 0x0c;
public const ADD_ENTITY_PACKET = 0x0d;
public const REMOVE_ENTITY_PACKET = 0x0e;
public const ADD_ITEM_ENTITY_PACKET = 0x0f;
public const ADD_ACTOR_PACKET = 0x0d;
public const REMOVE_ACTOR_PACKET = 0x0e;
public const ADD_ITEM_ACTOR_PACKET = 0x0f;
public const TAKE_ITEM_ENTITY_PACKET = 0x11;
public const MOVE_ENTITY_ABSOLUTE_PACKET = 0x12;
public const TAKE_ITEM_ACTOR_PACKET = 0x11;
public const MOVE_ACTOR_ABSOLUTE_PACKET = 0x12;
public const MOVE_PLAYER_PACKET = 0x13;
public const RIDER_JUMP_PACKET = 0x14;
public const UPDATE_BLOCK_PACKET = 0x15;
@ -75,7 +75,7 @@ interface ProtocolInfo{
public const LEVEL_SOUND_EVENT_PACKET_V1 = 0x18;
public const LEVEL_EVENT_PACKET = 0x19;
public const BLOCK_EVENT_PACKET = 0x1a;
public const ENTITY_EVENT_PACKET = 0x1b;
public const ACTOR_EVENT_PACKET = 0x1b;
public const MOB_EFFECT_PACKET = 0x1c;
public const UPDATE_ATTRIBUTES_PACKET = 0x1d;
public const INVENTORY_TRANSACTION_PACKET = 0x1e;
@ -83,13 +83,13 @@ interface ProtocolInfo{
public const MOB_ARMOR_EQUIPMENT_PACKET = 0x20;
public const INTERACT_PACKET = 0x21;
public const BLOCK_PICK_REQUEST_PACKET = 0x22;
public const ENTITY_PICK_REQUEST_PACKET = 0x23;
public const ACTOR_PICK_REQUEST_PACKET = 0x23;
public const PLAYER_ACTION_PACKET = 0x24;
public const ENTITY_FALL_PACKET = 0x25;
public const ACTOR_FALL_PACKET = 0x25;
public const HURT_ARMOR_PACKET = 0x26;
public const SET_ENTITY_DATA_PACKET = 0x27;
public const SET_ENTITY_MOTION_PACKET = 0x28;
public const SET_ENTITY_LINK_PACKET = 0x29;
public const SET_ACTOR_DATA_PACKET = 0x27;
public const SET_ACTOR_MOTION_PACKET = 0x28;
public const SET_ACTOR_LINK_PACKET = 0x29;
public const SET_HEALTH_PACKET = 0x2a;
public const SET_SPAWN_POSITION_PACKET = 0x2b;
public const ANIMATE_PACKET = 0x2c;
@ -104,9 +104,9 @@ interface ProtocolInfo{
public const CRAFTING_EVENT_PACKET = 0x35;
public const GUI_DATA_PICK_ITEM_PACKET = 0x36;
public const ADVENTURE_SETTINGS_PACKET = 0x37;
public const BLOCK_ENTITY_DATA_PACKET = 0x38;
public const BLOCK_ACTOR_DATA_PACKET = 0x38;
public const PLAYER_INPUT_PACKET = 0x39;
public const FULL_CHUNK_DATA_PACKET = 0x3a;
public const LEVEL_CHUNK_PACKET = 0x3a;
public const SET_COMMANDS_ENABLED_PACKET = 0x3b;
public const SET_DIFFICULTY_PACKET = 0x3c;
public const CHANGE_DIMENSION_PACKET = 0x3d;
@ -159,7 +159,7 @@ interface ProtocolInfo{
public const SET_SCORE_PACKET = 0x6c;
public const LAB_TABLE_PACKET = 0x6d;
public const UPDATE_BLOCK_SYNCED_PACKET = 0x6e;
public const MOVE_ENTITY_DELTA_PACKET = 0x6f;
public const MOVE_ACTOR_DELTA_PACKET = 0x6f;
public const SET_SCOREBOARD_IDENTITY_PACKET = 0x70;
public const SET_LOCAL_PLAYER_AS_INITIALIZED_PACKET = 0x71;
public const UPDATE_SOFT_ENUM_PACKET = 0x72;
@ -167,14 +167,23 @@ interface ProtocolInfo{
public const SCRIPT_CUSTOM_EVENT_PACKET = 0x75;
public const SPAWN_PARTICLE_EFFECT_PACKET = 0x76;
public const AVAILABLE_ENTITY_IDENTIFIERS_PACKET = 0x77;
public const AVAILABLE_ACTOR_IDENTIFIERS_PACKET = 0x77;
public const LEVEL_SOUND_EVENT_PACKET_V2 = 0x78;
public const NETWORK_CHUNK_PUBLISHER_UPDATE_PACKET = 0x79;
public const BIOME_DEFINITION_LIST_PACKET = 0x7a;
public const LEVEL_SOUND_EVENT_PACKET = 0x7b;
public const LECTERN_UPDATE_PACKET = 0x7c;
public const VIDEO_STREAM_CONNECT_PACKET = 0x7d;
public const MAP_CREATE_LOCKED_COPY_PACKET = 0x7e;
public const ON_SCREEN_TEXTURE_ANIMATION_PACKET = 0x7f;
public const LEVEL_EVENT_GENERIC_PACKET = 0x7c;
public const LECTERN_UPDATE_PACKET = 0x7d;
public const VIDEO_STREAM_CONNECT_PACKET = 0x7e;
public const ADD_ENTITY_PACKET = 0x7f;
public const REMOVE_ENTITY_PACKET = 0x80;
public const CLIENT_CACHE_STATUS_PACKET = 0x81;
public const ON_SCREEN_TEXTURE_ANIMATION_PACKET = 0x82;
public const MAP_CREATE_LOCKED_COPY_PACKET = 0x83;
public const STRUCTURE_TEMPLATE_DATA_EXPORT_REQUEST_PACKET = 0x84;
public const STRUCTURE_TEMPLATE_DATA_EXPORT_RESPONSE_PACKET = 0x85;
public const UPDATE_BLOCK_PROPERTIES_PACKET = 0x86;
public const CLIENT_CACHE_BLOB_STATUS_PACKET = 0x87;
public const CLIENT_CACHE_MISS_RESPONSE_PACKET = 0x88;
}

View 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;
#include <rules/DataPacket.h>
use pocketmine\network\mcpe\NetworkSession;
class RemoveActorPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::REMOVE_ACTOR_PACKET;
/** @var int */
public $entityUniqueId;
protected function decodePayload(){
$this->entityUniqueId = $this->getEntityUniqueId();
}
protected function encodePayload(){
$this->putEntityUniqueId($this->entityUniqueId);
}
public function handle(NetworkSession $session) : bool{
return $session->handleRemoveActor($this);
}
}

View File

@ -25,24 +25,36 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\mcpe\NetworkSession;
class RemoveEntityPacket extends DataPacket{
class RemoveEntityPacket extends DataPacket/* implements ClientboundPacket*/{
public const NETWORK_ID = ProtocolInfo::REMOVE_ENTITY_PACKET;
/** @var int */
public $entityUniqueId;
private $uvarint1;
protected function decodePayload(){
$this->entityUniqueId = $this->getEntityUniqueId();
public static function create(int $uvarint1) : self{
$result = new self;
$result->uvarint1 = $uvarint1;
return $result;
}
protected function encodePayload(){
$this->putEntityUniqueId($this->entityUniqueId);
/**
* @return int
*/
public function getUvarint1() : int{
return $this->uvarint1;
}
public function handle(NetworkSession $session) : bool{
return $session->handleRemoveEntity($this);
protected function decodePayload() : void{
$this->uvarint1 = $this->getUnsignedVarInt();
}
protected function encodePayload() : void{
$this->putUnsignedVarInt($this->uvarint1);
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleRemoveEntity($this);
}
}

View File

@ -28,6 +28,7 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\types\ResourcePackType;
class ResourcePackDataInfoPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::RESOURCE_PACK_DATA_INFO_PACKET;
@ -42,6 +43,10 @@ class ResourcePackDataInfoPacket extends DataPacket{
public $compressedPackSize;
/** @var string */
public $sha256;
/** @var bool */
public $isPremium = false;
/** @var int */
public $packType = ResourcePackType::RESOURCES; //TODO: check the values for this
protected function decodePayload(){
$this->packId = $this->getString();
@ -49,6 +54,8 @@ class ResourcePackDataInfoPacket extends DataPacket{
$this->chunkCount = $this->getLInt();
$this->compressedPackSize = $this->getLLong();
$this->sha256 = $this->getString();
$this->isPremium = $this->getBool();
$this->packType = $this->getByte();
}
protected function encodePayload(){
@ -57,6 +64,8 @@ class ResourcePackDataInfoPacket extends DataPacket{
$this->putLInt($this->chunkCount);
$this->putLLong($this->compressedPackSize);
$this->putString($this->sha256);
$this->putBool($this->isPremium);
$this->putByte($this->packType);
}
public function handle(NetworkSession $session) : bool{

View File

@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\mcpe\NetworkSession;
class SetEntityDataPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::SET_ENTITY_DATA_PACKET;
class SetActorDataPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::SET_ACTOR_DATA_PACKET;
/** @var int */
public $entityRuntimeId;
@ -47,6 +47,6 @@ class SetEntityDataPacket extends DataPacket{
}
public function handle(NetworkSession $session) : bool{
return $session->handleSetEntityData($this);
return $session->handleSetActorData($this);
}
}

View File

@ -29,8 +29,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\types\EntityLink;
class SetEntityLinkPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::SET_ENTITY_LINK_PACKET;
class SetActorLinkPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::SET_ACTOR_LINK_PACKET;
/** @var EntityLink */
public $link;
@ -44,6 +44,6 @@ class SetEntityLinkPacket extends DataPacket{
}
public function handle(NetworkSession $session) : bool{
return $session->handleSetEntityLink($this);
return $session->handleSetActorLink($this);
}
}

View File

@ -29,8 +29,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\NetworkSession;
class SetEntityMotionPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::SET_ENTITY_MOTION_PACKET;
class SetActorMotionPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::SET_ACTOR_MOTION_PACKET;
/** @var int */
public $entityRuntimeId;
@ -48,6 +48,6 @@ class SetEntityMotionPacket extends DataPacket{
}
public function handle(NetworkSession $session) : bool{
return $session->handleSetEntityMotion($this);
return $session->handleSetActorMotion($this);
}
}

View File

@ -61,6 +61,7 @@ class SetScorePacket extends DataPacket{
throw new \UnexpectedValueException("Unknown entry type $entry->type");
}
}
$this->entries[] = $entry;
}
}

View File

@ -32,12 +32,17 @@ use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
use function count;
use function file_get_contents;
use function json_decode;
use const pocketmine\RESOURCE_PATH;
class StartGamePacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::START_GAME_PACKET;
/** @var string|null */
private static $runtimeIdTableCache;
private static $blockTableCache = null;
/** @var string|null */
private static $itemTableCache = null;
/** @var int */
public $entityUniqueId;
@ -122,6 +127,8 @@ class StartGamePacket extends DataPacket{
public $isFromWorldTemplate = false;
/** @var bool */
public $isWorldTemplateOptionLocked = false;
/** @var bool */
public $onlySpawnV1Villagers = false;
/** @var string */
public $levelId = ""; //base64 string, usually the same as world folder name in vanilla
@ -138,11 +145,10 @@ class StartGamePacket extends DataPacket{
/** @var string */
public $multiplayerCorrelationId = ""; //TODO: this should be filled with a UUID of some sort
/** @var bool */
public $onlySpawnV1Villagers = false;
/** @var array|null each entry must have a "name" (string) and "data" (int16) element */
public $runtimeIdTable = null;
/** @var array|null ["name" (string), "data" (int16), "legacy_id" (int16)] */
public $blockTable = null;
/** @var array|null string (name) => int16 (legacyID) */
public $itemTable = null;
protected function decodePayload(){
$this->entityUniqueId = $this->getEntityUniqueId();
@ -185,6 +191,7 @@ class StartGamePacket extends DataPacket{
$this->useMsaGamertagsOnly = $this->getBool();
$this->isFromWorldTemplate = $this->getBool();
$this->isWorldTemplateOptionLocked = $this->getBool();
$this->onlySpawnV1Villagers = $this->getBool();
$this->levelId = $this->getString();
$this->worldName = $this->getString();
@ -194,18 +201,23 @@ class StartGamePacket extends DataPacket{
$this->enchantmentSeed = $this->getVarInt();
$count = $this->getUnsignedVarInt();
$table = [];
for($i = 0; $i < $count; ++$i){
$this->blockTable = [];
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
$id = $this->getString();
$data = $this->getLShort();
$data = $this->getSignedLShort();
$unknown = $this->getSignedLShort();
$table[$i] = ["name" => $id, "data" => $data];
$this->blockTable[$i] = ["name" => $id, "data" => $data, "legacy_id" => $unknown];
}
$this->itemTable = [];
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
$id = $this->getString();
$legacyId = $this->getSignedLShort();
$this->itemTable[$id] = $legacyId;
}
$this->runtimeIdTable = $table;
$this->multiplayerCorrelationId = $this->getString();
$this->onlySpawnV1Villagers = $this->getBool();
}
protected function encodePayload(){
@ -249,6 +261,7 @@ class StartGamePacket extends DataPacket{
$this->putBool($this->useMsaGamertagsOnly);
$this->putBool($this->isFromWorldTemplate);
$this->putBool($this->isWorldTemplateOptionLocked);
$this->putBool($this->onlySpawnV1Villagers);
$this->putString($this->levelId);
$this->putString($this->worldName);
@ -258,18 +271,25 @@ class StartGamePacket extends DataPacket{
$this->putVarInt($this->enchantmentSeed);
if($this->runtimeIdTable === null){
if(self::$runtimeIdTableCache === null){
if($this->blockTable === null){
if(self::$blockTableCache === null){
//this is a really nasty hack, but it'll do for now
self::$runtimeIdTableCache = self::serializeBlockTable(RuntimeBlockMapping::getBedrockKnownStates());
self::$blockTableCache = self::serializeBlockTable(RuntimeBlockMapping::getBedrockKnownStates());
}
$this->put(self::$runtimeIdTableCache);
$this->put(self::$blockTableCache);
}else{
$this->put(self::serializeBlockTable($this->runtimeIdTable));
$this->put(self::serializeBlockTable($this->blockTable));
}
if($this->itemTable === null){
if(self::$itemTableCache === null){
self::$itemTableCache = self::serializeItemTable(json_decode(file_get_contents(RESOURCE_PATH . '/vanilla/item_id_map.json'), true));
}
$this->put(self::$itemTableCache);
}else{
$this->put(self::serializeItemTable($this->itemTable));
}
$this->putString($this->multiplayerCorrelationId);
$this->putBool($this->onlySpawnV1Villagers);
}
private static function serializeBlockTable(array $table) : string{
@ -278,6 +298,17 @@ class StartGamePacket extends DataPacket{
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{
$stream = new NetworkBinaryStream();
$stream->putUnsignedVarInt(count($table));
foreach($table as $name => $legacyId){
$stream->putString($name);
$stream->putLShort($legacyId);
}
return $stream->getBuffer();
}

View File

@ -0,0 +1,44 @@
<?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\NetworkSession;
class StructureTemplateDataExportRequestPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::STRUCTURE_TEMPLATE_DATA_EXPORT_REQUEST_PACKET;
protected function decodePayload() : void{
//TODO
}
protected function encodePayload() : void{
//TODO
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleStructureTemplateDataExportRequest($this);
}
}

View File

@ -0,0 +1,44 @@
<?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\NetworkSession;
class StructureTemplateDataExportResponsePacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::STRUCTURE_TEMPLATE_DATA_EXPORT_RESPONSE_PACKET;
protected function decodePayload() : void{
//TODO
}
protected function encodePayload() : void{
//TODO
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleStructureTemplateDataExportResponse($this);
}
}

View File

@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\mcpe\NetworkSession;
class TakeItemEntityPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::TAKE_ITEM_ENTITY_PACKET;
class TakeItemActorPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::TAKE_ITEM_ACTOR_PACKET;
/** @var int */
public $target;
@ -47,6 +47,6 @@ class TakeItemEntityPacket extends DataPacket{
}
public function handle(NetworkSession $session) : bool{
return $session->handleTakeItemEntity($this);
return $session->handleTakeItemActor($this);
}
}

View File

@ -25,32 +25,31 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\nbt\NetworkLittleEndianNBTStream;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\NetworkSession;
class FullChunkDataPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::FULL_CHUNK_DATA_PACKET;
class UpdateBlockPropertiesPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::UPDATE_BLOCK_PROPERTIES_PACKET;
/** @var int */
public $chunkX;
/** @var int */
public $chunkZ;
/** @var string */
public $data;
private $nbt;
protected function decodePayload(){
$this->chunkX = $this->getVarInt();
$this->chunkZ = $this->getVarInt();
$this->data = $this->getString();
public static function create(CompoundTag $data) : self{
$result = new self;
$result->nbt = (new NetworkLittleEndianNBTStream())->write($data);
return $result;
}
protected function encodePayload(){
$this->putVarInt($this->chunkX);
$this->putVarInt($this->chunkZ);
$this->putString($this->data);
protected function decodePayload() : void{
$this->nbt = $this->getRemaining();
}
public function handle(NetworkSession $session) : bool{
return $session->handleFullChunkData($this);
protected function encodePayload() : void{
$this->put($this->nbt);
}
public function handle(NetworkSession $handler) : bool{
return $handler->handleUpdateBlockProperties($this);
}
}

View File

@ -39,17 +39,25 @@ class VideoStreamConnectPacket extends DataPacket/* implements ClientboundPacket
public $frameSendFrequency;
/** @var int */
public $action;
/** @var int */
public $resolutionX;
/** @var int */
public $resolutionY;
protected function decodePayload() : void{
$this->serverUri = $this->getString();
$this->frameSendFrequency = $this->getLFloat();
$this->action = $this->getByte();
$this->resolutionX = $this->getLInt();
$this->resolutionY = $this->getLInt();
}
protected function encodePayload() : void{
$this->putString($this->serverUri);
$this->putLFloat($this->frameSendFrequency);
$this->putByte($this->action);
$this->putLInt($this->resolutionX);
$this->putLInt($this->resolutionY);
}
public function handle(NetworkSession $session) : bool{

View File

@ -0,0 +1,56 @@
<?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 ChunkCacheBlob{
/** @var int */
private $hash;
/** @var string */
private $payload;
/**
* ChunkCacheBlob constructor.
*
* @param int $hash
* @param string $payload
*/
public function __construct(int $hash, string $payload){
$this->hash = $hash;
$this->payload = $payload;
}
/**
* @return int
*/
public function getHash() : int{
return $this->hash;
}
/**
* @return string
*/
public function getPayload() : string{
return $this->payload;
}
}

View File

@ -0,0 +1,38 @@
<?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 ResourcePackType{
private function __construct(){
//NOOP
}
public const INVALID = 0;
public const RESOURCES = 1;
public const BEHAVIORS = 2;
public const WORLD_TEMPLATE = 3;
public const ADDON = 4; //scripts?
public const SKINS = 5;
}

View File

@ -56,9 +56,11 @@ final class RuntimeBlockMapping{
foreach($compressedTable as $prefix => $entries){
foreach($entries as $shortStringId => $states){
foreach($states as $state){
$name = "$prefix:$shortStringId";
$decompressed[] = [
"name" => "$prefix:$shortStringId",
"data" => $state
"name" => $name,
"data" => $state,
"legacy_id" => $legacyIdMap[$name]
];
}
}
@ -66,11 +68,12 @@ final class RuntimeBlockMapping{
self::$bedrockKnownStates = self::randomizeTable($decompressed);
foreach(self::$bedrockKnownStates as $k => $obj){
//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
if(!isset($legacyIdMap[$obj["name"]])){
if($obj["data"] > 15){
//TODO: in 1.12 they started using data values bigger than 4 bits which we can't handle right now
continue;
}
self::registerMapping($k, $legacyIdMap[$obj["name"]], $obj["data"]);
//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
self::registerMapping($k, $obj["legacy_id"], $obj["data"]);
}
}

View File

@ -28,7 +28,7 @@ use pocketmine\nbt\NetworkLittleEndianNBTStream;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
use pocketmine\Player;
abstract class Spawnable extends Tile{
@ -37,8 +37,8 @@ abstract class Spawnable extends Tile{
/** @var NetworkLittleEndianNBTStream|null */
private static $nbtWriter = null;
public function createSpawnPacket() : BlockEntityDataPacket{
$pk = new BlockEntityDataPacket();
public function createSpawnPacket() : BlockActorDataPacket{
$pk = new BlockActorDataPacket();
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;