Merge branch 'stable' into next-minor

This commit is contained in:
Dylan K. Taylor 2019-07-26 19:50:17 +01:00
commit bb048fb361
87 changed files with 1961 additions and 908 deletions

View File

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

View File

@ -55,3 +55,15 @@ This changelog **does not account for protocol changes**. If your plugin uses th
- Fixed sluggish playercount updating on MOTD. - Fixed sluggish playercount updating on MOTD.
- Added new MultiRecipe UUIDs. - Added new MultiRecipe UUIDs.
- Added an extra field to `StartGamePacket` to resolve minor incompatibility issues on different 1.11.x patch versions. - Added an extra field to `StartGamePacket` to resolve minor incompatibility issues on different 1.11.x patch versions.
# 3.8.6
- Fixed `Entity->isNameTagAlwaysVisible()` not working.
- Log messages are now cleaned of invalid UTF-8 sequences before emitting them.
- Fixed negative integers being considered as strings for world seeds.
- 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.

54
changelogs/3.9.md Normal file
View File

@ -0,0 +1,54 @@
**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`.
# 3.9.2
- Logger warnings for illegal player movements have been lowered to debug.
- TNT explosions now start from the center instead of the base. This fixes unexpected results when TNT is lit on top of obsidian.
- Fixed the `loadbefore` directive in `plugin.yml` sometimes being ignored.
- Fixed `Item->setCustomName()` with an empty string leaving behind an empty tag.
- Fixed incorrect positioning of bucket empty sound.
- Fixed some incorrect tag parsing in `/give` involving quoted numbers.

View File

@ -17,17 +17,17 @@
"ext-openssl": "*", "ext-openssl": "*",
"ext-pcre": "*", "ext-pcre": "*",
"ext-phar": "*", "ext-phar": "*",
"ext-pthreads": ">=3.1.7dev", "ext-pthreads": "~3.2.0",
"ext-reflection": "*", "ext-reflection": "*",
"ext-sockets": "*", "ext-sockets": "*",
"ext-spl": "*", "ext-spl": "*",
"ext-yaml": ">=2.0.0", "ext-yaml": ">=2.0.0",
"ext-zip": "*", "ext-zip": "*",
"ext-zlib": ">=1.2.11", "ext-zlib": ">=1.2.11",
"pocketmine/raklib": "^0.12.0", "pocketmine/raklib": "^0.12.5",
"pocketmine/spl": "^0.3.0", "pocketmine/spl": "^0.3.0",
"pocketmine/binaryutils": "^0.1.0", "pocketmine/binaryutils": "^0.1.9",
"pocketmine/nbt": "^0.2.6", "pocketmine/nbt": "^0.2.10",
"pocketmine/math": "^0.2.0", "pocketmine/math": "^0.2.0",
"pocketmine/snooze": "^0.1.0", "pocketmine/snooze": "^0.1.0",
"daverandom/callback-validator": "dev-master", "daverandom/callback-validator": "dev-master",

49
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "2f5313e4ebd7b62c785cf683b27464b4", "content-hash": "377d9e0ab5f1a9a4ef9b664706d26f5b",
"packages": [ "packages": [
{ {
"name": "adhocore/json-comment", "name": "adhocore/json-comment",
@ -92,16 +92,16 @@
}, },
{ {
"name": "pocketmine/binaryutils", "name": "pocketmine/binaryutils",
"version": "0.1.8", "version": "0.1.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/pmmp/BinaryUtils.git", "url": "https://github.com/pmmp/BinaryUtils.git",
"reference": "33f511715d22418c03368b49b45a6c25d6b33806" "reference": "8b3b1160679398387cb896fd5d06018413437dfa"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/33f511715d22418c03368b49b45a6c25d6b33806", "url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/8b3b1160679398387cb896fd5d06018413437dfa",
"reference": "33f511715d22418c03368b49b45a6c25d6b33806", "reference": "8b3b1160679398387cb896fd5d06018413437dfa",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -119,10 +119,10 @@
], ],
"description": "Classes and methods for conveniently handling binary data", "description": "Classes and methods for conveniently handling binary data",
"support": { "support": {
"source": "https://github.com/pmmp/BinaryUtils/tree/0.1.8", "source": "https://github.com/pmmp/BinaryUtils/tree/0.1.9",
"issues": "https://github.com/pmmp/BinaryUtils/issues" "issues": "https://github.com/pmmp/BinaryUtils/issues"
}, },
"time": "2019-01-16T17:31:44+00:00" "time": "2019-07-22T13:15:53+00:00"
}, },
{ {
"name": "pocketmine/math", "name": "pocketmine/math",
@ -160,23 +160,23 @@
}, },
{ {
"name": "pocketmine/nbt", "name": "pocketmine/nbt",
"version": "0.2.7", "version": "0.2.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/pmmp/NBT.git", "url": "https://github.com/pmmp/NBT.git",
"reference": "2f176c9f2fd9b31db8bc2ada2f38990157ec8f1a" "reference": "2db27aebe7dc89772aaa8df53361eef801f60063"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/2f176c9f2fd9b31db8bc2ada2f38990157ec8f1a", "url": "https://api.github.com/repos/pmmp/NBT/zipball/2db27aebe7dc89772aaa8df53361eef801f60063",
"reference": "2f176c9f2fd9b31db8bc2ada2f38990157ec8f1a", "reference": "2db27aebe7dc89772aaa8df53361eef801f60063",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-zlib": "*", "ext-zlib": "*",
"php": ">=7.2.0", "php": ">=7.2.0",
"php-64bit": "*", "php-64bit": "*",
"pocketmine/binaryutils": "^0.1.0" "pocketmine/binaryutils": "^0.1.9"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@ -194,33 +194,33 @@
], ],
"description": "PHP library for working with Named Binary Tags", "description": "PHP library for working with Named Binary Tags",
"support": { "support": {
"source": "https://github.com/pmmp/NBT/tree/0.2.7", "source": "https://github.com/pmmp/NBT/tree/0.2.10",
"issues": "https://github.com/pmmp/NBT/issues" "issues": "https://github.com/pmmp/NBT/issues"
}, },
"time": "2019-03-29T19:39:42+00:00" "time": "2019-07-22T15:22:23+00:00"
}, },
{ {
"name": "pocketmine/raklib", "name": "pocketmine/raklib",
"version": "0.12.4", "version": "0.12.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/pmmp/RakLib.git", "url": "https://github.com/pmmp/RakLib.git",
"reference": "fc1ccc8e61b9033e5372436b2e28a7a95388373f" "reference": "874db2d3c24117db2221c1e4550380478aeea852"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/fc1ccc8e61b9033e5372436b2e28a7a95388373f", "url": "https://api.github.com/repos/pmmp/RakLib/zipball/874db2d3c24117db2221c1e4550380478aeea852",
"reference": "fc1ccc8e61b9033e5372436b2e28a7a95388373f", "reference": "874db2d3c24117db2221c1e4550380478aeea852",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-bcmath": "*", "ext-bcmath": "*",
"ext-pthreads": ">=3.1.7dev", "ext-pthreads": "~3.2.0",
"ext-sockets": "*", "ext-sockets": "*",
"php": ">=7.2.0", "php": ">=7.2.0",
"php-64bit": "*", "php-64bit": "*",
"php-ipv6": "*", "php-ipv6": "*",
"pocketmine/binaryutils": "^0.1.0", "pocketmine/binaryutils": "^0.1.9",
"pocketmine/snooze": "^0.1.0", "pocketmine/snooze": "^0.1.0",
"pocketmine/spl": "^0.3.0" "pocketmine/spl": "^0.3.0"
}, },
@ -235,10 +235,10 @@
], ],
"description": "A RakNet server implementation written in PHP", "description": "A RakNet server implementation written in PHP",
"support": { "support": {
"source": "https://github.com/pmmp/RakLib/tree/0.12.4", "source": "https://github.com/pmmp/RakLib/tree/0.12",
"issues": "https://github.com/pmmp/RakLib/issues" "issues": "https://github.com/pmmp/RakLib/issues"
}, },
"time": "2019-05-02T14:53:51+00:00" "time": "2019-07-22T14:38:20+00:00"
}, },
{ {
"name": "pocketmine/snooze", "name": "pocketmine/snooze",
@ -302,7 +302,7 @@
], ],
"description": "Standard library files required by PocketMine-MP and related projects", "description": "Standard library files required by PocketMine-MP and related projects",
"support": { "support": {
"source": "https://github.com/pmmp/SPL/tree/0.3.2" "source": "https://github.com/pmmp/SPL/tree/master"
}, },
"time": "2018-08-12T15:17:39+00:00" "time": "2018-08-12T15:17:39+00:00"
} }
@ -311,7 +311,6 @@
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": { "stability-flags": {
"ext-pthreads": 20,
"daverandom/callback-validator": 20 "daverandom/callback-validator": 20
}, },
"prefer-stable": false, "prefer-stable": false,
@ -329,7 +328,7 @@
"ext-openssl": "*", "ext-openssl": "*",
"ext-pcre": "*", "ext-pcre": "*",
"ext-phar": "*", "ext-phar": "*",
"ext-pthreads": ">=3.1.7dev", "ext-pthreads": "~3.2.0",
"ext-reflection": "*", "ext-reflection": "*",
"ext-sockets": "*", "ext-sockets": "*",
"ext-spl": "*", "ext-spl": "*",

View File

@ -530,7 +530,7 @@ HIDE_FRIEND_COMPOUNDS = NO
# blocks will be appended to the function's detailed documentation block. # blocks will be appended to the function's detailed documentation block.
# The default value is: NO. # The default value is: NO.
HIDE_IN_BODY_DOCS = NO HIDE_IN_BODY_DOCS = YES
# The INTERNAL_DOCS tag determines if documentation that is typed after a # The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation # \internal command is included. If the tag is set to NO then the documentation
@ -600,7 +600,7 @@ SORT_MEMBER_DOCS = YES
# this will also influence the order of the classes in the class list. # this will also influence the order of the classes in the class list.
# The default value is: NO. # The default value is: NO.
SORT_BRIEF_DOCS = NO SORT_BRIEF_DOCS = YES
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and # (brief and detailed) documentation of class members so that constructors and
@ -612,7 +612,7 @@ SORT_BRIEF_DOCS = NO
# detailed member documentation. # detailed member documentation.
# The default value is: NO. # The default value is: NO.
SORT_MEMBERS_CTORS_1ST = NO SORT_MEMBERS_CTORS_1ST = YES
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will # of group names into alphabetical order. If set to NO the group names will
@ -1565,7 +1565,7 @@ MATHJAX_FORMAT = HTML-CSS
# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. # The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
# This tag requires that the tag USE_MATHJAX is set to YES. # This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example # extension names that should be enabled during MathJax rendering. For example

View File

@ -99,20 +99,20 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\DoubleTag; use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\ListTag;
use pocketmine\network\mcpe\PlayerNetworkSessionAdapter; use pocketmine\network\mcpe\PlayerNetworkSessionAdapter;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket; use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket;
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket; use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
use pocketmine\network\mcpe\protocol\AvailableEntityIdentifiersPacket;
use pocketmine\network\mcpe\protocol\BatchPacket; use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket; 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\BlockPickRequestPacket;
use pocketmine\network\mcpe\protocol\BookEditPacket; use pocketmine\network\mcpe\protocol\BookEditPacket;
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket; use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
use pocketmine\network\mcpe\protocol\ContainerClosePacket; use pocketmine\network\mcpe\protocol\ContainerClosePacket;
use pocketmine\network\mcpe\protocol\DataPacket; use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\DisconnectPacket; use pocketmine\network\mcpe\protocol\DisconnectPacket;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\InteractPacket; use pocketmine\network\mcpe\protocol\InteractPacket;
use pocketmine\network\mcpe\protocol\InventoryTransactionPacket; use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket; use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
@ -211,7 +211,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
public const VIEW = Player::SPECTATOR; public const VIEW = Player::SPECTATOR;
/** /**
* Checks a supplied username and checks it is valid. * Validates the given username.
* *
* @param string $name * @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 * @return string
*/ */
@ -1596,7 +1596,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
* If you must tamper with this code, be aware that this can cause very nasty results. Do not waste our time * If you must tamper with this code, be aware that this can cause very nasty results. Do not waste our time
* asking for help if you suffer the consequences of messing with this. * asking for help if you suffer the consequences of messing with this.
*/ */
$this->server->getLogger()->warning($this->getName() . " moved too fast, reverting movement"); $this->server->getLogger()->debug($this->getName() . " moved too fast, reverting movement");
$this->server->getLogger()->debug("Old position: " . $this->asVector3() . ", new position: " . $this->newPosition); $this->server->getLogger()->debug("Old position: " . $this->asVector3() . ", new position: " . $this->newPosition);
$revert = true; $revert = true;
}elseif(!$this->level->isInLoadedTerrain($newPos) or !$this->level->isChunkGenerated($newPos->getFloorX() >> 4, $newPos->getFloorZ() >> 4)){ }elseif(!$this->level->isInLoadedTerrain($newPos) or !$this->level->isChunkGenerated($newPos->getFloorX() >> 4, $newPos->getFloorZ() >> 4)){
@ -1621,7 +1621,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$revert = true; $revert = true;
$this->server->getLogger()->warning($this->getServer()->getLanguage()->translateString("pocketmine.player.invalidMove", [$this->getName()])); $this->server->getLogger()->debug($this->getServer()->getLanguage()->translateString("pocketmine.player.invalidMove", [$this->getName()]));
$this->server->getLogger()->debug("Old position: " . $this->asVector3() . ", new position: " . $this->newPosition); $this->server->getLogger()->debug("Old position: " . $this->asVector3() . ", new position: " . $this->newPosition);
} }
} }
@ -2157,7 +2157,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$pk->worldName = $this->server->getMotd(); $pk->worldName = $this->server->getMotd();
$this->dataPacket($pk); $this->dataPacket($pk);
$this->sendDataPacket(new AvailableEntityIdentifiersPacket()); $this->sendDataPacket(new AvailableActorIdentifiersPacket());
$this->sendDataPacket(new BiomeDefinitionListPacket()); $this->sendDataPacket(new BiomeDefinitionListPacket());
$this->level->sendTime($this); $this->level->sendTime($this);
@ -2279,14 +2279,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return true; return true;
} }
public function handleEntityEvent(EntityEventPacket $packet) : bool{ public function handleEntityEvent(ActorEventPacket $packet) : bool{
if(!$this->spawned or !$this->isAlive()){ if(!$this->spawned or !$this->isAlive()){
return true; return true;
} }
$this->doCloseInventory(); $this->doCloseInventory();
switch($packet->event){ switch($packet->event){
case EntityEventPacket::EATING_ITEM: case ActorEventPacket::EATING_ITEM:
if($packet->data === 0){ if($packet->data === 0){
return false; return false;
} }
@ -2855,6 +2855,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
case PlayerActionPacket::ACTION_STOP_SWIMMING: case PlayerActionPacket::ACTION_STOP_SWIMMING:
//TODO: handle this when it doesn't spam every damn tick (yet another spam bug!!) //TODO: handle this when it doesn't spam every damn tick (yet another spam bug!!)
break; break;
case PlayerActionPacket::ACTION_INTERACT_BLOCK: //ignored (for now)
break;
default: default:
$this->server->getLogger()->debug("Unhandled/unknown player action type " . $packet->action . " from " . $this->getName()); $this->server->getLogger()->debug("Unhandled/unknown player action type " . $packet->action . " from " . $this->getName());
return false; return false;
@ -2981,7 +2983,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return $handled; return $handled;
} }
public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{ public function handleBlockEntityData(BlockActorDataPacket $packet) : bool{
if(!$this->spawned or !$this->isAlive()){ if(!$this->spawned or !$this->isAlive()){
return true; return true;
} }
@ -3416,7 +3418,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$pk->needsTranslation = true; $pk->needsTranslation = true;
$pk->message = $this->server->getLanguage()->translateString($message, $parameters, "pocketmine."); $pk->message = $this->server->getLanguage()->translateString($message, $parameters, "pocketmine.");
foreach($parameters as $i => $p){ foreach($parameters as $i => $p){
$parameters[$i] = $this->server->getLanguage()->translateString($p, $parameters, "pocketmine."); $parameters[$i] = $this->server->getLanguage()->translateString($p, [], "pocketmine.");
} }
$pk->parameters = $parameters; $pk->parameters = $parameters;
}else{ }else{

View File

@ -28,6 +28,7 @@ namespace {
namespace pocketmine { namespace pocketmine {
use pocketmine\utils\Internet;
use pocketmine\utils\MainLogger; use pocketmine\utils\MainLogger;
use pocketmine\utils\Process; use pocketmine\utils\Process;
use pocketmine\utils\ServerKiller; use pocketmine\utils\ServerKiller;
@ -103,8 +104,8 @@ namespace pocketmine {
if(substr_count($pthreads_version, ".") < 2){ if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version"; $pthreads_version = "0.$pthreads_version";
} }
if(version_compare($pthreads_version, "3.1.7dev") < 0){ if(version_compare($pthreads_version, "3.2.0") < 0){
$messages[] = "pthreads >= 3.1.7dev is required, while you have $pthreads_version."; $messages[] = "pthreads >= 3.2.0 is required, while you have $pthreads_version.";
} }
} }
@ -122,6 +123,7 @@ namespace pocketmine {
return $messages; return $messages;
} }
function server(){
if(!empty($messages = check_platform_dependencies())){ if(!empty($messages = check_platform_dependencies())){
echo PHP_EOL; echo PHP_EOL;
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown"; $binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
@ -295,3 +297,6 @@ namespace pocketmine {
exit($exitCode); exit($exitCode);
} }
\pocketmine\server();
}

View File

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

View File

@ -32,6 +32,7 @@ use pocketmine\level\sound\FizzSound;
use pocketmine\math\AxisAlignedBB; use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use function array_fill; use function array_fill;
use function intdiv;
use function lcg_value; use function lcg_value;
use function min; use function min;
@ -372,7 +373,7 @@ abstract class Liquid extends Transparent{
*/ */
private function getOptimalFlowDirections() : array{ private function getOptimalFlowDirections() : array{
$flowCost = array_fill(0, 4, 1000); $flowCost = array_fill(0, 4, 1000);
$maxCost = 4 / $this->getFlowDecayPerBlock(); $maxCost = intdiv(4, $this->getFlowDecayPerBlock());
for($j = 0; $j < 4; ++$j){ for($j = 0; $j < 4; ++$j){
$x = $this->x; $x = $this->x;
$y = $this->y; $y = $this->y;

View File

@ -74,14 +74,14 @@ class FormattedCommandAlias extends Command{
$index = strpos($formatString, '$'); $index = strpos($formatString, '$');
while($index !== false){ while($index !== false){
$start = $index; $start = $index;
if($index > 0 and $formatString{$start - 1} === "\\"){ if($index > 0 and $formatString[$start - 1] === "\\"){
$formatString = substr($formatString, 0, $start - 1) . substr($formatString, $start); $formatString = substr($formatString, 0, $start - 1) . substr($formatString, $start);
$index = strpos($formatString, '$', $index); $index = strpos($formatString, '$', $index);
continue; continue;
} }
$required = false; $required = false;
if($formatString{$index + 1} == '$'){ if($formatString[$index + 1] == '$'){
$required = true; $required = true;
++$index; ++$index;
@ -91,7 +91,7 @@ class FormattedCommandAlias extends Command{
$argStart = $index; $argStart = $index;
while($index < strlen($formatString) and self::inRange(ord($formatString{$index}) - 48, 0, 9)){ while($index < strlen($formatString) and self::inRange(ord($formatString[$index]) - 48, 0, 9)){
++$index; ++$index;
} }
@ -109,7 +109,7 @@ class FormattedCommandAlias extends Command{
$rest = false; $rest = false;
if($index < strlen($formatString) and $formatString{$index} === "-"){ if($index < strlen($formatString) and $formatString[$index] === "-"){
$rest = true; $rest = true;
++$index; ++$index;
} }

View File

@ -65,7 +65,7 @@ abstract class VanillaCommand extends Command{
* @return float * @return float
*/ */
protected function getRelativeDouble(float $original, CommandSender $sender, string $input, float $min = self::MIN_COORD, float $max = self::MAX_COORD) : float{ protected function getRelativeDouble(float $original, CommandSender $sender, string $input, float $min = self::MIN_COORD, float $max = self::MAX_COORD) : float{
if($input{0} === "~"){ if($input[0] === "~"){
$value = $this->getDouble($sender, substr($input, 1)); $value = $this->getDouble($sender, substr($input, 1));
return $original + $value; return $original + $value;

View File

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

View File

@ -46,8 +46,8 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag; use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\AddPlayerPacket; use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\network\mcpe\protocol\LevelEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\PlayerListPacket; use pocketmine\network\mcpe\protocol\PlayerListPacket;
@ -628,7 +628,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
//Old hotbar saving stuff, ignore it //Old hotbar saving stuff, ignore it
}elseif($slot >= 100 and $slot < 104){ //Armor }elseif($slot >= 100 and $slot < 104){ //Armor
$this->armorInventory->setItem($slot - 100, Item::nbtDeserialize($item)); $this->armorInventory->setItem($slot - 100, Item::nbtDeserialize($item));
}else{ }elseif($slot >= 9 and $slot < $this->inventory->getSize() + 9){
$this->inventory->setItem($slot - 9, Item::nbtDeserialize($item)); $this->inventory->setItem($slot - 9, Item::nbtDeserialize($item));
} }
} }
@ -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::FIRE_RESISTANCE), 40 * 20, 1));
$this->addEffect(new EffectInstance(Effect::getEffect(Effect::ABSORPTION), 5 * 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); $this->level->broadcastLevelEvent($this->add(0, $this->eyeHeight, 0), LevelEventPacket::EVENT_SOUND_TOTEM);
$hand = $this->inventory->getItemInHand(); $hand = $this->inventory->getItemInHand();

View File

@ -44,7 +44,7 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\FloatTag; use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag; 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\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\MobEffectPacket; use pocketmine\network\mcpe\protocol\MobEffectPacket;
use pocketmine\Player; use pocketmine\Player;
@ -143,7 +143,7 @@ abstract class Living extends Entity implements Damageable{
parent::setHealth($amount); parent::setHealth($amount);
$this->attributeMap->getAttribute(Attribute::HEALTH)->setValue(ceil($this->getHealth()), true); $this->attributeMap->getAttribute(Attribute::HEALTH)->setValue(ceil($this->getHealth()), true);
if($this->isAlive() and !$wasAlive){ if($this->isAlive() and !$wasAlive){
$this->broadcastEntityEvent(EntityEventPacket::RESPAWN); $this->broadcastEntityEvent(ActorEventPacket::RESPAWN);
} }
} }
@ -541,7 +541,9 @@ abstract class Living extends Entity implements Damageable{
} }
public function attack(EntityDamageEvent $source) : void{ public function attack(EntityDamageEvent $source) : void{
if($this->attackTime > 0 or $this->noDamageTicks > 0){ if($this->noDamageTicks > 0){
$source->setCancelled();
}elseif($this->attackTime > 0){
$lastCause = $this->getLastDamageCause(); $lastCause = $this->getLastDamageCause();
if($lastCause !== null and $lastCause->getBaseDamage() >= $source->getBaseDamage()){ if($lastCause !== null and $lastCause->getBaseDamage() >= $source->getBaseDamage()){
$source->setCancelled(); $source->setCancelled();
@ -604,7 +606,7 @@ abstract class Living extends Entity implements Damageable{
} }
protected function doHitAnimation() : void{ 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{ public function knockBack(Entity $attacker, float $damage, float $x, float $z, float $base = 0.4) : void{
@ -661,7 +663,7 @@ abstract class Living extends Entity implements Damageable{
} }
protected function startDeathAnimation() : void{ protected function startDeathAnimation() : void{
$this->broadcastEntityEvent(EntityEventPacket::DEATH_ANIMATION); $this->broadcastEntityEvent(ActorEventPacket::DEATH_ANIMATION);
} }
protected function endDeathAnimation() : void{ protected function endDeathAnimation() : void{

View File

@ -28,7 +28,7 @@ use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\item\ItemFactory; use pocketmine\item\ItemFactory;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\EntityEventPacket; use pocketmine\network\mcpe\protocol\ActorEventPacket;
use function atan2; use function atan2;
use function mt_rand; use function mt_rand;
use function sqrt; 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->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\entity\ItemSpawnEvent;
use pocketmine\event\inventory\InventoryPickupItemEvent; use pocketmine\event\inventory\InventoryPickupItemEvent;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\network\mcpe\protocol\AddItemEntityPacket; use pocketmine\network\mcpe\protocol\AddItemActorPacket;
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket; use pocketmine\network\mcpe\protocol\TakeItemActorPacket;
use pocketmine\Player; use pocketmine\Player;
use function get_class; use function get_class;
@ -192,7 +192,7 @@ class ItemEntity extends Entity{
} }
protected function sendSpawnPacket(Player $player) : void{ protected function sendSpawnPacket(Player $player) : void{
$pk = new AddItemEntityPacket(); $pk = new AddItemActorPacket();
$pk->entityRuntimeId = $this->getId(); $pk->entityRuntimeId = $this->getId();
$pk->position = $this->asVector3(); $pk->position = $this->asVector3();
$pk->motion = $this->getMotion(); $pk->motion = $this->getMotion();
@ -229,7 +229,7 @@ class ItemEntity extends Entity{
break; break;
} }
$pk = new TakeItemEntityPacket(); $pk = new TakeItemActorPacket();
$pk->eid = $player->getId(); $pk->eid = $player->getId();
$pk->target = $this->getId(); $pk->target = $this->getId();
$this->server->broadcastPacket($this->getViewers(), $pk); $this->server->broadcastPacket($this->getViewers(), $pk);

View File

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

View File

@ -28,6 +28,7 @@ use pocketmine\entity\Explosive;
use pocketmine\event\entity\EntityDamageEvent; use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\ExplosionPrimeEvent; use pocketmine\event\entity\ExplosionPrimeEvent;
use pocketmine\level\Explosion; use pocketmine\level\Explosion;
use pocketmine\level\Position;
use pocketmine\nbt\tag\ShortTag; use pocketmine\nbt\tag\ShortTag;
use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\network\mcpe\protocol\LevelEventPacket;
@ -105,7 +106,7 @@ class PrimedTNT extends Entity implements Explosive{
$ev = new ExplosionPrimeEvent($this, 4); $ev = new ExplosionPrimeEvent($this, 4);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$explosion = new Explosion($this, $ev->getForce(), $this); $explosion = new Explosion(Position::fromObject($this->add(0, $this->height / 2, 0), $this->level), $ev->getForce(), $this);
if($ev->isBlockBreaking()){ if($ev->isBlockBreaking()){
$explosion->explodeA(); $explosion->explodeA();
} }

View File

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

View File

@ -79,8 +79,8 @@ class ShapedRecipe implements CraftingRecipe{
} }
for($x = 0; $x < $this->width; ++$x){ for($x = 0; $x < $this->width; ++$x){
if($row{$x} !== ' ' and !isset($ingredients[$row{$x}])){ if($row[$x] !== ' ' and !isset($ingredients[$row[$x]])){
throw new \InvalidArgumentException("No item specified for symbol '" . $row{$x} . "'"); throw new \InvalidArgumentException("No item specified for symbol '" . $row[$x] . "'");
} }
} }
} }

View File

@ -85,7 +85,7 @@ class Bucket extends Item implements Consumable{
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
$player->getLevel()->setBlock($blockReplace, $resultBlock->getFlowingForm(), true, true); $player->getLevel()->setBlock($blockReplace, $resultBlock->getFlowingForm(), true, true);
$player->getLevel()->broadcastLevelSoundEvent($blockClicked->add(0.5, 0.5, 0.5), $resultBlock->getBucketEmptySound()); $player->getLevel()->broadcastLevelSoundEvent($blockReplace->add(0.5, 0.5, 0.5), $resultBlock->getBucketEmptySound());
if($player->isSurvival()){ if($player->isSurvival()){
$player->getInventory()->setItemInHand($ev->getItem()); $player->getInventory()->setItemInHand($ev->getItem());

View File

@ -467,7 +467,7 @@ class Item implements ItemIds, \JsonSerializable{
*/ */
public function setCustomName(string $name) : Item{ public function setCustomName(string $name) : Item{
if($name === ""){ if($name === ""){
$this->clearCustomName(); return $this->clearCustomName();
} }
/** @var CompoundTag $display */ /** @var CompoundTag $display */

View File

@ -190,7 +190,7 @@ class BaseLang{
$len = strlen($text); $len = strlen($text);
for($i = 0; $i < $len; ++$i){ for($i = 0; $i < $len; ++$i){
$c = $text{$i}; $c = $text[$i];
if($replaceString !== null){ if($replaceString !== null){
$ord = ord($c); $ord = ord($c);
if( if(

View File

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

View File

@ -460,7 +460,7 @@ class Chunk{
* @return int 0-255 * @return int 0-255
*/ */
public function getBiomeId(int $x, int $z) : int{ public function getBiomeId(int $x, int $z) : int{
return ord($this->biomeIds{($z << 4) | $x}); return ord($this->biomeIds[($z << 4) | $x]);
} }
/** /**
@ -472,7 +472,7 @@ class Chunk{
*/ */
public function setBiomeId(int $x, int $z, int $biomeId){ public function setBiomeId(int $x, int $z, int $biomeId){
$this->hasChanged = true; $this->hasChanged = true;
$this->biomeIds{($z << 4) | $x} = chr($biomeId & 0xff); $this->biomeIds[($z << 4) | $x] = chr($biomeId & 0xff);
} }
/** /**
@ -869,13 +869,10 @@ class Chunk{
public function networkSerialize() : string{ public function networkSerialize() : string{
$result = ""; $result = "";
$subChunkCount = $this->getSubChunkSendCount(); $subChunkCount = $this->getSubChunkSendCount();
$result .= chr($subChunkCount);
for($y = 0; $y < $subChunkCount; ++$y){ for($y = 0; $y < $subChunkCount; ++$y){
$result .= $this->subChunks[$y]->networkSerialize(); $result .= $this->subChunks[$y]->networkSerialize();
} }
$result .= pack("v*", ...$this->heightMap) $result .= $this->biomeIds . chr(0); //border block array count
. $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. //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){ foreach($this->tiles as $tile){

View File

@ -71,31 +71,31 @@ class SubChunk implements SubChunkInterface{
} }
public function getBlockId(int $x, int $y, int $z) : int{ public function getBlockId(int $x, int $y, int $z) : int{
return ord($this->ids{($x << 8) | ($z << 4) | $y}); return ord($this->ids[($x << 8) | ($z << 4) | $y]);
} }
public function setBlockId(int $x, int $y, int $z, int $id) : bool{ public function setBlockId(int $x, int $y, int $z, int $id) : bool{
$this->ids{($x << 8) | ($z << 4) | $y} = chr($id); $this->ids[($x << 8) | ($z << 4) | $y] = chr($id);
return true; return true;
} }
public function getBlockData(int $x, int $y, int $z) : int{ public function getBlockData(int $x, int $y, int $z) : int{
return (ord($this->data{($x << 7) | ($z << 3) | ($y >> 1)}) >> (($y & 1) << 2)) & 0xf; return (ord($this->data[($x << 7) | ($z << 3) | ($y >> 1)]) >> (($y & 1) << 2)) & 0xf;
} }
public function setBlockData(int $x, int $y, int $z, int $data) : bool{ public function setBlockData(int $x, int $y, int $z, int $data) : bool{
$i = ($x << 7) | ($z << 3) | ($y >> 1); $i = ($x << 7) | ($z << 3) | ($y >> 1);
$shift = ($y & 1) << 2; $shift = ($y & 1) << 2;
$byte = ord($this->data{$i}); $byte = ord($this->data[$i]);
$this->data{$i} = chr(($byte & ~(0xf << $shift)) | (($data & 0xf) << $shift)); $this->data[$i] = chr(($byte & ~(0xf << $shift)) | (($data & 0xf) << $shift));
return true; return true;
} }
public function getFullBlock(int $x, int $y, int $z) : int{ public function getFullBlock(int $x, int $y, int $z) : int{
$i = ($x << 8) | ($z << 4) | $y; $i = ($x << 8) | ($z << 4) | $y;
return (ord($this->ids{$i}) << 4) | ((ord($this->data{$i >> 1}) >> (($y & 1) << 2)) & 0xf); return (ord($this->ids[$i]) << 4) | ((ord($this->data[$i >> 1]) >> (($y & 1) << 2)) & 0xf);
} }
public function setBlock(int $x, int $y, int $z, ?int $id = null, ?int $data = null) : bool{ public function setBlock(int $x, int $y, int $z, ?int $id = null, ?int $data = null) : bool{
@ -103,8 +103,8 @@ class SubChunk implements SubChunkInterface{
$changed = false; $changed = false;
if($id !== null){ if($id !== null){
$block = chr($id); $block = chr($id);
if($this->ids{$i} !== $block){ if($this->ids[$i] !== $block){
$this->ids{$i} = $block; $this->ids[$i] = $block;
$changed = true; $changed = true;
} }
} }
@ -113,10 +113,10 @@ class SubChunk implements SubChunkInterface{
$i >>= 1; $i >>= 1;
$shift = ($y & 1) << 2; $shift = ($y & 1) << 2;
$oldPair = ord($this->data{$i}); $oldPair = ord($this->data[$i]);
$newPair = ($oldPair & ~(0xf << $shift)) | (($data & 0xf) << $shift); $newPair = ($oldPair & ~(0xf << $shift)) | (($data & 0xf) << $shift);
if($newPair !== $oldPair){ if($newPair !== $oldPair){
$this->data{$i} = chr($newPair); $this->data[$i] = chr($newPair);
$changed = true; $changed = true;
} }
} }
@ -125,29 +125,29 @@ class SubChunk implements SubChunkInterface{
} }
public function getBlockLight(int $x, int $y, int $z) : int{ public function getBlockLight(int $x, int $y, int $z) : int{
return (ord($this->blockLight{($x << 7) | ($z << 3) | ($y >> 1)}) >> (($y & 1) << 2)) & 0xf; return (ord($this->blockLight[($x << 7) | ($z << 3) | ($y >> 1)]) >> (($y & 1) << 2)) & 0xf;
} }
public function setBlockLight(int $x, int $y, int $z, int $level) : bool{ public function setBlockLight(int $x, int $y, int $z, int $level) : bool{
$i = ($x << 7) | ($z << 3) | ($y >> 1); $i = ($x << 7) | ($z << 3) | ($y >> 1);
$shift = ($y & 1) << 2; $shift = ($y & 1) << 2;
$byte = ord($this->blockLight{$i}); $byte = ord($this->blockLight[$i]);
$this->blockLight{$i} = chr(($byte & ~(0xf << $shift)) | (($level & 0xf) << $shift)); $this->blockLight[$i] = chr(($byte & ~(0xf << $shift)) | (($level & 0xf) << $shift));
return true; return true;
} }
public function getBlockSkyLight(int $x, int $y, int $z) : int{ public function getBlockSkyLight(int $x, int $y, int $z) : int{
return (ord($this->skyLight{($x << 7) | ($z << 3) | ($y >> 1)}) >> (($y & 1) << 2)) & 0xf; return (ord($this->skyLight[($x << 7) | ($z << 3) | ($y >> 1)]) >> (($y & 1) << 2)) & 0xf;
} }
public function setBlockSkyLight(int $x, int $y, int $z, int $level) : bool{ public function setBlockSkyLight(int $x, int $y, int $z, int $level) : bool{
$i = ($x << 7) | ($z << 3) | ($y >> 1); $i = ($x << 7) | ($z << 3) | ($y >> 1);
$shift = ($y & 1) << 2; $shift = ($y & 1) << 2;
$byte = ord($this->skyLight{$i}); $byte = ord($this->skyLight[$i]);
$this->skyLight{$i} = chr(($byte & ~(0xf << $shift)) | (($level & 0xf) << $shift)); $this->skyLight[$i] = chr(($byte & ~(0xf << $shift)) | (($level & 0xf) << $shift));
return true; return true;
} }
@ -156,7 +156,7 @@ class SubChunk implements SubChunkInterface{
$low = ($x << 8) | ($z << 4); $low = ($x << 8) | ($z << 4);
$i = $low | 0x0f; $i = $low | 0x0f;
for(; $i >= $low; --$i){ for(; $i >= $low; --$i){
if($this->ids{$i} !== "\x00"){ if($this->ids[$i] !== "\x00"){
return $i & 0x0f; return $i & 0x0f;
} }
} }

View File

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

View File

@ -47,7 +47,7 @@ if(!extension_loaded('pocketmine_chunkutils')){
for($z = $x; $z < $zM; $z += 16){ for($z = $x; $z < $zM; $z += 16){
$yM = $z + 4096; $yM = $z + 4096;
for($y = $z; $y < $yM; $y += 256){ for($y = $z; $y < $yM; $y += 256){
$result{$i} = $array{$y}; $result[$i] = $array[$y];
++$i; ++$i;
} }
} }
@ -76,13 +76,13 @@ if(!extension_loaded('pocketmine_chunkutils')){
for($y = 0; $y < 8; ++$y){ for($y = 0; $y < 8; ++$y){
$j = (($y << 8) | $zx); $j = (($y << 8) | $zx);
$j80 = ($j | 0x80); $j80 = ($j | 0x80);
if($array{$j} === $commonValue and $array{$j80} === $commonValue){ if($array[$j] === $commonValue and $array[$j80] === $commonValue){
//values are already filled //values are already filled
}else{ }else{
$i1 = ord($array{$j}); $i1 = ord($array[$j]);
$i2 = ord($array{$j80}); $i2 = ord($array[$j80]);
$result{$i} = chr(($i2 << 4) | ($i1 & 0x0f)); $result[$i] = chr(($i2 << 4) | ($i1 & 0x0f));
$result{$i | 0x80} = chr(($i1 >> 4) | ($i2 & 0xf0)); $result[$i | 0x80] = chr(($i1 >> 4) | ($i2 & 0xf0));
} }
$i++; $i++;
} }
@ -104,7 +104,7 @@ if(!extension_loaded('pocketmine_chunkutils')){
public static function convertBiomeColors(array $array) : string{ public static function convertBiomeColors(array $array) : string{
$result = str_repeat("\x00", 256); $result = str_repeat("\x00", 256);
foreach($array as $i => $color){ foreach($array as $i => $color){
$result{$i} = chr(($color >> 24) & 0xff); $result[$i] = chr(($color >> 24) & 0xff);
} }
return $result; return $result;
} }

View File

@ -30,7 +30,7 @@ use pocketmine\level\ChunkManager;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\utils\Random; use pocketmine\utils\Random;
use pocketmine\utils\Utils; use pocketmine\utils\Utils;
use function ctype_digit; use function preg_match;
abstract class Generator{ abstract class Generator{
@ -44,7 +44,7 @@ abstract class Generator{
public static function convertSeed(string $seed) : ?int{ public static function convertSeed(string $seed) : ?int{
if($seed === ""){ //empty seed should cause a random seed to be selected - can't use 0 here because 0 is a valid seed if($seed === ""){ //empty seed should cause a random seed to be selected - can't use 0 here because 0 is a valid seed
$convertedSeed = null; $convertedSeed = null;
}elseif(ctype_digit($seed)){ //this avoids treating seeds like "404.4" as integer seeds }elseif(preg_match('/^-?\d+$/', $seed) === 1){ //this avoids treating seeds like "404.4" as integer seeds
$convertedSeed = (int) $seed; $convertedSeed = (int) $seed;
}else{ }else{
$convertedSeed = Utils::javaStringHash($seed); $convertedSeed = Utils::javaStringHash($seed);

View File

@ -48,7 +48,7 @@ class GroundCover extends Populator{
$column = $chunk->getBlockIdColumn($x, $z); $column = $chunk->getBlockIdColumn($x, $z);
for($y = 127; $y > 0; --$y){ for($y = 127; $y > 0; --$y){
if($column{$y} !== "\x00" and !BlockFactory::get(ord($column{$y}))->isTransparent()){ if($column[$y] !== "\x00" and !BlockFactory::get(ord($column[$y]))->isTransparent()){
break; break;
} }
} }
@ -56,10 +56,10 @@ class GroundCover extends Populator{
$endY = $startY - count($cover); $endY = $startY - count($cover);
for($y = $startY; $y > $endY and $y >= 0; --$y){ for($y = $startY; $y > $endY and $y >= 0; --$y){
$b = $cover[$startY - $y]; $b = $cover[$startY - $y];
if($column{$y} === "\x00" and $b->isSolid()){ if($column[$y] === "\x00" and $b->isSolid()){
break; break;
} }
if($b->canBeFlowedInto() and BlockFactory::get(ord($column{$y})) instanceof Liquid){ if($b->canBeFlowedInto() and BlockFactory::get(ord($column[$y])) instanceof Liquid){
continue; continue;
} }
if($b->getDamage() === 0){ if($b->getDamage() === 0){

View File

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

View File

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

View File

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

View File

@ -23,18 +23,22 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe; 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\AddBehaviorTreePacket;
use pocketmine\network\mcpe\protocol\AddEntityPacket; 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\AddPaintingPacket;
use pocketmine\network\mcpe\protocol\AddPlayerPacket; use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket; use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\AutomationClientConnectPacket; use pocketmine\network\mcpe\protocol\AutomationClientConnectPacket;
use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket;
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket; use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
use pocketmine\network\mcpe\protocol\AvailableEntityIdentifiersPacket;
use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket; 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\BlockEventPacket;
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket; use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
use pocketmine\network\mcpe\protocol\BookEditPacket; 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\ChangeDimensionPacket;
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket; use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
use pocketmine\network\mcpe\protocol\ClientboundMapItemDataPacket; 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\ClientToServerHandshakePacket;
use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket; use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket;
use pocketmine\network\mcpe\protocol\CommandOutputPacket; use pocketmine\network\mcpe\protocol\CommandOutputPacket;
@ -54,12 +61,8 @@ use pocketmine\network\mcpe\protocol\CraftingDataPacket;
use pocketmine\network\mcpe\protocol\CraftingEventPacket; use pocketmine\network\mcpe\protocol\CraftingEventPacket;
use pocketmine\network\mcpe\protocol\DataPacket; use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\DisconnectPacket; 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\EventPacket;
use pocketmine\network\mcpe\protocol\ExplodePacket; use pocketmine\network\mcpe\protocol\ExplodePacket;
use pocketmine\network\mcpe\protocol\FullChunkDataPacket;
use pocketmine\network\mcpe\protocol\GameRulesChangedPacket; use pocketmine\network\mcpe\protocol\GameRulesChangedPacket;
use pocketmine\network\mcpe\protocol\GuiDataPickItemPacket; use pocketmine\network\mcpe\protocol\GuiDataPickItemPacket;
use pocketmine\network\mcpe\protocol\HurtArmorPacket; use pocketmine\network\mcpe\protocol\HurtArmorPacket;
@ -70,6 +73,8 @@ use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket; use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
use pocketmine\network\mcpe\protocol\LabTablePacket; use pocketmine\network\mcpe\protocol\LabTablePacket;
use pocketmine\network\mcpe\protocol\LecternUpdatePacket; 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\LevelEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacketV1; 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\MobEquipmentPacket;
use pocketmine\network\mcpe\protocol\ModalFormRequestPacket; use pocketmine\network\mcpe\protocol\ModalFormRequestPacket;
use pocketmine\network\mcpe\protocol\ModalFormResponsePacket; use pocketmine\network\mcpe\protocol\ModalFormResponsePacket;
use pocketmine\network\mcpe\protocol\MoveEntityAbsolutePacket; use pocketmine\network\mcpe\protocol\MoveActorAbsolutePacket;
use pocketmine\network\mcpe\protocol\MoveEntityDeltaPacket; use pocketmine\network\mcpe\protocol\MoveActorDeltaPacket;
use pocketmine\network\mcpe\protocol\MovePlayerPacket; use pocketmine\network\mcpe\protocol\MovePlayerPacket;
use pocketmine\network\mcpe\protocol\NetworkChunkPublisherUpdatePacket; use pocketmine\network\mcpe\protocol\NetworkChunkPublisherUpdatePacket;
use pocketmine\network\mcpe\protocol\NetworkStackLatencyPacket; 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\PlaySoundPacket;
use pocketmine\network\mcpe\protocol\PlayStatusPacket; use pocketmine\network\mcpe\protocol\PlayStatusPacket;
use pocketmine\network\mcpe\protocol\PurchaseReceiptPacket; use pocketmine\network\mcpe\protocol\PurchaseReceiptPacket;
use pocketmine\network\mcpe\protocol\RemoveActorPacket;
use pocketmine\network\mcpe\protocol\RemoveEntityPacket; use pocketmine\network\mcpe\protocol\RemoveEntityPacket;
use pocketmine\network\mcpe\protocol\RemoveObjectivePacket; use pocketmine\network\mcpe\protocol\RemoveObjectivePacket;
use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket; 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\ServerSettingsRequestPacket;
use pocketmine\network\mcpe\protocol\ServerSettingsResponsePacket; use pocketmine\network\mcpe\protocol\ServerSettingsResponsePacket;
use pocketmine\network\mcpe\protocol\ServerToClientHandshakePacket; 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\SetCommandsEnabledPacket;
use pocketmine\network\mcpe\protocol\SetDefaultGameTypePacket; use pocketmine\network\mcpe\protocol\SetDefaultGameTypePacket;
use pocketmine\network\mcpe\protocol\SetDifficultyPacket; use pocketmine\network\mcpe\protocol\SetDifficultyPacket;
use pocketmine\network\mcpe\protocol\SetDisplayObjectivePacket; 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\SetHealthPacket;
use pocketmine\network\mcpe\protocol\SetLastHurtByPacket; use pocketmine\network\mcpe\protocol\SetLastHurtByPacket;
use pocketmine\network\mcpe\protocol\SetLocalPlayerAsInitializedPacket; 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\StartGamePacket;
use pocketmine\network\mcpe\protocol\StopSoundPacket; use pocketmine\network\mcpe\protocol\StopSoundPacket;
use pocketmine\network\mcpe\protocol\StructureBlockUpdatePacket; use pocketmine\network\mcpe\protocol\StructureBlockUpdatePacket;
use pocketmine\network\mcpe\protocol\StructureTemplateDataExportRequestPacket;
use pocketmine\network\mcpe\protocol\StructureTemplateDataExportResponsePacket;
use pocketmine\network\mcpe\protocol\SubClientLoginPacket; 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\TextPacket;
use pocketmine\network\mcpe\protocol\TransferPacket; use pocketmine\network\mcpe\protocol\TransferPacket;
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket; use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket; use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPropertiesPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockSyncedPacket; use pocketmine\network\mcpe\protocol\UpdateBlockSyncedPacket;
use pocketmine\network\mcpe\protocol\UpdateEquipPacket; use pocketmine\network\mcpe\protocol\UpdateEquipPacket;
use pocketmine\network\mcpe\protocol\UpdateSoftEnumPacket; use pocketmine\network\mcpe\protocol\UpdateSoftEnumPacket;
@ -202,23 +211,23 @@ abstract class NetworkSession{
return false; return false;
} }
public function handleAddEntity(AddEntityPacket $packet) : bool{ public function handleAddActor(AddActorPacket $packet) : bool{
return false; return false;
} }
public function handleRemoveEntity(RemoveEntityPacket $packet) : bool{ public function handleRemoveActor(RemoveActorPacket $packet) : bool{
return false; return false;
} }
public function handleAddItemEntity(AddItemEntityPacket $packet) : bool{ public function handleAddItemActor(AddItemActorPacket $packet) : bool{
return false; return false;
} }
public function handleTakeItemEntity(TakeItemEntityPacket $packet) : bool{ public function handleTakeItemActor(TakeItemActorPacket $packet) : bool{
return false; return false;
} }
public function handleMoveEntityAbsolute(MoveEntityAbsolutePacket $packet) : bool{ public function handleMoveActorAbsolute(MoveActorAbsolutePacket $packet) : bool{
return false; return false;
} }
@ -254,7 +263,7 @@ abstract class NetworkSession{
return false; return false;
} }
public function handleEntityEvent(EntityEventPacket $packet) : bool{ public function handleActorEvent(ActorEventPacket $packet) : bool{
return false; return false;
} }
@ -286,7 +295,7 @@ abstract class NetworkSession{
return false; return false;
} }
public function handleEntityPickRequest(EntityPickRequestPacket $packet) : bool{ public function handleActorPickRequest(ActorPickRequestPacket $packet) : bool{
return false; return false;
} }
@ -294,7 +303,7 @@ abstract class NetworkSession{
return false; return false;
} }
public function handleEntityFall(EntityFallPacket $packet) : bool{ public function handleActorFall(ActorFallPacket $packet) : bool{
return false; return false;
} }
@ -302,15 +311,15 @@ abstract class NetworkSession{
return false; return false;
} }
public function handleSetEntityData(SetEntityDataPacket $packet) : bool{ public function handleSetActorData(SetActorDataPacket $packet) : bool{
return false; return false;
} }
public function handleSetEntityMotion(SetEntityMotionPacket $packet) : bool{ public function handleSetActorMotion(SetActorMotionPacket $packet) : bool{
return false; return false;
} }
public function handleSetEntityLink(SetEntityLinkPacket $packet) : bool{ public function handleSetActorLink(SetActorLinkPacket $packet) : bool{
return false; return false;
} }
@ -370,7 +379,7 @@ abstract class NetworkSession{
return false; return false;
} }
public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{ public function handleBlockActorData(BlockActorDataPacket $packet) : bool{
return false; return false;
} }
@ -378,7 +387,7 @@ abstract class NetworkSession{
return false; return false;
} }
public function handleFullChunkData(FullChunkDataPacket $packet) : bool{ public function handleLevelChunk(LevelChunkPacket $packet) : bool{
return false; return false;
} }
@ -590,7 +599,7 @@ abstract class NetworkSession{
return false; return false;
} }
public function handleMoveEntityDelta(MoveEntityDeltaPacket $packet) : bool{ public function handleMoveActorDelta(MoveActorDeltaPacket $packet) : bool{
return false; return false;
} }
@ -618,7 +627,7 @@ abstract class NetworkSession{
return false; return false;
} }
public function handleAvailableEntityIdentifiers(AvailableEntityIdentifiersPacket $packet) : bool{ public function handleAvailableActorIdentifiers(AvailableActorIdentifiersPacket $packet) : bool{
return false; return false;
} }
@ -638,6 +647,10 @@ abstract class NetworkSession{
return false; return false;
} }
public function handleLevelEventGeneric(LevelEventGenericPacket $packet) : bool{
return false;
}
public function handleLecternUpdate(LecternUpdatePacket $packet) : bool{ public function handleLecternUpdate(LecternUpdatePacket $packet) : bool{
return false; return false;
} }
@ -646,11 +659,43 @@ abstract class NetworkSession{
return false; 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; return false;
} }
public function handleOnScreenTextureAnimation(OnScreenTextureAnimationPacket $packet) : bool{ public function handleOnScreenTextureAnimation(OnScreenTextureAnimationPacket $packet) : bool{
return false; 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\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\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket; 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\BlockPickRequestPacket;
use pocketmine\network\mcpe\protocol\BookEditPacket; use pocketmine\network\mcpe\protocol\BookEditPacket;
use pocketmine\network\mcpe\protocol\BossEventPacket; 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\ContainerClosePacket;
use pocketmine\network\mcpe\protocol\CraftingEventPacket; use pocketmine\network\mcpe\protocol\CraftingEventPacket;
use pocketmine\network\mcpe\protocol\DataPacket; 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\InteractPacket;
use pocketmine\network\mcpe\protocol\InventoryTransactionPacket; use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket; use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
@ -142,7 +142,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
return true; //useless leftover from 1.8 return true; //useless leftover from 1.8
} }
public function handleEntityEvent(EntityEventPacket $packet) : bool{ public function handleActorEvent(ActorEventPacket $packet) : bool{
return $this->player->handleEntityEvent($packet); return $this->player->handleEntityEvent($packet);
} }
@ -166,7 +166,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
return $this->player->handleBlockPickRequest($packet); return $this->player->handleBlockPickRequest($packet);
} }
public function handleEntityPickRequest(EntityPickRequestPacket $packet) : bool{ public function handleActorPickRequest(ActorPickRequestPacket $packet) : bool{
return false; //TODO return false; //TODO
} }
@ -174,7 +174,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
return $this->player->handlePlayerAction($packet); return $this->player->handlePlayerAction($packet);
} }
public function handleEntityFall(EntityFallPacket $packet) : bool{ public function handleActorFall(ActorFallPacket $packet) : bool{
return true; //Not used return true; //Not used
} }
@ -198,7 +198,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
return $this->player->handleAdventureSettings($packet); return $this->player->handleAdventureSettings($packet);
} }
public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{ public function handleBlockActorData(BlockActorDataPacket $packet) : bool{
return $this->player->handleBlockEntityData($packet); return $this->player->handleBlockEntityData($packet);
} }

View File

@ -120,12 +120,12 @@ class VerifyLoginTask extends AsyncTask{
[$rString, $sString] = str_split($plainSignature, 48); [$rString, $sString] = str_split($plainSignature, 48);
$rString = ltrim($rString, "\x00"); $rString = ltrim($rString, "\x00");
if(ord($rString{0}) >= 128){ //Would be considered signed, pad it with an extra zero if(ord($rString[0]) >= 128){ //Would be considered signed, pad it with an extra zero
$rString = "\x00" . $rString; $rString = "\x00" . $rString;
} }
$sString = ltrim($sString, "\x00"); $sString = ltrim($sString, "\x00");
if(ord($sString{0}) >= 128){ //Would be considered signed, pad it with an extra zero if(ord($sString[0]) >= 128){ //Would be considered signed, pad it with an extra zero
$sString = "\x00" . $sString; $sString = "\x00" . $sString;
} }

View File

@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\NetworkSession;
class EntityEventPacket extends DataPacket{ class ActorEventPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ENTITY_EVENT_PACKET; public const NETWORK_ID = ProtocolInfo::ACTOR_EVENT_PACKET;
public const HURT_ANIMATION = 2; public const HURT_ANIMATION = 2;
public const DEATH_ANIMATION = 3; public const DEATH_ANIMATION = 3;
@ -103,6 +103,6 @@ class EntityEventPacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ 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; use pocketmine\network\mcpe\NetworkSession;
class EntityFallPacket extends DataPacket{ class ActorFallPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ENTITY_FALL_PACKET; public const NETWORK_ID = ProtocolInfo::ACTOR_FALL_PACKET;
/** @var int */ /** @var int */
public $entityRuntimeId; public $entityRuntimeId;
@ -51,6 +51,6 @@ class EntityFallPacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ 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; use pocketmine\network\mcpe\NetworkSession;
class EntityPickRequestPacket extends DataPacket{ class ActorPickRequestPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ENTITY_PICK_REQUEST_PACKET; public const NETWORK_ID = ProtocolInfo::ACTOR_PICK_REQUEST_PACKET;
/** @var int */ /** @var int */
public $entityUniqueId; public $entityUniqueId;
@ -46,6 +46,6 @@ class EntityPickRequestPacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ 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> #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\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; public const NETWORK_ID = ProtocolInfo::ADD_ENTITY_PACKET;
/* /** @var int */
* Really really really really really nasty hack, to preserve backwards compatibility. private $uvarint1;
* 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). public static function create(int $uvarint1) : self{
* $result = new self;
* TODO: remove this on 4.0 $result->uvarint1 = $uvarint1;
return $result;
}
/**
* @return int
*/ */
public const LEGACY_ID_MAP_BC = [ public function getUvarint1() : int{
EntityIds::NPC => "minecraft:npc", return $this->uvarint1;
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(); protected function decodePayload() : void{
$linkCount = $this->getUnsignedVarInt(); $this->uvarint1 = $this->getUnsignedVarInt();
for($i = 0; $i < $linkCount; ++$i){
$this->links[] = $this->getEntityLink();
}
} }
protected function encodePayload(){ protected function encodePayload() : void{
$this->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId); $this->putUnsignedVarInt($this->uvarint1);
$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); public function handle(NetworkSession $handler) : bool{
$this->putUnsignedVarInt(count($this->links)); return $handler->handleAddEntity($this);
foreach($this->links as $link){
$this->putEntityLink($link);
}
}
public function handle(NetworkSession $session) : bool{
return $session->handleAddEntity($this);
} }
} }

View File

@ -29,8 +29,8 @@ use pocketmine\item\Item;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\NetworkSession;
class AddItemEntityPacket extends DataPacket{ class AddItemActorPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ENTITY_PACKET; public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ACTOR_PACKET;
/** @var int|null */ /** @var int|null */
public $entityUniqueId = null; //TODO public $entityUniqueId = null; //TODO
@ -68,6 +68,6 @@ class AddItemEntityPacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ 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> #include <rules/DataPacket.h>
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\NetworkSession;
class AddPaintingPacket extends DataPacket{ class AddPaintingPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::ADD_PAINTING_PACKET; public const NETWORK_ID = ProtocolInfo::ADD_PAINTING_PACKET;
/** @var string */
public $title;
/** @var int */
public $entityRuntimeId;
/** @var int */
public $x;
/** @var int|null */ /** @var int|null */
public $entityUniqueId = null; public $entityUniqueId = null;
/** @var int */ /** @var int */
public $y; public $entityRuntimeId;
/** @var int */ /** @var Vector3 */
public $z; public $position;
/** @var int */ /** @var int */
public $direction; public $direction;
/** @var string */
public $title;
protected function decodePayload(){ protected function decodePayload(){
$this->entityUniqueId = $this->getEntityUniqueId(); $this->entityUniqueId = $this->getEntityUniqueId();
$this->entityRuntimeId = $this->getEntityRuntimeId(); $this->entityRuntimeId = $this->getEntityRuntimeId();
$this->getBlockPosition($this->x, $this->y, $this->z); $this->position = $this->getVector3();
$this->direction = $this->getVarInt(); $this->direction = $this->getVarInt();
$this->title = $this->getString(); $this->title = $this->getString();
} }
@ -57,7 +54,7 @@ class AddPaintingPacket extends DataPacket{
protected function encodePayload(){ protected function encodePayload(){
$this->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId); $this->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId);
$this->putEntityRuntimeId($this->entityRuntimeId); $this->putEntityRuntimeId($this->entityRuntimeId);
$this->putBlockPosition($this->x, $this->y, $this->z); $this->putVector3($this->position);
$this->putVarInt($this->direction); $this->putVarInt($this->direction);
$this->putString($this->title); $this->putString($this->title);
} }

View File

@ -35,6 +35,8 @@ class AnimatePacket extends DataPacket{
public const ACTION_STOP_SLEEP = 3; public const ACTION_STOP_SLEEP = 3;
public const ACTION_CRITICAL_HIT = 4; public const ACTION_CRITICAL_HIT = 4;
public const ACTION_ROW_RIGHT = 128;
public const ACTION_ROW_LEFT = 129;
/** @var int */ /** @var int */
public $action; public $action;

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; use pocketmine\network\mcpe\NetworkSession;
class BlockEntityDataPacket extends DataPacket{ class BlockActorDataPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::BLOCK_ENTITY_DATA_PACKET; public const NETWORK_ID = ProtocolInfo::BLOCK_ACTOR_DATA_PACKET;
/** @var int */ /** @var int */
public $x; public $x;
@ -51,6 +51,6 @@ class BlockEntityDataPacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ 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; public $name;
/** @var bool */ /** @var bool */
public $shouldTrackOutput; public $shouldTrackOutput;
/** @var int */
public $tickDelay;
/** @var bool */
public $executeOnFirstTick;
protected function decodePayload(){ protected function decodePayload(){
$this->isBlock = $this->getBool(); $this->isBlock = $this->getBool();
@ -78,6 +82,8 @@ class CommandBlockUpdatePacket extends DataPacket{
$this->name = $this->getString(); $this->name = $this->getString();
$this->shouldTrackOutput = $this->getBool(); $this->shouldTrackOutput = $this->getBool();
$this->tickDelay = $this->getLInt();
$this->executeOnFirstTick = $this->getBool();
} }
protected function encodePayload(){ protected function encodePayload(){
@ -97,6 +103,8 @@ class CommandBlockUpdatePacket extends DataPacket{
$this->putString($this->name); $this->putString($this->name);
$this->putBool($this->shouldTrackOutput); $this->putBool($this->shouldTrackOutput);
$this->putLInt($this->tickDelay);
$this->putBool($this->executeOnFirstTick);
} }
public function handle(NetworkSession $session) : bool{ public function handle(NetworkSession $session) : bool{

View File

@ -33,6 +33,9 @@ use pocketmine\item\Item;
use pocketmine\item\ItemFactory; use pocketmine\item\ItemFactory;
use pocketmine\network\mcpe\NetworkBinaryStream; use pocketmine\network\mcpe\NetworkBinaryStream;
use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\NetworkSession;
#ifndef COMPILE
use pocketmine\utils\Binary;
#endif
use function count; use function count;
use function str_repeat; use function str_repeat;
@ -72,11 +75,13 @@ class CraftingDataPacket extends DataPacket{
case self::ENTRY_SHAPELESS: case self::ENTRY_SHAPELESS:
case self::ENTRY_SHULKER_BOX: case self::ENTRY_SHULKER_BOX:
case self::ENTRY_SHAPELESS_CHEMISTRY: case self::ENTRY_SHAPELESS_CHEMISTRY:
$entry["recipe_id"] = $this->getString();
$ingredientCount = $this->getUnsignedVarInt(); $ingredientCount = $this->getUnsignedVarInt();
/** @var Item */ /** @var Item */
$entry["input"] = []; $entry["input"] = [];
for($j = 0; $j < $ingredientCount; ++$j){ 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(); $resultCount = $this->getUnsignedVarInt();
$entry["output"] = []; $entry["output"] = [];
@ -85,16 +90,19 @@ class CraftingDataPacket extends DataPacket{
} }
$entry["uuid"] = $this->getUUID()->toString(); $entry["uuid"] = $this->getUUID()->toString();
$entry["block"] = $this->getString(); $entry["block"] = $this->getString();
$entry["priority"] = $this->getVarInt();
break; break;
case self::ENTRY_SHAPED: case self::ENTRY_SHAPED:
case self::ENTRY_SHAPED_CHEMISTRY: case self::ENTRY_SHAPED_CHEMISTRY:
$entry["recipe_id"] = $this->getString();
$entry["width"] = $this->getVarInt(); $entry["width"] = $this->getVarInt();
$entry["height"] = $this->getVarInt(); $entry["height"] = $this->getVarInt();
$count = $entry["width"] * $entry["height"]; $count = $entry["width"] * $entry["height"];
$entry["input"] = []; $entry["input"] = [];
for($j = 0; $j < $count; ++$j){ 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(); $resultCount = $this->getUnsignedVarInt();
$entry["output"] = []; $entry["output"] = [];
@ -103,6 +111,7 @@ class CraftingDataPacket extends DataPacket{
} }
$entry["uuid"] = $this->getUUID()->toString(); $entry["uuid"] = $this->getUUID()->toString();
$entry["block"] = $this->getString(); $entry["block"] = $this->getString();
$entry["priority"] = $this->getVarInt();
break; break;
case self::ENTRY_FURNACE: case self::ENTRY_FURNACE:
@ -116,7 +125,10 @@ class CraftingDataPacket extends DataPacket{
} }
} }
$entry["input"] = ItemFactory::get($inputId, $inputData); $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(); $entry["block"] = $this->getString();
break; break;
@ -131,11 +143,11 @@ class CraftingDataPacket extends DataPacket{
$this->getBool(); //cleanRecipes $this->getBool(); //cleanRecipes
} }
private static function writeEntry($entry, NetworkBinaryStream $stream){ private static function writeEntry($entry, NetworkBinaryStream $stream, int $pos){
if($entry instanceof ShapelessRecipe){ if($entry instanceof ShapelessRecipe){
return self::writeShapelessRecipe($entry, $stream); return self::writeShapelessRecipe($entry, $stream, $pos);
}elseif($entry instanceof ShapedRecipe){ }elseif($entry instanceof ShapedRecipe){
return self::writeShapedRecipe($entry, $stream); return self::writeShapedRecipe($entry, $stream, $pos);
}elseif($entry instanceof FurnaceRecipe){ }elseif($entry instanceof FurnaceRecipe){
return self::writeFurnaceRecipe($entry, $stream); return self::writeFurnaceRecipe($entry, $stream);
} }
@ -144,10 +156,11 @@ class CraftingDataPacket extends DataPacket{
return -1; 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()); $stream->putUnsignedVarInt($recipe->getIngredientCount());
foreach($recipe->getIngredientList() as $item){ foreach($recipe->getIngredientList() as $item){
$stream->putSlot($item); $stream->putRecipeIngredient($item);
} }
$results = $recipe->getResults(); $results = $recipe->getResults();
@ -158,17 +171,19 @@ class CraftingDataPacket extends DataPacket{
$stream->put(str_repeat("\x00", 16)); //Null UUID $stream->put(str_repeat("\x00", 16)); //Null UUID
$stream->putString("crafting_table"); //TODO: blocktype (no prefix) (this might require internal API breaks) $stream->putString("crafting_table"); //TODO: blocktype (no prefix) (this might require internal API breaks)
$stream->putVarInt(50); //TODO: priority
return CraftingDataPacket::ENTRY_SHAPELESS; 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->getWidth());
$stream->putVarInt($recipe->getHeight()); $stream->putVarInt($recipe->getHeight());
for($z = 0; $z < $recipe->getHeight(); ++$z){ for($z = 0; $z < $recipe->getHeight(); ++$z){
for($x = 0; $x < $recipe->getWidth(); ++$x){ 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->put(str_repeat("\x00", 16)); //Null UUID
$stream->putString("crafting_table"); //TODO: blocktype (no prefix) (this might require internal API breaks) $stream->putString("crafting_table"); //TODO: blocktype (no prefix) (this might require internal API breaks)
$stream->putVarInt(50); //TODO: priority
return CraftingDataPacket::ENTRY_SHAPED; return CraftingDataPacket::ENTRY_SHAPED;
} }
@ -212,8 +228,9 @@ class CraftingDataPacket extends DataPacket{
$this->putUnsignedVarInt(count($this->entries)); $this->putUnsignedVarInt(count($this->entries));
$writer = new NetworkBinaryStream(); $writer = new NetworkBinaryStream();
$counter = 0;
foreach($this->entries as $d){ foreach($this->entries as $d){
$entryType = self::writeEntry($d, $writer); $entryType = self::writeEntry($d, $writer, $counter++);
if($entryType >= 0){ if($entryType >= 0){
$this->putVarInt($entryType); $this->putVarInt($entryType);
$this->put($writer->getBuffer()); $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_STUN = 261;
public const SOUND_BLOCK_SWEET_BERRY_BUSH_HURT = 262; public const SOUND_BLOCK_SWEET_BERRY_BUSH_HURT = 262;
public const SOUND_BLOCK_SWEET_BERRY_BUSH_PICK = 263; public const SOUND_BLOCK_SWEET_BERRY_BUSH_PICK = 263;
public const SOUND_UI_CARTOGRAPHY_TABLE_TAKE_RESULT = 264; public const SOUND_BLOCK_CARTOGRAPHY_TABLE_USE = 264;
public const SOUND_UI_STONECUTTER_TAKE_RESULT = 265; public const SOUND_BLOCK_STONECUTTER_USE = 265;
public const SOUND_BLOCK_COMPOSTER_EMPTY = 266; public const SOUND_BLOCK_COMPOSTER_EMPTY = 266;
public const SOUND_BLOCK_COMPOSTER_FILL = 267; public const SOUND_BLOCK_COMPOSTER_FILL = 267;
public const SOUND_BLOCK_COMPOSTER_FILL_SUCCESS = 268; 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_BLOCK_BARREL_CLOSE = 271;
public const SOUND_RAID_HORN = 272; public const SOUND_RAID_HORN = 272;
public const SOUND_BLOCK_LOOM_USE = 273; 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 */ /** @var int */
public $sound; public $sound;

View File

@ -29,8 +29,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\NetworkSession;
class MoveEntityAbsolutePacket extends DataPacket{ class MoveActorAbsolutePacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::MOVE_ENTITY_ABSOLUTE_PACKET; public const NETWORK_ID = ProtocolInfo::MOVE_ACTOR_ABSOLUTE_PACKET;
public const FLAG_GROUND = 0x01; public const FLAG_GROUND = 0x01;
public const FLAG_TELEPORT = 0x02; public const FLAG_TELEPORT = 0x02;
@ -67,6 +67,6 @@ class MoveEntityAbsolutePacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ 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; use pocketmine\network\mcpe\NetworkSession;
class MoveEntityDeltaPacket extends DataPacket{ class MoveActorDeltaPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::MOVE_ENTITY_DELTA_PACKET; public const NETWORK_ID = ProtocolInfo::MOVE_ACTOR_DELTA_PACKET;
public const FLAG_HAS_X = 0x01; public const FLAG_HAS_X = 0x01;
public const FLAG_HAS_Y = 0x02; public const FLAG_HAS_Y = 0x02;
@ -103,6 +103,6 @@ class MoveEntityDeltaPacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ 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 SetTimePacket());
static::registerPacket(new StartGamePacket()); static::registerPacket(new StartGamePacket());
static::registerPacket(new AddPlayerPacket()); static::registerPacket(new AddPlayerPacket());
static::registerPacket(new AddEntityPacket()); static::registerPacket(new AddActorPacket());
static::registerPacket(new RemoveEntityPacket()); static::registerPacket(new RemoveActorPacket());
static::registerPacket(new AddItemEntityPacket()); static::registerPacket(new AddItemActorPacket());
static::registerPacket(new TakeItemEntityPacket()); static::registerPacket(new TakeItemActorPacket());
static::registerPacket(new MoveEntityAbsolutePacket()); static::registerPacket(new MoveActorAbsolutePacket());
static::registerPacket(new MovePlayerPacket()); static::registerPacket(new MovePlayerPacket());
static::registerPacket(new RiderJumpPacket()); static::registerPacket(new RiderJumpPacket());
static::registerPacket(new UpdateBlockPacket()); static::registerPacket(new UpdateBlockPacket());
@ -58,7 +58,7 @@ class PacketPool{
static::registerPacket(new LevelSoundEventPacketV1()); static::registerPacket(new LevelSoundEventPacketV1());
static::registerPacket(new LevelEventPacket()); static::registerPacket(new LevelEventPacket());
static::registerPacket(new BlockEventPacket()); static::registerPacket(new BlockEventPacket());
static::registerPacket(new EntityEventPacket()); static::registerPacket(new ActorEventPacket());
static::registerPacket(new MobEffectPacket()); static::registerPacket(new MobEffectPacket());
static::registerPacket(new UpdateAttributesPacket()); static::registerPacket(new UpdateAttributesPacket());
static::registerPacket(new InventoryTransactionPacket()); static::registerPacket(new InventoryTransactionPacket());
@ -66,13 +66,13 @@ class PacketPool{
static::registerPacket(new MobArmorEquipmentPacket()); static::registerPacket(new MobArmorEquipmentPacket());
static::registerPacket(new InteractPacket()); static::registerPacket(new InteractPacket());
static::registerPacket(new BlockPickRequestPacket()); static::registerPacket(new BlockPickRequestPacket());
static::registerPacket(new EntityPickRequestPacket()); static::registerPacket(new ActorPickRequestPacket());
static::registerPacket(new PlayerActionPacket()); static::registerPacket(new PlayerActionPacket());
static::registerPacket(new EntityFallPacket()); static::registerPacket(new ActorFallPacket());
static::registerPacket(new HurtArmorPacket()); static::registerPacket(new HurtArmorPacket());
static::registerPacket(new SetEntityDataPacket()); static::registerPacket(new SetActorDataPacket());
static::registerPacket(new SetEntityMotionPacket()); static::registerPacket(new SetActorMotionPacket());
static::registerPacket(new SetEntityLinkPacket()); static::registerPacket(new SetActorLinkPacket());
static::registerPacket(new SetHealthPacket()); static::registerPacket(new SetHealthPacket());
static::registerPacket(new SetSpawnPositionPacket()); static::registerPacket(new SetSpawnPositionPacket());
static::registerPacket(new AnimatePacket()); static::registerPacket(new AnimatePacket());
@ -87,9 +87,9 @@ class PacketPool{
static::registerPacket(new CraftingEventPacket()); static::registerPacket(new CraftingEventPacket());
static::registerPacket(new GuiDataPickItemPacket()); static::registerPacket(new GuiDataPickItemPacket());
static::registerPacket(new AdventureSettingsPacket()); static::registerPacket(new AdventureSettingsPacket());
static::registerPacket(new BlockEntityDataPacket()); static::registerPacket(new BlockActorDataPacket());
static::registerPacket(new PlayerInputPacket()); static::registerPacket(new PlayerInputPacket());
static::registerPacket(new FullChunkDataPacket()); static::registerPacket(new LevelChunkPacket());
static::registerPacket(new SetCommandsEnabledPacket()); static::registerPacket(new SetCommandsEnabledPacket());
static::registerPacket(new SetDifficultyPacket()); static::registerPacket(new SetDifficultyPacket());
static::registerPacket(new ChangeDimensionPacket()); static::registerPacket(new ChangeDimensionPacket());
@ -142,22 +142,31 @@ class PacketPool{
static::registerPacket(new SetScorePacket()); static::registerPacket(new SetScorePacket());
static::registerPacket(new LabTablePacket()); static::registerPacket(new LabTablePacket());
static::registerPacket(new UpdateBlockSyncedPacket()); static::registerPacket(new UpdateBlockSyncedPacket());
static::registerPacket(new MoveEntityDeltaPacket()); static::registerPacket(new MoveActorDeltaPacket());
static::registerPacket(new SetScoreboardIdentityPacket()); static::registerPacket(new SetScoreboardIdentityPacket());
static::registerPacket(new SetLocalPlayerAsInitializedPacket()); static::registerPacket(new SetLocalPlayerAsInitializedPacket());
static::registerPacket(new UpdateSoftEnumPacket()); static::registerPacket(new UpdateSoftEnumPacket());
static::registerPacket(new NetworkStackLatencyPacket()); static::registerPacket(new NetworkStackLatencyPacket());
static::registerPacket(new ScriptCustomEventPacket()); static::registerPacket(new ScriptCustomEventPacket());
static::registerPacket(new SpawnParticleEffectPacket()); static::registerPacket(new SpawnParticleEffectPacket());
static::registerPacket(new AvailableEntityIdentifiersPacket()); static::registerPacket(new AvailableActorIdentifiersPacket());
static::registerPacket(new LevelSoundEventPacketV2()); static::registerPacket(new LevelSoundEventPacketV2());
static::registerPacket(new NetworkChunkPublisherUpdatePacket()); static::registerPacket(new NetworkChunkPublisherUpdatePacket());
static::registerPacket(new BiomeDefinitionListPacket()); static::registerPacket(new BiomeDefinitionListPacket());
static::registerPacket(new LevelSoundEventPacket()); static::registerPacket(new LevelSoundEventPacket());
static::registerPacket(new LevelEventGenericPacket());
static::registerPacket(new LecternUpdatePacket()); static::registerPacket(new LecternUpdatePacket());
static::registerPacket(new VideoStreamConnectPacket()); 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 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_STOP_SWIMMING = 22;
public const ACTION_START_SPIN_ATTACK = 23; public const ACTION_START_SPIN_ATTACK = 23;
public const ACTION_STOP_SPIN_ATTACK = 24; public const ACTION_STOP_SPIN_ATTACK = 24;
public const ACTION_INTERACT_BLOCK = 25;
/** @var int */ /** @var int */
public $entityRuntimeId; public $entityRuntimeId;

View File

@ -39,15 +39,15 @@ interface ProtocolInfo{
/** /**
* Actual Minecraft: PE protocol version * 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. * 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. * 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 LOGIN_PACKET = 0x01;
public const PLAY_STATUS_PACKET = 0x02; public const PLAY_STATUS_PACKET = 0x02;
@ -61,12 +61,12 @@ interface ProtocolInfo{
public const SET_TIME_PACKET = 0x0a; public const SET_TIME_PACKET = 0x0a;
public const START_GAME_PACKET = 0x0b; public const START_GAME_PACKET = 0x0b;
public const ADD_PLAYER_PACKET = 0x0c; public const ADD_PLAYER_PACKET = 0x0c;
public const ADD_ENTITY_PACKET = 0x0d; public const ADD_ACTOR_PACKET = 0x0d;
public const REMOVE_ENTITY_PACKET = 0x0e; public const REMOVE_ACTOR_PACKET = 0x0e;
public const ADD_ITEM_ENTITY_PACKET = 0x0f; public const ADD_ITEM_ACTOR_PACKET = 0x0f;
public const TAKE_ITEM_ENTITY_PACKET = 0x11; public const TAKE_ITEM_ACTOR_PACKET = 0x11;
public const MOVE_ENTITY_ABSOLUTE_PACKET = 0x12; public const MOVE_ACTOR_ABSOLUTE_PACKET = 0x12;
public const MOVE_PLAYER_PACKET = 0x13; public const MOVE_PLAYER_PACKET = 0x13;
public const RIDER_JUMP_PACKET = 0x14; public const RIDER_JUMP_PACKET = 0x14;
public const UPDATE_BLOCK_PACKET = 0x15; public const UPDATE_BLOCK_PACKET = 0x15;
@ -75,7 +75,7 @@ interface ProtocolInfo{
public const LEVEL_SOUND_EVENT_PACKET_V1 = 0x18; public const LEVEL_SOUND_EVENT_PACKET_V1 = 0x18;
public const LEVEL_EVENT_PACKET = 0x19; public const LEVEL_EVENT_PACKET = 0x19;
public const BLOCK_EVENT_PACKET = 0x1a; public const BLOCK_EVENT_PACKET = 0x1a;
public const ENTITY_EVENT_PACKET = 0x1b; public const ACTOR_EVENT_PACKET = 0x1b;
public const MOB_EFFECT_PACKET = 0x1c; public const MOB_EFFECT_PACKET = 0x1c;
public const UPDATE_ATTRIBUTES_PACKET = 0x1d; public const UPDATE_ATTRIBUTES_PACKET = 0x1d;
public const INVENTORY_TRANSACTION_PACKET = 0x1e; public const INVENTORY_TRANSACTION_PACKET = 0x1e;
@ -83,13 +83,13 @@ interface ProtocolInfo{
public const MOB_ARMOR_EQUIPMENT_PACKET = 0x20; public const MOB_ARMOR_EQUIPMENT_PACKET = 0x20;
public const INTERACT_PACKET = 0x21; public const INTERACT_PACKET = 0x21;
public const BLOCK_PICK_REQUEST_PACKET = 0x22; 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 PLAYER_ACTION_PACKET = 0x24;
public const ENTITY_FALL_PACKET = 0x25; public const ACTOR_FALL_PACKET = 0x25;
public const HURT_ARMOR_PACKET = 0x26; public const HURT_ARMOR_PACKET = 0x26;
public const SET_ENTITY_DATA_PACKET = 0x27; public const SET_ACTOR_DATA_PACKET = 0x27;
public const SET_ENTITY_MOTION_PACKET = 0x28; public const SET_ACTOR_MOTION_PACKET = 0x28;
public const SET_ENTITY_LINK_PACKET = 0x29; public const SET_ACTOR_LINK_PACKET = 0x29;
public const SET_HEALTH_PACKET = 0x2a; public const SET_HEALTH_PACKET = 0x2a;
public const SET_SPAWN_POSITION_PACKET = 0x2b; public const SET_SPAWN_POSITION_PACKET = 0x2b;
public const ANIMATE_PACKET = 0x2c; public const ANIMATE_PACKET = 0x2c;
@ -104,9 +104,9 @@ interface ProtocolInfo{
public const CRAFTING_EVENT_PACKET = 0x35; public const CRAFTING_EVENT_PACKET = 0x35;
public const GUI_DATA_PICK_ITEM_PACKET = 0x36; public const GUI_DATA_PICK_ITEM_PACKET = 0x36;
public const ADVENTURE_SETTINGS_PACKET = 0x37; 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 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_COMMANDS_ENABLED_PACKET = 0x3b;
public const SET_DIFFICULTY_PACKET = 0x3c; public const SET_DIFFICULTY_PACKET = 0x3c;
public const CHANGE_DIMENSION_PACKET = 0x3d; public const CHANGE_DIMENSION_PACKET = 0x3d;
@ -159,7 +159,7 @@ interface ProtocolInfo{
public const SET_SCORE_PACKET = 0x6c; public const SET_SCORE_PACKET = 0x6c;
public const LAB_TABLE_PACKET = 0x6d; public const LAB_TABLE_PACKET = 0x6d;
public const UPDATE_BLOCK_SYNCED_PACKET = 0x6e; 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_SCOREBOARD_IDENTITY_PACKET = 0x70;
public const SET_LOCAL_PLAYER_AS_INITIALIZED_PACKET = 0x71; public const SET_LOCAL_PLAYER_AS_INITIALIZED_PACKET = 0x71;
public const UPDATE_SOFT_ENUM_PACKET = 0x72; public const UPDATE_SOFT_ENUM_PACKET = 0x72;
@ -167,14 +167,23 @@ interface ProtocolInfo{
public const SCRIPT_CUSTOM_EVENT_PACKET = 0x75; public const SCRIPT_CUSTOM_EVENT_PACKET = 0x75;
public const SPAWN_PARTICLE_EFFECT_PACKET = 0x76; 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 LEVEL_SOUND_EVENT_PACKET_V2 = 0x78;
public const NETWORK_CHUNK_PUBLISHER_UPDATE_PACKET = 0x79; public const NETWORK_CHUNK_PUBLISHER_UPDATE_PACKET = 0x79;
public const BIOME_DEFINITION_LIST_PACKET = 0x7a; public const BIOME_DEFINITION_LIST_PACKET = 0x7a;
public const LEVEL_SOUND_EVENT_PACKET = 0x7b; public const LEVEL_SOUND_EVENT_PACKET = 0x7b;
public const LECTERN_UPDATE_PACKET = 0x7c; public const LEVEL_EVENT_GENERIC_PACKET = 0x7c;
public const VIDEO_STREAM_CONNECT_PACKET = 0x7d; public const LECTERN_UPDATE_PACKET = 0x7d;
public const MAP_CREATE_LOCKED_COPY_PACKET = 0x7e; public const VIDEO_STREAM_CONNECT_PACKET = 0x7e;
public const ON_SCREEN_TEXTURE_ANIMATION_PACKET = 0x7f; 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> #include <rules/DataPacket.h>
use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\NetworkSession;
class RemoveEntityPacket extends DataPacket{ class RemoveEntityPacket extends DataPacket/* implements ClientboundPacket*/{
public const NETWORK_ID = ProtocolInfo::REMOVE_ENTITY_PACKET; public const NETWORK_ID = ProtocolInfo::REMOVE_ENTITY_PACKET;
/** @var int */ /** @var int */
public $entityUniqueId; private $uvarint1;
protected function decodePayload(){ public static function create(int $uvarint1) : self{
$this->entityUniqueId = $this->getEntityUniqueId(); $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{ protected function decodePayload() : void{
return $session->handleRemoveEntity($this); $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\NetworkSession;
use pocketmine\network\mcpe\protocol\types\ResourcePackType;
class ResourcePackDataInfoPacket extends DataPacket{ class ResourcePackDataInfoPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::RESOURCE_PACK_DATA_INFO_PACKET; public const NETWORK_ID = ProtocolInfo::RESOURCE_PACK_DATA_INFO_PACKET;
@ -42,6 +43,10 @@ class ResourcePackDataInfoPacket extends DataPacket{
public $compressedPackSize; public $compressedPackSize;
/** @var string */ /** @var string */
public $sha256; public $sha256;
/** @var bool */
public $isPremium = false;
/** @var int */
public $packType = ResourcePackType::RESOURCES; //TODO: check the values for this
protected function decodePayload(){ protected function decodePayload(){
$this->packId = $this->getString(); $this->packId = $this->getString();
@ -49,6 +54,8 @@ class ResourcePackDataInfoPacket extends DataPacket{
$this->chunkCount = $this->getLInt(); $this->chunkCount = $this->getLInt();
$this->compressedPackSize = $this->getLLong(); $this->compressedPackSize = $this->getLLong();
$this->sha256 = $this->getString(); $this->sha256 = $this->getString();
$this->isPremium = $this->getBool();
$this->packType = $this->getByte();
} }
protected function encodePayload(){ protected function encodePayload(){
@ -57,6 +64,8 @@ class ResourcePackDataInfoPacket extends DataPacket{
$this->putLInt($this->chunkCount); $this->putLInt($this->chunkCount);
$this->putLLong($this->compressedPackSize); $this->putLLong($this->compressedPackSize);
$this->putString($this->sha256); $this->putString($this->sha256);
$this->putBool($this->isPremium);
$this->putByte($this->packType);
} }
public function handle(NetworkSession $session) : bool{ public function handle(NetworkSession $session) : bool{

View File

@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\NetworkSession;
class SetEntityDataPacket extends DataPacket{ class SetActorDataPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::SET_ENTITY_DATA_PACKET; public const NETWORK_ID = ProtocolInfo::SET_ACTOR_DATA_PACKET;
/** @var int */ /** @var int */
public $entityRuntimeId; public $entityRuntimeId;
@ -47,6 +47,6 @@ class SetEntityDataPacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ 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\NetworkSession;
use pocketmine\network\mcpe\protocol\types\EntityLink; use pocketmine\network\mcpe\protocol\types\EntityLink;
class SetEntityLinkPacket extends DataPacket{ class SetActorLinkPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::SET_ENTITY_LINK_PACKET; public const NETWORK_ID = ProtocolInfo::SET_ACTOR_LINK_PACKET;
/** @var EntityLink */ /** @var EntityLink */
public $link; public $link;
@ -44,6 +44,6 @@ class SetEntityLinkPacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ 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\math\Vector3;
use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\NetworkSession;
class SetEntityMotionPacket extends DataPacket{ class SetActorMotionPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::SET_ENTITY_MOTION_PACKET; public const NETWORK_ID = ProtocolInfo::SET_ACTOR_MOTION_PACKET;
/** @var int */ /** @var int */
public $entityRuntimeId; public $entityRuntimeId;
@ -48,6 +48,6 @@ class SetEntityMotionPacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ 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"); 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\PlayerPermissions;
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping; use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
use function count; use function count;
use function file_get_contents;
use function json_decode;
use const pocketmine\RESOURCE_PATH;
class StartGamePacket extends DataPacket{ class StartGamePacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::START_GAME_PACKET; public const NETWORK_ID = ProtocolInfo::START_GAME_PACKET;
/** @var string|null */ /** @var string|null */
private static $runtimeIdTableCache; private static $blockTableCache = null;
/** @var string|null */
private static $itemTableCache = null;
/** @var int */ /** @var int */
public $entityUniqueId; public $entityUniqueId;
@ -122,6 +127,8 @@ class StartGamePacket extends DataPacket{
public $isFromWorldTemplate = false; public $isFromWorldTemplate = false;
/** @var bool */ /** @var bool */
public $isWorldTemplateOptionLocked = false; public $isWorldTemplateOptionLocked = false;
/** @var bool */
public $onlySpawnV1Villagers = false;
/** @var string */ /** @var string */
public $levelId = ""; //base64 string, usually the same as world folder name in vanilla public $levelId = ""; //base64 string, usually the same as world folder name in vanilla
@ -138,11 +145,10 @@ class StartGamePacket extends DataPacket{
/** @var string */ /** @var string */
public $multiplayerCorrelationId = ""; //TODO: this should be filled with a UUID of some sort public $multiplayerCorrelationId = ""; //TODO: this should be filled with a UUID of some sort
/** @var bool */ /** @var array|null ["name" (string), "data" (int16), "legacy_id" (int16)] */
public $onlySpawnV1Villagers = false; public $blockTable = null;
/** @var array|null string (name) => int16 (legacyID) */
/** @var array|null each entry must have a "name" (string) and "data" (int16) element */ public $itemTable = null;
public $runtimeIdTable = null;
protected function decodePayload(){ protected function decodePayload(){
$this->entityUniqueId = $this->getEntityUniqueId(); $this->entityUniqueId = $this->getEntityUniqueId();
@ -185,6 +191,7 @@ class StartGamePacket extends DataPacket{
$this->useMsaGamertagsOnly = $this->getBool(); $this->useMsaGamertagsOnly = $this->getBool();
$this->isFromWorldTemplate = $this->getBool(); $this->isFromWorldTemplate = $this->getBool();
$this->isWorldTemplateOptionLocked = $this->getBool(); $this->isWorldTemplateOptionLocked = $this->getBool();
$this->onlySpawnV1Villagers = $this->getBool();
$this->levelId = $this->getString(); $this->levelId = $this->getString();
$this->worldName = $this->getString(); $this->worldName = $this->getString();
@ -194,18 +201,23 @@ class StartGamePacket extends DataPacket{
$this->enchantmentSeed = $this->getVarInt(); $this->enchantmentSeed = $this->getVarInt();
$count = $this->getUnsignedVarInt(); $this->blockTable = [];
$table = []; for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
for($i = 0; $i < $count; ++$i){
$id = $this->getString(); $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->multiplayerCorrelationId = $this->getString();
$this->onlySpawnV1Villagers = $this->getBool();
} }
protected function encodePayload(){ protected function encodePayload(){
@ -249,6 +261,7 @@ class StartGamePacket extends DataPacket{
$this->putBool($this->useMsaGamertagsOnly); $this->putBool($this->useMsaGamertagsOnly);
$this->putBool($this->isFromWorldTemplate); $this->putBool($this->isFromWorldTemplate);
$this->putBool($this->isWorldTemplateOptionLocked); $this->putBool($this->isWorldTemplateOptionLocked);
$this->putBool($this->onlySpawnV1Villagers);
$this->putString($this->levelId); $this->putString($this->levelId);
$this->putString($this->worldName); $this->putString($this->worldName);
@ -258,18 +271,25 @@ class StartGamePacket extends DataPacket{
$this->putVarInt($this->enchantmentSeed); $this->putVarInt($this->enchantmentSeed);
if($this->runtimeIdTable === null){ if($this->blockTable === null){
if(self::$runtimeIdTableCache === null){ if(self::$blockTableCache === null){
//this is a really nasty hack, but it'll do for now //this is a really nasty hack, but it'll do for now
self::$runtimeIdTableCache = self::serializeBlockTable(RuntimeBlockMapping::getBedrockKnownStates()); self::$blockTableCache = self::serializeBlockTable(RuntimeBlockMapping::getBedrockKnownStates());
} }
$this->put(self::$runtimeIdTableCache); $this->put(self::$blockTableCache);
}else{ }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->putString($this->multiplayerCorrelationId);
$this->putBool($this->onlySpawnV1Villagers);
} }
private static function serializeBlockTable(array $table) : string{ private static function serializeBlockTable(array $table) : string{
@ -278,6 +298,17 @@ class StartGamePacket extends DataPacket{
foreach($table as $v){ foreach($table as $v){
$stream->putString($v["name"]); $stream->putString($v["name"]);
$stream->putLShort($v["data"]); $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(); 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; use pocketmine\network\mcpe\NetworkSession;
class TakeItemEntityPacket extends DataPacket{ class TakeItemActorPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::TAKE_ITEM_ENTITY_PACKET; public const NETWORK_ID = ProtocolInfo::TAKE_ITEM_ACTOR_PACKET;
/** @var int */ /** @var int */
public $target; public $target;
@ -47,6 +47,6 @@ class TakeItemEntityPacket extends DataPacket{
} }
public function handle(NetworkSession $session) : bool{ public function handle(NetworkSession $session) : bool{
return $session->handleTakeItemEntity($this); return $session->handleTakeItemActor($this);
} }
} }

View File

@ -37,7 +37,7 @@ class UnknownPacket extends DataPacket{
public function pid(){ public function pid(){
if(strlen($this->payload ?? "") > 0){ if(strlen($this->payload ?? "") > 0){
return ord($this->payload{0}); return ord($this->payload[0]);
} }
return self::NETWORK_ID; return self::NETWORK_ID;
} }

View File

@ -25,32 +25,31 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h> #include <rules/DataPacket.h>
use pocketmine\nbt\NetworkLittleEndianNBTStream;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\NetworkSession;
class FullChunkDataPacket extends DataPacket{ class UpdateBlockPropertiesPacket extends DataPacket{
public const NETWORK_ID = ProtocolInfo::FULL_CHUNK_DATA_PACKET; public const NETWORK_ID = ProtocolInfo::UPDATE_BLOCK_PROPERTIES_PACKET;
/** @var int */
public $chunkX;
/** @var int */
public $chunkZ;
/** @var string */ /** @var string */
public $data; private $nbt;
protected function decodePayload(){ public static function create(CompoundTag $data) : self{
$this->chunkX = $this->getVarInt(); $result = new self;
$this->chunkZ = $this->getVarInt(); $result->nbt = (new NetworkLittleEndianNBTStream())->write($data);
$this->data = $this->getString(); return $result;
} }
protected function encodePayload(){ protected function decodePayload() : void{
$this->putVarInt($this->chunkX); $this->nbt = $this->getRemaining();
$this->putVarInt($this->chunkZ);
$this->putString($this->data);
} }
public function handle(NetworkSession $session) : bool{ protected function encodePayload() : void{
return $session->handleFullChunkData($this); $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; public $frameSendFrequency;
/** @var int */ /** @var int */
public $action; public $action;
/** @var int */
public $resolutionX;
/** @var int */
public $resolutionY;
protected function decodePayload() : void{ protected function decodePayload() : void{
$this->serverUri = $this->getString(); $this->serverUri = $this->getString();
$this->frameSendFrequency = $this->getLFloat(); $this->frameSendFrequency = $this->getLFloat();
$this->action = $this->getByte(); $this->action = $this->getByte();
$this->resolutionX = $this->getLInt();
$this->resolutionY = $this->getLInt();
} }
protected function encodePayload() : void{ protected function encodePayload() : void{
$this->putString($this->serverUri); $this->putString($this->serverUri);
$this->putLFloat($this->frameSendFrequency); $this->putLFloat($this->frameSendFrequency);
$this->putByte($this->action); $this->putByte($this->action);
$this->putLInt($this->resolutionX);
$this->putLInt($this->resolutionY);
} }
public function handle(NetworkSession $session) : bool{ 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($compressedTable as $prefix => $entries){
foreach($entries as $shortStringId => $states){ foreach($entries as $shortStringId => $states){
foreach($states as $state){ foreach($states as $state){
$name = "$prefix:$shortStringId";
$decompressed[] = [ $decompressed[] = [
"name" => "$prefix:$shortStringId", "name" => $name,
"data" => $state "data" => $state,
"legacy_id" => $legacyIdMap[$name]
]; ];
} }
} }
@ -66,11 +68,12 @@ final class RuntimeBlockMapping{
self::$bedrockKnownStates = self::randomizeTable($decompressed); self::$bedrockKnownStates = self::randomizeTable($decompressed);
foreach(self::$bedrockKnownStates as $k => $obj){ 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($obj["data"] > 15){
if(!isset($legacyIdMap[$obj["name"]])){ //TODO: in 1.12 they started using data values bigger than 4 bits which we can't handle right now
continue; 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

@ -92,7 +92,7 @@ class QueryHandler{
public function handle(AdvancedSourceInterface $interface, string $address, int $port, string $packet){ public function handle(AdvancedSourceInterface $interface, string $address, int $port, string $packet){
$offset = 2; $offset = 2;
$packetType = ord($packet{$offset++}); $packetType = ord($packet[$offset++]);
$sessionID = Binary::readInt(substr($packet, $offset, 4)); $sessionID = Binary::readInt(substr($packet, $offset, 4));
$offset += 4; $offset += 4;
$payload = substr($packet, $offset); $payload = substr($packet, $offset);

View File

@ -154,7 +154,7 @@ class BanList{
$fp = @fopen($this->file, "r"); $fp = @fopen($this->file, "r");
if(is_resource($fp)){ if(is_resource($fp)){
while(($line = fgets($fp)) !== false){ while(($line = fgets($fp)) !== false){
if($line{0} !== "#"){ if($line[0] !== "#"){
try{ try{
$entry = BanEntry::fromString($line); $entry = BanEntry::fromString($line);
if($entry instanceof BanEntry){ if($entry instanceof BanEntry){

View File

@ -286,7 +286,7 @@ class PluginManager{
$plugins[$name] = $file; $plugins[$name] = $file;
$softDependencies[$name] = $description->getSoftDepend(); $softDependencies[$name] = array_merge($softDependencies[$name] ?? [], $description->getSoftDepend());
$dependencies[$name] = $description->getDepend(); $dependencies[$name] = $description->getDepend();
foreach($description->getLoadBefore() as $before){ foreach($description->getLoadBefore() as $before){

@ -1 +1 @@
Subproject commit 7d9cec8861a9de033da78bb133f8159f2dfd41c5 Subproject commit b5a8c68c4262e5d9d7f8280c1d07c252a5e8dbf8

View File

@ -34,12 +34,12 @@ use function unserialize;
* *
* An AsyncTask does not have its own thread. It is queued into an AsyncPool and executed if there is an async worker * An AsyncTask does not have its own thread. It is queued into an AsyncPool and executed if there is an async worker
* with no AsyncTask running. Therefore, an AsyncTask SHOULD NOT execute for more than a few seconds. For tasks that * with no AsyncTask running. Therefore, an AsyncTask SHOULD NOT execute for more than a few seconds. For tasks that
* run for a long time or infinitely, start another {@link \pocketmine\Thread} instead. * run for a long time or infinitely, start another thread instead.
* *
* WARNING: Any non-Threaded objects WILL BE SERIALIZED when assigned to members of AsyncTasks or other Threaded object. * WARNING: Any non-Threaded objects WILL BE SERIALIZED when assigned to members of AsyncTasks or other Threaded object.
* If later accessed from said Threaded object, you will be operating on a COPY OF THE OBJECT, NOT THE ORIGINAL OBJECT. * If later accessed from said Threaded object, you will be operating on a COPY OF THE OBJECT, NOT THE ORIGINAL OBJECT.
* If you want to store non-serializable objects to access when the task completes, store them using * If you want to store non-serializable objects to access when the task completes, store them using
* {@link AsyncTask#storeLocal}. * {@link AsyncTask::storeLocal}.
* *
* WARNING: As of pthreads v3.1.6, arrays are converted to Volatile objects when assigned as members of Threaded objects. * WARNING: As of pthreads v3.1.6, arrays are converted to Volatile objects when assigned as members of Threaded objects.
* Keep this in mind when using arrays stored as members of your AsyncTask. * Keep this in mind when using arrays stored as members of your AsyncTask.
@ -185,8 +185,8 @@ abstract class AsyncTask extends Collectable{
} }
/** /**
* Call this method from {@link AsyncTask#onRun} (AsyncTask execution thread) to schedule a call to * Call this method from {@link AsyncTask::onRun} (AsyncTask execution thread) to schedule a call to
* {@link AsyncTask#onProgressUpdate} from the main thread with the given progress parameter. * {@link AsyncTask::onProgressUpdate} from the main thread with the given progress parameter.
* *
* @param mixed $progress A value that can be safely serialize()'ed. * @param mixed $progress A value that can be safely serialize()'ed.
*/ */
@ -207,12 +207,12 @@ abstract class AsyncTask extends Collectable{
} }
/** /**
* Called from the main thread after {@link AsyncTask#publishProgress} is called. * Called from the main thread after {@link AsyncTask::publishProgress} is called.
* All {@link AsyncTask#publishProgress} calls should result in {@link AsyncTask#onProgressUpdate} calls before * All {@link AsyncTask::publishProgress} calls should result in {@link AsyncTask::onProgressUpdate} calls before
* {@link AsyncTask#onCompletion} is called. * {@link AsyncTask::onCompletion} is called.
* *
* @param Server $server * @param Server $server
* @param mixed $progress The parameter passed to {@link AsyncTask#publishProgress}. It is serialize()'ed * @param mixed $progress The parameter passed to {@link AsyncTask::publishProgress}. It is serialize()'ed
* and then unserialize()'ed, as if it has been cloned. * and then unserialize()'ed, as if it has been cloned.
*/ */
public function onProgressUpdate(Server $server, $progress){ public function onProgressUpdate(Server $server, $progress){
@ -221,20 +221,20 @@ abstract class AsyncTask extends Collectable{
/** /**
* Saves mixed data in thread-local storage on the parent thread. You may use this to retain references to objects * Saves mixed data in thread-local storage on the parent thread. You may use this to retain references to objects
* or arrays which you need to access in {@link AsyncTask#onCompletion} which cannot be stored as a property of * or arrays which you need to access in {@link AsyncTask::onCompletion} which cannot be stored as a property of
* your task (due to them becoming serialized). * your task (due to them becoming serialized).
* *
* Scalar types can be stored directly in class properties instead of using this storage. * Scalar types can be stored directly in class properties instead of using this storage.
* *
* Objects stored in this storage MUST be retrieved through {@link #fetchLocal} when {@link #onCompletion} is called. * Objects stored in this storage MUST be retrieved through {@link AsyncTask::fetchLocal} when {@link AsyncTask::onCompletion} is called.
* Otherwise, a NOTICE level message will be raised and the reference will be removed after onCompletion exits. * Otherwise, a NOTICE level message will be raised and the reference will be removed after onCompletion exits.
* *
* WARNING: Use this method carefully. It might take a long time before an AsyncTask is completed. PocketMine will * WARNING: Use this method carefully. It might take a long time before an AsyncTask is completed. PocketMine will
* keep a strong reference to objects passed in this method. This may result in a light memory leak. Usually this * keep a strong reference to objects passed in this method. This may result in a light memory leak. Usually this
* does not cause memory failure, but be aware that the object may be no longer usable when the AsyncTask completes. * does not cause memory failure, but be aware that the object may be no longer usable when the AsyncTask completes.
* (E.g. a {@link \pocketmine\Level} object is no longer usable because it is unloaded while the AsyncTask is * (E.g. a Level object is no longer usable because it is unloaded while the AsyncTask is executing, or even a
* executing, or even a plugin might be unloaded). Since PocketMine keeps a strong reference, the objects are still * plugin might be unloaded). Since PocketMine keeps a strong reference, the objects are still valid, but the
* valid, but the implementation is responsible for checking whether these objects are still usable. * implementation is responsible for checking whether these objects are still usable.
* *
* WARNING: THIS METHOD SHOULD ONLY BE CALLED FROM THE MAIN THREAD! * WARNING: THIS METHOD SHOULD ONLY BE CALLED FROM THE MAIN THREAD!
* *
@ -259,13 +259,13 @@ abstract class AsyncTask extends Collectable{
/** /**
* Returns and removes mixed data in thread-local storage on the parent thread. Call this method from * Returns and removes mixed data in thread-local storage on the parent thread. Call this method from
* {@link AsyncTask#onCompletion} to fetch the data stored in the object store, if any. * {@link AsyncTask::onCompletion} to fetch the data stored in the object store, if any.
* *
* If no data was stored in the local store, or if the data was already retrieved by a previous call to fetchLocal, * If no data was stored in the local store, or if the data was already retrieved by a previous call to fetchLocal,
* do NOT call this method, or an exception will be thrown. * do NOT call this method, or an exception will be thrown.
* *
* Do not call this method from {@link AsyncTask#onProgressUpdate}, because this method deletes stored data, which * Do not call this method from {@link AsyncTask::onProgressUpdate}, because this method deletes stored data, which
* means that you will not be able to retrieve it again afterwards. Use {@link AsyncTask#peekLocal} instead to * means that you will not be able to retrieve it again afterwards. Use {@link AsyncTask::peekLocal} instead to
* retrieve stored data without removing it from the store. * retrieve stored data without removing it from the store.
* *
* WARNING: THIS METHOD SHOULD ONLY BE CALLED FROM THE MAIN THREAD! * WARNING: THIS METHOD SHOULD ONLY BE CALLED FROM THE MAIN THREAD!
@ -287,11 +287,11 @@ abstract class AsyncTask extends Collectable{
/** /**
* Returns mixed data in thread-local storage on the parent thread **without clearing** it. Call this method from * Returns mixed data in thread-local storage on the parent thread **without clearing** it. Call this method from
* {@link AsyncTask#onProgressUpdate} to fetch the data stored if you need to be able to access the data later on, * {@link AsyncTask::onProgressUpdate} to fetch the data stored if you need to be able to access the data later on,
* such as in another progress update. * such as in another progress update.
* *
* Use {@link AsyncTask#fetchLocal} instead from {@link AsyncTask#onCompletion}, because this method does not delete * Use {@link AsyncTask::fetchLocal} instead from {@link AsyncTask::onCompletion}, because this method does not delete
* the data, and not clearing the data will result in a warning for memory leak after {@link AsyncTask#onCompletion} * the data, and not clearing the data will result in a warning for memory leak after {@link AsyncTask::onCompletion}
* finished executing. * finished executing.
* *
* WARNING: THIS METHOD SHOULD ONLY BE CALLED FROM THE MAIN THREAD! * WARNING: THIS METHOD SHOULD ONLY BE CALLED FROM THE MAIN THREAD!

View File

@ -31,9 +31,7 @@ use function unserialize;
/** /**
* Executes a consecutive list of cURL operations. * Executes a consecutive list of cURL operations.
* *
* The result of this AsyncTask is an array of arrays (returned from {@link Utils::simpleCurl}) or InternetException objects. * The result of this AsyncTask is an array of arrays (returned from {@link Internet::simpleCurl}) or InternetException objects.
*
* @package pocketmine\scheduler
*/ */
class BulkCurlTask extends AsyncTask{ class BulkCurlTask extends AsyncTask{
private $operations; private $operations;

View File

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

View File

@ -300,7 +300,7 @@ class MainLogger extends \AttachableThreadedLogger{
$threadName = (new \ReflectionClass($thread))->getShortName() . " thread"; $threadName = (new \ReflectionClass($thread))->getShortName() . " thread";
} }
$message = sprintf($this->format, $time->format("H:i:s"), $color, $threadName, $prefix, $message); $message = sprintf($this->format, $time->format("H:i:s"), $color, $threadName, $prefix, TextFormat::clean($message, false));
if(!Terminal::isInit()){ if(!Terminal::isInit()){
Terminal::init($this->mainThreadHasFormattingCodes); //lazy-init colour codes because we don't know if they've been registered on this thread Terminal::init($this->mainThreadHasFormattingCodes); //lazy-init colour codes because we don't know if they've been registered on this thread

View File

@ -455,7 +455,7 @@ class Utils{
public static function javaStringHash(string $string) : int{ public static function javaStringHash(string $string) : int{
$hash = 0; $hash = 0;
for($i = 0, $len = strlen($string); $i < $len; $i++){ for($i = 0, $len = strlen($string); $i < $len; $i++){
$ord = ord($string{$i}); $ord = ord($string[$i]);
if($ord & 0x80){ if($ord & 0x80){
$ord -= 0x100; $ord -= 0x100;
} }