mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 19:24:12 +00:00
Compare commits
102 Commits
5.5.0-BETA
...
5.7.1
Author | SHA1 | Date | |
---|---|---|---|
2c17f82eb8 | |||
e6e2c54ec9 | |||
abce512860 | |||
0093732d49 | |||
1402571055 | |||
34bb86d2bf | |||
0b2fc84827 | |||
22b9e70372 | |||
a222636476 | |||
fb586cc562 | |||
f3f22ba48b | |||
a2e6e2e5b9 | |||
1aaaadb909 | |||
53a740433f | |||
9fcc9f4338 | |||
73b1fba53c | |||
e4888d7102 | |||
450ad42202 | |||
1c5d3b43be | |||
decc188302 | |||
8fa5c7cdab | |||
7dd3a70d2e | |||
b3390458b4 | |||
b4d55e4384 | |||
932116fa52 | |||
7b5c30bc2c | |||
c14eb63f9b | |||
224a69b11a | |||
15ba642258 | |||
edea793a98 | |||
1da7e3586b | |||
7d200247f8 | |||
2d697c5f04 | |||
364f408eb1 | |||
660e2b8173 | |||
9facb98327 | |||
7e42a03db3 | |||
94a17f59d2 | |||
ed4088755f | |||
ff89d4d055 | |||
8f804f6f34 | |||
c3bca9e172 | |||
c028bb9055 | |||
f151047b5e | |||
77566db766 | |||
dd2e6ea33f | |||
d138a15a32 | |||
7a2cfa92b6 | |||
912fd3f5c6 | |||
5eca90d478 | |||
338bb3fe6d | |||
f485f7fb46 | |||
63eba3eb53 | |||
914eb62e94 | |||
a85814d0c9 | |||
eb2e472b01 | |||
6553852d99 | |||
540476365f | |||
efafc2c6ca | |||
d7f69c5e24 | |||
0e87ee1e0e | |||
03ecc98a24 | |||
a5aeabd836 | |||
fe94379a93 | |||
79acc4fed4 | |||
c8d357f4eb | |||
ec1cd5967d | |||
5a010e8213 | |||
73a44d50ee | |||
6aab07debd | |||
b160b87e24 | |||
690ee4c574 | |||
a0c7587b68 | |||
be4e091d40 | |||
857c2edc2c | |||
b1ab69ac6c | |||
e95a920fb8 | |||
67f399b238 | |||
a7c806d549 | |||
0920c76a35 | |||
a91ca999fe | |||
ce04478395 | |||
28ce7ac5fd | |||
540f088eda | |||
19e3d339f6 | |||
9fdb6ba5aa | |||
4a0a538278 | |||
2912e7ca29 | |||
31d8cc1cb5 | |||
506d8d1064 | |||
d1a7c1d453 | |||
b56f1b679e | |||
1a18e32011 | |||
09c9dfb576 | |||
f2b710c083 | |||
c7a311c17a | |||
ce53a221a5 | |||
4cc858829f | |||
e852a43821 | |||
05f40b1315 | |||
7aaef8cb89 | |||
9d4c37fc3a |
16
.github/workflows/build-docker-image.yml
vendored
16
.github/workflows/build-docker-image.yml
vendored
@ -12,23 +12,23 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Clone pmmp/PocketMine-Docker repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: pmmp/PocketMine-Docker
|
||||
fetch-depth: 1
|
||||
@ -53,7 +53,7 @@ jobs:
|
||||
run: echo NAME=$(echo "${GITHUB_REPOSITORY,,}") >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build image for tag
|
||||
uses: docker/build-push-action@v4.1.1
|
||||
uses: docker/build-push-action@v5.0.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
@ -66,7 +66,7 @@ jobs:
|
||||
|
||||
- name: Build image for major tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v4.1.1
|
||||
uses: docker/build-push-action@v5.0.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
@ -79,7 +79,7 @@ jobs:
|
||||
|
||||
- name: Build image for minor tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v4.1.1
|
||||
uses: docker/build-push-action@v5.0.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
@ -92,7 +92,7 @@ jobs:
|
||||
|
||||
- name: Build image for latest tag
|
||||
if: steps.channel.outputs.CHANNEL == 'stable'
|
||||
uses: docker/build-push-action@v4.1.1
|
||||
uses: docker/build-push-action@v5.0.0
|
||||
with:
|
||||
push: true
|
||||
context: ./pocketmine-mp
|
||||
|
4
.github/workflows/discord-release-notify.yml
vendored
4
.github/workflows/discord-release-notify.yml
vendored
@ -10,10 +10,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.25.5
|
||||
uses: shivammathur/setup-php@2.26.0
|
||||
with:
|
||||
php-version: 8.1
|
||||
|
||||
|
6
.github/workflows/draft-release.yml
vendored
6
.github/workflows/draft-release.yml
vendored
@ -15,12 +15,12 @@ jobs:
|
||||
php-version: [8.1]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@2.25.5
|
||||
uses: shivammathur/setup-php@2.26.0
|
||||
with:
|
||||
php-version: ${{ matrix.php-version }}
|
||||
|
||||
@ -86,7 +86,7 @@ jobs:
|
||||
${{ github.workspace }}/build_info.json
|
||||
|
||||
- name: Create draft release
|
||||
uses: ncipollo/release-action@v1.12.0
|
||||
uses: ncipollo/release-action@v1.13.0
|
||||
with:
|
||||
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
|
||||
commit: ${{ github.sha }}
|
||||
|
15
.github/workflows/main.yml
vendored
15
.github/workflows/main.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
php: ["8.1", "8.2"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
@ -52,7 +52,7 @@ jobs:
|
||||
php: ["8.1", "8.2"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
@ -87,7 +87,7 @@ jobs:
|
||||
php: ["8.1", "8.2"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@ -124,7 +124,7 @@ jobs:
|
||||
php: ["8.1", "8.2"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP
|
||||
uses: pmmp/setup-php-action@2.0.0
|
||||
@ -158,6 +158,9 @@ jobs:
|
||||
- name: Regenerate BedrockData available files constants
|
||||
run: php build/generate-bedrockdata-path-consts.php
|
||||
|
||||
- name: Regenerate YmlServerProperties constants
|
||||
run: php build/generate-pocketmine-yml-property-consts.php
|
||||
|
||||
- name: Verify code is unchanged
|
||||
run: |
|
||||
git diff
|
||||
@ -170,10 +173,10 @@ jobs:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.25.5
|
||||
uses: shivammathur/setup-php@2.26.0
|
||||
with:
|
||||
php-version: 8.1
|
||||
tools: php-cs-fixer:3.17
|
||||
|
2
.github/workflows/update-updater-api.yml
vendored
2
.github/workflows/update-updater-api.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
- name: Install jq
|
||||
run: sudo apt update && sudo apt install jq -y
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/update.pmmp.io
|
||||
ssh-key: ${{ secrets.UPDATE_PMMP_IO_DEPLOY_KEY }}
|
||||
|
@ -88,45 +88,58 @@ Depending on the changes, maintainers might ask you to make changes to the PR to
|
||||
### Requirements
|
||||
The following are required as a minimum for pull requests. PRs that don't meet these requirements will be declined unless updated to meet them.
|
||||
|
||||
#### Licensing
|
||||
PocketMine-MP is licensed under [LGPLv3 license](LICENSE).
|
||||
By proposing a pull request, you agree to your code being distributed within PocketMine-MP under the same license.
|
||||
If you take code from other projects, that code MUST be licensed under an LGPL-compatible license.
|
||||
|
||||
#### PRs should be about exactly ONE thing
|
||||
If you want to make multiple changes, those changes should each be contributed as separate pull requests. **DO NOT** mix unrelated changes.
|
||||
|
||||
#### PRs must not include unnecessary/unrelated changes
|
||||
Do not include changes which aren't strictly necessary. This makes it harder to review a PR, because the code diff becomes larger and harder to review.
|
||||
This means:
|
||||
- don't reformat or rearrange existing code
|
||||
- don't change things that aren't related to the PR's objective
|
||||
- don't rewrite existing code just to make it "look nicer"
|
||||
- don't change PhpDocs to native types in code you didn't write
|
||||
|
||||
#### Tests must be provided
|
||||
Where possible, PHPUnit tests should be written for new or changed code.
|
||||
If that's not possible (e.g. for in-game functionality), the code must be tested manually and details of the tests done must be provided.
|
||||
**Simply saying "Tested" is not acceptable** and will lead to your PR being declined.
|
||||
|
||||
#### Comments and documentation must be written in American English
|
||||
English is the shared languages of all current maintainers.
|
||||
|
||||
#### Code must be in the PocketMine-MP style
|
||||
It's your responsibility to ensure your code matches the formatting and styling of the rest of the code.
|
||||
If you use PhpStorm, a `Project` code style is provided, which you can use to automatically format new code.
|
||||
You can also use [`php-cs-fixer`](https://github.com/FriendsOfPHP/PHP-CS-Fixer) to format your code.
|
||||
- **All code must be licensed under the [LGPLv3 license](LICENSE)** as per PocketMine-MP's own license, or a compatible license.
|
||||
- By proposing a pull request, you agree to your code being distributed within PocketMine-MP under the same license.
|
||||
- If you take code from other projects, that code MUST be licensed under an LGPL-compatible license.
|
||||
- **PRs should be about ONE thing**
|
||||
- If you want to make multiple changes, those changes should each be contributed as separate pull requests. **DO NOT** mix unrelated changes.
|
||||
- **Do not include unnecessary changes.** This makes the code diff larger and more noisy, making it harder to review.
|
||||
- Don't change things that aren't related to the PR's objective
|
||||
- Don't reformat or rearrange existing code without a good reason related to the PR's objective
|
||||
- Don't rewrite existing code just to make it "look nicer"
|
||||
- Don't change PhpDocs to native types in code you didn't write, unless that's the objective of the PR
|
||||
- **Test code changes, and tell us what tests have been done.**
|
||||
- Where possible, PHPUnit tests should be written for new or changed code. If that's not possible (e.g. for in-game functionality), the code must be tested manually and details of the tests done must be provided.
|
||||
- **Simply saying "Tested" is not acceptable** and could lead to your PR being declined.
|
||||
- **Code, comments and documentation must be written in American English.** English is the shared languages of all current maintainers.
|
||||
- **Code must be in the PocketMine-MP style.**
|
||||
- It's your responsibility to ensure your code matches the formatting and styling of the rest of the code.
|
||||
- If you use PhpStorm, a `Project` code style is provided, which you can use to automatically format new code.
|
||||
- You can also use [`php-cs-fixer`](https://github.com/FriendsOfPHP/PHP-CS-Fixer) to format your code.
|
||||
- **Use `final` and `private` wherever possible**.
|
||||
- Changing from `private` to `protected` or `final` to non-`final` doesn't break backwards compatibility, but the opposite does.
|
||||
- `private` and `final` also enable certain performance optimizations which are otherwise not possible.
|
||||
- `private` members can be freely changed, added and removed in the future, so it's ideal for internal functions. Abusing `protected` makes internal improvements inconvenient.
|
||||
- "Let's leave it protected/public in case someone needs it for ... idk what" is **not a valid reason to expose things**. If there isn't a clear reason for something to be accessible from the outside, don't expose it.
|
||||
- **This is a lesson learned through years of experience.** You may not like it, but it's for the best.
|
||||
- **Immutable things are almost always preferred.**
|
||||
- Do not add unnecessary setters or public writable properties to classes. As above, "Let's leave it in case someone needs it" is **not a valid reason to expose things**.
|
||||
- Mutable classes and properties are unpredictable, since code has no way to know if the object it's working with might be randomly modified by another part of the code. This makes it harder to maintain code and debug issues.
|
||||
- Most classes exist only to hold some data. These are called "data transfer objects" (DTOs). These types of classes should pretty much always be immutable.
|
||||
- Make use of `final`, `private` and `readonly` modifiers.
|
||||
|
||||
### Recommendations
|
||||
|
||||
- **Be patient.** Reviewing pull requests takes a lot of time and energy, and maintainers are often unavailable or busy. Your PR might not receive attention for a while.
|
||||
- Remember, PRs with small diffs are much easier to review. Small PRs are generally reviewed and merged much faster than large ones.
|
||||
- **Start small.** Try fixing minor bugs or doing something isolated (e.g. adding a new block or item) before attempting larger changes.
|
||||
- This helps you get familiar with the codebase, the contribution process, and the expectations of maintainers.
|
||||
- Check out the [issues page]() for something that you could tackle without too much effort.
|
||||
- **Do not copy-paste other people's code**. Many PRs involve discussion about the changes, and changes are often requested by reviewers. If you don't understand the code you're copy-pasting, your PR is likely to fail.
|
||||
- **Do not edit code directly on github.com.** We recommend learning how to use [`git`](https://git-scm.com). `git` allows you to "clone" a repository onto your computer, so that you can make changes using an IDE.
|
||||
- **Use an IDE, not a text editor.** We recommend PhpStorm or VSCode.
|
||||
- **Do not make large pull requests without an RFC.**
|
||||
- Large changes should be discussed beforehand using the [RFC / Change Proposal](#rfcs--change-proposals) process.
|
||||
- Large changes are much harder to review, and are more likely to be declined if maintainers don't have a good idea what you're trying to do in advance.
|
||||
- **Create a new branch on your fork for each pull request.** This allows you to use the same fork to make multiple pull requests at the same time.
|
||||
- **Make your PR diff as small as possible.** Smaller PRs are **much more likely** to be accepted, as they are easier to review.
|
||||
- Avoid moving code around in files if possible.
|
||||
- Don't make random CS changes. This makes the diff noisier and harder to review.
|
||||
- **Use descriptive commit titles.** You can see an example [here](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
||||
- **Do not include multiple unrelated changes in one commit.** An atomic style for commits is preferred - this means that changes included in a commit should be part of a single distinct change set. See [this link](https://www.freshconsulting.com/atomic-commits/) for more information on atomic commits. See the [documentation on `git add`](https://git-scm.com/docs/git-add) for information on how to isolate local changes for committing.
|
||||
- **Your pull request will be checked and discussed in due time.** Since the team is scattered all around the world, your PR may not receive any attention for some time.
|
||||
- **Do not make large pull requests without an RFC.** Large changes should be discussed beforehand using the [RFC / Change Proposal](#rfcs--change-proposals) process. Large changes are much harder to review and are more likely to be declined if maintainers don't have a good idea what you're trying to do in advance.
|
||||
- **Do not copy-paste code**. There are potential license issues implicit with copy-pasting, and copy-paste usually indicates a lack of understanding of the actual code. Copy-pasted code is obvious a mile off and **any PR like this is likely to be closed**. If you want to use somebody else's code from a Git repository, **use [GIT's cherry-pick feature](https://git-scm.com/docs/git-cherry-pick)** to cherry-pick the commit.
|
||||
- **Split unrelated changes into multiple commits.**
|
||||
- An atomic style for commits is preferred - this means that changes included in a commit should be part of a single distinct change set.
|
||||
- If you need to use "and" or "multiple changes" in your commit message, the commit probably needs to be split up. There are exceptions, but this is a good rule of thumb.
|
||||
- See [this link](https://www.freshconsulting.com/atomic-commits/) for more information on atomic commits.
|
||||
- See the [documentation on `git add -i` or `git add -p`](https://git-scm.com/docs/git-add) for information on how to split up local changes for committing.
|
||||
|
||||
|
||||
**Thanks for contributing to PocketMine-MP!**
|
||||
|
120
build/generate-pocketmine-yml-property-consts.php
Normal file
120
build/generate-pocketmine-yml-property-consts.php
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use pocketmine\utils\Filesystem;
|
||||
use pocketmine\utils\Utils;
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
$defaultConfig = yaml_parse(Filesystem::fileGetContents(dirname(__DIR__) . '/resources/pocketmine.yml'));
|
||||
|
||||
if(!is_array($defaultConfig)){
|
||||
fwrite(STDERR, "Invalid default pocketmine.yml\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$constants = [];
|
||||
|
||||
/**
|
||||
* @param mixed[] $properties
|
||||
* @param string[] $constants
|
||||
* @phpstan-param array<string, string> $constants
|
||||
* @phpstan-param-out array<string, string> $constants
|
||||
*/
|
||||
function collectProperties(string $prefix, array $properties, array &$constants) : void{
|
||||
foreach($properties as $propertyName => $property){
|
||||
$fullPropertyName = ($prefix !== "" ? $prefix . "." : "") . $propertyName;
|
||||
|
||||
$constName = str_replace([".", "-"], "_", strtoupper($fullPropertyName));
|
||||
$constants[$constName] = $fullPropertyName;
|
||||
|
||||
if(is_array($property)){
|
||||
collectProperties($fullPropertyName, $property, $constants);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectProperties("", $defaultConfig, $constants);
|
||||
ksort($constants, SORT_STRING);
|
||||
|
||||
$file = fopen(dirname(__DIR__) . '/src/YmlServerProperties.php', 'wb');
|
||||
if($file === false){
|
||||
fwrite(STDERR, "Failed to open output file\n");
|
||||
exit(1);
|
||||
}
|
||||
fwrite($file, "<?php\n");
|
||||
fwrite($file, <<<'HEADER'
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
HEADER
|
||||
);
|
||||
fwrite($file, "declare(strict_types=1);\n\n");
|
||||
fwrite($file, "namespace pocketmine;\n\n");
|
||||
|
||||
fwrite($file, <<<'DOC'
|
||||
/**
|
||||
* @internal
|
||||
* Constants for all properties available in pocketmine.yml.
|
||||
* This is generated by build/generate-pocketmine-yml-property-consts.php.
|
||||
* Do not edit this file manually.
|
||||
*/
|
||||
|
||||
DOC
|
||||
);
|
||||
fwrite($file, "final class YmlServerProperties{\n");
|
||||
fwrite($file, <<<'CONSTRUCTOR'
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
|
||||
CONSTRUCTOR
|
||||
);
|
||||
foreach(Utils::stringifyKeys($constants) as $constName => $propertyName){
|
||||
fwrite($file, "\tpublic const $constName = '$propertyName';\n");
|
||||
}
|
||||
fwrite($file, "}\n");
|
||||
|
||||
fclose($file);
|
||||
|
||||
echo "Done. Don't forget to run CS fixup after generating code.\n";
|
Submodule build/php updated: a053f65e18...a34e48e7da
@ -60,3 +60,9 @@ Released 9th August 2023.
|
||||
- Fixed `PluginBase->saveResource()` leaking file resources when the data file already exists in the plugin's data folder. This bug existed since 2014 and was only discovered recently.
|
||||
- Fixed coral blocks becoming dead after calling `getDropsForCompatibleTool()` on them.
|
||||
- Fixed `BlockDeathEvent->getOldState()` returning a block which is already dead.
|
||||
|
||||
# 4.23.6
|
||||
Released 21st August 2023.
|
||||
|
||||
## Fixes
|
||||
- Added a workaround for armor and other inventories not working correctly after inventory sync. This is caused by a client bug.
|
||||
|
17
changelogs/4.24.md
Normal file
17
changelogs/4.24.md
Normal file
@ -0,0 +1,17 @@
|
||||
# 4.24.0
|
||||
Released 20th September 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.20.30**
|
||||
|
||||
This is a support release for Minecraft: Bedrock Edition 1.20.30.
|
||||
|
||||
**Plugin compatibility:** Plugins for previous 4.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` namespace.
|
||||
Do not update plugin minimum API versions unless you need new features added in this release.
|
||||
|
||||
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.20.30.
|
||||
- Removed support for older versions.
|
||||
- Updated 4.x obsoletion message.
|
16
changelogs/4.25.md
Normal file
16
changelogs/4.25.md
Normal file
@ -0,0 +1,16 @@
|
||||
# 4.25.0
|
||||
Released 26th October 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.20.40**
|
||||
|
||||
This is a support release for Minecraft: Bedrock Edition 1.20.40.
|
||||
|
||||
**Plugin compatibility:** Plugins for previous 4.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` namespace.
|
||||
Do not update plugin minimum API versions unless you need new features added in this release.
|
||||
|
||||
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.20.40.
|
||||
- Removed support for older versions.
|
@ -107,3 +107,27 @@ Released 9th August 2023.
|
||||
## Fixes
|
||||
- Fixed cake accepting candle placement when slices have already been eaten.
|
||||
- Fixed fire charges not lighting candles.
|
||||
|
||||
# 5.4.3
|
||||
Released 21st August 2023.
|
||||
|
||||
## Included releases
|
||||
- [4.23.6](https://github.com/pmmp/PocketMine-MP/blob/4.23.6/changelogs/4.23.md#4236) - Armor inventory client bug workaround
|
||||
|
||||
## Fixes
|
||||
- Fixed crashdumps not generating correctly on fatal errors.
|
||||
- Fixed `PotionCauldron::setPotionItem()` not validating the item type.
|
||||
- Fixed chorus fruit not considering teleport destinations below y=0.
|
||||
- Fixed cake dropping itself when mined.
|
||||
|
||||
# 5.4.4
|
||||
Released 6th September 2023.
|
||||
|
||||
## General
|
||||
- Crashdumps caused by non-phar plugins are now submitted to the Crash Archive, the same as other plugins. Previously, non-phar plugin crashes would not be submitted, causing maintainers to potentially miss important issues.
|
||||
|
||||
## Fixes
|
||||
- Fixed player Y coordinates sometimes being slightly below the top of the block they were standing on (floating point error due to subtracting eye height).
|
||||
- Fixed template slot of smithing tables not accepting any items.
|
||||
- `tools/generate-bedrock-data-from-packets.php` is now significantly less spammy when warning about duplicated recipes.
|
||||
- Fixed empty stack traces in `lastError` data of crashdumps.
|
||||
|
@ -1,7 +1,7 @@
|
||||
# 5.5.0-BETA1
|
||||
Released 23rd August 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.20.0**
|
||||
**For Minecraft: Bedrock Edition 1.20.10**
|
||||
|
||||
This is a minor feature release, including performance improvements, new API methods, and new gameplay features.
|
||||
|
||||
|
162
changelogs/5.5.md
Normal file
162
changelogs/5.5.md
Normal file
@ -0,0 +1,162 @@
|
||||
# 5.5.0
|
||||
Released 6th September 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.20.10**
|
||||
|
||||
This is a minor feature release, including performance improvements, new API methods, and new gameplay features.
|
||||
|
||||
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
|
||||
Do not update plugin minimum API versions unless you need new features added in this release.
|
||||
|
||||
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||
|
||||
## Dependencies
|
||||
- Updated `pocketmine/math` dependency to [`1.0.0`](https://github.com/pmmp/Math/releases/tag/1.0.0).
|
||||
- Updated `pocketmine/nbt` dependency to [`1.0.0`](https://github.com/pmmp/NBT/releases/tag/1.0.0).
|
||||
|
||||
## Performance
|
||||
- Some events are now no longer fired if no handlers are registered.
|
||||
- This improves performance by avoiding unnecessary object allocations and function calls.
|
||||
- Events such as `DataPacketReceiveEvent`, `DataPacketSendEvent` and `PlayerMoveEvent` are optimized away almost completely by this change, offering some much-needed performance gains.
|
||||
- Significantly improved performance of small moving entities, such as dropped items.
|
||||
- This was achieved by a combination of changes, which together improved observed performance with 2000 item entities moving in water by 30-40%.
|
||||
- The benefit of this will be most noticeable in SkyBlock servers, where large cactus farms can generate thousands of dropped items.
|
||||
- `World->getCollisionBoxes()` now uses an improved search method, which reduces the work done by the function by almost 90% for small entities.
|
||||
- This improves performance of collision detection for small entities, such as dropped items.
|
||||
|
||||
## Gameplay
|
||||
### General
|
||||
- Implemented enchanting using an enchanting table (yes, finally!)
|
||||
- Thanks to [@S3v3Nice](https://github.com/S3v3Nice) for investing lots of time and effort into developing this.
|
||||
- Since this feature is quite complex, it's possible there may be bugs. Please be vigilant and report any issues you find.
|
||||
|
||||
### Blocks
|
||||
- The following new blocks have been implemented:
|
||||
- Pink Petals
|
||||
- Pressure plates are now functional, in the sense that they react when entities stand on them and perform the correct logic.
|
||||
- Note that since redstone is not yet implemented, pressure plates do not activate any redstone devices, similar to buttons and levers.
|
||||
- Signs can now be edited by right-clicking them.
|
||||
- Signs can now be waxed using a honeycomb, which prevents them from being edited.
|
||||
|
||||
### Items
|
||||
- The following new items have been implemented:
|
||||
- Enchanted Book
|
||||
|
||||
## API
|
||||
### `pocketmine\block`
|
||||
- The following new API methods have been added:
|
||||
- `public Block->getEnchantmentTags() : list<string>` returns a list of strings indicating which types of enchantment can be applied to the block when in item form
|
||||
- `public BlockTypeInfo->getEnchantmentTags() : list<string>`
|
||||
- `protected PressurePlate->getActivationBox() : AxisAlignedBB` - returns the AABB entities must intersect with in order to activate the pressure plate (not the same as the visual shape)
|
||||
- `protected PressurePlate->hasOutputSignal() : bool` - returns whether the pressure plate has an output signal - this should be implemented by subclasses
|
||||
- `protected PressurePlate->calculatePlateState() : array{Block, ?bool}` - returns the state the pressure plate will change to if the given list of entities are standing on it, and a bool indicating whether the plate activated or deactivated this tick
|
||||
- `protected PressurePlate->filterIrrelevantEntities(list<Entity> $entities) : list<Entity>` - returns the given list filtered of entities that don't affect the plate's state (e.g. dropped items don't affect stone pressure plates)
|
||||
- `public BaseSign->isWaxed() : bool`
|
||||
- `public BaseSign->setWaxed(bool $waxed) : $this`
|
||||
- `public inventory\EnchantInventory->getInput() : Item`
|
||||
- `public inventory\EnchantInventory->getLapis() : Item`
|
||||
- `public inventory\EnchantInventory->getOutput(int $optionId) : ?Item` - returns the item that would be produced if the input item was enchanted with the selected option, or `null` if the option is invalid
|
||||
- `public inventory\EnchantInventory->getOption(int $optionId) : EnchantOption` - returns the enchanting option at the given index
|
||||
- The following API methods have signature changes:
|
||||
- `BlockTypeInfo->__construct()` now accepts an optional `list<string> $enchantmentTags` parameter
|
||||
- `PressurePlate->__construct()` now accepts an optional `int $deactivationDelayTicks` parameter
|
||||
- `WeightedPressurePlate->__construct()` now accepts optional `int $deactivationDelayTicks` and `float $signalStrengthFactor` parameters
|
||||
- `SimplePressurePlate->__construct()` now accepts an optional `int $deactivationDelayTicks` parameter
|
||||
- The following new classes have been added:
|
||||
- `PinkPetals`
|
||||
- `utils\BlockEventHelper` - provides helper methods for calling block-related events
|
||||
- The following classes have been deprecated:
|
||||
- `WeightedPressurePlateLight`
|
||||
- `WeightedPressurePlateHeavy`
|
||||
|
||||
### `pocketmine\entity`
|
||||
- The following new API methods have been added:
|
||||
- `public Human->getEnchantmentSeed() : int` - returns the current seed used to randomize options shown on the enchanting table for this human
|
||||
- `public Human->setEnchantmentSeed(int $seed) : void`
|
||||
- `public Human->regenerateEnchantmentSeed() : void` - returns a new randomly generated seed which can be set with `setEnchantmentSeed()`
|
||||
|
||||
### `pocketmine\event`
|
||||
- The following new classes have been added:
|
||||
- `block\FarmlandHydrationChangeEvent` - called when farmland is hydrated or dehydrated
|
||||
- `block\PressurePlateUpdateEvent` - called when a pressure plate is activated or changes its power output
|
||||
- `player\PlayerEnchantingOptionsRequestEvent` - called when a player puts an item to be enchanted into an enchanting table, to allow plugins to modify the enchanting options shown
|
||||
- `player\PlayerItemEnchantEvent` - called when a player enchants an item in an enchanting table
|
||||
- `world\WorldDifficultyChangeEvent` - called when a world's difficulty is changed
|
||||
- The following new API methods have been added:
|
||||
- `public static Event::hasHandlers() : bool` - returns whether the event class has any registered handlers - used like `SomeEvent::hasHandlers()`
|
||||
- `public HandlerListManager->getHandlersFor(class-string<? extends Event> $event) : list<RegisteredListener>` - returns a list of all registered listeners for the given event class, using cache if available
|
||||
|
||||
### `pocketmine\inventory\transaction`
|
||||
- The following new classes have been added:
|
||||
- `EnchantingTransaction` - used when a player enchants an item in an enchanting table
|
||||
|
||||
### `pocketmine\item`
|
||||
- The following new API methods have been added:
|
||||
- `public Armor->getMaterial() : ArmorMaterial` - returns an object containing properties shared by all items of the same armor material
|
||||
- `public ArmorTypeInfo->getMaterial() : ArmorMaterial`
|
||||
- `public Item->getEnchantability() : int` - returns the enchantability value of the item - higher values increase the chance of more powerful enchantments being offered by an enchanting table
|
||||
- `public Item->getEnchantmentTags() : list<string>` - returns a list of strings indicating which types of enchantment can be applied to the item
|
||||
- `public ToolTier->getEnchantability() : int`
|
||||
- The following API methods have signature changes:
|
||||
- `Item->__construct()` now accepts an optional `list<string> $enchantmentTags` parameter
|
||||
- `ArmorTypeInfo->__construct()` now accepts an optional `?ArmorMaterial $material` parameter
|
||||
- The following new classes have been added:
|
||||
- `ArmorMaterial` - container for shared armor properties
|
||||
- `VanillaArmorMaterials` - all vanilla armor materials
|
||||
- `EnchantedBook` - represents an enchanted book item
|
||||
|
||||
### `pocketmine\item\enchantment`
|
||||
- The following new classes have been added:
|
||||
- `AvailableEnchantmentRegistry` - enchantments to be displayed on the enchanting table are selected from here - custom enchantments may be added
|
||||
- `EnchantingHelper` - static class containing various helper methods for enchanting tables
|
||||
- `EnchantingOption` - represents an option on the enchanting table menu
|
||||
- `IncompatibleEnchantmentGroups` - list of constants naming groups of enchantments that are incompatible with each other - custom enchantments may be added using these group names to make them incompatible with existing enchantments in the same group
|
||||
- `IncompatibleEnchantmentRegistry` - manages which enchantments are considered incompatible with each other - custom enchantments may be added using existing group names to make them incompatible with existing enchantments in the same group, or to entirely new groups
|
||||
- `ItemEnchantmentTagRegistry` - manages item enchantment compatibility tags and which tags include which other tags
|
||||
- `ItemEnchantmentTags` - list of constants naming item types for enchantment compatibility checks
|
||||
- The following classes have been deprecated
|
||||
- `ItemFlags`
|
||||
- The following API methods have been added:
|
||||
- `public Enchantment->isCompatibleWith(Enchantment $other) : bool`
|
||||
- `public Enchantment->getMinEnchantingPower()` - returns the minimum enchanting power (derived from enchantability and number of bookshelves) needed to allow this enchantment to show on the enchanting table with a given level
|
||||
- `public Enchantment->getMaxEnchantingPower()` - upper limit of enchanting power for this enchantment to be offered on the enchanting table with a given level
|
||||
- The following API methods have signature changes:
|
||||
- `Enchantment->__construct()` now accepts optional `(\Closure(int $level) : int)|null $minEnchantingPower` and `int $enchantingPowerRange` parameters
|
||||
- `Enchantment->__construct()` parameters `$primaryItemFlags` and `$secondaryItemFlags` are now deprecated and no longer used
|
||||
- `ProtectionEnchantment->__construct()` has extra parameters to reflect `Enchantment->__construct()` changes
|
||||
- The following API methods have been deprecated:
|
||||
- `Enchantment->getPrimaryItemFlags()` - use API methods provided by `AvailableEnchantmentRegistry` instead
|
||||
- `Enchantment->getSecondaryItemFlags()` - use API methods provided by `AvailableEnchantmentRegistry` instead
|
||||
- `Enchantment->hasPrimaryItemType()`
|
||||
- `Enchantment->hasSecondaryItemType()`
|
||||
|
||||
### `pocketmine\plugin`
|
||||
- The following new API methods have been added:
|
||||
- `public PluginBase->getResourcePath(string $filename) : string` - returns a URI to an embedded resource file that can be used with `file_get_contents()` and similar functions
|
||||
- `public PluginBase->getResourceFolder() : string` - returns a URI to the plugin's folder of embedded resources
|
||||
- The following API methods have been deprecated:
|
||||
- `PluginBase->getResource()` - prefer using `getResourcePath()` with `file_get_contents()` or other PHP built-in functions instead
|
||||
|
||||
### `pocketmine\resourcepacks`
|
||||
- The following new API methods have been added:
|
||||
- `public ResourcePackManager->setResourcePacksRequired(bool $value) : void` - sets whether players must accept resource packs in order to join
|
||||
|
||||
### `pocketmine\world\generator`
|
||||
- The following new API methods have been added:
|
||||
- `public GeneratorManager->addAlias(string $name, string $alias) : void` - allows registering a generator alias without copying the generator registration parameters
|
||||
|
||||
### `pocketmine\world\sound`
|
||||
- The following new classes have been added:
|
||||
- `PressurePlateActivateSound`
|
||||
- `PressurePlateDeactivateSound`
|
||||
|
||||
### `pocketmine\utils`
|
||||
- The following new API methods have been added:
|
||||
- `public StringToTParser->registerAlias(string $existing, string $alias) : void` - allows registering a string alias without copying registration parameters
|
||||
|
||||
## Internals
|
||||
- Various `TypeIdMap` classes in the `pocketmine\data\bedrock` package now use the new `IntSaveIdMapTrait` to reduce code duplication.
|
||||
- Added a new `ServerProperties` class containing constants for all known `server.properties` keys.
|
||||
- Added a new `YmlServerProperties` class containing generated constants for all known `pocketmine.yml` keys. These keys can be used with `Config->getNested()`.
|
||||
|
34
changelogs/5.6.md
Normal file
34
changelogs/5.6.md
Normal file
@ -0,0 +1,34 @@
|
||||
# 5.6.0
|
||||
Released 20th September 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.20.30**
|
||||
|
||||
This is a support release for Minecraft: Bedrock Edition 1.20.30.
|
||||
|
||||
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
|
||||
Do not update plugin minimum API versions unless you need new features added in this release.
|
||||
|
||||
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.20.30.
|
||||
- Removed support for older versions.
|
||||
|
||||
## Fixes
|
||||
- Fixed support conditions for hanging roots, cave vines and dead bushes.
|
||||
- Fixed connection conditions for fences, glass panes, iron bars, and walls.
|
||||
|
||||
# 5.6.1
|
||||
Released 20th October 2023.
|
||||
|
||||
## Performance
|
||||
- Improved performance of cactus growth by disabling neighbour updates when only the age property was updated. While this isn't a perfect solution, it provides significant performance gains for servers with large cactus farms.
|
||||
|
||||
## Fixes
|
||||
- Fixed `tools/generate-bedrock-data-from-packets.php` incorrectly interpreting network meta as blockstates in some cases (broken crafting recipes).
|
||||
- Fixed crafting recipes involving beds, skulls and some other items not working correctly (incorrectly interpreted data).
|
||||
- Fixed crashes when flower pot or cauldron blockentities exist in places where they shouldn't (leftovers from upgraded PM3 worlds).
|
||||
- Fixed `Entity->broadcastSound()` not firing `WorldSoundEvent` (bypassing internal sound system).
|
||||
- Fixed wooden signs, buttons and doors not being able to be used as furnace fuel.
|
||||
- Fixed bone meal and tools only working when used on the top side of dirt and grass. Bone meal now works from any side, and tools work on any side except the bottom.
|
27
changelogs/5.7.md
Normal file
27
changelogs/5.7.md
Normal file
@ -0,0 +1,27 @@
|
||||
# 5.7.0
|
||||
Released 26th October 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.20.40**
|
||||
|
||||
This is a support release for Minecraft: Bedrock Edition 1.20.40.
|
||||
|
||||
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
|
||||
Do not update plugin minimum API versions unless you need new features added in this release.
|
||||
|
||||
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
|
||||
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
|
||||
|
||||
## General
|
||||
- Added support for Minecraft: Bedrock Edition 1.20.40.
|
||||
- Removed support for older versions.
|
||||
|
||||
## Fixes
|
||||
- Fixed `cartography_table`, `smithing_table`, `stripped_cherry_log` and `stripped_cherry_wood` not working in `StringToItemParser`.
|
||||
- Fixed `Promise<null>::onCompletion()` always calling the reject handler if the promise was already completed.
|
||||
|
||||
# 5.7.1
|
||||
Released 1st November 2023.
|
||||
|
||||
## Fixes
|
||||
- Fixed non-reentrant-safe code in `PermissionManager` and various other subscriber subsystems.
|
||||
- These issues caused server crashes when deleting a subscriber indirectly triggered the deletion of other subscribers (e.g. due to the GC activating in `unset()`).
|
@ -33,10 +33,10 @@
|
||||
"composer-runtime-api": "^2.0",
|
||||
"adhocore/json-comment": "~1.2.0",
|
||||
"pocketmine/netresearch-jsonmapper": "~v4.2.1000",
|
||||
"pocketmine/bedrock-block-upgrade-schema": "~3.1.0+bedrock-1.20.10",
|
||||
"pocketmine/bedrock-data": "~2.4.0+bedrock-1.20.10",
|
||||
"pocketmine/bedrock-item-upgrade-schema": "~1.4.0+bedrock-1.20.10",
|
||||
"pocketmine/bedrock-protocol": "~23.0.2+bedrock-1.20.10",
|
||||
"pocketmine/bedrock-block-upgrade-schema": "~3.3.0+bedrock-1.20.40",
|
||||
"pocketmine/bedrock-data": "~2.6.0+bedrock-1.20.40",
|
||||
"pocketmine/bedrock-item-upgrade-schema": "~1.5.0+bedrock-1.20.30",
|
||||
"pocketmine/bedrock-protocol": "~25.0.0+bedrock-1.20.40",
|
||||
"pocketmine/binaryutils": "^0.2.1",
|
||||
"pocketmine/callback-validator": "^1.0.2",
|
||||
"pocketmine/color": "^0.3.0",
|
||||
@ -52,10 +52,10 @@
|
||||
"symfony/filesystem": "~6.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.10.16",
|
||||
"phpstan/phpstan": "1.10.40",
|
||||
"phpstan/phpstan-phpunit": "^1.1.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.2.0",
|
||||
"phpunit/phpunit": "^10.1"
|
||||
"phpunit/phpunit": "~10.3.0 || ~10.2.0 || ~10.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
218
composer.lock
generated
218
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": "9237955fd97ba7c1697d80314fa9ad6f",
|
||||
"content-hash": "ca499c3c5acafac837f7384ecdae136e",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -122,16 +122,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-block-upgrade-schema",
|
||||
"version": "3.1.0",
|
||||
"version": "3.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockBlockUpgradeSchema.git",
|
||||
"reference": "6d4ae416043337946a22fc31e8065ca2c21f472d"
|
||||
"reference": "ee46b9367af262bbddd9f122d4d5b5b495b892e7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/6d4ae416043337946a22fc31e8065ca2c21f472d",
|
||||
"reference": "6d4ae416043337946a22fc31e8065ca2c21f472d",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/ee46b9367af262bbddd9f122d4d5b5b495b892e7",
|
||||
"reference": "ee46b9367af262bbddd9f122d4d5b5b495b892e7",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -142,22 +142,22 @@
|
||||
"description": "Schemas describing how to upgrade saved block data in older Minecraft: Bedrock Edition world saves",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/BedrockBlockUpgradeSchema/issues",
|
||||
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/3.1.0"
|
||||
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/3.3.0"
|
||||
},
|
||||
"time": "2023-07-12T12:05:36+00:00"
|
||||
"time": "2023-10-16T16:11:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-data",
|
||||
"version": "2.4.0+bedrock-1.20.10",
|
||||
"version": "2.6.0+bedrock-1.20.40",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockData.git",
|
||||
"reference": "f98bd1cae46d2920058acf3b23c0bedeac79f4ab"
|
||||
"reference": "37e780d28b470230bda3579b04cb50d406e3fbe6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/f98bd1cae46d2920058acf3b23c0bedeac79f4ab",
|
||||
"reference": "f98bd1cae46d2920058acf3b23c0bedeac79f4ab",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/37e780d28b470230bda3579b04cb50d406e3fbe6",
|
||||
"reference": "37e780d28b470230bda3579b04cb50d406e3fbe6",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -168,22 +168,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.20.10"
|
||||
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.20.40"
|
||||
},
|
||||
"time": "2023-07-12T11:51:54+00:00"
|
||||
"time": "2023-10-26T10:39:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-item-upgrade-schema",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockItemUpgradeSchema.git",
|
||||
"reference": "60d199afe5e371fd189b21d685ec1fed6ba54230"
|
||||
"reference": "3edc9ebbad9a4f2d9c8f53b3a5ba44d4a792ad93"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/60d199afe5e371fd189b21d685ec1fed6ba54230",
|
||||
"reference": "60d199afe5e371fd189b21d685ec1fed6ba54230",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/3edc9ebbad9a4f2d9c8f53b3a5ba44d4a792ad93",
|
||||
"reference": "3edc9ebbad9a4f2d9c8f53b3a5ba44d4a792ad93",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
@ -194,36 +194,36 @@
|
||||
"description": "JSON schemas for upgrading items found in older Minecraft: Bedrock world saves",
|
||||
"support": {
|
||||
"issues": "https://github.com/pmmp/BedrockItemUpgradeSchema/issues",
|
||||
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.4.0"
|
||||
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.5.0"
|
||||
},
|
||||
"time": "2023-07-12T12:08:37+00:00"
|
||||
"time": "2023-09-01T19:58:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/bedrock-protocol",
|
||||
"version": "23.0.3+bedrock-1.20.10",
|
||||
"version": "25.0.0+bedrock-1.20.40",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BedrockProtocol.git",
|
||||
"reference": "e4157c7af3f91e1b08fe21be171eb73dad7029e9"
|
||||
"reference": "69c36c96f6835e93fc278071aa2bb9829abe5cf8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/e4157c7af3f91e1b08fe21be171eb73dad7029e9",
|
||||
"reference": "e4157c7af3f91e1b08fe21be171eb73dad7029e9",
|
||||
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/69c36c96f6835e93fc278071aa2bb9829abe5cf8",
|
||||
"reference": "69c36c96f6835e93fc278071aa2bb9829abe5cf8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"netresearch/jsonmapper": "^4.0",
|
||||
"php": "^8.0",
|
||||
"php": "^8.1",
|
||||
"pocketmine/binaryutils": "^0.2.0",
|
||||
"pocketmine/color": "^0.2.0 || ^0.3.0",
|
||||
"pocketmine/math": "^0.3.0 || ^0.4.0 || ^1.0.0",
|
||||
"pocketmine/nbt": "^0.3.0 || ^1.0.0",
|
||||
"pocketmine/nbt": "^1.0.0",
|
||||
"ramsey/uuid": "^4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.10.7",
|
||||
"phpstan/phpstan": "1.10.33",
|
||||
"phpstan/phpstan-phpunit": "^1.0.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.0.0",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
@ -241,9 +241,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/23.0.3+bedrock-1.20.10"
|
||||
"source": "https://github.com/pmmp/BedrockProtocol/tree/25.0.0+bedrock-1.20.40"
|
||||
},
|
||||
"time": "2023-08-03T15:30:52+00:00"
|
||||
"time": "2023-10-26T11:03:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
@ -985,16 +985,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.27.0",
|
||||
"version": "v1.28.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
|
||||
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
|
||||
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
|
||||
"reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1009,7 +1009,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.27-dev"
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -1047,7 +1047,7 @@
|
||||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1063,20 +1063,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
"time": "2023-01-26T09:26:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.27.0",
|
||||
"version": "v1.28.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
|
||||
"reference": "42292d99c55abe617799667f454222c54c60e229"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
|
||||
"reference": "42292d99c55abe617799667f454222c54c60e229",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1091,7 +1091,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.27-dev"
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -1130,7 +1130,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1146,7 +1146,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
"time": "2023-07-28T09:04:16+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
@ -1378,16 +1378,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.10.16",
|
||||
"version": "1.10.40",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "352bdbb960bb523e3d71b834862589f910921c23"
|
||||
"reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/352bdbb960bb523e3d71b834862589f910921c23",
|
||||
"reference": "352bdbb960bb523e3d71b834862589f910921c23",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/93c84b5bf7669920d823631e39904d69b9c7dc5d",
|
||||
"reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1436,20 +1436,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-06-05T08:21:46+00:00"
|
||||
"time": "2023-10-30T14:48:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-phpunit",
|
||||
"version": "1.3.13",
|
||||
"version": "1.3.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-phpunit.git",
|
||||
"reference": "d8bdab0218c5eb0964338d24a8511b65e9c94fa5"
|
||||
"reference": "70ecacc64fe8090d8d2a33db5a51fe8e88acd93a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/d8bdab0218c5eb0964338d24a8511b65e9c94fa5",
|
||||
"reference": "d8bdab0218c5eb0964338d24a8511b65e9c94fa5",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/70ecacc64fe8090d8d2a33db5a51fe8e88acd93a",
|
||||
"reference": "70ecacc64fe8090d8d2a33db5a51fe8e88acd93a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1462,7 +1462,7 @@
|
||||
"require-dev": {
|
||||
"nikic/php-parser": "^4.13.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
"phpstan/phpstan-strict-rules": "^1.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.5.1",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"type": "phpstan-extension",
|
||||
@ -1486,27 +1486,27 @@
|
||||
"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.3.13"
|
||||
"source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.15"
|
||||
},
|
||||
"time": "2023-05-26T11:05:59+00:00"
|
||||
"time": "2023-10-09T18:58:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-strict-rules",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
|
||||
"reference": "b21c03d4f6f3a446e4311155f4be9d65048218e6"
|
||||
"reference": "7a50e9662ee9f3942e4aaaf3d603653f60282542"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/b21c03d4f6f3a446e4311155f4be9d65048218e6",
|
||||
"reference": "b21c03d4f6f3a446e4311155f4be9d65048218e6",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/7a50e9662ee9f3942e4aaaf3d603653f60282542",
|
||||
"reference": "7a50e9662ee9f3942e4aaaf3d603653f60282542",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0",
|
||||
"phpstan/phpstan": "^1.10"
|
||||
"phpstan/phpstan": "^1.10.34"
|
||||
},
|
||||
"require-dev": {
|
||||
"nikic/php-parser": "^4.13.0",
|
||||
@ -1535,22 +1535,22 @@
|
||||
"description": "Extra strict and opinionated rules for PHPStan",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.1"
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.2"
|
||||
},
|
||||
"time": "2023-03-29T14:47:40+00:00"
|
||||
"time": "2023-10-30T14:35:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "10.1.3",
|
||||
"version": "10.1.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
||||
"reference": "be1fe461fdc917de2a29a452ccf2657d325b443d"
|
||||
"reference": "355324ca4980b8916c18b9db29f3ef484078f26e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/be1fe461fdc917de2a29a452ccf2657d325b443d",
|
||||
"reference": "be1fe461fdc917de2a29a452ccf2657d325b443d",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/355324ca4980b8916c18b9db29f3ef484078f26e",
|
||||
"reference": "355324ca4980b8916c18b9db29f3ef484078f26e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1607,7 +1607,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
|
||||
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.3"
|
||||
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.7"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1615,20 +1615,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-26T13:45:28+00:00"
|
||||
"time": "2023-10-04T15:34:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-file-iterator",
|
||||
"version": "4.0.2",
|
||||
"version": "4.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
|
||||
"reference": "5647d65443818959172645e7ed999217360654b6"
|
||||
"reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/5647d65443818959172645e7ed999217360654b6",
|
||||
"reference": "5647d65443818959172645e7ed999217360654b6",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c",
|
||||
"reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1668,7 +1668,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
|
||||
"security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.2"
|
||||
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1676,7 +1676,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-05-07T09:13:23+00:00"
|
||||
"time": "2023-08-31T06:24:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-invoker",
|
||||
@ -1743,16 +1743,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-text-template",
|
||||
"version": "3.0.0",
|
||||
"version": "3.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/php-text-template.git",
|
||||
"reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d"
|
||||
"reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/9f3d3709577a527025f55bcf0f7ab8052c8bb37d",
|
||||
"reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748",
|
||||
"reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1790,7 +1790,8 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
|
||||
"source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.0"
|
||||
"security": "https://github.com/sebastianbergmann/php-text-template/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1798,7 +1799,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-03T06:56:46+00:00"
|
||||
"time": "2023-08-31T14:07:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-timer",
|
||||
@ -1861,16 +1862,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "10.3.2",
|
||||
"version": "10.3.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "0dafb1175c366dd274eaa9a625e914451506bcd1"
|
||||
"reference": "747c3b2038f1139e3dcd9886a3f5a948648b7503"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0dafb1175c366dd274eaa9a625e914451506bcd1",
|
||||
"reference": "0dafb1175c366dd274eaa9a625e914451506bcd1",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/747c3b2038f1139e3dcd9886a3f5a948648b7503",
|
||||
"reference": "747c3b2038f1139e3dcd9886a3f5a948648b7503",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1884,7 +1885,7 @@
|
||||
"phar-io/manifest": "^2.0.3",
|
||||
"phar-io/version": "^3.0.2",
|
||||
"php": ">=8.1",
|
||||
"phpunit/php-code-coverage": "^10.1.1",
|
||||
"phpunit/php-code-coverage": "^10.1.5",
|
||||
"phpunit/php-file-iterator": "^4.0",
|
||||
"phpunit/php-invoker": "^4.0",
|
||||
"phpunit/php-text-template": "^3.0",
|
||||
@ -1894,7 +1895,7 @@
|
||||
"sebastian/comparator": "^5.0",
|
||||
"sebastian/diff": "^5.0",
|
||||
"sebastian/environment": "^6.0",
|
||||
"sebastian/exporter": "^5.0",
|
||||
"sebastian/exporter": "^5.1",
|
||||
"sebastian/global-state": "^6.0.1",
|
||||
"sebastian/object-enumerator": "^5.0",
|
||||
"sebastian/recursion-context": "^5.0",
|
||||
@ -1942,7 +1943,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.2"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -1958,7 +1959,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-08-15T05:34:23+00:00"
|
||||
"time": "2023-09-19T05:42:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
@ -2206,16 +2207,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/complexity",
|
||||
"version": "3.0.0",
|
||||
"version": "3.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/complexity.git",
|
||||
"reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6"
|
||||
"reference": "68cfb347a44871f01e33ab0ef8215966432f6957"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/e67d240970c9dc7ea7b2123a6d520e334dd61dc6",
|
||||
"reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68cfb347a44871f01e33ab0ef8215966432f6957",
|
||||
"reference": "68cfb347a44871f01e33ab0ef8215966432f6957",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2228,7 +2229,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.0-dev"
|
||||
"dev-main": "3.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -2251,7 +2252,8 @@
|
||||
"homepage": "https://github.com/sebastianbergmann/complexity",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/complexity/issues",
|
||||
"source": "https://github.com/sebastianbergmann/complexity/tree/3.0.0"
|
||||
"security": "https://github.com/sebastianbergmann/complexity/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/complexity/tree/3.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2259,7 +2261,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-03T06:59:47+00:00"
|
||||
"time": "2023-09-28T11:50:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/diff",
|
||||
@ -2394,16 +2396,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
"version": "5.0.0",
|
||||
"version": "5.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/exporter.git",
|
||||
"reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0"
|
||||
"reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0",
|
||||
"reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/64f51654862e0f5e318db7e9dcc2292c63cdbddc",
|
||||
"reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2417,7 +2419,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "5.0-dev"
|
||||
"dev-main": "5.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@ -2459,7 +2461,8 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/exporter/issues",
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/5.0.0"
|
||||
"security": "https://github.com/sebastianbergmann/exporter/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/exporter/tree/5.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2467,7 +2470,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-03T07:06:49+00:00"
|
||||
"time": "2023-09-24T13:22:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/global-state",
|
||||
@ -2533,16 +2536,16 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/lines-of-code",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
|
||||
"reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130"
|
||||
"reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/17c4d940ecafb3d15d2cf916f4108f664e28b130",
|
||||
"reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d",
|
||||
"reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2578,7 +2581,8 @@
|
||||
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
|
||||
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.0"
|
||||
"security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -2586,7 +2590,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-03T07:08:02+00:00"
|
||||
"time": "2023-08-31T09:25:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/object-enumerator",
|
||||
|
@ -30,6 +30,7 @@ use pocketmine\scheduler\GarbageCollectionTask;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\YmlServerProperties as Yml;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function arsort;
|
||||
use function count;
|
||||
@ -109,7 +110,7 @@ class MemoryManager{
|
||||
}
|
||||
|
||||
private function init(ServerConfigGroup $config) : void{
|
||||
$this->memoryLimit = $config->getPropertyInt("memory.main-limit", 0) * 1024 * 1024;
|
||||
$this->memoryLimit = $config->getPropertyInt(Yml::MEMORY_MAIN_LIMIT, 0) * 1024 * 1024;
|
||||
|
||||
$defaultMemory = 1024;
|
||||
|
||||
@ -127,7 +128,7 @@ class MemoryManager{
|
||||
}
|
||||
}
|
||||
|
||||
$hardLimit = $config->getPropertyInt("memory.main-hard-limit", $defaultMemory);
|
||||
$hardLimit = $config->getPropertyInt(Yml::MEMORY_MAIN_HARD_LIMIT, $defaultMemory);
|
||||
|
||||
if($hardLimit <= 0){
|
||||
ini_set("memory_limit", '-1');
|
||||
@ -135,22 +136,22 @@ class MemoryManager{
|
||||
ini_set("memory_limit", $hardLimit . "M");
|
||||
}
|
||||
|
||||
$this->globalMemoryLimit = $config->getPropertyInt("memory.global-limit", 0) * 1024 * 1024;
|
||||
$this->checkRate = $config->getPropertyInt("memory.check-rate", self::DEFAULT_CHECK_RATE);
|
||||
$this->continuousTrigger = $config->getPropertyBool("memory.continuous-trigger", true);
|
||||
$this->continuousTriggerRate = $config->getPropertyInt("memory.continuous-trigger-rate", self::DEFAULT_CONTINUOUS_TRIGGER_RATE);
|
||||
$this->globalMemoryLimit = $config->getPropertyInt(Yml::MEMORY_GLOBAL_LIMIT, 0) * 1024 * 1024;
|
||||
$this->checkRate = $config->getPropertyInt(Yml::MEMORY_CHECK_RATE, self::DEFAULT_CHECK_RATE);
|
||||
$this->continuousTrigger = $config->getPropertyBool(Yml::MEMORY_CONTINUOUS_TRIGGER, true);
|
||||
$this->continuousTriggerRate = $config->getPropertyInt(Yml::MEMORY_CONTINUOUS_TRIGGER_RATE, self::DEFAULT_CONTINUOUS_TRIGGER_RATE);
|
||||
|
||||
$this->garbageCollectionPeriod = $config->getPropertyInt("memory.garbage-collection.period", self::DEFAULT_TICKS_PER_GC);
|
||||
$this->garbageCollectionTrigger = $config->getPropertyBool("memory.garbage-collection.low-memory-trigger", true);
|
||||
$this->garbageCollectionAsync = $config->getPropertyBool("memory.garbage-collection.collect-async-worker", true);
|
||||
$this->garbageCollectionPeriod = $config->getPropertyInt(Yml::MEMORY_GARBAGE_COLLECTION_PERIOD, self::DEFAULT_TICKS_PER_GC);
|
||||
$this->garbageCollectionTrigger = $config->getPropertyBool(Yml::MEMORY_GARBAGE_COLLECTION_LOW_MEMORY_TRIGGER, true);
|
||||
$this->garbageCollectionAsync = $config->getPropertyBool(Yml::MEMORY_GARBAGE_COLLECTION_COLLECT_ASYNC_WORKER, true);
|
||||
|
||||
$this->lowMemChunkRadiusOverride = $config->getPropertyInt("memory.max-chunks.chunk-radius", 4);
|
||||
$this->lowMemChunkGC = $config->getPropertyBool("memory.max-chunks.trigger-chunk-collect", true);
|
||||
$this->lowMemChunkRadiusOverride = $config->getPropertyInt(Yml::MEMORY_MAX_CHUNKS_CHUNK_RADIUS, 4);
|
||||
$this->lowMemChunkGC = $config->getPropertyBool(Yml::MEMORY_MAX_CHUNKS_TRIGGER_CHUNK_COLLECT, true);
|
||||
|
||||
$this->lowMemDisableChunkCache = $config->getPropertyBool("memory.world-caches.disable-chunk-cache", true);
|
||||
$this->lowMemClearWorldCache = $config->getPropertyBool("memory.world-caches.low-memory-trigger", true);
|
||||
$this->lowMemDisableChunkCache = $config->getPropertyBool(Yml::MEMORY_WORLD_CACHES_DISABLE_CHUNK_CACHE, true);
|
||||
$this->lowMemClearWorldCache = $config->getPropertyBool(Yml::MEMORY_WORLD_CACHES_LOW_MEMORY_TRIGGER, true);
|
||||
|
||||
$this->dumpWorkers = $config->getPropertyBool("memory.memory-dump.dump-async-worker", true);
|
||||
$this->dumpWorkers = $config->getPropertyBool(Yml::MEMORY_MEMORY_DUMP_DUMP_ASYNC_WORKER, true);
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
@ -359,7 +360,7 @@ class MemoryManager{
|
||||
'_SESSION' => true
|
||||
];
|
||||
|
||||
foreach(Utils::stringifyKeys($GLOBALS) as $varName => $value){
|
||||
foreach($GLOBALS as $varName => $value){
|
||||
if(isset($ignoredGlobals[$varName])){
|
||||
continue;
|
||||
}
|
||||
|
163
src/Server.php
163
src/Server.php
@ -80,7 +80,6 @@ use pocketmine\player\PlayerDataProvider;
|
||||
use pocketmine\player\PlayerDataSaveException;
|
||||
use pocketmine\player\PlayerInfo;
|
||||
use pocketmine\plugin\PharPluginLoader;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use pocketmine\plugin\PluginEnableOrder;
|
||||
use pocketmine\plugin\PluginGraylist;
|
||||
use pocketmine\plugin\PluginManager;
|
||||
@ -120,6 +119,7 @@ use pocketmine\world\Position;
|
||||
use pocketmine\world\World;
|
||||
use pocketmine\world\WorldCreationOptions;
|
||||
use pocketmine\world\WorldManager;
|
||||
use pocketmine\YmlServerProperties as Yml;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function array_fill;
|
||||
@ -357,15 +357,15 @@ class Server{
|
||||
}
|
||||
|
||||
public function getPort() : int{
|
||||
return $this->configGroup->getConfigInt("server-port", self::DEFAULT_PORT_IPV4);
|
||||
return $this->configGroup->getConfigInt(ServerProperties::SERVER_PORT_IPV4, self::DEFAULT_PORT_IPV4);
|
||||
}
|
||||
|
||||
public function getPortV6() : int{
|
||||
return $this->configGroup->getConfigInt("server-portv6", self::DEFAULT_PORT_IPV6);
|
||||
return $this->configGroup->getConfigInt(ServerProperties::SERVER_PORT_IPV6, self::DEFAULT_PORT_IPV6);
|
||||
}
|
||||
|
||||
public function getViewDistance() : int{
|
||||
return max(2, $this->configGroup->getConfigInt("view-distance", self::DEFAULT_MAX_VIEW_DISTANCE));
|
||||
return max(2, $this->configGroup->getConfigInt(ServerProperties::VIEW_DISTANCE, self::DEFAULT_MAX_VIEW_DISTANCE));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -376,12 +376,12 @@ class Server{
|
||||
}
|
||||
|
||||
public function getIp() : string{
|
||||
$str = $this->configGroup->getConfigString("server-ip");
|
||||
$str = $this->configGroup->getConfigString(ServerProperties::SERVER_IPV4);
|
||||
return $str !== "" ? $str : "0.0.0.0";
|
||||
}
|
||||
|
||||
public function getIpV6() : string{
|
||||
$str = $this->configGroup->getConfigString("server-ipv6");
|
||||
$str = $this->configGroup->getConfigString(ServerProperties::SERVER_IPV6);
|
||||
return $str !== "" ? $str : "::";
|
||||
}
|
||||
|
||||
@ -390,30 +390,30 @@ class Server{
|
||||
}
|
||||
|
||||
public function getGamemode() : GameMode{
|
||||
return GameMode::fromString($this->configGroup->getConfigString("gamemode", GameMode::SURVIVAL()->name())) ?? GameMode::SURVIVAL();
|
||||
return GameMode::fromString($this->configGroup->getConfigString(ServerProperties::GAME_MODE, GameMode::SURVIVAL()->name())) ?? GameMode::SURVIVAL();
|
||||
}
|
||||
|
||||
public function getForceGamemode() : bool{
|
||||
return $this->configGroup->getConfigBool("force-gamemode", false);
|
||||
return $this->configGroup->getConfigBool(ServerProperties::FORCE_GAME_MODE, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Server global difficulty. Note that this may be overridden in individual worlds.
|
||||
*/
|
||||
public function getDifficulty() : int{
|
||||
return $this->configGroup->getConfigInt("difficulty", World::DIFFICULTY_NORMAL);
|
||||
return $this->configGroup->getConfigInt(ServerProperties::DIFFICULTY, World::DIFFICULTY_NORMAL);
|
||||
}
|
||||
|
||||
public function hasWhitelist() : bool{
|
||||
return $this->configGroup->getConfigBool("white-list", false);
|
||||
return $this->configGroup->getConfigBool(ServerProperties::WHITELIST, false);
|
||||
}
|
||||
|
||||
public function isHardcore() : bool{
|
||||
return $this->configGroup->getConfigBool("hardcore", false);
|
||||
return $this->configGroup->getConfigBool(ServerProperties::HARDCORE, false);
|
||||
}
|
||||
|
||||
public function getMotd() : string{
|
||||
return $this->configGroup->getConfigString("motd", self::DEFAULT_SERVER_NAME);
|
||||
return $this->configGroup->getConfigString(ServerProperties::MOTD, self::DEFAULT_SERVER_NAME);
|
||||
}
|
||||
|
||||
public function getLoader() : ThreadSafeClassLoader{
|
||||
@ -496,7 +496,7 @@ class Server{
|
||||
}
|
||||
|
||||
public function shouldSavePlayerData() : bool{
|
||||
return $this->configGroup->getPropertyBool("player.save-player-data", true);
|
||||
return $this->configGroup->getPropertyBool(Yml::PLAYER_SAVE_PLAYER_DATA, true);
|
||||
}
|
||||
|
||||
public function getOfflinePlayer(string $name) : Player|OfflinePlayer|null{
|
||||
@ -570,6 +570,7 @@ class Server{
|
||||
$playerPromiseResolver = new PromiseResolver();
|
||||
|
||||
$createPlayer = function(Location $location) use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $offlinePlayerData) : void{
|
||||
/** @see Player::__construct() */
|
||||
$player = new $class($this, $session, $playerInfo, $authenticated, $location, $offlinePlayerData);
|
||||
if(!$player->hasPlayedBefore()){
|
||||
$player->onGround = true; //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
|
||||
@ -736,7 +737,7 @@ class Server{
|
||||
* @return string[][]
|
||||
*/
|
||||
public function getCommandAliases() : array{
|
||||
$section = $this->configGroup->getProperty("aliases");
|
||||
$section = $this->configGroup->getProperty(YmlServerProperties::ALIASES);
|
||||
$result = [];
|
||||
if(is_array($section)){
|
||||
foreach($section as $key => $value){
|
||||
@ -811,36 +812,36 @@ class Server{
|
||||
$this->configGroup = new ServerConfigGroup(
|
||||
new Config($pocketmineYmlPath, Config::YAML, []),
|
||||
new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES, [
|
||||
"motd" => self::DEFAULT_SERVER_NAME,
|
||||
"server-port" => self::DEFAULT_PORT_IPV4,
|
||||
"server-portv6" => self::DEFAULT_PORT_IPV6,
|
||||
"enable-ipv6" => true,
|
||||
"white-list" => false,
|
||||
"max-players" => self::DEFAULT_MAX_PLAYERS,
|
||||
"gamemode" => GameMode::SURVIVAL()->name(),
|
||||
"force-gamemode" => false,
|
||||
"hardcore" => false,
|
||||
"pvp" => true,
|
||||
"difficulty" => World::DIFFICULTY_NORMAL,
|
||||
"generator-settings" => "",
|
||||
"level-name" => "world",
|
||||
"level-seed" => "",
|
||||
"level-type" => "DEFAULT",
|
||||
"enable-query" => true,
|
||||
"auto-save" => true,
|
||||
"view-distance" => self::DEFAULT_MAX_VIEW_DISTANCE,
|
||||
"xbox-auth" => true,
|
||||
"language" => "eng"
|
||||
ServerProperties::MOTD => self::DEFAULT_SERVER_NAME,
|
||||
ServerProperties::SERVER_PORT_IPV4 => self::DEFAULT_PORT_IPV4,
|
||||
ServerProperties::SERVER_PORT_IPV6 => self::DEFAULT_PORT_IPV6,
|
||||
ServerProperties::ENABLE_IPV6 => true,
|
||||
ServerProperties::WHITELIST => false,
|
||||
ServerProperties::MAX_PLAYERS => self::DEFAULT_MAX_PLAYERS,
|
||||
ServerProperties::GAME_MODE => GameMode::SURVIVAL()->name(),
|
||||
ServerProperties::FORCE_GAME_MODE => false,
|
||||
ServerProperties::HARDCORE => false,
|
||||
ServerProperties::PVP => true,
|
||||
ServerProperties::DIFFICULTY => World::DIFFICULTY_NORMAL,
|
||||
ServerProperties::DEFAULT_WORLD_GENERATOR_SETTINGS => "",
|
||||
ServerProperties::DEFAULT_WORLD_NAME => "world",
|
||||
ServerProperties::DEFAULT_WORLD_SEED => "",
|
||||
ServerProperties::DEFAULT_WORLD_GENERATOR => "DEFAULT",
|
||||
ServerProperties::ENABLE_QUERY => true,
|
||||
ServerProperties::AUTO_SAVE => true,
|
||||
ServerProperties::VIEW_DISTANCE => self::DEFAULT_MAX_VIEW_DISTANCE,
|
||||
ServerProperties::XBOX_AUTH => true,
|
||||
ServerProperties::LANGUAGE => "eng"
|
||||
])
|
||||
);
|
||||
|
||||
$debugLogLevel = $this->configGroup->getPropertyInt("debug.level", 1);
|
||||
$debugLogLevel = $this->configGroup->getPropertyInt(Yml::DEBUG_LEVEL, 1);
|
||||
if($this->logger instanceof MainLogger){
|
||||
$this->logger->setLogDebug($debugLogLevel > 1);
|
||||
}
|
||||
|
||||
$this->forceLanguage = $this->configGroup->getPropertyBool("settings.force-language", false);
|
||||
$selectedLang = $this->configGroup->getConfigString("language", $this->configGroup->getPropertyString("settings.language", Language::FALLBACK_LANGUAGE));
|
||||
$this->forceLanguage = $this->configGroup->getPropertyBool(Yml::SETTINGS_FORCE_LANGUAGE, false);
|
||||
$selectedLang = $this->configGroup->getConfigString(ServerProperties::LANGUAGE, $this->configGroup->getPropertyString("settings.language", Language::FALLBACK_LANGUAGE));
|
||||
try{
|
||||
$this->language = new Language($selectedLang);
|
||||
}catch(LanguageNotFoundException $e){
|
||||
@ -856,11 +857,11 @@ class Server{
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::language_selected($this->getLanguage()->getName(), $this->getLanguage()->getLang())));
|
||||
|
||||
if(VersionInfo::IS_DEVELOPMENT_BUILD){
|
||||
if(!$this->configGroup->getPropertyBool("settings.enable-dev-builds", false)){
|
||||
if(!$this->configGroup->getPropertyBool(Yml::SETTINGS_ENABLE_DEV_BUILDS, false)){
|
||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error1(VersionInfo::NAME)));
|
||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error2()));
|
||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error3()));
|
||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error4("settings.enable-dev-builds")));
|
||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error4(YmlServerProperties::SETTINGS_ENABLE_DEV_BUILDS)));
|
||||
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error5("https://github.com/pmmp/PocketMine-MP/releases")));
|
||||
$this->forceShutdownExit();
|
||||
|
||||
@ -878,7 +879,7 @@ class Server{
|
||||
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_start(TextFormat::AQUA . $this->getVersion() . TextFormat::RESET)));
|
||||
|
||||
if(($poolSize = $this->configGroup->getPropertyString("settings.async-workers", "auto")) === "auto"){
|
||||
if(($poolSize = $this->configGroup->getPropertyString(Yml::SETTINGS_ASYNC_WORKERS, "auto")) === "auto"){
|
||||
$poolSize = 2;
|
||||
$processors = Utils::getCoreCount() - 2;
|
||||
|
||||
@ -889,32 +890,32 @@ class Server{
|
||||
$poolSize = max(1, (int) $poolSize);
|
||||
}
|
||||
|
||||
$this->asyncPool = new AsyncPool($poolSize, max(-1, $this->configGroup->getPropertyInt("memory.async-worker-hard-limit", 256)), $this->autoloader, $this->logger, $this->tickSleeper);
|
||||
$this->asyncPool = new AsyncPool($poolSize, max(-1, $this->configGroup->getPropertyInt(Yml::MEMORY_ASYNC_WORKER_HARD_LIMIT, 256)), $this->autoloader, $this->logger, $this->tickSleeper);
|
||||
|
||||
$netCompressionThreshold = -1;
|
||||
if($this->configGroup->getPropertyInt("network.batch-threshold", 256) >= 0){
|
||||
$netCompressionThreshold = $this->configGroup->getPropertyInt("network.batch-threshold", 256);
|
||||
if($this->configGroup->getPropertyInt(Yml::NETWORK_BATCH_THRESHOLD, 256) >= 0){
|
||||
$netCompressionThreshold = $this->configGroup->getPropertyInt(Yml::NETWORK_BATCH_THRESHOLD, 256);
|
||||
}
|
||||
if($netCompressionThreshold < 0){
|
||||
$netCompressionThreshold = null;
|
||||
}
|
||||
|
||||
$netCompressionLevel = $this->configGroup->getPropertyInt("network.compression-level", 6);
|
||||
$netCompressionLevel = $this->configGroup->getPropertyInt(Yml::NETWORK_COMPRESSION_LEVEL, 6);
|
||||
if($netCompressionLevel < 1 || $netCompressionLevel > 9){
|
||||
$this->logger->warning("Invalid network compression level $netCompressionLevel set, setting to default 6");
|
||||
$netCompressionLevel = 6;
|
||||
}
|
||||
ZlibCompressor::setInstance(new ZlibCompressor($netCompressionLevel, $netCompressionThreshold, ZlibCompressor::DEFAULT_MAX_DECOMPRESSION_SIZE));
|
||||
|
||||
$this->networkCompressionAsync = $this->configGroup->getPropertyBool("network.async-compression", true);
|
||||
$this->networkCompressionAsync = $this->configGroup->getPropertyBool(Yml::NETWORK_ASYNC_COMPRESSION, true);
|
||||
$this->networkCompressionAsyncThreshold = max(
|
||||
$this->configGroup->getPropertyInt("network.async-compression-threshold", self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD),
|
||||
$this->configGroup->getPropertyInt(Yml::NETWORK_ASYNC_COMPRESSION_THRESHOLD, self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD),
|
||||
$netCompressionThreshold ?? self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD
|
||||
);
|
||||
|
||||
EncryptionContext::$ENABLED = $this->configGroup->getPropertyBool("network.enable-encryption", true);
|
||||
EncryptionContext::$ENABLED = $this->configGroup->getPropertyBool(Yml::NETWORK_ENABLE_ENCRYPTION, true);
|
||||
|
||||
$this->doTitleTick = $this->configGroup->getPropertyBool("console.title-tick", true) && Terminal::hasFormattingCodes();
|
||||
$this->doTitleTick = $this->configGroup->getPropertyBool(Yml::CONSOLE_TITLE_TICK, true) && Terminal::hasFormattingCodes();
|
||||
|
||||
$this->operators = new Config(Path::join($this->dataPath, "ops.txt"), Config::ENUM);
|
||||
$this->whitelist = new Config(Path::join($this->dataPath, "white-list.txt"), Config::ENUM);
|
||||
@ -932,9 +933,9 @@ class Server{
|
||||
$this->banByIP = new BanList($bannedIpsTxt);
|
||||
$this->banByIP->load();
|
||||
|
||||
$this->maxPlayers = $this->configGroup->getConfigInt("max-players", self::DEFAULT_MAX_PLAYERS);
|
||||
$this->maxPlayers = $this->configGroup->getConfigInt(ServerProperties::MAX_PLAYERS, self::DEFAULT_MAX_PLAYERS);
|
||||
|
||||
$this->onlineMode = $this->configGroup->getConfigBool("xbox-auth", true);
|
||||
$this->onlineMode = $this->configGroup->getConfigBool(ServerProperties::XBOX_AUTH, true);
|
||||
if($this->onlineMode){
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_auth_enabled()));
|
||||
}else{
|
||||
@ -943,8 +944,8 @@ class Server{
|
||||
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_authProperty_disabled()));
|
||||
}
|
||||
|
||||
if($this->configGroup->getConfigBool("hardcore", false) && $this->getDifficulty() < World::DIFFICULTY_HARD){
|
||||
$this->configGroup->setConfigInt("difficulty", World::DIFFICULTY_HARD);
|
||||
if($this->configGroup->getConfigBool(ServerProperties::HARDCORE, false) && $this->getDifficulty() < World::DIFFICULTY_HARD){
|
||||
$this->configGroup->setConfigInt(ServerProperties::DIFFICULTY, World::DIFFICULTY_HARD);
|
||||
}
|
||||
|
||||
@cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion());
|
||||
@ -963,8 +964,8 @@ class Server{
|
||||
)));
|
||||
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_license($this->getName())));
|
||||
|
||||
TimingsHandler::setEnabled($this->configGroup->getPropertyBool("settings.enable-profiling", false));
|
||||
$this->profilingTickRate = $this->configGroup->getPropertyInt("settings.profile-report-trigger", self::TARGET_TICKS_PER_SECOND);
|
||||
TimingsHandler::setEnabled($this->configGroup->getPropertyBool(Yml::SETTINGS_ENABLE_PROFILING, false));
|
||||
$this->profilingTickRate = $this->configGroup->getPropertyInt(Yml::SETTINGS_PROFILE_REPORT_TRIGGER, self::TARGET_TICKS_PER_SECOND);
|
||||
|
||||
DefaultPermissions::registerCorePermissions();
|
||||
|
||||
@ -986,13 +987,13 @@ class Server{
|
||||
$this->forceShutdownExit();
|
||||
return;
|
||||
}
|
||||
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool("plugins.legacy-data-dir", true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist);
|
||||
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool(Yml::PLUGINS_LEGACY_DATA_DIR, true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist);
|
||||
$this->pluginManager->registerInterface(new PharPluginLoader($this->autoloader));
|
||||
$this->pluginManager->registerInterface(new ScriptPluginLoader());
|
||||
|
||||
$providerManager = new WorldProviderManager();
|
||||
if(
|
||||
($format = $providerManager->getProviderByName($formatName = $this->configGroup->getPropertyString("level-settings.default-format", ""))) !== null &&
|
||||
($format = $providerManager->getProviderByName($formatName = $this->configGroup->getPropertyString(Yml::LEVEL_SETTINGS_DEFAULT_FORMAT, ""))) !== null &&
|
||||
$format instanceof WritableWorldProviderManagerEntry
|
||||
){
|
||||
$providerManager->setDefault($format);
|
||||
@ -1001,10 +1002,10 @@ class Server{
|
||||
}
|
||||
|
||||
$this->worldManager = new WorldManager($this, Path::join($this->dataPath, "worlds"), $providerManager);
|
||||
$this->worldManager->setAutoSave($this->configGroup->getConfigBool("auto-save", $this->worldManager->getAutoSave()));
|
||||
$this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt("ticks-per.autosave", $this->worldManager->getAutoSaveInterval()));
|
||||
$this->worldManager->setAutoSave($this->configGroup->getConfigBool(ServerProperties::AUTO_SAVE, $this->worldManager->getAutoSave()));
|
||||
$this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt(Yml::TICKS_PER_AUTOSAVE, $this->worldManager->getAutoSaveInterval()));
|
||||
|
||||
$this->updater = new UpdateChecker($this, $this->configGroup->getPropertyString("auto-updater.host", "update.pmmp.io"));
|
||||
$this->updater = new UpdateChecker($this, $this->configGroup->getPropertyString(Yml::AUTO_UPDATER_HOST, "update.pmmp.io"));
|
||||
|
||||
$this->queryInfo = new QueryInfo($this);
|
||||
|
||||
@ -1041,7 +1042,7 @@ class Server{
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){
|
||||
if($this->configGroup->getPropertyBool(Yml::ANONYMOUS_STATISTICS_ENABLED, true)){
|
||||
$this->sendUsageTicker = self::TICKS_PER_STATS_REPORT;
|
||||
$this->sendUsage(SendUsageTask::TYPE_OPEN);
|
||||
}
|
||||
@ -1057,7 +1058,7 @@ class Server{
|
||||
$this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_USERS, $forwarder);
|
||||
|
||||
//TODO: move console parts to a separate component
|
||||
if($this->configGroup->getPropertyBool("console.enable-input", true)){
|
||||
if($this->configGroup->getPropertyBool(Yml::CONSOLE_ENABLE_INPUT, true)){
|
||||
$this->console = new ConsoleReaderChildProcessDaemon($this->logger);
|
||||
}
|
||||
|
||||
@ -1092,7 +1093,7 @@ class Server{
|
||||
|
||||
$anyWorldFailedToLoad = false;
|
||||
|
||||
foreach((array) $this->configGroup->getProperty("worlds", []) as $name => $options){
|
||||
foreach((array) $this->configGroup->getProperty(Yml::WORLDS, []) as $name => $options){
|
||||
if($options === null){
|
||||
$options = [];
|
||||
}elseif(!is_array($options)){
|
||||
@ -1136,11 +1137,11 @@ class Server{
|
||||
}
|
||||
|
||||
if($this->worldManager->getDefaultWorld() === null){
|
||||
$default = $this->configGroup->getConfigString("level-name", "world");
|
||||
$default = $this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_NAME, "world");
|
||||
if(trim($default) == ""){
|
||||
$this->getLogger()->warning("level-name cannot be null, using default");
|
||||
$default = "world";
|
||||
$this->configGroup->setConfigString("level-name", "world");
|
||||
$this->configGroup->setConfigString(ServerProperties::DEFAULT_WORLD_NAME, "world");
|
||||
}
|
||||
if(!$this->worldManager->loadWorld($default, true)){
|
||||
if($this->worldManager->isWorldGenerated($default)){
|
||||
@ -1148,8 +1149,8 @@ class Server{
|
||||
|
||||
return false;
|
||||
}
|
||||
$generatorName = $this->configGroup->getConfigString("level-type");
|
||||
$generatorOptions = $this->configGroup->getConfigString("generator-settings");
|
||||
$generatorName = $this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_GENERATOR);
|
||||
$generatorOptions = $this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_GENERATOR_SETTINGS);
|
||||
$generatorClass = $getGenerator($generatorName, $generatorOptions, $default);
|
||||
|
||||
if($generatorClass === null){
|
||||
@ -1159,7 +1160,7 @@ class Server{
|
||||
$creationOptions = WorldCreationOptions::create()
|
||||
->setGeneratorClass($generatorClass)
|
||||
->setGeneratorOptions($generatorOptions);
|
||||
$convertedSeed = Generator::convertSeed($this->configGroup->getConfigString("level-seed"));
|
||||
$convertedSeed = Generator::convertSeed($this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_SEED));
|
||||
if($convertedSeed !== null){
|
||||
$creationOptions->setSeed($convertedSeed);
|
||||
}
|
||||
@ -1213,7 +1214,7 @@ class Server{
|
||||
}
|
||||
|
||||
private function startupPrepareNetworkInterfaces() : bool{
|
||||
$useQuery = $this->configGroup->getConfigBool("enable-query", true);
|
||||
$useQuery = $this->configGroup->getConfigBool(ServerProperties::ENABLE_QUERY, true);
|
||||
|
||||
$typeConverter = TypeConverter::getInstance();
|
||||
$packetSerializerContext = new PacketSerializerContext($typeConverter->getItemTypeDictionary());
|
||||
@ -1223,7 +1224,7 @@ class Server{
|
||||
if(
|
||||
!$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter) ||
|
||||
(
|
||||
$this->configGroup->getConfigBool("enable-ipv6", true) &&
|
||||
$this->configGroup->getConfigBool(ServerProperties::ENABLE_IPV6, true) &&
|
||||
!$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter)
|
||||
)
|
||||
){
|
||||
@ -1238,7 +1239,7 @@ class Server{
|
||||
$this->network->blockAddress($entry->getName(), -1);
|
||||
}
|
||||
|
||||
if($this->configGroup->getPropertyBool("network.upnp-forwarding", false)){
|
||||
if($this->configGroup->getPropertyBool(Yml::NETWORK_UPNP_FORWARDING, false)){
|
||||
$this->network->registerInterface(new UPnPNetworkInterface($this->logger, Internet::getInternalIP(), $this->getPort()));
|
||||
}
|
||||
|
||||
@ -1258,9 +1259,10 @@ class Server{
|
||||
*/
|
||||
public function unsubscribeFromBroadcastChannel(string $channelId, CommandSender $subscriber) : void{
|
||||
if(isset($this->broadcastSubscribers[$channelId][spl_object_id($subscriber)])){
|
||||
unset($this->broadcastSubscribers[$channelId][spl_object_id($subscriber)]);
|
||||
if(count($this->broadcastSubscribers[$channelId]) === 0){
|
||||
if(count($this->broadcastSubscribers[$channelId]) === 1){
|
||||
unset($this->broadcastSubscribers[$channelId]);
|
||||
}else{
|
||||
unset($this->broadcastSubscribers[$channelId][spl_object_id($subscriber)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1458,7 +1460,7 @@ class Server{
|
||||
}
|
||||
|
||||
if(isset($this->network)){
|
||||
$this->network->getSessionManager()->close($this->configGroup->getPropertyString("settings.shutdown-message", "Server closed"));
|
||||
$this->network->getSessionManager()->close($this->configGroup->getPropertyString(YmlServerProperties::SETTINGS_SHUTDOWN_MESSAGE, "Server closed"));
|
||||
}
|
||||
|
||||
if(isset($this->worldManager)){
|
||||
@ -1595,7 +1597,7 @@ class Server{
|
||||
|
||||
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_submit($crashDumpPath)));
|
||||
|
||||
if($this->configGroup->getPropertyBool("auto-report.enabled", true)){
|
||||
if($this->configGroup->getPropertyBool(Yml::AUTO_REPORT_ENABLED, true)){
|
||||
$report = true;
|
||||
|
||||
$stamp = Path::join($this->getDataPath(), "crashdumps", ".last_crash");
|
||||
@ -1606,15 +1608,6 @@ class Server{
|
||||
}
|
||||
@touch($stamp); //update file timestamp
|
||||
|
||||
$plugin = $dump->getData()->plugin;
|
||||
if($plugin !== ""){
|
||||
$p = $this->pluginManager->getPlugin($plugin);
|
||||
if($p instanceof Plugin && !($p->getPluginLoader() instanceof PharPluginLoader)){
|
||||
$this->logger->debug("Not sending crashdump due to caused by non-phar plugin");
|
||||
$report = false;
|
||||
}
|
||||
}
|
||||
|
||||
if($dump->getData()->error["type"] === \ParseError::class){
|
||||
$report = false;
|
||||
}
|
||||
@ -1625,7 +1618,7 @@ class Server{
|
||||
}
|
||||
|
||||
if($report){
|
||||
$url = ($this->configGroup->getPropertyBool("auto-report.use-https", true) ? "https" : "http") . "://" . $this->configGroup->getPropertyString("auto-report.host", "crash.pmmp.io") . "/submit/api";
|
||||
$url = ($this->configGroup->getPropertyBool(Yml::AUTO_REPORT_USE_HTTPS, true) ? "https" : "http") . "://" . $this->configGroup->getPropertyString(Yml::AUTO_REPORT_HOST, "crash.pmmp.io") . "/submit/api";
|
||||
$postUrlError = "Unknown error";
|
||||
$reply = Internet::postURL($url, [
|
||||
"report" => "yes",
|
||||
@ -1736,7 +1729,7 @@ class Server{
|
||||
}
|
||||
|
||||
public function sendUsage(int $type = SendUsageTask::TYPE_STATUS) : void{
|
||||
if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){
|
||||
if($this->configGroup->getPropertyBool(Yml::ANONYMOUS_STATISTICS_ENABLED, true)){
|
||||
$this->asyncPool->submitTask(new SendUsageTask($this, $type, $this->uniquePlayers));
|
||||
}
|
||||
$this->uniquePlayers = [];
|
||||
|
58
src/ServerProperties.php
Normal file
58
src/ServerProperties.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Constants for all properties available in server.properties.
|
||||
*/
|
||||
final class ServerProperties{
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
public const AUTO_SAVE = "auto-save";
|
||||
public const DEFAULT_WORLD_GENERATOR = "level-type";
|
||||
public const DEFAULT_WORLD_GENERATOR_SETTINGS = "generator-settings";
|
||||
public const DEFAULT_WORLD_NAME = "level-name";
|
||||
public const DEFAULT_WORLD_SEED = "level-seed";
|
||||
public const DIFFICULTY = "difficulty";
|
||||
public const ENABLE_IPV6 = "enable-ipv6";
|
||||
public const ENABLE_QUERY = "enable-query";
|
||||
public const FORCE_GAME_MODE = "force-gamemode";
|
||||
public const GAME_MODE = "gamemode";
|
||||
public const HARDCORE = "hardcore";
|
||||
public const LANGUAGE = "language";
|
||||
public const MAX_PLAYERS = "max-players";
|
||||
public const MOTD = "motd";
|
||||
public const PVP = "pvp";
|
||||
public const SERVER_IPV4 = "server-ip";
|
||||
public const SERVER_IPV6 = "server-ipv6";
|
||||
public const SERVER_PORT_IPV4 = "server-port";
|
||||
public const SERVER_PORT_IPV6 = "server-portv6";
|
||||
public const VIEW_DISTANCE = "view-distance";
|
||||
public const WHITELIST = "white-list";
|
||||
public const XBOX_AUTH = "xbox-auth";
|
||||
}
|
@ -31,9 +31,9 @@ use function str_repeat;
|
||||
|
||||
final class VersionInfo{
|
||||
public const NAME = "PocketMine-MP";
|
||||
public const BASE_VERSION = "5.5.0-BETA1";
|
||||
public const BASE_VERSION = "5.7.1";
|
||||
public const IS_DEVELOPMENT_BUILD = false;
|
||||
public const BUILD_CHANNEL = "beta";
|
||||
public const BUILD_CHANNEL = "stable";
|
||||
|
||||
/**
|
||||
* PocketMine-MP-specific version ID for world data. Used to determine what fixes need to be applied to old world
|
||||
|
118
src/YmlServerProperties.php
Normal file
118
src/YmlServerProperties.php
Normal file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Constants for all properties available in pocketmine.yml.
|
||||
* This is generated by build/generate-pocketmine-yml-property-consts.php.
|
||||
* Do not edit this file manually.
|
||||
*/
|
||||
final class YmlServerProperties{
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
public const ALIASES = 'aliases';
|
||||
public const ANONYMOUS_STATISTICS = 'anonymous-statistics';
|
||||
public const ANONYMOUS_STATISTICS_ENABLED = 'anonymous-statistics.enabled';
|
||||
public const ANONYMOUS_STATISTICS_HOST = 'anonymous-statistics.host';
|
||||
public const AUTO_REPORT = 'auto-report';
|
||||
public const AUTO_REPORT_ENABLED = 'auto-report.enabled';
|
||||
public const AUTO_REPORT_HOST = 'auto-report.host';
|
||||
public const AUTO_REPORT_SEND_CODE = 'auto-report.send-code';
|
||||
public const AUTO_REPORT_SEND_PHPINFO = 'auto-report.send-phpinfo';
|
||||
public const AUTO_REPORT_SEND_SETTINGS = 'auto-report.send-settings';
|
||||
public const AUTO_REPORT_USE_HTTPS = 'auto-report.use-https';
|
||||
public const AUTO_UPDATER = 'auto-updater';
|
||||
public const AUTO_UPDATER_ENABLED = 'auto-updater.enabled';
|
||||
public const AUTO_UPDATER_HOST = 'auto-updater.host';
|
||||
public const AUTO_UPDATER_ON_UPDATE = 'auto-updater.on-update';
|
||||
public const AUTO_UPDATER_ON_UPDATE_WARN_CONSOLE = 'auto-updater.on-update.warn-console';
|
||||
public const AUTO_UPDATER_PREFERRED_CHANNEL = 'auto-updater.preferred-channel';
|
||||
public const AUTO_UPDATER_SUGGEST_CHANNELS = 'auto-updater.suggest-channels';
|
||||
public const CHUNK_GENERATION = 'chunk-generation';
|
||||
public const CHUNK_GENERATION_POPULATION_QUEUE_SIZE = 'chunk-generation.population-queue-size';
|
||||
public const CHUNK_SENDING = 'chunk-sending';
|
||||
public const CHUNK_SENDING_PER_TICK = 'chunk-sending.per-tick';
|
||||
public const CHUNK_SENDING_SPAWN_RADIUS = 'chunk-sending.spawn-radius';
|
||||
public const CHUNK_TICKING = 'chunk-ticking';
|
||||
public const CHUNK_TICKING_BLOCKS_PER_SUBCHUNK_PER_TICK = 'chunk-ticking.blocks-per-subchunk-per-tick';
|
||||
public const CHUNK_TICKING_DISABLE_BLOCK_TICKING = 'chunk-ticking.disable-block-ticking';
|
||||
public const CHUNK_TICKING_TICK_RADIUS = 'chunk-ticking.tick-radius';
|
||||
public const CONSOLE = 'console';
|
||||
public const CONSOLE_ENABLE_INPUT = 'console.enable-input';
|
||||
public const CONSOLE_TITLE_TICK = 'console.title-tick';
|
||||
public const DEBUG = 'debug';
|
||||
public const DEBUG_LEVEL = 'debug.level';
|
||||
public const LEVEL_SETTINGS = 'level-settings';
|
||||
public const LEVEL_SETTINGS_DEFAULT_FORMAT = 'level-settings.default-format';
|
||||
public const MEMORY = 'memory';
|
||||
public const MEMORY_ASYNC_WORKER_HARD_LIMIT = 'memory.async-worker-hard-limit';
|
||||
public const MEMORY_CHECK_RATE = 'memory.check-rate';
|
||||
public const MEMORY_CONTINUOUS_TRIGGER = 'memory.continuous-trigger';
|
||||
public const MEMORY_CONTINUOUS_TRIGGER_RATE = 'memory.continuous-trigger-rate';
|
||||
public const MEMORY_GARBAGE_COLLECTION = 'memory.garbage-collection';
|
||||
public const MEMORY_GARBAGE_COLLECTION_COLLECT_ASYNC_WORKER = 'memory.garbage-collection.collect-async-worker';
|
||||
public const MEMORY_GARBAGE_COLLECTION_LOW_MEMORY_TRIGGER = 'memory.garbage-collection.low-memory-trigger';
|
||||
public const MEMORY_GARBAGE_COLLECTION_PERIOD = 'memory.garbage-collection.period';
|
||||
public const MEMORY_GLOBAL_LIMIT = 'memory.global-limit';
|
||||
public const MEMORY_MAIN_HARD_LIMIT = 'memory.main-hard-limit';
|
||||
public const MEMORY_MAIN_LIMIT = 'memory.main-limit';
|
||||
public const MEMORY_MAX_CHUNKS = 'memory.max-chunks';
|
||||
public const MEMORY_MAX_CHUNKS_CHUNK_RADIUS = 'memory.max-chunks.chunk-radius';
|
||||
public const MEMORY_MAX_CHUNKS_TRIGGER_CHUNK_COLLECT = 'memory.max-chunks.trigger-chunk-collect';
|
||||
public const MEMORY_MEMORY_DUMP = 'memory.memory-dump';
|
||||
public const MEMORY_MEMORY_DUMP_DUMP_ASYNC_WORKER = 'memory.memory-dump.dump-async-worker';
|
||||
public const MEMORY_WORLD_CACHES = 'memory.world-caches';
|
||||
public const MEMORY_WORLD_CACHES_DISABLE_CHUNK_CACHE = 'memory.world-caches.disable-chunk-cache';
|
||||
public const MEMORY_WORLD_CACHES_LOW_MEMORY_TRIGGER = 'memory.world-caches.low-memory-trigger';
|
||||
public const NETWORK = 'network';
|
||||
public const NETWORK_ASYNC_COMPRESSION = 'network.async-compression';
|
||||
public const NETWORK_ASYNC_COMPRESSION_THRESHOLD = 'network.async-compression-threshold';
|
||||
public const NETWORK_BATCH_THRESHOLD = 'network.batch-threshold';
|
||||
public const NETWORK_COMPRESSION_LEVEL = 'network.compression-level';
|
||||
public const NETWORK_ENABLE_ENCRYPTION = 'network.enable-encryption';
|
||||
public const NETWORK_MAX_MTU_SIZE = 'network.max-mtu-size';
|
||||
public const NETWORK_UPNP_FORWARDING = 'network.upnp-forwarding';
|
||||
public const PLAYER = 'player';
|
||||
public const PLAYER_SAVE_PLAYER_DATA = 'player.save-player-data';
|
||||
public const PLAYER_VERIFY_XUID = 'player.verify-xuid';
|
||||
public const PLUGINS = 'plugins';
|
||||
public const PLUGINS_LEGACY_DATA_DIR = 'plugins.legacy-data-dir';
|
||||
public const SETTINGS = 'settings';
|
||||
public const SETTINGS_ASYNC_WORKERS = 'settings.async-workers';
|
||||
public const SETTINGS_ENABLE_DEV_BUILDS = 'settings.enable-dev-builds';
|
||||
public const SETTINGS_ENABLE_PROFILING = 'settings.enable-profiling';
|
||||
public const SETTINGS_FORCE_LANGUAGE = 'settings.force-language';
|
||||
public const SETTINGS_PROFILE_REPORT_TRIGGER = 'settings.profile-report-trigger';
|
||||
public const SETTINGS_QUERY_PLUGINS = 'settings.query-plugins';
|
||||
public const SETTINGS_SHUTDOWN_MESSAGE = 'settings.shutdown-message';
|
||||
public const TICKS_PER = 'ticks-per';
|
||||
public const TICKS_PER_AUTOSAVE = 'ticks-per.autosave';
|
||||
public const TIMINGS = 'timings';
|
||||
public const TIMINGS_HOST = 'timings.host';
|
||||
public const WORLDS = 'worlds';
|
||||
}
|
@ -271,4 +271,8 @@ abstract class BaseSign extends Transparent{
|
||||
public function asItem() : Item{
|
||||
return ($this->asItemCallback)();
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return $this->woodType->isFlammable() ? 200 : 0;
|
||||
}
|
||||
}
|
||||
|
@ -117,10 +117,10 @@ class Cactus extends Transparent{
|
||||
}
|
||||
}
|
||||
$this->age = 0;
|
||||
$world->setBlock($this->position, $this);
|
||||
$world->setBlock($this->position, $this, update: false);
|
||||
}else{
|
||||
++$this->age;
|
||||
$world->setBlock($this->position, $this);
|
||||
$world->setBlock($this->position, $this, update: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,8 @@ class CaveVines extends Flowable{
|
||||
}
|
||||
|
||||
private function canBeSupportedAt(Block $block) : bool{
|
||||
return $block->getAdjacentSupportType(Facing::UP)->equals(SupportType::FULL()) || $block->hasSameTypeId($this);
|
||||
$supportBlock = $block->getSide(Facing::UP);
|
||||
return $supportBlock->getSupportType(Facing::DOWN)->equals(SupportType::FULL()) || $supportBlock->hasSameTypeId($this);
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
|
@ -66,13 +66,19 @@ class DeadBush extends Flowable{
|
||||
}
|
||||
|
||||
private function canBeSupportedBy(Block $block) : bool{
|
||||
$blockId = $block->getTypeId();
|
||||
return $blockId === BlockTypeIds::SAND
|
||||
|| $blockId === BlockTypeIds::RED_SAND
|
||||
|| $blockId === BlockTypeIds::PODZOL
|
||||
|| $blockId === BlockTypeIds::MYCELIUM
|
||||
|| $blockId === BlockTypeIds::DIRT
|
||||
|| $blockId === BlockTypeIds::HARDENED_CLAY
|
||||
|| $blockId === BlockTypeIds::STAINED_CLAY;
|
||||
return
|
||||
$block->hasTypeTag(BlockTypeTags::SAND) ||
|
||||
$block->hasTypeTag(BlockTypeTags::MUD) ||
|
||||
match($block->getTypeId()){
|
||||
//can't use DIRT tag here because it includes farmland
|
||||
BlockTypeIds::PODZOL,
|
||||
BlockTypeIds::MYCELIUM,
|
||||
BlockTypeIds::DIRT,
|
||||
BlockTypeIds::GRASS,
|
||||
BlockTypeIds::HARDENED_CLAY,
|
||||
BlockTypeIds::STAINED_CLAY => true,
|
||||
//TODO: moss block
|
||||
default => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,12 @@ class Dirt extends Opaque{
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
$world = $this->position->getWorld();
|
||||
if($face === Facing::UP && $item instanceof Hoe){
|
||||
if($face !== Facing::DOWN && $item instanceof Hoe){
|
||||
$up = $this->getSide(Facing::UP);
|
||||
if($up->getTypeId() !== BlockTypeIds::AIR){
|
||||
return true;
|
||||
}
|
||||
|
||||
$item->applyDamage(1);
|
||||
|
||||
$newBlock = $this->dirtType->equals(DirtType::NORMAL()) ? VanillaBlocks::FARMLAND() : VanillaBlocks::DIRT();
|
||||
|
@ -42,7 +42,7 @@ class Fence extends Transparent{
|
||||
|
||||
foreach(Facing::HORIZONTAL as $facing){
|
||||
$block = $this->getSide($facing);
|
||||
if($block instanceof static || $block instanceof FenceGate || ($block->isSolid() && !$block->isTransparent())){
|
||||
if($block instanceof static || $block instanceof FenceGate || $block->getSupportType(Facing::opposite($facing))->equals(SupportType::FULL())){
|
||||
$this->connections[$facing] = true;
|
||||
}else{
|
||||
unset($this->connections[$facing]);
|
||||
|
@ -82,7 +82,7 @@ class Grass extends Opaque{
|
||||
}
|
||||
|
||||
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
|
||||
if($face !== Facing::UP){
|
||||
if($this->getSide(Facing::UP)->getTypeId() !== BlockTypeIds::AIR){
|
||||
return false;
|
||||
}
|
||||
$world = $this->position->getWorld();
|
||||
@ -91,20 +91,23 @@ class Grass extends Opaque{
|
||||
TallGrassObject::growGrass($world, $this->position, new Random(mt_rand()), 8, 2);
|
||||
|
||||
return true;
|
||||
}elseif($item instanceof Hoe){
|
||||
$item->applyDamage(1);
|
||||
$newBlock = VanillaBlocks::FARMLAND();
|
||||
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
|
||||
$world->setBlock($this->position, $newBlock);
|
||||
}
|
||||
if($face !== Facing::DOWN){
|
||||
if($item instanceof Hoe){
|
||||
$item->applyDamage(1);
|
||||
$newBlock = VanillaBlocks::FARMLAND();
|
||||
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
|
||||
$world->setBlock($this->position, $newBlock);
|
||||
|
||||
return true;
|
||||
}elseif($item instanceof Shovel && $this->getSide(Facing::UP)->getTypeId() === BlockTypeIds::AIR){
|
||||
$item->applyDamage(1);
|
||||
$newBlock = VanillaBlocks::GRASS_PATH();
|
||||
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
|
||||
$world->setBlock($this->position, $newBlock);
|
||||
return true;
|
||||
}elseif($item instanceof Shovel){
|
||||
$item->applyDamage(1);
|
||||
$newBlock = VanillaBlocks::GRASS_PATH();
|
||||
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
|
||||
$world->setBlock($this->position, $newBlock);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -32,19 +32,19 @@ use pocketmine\world\BlockTransaction;
|
||||
|
||||
final class HangingRoots extends Flowable{
|
||||
|
||||
private function canBeSupportedBy(Block $block) : bool{
|
||||
return $block->isSolid(); //TODO: not sure if this is the correct logic
|
||||
private function canBeSupportedAt(Block $block) : bool{
|
||||
return $block->getAdjacentSupportType(Facing::UP)->hasCenterSupport(); //weird I know, but they can be placed on the bottom of fences
|
||||
}
|
||||
|
||||
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
|
||||
if(!$blockReplace->getSide(Facing::UP)->isSolid()){
|
||||
if(!$this->canBeSupportedAt($blockReplace)){
|
||||
return false;
|
||||
}
|
||||
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
|
||||
}
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
if(!$this->canBeSupportedBy($this->getSide(Facing::UP))){
|
||||
if(!$this->canBeSupportedAt($this)){
|
||||
$this->position->getWorld()->useBreakOn($this->position);
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ class Thin extends Transparent{
|
||||
|
||||
foreach(Facing::HORIZONTAL as $facing){
|
||||
$side = $this->getSide($facing);
|
||||
if($side instanceof Thin || $side instanceof Wall || $side->isFullCube()){
|
||||
if($side instanceof Thin || $side instanceof Wall || $side->getSupportType(Facing::opposite($facing))->equals(SupportType::FULL())){
|
||||
$this->connections[$facing] = true;
|
||||
}else{
|
||||
unset($this->connections[$facing]);
|
||||
|
@ -101,7 +101,7 @@ class Wall extends Transparent{
|
||||
|
||||
foreach(Facing::HORIZONTAL as $facing){
|
||||
$block = $this->getSide($facing);
|
||||
if($block instanceof static || $block instanceof FenceGate || $block instanceof Thin || ($block->isSolid() && !$block->isTransparent())){
|
||||
if($block instanceof static || $block instanceof FenceGate || $block instanceof Thin || $block->getSupportType(Facing::opposite($facing))->equals(SupportType::FULL())){
|
||||
if(!isset($this->connections[$facing])){
|
||||
$this->connections[$facing] = WallConnectionType::SHORT();
|
||||
$changed++;
|
||||
|
@ -35,4 +35,8 @@ class WoodenButton extends Button{
|
||||
public function hasEntityCollision() : bool{
|
||||
return false; //TODO: arrows activate wooden buttons
|
||||
}
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return $this->woodType->isFlammable() ? 100 : 0;
|
||||
}
|
||||
}
|
||||
|
@ -27,4 +27,8 @@ use pocketmine\block\utils\WoodTypeTrait;
|
||||
|
||||
class WoodenDoor extends Door{
|
||||
use WoodTypeTrait;
|
||||
|
||||
public function getFuelTime() : int{
|
||||
return $this->woodType->isFlammable() ? 200 : 0;
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,6 @@ final class SmithingTableInventory extends SimpleInventory implements BlockInven
|
||||
|
||||
public function __construct(Position $holder){
|
||||
$this->holder = $holder;
|
||||
parent::__construct(2);
|
||||
parent::__construct(3);
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\GameMode;
|
||||
use pocketmine\ServerProperties;
|
||||
use function count;
|
||||
|
||||
class DefaultGamemodeCommand extends VanillaCommand{
|
||||
@ -52,7 +53,7 @@ class DefaultGamemodeCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
$sender->getServer()->getConfigGroup()->setConfigString("gamemode", $gameMode->name());
|
||||
$sender->getServer()->getConfigGroup()->setConfigString(ServerProperties::GAME_MODE, $gameMode->name());
|
||||
$sender->sendMessage(KnownTranslationFactory::commands_defaultgamemode_success($gameMode->getTranslatableName()));
|
||||
return true;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\ServerProperties;
|
||||
use pocketmine\world\World;
|
||||
use function count;
|
||||
|
||||
@ -54,7 +55,7 @@ class DifficultyCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
if($difficulty !== -1){
|
||||
$sender->getServer()->getConfigGroup()->setConfigInt("difficulty", $difficulty);
|
||||
$sender->getServer()->getConfigGroup()->setConfigInt(ServerProperties::DIFFICULTY, $difficulty);
|
||||
|
||||
//TODO: add per-world support
|
||||
foreach($sender->getServer()->getWorldManager()->getWorlds() as $world){
|
||||
|
@ -35,6 +35,7 @@ use pocketmine\timings\TimingsHandler;
|
||||
use pocketmine\utils\InternetException;
|
||||
use pocketmine\utils\InternetRequestResult;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\YmlServerProperties;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function count;
|
||||
use function fclose;
|
||||
@ -130,7 +131,7 @@ class TimingsCommand extends VanillaCommand{
|
||||
];
|
||||
fclose($fileTimings);
|
||||
|
||||
$host = $sender->getServer()->getConfigGroup()->getPropertyString("timings.host", "timings.pmmp.io");
|
||||
$host = $sender->getServer()->getConfigGroup()->getPropertyString(YmlServerProperties::TIMINGS_HOST, "timings.pmmp.io");
|
||||
|
||||
$sender->getServer()->getAsyncPool()->submitTask(new BulkCurlTask(
|
||||
[new BulkCurlTaskOperation(
|
||||
|
@ -30,6 +30,7 @@ use pocketmine\lang\KnownTranslationFactory;
|
||||
use pocketmine\permission\DefaultPermissionNames;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\ServerProperties;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function sort;
|
||||
@ -71,7 +72,7 @@ class WhitelistCommand extends VanillaCommand{
|
||||
case "on":
|
||||
if($this->testPermission($sender, DefaultPermissionNames::COMMAND_WHITELIST_ENABLE)){
|
||||
$server = $sender->getServer();
|
||||
$server->getConfigGroup()->setConfigBool("white-list", true);
|
||||
$server->getConfigGroup()->setConfigBool(ServerProperties::WHITELIST, true);
|
||||
$this->kickNonWhitelistedPlayers($server);
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_whitelist_enabled());
|
||||
}
|
||||
@ -79,7 +80,7 @@ class WhitelistCommand extends VanillaCommand{
|
||||
return true;
|
||||
case "off":
|
||||
if($this->testPermission($sender, DefaultPermissionNames::COMMAND_WHITELIST_DISABLE)){
|
||||
$sender->getServer()->getConfigGroup()->setConfigBool("white-list", false);
|
||||
$sender->getServer()->getConfigGroup()->setConfigBool(ServerProperties::WHITELIST, false);
|
||||
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_whitelist_disabled());
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Filesystem;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\VersionInfo;
|
||||
use pocketmine\YmlServerProperties;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use function array_map;
|
||||
use function base64_encode;
|
||||
@ -152,7 +153,7 @@ class CrashDump{
|
||||
private function extraData() : void{
|
||||
global $argv;
|
||||
|
||||
if($this->server->getConfigGroup()->getPropertyBool("auto-report.send-settings", true)){
|
||||
if($this->server->getConfigGroup()->getPropertyBool(YmlServerProperties::AUTO_REPORT_SEND_SETTINGS, true)){
|
||||
$this->data->parameters = (array) $argv;
|
||||
if(($serverDotProperties = @file_get_contents(Path::join($this->server->getDataPath(), "server.properties"))) !== false){
|
||||
$this->data->serverDotProperties = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $serverDotProperties) ?? throw new AssumptionFailedError("Pattern is valid");
|
||||
@ -170,7 +171,7 @@ class CrashDump{
|
||||
|
||||
$this->data->jit_mode = Utils::getOpcacheJitMode();
|
||||
|
||||
if($this->server->getConfigGroup()->getPropertyBool("auto-report.send-phpinfo", true)){
|
||||
if($this->server->getConfigGroup()->getPropertyBool(YmlServerProperties::AUTO_REPORT_SEND_PHPINFO, true)){
|
||||
ob_start();
|
||||
phpinfo();
|
||||
$this->data->phpinfo = ob_get_contents(); // @phpstan-ignore-line
|
||||
@ -206,6 +207,7 @@ class CrashDump{
|
||||
if(isset($lastError)){
|
||||
$this->data->lastError = $lastError;
|
||||
$this->data->lastError["message"] = mb_scrub($this->data->lastError["message"], 'UTF-8');
|
||||
$this->data->lastError["trace"] = array_map(array: $lastError["trace"], callback: fn(ThreadCrashInfoFrame $frame) => $frame->getPrintableFrame());
|
||||
}
|
||||
|
||||
$this->data->error = $error;
|
||||
@ -225,7 +227,7 @@ class CrashDump{
|
||||
}
|
||||
}
|
||||
|
||||
if($this->server->getConfigGroup()->getPropertyBool("auto-report.send-code", true) && file_exists($error["fullFile"])){
|
||||
if($this->server->getConfigGroup()->getPropertyBool(YmlServerProperties::AUTO_REPORT_SEND_CODE, true) && file_exists($error["fullFile"])){
|
||||
$file = @file($error["fullFile"], FILE_IGNORE_NEW_LINES);
|
||||
if($file !== false){
|
||||
for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10 && isset($file[$l]); ++$l){
|
||||
|
@ -29,18 +29,10 @@ use pocketmine\utils\SingletonTrait;
|
||||
|
||||
final class DyeColorIdMap{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var DyeColor[]
|
||||
* @phpstan-var array<int, DyeColor>
|
||||
*/
|
||||
private array $idToEnum = [];
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private array $enumToId = [];
|
||||
/** @phpstan-use IntSaveIdMapTrait<DyeColor> */
|
||||
use IntSaveIdMapTrait {
|
||||
register as registerInt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var DyeColor[]
|
||||
@ -74,16 +66,11 @@ final class DyeColorIdMap{
|
||||
}
|
||||
|
||||
private function register(int $id, string $itemId, DyeColor $color) : void{
|
||||
$this->idToEnum[$id] = $color;
|
||||
$this->enumToId[$color->id()] = $id;
|
||||
$this->registerInt($id, $color);
|
||||
$this->itemIdToEnum[$itemId] = $color;
|
||||
$this->enumToItemId[$color->id()] = $itemId;
|
||||
}
|
||||
|
||||
public function toId(DyeColor $color) : int{
|
||||
return $this->enumToId[$color->id()]; //TODO: is it possible for this to be missing?
|
||||
}
|
||||
|
||||
public function toInvertedId(DyeColor $color) : int{
|
||||
return ~$this->toId($color) & 0xf;
|
||||
}
|
||||
@ -92,10 +79,6 @@ final class DyeColorIdMap{
|
||||
return $this->enumToItemId[$color->id()];
|
||||
}
|
||||
|
||||
public function fromId(int $id) : ?DyeColor{
|
||||
return $this->idToEnum[$id] ?? null;
|
||||
}
|
||||
|
||||
public function fromInvertedId(int $id) : ?DyeColor{
|
||||
return $this->fromId(~$id & 0xf);
|
||||
}
|
||||
|
@ -26,23 +26,11 @@ namespace pocketmine\data\bedrock;
|
||||
use pocketmine\entity\effect\Effect;
|
||||
use pocketmine\entity\effect\VanillaEffects;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use function array_key_exists;
|
||||
use function spl_object_id;
|
||||
|
||||
final class EffectIdMap{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var Effect[]
|
||||
* @phpstan-var array<int, Effect>
|
||||
*/
|
||||
private array $idToEffect = [];
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private array $effectToId = [];
|
||||
/** @phpstan-use IntSaveIdMapTrait<Effect> */
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
$this->register(EffectIds::SPEED, VanillaEffects::SPEED());
|
||||
@ -76,24 +64,4 @@ final class EffectIdMap{
|
||||
//TODO: VILLAGE_HERO
|
||||
$this->register(EffectIds::DARKNESS, VanillaEffects::DARKNESS());
|
||||
}
|
||||
|
||||
//TODO: not a big fan of the code duplication here :(
|
||||
|
||||
public function register(int $mcpeId, Effect $effect) : void{
|
||||
$this->idToEffect[$mcpeId] = $effect;
|
||||
$this->effectToId[spl_object_id($effect)] = $mcpeId;
|
||||
}
|
||||
|
||||
public function fromId(int $id) : ?Effect{
|
||||
//we might not have all the effect IDs registered
|
||||
return $this->idToEffect[$id] ?? null;
|
||||
}
|
||||
|
||||
public function toId(Effect $effect) : int{
|
||||
if(!array_key_exists(spl_object_id($effect), $this->effectToId)){
|
||||
//this should never happen, so we treat it as an exceptional condition
|
||||
throw new \InvalidArgumentException("Effect does not have a mapped ID");
|
||||
}
|
||||
return $this->effectToId[spl_object_id($effect)];
|
||||
}
|
||||
}
|
||||
|
@ -26,25 +26,14 @@ namespace pocketmine\data\bedrock;
|
||||
use pocketmine\item\enchantment\Enchantment;
|
||||
use pocketmine\item\enchantment\VanillaEnchantments;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use function array_key_exists;
|
||||
use function spl_object_id;
|
||||
|
||||
/**
|
||||
* Handles translation of internal enchantment types to and from Minecraft: Bedrock IDs.
|
||||
*/
|
||||
final class EnchantmentIdMap{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var Enchantment[]
|
||||
* @phpstan-var array<int, Enchantment>
|
||||
*/
|
||||
private array $idToEnch = [];
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private array $enchToId = [];
|
||||
/** @phpstan-use IntSaveIdMapTrait<Enchantment> */
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
$this->register(EnchantmentIds::PROTECTION, VanillaEnchantments::PROTECTION());
|
||||
@ -77,22 +66,4 @@ final class EnchantmentIdMap{
|
||||
|
||||
$this->register(EnchantmentIds::SWIFT_SNEAK, VanillaEnchantments::SWIFT_SNEAK());
|
||||
}
|
||||
|
||||
public function register(int $mcpeId, Enchantment $enchantment) : void{
|
||||
$this->idToEnch[$mcpeId] = $enchantment;
|
||||
$this->enchToId[spl_object_id($enchantment)] = $mcpeId;
|
||||
}
|
||||
|
||||
public function fromId(int $id) : ?Enchantment{
|
||||
//we might not have all the enchantment IDs registered
|
||||
return $this->idToEnch[$id] ?? null;
|
||||
}
|
||||
|
||||
public function toId(Enchantment $enchantment) : int{
|
||||
if(!array_key_exists(spl_object_id($enchantment), $this->enchToId)){
|
||||
//this should never happen, so we treat it as an exceptional condition
|
||||
throw new \InvalidArgumentException("Enchantment does not have a mapped ID");
|
||||
}
|
||||
return $this->enchToId[spl_object_id($enchantment)];
|
||||
}
|
||||
}
|
||||
|
81
src/data/bedrock/IntSaveIdMapTrait.php
Normal file
81
src/data/bedrock/IntSaveIdMapTrait.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\data\bedrock;
|
||||
|
||||
use function array_key_exists;
|
||||
use function spl_object_id;
|
||||
|
||||
/**
|
||||
* @phpstan-template TObject of object
|
||||
*/
|
||||
trait IntSaveIdMapTrait{
|
||||
|
||||
/**
|
||||
* @var object[]
|
||||
* @phpstan-var array<int, TObject>
|
||||
*/
|
||||
private array $idToEnum = [];
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private array $enumToId = [];
|
||||
|
||||
/**
|
||||
* @phpstan-param TObject $enum
|
||||
*/
|
||||
protected function getRuntimeId(object $enum) : int{
|
||||
//this is fine for enums and non-cloning object registries
|
||||
return spl_object_id($enum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param TObject $enum
|
||||
*/
|
||||
public function register(int $saveId, object $enum) : void{
|
||||
$this->idToEnum[$saveId] = $enum;
|
||||
$this->enumToId[$this->getRuntimeId($enum)] = $saveId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-return TObject|null
|
||||
*/
|
||||
public function fromId(int $id) : ?object{
|
||||
//we might not have all the effect IDs registered
|
||||
return $this->idToEnum[$id] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param TObject $enum
|
||||
*/
|
||||
public function toId(object $enum) : int{
|
||||
$runtimeId = $this->getRuntimeId($enum);
|
||||
if(!array_key_exists($runtimeId, $this->enumToId)){
|
||||
//this should never happen, so we treat it as an exceptional condition
|
||||
throw new \InvalidArgumentException("Object does not have a mapped save ID");
|
||||
}
|
||||
return $this->enumToId[$runtimeId];
|
||||
}
|
||||
}
|
@ -28,18 +28,8 @@ use pocketmine\utils\SingletonTrait;
|
||||
|
||||
final class MedicineTypeIdMap{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var MedicineType[]
|
||||
* @phpstan-var array<int, MedicineType>
|
||||
*/
|
||||
private array $idToEnum = [];
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private array $enumToId = [];
|
||||
/** @phpstan-use IntSaveIdMapTrait<MedicineType> */
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
$this->register(MedicineTypeIds::ANTIDOTE, MedicineType::ANTIDOTE());
|
||||
@ -47,20 +37,4 @@ final class MedicineTypeIdMap{
|
||||
$this->register(MedicineTypeIds::EYE_DROPS, MedicineType::EYE_DROPS());
|
||||
$this->register(MedicineTypeIds::TONIC, MedicineType::TONIC());
|
||||
}
|
||||
|
||||
private function register(int $id, MedicineType $type) : void{
|
||||
$this->idToEnum[$id] = $type;
|
||||
$this->enumToId[$type->id()] = $id;
|
||||
}
|
||||
|
||||
public function fromId(int $id) : ?MedicineType{
|
||||
return $this->idToEnum[$id] ?? null;
|
||||
}
|
||||
|
||||
public function toId(MedicineType $type) : int{
|
||||
if(!isset($this->enumToId[$type->id()])){
|
||||
throw new \InvalidArgumentException("Type does not have a mapped ID");
|
||||
}
|
||||
return $this->enumToId[$type->id()];
|
||||
}
|
||||
}
|
||||
|
@ -28,18 +28,8 @@ use pocketmine\utils\SingletonTrait;
|
||||
|
||||
final class MobHeadTypeIdMap{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var MobHeadType[]
|
||||
* @phpstan-var array<int, MobHeadType>
|
||||
*/
|
||||
private array $idToEnum = [];
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private array $enumToId = [];
|
||||
/** @phpstan-use IntSaveIdMapTrait<MobHeadType> */
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
$this->register(0, MobHeadType::SKELETON());
|
||||
@ -50,20 +40,4 @@ final class MobHeadTypeIdMap{
|
||||
$this->register(5, MobHeadType::DRAGON());
|
||||
$this->register(6, MobHeadType::PIGLIN());
|
||||
}
|
||||
|
||||
private function register(int $id, MobHeadType $type) : void{
|
||||
$this->idToEnum[$id] = $type;
|
||||
$this->enumToId[$type->id()] = $id;
|
||||
}
|
||||
|
||||
public function fromId(int $id) : ?MobHeadType{
|
||||
return $this->idToEnum[$id] ?? null;
|
||||
}
|
||||
|
||||
public function toId(MobHeadType $type) : int{
|
||||
if(!isset($this->enumToId[$type->id()])){
|
||||
throw new \InvalidArgumentException("Type does not have a mapped ID");
|
||||
}
|
||||
return $this->enumToId[$type->id()];
|
||||
}
|
||||
}
|
||||
|
@ -26,21 +26,11 @@ namespace pocketmine\data\bedrock;
|
||||
use pocketmine\block\utils\MushroomBlockType;
|
||||
use pocketmine\data\bedrock\block\BlockLegacyMetadata as LegacyMeta;
|
||||
use pocketmine\utils\SingletonTrait;
|
||||
use function array_key_exists;
|
||||
|
||||
final class MushroomBlockTypeIdMap{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var MushroomBlockType[]
|
||||
* @phpstan-var array<int, MushroomBlockType>
|
||||
*/
|
||||
private array $idToEnum = [];
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private array $enumToId = [];
|
||||
/** @phpstan-use IntSaveIdMapTrait<MushroomBlockType> */
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
public function __construct(){
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_ALL_PORES, MushroomBlockType::PORES());
|
||||
@ -55,20 +45,4 @@ final class MushroomBlockTypeIdMap{
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTHEAST_CORNER, MushroomBlockType::CAP_SOUTHEAST());
|
||||
$this->register(LegacyMeta::MUSHROOM_BLOCK_ALL_CAP, MushroomBlockType::ALL_CAP());
|
||||
}
|
||||
|
||||
public function register(int $id, MushroomBlockType $type) : void{
|
||||
$this->idToEnum[$id] = $type;
|
||||
$this->enumToId[$type->id()] = $id;
|
||||
}
|
||||
|
||||
public function fromId(int $id) : ?MushroomBlockType{
|
||||
return $this->idToEnum[$id] ?? null;
|
||||
}
|
||||
|
||||
public function toId(MushroomBlockType $type) : int{
|
||||
if(!array_key_exists($type->id(), $this->enumToId)){
|
||||
throw new \InvalidArgumentException("Mushroom block type does not have a mapped ID"); //this should never happen
|
||||
}
|
||||
return $this->enumToId[$type->id()];
|
||||
}
|
||||
}
|
||||
|
@ -28,18 +28,8 @@ use pocketmine\world\sound\NoteInstrument;
|
||||
|
||||
final class NoteInstrumentIdMap{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var NoteInstrument[]
|
||||
* @phpstan-var array<int, NoteInstrument>
|
||||
*/
|
||||
private array $idToEnum = [];
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private array $enumToId = [];
|
||||
/** @phpstan-use IntSaveIdMapTrait<NoteInstrument> */
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
$this->register(0, NoteInstrument::PIANO());
|
||||
@ -59,20 +49,4 @@ final class NoteInstrumentIdMap{
|
||||
$this->register(14, NoteInstrument::BANJO());
|
||||
$this->register(15, NoteInstrument::PLING());
|
||||
}
|
||||
|
||||
private function register(int $id, NoteInstrument $instrument) : void{
|
||||
$this->idToEnum[$id] = $instrument;
|
||||
$this->enumToId[$instrument->id()] = $id;
|
||||
}
|
||||
|
||||
public function fromId(int $id) : ?NoteInstrument{
|
||||
return $this->idToEnum[$id] ?? null;
|
||||
}
|
||||
|
||||
public function toId(NoteInstrument $instrument) : int{
|
||||
if(!isset($this->enumToId[$instrument->id()])){
|
||||
throw new \InvalidArgumentException("Type does not have a mapped ID");
|
||||
}
|
||||
return $this->enumToId[$instrument->id()];
|
||||
}
|
||||
}
|
||||
|
@ -28,18 +28,8 @@ use pocketmine\utils\SingletonTrait;
|
||||
|
||||
final class PotionTypeIdMap{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var PotionType[]
|
||||
* @phpstan-var array<int, PotionType>
|
||||
*/
|
||||
private array $idToEnum = [];
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private array $enumToId = [];
|
||||
/** @phpstan-use IntSaveIdMapTrait<PotionType> */
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
$this->register(PotionTypeIds::WATER, PotionType::WATER());
|
||||
@ -86,20 +76,4 @@ final class PotionTypeIdMap{
|
||||
$this->register(PotionTypeIds::LONG_SLOW_FALLING, PotionType::LONG_SLOW_FALLING());
|
||||
$this->register(PotionTypeIds::STRONG_SLOWNESS, PotionType::STRONG_SLOWNESS());
|
||||
}
|
||||
|
||||
private function register(int $id, PotionType $type) : void{
|
||||
$this->idToEnum[$id] = $type;
|
||||
$this->enumToId[$type->id()] = $id;
|
||||
}
|
||||
|
||||
public function fromId(int $id) : ?PotionType{
|
||||
return $this->idToEnum[$id] ?? null;
|
||||
}
|
||||
|
||||
public function toId(PotionType $type) : int{
|
||||
if(!isset($this->enumToId[$type->id()])){
|
||||
throw new \InvalidArgumentException("Type does not have a mapped ID");
|
||||
}
|
||||
return $this->enumToId[$type->id()];
|
||||
}
|
||||
}
|
||||
|
@ -28,18 +28,8 @@ use pocketmine\utils\SingletonTrait;
|
||||
|
||||
final class SuspiciousStewTypeIdMap{
|
||||
use SingletonTrait;
|
||||
|
||||
/**
|
||||
* @var SuspiciousStewType[]
|
||||
* @phpstan-var array<int, SuspiciousStewType>
|
||||
*/
|
||||
private array $idToEnum = [];
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
* @phpstan-var array<int, int>
|
||||
*/
|
||||
private array $enumToId = [];
|
||||
/** @phpstan-use IntSaveIdMapTrait<SuspiciousStewType> */
|
||||
use IntSaveIdMapTrait;
|
||||
|
||||
private function __construct(){
|
||||
$this->register(SuspiciousStewTypeIds::POPPY, SuspiciousStewType::POPPY());
|
||||
@ -53,20 +43,4 @@ final class SuspiciousStewTypeIdMap{
|
||||
$this->register(SuspiciousStewTypeIds::OXEYE_DAISY, SuspiciousStewType::OXEYE_DAISY());
|
||||
$this->register(SuspiciousStewTypeIds::WITHER_ROSE, SuspiciousStewType::WITHER_ROSE());
|
||||
}
|
||||
|
||||
private function register(int $id, SuspiciousStewType $type) : void{
|
||||
$this->idToEnum[$id] = $type;
|
||||
$this->enumToId[$type->id()] = $id;
|
||||
}
|
||||
|
||||
public function fromId(int $id) : ?SuspiciousStewType{
|
||||
return $this->idToEnum[$id] ?? null;
|
||||
}
|
||||
|
||||
public function toId(SuspiciousStewType $type) : int{
|
||||
if(!isset($this->enumToId[$type->id()])){
|
||||
throw new \InvalidArgumentException("Type does not have a mapped ID");
|
||||
}
|
||||
return $this->enumToId[$type->id()];
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ final class BlockStateData{
|
||||
public const CURRENT_VERSION =
|
||||
(1 << 24) | //major
|
||||
(20 << 16) | //minor
|
||||
(10 << 8) | //patch
|
||||
(32); //revision
|
||||
(40 << 8) | //patch
|
||||
(3); //revision
|
||||
|
||||
public const TAG_NAME = "name";
|
||||
public const TAG_STATES = "states";
|
||||
|
@ -98,8 +98,10 @@ final class BlockStateNames{
|
||||
public const LEVER_DIRECTION = "lever_direction";
|
||||
public const LIQUID_DEPTH = "liquid_depth";
|
||||
public const LIT = "lit";
|
||||
public const MC_BLOCK_FACE = "minecraft:block_face";
|
||||
public const MC_CARDINAL_DIRECTION = "minecraft:cardinal_direction";
|
||||
public const MC_FACING_DIRECTION = "minecraft:facing_direction";
|
||||
public const MC_VERTICAL_HALF = "minecraft:vertical_half";
|
||||
public const MOISTURIZED_AMOUNT = "moisturized_amount";
|
||||
public const MONSTER_EGG_STONE_TYPE = "monster_egg_stone_type";
|
||||
public const MULTI_FACE_DIRECTION_BITS = "multi_face_direction_bits";
|
||||
@ -141,7 +143,6 @@ final class BlockStateNames{
|
||||
public const SUSPENDED_BIT = "suspended_bit";
|
||||
public const TALL_GRASS_TYPE = "tall_grass_type";
|
||||
public const TOGGLE_BIT = "toggle_bit";
|
||||
public const TOP_SLOT_BIT = "top_slot_bit";
|
||||
public const TORCH_FACING_DIRECTION = "torch_facing_direction";
|
||||
public const TRIGGERED_BIT = "triggered_bit";
|
||||
public const TURTLE_EGG_COUNT = "turtle_egg_count";
|
||||
|
@ -131,6 +131,13 @@ final class BlockStateStringValues{
|
||||
public const LEVER_DIRECTION_UP_NORTH_SOUTH = "up_north_south";
|
||||
public const LEVER_DIRECTION_WEST = "west";
|
||||
|
||||
public const MC_BLOCK_FACE_DOWN = "down";
|
||||
public const MC_BLOCK_FACE_EAST = "east";
|
||||
public const MC_BLOCK_FACE_NORTH = "north";
|
||||
public const MC_BLOCK_FACE_SOUTH = "south";
|
||||
public const MC_BLOCK_FACE_UP = "up";
|
||||
public const MC_BLOCK_FACE_WEST = "west";
|
||||
|
||||
public const MC_CARDINAL_DIRECTION_EAST = "east";
|
||||
public const MC_CARDINAL_DIRECTION_NORTH = "north";
|
||||
public const MC_CARDINAL_DIRECTION_SOUTH = "south";
|
||||
@ -143,6 +150,9 @@ final class BlockStateStringValues{
|
||||
public const MC_FACING_DIRECTION_UP = "up";
|
||||
public const MC_FACING_DIRECTION_WEST = "west";
|
||||
|
||||
public const MC_VERTICAL_HALF_BOTTOM = "bottom";
|
||||
public const MC_VERTICAL_HALF_TOP = "top";
|
||||
|
||||
public const MONSTER_EGG_STONE_TYPE_CHISELED_STONE_BRICK = "chiseled_stone_brick";
|
||||
public const MONSTER_EGG_STONE_TYPE_COBBLESTONE = "cobblestone";
|
||||
public const MONSTER_EGG_STONE_TYPE_CRACKED_STONE_BRICK = "cracked_stone_brick";
|
||||
|
@ -99,8 +99,12 @@ final class BlockTypeNames{
|
||||
public const BLACK_CANDLE_CAKE = "minecraft:black_candle_cake";
|
||||
public const BLACK_CARPET = "minecraft:black_carpet";
|
||||
public const BLACK_CONCRETE = "minecraft:black_concrete";
|
||||
public const BLACK_CONCRETE_POWDER = "minecraft:black_concrete_powder";
|
||||
public const BLACK_GLAZED_TERRACOTTA = "minecraft:black_glazed_terracotta";
|
||||
public const BLACK_SHULKER_BOX = "minecraft:black_shulker_box";
|
||||
public const BLACK_STAINED_GLASS = "minecraft:black_stained_glass";
|
||||
public const BLACK_STAINED_GLASS_PANE = "minecraft:black_stained_glass_pane";
|
||||
public const BLACK_TERRACOTTA = "minecraft:black_terracotta";
|
||||
public const BLACK_WOOL = "minecraft:black_wool";
|
||||
public const BLACKSTONE = "minecraft:blackstone";
|
||||
public const BLACKSTONE_DOUBLE_SLAB = "minecraft:blackstone_double_slab";
|
||||
@ -112,9 +116,13 @@ final class BlockTypeNames{
|
||||
public const BLUE_CANDLE_CAKE = "minecraft:blue_candle_cake";
|
||||
public const BLUE_CARPET = "minecraft:blue_carpet";
|
||||
public const BLUE_CONCRETE = "minecraft:blue_concrete";
|
||||
public const BLUE_CONCRETE_POWDER = "minecraft:blue_concrete_powder";
|
||||
public const BLUE_GLAZED_TERRACOTTA = "minecraft:blue_glazed_terracotta";
|
||||
public const BLUE_ICE = "minecraft:blue_ice";
|
||||
public const BLUE_SHULKER_BOX = "minecraft:blue_shulker_box";
|
||||
public const BLUE_STAINED_GLASS = "minecraft:blue_stained_glass";
|
||||
public const BLUE_STAINED_GLASS_PANE = "minecraft:blue_stained_glass_pane";
|
||||
public const BLUE_TERRACOTTA = "minecraft:blue_terracotta";
|
||||
public const BLUE_WOOL = "minecraft:blue_wool";
|
||||
public const BONE_BLOCK = "minecraft:bone_block";
|
||||
public const BOOKSHELF = "minecraft:bookshelf";
|
||||
@ -127,10 +135,14 @@ final class BlockTypeNames{
|
||||
public const BROWN_CANDLE_CAKE = "minecraft:brown_candle_cake";
|
||||
public const BROWN_CARPET = "minecraft:brown_carpet";
|
||||
public const BROWN_CONCRETE = "minecraft:brown_concrete";
|
||||
public const BROWN_CONCRETE_POWDER = "minecraft:brown_concrete_powder";
|
||||
public const BROWN_GLAZED_TERRACOTTA = "minecraft:brown_glazed_terracotta";
|
||||
public const BROWN_MUSHROOM = "minecraft:brown_mushroom";
|
||||
public const BROWN_MUSHROOM_BLOCK = "minecraft:brown_mushroom_block";
|
||||
public const BROWN_SHULKER_BOX = "minecraft:brown_shulker_box";
|
||||
public const BROWN_STAINED_GLASS = "minecraft:brown_stained_glass";
|
||||
public const BROWN_STAINED_GLASS_PANE = "minecraft:brown_stained_glass_pane";
|
||||
public const BROWN_TERRACOTTA = "minecraft:brown_terracotta";
|
||||
public const BROWN_WOOL = "minecraft:brown_wool";
|
||||
public const BUBBLE_COLUMN = "minecraft:bubble_column";
|
||||
public const BUBBLE_CORAL = "minecraft:bubble_coral";
|
||||
@ -194,7 +206,6 @@ final class BlockTypeNames{
|
||||
public const COLORED_TORCH_RG = "minecraft:colored_torch_rg";
|
||||
public const COMMAND_BLOCK = "minecraft:command_block";
|
||||
public const COMPOSTER = "minecraft:composter";
|
||||
public const CONCRETE_POWDER = "minecraft:concrete_powder";
|
||||
public const CONDUIT = "minecraft:conduit";
|
||||
public const COPPER_BLOCK = "minecraft:copper_block";
|
||||
public const COPPER_ORE = "minecraft:copper_ore";
|
||||
@ -235,8 +246,12 @@ final class BlockTypeNames{
|
||||
public const CYAN_CANDLE_CAKE = "minecraft:cyan_candle_cake";
|
||||
public const CYAN_CARPET = "minecraft:cyan_carpet";
|
||||
public const CYAN_CONCRETE = "minecraft:cyan_concrete";
|
||||
public const CYAN_CONCRETE_POWDER = "minecraft:cyan_concrete_powder";
|
||||
public const CYAN_GLAZED_TERRACOTTA = "minecraft:cyan_glazed_terracotta";
|
||||
public const CYAN_SHULKER_BOX = "minecraft:cyan_shulker_box";
|
||||
public const CYAN_STAINED_GLASS = "minecraft:cyan_stained_glass";
|
||||
public const CYAN_STAINED_GLASS_PANE = "minecraft:cyan_stained_glass_pane";
|
||||
public const CYAN_TERRACOTTA = "minecraft:cyan_terracotta";
|
||||
public const CYAN_WOOL = "minecraft:cyan_wool";
|
||||
public const DARK_OAK_BUTTON = "minecraft:dark_oak_button";
|
||||
public const DARK_OAK_DOOR = "minecraft:dark_oak_door";
|
||||
@ -463,15 +478,23 @@ final class BlockTypeNames{
|
||||
public const GRAY_CANDLE_CAKE = "minecraft:gray_candle_cake";
|
||||
public const GRAY_CARPET = "minecraft:gray_carpet";
|
||||
public const GRAY_CONCRETE = "minecraft:gray_concrete";
|
||||
public const GRAY_CONCRETE_POWDER = "minecraft:gray_concrete_powder";
|
||||
public const GRAY_GLAZED_TERRACOTTA = "minecraft:gray_glazed_terracotta";
|
||||
public const GRAY_SHULKER_BOX = "minecraft:gray_shulker_box";
|
||||
public const GRAY_STAINED_GLASS = "minecraft:gray_stained_glass";
|
||||
public const GRAY_STAINED_GLASS_PANE = "minecraft:gray_stained_glass_pane";
|
||||
public const GRAY_TERRACOTTA = "minecraft:gray_terracotta";
|
||||
public const GRAY_WOOL = "minecraft:gray_wool";
|
||||
public const GREEN_CANDLE = "minecraft:green_candle";
|
||||
public const GREEN_CANDLE_CAKE = "minecraft:green_candle_cake";
|
||||
public const GREEN_CARPET = "minecraft:green_carpet";
|
||||
public const GREEN_CONCRETE = "minecraft:green_concrete";
|
||||
public const GREEN_CONCRETE_POWDER = "minecraft:green_concrete_powder";
|
||||
public const GREEN_GLAZED_TERRACOTTA = "minecraft:green_glazed_terracotta";
|
||||
public const GREEN_SHULKER_BOX = "minecraft:green_shulker_box";
|
||||
public const GREEN_STAINED_GLASS = "minecraft:green_stained_glass";
|
||||
public const GREEN_STAINED_GLASS_PANE = "minecraft:green_stained_glass_pane";
|
||||
public const GREEN_TERRACOTTA = "minecraft:green_terracotta";
|
||||
public const GREEN_WOOL = "minecraft:green_wool";
|
||||
public const GRINDSTONE = "minecraft:grindstone";
|
||||
public const HANGING_ROOTS = "minecraft:hanging_roots";
|
||||
@ -525,14 +548,22 @@ final class BlockTypeNames{
|
||||
public const LIGHT_BLUE_CANDLE_CAKE = "minecraft:light_blue_candle_cake";
|
||||
public const LIGHT_BLUE_CARPET = "minecraft:light_blue_carpet";
|
||||
public const LIGHT_BLUE_CONCRETE = "minecraft:light_blue_concrete";
|
||||
public const LIGHT_BLUE_CONCRETE_POWDER = "minecraft:light_blue_concrete_powder";
|
||||
public const LIGHT_BLUE_GLAZED_TERRACOTTA = "minecraft:light_blue_glazed_terracotta";
|
||||
public const LIGHT_BLUE_SHULKER_BOX = "minecraft:light_blue_shulker_box";
|
||||
public const LIGHT_BLUE_STAINED_GLASS = "minecraft:light_blue_stained_glass";
|
||||
public const LIGHT_BLUE_STAINED_GLASS_PANE = "minecraft:light_blue_stained_glass_pane";
|
||||
public const LIGHT_BLUE_TERRACOTTA = "minecraft:light_blue_terracotta";
|
||||
public const LIGHT_BLUE_WOOL = "minecraft:light_blue_wool";
|
||||
public const LIGHT_GRAY_CANDLE = "minecraft:light_gray_candle";
|
||||
public const LIGHT_GRAY_CANDLE_CAKE = "minecraft:light_gray_candle_cake";
|
||||
public const LIGHT_GRAY_CARPET = "minecraft:light_gray_carpet";
|
||||
public const LIGHT_GRAY_CONCRETE = "minecraft:light_gray_concrete";
|
||||
public const LIGHT_GRAY_CONCRETE_POWDER = "minecraft:light_gray_concrete_powder";
|
||||
public const LIGHT_GRAY_SHULKER_BOX = "minecraft:light_gray_shulker_box";
|
||||
public const LIGHT_GRAY_STAINED_GLASS = "minecraft:light_gray_stained_glass";
|
||||
public const LIGHT_GRAY_STAINED_GLASS_PANE = "minecraft:light_gray_stained_glass_pane";
|
||||
public const LIGHT_GRAY_TERRACOTTA = "minecraft:light_gray_terracotta";
|
||||
public const LIGHT_GRAY_WOOL = "minecraft:light_gray_wool";
|
||||
public const LIGHT_WEIGHTED_PRESSURE_PLATE = "minecraft:light_weighted_pressure_plate";
|
||||
public const LIGHTNING_ROD = "minecraft:lightning_rod";
|
||||
@ -540,8 +571,12 @@ final class BlockTypeNames{
|
||||
public const LIME_CANDLE_CAKE = "minecraft:lime_candle_cake";
|
||||
public const LIME_CARPET = "minecraft:lime_carpet";
|
||||
public const LIME_CONCRETE = "minecraft:lime_concrete";
|
||||
public const LIME_CONCRETE_POWDER = "minecraft:lime_concrete_powder";
|
||||
public const LIME_GLAZED_TERRACOTTA = "minecraft:lime_glazed_terracotta";
|
||||
public const LIME_SHULKER_BOX = "minecraft:lime_shulker_box";
|
||||
public const LIME_STAINED_GLASS = "minecraft:lime_stained_glass";
|
||||
public const LIME_STAINED_GLASS_PANE = "minecraft:lime_stained_glass_pane";
|
||||
public const LIME_TERRACOTTA = "minecraft:lime_terracotta";
|
||||
public const LIME_WOOL = "minecraft:lime_wool";
|
||||
public const LIT_BLAST_FURNACE = "minecraft:lit_blast_furnace";
|
||||
public const LIT_DEEPSLATE_REDSTONE_ORE = "minecraft:lit_deepslate_redstone_ore";
|
||||
@ -556,8 +591,12 @@ final class BlockTypeNames{
|
||||
public const MAGENTA_CANDLE_CAKE = "minecraft:magenta_candle_cake";
|
||||
public const MAGENTA_CARPET = "minecraft:magenta_carpet";
|
||||
public const MAGENTA_CONCRETE = "minecraft:magenta_concrete";
|
||||
public const MAGENTA_CONCRETE_POWDER = "minecraft:magenta_concrete_powder";
|
||||
public const MAGENTA_GLAZED_TERRACOTTA = "minecraft:magenta_glazed_terracotta";
|
||||
public const MAGENTA_SHULKER_BOX = "minecraft:magenta_shulker_box";
|
||||
public const MAGENTA_STAINED_GLASS = "minecraft:magenta_stained_glass";
|
||||
public const MAGENTA_STAINED_GLASS_PANE = "minecraft:magenta_stained_glass_pane";
|
||||
public const MAGENTA_TERRACOTTA = "minecraft:magenta_terracotta";
|
||||
public const MAGENTA_WOOL = "minecraft:magenta_wool";
|
||||
public const MAGMA = "minecraft:magma";
|
||||
public const MANGROVE_BUTTON = "minecraft:mangrove_button";
|
||||
@ -620,8 +659,12 @@ final class BlockTypeNames{
|
||||
public const ORANGE_CANDLE_CAKE = "minecraft:orange_candle_cake";
|
||||
public const ORANGE_CARPET = "minecraft:orange_carpet";
|
||||
public const ORANGE_CONCRETE = "minecraft:orange_concrete";
|
||||
public const ORANGE_CONCRETE_POWDER = "minecraft:orange_concrete_powder";
|
||||
public const ORANGE_GLAZED_TERRACOTTA = "minecraft:orange_glazed_terracotta";
|
||||
public const ORANGE_SHULKER_BOX = "minecraft:orange_shulker_box";
|
||||
public const ORANGE_STAINED_GLASS = "minecraft:orange_stained_glass";
|
||||
public const ORANGE_STAINED_GLASS_PANE = "minecraft:orange_stained_glass_pane";
|
||||
public const ORANGE_TERRACOTTA = "minecraft:orange_terracotta";
|
||||
public const ORANGE_WOOL = "minecraft:orange_wool";
|
||||
public const OXIDIZED_COPPER = "minecraft:oxidized_copper";
|
||||
public const OXIDIZED_CUT_COPPER = "minecraft:oxidized_cut_copper";
|
||||
@ -635,9 +678,13 @@ final class BlockTypeNames{
|
||||
public const PINK_CANDLE_CAKE = "minecraft:pink_candle_cake";
|
||||
public const PINK_CARPET = "minecraft:pink_carpet";
|
||||
public const PINK_CONCRETE = "minecraft:pink_concrete";
|
||||
public const PINK_CONCRETE_POWDER = "minecraft:pink_concrete_powder";
|
||||
public const PINK_GLAZED_TERRACOTTA = "minecraft:pink_glazed_terracotta";
|
||||
public const PINK_PETALS = "minecraft:pink_petals";
|
||||
public const PINK_SHULKER_BOX = "minecraft:pink_shulker_box";
|
||||
public const PINK_STAINED_GLASS = "minecraft:pink_stained_glass";
|
||||
public const PINK_STAINED_GLASS_PANE = "minecraft:pink_stained_glass_pane";
|
||||
public const PINK_TERRACOTTA = "minecraft:pink_terracotta";
|
||||
public const PINK_WOOL = "minecraft:pink_wool";
|
||||
public const PISTON = "minecraft:piston";
|
||||
public const PISTON_ARM_COLLISION = "minecraft:piston_arm_collision";
|
||||
@ -681,8 +728,12 @@ final class BlockTypeNames{
|
||||
public const PURPLE_CANDLE_CAKE = "minecraft:purple_candle_cake";
|
||||
public const PURPLE_CARPET = "minecraft:purple_carpet";
|
||||
public const PURPLE_CONCRETE = "minecraft:purple_concrete";
|
||||
public const PURPLE_CONCRETE_POWDER = "minecraft:purple_concrete_powder";
|
||||
public const PURPLE_GLAZED_TERRACOTTA = "minecraft:purple_glazed_terracotta";
|
||||
public const PURPLE_SHULKER_BOX = "minecraft:purple_shulker_box";
|
||||
public const PURPLE_STAINED_GLASS = "minecraft:purple_stained_glass";
|
||||
public const PURPLE_STAINED_GLASS_PANE = "minecraft:purple_stained_glass_pane";
|
||||
public const PURPLE_TERRACOTTA = "minecraft:purple_terracotta";
|
||||
public const PURPLE_WOOL = "minecraft:purple_wool";
|
||||
public const PURPUR_BLOCK = "minecraft:purpur_block";
|
||||
public const PURPUR_STAIRS = "minecraft:purpur_stairs";
|
||||
@ -698,6 +749,7 @@ final class BlockTypeNames{
|
||||
public const RED_CANDLE_CAKE = "minecraft:red_candle_cake";
|
||||
public const RED_CARPET = "minecraft:red_carpet";
|
||||
public const RED_CONCRETE = "minecraft:red_concrete";
|
||||
public const RED_CONCRETE_POWDER = "minecraft:red_concrete_powder";
|
||||
public const RED_FLOWER = "minecraft:red_flower";
|
||||
public const RED_GLAZED_TERRACOTTA = "minecraft:red_glazed_terracotta";
|
||||
public const RED_MUSHROOM = "minecraft:red_mushroom";
|
||||
@ -707,6 +759,9 @@ final class BlockTypeNames{
|
||||
public const RED_SANDSTONE = "minecraft:red_sandstone";
|
||||
public const RED_SANDSTONE_STAIRS = "minecraft:red_sandstone_stairs";
|
||||
public const RED_SHULKER_BOX = "minecraft:red_shulker_box";
|
||||
public const RED_STAINED_GLASS = "minecraft:red_stained_glass";
|
||||
public const RED_STAINED_GLASS_PANE = "minecraft:red_stained_glass_pane";
|
||||
public const RED_TERRACOTTA = "minecraft:red_terracotta";
|
||||
public const RED_WOOL = "minecraft:red_wool";
|
||||
public const REDSTONE_BLOCK = "minecraft:redstone_block";
|
||||
public const REDSTONE_LAMP = "minecraft:redstone_lamp";
|
||||
@ -766,9 +821,6 @@ final class BlockTypeNames{
|
||||
public const SPRUCE_STANDING_SIGN = "minecraft:spruce_standing_sign";
|
||||
public const SPRUCE_TRAPDOOR = "minecraft:spruce_trapdoor";
|
||||
public const SPRUCE_WALL_SIGN = "minecraft:spruce_wall_sign";
|
||||
public const STAINED_GLASS = "minecraft:stained_glass";
|
||||
public const STAINED_GLASS_PANE = "minecraft:stained_glass_pane";
|
||||
public const STAINED_HARDENED_CLAY = "minecraft:stained_hardened_clay";
|
||||
public const STANDING_BANNER = "minecraft:standing_banner";
|
||||
public const STANDING_SIGN = "minecraft:standing_sign";
|
||||
public const STICKY_PISTON = "minecraft:sticky_piston";
|
||||
@ -883,8 +935,12 @@ final class BlockTypeNames{
|
||||
public const WHITE_CANDLE_CAKE = "minecraft:white_candle_cake";
|
||||
public const WHITE_CARPET = "minecraft:white_carpet";
|
||||
public const WHITE_CONCRETE = "minecraft:white_concrete";
|
||||
public const WHITE_CONCRETE_POWDER = "minecraft:white_concrete_powder";
|
||||
public const WHITE_GLAZED_TERRACOTTA = "minecraft:white_glazed_terracotta";
|
||||
public const WHITE_SHULKER_BOX = "minecraft:white_shulker_box";
|
||||
public const WHITE_STAINED_GLASS = "minecraft:white_stained_glass";
|
||||
public const WHITE_STAINED_GLASS_PANE = "minecraft:white_stained_glass_pane";
|
||||
public const WHITE_TERRACOTTA = "minecraft:white_terracotta";
|
||||
public const WHITE_WOOL = "minecraft:white_wool";
|
||||
public const WITHER_ROSE = "minecraft:wither_rose";
|
||||
public const WOOD = "minecraft:wood";
|
||||
@ -896,8 +952,12 @@ final class BlockTypeNames{
|
||||
public const YELLOW_CANDLE_CAKE = "minecraft:yellow_candle_cake";
|
||||
public const YELLOW_CARPET = "minecraft:yellow_carpet";
|
||||
public const YELLOW_CONCRETE = "minecraft:yellow_concrete";
|
||||
public const YELLOW_CONCRETE_POWDER = "minecraft:yellow_concrete_powder";
|
||||
public const YELLOW_FLOWER = "minecraft:yellow_flower";
|
||||
public const YELLOW_GLAZED_TERRACOTTA = "minecraft:yellow_glazed_terracotta";
|
||||
public const YELLOW_SHULKER_BOX = "minecraft:yellow_shulker_box";
|
||||
public const YELLOW_STAINED_GLASS = "minecraft:yellow_stained_glass";
|
||||
public const YELLOW_STAINED_GLASS_PANE = "minecraft:yellow_stained_glass_pane";
|
||||
public const YELLOW_TERRACOTTA = "minecraft:yellow_terracotta";
|
||||
public const YELLOW_WOOL = "minecraft:yellow_wool";
|
||||
}
|
||||
|
@ -415,6 +415,86 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
DyeColor::YELLOW() => Ids::YELLOW_CONCRETE,
|
||||
default => throw new AssumptionFailedError("Unhandled dye colour " . $color->name())
|
||||
}));
|
||||
|
||||
$this->map(Blocks::CONCRETE_POWDER(), fn(ConcretePowder $block) => Writer::create(match($color = $block->getColor()){
|
||||
DyeColor::BLACK() => Ids::BLACK_CONCRETE_POWDER,
|
||||
DyeColor::BLUE() => Ids::BLUE_CONCRETE_POWDER,
|
||||
DyeColor::BROWN() => Ids::BROWN_CONCRETE_POWDER,
|
||||
DyeColor::CYAN() => Ids::CYAN_CONCRETE_POWDER,
|
||||
DyeColor::GRAY() => Ids::GRAY_CONCRETE_POWDER,
|
||||
DyeColor::GREEN() => Ids::GREEN_CONCRETE_POWDER,
|
||||
DyeColor::LIGHT_BLUE() => Ids::LIGHT_BLUE_CONCRETE_POWDER,
|
||||
DyeColor::LIGHT_GRAY() => Ids::LIGHT_GRAY_CONCRETE_POWDER,
|
||||
DyeColor::LIME() => Ids::LIME_CONCRETE_POWDER,
|
||||
DyeColor::MAGENTA() => Ids::MAGENTA_CONCRETE_POWDER,
|
||||
DyeColor::ORANGE() => Ids::ORANGE_CONCRETE_POWDER,
|
||||
DyeColor::PINK() => Ids::PINK_CONCRETE_POWDER,
|
||||
DyeColor::PURPLE() => Ids::PURPLE_CONCRETE_POWDER,
|
||||
DyeColor::RED() => Ids::RED_CONCRETE_POWDER,
|
||||
DyeColor::WHITE() => Ids::WHITE_CONCRETE_POWDER,
|
||||
DyeColor::YELLOW() => Ids::YELLOW_CONCRETE_POWDER,
|
||||
default => throw new AssumptionFailedError("Unhandled dye colour " . $color->name())
|
||||
}));
|
||||
|
||||
$this->map(Blocks::STAINED_CLAY(), fn(StainedHardenedClay $block) => Writer::create(match($color = $block->getColor()){
|
||||
DyeColor::BLACK() => Ids::BLACK_TERRACOTTA,
|
||||
DyeColor::BLUE() => Ids::BLUE_TERRACOTTA,
|
||||
DyeColor::BROWN() => Ids::BROWN_TERRACOTTA,
|
||||
DyeColor::CYAN() => Ids::CYAN_TERRACOTTA,
|
||||
DyeColor::GRAY() => Ids::GRAY_TERRACOTTA,
|
||||
DyeColor::GREEN() => Ids::GREEN_TERRACOTTA,
|
||||
DyeColor::LIGHT_BLUE() => Ids::LIGHT_BLUE_TERRACOTTA,
|
||||
DyeColor::LIGHT_GRAY() => Ids::LIGHT_GRAY_TERRACOTTA,
|
||||
DyeColor::LIME() => Ids::LIME_TERRACOTTA,
|
||||
DyeColor::MAGENTA() => Ids::MAGENTA_TERRACOTTA,
|
||||
DyeColor::ORANGE() => Ids::ORANGE_TERRACOTTA,
|
||||
DyeColor::PINK() => Ids::PINK_TERRACOTTA,
|
||||
DyeColor::PURPLE() => Ids::PURPLE_TERRACOTTA,
|
||||
DyeColor::RED() => Ids::RED_TERRACOTTA,
|
||||
DyeColor::WHITE() => Ids::WHITE_TERRACOTTA,
|
||||
DyeColor::YELLOW() => Ids::YELLOW_TERRACOTTA,
|
||||
default => throw new AssumptionFailedError("Unhandled dye colour " . $color->name())
|
||||
}));
|
||||
|
||||
$this->map(Blocks::STAINED_GLASS(), fn(StainedGlass $block) => Writer::create(match($color = $block->getColor()){
|
||||
DyeColor::BLACK() => Ids::BLACK_STAINED_GLASS,
|
||||
DyeColor::BLUE() => Ids::BLUE_STAINED_GLASS,
|
||||
DyeColor::BROWN() => Ids::BROWN_STAINED_GLASS,
|
||||
DyeColor::CYAN() => Ids::CYAN_STAINED_GLASS,
|
||||
DyeColor::GRAY() => Ids::GRAY_STAINED_GLASS,
|
||||
DyeColor::GREEN() => Ids::GREEN_STAINED_GLASS,
|
||||
DyeColor::LIGHT_BLUE() => Ids::LIGHT_BLUE_STAINED_GLASS,
|
||||
DyeColor::LIGHT_GRAY() => Ids::LIGHT_GRAY_STAINED_GLASS,
|
||||
DyeColor::LIME() => Ids::LIME_STAINED_GLASS,
|
||||
DyeColor::MAGENTA() => Ids::MAGENTA_STAINED_GLASS,
|
||||
DyeColor::ORANGE() => Ids::ORANGE_STAINED_GLASS,
|
||||
DyeColor::PINK() => Ids::PINK_STAINED_GLASS,
|
||||
DyeColor::PURPLE() => Ids::PURPLE_STAINED_GLASS,
|
||||
DyeColor::RED() => Ids::RED_STAINED_GLASS,
|
||||
DyeColor::WHITE() => Ids::WHITE_STAINED_GLASS,
|
||||
DyeColor::YELLOW() => Ids::YELLOW_STAINED_GLASS,
|
||||
default => throw new AssumptionFailedError("Unhandled dye colour " . $color->name())
|
||||
}));
|
||||
|
||||
$this->map(Blocks::STAINED_GLASS_PANE(), fn(StainedGlassPane $block) => Writer::create(match($color = $block->getColor()){
|
||||
DyeColor::BLACK() => Ids::BLACK_STAINED_GLASS_PANE,
|
||||
DyeColor::BLUE() => Ids::BLUE_STAINED_GLASS_PANE,
|
||||
DyeColor::BROWN() => Ids::BROWN_STAINED_GLASS_PANE,
|
||||
DyeColor::CYAN() => Ids::CYAN_STAINED_GLASS_PANE,
|
||||
DyeColor::GRAY() => Ids::GRAY_STAINED_GLASS_PANE,
|
||||
DyeColor::GREEN() => Ids::GREEN_STAINED_GLASS_PANE,
|
||||
DyeColor::LIGHT_BLUE() => Ids::LIGHT_BLUE_STAINED_GLASS_PANE,
|
||||
DyeColor::LIGHT_GRAY() => Ids::LIGHT_GRAY_STAINED_GLASS_PANE,
|
||||
DyeColor::LIME() => Ids::LIME_STAINED_GLASS_PANE,
|
||||
DyeColor::MAGENTA() => Ids::MAGENTA_STAINED_GLASS_PANE,
|
||||
DyeColor::ORANGE() => Ids::ORANGE_STAINED_GLASS_PANE,
|
||||
DyeColor::PINK() => Ids::PINK_STAINED_GLASS_PANE,
|
||||
DyeColor::PURPLE() => Ids::PURPLE_STAINED_GLASS_PANE,
|
||||
DyeColor::RED() => Ids::RED_STAINED_GLASS_PANE,
|
||||
DyeColor::WHITE() => Ids::WHITE_STAINED_GLASS_PANE,
|
||||
DyeColor::YELLOW() => Ids::YELLOW_STAINED_GLASS_PANE,
|
||||
default => throw new AssumptionFailedError("Unhandled dye colour " . $color->name())
|
||||
}));
|
||||
}
|
||||
|
||||
private function registerFlatCoralSerializers() : void{
|
||||
@ -905,7 +985,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->map(Blocks::ANDESITE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_ANDESITE));
|
||||
$this->map(Blocks::ANVIL(), function(Anvil $block) : Writer{
|
||||
return Writer::create(Ids::ANVIL)
|
||||
->writeLegacyHorizontalFacing($block->getFacing())
|
||||
->writeCardinalHorizontalFacing($block->getFacing())
|
||||
->writeString(StateNames::DAMAGE, match($damage = $block->getDamage()){
|
||||
0 => StringValues::DAMAGE_UNDAMAGED,
|
||||
1 => StringValues::DAMAGE_SLIGHTLY_DAMAGED,
|
||||
@ -965,7 +1045,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
});
|
||||
$this->map(Blocks::BIG_DRIPLEAF_HEAD(), function(BigDripleafHead $block) : Writer{
|
||||
return Writer::create(Ids::BIG_DRIPLEAF)
|
||||
->writeLegacyHorizontalFacing($block->getFacing())
|
||||
->writeCardinalHorizontalFacing($block->getFacing())
|
||||
->writeString(StateNames::BIG_DRIPLEAF_TILT, match($block->getLeafState()->id()){
|
||||
DripleafState::STABLE()->id() => StringValues::BIG_DRIPLEAF_TILT_NONE,
|
||||
DripleafState::UNSTABLE()->id() => StringValues::BIG_DRIPLEAF_TILT_UNSTABLE,
|
||||
@ -977,7 +1057,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
});
|
||||
$this->map(Blocks::BIG_DRIPLEAF_STEM(), function(BigDripleafStem $block) : Writer{
|
||||
return Writer::create(Ids::BIG_DRIPLEAF)
|
||||
->writeLegacyHorizontalFacing($block->getFacing())
|
||||
->writeCardinalHorizontalFacing($block->getFacing())
|
||||
->writeString(StateNames::BIG_DRIPLEAF_TILT, StringValues::BIG_DRIPLEAF_TILT_NONE)
|
||||
->writeBool(StateNames::BIG_DRIPLEAF_HEAD, false);
|
||||
});
|
||||
@ -1033,7 +1113,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
});
|
||||
$this->map(Blocks::CHEST(), function(Chest $block) : Writer{
|
||||
return Writer::create(Ids::CHEST)
|
||||
->writeHorizontalFacing($block->getFacing());
|
||||
->writeCardinalHorizontalFacing($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::CHISELED_QUARTZ(), fn(SimplePillar $block) => Helper::encodeQuartz(StringValues::CHISEL_TYPE_CHISELED, $block->getAxis()));
|
||||
$this->map(Blocks::CHISELED_RED_SANDSTONE(), fn() => Helper::encodeSandstone(Ids::RED_SANDSTONE, StringValues::SAND_STONE_TYPE_HEIROGLYPHS));
|
||||
@ -1129,10 +1209,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeLegacyHorizontalFacing(Facing::opposite($block->getFacing()));
|
||||
});
|
||||
$this->map(Blocks::COMPOUND_CREATOR(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, StringValues::CHEMISTRY_TABLE_TYPE_COMPOUND_CREATOR, new Writer(Ids::CHEMISTRY_TABLE)));
|
||||
$this->map(Blocks::CONCRETE_POWDER(), function(ConcretePowder $block) : Writer{
|
||||
return Writer::create(Ids::CONCRETE_POWDER)
|
||||
->writeColor($block->getColor());
|
||||
});
|
||||
$this->map(Blocks::CORAL_BLOCK(), function(CoralBlock $block) : Writer{
|
||||
return Writer::create(Ids::CORAL_BLOCK)
|
||||
->writeBool(StateNames::DEAD_BIT, $block->isDead())
|
||||
@ -1198,12 +1274,12 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->map(Blocks::ELEMENT_CONSTRUCTOR(), fn(ChemistryTable $block) => Helper::encodeChemistryTable($block, StringValues::CHEMISTRY_TABLE_TYPE_ELEMENT_CONSTRUCTOR, new Writer(Ids::CHEMISTRY_TABLE)));
|
||||
$this->map(Blocks::ENDER_CHEST(), function(EnderChest $block) : Writer{
|
||||
return Writer::create(Ids::ENDER_CHEST)
|
||||
->writeHorizontalFacing($block->getFacing());
|
||||
->writeCardinalHorizontalFacing($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::END_PORTAL_FRAME(), function(EndPortalFrame $block) : Writer{
|
||||
return Writer::create(Ids::END_PORTAL_FRAME)
|
||||
->writeBool(StateNames::END_PORTAL_EYE_BIT, $block->hasEye())
|
||||
->writeLegacyHorizontalFacing($block->getFacing());
|
||||
->writeCardinalHorizontalFacing($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::END_ROD(), function(EndRod $block) : Writer{
|
||||
return Writer::create(Ids::END_ROD)
|
||||
@ -1291,7 +1367,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->map(Blocks::LECTERN(), function(Lectern $block) : Writer{
|
||||
return Writer::create(Ids::LECTERN)
|
||||
->writeBool(StateNames::POWERED_BIT, $block->isProducingSignal())
|
||||
->writeLegacyHorizontalFacing($block->getFacing());
|
||||
->writeCardinalHorizontalFacing($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::LEVER(), function(Lever $block) : Writer{
|
||||
return Writer::create(Ids::LEVER)
|
||||
@ -1367,7 +1443,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
$this->map(Blocks::PEONY(), fn(DoublePlant $block) => Helper::encodeDoublePlant($block, StringValues::DOUBLE_PLANT_TYPE_PAEONIA, Writer::create(Ids::DOUBLE_PLANT)));
|
||||
$this->map(Blocks::PINK_PETALS(), function(PinkPetals $block) : Writer{
|
||||
return Writer::create(Ids::PINK_PETALS)
|
||||
->writeLegacyHorizontalFacing($block->getFacing())
|
||||
->writeCardinalHorizontalFacing($block->getFacing())
|
||||
->writeInt(StateNames::GROWTH, $block->getCount() - 1);
|
||||
});
|
||||
$this->map(Blocks::PINK_TULIP(), fn() => Helper::encodeRedFlower(StringValues::FLOWER_TYPE_TULIP_PINK));
|
||||
@ -1441,13 +1517,13 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
return Writer::create($block->isPowered() ? Ids::POWERED_COMPARATOR : Ids::UNPOWERED_COMPARATOR)
|
||||
->writeBool(StateNames::OUTPUT_LIT_BIT, $block->isPowered())
|
||||
->writeBool(StateNames::OUTPUT_SUBTRACT_BIT, $block->isSubtractMode())
|
||||
->writeLegacyHorizontalFacing($block->getFacing());
|
||||
->writeCardinalHorizontalFacing($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::REDSTONE_LAMP(), fn(RedstoneLamp $block) => new Writer($block->isPowered() ? Ids::LIT_REDSTONE_LAMP : Ids::REDSTONE_LAMP));
|
||||
$this->map(Blocks::REDSTONE_ORE(), fn(RedstoneOre $block) => new Writer($block->isLit() ? Ids::LIT_REDSTONE_ORE : Ids::REDSTONE_ORE));
|
||||
$this->map(Blocks::REDSTONE_REPEATER(), function(RedstoneRepeater $block) : Writer{
|
||||
return Writer::create($block->isPowered() ? Ids::POWERED_REPEATER : Ids::UNPOWERED_REPEATER)
|
||||
->writeLegacyHorizontalFacing($block->getFacing())
|
||||
->writeCardinalHorizontalFacing($block->getFacing())
|
||||
->writeInt(StateNames::REPEATER_DELAY, $block->getDelay() - 1);
|
||||
});
|
||||
$this->map(Blocks::REDSTONE_TORCH(), function(RedstoneTorch $block) : Writer{
|
||||
@ -1484,7 +1560,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
});
|
||||
$this->map(Blocks::SMALL_DRIPLEAF(), function(SmallDripleaf $block) : Writer{
|
||||
return Writer::create(Ids::SMALL_DRIPLEAF_BLOCK)
|
||||
->writeLegacyHorizontalFacing($block->getFacing())
|
||||
->writeCardinalHorizontalFacing($block->getFacing())
|
||||
->writeBool(StateNames::UPPER_BLOCK_BIT, $block->isTop());
|
||||
});
|
||||
$this->map(Blocks::SMOKER(), fn(Furnace $block) => Helper::encodeFurnace($block, Ids::SMOKER, Ids::LIT_SMOKER));
|
||||
@ -1520,18 +1596,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
->writeString(StateNames::SPONGE_TYPE, $block->isWet() ? StringValues::SPONGE_TYPE_WET : StringValues::SPONGE_TYPE_DRY);
|
||||
});
|
||||
$this->map(Blocks::SPRUCE_SAPLING(), fn(Sapling $block) => Helper::encodeSapling($block, StringValues::SAPLING_TYPE_SPRUCE));
|
||||
$this->map(Blocks::STAINED_CLAY(), function(StainedHardenedClay $block) : Writer{
|
||||
return Writer::create(Ids::STAINED_HARDENED_CLAY)
|
||||
->writeColor($block->getColor());
|
||||
});
|
||||
$this->map(Blocks::STAINED_GLASS(), function(StainedGlass $block) : Writer{
|
||||
return Writer::create(Ids::STAINED_GLASS)
|
||||
->writeColor($block->getColor());
|
||||
});
|
||||
$this->map(Blocks::STAINED_GLASS_PANE(), function(StainedGlassPane $block) : Writer{
|
||||
return Writer::create(Ids::STAINED_GLASS_PANE)
|
||||
->writeColor($block->getColor());
|
||||
});
|
||||
$this->map(Blocks::STAINED_HARDENED_GLASS(), function(StainedHardenedGlass $block) : Writer{
|
||||
return Writer::create(Ids::HARD_STAINED_GLASS)
|
||||
->writeColor($block->getColor());
|
||||
@ -1542,7 +1606,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
});
|
||||
$this->map(Blocks::STONE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_STONE));
|
||||
$this->map(Blocks::STONECUTTER(), fn(Stonecutter $block) => Writer::create(Ids::STONECUTTER_BLOCK)
|
||||
->writeHorizontalFacing($block->getFacing()));
|
||||
->writeCardinalHorizontalFacing($block->getFacing()));
|
||||
$this->map(Blocks::STONE_BRICKS(), fn() => Helper::encodeStoneBricks(StringValues::STONE_BRICK_TYPE_DEFAULT));
|
||||
$this->map(Blocks::STONE_BRICK_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab1($block, StringValues::STONE_SLAB_TYPE_STONE_BRICK));
|
||||
$this->mapStairs(Blocks::STONE_BRICK_STAIRS(), Ids::STONE_BRICK_STAIRS);
|
||||
@ -1573,7 +1637,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
|
||||
});
|
||||
$this->map(Blocks::TRAPPED_CHEST(), function(TrappedChest $block) : Writer{
|
||||
return Writer::create(Ids::TRAPPED_CHEST)
|
||||
->writeHorizontalFacing($block->getFacing());
|
||||
->writeCardinalHorizontalFacing($block->getFacing());
|
||||
});
|
||||
$this->map(Blocks::TRIPWIRE(), function(Tripwire $block) : Writer{
|
||||
return Writer::create(Ids::TRIP_WIRE)
|
||||
|
@ -93,7 +93,7 @@ final class BlockStateDeserializerHelper{
|
||||
/** @throws BlockStateDeserializeException */
|
||||
public static function decodeComparator(RedstoneComparator $block, BlockStateReader $in) : RedstoneComparator{
|
||||
return $block
|
||||
->setFacing($in->readLegacyHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setPowered($in->readBool(BlockStateNames::OUTPUT_LIT_BIT))
|
||||
->setSubtractMode($in->readBool(BlockStateNames::OUTPUT_SUBTRACT_BIT));
|
||||
}
|
||||
@ -216,7 +216,7 @@ final class BlockStateDeserializerHelper{
|
||||
/** @throws BlockStateDeserializeException */
|
||||
public static function decodeRepeater(RedstoneRepeater $block, BlockStateReader $in) : RedstoneRepeater{
|
||||
return $block
|
||||
->setFacing($in->readLegacyHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setDelay($in->readBoundedInt(BlockStateNames::REPEATER_DELAY, 0, 3) + 1);
|
||||
}
|
||||
|
||||
|
@ -293,7 +293,11 @@ final class BlockStateReader{
|
||||
|
||||
/** @throws BlockStateDeserializeException */
|
||||
public function readSlabPosition() : SlabType{
|
||||
return $this->readBool(BlockStateNames::TOP_SLOT_BIT) ? SlabType::TOP() : SlabType::BOTTOM();
|
||||
return match($rawValue = $this->readString(BlockStateNames::MC_VERTICAL_HALF)){
|
||||
StringValues::MC_VERTICAL_HALF_BOTTOM => SlabType::BOTTOM(),
|
||||
StringValues::MC_VERTICAL_HALF_TOP => SlabType::TOP(),
|
||||
default => throw $this->badValueException(BlockStateNames::MC_VERTICAL_HALF, $rawValue, "Invalid slab position"),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,7 +137,7 @@ final class BlockStateSerializerHelper{
|
||||
|
||||
public static function encodeFurnace(Furnace $block, string $unlitId, string $litId) : BlockStateWriter{
|
||||
return BlockStateWriter::create($block->isLit() ? $litId : $unlitId)
|
||||
->writeHorizontalFacing($block->getFacing());
|
||||
->writeCardinalHorizontalFacing($block->getFacing());
|
||||
}
|
||||
|
||||
public static function encodeItemFrame(ItemFrame $block, string $id) : BlockStateWriter{
|
||||
@ -211,9 +211,8 @@ final class BlockStateSerializerHelper{
|
||||
public static function encodeSlab(Slab $block, string $singleId, string $doubleId) : BlockStateWriter{
|
||||
$slabType = $block->getSlabType();
|
||||
return BlockStateWriter::create($slabType->equals(SlabType::DOUBLE()) ? $doubleId : $singleId)
|
||||
|
||||
//this is (intentionally) also written for double slabs (as zero) to maintain bug parity with MCPE
|
||||
->writeBool(BlockStateNames::TOP_SLOT_BIT, $slabType->equals(SlabType::TOP()));
|
||||
->writeSlabPosition($slabType->equals(SlabType::DOUBLE()) ? SlabType::BOTTOM() : $slabType);
|
||||
}
|
||||
|
||||
public static function encodeStairs(Stair $block, BlockStateWriter $out) : BlockStateWriter{
|
||||
|
@ -113,7 +113,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
public function mapSlab(string $singleId, string $doubleId, \Closure $getBlock) : void{
|
||||
$this->map($singleId, fn(Reader $in) : Slab => $getBlock($in)->setSlabType($in->readSlabPosition()));
|
||||
$this->map($doubleId, function(Reader $in) use ($getBlock) : Slab{
|
||||
$in->ignored(StateNames::TOP_SLOT_BIT);
|
||||
$in->ignored(StateNames::MC_VERTICAL_HALF);
|
||||
return $getBlock($in)->setSlabType(SlabType::DOUBLE());
|
||||
});
|
||||
}
|
||||
@ -288,6 +288,90 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
] as $id => $color){
|
||||
$this->mapSimple($id, fn() => Blocks::CONCRETE()->setColor($color));
|
||||
}
|
||||
|
||||
foreach([
|
||||
Ids::BLACK_CONCRETE_POWDER => DyeColor::BLACK(),
|
||||
Ids::BLUE_CONCRETE_POWDER => DyeColor::BLUE(),
|
||||
Ids::BROWN_CONCRETE_POWDER => DyeColor::BROWN(),
|
||||
Ids::CYAN_CONCRETE_POWDER => DyeColor::CYAN(),
|
||||
Ids::GRAY_CONCRETE_POWDER => DyeColor::GRAY(),
|
||||
Ids::GREEN_CONCRETE_POWDER => DyeColor::GREEN(),
|
||||
Ids::LIGHT_BLUE_CONCRETE_POWDER => DyeColor::LIGHT_BLUE(),
|
||||
Ids::LIGHT_GRAY_CONCRETE_POWDER => DyeColor::LIGHT_GRAY(),
|
||||
Ids::LIME_CONCRETE_POWDER => DyeColor::LIME(),
|
||||
Ids::MAGENTA_CONCRETE_POWDER => DyeColor::MAGENTA(),
|
||||
Ids::ORANGE_CONCRETE_POWDER => DyeColor::ORANGE(),
|
||||
Ids::PINK_CONCRETE_POWDER => DyeColor::PINK(),
|
||||
Ids::PURPLE_CONCRETE_POWDER => DyeColor::PURPLE(),
|
||||
Ids::RED_CONCRETE_POWDER => DyeColor::RED(),
|
||||
Ids::WHITE_CONCRETE_POWDER => DyeColor::WHITE(),
|
||||
Ids::YELLOW_CONCRETE_POWDER => DyeColor::YELLOW(),
|
||||
] as $id => $color){
|
||||
$this->mapSimple($id, fn() => Blocks::CONCRETE_POWDER()->setColor($color));
|
||||
}
|
||||
|
||||
foreach([
|
||||
Ids::BLACK_TERRACOTTA => DyeColor::BLACK(),
|
||||
Ids::BLUE_TERRACOTTA => DyeColor::BLUE(),
|
||||
Ids::BROWN_TERRACOTTA => DyeColor::BROWN(),
|
||||
Ids::CYAN_TERRACOTTA => DyeColor::CYAN(),
|
||||
Ids::GRAY_TERRACOTTA => DyeColor::GRAY(),
|
||||
Ids::GREEN_TERRACOTTA => DyeColor::GREEN(),
|
||||
Ids::LIGHT_BLUE_TERRACOTTA => DyeColor::LIGHT_BLUE(),
|
||||
Ids::LIGHT_GRAY_TERRACOTTA => DyeColor::LIGHT_GRAY(),
|
||||
Ids::LIME_TERRACOTTA => DyeColor::LIME(),
|
||||
Ids::MAGENTA_TERRACOTTA => DyeColor::MAGENTA(),
|
||||
Ids::ORANGE_TERRACOTTA => DyeColor::ORANGE(),
|
||||
Ids::PINK_TERRACOTTA => DyeColor::PINK(),
|
||||
Ids::PURPLE_TERRACOTTA => DyeColor::PURPLE(),
|
||||
Ids::RED_TERRACOTTA => DyeColor::RED(),
|
||||
Ids::WHITE_TERRACOTTA => DyeColor::WHITE(),
|
||||
Ids::YELLOW_TERRACOTTA => DyeColor::YELLOW(),
|
||||
] as $id => $color){
|
||||
$this->mapSimple($id, fn() => Blocks::STAINED_CLAY()->setColor($color));
|
||||
}
|
||||
|
||||
foreach([
|
||||
Ids::BLACK_STAINED_GLASS => DyeColor::BLACK(),
|
||||
Ids::BLUE_STAINED_GLASS => DyeColor::BLUE(),
|
||||
Ids::BROWN_STAINED_GLASS => DyeColor::BROWN(),
|
||||
Ids::CYAN_STAINED_GLASS => DyeColor::CYAN(),
|
||||
Ids::GRAY_STAINED_GLASS => DyeColor::GRAY(),
|
||||
Ids::GREEN_STAINED_GLASS => DyeColor::GREEN(),
|
||||
Ids::LIGHT_BLUE_STAINED_GLASS => DyeColor::LIGHT_BLUE(),
|
||||
Ids::LIGHT_GRAY_STAINED_GLASS => DyeColor::LIGHT_GRAY(),
|
||||
Ids::LIME_STAINED_GLASS => DyeColor::LIME(),
|
||||
Ids::MAGENTA_STAINED_GLASS => DyeColor::MAGENTA(),
|
||||
Ids::ORANGE_STAINED_GLASS => DyeColor::ORANGE(),
|
||||
Ids::PINK_STAINED_GLASS => DyeColor::PINK(),
|
||||
Ids::PURPLE_STAINED_GLASS => DyeColor::PURPLE(),
|
||||
Ids::RED_STAINED_GLASS => DyeColor::RED(),
|
||||
Ids::WHITE_STAINED_GLASS => DyeColor::WHITE(),
|
||||
Ids::YELLOW_STAINED_GLASS => DyeColor::YELLOW(),
|
||||
] as $id => $color){
|
||||
$this->mapSimple($id, fn() => Blocks::STAINED_GLASS()->setColor($color));
|
||||
}
|
||||
|
||||
foreach([
|
||||
Ids::BLACK_STAINED_GLASS_PANE => DyeColor::BLACK(),
|
||||
Ids::BLUE_STAINED_GLASS_PANE => DyeColor::BLUE(),
|
||||
Ids::BROWN_STAINED_GLASS_PANE => DyeColor::BROWN(),
|
||||
Ids::CYAN_STAINED_GLASS_PANE => DyeColor::CYAN(),
|
||||
Ids::GRAY_STAINED_GLASS_PANE => DyeColor::GRAY(),
|
||||
Ids::GREEN_STAINED_GLASS_PANE => DyeColor::GREEN(),
|
||||
Ids::LIGHT_BLUE_STAINED_GLASS_PANE => DyeColor::LIGHT_BLUE(),
|
||||
Ids::LIGHT_GRAY_STAINED_GLASS_PANE => DyeColor::LIGHT_GRAY(),
|
||||
Ids::LIME_STAINED_GLASS_PANE => DyeColor::LIME(),
|
||||
Ids::MAGENTA_STAINED_GLASS_PANE => DyeColor::MAGENTA(),
|
||||
Ids::ORANGE_STAINED_GLASS_PANE => DyeColor::ORANGE(),
|
||||
Ids::PINK_STAINED_GLASS_PANE => DyeColor::PINK(),
|
||||
Ids::PURPLE_STAINED_GLASS_PANE => DyeColor::PURPLE(),
|
||||
Ids::RED_STAINED_GLASS_PANE => DyeColor::RED(),
|
||||
Ids::WHITE_STAINED_GLASS_PANE => DyeColor::WHITE(),
|
||||
Ids::YELLOW_STAINED_GLASS_PANE => DyeColor::YELLOW(),
|
||||
] as $id => $color){
|
||||
$this->mapSimple($id, fn() => Blocks::STAINED_GLASS_PANE()->setColor($color));
|
||||
}
|
||||
}
|
||||
|
||||
private function registerFlatCoralDeserializers() : void{
|
||||
@ -781,7 +865,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
StringValues::DAMAGE_BROKEN => 0,
|
||||
default => throw $in->badValueException(StateNames::DAMAGE, $value),
|
||||
})
|
||||
->setFacing($in->readLegacyHorizontalFacing());
|
||||
->setFacing($in->readCardinalHorizontalFacing());
|
||||
});
|
||||
$this->map(Ids::BAMBOO, function(Reader $in) : Block{
|
||||
return Blocks::BAMBOO()
|
||||
@ -831,7 +915,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::BIG_DRIPLEAF, function(Reader $in) : Block{
|
||||
if($in->readBool(StateNames::BIG_DRIPLEAF_HEAD)){
|
||||
return Blocks::BIG_DRIPLEAF_HEAD()
|
||||
->setFacing($in->readLegacyHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setLeafState(match($type = $in->readString(StateNames::BIG_DRIPLEAF_TILT)){
|
||||
StringValues::BIG_DRIPLEAF_TILT_NONE => DripleafState::STABLE(),
|
||||
StringValues::BIG_DRIPLEAF_TILT_UNSTABLE => DripleafState::UNSTABLE(),
|
||||
@ -841,7 +925,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
});
|
||||
}else{
|
||||
$in->ignored(StateNames::BIG_DRIPLEAF_TILT);
|
||||
return Blocks::BIG_DRIPLEAF_STEM()->setFacing($in->readLegacyHorizontalFacing());
|
||||
return Blocks::BIG_DRIPLEAF_STEM()->setFacing($in->readCardinalHorizontalFacing());
|
||||
}
|
||||
});
|
||||
$this->mapSlab(Ids::BLACKSTONE_SLAB, Ids::BLACKSTONE_DOUBLE_SLAB, fn() => Blocks::BLACKSTONE_SLAB());
|
||||
@ -849,7 +933,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::BLACKSTONE_WALL, fn(Reader $in) => Helper::decodeWall(Blocks::BLACKSTONE_WALL(), $in));
|
||||
$this->map(Ids::BLAST_FURNACE, function(Reader $in) : Block{
|
||||
return Blocks::BLAST_FURNACE()
|
||||
->setFacing($in->readHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setLit(false);
|
||||
});
|
||||
$this->map(Ids::BONE_BLOCK, function(Reader $in) : Block{
|
||||
@ -910,7 +994,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
});
|
||||
$this->map(Ids::CHEST, function(Reader $in) : Block{
|
||||
return Blocks::CHEST()
|
||||
->setFacing($in->readHorizontalFacing());
|
||||
->setFacing($in->readCardinalHorizontalFacing());
|
||||
});
|
||||
$this->map(Ids::CHORUS_FLOWER, function(Reader $in) : Block{
|
||||
return Blocks::CHORUS_FLOWER()
|
||||
@ -935,10 +1019,6 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
Blocks::GREEN_TORCH()->setFacing($in->readTorchFacing()) :
|
||||
Blocks::RED_TORCH()->setFacing($in->readTorchFacing());
|
||||
});
|
||||
$this->map(Ids::CONCRETE_POWDER, function(Reader $in) : Block{
|
||||
return Blocks::CONCRETE_POWDER()
|
||||
->setColor($in->readColor());
|
||||
});
|
||||
$this->map(Ids::COPPER_BLOCK, fn() => Helper::decodeCopper(Blocks::COPPER(), CopperOxidation::NONE()));
|
||||
$this->map(Ids::CUT_COPPER, fn() => Helper::decodeCopper(Blocks::CUT_COPPER(), CopperOxidation::NONE()));
|
||||
$this->mapSlab(Ids::CUT_COPPER_SLAB, Ids::DOUBLE_CUT_COPPER_SLAB, fn() => Helper::decodeCopper(Blocks::CUT_COPPER_SLAB(), CopperOxidation::NONE()));
|
||||
@ -1007,7 +1087,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::END_PORTAL_FRAME, function(Reader $in) : Block{
|
||||
return Blocks::END_PORTAL_FRAME()
|
||||
->setEye($in->readBool(StateNames::END_PORTAL_EYE_BIT))
|
||||
->setFacing($in->readLegacyHorizontalFacing());
|
||||
->setFacing($in->readCardinalHorizontalFacing());
|
||||
});
|
||||
$this->map(Ids::END_ROD, function(Reader $in) : Block{
|
||||
return Blocks::END_ROD()
|
||||
@ -1015,7 +1095,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
});
|
||||
$this->map(Ids::ENDER_CHEST, function(Reader $in) : Block{
|
||||
return Blocks::ENDER_CHEST()
|
||||
->setFacing($in->readHorizontalFacing());
|
||||
->setFacing($in->readCardinalHorizontalFacing());
|
||||
});
|
||||
$this->map(Ids::EXPOSED_COPPER, fn() => Helper::decodeCopper(Blocks::COPPER(), CopperOxidation::EXPOSED()));
|
||||
$this->map(Ids::EXPOSED_CUT_COPPER, fn() => Helper::decodeCopper(Blocks::CUT_COPPER(), CopperOxidation::EXPOSED()));
|
||||
@ -1042,7 +1122,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
});
|
||||
$this->map(Ids::FURNACE, function(Reader $in) : Block{
|
||||
return Blocks::FURNACE()
|
||||
->setFacing($in->readHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setLit(false);
|
||||
});
|
||||
$this->map(Ids::GLOW_LICHEN, fn(Reader $in) => Blocks::GLOW_LICHEN()->setFaces($in->readFacingFlags()));
|
||||
@ -1084,7 +1164,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::LAVA, fn(Reader $in) => Helper::decodeStillLiquid(Blocks::LAVA(), $in));
|
||||
$this->map(Ids::LECTERN, function(Reader $in) : Block{
|
||||
return Blocks::LECTERN()
|
||||
->setFacing($in->readLegacyHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setProducingSignal($in->readBool(StateNames::POWERED_BIT));
|
||||
});
|
||||
$this->map(Ids::LEVER, function(Reader $in) : Block{
|
||||
@ -1113,13 +1193,13 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
$this->map(Ids::LIGHT_WEIGHTED_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeWeightedPressurePlate(Blocks::WEIGHTED_PRESSURE_PLATE_LIGHT(), $in));
|
||||
$this->map(Ids::LIT_BLAST_FURNACE, function(Reader $in) : Block{
|
||||
return Blocks::BLAST_FURNACE()
|
||||
->setFacing($in->readHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setLit(true);
|
||||
});
|
||||
$this->map(Ids::LIT_DEEPSLATE_REDSTONE_ORE, fn() => Blocks::DEEPSLATE_REDSTONE_ORE()->setLit(true));
|
||||
$this->map(Ids::LIT_FURNACE, function(Reader $in) : Block{
|
||||
return Blocks::FURNACE()
|
||||
->setFacing($in->readHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setLit(true);
|
||||
});
|
||||
$this->map(Ids::LIT_PUMPKIN, function(Reader $in) : Block{
|
||||
@ -1136,7 +1216,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
});
|
||||
$this->map(Ids::LIT_SMOKER, function(Reader $in) : Block{
|
||||
return Blocks::SMOKER()
|
||||
->setFacing($in->readHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setLit(true);
|
||||
});
|
||||
$this->map(Ids::LOOM, function(Reader $in) : Block{
|
||||
@ -1180,7 +1260,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
//Pink petals only uses 0-3, but GROWTH state can go up to 7
|
||||
$growth = $in->readBoundedInt(StateNames::GROWTH, 0, 7);
|
||||
return Blocks::PINK_PETALS()
|
||||
->setFacing($in->readLegacyHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setCount(min($growth + 1, PinkPetals::MAX_COUNT));
|
||||
});
|
||||
$this->mapStairs(Ids::POLISHED_ANDESITE_STAIRS, fn() => Blocks::POLISHED_ANDESITE_STAIRS());
|
||||
@ -1354,12 +1434,12 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
});
|
||||
$this->map(Ids::SMOKER, function(Reader $in) : Block{
|
||||
return Blocks::SMOKER()
|
||||
->setFacing($in->readHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setLit(false);
|
||||
});
|
||||
$this->map(Ids::SMALL_DRIPLEAF_BLOCK, function(Reader $in) : Block{
|
||||
return Blocks::SMALL_DRIPLEAF()
|
||||
->setFacing($in->readLegacyHorizontalFacing())
|
||||
->setFacing($in->readCardinalHorizontalFacing())
|
||||
->setTop($in->readBool(StateNames::UPPER_BLOCK_BIT));
|
||||
});
|
||||
$this->mapStairs(Ids::SMOOTH_QUARTZ_STAIRS, fn() => Blocks::SMOOTH_QUARTZ_STAIRS());
|
||||
@ -1388,18 +1468,6 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
default => throw $in->badValueException(StateNames::SPONGE_TYPE, $type),
|
||||
});
|
||||
});
|
||||
$this->map(Ids::STAINED_GLASS, function(Reader $in) : Block{
|
||||
return Blocks::STAINED_GLASS()
|
||||
->setColor($in->readColor());
|
||||
});
|
||||
$this->map(Ids::STAINED_GLASS_PANE, function(Reader $in) : Block{
|
||||
return Blocks::STAINED_GLASS_PANE()
|
||||
->setColor($in->readColor());
|
||||
});
|
||||
$this->map(Ids::STAINED_HARDENED_CLAY, function(Reader $in) : Block{
|
||||
return Blocks::STAINED_CLAY()
|
||||
->setColor($in->readColor());
|
||||
});
|
||||
$this->map(Ids::STANDING_BANNER, function(Reader $in) : Block{
|
||||
return Blocks::BANNER()
|
||||
->setRotation($in->readBoundedInt(StateNames::GROUND_SIGN_DIRECTION, 0, 15));
|
||||
@ -1436,7 +1504,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
});
|
||||
$this->map(Ids::STONECUTTER_BLOCK, function(Reader $in) : Block{
|
||||
return Blocks::STONECUTTER()
|
||||
->setFacing($in->readHorizontalFacing());
|
||||
->setFacing($in->readCardinalHorizontalFacing());
|
||||
});
|
||||
$this->map(Ids::SWEET_BERRY_BUSH, function(Reader $in) : Block{
|
||||
//berry bush only wants 0-3, but it can be bigger in MCPE due to misuse of GROWTH state which goes up to 7
|
||||
@ -1462,7 +1530,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
|
||||
});
|
||||
$this->map(Ids::TRAPPED_CHEST, function(Reader $in) : Block{
|
||||
return Blocks::TRAPPED_CHEST()
|
||||
->setFacing($in->readHorizontalFacing());
|
||||
->setFacing($in->readCardinalHorizontalFacing());
|
||||
});
|
||||
$this->map(Ids::TRIP_WIRE, function(Reader $in) : Block{
|
||||
return Blocks::TRIPWIRE()
|
||||
|
@ -246,9 +246,9 @@ final class BlockStateWriter{
|
||||
|
||||
/** @return $this */
|
||||
public function writeSlabPosition(SlabType $slabType) : self{
|
||||
$this->writeBool(BlockStateNames::TOP_SLOT_BIT, match($slabType->id()){
|
||||
SlabType::TOP()->id() => true,
|
||||
SlabType::BOTTOM()->id() => false,
|
||||
$this->writeString(BlockStateNames::MC_VERTICAL_HALF, match($slabType->id()){
|
||||
SlabType::TOP()->id() => StringValues::MC_VERTICAL_HALF_TOP,
|
||||
SlabType::BOTTOM()->id() => StringValues::MC_VERTICAL_HALF_BOTTOM,
|
||||
default => throw new BlockStateSerializeException("Invalid slab type " . $slabType->name())
|
||||
});
|
||||
return $this;
|
||||
|
@ -125,6 +125,7 @@ final class ItemTypeNames{
|
||||
public const COMPASS = "minecraft:compass";
|
||||
public const COMPOUND = "minecraft:compound";
|
||||
public const CONCRETE = "minecraft:concrete";
|
||||
public const CONCRETE_POWDER = "minecraft:concrete_powder";
|
||||
public const COOKED_BEEF = "minecraft:cooked_beef";
|
||||
public const COOKED_CHICKEN = "minecraft:cooked_chicken";
|
||||
public const COOKED_COD = "minecraft:cooked_cod";
|
||||
@ -437,6 +438,9 @@ final class ItemTypeNames{
|
||||
public const SPRUCE_SIGN = "minecraft:spruce_sign";
|
||||
public const SPYGLASS = "minecraft:spyglass";
|
||||
public const SQUID_SPAWN_EGG = "minecraft:squid_spawn_egg";
|
||||
public const STAINED_GLASS = "minecraft:stained_glass";
|
||||
public const STAINED_GLASS_PANE = "minecraft:stained_glass_pane";
|
||||
public const STAINED_HARDENED_CLAY = "minecraft:stained_hardened_clay";
|
||||
public const STICK = "minecraft:stick";
|
||||
public const STONE_AXE = "minecraft:stone_axe";
|
||||
public const STONE_HOE = "minecraft:stone_hoe";
|
||||
|
@ -1686,7 +1686,7 @@ abstract class Entity{
|
||||
*/
|
||||
public function broadcastSound(Sound $sound, ?array $targets = null) : void{
|
||||
if(!$this->silent){
|
||||
NetworkBroadcastUtils::broadcastPackets($targets ?? $this->getViewers(), $sound->encode($this->location));
|
||||
$this->getWorld()->addSound($this->location->asVector3(), $sound, $targets ?? $this->getViewers());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,6 +205,7 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->registerBlock("carpet", fn() => Blocks::CARPET());
|
||||
$result->registerBlock("carrot_block", fn() => Blocks::CARROTS());
|
||||
$result->registerBlock("carrots", fn() => Blocks::CARROTS());
|
||||
$result->registerBlock("cartography_table", fn() => Blocks::CARTOGRAPHY_TABLE());
|
||||
$result->registerBlock("carved_pumpkin", fn() => Blocks::CARVED_PUMPKIN());
|
||||
$result->registerBlock("cauldron", fn() => Blocks::CAULDRON());
|
||||
$result->registerBlock("cave_vines", fn() => Blocks::CAVE_VINES());
|
||||
@ -975,6 +976,7 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->registerBlock("slime", fn() => Blocks::SLIME());
|
||||
$result->registerBlock("slime_block", fn() => Blocks::SLIME());
|
||||
$result->registerBlock("small_dripleaf", fn() => Blocks::SMALL_DRIPLEAF());
|
||||
$result->registerBlock("smithing_table", fn() => Blocks::SMITHING_TABLE());
|
||||
$result->registerBlock("smoker", fn() => Blocks::SMOKER());
|
||||
$result->registerBlock("smooth_basalt", fn() => Blocks::SMOOTH_BASALT());
|
||||
$result->registerBlock("smooth_quartz", fn() => Blocks::SMOOTH_QUARTZ());
|
||||
@ -1047,6 +1049,8 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->registerBlock("stripped_acacia_wood", fn() => Blocks::ACACIA_WOOD()->setStripped(true));
|
||||
$result->registerBlock("stripped_birch_log", fn() => Blocks::BIRCH_LOG()->setStripped(true));
|
||||
$result->registerBlock("stripped_birch_wood", fn() => Blocks::BIRCH_WOOD()->setStripped(true));
|
||||
$result->registerBlock("stripped_cherry_log", fn() => Blocks::CHERRY_LOG()->setStripped(true));
|
||||
$result->registerBlock("stripped_cherry_wood", fn() => Blocks::CHERRY_WOOD()->setStripped(true));
|
||||
$result->registerBlock("stripped_crimson_hyphae", fn() => Blocks::CRIMSON_HYPHAE()->setStripped(true));
|
||||
$result->registerBlock("stripped_crimson_stem", fn() => Blocks::CRIMSON_STEM()->setStripped(true));
|
||||
$result->registerBlock("stripped_dark_oak_log", fn() => Blocks::DARK_OAK_LOG()->setStripped(true));
|
||||
|
@ -108,6 +108,7 @@ use pocketmine\utils\BinaryStream;
|
||||
use pocketmine\utils\ObjectSet;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\world\Position;
|
||||
use pocketmine\YmlServerProperties;
|
||||
use function array_map;
|
||||
use function array_values;
|
||||
use function base64_encode;
|
||||
@ -641,7 +642,7 @@ class NetworkSession{
|
||||
}else{
|
||||
$translated = $message;
|
||||
}
|
||||
$this->sendDataPacket(DisconnectPacket::create($translated));
|
||||
$this->sendDataPacket(DisconnectPacket::create(0, $translated));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -740,7 +741,7 @@ class NetworkSession{
|
||||
}
|
||||
$this->logger->debug("Xbox Live authenticated: " . ($this->authenticated ? "YES" : "NO"));
|
||||
|
||||
$checkXUID = $this->server->getConfigGroup()->getPropertyBool("player.verify-xuid", true);
|
||||
$checkXUID = $this->server->getConfigGroup()->getPropertyBool(YmlServerProperties::PLAYER_VERIFY_XUID, true);
|
||||
$myXUID = $this->info instanceof XboxLivePlayerInfo ? $this->info->getXuid() : "";
|
||||
$kickForXUIDMismatch = function(string $xuid) use ($checkXUID, $myXUID) : bool{
|
||||
if($checkXUID && $myXUID !== $xuid){
|
||||
|
@ -79,7 +79,6 @@ use pocketmine\network\mcpe\protocol\PlayerAuthInputPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerHotbarPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerInputPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerSkinPacket;
|
||||
use pocketmine\network\mcpe\protocol\RequestAbilityPacket;
|
||||
use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket;
|
||||
use pocketmine\network\mcpe\protocol\ServerSettingsRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\SetActorMotionPacket;
|
||||
@ -116,7 +115,6 @@ use function fmod;
|
||||
use function get_debug_type;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function is_bool;
|
||||
use function is_infinite;
|
||||
use function is_nan;
|
||||
use function json_decode;
|
||||
@ -201,7 +199,7 @@ class InGamePacketHandler extends PacketHandler{
|
||||
}
|
||||
|
||||
$hasMoved = $this->lastPlayerAuthInputPosition === null || !$this->lastPlayerAuthInputPosition->equals($rawPos);
|
||||
$newPos = $rawPos->round(4)->subtract(0, 1.62, 0);
|
||||
$newPos = $rawPos->subtract(0, 1.62, 0)->round(4);
|
||||
|
||||
if($this->forceMoveSync && $hasMoved){
|
||||
$curPos = $this->player->getLocation();
|
||||
@ -224,11 +222,13 @@ class InGamePacketHandler extends PacketHandler{
|
||||
$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);
|
||||
$flying = $this->resolveOnOffInputFlags($inputFlags, PlayerAuthInputFlags::START_FLYING, PlayerAuthInputFlags::STOP_FLYING);
|
||||
$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));
|
||||
($gliding !== null && !$this->player->toggleGlide($gliding)) |
|
||||
($flying !== null && !$this->player->toggleFlight($flying));
|
||||
if((bool) $mismatch){
|
||||
$this->player->sendData([$this->player]);
|
||||
}
|
||||
@ -1032,22 +1032,4 @@ class InGamePacketHandler extends PacketHandler{
|
||||
$this->player->emote($packet->getEmoteId());
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleRequestAbility(RequestAbilityPacket $packet) : bool{
|
||||
if($packet->getAbilityId() === RequestAbilityPacket::ABILITY_FLYING){
|
||||
$isFlying = $packet->getAbilityValue();
|
||||
if(!is_bool($isFlying)){
|
||||
throw new PacketHandlingException("Flying ability should always have a bool value");
|
||||
}
|
||||
if($isFlying !== $this->player->isFlying()){
|
||||
if(!$this->player->toggleFlight($isFlying)){
|
||||
$this->session->syncAbilities($this->player);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ class ResourcePacksPacketHandler extends PacketHandler{
|
||||
);
|
||||
}, $this->resourcePackManager->getResourceStack());
|
||||
//TODO: support forcing server packs
|
||||
$this->session->sendDataPacket(ResourcePacksInfoPacket::create($resourcePackEntries, [], $this->resourcePackManager->resourcePacksRequired(), false, false));
|
||||
$this->session->sendDataPacket(ResourcePacksInfoPacket::create($resourcePackEntries, [], $this->resourcePackManager->resourcePacksRequired(), false, false, []));
|
||||
$this->session->getLogger()->debug("Waiting for client to accept resource packs");
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ use pocketmine\Server;
|
||||
use pocketmine\thread\ThreadCrashException;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\YmlServerProperties;
|
||||
use raklib\generic\DisconnectReason;
|
||||
use raklib\generic\SocketException;
|
||||
use raklib\protocol\EncapsulatedPacket;
|
||||
@ -125,7 +126,7 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{
|
||||
$threadToMainBuffer,
|
||||
new InternetAddress($ip, $port, $ipV6 ? 6 : 4),
|
||||
$this->rakServerId,
|
||||
$this->server->getConfigGroup()->getPropertyInt("network.max-mtu-size", 1492),
|
||||
$this->server->getConfigGroup()->getPropertyInt(YmlServerProperties::NETWORK_MAX_MTU_SIZE, 1492),
|
||||
self::MCPE_RAKNET_PROTOCOL_VERSION,
|
||||
$sleeperEntry
|
||||
);
|
||||
|
@ -29,6 +29,7 @@ use pocketmine\plugin\Plugin;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\YmlServerProperties;
|
||||
use function array_map;
|
||||
use function chr;
|
||||
use function count;
|
||||
@ -66,7 +67,7 @@ final class QueryInfo{
|
||||
|
||||
public function __construct(Server $server){
|
||||
$this->serverName = $server->getMotd();
|
||||
$this->listPlugins = $server->getConfigGroup()->getPropertyBool("settings.query-plugins", true);
|
||||
$this->listPlugins = $server->getConfigGroup()->getPropertyBool(YmlServerProperties::SETTINGS_QUERY_PLUGINS, true);
|
||||
$this->plugins = $server->getPluginManager()->getPlugins();
|
||||
$this->players = array_map(fn(Player $p) => $p->getName(), $server->getOnlinePlayers());
|
||||
|
||||
|
@ -72,19 +72,21 @@ class PermissionManager{
|
||||
}
|
||||
|
||||
public function unsubscribeFromPermission(string $permission, PermissibleInternal $permissible) : void{
|
||||
if(isset($this->permSubs[$permission])){
|
||||
unset($this->permSubs[$permission][spl_object_id($permissible)]);
|
||||
if(count($this->permSubs[$permission]) === 0){
|
||||
if(isset($this->permSubs[$permission][spl_object_id($permissible)])){
|
||||
if(count($this->permSubs[$permission]) === 1){
|
||||
unset($this->permSubs[$permission]);
|
||||
}else{
|
||||
unset($this->permSubs[$permission][spl_object_id($permissible)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function unsubscribeFromAllPermissions(PermissibleInternal $permissible) : void{
|
||||
foreach($this->permSubs as $permission => $subs){
|
||||
unset($this->permSubs[$permission][spl_object_id($permissible)]);
|
||||
if(count($this->permSubs[$permission]) === 0){
|
||||
if(count($subs) === 1 && isset($subs[spl_object_id($permissible)])){
|
||||
unset($this->permSubs[$permission]);
|
||||
}else{
|
||||
unset($this->permSubs[$permission][spl_object_id($permissible)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -119,6 +119,7 @@ use pocketmine\permission\PermissibleBase;
|
||||
use pocketmine\permission\PermissibleDelegateTrait;
|
||||
use pocketmine\player\chat\StandardChatFormatter;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\ServerProperties;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -134,6 +135,7 @@ use pocketmine\world\sound\FireExtinguishSound;
|
||||
use pocketmine\world\sound\ItemBreakSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
use pocketmine\world\World;
|
||||
use pocketmine\YmlServerProperties;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use function abs;
|
||||
use function array_filter;
|
||||
@ -317,8 +319,8 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
$rootPermissions[DefaultPermissions::ROOT_OPERATOR] = true;
|
||||
}
|
||||
$this->perm = new PermissibleBase($rootPermissions);
|
||||
$this->chunksPerTick = $this->server->getConfigGroup()->getPropertyInt("chunk-sending.per-tick", 4);
|
||||
$this->spawnThreshold = (int) (($this->server->getConfigGroup()->getPropertyInt("chunk-sending.spawn-radius", 4) ** 2) * M_PI);
|
||||
$this->chunksPerTick = $this->server->getConfigGroup()->getPropertyInt(YmlServerProperties::CHUNK_SENDING_PER_TICK, 4);
|
||||
$this->spawnThreshold = (int) (($this->server->getConfigGroup()->getPropertyInt(YmlServerProperties::CHUNK_SENDING_SPAWN_RADIUS, 4) ** 2) * M_PI);
|
||||
$this->chunkSelector = new ChunkSelector();
|
||||
|
||||
$this->chunkLoader = new class implements ChunkLoader{};
|
||||
@ -583,7 +585,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
|
||||
$this->viewDistance = $newViewDistance;
|
||||
|
||||
$this->spawnThreshold = (int) (min($this->viewDistance, $this->server->getConfigGroup()->getPropertyInt("chunk-sending.spawn-radius", 4)) ** 2 * M_PI);
|
||||
$this->spawnThreshold = (int) (min($this->viewDistance, $this->server->getConfigGroup()->getPropertyInt(YmlServerProperties::CHUNK_SENDING_SPAWN_RADIUS, 4)) ** 2 * M_PI);
|
||||
|
||||
$this->nextChunkOrderRun = 0;
|
||||
|
||||
@ -1844,7 +1846,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
|
||||
if(!$this->canInteract($entity->getLocation(), self::MAX_REACH_DISTANCE_ENTITY_INTERACTION)){
|
||||
$this->logger->debug("Cancelled attack of entity " . $entity->getId() . " due to not currently being interactable");
|
||||
$ev->cancel();
|
||||
}elseif($this->isSpectator() || ($entity instanceof Player && !$this->server->getConfigGroup()->getConfigBool("pvp"))){
|
||||
}elseif($this->isSpectator() || ($entity instanceof Player && !$this->server->getConfigGroup()->getConfigBool(ServerProperties::PVP))){
|
||||
$ev->cancel();
|
||||
}
|
||||
|
||||
|
@ -510,9 +510,12 @@ class PluginManager{
|
||||
|
||||
unset($this->enabledPlugins[$plugin->getDescription()->getName()]);
|
||||
foreach(Utils::stringifyKeys($this->pluginDependents) as $dependency => $dependentList){
|
||||
unset($this->pluginDependents[$dependency][$plugin->getDescription()->getName()]);
|
||||
if(count($this->pluginDependents[$dependency]) === 0){
|
||||
unset($this->pluginDependents[$dependency]);
|
||||
if(isset($this->pluginDependents[$dependency][$plugin->getDescription()->getName()])){
|
||||
if(count($this->pluginDependents[$dependency]) === 1){
|
||||
unset($this->pluginDependents[$dependency]);
|
||||
}else{
|
||||
unset($this->pluginDependents[$dependency][$plugin->getDescription()->getName()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,11 @@ final class Promise{
|
||||
* @phpstan-param \Closure() : void $onFailure
|
||||
*/
|
||||
public function onCompletion(\Closure $onSuccess, \Closure $onFailure) : void{
|
||||
if($this->shared->resolved){
|
||||
$this->shared->result === null ? $onFailure() : $onSuccess($this->shared->result);
|
||||
$state = $this->shared->state;
|
||||
if($state === true){
|
||||
$onSuccess($this->shared->result);
|
||||
}elseif($state === false){
|
||||
$onFailure();
|
||||
}else{
|
||||
$this->shared->onSuccess[spl_object_id($onSuccess)] = $onSuccess;
|
||||
$this->shared->onFailure[spl_object_id($onFailure)] = $onFailure;
|
||||
@ -50,6 +53,8 @@ final class Promise{
|
||||
}
|
||||
|
||||
public function isResolved() : bool{
|
||||
return $this->shared->resolved;
|
||||
//TODO: perhaps this should return true when rejected? currently there's no way to tell if a promise was
|
||||
//rejected or just hasn't been resolved yet
|
||||
return $this->shared->state === true;
|
||||
}
|
||||
}
|
||||
|
@ -41,10 +41,10 @@ final class PromiseResolver{
|
||||
* @phpstan-param TValue $value
|
||||
*/
|
||||
public function resolve(mixed $value) : void{
|
||||
if($this->shared->resolved){
|
||||
if($this->shared->state !== null){
|
||||
throw new \LogicException("Promise has already been resolved/rejected");
|
||||
}
|
||||
$this->shared->resolved = true;
|
||||
$this->shared->state = true;
|
||||
$this->shared->result = $value;
|
||||
foreach($this->shared->onSuccess as $c){
|
||||
$c($value);
|
||||
@ -54,10 +54,10 @@ final class PromiseResolver{
|
||||
}
|
||||
|
||||
public function reject() : void{
|
||||
if($this->shared->resolved){
|
||||
if($this->shared->state !== null){
|
||||
throw new \LogicException("Promise has already been resolved/rejected");
|
||||
}
|
||||
$this->shared->resolved = true;
|
||||
$this->shared->state = false;
|
||||
foreach($this->shared->onFailure as $c){
|
||||
$c();
|
||||
}
|
||||
|
@ -41,8 +41,8 @@ final class PromiseSharedData{
|
||||
*/
|
||||
public array $onFailure = [];
|
||||
|
||||
public bool $resolved = false;
|
||||
public ?bool $state = null;
|
||||
|
||||
/** @phpstan-var TValue|null */
|
||||
public mixed $result = null;
|
||||
/** @phpstan-var TValue */
|
||||
public mixed $result;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ use pocketmine\utils\Internet;
|
||||
use pocketmine\utils\Process;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\VersionInfo;
|
||||
use pocketmine\YmlServerProperties;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use function array_map;
|
||||
use function array_values;
|
||||
@ -57,7 +58,7 @@ class SendUsageTask extends AsyncTask{
|
||||
* @phpstan-param array<string, string> $playerList
|
||||
*/
|
||||
public function __construct(Server $server, int $type, array $playerList = []){
|
||||
$endpoint = "http://" . $server->getConfigGroup()->getPropertyString("anonymous-statistics.host", "stats.pocketmine.net") . "/";
|
||||
$endpoint = "http://" . $server->getConfigGroup()->getPropertyString(YmlServerProperties::ANONYMOUS_STATISTICS_HOST, "stats.pocketmine.net") . "/";
|
||||
|
||||
$data = [];
|
||||
$data["uniqueServerId"] = $server->getServerUniqueId()->toString();
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\event\server\UpdateNotifyEvent;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\VersionString;
|
||||
use pocketmine\VersionInfo;
|
||||
use pocketmine\YmlServerProperties;
|
||||
use function date;
|
||||
use function strtolower;
|
||||
use function ucfirst;
|
||||
@ -43,7 +44,7 @@ class UpdateChecker{
|
||||
$this->logger = new \PrefixedLogger($server->getLogger(), "Update Checker");
|
||||
$this->endpoint = "http://$endpoint/api/";
|
||||
|
||||
if($server->getConfigGroup()->getPropertyBool("auto-updater.enabled", true)){
|
||||
if($server->getConfigGroup()->getPropertyBool(YmlServerProperties::AUTO_UPDATER_ENABLED, true)){
|
||||
$this->doCheck();
|
||||
}
|
||||
}
|
||||
@ -59,7 +60,7 @@ class UpdateChecker{
|
||||
$this->checkUpdate($updateInfo);
|
||||
if($this->hasUpdate()){
|
||||
(new UpdateNotifyEvent($this))->call();
|
||||
if($this->server->getConfigGroup()->getPropertyBool("auto-updater.on-update.warn-console", true)){
|
||||
if($this->server->getConfigGroup()->getPropertyBool(YmlServerProperties::AUTO_UPDATER_ON_UPDATE_WARN_CONSOLE, true)){
|
||||
$this->showConsoleUpdate();
|
||||
}
|
||||
}else{
|
||||
@ -157,7 +158,7 @@ class UpdateChecker{
|
||||
* Returns the channel used for update checking (stable, beta, dev)
|
||||
*/
|
||||
public function getChannel() : string{
|
||||
return strtolower($this->server->getConfigGroup()->getPropertyString("auto-updater.preferred-channel", "stable"));
|
||||
return strtolower($this->server->getConfigGroup()->getPropertyString(YmlServerProperties::AUTO_UPDATER_PREFERRED_CHANNEL, "stable"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,8 +37,8 @@ use function preg_match;
|
||||
*/
|
||||
trait RegistryTrait{
|
||||
/**
|
||||
* @var object[]
|
||||
* @phpstan-var array<string, object>
|
||||
* @var object[]|null
|
||||
* @phpstan-var array<string, object>|null
|
||||
*/
|
||||
private static $members = null;
|
||||
|
||||
@ -54,6 +54,9 @@ trait RegistryTrait{
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private static function _registryRegister(string $name, object $member) : void{
|
||||
if(self::$members === null){
|
||||
throw new AssumptionFailedError("Cannot register members outside of " . self::class . "::setup()");
|
||||
}
|
||||
self::verifyName($name);
|
||||
$upperName = mb_strtoupper($name);
|
||||
if(isset(self::$members[$upperName])){
|
||||
@ -86,6 +89,9 @@ trait RegistryTrait{
|
||||
*/
|
||||
private static function _registryFromString(string $name) : object{
|
||||
self::checkInit();
|
||||
if(self::$members === null){
|
||||
throw new AssumptionFailedError(self::class . "::checkInit() did not initialize self::\$members correctly");
|
||||
}
|
||||
$upperName = mb_strtoupper($name);
|
||||
if(!isset(self::$members[$upperName])){
|
||||
throw new \InvalidArgumentException("No such registry member: " . self::class . "::" . $upperName);
|
||||
@ -121,6 +127,6 @@ trait RegistryTrait{
|
||||
*/
|
||||
private static function _registryGetAll() : array{
|
||||
self::checkInit();
|
||||
return array_map(self::preprocessMember(...), self::$members);
|
||||
return array_map(self::preprocessMember(...), self::$members ?? throw new AssumptionFailedError(self::class . "::checkInit() did not initialize self::\$members correctly"));
|
||||
}
|
||||
}
|
||||
|
@ -104,6 +104,7 @@ use pocketmine\world\particle\Particle;
|
||||
use pocketmine\world\sound\BlockPlaceSound;
|
||||
use pocketmine\world\sound\Sound;
|
||||
use pocketmine\world\utils\SubChunkExplorer;
|
||||
use pocketmine\YmlServerProperties;
|
||||
use function abs;
|
||||
use function array_filter;
|
||||
use function array_key_exists;
|
||||
@ -513,14 +514,14 @@ class World implements ChunkManager{
|
||||
$this->time = $this->provider->getWorldData()->getTime();
|
||||
|
||||
$cfg = $this->server->getConfigGroup();
|
||||
$this->chunkTickRadius = min($this->server->getViewDistance(), max(0, $cfg->getPropertyInt("chunk-ticking.tick-radius", 4)));
|
||||
$this->chunkTickRadius = min($this->server->getViewDistance(), max(0, $cfg->getPropertyInt(YmlServerProperties::CHUNK_TICKING_TICK_RADIUS, 4)));
|
||||
if($cfg->getPropertyInt("chunk-ticking.per-tick", 40) <= 0){
|
||||
//TODO: this needs l10n
|
||||
$this->logger->warning("\"chunk-ticking.per-tick\" setting is deprecated, but you've used it to disable chunk ticking. Set \"chunk-ticking.tick-radius\" to 0 in \"pocketmine.yml\" instead.");
|
||||
$this->chunkTickRadius = 0;
|
||||
}
|
||||
$this->tickedBlocksPerSubchunkPerTick = $cfg->getPropertyInt("chunk-ticking.blocks-per-subchunk-per-tick", self::DEFAULT_TICKED_BLOCKS_PER_SUBCHUNK_PER_TICK);
|
||||
$this->maxConcurrentChunkPopulationTasks = $cfg->getPropertyInt("chunk-generation.population-queue-size", 2);
|
||||
$this->tickedBlocksPerSubchunkPerTick = $cfg->getPropertyInt(YmlServerProperties::CHUNK_TICKING_BLOCKS_PER_SUBCHUNK_PER_TICK, self::DEFAULT_TICKED_BLOCKS_PER_SUBCHUNK_PER_TICK);
|
||||
$this->maxConcurrentChunkPopulationTasks = $cfg->getPropertyInt(YmlServerProperties::CHUNK_GENERATION_POPULATION_QUEUE_SIZE, 2);
|
||||
|
||||
$this->initRandomTickBlocksFromConfig($cfg);
|
||||
|
||||
@ -541,7 +542,7 @@ class World implements ChunkManager{
|
||||
private function initRandomTickBlocksFromConfig(ServerConfigGroup $cfg) : void{
|
||||
$dontTickBlocks = [];
|
||||
$parser = StringToItemParser::getInstance();
|
||||
foreach($cfg->getProperty("chunk-ticking.disable-block-ticking", []) as $name){
|
||||
foreach($cfg->getProperty(YmlServerProperties::CHUNK_TICKING_DISABLE_BLOCK_TICKING, []) as $name){
|
||||
$name = (string) $name;
|
||||
$item = $parser->parse($name);
|
||||
if($item !== null){
|
||||
@ -825,14 +826,15 @@ class World implements ChunkManager{
|
||||
$chunkHash = World::chunkHash($chunkX, $chunkZ);
|
||||
$loaderId = spl_object_id($loader);
|
||||
if(isset($this->chunkLoaders[$chunkHash][$loaderId])){
|
||||
unset($this->chunkLoaders[$chunkHash][$loaderId]);
|
||||
if(count($this->chunkLoaders[$chunkHash]) === 0){
|
||||
if(count($this->chunkLoaders[$chunkHash]) === 1){
|
||||
unset($this->chunkLoaders[$chunkHash]);
|
||||
$this->unloadChunkRequest($chunkX, $chunkZ, true);
|
||||
if(isset($this->chunkPopulationRequestMap[$chunkHash]) && !isset($this->activeChunkPopulationTasks[$chunkHash])){
|
||||
$this->chunkPopulationRequestMap[$chunkHash]->reject();
|
||||
unset($this->chunkPopulationRequestMap[$chunkHash]);
|
||||
}
|
||||
}else{
|
||||
unset($this->chunkLoaders[$chunkHash][$loaderId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -860,11 +862,12 @@ class World implements ChunkManager{
|
||||
public function unregisterChunkListener(ChunkListener $listener, int $chunkX, int $chunkZ) : void{
|
||||
$hash = World::chunkHash($chunkX, $chunkZ);
|
||||
if(isset($this->chunkListeners[$hash])){
|
||||
unset($this->chunkListeners[$hash][spl_object_id($listener)]);
|
||||
unset($this->playerChunkListeners[$hash][spl_object_id($listener)]);
|
||||
if(count($this->chunkListeners[$hash]) === 0){
|
||||
if(count($this->chunkListeners[$hash]) === 1){
|
||||
unset($this->chunkListeners[$hash]);
|
||||
unset($this->playerChunkListeners[$hash]);
|
||||
}else{
|
||||
unset($this->chunkListeners[$hash][spl_object_id($listener)]);
|
||||
unset($this->playerChunkListeners[$hash][spl_object_id($listener)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1101,19 +1104,22 @@ class World implements ChunkManager{
|
||||
$blockPosition = BlockPosition::fromVector3($b);
|
||||
|
||||
$tile = $this->getTileAt($b->x, $b->y, $b->z);
|
||||
if($tile instanceof Spawnable && count($fakeStateProperties = $tile->getRenderUpdateBugWorkaroundStateProperties($fullBlock)) > 0){
|
||||
$originalStateData = $blockTranslator->internalIdToNetworkStateData($fullBlock->getStateId());
|
||||
$fakeStateData = new BlockStateData(
|
||||
$originalStateData->getName(),
|
||||
array_merge($originalStateData->getStates(), $fakeStateProperties),
|
||||
$originalStateData->getVersion()
|
||||
);
|
||||
$packets[] = UpdateBlockPacket::create(
|
||||
$blockPosition,
|
||||
$blockTranslator->getBlockStateDictionary()->lookupStateIdFromData($fakeStateData) ?? throw new AssumptionFailedError("Unmapped fake blockstate data: " . $fakeStateData->toNbt()),
|
||||
UpdateBlockPacket::FLAG_NETWORK,
|
||||
UpdateBlockPacket::DATA_LAYER_NORMAL
|
||||
);
|
||||
if($tile instanceof Spawnable){
|
||||
$expectedClass = $fullBlock->getIdInfo()->getTileClass();
|
||||
if($expectedClass !== null && $tile instanceof $expectedClass && count($fakeStateProperties = $tile->getRenderUpdateBugWorkaroundStateProperties($fullBlock)) > 0){
|
||||
$originalStateData = $blockTranslator->internalIdToNetworkStateData($fullBlock->getStateId());
|
||||
$fakeStateData = new BlockStateData(
|
||||
$originalStateData->getName(),
|
||||
array_merge($originalStateData->getStates(), $fakeStateProperties),
|
||||
$originalStateData->getVersion()
|
||||
);
|
||||
$packets[] = UpdateBlockPacket::create(
|
||||
$blockPosition,
|
||||
$blockTranslator->getBlockStateDictionary()->lookupStateIdFromData($fakeStateData) ?? throw new AssumptionFailedError("Unmapped fake blockstate data: " . $fakeStateData->toNbt()),
|
||||
UpdateBlockPacket::FLAG_NETWORK,
|
||||
UpdateBlockPacket::DATA_LAYER_NORMAL
|
||||
);
|
||||
}
|
||||
}
|
||||
$packets[] = UpdateBlockPacket::create(
|
||||
$blockPosition,
|
||||
@ -1220,13 +1226,14 @@ class World implements ChunkManager{
|
||||
$chunkHash = World::chunkHash($chunkX, $chunkZ);
|
||||
$tickerId = spl_object_id($ticker);
|
||||
if(isset($this->registeredTickingChunks[$chunkHash][$tickerId])){
|
||||
unset($this->registeredTickingChunks[$chunkHash][$tickerId]);
|
||||
if(count($this->registeredTickingChunks[$chunkHash]) === 0){
|
||||
if(count($this->registeredTickingChunks[$chunkHash]) === 1){
|
||||
unset(
|
||||
$this->registeredTickingChunks[$chunkHash],
|
||||
$this->recheckTickingChunks[$chunkHash],
|
||||
$this->validTickingChunks[$chunkHash]
|
||||
);
|
||||
}else{
|
||||
unset($this->registeredTickingChunks[$chunkHash][$tickerId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2641,9 +2648,10 @@ class World implements ChunkManager{
|
||||
$pos = $this->entityLastKnownPositions[$entity->getId()];
|
||||
$chunkHash = World::chunkHash($pos->getFloorX() >> Chunk::COORD_BIT_SIZE, $pos->getFloorZ() >> Chunk::COORD_BIT_SIZE);
|
||||
if(isset($this->entitiesByChunk[$chunkHash][$entity->getId()])){
|
||||
unset($this->entitiesByChunk[$chunkHash][$entity->getId()]);
|
||||
if(count($this->entitiesByChunk[$chunkHash]) === 0){
|
||||
if(count($this->entitiesByChunk[$chunkHash]) === 1){
|
||||
unset($this->entitiesByChunk[$chunkHash]);
|
||||
}else{
|
||||
unset($this->entitiesByChunk[$chunkHash][$entity->getId()]);
|
||||
}
|
||||
}
|
||||
unset($this->entityLastKnownPositions[$entity->getId()]);
|
||||
@ -2676,9 +2684,10 @@ class World implements ChunkManager{
|
||||
if($oldChunkX !== $newChunkX || $oldChunkZ !== $newChunkZ){
|
||||
$oldChunkHash = World::chunkHash($oldChunkX, $oldChunkZ);
|
||||
if(isset($this->entitiesByChunk[$oldChunkHash][$entity->getId()])){
|
||||
unset($this->entitiesByChunk[$oldChunkHash][$entity->getId()]);
|
||||
if(count($this->entitiesByChunk[$oldChunkHash]) === 0){
|
||||
if(count($this->entitiesByChunk[$oldChunkHash]) === 1){
|
||||
unset($this->entitiesByChunk[$oldChunkHash]);
|
||||
}else{
|
||||
unset($this->entitiesByChunk[$oldChunkHash][$entity->getId()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,11 +51,11 @@ use function time;
|
||||
class BedrockWorldData extends BaseNbtWorldData{
|
||||
|
||||
public const CURRENT_STORAGE_VERSION = 10;
|
||||
public const CURRENT_STORAGE_NETWORK_VERSION = 594;
|
||||
public const CURRENT_STORAGE_NETWORK_VERSION = 622;
|
||||
public const CURRENT_CLIENT_VERSION_TARGET = [
|
||||
1, //major
|
||||
20, //minor
|
||||
10, //patch
|
||||
40, //patch
|
||||
1, //revision
|
||||
0 //is beta
|
||||
];
|
||||
|
@ -1200,16 +1200,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../phpunit/block/regenerate_consistency_check.php
|
||||
|
||||
-
|
||||
message: "#^Property pocketmine\\\\event\\\\HandlerListManagerTest\\:\\:\\$isValidFunc \\(Closure\\(ReflectionClass\\<pocketmine\\\\event\\\\Event\\>\\)\\: bool\\) does not accept Closure\\|null\\.$#"
|
||||
count: 1
|
||||
path: ../../phpunit/event/HandlerListManagerTest.php
|
||||
|
||||
-
|
||||
message: "#^Property pocketmine\\\\event\\\\HandlerListManagerTest\\:\\:\\$resolveParentFunc \\(Closure\\(ReflectionClass\\<pocketmine\\\\event\\\\Event\\>\\)\\: \\(ReflectionClass\\<pocketmine\\\\event\\\\Event\\>\\|null\\)\\) does not accept Closure\\|null\\.$#"
|
||||
count: 1
|
||||
path: ../../phpunit/event/HandlerListManagerTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$logFile of class pocketmine\\\\utils\\\\MainLogger constructor expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
|
@ -1,6 +1,11 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Property pocketmine\\\\network\\\\mcpe\\\\handler\\\\StupidJsonDecodeTest\\:\\:\\$stupidJsonDecodeFunc \\(Closure\\(string, bool\\=\\)\\: mixed\\) does not accept Closure\\|null\\.$#"
|
||||
message: "#^Property pocketmine\\\\event\\\\HandlerListManagerTest\\:\\:\\$isValidFunc \\(Closure\\(ReflectionClass\\<pocketmine\\\\event\\\\Event\\>\\)\\: bool\\) does not accept Closure\\|null\\.$#"
|
||||
count: 1
|
||||
path: ../../phpunit/network/mcpe/handler/StupidJsonDecodeTest.php
|
||||
path: ../../phpunit/event/HandlerListManagerTest.php
|
||||
|
||||
-
|
||||
message: "#^Property pocketmine\\\\event\\\\HandlerListManagerTest\\:\\:\\$resolveParentFunc \\(Closure\\(ReflectionClass\\<pocketmine\\\\event\\\\Event\\>\\)\\: \\(ReflectionClass\\<pocketmine\\\\event\\\\Event\\>\\|null\\)\\) does not accept Closure\\|null\\.$#"
|
||||
count: 1
|
||||
path: ../../phpunit/event/HandlerListManagerTest.php
|
||||
|
@ -5,11 +5,26 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/block/BaseBanner.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\block\\\\CakeWithCandle\\:\\:onInteractCandle\\(\\) has parameter \\$returnedItems with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/block/CakeWithCandle.php
|
||||
|
||||
-
|
||||
message: "#^Method pocketmine\\\\block\\\\DoubleTallGrass\\:\\:traitGetDropsForIncompatibleTool\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/block/DoubleTallGrass.php
|
||||
|
||||
-
|
||||
message: "#^Call to function assert\\(\\) with false and 'unknown hit type' will always evaluate to false\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/entity/projectile/Projectile.php
|
||||
|
||||
-
|
||||
message: "#^Match arm comparison between 1\\|2\\|3\\|4 and 0 is always false\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/network/mcpe/handler/InGamePacketHandler.php
|
||||
|
||||
-
|
||||
message: "#^Match arm comparison between 4 and 4 is always true\\.$#"
|
||||
count: 1
|
||||
@ -35,11 +50,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/plugin/PluginManager.php
|
||||
|
||||
-
|
||||
message: "#^Static property pocketmine\\\\scheduler\\\\AsyncTask\\:\\:\\$threadLocalStorage \\(ArrayObject\\<int, array\\<string, mixed\\>\\>\\|null\\) does not accept non\\-empty\\-array\\<int, non\\-empty\\-array\\<string, mixed\\>\\>\\|ArrayObject\\<int, array\\<string, mixed\\>\\>\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/scheduler/AsyncTask.php
|
||||
|
||||
-
|
||||
message: "#^Casting to int something that's already int\\.$#"
|
||||
count: 1
|
||||
|
42
tests/phpunit/promise/PromiseTest.php
Normal file
42
tests/phpunit/promise/PromiseTest.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\promise;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class PromiseTest extends TestCase{
|
||||
|
||||
public function testPromiseNull() : void{
|
||||
$resolver = new PromiseResolver();
|
||||
$resolver->resolve(null);
|
||||
$resolver->getPromise()->onCompletion(
|
||||
function(mixed $value) : void{
|
||||
self::assertNull($value);
|
||||
},
|
||||
function() : void{
|
||||
self::fail("Promise should not be rejected");
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -276,7 +276,7 @@ class ParserPacketHandler extends PacketHandler{
|
||||
$meta = $descriptor->getMeta();
|
||||
if($meta !== 32767){
|
||||
$blockStateId = $this->blockTranslator->getBlockStateDictionary()->lookupStateIdFromIdMeta($data->name, $meta);
|
||||
if($blockStateId !== null){
|
||||
if($this->blockItemIdMap->lookupBlockId($data->name) !== null && $blockStateId !== null){
|
||||
$blockState = $this->blockTranslator->getBlockStateDictionary()->generateDataFromStateId($blockStateId);
|
||||
if($blockState !== null && count($blockState->getStates()) > 0){
|
||||
$data->block_states = self::blockStatePropertiesToString($blockState);
|
||||
@ -440,17 +440,22 @@ class ParserPacketHandler extends PacketHandler{
|
||||
//how the data is ordered doesn't matter as long as it's reproducible
|
||||
foreach($recipes as $_type => $entries){
|
||||
$_sortedRecipes = [];
|
||||
$_seen = [];
|
||||
foreach($entries as $entry){
|
||||
$entry = self::sort($entry);
|
||||
$_key = json_encode($entry);
|
||||
while(isset($_sortedRecipes[$_key])){
|
||||
echo "warning: duplicated $_type recipe: $_key\n";
|
||||
$_key .= "a";
|
||||
}
|
||||
$_sortedRecipes[$_key] = $entry;
|
||||
$duplicates = $_seen[$_key] ??= 0;
|
||||
$_seen[$_key]++;
|
||||
$suffix = chr(ord("a") + $duplicates);
|
||||
$_sortedRecipes[$_key . $suffix] = $entry;
|
||||
}
|
||||
ksort($_sortedRecipes, SORT_STRING);
|
||||
$recipes[$_type] = array_values($_sortedRecipes);
|
||||
foreach($_seen as $_key => $_seenCount){
|
||||
if($_seenCount > 1){
|
||||
fwrite(STDERR, "warning: $_type recipe $_key was seen $_seenCount times\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ksort($recipes, SORT_STRING);
|
||||
|
Reference in New Issue
Block a user