mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-21 16:24:05 +00:00
Merge remote-tracking branch 'upstream/minor-next' into feat/async-events
This commit is contained in:
commit
64bbff6286
4
.github/workflows/discord-release-notify.yml
vendored
4
.github/workflows/discord-release-notify.yml
vendored
@ -13,9 +13,9 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.26.0
|
||||
uses: shivammathur/setup-php@2.27.1
|
||||
with:
|
||||
php-version: 8.1
|
||||
php-version: 8.2
|
||||
|
||||
- name: Restore Composer package cache
|
||||
uses: actions/cache@v3
|
||||
|
4
.github/workflows/draft-release.yml
vendored
4
.github/workflows/draft-release.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-version: [8.1]
|
||||
php-version: [8.2]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -20,7 +20,7 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@2.26.0
|
||||
uses: shivammathur/setup-php@2.27.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-version }}
|
||||
|
||||
|
6
.github/workflows/main.yml
vendored
6
.github/workflows/main.yml
vendored
@ -173,10 +173,10 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup PHP and tools
|
||||
uses: shivammathur/setup-php@2.26.0
|
||||
uses: shivammathur/setup-php@2.27.1
|
||||
with:
|
||||
php-version: 8.1
|
||||
tools: php-cs-fixer:3.17
|
||||
php-version: 8.2
|
||||
tools: php-cs-fixer:3.38
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
## Pre-requisites
|
||||
- A bash shell (git bash is sufficient for Windows)
|
||||
- [`git`](https://git-scm.com) available in your shell
|
||||
- PHP 8.1 or newer available in your shell
|
||||
- PHP 8.2 or newer available in your shell
|
||||
- [`composer`](https://getcomposer.org) available in your shell
|
||||
|
||||
## Custom PHP binaries
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit a34e48e7da753b633ffaa4a4f9516eae4bb97baa
|
||||
Subproject commit 39885cf24826773bc3a0e8134e04a2032e97f477
|
@ -18,3 +18,10 @@ Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if
|
||||
## 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()`).
|
||||
|
138
changelogs/5.8.md
Normal file
138
changelogs/5.8.md
Normal file
@ -0,0 +1,138 @@
|
||||
# 5.8.0
|
||||
Released 1st November 2023.
|
||||
|
||||
**Borked release, forgot to merge branches.**
|
||||
|
||||
# 5.8.1
|
||||
Released 1st November 2023.
|
||||
|
||||
**For Minecraft: Bedrock Edition 1.20.40**
|
||||
|
||||
This is a minor feature release, including new gameplay features, various performance improvements to internal `World` and `Block` systems, and changes to the API.
|
||||
|
||||
**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
|
||||
- Neighbour block updates now have a separate timer for timings. Previously, these were counted under `Scheduled Block Updates`, which was misleading.
|
||||
|
||||
## Performance
|
||||
- `LightUpdate` now avoids attempting to propagate back in the same direction the light came from. This produces a small performance improvement of around 6% in light propagation.
|
||||
- Improved worst-case (non-cached) performance of `World::getCollisionBlocks()` (and its successor `World::getBlockCollisionBlocks()`).
|
||||
- While 5.5.0 introduced caching at the `World` level for AABBs, the cache was rarely useful due to entity and player movement being too unpredictable. This meant that most users saw a performance degradation with lots of moving entities, except in specific situations.
|
||||
- Performance for fetching non-cached AABBs for a cell is now improved by 2x. Overall performance benefit to a server depends on the number of entities and players.
|
||||
- Added cache for hydrated farmland blocks to remember the last known location of nearby water.
|
||||
- If nearby water sources are not changed, this cache allows hydrated farmland to completely avoid checking up to 161 nearby blocks for water after the first check.
|
||||
- Tests with large wheat farms showed a 25% performance improvement in overall server performance compared to previous 5.x versions.
|
||||
- Migrated various internal enums to native PHP 8.1 enums. Bypassing magic `__callStatic()` accessors improved performance in many areas, although it's hard to quantify the exact benefit.
|
||||
- Made use of `Facing::OFFSET` constant in various places to avoid unnecessary `Vector3` and `Position` object allocations. Many pathways benefit from this, including neighbour block updates (due to faster `Block::getSide()` and less useless objects).
|
||||
- Avoided clearing block AABB caches except when strictly necessary. Previously, the cache was wiped every time blocks were read from the world, making them mostly useless.
|
||||
- Avoided random updates on blocks which have reached their final state, such as fully-grown crops. This produces a minimal performance improvement.
|
||||
- Removed useless checks in some `World` hot paths.
|
||||
|
||||
## API
|
||||
### General
|
||||
- All enums have been migrated to native PHP 8.1 enums.
|
||||
- For now, the old APIs and accessors are still usable (via `LegacyEnumShimTrait`), but these will be removed in the next major release.
|
||||
- `EnumTrait` has been deprecated, and will be removed in the next major release.
|
||||
- Migration for most plugin developers will simply involve deleting `()` from the end of enum case usages, which is a trivial change and also improves performance.
|
||||
- Plugin usages of `EnumTrait` are encouraged to move to native enums, optionally using `LegacyEnumShimTrait` to provide backwards compatibility.
|
||||
- See [this code](https://github.com/pmmp/PocketMine-MP/blob/9832fe899f13a8ea47cc9d73de7088f7775a12f5/src/block/utils/DyeColor.php#L85-L107) for an example of how to associate properties with enum cases (since native enums don't support this directly).
|
||||
- Thanks to improvements in `RuntimeDataDescriber`, any native enum can now be used as a custom block's state property.
|
||||
|
||||
### `pocketmine\block`
|
||||
- The following classes have been added:
|
||||
- `utils\AgeableTrait` - used by blocks which have an age property, such as crops
|
||||
- `utils\StaticSupportTrait` - used by blocks which have the same support requirements regardless of their state, such as crops
|
||||
|
||||
### `pocketmine\data\runtime`
|
||||
- The following API methods have been added:
|
||||
- `public RuntimeDataDescriber->boundedIntAuto(int $min, int $max, int &$value) : void` - similar to `boundedInt()`, but automatically calculates the needed number of bits based on the given min/max
|
||||
- `public RuntimeDataDescriber->enum(T extends \UnitEnum &$case) : void` - describes any native PHP 8.1 enum case
|
||||
- `public RuntimeDataDescriber->enumSet(array<int, T extends \UnitEnum> &$set, array<int, T extends \UnitEnum> $allCases) : void` - describes a set of enum cases (similar to bitflags)
|
||||
- The following API methods have been deprecated:
|
||||
- `RuntimeDataDescriber->bellAttachmentType()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->boundedInt()` - use `boundedIntAuto()` instead
|
||||
- `RuntimeDataDescriber->brewingStandSlots()` - use `enumSet()` instead
|
||||
- `RuntimeDataDescriber->copperOxidation()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->coralType()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->dirtType()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->dripleafState()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->dyeColor()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->froglightType()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->leverFacing()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->medicineType()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->mobHeadType()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->mushroomBlockType()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->potionType()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->slabType()` - use `enum()` instead
|
||||
- `RuntimeDataDescriber->suspiciousStewType()` - use `enum()` instead
|
||||
|
||||
### `pocketmine\player`
|
||||
- `TitleID` is now included in `PlayerInfo` metadata for plugin consumption.
|
||||
|
||||
### `pocketmine\world`
|
||||
- The following API methods have been added:
|
||||
- `public World->getBlockCollisionBoxes(AxisAlignedBB $bb) : list<AxisAlignedBB>` - similar to `getCollisionBoxes` but exclusively for blocks, avoiding the need for conditionally useless parameters
|
||||
- The following API methods have been deprecated:
|
||||
- `World->getCollisionBoxes()` - use `getBlockCollisionBoxes()` instead (alongside `getCollidingEntities()` if entity collision boxes are also required)
|
||||
|
||||
### `pocketmine\utils`
|
||||
- The following classes have been deprecated:
|
||||
- `EnumTrait` - use native PHP 8.1 enums instead
|
||||
- The following classes have been added:
|
||||
- `LegacyEnumShimTrait` - can be `use`d by native PHP 8.1 enums to provide the same API as `EnumTrait`
|
||||
|
||||
## Gameplay
|
||||
### Blocks
|
||||
- Implemented the following blocks:
|
||||
- Amethyst
|
||||
- Amethyst Cluster
|
||||
- Chiseled Bookshelf
|
||||
- Crimson Roots
|
||||
- Pitcher Crop
|
||||
- Pitcher Plant
|
||||
- Torchflower
|
||||
- Torchflower Crop
|
||||
- Warped Roots
|
||||
|
||||
### Items
|
||||
- Implemented the following items:
|
||||
- Pitcher Pod
|
||||
- Torchflower Seeds
|
||||
|
||||
## Internals
|
||||
- `Farmland` block now has an extra property (`waterPositionIndex`) stored in its blockstate ID to track the position of nearby water. This property is not saved to disk, and is only used for caching.
|
||||
- The format of internal blockstate ID has been updated.
|
||||
- The lower `11` bits are now reserved for state data (previously `8` bits). This increase facilitates the new cache for `Farmland` blocks.
|
||||
- The state data bits are now XOR'd with the `xxh3` of the block's type ID, instead of being directly XOR'd with the type ID.
|
||||
- This XOR improves the distribution of the lower bits of the blockstate ID, which is important for hashtable indexing to minimize collisions.
|
||||
- Previously, the lower bits were XOR'd with the type ID directly, but the effectiveness of this reduced as more state data bits were added.
|
||||
- `xxh3` produces consistently good results for this purpose regardless of the number of state data bits allocated.
|
||||
- Hash collisions with blockstate IDs are reduced by 50% with this change, which is a happy side effect.
|
||||
- This is backwards-incompatible, so anyone saving internal blockstate IDs on disk or in a DB will be burned by this change (though they shouldn't have been doing that anyway).
|
||||
- Removed code generation step for `RuntimeDataDescriber` enum serialization. All described enums now use PHP 8.1 native enums, which can be described without codegen using `RuntimeDataDescriber->enum()`.
|
||||
- Added `DeprecatedLegacyEnumAccessRule` custom PHPStan rule to flag legacy `EnumTrait` case accessors.
|
||||
- Cleaned up remaining hardcoded `Config` keys in `SetupWizard`. These usages now use auto-generated constants like the rest of the codebase.
|
||||
|
||||
# 5.8.2
|
||||
Released 9th November 2023.
|
||||
|
||||
## Performance
|
||||
- Improved performance of small packet zero-compression (unintended use of slow zlib compressor instead of fast libdeflate one).
|
||||
- This affected the majority of outbound packets, as most packets are below the 256-byte threshold for compression.
|
||||
- This faster method is over 20x faster than the old method, producing noticeable performance gains for large servers.
|
||||
|
||||
## Fixes
|
||||
- Fixed melons and pumpkins not growing.
|
||||
- Fixed melon and pumpkin stems not attaching to the grown melon/pumpkin.
|
||||
- Fixed iron and gold ores not being affected by the Fortune enchantment.
|
||||
- Fixed ancient debris burning in lava.
|
||||
- Fixed sign (front) text loading from vanilla world saves (back text is not yet supported).
|
||||
|
||||
## Internals
|
||||
- Removed bogus optimization from `tools/generate-blockstate-upgrade-schema.php` that could cause incorrect `remappedStates` generation when some of the states stayed under the old ID.
|
||||
- Fixed possible crash in `BlockStateUpgrader` name flattening rule handling with invalid blockstate NBT data.
|
@ -52,7 +52,7 @@
|
||||
"symfony/filesystem": "~6.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.10.39",
|
||||
"phpstan/phpstan": "1.10.41",
|
||||
"phpstan/phpstan-phpunit": "^1.1.0",
|
||||
"phpstan/phpstan-strict-rules": "^1.2.0",
|
||||
"phpunit/phpunit": "~10.3.0 || ~10.2.0 || ~10.1.0"
|
||||
|
26
composer.lock
generated
26
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": "feefde772166966ee8065e613fe9a56e",
|
||||
"content-hash": "5c19f4766fd04be0cbd38d9f4681864e",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
@ -1378,16 +1378,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.10.39",
|
||||
"version": "1.10.41",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "d9dedb0413f678b4d03cbc2279a48f91592c97c4"
|
||||
"reference": "c6174523c2a69231df55bdc65b61655e72876d76"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/d9dedb0413f678b4d03cbc2279a48f91592c97c4",
|
||||
"reference": "d9dedb0413f678b4d03cbc2279a48f91592c97c4",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/c6174523c2a69231df55bdc65b61655e72876d76",
|
||||
"reference": "c6174523c2a69231df55bdc65b61655e72876d76",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1436,7 +1436,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-10-17T15:46:26+00:00"
|
||||
"time": "2023-11-05T12:57:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-phpunit",
|
||||
@ -1492,21 +1492,21 @@
|
||||
},
|
||||
{
|
||||
"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,9 +1535,9 @@
|
||||
"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",
|
||||
|
48
src/BootstrapOptions.php
Normal file
48
src/BootstrapOptions.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
/**
|
||||
* Constants for all the command-line options that PocketMine-MP supports.
|
||||
* Other options not listed here can be used to override server.properties and pocketmine.yml values temporarily.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class BootstrapOptions{
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
/** Disables the setup wizard on first startup */
|
||||
public const NO_WIZARD = "no-wizard";
|
||||
/** Force-disables console text colour and formatting */
|
||||
public const DISABLE_ANSI = "disable-ansi";
|
||||
/** Force-enables console text colour and formatting */
|
||||
public const ENABLE_ANSI = "enable-ansi";
|
||||
/** Path to look in for plugins */
|
||||
public const PLUGINS = "plugins";
|
||||
/** Path to store and load server data */
|
||||
public const DATA = "data";
|
||||
}
|
@ -144,6 +144,13 @@ namespace pocketmine {
|
||||
$messages[] = "chunkutils2 ^$wantedVersionMin is required, while you have $chunkutils2_version.";
|
||||
}
|
||||
|
||||
if(($libdeflate_version = phpversion("libdeflate")) !== false){
|
||||
//make sure level 0 compression is available
|
||||
if(version_compare($libdeflate_version, "0.2.0") < 0 || version_compare($libdeflate_version, "0.3.0") >= 0){
|
||||
$messages[] = "php-libdeflate ^0.2.0 is required, while you have $libdeflate_version.";
|
||||
}
|
||||
}
|
||||
|
||||
if(extension_loaded("pocketmine")){
|
||||
$messages[] = "The native PocketMine extension is no longer supported.";
|
||||
}
|
||||
@ -267,8 +274,8 @@ JIT_WARNING
|
||||
ErrorToExceptionHandler::set();
|
||||
|
||||
$cwd = Utils::assumeNotFalse(realpath(Utils::assumeNotFalse(getcwd())));
|
||||
$dataPath = getopt_string("data") ?? $cwd;
|
||||
$pluginPath = getopt_string("plugins") ?? $cwd . DIRECTORY_SEPARATOR . "plugins";
|
||||
$dataPath = getopt_string(BootstrapOptions::DATA) ?? $cwd;
|
||||
$pluginPath = getopt_string(BootstrapOptions::PLUGINS) ?? $cwd . DIRECTORY_SEPARATOR . "plugins";
|
||||
Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX);
|
||||
|
||||
if(!@mkdir($dataPath, 0777, true) && !is_dir($dataPath)){
|
||||
@ -301,10 +308,10 @@ JIT_WARNING
|
||||
//Logger has a dependency on timezone
|
||||
Timezone::init();
|
||||
|
||||
$opts = getopt("", ["no-wizard", "enable-ansi", "disable-ansi"]);
|
||||
if(isset($opts["enable-ansi"])){
|
||||
$opts = getopt("", [BootstrapOptions::NO_WIZARD, BootstrapOptions::ENABLE_ANSI, BootstrapOptions::DISABLE_ANSI]);
|
||||
if(isset($opts[BootstrapOptions::ENABLE_ANSI])){
|
||||
Terminal::init(true);
|
||||
}elseif(isset($opts["disable-ansi"])){
|
||||
}elseif(isset($opts[BootstrapOptions::DISABLE_ANSI])){
|
||||
Terminal::init(false);
|
||||
}else{
|
||||
Terminal::init();
|
||||
@ -317,7 +324,7 @@ JIT_WARNING
|
||||
|
||||
$exitCode = 0;
|
||||
do{
|
||||
if(!file_exists(Path::join($dataPath, "server.properties")) && !isset($opts["no-wizard"])){
|
||||
if(!file_exists(Path::join($dataPath, "server.properties")) && !isset($opts[BootstrapOptions::NO_WIZARD])){
|
||||
$installer = new SetupWizard($dataPath);
|
||||
if(!$installer->run()){
|
||||
$exitCode = -1;
|
||||
|
@ -1259,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)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ use function str_repeat;
|
||||
|
||||
final class VersionInfo{
|
||||
public const NAME = "PocketMine-MP";
|
||||
public const BASE_VERSION = "5.7.1";
|
||||
public const BASE_VERSION = "5.8.3";
|
||||
public const IS_DEVELOPMENT_BUILD = true;
|
||||
public const BUILD_CHANNEL = "stable";
|
||||
|
||||
|
@ -270,11 +270,22 @@ class Block{
|
||||
}
|
||||
|
||||
private function encodeFullState() : int{
|
||||
$writer = new RuntimeDataWriter($this->requiredBlockItemStateDataBits + $this->requiredBlockOnlyStateDataBits);
|
||||
$writer->writeInt($this->requiredBlockItemStateDataBits, $this->encodeBlockItemState());
|
||||
$writer->writeInt($this->requiredBlockOnlyStateDataBits, $this->encodeBlockOnlyState());
|
||||
$blockItemBits = $this->requiredBlockItemStateDataBits;
|
||||
$blockOnlyBits = $this->requiredBlockOnlyStateDataBits;
|
||||
|
||||
return $writer->getValue();
|
||||
if($blockOnlyBits === 0 && $blockItemBits === 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
$result = 0;
|
||||
if($blockItemBits > 0){
|
||||
$result |= $this->encodeBlockItemState();
|
||||
}
|
||||
if($blockOnlyBits > 0){
|
||||
$result |= $this->encodeBlockOnlyState() << $blockItemBits;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\AgeableTrait;
|
||||
use pocketmine\block\utils\BlockEventHelper;
|
||||
use pocketmine\block\utils\CropGrowthHelper;
|
||||
use pocketmine\block\utils\StaticSupportTrait;
|
||||
use pocketmine\item\Fertilizer;
|
||||
use pocketmine\item\Item;
|
||||
@ -66,7 +67,7 @@ abstract class Crops extends Flowable{
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if($this->age < self::MAX_AGE && mt_rand(0, 2) === 1){
|
||||
if($this->age < self::MAX_AGE && CropGrowthHelper::canGrow($this)){
|
||||
$block = clone $this;
|
||||
++$block->age;
|
||||
BlockEventHelper::grow($this, $block, null);
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\AgeableTrait;
|
||||
use pocketmine\block\utils\CropGrowthHelper;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\event\block\StructureGrowEvent;
|
||||
use pocketmine\item\Fertilizer;
|
||||
@ -34,7 +35,6 @@ use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function mt_rand;
|
||||
|
||||
final class DoublePitcherCrop extends DoublePlant{
|
||||
use AgeableTrait {
|
||||
@ -101,9 +101,8 @@ final class DoublePitcherCrop extends DoublePlant{
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
//TODO: the growth speed is influenced by farmland and nearby crops
|
||||
//only the bottom half of the plant can grow randomly
|
||||
if(mt_rand(0, 2) === 0 && !$this->top){
|
||||
if(CropGrowthHelper::canGrow($this) && !$this->top){
|
||||
$this->grow(null);
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\FortuneDropHelper;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
|
||||
final class GoldOre extends Opaque{
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [VanillaItems::RAW_GOLD()];
|
||||
return [VanillaItems::RAW_GOLD()->setCount(FortuneDropHelper::weighted($item, min: 1, maxBase: 1))];
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{ return true; }
|
||||
|
@ -23,13 +23,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\FortuneDropHelper;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\VanillaItems;
|
||||
|
||||
final class IronOre extends Opaque{
|
||||
|
||||
public function getDropsForCompatibleTool(Item $item) : array{
|
||||
return [VanillaItems::RAW_IRON()];
|
||||
return [VanillaItems::RAW_IRON()->setCount(FortuneDropHelper::weighted($item, min: 1, maxBase: 1))];
|
||||
}
|
||||
|
||||
public function isAffectedBySilkTouch() : bool{ return true; }
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\AgeableTrait;
|
||||
use pocketmine\block\utils\BlockEventHelper;
|
||||
use pocketmine\block\utils\CropGrowthHelper;
|
||||
use pocketmine\block\utils\StaticSupportTrait;
|
||||
use pocketmine\event\block\StructureGrowEvent;
|
||||
use pocketmine\item\Fertilizer;
|
||||
@ -35,7 +36,6 @@ use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use pocketmine\world\BlockTransaction;
|
||||
use function mt_rand;
|
||||
|
||||
final class PitcherCrop extends Flowable{
|
||||
use AgeableTrait;
|
||||
@ -97,8 +97,7 @@ final class PitcherCrop extends Flowable{
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
//TODO: the growth speed is influenced by farmland and nearby crops
|
||||
if(mt_rand(0, 2) === 0){
|
||||
if(CropGrowthHelper::canGrow($this)){
|
||||
$this->grow(null);
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockEventHelper;
|
||||
use pocketmine\block\utils\CropGrowthHelper;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Facing;
|
||||
@ -58,8 +59,12 @@ abstract class Stem extends Crops{
|
||||
parent::onNearbyBlockChange();
|
||||
}
|
||||
|
||||
public function ticksRandomly() : bool{
|
||||
return $this->age < self::MAX_AGE || $this->facing === Facing::UP;
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if($this->facing === Facing::UP && mt_rand(0, 2) === 1){
|
||||
if($this->facing === Facing::UP && CropGrowthHelper::canGrow($this)){
|
||||
$world = $this->position->getWorld();
|
||||
if($this->age < self::MAX_AGE){
|
||||
$block = clone $this;
|
||||
@ -76,7 +81,9 @@ abstract class Stem extends Crops{
|
||||
$facing = Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)];
|
||||
$side = $this->getSide($facing);
|
||||
if($side->getTypeId() === BlockTypeIds::AIR && $side->getSide(Facing::DOWN)->hasTypeTag(BlockTypeTags::DIRT)){
|
||||
BlockEventHelper::grow($side, $grow, null);
|
||||
if(BlockEventHelper::grow($side, $grow, null)){
|
||||
$this->position->getWorld()->setBlock($this->position, $this->setFacing($facing));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\block\utils\BlockEventHelper;
|
||||
use pocketmine\block\utils\CropGrowthHelper;
|
||||
use pocketmine\block\utils\StaticSupportTrait;
|
||||
use pocketmine\data\runtime\RuntimeDataDescriber;
|
||||
use pocketmine\item\Fertilizer;
|
||||
@ -32,7 +33,6 @@ use pocketmine\item\VanillaItems;
|
||||
use pocketmine\math\Facing;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\player\Player;
|
||||
use function mt_rand;
|
||||
|
||||
final class TorchflowerCrop extends Flowable{
|
||||
use StaticSupportTrait;
|
||||
@ -79,7 +79,7 @@ final class TorchflowerCrop extends Flowable{
|
||||
}
|
||||
|
||||
public function onRandomTick() : void{
|
||||
if(mt_rand(0, 2) === 1){
|
||||
if(CropGrowthHelper::canGrow($this)){
|
||||
BlockEventHelper::grow($this, $this->getNextState(), null);
|
||||
}
|
||||
}
|
||||
|
@ -1495,7 +1495,9 @@ final class VanillaBlocks{
|
||||
//for some reason, slabs have weird hardness like the legacy ones
|
||||
$slabBreakInfo = new Info(BreakInfo::pickaxe(2.0, ToolTier::WOOD, 30.0));
|
||||
|
||||
self::register("ancient_debris", new Opaque(new BID(Ids::ANCIENT_DEBRIS), "Ancient Debris", new Info(BreakInfo::pickaxe(30, ToolTier::DIAMOND, 3600.0))));
|
||||
self::register("ancient_debris", new class(new BID(Ids::ANCIENT_DEBRIS), "Ancient Debris", new Info(BreakInfo::pickaxe(30, ToolTier::DIAMOND, 3600.0))) extends Opaque{
|
||||
public function isFireProofAsItem() : bool{ return true; }
|
||||
});
|
||||
$netheriteBreakInfo = new Info(BreakInfo::pickaxe(50, ToolTier::DIAMOND, 3600.0));
|
||||
self::register("netherite", new class(new BID(Ids::NETHERITE), "Netherite Block", $netheriteBreakInfo) extends Opaque{
|
||||
public function isFireProofAsItem() : bool{ return true; }
|
||||
|
@ -77,22 +77,30 @@ class Sign extends Spawnable{
|
||||
parent::__construct($world, $pos);
|
||||
}
|
||||
|
||||
private function readTextTag(CompoundTag $nbt, bool $lightingBugResolved) : void{
|
||||
$baseColor = new Color(0, 0, 0);
|
||||
$glowingText = false;
|
||||
if(($baseColorTag = $nbt->getTag(self::TAG_TEXT_COLOR)) instanceof IntTag){
|
||||
$baseColor = Color::fromARGB(Binary::unsignInt($baseColorTag->getValue()));
|
||||
}
|
||||
if($lightingBugResolved && ($glowingTextTag = $nbt->getTag(self::TAG_GLOWING_TEXT)) instanceof ByteTag){
|
||||
//both of these must be 1 - if only one is set, it's a leftover from 1.16.210 experimental features
|
||||
//see https://bugs.mojang.com/browse/MCPE-117835
|
||||
$glowingText = $glowingTextTag->getValue() !== 0;
|
||||
}
|
||||
$this->text = SignText::fromBlob(mb_scrub($nbt->getString(self::TAG_TEXT_BLOB), 'UTF-8'), $baseColor, $glowingText);
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
if(($textBlobTag = $nbt->getTag(self::TAG_TEXT_BLOB)) instanceof StringTag){ //MCPE 1.2 save format
|
||||
$baseColor = new Color(0, 0, 0);
|
||||
$glowingText = false;
|
||||
if(($baseColorTag = $nbt->getTag(self::TAG_TEXT_COLOR)) instanceof IntTag){
|
||||
$baseColor = Color::fromARGB(Binary::unsignInt($baseColorTag->getValue()));
|
||||
$frontTextTag = $nbt->getTag(self::TAG_FRONT_TEXT);
|
||||
if($frontTextTag instanceof CompoundTag){
|
||||
$this->readTextTag($frontTextTag, true);
|
||||
}elseif($nbt->getTag(self::TAG_TEXT_BLOB) instanceof StringTag){ //MCPE 1.2 save format
|
||||
$lightingBugResolved = false;
|
||||
if(($lightingBugResolvedTag = $nbt->getTag(self::TAG_LEGACY_BUG_RESOLVE)) instanceof ByteTag){
|
||||
$lightingBugResolved = $lightingBugResolvedTag->getValue() !== 0;
|
||||
}
|
||||
if(
|
||||
($glowingTextTag = $nbt->getTag(self::TAG_GLOWING_TEXT)) instanceof ByteTag &&
|
||||
($lightingBugResolvedTag = $nbt->getTag(self::TAG_LEGACY_BUG_RESOLVE)) instanceof ByteTag
|
||||
){
|
||||
//both of these must be 1 - if only one is set, it's a leftover from 1.16.210 experimental features
|
||||
//see https://bugs.mojang.com/browse/MCPE-117835
|
||||
$glowingText = $glowingTextTag->getValue() !== 0 && $lightingBugResolvedTag->getValue() !== 0;
|
||||
}
|
||||
$this->text = SignText::fromBlob(mb_scrub($textBlobTag->getValue(), 'UTF-8'), $baseColor, $glowingText);
|
||||
$this->readTextTag($nbt, $lightingBugResolved);
|
||||
}else{
|
||||
$text = [];
|
||||
for($i = 0; $i < SignText::LINE_COUNT; ++$i){
|
||||
@ -107,15 +115,19 @@ class Sign extends Spawnable{
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
$nbt->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()));
|
||||
$nbt->setTag(self::TAG_FRONT_TEXT, CompoundTag::create()
|
||||
->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()))
|
||||
->setInt(self::TAG_TEXT_COLOR, Binary::signInt($this->text->getBaseColor()->toARGB()))
|
||||
->setByte(self::TAG_GLOWING_TEXT, $this->text->isGlowing() ? 1 : 0)
|
||||
->setByte(self::TAG_PERSIST_FORMATTING, 1)
|
||||
);
|
||||
$nbt->setTag(self::TAG_BACK_TEXT, CompoundTag::create()
|
||||
->setString(self::TAG_TEXT_BLOB, "")
|
||||
->setInt(self::TAG_TEXT_COLOR, Binary::signInt(0xff_00_00_00))
|
||||
->setByte(self::TAG_GLOWING_TEXT, 0)
|
||||
->setByte(self::TAG_PERSIST_FORMATTING, 1)
|
||||
);
|
||||
|
||||
for($i = 0; $i < SignText::LINE_COUNT; ++$i){ //Backwards-compatibility
|
||||
$textKey = sprintf(self::TAG_TEXT_LINE, $i + 1);
|
||||
$nbt->setString($textKey, $this->text->getLine($i));
|
||||
}
|
||||
$nbt->setInt(self::TAG_TEXT_COLOR, Binary::signInt($this->text->getBaseColor()->toARGB()));
|
||||
$nbt->setByte(self::TAG_GLOWING_TEXT, $this->text->isGlowing() ? 1 : 0);
|
||||
$nbt->setByte(self::TAG_LEGACY_BUG_RESOLVE, 1);
|
||||
$nbt->setByte(self::TAG_WAXED, $this->waxed ? 1 : 0);
|
||||
}
|
||||
|
||||
|
120
src/block/utils/CropGrowthHelper.php
Normal file
120
src/block/utils/CropGrowthHelper.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);
|
||||
|
||||
namespace pocketmine\block\utils;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\Farmland;
|
||||
use function mt_rand;
|
||||
|
||||
final class CropGrowthHelper{
|
||||
|
||||
private const ON_HYDRATED_FARMLAND_BONUS = 3;
|
||||
private const ON_DRY_FARMLAND_BONUS = 1;
|
||||
private const ADJACENT_HYDRATED_FARMLAND_BONUS = 3 / 4;
|
||||
private const ADJACENT_DRY_FARMLAND_BONUS = 1 / 4;
|
||||
|
||||
private const IMPROPER_ARRANGEMENT_DIVISOR = 2;
|
||||
|
||||
private const MIN_LIGHT_LEVEL = 9;
|
||||
|
||||
private function __construct(){
|
||||
//NOOP
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the speed at which this crop will grow, depending on its surroundings.
|
||||
* The default is once every 26 random ticks.
|
||||
*
|
||||
* Things which influence this include nearby farmland (bonus for hydrated farmland) and the position of other
|
||||
* nearby crops of the same type (nearby crops of the same type will negatively influence growth speed unless
|
||||
* planted in rows and properly spaced apart).
|
||||
*/
|
||||
public static function calculateMultiplier(Block $block) : float{
|
||||
$result = 1;
|
||||
|
||||
$position = $block->getPosition();
|
||||
|
||||
$world = $position->getWorld();
|
||||
$baseX = $position->getFloorX();
|
||||
$baseY = $position->getFloorY();
|
||||
$baseZ = $position->getFloorZ();
|
||||
|
||||
$farmland = $world->getBlockAt($baseX, $baseY - 1, $baseZ);
|
||||
|
||||
if($farmland instanceof Farmland){
|
||||
$result += $farmland->getWetness() > 0 ? self::ON_HYDRATED_FARMLAND_BONUS : self::ON_DRY_FARMLAND_BONUS;
|
||||
}
|
||||
|
||||
$xRow = false;
|
||||
$zRow = false;
|
||||
$improperArrangement = false;
|
||||
|
||||
for($x = -1; $x <= 1; $x++){
|
||||
for($z = -1; $z <= 1; $z++){
|
||||
if($x === 0 && $z === 0){
|
||||
continue;
|
||||
}
|
||||
$nextFarmland = $world->getBlockAt($baseX + $x, $baseY - 1, $baseZ + $z);
|
||||
|
||||
if(!$nextFarmland instanceof Farmland){
|
||||
continue;
|
||||
}
|
||||
|
||||
$result += $nextFarmland->getWetness() > 0 ? self::ADJACENT_HYDRATED_FARMLAND_BONUS : self::ADJACENT_DRY_FARMLAND_BONUS;
|
||||
|
||||
if(!$improperArrangement){
|
||||
$nextCrop = $world->getBlockAt($baseX + $x, $baseY, $baseZ + $z);
|
||||
if($nextCrop->hasSameTypeId($block)){
|
||||
match(0){
|
||||
$x => $zRow ? $improperArrangement = true : $xRow = true,
|
||||
$z => $xRow ? $improperArrangement = true : $zRow = true,
|
||||
default => $improperArrangement = true,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//crops can be arranged in rows, but the rows must not cross and must be spaced apart by at least one block
|
||||
if($improperArrangement){
|
||||
$result /= self::IMPROPER_ARRANGEMENT_DIVISOR;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function hasEnoughLight(Block $block, int $minLevel = self::MIN_LIGHT_LEVEL) : bool{
|
||||
$position = $block->getPosition();
|
||||
$world = $position->getWorld();
|
||||
|
||||
//crop growth is not affected by time of day since 1.11 or so
|
||||
return $world->getPotentialLightAt($position->x, $position->y, $position->z) >= $minLevel;
|
||||
}
|
||||
|
||||
public static function canGrow(Block $block) : bool{
|
||||
//while it may be tempting to use mt_rand(0, 25) < multiplier, this would make crops grow a bit faster than
|
||||
//vanilla in most cases due to the remainder of 25 / multiplier not being discarded
|
||||
return mt_rand(0, (int) (25 / self::calculateMultiplier($block))) === 0 && self::hasEnoughLight($block);
|
||||
}
|
||||
}
|
@ -86,7 +86,7 @@ final class BlockStateUpgrader{
|
||||
if(is_string($remap->newName)){
|
||||
$newName = $remap->newName;
|
||||
}else{
|
||||
$flattenedValue = $oldState[$remap->newName->flattenedProperty];
|
||||
$flattenedValue = $oldState[$remap->newName->flattenedProperty] ?? null;
|
||||
if($flattenedValue instanceof StringTag){
|
||||
$newName = sprintf("%s%s%s", $remap->newName->prefix, $flattenedValue->getValue(), $remap->newName->suffix);
|
||||
unset($oldState[$remap->newName->flattenedProperty]);
|
||||
|
@ -193,6 +193,7 @@ final class ItemSerializerDeserializerRegistrar{
|
||||
$this->map1to1Item(Ids::CLAY_BALL, Items::CLAY());
|
||||
$this->map1to1Item(Ids::CLOCK, Items::CLOCK());
|
||||
$this->map1to1Item(Ids::COAL, Items::COAL());
|
||||
$this->map1to1Item(Ids::COAST_ARMOR_TRIM_SMITHING_TEMPLATE, Items::COAST_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::COCOA_BEANS, Items::COCOA_BEANS());
|
||||
$this->map1to1Item(Ids::COD, Items::RAW_FISH());
|
||||
$this->map1to1Item(Ids::COMPASS, Items::COMPASS());
|
||||
@ -221,6 +222,7 @@ final class ItemSerializerDeserializerRegistrar{
|
||||
$this->map1to1Item(Ids::DISC_FRAGMENT_5, Items::DISC_FRAGMENT_5());
|
||||
$this->map1to1Item(Ids::DRAGON_BREATH, Items::DRAGON_BREATH());
|
||||
$this->map1to1Item(Ids::DRIED_KELP, Items::DRIED_KELP());
|
||||
$this->map1to1Item(Ids::DUNE_ARMOR_TRIM_SMITHING_TEMPLATE, Items::DUNE_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::ECHO_SHARD, Items::ECHO_SHARD());
|
||||
$this->map1to1Item(Ids::EGG, Items::EGG());
|
||||
$this->map1to1Item(Ids::EMERALD, Items::EMERALD());
|
||||
@ -228,6 +230,7 @@ final class ItemSerializerDeserializerRegistrar{
|
||||
$this->map1to1Item(Ids::ENCHANTED_GOLDEN_APPLE, Items::ENCHANTED_GOLDEN_APPLE());
|
||||
$this->map1to1Item(Ids::ENDER_PEARL, Items::ENDER_PEARL());
|
||||
$this->map1to1Item(Ids::EXPERIENCE_BOTTLE, Items::EXPERIENCE_BOTTLE());
|
||||
$this->map1to1Item(Ids::EYE_ARMOR_TRIM_SMITHING_TEMPLATE, Items::EYE_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::FEATHER, Items::FEATHER());
|
||||
$this->map1to1Item(Ids::FERMENTED_SPIDER_EYE, Items::FERMENTED_SPIDER_EYE());
|
||||
$this->map1to1Item(Ids::FIRE_CHARGE, Items::FIRE_CHARGE());
|
||||
@ -257,6 +260,7 @@ final class ItemSerializerDeserializerRegistrar{
|
||||
$this->map1to1Item(Ids::HEART_OF_THE_SEA, Items::HEART_OF_THE_SEA());
|
||||
$this->map1to1Item(Ids::HONEY_BOTTLE, Items::HONEY_BOTTLE());
|
||||
$this->map1to1Item(Ids::HONEYCOMB, Items::HONEYCOMB());
|
||||
$this->map1to1Item(Ids::HOST_ARMOR_TRIM_SMITHING_TEMPLATE, Items::HOST_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::INK_SAC, Items::INK_SAC());
|
||||
$this->map1to1Item(Ids::IRON_AXE, Items::IRON_AXE());
|
||||
$this->map1to1Item(Ids::IRON_BOOTS, Items::IRON_BOOTS());
|
||||
@ -316,6 +320,7 @@ final class ItemSerializerDeserializerRegistrar{
|
||||
$this->map1to1Item(Ids::NETHERITE_SCRAP, Items::NETHERITE_SCRAP());
|
||||
$this->map1to1Item(Ids::NETHERITE_SHOVEL, Items::NETHERITE_SHOVEL());
|
||||
$this->map1to1Item(Ids::NETHERITE_SWORD, Items::NETHERITE_SWORD());
|
||||
$this->map1to1Item(Ids::NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items::NETHERITE_UPGRADE_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::OAK_BOAT, Items::OAK_BOAT());
|
||||
$this->map1to1Item(Ids::OAK_SIGN, Items::OAK_SIGN());
|
||||
$this->map1to1Item(Ids::PAINTING, Items::PAINTING());
|
||||
@ -335,18 +340,25 @@ final class ItemSerializerDeserializerRegistrar{
|
||||
$this->map1to1Item(Ids::RABBIT_FOOT, Items::RABBIT_FOOT());
|
||||
$this->map1to1Item(Ids::RABBIT_HIDE, Items::RABBIT_HIDE());
|
||||
$this->map1to1Item(Ids::RABBIT_STEW, Items::RABBIT_STEW());
|
||||
$this->map1to1Item(Ids::RAISER_ARMOR_TRIM_SMITHING_TEMPLATE, Items::RAISER_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::RAW_COPPER, Items::RAW_COPPER());
|
||||
$this->map1to1Item(Ids::RAW_GOLD, Items::RAW_GOLD());
|
||||
$this->map1to1Item(Ids::RAW_IRON, Items::RAW_IRON());
|
||||
$this->map1to1Item(Ids::REDSTONE, Items::REDSTONE_DUST());
|
||||
$this->map1to1Item(Ids::RIB_ARMOR_TRIM_SMITHING_TEMPLATE, Items::RIB_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::ROTTEN_FLESH, Items::ROTTEN_FLESH());
|
||||
$this->map1to1Item(Ids::SALMON, Items::RAW_SALMON());
|
||||
$this->map1to1Item(Ids::SCUTE, Items::SCUTE());
|
||||
$this->map1to1Item(Ids::SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE, Items::SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE, Items::SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::SHEARS, Items::SHEARS());
|
||||
$this->map1to1Item(Ids::SHULKER_SHELL, Items::SHULKER_SHELL());
|
||||
$this->map1to1Item(Ids::SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE, Items::SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::SLIME_BALL, Items::SLIMEBALL());
|
||||
$this->map1to1Item(Ids::SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE, Items::SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::SNOWBALL, Items::SNOWBALL());
|
||||
$this->map1to1Item(Ids::SPIDER_EYE, Items::SPIDER_EYE());
|
||||
$this->map1to1Item(Ids::SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE, Items::SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::SPRUCE_BOAT, Items::SPRUCE_BOAT());
|
||||
$this->map1to1Item(Ids::SPRUCE_SIGN, Items::SPRUCE_SIGN());
|
||||
$this->map1to1Item(Ids::SPYGLASS, Items::SPYGLASS());
|
||||
@ -361,14 +373,19 @@ final class ItemSerializerDeserializerRegistrar{
|
||||
$this->map1to1Item(Ids::SUGAR, Items::SUGAR());
|
||||
$this->map1to1Item(Ids::SWEET_BERRIES, Items::SWEET_BERRIES());
|
||||
$this->map1to1Item(Ids::TORCHFLOWER_SEEDS, Items::TORCHFLOWER_SEEDS());
|
||||
$this->map1to1Item(Ids::TIDE_ARMOR_TRIM_SMITHING_TEMPLATE, Items::TIDE_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::TOTEM_OF_UNDYING, Items::TOTEM());
|
||||
$this->map1to1Item(Ids::TROPICAL_FISH, Items::CLOWNFISH());
|
||||
$this->map1to1Item(Ids::TURTLE_HELMET, Items::TURTLE_HELMET());
|
||||
$this->map1to1Item(Ids::VEX_ARMOR_TRIM_SMITHING_TEMPLATE, Items::VEX_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::VILLAGER_SPAWN_EGG, Items::VILLAGER_SPAWN_EGG());
|
||||
$this->map1to1Item(Ids::WARD_ARMOR_TRIM_SMITHING_TEMPLATE, Items::WARD_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::WARPED_SIGN, Items::WARPED_SIGN());
|
||||
$this->map1to1Item(Ids::WATER_BUCKET, Items::WATER_BUCKET());
|
||||
$this->map1to1Item(Ids::WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE, Items::WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::WHEAT, Items::WHEAT());
|
||||
$this->map1to1Item(Ids::WHEAT_SEEDS, Items::WHEAT_SEEDS());
|
||||
$this->map1to1Item(Ids::WILD_ARMOR_TRIM_SMITHING_TEMPLATE, Items::WILD_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$this->map1to1Item(Ids::WOODEN_AXE, Items::WOODEN_AXE());
|
||||
$this->map1to1Item(Ids::WOODEN_HOE, Items::WOODEN_HOE());
|
||||
$this->map1to1Item(Ids::WOODEN_PICKAXE, Items::WOODEN_PICKAXE());
|
||||
|
@ -305,8 +305,25 @@ final class ItemTypeIds{
|
||||
public const CHERRY_SIGN = 20266;
|
||||
public const ENCHANTED_BOOK = 20267;
|
||||
public const TORCHFLOWER_SEEDS = 20268;
|
||||
public const NETHERITE_UPGRADE_SMITHING_TEMPLATE = 20269;
|
||||
public const SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE = 20270;
|
||||
public const VEX_ARMOR_TRIM_SMITHING_TEMPLATE = 20271;
|
||||
public const WILD_ARMOR_TRIM_SMITHING_TEMPLATE = 20272;
|
||||
public const COAST_ARMOR_TRIM_SMITHING_TEMPLATE = 20273;
|
||||
public const DUNE_ARMOR_TRIM_SMITHING_TEMPLATE = 20274;
|
||||
public const WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE = 20275;
|
||||
public const RAISER_ARMOR_TRIM_SMITHING_TEMPLATE = 20276;
|
||||
public const SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE = 20277;
|
||||
public const HOST_ARMOR_TRIM_SMITHING_TEMPLATE = 20278;
|
||||
public const WARD_ARMOR_TRIM_SMITHING_TEMPLATE = 20279;
|
||||
public const SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE = 20280;
|
||||
public const TIDE_ARMOR_TRIM_SMITHING_TEMPLATE = 20281;
|
||||
public const SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE = 20282;
|
||||
public const RIB_ARMOR_TRIM_SMITHING_TEMPLATE = 20283;
|
||||
public const EYE_ARMOR_TRIM_SMITHING_TEMPLATE = 20284;
|
||||
public const SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE = 20285;
|
||||
|
||||
public const FIRST_UNUSED_ITEM_ID = 20269;
|
||||
public const FIRST_UNUSED_ITEM_ID = 20286;
|
||||
|
||||
private static int $nextDynamicId = self::FIRST_UNUSED_ITEM_ID;
|
||||
|
||||
|
@ -1264,6 +1264,7 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->register("clown_fish", fn() => Items::CLOWNFISH());
|
||||
$result->register("clownfish", fn() => Items::CLOWNFISH());
|
||||
$result->register("coal", fn() => Items::COAL());
|
||||
$result->register("coast_armor_trim_smithing_template", fn() => Items::COAST_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("cocoa_beans", fn() => Items::COCOA_BEANS());
|
||||
$result->register("cod", fn() => Items::RAW_FISH());
|
||||
$result->register("compass", fn() => Items::COMPASS());
|
||||
@ -1292,6 +1293,7 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->register("disc_fragment_5", fn() => Items::DISC_FRAGMENT_5());
|
||||
$result->register("dragon_breath", fn() => Items::DRAGON_BREATH());
|
||||
$result->register("dried_kelp", fn() => Items::DRIED_KELP());
|
||||
$result->register("dune_armor_trim_smithing_template", fn() => Items::DUNE_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("dye", fn() => Items::INK_SAC());
|
||||
$result->register("echo_shard", fn() => Items::ECHO_SHARD());
|
||||
$result->register("egg", fn() => Items::EGG());
|
||||
@ -1302,6 +1304,7 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->register("enchanting_bottle", fn() => Items::EXPERIENCE_BOTTLE());
|
||||
$result->register("ender_pearl", fn() => Items::ENDER_PEARL());
|
||||
$result->register("experience_bottle", fn() => Items::EXPERIENCE_BOTTLE());
|
||||
$result->register("eye_armor_trim_smithing_template", fn() => Items::EYE_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("eye_drops", fn() => Items::MEDICINE()->setType(MedicineType::EYE_DROPS));
|
||||
$result->register("feather", fn() => Items::FEATHER());
|
||||
$result->register("fermented_spider_eye", fn() => Items::FERMENTED_SPIDER_EYE());
|
||||
@ -1343,6 +1346,7 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->register("gunpowder", fn() => Items::GUNPOWDER());
|
||||
$result->register("heart_of_the_sea", fn() => Items::HEART_OF_THE_SEA());
|
||||
$result->register("honey_bottle", fn() => Items::HONEY_BOTTLE());
|
||||
$result->register("host_armor_trim_smithing_template", fn() => Items::HOST_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("honeycomb", fn() => Items::HONEYCOMB());
|
||||
$result->register("ink_sac", fn() => Items::INK_SAC());
|
||||
$result->register("iron_axe", fn() => Items::IRON_AXE());
|
||||
@ -1396,6 +1400,7 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->register("netherite_shovel", fn() => Items::NETHERITE_SHOVEL());
|
||||
$result->register("netherite_sword", fn() => Items::NETHERITE_SWORD());
|
||||
$result->register("netherstar", fn() => Items::NETHER_STAR());
|
||||
$result->register("netherite_upgrade_smithing_template", fn() => Items::NETHERITE_UPGRADE_SMITHING_TEMPLATE());
|
||||
$result->register("oak_boat", fn() => Items::OAK_BOAT());
|
||||
$result->register("painting", fn() => Items::PAINTING());
|
||||
$result->register("paper", fn() => Items::PAPER());
|
||||
@ -1416,6 +1421,7 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->register("rabbit_foot", fn() => Items::RABBIT_FOOT());
|
||||
$result->register("rabbit_hide", fn() => Items::RABBIT_HIDE());
|
||||
$result->register("rabbit_stew", fn() => Items::RABBIT_STEW());
|
||||
$result->register("raiser_armor_trim_smithing_template", fn() => Items::RAISER_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("raw_beef", fn() => Items::RAW_BEEF());
|
||||
$result->register("raw_cod", fn() => Items::RAW_FISH());
|
||||
$result->register("raw_copper", fn() => Items::RAW_COPPER());
|
||||
@ -1444,17 +1450,23 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->register("record_ward", fn() => Items::RECORD_WARD());
|
||||
$result->register("redstone", fn() => Items::REDSTONE_DUST());
|
||||
$result->register("redstone_dust", fn() => Items::REDSTONE_DUST());
|
||||
$result->register("rib_armor_trim_smithing_template", fn() => Items::RIB_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("rotten_flesh", fn() => Items::ROTTEN_FLESH());
|
||||
$result->register("salmon", fn() => Items::RAW_SALMON());
|
||||
$result->register("scute", fn() => Items::SCUTE());
|
||||
$result->register("sentry_armor_trim_smithing_template", fn() => Items::SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("shaper_armor_trim_smithing_template", fn() => Items::SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("seeds", fn() => Items::WHEAT_SEEDS());
|
||||
$result->register("shears", fn() => Items::SHEARS());
|
||||
$result->register("shulker_shell", fn() => Items::SHULKER_SHELL());
|
||||
$result->register("silence_armor_trim_smithing_template", fn() => Items::SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("slime_ball", fn() => Items::SLIMEBALL());
|
||||
$result->register("snout_armor_trim_smithing_template", fn() => Items::SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("slimeball", fn() => Items::SLIMEBALL());
|
||||
$result->register("snowball", fn() => Items::SNOWBALL());
|
||||
$result->register("speckled_melon", fn() => Items::GLISTERING_MELON());
|
||||
$result->register("spider_eye", fn() => Items::SPIDER_EYE());
|
||||
$result->register("spire_armor_trim_smithing_template", fn() => Items::SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("splash_potion", fn() => Items::SPLASH_POTION());
|
||||
$result->register("spruce_boat", fn() => Items::SPRUCE_BOAT());
|
||||
$result->register("spyglass", fn() => Items::SPYGLASS());
|
||||
@ -1473,13 +1485,18 @@ final class StringToItemParser extends StringToTParser{
|
||||
$result->register("sweet_berries", fn() => Items::SWEET_BERRIES());
|
||||
$result->register("tonic", fn() => Items::MEDICINE()->setType(MedicineType::TONIC));
|
||||
$result->register("torchflower_seeds", fn() => Items::TORCHFLOWER_SEEDS());
|
||||
$result->register("tide_armor_trim_smithing_template", fn() => Items::TIDE_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("totem", fn() => Items::TOTEM());
|
||||
$result->register("turtle_helmet", fn() => Items::TURTLE_HELMET());
|
||||
$result->register("vex_armor_trim_smithing_template", fn() => Items::VEX_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("turtle_shell_piece", fn() => Items::SCUTE());
|
||||
$result->register("villager_spawn_egg", fn() => Items::VILLAGER_SPAWN_EGG());
|
||||
$result->register("ward_armor_trim_smithing_template", fn() => Items::WARD_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("water_bucket", fn() => Items::WATER_BUCKET());
|
||||
$result->register("wayfinder_armor_trim_smithing_template", fn() => Items::WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("wheat", fn() => Items::WHEAT());
|
||||
$result->register("wheat_seeds", fn() => Items::WHEAT_SEEDS());
|
||||
$result->register("wild_armor_trim_smithing_template", fn() => Items::WILD_ARMOR_TRIM_SMITHING_TEMPLATE());
|
||||
$result->register("wooden_axe", fn() => Items::WOODEN_AXE());
|
||||
$result->register("wooden_hoe", fn() => Items::WOODEN_HOE());
|
||||
$result->register("wooden_pickaxe", fn() => Items::WOODEN_PICKAXE());
|
||||
|
@ -121,6 +121,7 @@ use function strtolower;
|
||||
* @method static Clock CLOCK()
|
||||
* @method static Clownfish CLOWNFISH()
|
||||
* @method static Coal COAL()
|
||||
* @method static Item COAST_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static CocoaBeans COCOA_BEANS()
|
||||
* @method static Compass COMPASS()
|
||||
* @method static CookedChicken COOKED_CHICKEN()
|
||||
@ -148,6 +149,7 @@ use function strtolower;
|
||||
* @method static Item DISC_FRAGMENT_5()
|
||||
* @method static Item DRAGON_BREATH()
|
||||
* @method static DriedKelp DRIED_KELP()
|
||||
* @method static Item DUNE_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static Dye DYE()
|
||||
* @method static Item ECHO_SHARD()
|
||||
* @method static Egg EGG()
|
||||
@ -156,6 +158,7 @@ use function strtolower;
|
||||
* @method static GoldenAppleEnchanted ENCHANTED_GOLDEN_APPLE()
|
||||
* @method static EnderPearl ENDER_PEARL()
|
||||
* @method static ExperienceBottle EXPERIENCE_BOTTLE()
|
||||
* @method static Item EYE_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static Item FEATHER()
|
||||
* @method static Item FERMENTED_SPIDER_EYE()
|
||||
* @method static FireCharge FIRE_CHARGE()
|
||||
@ -185,6 +188,7 @@ use function strtolower;
|
||||
* @method static Item HEART_OF_THE_SEA()
|
||||
* @method static Item HONEYCOMB()
|
||||
* @method static HoneyBottle HONEY_BOTTLE()
|
||||
* @method static Item HOST_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static Item INK_SAC()
|
||||
* @method static Axe IRON_AXE()
|
||||
* @method static Armor IRON_BOOTS()
|
||||
@ -227,6 +231,7 @@ use function strtolower;
|
||||
* @method static Item NETHERITE_SCRAP()
|
||||
* @method static Shovel NETHERITE_SHOVEL()
|
||||
* @method static Sword NETHERITE_SWORD()
|
||||
* @method static Item NETHERITE_UPGRADE_SMITHING_TEMPLATE()
|
||||
* @method static Item NETHER_BRICK()
|
||||
* @method static Item NETHER_QUARTZ()
|
||||
* @method static Item NETHER_STAR()
|
||||
@ -247,6 +252,7 @@ use function strtolower;
|
||||
* @method static Item RABBIT_FOOT()
|
||||
* @method static Item RABBIT_HIDE()
|
||||
* @method static RabbitStew RABBIT_STEW()
|
||||
* @method static Item RAISER_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static RawBeef RAW_BEEF()
|
||||
* @method static RawChicken RAW_CHICKEN()
|
||||
* @method static Item RAW_COPPER()
|
||||
@ -273,13 +279,19 @@ use function strtolower;
|
||||
* @method static Record RECORD_WAIT()
|
||||
* @method static Record RECORD_WARD()
|
||||
* @method static Redstone REDSTONE_DUST()
|
||||
* @method static Item RIB_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static RottenFlesh ROTTEN_FLESH()
|
||||
* @method static Item SCUTE()
|
||||
* @method static Item SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static Item SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static Shears SHEARS()
|
||||
* @method static Item SHULKER_SHELL()
|
||||
* @method static Item SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static Item SLIMEBALL()
|
||||
* @method static Item SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static Snowball SNOWBALL()
|
||||
* @method static SpiderEye SPIDER_EYE()
|
||||
* @method static Item SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static SplashPotion SPLASH_POTION()
|
||||
* @method static Boat SPRUCE_BOAT()
|
||||
* @method static ItemBlockWallOrFloor SPRUCE_SIGN()
|
||||
@ -296,14 +308,19 @@ use function strtolower;
|
||||
* @method static Item SUGAR()
|
||||
* @method static SuspiciousStew SUSPICIOUS_STEW()
|
||||
* @method static SweetBerries SWEET_BERRIES()
|
||||
* @method static Item TIDE_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static TorchflowerSeeds TORCHFLOWER_SEEDS()
|
||||
* @method static Totem TOTEM()
|
||||
* @method static TurtleHelmet TURTLE_HELMET()
|
||||
* @method static Item VEX_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static SpawnEgg VILLAGER_SPAWN_EGG()
|
||||
* @method static Item WARD_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static ItemBlockWallOrFloor WARPED_SIGN()
|
||||
* @method static LiquidBucket WATER_BUCKET()
|
||||
* @method static Item WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static Item WHEAT()
|
||||
* @method static WheatSeeds WHEAT_SEEDS()
|
||||
* @method static Item WILD_ARMOR_TRIM_SMITHING_TEMPLATE()
|
||||
* @method static Axe WOODEN_AXE()
|
||||
* @method static Hoe WOODEN_HOE()
|
||||
* @method static Pickaxe WOODEN_PICKAXE()
|
||||
@ -339,6 +356,7 @@ final class VanillaItems{
|
||||
self::registerArmorItems();
|
||||
self::registerSpawnEggs();
|
||||
self::registerTierToolItems();
|
||||
self::registerSmithingTemplates();
|
||||
|
||||
self::register("air", Blocks::AIR()->asItem()->setCount(0));
|
||||
|
||||
@ -644,4 +662,24 @@ final class VanillaItems{
|
||||
self::register("netherite_leggings", new Armor(new IID(Ids::NETHERITE_LEGGINGS), "Netherite Leggings", new ArmorTypeInfo(6, 556, ArmorInventory::SLOT_LEGS, 3, true, material: ArmorMaterials::NETHERITE()), [EnchantmentTags::LEGGINGS]));
|
||||
}
|
||||
|
||||
private static function registerSmithingTemplates() : void{
|
||||
self::register("netherite_upgrade_smithing_template", new Item(new IID(Ids::NETHERITE_UPGRADE_SMITHING_TEMPLATE), "Netherite Upgrade Smithing Template"));
|
||||
self::register("coast_armor_trim_smithing_template", new Item(new IID(Ids::COAST_ARMOR_TRIM_SMITHING_TEMPLATE), "Coast Armor Trim Smithing Template"));
|
||||
self::register("dune_armor_trim_smithing_template", new Item(new IID(Ids::DUNE_ARMOR_TRIM_SMITHING_TEMPLATE), "Dune Armor Trim Smithing Template"));
|
||||
self::register("eye_armor_trim_smithing_template", new Item(new IID(Ids::EYE_ARMOR_TRIM_SMITHING_TEMPLATE), "Eye Armor Trim Smithing Template"));
|
||||
self::register("host_armor_trim_smithing_template", new Item(new IID(Ids::HOST_ARMOR_TRIM_SMITHING_TEMPLATE), "Host Armor Trim Smithing Template"));
|
||||
self::register("raiser_armor_trim_smithing_template", new Item(new IID(Ids::RAISER_ARMOR_TRIM_SMITHING_TEMPLATE), "Raiser Armor Trim Smithing Template"));
|
||||
self::register("rib_armor_trim_smithing_template", new Item(new IID(Ids::RIB_ARMOR_TRIM_SMITHING_TEMPLATE), "Rib Armor Trim Smithing Template"));
|
||||
self::register("sentry_armor_trim_smithing_template", new Item(new IID(Ids::SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE), "Sentry Armor Trim Smithing Template"));
|
||||
self::register("shaper_armor_trim_smithing_template", new Item(new IID(Ids::SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE), "Shaper Armor Trim Smithing Template"));
|
||||
self::register("silence_armor_trim_smithing_template", new Item(new IID(Ids::SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE), "Silence Armor Trim Smithing Template"));
|
||||
self::register("snout_armor_trim_smithing_template", new Item(new IID(Ids::SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE), "Snout Armor Trim Smithing Template"));
|
||||
self::register("spire_armor_trim_smithing_template", new Item(new IID(Ids::SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE), "Spire Armor Trim Smithing Template"));
|
||||
self::register("tide_armor_trim_smithing_template", new Item(new IID(Ids::TIDE_ARMOR_TRIM_SMITHING_TEMPLATE), "Tide Armor Trim Smithing Template"));
|
||||
self::register("vex_armor_trim_smithing_template", new Item(new IID(Ids::VEX_ARMOR_TRIM_SMITHING_TEMPLATE), "Vex Armor Trim Smithing Template"));
|
||||
self::register("ward_armor_trim_smithing_template", new Item(new IID(Ids::WARD_ARMOR_TRIM_SMITHING_TEMPLATE), "Ward Armor Trim Smithing Template"));
|
||||
self::register("wayfinder_armor_trim_smithing_template", new Item(new IID(Ids::WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE), "Wayfinder Armor Trim Smithing Template"));
|
||||
self::register("wild_armor_trim_smithing_template", new Item(new IID(Ids::WILD_ARMOR_TRIM_SMITHING_TEMPLATE), "Wild Armor Trim Smithing Template"));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -67,17 +67,12 @@ final class ZlibCompressor implements Compressor{
|
||||
return $result;
|
||||
}
|
||||
|
||||
private static function zlib_encode(string $data, int $level) : string{
|
||||
return Utils::assumeNotFalse(zlib_encode($data, ZLIB_ENCODING_RAW, $level), "ZLIB compression failed");
|
||||
}
|
||||
|
||||
public function compress(string $payload) : string{
|
||||
$compressible = $this->minCompressionSize !== null && strlen($payload) >= $this->minCompressionSize;
|
||||
if(function_exists('libdeflate_deflate_compress')){
|
||||
return $compressible ?
|
||||
libdeflate_deflate_compress($payload, $this->level) :
|
||||
self::zlib_encode($payload, 0);
|
||||
}
|
||||
return self::zlib_encode($payload, $compressible ? $this->level : 0);
|
||||
$level = $compressible ? $this->level : 0;
|
||||
|
||||
return function_exists('libdeflate_deflate_compress') ?
|
||||
libdeflate_deflate_compress($payload, $level) :
|
||||
Utils::assumeNotFalse(zlib_encode($payload, ZLIB_ENCODING_RAW, $level), "ZLIB compression failed");
|
||||
}
|
||||
}
|
||||
|
@ -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)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -513,9 +513,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()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ use function get_class;
|
||||
use function str_starts_with;
|
||||
|
||||
abstract class Timings{
|
||||
public const GROUP_MINECRAFT = "Minecraft";
|
||||
public const GROUP_BREAKDOWN = "Minecraft - Breakdown";
|
||||
|
||||
private static bool $initialized = false;
|
||||
@ -137,8 +138,8 @@ abstract class Timings{
|
||||
self::$initialized = true;
|
||||
|
||||
self::$fullTick = new TimingsHandler("Full Server Tick");
|
||||
self::$serverTick = new TimingsHandler("Server Tick Update Cycle", self::$fullTick, group: self::GROUP_BREAKDOWN);
|
||||
self::$serverInterrupts = new TimingsHandler("Server Mid-Tick Processing", self::$fullTick, group: self::GROUP_BREAKDOWN);
|
||||
self::$serverTick = new TimingsHandler("Server Tick Update Cycle", self::$fullTick);
|
||||
self::$serverInterrupts = new TimingsHandler("Server Mid-Tick Processing", self::$fullTick);
|
||||
self::$memoryManager = new TimingsHandler("Memory Manager");
|
||||
self::$garbageCollector = new TimingsHandler("Garbage Collector", self::$memoryManager);
|
||||
self::$titleTick = new TimingsHandler("Console Title Tick");
|
||||
@ -146,51 +147,51 @@ abstract class Timings{
|
||||
self::$connection = new TimingsHandler("Connection Handler");
|
||||
|
||||
self::$playerNetworkSend = new TimingsHandler("Player Network Send", self::$connection);
|
||||
self::$playerNetworkSendCompress = new TimingsHandler("Player Network Send - Compression", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
|
||||
self::$playerNetworkSendCompressBroadcast = new TimingsHandler("Player Network Send - Compression (Broadcast)", self::$playerNetworkSendCompress, group: self::GROUP_BREAKDOWN);
|
||||
self::$playerNetworkSendCompressSessionBuffer = new TimingsHandler("Player Network Send - Compression (Session Buffer)", self::$playerNetworkSendCompress, group: self::GROUP_BREAKDOWN);
|
||||
self::$playerNetworkSendEncrypt = new TimingsHandler("Player Network Send - Encryption", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
|
||||
self::$playerNetworkSendInventorySync = new TimingsHandler("Player Network Send - Inventory Sync", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
|
||||
self::$playerNetworkSendPreSpawnGameData = new TimingsHandler("Player Network Send - Pre-Spawn Game Data", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
|
||||
self::$playerNetworkSendCompress = new TimingsHandler("Player Network Send - Compression", self::$playerNetworkSend);
|
||||
self::$playerNetworkSendCompressBroadcast = new TimingsHandler("Player Network Send - Compression (Broadcast)", self::$playerNetworkSendCompress);
|
||||
self::$playerNetworkSendCompressSessionBuffer = new TimingsHandler("Player Network Send - Compression (Session Buffer)", self::$playerNetworkSendCompress);
|
||||
self::$playerNetworkSendEncrypt = new TimingsHandler("Player Network Send - Encryption", self::$playerNetworkSend);
|
||||
self::$playerNetworkSendInventorySync = new TimingsHandler("Player Network Send - Inventory Sync", self::$playerNetworkSend);
|
||||
self::$playerNetworkSendPreSpawnGameData = new TimingsHandler("Player Network Send - Pre-Spawn Game Data", self::$playerNetworkSend);
|
||||
|
||||
self::$playerNetworkReceive = new TimingsHandler("Player Network Receive", self::$connection);
|
||||
self::$playerNetworkReceiveDecompress = new TimingsHandler("Player Network Receive - Decompression", self::$playerNetworkReceive, group: self::GROUP_BREAKDOWN);
|
||||
self::$playerNetworkReceiveDecrypt = new TimingsHandler("Player Network Receive - Decryption", self::$playerNetworkReceive, group: self::GROUP_BREAKDOWN);
|
||||
self::$playerNetworkReceiveDecompress = new TimingsHandler("Player Network Receive - Decompression", self::$playerNetworkReceive);
|
||||
self::$playerNetworkReceiveDecrypt = new TimingsHandler("Player Network Receive - Decryption", self::$playerNetworkReceive);
|
||||
|
||||
self::$broadcastPackets = new TimingsHandler("Broadcast Packets", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
|
||||
self::$broadcastPackets = new TimingsHandler("Broadcast Packets", self::$playerNetworkSend);
|
||||
|
||||
self::$playerMove = new TimingsHandler("Player Movement");
|
||||
self::$playerChunkOrder = new TimingsHandler("Player Order Chunks");
|
||||
self::$playerChunkSend = new TimingsHandler("Player Network Send - Chunks", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
|
||||
self::$playerChunkSend = new TimingsHandler("Player Network Send - Chunks", self::$playerNetworkSend);
|
||||
self::$scheduler = new TimingsHandler("Scheduler");
|
||||
self::$serverCommand = new TimingsHandler("Server Command");
|
||||
self::$permissibleCalculation = new TimingsHandler("Permissible Calculation");
|
||||
self::$permissibleCalculationDiff = new TimingsHandler("Permissible Calculation - Diff", self::$permissibleCalculation, group: self::GROUP_BREAKDOWN);
|
||||
self::$permissibleCalculationCallback = new TimingsHandler("Permissible Calculation - Callbacks", self::$permissibleCalculation, group: self::GROUP_BREAKDOWN);
|
||||
self::$permissibleCalculationDiff = new TimingsHandler("Permissible Calculation - Diff", self::$permissibleCalculation);
|
||||
self::$permissibleCalculationCallback = new TimingsHandler("Permissible Calculation - Callbacks", self::$permissibleCalculation);
|
||||
|
||||
self::$syncPlayerDataLoad = new TimingsHandler("Player Data Load");
|
||||
self::$syncPlayerDataSave = new TimingsHandler("Player Data Save");
|
||||
|
||||
self::$entityMove = new TimingsHandler("Entity Movement", group: self::GROUP_BREAKDOWN);
|
||||
self::$entityMoveCollision = new TimingsHandler("Entity Movement - Collision Checks", self::$entityMove, group: self::GROUP_BREAKDOWN);
|
||||
self::$entityMove = new TimingsHandler("Entity Movement");
|
||||
self::$entityMoveCollision = new TimingsHandler("Entity Movement - Collision Checks", self::$entityMove);
|
||||
|
||||
self::$projectileMove = new TimingsHandler("Projectile Movement", self::$entityMove, group: self::GROUP_BREAKDOWN);
|
||||
self::$projectileMoveRayTrace = new TimingsHandler("Projectile Movement - Ray Tracing", self::$projectileMove, group: self::GROUP_BREAKDOWN);
|
||||
self::$projectileMove = new TimingsHandler("Projectile Movement", self::$entityMove);
|
||||
self::$projectileMoveRayTrace = new TimingsHandler("Projectile Movement - Ray Tracing", self::$projectileMove);
|
||||
|
||||
self::$playerCheckNearEntities = new TimingsHandler("checkNearEntities", group: self::GROUP_BREAKDOWN);
|
||||
self::$entityBaseTick = new TimingsHandler("Entity Base Tick", group: self::GROUP_BREAKDOWN);
|
||||
self::$livingEntityBaseTick = new TimingsHandler("Entity Base Tick - Living", group: self::GROUP_BREAKDOWN);
|
||||
self::$itemEntityBaseTick = new TimingsHandler("Entity Base Tick - ItemEntity", group: self::GROUP_BREAKDOWN);
|
||||
self::$playerCheckNearEntities = new TimingsHandler("checkNearEntities");
|
||||
self::$entityBaseTick = new TimingsHandler("Entity Base Tick");
|
||||
self::$livingEntityBaseTick = new TimingsHandler("Entity Base Tick - Living");
|
||||
self::$itemEntityBaseTick = new TimingsHandler("Entity Base Tick - ItemEntity");
|
||||
|
||||
self::$schedulerSync = new TimingsHandler("Scheduler - Sync Tasks", group: self::GROUP_BREAKDOWN);
|
||||
self::$schedulerSync = new TimingsHandler("Scheduler - Sync Tasks");
|
||||
|
||||
self::$schedulerAsync = new TimingsHandler("Scheduler - Async Tasks", group: self::GROUP_BREAKDOWN);
|
||||
self::$asyncTaskProgressUpdateParent = new TimingsHandler("Async Tasks - Progress Updates", self::$schedulerAsync, group: self::GROUP_BREAKDOWN);
|
||||
self::$asyncTaskCompletionParent = new TimingsHandler("Async Tasks - Completion Handlers", self::$schedulerAsync, group: self::GROUP_BREAKDOWN);
|
||||
self::$asyncTaskErrorParent = new TimingsHandler("Async Tasks - Error Handlers", self::$schedulerAsync, group: self::GROUP_BREAKDOWN);
|
||||
self::$schedulerAsync = new TimingsHandler("Scheduler - Async Tasks");
|
||||
self::$asyncTaskProgressUpdateParent = new TimingsHandler("Async Tasks - Progress Updates", self::$schedulerAsync);
|
||||
self::$asyncTaskCompletionParent = new TimingsHandler("Async Tasks - Completion Handlers", self::$schedulerAsync);
|
||||
self::$asyncTaskErrorParent = new TimingsHandler("Async Tasks - Error Handlers", self::$schedulerAsync);
|
||||
|
||||
self::$playerCommand = new TimingsHandler("Player Command", group: self::GROUP_BREAKDOWN);
|
||||
self::$craftingDataCacheRebuild = new TimingsHandler("Build CraftingDataPacket Cache", group: self::GROUP_BREAKDOWN);
|
||||
self::$playerCommand = new TimingsHandler("Player Command");
|
||||
self::$craftingDataCacheRebuild = new TimingsHandler("Build CraftingDataPacket Cache");
|
||||
|
||||
}
|
||||
|
||||
@ -232,7 +233,7 @@ abstract class Timings{
|
||||
}else{
|
||||
$displayName = self::shortenCoreClassName($entity::class, "pocketmine\\entity\\");
|
||||
}
|
||||
self::$entityTypeTimingMap[$entity::class] = new TimingsHandler("Entity Tick - " . $displayName, group: self::GROUP_BREAKDOWN);
|
||||
self::$entityTypeTimingMap[$entity::class] = new TimingsHandler("Entity Tick - " . $displayName);
|
||||
}
|
||||
|
||||
return self::$entityTypeTimingMap[$entity::class];
|
||||
@ -242,8 +243,7 @@ abstract class Timings{
|
||||
self::init();
|
||||
if(!isset(self::$tileEntityTypeTimingMap[$tile::class])){
|
||||
self::$tileEntityTypeTimingMap[$tile::class] = new TimingsHandler(
|
||||
"Block Entity Tick - " . self::shortenCoreClassName($tile::class, "pocketmine\\block\\tile\\"),
|
||||
group: self::GROUP_BREAKDOWN
|
||||
"Block Entity Tick - " . self::shortenCoreClassName($tile::class, "pocketmine\\block\\tile\\")
|
||||
);
|
||||
}
|
||||
|
||||
@ -253,7 +253,7 @@ abstract class Timings{
|
||||
public static function getReceiveDataPacketTimings(ServerboundPacket $pk) : TimingsHandler{
|
||||
self::init();
|
||||
if(!isset(self::$packetReceiveTimingMap[$pk::class])){
|
||||
self::$packetReceiveTimingMap[$pk::class] = new TimingsHandler("Receive - " . $pk->getName(), self::$playerNetworkReceive, group: self::GROUP_BREAKDOWN);
|
||||
self::$packetReceiveTimingMap[$pk::class] = new TimingsHandler("Receive - " . $pk->getName(), self::$playerNetworkReceive);
|
||||
}
|
||||
|
||||
return self::$packetReceiveTimingMap[$pk::class];
|
||||
@ -262,31 +262,28 @@ abstract class Timings{
|
||||
public static function getDecodeDataPacketTimings(ServerboundPacket $pk) : TimingsHandler{
|
||||
return self::$packetDecodeTimingMap[$pk::class] ??= new TimingsHandler(
|
||||
"Decode - " . $pk->getName(),
|
||||
self::getReceiveDataPacketTimings($pk),
|
||||
group: self::GROUP_BREAKDOWN
|
||||
self::getReceiveDataPacketTimings($pk)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getHandleDataPacketTimings(ServerboundPacket $pk) : TimingsHandler{
|
||||
return self::$packetHandleTimingMap[$pk::class] ??= new TimingsHandler(
|
||||
"Handler - " . $pk->getName(),
|
||||
self::getReceiveDataPacketTimings($pk),
|
||||
group: self::GROUP_BREAKDOWN
|
||||
self::getReceiveDataPacketTimings($pk)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getEncodeDataPacketTimings(ClientboundPacket $pk) : TimingsHandler{
|
||||
return self::$packetEncodeTimingMap[$pk::class] ??= new TimingsHandler(
|
||||
"Encode - " . $pk->getName(),
|
||||
self::getSendDataPacketTimings($pk),
|
||||
group: self::GROUP_BREAKDOWN
|
||||
self::getSendDataPacketTimings($pk)
|
||||
);
|
||||
}
|
||||
|
||||
public static function getSendDataPacketTimings(ClientboundPacket $pk) : TimingsHandler{
|
||||
self::init();
|
||||
if(!isset(self::$packetSendTimingMap[$pk::class])){
|
||||
self::$packetSendTimingMap[$pk::class] = new TimingsHandler("Send - " . $pk->getName(), self::$playerNetworkSend, group: self::GROUP_BREAKDOWN);
|
||||
self::$packetSendTimingMap[$pk::class] = new TimingsHandler("Send - " . $pk->getName(), self::$playerNetworkSend);
|
||||
}
|
||||
|
||||
return self::$packetSendTimingMap[$pk::class];
|
||||
@ -295,7 +292,7 @@ abstract class Timings{
|
||||
public static function getCommandDispatchTimings(string $commandName) : TimingsHandler{
|
||||
self::init();
|
||||
|
||||
return self::$commandTimingMap[$commandName] ??= new TimingsHandler("Command - " . $commandName, group: self::GROUP_BREAKDOWN);
|
||||
return self::$commandTimingMap[$commandName] ??= new TimingsHandler("Command - " . $commandName);
|
||||
}
|
||||
|
||||
public static function getEventTimings(Event $event) : TimingsHandler{
|
||||
@ -328,7 +325,7 @@ abstract class Timings{
|
||||
return self::$eventHandlers[$event][$handlerName];
|
||||
}
|
||||
|
||||
public static function getAsyncTaskProgressUpdateTimings(AsyncTask $task, string $group = self::GROUP_BREAKDOWN) : TimingsHandler{
|
||||
public static function getAsyncTaskProgressUpdateTimings(AsyncTask $task, string $group = self::GROUP_MINECRAFT) : TimingsHandler{
|
||||
$taskClass = $task::class;
|
||||
if(!isset(self::$asyncTaskProgressUpdate[$taskClass])){
|
||||
self::init();
|
||||
@ -342,7 +339,7 @@ abstract class Timings{
|
||||
return self::$asyncTaskProgressUpdate[$taskClass];
|
||||
}
|
||||
|
||||
public static function getAsyncTaskCompletionTimings(AsyncTask $task, string $group = self::GROUP_BREAKDOWN) : TimingsHandler{
|
||||
public static function getAsyncTaskCompletionTimings(AsyncTask $task, string $group = self::GROUP_MINECRAFT) : TimingsHandler{
|
||||
$taskClass = $task::class;
|
||||
if(!isset(self::$asyncTaskCompletion[$taskClass])){
|
||||
self::init();
|
||||
@ -356,7 +353,7 @@ abstract class Timings{
|
||||
return self::$asyncTaskCompletion[$taskClass];
|
||||
}
|
||||
|
||||
public static function getAsyncTaskErrorTimings(AsyncTask $task, string $group = self::GROUP_BREAKDOWN) : TimingsHandler{
|
||||
public static function getAsyncTaskErrorTimings(AsyncTask $task, string $group = self::GROUP_MINECRAFT) : TimingsHandler{
|
||||
$taskClass = $task::class;
|
||||
if(!isset(self::$asyncTaskError[$taskClass])){
|
||||
self::init();
|
||||
|
@ -120,7 +120,7 @@ class TimingsHandler{
|
||||
public function __construct(
|
||||
private string $name,
|
||||
private ?TimingsHandler $parent = null,
|
||||
private string $group = "Minecraft"
|
||||
private string $group = Timings::GROUP_MINECRAFT
|
||||
){}
|
||||
|
||||
public function getName() : string{ return $this->name; }
|
||||
|
@ -826,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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -861,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)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1219,13 +1221,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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1663,16 +1666,19 @@ class World implements ChunkManager{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the highest available level of any type of light at the given coordinates, adjusted for the current
|
||||
* weather and time of day.
|
||||
* Returns the highest level of any type of light at the given coordinates, adjusted for the current weather and
|
||||
* time of day.
|
||||
*/
|
||||
public function getFullLight(Vector3 $pos) : int{
|
||||
return $this->getFullLightAt($pos->x, $pos->y, $pos->z);
|
||||
$floorX = $pos->getFloorX();
|
||||
$floorY = $pos->getFloorY();
|
||||
$floorZ = $pos->getFloorZ();
|
||||
return $this->getFullLightAt($floorX, $floorY, $floorZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the highest available level of any type of light at the given coordinates, adjusted for the current
|
||||
* weather and time of day.
|
||||
* Returns the highest level of any type of light at the given coordinates, adjusted for the current weather and
|
||||
* time of day.
|
||||
*/
|
||||
public function getFullLightAt(int $x, int $y, int $z) : int{
|
||||
$skyLight = $this->getRealBlockSkyLightAt($x, $y, $z);
|
||||
@ -1684,18 +1690,43 @@ class World implements ChunkManager{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the highest available level of any type of light at, or adjacent to, the given coordinates, adjusted for
|
||||
* the current weather and time of day.
|
||||
* Returns the highest level of any type of light at, or adjacent to, the given coordinates, adjusted for the
|
||||
* current weather and time of day.
|
||||
*/
|
||||
public function getHighestAdjacentFullLightAt(int $x, int $y, int $z) : int{
|
||||
return $this->getHighestAdjacentLight($x, $y, $z, $this->getFullLightAt(...));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the highest potential level of any type of light at the target coordinates.
|
||||
* This is not affected by weather or time of day.
|
||||
*/
|
||||
public function getPotentialLight(Vector3 $pos) : int{
|
||||
$floorX = $pos->getFloorX();
|
||||
$floorY = $pos->getFloorY();
|
||||
$floorZ = $pos->getFloorZ();
|
||||
return $this->getPotentialLightAt($floorX, $floorY, $floorZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the highest potential level of any type of light at the target coordinates.
|
||||
* This is not affected by weather or time of day.
|
||||
*/
|
||||
public function getPotentialLightAt(int $x, int $y, int $z) : int{
|
||||
return max($this->getPotentialBlockSkyLightAt($x, $y, $z), $this->getBlockLightAt($x, $y, $z));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the highest potential level of any type of light at, or adjacent to, the given coordinates.
|
||||
* This is not affected by weather or time of day.
|
||||
*/
|
||||
public function getHighestAdjacentPotentialLightAt(int $x, int $y, int $z) : int{
|
||||
return $this->getHighestAdjacentLight($x, $y, $z, $this->getPotentialLightAt(...));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the highest potential level of sky light at the target coordinates, regardless of the time of day or
|
||||
* weather conditions.
|
||||
* You usually don't want to use this for vanilla gameplay logic; prefer the real sky light instead.
|
||||
* @see World::getRealBlockSkyLightAt()
|
||||
*
|
||||
* @return int 0-15
|
||||
*/
|
||||
@ -2292,9 +2323,6 @@ class World implements ChunkManager{
|
||||
|
||||
for($x = $minX; $x <= $maxX; ++$x){
|
||||
for($z = $minZ; $z <= $maxZ; ++$z){
|
||||
if(!$this->isChunkLoaded($x, $z)){
|
||||
continue;
|
||||
}
|
||||
foreach($this->getChunkEntities($x, $z) as $ent){
|
||||
if($ent !== $entity && $ent->boundingBox->intersectsWith($bb)){
|
||||
$nearby[] = $ent;
|
||||
@ -2335,9 +2363,6 @@ class World implements ChunkManager{
|
||||
|
||||
for($x = $minX; $x <= $maxX; ++$x){
|
||||
for($z = $minZ; $z <= $maxZ; ++$z){
|
||||
if(!$this->isChunkLoaded($x, $z)){
|
||||
continue;
|
||||
}
|
||||
foreach($this->getChunkEntities($x, $z) as $entity){
|
||||
if(!($entity instanceof $entityType) || $entity->isFlaggedForDespawn() || (!$includeDead && !$entity->isAlive())){
|
||||
continue;
|
||||
@ -2664,9 +2689,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()]);
|
||||
@ -2699,9 +2725,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()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\world;
|
||||
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\timings\TimingsHandler;
|
||||
|
||||
class WorldTimings{
|
||||
@ -66,7 +65,7 @@ class WorldTimings{
|
||||
private static function newTimer(string $worldName, string $timerName) : TimingsHandler{
|
||||
$aggregator = self::$aggregators[$timerName] ??= new TimingsHandler("Worlds - $timerName"); //displayed in Minecraft primary table
|
||||
|
||||
return new TimingsHandler("$worldName - $timerName", $aggregator, Timings::GROUP_BREAKDOWN);
|
||||
return new TimingsHandler("$worldName - $timerName", $aggregator);
|
||||
}
|
||||
|
||||
public function __construct(World $world){
|
||||
|
@ -425,6 +425,21 @@ parameters:
|
||||
count: 3
|
||||
path: ../../../src/block/tile/Spawnable.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\world\\\\World\\:\\:getPotentialLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/block/utils/CropGrowthHelper.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\world\\\\World\\:\\:getPotentialLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/block/utils/CropGrowthHelper.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\world\\\\World\\:\\:getPotentialLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/block/utils/CropGrowthHelper.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method addParticle\\(\\) on pocketmine\\\\world\\\\World\\|null\\.$#"
|
||||
count: 1
|
||||
@ -910,11 +925,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/world/World.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\world\\\\World\\:\\:getFullLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/world/World.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$x of method pocketmine\\\\world\\\\World\\:\\:getTileAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
@ -940,11 +950,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/world/World.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\world\\\\World\\:\\:getFullLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/world/World.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$y of method pocketmine\\\\world\\\\World\\:\\:getTileAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
@ -975,11 +980,6 @@ parameters:
|
||||
count: 1
|
||||
path: ../../../src/world/World.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\world\\\\World\\:\\:getFullLightAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: ../../../src/world/World.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$z of method pocketmine\\\\world\\\\World\\:\\:getTileAt\\(\\) expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
|
@ -37,7 +37,6 @@ use pocketmine\network\mcpe\protocol\serializer\NetworkNbtSerializer;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
use pocketmine\utils\Filesystem;
|
||||
use pocketmine\utils\Utils;
|
||||
use function array_filter;
|
||||
use function array_key_first;
|
||||
use function array_keys;
|
||||
use function array_map;
|
||||
@ -481,16 +480,9 @@ function generateBlockStateUpgradeSchema(array $upgradeTable) : BlockStateUpgrad
|
||||
throw new \RuntimeException("States with the same ID should be fully consistent");
|
||||
}
|
||||
}else{
|
||||
if(isset($newNameFound[$oldName])){
|
||||
//some of the states stayed under the same ID - we can process these as normal states
|
||||
$stateGroup = array_filter($blockStateMappings, fn(BlockStateMapping $m) => $m->new->getName() === $oldName);
|
||||
if(processStateGroup($oldName, $stateGroup, $result)){
|
||||
foreach(Utils::stringifyKeys($stateGroup) as $k => $mapping){
|
||||
unset($blockStateMappings[$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
//block mapped to multiple different new IDs; we can't guess these, so we just do a plain old remap
|
||||
//even if some of the states stay under the same ID, the compression techniques used by this function
|
||||
//implicitly rely on knowing the full set of old states and their new transformations
|
||||
$result->remappedStates[$oldName] = processRemappedStates($blockStateMappings);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user