mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 03:06:55 +00:00
Compare commits
52 Commits
Author | SHA1 | Date | |
---|---|---|---|
3339225fe8 | |||
df33e179e5 | |||
624a7dff16 | |||
1d314ad4ce | |||
5a98b08ee8 | |||
d9d02d526a | |||
f272986903 | |||
988da8eaab | |||
ea7f706aed | |||
52e3f1e269 | |||
4c9d2a989e | |||
022db5cbe3 | |||
3bbf558883 | |||
1d68d9f71a | |||
f2e8824242 | |||
a0e47b5a64 | |||
f7465f55e7 | |||
741182c55f | |||
2efce35331 | |||
d1dfbd95e2 | |||
1aee5b1ed8 | |||
fefd3e6b29 | |||
9b43be9d9c | |||
ea677154cb | |||
7f2802e75f | |||
f924208881 | |||
6bea2961d9 | |||
ac3a6033b9 | |||
d7e6b01216 | |||
26aee7ff73 | |||
319c8fe32c | |||
ce121ccea9 | |||
7f1a4185b5 | |||
8cc7fb9dd9 | |||
194cb1fb84 | |||
8ea106c091 | |||
a6cb3313b0 | |||
c6374b79b0 | |||
901449b0b1 | |||
4e777572c9 | |||
90a8595a40 | |||
bf71eb448a | |||
2c29d272ad | |||
98aa2b9ff9 | |||
ea33a04d00 | |||
4a94cb85a2 | |||
b7e6854189 | |||
2b8a54f8ff | |||
a5dab0f61e | |||
824f1f24ff | |||
f4f5c3128f | |||
fdd42fd15f |
97
.github/workflows/build-docker-image.yml
vendored
Normal file
97
.github/workflows/build-docker-image.yml
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
name: Update Docker Hub images
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Update Docker Hub images
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Clone pmmp/PocketMine-Docker repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: pmmp/PocketMine-Docker
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Get tag names
|
||||
id: tag-name
|
||||
run: |
|
||||
VERSION=$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{')
|
||||
echo ::set-output name=TAG_NAME::$VERSION
|
||||
echo ::set-output name=MAJOR::$(echo $VERSION | cut -d. -f1)
|
||||
echo ::set-output name=MINOR::$(echo $VERSION | cut -d. -f1-2)
|
||||
|
||||
- name: Download new release information
|
||||
run: curl -f -L ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.tag-name.outputs.TAG_NAME }}/build_info.json -o new_build_info.json
|
||||
|
||||
- name: Detect channel
|
||||
id: channel
|
||||
run: echo ::set-output name=CHANNEL::$(jq -r '.channel' new_build_info.json)
|
||||
|
||||
- name: Get name of Docker repository name
|
||||
id: docker-repo-name
|
||||
run: echo ::set-output name=NAME::$(echo "${GITHUB_REPOSITORY,,}")
|
||||
|
||||
- name: Build image for tag
|
||||
uses: docker/build-push-action@v2.10.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
tags: |
|
||||
${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
# ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
build-args: |
|
||||
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
PMMP_REPO=${{ github.repository }}
|
||||
|
||||
- name: Build image for major tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v2.10.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
tags: |
|
||||
${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MAJOR }}
|
||||
# ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MAJOR }}
|
||||
build-args: |
|
||||
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
PMMP_REPO=${{ github.repository }}
|
||||
|
||||
- name: Build image for minor tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v2.10.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
tags: |
|
||||
${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MINOR }}
|
||||
# ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:${{ steps.tag-name.outputs.MINOR }}
|
||||
build-args: |
|
||||
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
PMMP_REPO=${{ github.repository }}
|
||||
|
||||
- name: Build image for latest tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v2.10.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
tags: |
|
||||
${{ steps.docker-repo-name.outputs.NAME }}:latest
|
||||
# ghcr.io/${{ steps.docker-repo-name.outputs.NAME }}:latest
|
||||
build-args: |
|
||||
PMMP_TAG=${{ steps.tag-name.outputs.TAG_NAME }}
|
||||
PMMP_REPO=${{ github.repository }}
|
10
.github/workflows/main.yml
vendored
10
.github/workflows/main.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.16]
|
||||
php: [8.0.18]
|
||||
|
||||
steps:
|
||||
- name: Build and prepare PHP cache
|
||||
@ -31,7 +31,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.16]
|
||||
php: [8.0.18]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@ -69,7 +69,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.16]
|
||||
php: [8.0.18]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@ -107,7 +107,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.16]
|
||||
php: [8.0.18]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@ -147,7 +147,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image: [ubuntu-20.04]
|
||||
php: [8.0.16]
|
||||
php: [8.0.18]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
Submodule build/php updated: b6bb7114b3...1fae6b8d4a
@ -57,3 +57,65 @@ Released 18th March 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed a crash when handling out-of-bounds meta values on the network.
|
||||
|
||||
# 4.2.5
|
||||
Released 28th March 2022.
|
||||
|
||||
## General
|
||||
- The layout of the human-readable part of crashdumps has been changed in an effort to improve the useful information density. It is hoped that this change will cause more useful information to be provided when people paste crash traces on Discord, since all the most important information is now at the top of the file.
|
||||
- Version, git hash, PHP version and OS have been moved to the top of the crashdump.
|
||||
- Backtrace has been moved above code sample.
|
||||
- Docker images are now built by GitHub Actions (first live test).
|
||||
|
||||
## Technical
|
||||
- The methods of `Inventory` and `BaseInventory` have been rearranged to improve coherency.
|
||||
|
||||
## Fixes
|
||||
### API
|
||||
- Enum members of enums created using `EnumTrait` are now able to have single-character names.
|
||||
- Registry members of registries created using `RegistryTrait` or `CloningRegistryTrait` now have their names checked for invalid characters.
|
||||
- `Entity::__construct()` now uses a guard variable to prevent it from being called multiple times unintentionally. This is necessary because `Entity::__construct()` has side effects.
|
||||
- Fixed `PlayerItemHeldEvent` not being called when the content of the held slot was changed (e.g. replacing the held item via inventory menu).
|
||||
|
||||
### Gameplay
|
||||
- Reduced the appearance of ghost items in unsupported gameplay scenarios using client prediction information. This fixes, for example, the appearance of ghost items when right-clicking on a filled flower pot.
|
||||
|
||||
# 4.2.6
|
||||
Released 1st April 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed buffer length underflow crash in `LoginPacket` handling.
|
||||
|
||||
# 4.2.7
|
||||
Released 15th April 2022.
|
||||
|
||||
## General
|
||||
- Added lots more documentation (in comments) about the `aliases` section in `pocketmine.yml`. You can read about this feature in the `aliases` section of the [updated `pocketmine.yml` template](/resources/pocketmine.yml).
|
||||
- Improved wording of documentation of `PlayerPreLoginEvent`.
|
||||
|
||||
## Fixes
|
||||
- Fixed core server crash when a plugin causes another plugin to be disabled during a scheduled task.
|
||||
- Fixed core server crash when loading a plugin with an abstract main class.
|
||||
- Fixed ghost items in many interaction situations (most notably, using projectiles while looking at an entity or block).
|
||||
- Implemented a workaround for a client teleport bug which led to player positions not updating properly when using ender pearls.
|
||||
- Fixed buggy movement when teleporting the player during `PlayerToggleSneakEvent`, `PlayerToggleSprintEvent`, `PlayerToggleSwimEvent` and `PlayerToggleGlideEvent`.
|
||||
|
||||
# 4.2.8
|
||||
Released 17th April 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed a memory leak in RakLib which could result in a server crash when players stay online for a long time.
|
||||
- Fixed server crash when attempting to load a corrupted empty resource pack.
|
||||
- Fixed users with the same name with differerently cased letters being able to duplicate items (userdata is matched by case-insensitive name).
|
||||
|
||||
# 4.2.9
|
||||
Released 19th April 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed several potential crashes when deserializing item NBT (due to insufficient validation of input data).
|
||||
|
||||
# 4.2.10
|
||||
Released 20th April 2022.
|
||||
|
||||
## Fixes
|
||||
- Fixed performance issue when chat messages received from the client contain many newlines. This security vulnerability was disclosed publicly necessitating a priority fix.
|
||||
|
@ -35,13 +35,13 @@
|
||||
"fgrosse/phpasn1": "^2.3",
|
||||
"netresearch/jsonmapper": "^4.0",
|
||||
"pocketmine/bedrock-data": "~1.6.0+bedrock-1.18.10",
|
||||
"pocketmine/bedrock-protocol": "~8.0.0+bedrock-1.18.10",
|
||||
"pocketmine/bedrock-protocol": "~8.0.2+bedrock-1.18.10",
|
||||
"pocketmine/binaryutils": "^0.2.1",
|
||||
"pocketmine/callback-validator": "^1.0.2",
|
||||
"pocketmine/classloader": "^0.2.0",
|
||||
"pocketmine/color": "^0.2.0",
|
||||
"pocketmine/errorhandler": "^0.6.0",
|
||||
"pocketmine/locale-data": "~2.4.2",
|
||||
"pocketmine/locale-data": "~2.5.0",
|
||||
"pocketmine/log": "^0.4.0",
|
||||
"pocketmine/log-pthreads": "^0.4.0",
|
||||
"pocketmine/math": "^0.4.0",
|
||||
@ -53,8 +53,8 @@
|
||||
"webmozart/path-util": "^2.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.4.10",
|
||||
"phpstan/phpstan-phpunit": "^1.0.0",
|
||||
"phpstan/phpstan": "1.5.6",
|
||||
"phpstan/phpstan-phpunit": "^1.1.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.0.0",
|
||||
"phpunit/phpunit": "^9.2"
|
||||
},
|
||||
|
216
composer.lock
generated
216
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": "f3800582ad388d0ec2a95dffc3742d8e",
|
||||
"content-hash": "b20ae069f5f467084bcbaae90c893bc9",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -275,16 +275,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-protocol",
|
||||
"version": "8.0.1+bedrock-1.18.10",
|
||||
"version": "8.0.2+bedrock-1.18.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockProtocol.git",
|
||||
"reference": "a740f6095b35278c0e0dac6db84a5e4d2456b113"
|
||||
"reference": "d1f1afdbb4ea61ea52eb511a79ee1ca561da349c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/a740f6095b35278c0e0dac6db84a5e4d2456b113",
|
||||
"reference": "a740f6095b35278c0e0dac6db84a5e4d2456b113",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/d1f1afdbb4ea61ea52eb511a79ee1ca561da349c",
|
||||
"reference": "d1f1afdbb4ea61ea52eb511a79ee1ca561da349c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -298,7 +298,7 @@
|
||||
"ramsey/uuid": "^4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.4.5",
|
||||
"phpstan/phpstan": "1.5.3",
|
||||
"phpstan/phpstan-phpunit": "^1.0.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.0.0",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
@ -316,9 +316,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/8.0.1+bedrock-1.18.10"
|
||||
"source": "https://github.com/pmmp/BedrockProtocol/tree/8.0.2+bedrock-1.18.10"
|
||||
},
|
||||
"time": "2022-02-21T03:31:48+00:00"
|
||||
"time": "2022-04-01T21:55:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
@ -536,16 +536,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/locale-data",
|
||||
"version": "2.4.3",
|
||||
"version": "2.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Language.git",
|
||||
"reference": "4d0b081f1a79407e087968ea76aaf330db6ea2b5"
|
||||
"reference": "df6fc7f2b48850b306c60466a11f7a27bb8fe1de"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Language/zipball/4d0b081f1a79407e087968ea76aaf330db6ea2b5",
|
||||
"reference": "4d0b081f1a79407e087968ea76aaf330db6ea2b5",
|
||||
"url": "https://api.github.com/repos/pmmp/Language/zipball/df6fc7f2b48850b306c60466a11f7a27bb8fe1de",
|
||||
"reference": "df6fc7f2b48850b306c60466a11f7a27bb8fe1de",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -553,9 +553,9 @@
|
||||
"description": "Language resources used by PocketMine-MP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/Language/issues",
|
||||
"source": "https://github.com/pmmp/Language/tree/2.4.3"
|
||||
"source": "https://github.com/pmmp/Language/tree/2.5.0"
|
||||
},
|
||||
"time": "2022-01-25T23:18:24+00:00"
|
||||
"time": "2022-04-01T22:36:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/log",
|
||||
@ -727,16 +727,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/raklib",
|
||||
"version": "0.14.3",
|
||||
"version": "0.14.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/RakLib.git",
|
||||
"reference": "4798576fec0364266dce23b368a7fec5e5de7927"
|
||||
"reference": "1ea8e3b95a1b6bf785dc27d76578657be4185f42"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/4798576fec0364266dce23b368a7fec5e5de7927",
|
||||
"reference": "4798576fec0364266dce23b368a7fec5e5de7927",
|
||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/1ea8e3b95a1b6bf785dc27d76578657be4185f42",
|
||||
"reference": "1ea8e3b95a1b6bf785dc27d76578657be4185f42",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -748,7 +748,7 @@
|
||||
"pocketmine/log": "^0.3.0 || ^0.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.3.3",
|
||||
"phpstan/phpstan": "1.5.4",
|
||||
"phpstan/phpstan-strict-rules": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
@ -764,9 +764,9 @@
|
||||
"description": "A RakNet server implementation written in PHP",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/RakLib/issues",
|
||||
"source": "https://github.com/pmmp/RakLib/tree/0.14.3"
|
||||
"source": "https://github.com/pmmp/RakLib/tree/0.14.4"
|
||||
},
|
||||
"time": "2022-01-10T21:29:48+00:00"
|
||||
"time": "2022-04-17T18:42:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/raklib-ipc",
|
||||
@ -930,25 +930,24 @@
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
"version": "4.2.3",
|
||||
"version": "4.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/uuid.git",
|
||||
"reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df"
|
||||
"reference": "8505afd4fea63b81a85d3b7b53ac3cb8dc347c28"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
|
||||
"reference": "fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df",
|
||||
"url": "https://api.github.com/repos/ramsey/uuid/zipball/8505afd4fea63b81a85d3b7b53ac3cb8dc347c28",
|
||||
"reference": "8505afd4fea63b81a85d3b7b53ac3cb8dc347c28",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"brick/math": "^0.8 || ^0.9",
|
||||
"ext-ctype": "*",
|
||||
"ext-json": "*",
|
||||
"php": "^7.2 || ^8.0",
|
||||
"ramsey/collection": "^1.0",
|
||||
"symfony/polyfill-ctype": "^1.8",
|
||||
"symfony/polyfill-php80": "^1.14"
|
||||
"php": "^8.0",
|
||||
"ramsey/collection": "^1.0"
|
||||
},
|
||||
"replace": {
|
||||
"rhumsaa/uuid": "self.version"
|
||||
@ -985,9 +984,6 @@
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "4.x-dev"
|
||||
},
|
||||
"captainhook": {
|
||||
"force-install": true
|
||||
}
|
||||
@ -1012,7 +1008,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ramsey/uuid/issues",
|
||||
"source": "https://github.com/ramsey/uuid/tree/4.2.3"
|
||||
"source": "https://github.com/ramsey/uuid/tree/4.3.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1024,7 +1020,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-09-25T23:10:38+00:00"
|
||||
"time": "2022-03-27T21:42:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
@ -1108,89 +1104,6 @@
|
||||
],
|
||||
"time": "2021-10-20T20:35:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.25.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4407588e0d3f1f52efb65fbe92babe41f37fe50c",
|
||||
"reference": "4407588e0d3f1f52efb65fbe92babe41f37fe50c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.23-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Php80\\": ""
|
||||
},
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ion Bazan",
|
||||
"email": "ion.bazan@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.25.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-04T08:16:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php81",
|
||||
"version": "v1.25.0",
|
||||
@ -1789,16 +1702,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/type-resolver",
|
||||
"version": "1.6.0",
|
||||
"version": "1.6.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/TypeResolver.git",
|
||||
"reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706"
|
||||
"reference": "77a32518733312af16a44300404e945338981de3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/93ebd0014cab80c4ea9f5e297ea48672f1b87706",
|
||||
"reference": "93ebd0014cab80c4ea9f5e297ea48672f1b87706",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3",
|
||||
"reference": "77a32518733312af16a44300404e945338981de3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1833,9 +1746,9 @@
|
||||
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
|
||||
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.0"
|
||||
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1"
|
||||
},
|
||||
"time": "2022-01-04T19:58:01+00:00"
|
||||
"time": "2022-03-15T21:29:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
@ -1906,20 +1819,20 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.4.10",
|
||||
"version": "1.5.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "898c479c39caa727bedf4311dd294a8f4e250e72"
|
||||
"reference": "799dd8c2d2c9c704bb55d2078078cb970cf0f6d1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/898c479c39caa727bedf4311dd294a8f4e250e72",
|
||||
"reference": "898c479c39caa727bedf4311dd294a8f4e250e72",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/799dd8c2d2c9c704bb55d2078078cb970cf0f6d1",
|
||||
"reference": "799dd8c2d2c9c704bb55d2078078cb970cf0f6d1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1|^8.0"
|
||||
"php": "^7.2|^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan-shim": "*"
|
||||
@ -1941,7 +1854,7 @@
|
||||
"description": "PHPStan - PHP Static Analysis Tool",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||
"source": "https://github.com/phpstan/phpstan/tree/1.4.10"
|
||||
"source": "https://github.com/phpstan/phpstan/tree/1.5.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1961,25 +1874,25 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-14T10:25:45+00:00"
|
||||
"time": "2022-04-15T11:13:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-phpunit",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-phpunit.git",
|
||||
"reference": "9eb88c9f689003a8a2a5ae9e010338ee94dc39b3"
|
||||
"reference": "09133ce914f1388a8bb8c7f8573aaa3723cff52a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/9eb88c9f689003a8a2a5ae9e010338ee94dc39b3",
|
||||
"reference": "9eb88c9f689003a8a2a5ae9e010338ee94dc39b3",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/09133ce914f1388a8bb8c7f8573aaa3723cff52a",
|
||||
"reference": "09133ce914f1388a8bb8c7f8573aaa3723cff52a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0",
|
||||
"phpstan/phpstan": "^1.0"
|
||||
"php": "^7.2 || ^8.0",
|
||||
"phpstan/phpstan": "^1.5.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpunit/phpunit": "<7.0"
|
||||
@ -1992,9 +1905,6 @@
|
||||
},
|
||||
"type": "phpstan-extension",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
},
|
||||
"phpstan": {
|
||||
"includes": [
|
||||
"extension.neon",
|
||||
@ -2014,9 +1924,9 @@
|
||||
"description": "PHPUnit extensions and rules for PHPStan",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-phpunit/tree/1.0.0"
|
||||
"source": "https://github.com/phpstan/phpstan-phpunit/tree/1.1.0"
|
||||
},
|
||||
"time": "2021-10-14T08:03:54+00:00"
|
||||
"time": "2022-03-28T09:20:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-strict-rules",
|
||||
@ -2389,16 +2299,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.5.19",
|
||||
"version": "9.5.20",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "35ea4b7f3acabb26f4bb640f8c30866c401da807"
|
||||
"reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/35ea4b7f3acabb26f4bb640f8c30866c401da807",
|
||||
"reference": "35ea4b7f3acabb26f4bb640f8c30866c401da807",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/12bc8879fb65aef2138b26fc633cb1e3620cffba",
|
||||
"reference": "12bc8879fb65aef2138b26fc633cb1e3620cffba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2476,7 +2386,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.19"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.20"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2488,7 +2398,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-03-15T09:57:31+00:00"
|
||||
"time": "2022-04-01T12:37:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
@ -2856,16 +2766,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/environment",
|
||||
"version": "5.1.3",
|
||||
"version": "5.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/environment.git",
|
||||
"reference": "388b6ced16caa751030f6a69e588299fa09200ac"
|
||||
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac",
|
||||
"reference": "388b6ced16caa751030f6a69e588299fa09200ac",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
|
||||
"reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2907,7 +2817,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/environment/issues",
|
||||
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.3"
|
||||
"source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2915,7 +2825,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-09-28T05:52:38+00:00"
|
||||
"time": "2022-04-03T09:37:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
|
@ -173,10 +173,31 @@ console:
|
||||
title-tick: true
|
||||
|
||||
aliases:
|
||||
#Examples:
|
||||
#showtheversion: version
|
||||
##This section allows you to add, remove or remap command aliases.
|
||||
##A single alias can call one or more other commands (or aliases).
|
||||
##Aliases defined here will override any command aliases declared by plugins or PocketMine-MP itself.
|
||||
|
||||
##To remove an alias, set it to [], like so (note that prefixed aliases like "pocketmine:stop" will remain and can't
|
||||
##be removed):
|
||||
#stop: []
|
||||
|
||||
##Commands are not removed, only their aliases. You can still refer to a command using its full (prefixed)
|
||||
##name, even if all its aliases are overwritten. The full name is usually something like "pocketmine:commandname" or
|
||||
##"pluginname:commandname".
|
||||
#abort: [pocketmine:stop]
|
||||
|
||||
##To add an alias, list the command(s) that it calls:
|
||||
#showtheversion: [version]
|
||||
#savestop: [save-all, stop]
|
||||
|
||||
##To invoke another command with arguments, use $1 to pass the first argument, $2 for the second etc:
|
||||
#giveadmin: [op $1] ## `giveadmin alex` -> `op alex`
|
||||
#kill: [suicide, say "I tried to kill $1"] ## `kill alex` -> `suicide` + `say "I tried to kill alex"`
|
||||
#giverandom: [give $1 $2, say "Someone has just received a $2!"] ## `giverandom alex diamond` -> `give alex diamond` + `say "Someone has just received a diamond!"`
|
||||
|
||||
##To change an existing command alias and make it do something else:
|
||||
#tp: [suicide]
|
||||
|
||||
worlds:
|
||||
#These settings will override the generator set in server.properties and allows loading multiple worlds
|
||||
#Example:
|
||||
|
@ -132,6 +132,7 @@ use function get_class;
|
||||
use function ini_set;
|
||||
use function is_array;
|
||||
use function is_dir;
|
||||
use function is_object;
|
||||
use function is_resource;
|
||||
use function is_string;
|
||||
use function json_decode;
|
||||
@ -1606,7 +1607,7 @@ class Server{
|
||||
"reportPaste" => base64_encode($dump->getEncodedData())
|
||||
], 10, [], $postUrlError);
|
||||
|
||||
if($reply !== null && ($data = json_decode($reply->getBody())) !== null){
|
||||
if($reply !== null && is_object($data = json_decode($reply->getBody()))){
|
||||
if(isset($data->crashId) && isset($data->crashUrl)){
|
||||
$reportId = $data->crashId;
|
||||
$reportUrl = $data->crashUrl;
|
||||
|
@ -31,7 +31,7 @@ use function str_repeat;
|
||||
|
||||
final class VersionInfo{
|
||||
public const NAME = "PocketMine-MP";
|
||||
public const BASE_VERSION = "4.2.4";
|
||||
public const BASE_VERSION = "4.2.10";
|
||||
public const IS_DEVELOPMENT_BUILD = false;
|
||||
public const BUILD_CHANNEL = "stable";
|
||||
|
||||
|
@ -44,7 +44,7 @@ trait ContainerTrait{
|
||||
abstract public function getRealInventory();
|
||||
|
||||
protected function loadItems(CompoundTag $tag) : void{
|
||||
if(($inventoryTag = $tag->getTag(Container::TAG_ITEMS)) instanceof ListTag){
|
||||
if(($inventoryTag = $tag->getTag(Container::TAG_ITEMS)) instanceof ListTag && $inventoryTag->getTagType() === NBT::TAG_Compound){
|
||||
$inventory = $this->getRealInventory();
|
||||
$listeners = $inventory->getListeners()->toArray();
|
||||
$inventory->getListeners()->remove(...$listeners); //prevent any events being fired by initialization
|
||||
|
@ -44,10 +44,11 @@ final class CrashDumpRenderer{
|
||||
$this->addLine($this->data->general->name . " Crash Dump " . date("D M j H:i:s T Y", (int) $this->data->time));
|
||||
$this->addLine();
|
||||
|
||||
$this->addLine("Error: " . $this->data->error["message"]);
|
||||
$this->addLine("File: " . $this->data->error["file"]);
|
||||
$this->addLine("Line: " . $this->data->error["line"]);
|
||||
$this->addLine("Type: " . $this->data->error["type"]);
|
||||
$version = new VersionString($this->data->general->base_version, $this->data->general->is_dev, $this->data->general->build);
|
||||
$this->addLine($this->data->general->name . " version: " . $version->getFullVersion(true) . " [Protocol " . $this->data->general->protocol . "]");
|
||||
$this->addLine("Git commit: " . $this->data->general->git);
|
||||
$this->addLine("PHP version: " . $this->data->general->php);
|
||||
$this->addLine("OS: " . $this->data->general->php_os . ", " . $this->data->general->os);
|
||||
|
||||
if($this->data->plugin_involvement !== CrashDump::PLUGIN_INVOLVEMENT_NONE){
|
||||
$this->addLine();
|
||||
@ -62,30 +63,21 @@ final class CrashDumpRenderer{
|
||||
}
|
||||
|
||||
$this->addLine();
|
||||
$this->addLine("Code:");
|
||||
|
||||
foreach($this->data->code as $lineNumber => $line){
|
||||
$this->addLine("[$lineNumber] $line");
|
||||
}
|
||||
|
||||
$this->addLine();
|
||||
$this->addLine("Error: " . $this->data->error["message"]);
|
||||
$this->addLine("File: " . $this->data->error["file"]);
|
||||
$this->addLine("Line: " . $this->data->error["line"]);
|
||||
$this->addLine("Type: " . $this->data->error["type"]);
|
||||
$this->addLine("Backtrace:");
|
||||
foreach($this->data->trace as $line){
|
||||
$this->addLine($line);
|
||||
}
|
||||
|
||||
$this->addLine();
|
||||
$this->addLine("Code:");
|
||||
|
||||
$version = new VersionString($this->data->general->base_version, $this->data->general->is_dev, $this->data->general->build);
|
||||
|
||||
$this->addLine($this->data->general->name . " version: " . $version->getFullVersion(true) . " [Protocol " . $this->data->general->protocol . "]");
|
||||
$this->addLine("Git commit: " . $this->data->general->git);
|
||||
$this->addLine("uname -a: " . $this->data->general->uname);
|
||||
$this->addLine("PHP Version: " . $this->data->general->php);
|
||||
$this->addLine("Zend version: " . $this->data->general->zend);
|
||||
$this->addLine("OS: " . $this->data->general->php_os . ", " . $this->data->general->os);
|
||||
$this->addLine("Composer libraries: ");
|
||||
foreach(Utils::stringifyKeys($this->data->general->composer_libraries) as $library => $libraryVersion){
|
||||
$this->addLine("- $library $libraryVersion");
|
||||
foreach($this->data->code as $lineNumber => $line){
|
||||
$this->addLine("[$lineNumber] $line");
|
||||
}
|
||||
|
||||
if(count($this->data->plugins) > 0){
|
||||
@ -95,6 +87,14 @@ final class CrashDumpRenderer{
|
||||
$this->addLine($p->name . " " . $p->version . " by " . implode(", ", $p->authors) . " for API(s) " . implode(", ", $p->api));
|
||||
}
|
||||
}
|
||||
|
||||
$this->addLine();
|
||||
$this->addLine("uname -a: " . $this->data->general->uname);
|
||||
$this->addLine("Zend version: " . $this->data->general->zend);
|
||||
$this->addLine("Composer libraries: ");
|
||||
foreach(Utils::stringifyKeys($this->data->general->composer_libraries) as $library => $libraryVersion){
|
||||
$this->addLine("- $library $libraryVersion");
|
||||
}
|
||||
}
|
||||
|
||||
public function addLine(string $line = "") : void{
|
||||
|
@ -216,7 +216,13 @@ abstract class Entity{
|
||||
/** @var int|null */
|
||||
protected $targetId = null;
|
||||
|
||||
private bool $constructorCalled = false;
|
||||
|
||||
public function __construct(Location $location, ?CompoundTag $nbt = null){
|
||||
if($this->constructorCalled){
|
||||
throw new \LogicException("Attempted to call constructor for an Entity multiple times");
|
||||
}
|
||||
$this->constructorCalled = true;
|
||||
Utils::checkLocationNotInfOrNaN($location);
|
||||
|
||||
$this->timings = Timings::getEntityTimings($this);
|
||||
@ -762,17 +768,29 @@ abstract class Entity{
|
||||
}
|
||||
|
||||
protected function broadcastMovement(bool $teleport = false) : void{
|
||||
$this->server->broadcastPackets($this->hasSpawned, [MoveActorAbsolutePacket::create(
|
||||
$this->id,
|
||||
$this->getOffsetPosition($this->location),
|
||||
$this->location->pitch,
|
||||
$this->location->yaw,
|
||||
$this->location->yaw,
|
||||
(
|
||||
($teleport ? MoveActorAbsolutePacket::FLAG_TELEPORT : 0) |
|
||||
($this->onGround ? MoveActorAbsolutePacket::FLAG_GROUND : 0)
|
||||
)
|
||||
)]);
|
||||
if($teleport){
|
||||
//TODO: HACK! workaround for https://github.com/pmmp/PocketMine-MP/issues/4394
|
||||
//this happens because MoveActor*Packet doesn't clear interpolation targets on the client, so the entity
|
||||
//snaps to the teleport position, but then lerps back to the original position if a normal movement for the
|
||||
//entity was recently broadcasted. This can be seen with players throwing ender pearls.
|
||||
//TODO: remove this if the bug ever gets fixed (lol)
|
||||
foreach($this->hasSpawned as $player){
|
||||
$this->despawnFrom($player);
|
||||
$this->spawnTo($player);
|
||||
}
|
||||
}else{
|
||||
$this->server->broadcastPackets($this->hasSpawned, [MoveActorAbsolutePacket::create(
|
||||
$this->id,
|
||||
$this->getOffsetPosition($this->location),
|
||||
$this->location->pitch,
|
||||
$this->location->yaw,
|
||||
$this->location->yaw,
|
||||
(
|
||||
//TODO: if the above hack for #4394 gets removed, we should be setting FLAG_TELEPORT here
|
||||
($this->onGround ? MoveActorAbsolutePacket::FLAG_GROUND : 0)
|
||||
)
|
||||
)]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function broadcastMotion() : void{
|
||||
|
@ -31,7 +31,7 @@ use function count;
|
||||
|
||||
/**
|
||||
* Called when a player connects to the server, prior to authentication taking place.
|
||||
* Cancelling this event will cause the player to be disconnected with the kick message set.
|
||||
* Set a kick reason to cancel the event and disconnect the player with the kick message set.
|
||||
*
|
||||
* This event should be used to decide if the player may continue to login to the server. Do things like checking
|
||||
* bans, whitelisting, server-full etc here.
|
||||
|
@ -55,6 +55,25 @@ abstract class BaseInventory implements Inventory{
|
||||
return $this->maxStackSize;
|
||||
}
|
||||
|
||||
public function setMaxStackSize(int $size) : void{
|
||||
$this->maxStackSize = $size;
|
||||
}
|
||||
|
||||
abstract protected function internalSetItem(int $index, Item $item) : void;
|
||||
|
||||
public function setItem(int $index, Item $item) : void{
|
||||
if($item->isNull()){
|
||||
$item = VanillaItems::AIR();
|
||||
}else{
|
||||
$item = clone $item;
|
||||
}
|
||||
|
||||
$oldItem = $this->getItem($index);
|
||||
|
||||
$this->internalSetItem($index, $item);
|
||||
$this->onSlotChange($index, $oldItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Item[] $items
|
||||
*/
|
||||
@ -85,21 +104,6 @@ abstract class BaseInventory implements Inventory{
|
||||
$this->onContentChange($oldContents);
|
||||
}
|
||||
|
||||
abstract protected function internalSetItem(int $index, Item $item) : void;
|
||||
|
||||
public function setItem(int $index, Item $item) : void{
|
||||
if($item->isNull()){
|
||||
$item = VanillaItems::AIR();
|
||||
}else{
|
||||
$item = clone $item;
|
||||
}
|
||||
|
||||
$oldItem = $this->getItem($index);
|
||||
|
||||
$this->internalSetItem($index, $item);
|
||||
$this->onSlotChange($index, $oldItem);
|
||||
}
|
||||
|
||||
public function contains(Item $item) : bool{
|
||||
$count = max(1, $item->getCount());
|
||||
$checkDamage = !$item->hasAnyDamageValue();
|
||||
@ -128,18 +132,6 @@ abstract class BaseInventory implements Inventory{
|
||||
|
||||
return $slots;
|
||||
}
|
||||
|
||||
public function remove(Item $item) : void{
|
||||
$checkDamage = !$item->hasAnyDamageValue();
|
||||
$checkTags = $item->hasNamedTag();
|
||||
|
||||
foreach($this->getContents() as $index => $i){
|
||||
if($item->equals($i, $checkDamage, $checkTags)){
|
||||
$this->clear($index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function first(Item $item, bool $exact = false) : int{
|
||||
$count = $exact ? $item->getCount() : max(1, $item->getCount());
|
||||
$checkDamage = $exact || !$item->hasAnyDamageValue();
|
||||
@ -253,6 +245,17 @@ abstract class BaseInventory implements Inventory{
|
||||
return $slot;
|
||||
}
|
||||
|
||||
public function remove(Item $item) : void{
|
||||
$checkDamage = !$item->hasAnyDamageValue();
|
||||
$checkTags = $item->hasNamedTag();
|
||||
|
||||
foreach($this->getContents() as $index => $i){
|
||||
if($item->equals($i, $checkDamage, $checkTags)){
|
||||
$this->clear($index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function removeItem(Item ...$slots) : array{
|
||||
/** @var Item[] $itemSlots */
|
||||
/** @var Item[] $slots */
|
||||
@ -323,10 +326,6 @@ abstract class BaseInventory implements Inventory{
|
||||
}
|
||||
}
|
||||
|
||||
public function setMaxStackSize(int $size) : void{
|
||||
$this->maxStackSize = $size;
|
||||
}
|
||||
|
||||
public function onOpen(Player $who) : void{
|
||||
$this->viewers[spl_object_id($who)] = $who;
|
||||
}
|
||||
|
@ -46,6 +46,16 @@ interface Inventory{
|
||||
*/
|
||||
public function setItem(int $index, Item $item) : void;
|
||||
|
||||
/**
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getContents(bool $includeEmpty = false) : array;
|
||||
|
||||
/**
|
||||
* @param Item[] $items
|
||||
*/
|
||||
public function setContents(array $items) : void;
|
||||
|
||||
/**
|
||||
* Stores the given Items in the inventory. This will try to fill
|
||||
* existing stacks and empty slots as well as it can.
|
||||
@ -66,24 +76,6 @@ interface Inventory{
|
||||
*/
|
||||
public function getAddableItemQuantity(Item $item) : int;
|
||||
|
||||
/**
|
||||
* Removes the given Item from the inventory.
|
||||
* It will return the Items that couldn't be removed.
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function removeItem(Item ...$slots) : array;
|
||||
|
||||
/**
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getContents(bool $includeEmpty = false) : array;
|
||||
|
||||
/**
|
||||
* @param Item[] $items
|
||||
*/
|
||||
public function setContents(array $items) : void;
|
||||
|
||||
/**
|
||||
* Checks if the inventory contains any Item with the same material data.
|
||||
* It will check id, amount, and metadata (if not null)
|
||||
@ -121,6 +113,14 @@ interface Inventory{
|
||||
*/
|
||||
public function remove(Item $item) : void;
|
||||
|
||||
/**
|
||||
* Removes the given Item from the inventory.
|
||||
* It will return the Items that couldn't be removed.
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function removeItem(Item ...$slots) : array;
|
||||
|
||||
/**
|
||||
* Will clear a specific slot
|
||||
*/
|
||||
|
@ -52,6 +52,10 @@ class SimpleInventory extends BaseInventory{
|
||||
return $this->slots[$index] !== null ? clone $this->slots[$index] : VanillaItems::AIR();
|
||||
}
|
||||
|
||||
protected function internalSetItem(int $index, Item $item) : void{
|
||||
$this->slots[$index] = $item->isNull() ? null : $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Item[]
|
||||
*/
|
||||
@ -78,8 +82,4 @@ class SimpleInventory extends BaseInventory{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function internalSetItem(int $index, Item $item) : void{
|
||||
$this->slots[$index] = $item->isNull() ? null : $item;
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ use pocketmine\block\utils\BannerPatternLayer;
|
||||
use pocketmine\block\utils\DyeColor;
|
||||
use pocketmine\data\bedrock\BannerPatternTypeIdMap;
|
||||
use pocketmine\data\bedrock\DyeColorIdMap;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\nbt\tag\ListTag;
|
||||
use function count;
|
||||
@ -98,7 +99,7 @@ class Banner extends ItemBlockWallOrFloor{
|
||||
$colorIdMap = DyeColorIdMap::getInstance();
|
||||
$patternIdMap = BannerPatternTypeIdMap::getInstance();
|
||||
$patterns = $tag->getListTag(self::TAG_PATTERNS);
|
||||
if($patterns !== null){
|
||||
if($patterns !== null && $patterns->getTagType() === NBT::TAG_Compound){
|
||||
/** @var CompoundTag $t */
|
||||
foreach($patterns as $t){
|
||||
$patternColor = $colorIdMap->fromInvertedId($t->getInt(self::TAG_PATTERN_COLOR)) ?? DyeColor::BLACK(); //TODO: missing pattern colour should be an error
|
||||
|
@ -306,7 +306,7 @@ class Item implements \JsonSerializable{
|
||||
|
||||
$this->canPlaceOn = [];
|
||||
$canPlaceOn = $tag->getListTag("CanPlaceOn");
|
||||
if($canPlaceOn !== null){
|
||||
if($canPlaceOn !== null && $canPlaceOn->getTagType() === NBT::TAG_String){
|
||||
/** @var StringTag $entry */
|
||||
foreach($canPlaceOn as $entry){
|
||||
$this->canPlaceOn[$entry->getValue()] = $entry->getValue();
|
||||
@ -314,7 +314,7 @@ class Item implements \JsonSerializable{
|
||||
}
|
||||
$this->canDestroy = [];
|
||||
$canDestroy = $tag->getListTag("CanDestroy");
|
||||
if($canDestroy !== null){
|
||||
if($canDestroy !== null && $canDestroy->getTagType() === NBT::TAG_String){
|
||||
/** @var StringTag $entry */
|
||||
foreach($canDestroy as $entry){
|
||||
$this->canDestroy[$entry->getValue()] = $entry->getValue();
|
||||
|
@ -1829,6 +1829,10 @@ final class KnownTranslationFactory{
|
||||
]);
|
||||
}
|
||||
|
||||
public static function pocketmine_plugin_mainClassAbstract() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::POCKETMINE_PLUGIN_MAINCLASSABSTRACT, []);
|
||||
}
|
||||
|
||||
public static function pocketmine_plugin_mainClassNotFound() : Translatable{
|
||||
return new Translatable(KnownTranslationKeys::POCKETMINE_PLUGIN_MAINCLASSNOTFOUND, []);
|
||||
}
|
||||
|
@ -379,6 +379,7 @@ final class KnownTranslationKeys{
|
||||
public const POCKETMINE_PLUGIN_INVALIDMANIFEST = "pocketmine.plugin.invalidManifest";
|
||||
public const POCKETMINE_PLUGIN_LOAD = "pocketmine.plugin.load";
|
||||
public const POCKETMINE_PLUGIN_LOADERROR = "pocketmine.plugin.loadError";
|
||||
public const POCKETMINE_PLUGIN_MAINCLASSABSTRACT = "pocketmine.plugin.mainClassAbstract";
|
||||
public const POCKETMINE_PLUGIN_MAINCLASSNOTFOUND = "pocketmine.plugin.mainClassNotFound";
|
||||
public const POCKETMINE_PLUGIN_MAINCLASSWRONGTYPE = "pocketmine.plugin.mainClassWrongType";
|
||||
public const POCKETMINE_PLUGIN_RESTRICTEDNAME = "pocketmine.plugin.restrictedName";
|
||||
|
@ -59,7 +59,9 @@ use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\ObjectSet;
|
||||
use function array_map;
|
||||
use function array_search;
|
||||
use function get_class;
|
||||
use function max;
|
||||
use function spl_object_id;
|
||||
|
||||
/**
|
||||
* @phpstan-type ContainerOpenClosure \Closure(int $id, Inventory $inventory) : (list<ClientboundPacket>|null)
|
||||
@ -304,6 +306,28 @@ class InventoryManager{
|
||||
}
|
||||
}
|
||||
|
||||
public function syncMismatchedPredictedSlotChanges() : void{
|
||||
foreach($this->initiatedSlotChanges as $windowId => $slots){
|
||||
if(!isset($this->windowMap[$windowId])){
|
||||
continue;
|
||||
}
|
||||
$inventory = $this->windowMap[$windowId];
|
||||
|
||||
foreach($slots as $slot => $expectedItem){
|
||||
if(!$inventory->slotExists($slot)){
|
||||
continue; //TODO: size desync ???
|
||||
}
|
||||
$actualItem = $inventory->getItem($slot);
|
||||
if(!$actualItem->equalsExact($expectedItem)){
|
||||
$this->session->getLogger()->debug("Detected prediction mismatch in inventory " . get_class($inventory) . "#" . spl_object_id($inventory) . " slot $slot");
|
||||
$this->syncSlot($inventory, $slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->initiatedSlotChanges = [];
|
||||
}
|
||||
|
||||
public function syncData(Inventory $inventory, int $propertyId, int $value) : void{
|
||||
$windowId = $this->getWindowId($inventory);
|
||||
if($windowId !== null){
|
||||
|
@ -125,6 +125,7 @@ use function get_class;
|
||||
use function in_array;
|
||||
use function json_encode;
|
||||
use function ksort;
|
||||
use function strcasecmp;
|
||||
use function strlen;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
@ -635,7 +636,7 @@ class NetworkSession{
|
||||
continue;
|
||||
}
|
||||
$info = $existingSession->getPlayerInfo();
|
||||
if($info !== null && ($info->getUsername() === $this->info->getUsername() || $info->getUuid()->equals($this->info->getUuid()))){
|
||||
if($info !== null && (strcasecmp($info->getUsername(), $this->info->getUsername()) === 0 || $info->getUuid()->equals($this->info->getUuid()))){
|
||||
if($kickForXUIDMismatch($info instanceof XboxLivePlayerInfo ? $info->getXuid() : "")){
|
||||
return;
|
||||
}
|
||||
|
@ -228,15 +228,21 @@ class InGamePacketHandler extends PacketHandler{
|
||||
$this->player->jump();
|
||||
}
|
||||
|
||||
//TODO: this packet has WAYYYYY more useful information that we're not using
|
||||
$this->player->handleMovement($newPos);
|
||||
if(!$this->forceMoveSync){
|
||||
//TODO: this packet has WAYYYYY more useful information that we're not using
|
||||
$this->player->handleMovement($newPos);
|
||||
}
|
||||
|
||||
$packetHandled = true;
|
||||
|
||||
$useItemTransaction = $packet->getItemInteractionData();
|
||||
if($useItemTransaction !== null && !$this->handleUseItemTransaction($useItemTransaction->getTransactionData())){
|
||||
$packetHandled = false;
|
||||
$this->session->getLogger()->debug("Unhandled transaction in PlayerAuthInputPacket (type " . $useItemTransaction->getTransactionData()->getActionType() . ")");
|
||||
if($useItemTransaction !== null){
|
||||
if(!$this->handleUseItemTransaction($useItemTransaction->getTransactionData())){
|
||||
$packetHandled = false;
|
||||
$this->session->getLogger()->debug("Unhandled transaction in PlayerAuthInputPacket (type " . $useItemTransaction->getTransactionData()->getActionType() . ")");
|
||||
}else{
|
||||
$this->inventoryManager->syncMismatchedPredictedSlotChanges();
|
||||
}
|
||||
}
|
||||
|
||||
$blockActions = $packet->getBlockActions();
|
||||
@ -304,6 +310,8 @@ class InGamePacketHandler extends PacketHandler{
|
||||
|
||||
if(!$result){
|
||||
$this->inventoryManager->syncAll();
|
||||
}else{
|
||||
$this->inventoryManager->syncMismatchedPredictedSlotChanges();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
@ -451,13 +459,10 @@ class InGamePacketHandler extends PacketHandler{
|
||||
if(!$this->player->consumeHeldItem()){
|
||||
$hungerAttr = $this->player->getAttributeMap()->get(Attribute::HUNGER) ?? throw new AssumptionFailedError();
|
||||
$hungerAttr->markSynchronized(false);
|
||||
$this->inventoryManager->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if(!$this->player->useHeldItem()){
|
||||
$this->inventoryManager->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
|
||||
}
|
||||
$this->player->useHeldItem();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -477,7 +482,6 @@ class InGamePacketHandler extends PacketHandler{
|
||||
* Internal function used to execute rollbacks when an action fails on a block.
|
||||
*/
|
||||
private function onFailedBlockAction(Vector3 $blockPos, ?int $face) : void{
|
||||
$this->inventoryManager->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
|
||||
if($blockPos->distanceSquared($this->player->getLocation()) < 10000){
|
||||
$blocks = $blockPos->sidesArray();
|
||||
if($face !== null){
|
||||
@ -506,14 +510,10 @@ class InGamePacketHandler extends PacketHandler{
|
||||
//TODO: use transactiondata for rollbacks here
|
||||
switch($data->getActionType()){
|
||||
case UseItemOnEntityTransactionData::ACTION_INTERACT:
|
||||
if(!$this->player->interactEntity($target, $data->getClickPosition())){
|
||||
$this->inventoryManager->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
|
||||
}
|
||||
$this->player->interactEntity($target, $data->getClickPosition());
|
||||
return true;
|
||||
case UseItemOnEntityTransactionData::ACTION_ATTACK:
|
||||
if(!$this->player->attackEntity($target)){
|
||||
$this->inventoryManager->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
|
||||
}
|
||||
$this->player->attackEntity($target);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -313,6 +313,16 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
$this->setNameTag($this->username);
|
||||
}
|
||||
|
||||
private function callDummyItemHeldEvent() : void{
|
||||
$slot = $this->inventory->getHeldItemIndex();
|
||||
|
||||
$event = new PlayerItemHeldEvent($this, $this->inventory->getItem($slot), $slot);
|
||||
$event->call();
|
||||
//TODO: this event is actually cancellable, but cancelling it here has no meaningful result, so we
|
||||
//just ignore it. We fire this only because the content of the held slot changed, not because the
|
||||
//held slot index changed. We can't prevent that from here, and nor would it be sensible to.
|
||||
}
|
||||
|
||||
protected function initEntity(CompoundTag $nbt) : void{
|
||||
parent::initEntity($nbt);
|
||||
$this->addDefaultWindows();
|
||||
@ -321,10 +331,13 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
function(Inventory $unused, int $slot) : void{
|
||||
if($slot === $this->inventory->getHeldItemIndex()){
|
||||
$this->setUsingItem(false);
|
||||
|
||||
$this->callDummyItemHeldEvent();
|
||||
}
|
||||
},
|
||||
function() : void{
|
||||
$this->setUsingItem(false);
|
||||
$this->callDummyItemHeldEvent();
|
||||
}
|
||||
));
|
||||
|
||||
@ -1364,8 +1377,14 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
public function chat(string $message) : bool{
|
||||
$this->removeCurrentWindow();
|
||||
|
||||
//Fast length check, to make sure we don't get hung trying to explode MBs of string ...
|
||||
$maxTotalLength = $this->messageCounter * (self::MAX_CHAT_BYTE_LENGTH + 1);
|
||||
if(strlen($message) > $maxTotalLength){
|
||||
return false;
|
||||
}
|
||||
|
||||
$message = TextFormat::clean($message, false);
|
||||
foreach(explode("\n", $message) as $messagePart){
|
||||
foreach(explode("\n", $message, $this->messageCounter + 1) as $messagePart){
|
||||
if(trim($messagePart) !== "" && strlen($messagePart) <= self::MAX_CHAT_BYTE_LENGTH && mb_strlen($messagePart, 'UTF-8') <= self::MAX_CHAT_CHAR_LENGTH && $this->messageCounter-- > 0){
|
||||
if(strpos($messagePart, './') === 0){
|
||||
$messagePart = substr($messagePart, 1);
|
||||
|
@ -166,6 +166,14 @@ class PluginManager{
|
||||
)));
|
||||
return null;
|
||||
}
|
||||
$reflect = new \ReflectionClass($mainClass); //this shouldn't throw; we already checked that it exists
|
||||
if(!$reflect->isInstantiable()){
|
||||
$this->server->getLogger()->error($language->translate(KnownTranslationFactory::pocketmine_plugin_loadError(
|
||||
$description->getName(),
|
||||
KnownTranslationFactory::pocketmine_plugin_mainClassAbstract()
|
||||
)));
|
||||
return null;
|
||||
}
|
||||
|
||||
$permManager = PermissionManager::getInstance();
|
||||
foreach($description->getPermissions() as $permsGroup){
|
||||
@ -463,8 +471,12 @@ class PluginManager{
|
||||
}
|
||||
|
||||
public function tickSchedulers(int $currentTick) : void{
|
||||
foreach($this->enabledPlugins as $p){
|
||||
$p->getScheduler()->mainThreadHeartbeat($currentTick);
|
||||
foreach($this->enabledPlugins as $pluginName => $p){
|
||||
if(isset($this->enabledPlugins[$pluginName])){
|
||||
//the plugin may have been disabled as a result of updating other plugins' schedulers, and therefore
|
||||
//removed from enabledPlugins; however, foreach will still see it due to copy-on-write
|
||||
$p->getScheduler()->mainThreadHeartbeat($currentTick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,6 +64,13 @@ class ZippedResourcePack implements ResourcePack{
|
||||
if(!file_exists($zipPath)){
|
||||
throw new ResourcePackException("File not found");
|
||||
}
|
||||
$size = filesize($zipPath);
|
||||
if($size === false){
|
||||
throw new ResourcePackException("Unable to determine size of file");
|
||||
}
|
||||
if($size === 0){
|
||||
throw new ResourcePackException("Empty file, probably corrupted");
|
||||
}
|
||||
|
||||
$archive = new \ZipArchive();
|
||||
if(($openResult = $archive->open($zipPath)) !== true){
|
||||
|
@ -64,6 +64,9 @@ class ThreadManager extends \Volatile{
|
||||
*/
|
||||
public function getAll() : array{
|
||||
$array = [];
|
||||
/**
|
||||
* @var Worker|Thread $thread
|
||||
*/
|
||||
foreach($this as $key => $thread){
|
||||
$array[$key] = $thread;
|
||||
}
|
||||
|
@ -23,8 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\utils;
|
||||
|
||||
use function preg_match;
|
||||
|
||||
trait EnumTrait{
|
||||
use RegistryTrait;
|
||||
use NotCloneable;
|
||||
@ -70,9 +68,7 @@ trait EnumTrait{
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function __construct(string $enumName){
|
||||
if(preg_match('/^\D[A-Za-z\d_]+$/u', $enumName, $matches) === 0){
|
||||
throw new \InvalidArgumentException("Invalid enum member name \"$enumName\", should only contain letters, numbers and underscores, and must not start with a number");
|
||||
}
|
||||
self::verifyName($enumName);
|
||||
$this->enumName = $enumName;
|
||||
if(self::$nextId === null){
|
||||
self::$nextId = Process::pid(); //this provides enough base entropy to prevent hardcoding
|
||||
|
@ -32,7 +32,6 @@ use function curl_getinfo;
|
||||
use function curl_init;
|
||||
use function curl_setopt_array;
|
||||
use function explode;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
use function preg_match;
|
||||
use function socket_close;
|
||||
@ -220,7 +219,6 @@ class Internet{
|
||||
}
|
||||
if(!is_string($raw)) throw new AssumptionFailedError("curl_exec() should return string|false when CURLOPT_RETURNTRANSFER is set");
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
if(!is_int($httpCode)) throw new AssumptionFailedError("curl_getinfo(CURLINFO_HTTP_CODE) always returns int");
|
||||
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||
$rawHeaders = substr($raw, 0, $headerSize);
|
||||
$body = substr($raw, $headerSize);
|
||||
|
@ -26,17 +26,25 @@ namespace pocketmine\utils;
|
||||
use function array_map;
|
||||
use function count;
|
||||
use function mb_strtoupper;
|
||||
use function preg_match;
|
||||
|
||||
trait RegistryTrait{
|
||||
/** @var object[] */
|
||||
private static $members = null;
|
||||
|
||||
private static function verifyName(string $name) : void{
|
||||
if(preg_match('/^(?!\d)[A-Za-z\d_]+$/u', $name) === 0){
|
||||
throw new \InvalidArgumentException("Invalid member name \"$name\", should only contain letters, numbers and underscores, and must not start with a number");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given object to the registry.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private static function _registryRegister(string $name, object $member) : void{
|
||||
self::verifyName($name);
|
||||
$upperName = mb_strtoupper($name);
|
||||
if(isset(self::$members[$upperName])){
|
||||
throw new \InvalidArgumentException("\"$upperName\" is already reserved");
|
||||
|
@ -905,11 +905,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/scheduler/TaskScheduler.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\thread\\\\ThreadManager\\:\\:getAll\\(\\) should return array\\<pocketmine\\\\thread\\\\Thread\\|pocketmine\\\\thread\\\\Worker\\> but returns array\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/thread/ThreadManager.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset string on mixed\\.$#"
|
||||
count: 3
|
||||
@ -925,16 +920,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/utils/Config.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$offset of function substr expects int, mixed given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/utils/Internet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$length of function substr expects int\\|null, mixed given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/utils/Internet.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$string of function trim expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
|
@ -86,7 +86,7 @@ parameters:
|
||||
path: ../../../src/world/format/io/region/RegionLoader.php
|
||||
|
||||
-
|
||||
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertNotSame\\(\\) with arguments stdClass, stdClass and 'Cloning registry…' will always evaluate to false\\.$#"
|
||||
message: "#^Negated boolean expression is always true\\.$#"
|
||||
count: 1
|
||||
path: ../../phpunit/utils/CloningRegistryTraitTest.php
|
||||
path: ../../../src/network/mcpe/handler/InGamePacketHandler.php
|
||||
|
||||
|
Reference in New Issue
Block a user