Compare commits

..

18 Commits
4.6.1 ... 4.7.0

Author SHA1 Message Date
a21419d120 Release 4.7.0 2022-08-09 19:24:01 +01:00
c2b599166c Added new shiny webhook for Discord release notifications 2022-08-09 19:21:36 +01:00
df7a1fcba6 Changes for 1.19.20 2022-08-09 19:06:05 +01:00
d77a95e4af actions/draft-release: bake the full changelog blob URL into the release notes, to ensure it works properly in emails and embeds 2022-08-06 15:49:04 +01:00
5c72807b16 Bump shivammathur/setup-php from 2.21.0 to 2.21.1 (#5199)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.21.0 to 2.21.1.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.21.0...2.21.1)

---
updated-dependencies:
- dependency-name: shivammathur/setup-php
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-06 15:39:36 +01:00
5c6927e16c 4.6.3 is next 2022-08-06 15:35:47 +01:00
9abbb85a93 Release 4.6.2 2022-08-06 15:35:47 +01:00
554182b2cb Update composer dependencies 2022-08-06 15:27:11 +01:00
d669a6f0c7 ReversePriorityQueue: add ReturnTypeWillChange attribute
it's doubtful any plugin dev is extending this, but nonetheless, we can't change it in a patch.
2022-07-27 03:51:06 +01:00
5d9f783037 InGamePacketHandler: do not update player rotation if it didn't change
setRotation() does an alarmingly large amount of work...
2022-07-24 21:07:35 +01:00
01ca14c314 InGamePacketHandler: avoid processing movement if position is unchanged since last tick 2022-07-24 21:00:12 +01:00
608c6ed6db Improved suboptimal code in Player::handleMovement() 2022-07-24 20:51:28 +01:00
c26631d06d InGamePacketHandler: avoid useless object allocations when forceMoveSync=false (99.9% of the time) 2022-07-24 20:44:27 +01:00
b75bc61a64 InGamePacketHandler: don't bother checking for flag changes if the flag fields are identical
we don't need to check this on a bit by bit level if the integers are the same.

this saves 2-3 microseconds per packet on my machine, which doesn't sound like much, but it adds up when there are lots of players.
2022-07-24 20:35:49 +01:00
3724479be3 InGamePacketHandler: improve performance of input flag resolving 2022-07-24 20:33:35 +01:00
eb916fe43d Use a falling block entity to improve client side performance of FloatingTextParticle (#4714)
Performance tests show that this has a considerable client-side performance advantage over using players. In my local tests, using 1000 floating texts in a 10x10x10 area, I observed an FPS increase from 1.5 to 8.0.
2022-07-24 18:22:21 +01:00
5e3b3a0700 Fix assert spam on debug clients 2022-07-24 17:51:02 +01:00
e10a624444 4.6.2 is next 2022-07-22 19:35:10 +01:00
18 changed files with 301 additions and 121 deletions

View File

@ -0,0 +1,100 @@
<?php
declare(strict_types=1);
namespace pocketmine;
use pocketmine\utils\Internet;
use function dirname;
use function fwrite;
use function is_array;
use function json_decode;
use function json_encode;
use const JSON_THROW_ON_ERROR;
use const STDERR;
require dirname(__DIR__, 2) . '/vendor/autoload.php';
/**
* @phpstan-return array<string, mixed>
*/
function generateDiscordEmbed(string $version, string $channel, string $description, string $detailsUrl, string $sourceUrl, string $pharDownloadUrl) : array{
return [
"embeds" => [
[
"title" => "New PocketMine-MP release: $version ($channel)",
"description" => <<<DESCRIPTION
$description
[Details]($detailsUrl) | [Source Code]($sourceUrl) | [Download]($pharDownloadUrl)
DESCRIPTION,
"url" => $detailsUrl,
"color" => $channel === "stable" ? 0x57ab5a : 0xc69026
]
]
];
}
if(count($argv) !== 5){
fwrite(STDERR, "Required arguments: github repo, version, API token\n");
exit(1);
}
[, $repo, $tagName, $token, $hookURL] = $argv;
$result = Internet::getURL('https://api.github.com/repos/' . $repo . '/releases/tags/' . $tagName, extraHeaders: [
'Authorization: token ' . $token
]);
if($result === null){
fwrite(STDERR, "failed to access GitHub API\n");
return;
}
if($result->getCode() !== 200){
fwrite(STDERR, "Error accessing GitHub API: " . $result->getCode() . "\n");
fwrite(STDERR, $result->getBody() . "\n");
exit(1);
}
$releaseInfoJson = json_decode($result->getBody(), true, JSON_THROW_ON_ERROR);
if(!is_array($releaseInfoJson)){
fwrite(STDERR, "Invalid release JSON returned from GitHub API\n");
exit(1);
}
$buildInfoPath = 'https://github.com/' . $repo . '/releases/download/' . $tagName . '/build_info.json';
$buildInfoResult = Internet::getURL($buildInfoPath, extraHeaders: [
'Authorization: token ' . $token
]);
if($buildInfoResult === null){
fwrite(STDERR, "missing build_info.json\n");
exit(1);
}
if($buildInfoResult->getCode() !== 200){
fwrite(STDERR, "error accessing build_info.json: " . $buildInfoResult->getCode() . "\n");
fwrite(STDERR, $buildInfoResult->getBody() . "\n");
exit(1);
}
$buildInfoJson = json_decode($buildInfoResult->getBody(), true, JSON_THROW_ON_ERROR);
if(!is_array($buildInfoJson)){
fwrite(STDERR, "invalid build_info.json\n");
exit(1);
}
$detailsUrl = $buildInfoJson["details_url"];
$sourceUrl = $buildInfoJson["source_url"];
$pharDownloadUrl = $buildInfoJson["download_url"];
$description = $releaseInfoJson["body"];
$discordPayload = generateDiscordEmbed($buildInfoJson["base_version"], $buildInfoJson["channel"], $description, $detailsUrl, $sourceUrl, $pharDownloadUrl);
$response = Internet::postURL(
$hookURL,
json_encode($discordPayload, JSON_THROW_ON_ERROR),
extraHeaders: ['Content-Type: application/json']
);
if($response?->getCode() !== 204){
fwrite(STDERR, "failed to send Discord webhook\n");
fwrite(STDERR, $response?->getBody() ?? "no response body\n");
exit(1);
}

View File

@ -0,0 +1,25 @@
name: Notify Discord webhook of release
on:
release:
types:
- published
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.21.1
with:
php-version: 8.0
- name: Get actual tag name
id: tag-name
run: echo ::set-output name=TAG_NAME::$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{')
- name: Run webhook post script
run: php .github/workflows/discord-release-embed.php ${{ github.repo }} ${{ steps.tag-name.outputs.TAG_NAME }} ${{ github.token }} ${{ secrets.DISCORD_RELEASE_WEBHOOK }}

View File

@ -18,7 +18,7 @@ jobs:
submodules: true
- name: Setup PHP
uses: shivammathur/setup-php@2.21.0
uses: shivammathur/setup-php@2.21.1
with:
php-version: 8.0
@ -80,4 +80,4 @@ jobs:
body: |
**For Minecraft: Bedrock Edition ${{ steps.get-pm-version.outputs.MCPE_VERSION }}**
Please see the [changelogs](/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
Please see the [changelogs](${{ github.server_url }}/${{ github.repository }}/blob/${{ steps.get-pm-version.outputs.PM_VERSION }}/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.

View File

@ -195,7 +195,7 @@ jobs:
- uses: actions/checkout@v3
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.21.0
uses: shivammathur/setup-php@2.21.1
with:
php-version: 8.0
tools: php-cs-fixer:3.2

View File

@ -29,3 +29,14 @@ Released 22nd July 2022.
- Fixed incorrect fire ticks when being set on fire by lava (8 seconds in Bedrock instead of 15).
- `Entity->attack()` now cancels damage from `FIRE` and `FIRE_TICK` damage causes if the entity is fireproof.
- Fixed inventory windows getting force-closed when the client attempts to use an enchanting table or anvil.
# 4.6.2
Released 6th August 2022.
## Core
- Improved server-side performance of `PlayerAuthInputPacket` handler.
- Improved client-side performance of `FloatingTextParticle` by using an invisible falling block entity. This offered a roughly 5x performance improvement over using tiny invisible players in local testing.
## Fixes
- Fixed assert failures and debug spam on debug Minecraft clients related to abilities in `AddPlayerPacket`.
- Fixed crash in `ReversePriorityQueue` on PHP 8.1 by adding `#[ReturnTypeWillChange]` attribute.

14
changelogs/4.7.md Normal file
View File

@ -0,0 +1,14 @@
**For Minecraft: Bedrock Edition 1.19.20**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.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.
# 4.7.0
Released 9th August 2022.
## General
- Added support for Minecraft: Bedrock Edition 1.19.20.
- Removed support for older versions.

View File

@ -34,8 +34,8 @@
"adhocore/json-comment": "^1.1",
"fgrosse/phpasn1": "^2.3",
"netresearch/jsonmapper": "^4.0",
"pocketmine/bedrock-data": "~1.9.0+bedrock-1.19.10",
"pocketmine/bedrock-protocol": "~11.0.0+bedrock-1.19.10",
"pocketmine/bedrock-data": "~1.10.0+bedrock-1.19.20",
"pocketmine/bedrock-protocol": "~12.0.0+bedrock-1.19.20",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/classloader": "^0.2.0",
@ -53,7 +53,7 @@
"webmozart/path-util": "^2.3"
},
"require-dev": {
"phpstan/phpstan": "1.8.0",
"phpstan/phpstan": "1.8.2",
"phpstan/phpstan-phpunit": "^1.1.0",
"phpstan/phpstan-strict-rules": "^1.2.0",
"phpunit/phpunit": "^9.2"

75
composer.lock generated
View File

@ -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": "e03c7f446cee1fdb97ee79817c78470a",
"content-hash": "80afa24adf37096a23643e051d6128ce",
"packages": [
{
"name": "adhocore/json-comment",
@ -63,26 +63,26 @@
},
{
"name": "brick/math",
"version": "0.9.3",
"version": "0.10.1",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
"reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae"
"reference": "de846578401f4e58f911b3afeb62ced56365ed87"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/brick/math/zipball/ca57d18f028f84f777b2168cd1911b0dee2343ae",
"reference": "ca57d18f028f84f777b2168cd1911b0dee2343ae",
"url": "https://api.github.com/repos/brick/math/zipball/de846578401f4e58f911b3afeb62ced56365ed87",
"reference": "de846578401f4e58f911b3afeb62ced56365ed87",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.1 || ^8.0"
"php": "^7.4 || ^8.0"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
"phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
"vimeo/psalm": "4.9.2"
"phpunit/phpunit": "^9.0",
"vimeo/psalm": "4.25.0"
},
"type": "library",
"autoload": {
@ -107,19 +107,15 @@
],
"support": {
"issues": "https://github.com/brick/math/issues",
"source": "https://github.com/brick/math/tree/0.9.3"
"source": "https://github.com/brick/math/tree/0.10.1"
},
"funding": [
{
"url": "https://github.com/BenMorel",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/brick/math",
"type": "tidelift"
}
],
"time": "2021-08-15T20:50:18+00:00"
"time": "2022-08-01T22:54:31+00:00"
},
{
"name": "fgrosse/phpasn1",
@ -249,16 +245,16 @@
},
{
"name": "pocketmine/bedrock-data",
"version": "1.9.0+bedrock-1.19.10",
"version": "1.10.0+bedrock-1.19.20",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockData.git",
"reference": "ecd798a3e7ead50b7da73141bbb0c4ba14dd76a1"
"reference": "43610f6749f22d15ede6b60ed5402bdeff47453e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/ecd798a3e7ead50b7da73141bbb0c4ba14dd76a1",
"reference": "ecd798a3e7ead50b7da73141bbb0c4ba14dd76a1",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/43610f6749f22d15ede6b60ed5402bdeff47453e",
"reference": "43610f6749f22d15ede6b60ed5402bdeff47453e",
"shasum": ""
},
"type": "library",
@ -269,22 +265,22 @@
"description": "Blobs of data generated from Minecraft: Bedrock Edition, used by PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/BedrockData/issues",
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.19.10"
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.19.20"
},
"time": "2022-07-12T19:33:21+00:00"
"time": "2022-08-09T17:44:22+00:00"
},
{
"name": "pocketmine/bedrock-protocol",
"version": "11.0.0+bedrock-1.19.10",
"version": "12.0.0+bedrock-1.19.20",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "705f928bd010ba093d8781d20006e4cd5f79f335"
"reference": "c2778039544fa0c7c5bd3af7963149e7552f4215"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/705f928bd010ba093d8781d20006e4cd5f79f335",
"reference": "705f928bd010ba093d8781d20006e4cd5f79f335",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/c2778039544fa0c7c5bd3af7963149e7552f4215",
"reference": "c2778039544fa0c7c5bd3af7963149e7552f4215",
"shasum": ""
},
"require": {
@ -316,9 +312,9 @@
"description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP",
"support": {
"issues": "https://github.com/pmmp/BedrockProtocol/issues",
"source": "https://github.com/pmmp/BedrockProtocol/tree/11.0.0+bedrock-1.19.10"
"source": "https://github.com/pmmp/BedrockProtocol/tree/bedrock-1.19.20"
},
"time": "2022-07-12T23:47:47+00:00"
"time": "2022-08-09T17:57:29+00:00"
},
{
"name": "pocketmine/binaryutils",
@ -930,20 +926,20 @@
},
{
"name": "ramsey/uuid",
"version": "4.3.1",
"version": "4.4.0",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
"reference": "8505afd4fea63b81a85d3b7b53ac3cb8dc347c28"
"reference": "373f7bacfcf3de038778ff27dcce5672ddbf4c8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/8505afd4fea63b81a85d3b7b53ac3cb8dc347c28",
"reference": "8505afd4fea63b81a85d3b7b53ac3cb8dc347c28",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/373f7bacfcf3de038778ff27dcce5672ddbf4c8a",
"reference": "373f7bacfcf3de038778ff27dcce5672ddbf4c8a",
"shasum": ""
},
"require": {
"brick/math": "^0.8 || ^0.9",
"brick/math": "^0.8 || ^0.9 || ^0.10",
"ext-ctype": "*",
"ext-json": "*",
"php": "^8.0",
@ -959,7 +955,6 @@
"doctrine/annotations": "^1.8",
"ergebnis/composer-normalize": "^2.15",
"mockery/mockery": "^1.3",
"moontoast/math": "^1.1",
"paragonie/random-lib": "^2",
"php-mock/php-mock": "^2.2",
"php-mock/php-mock-mockery": "^1.3",
@ -1008,7 +1003,7 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
"source": "https://github.com/ramsey/uuid/tree/4.3.1"
"source": "https://github.com/ramsey/uuid/tree/4.4.0"
},
"funding": [
{
@ -1020,7 +1015,7 @@
"type": "tidelift"
}
],
"time": "2022-03-27T21:42:02+00:00"
"time": "2022-08-05T17:58:37+00:00"
},
{
"name": "symfony/polyfill-php81",
@ -1737,16 +1732,16 @@
},
{
"name": "phpstan/phpstan",
"version": "1.8.0",
"version": "1.8.2",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "b7648d4ee9321665acaf112e49da9fd93df8fbd5"
"reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/b7648d4ee9321665acaf112e49da9fd93df8fbd5",
"reference": "b7648d4ee9321665acaf112e49da9fd93df8fbd5",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/c53312ecc575caf07b0e90dee43883fdf90ca67c",
"reference": "c53312ecc575caf07b0e90dee43883fdf90ca67c",
"shasum": ""
},
"require": {
@ -1772,7 +1767,7 @@
"description": "PHPStan - PHP Static Analysis Tool",
"support": {
"issues": "https://github.com/phpstan/phpstan/issues",
"source": "https://github.com/phpstan/phpstan/tree/1.8.0"
"source": "https://github.com/phpstan/phpstan/tree/1.8.2"
},
"funding": [
{
@ -1792,7 +1787,7 @@
"type": "tidelift"
}
],
"time": "2022-06-29T08:53:31+00:00"
"time": "2022-07-20T09:57:31+00:00"
},
{
"name": "phpstan/phpstan-phpunit",

View File

@ -31,7 +31,7 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
public const BASE_VERSION = "4.6.1";
public const BASE_VERSION = "4.7.0";
public const IS_DEVELOPMENT_BUILD = false;
public const BUILD_CHANNEL = "stable";

View File

@ -1466,7 +1466,7 @@ abstract class Entity{
$this->location->yaw, //TODO: head yaw
$this->location->yaw, //TODO: body yaw (wtf mojang?)
array_map(function(Attribute $attr) : NetworkAttribute{
return new NetworkAttribute($attr->getId(), $attr->getMinValue(), $attr->getMaxValue(), $attr->getValue(), $attr->getDefaultValue());
return new NetworkAttribute($attr->getId(), $attr->getMinValue(), $attr->getMaxValue(), $attr->getValue(), $attr->getDefaultValue(), []);
}, $this->attributeMap->getAll()),
$this->getAllNetworkData(),
[] //TODO: entity links

View File

@ -50,6 +50,7 @@ use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\PlayerListPacket;
use pocketmine\network\mcpe\protocol\PlayerSkinPacket;
use pocketmine\network\mcpe\protocol\types\command\CommandPermissions;
use pocketmine\network\mcpe\protocol\types\DeviceOS;
use pocketmine\network\mcpe\protocol\types\entity\EntityIds;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
@ -57,12 +58,15 @@ use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty;
use pocketmine\network\mcpe\protocol\types\GameMode;
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
use pocketmine\network\mcpe\protocol\types\PlayerPermissions;
use pocketmine\network\mcpe\protocol\types\UpdateAbilitiesPacketLayer;
use pocketmine\network\mcpe\protocol\UpdateAbilitiesPacket;
use pocketmine\player\Player;
use pocketmine\utils\Limits;
use pocketmine\world\sound\TotemUseSound;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
use function array_fill;
use function array_filter;
use function array_key_exists;
use function array_merge;
@ -481,7 +485,14 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->getInventory()->getItemInHand())),
GameMode::SURVIVAL,
$this->getAllNetworkData(),
UpdateAbilitiesPacket::create(0, 0, $this->getId() /* TODO: this should be unique ID */, []),
UpdateAbilitiesPacket::create(CommandPermissions::NORMAL, PlayerPermissions::VISITOR, $this->getId() /* TODO: this should be unique ID */, [
new UpdateAbilitiesPacketLayer(
UpdateAbilitiesPacketLayer::LAYER_BASE,
array_fill(0, UpdateAbilitiesPacketLayer::NUMBER_OF_ABILITIES, false),
0.0,
0.0
)
]),
[], //TODO: entity links
"", //device ID (we intentionally don't send this - secvuln)
DeviceOS::UNKNOWN //we intentionally don't send this (secvuln)

View File

@ -30,6 +30,7 @@ use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
use pocketmine\network\mcpe\protocol\LevelChunkPacket;
use pocketmine\network\mcpe\protocol\serializer\PacketBatch;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializerContext;
use pocketmine\network\mcpe\protocol\types\ChunkPosition;
use pocketmine\network\mcpe\serializer\ChunkSerializer;
use pocketmine\scheduler\AsyncTask;
use pocketmine\world\format\Chunk;
@ -71,7 +72,7 @@ class ChunkRequestTask extends AsyncTask{
$subCount = ChunkSerializer::getSubChunkCount($chunk) + ChunkSerializer::LOWER_PADDING_SIZE;
$encoderContext = new PacketSerializerContext(GlobalItemTypeDictionary::getInstance()->getDictionary());
$payload = ChunkSerializer::serializeFullChunk($chunk, RuntimeBlockMapping::getInstance(), $encoderContext, $this->tiles);
$this->setResult($this->compressor->compress(PacketBatch::fromPackets($encoderContext, LevelChunkPacket::create($this->chunkX, $this->chunkZ, $subCount, false, null, $payload))->getBuffer()));
$this->setResult($this->compressor->compress(PacketBatch::fromPackets($encoderContext, LevelChunkPacket::create(new ChunkPosition($this->chunkX, $this->chunkZ), $subCount, false, null, $payload))->getBuffer()));
}
public function onError() : void{

View File

@ -756,7 +756,7 @@ class NetworkSession{
}
public function syncViewAreaCenterPoint(Vector3 $newPos, int $viewDistance) : void{
$this->sendDataPacket(NetworkChunkPublisherUpdatePacket::create(BlockPosition::fromVector3($newPos), $viewDistance * 16)); //blocks, not chunks >.>
$this->sendDataPacket(NetworkChunkPublisherUpdatePacket::create(BlockPosition::fromVector3($newPos), $viewDistance * 16, [])); //blocks, not chunks >.>
}
public function syncPlayerSpawnPoint(Position $newSpawn) : void{
@ -834,7 +834,7 @@ class NetworkSession{
public function syncAttributes(Living $entity, array $attributes) : void{
if(count($attributes) > 0){
$this->sendDataPacket(UpdateAttributesPacket::create($entity->getId(), array_map(function(Attribute $attr) : NetworkAttribute{
return new NetworkAttribute($attr->getId(), $attr->getMinValue(), $attr->getMaxValue(), $attr->getValue(), $attr->getDefaultValue());
return new NetworkAttribute($attr->getId(), $attr->getMinValue(), $attr->getMaxValue(), $attr->getValue(), $attr->getDefaultValue(), []);
}, $attributes), 0));
}
}

View File

@ -145,6 +145,11 @@ class InGamePacketHandler extends PacketHandler{
/** @var UseItemTransactionData|null */
protected $lastRightClickData = null;
protected ?Vector3 $lastPlayerAuthInputPosition = null;
protected ?float $lastPlayerAuthInputYaw = null;
protected ?float $lastPlayerAuthInputPitch = null;
protected ?int $lastPlayerAuthInputFlags = null;
/** @var bool */
public $forceMoveSync = false;
@ -168,9 +173,10 @@ class InGamePacketHandler extends PacketHandler{
return true;
}
private function resolveOnOffInputFlags(PlayerAuthInputPacket $packet, int $startFlag, int $stopFlag) : ?bool{
$enabled = $packet->hasFlag($startFlag);
if($enabled !== $packet->hasFlag($stopFlag)){
private function resolveOnOffInputFlags(int $inputFlags, int $startFlag, int $stopFlag) : ?bool{
$enabled = ($inputFlags & (1 << $startFlag)) !== 0;
$disabled = ($inputFlags & (1 << $stopFlag)) !== 0;
if($enabled !== $disabled){
return $enabled;
}
//neither flag was set, or both were set
@ -179,51 +185,68 @@ class InGamePacketHandler extends PacketHandler{
public function handlePlayerAuthInput(PlayerAuthInputPacket $packet) : bool{
$rawPos = $packet->getPosition();
foreach([$rawPos->x, $rawPos->y, $rawPos->z, $packet->getYaw(), $packet->getHeadYaw(), $packet->getPitch()] as $float){
$rawYaw = $packet->getYaw();
$rawPitch = $packet->getPitch();
foreach([$rawPos->x, $rawPos->y, $rawPos->z, $rawYaw, $packet->getHeadYaw(), $rawPitch] as $float){
if(is_infinite($float) || is_nan($float)){
$this->session->getLogger()->debug("Invalid movement received, contains NAN/INF components");
return false;
}
}
$yaw = fmod($packet->getYaw(), 360);
$pitch = fmod($packet->getPitch(), 360);
if($yaw < 0){
$yaw += 360;
if($rawYaw !== $this->lastPlayerAuthInputYaw || $rawPitch !== $this->lastPlayerAuthInputPitch){
$this->lastPlayerAuthInputYaw = $rawYaw;
$this->lastPlayerAuthInputPitch = $rawPitch;
$yaw = fmod($rawYaw, 360);
$pitch = fmod($rawPitch, 360);
if($yaw < 0){
$yaw += 360;
}
$this->player->setRotation($yaw, $pitch);
}
$this->player->setRotation($yaw, $pitch);
$curPos = $this->player->getLocation();
$hasMoved = $this->lastPlayerAuthInputPosition === null || !$this->lastPlayerAuthInputPosition->equals($rawPos);
$newPos = $rawPos->round(4)->subtract(0, 1.62, 0);
if($this->forceMoveSync && $newPos->distanceSquared($curPos) > 1){ //Tolerate up to 1 block to avoid problems with client-sided physics when spawning in blocks
$this->session->getLogger()->debug("Got outdated pre-teleport movement, received " . $newPos . ", expected " . $curPos);
//Still getting movements from before teleport, ignore them
return false;
if($this->forceMoveSync && $hasMoved){
$curPos = $this->player->getLocation();
if($newPos->distanceSquared($curPos) > 1){ //Tolerate up to 1 block to avoid problems with client-sided physics when spawning in blocks
$this->session->getLogger()->debug("Got outdated pre-teleport movement, received " . $newPos . ", expected " . $curPos);
//Still getting movements from before teleport, ignore them
return false;
}
// Once we get a movement within a reasonable distance, treat it as a teleport ACK and remove position lock
$this->forceMoveSync = false;
}
// Once we get a movement within a reasonable distance, treat it as a teleport ACK and remove position lock
$this->forceMoveSync = false;
$inputFlags = $packet->getInputFlags();
if($inputFlags !== $this->lastPlayerAuthInputFlags){
$this->lastPlayerAuthInputFlags = $inputFlags;
$sneaking = $this->resolveOnOffInputFlags($packet, PlayerAuthInputFlags::START_SNEAKING, PlayerAuthInputFlags::STOP_SNEAKING);
$sprinting = $this->resolveOnOffInputFlags($packet, PlayerAuthInputFlags::START_SPRINTING, PlayerAuthInputFlags::STOP_SPRINTING);
$swimming = $this->resolveOnOffInputFlags($packet, PlayerAuthInputFlags::START_SWIMMING, PlayerAuthInputFlags::STOP_SWIMMING);
$gliding = $this->resolveOnOffInputFlags($packet, PlayerAuthInputFlags::START_GLIDING, PlayerAuthInputFlags::STOP_GLIDING);
$mismatch =
($sneaking !== null && !$this->player->toggleSneak($sneaking)) |
($sprinting !== null && !$this->player->toggleSprint($sprinting)) |
($swimming !== null && !$this->player->toggleSwim($swimming)) |
($gliding !== null && !$this->player->toggleGlide($gliding));
if((bool) $mismatch){
$this->player->sendData([$this->player]);
$sneaking = $this->resolveOnOffInputFlags($inputFlags, PlayerAuthInputFlags::START_SNEAKING, PlayerAuthInputFlags::STOP_SNEAKING);
$sprinting = $this->resolveOnOffInputFlags($inputFlags, PlayerAuthInputFlags::START_SPRINTING, PlayerAuthInputFlags::STOP_SPRINTING);
$swimming = $this->resolveOnOffInputFlags($inputFlags, PlayerAuthInputFlags::START_SWIMMING, PlayerAuthInputFlags::STOP_SWIMMING);
$gliding = $this->resolveOnOffInputFlags($inputFlags, PlayerAuthInputFlags::START_GLIDING, PlayerAuthInputFlags::STOP_GLIDING);
$mismatch =
($sneaking !== null && !$this->player->toggleSneak($sneaking)) |
($sprinting !== null && !$this->player->toggleSprint($sprinting)) |
($swimming !== null && !$this->player->toggleSwim($swimming)) |
($gliding !== null && !$this->player->toggleGlide($gliding));
if((bool) $mismatch){
$this->player->sendData([$this->player]);
}
if($packet->hasFlag(PlayerAuthInputFlags::START_JUMPING)){
$this->player->jump();
}
}
if($packet->hasFlag(PlayerAuthInputFlags::START_JUMPING)){
$this->player->jump();
}
if(!$this->forceMoveSync){
if(!$this->forceMoveSync && $hasMoved){
$this->lastPlayerAuthInputPosition = $rawPos;
//TODO: this packet has WAYYYYY more useful information that we're not using
$this->player->handleMovement($newPos);
}
@ -867,7 +890,14 @@ class InGamePacketHandler extends PacketHandler{
}
public function handleModalFormResponse(ModalFormResponsePacket $packet) : bool{
return $this->player->onFormSubmit($packet->formId, self::stupid_json_decode($packet->formData, true));
if($packet->cancelReason !== null){
//TODO: make APIs for this to allow plugins to use this information
return $this->player->onFormSubmit($packet->formId, null);
}elseif($packet->formData !== null){
return $this->player->onFormSubmit($packet->formId, self::stupid_json_decode($packet->formData, true));
}else{
throw new PacketHandlingException("Expected either formData or cancelReason to be set in ModalFormResponsePacket");
}
}
/**

View File

@ -98,9 +98,10 @@ class PreSpawnPacketHandler extends PacketHandler{
false,
sprintf("%s %s", VersionInfo::NAME, VersionInfo::VERSION()->getFullVersion(true)),
Uuid::fromString(Uuid::NIL),
false,
[],
0,
GlobalItemTypeDictionary::getInstance()->getDictionary()->getEntries()
GlobalItemTypeDictionary::getInstance()->getDictionary()->getEntries(),
));
$this->session->sendDataPacket(StaticPacketCache::getInstance()->getAvailableActorIdentifiers());

View File

@ -1180,7 +1180,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
return;
}
$oldPos = $this->getLocation();
$oldPos = $this->location;
$distanceSquared = $newPos->distanceSquared($oldPos);
$revert = false;
@ -1198,7 +1198,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
* asking for help if you suffer the consequences of messing with this.
*/
$this->logger->debug("Moved too fast, reverting movement");
$this->logger->debug("Old position: " . $this->location->asVector3() . ", new position: " . $newPos);
$this->logger->debug("Old position: " . $oldPos->asVector3() . ", new position: " . $newPos);
$revert = true;
}elseif(!$this->getWorld()->isInLoadedTerrain($newPos)){
$revert = true;
@ -1206,9 +1206,9 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
}
if(!$revert && $distanceSquared != 0){
$dx = $newPos->x - $this->location->x;
$dy = $newPos->y - $this->location->y;
$dz = $newPos->z - $this->location->z;
$dx = $newPos->x - $oldPos->x;
$dy = $newPos->y - $oldPos->y;
$dz = $newPos->z - $oldPos->z;
$this->move($dx, $dy, $dz);
}

View File

@ -38,6 +38,7 @@ class ReversePriorityQueue extends \SplPriorityQueue{
*
* @return int
*/
#[\ReturnTypeWillChange]
public function compare($priority1, $priority2){
//TODO: this will crash if non-numeric priorities are used
return (int) -($priority1 - $priority2);

View File

@ -23,25 +23,20 @@ declare(strict_types=1);
namespace pocketmine\world\particle;
use pocketmine\block\VanillaBlocks;
use pocketmine\entity\Entity;
use pocketmine\entity\Skin;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\convert\SkinAdapterSingleton;
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\PlayerListPacket;
use pocketmine\network\mcpe\convert\RuntimeBlockMapping;
use pocketmine\network\mcpe\protocol\AddActorPacket;
use pocketmine\network\mcpe\protocol\RemoveActorPacket;
use pocketmine\network\mcpe\protocol\types\DeviceOS;
use pocketmine\network\mcpe\protocol\types\entity\ByteMetadataProperty;
use pocketmine\network\mcpe\protocol\types\entity\EntityIds;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
use pocketmine\network\mcpe\protocol\types\entity\FloatMetadataProperty;
use pocketmine\network\mcpe\protocol\types\entity\IntMetadataProperty;
use pocketmine\network\mcpe\protocol\types\entity\LongMetadataProperty;
use pocketmine\network\mcpe\protocol\types\GameMode;
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
use pocketmine\network\mcpe\protocol\types\inventory\ItemStackWrapper;
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
use pocketmine\network\mcpe\protocol\UpdateAbilitiesPacket;
use Ramsey\Uuid\Uuid;
use function str_repeat;
use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty;
class FloatingTextParticle implements Particle{
//TODO: HACK!
@ -94,38 +89,34 @@ class FloatingTextParticle implements Particle{
}
if(!$this->invisible){
$uuid = Uuid::uuid4();
$name = $this->title . ($this->text !== "" ? "\n" . $this->text : "");
$p[] = PlayerListPacket::add([PlayerListEntry::createAdditionEntry($uuid, $this->entityId, $name, SkinAdapterSingleton::get()->toSkinData(new Skin("Standard_Custom", str_repeat("\x00", 8192))))]);
$actorFlags = (
1 << EntityMetadataFlags::IMMOBILE
);
$actorMetadata = [
EntityMetadataProperties::FLAGS => new LongMetadataProperty($actorFlags),
EntityMetadataProperties::SCALE => new FloatMetadataProperty(0.01) //zero causes problems on debug builds
EntityMetadataProperties::SCALE => new FloatMetadataProperty(0.01), //zero causes problems on debug builds
EntityMetadataProperties::BOUNDING_BOX_WIDTH => new FloatMetadataProperty(0.0),
EntityMetadataProperties::BOUNDING_BOX_HEIGHT => new FloatMetadataProperty(0.0),
EntityMetadataProperties::NAMETAG => new StringMetadataProperty($name),
EntityMetadataProperties::VARIANT => new IntMetadataProperty(RuntimeBlockMapping::getInstance()->toRuntimeId(VanillaBlocks::AIR()->getFullId())),
EntityMetadataProperties::ALWAYS_SHOW_NAMETAG => new ByteMetadataProperty(1),
];
$p[] = AddPlayerPacket::create(
$uuid,
$name,
$p[] = AddActorPacket::create(
$this->entityId, //TODO: actor unique ID
"",
$pos, //TODO: check offset
$this->entityId,
EntityIds::FALLING_BLOCK,
$pos, //TODO: check offset (0.49?)
null,
0,
0,
0,
ItemStackWrapper::legacy(ItemStack::null()),
GameMode::SURVIVAL,
$actorMetadata,
UpdateAbilitiesPacket::create(0, 0, $this->entityId, []),
0,
[],
"",
DeviceOS::UNKNOWN
$actorMetadata,
[]
);
$p[] = PlayerListPacket::remove([PlayerListEntry::createRemovalEntry($uuid)]);
}
return $p;