mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-21 00:07:30 +00:00
Merge branch 'stable' into next-minor
This commit is contained in:
commit
bb048fb361
@ -39,7 +39,11 @@ use const STDIN;
|
||||
require_once dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
|
||||
require_once dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
$currentVer = new VersionString(BASE_VERSION);
|
||||
if(isset($argv[1])){
|
||||
$currentVer = new VersionString($argv[1]);
|
||||
}else{
|
||||
$currentVer = new VersionString(BASE_VERSION);
|
||||
}
|
||||
$nextVer = new VersionString(sprintf(
|
||||
"%u.%u.%u",
|
||||
$currentVer->getMajor(),
|
||||
@ -47,27 +51,31 @@ $nextVer = new VersionString(sprintf(
|
||||
$currentVer->getPatch() + 1
|
||||
));
|
||||
|
||||
|
||||
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev) : void{
|
||||
$versionInfo = file_get_contents($versionInfoPath);
|
||||
$versionInfo = preg_replace(
|
||||
$pattern = '/^const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
|
||||
'const BASE_VERSION = "' . $newVersion . '";',
|
||||
$versionInfo
|
||||
);
|
||||
$versionInfo = preg_replace(
|
||||
'/^const IS_DEVELOPMENT_BUILD = (?:true|false);$/m',
|
||||
'const IS_DEVELOPMENT_BUILD = ' . ($isDev ? 'true' : 'false'). ';',
|
||||
$versionInfo
|
||||
);
|
||||
file_put_contents($versionInfoPath, $versionInfo);
|
||||
}
|
||||
$versionInfoPath = dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
|
||||
$versionInfo = file_get_contents($versionInfoPath);
|
||||
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false);
|
||||
|
||||
file_put_contents($versionInfoPath, preg_replace(
|
||||
'/^const IS_DEVELOPMENT_BUILD = true;$/m',
|
||||
'const IS_DEVELOPMENT_BUILD = false;',
|
||||
$versionInfo
|
||||
));
|
||||
echo "please add appropriate notes to the changelog and press enter...";
|
||||
fgets(STDIN);
|
||||
system('git add "' . dirname(__DIR__) . '/changelogs"');
|
||||
system('git commit -m "Release ' . BASE_VERSION . '" --include "' . $versionInfoPath . '"');
|
||||
system('git tag ' . BASE_VERSION);
|
||||
file_put_contents($versionInfoPath, $mod = preg_replace(
|
||||
$pattern = '/^const BASE_VERSION = "' . preg_quote(BASE_VERSION, '/') . '";$/m',
|
||||
'const BASE_VERSION = "' . $nextVer->getBaseVersion() . '";',
|
||||
$versionInfo
|
||||
));
|
||||
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
|
||||
system('git tag ' . $currentVer->getBaseVersion());
|
||||
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true);
|
||||
system('git add "' . $versionInfoPath . '"');
|
||||
system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"');
|
||||
echo "pushing changes in 10 seconds";
|
||||
echo "pushing changes in 10 seconds\n";
|
||||
sleep(10);
|
||||
system('git push origin HEAD ' . BASE_VERSION);
|
||||
system('git push origin HEAD ' . $currentVer->getBaseVersion());
|
||||
|
@ -55,3 +55,15 @@ This changelog **does not account for protocol changes**. If your plugin uses th
|
||||
- Fixed sluggish playercount updating on MOTD.
|
||||
- Added new MultiRecipe UUIDs.
|
||||
- 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
54
changelogs/3.9.md
Normal 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.
|
@ -17,17 +17,17 @@
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-phar": "*",
|
||||
"ext-pthreads": ">=3.1.7dev",
|
||||
"ext-pthreads": "~3.2.0",
|
||||
"ext-reflection": "*",
|
||||
"ext-sockets": "*",
|
||||
"ext-spl": "*",
|
||||
"ext-yaml": ">=2.0.0",
|
||||
"ext-zip": "*",
|
||||
"ext-zlib": ">=1.2.11",
|
||||
"pocketmine/raklib": "^0.12.0",
|
||||
"pocketmine/raklib": "^0.12.5",
|
||||
"pocketmine/spl": "^0.3.0",
|
||||
"pocketmine/binaryutils": "^0.1.0",
|
||||
"pocketmine/nbt": "^0.2.6",
|
||||
"pocketmine/binaryutils": "^0.1.9",
|
||||
"pocketmine/nbt": "^0.2.10",
|
||||
"pocketmine/math": "^0.2.0",
|
||||
"pocketmine/snooze": "^0.1.0",
|
||||
"daverandom/callback-validator": "dev-master",
|
||||
|
49
composer.lock
generated
49
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2f5313e4ebd7b62c785cf683b27464b4",
|
||||
"content-hash": "377d9e0ab5f1a9a4ef9b664706d26f5b",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -92,16 +92,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
"version": "0.1.8",
|
||||
"version": "0.1.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BinaryUtils.git",
|
||||
"reference": "33f511715d22418c03368b49b45a6c25d6b33806"
|
||||
"reference": "8b3b1160679398387cb896fd5d06018413437dfa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/33f511715d22418c03368b49b45a6c25d6b33806",
|
||||
"reference": "33f511715d22418c03368b49b45a6c25d6b33806",
|
||||
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/8b3b1160679398387cb896fd5d06018413437dfa",
|
||||
"reference": "8b3b1160679398387cb896fd5d06018413437dfa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -119,10 +119,10 @@
|
||||
],
|
||||
"description": "Classes and methods for conveniently handling binary data",
|
||||
"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"
|
||||
},
|
||||
"time": "2019-01-16T17:31:44+00:00"
|
||||
"time": "2019-07-22T13:15:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/math",
|
||||
@ -160,23 +160,23 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/nbt",
|
||||
"version": "0.2.7",
|
||||
"version": "0.2.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/NBT.git",
|
||||
"reference": "2f176c9f2fd9b31db8bc2ada2f38990157ec8f1a"
|
||||
"reference": "2db27aebe7dc89772aaa8df53361eef801f60063"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/NBT/zipball/2f176c9f2fd9b31db8bc2ada2f38990157ec8f1a",
|
||||
"reference": "2f176c9f2fd9b31db8bc2ada2f38990157ec8f1a",
|
||||
"url": "https://api.github.com/repos/pmmp/NBT/zipball/2db27aebe7dc89772aaa8df53361eef801f60063",
|
||||
"reference": "2db27aebe7dc89772aaa8df53361eef801f60063",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-zlib": "*",
|
||||
"php": ">=7.2.0",
|
||||
"php-64bit": "*",
|
||||
"pocketmine/binaryutils": "^0.1.0"
|
||||
"pocketmine/binaryutils": "^0.1.9"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
@ -194,33 +194,33 @@
|
||||
],
|
||||
"description": "PHP library for working with Named Binary Tags",
|
||||
"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"
|
||||
},
|
||||
"time": "2019-03-29T19:39:42+00:00"
|
||||
"time": "2019-07-22T15:22:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/raklib",
|
||||
"version": "0.12.4",
|
||||
"version": "0.12.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/RakLib.git",
|
||||
"reference": "fc1ccc8e61b9033e5372436b2e28a7a95388373f"
|
||||
"reference": "874db2d3c24117db2221c1e4550380478aeea852"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/fc1ccc8e61b9033e5372436b2e28a7a95388373f",
|
||||
"reference": "fc1ccc8e61b9033e5372436b2e28a7a95388373f",
|
||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/874db2d3c24117db2221c1e4550380478aeea852",
|
||||
"reference": "874db2d3c24117db2221c1e4550380478aeea852",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-bcmath": "*",
|
||||
"ext-pthreads": ">=3.1.7dev",
|
||||
"ext-pthreads": "~3.2.0",
|
||||
"ext-sockets": "*",
|
||||
"php": ">=7.2.0",
|
||||
"php-64bit": "*",
|
||||
"php-ipv6": "*",
|
||||
"pocketmine/binaryutils": "^0.1.0",
|
||||
"pocketmine/binaryutils": "^0.1.9",
|
||||
"pocketmine/snooze": "^0.1.0",
|
||||
"pocketmine/spl": "^0.3.0"
|
||||
},
|
||||
@ -235,10 +235,10 @@
|
||||
],
|
||||
"description": "A RakNet server implementation written in PHP",
|
||||
"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"
|
||||
},
|
||||
"time": "2019-05-02T14:53:51+00:00"
|
||||
"time": "2019-07-22T14:38:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/snooze",
|
||||
@ -302,7 +302,7 @@
|
||||
],
|
||||
"description": "Standard library files required by PocketMine-MP and related projects",
|
||||
"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"
|
||||
}
|
||||
@ -311,7 +311,6 @@
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"ext-pthreads": 20,
|
||||
"daverandom/callback-validator": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
@ -329,7 +328,7 @@
|
||||
"ext-openssl": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-phar": "*",
|
||||
"ext-pthreads": ">=3.1.7dev",
|
||||
"ext-pthreads": "~3.2.0",
|
||||
"ext-reflection": "*",
|
||||
"ext-sockets": "*",
|
||||
"ext-spl": "*",
|
||||
|
@ -530,7 +530,7 @@ HIDE_FRIEND_COMPOUNDS = NO
|
||||
# blocks will be appended to the function's detailed documentation block.
|
||||
# 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
|
||||
# \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.
|
||||
# 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
|
||||
# (brief and detailed) documentation of class members so that constructors and
|
||||
@ -612,7 +612,7 @@ SORT_BRIEF_DOCS = NO
|
||||
# detailed member documentation.
|
||||
# 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
|
||||
# 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/.
|
||||
# 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
|
||||
# extension names that should be enabled during MathJax rendering. For example
|
||||
|
@ -99,20 +99,20 @@ use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\DoubleTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\network\mcpe\PlayerNetworkSessionAdapter;
|
||||
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
|
||||
use pocketmine\network\mcpe\protocol\AnimatePacket;
|
||||
use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket;
|
||||
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
|
||||
use pocketmine\network\mcpe\protocol\AvailableEntityIdentifiersPacket;
|
||||
use pocketmine\network\mcpe\protocol\BatchPacket;
|
||||
use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\BookEditPacket;
|
||||
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
|
||||
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
|
||||
use pocketmine\network\mcpe\protocol\DataPacket;
|
||||
use pocketmine\network\mcpe\protocol\DisconnectPacket;
|
||||
use pocketmine\network\mcpe\protocol\EntityEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\InteractPacket;
|
||||
use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
|
||||
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
|
||||
@ -211,7 +211,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
public const VIEW = Player::SPECTATOR;
|
||||
|
||||
/**
|
||||
* Checks a supplied username and checks it is valid.
|
||||
* Validates the given username.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
@ -800,7 +800,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the "friendly" name to display of this player to use in the chat.
|
||||
* Returns the "friendly" display name of this player to use in the chat.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@ -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
|
||||
* 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);
|
||||
$revert = true;
|
||||
}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()){
|
||||
$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);
|
||||
}
|
||||
}
|
||||
@ -2157,7 +2157,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$pk->worldName = $this->server->getMotd();
|
||||
$this->dataPacket($pk);
|
||||
|
||||
$this->sendDataPacket(new AvailableEntityIdentifiersPacket());
|
||||
$this->sendDataPacket(new AvailableActorIdentifiersPacket());
|
||||
$this->sendDataPacket(new BiomeDefinitionListPacket());
|
||||
|
||||
$this->level->sendTime($this);
|
||||
@ -2279,14 +2279,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleEntityEvent(EntityEventPacket $packet) : bool{
|
||||
public function handleEntityEvent(ActorEventPacket $packet) : bool{
|
||||
if(!$this->spawned or !$this->isAlive()){
|
||||
return true;
|
||||
}
|
||||
$this->doCloseInventory();
|
||||
|
||||
switch($packet->event){
|
||||
case EntityEventPacket::EATING_ITEM:
|
||||
case ActorEventPacket::EATING_ITEM:
|
||||
if($packet->data === 0){
|
||||
return false;
|
||||
}
|
||||
@ -2855,6 +2855,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
case PlayerActionPacket::ACTION_STOP_SWIMMING:
|
||||
//TODO: handle this when it doesn't spam every damn tick (yet another spam bug!!)
|
||||
break;
|
||||
case PlayerActionPacket::ACTION_INTERACT_BLOCK: //ignored (for now)
|
||||
break;
|
||||
default:
|
||||
$this->server->getLogger()->debug("Unhandled/unknown player action type " . $packet->action . " from " . $this->getName());
|
||||
return false;
|
||||
@ -2981,7 +2983,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return $handled;
|
||||
}
|
||||
|
||||
public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{
|
||||
public function handleBlockEntityData(BlockActorDataPacket $packet) : bool{
|
||||
if(!$this->spawned or !$this->isAlive()){
|
||||
return true;
|
||||
}
|
||||
@ -3416,7 +3418,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$pk->needsTranslation = true;
|
||||
$pk->message = $this->server->getLanguage()->translateString($message, $parameters, "pocketmine.");
|
||||
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;
|
||||
}else{
|
||||
|
@ -28,6 +28,7 @@ namespace {
|
||||
|
||||
namespace pocketmine {
|
||||
|
||||
use pocketmine\utils\Internet;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\ServerKiller;
|
||||
@ -103,8 +104,8 @@ namespace pocketmine {
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "3.1.7dev") < 0){
|
||||
$messages[] = "pthreads >= 3.1.7dev is required, while you have $pthreads_version.";
|
||||
if(version_compare($pthreads_version, "3.2.0") < 0){
|
||||
$messages[] = "pthreads >= 3.2.0 is required, while you have $pthreads_version.";
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,176 +123,180 @@ namespace pocketmine {
|
||||
return $messages;
|
||||
}
|
||||
|
||||
if(!empty($messages = check_platform_dependencies())){
|
||||
echo PHP_EOL;
|
||||
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
|
||||
critical_error("Selected PHP binary ($binary) does not satisfy some requirements.");
|
||||
foreach($messages as $m){
|
||||
echo " - $m" . PHP_EOL;
|
||||
}
|
||||
critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
|
||||
echo PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
unset($messages);
|
||||
|
||||
error_reporting(-1);
|
||||
|
||||
if(\Phar::running(true) !== ""){
|
||||
define('pocketmine\PATH', \Phar::running(true) . "/");
|
||||
}else{
|
||||
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
$opts = getopt("", ["bootstrap:"]);
|
||||
if(isset($opts["bootstrap"])){
|
||||
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
|
||||
}else{
|
||||
$bootstrap = \pocketmine\PATH . 'vendor/autoload.php';
|
||||
}
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||
|
||||
if(\pocketmine\COMPOSER_AUTOLOADER_PATH !== false and is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
|
||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||
}else{
|
||||
critical_error("Composer autoloader not found at " . $bootstrap);
|
||||
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
set_error_handler([Utils::class, 'errorExceptionHandler']);
|
||||
|
||||
/*
|
||||
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
||||
*/
|
||||
$autoloader = new \BaseClassLoader();
|
||||
$autoloader->register(false);
|
||||
|
||||
set_time_limit(0); //Who set it to 30 seconds?!?!
|
||||
|
||||
ini_set("allow_url_fopen", '1');
|
||||
ini_set("display_errors", '1');
|
||||
ini_set("display_startup_errors", '1');
|
||||
ini_set("default_charset", "utf-8");
|
||||
|
||||
ini_set("memory_limit", '-1');
|
||||
|
||||
define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'src' . DIRECTORY_SEPARATOR . 'pocketmine' . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR);
|
||||
|
||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
|
||||
|
||||
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR);
|
||||
define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
|
||||
|
||||
if(!file_exists(\pocketmine\DATA)){
|
||||
mkdir(\pocketmine\DATA, 0777, true);
|
||||
}
|
||||
|
||||
define('pocketmine\LOCK_FILE_PATH', \pocketmine\DATA . 'server.lock');
|
||||
define('pocketmine\LOCK_FILE', fopen(\pocketmine\LOCK_FILE_PATH, "a+b"));
|
||||
if(!flock(\pocketmine\LOCK_FILE, LOCK_EX | LOCK_NB)){
|
||||
//wait for a shared lock to avoid race conditions if two servers started at the same time - this makes sure the
|
||||
//other server wrote its PID and released exclusive lock before we get our lock
|
||||
flock(\pocketmine\LOCK_FILE, LOCK_SH);
|
||||
$pid = stream_get_contents(\pocketmine\LOCK_FILE);
|
||||
critical_error("Another " . \pocketmine\NAME . " instance (PID $pid) is already using this folder (" . realpath(\pocketmine\DATA) . ").");
|
||||
critical_error("Please stop the other server first before running a new one.");
|
||||
exit(1);
|
||||
}
|
||||
ftruncate(\pocketmine\LOCK_FILE, 0);
|
||||
fwrite(\pocketmine\LOCK_FILE, (string) getmypid());
|
||||
fflush(\pocketmine\LOCK_FILE);
|
||||
flock(\pocketmine\LOCK_FILE, LOCK_SH); //prevent acquiring an exclusive lock from another process, but allow reading
|
||||
|
||||
//Logger has a dependency on timezone
|
||||
$tzError = Timezone::init();
|
||||
|
||||
if(isset($opts["enable-ansi"])){
|
||||
Terminal::init(true);
|
||||
}elseif(isset($opts["disable-ansi"])){
|
||||
Terminal::init(false);
|
||||
}else{
|
||||
Terminal::init();
|
||||
}
|
||||
|
||||
$logger = new MainLogger(\pocketmine\DATA . "server.log");
|
||||
$logger->registerStatic();
|
||||
|
||||
foreach($tzError as $e){
|
||||
$logger->warning($e);
|
||||
}
|
||||
unset($tzError);
|
||||
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running " . \pocketmine\NAME . " with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
|
||||
}
|
||||
if(!extension_loaded("pocketmine_chunkutils")){
|
||||
$logger->warning("ChunkUtils extension is missing. Anvil-format worlds will experience degraded performance.");
|
||||
}
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
|
||||
}
|
||||
|
||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||
define('pocketmine\VERSION', $version->getFullVersion(true));
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
if(Process::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){
|
||||
$gitHash = trim($out);
|
||||
if(Process::execute("git diff --quiet") === 1 or Process::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||
$gitHash .= "-dirty";
|
||||
function server(){
|
||||
if(!empty($messages = check_platform_dependencies())){
|
||||
echo PHP_EOL;
|
||||
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
|
||||
critical_error("Selected PHP binary ($binary) does not satisfy some requirements.");
|
||||
foreach($messages as $m){
|
||||
echo " - $m" . PHP_EOL;
|
||||
}
|
||||
critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
|
||||
echo PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
}else{
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(isset($meta["git"])){
|
||||
$gitHash = $meta["git"];
|
||||
unset($messages);
|
||||
|
||||
error_reporting(-1);
|
||||
|
||||
if(\Phar::running(true) !== ""){
|
||||
define('pocketmine\PATH', \Phar::running(true) . "/");
|
||||
}else{
|
||||
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
}
|
||||
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
$opts = getopt("", ["bootstrap:"]);
|
||||
if(isset($opts["bootstrap"])){
|
||||
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
|
||||
}else{
|
||||
$bootstrap = \pocketmine\PATH . 'vendor/autoload.php';
|
||||
}
|
||||
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
|
||||
|
||||
if(\pocketmine\COMPOSER_AUTOLOADER_PATH !== false and is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
|
||||
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
|
||||
}else{
|
||||
critical_error("Composer autoloader not found at " . $bootstrap);
|
||||
critical_error("Please install/update Composer dependencies or use provided builds.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
set_error_handler([Utils::class, 'errorExceptionHandler']);
|
||||
|
||||
$exitCode = 0;
|
||||
do{
|
||||
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||
$installer = new SetupWizard();
|
||||
if(!$installer->run()){
|
||||
$exitCode = -1;
|
||||
break;
|
||||
/*
|
||||
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
|
||||
*/
|
||||
$autoloader = new \BaseClassLoader();
|
||||
$autoloader->register(false);
|
||||
|
||||
set_time_limit(0); //Who set it to 30 seconds?!?!
|
||||
|
||||
ini_set("allow_url_fopen", '1');
|
||||
ini_set("display_errors", '1');
|
||||
ini_set("display_startup_errors", '1');
|
||||
ini_set("default_charset", "utf-8");
|
||||
|
||||
ini_set("memory_limit", '-1');
|
||||
|
||||
define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'src' . DIRECTORY_SEPARATOR . 'pocketmine' . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR);
|
||||
|
||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
|
||||
|
||||
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR);
|
||||
define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
|
||||
|
||||
if(!file_exists(\pocketmine\DATA)){
|
||||
mkdir(\pocketmine\DATA, 0777, true);
|
||||
}
|
||||
|
||||
define('pocketmine\LOCK_FILE_PATH', \pocketmine\DATA . 'server.lock');
|
||||
define('pocketmine\LOCK_FILE', fopen(\pocketmine\LOCK_FILE_PATH, "a+b"));
|
||||
if(!flock(\pocketmine\LOCK_FILE, LOCK_EX | LOCK_NB)){
|
||||
//wait for a shared lock to avoid race conditions if two servers started at the same time - this makes sure the
|
||||
//other server wrote its PID and released exclusive lock before we get our lock
|
||||
flock(\pocketmine\LOCK_FILE, LOCK_SH);
|
||||
$pid = stream_get_contents(\pocketmine\LOCK_FILE);
|
||||
critical_error("Another " . \pocketmine\NAME . " instance (PID $pid) is already using this folder (" . realpath(\pocketmine\DATA) . ").");
|
||||
critical_error("Please stop the other server first before running a new one.");
|
||||
exit(1);
|
||||
}
|
||||
ftruncate(\pocketmine\LOCK_FILE, 0);
|
||||
fwrite(\pocketmine\LOCK_FILE, (string) getmypid());
|
||||
fflush(\pocketmine\LOCK_FILE);
|
||||
flock(\pocketmine\LOCK_FILE, LOCK_SH); //prevent acquiring an exclusive lock from another process, but allow reading
|
||||
|
||||
//Logger has a dependency on timezone
|
||||
$tzError = Timezone::init();
|
||||
|
||||
if(isset($opts["enable-ansi"])){
|
||||
Terminal::init(true);
|
||||
}elseif(isset($opts["disable-ansi"])){
|
||||
Terminal::init(false);
|
||||
}else{
|
||||
Terminal::init();
|
||||
}
|
||||
|
||||
$logger = new MainLogger(\pocketmine\DATA . "server.log");
|
||||
$logger->registerStatic();
|
||||
|
||||
foreach($tzError as $e){
|
||||
$logger->warning($e);
|
||||
}
|
||||
unset($tzError);
|
||||
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running " . \pocketmine\NAME . " with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
|
||||
}
|
||||
if(!extension_loaded("pocketmine_chunkutils")){
|
||||
$logger->warning("ChunkUtils extension is missing. Anvil-format worlds will experience degraded performance.");
|
||||
}
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
|
||||
}
|
||||
|
||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||
define('pocketmine\VERSION', $version->getFullVersion(true));
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
if(Process::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){
|
||||
$gitHash = trim($out);
|
||||
if(Process::execute("git diff --quiet") === 1 or Process::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||
$gitHash .= "-dirty";
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$phar = new \Phar(\Phar::running(false));
|
||||
$meta = $phar->getMetadata();
|
||||
if(isset($meta["git"])){
|
||||
$gitHash = $meta["git"];
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: move this to a Server field
|
||||
define('pocketmine\START_TIME', microtime(true));
|
||||
ThreadManager::init();
|
||||
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
$logger->info("Stopping other threads");
|
||||
|
||||
$killer = new ServerKiller(8);
|
||||
$killer->start(PTHREADS_INHERIT_NONE);
|
||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
|
||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
$exitCode = 0;
|
||||
do{
|
||||
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||
$installer = new SetupWizard();
|
||||
if(!$installer->run()){
|
||||
$exitCode = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Process::kill(getmypid());
|
||||
}
|
||||
}while(false);
|
||||
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
//TODO: move this to a Server field
|
||||
define('pocketmine\START_TIME', microtime(true));
|
||||
ThreadManager::init();
|
||||
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
|
||||
echo Terminal::$FORMAT_RESET . PHP_EOL;
|
||||
$logger->info("Stopping other threads");
|
||||
|
||||
exit($exitCode);
|
||||
$killer = new ServerKiller(8);
|
||||
$killer->start(PTHREADS_INHERIT_NONE);
|
||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||
|
||||
if(ThreadManager::getInstance()->stopAll() > 0){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
Process::kill(getmypid());
|
||||
}
|
||||
}while(false);
|
||||
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
|
||||
echo Terminal::$FORMAT_RESET . PHP_EOL;
|
||||
|
||||
exit($exitCode);
|
||||
}
|
||||
|
||||
\pocketmine\server();
|
||||
}
|
||||
|
@ -22,6 +22,6 @@
|
||||
namespace pocketmine;
|
||||
|
||||
const NAME = "PocketMine-MP";
|
||||
const BASE_VERSION = "3.8.6";
|
||||
const BASE_VERSION = "3.9.3";
|
||||
const IS_DEVELOPMENT_BUILD = true;
|
||||
const BUILD_NUMBER = 0;
|
||||
|
@ -32,6 +32,7 @@ use pocketmine\level\sound\FizzSound;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use function array_fill;
|
||||
use function intdiv;
|
||||
use function lcg_value;
|
||||
use function min;
|
||||
|
||||
@ -372,7 +373,7 @@ abstract class Liquid extends Transparent{
|
||||
*/
|
||||
private function getOptimalFlowDirections() : array{
|
||||
$flowCost = array_fill(0, 4, 1000);
|
||||
$maxCost = 4 / $this->getFlowDecayPerBlock();
|
||||
$maxCost = intdiv(4, $this->getFlowDecayPerBlock());
|
||||
for($j = 0; $j < 4; ++$j){
|
||||
$x = $this->x;
|
||||
$y = $this->y;
|
||||
|
@ -74,14 +74,14 @@ class FormattedCommandAlias extends Command{
|
||||
$index = strpos($formatString, '$');
|
||||
while($index !== false){
|
||||
$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);
|
||||
$index = strpos($formatString, '$', $index);
|
||||
continue;
|
||||
}
|
||||
|
||||
$required = false;
|
||||
if($formatString{$index + 1} == '$'){
|
||||
if($formatString[$index + 1] == '$'){
|
||||
$required = true;
|
||||
|
||||
++$index;
|
||||
@ -91,7 +91,7 @@ class FormattedCommandAlias extends Command{
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ class FormattedCommandAlias extends Command{
|
||||
|
||||
$rest = false;
|
||||
|
||||
if($index < strlen($formatString) and $formatString{$index} === "-"){
|
||||
if($index < strlen($formatString) and $formatString[$index] === "-"){
|
||||
$rest = true;
|
||||
++$index;
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ abstract class VanillaCommand extends Command{
|
||||
* @return 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));
|
||||
|
||||
return $original + $value;
|
||||
|
@ -62,12 +62,12 @@ use pocketmine\nbt\tag\DoubleTag;
|
||||
use pocketmine\nbt\tag\FloatTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\network\mcpe\protocol\AddEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\EntityEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\MoveEntityAbsolutePacket;
|
||||
use pocketmine\network\mcpe\protocol\RemoveEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetEntityDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetEntityMotionPacket;
|
||||
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddActorPacket;
|
||||
use pocketmine\network\mcpe\protocol\MoveActorAbsolutePacket;
|
||||
use pocketmine\network\mcpe\protocol\RemoveActorPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetActorDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetActorMotionPacket;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use pocketmine\Server;
|
||||
@ -154,70 +154,76 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
public const DATA_LEAD_HOLDER_EID = 37; //long
|
||||
public const DATA_SCALE = 38; //float
|
||||
public const DATA_HAS_NPC_COMPONENT = 39; //byte (???)
|
||||
public const DATA_SKIN_ID = 40; //string
|
||||
public const DATA_NPC_SKIN_ID = 41; //string
|
||||
public const DATA_URL_TAG = 42; //string
|
||||
public const DATA_MAX_AIR = 43; //short
|
||||
public const DATA_MARK_VARIANT = 44; //int
|
||||
public const DATA_CONTAINER_TYPE = 45; //byte (ContainerComponent)
|
||||
public const DATA_CONTAINER_BASE_SIZE = 46; //int (ContainerComponent)
|
||||
public const DATA_CONTAINER_EXTRA_SLOTS_PER_STRENGTH = 47; //int (used for llamas, inventory size is baseSize + thisProp * strength)
|
||||
public const DATA_BLOCK_TARGET = 48; //block coords (ender crystal)
|
||||
public const DATA_WITHER_INVULNERABLE_TICKS = 49; //int
|
||||
public const DATA_WITHER_TARGET_1 = 50; //long
|
||||
public const DATA_WITHER_TARGET_2 = 51; //long
|
||||
public const DATA_WITHER_TARGET_3 = 52; //long
|
||||
/* 53 (short) */
|
||||
public const DATA_BOUNDING_BOX_WIDTH = 54; //float
|
||||
public const DATA_BOUNDING_BOX_HEIGHT = 55; //float
|
||||
public const DATA_FUSE_LENGTH = 56; //int
|
||||
public const DATA_RIDER_SEAT_POSITION = 57; //vector3f
|
||||
public const DATA_RIDER_ROTATION_LOCKED = 58; //byte
|
||||
public const DATA_RIDER_MAX_ROTATION = 59; //float
|
||||
public const DATA_RIDER_MIN_ROTATION = 60; //float
|
||||
public const DATA_AREA_EFFECT_CLOUD_RADIUS = 61; //float
|
||||
public const DATA_AREA_EFFECT_CLOUD_WAITING = 62; //int
|
||||
public const DATA_AREA_EFFECT_CLOUD_PARTICLE_ID = 63; //int
|
||||
/* 64 (int) shulker-related */
|
||||
public const DATA_SHULKER_ATTACH_FACE = 65; //byte
|
||||
/* 66 (short) shulker-related */
|
||||
public const DATA_SHULKER_ATTACH_POS = 67; //block coords
|
||||
public const DATA_TRADING_PLAYER_EID = 68; //long
|
||||
public const DATA_NPC_SKIN_INDEX = 40; //string
|
||||
public const DATA_NPC_ACTIONS = 41; //string (maybe JSON blob?)
|
||||
public const DATA_MAX_AIR = 42; //short
|
||||
public const DATA_MARK_VARIANT = 43; //int
|
||||
public const DATA_CONTAINER_TYPE = 44; //byte (ContainerComponent)
|
||||
public const DATA_CONTAINER_BASE_SIZE = 45; //int (ContainerComponent)
|
||||
public const DATA_CONTAINER_EXTRA_SLOTS_PER_STRENGTH = 46; //int (used for llamas, inventory size is baseSize + thisProp * strength)
|
||||
public const DATA_BLOCK_TARGET = 47; //block coords (ender crystal)
|
||||
public const DATA_WITHER_INVULNERABLE_TICKS = 48; //int
|
||||
public const DATA_WITHER_TARGET_1 = 49; //long
|
||||
public const DATA_WITHER_TARGET_2 = 50; //long
|
||||
public const DATA_WITHER_TARGET_3 = 51; //long
|
||||
/* 52 (short) */
|
||||
public const DATA_BOUNDING_BOX_WIDTH = 53; //float
|
||||
public const DATA_BOUNDING_BOX_HEIGHT = 54; //float
|
||||
public const DATA_FUSE_LENGTH = 55; //int
|
||||
public const DATA_RIDER_SEAT_POSITION = 56; //vector3f
|
||||
public const DATA_RIDER_ROTATION_LOCKED = 57; //byte
|
||||
public const DATA_RIDER_MAX_ROTATION = 58; //float
|
||||
public const DATA_RIDER_MIN_ROTATION = 59; //float
|
||||
public const DATA_AREA_EFFECT_CLOUD_RADIUS = 60; //float
|
||||
public const DATA_AREA_EFFECT_CLOUD_WAITING = 61; //int
|
||||
public const DATA_AREA_EFFECT_CLOUD_PARTICLE_ID = 62; //int
|
||||
/* 63 (int) shulker-related */
|
||||
public const DATA_SHULKER_ATTACH_FACE = 64; //byte
|
||||
/* 65 (short) shulker-related */
|
||||
public const DATA_SHULKER_ATTACH_POS = 66; //block coords
|
||||
public const DATA_TRADING_PLAYER_EID = 67; //long
|
||||
|
||||
/* 70 (byte) command-block */
|
||||
public const DATA_COMMAND_BLOCK_COMMAND = 71; //string
|
||||
public const DATA_COMMAND_BLOCK_LAST_OUTPUT = 72; //string
|
||||
public const DATA_COMMAND_BLOCK_TRACK_OUTPUT = 73; //byte
|
||||
public const DATA_CONTROLLING_RIDER_SEAT_NUMBER = 74; //byte
|
||||
public const DATA_STRENGTH = 75; //int
|
||||
public const DATA_MAX_STRENGTH = 76; //int
|
||||
/* 77 (int) */
|
||||
public const DATA_LIMITED_LIFE = 78;
|
||||
public const DATA_ARMOR_STAND_POSE_INDEX = 79; //int
|
||||
public const DATA_ENDER_CRYSTAL_TIME_OFFSET = 80; //int
|
||||
public const DATA_ALWAYS_SHOW_NAMETAG = 81; //byte: -1 = default, 0 = only when looked at, 1 = always
|
||||
public const DATA_COLOR_2 = 82; //byte
|
||||
/* 83 (unknown) */
|
||||
public const DATA_SCORE_TAG = 84; //string
|
||||
public const DATA_BALLOON_ATTACHED_ENTITY = 85; //int64, entity unique ID of owner
|
||||
public const DATA_PUFFERFISH_SIZE = 86; //byte
|
||||
public const DATA_BOAT_BUBBLE_TIME = 87; //int (time in bubble column)
|
||||
public const DATA_PLAYER_AGENT_EID = 88; //long
|
||||
/* 89 (float) related to panda sitting
|
||||
* 90 (float) related to panda sitting */
|
||||
public const DATA_EAT_COUNTER = 91; //int (used by pandas)
|
||||
public const DATA_FLAGS2 = 92; //long (extended data flags)
|
||||
/* 93 (float) related to panda lying down
|
||||
* 94 (float) related to panda lying down */
|
||||
public const DATA_AREA_EFFECT_CLOUD_DURATION = 95; //int
|
||||
public const DATA_AREA_EFFECT_CLOUD_SPAWN_TIME = 96; //int
|
||||
public const DATA_AREA_EFFECT_CLOUD_RADIUS_PER_TICK = 97; //float, usually negative
|
||||
public const DATA_AREA_EFFECT_CLOUD_RADIUS_CHANGE_ON_PICKUP = 98; //float
|
||||
public const DATA_AREA_EFFECT_CLOUD_PICKUP_COUNT = 99; //int
|
||||
public const DATA_INTERACTIVE_TAG = 100; //string (button text)
|
||||
public const DATA_TRADE_TIER = 101; //int
|
||||
public const DATA_MAX_TRADE_TIER = 102; //int
|
||||
public const DATA_TRADE_XP = 103; //int
|
||||
/* 69 (byte) command-block */
|
||||
public const DATA_COMMAND_BLOCK_COMMAND = 70; //string
|
||||
public const DATA_COMMAND_BLOCK_LAST_OUTPUT = 71; //string
|
||||
public const DATA_COMMAND_BLOCK_TRACK_OUTPUT = 72; //byte
|
||||
public const DATA_CONTROLLING_RIDER_SEAT_NUMBER = 73; //byte
|
||||
public const DATA_STRENGTH = 74; //int
|
||||
public const DATA_MAX_STRENGTH = 75; //int
|
||||
/* 76 (int) */
|
||||
public const DATA_LIMITED_LIFE = 77;
|
||||
public const DATA_ARMOR_STAND_POSE_INDEX = 78; //int
|
||||
public const DATA_ENDER_CRYSTAL_TIME_OFFSET = 79; //int
|
||||
public const DATA_ALWAYS_SHOW_NAMETAG = 80; //byte: -1 = default, 0 = only when looked at, 1 = always
|
||||
public const DATA_COLOR_2 = 81; //byte
|
||||
/* 82 (unknown) */
|
||||
public const DATA_SCORE_TAG = 83; //string
|
||||
public const DATA_BALLOON_ATTACHED_ENTITY = 84; //int64, entity unique ID of owner
|
||||
public const DATA_PUFFERFISH_SIZE = 85; //byte
|
||||
public const DATA_BOAT_BUBBLE_TIME = 86; //int (time in bubble column)
|
||||
public const DATA_PLAYER_AGENT_EID = 87; //long
|
||||
/* 88 (float) related to panda sitting
|
||||
* 89 (float) related to panda sitting */
|
||||
public const DATA_EAT_COUNTER = 90; //int (used by pandas)
|
||||
public const DATA_FLAGS2 = 91; //long (extended data flags)
|
||||
/* 92 (float) related to panda lying down
|
||||
* 93 (float) related to panda lying down */
|
||||
public const DATA_AREA_EFFECT_CLOUD_DURATION = 94; //int
|
||||
public const DATA_AREA_EFFECT_CLOUD_SPAWN_TIME = 95; //int
|
||||
public const DATA_AREA_EFFECT_CLOUD_RADIUS_PER_TICK = 96; //float, usually negative
|
||||
public const DATA_AREA_EFFECT_CLOUD_RADIUS_CHANGE_ON_PICKUP = 97; //float
|
||||
public const DATA_AREA_EFFECT_CLOUD_PICKUP_COUNT = 98; //int
|
||||
public const DATA_INTERACTIVE_TAG = 99; //string (button text)
|
||||
public const DATA_TRADE_TIER = 100; //int
|
||||
public const DATA_MAX_TRADE_TIER = 101; //int
|
||||
public const DATA_TRADE_XP = 102; //int
|
||||
public const DATA_SKIN_ID = 103; //int ???
|
||||
/* 104 (int) related to wither */
|
||||
public const DATA_COMMAND_BLOCK_TICK_DELAY = 105; //int
|
||||
public const DATA_COMMAND_BLOCK_EXECUTE_ON_FIRST_TICK = 106; //byte
|
||||
public const DATA_AMBIENT_SOUND_INTERVAL_MIN = 107; //float
|
||||
public const DATA_AMBIENT_SOUND_INTERVAL_RANGE = 108; //float
|
||||
public const DATA_AMBIENT_SOUND_EVENT = 109; //string
|
||||
|
||||
public const DATA_FLAG_ONFIRE = 0;
|
||||
public const DATA_FLAG_SNEAKING = 1;
|
||||
@ -662,7 +668,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
* @return 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->setGenericFlag(self::DATA_FLAG_ONFIRE, true);
|
||||
$this->setGenericFlag(self::DATA_FLAG_ONFIRE, $this->isOnFire());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1235,7 +1241,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
}
|
||||
|
||||
protected function broadcastMovement(bool $teleport = false) : void{
|
||||
$pk = new MoveEntityAbsolutePacket();
|
||||
$pk = new MoveActorAbsolutePacket();
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->position = $this->getOffsetPosition($this);
|
||||
|
||||
@ -1247,14 +1253,14 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
$pk->zRot = $this->yaw;
|
||||
|
||||
if($teleport){
|
||||
$pk->flags |= MoveEntityAbsolutePacket::FLAG_TELEPORT;
|
||||
$pk->flags |= MoveActorAbsolutePacket::FLAG_TELEPORT;
|
||||
}
|
||||
|
||||
$this->level->broadcastPacketToViewers($this, $pk);
|
||||
}
|
||||
|
||||
protected function broadcastMotion() : void{
|
||||
$pk = new SetEntityMotionPacket();
|
||||
$pk = new SetActorMotionPacket();
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->motion = $this->getMotion();
|
||||
|
||||
@ -2021,7 +2027,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
* @param Player $player
|
||||
*/
|
||||
protected function sendSpawnPacket(Player $player) : void{
|
||||
$pk = new AddEntityPacket();
|
||||
$pk = new AddActorPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->type = static::NETWORK_ID;
|
||||
$pk->position = $this->asVector3();
|
||||
@ -2071,7 +2077,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
public function despawnFrom(Player $player, bool $send = true) : void{
|
||||
if(isset($this->hasSpawned[$player->getLoaderId()])){
|
||||
if($send){
|
||||
$pk = new RemoveEntityPacket();
|
||||
$pk = new RemoveActorPacket();
|
||||
$pk->entityUniqueId = $this->id;
|
||||
$player->dataPacket($pk);
|
||||
}
|
||||
@ -2193,7 +2199,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
$player = [$player];
|
||||
}
|
||||
|
||||
$pk = new SetEntityDataPacket();
|
||||
$pk = new SetActorDataPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->metadata = $data ?? $this->propertyManager->getAll();
|
||||
|
||||
@ -2210,7 +2216,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
|
||||
}
|
||||
|
||||
public function broadcastEntityEvent(int $eventId, ?int $eventData = null, ?array $players = null) : void{
|
||||
$pk = new EntityEventPacket();
|
||||
$pk = new ActorEventPacket();
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->event = $eventId;
|
||||
$pk->data = $eventData ?? 0;
|
||||
|
@ -46,8 +46,8 @@ use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
|
||||
use pocketmine\network\mcpe\protocol\EntityEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerListPacket;
|
||||
@ -628,7 +628,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
//Old hotbar saving stuff, ignore it
|
||||
}elseif($slot >= 100 and $slot < 104){ //Armor
|
||||
$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));
|
||||
}
|
||||
}
|
||||
@ -754,7 +754,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
$this->addEffect(new EffectInstance(Effect::getEffect(Effect::FIRE_RESISTANCE), 40 * 20, 1));
|
||||
$this->addEffect(new EffectInstance(Effect::getEffect(Effect::ABSORPTION), 5 * 20, 1));
|
||||
|
||||
$this->broadcastEntityEvent(EntityEventPacket::CONSUME_TOTEM);
|
||||
$this->broadcastEntityEvent(ActorEventPacket::CONSUME_TOTEM);
|
||||
$this->level->broadcastLevelEvent($this->add(0, $this->eyeHeight, 0), LevelEventPacket::EVENT_SOUND_TOTEM);
|
||||
|
||||
$hand = $this->inventory->getItemInHand();
|
||||
|
@ -44,7 +44,7 @@ use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\FloatTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\network\mcpe\protocol\EntityEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\MobEffectPacket;
|
||||
use pocketmine\Player;
|
||||
@ -143,7 +143,7 @@ abstract class Living extends Entity implements Damageable{
|
||||
parent::setHealth($amount);
|
||||
$this->attributeMap->getAttribute(Attribute::HEALTH)->setValue(ceil($this->getHealth()), true);
|
||||
if($this->isAlive() and !$wasAlive){
|
||||
$this->broadcastEntityEvent(EntityEventPacket::RESPAWN);
|
||||
$this->broadcastEntityEvent(ActorEventPacket::RESPAWN);
|
||||
}
|
||||
}
|
||||
|
||||
@ -541,7 +541,9 @@ abstract class Living extends Entity implements Damageable{
|
||||
}
|
||||
|
||||
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();
|
||||
if($lastCause !== null and $lastCause->getBaseDamage() >= $source->getBaseDamage()){
|
||||
$source->setCancelled();
|
||||
@ -604,7 +606,7 @@ abstract class Living extends Entity implements Damageable{
|
||||
}
|
||||
|
||||
protected function doHitAnimation() : void{
|
||||
$this->broadcastEntityEvent(EntityEventPacket::HURT_ANIMATION);
|
||||
$this->broadcastEntityEvent(ActorEventPacket::HURT_ANIMATION);
|
||||
}
|
||||
|
||||
public function knockBack(Entity $attacker, float $damage, float $x, float $z, float $base = 0.4) : void{
|
||||
@ -661,7 +663,7 @@ abstract class Living extends Entity implements Damageable{
|
||||
}
|
||||
|
||||
protected function startDeathAnimation() : void{
|
||||
$this->broadcastEntityEvent(EntityEventPacket::DEATH_ANIMATION);
|
||||
$this->broadcastEntityEvent(ActorEventPacket::DEATH_ANIMATION);
|
||||
}
|
||||
|
||||
protected function endDeathAnimation() : void{
|
||||
|
@ -28,7 +28,7 @@ use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\EntityEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||
use function atan2;
|
||||
use function mt_rand;
|
||||
use function sqrt;
|
||||
@ -68,7 +68,7 @@ class Squid extends WaterAnimal{
|
||||
$this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize();
|
||||
}
|
||||
|
||||
$this->broadcastEntityEvent(EntityEventPacket::SQUID_INK_CLOUD);
|
||||
$this->broadcastEntityEvent(ActorEventPacket::SQUID_INK_CLOUD);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,8 @@ use pocketmine\event\entity\ItemDespawnEvent;
|
||||
use pocketmine\event\entity\ItemSpawnEvent;
|
||||
use pocketmine\event\inventory\InventoryPickupItemEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\network\mcpe\protocol\AddItemEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddItemActorPacket;
|
||||
use pocketmine\network\mcpe\protocol\TakeItemActorPacket;
|
||||
use pocketmine\Player;
|
||||
use function get_class;
|
||||
|
||||
@ -192,7 +192,7 @@ class ItemEntity extends Entity{
|
||||
}
|
||||
|
||||
protected function sendSpawnPacket(Player $player) : void{
|
||||
$pk = new AddItemEntityPacket();
|
||||
$pk = new AddItemActorPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->position = $this->asVector3();
|
||||
$pk->motion = $this->getMotion();
|
||||
@ -229,7 +229,7 @@ class ItemEntity extends Entity{
|
||||
break;
|
||||
}
|
||||
|
||||
$pk = new TakeItemEntityPacket();
|
||||
$pk = new TakeItemActorPacket();
|
||||
$pk->eid = $player->getId();
|
||||
$pk->target = $this->getId();
|
||||
$this->server->broadcastPacket($this->getViewers(), $pk);
|
||||
|
@ -152,9 +152,11 @@ class Painting extends Entity{
|
||||
protected function sendSpawnPacket(Player $player) : void{
|
||||
$pk = new AddPaintingPacket();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->x = $this->blockIn->x;
|
||||
$pk->y = $this->blockIn->y;
|
||||
$pk->z = $this->blockIn->z;
|
||||
$pk->position = new Vector3(
|
||||
($this->boundingBox->minX + $this->boundingBox->maxX) / 2,
|
||||
($this->boundingBox->minY + $this->boundingBox->maxY) / 2,
|
||||
($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2
|
||||
);
|
||||
$pk->direction = $this->direction;
|
||||
$pk->title = $this->motive;
|
||||
|
||||
|
@ -28,6 +28,7 @@ use pocketmine\entity\Explosive;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\event\entity\ExplosionPrimeEvent;
|
||||
use pocketmine\level\Explosion;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\nbt\tag\ShortTag;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
|
||||
@ -105,7 +106,7 @@ class PrimedTNT extends Entity implements Explosive{
|
||||
$ev = new ExplosionPrimeEvent($this, 4);
|
||||
$ev->call();
|
||||
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()){
|
||||
$explosion->explodeA();
|
||||
}
|
||||
|
@ -32,9 +32,9 @@ use pocketmine\item\ItemFactory;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\RayTraceResult;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\network\mcpe\protocol\EntityEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\TakeItemActorPacket;
|
||||
use pocketmine\Player;
|
||||
use function mt_rand;
|
||||
use function sqrt;
|
||||
@ -143,7 +143,7 @@ class Arrow extends Projectile{
|
||||
|
||||
protected function onHitBlock(Block $blockHit, RayTraceResult $hitResult) : void{
|
||||
parent::onHitBlock($blockHit, $hitResult);
|
||||
$this->broadcastEntityEvent(EntityEventPacket::ARROW_SHAKE, 7); //7 ticks
|
||||
$this->broadcastEntityEvent(ActorEventPacket::ARROW_SHAKE, 7); //7 ticks
|
||||
}
|
||||
|
||||
protected function onHitEntity(Entity $entityHit, RayTraceResult $hitResult) : void{
|
||||
@ -193,7 +193,7 @@ class Arrow extends Projectile{
|
||||
return;
|
||||
}
|
||||
|
||||
$pk = new TakeItemEntityPacket();
|
||||
$pk = new TakeItemActorPacket();
|
||||
$pk->eid = $player->getId();
|
||||
$pk->target = $this->getId();
|
||||
$this->server->broadcastPacket($this->getViewers(), $pk);
|
||||
|
@ -79,8 +79,8 @@ class ShapedRecipe implements CraftingRecipe{
|
||||
}
|
||||
|
||||
for($x = 0; $x < $this->width; ++$x){
|
||||
if($row{$x} !== ' ' and !isset($ingredients[$row{$x}])){
|
||||
throw new \InvalidArgumentException("No item specified for symbol '" . $row{$x} . "'");
|
||||
if($row[$x] !== ' ' and !isset($ingredients[$row[$x]])){
|
||||
throw new \InvalidArgumentException("No item specified for symbol '" . $row[$x] . "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ class Bucket extends Item implements Consumable{
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$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()){
|
||||
$player->getInventory()->setItemInHand($ev->getItem());
|
||||
|
@ -467,7 +467,7 @@ class Item implements ItemIds, \JsonSerializable{
|
||||
*/
|
||||
public function setCustomName(string $name) : Item{
|
||||
if($name === ""){
|
||||
$this->clearCustomName();
|
||||
return $this->clearCustomName();
|
||||
}
|
||||
|
||||
/** @var CompoundTag $display */
|
||||
|
@ -190,7 +190,7 @@ class BaseLang{
|
||||
|
||||
$len = strlen($text);
|
||||
for($i = 0; $i < $len; ++$i){
|
||||
$c = $text{$i};
|
||||
$c = $text[$i];
|
||||
if($replaceString !== null){
|
||||
$ord = ord($c);
|
||||
if(
|
||||
|
@ -72,7 +72,7 @@ use pocketmine\metadata\Metadatable;
|
||||
use pocketmine\metadata\MetadataValue;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\network\mcpe\protocol\AddEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddActorPacket;
|
||||
use pocketmine\network\mcpe\protocol\BatchPacket;
|
||||
use pocketmine\network\mcpe\protocol\DataPacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
@ -564,7 +564,7 @@ class Level implements ChunkManager, Metadatable{
|
||||
$pk = new LevelSoundEventPacket();
|
||||
$pk->sound = $soundId;
|
||||
$pk->extraData = $extraData;
|
||||
$pk->entityType = AddEntityPacket::LEGACY_ID_MAP_BC[$entityTypeId] ?? ":";
|
||||
$pk->entityType = AddActorPacket::LEGACY_ID_MAP_BC[$entityTypeId] ?? ":";
|
||||
$pk->isBabyMob = $isBabyMob;
|
||||
$pk->disableRelativeVolume = $disableRelativeVolume;
|
||||
$pk->position = $pos->asVector3();
|
||||
|
@ -460,7 +460,7 @@ class Chunk{
|
||||
* @return int 0-255
|
||||
*/
|
||||
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){
|
||||
$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{
|
||||
$result = "";
|
||||
$subChunkCount = $this->getSubChunkSendCount();
|
||||
$result .= chr($subChunkCount);
|
||||
for($y = 0; $y < $subChunkCount; ++$y){
|
||||
$result .= $this->subChunks[$y]->networkSerialize();
|
||||
}
|
||||
$result .= pack("v*", ...$this->heightMap)
|
||||
. $this->biomeIds
|
||||
. chr(0); //border block array count
|
||||
$result .= $this->biomeIds . chr(0); //border block array count
|
||||
//Border block entry format: 1 byte (4 bits X, 4 bits Z). These are however useless since they crash the regular client.
|
||||
|
||||
foreach($this->tiles as $tile){
|
||||
|
@ -71,31 +71,31 @@ class SubChunk implements SubChunkInterface{
|
||||
}
|
||||
|
||||
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{
|
||||
$this->ids{($x << 8) | ($z << 4) | $y} = chr($id);
|
||||
$this->ids[($x << 8) | ($z << 4) | $y] = chr($id);
|
||||
return true;
|
||||
}
|
||||
|
||||
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{
|
||||
$i = ($x << 7) | ($z << 3) | ($y >> 1);
|
||||
|
||||
$shift = ($y & 1) << 2;
|
||||
$byte = ord($this->data{$i});
|
||||
$this->data{$i} = chr(($byte & ~(0xf << $shift)) | (($data & 0xf) << $shift));
|
||||
$byte = ord($this->data[$i]);
|
||||
$this->data[$i] = chr(($byte & ~(0xf << $shift)) | (($data & 0xf) << $shift));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFullBlock(int $x, int $y, int $z) : int{
|
||||
$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{
|
||||
@ -103,8 +103,8 @@ class SubChunk implements SubChunkInterface{
|
||||
$changed = false;
|
||||
if($id !== null){
|
||||
$block = chr($id);
|
||||
if($this->ids{$i} !== $block){
|
||||
$this->ids{$i} = $block;
|
||||
if($this->ids[$i] !== $block){
|
||||
$this->ids[$i] = $block;
|
||||
$changed = true;
|
||||
}
|
||||
}
|
||||
@ -113,10 +113,10 @@ class SubChunk implements SubChunkInterface{
|
||||
$i >>= 1;
|
||||
|
||||
$shift = ($y & 1) << 2;
|
||||
$oldPair = ord($this->data{$i});
|
||||
$oldPair = ord($this->data[$i]);
|
||||
$newPair = ($oldPair & ~(0xf << $shift)) | (($data & 0xf) << $shift);
|
||||
if($newPair !== $oldPair){
|
||||
$this->data{$i} = chr($newPair);
|
||||
$this->data[$i] = chr($newPair);
|
||||
$changed = true;
|
||||
}
|
||||
}
|
||||
@ -125,29 +125,29 @@ class SubChunk implements SubChunkInterface{
|
||||
}
|
||||
|
||||
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{
|
||||
$i = ($x << 7) | ($z << 3) | ($y >> 1);
|
||||
|
||||
$shift = ($y & 1) << 2;
|
||||
$byte = ord($this->blockLight{$i});
|
||||
$this->blockLight{$i} = chr(($byte & ~(0xf << $shift)) | (($level & 0xf) << $shift));
|
||||
$byte = ord($this->blockLight[$i]);
|
||||
$this->blockLight[$i] = chr(($byte & ~(0xf << $shift)) | (($level & 0xf) << $shift));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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{
|
||||
$i = ($x << 7) | ($z << 3) | ($y >> 1);
|
||||
|
||||
$shift = ($y & 1) << 2;
|
||||
$byte = ord($this->skyLight{$i});
|
||||
$this->skyLight{$i} = chr(($byte & ~(0xf << $shift)) | (($level & 0xf) << $shift));
|
||||
$byte = ord($this->skyLight[$i]);
|
||||
$this->skyLight[$i] = chr(($byte & ~(0xf << $shift)) | (($level & 0xf) << $shift));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -156,7 +156,7 @@ class SubChunk implements SubChunkInterface{
|
||||
$low = ($x << 8) | ($z << 4);
|
||||
$i = $low | 0x0f;
|
||||
for(; $i >= $low; --$i){
|
||||
if($this->ids{$i} !== "\x00"){
|
||||
if($this->ids[$i] !== "\x00"){
|
||||
return $i & 0x0f;
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ namespace pocketmine\level\format\io;
|
||||
use pocketmine\level\format\Chunk;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\network\mcpe\protocol\BatchPacket;
|
||||
use pocketmine\network\mcpe\protocol\FullChunkDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelChunkPacket;
|
||||
use pocketmine\scheduler\AsyncTask;
|
||||
use pocketmine\Server;
|
||||
use function assert;
|
||||
@ -42,6 +42,9 @@ class ChunkRequestTask extends AsyncTask{
|
||||
|
||||
protected $compressionLevel;
|
||||
|
||||
/** @var int */
|
||||
private $subChunkCount;
|
||||
|
||||
public function __construct(Level $level, int $chunkX, int $chunkZ, Chunk $chunk){
|
||||
$this->levelId = $level->getId();
|
||||
$this->compressionLevel = $level->getServer()->networkCompressionLevel;
|
||||
@ -49,13 +52,11 @@ class ChunkRequestTask extends AsyncTask{
|
||||
$this->chunk = $chunk->networkSerialize();
|
||||
$this->chunkX = $chunkX;
|
||||
$this->chunkZ = $chunkZ;
|
||||
$this->subChunkCount = $chunk->getSubChunkSendCount();
|
||||
}
|
||||
|
||||
public function onRun(){
|
||||
$pk = new FullChunkDataPacket();
|
||||
$pk->chunkX = $this->chunkX;
|
||||
$pk->chunkZ = $this->chunkZ;
|
||||
$pk->data = $this->chunk;
|
||||
$pk = LevelChunkPacket::withoutCache($this->chunkX, $this->chunkZ, $this->subChunkCount, $this->chunk);
|
||||
|
||||
$batch = new BatchPacket();
|
||||
$batch->addPacket($pk);
|
||||
|
@ -47,7 +47,7 @@ if(!extension_loaded('pocketmine_chunkutils')){
|
||||
for($z = $x; $z < $zM; $z += 16){
|
||||
$yM = $z + 4096;
|
||||
for($y = $z; $y < $yM; $y += 256){
|
||||
$result{$i} = $array{$y};
|
||||
$result[$i] = $array[$y];
|
||||
++$i;
|
||||
}
|
||||
}
|
||||
@ -76,13 +76,13 @@ if(!extension_loaded('pocketmine_chunkutils')){
|
||||
for($y = 0; $y < 8; ++$y){
|
||||
$j = (($y << 8) | $zx);
|
||||
$j80 = ($j | 0x80);
|
||||
if($array{$j} === $commonValue and $array{$j80} === $commonValue){
|
||||
if($array[$j] === $commonValue and $array[$j80] === $commonValue){
|
||||
//values are already filled
|
||||
}else{
|
||||
$i1 = ord($array{$j});
|
||||
$i2 = ord($array{$j80});
|
||||
$result{$i} = chr(($i2 << 4) | ($i1 & 0x0f));
|
||||
$result{$i | 0x80} = chr(($i1 >> 4) | ($i2 & 0xf0));
|
||||
$i1 = ord($array[$j]);
|
||||
$i2 = ord($array[$j80]);
|
||||
$result[$i] = chr(($i2 << 4) | ($i1 & 0x0f));
|
||||
$result[$i | 0x80] = chr(($i1 >> 4) | ($i2 & 0xf0));
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
@ -104,7 +104,7 @@ if(!extension_loaded('pocketmine_chunkutils')){
|
||||
public static function convertBiomeColors(array $array) : string{
|
||||
$result = str_repeat("\x00", 256);
|
||||
foreach($array as $i => $color){
|
||||
$result{$i} = chr(($color >> 24) & 0xff);
|
||||
$result[$i] = chr(($color >> 24) & 0xff);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ use pocketmine\level\ChunkManager;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\utils\Random;
|
||||
use pocketmine\utils\Utils;
|
||||
use function ctype_digit;
|
||||
use function preg_match;
|
||||
|
||||
abstract class Generator{
|
||||
|
||||
@ -44,7 +44,7 @@ abstract class Generator{
|
||||
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
|
||||
$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;
|
||||
}else{
|
||||
$convertedSeed = Utils::javaStringHash($seed);
|
||||
|
@ -48,7 +48,7 @@ class GroundCover extends Populator{
|
||||
|
||||
$column = $chunk->getBlockIdColumn($x, $z);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -56,10 +56,10 @@ class GroundCover extends Populator{
|
||||
$endY = $startY - count($cover);
|
||||
for($y = $startY; $y > $endY and $y >= 0; --$y){
|
||||
$b = $cover[$startY - $y];
|
||||
if($column{$y} === "\x00" and $b->isSolid()){
|
||||
if($column[$y] === "\x00" and $b->isSolid()){
|
||||
break;
|
||||
}
|
||||
if($b->canBeFlowedInto() and BlockFactory::get(ord($column{$y})) instanceof Liquid){
|
||||
if($b->canBeFlowedInto() and BlockFactory::get(ord($column[$y])) instanceof Liquid){
|
||||
continue;
|
||||
}
|
||||
if($b->getDamage() === 0){
|
||||
|
@ -30,7 +30,7 @@ use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerListPacket;
|
||||
use pocketmine\network\mcpe\protocol\RemoveEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\RemoveActorPacket;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
|
||||
use pocketmine\utils\UUID;
|
||||
use function str_repeat;
|
||||
@ -84,7 +84,7 @@ class FloatingTextParticle extends Particle{
|
||||
if($this->entityId === null){
|
||||
$this->entityId = Entity::$entityCount++;
|
||||
}else{
|
||||
$pk0 = new RemoveEntityPacket();
|
||||
$pk0 = new RemoveActorPacket();
|
||||
$pk0->entityUniqueId = $this->entityId;
|
||||
|
||||
$p[] = $pk0;
|
||||
|
@ -29,59 +29,67 @@ use pocketmine\network\mcpe\protocol\DataPacket;
|
||||
abstract class Particle extends Vector3{
|
||||
|
||||
public const TYPE_BUBBLE = 1;
|
||||
public const TYPE_CRITICAL = 2;
|
||||
public const TYPE_BLOCK_FORCE_FIELD = 3;
|
||||
public const TYPE_SMOKE = 4;
|
||||
public const TYPE_EXPLODE = 5;
|
||||
public const TYPE_EVAPORATION = 6;
|
||||
public const TYPE_FLAME = 7;
|
||||
public const TYPE_LAVA = 8;
|
||||
public const TYPE_LARGE_SMOKE = 9;
|
||||
public const TYPE_REDSTONE = 10;
|
||||
public const TYPE_RISING_RED_DUST = 11;
|
||||
public const TYPE_ITEM_BREAK = 12;
|
||||
public const TYPE_SNOWBALL_POOF = 13;
|
||||
public const TYPE_HUGE_EXPLODE = 14;
|
||||
public const TYPE_HUGE_EXPLODE_SEED = 15;
|
||||
public const TYPE_MOB_FLAME = 16;
|
||||
public const TYPE_HEART = 17;
|
||||
public const TYPE_TERRAIN = 18;
|
||||
public const TYPE_SUSPENDED_TOWN = 19, TYPE_TOWN_AURA = 19;
|
||||
public const TYPE_PORTAL = 20;
|
||||
public const TYPE_SPLASH = 21, TYPE_WATER_SPLASH = 21;
|
||||
public const TYPE_WATER_WAKE = 22;
|
||||
public const TYPE_DRIP_WATER = 23;
|
||||
public const TYPE_DRIP_LAVA = 24;
|
||||
public const TYPE_FALLING_DUST = 25, TYPE_DUST = 25;
|
||||
public const TYPE_MOB_SPELL = 26;
|
||||
public const TYPE_MOB_SPELL_AMBIENT = 27;
|
||||
public const TYPE_MOB_SPELL_INSTANTANEOUS = 28;
|
||||
public const TYPE_INK = 29;
|
||||
public const TYPE_SLIME = 30;
|
||||
public const TYPE_RAIN_SPLASH = 31;
|
||||
public const TYPE_VILLAGER_ANGRY = 32;
|
||||
public const TYPE_VILLAGER_HAPPY = 33;
|
||||
public const TYPE_ENCHANTMENT_TABLE = 34;
|
||||
public const TYPE_TRACKING_EMITTER = 35;
|
||||
public const TYPE_NOTE = 36;
|
||||
public const TYPE_WITCH_SPELL = 37;
|
||||
public const TYPE_CARROT = 38;
|
||||
//39 unknown
|
||||
public const TYPE_END_ROD = 40;
|
||||
public const TYPE_DRAGONS_BREATH = 41;
|
||||
public const TYPE_SPIT = 42;
|
||||
public const TYPE_TOTEM = 43;
|
||||
public const TYPE_FOOD = 44;
|
||||
public const TYPE_FIREWORKS_STARTER = 45;
|
||||
public const TYPE_FIREWORKS_SPARK = 46;
|
||||
public const TYPE_FIREWORKS_OVERLAY = 47;
|
||||
public const TYPE_BALLOON_GAS = 48;
|
||||
public const TYPE_COLORED_FLAME = 49;
|
||||
public const TYPE_SPARKLER = 50;
|
||||
public const TYPE_CONDUIT = 51;
|
||||
public const TYPE_BUBBLE_COLUMN_UP = 52;
|
||||
public const TYPE_BUBBLE_COLUMN_DOWN = 53;
|
||||
public const TYPE_SNEEZE = 54;
|
||||
//2 same as 1
|
||||
public const TYPE_CRITICAL = 3;
|
||||
public const TYPE_BLOCK_FORCE_FIELD = 4;
|
||||
public const TYPE_SMOKE = 5;
|
||||
public const TYPE_EXPLODE = 6;
|
||||
public const TYPE_EVAPORATION = 7;
|
||||
public const TYPE_FLAME = 8;
|
||||
public const TYPE_LAVA = 9;
|
||||
public const TYPE_LARGE_SMOKE = 10;
|
||||
public const TYPE_REDSTONE = 11;
|
||||
public const TYPE_RISING_RED_DUST = 12;
|
||||
//62 same as 12
|
||||
public const TYPE_ITEM_BREAK = 13;
|
||||
public const TYPE_SNOWBALL_POOF = 14;
|
||||
public const TYPE_HUGE_EXPLODE = 15;
|
||||
//60 same as 15
|
||||
public const TYPE_HUGE_EXPLODE_SEED = 16;
|
||||
public const TYPE_MOB_FLAME = 17;
|
||||
public const TYPE_HEART = 18;
|
||||
public const TYPE_TERRAIN = 19;
|
||||
public const TYPE_SUSPENDED_TOWN = 20, TYPE_TOWN_AURA = 20;
|
||||
//61 same as 20
|
||||
public const TYPE_PORTAL = 21;
|
||||
//22 same as 21
|
||||
public const TYPE_SPLASH = 23, TYPE_WATER_SPLASH = 23;
|
||||
//24 same as 23
|
||||
public const TYPE_WATER_WAKE = 25;
|
||||
public const TYPE_DRIP_WATER = 26;
|
||||
public const TYPE_DRIP_LAVA = 27;
|
||||
public const TYPE_FALLING_DUST = 28, TYPE_DUST = 28;
|
||||
public const TYPE_MOB_SPELL = 29;
|
||||
public const TYPE_MOB_SPELL_AMBIENT = 30;
|
||||
public const TYPE_MOB_SPELL_INSTANTANEOUS = 31;
|
||||
public const TYPE_INK = 32;
|
||||
public const TYPE_SLIME = 33;
|
||||
public const TYPE_RAIN_SPLASH = 34;
|
||||
public const TYPE_VILLAGER_ANGRY = 35;
|
||||
//59 same as 35
|
||||
public const TYPE_VILLAGER_HAPPY = 36;
|
||||
public const TYPE_ENCHANTMENT_TABLE = 37;
|
||||
public const TYPE_TRACKING_EMITTER = 38;
|
||||
public const TYPE_NOTE = 39;
|
||||
public const TYPE_WITCH_SPELL = 40;
|
||||
public const TYPE_CARROT = 41;
|
||||
//42 unknown
|
||||
public const TYPE_END_ROD = 43;
|
||||
//58 same as 43
|
||||
public const TYPE_DRAGONS_BREATH = 44;
|
||||
public const TYPE_SPIT = 45;
|
||||
public const TYPE_TOTEM = 46;
|
||||
public const TYPE_FOOD = 47;
|
||||
public const TYPE_FIREWORKS_STARTER = 48;
|
||||
public const TYPE_FIREWORKS_SPARK = 49;
|
||||
public const TYPE_FIREWORKS_OVERLAY = 50;
|
||||
public const TYPE_BALLOON_GAS = 51;
|
||||
public const TYPE_COLORED_FLAME = 52;
|
||||
public const TYPE_SPARKLER = 53;
|
||||
public const TYPE_CONDUIT = 54;
|
||||
public const TYPE_BUBBLE_COLUMN_UP = 55;
|
||||
public const TYPE_BUBBLE_COLUMN_DOWN = 56;
|
||||
public const TYPE_SNEEZE = 57;
|
||||
|
||||
/**
|
||||
* @return DataPacket|DataPacket[]
|
||||
|
@ -27,12 +27,14 @@ namespace pocketmine\network\mcpe;
|
||||
|
||||
use pocketmine\entity\Attribute;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\item\Durable;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\ItemIds;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\NetworkLittleEndianNBTStream;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\network\mcpe\protocol\types\CommandOriginData;
|
||||
use pocketmine\network\mcpe\protocol\types\EntityLink;
|
||||
use pocketmine\utils\BinaryStream;
|
||||
@ -42,6 +44,9 @@ use function strlen;
|
||||
|
||||
class NetworkBinaryStream extends BinaryStream{
|
||||
|
||||
private const DAMAGE_TAG = "Damage"; //TAG_Int
|
||||
private const DAMAGE_TAG_CONFLICT_RESOLUTION = "___Damage_ProtocolCollisionResolution___";
|
||||
|
||||
public function getString() : string{
|
||||
return $this->get($this->getUnsignedVarInt());
|
||||
}
|
||||
@ -76,15 +81,12 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
|
||||
$auxValue = $this->getVarInt();
|
||||
$data = $auxValue >> 8;
|
||||
if($data === 0x7fff){
|
||||
$data = -1;
|
||||
}
|
||||
$cnt = $auxValue & 0xff;
|
||||
|
||||
$nbtLen = $this->getLShort();
|
||||
|
||||
/** @var CompoundTag|string $nbt */
|
||||
$nbt = "";
|
||||
/** @var CompoundTag|null $nbt */
|
||||
$nbt = null;
|
||||
if($nbtLen === 0xffff){
|
||||
$c = $this->getByte();
|
||||
if($c !== 1){
|
||||
@ -108,7 +110,22 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
if($id === ItemIds::SHIELD){
|
||||
$this->getVarLong(); //"blocking tick" (ffs mojang)
|
||||
}
|
||||
|
||||
if($nbt !== null){
|
||||
if($nbt->hasTag(self::DAMAGE_TAG, IntTag::class)){
|
||||
$data = $nbt->getInt(self::DAMAGE_TAG);
|
||||
$nbt->removeTag(self::DAMAGE_TAG);
|
||||
if($nbt->count() === 0){
|
||||
$nbt = null;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if(($conflicted = $nbt->getTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION)) !== null){
|
||||
$nbt->removeTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION);
|
||||
$conflicted->setName(self::DAMAGE_TAG);
|
||||
$nbt->setTag($conflicted);
|
||||
}
|
||||
}
|
||||
end:
|
||||
return ItemFactory::get($id, $data, $cnt, $nbt);
|
||||
}
|
||||
|
||||
@ -124,10 +141,27 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
$auxValue = (($item->getDamage() & 0x7fff) << 8) | $item->getCount();
|
||||
$this->putVarInt($auxValue);
|
||||
|
||||
$nbt = null;
|
||||
if($item->hasCompoundTag()){
|
||||
$nbt = clone $item->getNamedTag();
|
||||
}
|
||||
if($item instanceof Durable and $item->getDamage() > 0){
|
||||
if($nbt !== null){
|
||||
if(($existing = $nbt->getTag(self::DAMAGE_TAG)) !== null){
|
||||
$nbt->removeTag(self::DAMAGE_TAG);
|
||||
$existing->setName(self::DAMAGE_TAG_CONFLICT_RESOLUTION);
|
||||
$nbt->setTag($existing);
|
||||
}
|
||||
}else{
|
||||
$nbt = new CompoundTag();
|
||||
}
|
||||
$nbt->setInt(self::DAMAGE_TAG, $item->getDamage());
|
||||
}
|
||||
|
||||
if($nbt !== null){
|
||||
$this->putLShort(0xffff);
|
||||
$this->putByte(1); //TODO: some kind of count field? always 1 as of 1.9.0
|
||||
$this->put((new NetworkLittleEndianNBTStream())->write($item->getNamedTag()));
|
||||
$this->put((new NetworkLittleEndianNBTStream())->write($nbt));
|
||||
}else{
|
||||
$this->putLShort(0);
|
||||
}
|
||||
@ -140,6 +174,29 @@ class NetworkBinaryStream extends BinaryStream{
|
||||
}
|
||||
}
|
||||
|
||||
public function getRecipeIngredient() : Item{
|
||||
$id = $this->getVarInt();
|
||||
if($id === 0){
|
||||
return ItemFactory::get(ItemIds::AIR, 0, 0);
|
||||
}
|
||||
$meta = $this->getVarInt();
|
||||
if($meta === 0x7fff){
|
||||
$meta = -1;
|
||||
}
|
||||
$count = $this->getVarInt();
|
||||
return ItemFactory::get($id, $meta, $count);
|
||||
}
|
||||
|
||||
public function putRecipeIngredient(Item $item) : void{
|
||||
if($item->isNull()){
|
||||
$this->putVarInt(0);
|
||||
}else{
|
||||
$this->putVarInt($item->getId());
|
||||
$this->putVarInt($item->getDamage() & 0x7fff);
|
||||
$this->putVarInt($item->getCount());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes entity metadata from the stream.
|
||||
*
|
||||
|
@ -23,18 +23,22 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe;
|
||||
|
||||
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\ActorFallPacket;
|
||||
use pocketmine\network\mcpe\protocol\ActorPickRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddActorPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddBehaviorTreePacket;
|
||||
use pocketmine\network\mcpe\protocol\AddEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddItemEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddItemActorPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddPaintingPacket;
|
||||
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
|
||||
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
|
||||
use pocketmine\network\mcpe\protocol\AnimatePacket;
|
||||
use pocketmine\network\mcpe\protocol\AutomationClientConnectPacket;
|
||||
use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket;
|
||||
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
|
||||
use pocketmine\network\mcpe\protocol\AvailableEntityIdentifiersPacket;
|
||||
use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\BookEditPacket;
|
||||
@ -43,6 +47,9 @@ use pocketmine\network\mcpe\protocol\CameraPacket;
|
||||
use pocketmine\network\mcpe\protocol\ChangeDimensionPacket;
|
||||
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
|
||||
use pocketmine\network\mcpe\protocol\ClientboundMapItemDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\ClientCacheBlobStatusPacket;
|
||||
use pocketmine\network\mcpe\protocol\ClientCacheMissResponsePacket;
|
||||
use pocketmine\network\mcpe\protocol\ClientCacheStatusPacket;
|
||||
use pocketmine\network\mcpe\protocol\ClientToServerHandshakePacket;
|
||||
use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket;
|
||||
use pocketmine\network\mcpe\protocol\CommandOutputPacket;
|
||||
@ -54,12 +61,8 @@ use pocketmine\network\mcpe\protocol\CraftingDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\DataPacket;
|
||||
use pocketmine\network\mcpe\protocol\DisconnectPacket;
|
||||
use pocketmine\network\mcpe\protocol\EntityEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\EntityFallPacket;
|
||||
use pocketmine\network\mcpe\protocol\EntityPickRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\EventPacket;
|
||||
use pocketmine\network\mcpe\protocol\ExplodePacket;
|
||||
use pocketmine\network\mcpe\protocol\FullChunkDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\GameRulesChangedPacket;
|
||||
use pocketmine\network\mcpe\protocol\GuiDataPickItemPacket;
|
||||
use pocketmine\network\mcpe\protocol\HurtArmorPacket;
|
||||
@ -70,6 +73,8 @@ use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
|
||||
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
|
||||
use pocketmine\network\mcpe\protocol\LabTablePacket;
|
||||
use pocketmine\network\mcpe\protocol\LecternUpdatePacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelChunkPacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventGenericPacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\LevelSoundEventPacketV1;
|
||||
@ -82,8 +87,8 @@ use pocketmine\network\mcpe\protocol\MobEffectPacket;
|
||||
use pocketmine\network\mcpe\protocol\MobEquipmentPacket;
|
||||
use pocketmine\network\mcpe\protocol\ModalFormRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\ModalFormResponsePacket;
|
||||
use pocketmine\network\mcpe\protocol\MoveEntityAbsolutePacket;
|
||||
use pocketmine\network\mcpe\protocol\MoveEntityDeltaPacket;
|
||||
use pocketmine\network\mcpe\protocol\MoveActorAbsolutePacket;
|
||||
use pocketmine\network\mcpe\protocol\MoveActorDeltaPacket;
|
||||
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
|
||||
use pocketmine\network\mcpe\protocol\NetworkChunkPublisherUpdatePacket;
|
||||
use pocketmine\network\mcpe\protocol\NetworkStackLatencyPacket;
|
||||
@ -98,6 +103,7 @@ use pocketmine\network\mcpe\protocol\PlayerSkinPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlaySoundPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayStatusPacket;
|
||||
use pocketmine\network\mcpe\protocol\PurchaseReceiptPacket;
|
||||
use pocketmine\network\mcpe\protocol\RemoveActorPacket;
|
||||
use pocketmine\network\mcpe\protocol\RemoveEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\RemoveObjectivePacket;
|
||||
use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket;
|
||||
@ -113,13 +119,13 @@ use pocketmine\network\mcpe\protocol\ScriptCustomEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\ServerSettingsRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\ServerSettingsResponsePacket;
|
||||
use pocketmine\network\mcpe\protocol\ServerToClientHandshakePacket;
|
||||
use pocketmine\network\mcpe\protocol\SetActorDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetActorLinkPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetActorMotionPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetCommandsEnabledPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetDefaultGameTypePacket;
|
||||
use pocketmine\network\mcpe\protocol\SetDifficultyPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetDisplayObjectivePacket;
|
||||
use pocketmine\network\mcpe\protocol\SetEntityDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetEntityLinkPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetEntityMotionPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetHealthPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetLastHurtByPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetLocalPlayerAsInitializedPacket;
|
||||
@ -138,12 +144,15 @@ use pocketmine\network\mcpe\protocol\SpawnParticleEffectPacket;
|
||||
use pocketmine\network\mcpe\protocol\StartGamePacket;
|
||||
use pocketmine\network\mcpe\protocol\StopSoundPacket;
|
||||
use pocketmine\network\mcpe\protocol\StructureBlockUpdatePacket;
|
||||
use pocketmine\network\mcpe\protocol\StructureTemplateDataExportRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\StructureTemplateDataExportResponsePacket;
|
||||
use pocketmine\network\mcpe\protocol\SubClientLoginPacket;
|
||||
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\TakeItemActorPacket;
|
||||
use pocketmine\network\mcpe\protocol\TextPacket;
|
||||
use pocketmine\network\mcpe\protocol\TransferPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateBlockPropertiesPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateBlockSyncedPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateEquipPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateSoftEnumPacket;
|
||||
@ -202,23 +211,23 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleAddEntity(AddEntityPacket $packet) : bool{
|
||||
public function handleAddActor(AddActorPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleRemoveEntity(RemoveEntityPacket $packet) : bool{
|
||||
public function handleRemoveActor(RemoveActorPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleAddItemEntity(AddItemEntityPacket $packet) : bool{
|
||||
public function handleAddItemActor(AddItemActorPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleTakeItemEntity(TakeItemEntityPacket $packet) : bool{
|
||||
public function handleTakeItemActor(TakeItemActorPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleMoveEntityAbsolute(MoveEntityAbsolutePacket $packet) : bool{
|
||||
public function handleMoveActorAbsolute(MoveActorAbsolutePacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -254,7 +263,7 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleEntityEvent(EntityEventPacket $packet) : bool{
|
||||
public function handleActorEvent(ActorEventPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -286,7 +295,7 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleEntityPickRequest(EntityPickRequestPacket $packet) : bool{
|
||||
public function handleActorPickRequest(ActorPickRequestPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -294,7 +303,7 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleEntityFall(EntityFallPacket $packet) : bool{
|
||||
public function handleActorFall(ActorFallPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -302,15 +311,15 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleSetEntityData(SetEntityDataPacket $packet) : bool{
|
||||
public function handleSetActorData(SetActorDataPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleSetEntityMotion(SetEntityMotionPacket $packet) : bool{
|
||||
public function handleSetActorMotion(SetActorMotionPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleSetEntityLink(SetEntityLinkPacket $packet) : bool{
|
||||
public function handleSetActorLink(SetActorLinkPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -370,7 +379,7 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{
|
||||
public function handleBlockActorData(BlockActorDataPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -378,7 +387,7 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleFullChunkData(FullChunkDataPacket $packet) : bool{
|
||||
public function handleLevelChunk(LevelChunkPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -590,7 +599,7 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleMoveEntityDelta(MoveEntityDeltaPacket $packet) : bool{
|
||||
public function handleMoveActorDelta(MoveActorDeltaPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -618,7 +627,7 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleAvailableEntityIdentifiers(AvailableEntityIdentifiersPacket $packet) : bool{
|
||||
public function handleAvailableActorIdentifiers(AvailableActorIdentifiersPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -638,6 +647,10 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleLevelEventGeneric(LevelEventGenericPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleLecternUpdate(LecternUpdatePacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
@ -646,11 +659,43 @@ abstract class NetworkSession{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleMapCreateLockedCopy(MapCreateLockedCopyPacket $packet) : bool{
|
||||
public function handleAddEntity(AddEntityPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleRemoveEntity(RemoveEntityPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleClientCacheStatus(ClientCacheStatusPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleOnScreenTextureAnimation(OnScreenTextureAnimationPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleMapCreateLockedCopy(MapCreateLockedCopyPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleStructureTemplateDataExportRequest(StructureTemplateDataExportRequestPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleStructureTemplateDataExportResponse(StructureTemplateDataExportResponsePacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleUpdateBlockProperties(UpdateBlockPropertiesPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleClientCacheBlobStatus(ClientCacheBlobStatusPacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleClientCacheMissResponse(ClientCacheMissResponsePacket $packet) : bool{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,12 @@ namespace pocketmine\network\mcpe;
|
||||
|
||||
|
||||
use pocketmine\event\server\DataPacketReceiveEvent;
|
||||
use pocketmine\network\mcpe\protocol\ActorEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\ActorFallPacket;
|
||||
use pocketmine\network\mcpe\protocol\ActorPickRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
|
||||
use pocketmine\network\mcpe\protocol\AnimatePacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\BookEditPacket;
|
||||
use pocketmine\network\mcpe\protocol\BossEventPacket;
|
||||
@ -37,9 +40,6 @@ use pocketmine\network\mcpe\protocol\CommandRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
|
||||
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\DataPacket;
|
||||
use pocketmine\network\mcpe\protocol\EntityEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\EntityFallPacket;
|
||||
use pocketmine\network\mcpe\protocol\EntityPickRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\InteractPacket;
|
||||
use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
|
||||
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
|
||||
@ -142,7 +142,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
|
||||
return true; //useless leftover from 1.8
|
||||
}
|
||||
|
||||
public function handleEntityEvent(EntityEventPacket $packet) : bool{
|
||||
public function handleActorEvent(ActorEventPacket $packet) : bool{
|
||||
return $this->player->handleEntityEvent($packet);
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
|
||||
return $this->player->handleBlockPickRequest($packet);
|
||||
}
|
||||
|
||||
public function handleEntityPickRequest(EntityPickRequestPacket $packet) : bool{
|
||||
public function handleActorPickRequest(ActorPickRequestPacket $packet) : bool{
|
||||
return false; //TODO
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
|
||||
return $this->player->handlePlayerAction($packet);
|
||||
}
|
||||
|
||||
public function handleEntityFall(EntityFallPacket $packet) : bool{
|
||||
public function handleActorFall(ActorFallPacket $packet) : bool{
|
||||
return true; //Not used
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
|
||||
return $this->player->handleAdventureSettings($packet);
|
||||
}
|
||||
|
||||
public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{
|
||||
public function handleBlockActorData(BlockActorDataPacket $packet) : bool{
|
||||
return $this->player->handleBlockEntityData($packet);
|
||||
}
|
||||
|
||||
|
@ -120,12 +120,12 @@ class VerifyLoginTask extends AsyncTask{
|
||||
[$rString, $sString] = str_split($plainSignature, 48);
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class EntityEventPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::ENTITY_EVENT_PACKET;
|
||||
class ActorEventPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::ACTOR_EVENT_PACKET;
|
||||
|
||||
public const HURT_ANIMATION = 2;
|
||||
public const DEATH_ANIMATION = 3;
|
||||
@ -103,6 +103,6 @@ class EntityEventPacket extends DataPacket{
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleEntityEvent($this);
|
||||
return $session->handleActorEvent($this);
|
||||
}
|
||||
}
|
@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class EntityFallPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::ENTITY_FALL_PACKET;
|
||||
class ActorFallPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::ACTOR_FALL_PACKET;
|
||||
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
@ -51,6 +51,6 @@ class EntityFallPacket extends DataPacket{
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleEntityFall($this);
|
||||
return $session->handleActorFall($this);
|
||||
}
|
||||
}
|
@ -27,8 +27,8 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class EntityPickRequestPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::ENTITY_PICK_REQUEST_PACKET;
|
||||
class ActorPickRequestPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::ACTOR_PICK_REQUEST_PACKET;
|
||||
|
||||
/** @var int */
|
||||
public $entityUniqueId;
|
||||
@ -46,6 +46,6 @@ class EntityPickRequestPacket extends DataPacket{
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleEntityPickRequest($this);
|
||||
return $session->handleActorPickRequest($this);
|
||||
}
|
||||
}
|
240
src/pocketmine/network/mcpe/protocol/AddActorPacket.php
Normal file
240
src/pocketmine/network/mcpe/protocol/AddActorPacket.php
Normal 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);
|
||||
}
|
||||
}
|
@ -25,216 +25,36 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
use pocketmine\entity\Attribute;
|
||||
use pocketmine\entity\EntityIds;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\EntityLink;
|
||||
use function array_search;
|
||||
use function count;
|
||||
|
||||
class AddEntityPacket extends DataPacket{
|
||||
class AddEntityPacket extends DataPacket/* implements ClientboundPacket*/{
|
||||
public const NETWORK_ID = ProtocolInfo::ADD_ENTITY_PACKET;
|
||||
|
||||
/*
|
||||
* Really really really really really nasty hack, to preserve backwards compatibility.
|
||||
* We can't transition to string IDs within 3.x because the network IDs (the integer ones) are exposed
|
||||
* to the API in some places (for god's sake shoghi).
|
||||
*
|
||||
* TODO: remove this on 4.0
|
||||
/** @var int */
|
||||
private $uvarint1;
|
||||
|
||||
public static function create(int $uvarint1) : self{
|
||||
$result = new self;
|
||||
$result->uvarint1 = $uvarint1;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public const LEGACY_ID_MAP_BC = [
|
||||
EntityIds::NPC => "minecraft:npc",
|
||||
EntityIds::PLAYER => "minecraft:player",
|
||||
EntityIds::WITHER_SKELETON => "minecraft:wither_skeleton",
|
||||
EntityIds::HUSK => "minecraft:husk",
|
||||
EntityIds::STRAY => "minecraft:stray",
|
||||
EntityIds::WITCH => "minecraft:witch",
|
||||
EntityIds::ZOMBIE_VILLAGER => "minecraft:zombie_villager",
|
||||
EntityIds::BLAZE => "minecraft:blaze",
|
||||
EntityIds::MAGMA_CUBE => "minecraft:magma_cube",
|
||||
EntityIds::GHAST => "minecraft:ghast",
|
||||
EntityIds::CAVE_SPIDER => "minecraft:cave_spider",
|
||||
EntityIds::SILVERFISH => "minecraft:silverfish",
|
||||
EntityIds::ENDERMAN => "minecraft:enderman",
|
||||
EntityIds::SLIME => "minecraft:slime",
|
||||
EntityIds::ZOMBIE_PIGMAN => "minecraft:zombie_pigman",
|
||||
EntityIds::SPIDER => "minecraft:spider",
|
||||
EntityIds::SKELETON => "minecraft:skeleton",
|
||||
EntityIds::CREEPER => "minecraft:creeper",
|
||||
EntityIds::ZOMBIE => "minecraft:zombie",
|
||||
EntityIds::SKELETON_HORSE => "minecraft:skeleton_horse",
|
||||
EntityIds::MULE => "minecraft:mule",
|
||||
EntityIds::DONKEY => "minecraft:donkey",
|
||||
EntityIds::DOLPHIN => "minecraft:dolphin",
|
||||
EntityIds::TROPICALFISH => "minecraft:tropicalfish",
|
||||
EntityIds::WOLF => "minecraft:wolf",
|
||||
EntityIds::SQUID => "minecraft:squid",
|
||||
EntityIds::DROWNED => "minecraft:drowned",
|
||||
EntityIds::SHEEP => "minecraft:sheep",
|
||||
EntityIds::MOOSHROOM => "minecraft:mooshroom",
|
||||
EntityIds::PANDA => "minecraft:panda",
|
||||
EntityIds::SALMON => "minecraft:salmon",
|
||||
EntityIds::PIG => "minecraft:pig",
|
||||
EntityIds::VILLAGER => "minecraft:villager",
|
||||
EntityIds::COD => "minecraft:cod",
|
||||
EntityIds::PUFFERFISH => "minecraft:pufferfish",
|
||||
EntityIds::COW => "minecraft:cow",
|
||||
EntityIds::CHICKEN => "minecraft:chicken",
|
||||
EntityIds::BALLOON => "minecraft:balloon",
|
||||
EntityIds::LLAMA => "minecraft:llama",
|
||||
EntityIds::IRON_GOLEM => "minecraft:iron_golem",
|
||||
EntityIds::RABBIT => "minecraft:rabbit",
|
||||
EntityIds::SNOW_GOLEM => "minecraft:snow_golem",
|
||||
EntityIds::BAT => "minecraft:bat",
|
||||
EntityIds::OCELOT => "minecraft:ocelot",
|
||||
EntityIds::HORSE => "minecraft:horse",
|
||||
EntityIds::CAT => "minecraft:cat",
|
||||
EntityIds::POLAR_BEAR => "minecraft:polar_bear",
|
||||
EntityIds::ZOMBIE_HORSE => "minecraft:zombie_horse",
|
||||
EntityIds::TURTLE => "minecraft:turtle",
|
||||
EntityIds::PARROT => "minecraft:parrot",
|
||||
EntityIds::GUARDIAN => "minecraft:guardian",
|
||||
EntityIds::ELDER_GUARDIAN => "minecraft:elder_guardian",
|
||||
EntityIds::VINDICATOR => "minecraft:vindicator",
|
||||
EntityIds::WITHER => "minecraft:wither",
|
||||
EntityIds::ENDER_DRAGON => "minecraft:ender_dragon",
|
||||
EntityIds::SHULKER => "minecraft:shulker",
|
||||
EntityIds::ENDERMITE => "minecraft:endermite",
|
||||
EntityIds::MINECART => "minecraft:minecart",
|
||||
EntityIds::HOPPER_MINECART => "minecraft:hopper_minecart",
|
||||
EntityIds::TNT_MINECART => "minecraft:tnt_minecart",
|
||||
EntityIds::CHEST_MINECART => "minecraft:chest_minecart",
|
||||
EntityIds::COMMAND_BLOCK_MINECART => "minecraft:command_block_minecart",
|
||||
EntityIds::ARMOR_STAND => "minecraft:armor_stand",
|
||||
EntityIds::ITEM => "minecraft:item",
|
||||
EntityIds::TNT => "minecraft:tnt",
|
||||
EntityIds::FALLING_BLOCK => "minecraft:falling_block",
|
||||
EntityIds::XP_BOTTLE => "minecraft:xp_bottle",
|
||||
EntityIds::XP_ORB => "minecraft:xp_orb",
|
||||
EntityIds::EYE_OF_ENDER_SIGNAL => "minecraft:eye_of_ender_signal",
|
||||
EntityIds::ENDER_CRYSTAL => "minecraft:ender_crystal",
|
||||
EntityIds::SHULKER_BULLET => "minecraft:shulker_bullet",
|
||||
EntityIds::FISHING_HOOK => "minecraft:fishing_hook",
|
||||
EntityIds::DRAGON_FIREBALL => "minecraft:dragon_fireball",
|
||||
EntityIds::ARROW => "minecraft:arrow",
|
||||
EntityIds::SNOWBALL => "minecraft:snowball",
|
||||
EntityIds::EGG => "minecraft:egg",
|
||||
EntityIds::PAINTING => "minecraft:painting",
|
||||
EntityIds::THROWN_TRIDENT => "minecraft:thrown_trident",
|
||||
EntityIds::FIREBALL => "minecraft:fireball",
|
||||
EntityIds::SPLASH_POTION => "minecraft:splash_potion",
|
||||
EntityIds::ENDER_PEARL => "minecraft:ender_pearl",
|
||||
EntityIds::LEASH_KNOT => "minecraft:leash_knot",
|
||||
EntityIds::WITHER_SKULL => "minecraft:wither_skull",
|
||||
EntityIds::WITHER_SKULL_DANGEROUS => "minecraft:wither_skull_dangerous",
|
||||
EntityIds::BOAT => "minecraft:boat",
|
||||
EntityIds::LIGHTNING_BOLT => "minecraft:lightning_bolt",
|
||||
EntityIds::SMALL_FIREBALL => "minecraft:small_fireball",
|
||||
EntityIds::LLAMA_SPIT => "minecraft:llama_spit",
|
||||
EntityIds::AREA_EFFECT_CLOUD => "minecraft:area_effect_cloud",
|
||||
EntityIds::LINGERING_POTION => "minecraft:lingering_potion",
|
||||
EntityIds::FIREWORKS_ROCKET => "minecraft:fireworks_rocket",
|
||||
EntityIds::EVOCATION_FANG => "minecraft:evocation_fang",
|
||||
EntityIds::EVOCATION_ILLAGER => "minecraft:evocation_illager",
|
||||
EntityIds::VEX => "minecraft:vex",
|
||||
EntityIds::AGENT => "minecraft:agent",
|
||||
EntityIds::ICE_BOMB => "minecraft:ice_bomb",
|
||||
EntityIds::PHANTOM => "minecraft:phantom",
|
||||
EntityIds::TRIPOD_CAMERA => "minecraft:tripod_camera"
|
||||
];
|
||||
|
||||
/** @var int|null */
|
||||
public $entityUniqueId = null; //TODO
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
/** @var int */
|
||||
public $type;
|
||||
/** @var Vector3 */
|
||||
public $position;
|
||||
/** @var Vector3|null */
|
||||
public $motion;
|
||||
/** @var float */
|
||||
public $pitch = 0.0;
|
||||
/** @var float */
|
||||
public $yaw = 0.0;
|
||||
/** @var float */
|
||||
public $headYaw = 0.0;
|
||||
|
||||
/** @var Attribute[] */
|
||||
public $attributes = [];
|
||||
/** @var array */
|
||||
public $metadata = [];
|
||||
/** @var EntityLink[] */
|
||||
public $links = [];
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->entityUniqueId = $this->getEntityUniqueId();
|
||||
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
||||
$this->type = array_search($t = $this->getString(), self::LEGACY_ID_MAP_BC, true);
|
||||
if($this->type === false){
|
||||
throw new \UnexpectedValueException("Can't map ID $t to legacy ID");
|
||||
}
|
||||
$this->position = $this->getVector3();
|
||||
$this->motion = $this->getVector3();
|
||||
$this->pitch = $this->getLFloat();
|
||||
$this->yaw = $this->getLFloat();
|
||||
$this->headYaw = $this->getLFloat();
|
||||
|
||||
$attrCount = $this->getUnsignedVarInt();
|
||||
for($i = 0; $i < $attrCount; ++$i){
|
||||
$name = $this->getString();
|
||||
$min = $this->getLFloat();
|
||||
$current = $this->getLFloat();
|
||||
$max = $this->getLFloat();
|
||||
$attr = Attribute::getAttributeByName($name);
|
||||
|
||||
if($attr !== null){
|
||||
$attr->setMinValue($min);
|
||||
$attr->setMaxValue($max);
|
||||
$attr->setValue($current);
|
||||
$this->attributes[] = $attr;
|
||||
}else{
|
||||
throw new \UnexpectedValueException("Unknown attribute type \"$name\"");
|
||||
}
|
||||
}
|
||||
|
||||
$this->metadata = $this->getEntityMetadata();
|
||||
$linkCount = $this->getUnsignedVarInt();
|
||||
for($i = 0; $i < $linkCount; ++$i){
|
||||
$this->links[] = $this->getEntityLink();
|
||||
}
|
||||
public function getUvarint1() : int{
|
||||
return $this->uvarint1;
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
$this->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId);
|
||||
$this->putEntityRuntimeId($this->entityRuntimeId);
|
||||
if(!isset(self::LEGACY_ID_MAP_BC[$this->type])){
|
||||
throw new \InvalidArgumentException("Unknown entity numeric ID $this->type");
|
||||
}
|
||||
$this->putString(self::LEGACY_ID_MAP_BC[$this->type]);
|
||||
$this->putVector3($this->position);
|
||||
$this->putVector3Nullable($this->motion);
|
||||
$this->putLFloat($this->pitch);
|
||||
$this->putLFloat($this->yaw);
|
||||
$this->putLFloat($this->headYaw);
|
||||
|
||||
$this->putUnsignedVarInt(count($this->attributes));
|
||||
foreach($this->attributes as $attribute){
|
||||
$this->putString($attribute->getName());
|
||||
$this->putLFloat($attribute->getMinValue());
|
||||
$this->putLFloat($attribute->getValue());
|
||||
$this->putLFloat($attribute->getMaxValue());
|
||||
}
|
||||
|
||||
$this->putEntityMetadata($this->metadata);
|
||||
$this->putUnsignedVarInt(count($this->links));
|
||||
foreach($this->links as $link){
|
||||
$this->putEntityLink($link);
|
||||
}
|
||||
protected function decodePayload() : void{
|
||||
$this->uvarint1 = $this->getUnsignedVarInt();
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleAddEntity($this);
|
||||
protected function encodePayload() : void{
|
||||
$this->putUnsignedVarInt($this->uvarint1);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $handler) : bool{
|
||||
return $handler->handleAddEntity($this);
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class AddItemEntityPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ENTITY_PACKET;
|
||||
class AddItemActorPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ACTOR_PACKET;
|
||||
|
||||
/** @var int|null */
|
||||
public $entityUniqueId = null; //TODO
|
||||
@ -68,6 +68,6 @@ class AddItemEntityPacket extends DataPacket{
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleAddItemEntity($this);
|
||||
return $session->handleAddItemActor($this);
|
||||
}
|
||||
}
|
@ -26,30 +26,27 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class AddPaintingPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::ADD_PAINTING_PACKET;
|
||||
|
||||
/** @var string */
|
||||
public $title;
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
/** @var int */
|
||||
public $x;
|
||||
/** @var int|null */
|
||||
public $entityUniqueId = null;
|
||||
/** @var int */
|
||||
public $y;
|
||||
/** @var int */
|
||||
public $z;
|
||||
public $entityRuntimeId;
|
||||
/** @var Vector3 */
|
||||
public $position;
|
||||
/** @var int */
|
||||
public $direction;
|
||||
/** @var string */
|
||||
public $title;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->entityUniqueId = $this->getEntityUniqueId();
|
||||
$this->entityRuntimeId = $this->getEntityRuntimeId();
|
||||
$this->getBlockPosition($this->x, $this->y, $this->z);
|
||||
$this->position = $this->getVector3();
|
||||
$this->direction = $this->getVarInt();
|
||||
$this->title = $this->getString();
|
||||
}
|
||||
@ -57,7 +54,7 @@ class AddPaintingPacket extends DataPacket{
|
||||
protected function encodePayload(){
|
||||
$this->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId);
|
||||
$this->putEntityRuntimeId($this->entityRuntimeId);
|
||||
$this->putBlockPosition($this->x, $this->y, $this->z);
|
||||
$this->putVector3($this->position);
|
||||
$this->putVarInt($this->direction);
|
||||
$this->putString($this->title);
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ class AnimatePacket extends DataPacket{
|
||||
|
||||
public const ACTION_STOP_SLEEP = 3;
|
||||
public const ACTION_CRITICAL_HIT = 4;
|
||||
public const ACTION_ROW_RIGHT = 128;
|
||||
public const ACTION_ROW_LEFT = 129;
|
||||
|
||||
/** @var int */
|
||||
public $action;
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class BlockEntityDataPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::BLOCK_ENTITY_DATA_PACKET;
|
||||
class BlockActorDataPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::BLOCK_ACTOR_DATA_PACKET;
|
||||
|
||||
/** @var int */
|
||||
public $x;
|
||||
@ -51,6 +51,6 @@ class BlockEntityDataPacket extends DataPacket{
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleBlockEntityData($this);
|
||||
return $session->handleBlockActorData($this);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -59,6 +59,10 @@ class CommandBlockUpdatePacket extends DataPacket{
|
||||
public $name;
|
||||
/** @var bool */
|
||||
public $shouldTrackOutput;
|
||||
/** @var int */
|
||||
public $tickDelay;
|
||||
/** @var bool */
|
||||
public $executeOnFirstTick;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->isBlock = $this->getBool();
|
||||
@ -78,6 +82,8 @@ class CommandBlockUpdatePacket extends DataPacket{
|
||||
$this->name = $this->getString();
|
||||
|
||||
$this->shouldTrackOutput = $this->getBool();
|
||||
$this->tickDelay = $this->getLInt();
|
||||
$this->executeOnFirstTick = $this->getBool();
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
@ -97,6 +103,8 @@ class CommandBlockUpdatePacket extends DataPacket{
|
||||
$this->putString($this->name);
|
||||
|
||||
$this->putBool($this->shouldTrackOutput);
|
||||
$this->putLInt($this->tickDelay);
|
||||
$this->putBool($this->executeOnFirstTick);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -33,6 +33,9 @@ use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\network\mcpe\NetworkBinaryStream;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
#ifndef COMPILE
|
||||
use pocketmine\utils\Binary;
|
||||
#endif
|
||||
use function count;
|
||||
use function str_repeat;
|
||||
|
||||
@ -72,11 +75,13 @@ class CraftingDataPacket extends DataPacket{
|
||||
case self::ENTRY_SHAPELESS:
|
||||
case self::ENTRY_SHULKER_BOX:
|
||||
case self::ENTRY_SHAPELESS_CHEMISTRY:
|
||||
$entry["recipe_id"] = $this->getString();
|
||||
$ingredientCount = $this->getUnsignedVarInt();
|
||||
/** @var Item */
|
||||
$entry["input"] = [];
|
||||
for($j = 0; $j < $ingredientCount; ++$j){
|
||||
$entry["input"][] = $this->getSlot();
|
||||
$entry["input"][] = $in = $this->getRecipeIngredient();
|
||||
$in->setCount(1); //TODO HACK: they send a useless count field which breaks the PM crafting system because it isn't always 1
|
||||
}
|
||||
$resultCount = $this->getUnsignedVarInt();
|
||||
$entry["output"] = [];
|
||||
@ -85,16 +90,19 @@ class CraftingDataPacket extends DataPacket{
|
||||
}
|
||||
$entry["uuid"] = $this->getUUID()->toString();
|
||||
$entry["block"] = $this->getString();
|
||||
$entry["priority"] = $this->getVarInt();
|
||||
|
||||
break;
|
||||
case self::ENTRY_SHAPED:
|
||||
case self::ENTRY_SHAPED_CHEMISTRY:
|
||||
$entry["recipe_id"] = $this->getString();
|
||||
$entry["width"] = $this->getVarInt();
|
||||
$entry["height"] = $this->getVarInt();
|
||||
$count = $entry["width"] * $entry["height"];
|
||||
$entry["input"] = [];
|
||||
for($j = 0; $j < $count; ++$j){
|
||||
$entry["input"][] = $this->getSlot();
|
||||
$entry["input"][] = $in = $this->getRecipeIngredient();
|
||||
$in->setCount(1); //TODO HACK: they send a useless count field which breaks the PM crafting system
|
||||
}
|
||||
$resultCount = $this->getUnsignedVarInt();
|
||||
$entry["output"] = [];
|
||||
@ -103,6 +111,7 @@ class CraftingDataPacket extends DataPacket{
|
||||
}
|
||||
$entry["uuid"] = $this->getUUID()->toString();
|
||||
$entry["block"] = $this->getString();
|
||||
$entry["priority"] = $this->getVarInt();
|
||||
|
||||
break;
|
||||
case self::ENTRY_FURNACE:
|
||||
@ -116,7 +125,10 @@ class CraftingDataPacket extends DataPacket{
|
||||
}
|
||||
}
|
||||
$entry["input"] = ItemFactory::get($inputId, $inputData);
|
||||
$entry["output"] = $this->getSlot();
|
||||
$entry["output"] = $out = $this->getSlot();
|
||||
if($out->getDamage() === 0x7fff){
|
||||
$out->setDamage(0); //TODO HACK: some 1.12 furnace recipe outputs have wildcard damage values
|
||||
}
|
||||
$entry["block"] = $this->getString();
|
||||
|
||||
break;
|
||||
@ -131,11 +143,11 @@ class CraftingDataPacket extends DataPacket{
|
||||
$this->getBool(); //cleanRecipes
|
||||
}
|
||||
|
||||
private static function writeEntry($entry, NetworkBinaryStream $stream){
|
||||
private static function writeEntry($entry, NetworkBinaryStream $stream, int $pos){
|
||||
if($entry instanceof ShapelessRecipe){
|
||||
return self::writeShapelessRecipe($entry, $stream);
|
||||
return self::writeShapelessRecipe($entry, $stream, $pos);
|
||||
}elseif($entry instanceof ShapedRecipe){
|
||||
return self::writeShapedRecipe($entry, $stream);
|
||||
return self::writeShapedRecipe($entry, $stream, $pos);
|
||||
}elseif($entry instanceof FurnaceRecipe){
|
||||
return self::writeFurnaceRecipe($entry, $stream);
|
||||
}
|
||||
@ -144,10 +156,11 @@ class CraftingDataPacket extends DataPacket{
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static function writeShapelessRecipe(ShapelessRecipe $recipe, NetworkBinaryStream $stream){
|
||||
private static function writeShapelessRecipe(ShapelessRecipe $recipe, NetworkBinaryStream $stream, int $pos){
|
||||
$stream->putString(Binary::writeInt($pos)); //some kind of recipe ID, doesn't matter what it is as long as it's unique
|
||||
$stream->putUnsignedVarInt($recipe->getIngredientCount());
|
||||
foreach($recipe->getIngredientList() as $item){
|
||||
$stream->putSlot($item);
|
||||
$stream->putRecipeIngredient($item);
|
||||
}
|
||||
|
||||
$results = $recipe->getResults();
|
||||
@ -158,17 +171,19 @@ class CraftingDataPacket extends DataPacket{
|
||||
|
||||
$stream->put(str_repeat("\x00", 16)); //Null UUID
|
||||
$stream->putString("crafting_table"); //TODO: blocktype (no prefix) (this might require internal API breaks)
|
||||
$stream->putVarInt(50); //TODO: priority
|
||||
|
||||
return CraftingDataPacket::ENTRY_SHAPELESS;
|
||||
}
|
||||
|
||||
private static function writeShapedRecipe(ShapedRecipe $recipe, NetworkBinaryStream $stream){
|
||||
private static function writeShapedRecipe(ShapedRecipe $recipe, NetworkBinaryStream $stream, int $pos){
|
||||
$stream->putString(Binary::writeInt($pos)); //some kind of recipe ID, doesn't matter what it is as long as it's unique
|
||||
$stream->putVarInt($recipe->getWidth());
|
||||
$stream->putVarInt($recipe->getHeight());
|
||||
|
||||
for($z = 0; $z < $recipe->getHeight(); ++$z){
|
||||
for($x = 0; $x < $recipe->getWidth(); ++$x){
|
||||
$stream->putSlot($recipe->getIngredient($x, $z));
|
||||
$stream->putRecipeIngredient($recipe->getIngredient($x, $z));
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,6 +195,7 @@ class CraftingDataPacket extends DataPacket{
|
||||
|
||||
$stream->put(str_repeat("\x00", 16)); //Null UUID
|
||||
$stream->putString("crafting_table"); //TODO: blocktype (no prefix) (this might require internal API breaks)
|
||||
$stream->putVarInt(50); //TODO: priority
|
||||
|
||||
return CraftingDataPacket::ENTRY_SHAPED;
|
||||
}
|
||||
@ -212,8 +228,9 @@ class CraftingDataPacket extends DataPacket{
|
||||
$this->putUnsignedVarInt(count($this->entries));
|
||||
|
||||
$writer = new NetworkBinaryStream();
|
||||
$counter = 0;
|
||||
foreach($this->entries as $d){
|
||||
$entryType = self::writeEntry($d, $writer);
|
||||
$entryType = self::writeEntry($d, $writer, $counter++);
|
||||
if($entryType >= 0){
|
||||
$this->putVarInt($entryType);
|
||||
$this->put($writer->getBuffer());
|
||||
|
145
src/pocketmine/network/mcpe/protocol/LevelChunkPacket.php
Normal file
145
src/pocketmine/network/mcpe/protocol/LevelChunkPacket.php
Normal 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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -292,8 +292,8 @@ class LevelSoundEventPacket extends DataPacket{
|
||||
public const SOUND_STUN = 261;
|
||||
public const SOUND_BLOCK_SWEET_BERRY_BUSH_HURT = 262;
|
||||
public const SOUND_BLOCK_SWEET_BERRY_BUSH_PICK = 263;
|
||||
public const SOUND_UI_CARTOGRAPHY_TABLE_TAKE_RESULT = 264;
|
||||
public const SOUND_UI_STONECUTTER_TAKE_RESULT = 265;
|
||||
public const SOUND_BLOCK_CARTOGRAPHY_TABLE_USE = 264;
|
||||
public const SOUND_BLOCK_STONECUTTER_USE = 265;
|
||||
public const SOUND_BLOCK_COMPOSTER_EMPTY = 266;
|
||||
public const SOUND_BLOCK_COMPOSTER_FILL = 267;
|
||||
public const SOUND_BLOCK_COMPOSTER_FILL_SUCCESS = 268;
|
||||
@ -302,7 +302,14 @@ class LevelSoundEventPacket extends DataPacket{
|
||||
public const SOUND_BLOCK_BARREL_CLOSE = 271;
|
||||
public const SOUND_RAID_HORN = 272;
|
||||
public const SOUND_BLOCK_LOOM_USE = 273;
|
||||
public const SOUND_UNDEFINED = 274;
|
||||
public const SOUND_AMBIENT_IN_RAID = 274;
|
||||
public const SOUND_UI_CARTOGRAPHY_TABLE_TAKE_RESULT = 275;
|
||||
public const SOUND_UI_STONECUTTER_TAKE_RESULT = 276;
|
||||
public const SOUND_UI_LOOM_TAKE_RESULT = 277;
|
||||
public const SOUND_BLOCK_SMOKER_SMOKE = 278;
|
||||
public const SOUND_BLOCK_BLASTFURNACE_FIRE_CRACKLE = 279;
|
||||
public const SOUND_BLOCK_SMITHING_TABLE_USE = 280;
|
||||
public const SOUND_UNDEFINED = 281;
|
||||
|
||||
/** @var int */
|
||||
public $sound;
|
||||
|
@ -29,8 +29,8 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class MoveEntityAbsolutePacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::MOVE_ENTITY_ABSOLUTE_PACKET;
|
||||
class MoveActorAbsolutePacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::MOVE_ACTOR_ABSOLUTE_PACKET;
|
||||
|
||||
public const FLAG_GROUND = 0x01;
|
||||
public const FLAG_TELEPORT = 0x02;
|
||||
@ -67,6 +67,6 @@ class MoveEntityAbsolutePacket extends DataPacket{
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleMoveEntityAbsolute($this);
|
||||
return $session->handleMoveActorAbsolute($this);
|
||||
}
|
||||
}
|
@ -27,8 +27,8 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class MoveEntityDeltaPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::MOVE_ENTITY_DELTA_PACKET;
|
||||
class MoveActorDeltaPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::MOVE_ACTOR_DELTA_PACKET;
|
||||
|
||||
public const FLAG_HAS_X = 0x01;
|
||||
public const FLAG_HAS_Y = 0x02;
|
||||
@ -103,6 +103,6 @@ class MoveEntityDeltaPacket extends DataPacket{
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleMoveEntityDelta($this);
|
||||
return $session->handleMoveActorDelta($this);
|
||||
}
|
||||
}
|
@ -45,11 +45,11 @@ class PacketPool{
|
||||
static::registerPacket(new SetTimePacket());
|
||||
static::registerPacket(new StartGamePacket());
|
||||
static::registerPacket(new AddPlayerPacket());
|
||||
static::registerPacket(new AddEntityPacket());
|
||||
static::registerPacket(new RemoveEntityPacket());
|
||||
static::registerPacket(new AddItemEntityPacket());
|
||||
static::registerPacket(new TakeItemEntityPacket());
|
||||
static::registerPacket(new MoveEntityAbsolutePacket());
|
||||
static::registerPacket(new AddActorPacket());
|
||||
static::registerPacket(new RemoveActorPacket());
|
||||
static::registerPacket(new AddItemActorPacket());
|
||||
static::registerPacket(new TakeItemActorPacket());
|
||||
static::registerPacket(new MoveActorAbsolutePacket());
|
||||
static::registerPacket(new MovePlayerPacket());
|
||||
static::registerPacket(new RiderJumpPacket());
|
||||
static::registerPacket(new UpdateBlockPacket());
|
||||
@ -58,7 +58,7 @@ class PacketPool{
|
||||
static::registerPacket(new LevelSoundEventPacketV1());
|
||||
static::registerPacket(new LevelEventPacket());
|
||||
static::registerPacket(new BlockEventPacket());
|
||||
static::registerPacket(new EntityEventPacket());
|
||||
static::registerPacket(new ActorEventPacket());
|
||||
static::registerPacket(new MobEffectPacket());
|
||||
static::registerPacket(new UpdateAttributesPacket());
|
||||
static::registerPacket(new InventoryTransactionPacket());
|
||||
@ -66,13 +66,13 @@ class PacketPool{
|
||||
static::registerPacket(new MobArmorEquipmentPacket());
|
||||
static::registerPacket(new InteractPacket());
|
||||
static::registerPacket(new BlockPickRequestPacket());
|
||||
static::registerPacket(new EntityPickRequestPacket());
|
||||
static::registerPacket(new ActorPickRequestPacket());
|
||||
static::registerPacket(new PlayerActionPacket());
|
||||
static::registerPacket(new EntityFallPacket());
|
||||
static::registerPacket(new ActorFallPacket());
|
||||
static::registerPacket(new HurtArmorPacket());
|
||||
static::registerPacket(new SetEntityDataPacket());
|
||||
static::registerPacket(new SetEntityMotionPacket());
|
||||
static::registerPacket(new SetEntityLinkPacket());
|
||||
static::registerPacket(new SetActorDataPacket());
|
||||
static::registerPacket(new SetActorMotionPacket());
|
||||
static::registerPacket(new SetActorLinkPacket());
|
||||
static::registerPacket(new SetHealthPacket());
|
||||
static::registerPacket(new SetSpawnPositionPacket());
|
||||
static::registerPacket(new AnimatePacket());
|
||||
@ -87,9 +87,9 @@ class PacketPool{
|
||||
static::registerPacket(new CraftingEventPacket());
|
||||
static::registerPacket(new GuiDataPickItemPacket());
|
||||
static::registerPacket(new AdventureSettingsPacket());
|
||||
static::registerPacket(new BlockEntityDataPacket());
|
||||
static::registerPacket(new BlockActorDataPacket());
|
||||
static::registerPacket(new PlayerInputPacket());
|
||||
static::registerPacket(new FullChunkDataPacket());
|
||||
static::registerPacket(new LevelChunkPacket());
|
||||
static::registerPacket(new SetCommandsEnabledPacket());
|
||||
static::registerPacket(new SetDifficultyPacket());
|
||||
static::registerPacket(new ChangeDimensionPacket());
|
||||
@ -142,22 +142,31 @@ class PacketPool{
|
||||
static::registerPacket(new SetScorePacket());
|
||||
static::registerPacket(new LabTablePacket());
|
||||
static::registerPacket(new UpdateBlockSyncedPacket());
|
||||
static::registerPacket(new MoveEntityDeltaPacket());
|
||||
static::registerPacket(new MoveActorDeltaPacket());
|
||||
static::registerPacket(new SetScoreboardIdentityPacket());
|
||||
static::registerPacket(new SetLocalPlayerAsInitializedPacket());
|
||||
static::registerPacket(new UpdateSoftEnumPacket());
|
||||
static::registerPacket(new NetworkStackLatencyPacket());
|
||||
static::registerPacket(new ScriptCustomEventPacket());
|
||||
static::registerPacket(new SpawnParticleEffectPacket());
|
||||
static::registerPacket(new AvailableEntityIdentifiersPacket());
|
||||
static::registerPacket(new AvailableActorIdentifiersPacket());
|
||||
static::registerPacket(new LevelSoundEventPacketV2());
|
||||
static::registerPacket(new NetworkChunkPublisherUpdatePacket());
|
||||
static::registerPacket(new BiomeDefinitionListPacket());
|
||||
static::registerPacket(new LevelSoundEventPacket());
|
||||
static::registerPacket(new LevelEventGenericPacket());
|
||||
static::registerPacket(new LecternUpdatePacket());
|
||||
static::registerPacket(new VideoStreamConnectPacket());
|
||||
static::registerPacket(new MapCreateLockedCopyPacket());
|
||||
static::registerPacket(new AddEntityPacket());
|
||||
static::registerPacket(new RemoveEntityPacket());
|
||||
static::registerPacket(new ClientCacheStatusPacket());
|
||||
static::registerPacket(new OnScreenTextureAnimationPacket());
|
||||
static::registerPacket(new MapCreateLockedCopyPacket());
|
||||
static::registerPacket(new StructureTemplateDataExportRequestPacket());
|
||||
static::registerPacket(new StructureTemplateDataExportResponsePacket());
|
||||
static::registerPacket(new UpdateBlockPropertiesPacket());
|
||||
static::registerPacket(new ClientCacheBlobStatusPacket());
|
||||
static::registerPacket(new ClientCacheMissResponsePacket());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,6 +56,7 @@ class PlayerActionPacket extends DataPacket{
|
||||
public const ACTION_STOP_SWIMMING = 22;
|
||||
public const ACTION_START_SPIN_ATTACK = 23;
|
||||
public const ACTION_STOP_SPIN_ATTACK = 24;
|
||||
public const ACTION_INTERACT_BLOCK = 25;
|
||||
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
|
@ -39,15 +39,15 @@ interface ProtocolInfo{
|
||||
/**
|
||||
* Actual Minecraft: PE protocol version
|
||||
*/
|
||||
public const CURRENT_PROTOCOL = 354;
|
||||
public const CURRENT_PROTOCOL = 361;
|
||||
/**
|
||||
* Current Minecraft PE version reported by the server. This is usually the earliest currently supported version.
|
||||
*/
|
||||
public const MINECRAFT_VERSION = 'v1.11.0';
|
||||
public const MINECRAFT_VERSION = 'v1.12.0';
|
||||
/**
|
||||
* Version number sent to clients in ping responses.
|
||||
*/
|
||||
public const MINECRAFT_VERSION_NETWORK = '1.11.0';
|
||||
public const MINECRAFT_VERSION_NETWORK = '1.12.0';
|
||||
|
||||
public const LOGIN_PACKET = 0x01;
|
||||
public const PLAY_STATUS_PACKET = 0x02;
|
||||
@ -61,12 +61,12 @@ interface ProtocolInfo{
|
||||
public const SET_TIME_PACKET = 0x0a;
|
||||
public const START_GAME_PACKET = 0x0b;
|
||||
public const ADD_PLAYER_PACKET = 0x0c;
|
||||
public const ADD_ENTITY_PACKET = 0x0d;
|
||||
public const REMOVE_ENTITY_PACKET = 0x0e;
|
||||
public const ADD_ITEM_ENTITY_PACKET = 0x0f;
|
||||
public const ADD_ACTOR_PACKET = 0x0d;
|
||||
public const REMOVE_ACTOR_PACKET = 0x0e;
|
||||
public const ADD_ITEM_ACTOR_PACKET = 0x0f;
|
||||
|
||||
public const TAKE_ITEM_ENTITY_PACKET = 0x11;
|
||||
public const MOVE_ENTITY_ABSOLUTE_PACKET = 0x12;
|
||||
public const TAKE_ITEM_ACTOR_PACKET = 0x11;
|
||||
public const MOVE_ACTOR_ABSOLUTE_PACKET = 0x12;
|
||||
public const MOVE_PLAYER_PACKET = 0x13;
|
||||
public const RIDER_JUMP_PACKET = 0x14;
|
||||
public const UPDATE_BLOCK_PACKET = 0x15;
|
||||
@ -75,7 +75,7 @@ interface ProtocolInfo{
|
||||
public const LEVEL_SOUND_EVENT_PACKET_V1 = 0x18;
|
||||
public const LEVEL_EVENT_PACKET = 0x19;
|
||||
public const BLOCK_EVENT_PACKET = 0x1a;
|
||||
public const ENTITY_EVENT_PACKET = 0x1b;
|
||||
public const ACTOR_EVENT_PACKET = 0x1b;
|
||||
public const MOB_EFFECT_PACKET = 0x1c;
|
||||
public const UPDATE_ATTRIBUTES_PACKET = 0x1d;
|
||||
public const INVENTORY_TRANSACTION_PACKET = 0x1e;
|
||||
@ -83,13 +83,13 @@ interface ProtocolInfo{
|
||||
public const MOB_ARMOR_EQUIPMENT_PACKET = 0x20;
|
||||
public const INTERACT_PACKET = 0x21;
|
||||
public const BLOCK_PICK_REQUEST_PACKET = 0x22;
|
||||
public const ENTITY_PICK_REQUEST_PACKET = 0x23;
|
||||
public const ACTOR_PICK_REQUEST_PACKET = 0x23;
|
||||
public const PLAYER_ACTION_PACKET = 0x24;
|
||||
public const ENTITY_FALL_PACKET = 0x25;
|
||||
public const ACTOR_FALL_PACKET = 0x25;
|
||||
public const HURT_ARMOR_PACKET = 0x26;
|
||||
public const SET_ENTITY_DATA_PACKET = 0x27;
|
||||
public const SET_ENTITY_MOTION_PACKET = 0x28;
|
||||
public const SET_ENTITY_LINK_PACKET = 0x29;
|
||||
public const SET_ACTOR_DATA_PACKET = 0x27;
|
||||
public const SET_ACTOR_MOTION_PACKET = 0x28;
|
||||
public const SET_ACTOR_LINK_PACKET = 0x29;
|
||||
public const SET_HEALTH_PACKET = 0x2a;
|
||||
public const SET_SPAWN_POSITION_PACKET = 0x2b;
|
||||
public const ANIMATE_PACKET = 0x2c;
|
||||
@ -104,9 +104,9 @@ interface ProtocolInfo{
|
||||
public const CRAFTING_EVENT_PACKET = 0x35;
|
||||
public const GUI_DATA_PICK_ITEM_PACKET = 0x36;
|
||||
public const ADVENTURE_SETTINGS_PACKET = 0x37;
|
||||
public const BLOCK_ENTITY_DATA_PACKET = 0x38;
|
||||
public const BLOCK_ACTOR_DATA_PACKET = 0x38;
|
||||
public const PLAYER_INPUT_PACKET = 0x39;
|
||||
public const FULL_CHUNK_DATA_PACKET = 0x3a;
|
||||
public const LEVEL_CHUNK_PACKET = 0x3a;
|
||||
public const SET_COMMANDS_ENABLED_PACKET = 0x3b;
|
||||
public const SET_DIFFICULTY_PACKET = 0x3c;
|
||||
public const CHANGE_DIMENSION_PACKET = 0x3d;
|
||||
@ -159,7 +159,7 @@ interface ProtocolInfo{
|
||||
public const SET_SCORE_PACKET = 0x6c;
|
||||
public const LAB_TABLE_PACKET = 0x6d;
|
||||
public const UPDATE_BLOCK_SYNCED_PACKET = 0x6e;
|
||||
public const MOVE_ENTITY_DELTA_PACKET = 0x6f;
|
||||
public const MOVE_ACTOR_DELTA_PACKET = 0x6f;
|
||||
public const SET_SCOREBOARD_IDENTITY_PACKET = 0x70;
|
||||
public const SET_LOCAL_PLAYER_AS_INITIALIZED_PACKET = 0x71;
|
||||
public const UPDATE_SOFT_ENUM_PACKET = 0x72;
|
||||
@ -167,14 +167,23 @@ interface ProtocolInfo{
|
||||
|
||||
public const SCRIPT_CUSTOM_EVENT_PACKET = 0x75;
|
||||
public const SPAWN_PARTICLE_EFFECT_PACKET = 0x76;
|
||||
public const AVAILABLE_ENTITY_IDENTIFIERS_PACKET = 0x77;
|
||||
public const AVAILABLE_ACTOR_IDENTIFIERS_PACKET = 0x77;
|
||||
public const LEVEL_SOUND_EVENT_PACKET_V2 = 0x78;
|
||||
public const NETWORK_CHUNK_PUBLISHER_UPDATE_PACKET = 0x79;
|
||||
public const BIOME_DEFINITION_LIST_PACKET = 0x7a;
|
||||
public const LEVEL_SOUND_EVENT_PACKET = 0x7b;
|
||||
public const LECTERN_UPDATE_PACKET = 0x7c;
|
||||
public const VIDEO_STREAM_CONNECT_PACKET = 0x7d;
|
||||
public const MAP_CREATE_LOCKED_COPY_PACKET = 0x7e;
|
||||
public const ON_SCREEN_TEXTURE_ANIMATION_PACKET = 0x7f;
|
||||
public const LEVEL_EVENT_GENERIC_PACKET = 0x7c;
|
||||
public const LECTERN_UPDATE_PACKET = 0x7d;
|
||||
public const VIDEO_STREAM_CONNECT_PACKET = 0x7e;
|
||||
public const ADD_ENTITY_PACKET = 0x7f;
|
||||
public const REMOVE_ENTITY_PACKET = 0x80;
|
||||
public const CLIENT_CACHE_STATUS_PACKET = 0x81;
|
||||
public const ON_SCREEN_TEXTURE_ANIMATION_PACKET = 0x82;
|
||||
public const MAP_CREATE_LOCKED_COPY_PACKET = 0x83;
|
||||
public const STRUCTURE_TEMPLATE_DATA_EXPORT_REQUEST_PACKET = 0x84;
|
||||
public const STRUCTURE_TEMPLATE_DATA_EXPORT_RESPONSE_PACKET = 0x85;
|
||||
public const UPDATE_BLOCK_PROPERTIES_PACKET = 0x86;
|
||||
public const CLIENT_CACHE_BLOB_STATUS_PACKET = 0x87;
|
||||
public const CLIENT_CACHE_MISS_RESPONSE_PACKET = 0x88;
|
||||
|
||||
}
|
||||
|
48
src/pocketmine/network/mcpe/protocol/RemoveActorPacket.php
Normal file
48
src/pocketmine/network/mcpe/protocol/RemoveActorPacket.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
@ -25,24 +25,36 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class RemoveEntityPacket extends DataPacket{
|
||||
class RemoveEntityPacket extends DataPacket/* implements ClientboundPacket*/{
|
||||
public const NETWORK_ID = ProtocolInfo::REMOVE_ENTITY_PACKET;
|
||||
|
||||
/** @var int */
|
||||
public $entityUniqueId;
|
||||
private $uvarint1;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->entityUniqueId = $this->getEntityUniqueId();
|
||||
public static function create(int $uvarint1) : self{
|
||||
$result = new self;
|
||||
$result->uvarint1 = $uvarint1;
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
$this->putEntityUniqueId($this->entityUniqueId);
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getUvarint1() : int{
|
||||
return $this->uvarint1;
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleRemoveEntity($this);
|
||||
protected function decodePayload() : void{
|
||||
$this->uvarint1 = $this->getUnsignedVarInt();
|
||||
}
|
||||
|
||||
protected function encodePayload() : void{
|
||||
$this->putUnsignedVarInt($this->uvarint1);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $handler) : bool{
|
||||
return $handler->handleRemoveEntity($this);
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\ResourcePackType;
|
||||
|
||||
class ResourcePackDataInfoPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::RESOURCE_PACK_DATA_INFO_PACKET;
|
||||
@ -42,6 +43,10 @@ class ResourcePackDataInfoPacket extends DataPacket{
|
||||
public $compressedPackSize;
|
||||
/** @var string */
|
||||
public $sha256;
|
||||
/** @var bool */
|
||||
public $isPremium = false;
|
||||
/** @var int */
|
||||
public $packType = ResourcePackType::RESOURCES; //TODO: check the values for this
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->packId = $this->getString();
|
||||
@ -49,6 +54,8 @@ class ResourcePackDataInfoPacket extends DataPacket{
|
||||
$this->chunkCount = $this->getLInt();
|
||||
$this->compressedPackSize = $this->getLLong();
|
||||
$this->sha256 = $this->getString();
|
||||
$this->isPremium = $this->getBool();
|
||||
$this->packType = $this->getByte();
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
@ -57,6 +64,8 @@ class ResourcePackDataInfoPacket extends DataPacket{
|
||||
$this->putLInt($this->chunkCount);
|
||||
$this->putLLong($this->compressedPackSize);
|
||||
$this->putString($this->sha256);
|
||||
$this->putBool($this->isPremium);
|
||||
$this->putByte($this->packType);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class SetEntityDataPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::SET_ENTITY_DATA_PACKET;
|
||||
class SetActorDataPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::SET_ACTOR_DATA_PACKET;
|
||||
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
@ -47,6 +47,6 @@ class SetEntityDataPacket extends DataPacket{
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleSetEntityData($this);
|
||||
return $session->handleSetActorData($this);
|
||||
}
|
||||
}
|
@ -29,8 +29,8 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\EntityLink;
|
||||
|
||||
class SetEntityLinkPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::SET_ENTITY_LINK_PACKET;
|
||||
class SetActorLinkPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::SET_ACTOR_LINK_PACKET;
|
||||
|
||||
/** @var EntityLink */
|
||||
public $link;
|
||||
@ -44,6 +44,6 @@ class SetEntityLinkPacket extends DataPacket{
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleSetEntityLink($this);
|
||||
return $session->handleSetActorLink($this);
|
||||
}
|
||||
}
|
@ -29,8 +29,8 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class SetEntityMotionPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::SET_ENTITY_MOTION_PACKET;
|
||||
class SetActorMotionPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::SET_ACTOR_MOTION_PACKET;
|
||||
|
||||
/** @var int */
|
||||
public $entityRuntimeId;
|
||||
@ -48,6 +48,6 @@ class SetEntityMotionPacket extends DataPacket{
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleSetEntityMotion($this);
|
||||
return $session->handleSetActorMotion($this);
|
||||
}
|
||||
}
|
@ -61,6 +61,7 @@ class SetScorePacket extends DataPacket{
|
||||
throw new \UnexpectedValueException("Unknown entry type $entry->type");
|
||||
}
|
||||
}
|
||||
$this->entries[] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,12 +32,17 @@ use pocketmine\network\mcpe\NetworkSession;
|
||||
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
|
||||
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
|
||||
use function count;
|
||||
use function file_get_contents;
|
||||
use function json_decode;
|
||||
use const pocketmine\RESOURCE_PATH;
|
||||
|
||||
class StartGamePacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::START_GAME_PACKET;
|
||||
|
||||
/** @var string|null */
|
||||
private static $runtimeIdTableCache;
|
||||
private static $blockTableCache = null;
|
||||
/** @var string|null */
|
||||
private static $itemTableCache = null;
|
||||
|
||||
/** @var int */
|
||||
public $entityUniqueId;
|
||||
@ -122,6 +127,8 @@ class StartGamePacket extends DataPacket{
|
||||
public $isFromWorldTemplate = false;
|
||||
/** @var bool */
|
||||
public $isWorldTemplateOptionLocked = false;
|
||||
/** @var bool */
|
||||
public $onlySpawnV1Villagers = false;
|
||||
|
||||
/** @var string */
|
||||
public $levelId = ""; //base64 string, usually the same as world folder name in vanilla
|
||||
@ -138,11 +145,10 @@ class StartGamePacket extends DataPacket{
|
||||
/** @var string */
|
||||
public $multiplayerCorrelationId = ""; //TODO: this should be filled with a UUID of some sort
|
||||
|
||||
/** @var bool */
|
||||
public $onlySpawnV1Villagers = false;
|
||||
|
||||
/** @var array|null each entry must have a "name" (string) and "data" (int16) element */
|
||||
public $runtimeIdTable = null;
|
||||
/** @var array|null ["name" (string), "data" (int16), "legacy_id" (int16)] */
|
||||
public $blockTable = null;
|
||||
/** @var array|null string (name) => int16 (legacyID) */
|
||||
public $itemTable = null;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->entityUniqueId = $this->getEntityUniqueId();
|
||||
@ -185,6 +191,7 @@ class StartGamePacket extends DataPacket{
|
||||
$this->useMsaGamertagsOnly = $this->getBool();
|
||||
$this->isFromWorldTemplate = $this->getBool();
|
||||
$this->isWorldTemplateOptionLocked = $this->getBool();
|
||||
$this->onlySpawnV1Villagers = $this->getBool();
|
||||
|
||||
$this->levelId = $this->getString();
|
||||
$this->worldName = $this->getString();
|
||||
@ -194,18 +201,23 @@ class StartGamePacket extends DataPacket{
|
||||
|
||||
$this->enchantmentSeed = $this->getVarInt();
|
||||
|
||||
$count = $this->getUnsignedVarInt();
|
||||
$table = [];
|
||||
for($i = 0; $i < $count; ++$i){
|
||||
$this->blockTable = [];
|
||||
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||
$id = $this->getString();
|
||||
$data = $this->getLShort();
|
||||
$data = $this->getSignedLShort();
|
||||
$unknown = $this->getSignedLShort();
|
||||
|
||||
$table[$i] = ["name" => $id, "data" => $data];
|
||||
$this->blockTable[$i] = ["name" => $id, "data" => $data, "legacy_id" => $unknown];
|
||||
}
|
||||
$this->itemTable = [];
|
||||
for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){
|
||||
$id = $this->getString();
|
||||
$legacyId = $this->getSignedLShort();
|
||||
|
||||
$this->itemTable[$id] = $legacyId;
|
||||
}
|
||||
$this->runtimeIdTable = $table;
|
||||
|
||||
$this->multiplayerCorrelationId = $this->getString();
|
||||
$this->onlySpawnV1Villagers = $this->getBool();
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
@ -249,6 +261,7 @@ class StartGamePacket extends DataPacket{
|
||||
$this->putBool($this->useMsaGamertagsOnly);
|
||||
$this->putBool($this->isFromWorldTemplate);
|
||||
$this->putBool($this->isWorldTemplateOptionLocked);
|
||||
$this->putBool($this->onlySpawnV1Villagers);
|
||||
|
||||
$this->putString($this->levelId);
|
||||
$this->putString($this->worldName);
|
||||
@ -258,18 +271,25 @@ class StartGamePacket extends DataPacket{
|
||||
|
||||
$this->putVarInt($this->enchantmentSeed);
|
||||
|
||||
if($this->runtimeIdTable === null){
|
||||
if(self::$runtimeIdTableCache === null){
|
||||
if($this->blockTable === null){
|
||||
if(self::$blockTableCache === null){
|
||||
//this is a really nasty hack, but it'll do for now
|
||||
self::$runtimeIdTableCache = self::serializeBlockTable(RuntimeBlockMapping::getBedrockKnownStates());
|
||||
self::$blockTableCache = self::serializeBlockTable(RuntimeBlockMapping::getBedrockKnownStates());
|
||||
}
|
||||
$this->put(self::$runtimeIdTableCache);
|
||||
$this->put(self::$blockTableCache);
|
||||
}else{
|
||||
$this->put(self::serializeBlockTable($this->runtimeIdTable));
|
||||
$this->put(self::serializeBlockTable($this->blockTable));
|
||||
}
|
||||
if($this->itemTable === null){
|
||||
if(self::$itemTableCache === null){
|
||||
self::$itemTableCache = self::serializeItemTable(json_decode(file_get_contents(RESOURCE_PATH . '/vanilla/item_id_map.json'), true));
|
||||
}
|
||||
$this->put(self::$itemTableCache);
|
||||
}else{
|
||||
$this->put(self::serializeItemTable($this->itemTable));
|
||||
}
|
||||
|
||||
$this->putString($this->multiplayerCorrelationId);
|
||||
$this->putBool($this->onlySpawnV1Villagers);
|
||||
}
|
||||
|
||||
private static function serializeBlockTable(array $table) : string{
|
||||
@ -278,6 +298,17 @@ class StartGamePacket extends DataPacket{
|
||||
foreach($table as $v){
|
||||
$stream->putString($v["name"]);
|
||||
$stream->putLShort($v["data"]);
|
||||
$stream->putLShort($v["legacy_id"]);
|
||||
}
|
||||
return $stream->getBuffer();
|
||||
}
|
||||
|
||||
private static function serializeItemTable(array $table) : string{
|
||||
$stream = new NetworkBinaryStream();
|
||||
$stream->putUnsignedVarInt(count($table));
|
||||
foreach($table as $name => $legacyId){
|
||||
$stream->putString($name);
|
||||
$stream->putLShort($legacyId);
|
||||
}
|
||||
return $stream->getBuffer();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class TakeItemEntityPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::TAKE_ITEM_ENTITY_PACKET;
|
||||
class TakeItemActorPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::TAKE_ITEM_ACTOR_PACKET;
|
||||
|
||||
/** @var int */
|
||||
public $target;
|
||||
@ -47,6 +47,6 @@ class TakeItemEntityPacket extends DataPacket{
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleTakeItemEntity($this);
|
||||
return $session->handleTakeItemActor($this);
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ class UnknownPacket extends DataPacket{
|
||||
|
||||
public function pid(){
|
||||
if(strlen($this->payload ?? "") > 0){
|
||||
return ord($this->payload{0});
|
||||
return ord($this->payload[0]);
|
||||
}
|
||||
return self::NETWORK_ID;
|
||||
}
|
||||
|
@ -25,32 +25,31 @@ namespace pocketmine\network\mcpe\protocol;
|
||||
|
||||
#include <rules/DataPacket.h>
|
||||
|
||||
|
||||
use pocketmine\nbt\NetworkLittleEndianNBTStream;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
|
||||
class FullChunkDataPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::FULL_CHUNK_DATA_PACKET;
|
||||
class UpdateBlockPropertiesPacket extends DataPacket{
|
||||
public const NETWORK_ID = ProtocolInfo::UPDATE_BLOCK_PROPERTIES_PACKET;
|
||||
|
||||
/** @var int */
|
||||
public $chunkX;
|
||||
/** @var int */
|
||||
public $chunkZ;
|
||||
/** @var string */
|
||||
public $data;
|
||||
private $nbt;
|
||||
|
||||
protected function decodePayload(){
|
||||
$this->chunkX = $this->getVarInt();
|
||||
$this->chunkZ = $this->getVarInt();
|
||||
$this->data = $this->getString();
|
||||
public static function create(CompoundTag $data) : self{
|
||||
$result = new self;
|
||||
$result->nbt = (new NetworkLittleEndianNBTStream())->write($data);
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function encodePayload(){
|
||||
$this->putVarInt($this->chunkX);
|
||||
$this->putVarInt($this->chunkZ);
|
||||
$this->putString($this->data);
|
||||
protected function decodePayload() : void{
|
||||
$this->nbt = $this->getRemaining();
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
return $session->handleFullChunkData($this);
|
||||
protected function encodePayload() : void{
|
||||
$this->put($this->nbt);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $handler) : bool{
|
||||
return $handler->handleUpdateBlockProperties($this);
|
||||
}
|
||||
}
|
@ -39,17 +39,25 @@ class VideoStreamConnectPacket extends DataPacket/* implements ClientboundPacket
|
||||
public $frameSendFrequency;
|
||||
/** @var int */
|
||||
public $action;
|
||||
/** @var int */
|
||||
public $resolutionX;
|
||||
/** @var int */
|
||||
public $resolutionY;
|
||||
|
||||
protected function decodePayload() : void{
|
||||
$this->serverUri = $this->getString();
|
||||
$this->frameSendFrequency = $this->getLFloat();
|
||||
$this->action = $this->getByte();
|
||||
$this->resolutionX = $this->getLInt();
|
||||
$this->resolutionY = $this->getLInt();
|
||||
}
|
||||
|
||||
protected function encodePayload() : void{
|
||||
$this->putString($this->serverUri);
|
||||
$this->putLFloat($this->frameSendFrequency);
|
||||
$this->putByte($this->action);
|
||||
$this->putLInt($this->resolutionX);
|
||||
$this->putLInt($this->resolutionY);
|
||||
}
|
||||
|
||||
public function handle(NetworkSession $session) : bool{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -56,9 +56,11 @@ final class RuntimeBlockMapping{
|
||||
foreach($compressedTable as $prefix => $entries){
|
||||
foreach($entries as $shortStringId => $states){
|
||||
foreach($states as $state){
|
||||
$name = "$prefix:$shortStringId";
|
||||
$decompressed[] = [
|
||||
"name" => "$prefix:$shortStringId",
|
||||
"data" => $state
|
||||
"name" => $name,
|
||||
"data" => $state,
|
||||
"legacy_id" => $legacyIdMap[$name]
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -66,11 +68,12 @@ final class RuntimeBlockMapping{
|
||||
self::$bedrockKnownStates = self::randomizeTable($decompressed);
|
||||
|
||||
foreach(self::$bedrockKnownStates as $k => $obj){
|
||||
//this has to use the json offset to make sure the mapping is consistent with what we send over network, even though we aren't using all the entries
|
||||
if(!isset($legacyIdMap[$obj["name"]])){
|
||||
if($obj["data"] > 15){
|
||||
//TODO: in 1.12 they started using data values bigger than 4 bits which we can't handle right now
|
||||
continue;
|
||||
}
|
||||
self::registerMapping($k, $legacyIdMap[$obj["name"]], $obj["data"]);
|
||||
//this has to use the json offset to make sure the mapping is consistent with what we send over network, even though we aren't using all the entries
|
||||
self::registerMapping($k, $obj["legacy_id"], $obj["data"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ class QueryHandler{
|
||||
|
||||
public function handle(AdvancedSourceInterface $interface, string $address, int $port, string $packet){
|
||||
$offset = 2;
|
||||
$packetType = ord($packet{$offset++});
|
||||
$packetType = ord($packet[$offset++]);
|
||||
$sessionID = Binary::readInt(substr($packet, $offset, 4));
|
||||
$offset += 4;
|
||||
$payload = substr($packet, $offset);
|
||||
|
@ -154,7 +154,7 @@ class BanList{
|
||||
$fp = @fopen($this->file, "r");
|
||||
if(is_resource($fp)){
|
||||
while(($line = fgets($fp)) !== false){
|
||||
if($line{0} !== "#"){
|
||||
if($line[0] !== "#"){
|
||||
try{
|
||||
$entry = BanEntry::fromString($line);
|
||||
if($entry instanceof BanEntry){
|
||||
|
@ -286,7 +286,7 @@ class PluginManager{
|
||||
|
||||
$plugins[$name] = $file;
|
||||
|
||||
$softDependencies[$name] = $description->getSoftDepend();
|
||||
$softDependencies[$name] = array_merge($softDependencies[$name] ?? [], $description->getSoftDepend());
|
||||
$dependencies[$name] = $description->getDepend();
|
||||
|
||||
foreach($description->getLoadBefore() as $before){
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 7d9cec8861a9de033da78bb133f8159f2dfd41c5
|
||||
Subproject commit b5a8c68c4262e5d9d7f8280c1d07c252a5e8dbf8
|
@ -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
|
||||
* 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.
|
||||
* 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
|
||||
* {@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.
|
||||
* 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
|
||||
* {@link AsyncTask#onProgressUpdate} from the main thread with the given progress parameter.
|
||||
* 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.
|
||||
*
|
||||
* @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.
|
||||
* All {@link AsyncTask#publishProgress} calls should result in {@link AsyncTask#onProgressUpdate} calls before
|
||||
* {@link AsyncTask#onCompletion} 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
|
||||
* {@link AsyncTask::onCompletion} is called.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
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
|
||||
* 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).
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* executing, or even a plugin might be unloaded). Since PocketMine keeps a strong reference, the objects are still
|
||||
* valid, but the implementation is responsible for checking whether these objects are still usable.
|
||||
* (E.g. a Level object is no longer usable because it is unloaded while the AsyncTask is executing, or even a
|
||||
* plugin might be unloaded). Since PocketMine keeps a strong reference, the objects are still valid, but the
|
||||
* implementation is responsible for checking whether these objects are still usable.
|
||||
*
|
||||
* 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
|
||||
* {@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,
|
||||
* 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
|
||||
* means that you will not be able to retrieve it again afterwards. Use {@link AsyncTask#peekLocal} instead to
|
||||
* 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
|
||||
* retrieve stored data without removing it from the store.
|
||||
*
|
||||
* 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
|
||||
* {@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.
|
||||
*
|
||||
* 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}
|
||||
* 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}
|
||||
* finished executing.
|
||||
*
|
||||
* WARNING: THIS METHOD SHOULD ONLY BE CALLED FROM THE MAIN THREAD!
|
||||
|
@ -31,9 +31,7 @@ use function unserialize;
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @package pocketmine\scheduler
|
||||
* The result of this AsyncTask is an array of arrays (returned from {@link Internet::simpleCurl}) or InternetException objects.
|
||||
*/
|
||||
class BulkCurlTask extends AsyncTask{
|
||||
private $operations;
|
||||
|
@ -28,7 +28,7 @@ use pocketmine\nbt\NetworkLittleEndianNBTStream;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\IntTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
|
||||
use pocketmine\Player;
|
||||
|
||||
abstract class Spawnable extends Tile{
|
||||
@ -37,8 +37,8 @@ abstract class Spawnable extends Tile{
|
||||
/** @var NetworkLittleEndianNBTStream|null */
|
||||
private static $nbtWriter = null;
|
||||
|
||||
public function createSpawnPacket() : BlockEntityDataPacket{
|
||||
$pk = new BlockEntityDataPacket();
|
||||
public function createSpawnPacket() : BlockActorDataPacket{
|
||||
$pk = new BlockActorDataPacket();
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
$pk->z = $this->z;
|
||||
|
@ -300,7 +300,7 @@ class MainLogger extends \AttachableThreadedLogger{
|
||||
$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()){
|
||||
Terminal::init($this->mainThreadHasFormattingCodes); //lazy-init colour codes because we don't know if they've been registered on this thread
|
||||
|
@ -455,7 +455,7 @@ class Utils{
|
||||
public static function javaStringHash(string $string) : int{
|
||||
$hash = 0;
|
||||
for($i = 0, $len = strlen($string); $i < $len; $i++){
|
||||
$ord = ord($string{$i});
|
||||
$ord = ord($string[$i]);
|
||||
if($ord & 0x80){
|
||||
$ord -= 0x100;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user