Compare commits

...

660 Commits

Author SHA1 Message Date
decc188302 Release 5.6.1 2023-10-20 10:30:50 +01:00
8fa5c7cdab World: do not apply fake state properties from tile if the block doesn't expect this tile type
This was causing a variety of crashes due to incorrect tiles, presumably from PM3 worlds.
2023-10-20 10:28:46 +01:00
7dd3a70d2e Revert "World: discard tiles on load if they aren't the correct type or no tile is expected"
This reverts commit 8f804f6f34.

This change is too disruptive, since popular plugins like
ExtendedBlocks and ExtendedBlocksConverter relied on custom tiles.
Deleting them at this stage would prevent these plugins from working,
making it impossible to upgrade old data.

An alternative solution to this problem will need to be developed.
2023-10-20 10:16:49 +01:00
b3390458b4 Bump phpstan/phpstan from 1.10.38 to 1.10.39 (#6103)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.38 to 1.10.39.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.38...1.10.39)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-19 11:58:27 +01:00
b4d55e4384 Fixed dirt and grass block interactions when clicking on sides other than the top (#6071) 2023-10-18 10:40:01 +01:00
932116fa52 Server: re-added @see reference that somehow got deleted
this is useful when clicking through references in the call stack.
2023-10-18 10:23:02 +01:00
7b5c30bc2c WoodenDoor can be a fuel (#6101) 2023-10-17 22:10:08 +01:00
c14eb63f9b Wooden Button can be a fuel (#6099) 2023-10-17 16:30:35 +01:00
224a69b11a Sign can be a fuel (#6095) 2023-10-17 12:22:20 +01:00
15ba642258 Merge branch 'legacy/pm4' into stable 2023-10-16 21:28:48 +01:00
edea793a98 Downgrade PHPUnit to 10.3 until sebastianbergmann/phpunit#5539 is fixed 2023-10-16 21:25:53 +01:00
1da7e3586b Updated composer dependencies 2023-10-16 20:45:44 +01:00
7d200247f8 Cactus: do not update if only age changed
I'd prefer a smarter solution for this that automatically disables updates depending on which type of property was changed, but for now, this will significantly improve the performance of cactus farms.
The newly placed cactus block at the top cannot have updates disabled, though, since it needs to check its surroundings in case it grew into a space with a solid block next to it.

Thanks @KingOfTurkey38 for bringing this to light.
2023-10-13 12:45:11 +01:00
2d697c5f04 A random change that Composer 2.6 wanted to make 2023-10-09 18:27:20 +01:00
364f408eb1 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-10-09 18:22:54 +01:00
660e2b8173 Update build/php to pmmp/php-build-scripts@a34e48e7da 2023-10-09 18:22:28 +01:00
9facb98327 Bump phpunit/phpunit from 10.3.5 to 10.4.1 (#6082)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.3.5 to 10.4.1.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.4.1/ChangeLog-10.4.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.3.5...10.4.1)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 17:16:15 +01:00
7e42a03db3 Bump phpstan/phpstan from 1.10.37 to 1.10.38 (#6081)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.37 to 1.10.38.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.37...1.10.38)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 17:15:50 +01:00
94a17f59d2 fix(Entity): broadcastSound() not firing WorldSoundEvent (#6069) 2023-10-08 19:25:19 +01:00
ed4088755f Bump phpstan/phpstan from 1.10.35 to 1.10.37 (#6073)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.35 to 1.10.37.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.35...1.10.37)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-05 22:23:13 +01:00
ff89d4d055 Updated composer dependencies 2023-09-28 14:55:55 +01:00
8f804f6f34 World: discard tiles on load if they aren't the correct type or no tile is expected
in many instances, remnants of improperly removed blocks from PM3 have been causing problems, such as flower pot tiles where there are no flower pots.

this change might break some plugins which are using tiles for custom purposes, but this is a misuse that was never supported properly in the first place.
2023-09-27 14:57:06 +01:00
c3bca9e172 tools/generate-bedrock-data-from-packets: fixed interpreting item metadata as blockstates when the item ID could be interpreted as a block ID
this broke crafting recipes which accepted skulls as inputs, as well as nether wart and bed recipes.
2023-09-27 12:37:26 +01:00
c028bb9055 Bump docker/setup-buildx-action from 2 to 3 (#6049)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 14:50:57 +01:00
f151047b5e Bump docker/login-action from 2 to 3 (#6050)
Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 14:50:40 +01:00
77566db766 Bump docker/build-push-action from 4.1.1 to 5.0.0 (#6051)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4.1.1 to 5.0.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v4.1.1...v5.0.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 14:50:17 +01:00
dd2e6ea33f Bump shivammathur/setup-php from 2.25.5 to 2.26.0 (#6055)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.25.5 to 2.26.0.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.25.5...2.26.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-21 14:49:38 +01:00
d138a15a32 Merge branch 'legacy/pm4' into stable 2023-09-21 13:27:04 +01:00
7a2cfa92b6 Update composer dependencies 2023-09-21 13:23:09 +01:00
912fd3f5c6 PHPStan 1.10.35, plus workarounds 2023-09-21 13:22:14 +01:00
5eca90d478 5.6.1 is next 2023-09-20 19:00:51 +01:00
338bb3fe6d Release 5.6.0 2023-09-20 19:00:51 +01:00
f485f7fb46 Updated composer dependencies 2023-09-20 18:57:36 +01:00
63eba3eb53 Merge branch 'legacy/pm4' into stable 2023-09-20 18:40:58 +01:00
914eb62e94 4.24.1 is next 2023-09-20 18:40:07 +01:00
a85814d0c9 Release 4.24.0 2023-09-20 18:40:07 +01:00
eb2e472b01 Merge branch 'legacy/pm4' into stable 2023-09-20 18:36:41 +01:00
6553852d99 Updated for 1.20.30 release 2023-09-20 18:34:12 +01:00
540476365f Updated for 1.20.30 release 2023-09-20 18:14:59 +01:00
efafc2c6ca DeadBush: updated support requirements
since 1.20 they can now be placed on grass and mud.
2023-09-08 16:41:06 +01:00
d7f69c5e24 CaveVines: fixed incorrect support condition 2023-09-08 12:47:46 +01:00
0e87ee1e0e ÂHangingRoots: fixed incorrect support face 2023-09-08 12:22:00 +01:00
03ecc98a24 HangingRoots: fixed support conditions 2023-09-08 12:16:45 +01:00
a5aeabd836 RegistryTrait: fixed mishandling of self::$members
Since PHPStan doesn't warn about potential nulls on untyped properties, this flew under the radar.
2023-09-08 12:16:16 +01:00
fe94379a93 Fixed connection requirements for fences, glass, bars and walls
these connect to the back faces of stairs and to glass, for example.
2023-09-06 12:56:47 +01:00
79acc4fed4 5.5.1 is next 2023-09-06 12:13:26 +01:00
c8d357f4eb Release 5.5.0 2023-09-06 12:13:26 +01:00
ec1cd5967d Added private constructors for new internal classes 2023-09-06 12:12:11 +01:00
5a010e8213 Merge branch 'minor-next' into stable 2023-09-06 12:06:15 +01:00
73a44d50ee 5.4.5 is next 2023-09-06 11:53:04 +01:00
6aab07debd Release 5.4.4 2023-09-06 11:53:01 +01:00
b160b87e24 Server: stop discriminating against crashes caused by folder plugins
these are the de facto standard, which means that a lot of crashes aren't getting reported from servers with folder plugins.
2023-09-06 11:34:03 +01:00
690ee4c574 CrashDump: fixed empty elements in lastError trace
as shown by #6010
2023-09-06 11:24:08 +01:00
a0c7587b68 Update composer dependencies 2023-09-06 11:09:28 +01:00
be4e091d40 Update draft release notice 2023-09-06 11:03:15 +01:00
857c2edc2c Server: update obsoletion notice with new announcement and cutoff date 2023-09-06 10:58:41 +01:00
b1ab69ac6c Updated build/php submodule to pmmp/PHP-Binaries@3331f8c0d5 2023-09-06 10:51:22 +01:00
e95a920fb8 Update composer dependencies 2023-09-06 10:49:54 +01:00
67f399b238 Bump phpstan/phpstan-phpunit from 1.3.13 to 1.3.14 (#6021)
Bumps [phpstan/phpstan-phpunit](https://github.com/phpstan/phpstan-phpunit) from 1.3.13 to 1.3.14.
- [Release notes](https://github.com/phpstan/phpstan-phpunit/releases)
- [Commits](https://github.com/phpstan/phpstan-phpunit/compare/1.3.13...1.3.14)

---
updated-dependencies:
- dependency-name: phpstan/phpstan-phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-06 10:24:41 +01:00
a7c806d549 Bump phpunit/phpunit from 10.3.2 to 10.3.3 (#6033)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.3.2 to 10.3.3.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.3.3/ChangeLog-10.3.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.3.2...10.3.3)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-06 10:24:23 +01:00
0920c76a35 Bump build/php from 8884039 to 3331f8c (#6031)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `8884039` to `3331f8c`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](8884039bee...3331f8c0d5)

---
updated-dependencies:
- dependency-name: build/php
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-06 08:37:05 +01:00
a91ca999fe Bump actions/checkout from 3 to 4 (#6032)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-06 08:32:33 +01:00
ce04478395 Fix SmithingTableInventory size (#6035)
Since 1.20 SmithingTable has a new Template slot, size is now 3

Fix debug error from InventoryManager
2023-09-06 08:15:27 +01:00
28ce7ac5fd Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-09-04 18:10:41 +01:00
540f088eda tools/generate-bedrock-data-from-packets: make duplicate reporting less spammy 2023-09-01 20:51:45 +01:00
19e3d339f6 InGamePacketHandler: subtract from raw position before rounding it (#6022)
This allows better compensation for floating point errors introduced by the subtraction of the 1.62 height offset.

For example, if the player is at y=7 exactly, their Y coordinate will be reported as 8.62, which, because of floating point errors, will be something like `8.619999999`. Subtracting `1.62` from this (really something like `1.62000000000005...`) leads to the calculated Y coordinate being slightly below 7.

Rounding after subtracting this offset allows this to be rounded to 7 sharp. Similar errors appear in various other coordinates.
2023-08-29 11:43:21 +01:00
9fdb6ba5aa Mark some new things as internal 2023-08-25 14:02:49 +01:00
4a0a538278 CS 2023-08-25 13:27:40 +01:00
2912e7ca29 ... 2023-08-25 13:27:11 +01:00
31d8cc1cb5 Generate and use constants for pocketmine.yml constant names
a couple of usages of properties that no longer exist couldn't be migrated.
in addition, this revealed a couple of dead properties in the default file.

this is not an ideal solution (I'd much rather model the configs using classes and map them) but in the absence of a good and reliable library to do that, this is the next best thing.
2023-08-25 13:23:38 +01:00
506d8d1064 CS 2023-08-25 12:49:56 +01:00
d1a7c1d453 Constify server.properties references 2023-08-25 12:49:39 +01:00
b56f1b679e Deduplicate a bunch of repeated type ID map code 2023-08-25 12:30:54 +01:00
1a18e32011 Bump ncipollo/release-action from 1.12.0 to 1.13.0 (#6019)
Bumps [ncipollo/release-action](https://github.com/ncipollo/release-action) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/ncipollo/release-action/releases)
- [Commits](https://github.com/ncipollo/release-action/compare/v1.12.0...v1.13.0)

---
updated-dependencies:
- dependency-name: ncipollo/release-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-25 09:43:31 +01:00
09c9dfb576 Bump build/php from d75f83e to 8884039 (#6018)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `d75f83e` to `8884039`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](d75f83e7ef...8884039bee)

---
updated-dependencies:
- dependency-name: build/php
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-25 09:43:05 +01:00
f2b710c083 Bump build/php from a053f65 to d75f83e (#6017)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `a053f65` to `d75f83e`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](a053f65e18...d75f83e7ef)

---
updated-dependencies:
- dependency-name: build/php
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-24 08:31:31 +01:00
c7a311c17a COPILOT 2023-08-23 17:14:56 +01:00
ce53a221a5 5.5.0-BETA2 is next 2023-08-23 17:09:34 +01:00
c8100480ac Release 5.5.0-BETA1 2023-08-23 17:09:34 +01:00
8814d06dfd Fix CS 2023-08-23 17:00:18 +01:00
923f7561fb Enchantment: added @see tags to @deprecated methods 2023-08-23 16:53:09 +01:00
f4e1c31dcf Change some weird constant names 2023-08-23 16:52:47 +01:00
998fcf20db Remove useless Cancellable from PressurePlateUpdateEvent 2023-08-23 16:52:22 +01:00
1504fdca24 Use 'enchanting' terminology
'enchant' just didn't feel right, being a verb.
All these things pertain to the act of enchanting.

This is now also consistent with CraftingTransaction etc. The ship already sailed on EnchantInventory, which will have to be renamed at a later datte. However, that was already inconsistent with 'enchanting table', so that's the odd one out here.
2023-08-23 16:14:17 +01:00
bf668c0f6c Rename EnchantHelper related stuff
Perhaps this and EnchantOption should be called EnchantingHelper and EnchantingOption respectively. The terminology used is rather inconsistent, but 'enchantment' definitely isn't the right word here.
2023-08-23 16:07:02 +01:00
d942748203 Move enchanting seed generation to EnchantmentHelper 2023-08-23 15:52:49 +01:00
29fdc8b08d Private constructor for EnchantmentHelper 2023-08-23 15:49:31 +01:00
20a41b00ba StringToTParser: added registerAlias() 2023-08-23 15:24:29 +01:00
df96e023dc Require pocketmine/nbt 1.0.0 2023-08-23 14:42:50 +01:00
f4d5605de1 Use hasHandlers() on more warm-hot events 2023-08-23 14:35:53 +01:00
d03e4d17ec Use hasHandlers() for events in player movement processing pathway
this should offer a minor performance improvement.
2023-08-23 14:26:17 +01:00
4cc858829f 5.4.4 is next 2023-08-21 18:31:45 +01:00
e852a43821 Release 5.4.3 2023-08-21 18:31:45 +01:00
05f40b1315 Merge branch 'legacy/pm4' into stable 2023-08-21 18:27:18 +01:00
7aaef8cb89 4.23.7 is next 2023-08-21 18:26:50 +01:00
9d4c37fc3a Release 4.23.6 2023-08-21 18:26:47 +01:00
cd6abbe0bb BaseSign: remove redundant condition 2023-08-21 16:30:16 +01:00
22778583cf Sign: implement waxing using honeycomb 2023-08-21 16:28:17 +01:00
d44e0e87d0 BaseSign: implement sign editing
this was originally submitted by #6000, but considering the overcomplicated PR and the triviality of the feature, I figured it would be quicker to do it myself instead of having a bunch of back-and-forth bikeshedding over it.
2023-08-21 16:14:43 +01:00
47b448965d Merge branch 'stable' into minor-next 2023-08-21 16:08:27 +01:00
cfa2df82eb Merge branch 'legacy/pm4' into stable 2023-08-21 16:07:56 +01:00
7f78ec0a32 Include PHP binary URLs in GitHub releases and build info 2023-08-21 16:05:59 +01:00
8572311bf4 Remove dead PHPStan stub
closes #6003
2023-08-21 14:57:26 +01:00
18ca3a37d9 CrashDump: fixed crashdump generation failure on fatal error
closes #6007
2023-08-21 14:51:54 +01:00
b2414b4c29 EnchantTransaction: cleanup XP cost checking logic 2023-08-18 12:33:07 +01:00
b3c740081e Merge branch 'stable' into minor-next 2023-08-18 12:28:45 +01:00
4b41fca991 Merge branch 'legacy/pm4' into stable 2023-08-18 12:28:29 +01:00
9f09acc079 Workaround for slot IDs not changing client side when old item == new item
this is a really dumb bug and seems similar to the armor bug I fixed a while ago.

fixes #5987

it's unlikely that #5727 will be solved by this, but one can hope...
2023-08-18 12:27:27 +01:00
beaca8bb6d EnchantTransaction: fixed XP level costs when minimum level is less than the XP cost
this can happen and happens in vanilla too. In these cases, as much of the XP cost as possible is deducted.
2023-08-16 14:51:47 +01:00
e323c5dd76 Implement pressure plate activation logic and events (#5991)
closes #5936

This implements all of the basic activation logic for pressure plates.
It also introduces a PressurePlateUpdateEvent, which is called in pulses when entities are standing on top of the plate and when it deactivates. Deactivation can be detected by checking if the list of activating entities is empty.

---------

Co-authored-by: Javier León <58715544+JavierLeon9966@users.noreply.github.com>
2023-08-16 13:00:23 +01:00
b65b7a7f74 Bump tests/plugins/DevTools from 83f0db3 to 411fd5b (#5998)
Bumps [tests/plugins/DevTools](https://github.com/pmmp/DevTools) from `83f0db3` to `411fd5b`.
- [Release notes](https://github.com/pmmp/DevTools/releases)
- [Commits](83f0db3f9e...411fd5bdc0)

---
updated-dependencies:
- dependency-name: tests/plugins/DevTools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-16 09:38:16 +01:00
f516c3c502 EnchantCommand: ensure that books are turned into enchanted book items 2023-08-15 19:10:48 +01:00
5afbb9d807 Allow enchanted books to be enchanted
if an enchanted book is obtained via /give without enchantments, it should be able to receive enchantments in an enchanting table, exactly the same as regular books.
2023-08-15 19:10:03 +01:00
b330cbe8e2 Merge remote-tracking branch 'origin/stable' into minor-next 2023-08-15 17:41:41 +01:00
39867b97c5 Implement enchanting using enchanting tables (#5953)
Co-authored-by: Dylan K. Taylor <dktapps@pmmp.io>
2023-08-15 17:28:26 +01:00
4c25d38b44 Bump phpunit/phpunit from 10.3.1 to 10.3.2 (#5995)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.3.1 to 10.3.2.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.3.2/ChangeLog-10.3.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.3.1...10.3.2)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-15 12:05:23 +01:00
983aa79a0b Bump build/php from ed0bc4d to a053f65 (#5993)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `ed0bc4d` to `a053f65`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](ed0bc4d2af...a053f65e18)

---
updated-dependencies:
- dependency-name: build/php
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-15 09:30:51 +01:00
af9ae445fc Fix cake drops (#5985)
closes #5984
2023-08-10 17:42:32 +01:00
91d5a3ddfe PotionCauldron: fixed setPotionItem() not validating the given item
we should probably remove this API and have enums for potion container and type tbh... this API was a mistake
2023-08-10 16:06:41 +01:00
e48b5b2ec0 GeneratorManager: allow aliasing existing generators 2023-08-10 13:07:03 +01:00
f03e708f64 Fix chorus not working if the destination would be below y=0 (#5979) 2023-08-10 09:42:58 +01:00
37f2dafae1 PluginBase: make saveResource() use copy() instead of overengineered streams garbage 2023-08-09 16:16:11 +01:00
7826e0a11e Merge branch 'stable' into minor-next 2023-08-09 16:14:05 +01:00
97700636c6 PluginBase: added getResourceFolder() and getResourcePath(), deprecate getResource() (#5961)
This is a step towards #5958.

While it's not actually necessary to add these functions (since people could just use getFile() . "/resources/whatever.yml" instead), this helps preserve the convention of using the `resources` folder, which might be helpful for external tools.

As an example:
stream_get_contents($this->getResource("lang/eng.ini"));
(which is actually incorrect, since it leaks a resource)
can now be replaced by
file_get_contents($this->getResourcePath("lang/eng.ini"));
quite trivially.

getResourceFolder() can be used with scandir() to enumerate resources instead of using getResources(), although getResources() still provides utility in the relativized resource paths.
2023-08-09 16:09:16 +01:00
447f061566 Use Event::hasHandlers() for a few more hot events 2023-08-09 15:46:20 +01:00
b86b389fc5 changelog: fix link
[ci skip]
this is not technically wrong, but it's inconsistent with other changelogs
2023-08-09 15:33:02 +01:00
e27121a437 5.4.3 is next 2023-08-09 14:04:57 +01:00
2d5c9e64ce Release 5.4.2 2023-08-09 14:04:57 +01:00
78f5fbddf3 Merge branch 'legacy/pm4' into stable 2023-08-09 13:58:14 +01:00
aa3f4f2545 4.23.6 is next 2023-08-09 13:56:19 +01:00
f7279b6672 Release 4.23.5 2023-08-09 13:56:19 +01:00
2711ab4f00 Update composer dependencies 2023-08-09 13:49:19 +01:00
b4c5f5d58d PluginBase: fixed resource leak
all this time we've been harping at plugin devs to fix their own leaks, and here's one right under our noses that no one spotted for 10 years ...

this leak is rather common, since it will occur whenever a plugin attempts to save a resource which already exists in the data folder.

This bug was introduced in 2014 by commit 6328834681.
2023-08-09 13:28:05 +01:00
a5d8ef7a6c Add FarmlandHydrationChangeEvent (#5916) 2023-08-09 12:33:25 +01:00
59c88fe7f7 Added WorldDifficultyChangeEvent 2023-08-09 12:22:03 +01:00
735d9a5bf4 CandleTrait: allow candle to be lit by fire charges 2023-08-09 12:04:02 +01:00
f4a06605b1 Cake: only accept candle when no slices have been taken
otherwise, cake slices can be regenerated using candle
2023-08-09 11:42:08 +01:00
77dfbc4e23 Implemented pink petals (#5940) 2023-08-09 11:33:33 +01:00
662f2495e9 5.4.2 is next 2023-08-08 18:41:09 +01:00
b8a4ca45e4 Release 5.4.1 2023-08-08 18:41:06 +01:00
ebcd6a0bb2 CraftItemEvent: fixed inputs and outputs not being cloned 2023-08-08 18:29:49 +01:00
baefbce863 Merge branch 'stable' into minor-next 2023-08-08 18:27:50 +01:00
b45b4b5edf Update translations 2023-08-08 18:27:07 +01:00
9f14901820 Merge branch 'stable' into minor-next 2023-08-08 17:48:12 +01:00
dd79d4c463 Updated build/php submodule to pmmp/PHP-Binaries@ed0bc4d2af 2023-08-08 17:44:13 +01:00
9c1ab943bc Bump ext-pmmpthread min version to 6.0.7 2023-08-08 17:43:31 +01:00
2c74124e2e Update composer dependencies 2023-08-08 17:43:01 +01:00
514fc1ebb5 Bump phpunit/phpunit from 10.2.7 to 10.3.1 (#5965)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.2.7 to 10.3.1.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.3.1/ChangeLog-10.3.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.2.7...10.3.1)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-08 17:33:16 +01:00
c1638ffaab Ban foreach by-reference at the PHPStan level 2023-08-08 17:08:13 +01:00
710177ceb5 CS
this mistake actually hasn't happened for a while
2023-08-08 15:10:31 +01:00
2559d1719f All pocketmine\thread\Thread now log uncaught exceptions and fatal errors by default 2023-08-08 14:56:54 +01:00
2e58387a43 Fixed thread error capture fail in shutdown function
the shutdown handler currently isn't called until join(), which sets isKilled to true and stops the error information from being recorded.
2023-08-08 14:55:53 +01:00
515f8eae4c ÂResourcePackManager: allow setting force_resources from a plugin 2023-08-07 17:05:45 +01:00
35a28300f6 Podzol should be affected by silk touch (#5969) 2023-08-07 11:47:29 +01:00
1cf508abdb World: use Facing::OFFSET in getHighestAdjacentLight() 2023-08-03 16:51:09 +01:00
6ac45526f9 Use new features in pocketmine/math 1.0.0 2023-08-03 16:46:16 +01:00
c91c8c2f9e Improving performance of small moving entities (e.g. dropped items) (#5954)
* World: cache block AABBs directly in the world
this removes some indirection when fetching the AABBs, and also allows the AABB cache to live longer than the block cache.

In local testing this showed a 10-20% performance improvement, but it was difficult to properly measure.

* World: eliminate padding block checks in getCollisionBoxes()
this substantially improves the function's performance for small entities.

The padding of 1 block in each direction was previously necessary to account for blocks like fences, which might have an AABB larger than the cell containing them. However, by tracking this information in the collisionBoxCache directly, we can avoid the need to check this at the expense of slightly more complex code. This reduces the number of blocks checked for a moving item entity from 27-64 all the way down to 1-8, which is a major improvement.

Locally, this change allowed me to simulate 2100 item entities without lag, compared with 1500 on the previous commit.
2023-08-03 14:51:51 +01:00
81941ae9e5 Bump phpunit/phpunit from 10.2.6 to 10.2.7 (#5957)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.2.6 to 10.2.7.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.2.7/ChangeLog-10.2.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.2.6...10.2.7)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-02 18:05:30 +01:00
1a2c10e844 World: Fixed getSafeSpawn() not accepting seed positions below y=1 (#5955)
this should have been changed during the introduction of y=-64 minimum world height, but it got missed.
2023-08-02 18:05:16 +01:00
d88c3d8ced Fixed coral block killing itself when calling getDropsForCompatibleTool()
this might be called by plugins without actually breaking the block, in which case the block will glitch.
2023-08-02 13:43:36 +01:00
82f87cc2da Reduce repeated block-change-event related code
the new helper code reveals even more repetition, but this is at least consistent now.
2023-08-02 13:40:12 +01:00
bb0e648276 Fixed BlockDeathEvent usages showing an oldState which is already dead 2023-08-02 13:36:54 +01:00
6000bcccdd Merge pull request #5707 from pmmp/hot-events-optimisation
Avoid unnecessary event-related work in hot paths when the events have no registered handlers
2023-08-01 18:19:10 +01:00
0b86fafafb Hot path optimisation for DataPacketSendEvent 2023-08-01 17:41:53 +01:00
2608637210 HandlerListManager: track RegisteredListenerCache directly
This change improves the performance of calling an event with 0 handlers by about 10% with no other changes.

Since we have to access the list eventually anyway, we can cut out some unnecessary work by returning the handlers from the cache directly, instead of fetching the HandlerList for no reason.

This also improves the performance of Event::hasHandlers() by about 40%, which is pretty significant (120 ns -> 80 ns).
2023-08-01 17:37:49 +01:00
442d65143d Merge branch 'minor-next' into hot-events-optimisation 2023-08-01 17:01:52 +01:00
53de55dcde 5.4.1 is next 2023-08-01 12:46:56 +01:00
01664d2e81 Release 5.4.0 2023-08-01 12:46:53 +01:00
0a90a5928a Added TallGrassTrait, remove weirdly specific logic from FortuneDropHelper
this needs to be dealt with before release otherwise we'll be stuck with FortuneDropHelper::grass()
this is the obvious solution and should have been done some time ago - stuff like flammability was already a problem for double tall grass anyway
2023-08-01 12:33:36 +01:00
46f24b165a Rename PlayerMissedSwingEvent -> PlayerMissSwingEvent
all the other events are present tense, so it doesn't make sense for this one to be past tense.
2023-08-01 12:21:39 +01:00
6f09286fed Merge branch 'minor-next' into stable 2023-08-01 11:57:02 +01:00
774eb3e72b 5.3.5 is next 2023-08-01 11:16:51 +01:00
cd8219d9fd Release 5.3.4 2023-08-01 11:16:50 +01:00
52ce3444d8 Merge branch 'legacy/pm4' into stable 2023-08-01 11:13:31 +01:00
e9e5923639 4.23.5 is next 2023-08-01 11:12:52 +01:00
49a9da147b Release 4.23.4 2023-08-01 11:12:41 +01:00
4c0df5ee4e Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-07-31 11:30:18 +01:00
4c737b2ee3 Merge branch 'legacy/pm4' into stable 2023-07-31 11:29:58 +01:00
eb53b795d5 ItemEntity: fixed O(n^2) performance issue when many of the same unstackable item are in the same place
this produced a 40% performance improvement in a simulation with 800 item entities.

If the items were all different, then this would still be a problem. However, many of the same unstackable items occupying the same space is a problem for SkyBlock farms, so this should improve performance for SkyBlock quite a bit.
2023-07-31 11:29:12 +01:00
befd3637f6 Bump shivammathur/setup-php from 2.25.4 to 2.25.5 (#5951)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.25.4 to 2.25.5.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.25.4...2.25.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-31 11:13:51 +01:00
9b2a7b43c2 ItemEntity: fixed O(n^2) performance issue when many of the same unstackable item are in the same place
this produced a 40% performance improvement in a simulation with 800 item entities.

If the items were all different, then this would still be a problem. However, many of the same unstackable items occupying the same space is a problem for SkyBlock farms, so this should improve performance for SkyBlock quite a bit.
2023-07-28 16:06:29 +01:00
5ec3f4655f EntityDamageByEntityEvent: added APIs to get and set vertical knockback limits
this was requested and PR'd as far back as 2020 (see #3782).
Since no issue was filed about this, it became forgotten until #5946.
However, #5946 overcomplicates the solution to the problem, and breaks BC without an obvious reason.
2023-07-28 12:52:15 +01:00
c972e65741 EntityDamageByEntityEvent: document methods 2023-07-28 12:41:27 +01:00
a45763328b Added constants for default knockback force and vertical limit 2023-07-28 12:36:46 +01:00
82a5ea9ed3 Allow thread errors and their traces to be properly recorded in crashdumps (#5910)
until now, any thread crash would show as a generic crash since we aren't able to get the trace from the crashed thread directly. This uses some dirty tricks to export a partially serialized stack trace to the main thread, where it can be written into a crashdump.
This enables us to see proper crash information for async tasks in the crash archive (finally!!!) as well as being able to capture RakLib errors properly.
2023-07-26 16:26:03 +01:00
bbdcab7277 Player: Added animation to missSwing() (#5942) 2023-07-26 10:04:36 +01:00
6086ef667c Added handling for attack-air action (#5912) 2023-07-25 14:50:28 +01:00
486d4099df 5.3.4 is next 2023-07-24 17:29:59 +01:00
a1f34a460b Release 5.3.3 2023-07-24 17:29:56 +01:00
5ff03c81f8 Merge branch 'legacy/pm4' into stable 2023-07-24 17:00:13 +01:00
1c611a03e6 4.23.4 is next 2023-07-24 16:59:48 +01:00
948875b025 Release 4.23.3 2023-07-24 16:59:45 +01:00
fb43f59458 Merge branch 'stable' into minor-next 2023-07-24 16:45:49 +01:00
16dfd27935 Merge branch 'legacy/pm4' into stable 2023-07-24 16:45:24 +01:00
2a4909d328 Fixed missing handling for some ContainerUIIds
SMITHING_TABLE_TEMPLATE is new in 1.20
HORSE_EQUIP was always present, but somehow got overlooked when building up that big ugly switch table
2023-07-24 16:44:01 +01:00
b078e01b65 JwtUtils: handle DER <-> raw signature conversion in-house, drop fgrosse/phpasn1 dependency
normally I would hesitate to reinvent the wheel, but we only need a tiny subset of the ASN.1 spec which is trivial to implement by itself.
I'd rather this than depend on another library that could introduce security vulnerabilities (I'm looking at you, jsonmapper).

closes #5935
2023-07-24 13:36:12 +01:00
4eb9dacd3c Remove unnecessary HorizontalFacingTrait (#5930)
FacingOppositePlacingPlayerTrait already includes HorizontalFacingTrait, so we don't need to include it twice.
2023-07-24 12:16:56 +01:00
43770313ba Update symfony/filesystem to 6.3.x 2023-07-24 12:07:32 +01:00
3afe3b7f44 Merge branch 'stable' into minor-next 2023-07-24 12:02:24 +01:00
fd23281183 Merge branch 'legacy/pm4' into stable 2023-07-24 12:00:29 +01:00
70dd8732e2 Update build/php to pmmp/PHP-Binaries@46604f2f6a 2023-07-24 11:59:11 +01:00
cdf72563f4 Update composer dependencies 2023-07-24 11:58:50 +01:00
2779f92828 Bell: clean up code 2023-07-21 15:29:33 +01:00
5899f2fc1d Block: introduce new methods to reduce support type boilerplate checks
this switches from a 'can be supported by' concept to a 'can stay at this position' paradigm, which requires way less boilerplate code.

there may be further improvements we can make from here, such as adding traits, but this is a good first step.
2023-07-21 15:02:25 +01:00
9ef835c82d Merge remote-tracking branch 'origin/legacy/pm4' into stable 2023-07-21 11:07:32 +01:00
d65d8c3356 Fix typo in documentation of ChunkSelector:selectChunks() (#5924) 2023-07-21 10:34:34 +01:00
9b43ddecbd Drop usages of Process:kill() with subprocesses parameter
we don't need this any more with console reader improvements, and this was not working correctly anyway.

closes #5234
2023-07-20 17:10:39 +01:00
4bdd6410db Fire: fixed support requirements
closes #5599
2023-07-20 17:00:32 +01:00
6ea7fd7d6b ShulkerBox: do not offer support for other blocks 2023-07-20 16:36:25 +01:00
5e7f18cbcf StandardEntityEventBroadcaster: suppress client-side emote messages
if users want these, they can broadcast them themselves using Server::broadcastMessage(), which will also record the message in the server log like chat

closes #5669
2023-07-20 16:20:34 +01:00
4517948297 FrostedIce: Remove non-Bedrock melting behaviour (#5486) 2023-07-19 17:12:05 +01:00
777a901932 Bump shivammathur/setup-php from 2.25.2 to 2.25.4 (#5829)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.25.2 to 2.25.4.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.25.2...2.25.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-19 16:37:33 +01:00
24d979bd08 Fixed /kill not properly killing the player under certain conditions, closes #4680 (#5919)
This occurs if the player had very high levels of Health Boost or other weird modifications.

It doesn't really make sense to apply damage modifiers to suicide anyway.

Really I'm doubtful that suicide should even be considered a damage type (perhaps we should add an EntitySuicideEvent), but that's a discussion for another time.
2023-07-19 16:33:16 +01:00
86810c5e1c LevelDB: clearer error message 2023-07-19 16:31:10 +01:00
b33a9690e9 LevelDB: simplify condition 2023-07-19 16:30:13 +01:00
1b9c282194 LevelDB: tolerate incorrect number of biome palettes, as long as there are enough for each real subchunk
modern versions save 24 exactly, but previous versions saved more. We don't use the excess, so it's not a problem if they are missing, but this is nonetheless non-compliant with vanilla.
2023-07-19 16:29:14 +01:00
82b75e0ccb LevelDB: Remove happy debug message 2023-07-19 15:21:47 +01:00
6c59912ed5 LevelDB: workaround 0 bpb palettes with a length prefix
this was caused by a plugin overriding the world provider.

related:
-  https://github.com/pmmp/PocketMine-MP/issues/5911
-  https://github.com/Refaltor77/CustomItemAPI/issues/68

fixes #5911
2023-07-19 15:19:33 +01:00
3c34841dfc CS 2023-07-19 14:00:35 +01:00
914dd90b3d Use first-class closures in more places 2023-07-19 13:56:48 +01:00
537721fe7d Replace Closure::fromCallable() usages with first-class callables
PHP 8.1 <3
2023-07-19 13:34:42 +01:00
fba51e3bf9 Merge branch 'stable' into minor-next 2023-07-19 13:22:07 +01:00
763241b11f Fixed burning animations for fireproof entities
creative players are not technically fireproof; they just don't take any damage from fire
2023-07-19 12:32:00 +01:00
8414c78969 Fixed netherite items burning in lava 2023-07-19 11:49:52 +01:00
4637aae621 Living: do not apply noDamageTicks to suicide damage
suicide damage is a voluntary damage source, which noDamageTicks is intended to prevent getting damaged while the player gets their bearings after (re)spawning.
2023-07-19 11:43:09 +01:00
6fbc133e5d Merge branch 'stable' into minor-next 2023-07-18 22:22:37 +01:00
f38aee1fc5 5.3.3 is next 2023-07-18 22:18:39 +01:00
69abd5eb53 Release 5.3.2 2023-07-18 22:18:39 +01:00
f6ee7ddc9e Merge branch 'legacy/pm4' into stable 2023-07-18 22:15:23 +01:00
cff4a8d2bc 4.23.3 is next 2023-07-18 22:14:24 +01:00
20b7e8d702 Release 4.23.2 2023-07-18 22:14:23 +01:00
c6110be051 Update BedrockProtocol dependency 2023-07-18 22:12:33 +01:00
c053742f5d Living: avoid updates of non-armor slots and armor slots which took no damage
this was also updating empty slots ...
2023-07-18 13:04:11 +01:00
0051b34797 Living: fixed turtle helmet being non-removable and spamming inventory updates
closes #5786
2023-07-18 12:58:07 +01:00
a74ab756bd AsyncTask: strip out task cancellation functionality
closes #5854

Cancelling task runs doesn't make any sense.

- It breaks sequential task execution - later tasks might depend on state from earlier tasks
- It doesn't actually cancel the task - at best, it prevents it from running, but cannot interrupt it (though interrupting a task does not make sense either)

We don't use this "feature" in the core anymore since 22b5e5db5e, as this was causing unexpected behaviour for plugins anyway, along with the occasional shutdown crash due to inconsistent worker states.
2023-07-18 12:45:30 +01:00
90520c8962 Merge branch 'minor-next' of github.com:pmmp/PocketMine-MP into minor-next 2023-07-18 12:39:52 +01:00
2e9a4f2be2 Merge branch 'trees' into minor-next 2023-07-18 12:39:41 +01:00
e23806d417 Stem: fixed supporting block check issue (#5907)
This bug was introduced in dca752c72f
2023-07-18 12:31:20 +01:00
30db658d70 Bump phpunit/phpunit from 10.2.5 to 10.2.6 (#5909)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.2.5 to 10.2.6.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.2.6/ChangeLog-10.2.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.2.5...10.2.6)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-18 11:34:13 +01:00
83d11c7429 Implemented Big & Small dripleaf (#5835) 2023-07-17 16:30:52 +01:00
4c6b82f30a Merge remote-tracking branch 'origin/stable' into minor-next 2023-07-17 16:13:16 +01:00
fb6a7d279f Implement fortune enchantment (#5757) 2023-07-17 11:13:45 +01:00
0c1bfb058a Bump phpunit/phpunit from 10.2.3 to 10.2.5 (#5898)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.2.3 to 10.2.5.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.2.5/ChangeLog-10.2.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.2.3...10.2.5)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-14 17:45:36 +01:00
45d1ce9bb8 Don't mention enchantments in generic StringToTParser doc-comment (#5894) 2023-07-14 17:42:19 +01:00
8c8794ec71 Allow use ConsumingItemAnimation with Living entities (#5897) 2023-07-14 17:41:46 +01:00
b399eda21e Merge branch 'stable' into minor-next 2023-07-14 13:27:50 +01:00
f7c08dedee 5.3.2 is next 2023-07-14 13:08:58 +01:00
250d18e41b Release 5.3.1 2023-07-14 13:08:57 +01:00
86bd6777a3 4.23.2 is next 2023-07-14 13:06:26 +01:00
935df62006 Release 4.23.1 2023-07-14 13:06:26 +01:00
489a7ba365 Merge branch 'legacy/pm4' into stable 2023-07-14 13:03:14 +01:00
2709dd359c ProcessLoginTask: fixed backport errors 2023-07-14 12:37:50 +01:00
4e646d19a4 Harden login EC key validation 2023-07-14 11:55:47 +01:00
2a11762e61 Update JsonMapper dependency 2023-07-14 11:54:05 +01:00
dca752c72f Stem: implement facing property
fixes #5858

technically speaking, the sideways states for non-fully-grown stems shouldn't exist, but they do in Bedrock, and changing this code to split non-fully-grown stems from fully grown ones would likely require BC breaks.
This was the minimum necessary to achieve the desired functionality.
2023-07-13 14:50:26 +01:00
259cc305df Implement 1.20.10 short sneaking (#5892) 2023-07-13 13:36:53 +01:00
ace
7132ac0ad3 Implemented strong slowness potion (#5888) 2023-07-13 13:22:01 +01:00
0d8a06732a Merge branch 'stable' into minor-next 2023-07-13 12:59:53 +01:00
d2f4ba74c6 Updated build/php submodule to pmmp/PHP-Binaries@e0c918d137 2023-07-13 12:59:43 +01:00
d4716ef457 5.3.1 is next 2023-07-12 14:08:08 +01:00
d630b3af7b Release 5.3.0 2023-07-12 14:07:58 +01:00
c2bb51cb37 Merge branch 'legacy/pm4' into stable 2023-07-12 13:45:37 +01:00
7e0b5cf73d 4.23.1 is next 2023-07-12 13:44:16 +01:00
e903da8998 Release 4.23.0 2023-07-12 13:44:16 +01:00
b7210755a7 1.20.10 2023-07-12 13:39:39 +01:00
f2193d1ba7 1.20.10 2023-07-12 13:23:47 +01:00
4daacb2ab7 Merge branch 'legacy/pm4' into stable 2023-07-12 12:11:36 +01:00
f7977c9668 Update build/php submodule to pmmp/PHP-Binaries@16378ffcc3 2023-07-12 12:10:09 +01:00
93d3f439bf 5.2.2 is next 2023-07-11 16:04:43 +01:00
200e5f940c Release 5.2.1 2023-07-11 16:04:42 +01:00
9365ffa7fa Merge branch 'legacy/pm4' into stable 2023-07-11 16:02:06 +01:00
cfd9950b02 4.22.4 is next 2023-07-11 16:01:42 +01:00
8ebcdb452d Release 4.22.3 2023-07-11 16:01:38 +01:00
ef85fbffe1 Merge branch 'legacy/pm4' into stable 2023-07-11 15:10:55 +01:00
aacc00a911 update-updater-api: do not allow multiple jobs to run simultaneously
this would result in git conflicts if multiple releases are made at the same time

closes #5814
2023-07-11 15:10:35 +01:00
0c250a2ef0 InGamePacketHandler: fixed inconsistent handling of invalid data in BlockActorDataPacket 2023-07-11 12:53:29 +01:00
c01d2dc718 CreativeInventory per Player (#5694) 2023-07-06 11:08:13 +01:00
8f217ca6e0 Fixed borked changelog links 2023-07-04 16:12:01 +01:00
f0d5647aa2 5.2.1 is next 2023-07-04 15:58:09 +01:00
e6de9a70a2 Release 5.2.0 2023-07-04 15:58:09 +01:00
a34514c6a1 RuntimeDataDescriber: document that this is a sealed interface 2023-07-04 15:56:03 +01:00
6a80b210d4 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-07-04 14:44:00 +01:00
02ffb04b92 Merge branch 'minor-next' into stable 2023-07-04 14:43:23 +01:00
6cbb03bf9b README: change title of discussion section
[ci skip]

I've always hated the way the / looks here
2023-07-03 18:18:30 +01:00
3abd592b1f Update to pmmp/BedrockBlockUpgradeSchema@3.0.0 2023-07-03 18:07:51 +01:00
644b417d2c BlockStateData: added auxiliary toVanillaNbt() helper method
toNbt() adds PM version metadata, which might not always be desired.
2023-07-03 14:05:17 +01:00
588a754f1c Merge branch 'legacy/pm4' into stable 2023-07-01 13:33:59 +01:00
70dd9c7371 AsyncTask: fixed reentrancy bug tested by f8e6f036af 2023-07-01 13:27:32 +01:00
f8e6f036af AsyncPoolTest: added failing test case for AsyncTask::__destruct() reentrancy bug 2023-07-01 13:24:50 +01:00
5d51ffdfe3 Merge branch 'minor-next' into trees 2023-07-01 12:25:44 +01:00
a2a7006878 Merge branch 'stable' into minor-next 2023-07-01 12:25:11 +01:00
b78c18ad2d changelog: fix header size :(
[ci skip]
2023-07-01 12:23:19 +01:00
41281db6a5 5.1.4 is next 2023-07-01 12:18:13 +01:00
2278275505 Release 5.1.3 2023-07-01 12:18:10 +01:00
53a6d8451b Merge branch 'legacy/pm4' into stable 2023-07-01 12:05:42 +01:00
bbabccfc89 4.22.3 is next 2023-07-01 12:04:59 +01:00
1698eac6dc Release 4.22.2 2023-07-01 12:04:59 +01:00
83378d9403 Merge branch 'legacy/pm4' into stable 2023-07-01 11:57:59 +01:00
321972b87b Composer: do not allow automatic minor dependency updates
manual intervention should always be used here, since we need to present a consistent API to plugins.
2023-07-01 11:57:13 +01:00
24b74a96eb Merge branch 'legacy/pm4' into stable 2023-07-01 11:52:42 +01:00
e61796b146 Composer: do not allow automatic minor dependency updates
manual intervention should always be used here, since we need to present a consistent API to plugins.
2023-07-01 11:49:44 +01:00
c86c9b3ead Update Composer dependencies 2023-07-01 11:43:36 +01:00
249ef9c534 ProcessLoginTask: remove old key expiry
since we don't have a hard date for this, and I've already made one wrong educated guess, I'd rather not have another massive outage.
A security update will have to be made to remove the old key as soon as the new one is rolled. This is not ideal, but it's the least disruptive option.
2023-07-01 11:41:04 +01:00
17842703a1 Merge branch 'legacy/pm4' into stable 2023-07-01 10:29:23 +01:00
f4dab17a1b Added deprecation notices 2023-07-01 10:29:14 +01:00
eed423505e Merge branch 'legacy/pm4' into stable 2023-07-01 10:28:34 +01:00
c165670e0a Added support for using and generating blockstate upgrade schemas using newFlattenedName rules
see pmmp/BedrockBlockUpgradeSchema@f426fccbee
2023-06-26 16:20:01 +01:00
882d50b14e Reapply 470a3e1a3: tools/generate-blockstate-upgrade-schema: reduce dependencies for generating blockstate mappings 2023-06-26 16:09:51 +01:00
0b0b72f596 Reapply b8788c55c: tools/generate-blockstate-upgrade-schema: improve property remapping checks
this is now able to determine which properties were renamed and/or changed when multiple renames occurred in a single version.
This also fixes unrelated properties being considered mapped to each other when there was only one property in the old and new state (e.g. mapped_type and deprecated for hay_bale in 1.10). Now, these are properly considered as unrelated.
2023-06-26 16:09:09 +01:00
2654fb294b Merge branch 'stable' into minor-next 2023-06-26 16:08:22 +01:00
2b40c1a5be Revert "tools/generate-blockstate-upgrade-schema: improve property remapping checks"
This reverts commit b8788c55c5.

This changes behaviour, so it needs to target minor-next.
2023-06-26 16:07:52 +01:00
74d219dcb6 Revert "tools/generate-blockstate-upgrade-schema: reduce dependencies for generating blockstate mappings"
This reverts commit 470a3e1a3a.

This changes behaviour, so it needs to target minor-next.
2023-06-26 16:07:23 +01:00
470a3e1a3a tools/generate-blockstate-upgrade-schema: reduce dependencies for generating blockstate mappings 2023-06-26 12:40:17 +01:00
ad67fb7291 BlockStateUpgradeSchemaModelBlockRemap: added missing @required tag 2023-06-24 16:22:29 +01:00
3eed0a4620 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-06-24 16:14:37 +01:00
b8788c55c5 tools/generate-blockstate-upgrade-schema: improve property remapping checks
this is now able to determine which properties were renamed and/or changed when multiple renames occurred in a single version.
This also fixes unrelated properties being considered mapped to each other when there was only one property in the old and new state (e.g. mapped_type and deprecated for hay_bale in 1.10). Now, these are properly considered as unrelated.
2023-06-24 16:14:28 +01:00
c06763c59b Fixed crash in CakeWithCandle when block-picking 2023-06-23 12:55:47 +01:00
881451c40c Bump build/php from 8cb2a2b to 2a21c57 (#5856)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `8cb2a2b` to `2a21c57`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](8cb2a2b218...2a21c57900)

---
updated-dependencies:
- dependency-name: build/php
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-23 11:00:59 +01:00
36f52f1ade AsyncTask: remove ArrayObject hack
this is no longer a concern with pmmpthread + PHP 8.1 and up. The behaviour that caused statics to be inherited was caused by bugs in PHP 8.0 and below, which have now been fixed.
2023-06-22 13:58:48 +01:00
0240d35c05 AsyncTask and AsyncPool no longer tolerate uncaught errors in tasks
Since task execution depends on tasks executing sequentially on a particular worker in some cases (e.g. PopulationTask must be preceded by GeneratorRegisterTask), it doesn't make sense to continue task execution if an error occurs.
Moreover, a task crashing may render the whole server unstable, as it leaves the server in an undefined state. This is the same kind of problem we fixed with scheduled tasks in PM3.

In versions past, pthreads was unreliable enough that random tasks would crash without an obvious reason, forcing us to accommodate this. I still don't know the origin or frequency of said issues, but I think it's time to rip the band-aid off and solve these problems for real.
2023-06-22 13:29:36 +01:00
8dedbb7471 World: clamp clickVector components from 0-1
this ensures that #5827 won't randomly start crashing if clients give bad values.
2023-06-21 16:59:14 +01:00
6f82942c64 Block: document onInteract() clickVector 2023-06-21 16:57:39 +01:00
9d0d60afd1 BlockPlaceEvent: ensure that getPosition() is always correct
since BlockTransaction was designed to be World-agnostic, it can't position() any blocks, since Position requires a World.

This workaround is the best we can do for now; however, it would probably be wise to deprecate getTransaction() in favour of a dedicated getBlocks() method which takes care of this, as BlockPlaceEvent is currently quite obnoxious to use.
2023-06-21 15:36:48 +01:00
391732f00c Fix Player->setGamemode() doc comment (#5848)
this has been outdated likely since the 1.3 alpha days.
2023-06-21 09:29:48 +01:00
ad3f854701 Register aliases for new cherry wood blocks 2023-06-20 12:59:16 +01:00
64e09525f3 Added timings for AsyncTask completion handlers, progress updates and error handlers (#5798)
closes #5749
2023-06-20 12:38:45 +01:00
774f92435a StringToItemParser: added underwater_tnt alias 2023-06-20 12:34:16 +01:00
be8cca1d55 Bump docker/build-push-action from 4.1.0 to 4.1.1 (#5834)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v4.1.0...v4.1.1)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-19 15:25:26 +01:00
eb9f804781 ÂBedrockWorldData: throw less confusing errors on missing version tags 2023-06-19 12:22:50 +01:00
ace
bccda4fe44 Implement Piglin Head (#5839) 2023-06-19 12:07:49 +01:00
8f48f8a596 Added missing cherry door item, closes #5817 2023-06-13 18:18:13 +01:00
288ebfa08a Fixed a bunch of item IDs being missing
these items were all pretending to be blockitems when I dumped data, and I wasn't aware that they'd been omitted.
2023-06-13 18:15:47 +01:00
a3046eb6fa Merge branch 'stable' into minor-next 2023-06-13 18:06:06 +01:00
ff0199cdf8 Fixed blue candle being missing from the creative inventory
this coincidentally fixes mangrove doors being tagged with unwanted blockstate runtime IDs. Their items client-side are not actually blockitems, so the client doesn't expect them to have blockstate IDs attached.
This reduces the chaos in the creative inventory slightly (for some reason the client responds to this stuff by putting random creative items in the wrong places), but the mess is still substantial and I don't know what caused the rest of it.

closes #5818

technically we shouldn't be breaking BC of internals signatures in a patch release, but it's internals, and that's an unwritten rule anyway. In any case, no one is likely to be affected.
2023-06-13 18:03:10 +01:00
39a6a9ee70 Bump phpunit/phpunit from 10.2.1 to 10.2.2 (#5824)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.2.1 to 10.2.2.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.2.2/ChangeLog-10.2.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.2.1...10.2.2)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-12 13:40:48 +01:00
0939301938 Bump docker/build-push-action from 4.0.0 to 4.1.0 (#5823)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v4.0.0...v4.1.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-12 13:40:30 +01:00
202be92c06 RGB PMMP Logo (#5825) 2023-06-12 13:30:44 +01:00
df4a8d4788 AsyncTask: lazy-init progressUpdates (#5806)
this is only possible since pthreads 5.1 and pmmpthread

the performance cost of this one ThreadSafeArray allocation is 30% of the total cost of allocating an AsyncTask object on Windows, which is enormous.

In past versions we couldn't lazily initialize it, because the object might get destroyed before the main thread had a chance to dereference it, leading to a crash when collecting completed tasks. This is no longer an issue thanks to object rescue behaviour implemented in pthreads 5.1.
I think this is probably OK in terms of thread-safety, as only one thread writes the property.
2023-06-11 14:45:44 +01:00
1d25e15ec8 Bump build/php from fcbc15f to 8cb2a2b (#5820)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `fcbc15f` to `8cb2a2b`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](fcbc15f23e...8cb2a2b218)

---
updated-dependencies:
- dependency-name: build/php
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-11 14:45:01 +01:00
1b35c352cc StandardEntityEventBroadcaster: Accepting PacketBroadcaster interface instead of StandardPacketBroadcaster (#5813) 2023-06-11 13:48:58 +01:00
ab75838c89 First shot at implementing acacia trees
this is mostly working, but due to some issue with leaf decay, the edges of the larger canopy will decay within minutes.

I don't know why this is yet, but it's likely some incorrect implementation of Leaves causing the problem.

In addition, the secondary branch of acacia may generate next to the base block of the trunk, which I've never observed to happen in vanilla. This has a 2% chance of occurring, so I haven't been able to rule it out yet, but it probably shouldn't happen.
2023-06-10 18:35:42 +01:00
1533dc4e56 Added cherry leaves 2023-06-10 13:21:21 +01:00
3800c0480f Group leaves (de)serializers together 2023-06-09 19:19:29 +01:00
0f8e61eda4 Implemented new cherry-wood blocks 2023-06-09 18:04:52 +01:00
0eb5f9b684 Fixed missing ItemTypeNames (forgot to regenerate from 1.20) 2023-06-09 17:59:11 +01:00
0f9283fda1 Reduce chaos in blockstate (de)serializers wrt. wooden blocks
these started to get flattened in 1.19, and rather than dump them in random places in the main function I made a new method, creating placement inconsistencies.
2023-06-09 17:47:06 +01:00
ab8386ed5a Tests: verify that ItemTypeIds/BlockTypeIds constants match their corresponding VanillaItems/VanillaBlocks registrations 2023-06-09 15:49:10 +01:00
64c1776910 Merge branch 'stable' into minor-next 2023-06-09 13:57:47 +01:00
e85605af7f changelog: fixed typo
[ci skip]
2023-06-09 01:44:45 +01:00
92bd88c77c 5.1.3 is next 2023-06-09 01:37:46 +01:00
7cd317bf39 Release 5.1.2 2023-06-09 01:37:45 +01:00
35fc9abacf Merge branch 'legacy/pm4' into stable 2023-06-09 01:34:33 +01:00
dfd70615ad 4.22.2 is next 2023-06-09 01:33:35 +01:00
ee903cad1f Release 4.22.1 2023-06-09 01:33:35 +01:00
9a04481bec Entity: broadcast teleports as regular movements
fixes #5810

probably fixes #4986

#5810 was caused by the workaround for #4394, which broke in 1.20 for reasons I'm still unclear on.

As FLAG_TELEPORT does not work at all for non-player entities, and causes bugs with player entities, sending the teleport movement without the flag is the least buggy way to solve all of these issues. Having the client interpolate teleport movements is not ideal, but there doesn't seem to be a way to reliably prevent it without causing even more bugs, so this will have to do.
2023-06-09 01:24:57 +01:00
833f9401f9 Merge branch 'stable' into minor-next 2023-06-07 22:03:34 +01:00
a46dfaf677 5.1.2 is next 2023-06-07 21:59:28 +01:00
4a3b175468 Release 5.1.1 2023-06-07 21:59:28 +01:00
73ee94b62c Fixed BlockStateData::CURRENT_VERSION 2023-06-07 21:58:21 +01:00
ab83210aa0 5.1.1 is next 2023-06-07 21:35:11 +01:00
3f2d51c58a Release 5.1.0 2023-06-07 21:35:10 +01:00
13dee2a615 Merge branch 'legacy/pm4' into stable 2023-06-07 21:33:12 +01:00
5d514a274f Merge branch 'legacy/pm4' of github.com:pmmp/PocketMine-MP into legacy/pm4 2023-06-07 21:24:13 +01:00
2220dc557e 4.22.1 is next 2023-06-07 21:23:57 +01:00
b5fc31a781 Release 4.22.0 2023-06-07 21:23:54 +01:00
9a67e3d660 PM5-specific changes for 1.20.0.23 beta 2023-06-07 21:08:41 +01:00
132330e16f Merge branch 'legacy/pm4' into stable 2023-06-07 21:08:09 +01:00
179eec9754 PHP-CS-Fixer 3.17 2023-06-07 21:04:11 +01:00
441f1f534f Random change PHP-CS-Fixer wanted to make 2023-06-07 20:59:32 +01:00
e747478afd and one more 2023-06-07 20:58:15 +01:00
92c45dd7e1 Fixed PHPUnit deprecation warnings 2023-06-07 20:57:43 +01:00
2538880408 1.20.0 2023-06-07 20:56:59 +01:00
4af981d726 PHPStan 1.10.16
closes #5802
2023-06-05 17:07:19 +01:00
ab3ebc1aa8 Bump phpunit/phpunit from 10.2.0 to 10.2.1 (#5803)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.2.0 to 10.2.1.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.2.1/ChangeLog-10.2.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.2.0...10.2.1)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-05 15:01:41 +01:00
57cbc25080 Merge remote-tracking branch 'origin/stable' into minor-next 2023-06-04 16:10:07 +01:00
b9bdfe580b Bump version to 5.2.0+dev
next feature release go brrrr
2023-06-04 16:07:10 +01:00
6d7f44d8fe Implement glow lichen (#5401) 2023-06-04 16:04:08 +01:00
f9818efff4 Fixed PHPUnit deprecation warnings 2023-06-04 14:00:26 +01:00
7fef8f0ab6 5.0.2 is next 2023-06-03 21:56:30 +01:00
2f43ccea6f Release 5.0.1 2023-06-03 21:56:26 +01:00
af1f7e098b Require pmmpthread 6.0.1 2023-06-03 21:42:43 +01:00
1706fb43eb Updated build/php submodule to pmmp/PHP-Binaries@fcbc15f23e 2023-06-03 21:27:54 +01:00
8d7f8ff3f5 Merge branch 'legacy/pm4' into stable 2023-06-03 21:23:00 +01:00
c715efb18e Jukebox: fix music not stopping when destroyed by explosion
closes #5794
2023-06-03 21:22:26 +01:00
40be564689 BlockSpreadEvent: document poorly-named constructor parameters 2023-06-03 17:08:02 +01:00
4e031e7b3e Always drop spore blossom item when it is broken (#5796) 2023-06-03 16:07:44 +01:00
4340c26029 RuntimeDataSizeCalculator: Tidy up junk comments 2023-06-02 16:37:08 +01:00
9c6d4093ae Fixed crash when getting an item from a block which came from an item which came from a block
had a stroke yet?
2023-06-02 16:16:54 +01:00
007ef833d4 Merge branch 'legacy/pm4' into stable 2023-06-02 13:34:29 +01:00
6678360c00 Make changelogs less infuriating in PhpStorm 2023-06-02 13:34:16 +01:00
102fd4d63a CONTRIBUTING: pmmp/ClassLoader is no longer used by PM5 2023-06-02 13:12:50 +01:00
2c0715ac6e Bump phpunit/phpunit from 10.1.3 to 10.2.0 (#5790)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.1.3 to 10.2.0.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.2.0/ChangeLog-10.2.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.1.3...10.2.0)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-02 13:04:27 +01:00
f75bb061ce Bump tests/plugins/DevTools from 46d2479 to 83f0db3 (#5787)
Bumps [tests/plugins/DevTools](https://github.com/pmmp/DevTools) from `46d2479` to `83f0db3`.
- [Release notes](https://github.com/pmmp/DevTools/releases)
- [Commits](46d2479b73...83f0db3f9e)

---
updated-dependencies:
- dependency-name: tests/plugins/DevTools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-02 13:03:26 +01:00
73e7201acb 5.0.1 is next 2023-06-01 16:09:52 +01:00
b16cc69974 Release 5.0.0 2023-06-01 16:09:49 +01:00
5de4215169 Merge branch 'major-next' into stable 2023-06-01 15:44:56 +01:00
e128a4e1e7 Merge branch 'minor-next' into major-next 2023-06-01 14:54:03 +01:00
c95c600100 Merge branch 'stable' into minor-next 2023-06-01 14:52:28 +01:00
3db45b6a68 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-06-01 14:51:14 +01:00
3e87ad281f Use tagged fork of netresearch/jsonmapper
we need this for it to not be a huge pain in the ass to install PM as a composer dependency, which plugin CIs may do.
2023-06-01 14:51:04 +01:00
b72da777eb Bump tests/plugins/DevTools from a67f9af to a2f36e8 (#5785)
Bumps [tests/plugins/DevTools](https://github.com/pmmp/DevTools) from `a67f9af` to `a2f36e8`.
- [Release notes](https://github.com/pmmp/DevTools/releases)
- [Commits](a67f9af8d6...a2f36e8dbf)

---
updated-dependencies:
- dependency-name: tests/plugins/DevTools
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-01 13:45:20 +01:00
de49910e84 Fix CS 2023-05-31 22:18:25 +01:00
d2fe537159 Merge branch 'minor-next' into major-next 2023-05-31 22:12:39 +01:00
bb31df051d Merge branch 'stable' into minor-next 2023-05-31 22:10:18 +01:00
1101f35c17 Update setup-php-action to 2.0.0
this version vastly improves build time by using optimized prebuilts
instead of building the binaries on the runner.
2023-05-31 22:09:33 +01:00
07225df936 Block: fixed tile-stored properties sticking to the item in asItem()
this was enabling duplication of items, since the dropped item object would contain a Block which still referenced the framed Item.
2023-05-31 21:48:06 +01:00
3948dc4f75 Remove calls to ReflectionProperty::setAccessible() (#5783)
This is a no-op in PHP 8.1 and up.
2023-05-31 14:03:14 +01:00
4f4dca7fc0 Mark WoodLikeBlockIdHelper as internal 2023-05-30 21:41:25 +01:00
0ed5e94a72 Merge branch 'minor-next' into major-next 2023-05-30 16:15:56 +01:00
3a4e958e84 Merge branch 'stable' into minor-next 2023-05-30 16:08:03 +01:00
20942b37eb Update composer dependencies 2023-05-30 16:07:01 +01:00
d343db8750 4.21.2 is next 2023-05-30 14:42:59 +01:00
f2df702c67 Release 4.21.1 2023-05-30 14:42:59 +01:00
481270e6aa Merge tag '4.20.5' into stable 2023-05-30 14:42:11 +01:00
e7bdaa8579 Release 4.20.5 2023-05-30 14:35:17 +01:00
76749cbaa7 Use fork of JsonMapper to solve cweiske/jsonmapper#210 2023-05-30 14:30:28 +01:00
a897bdfaa0 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-05-30 14:17:21 +01:00
09668a37d6 Use fork of JsonMapper to solve cweiske/JsonMapper#210 2023-05-30 14:17:09 +01:00
ea92a23d0d Bump build/php from b1d5c0d to f2ece7b (#5765)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `b1d5c0d` to `f2ece7b`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](b1d5c0d737...f2ece7b30d)

---
updated-dependencies:
- dependency-name: build/php
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 21:37:18 +01:00
691e67018d Bump phpstan/phpstan-phpunit from 1.3.11 to 1.3.13 (#5772)
Bumps [phpstan/phpstan-phpunit](https://github.com/phpstan/phpstan-phpunit) from 1.3.11 to 1.3.13.
- [Release notes](https://github.com/phpstan/phpstan-phpunit/releases)
- [Commits](https://github.com/phpstan/phpstan-phpunit/compare/1.3.11...1.3.13)

---
updated-dependencies:
- dependency-name: phpstan/phpstan-phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 21:36:58 +01:00
fe2140a716 Bump shivammathur/setup-php from 2.25.1 to 2.25.2 (#5766)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.25.1 to 2.25.2.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.25.1...2.25.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 21:36:46 +01:00
8744032ab6 Fixed empty block handling after blockstate ID XOR change 2023-05-29 18:26:23 +01:00
5a9cdef40c Chunk: added DIRTY_FLAGS_ALL and DIRTY_FLAGS_NONE 2023-05-29 17:45:19 +01:00
a49842278a WorldProvider subsystem no longer depends on Chunk
Instead, it provides the data needed to construct the chunk, which doesn't require the provider to be aware of anywhere near as much logic.
2023-05-29 17:44:00 +01:00
d57954dff0 PopulationTask: ensure that unmodified chunks don't get sent back to the main thread for no reason 2023-05-29 17:30:04 +01:00
ce5e663a73 Assume chunks are dirty by default
having them be clean by default makes no sense. It only makes sense for them to be clean if they were loaded directly from disk without any alterations.

Default clean is a footgun.
2023-05-29 17:22:39 +01:00
c10be0f346 WorldProvider: allow loadChunk() to return additional information about the loaded chunk data
this will be needed for dealing with #5733. I don't plan to fix that before 5.0, but we need to make the appropriate BC breaks now, before release.
2023-05-29 17:03:39 +01:00
f5a1a0c9cb ÂInsert PM data version into blockstates, chunks, entities, tiles and level.dat
this information will allow us to correct for any bugs introduced by past versions.

however, we still need to propagate this information to permit actually using it when loading data.
2023-05-29 16:32:24 +01:00
7f1550ef04 Revert "Stop using insecure UUIDs from non-XBL players"
This reverts commit 9baf59702b.

I forgot this is also needed for the player list, and for skin updates
to work ... this will need to be revisited
2023-05-27 18:10:55 +01:00
9baf59702b Stop using insecure UUIDs from non-XBL players
closes #4076

I opted for the minimal approach of replacing only UUIDs for non-XBL players, since most servers are using XBL anyway (as they should).
2023-05-27 18:00:54 +01:00
473c062b40 Improve documentation for BlockTypeIds and ItemTypeIds 2023-05-27 17:28:36 +01:00
b8ba2d03ba Added new note instruments up to 1.19
1.20 adds extra ones for each type of mob head, but we're not supporting 1.20 yet.
2023-05-26 16:58:06 +01:00
06b0fa4d67 Fix PHPStan 2023-05-26 15:47:35 +01:00
fddab29e87 Move mob head and note instrument save IDs into pocketmine\data\bedrock
to be consistent, these shouldn't be exposed in the API like this...
I'm not very happy with the whole 'type ID map' paradigm (particularly its lack of static analysis guarantees), but the most important thing right now is to get this stuff out of the API so that plugin devs don't try and abuse it. We're not going to change the whole system days before PM5 release.
2023-05-26 15:47:12 +01:00
bdb0ed0701 Consistently use 'mob head' terminology in the API
previously, we were sometimes using 'mob head' and other times 'skull', sometimes even within the same file.
2023-05-26 15:08:00 +01:00
edafe9d21f Entity: Rename and document isImmobile() and friends
while I could implement server-side ability to disable entity movement, I don't think that's particularly useful. However, the intended function of this (disabling client sided AI) is useful, so it makes more sense to rename it to match its functionality, rather than changing its functionality to match the name.

closes #3130
2023-05-26 14:01:21 +01:00
cc77f18ff0 ÂBlock: added a TODO for getStateId() 2023-05-25 17:38:39 +01:00
24e897f813 Updated blockstate registry consistency check 2023-05-25 16:48:34 +01:00
ffe3556be1 Block: XOR state data with type ID, improve hash distribution
since most blocks have no state data, their lower 8 bits of state data were all zero.
This makes state IDs a bit more distributed for minimal cost.

I considered flipping these around and using type ID in the lower bits directly, but this worsened distribution for walls.

In the worst case, largest number of collisions drops from 11 to 5 with this change, and the number of states with unique hash keys increased from 3518 to 4461 (out of 7638). This is still a long way from perfect, but it's a decent improvement, improving the overall load factor from 1.6 to 1.3.

related to #5604
2023-05-25 16:35:45 +01:00
57330a7186 Bump build/php from f860ade to b1d5c0d (#5760)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `f860ade` to `b1d5c0d`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](f860ade30a...b1d5c0d737)

---
updated-dependencies:
- dependency-name: build/php
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 12:27:12 +01:00
2ebf8757c1 5.0.0-BETA5 is next 2023-05-23 01:53:00 +01:00
1c69116717 Release 5.0.0-BETA4 2023-05-23 01:52:57 +01:00
9d9c628acd Mark AsyncPoolWorkerEntry as @internal 2023-05-23 01:32:44 +01:00
cbda24d77e Consolidate worker data under AsyncPoolWorkerEntry
instead of having a bunch of arrays... this improves the system integrity and makes it less obnoxious to look at
2023-05-23 01:31:25 +01:00
ed64eac76f ... 2023-05-23 01:21:30 +01:00
a7aebed0a0 Update DevTools submodule to pmmp/DevTools@aa1586db05 2023-05-23 01:19:03 +01:00
c66a3a8b3e Update to Snooze 0.5.0 2023-05-23 01:09:22 +01:00
4aba9d9725 Absorb pocketmine/classloader into the core code
the only use for this class is to facilitate random runtime plugin loading, and it's not complete even for that purpose.

Since nothing but PM uses pocketmine/classloader anyway, it doesn't make sense to have it outside the core. As with LogPthreads, it's just adding more maintenance work.
2023-05-22 22:52:48 +01:00
d2c34615f5 Update build/php to pmmp/PHP-Binaries@b1d5c0d737 2023-05-22 22:35:39 +01:00
815b4e2bab Fix PHPStan 2023-05-21 16:48:07 +01:00
69273f3ff7 AsyncTask::setResult(): permit returning ThreadSafe objects to the main thread
this is now supported thanks to the object rescue feature implemented in pthreads 5.1, making returning of thread-safe values from async tasks possible.
This needs to be explicitly supported, since otherwise it will attempt to serialize them, which isn't supported anymore.
2023-05-21 16:37:41 +01:00
9ddac21de0 Bump shivammathur/setup-php from 2.24.0 to 2.25.1 (#5711)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.24.0 to 2.25.1.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.24.0...2.25.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-21 00:13:22 +01:00
fdb724c646 ItemSerializer: change exception type 2023-05-20 18:58:59 +01:00
3109a179db ... 2023-05-20 18:56:28 +01:00
5afeeb8f89 Remove nonsensical code from block and item serializers
At the time when I wrote this code, I was still in the head space of the kind of ID hijacking that PM4 plugins do to override built-in blocks.

However, this kind of internal ID reuse makes no sense in PM5, since said IDs are only used in the core itself at runtime to identify types and states.

Even if we were to allow overriding block deserializers, overriding serializers makes no sense whatsoever, since the original block would continue to exist and be accessible.
There is a case to be made to allow overriding the deserializer, but not for the serializer.
2023-05-20 18:55:36 +01:00
1cb7846f7c Remove LogPthreads from CONTRIBUTING.md 2023-05-20 18:24:10 +01:00
097feba4d5 Absorb pocketmine/log-pthreads into PM core
this was previously part of the abandoned package pocketmine/spl. It had to be separated in the PM3 days, because RakLib depended on it.

Since RakLib 0.13, RakLib stopped being dependent on or aware of pthreads, so it no longer depends on any thread-related packages.
It's also possible to absorb pocketmine/snooze and pocketmine/classloader back into the core with this in mind.
2023-05-20 16:57:24 +01:00
9509d7e04d Scrub PHPStan baselines 2023-05-20 01:51:21 +01:00
3116fb8187 ... 2023-05-20 01:47:50 +01:00
e0630fbb25 pmmpthread support 2023-05-20 01:29:26 +01:00
8245cfab0e PlayerDeathEvent: add ability to set message displayed on the death screen (#5726) 2023-05-19 16:18:18 +01:00
8454076235 WaterCauldron: remove more repeated code 2023-05-19 15:45:12 +01:00
4a3843a881 WaterCauldron: reduce code repetition 2023-05-19 15:40:04 +01:00
bd6af68f91 Update symfony/filesystem to 6.2.10 2023-05-19 15:13:34 +01:00
b27d3a5fce Merge branch 'stable' into minor-next 2023-05-19 15:11:20 +01:00
c91aa24daa Bump phpunit/phpunit from 9.6.8 to 10.1.3 (#5753)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.8 to 10.1.3.
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.1.3/ChangeLog-10.1.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.8...10.1.3)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-19 15:09:24 +01:00
b8a1b32461 Fixed late property initializing in UnknownBlock (#5755) 2023-05-18 19:53:37 +01:00
9c82507168 Merge remote-tracking branch 'origin/stable' into minor-next 2023-05-18 14:20:22 +01:00
db95bf8b9b Caching creative inventory entries (#5703)
Due to the high cost of Item::serializeCompoundTag(), it's very costly to rebuild this every time we need it. This is sent during the pre-spawn step, where we need to minimize costs as much as possible.
2023-05-18 14:11:28 +01:00
edcf0f8405 5.0.0-BETA4 is next 2023-05-17 19:47:42 +01:00
b8abe34904 Release 5.0.0-BETA3 2023-05-17 19:47:42 +01:00
7ac74180c9 Merge branch 'stable' into major-next 2023-05-17 19:46:50 +01:00
6186fc0bfe 4.21.1 is next 2023-05-17 16:45:35 +01:00
ef40934d24 Release 4.21.0 2023-05-17 16:45:32 +01:00
69b668355f Merge branch 'minor-next' into stable 2023-05-17 16:12:24 +01:00
ee9ce8a4f4 Merge branch 'minor-next' into major-next 2023-05-17 15:45:03 +01:00
59ca7b75e1 Fixed PHPStan error 2023-05-17 15:32:38 +01:00
9621836e36 Clean up confusing mess around block and item overriding
right now, I don't see an obvious reason to do this. If it turns out I was wrong later on, we can add functionality back, but we can't remove functionality after release.
2023-05-17 15:21:49 +01:00
0547383296 Update build/php submodule to pmmp/PHP-Binaries@f860ade30a 2023-05-17 15:08:05 +01:00
c7dff9ea40 bootstrap: remove ext-parallel bootstrapping code
I have no intention of using parallel, so this code is not necessary.
2023-05-17 14:11:43 +01:00
043350753b Drop PHP 8.0, 8.1 is now minimum version 2023-05-17 13:53:57 +01:00
5ad8016b99 Merge branch 'stable' into minor-next 2023-05-17 13:44:45 +01:00
2e5b2eed6e Update composer dependencies 2023-05-17 13:43:28 +01:00
5a0cde49cc AsyncPool: do not double-check progress updates on finished tasks
checkProgressUpdates is called directly before onCompletion, so we only need to call it again if the task isn't finished yet.
2023-05-16 23:37:58 +01:00
008a022ec1 Players now have finite resources in spectator mode
this seems like the logical solution for the block picking issues.
2023-05-16 23:02:33 +01:00
5c85a7c306 Merge remote-tracking branch 'origin/stable' into minor-next 2023-05-16 22:54:53 +01:00
599c4284f5 Introduce 10 KB threshold for async compression
due to the extremely large performance cost of instantiating AsyncTasks, it's usually not worth bothering with async compression except for very large packets.
While this large overhead can be significantly reduced by using specialized threads, it's early days in the testing stages for such improvements, and for now, we still have this to deal with.

Since async compression is always used prior to player spawn, this change may slightly improve the performance of the pre-join stage of the game.
2023-05-16 22:54:06 +01:00
9499e2e595 always the CS... 2023-05-16 14:22:03 +01:00
a4fea1444a Remove validateCallableSignature() calls from network hot paths
we rely on phpstan for validation of this internally, and plugins shouldn't be calling these methods anyway.
this significantly reduces the overhead of CompressBatchPromise.
2023-05-16 14:21:32 +01:00
c9bb4335a1 Item: added getStateId(), removed state data from public API
state data was only used for indexing stuff along with state ID anyway, so it makes more sense to lock it away in here instead.
2023-05-16 14:14:18 +01:00
015c668885 Change confusing 'type data' and 'state data' terminology for blocks and items
For blocks, we now use 'block-item state' and 'block-only state', which should be much clearer for people implementing custom stuff.
'block-item state', as the name suggests, sticks to the item when the block is acquired as an item.
'block-only state' applies only to the block and is discarded when the block is acquired as an item.

'type data' for items was also renamed, since 'type' is too ambiguous to be anything but super confusing.
2023-05-16 14:07:29 +01:00
ccb22ceb3f Fix flower pots being marked as pottable (#5747) 2023-05-16 12:31:30 +01:00
1ba47802a8 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-05-15 14:59:02 +01:00
9d111e13f1 CONTRIBUTING: added table of in-house dependencies and which classes, functions or namespaces they contain 2023-05-15 14:58:31 +01:00
44bc4d8c7c Bump phpstan/phpstan from 1.10.14 to 1.10.15 (#5741)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.14 to 1.10.15.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.14...1.10.15)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-10 15:02:59 +01:00
30f1d3e016 Fix code style (#5740) 2023-05-10 13:41:25 +01:00
7b1a1e5a18 BlockStateToObjectDeserializer: remove redundant helper 2023-05-08 22:16:55 +01:00
1b452f3a88 BlockStateToObjectDeserializer: make flat colour block handling less repetetive 2023-05-08 21:38:58 +01:00
fa719f37d5 Implement Cave Vines & Glow Berries (#5424) 2023-05-08 19:24:23 +01:00
d834266635 BlockGrowEvent: add player information for bonemeal usage (#5596)
this is in line with StructureGrowEvent, which also has a similar API.
2023-05-08 17:38:07 +01:00
d317347a9b WorldTimings: remove TODO
I tried this, and it didn't really provide any information that the tree table didn't already show.
2023-05-08 16:35:30 +01:00
077fac84bf Added aggregate timers for all world timings
this allows timings list view to display totals for these sections. It does make the tree view a bit more annoying in some cases though.
2023-05-08 16:27:46 +01:00
6f0eb019d2 ItemIdMetaUpgrader: added some auxiliary methods 2023-05-07 19:28:07 +01:00
fdb3a5b121 Fixed incorrect implementation of peak timings 2023-05-07 18:29:37 +01:00
8e6c1762d7 Merge branch 'minor-next' into major-next 2023-05-06 18:27:06 +01:00
e3bc36ab5b Merge branch 'stable' into minor-next 2023-05-06 18:26:47 +01:00
283ff28aa9 4.20.5 is next 2023-05-06 18:20:19 +01:00
c3ceeeace7 Release 4.20.4 2023-05-06 18:20:18 +01:00
aac4f6c0e1 Fixed all game modes allowing flight
moral of the story: do not trust that mojang things do what they say they do - the spectator ability layer always applies, regardless of whether the player is actually in spectator mode or not ...
2023-05-06 18:18:05 +01:00
926f68d8c5 Move SkinAdapter under TypeConverter, remove SkinAdapterSingleton
this is legacy cruft from PM3, which didn't have TypeConverter or SingletonTrait.
2023-05-06 17:53:24 +01:00
ed11fd5a83 CS again... 2023-05-06 17:51:00 +01:00
e0a6ec0c24 Start deglobalizing TypeConverter
there's a bunch of places we can't reach with this right now:

- particles
- sounds
- tile NBT
- entity metadata
- crafting data cache
- chunk encoding
- world block update encoding

this is a work in progress, but ultimately we want to get rid of these singletons entirely.
2023-05-06 17:47:09 +01:00
7cdf6b0946 Fixed merge error 2023-05-06 17:29:59 +01:00
5c7f4570b4 Merge branch 'minor-next' into major-next 2023-05-06 17:20:37 +01:00
bb60a9057f Merge branch 'stable' into minor-next 2023-05-06 17:08:29 +01:00
3b893961e4 4.20.4 is next 2023-05-06 17:01:49 +01:00
325ffec1be Release 4.20.3 2023-05-06 17:01:49 +01:00
fa715a074a Fixed TimingsHandler depth not getting reset when timings is disabled
When timings was disabled, internalStopTiming is not called, and timer depth is not decremented.
If timings is later reenabled, the next call to internalStartTiming will think the timer is already running, and won't generate any new records for the timer.
This has led to broken timings reports with missing Full Server Tick entries, amongst other things.
2023-05-06 16:56:39 +01:00
4caa2c7690 NetworkSession: send FLYING flag on spectator ability layer
fixes #5722

I'm not very clear why this works. PM doesn't use real spectator mode yet (we're still using the faux spectator mode PM has had for years, because I haven't yet assessed how real spectator mode will affect stuff like block interactions), so this ability layer shouldn't have any effect.

thank you @Alemiz112
2023-05-06 15:54:23 +01:00
d04da9b1d8 Reuse timings handlers for event handlers of the same events
due to direct repeated usage of registerEvent() with closures, we've seen some libraries like muqsit/SimplePacketHandler generate very large timings reports, because a new timings handler gets created every time a plugin registers or unregisters a new packet handler callback.

This change fixes the problem by ensuring that any handlers derived from the same function, handling the same event class, will share the same timer.
2023-05-06 15:42:52 +01:00
8a374df801 BlockTranslator: remove useless call to generateDataFromStateId()
BlockStateDictionary doesn't retain BlockStateData anymore, so this optimisation is just wasting CPU cycles.
2023-05-05 17:02:50 +01:00
02cf5ed388 RuntimeBlockMapping: lazy-load NBT blockstates
this saves a considerable amount of memory.

we don't actually need this state array in PM4 anyway, since we don't support the client-side chunk cache yet.
when the time comes to support it, it'll be much more practical to cache binary states and copy bytes anyway, instead of doing it the current way, which is both slow and memory-intensive.

Measured footprint change: 9 MB -> 400 KB.
2023-05-05 16:18:03 +01:00
6cad559dbe Merge branch 'stable' into minor-next 2023-05-05 16:08:30 +01:00
84a943bcec BaseInventory: slap a TODO on isSlotEmpty() 2023-05-05 16:06:37 +01:00
f2c6a75145 BlockStateDictionary: reduce memory footprint of id/meta -> state ID lookup by >60%
the aim of the game here is to avoid allocating lots of tiny arrays, which have a terrible overhead:useful-data ratio.
This reduces the footprint of the mapping from 1.6 MB to 600 KB.
2023-05-05 15:26:54 +01:00
09e823e304 BlockStateDictionary: remove useless indirection 2023-05-05 14:52:21 +01:00
289ede669d BlockTranslator: use less ambiguous function names 2023-05-05 14:47:23 +01:00
4f32f5e0b7 BlockStateDictionaryEntry: encode property names as well as values
sadly we need these to reconstruct the state upon deserialization
2023-05-05 13:41:06 +01:00
633e77a34c RuntimeBlockMapping: share states CompoundTags if they are the same
this allows saving about 4 MB of memory, because there are many blocks which have identical states, although they have different IDs.

this relies on a potentially risky assumption that the tags in knownStates won't be modified. If they are modified, the changes will influence all blockstates which share the tag.
However, I don't expect this to happen, and the 4 MB memory saving is substantial enough to be worth the risk.
2023-05-04 23:21:54 +01:00
092d130c96 RuntimeBlockMapping: borrow a hack from PM5 to reduce memory footprint
we can't change the internals of this on a patch release, but this hack provides a 12 MB memory usage reduction, which is very significant.
2023-05-04 23:01:10 +01:00
c09390d20f 4.20.3 is next 2023-05-04 21:06:30 +01:00
22f8623e17 Release 4.20.2 2023-05-04 21:06:27 +01:00
d8e77c1920 Tidy up crafting block registration
according to data dumps from bds-mod-mapping, fletching tables have a blast resistance of 12.5, just like the others.
2023-05-04 18:47:06 +01:00
85372633eb Tidy up BlockLegacyIdHelper stuff
I don't plan to make wood-like blocks have a dynamic wood/leaves/sapling type, as it's entirely possible their type properties will continue to diverge in future versions.
2023-05-04 17:05:22 +01:00
2c81446e5b Move TreeType to generator package, added dedicated SaplingType enum
TreeType includes a bunch of stuff that don't have regular saplings associated with them, such as mangrove and azalea trees.
Mangrove has a dedicated propagule block with different behaviour than the others, and azalea trees are grown from azalea blocks, which are solid and have different behaviour to saplings.

We may also want to account for crimson and warped 'trees' in TreeType too, although I'm not sure if those belong there or not.
2023-05-04 16:54:10 +01:00
299ff5d912 Register mangrove boat item 2023-05-04 16:39:23 +01:00
896dd2ec9d Boat: use BoatType enum instead of TreeType
TreeType really belongs in the generator package. Not all types of tree may have their own boat type (e.g. azalea).
We can't use WoodType for this either, because some types of wood also don't have associated boat types (crimson, warped).
2023-05-04 16:35:31 +01:00
f1417e8dc9 BlockStateDictionaryEntry: deduplicate encoded states
this saves about 500 KB of memory at no cost.
2023-05-04 16:14:41 +01:00
897ba9f2d9 BlockStateLookupCache: combine arrays for stateless and stateful blocks
this reduces memory usage by another 20 KB or so.
2023-05-04 15:29:27 +01:00
d2c37d8bcf BlockStateLookupCache: avoid allocating useless arrays for blocks with only 1 permutation
this saves about 120 KB of memory.
2023-05-04 15:16:18 +01:00
43fe819862 BlockStateDictionary: added a smelly hack that saves another 40 KB
this is really diminishing returns at this point...
2023-05-03 23:18:06 +01:00
f9d9cbd0f6 BlockStateDictionary: slash another 14% off memory usage by deduplicating block type names
perhaps we could construct a dictionary from BlockTypeNames reflection??
2023-05-03 23:14:53 +01:00
ed021d193d BlockTranslator: cut memory usage in half
this was achieved by storing binary representations of the blockstates, rather than the original BlockStateData.

Due to the insane object:data ratio of Tag objects (40:1 for ByteTag for example), modestly sized NBT can explode in memory footprint. This has been previously seen with the absurd 25 MB footprint on file load.
Previously, I attempted to mitigate this by deduplicating tag objects, but this was mitigating a symptom rather than addressing the cause.

We don't actually need to keep the NBT around in memory, since we don't actually use it for anything other than matching blockstates. In this case, we can allow the code to be possibly a little slower, since the lookup is anyway slow and the result will be cached.
In fact, using encoded ordered states as hash keys significantly improves the speed of lookups for stuff like walls, which have many thousands of states.

We keep around generateStateData(), since it's still possible we may need the BlockStateData associated, and it can be easily reconstructed from the binary-encoded representation in BlockStateDictionaryEntry.
2023-05-03 23:11:00 +01:00
32e6fdd95a Rename RuntimeBlockMapping -> BlockTranslator 2023-05-03 22:18:27 +01:00
01f340985a Centralize all conversion-related stuff under TypeConverter
instead of having singletons for everything, which are a nightmare to manage for multi version
2023-05-03 16:33:17 +01:00
5e462db0f8 Move MOTD game mode stringifying to RakLibInterface
since this is contextless (there's no way to know the version of the client requesting the MOTD), we can safely assume that this is not going to vary between protocol versions.
2023-05-03 13:36:24 +01:00
6beb80b8fe Fixed usages of BlockDataUpgrader which weren't accounting for thrown exceptions 2023-05-02 17:13:31 +01:00
4d0cecbac2 RegionWorldProvider: use provider logger instead of global logger 2023-05-02 16:47:25 +01:00
5fcf5e0c40 LevelDB: log more stuff, stop bailing on recoverable errors 2023-05-02 16:46:45 +01:00
f29e2f7110 WorldProviders now accept Loggers 2023-05-02 15:41:11 +01:00
d0d263191d Fix build 2023-05-02 14:21:33 +01:00
3366e1084b LightUpdate: squeeze 10-15% more performance out of propagation
we can use SubChunkExplorerStatus to decide whether or not to update the local light array reference.

We also dereference some properties into local variables, because dereferencing properties is slow. Indirect property dereferences add an extra performance penalty for every layer.
2023-05-02 14:05:55 +01:00
d0b9234841 SkyLightUpdate: deal with effective light during initial node discovery
this allows the propagation stage to ignore effective light, which allows for further optimisations.
2023-05-01 22:29:31 +01:00
d80f65ae7c BedrockWorldData: do not load worlds with a newer NetworkVersion than we support
often, protocol updates are done without consideration for the current world format version. We don't want to require the world support to be updated at the same time, since this might delay updates.
2023-05-01 17:53:08 +01:00
096daef0d0 World: added setDisplayName()
this is an obvious use case, and I'm not really sure why it wasn't supported sooner.
2023-05-01 16:29:07 +01:00
29694c19af BlockStateUpgradeSchemaUtils: Use independent suffixes for each property mapping list 2023-05-01 14:46:30 +01:00
b3e94ef1dc Chunk: update documentation 2023-05-01 14:46:30 +01:00
f04151dbe6 README: next-major branch was renamed (#5731)
[ci skip]
2023-05-01 14:08:20 +01:00
5dcd8bf289 Bump symfony/filesystem from 5.4.21 to 5.4.23 (#5730)
Bumps [symfony/filesystem](https://github.com/symfony/filesystem) from 5.4.21 to 5.4.23.
- [Release notes](https://github.com/symfony/filesystem/releases)
- [Changelog](https://github.com/symfony/filesystem/blob/6.2/CHANGELOG.md)
- [Commits](https://github.com/symfony/filesystem/compare/v5.4.21...v5.4.23)

---
updated-dependencies:
- dependency-name: symfony/filesystem
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-01 13:30:02 +01:00
17fe894229 TypeConverter: fixed crash on unknown blockitems (#5729)
morton2d_encode is 64-bit function when NBT int tag is 32-bit only, resulting in crash
2023-04-30 12:11:07 +01:00
728e0bc869 tools/generate-blockstate-upgrade-schema: allow multi-ID remaps to be processed as regular states if their ID didn't change
this allows remappedStates to only deal with stuff that has a different ID, which reduced the size of the 1.12 -> 1.13 schema quite nicely.
2023-04-28 20:58:18 +01:00
a1d44de487 Added support for compressing blockstate remaps using copiedState
this significantly reduces the size of schemas when state remaps are used (see pmmp/BedrockBlockUpgradeSchema@85b83b360e).

in addition, this will likely offer a substantial performance and memory saving when walls get flattened, which will eventually happen.
2023-04-28 20:35:37 +01:00
263e1e9950 Fixed bogus test expectations 2023-04-28 20:05:51 +01:00
2121152b76 Fix CS 2023-04-28 20:03:53 +01:00
a1cd1d7433 ... 2023-04-28 19:35:03 +01:00
04aabaee5e Fix CS 2023-04-28 19:31:08 +01:00
75410a5412 BlockStateUpgradeSchemaUtils: sort data before emitting JSON
this makes it easier to see what's changing, as well as making the order stable across multiple regenerations.
2023-04-28 19:31:00 +01:00
e2108557ab BlockStateUpgrader: make sure the returned state always has an updated version ID
PM itself doesn't require this, but it's useful for tools to know whether to upgrade the schema again (e.g. in testing scenarios).
2023-04-28 17:26:19 +01:00
ff8301b86c BlockStateData: fixed outdated version ID 2023-04-28 17:23:32 +01:00
869c836e2d BlockStateUpgradeSchemaUtils: ensure that remapped values are generated in a consistent order
this uses lexical order, which isn't ideal for numeric values (1, 10, 2, etc), but it's good enough to ensure that the order is stable.
2023-04-28 17:12:52 +01:00
b70ff32548 ItemTranslator: Fixed log items not displaying correctly on the client
closes #5724

this uses a (potentially bogus) assumption that the lowest mapped meta value associated with an ID is valid. I don't want to break this during a patch release, and this works for now.

In the future it would probably make more sense to bypass ItemTranslator entirely, and rely solely on the blockstate returned by RuntimeBlockMapping to fetch the correct ID. This is similar to how we serialize items for saving on disk in PM5.
2023-04-28 13:54:40 +01:00
73bf5d4b29 DoubleChestInventory: specialize isSlotEmpty() and getMatchingItemCount() 2023-04-27 21:17:55 +01:00
eb136e60c8 BaseInventory: added getMatchingItemCount() helper
this eliminates the performance issues described by #5719.
closes #5719

we may want to consider exposing a public API for this in the future, since it might be useful for plugins.
2023-04-27 21:08:35 +01:00
4228880509 BaseInventory: change dumb variable names in internalAddItem() 2023-04-27 20:29:02 +01:00
709d874204 BaseInventory: clean up max stack size handling
we can safely assume that:
- the inventory's max stack size won't change during the operation
- two items which stack together have the same max stack size
- the item's max stack size won't change during the operation
2023-04-27 20:27:05 +01:00
07dc10d6e6 World: improve performance of tickChunks() selection process (#5721)
Since light population is required to make a chunk tickable, a chunk may not be tickable for some time if the async workers get backlogged.
The previous version of this system only cached the eligibility result if the result was a "yes", but we can also track it when it's a "no", rather than rechecking it every tick.

This change should improve performance in factions and similar gamemodes, which involve large maps with sparsely distributed players, where each player likely has an independent, non-overlapping ticking chunk circle.

We also ditch TickingChunkEntry in favour of multiple arrays to track the eligibility states. This allows us to avoid rechecking the (even cached) readiness of potentially thousands of chunks. If there are no ticking chunks to recheck, this reduces the cost of the selection process to zero.
2023-04-27 16:59:29 +01:00
7f6269c432 Introduce and use optimised versions of Inventory->isSlotEmpty()
this avoids useless cloning, improving the performance of several functions.
2023-04-27 16:52:52 +01:00
194714b448 Merge branch 'stable' into minor-next 2023-04-27 15:37:54 +01:00
023460db2c BaseInventory: fixed internalAddItem() doing useless canStackWith() checks on null items
if the item is null, it's never going to stack with anything given to this function, because addItem() already discards null items.
2023-04-27 14:53:54 +01:00
2910ffebf4 4.20.2 is next 2023-04-27 13:31:02 +01:00
fea820a99e Release 4.20.1 2023-04-27 13:31:02 +01:00
7c19f14cf5 Fixed up offhand handling for ItemStackRequest, fixes #5723 2023-04-27 13:25:08 +01:00
5a54d09869 InventoryManager: verify slot existence in locateWindowAndSlot()
previously, this would happily return invalid slot IDs, potentially leading to a crash.
2023-04-27 13:18:28 +01:00
a8dec1adb1 PM5-specific changes for 1.19.80 2023-04-26 23:30:56 +01:00
0dca85af44 Merge branch 'minor-next' into major-next 2023-04-26 23:28:27 +01:00
4def4d52d9 Merge branch 'stable' into minor-next 2023-04-26 23:22:00 +01:00
1d10107024 4.20.1 is next 2023-04-26 23:15:38 +01:00
54ae4d0ea2 Release 4.20.0 2023-04-26 23:15:34 +01:00
0d21e591d1 Support sign editing UI in 1.19.80, with APIs to allow plugins to use it
this doesn't support editing the rear side of a sign, since the 1.12 format doesn't allow us to represent the rear text, and it would necessitate API breaks to support anyway.

However, we can quite trivially support APIs for the sign GUI, which plugins can use to enable editing signs. PocketMine-MP doesn't currently permit this, since it's currently an experimental feature in 1.20, but plugins can simply use Player->openSignEditor() to mimic it.

This is, however, a byproduct of the fact that APIs needed to be added in order to facilitate the use of OpenSignPacket in 1.19.80.
2023-04-26 22:55:05 +01:00
408616723c Changes for 1.19.80 2023-04-26 22:52:02 +01:00
9bfcd39f2a World: improve type info for getTickingChunks() 2023-04-26 17:06:52 +01:00
8102616ff4 Added ticking chunk count to /status
closes #5716
2023-04-26 17:05:31 +01:00
b162d688a3 CI: use php-cs-fixer 3.16 2023-04-26 16:05:06 +01:00
eb130f2906 Move primary version to PHP 8.1
8.0 is still supported for now, but won't be updated any longer.
2023-04-26 16:03:33 +01:00
3b09c3a48a actions: updated setup-php-action to pmmp/setup-php-action@c7fb29d835 2023-04-26 14:40:39 +01:00
87781cff4d Update GitHub Actions PHP versions 2023-04-26 14:38:40 +01:00
db0cf4bb5a Update composer dependencies 2023-04-26 14:35:05 +01:00
a0346fb6d3 Merge branch 'minor-next' into major-next 2023-04-26 14:29:32 +01:00
eb4679fefd Merge remote-tracking branch 'origin/stable' into minor-next 2023-04-26 14:28:29 +01:00
a4f2b99ed5 InGamePacketHandler: queue slots for syncing if they appear in requestChangedSlots
this is essentially a prediction without the actual predicted item. We have to sync these regardless of what happens.

fixes #5708
2023-04-24 14:06:29 +01:00
3ecc980bc4 ÂInventoryManagerEntry: fixed incorrect PHPDoc type 2023-04-24 13:42:11 +01:00
107b56154b ItemStackRequestExecutor: fixed stonecutter recipes
this uses the same dodgy hack used by CraftingTransaction, which assumes that getResultsFor() does not care about the crafting inputs.

While this is currently OK, since none of the currently-implemented recipes care about inputs anyway, it will become a problem when we implement shulker box recipes, so this needs to be addressed.

However, it can't be addressed without BC breaks, so this will have to be dealt with in PM5.

closes #5715
2023-04-24 13:35:00 +01:00
f86fde064d CraftingManager: fixed uninitialized field
I'm having deja vu about this ...
2023-04-24 12:34:34 +01:00
edcaeef831 VanillaBlocks: reduce width of element block registration 2023-04-21 21:33:45 +01:00
d4ca566fd0 Move block permutation generation into Block
this allows sealing off a whole bunch of internal APIs.
2023-04-21 20:38:28 +01:00
6c0ad9589b Block: rename isSameType() to hasSameTypeId()
this should remove any ambiguity about its behaviour.
2023-04-21 20:25:21 +01:00
84a16ce69a HandlerList: fixed crash on getting unused priority
these sub-arrays are no longer allocated if no handlers are registered.

fixes #5713
2023-04-21 16:19:15 +01:00
d06d3bc871 4.19.4 is next 2023-04-21 15:53:05 +01:00
11e34b3e5c Release 4.19.3 2023-04-21 15:53:02 +01:00
f9318bf286 TimingsHandler: stop throwing exceptions when timers aren't stopped in the right order
this is usually because of an uncaught exception interacting with a try...finally block.
This will normally result in a crash anyway, and we don't want to obscure the real error.
2023-04-21 15:38:11 +01:00
769be8e140 Fix CSÂ 2023-04-20 00:18:32 +01:00
c878bd8289 Merge remote-tracking branch 'origin/minor-next' into major-next 2023-04-20 00:18:19 +01:00
71b78b02d3 Merge remote-tracking branch 'origin/stable' into minor-next 2023-04-19 23:57:26 +01:00
4147d0dc75 tools/generate-blockstate-upgrade-schema: give better errors when a weird new blockstate version is found 2023-04-19 16:43:29 +01:00
674b65f789 Item: optimise serializeCompoundTag() a little 2023-04-18 16:18:34 +01:00
a77fc8109f TypeConverter: avoid repeated calls to getId() and getMeta() 2023-04-18 15:02:52 +01:00
6102740ee3 TypeConverter: use a less slow hack to restore meta values on items sent by the client
this isn't even really needed anymore, since we don't decode items from the client since 4.18.

However, this may still be useful for tools.
2023-04-18 15:00:34 +01:00
40168a457e TypeConverter: fixed coreItemStackToNet() causing item NBT to be prepared twice
hasNamedTag() calls getNamedTag(), which calls serializeCompoundTag(), which writes the item's properties into the given NBT tag.
2023-04-18 14:43:25 +01:00
d07acd0013 RakLibInterface: split error ID into 4-character chunks
this makes it easier to read, since the error ID can't be copy-pasted from the disconnection screen on the client.
2023-04-17 14:05:46 +01:00
0629d11e13 Avoid unnecessary events work in handleDataPacket if the events have no registered handlers
this particular optimisation became possible thanks to changes in 4.19.

I observed that the allocation of Event objects and calling ->call() was costing us a significant percentage of the time taken in PlayerAuthInputPacket handlers. This change produces a measurable 2 microsecond reduction in overhead for PlayerAuthInputPacket handling when players are not moving (10.7 -> 8.7 microseconds). On a server with 200 players, this translates into a 1% reduction in CPU load for PlayerAuthInputPacket alone. It will also benefit other packets, but not to the extent that PlayerAuthInputPacket benefits.
2023-04-16 20:51:55 +01:00
9561ae5af7 Entity: micro optimisation for checkBlockIntersections() 2023-04-16 17:57:51 +01:00
56fbd45dd5 Entity: avoid double-checking block intersections for moving entities
fixes #1824
2023-04-16 17:38:26 +01:00
b5dc72b0ee tools/simulate-chunk-selector: fixed the script being completely broken
getopt() behaviour is really, really dumb
2023-04-16 16:47:17 +01:00
4ba57f2b03 RegisteredListener: use try...finally to stop timings
While event handlers should not throw exceptions, we need to make sure the timings get stopped in the correct order, because the parent Event timer will be stopped due to using a finally block.
If this happens while the handler timing is still running, a second exception will occur, obscuring the real error.
2023-04-16 00:40:43 +01:00
1026811741 Merge branch 'minor-next' into major-next 2023-04-14 21:00:08 +01:00
84cb070d56 Merge branch 'stable' into minor-next 2023-04-14 20:12:33 +01:00
df0d72bf61 4.19.3 is next 2023-04-14 18:43:44 +01:00
a534ac759a Release 4.19.2 2023-04-14 18:43:41 +01:00
5ab954b7a0 Update composer dependencies 2023-04-14 18:31:57 +01:00
6c6f686f8e Timings: be more intelligent about shortening timer names
non-pocketmine classes may reuse the names of pocketmine core classes. We don't want timers to get erroneously reused in this case.
2023-04-14 18:24:53 +01:00
bf7975da57 Timings: use class to index packet timings, not IDs
on multi version servers, the same packet may have different IDs, or different packets might use the same ID. In these cases, we don't want the timings to get split up or erroneously reused.
2023-04-14 18:22:35 +01:00
7aeedd8220 Timings: fixed every player getting its own timings
we need a more consistent way to deal with this
2023-04-14 17:32:56 +01:00
3dd1ce2d02 4.19.2 is next 2023-04-14 16:47:46 +01:00
5a29d07021 Release 4.19.1 2023-04-14 16:47:43 +01:00
692e1253c6 Fixed AABB height for farmland and grass paths (fixed in 1.19.50) 2023-04-14 16:02:28 +01:00
ab0c444823 Player: fixed ticking chunks not being re-registered if they never left the view distance
closes #5699
2023-04-14 16:02:28 +01:00
e48a4aaa55 World: fixed chunk ticking not being disabled by setting chunk ticking radius to 0
I can't believe I missed this ...
2023-04-14 16:02:28 +01:00
6fc4ce0f86 ÂTimingsCommand: include HTTP response code in debug message
we should probably show this in the regular response message, but we need new translations for that.
2023-04-14 16:02:27 +01:00
6acabf7a1b Block: add clarifying note about isSameType()
I'm still not happy with this method though...
2023-04-13 13:40:53 +01:00
10243c7b2c Bump phpstan/phpstan from 1.10.11 to 1.10.13 (#5697)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.11 to 1.10.13.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.11...1.10.13)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-13 13:19:24 +01:00
b122703fd0 BaseCoral: fixed late property initialization 2023-04-13 13:18:47 +01:00
e40774d62f Block: make internal methods private (they are no longer used outside of Block) 2023-04-13 13:06:56 +01:00
027d8f7377 always the CS... 2023-04-13 12:55:18 +01:00
5950707267 Block: simplify required type data / state data bits code 2023-04-13 12:55:09 +01:00
6cace51a21 Remove unused variable 2023-04-13 12:47:17 +01:00
6703f46a08 Remove random dead TODOs 2023-04-13 12:47:08 +01:00
874fdf5adb ItemBlock: reference blocks directly (take 2)
This was first attempted in f64dc01bd1, but reverted, since I hadn't considered how to handle stripping state data from blocks.

This removes the abusable API RuntimeBlockStateRegistry::fromTypeId() and related methods. These were only used to allow ItemBlocks to magically start referencing other blocks if the blocks were overridden by a plugin, but this was never a well-supported use-case anyway.

Instead of relying on RuntimeBlockStateRegistry, we remember the state that the block had during its constructor, and use that to normalize the non-item properties for asItem().

closes #5609
2023-04-13 12:44:54 +01:00
1c626baf1a Fixed dodgy custom block registration test 2023-04-13 12:27:55 +01:00
c3a2199f0e Reduce global usage in world providers 2023-04-13 12:05:37 +01:00
499b29b53a Merge branch 'minor-next' into major-next 2023-04-12 21:04:08 +01:00
8102586ee0 Merge branch 'stable' into minor-next 2023-04-12 21:04:03 +01:00
18b528f72d ItemStackRequestExecutor: fixed borked taking of created items
closes #5695
2023-04-12 21:01:46 +01:00
0336394098 Human: remove useless NameTag tag
this is not written anywhere, so this code never does anything.
2023-04-12 16:44:10 +01:00
7e92da126d DelegateInventory: fixed slots being synced twice and breaking ItemStackRequests
the second time the slot is synced, there is no prediction, so the slot update isn't associated with a request anymore. This causes subsequent requests in the same packet to fail, since the dependency request ID isn't associated with the slot anymore.

This change fixes the problem by only allowing the backing inventory to trigger a call to DelegateInventory->on*Change(). While we could have removed and re-added the listener instead, this way is safer since it doesn't assume that the backing inventory won't modify the given item in setItem().

closes #5692
2023-04-12 15:43:51 +01:00
b80d7a57e3 Merge branch 'minor-next' into major-next 2023-04-11 23:56:28 +01:00
1569bed37a Merge branch 'stable' into minor-next 2023-04-11 23:56:22 +01:00
ba62e0f9cb WorldManager: fixed borked pre-generation for new worlds' spawn terrain
perhaps directly altering the behaviour of selectChunks() wasn't a good
idea? ...
2023-04-11 23:55:53 +01:00
a6e79c5004 TimingsHandler: remove useless paste metadata
these fields are not used by any version of timings, so this code is redundant.
2023-04-11 23:45:01 +01:00
858d4a2ed2 changelog: fixed indentation
I have no idea what happened here...
2023-04-11 23:35:14 +01:00
18658cb74d 5.0.0-BETA3 is next 2023-04-11 23:27:01 +01:00
501 changed files with 14386 additions and 5246 deletions

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
.github/readme/pocketmine-dark-rgb.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

BIN
.github/readme/pocketmine-rgb.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

View File

@ -12,23 +12,23 @@ jobs:
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Clone pmmp/PocketMine-Docker repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: pmmp/PocketMine-Docker
fetch-depth: 1
@ -53,7 +53,7 @@ jobs:
run: echo NAME=$(echo "${GITHUB_REPOSITORY,,}") >> $GITHUB_OUTPUT
- name: Build image for tag
uses: docker/build-push-action@v4.0.0
uses: docker/build-push-action@v5.0.0
with:
push: true
context: ./pocketmine-mp
@ -66,7 +66,7 @@ jobs:
- name: Build image for major tag
if: steps.channel.outputs.CHANNEL == 'stable'
uses: docker/build-push-action@v4.0.0
uses: docker/build-push-action@v5.0.0
with:
push: true
context: ./pocketmine-mp
@ -79,7 +79,7 @@ jobs:
- name: Build image for minor tag
if: steps.channel.outputs.CHANNEL == 'stable'
uses: docker/build-push-action@v4.0.0
uses: docker/build-push-action@v5.0.0
with:
push: true
context: ./pocketmine-mp
@ -92,7 +92,7 @@ jobs:
- name: Build image for latest tag
if: steps.channel.outputs.CHANNEL == 'stable'
uses: docker/build-push-action@v4.0.0
uses: docker/build-push-action@v5.0.0
with:
push: true
context: ./pocketmine-mp

View File

@ -18,7 +18,12 @@ require dirname(__DIR__, 2) . '/vendor/autoload.php';
/**
* @phpstan-return array<string, mixed>
*/
function generateDiscordEmbed(string $version, string $channel, string $description, string $detailsUrl, string $sourceUrl, string $pharDownloadUrl, string $buildLogUrl, int $newsPingRoleId) : array{
function generateDiscordEmbed(string $version, string $channel, string $description, string $detailsUrl, string $sourceUrl, string $pharDownloadUrl, string $buildLogUrl, int $newsPingRoleId, ?string $phpDownloadUrl) : array{
if($phpDownloadUrl !== null){
$phpEmbedLink = " | [PHP Binaries]($phpDownloadUrl)";
}else{
$phpEmbedLink = "";
}
return [
"content" => "<@&$newsPingRoleId> New PocketMine-MP release: $version ($channel)",
"embeds" => [
@ -27,7 +32,7 @@ function generateDiscordEmbed(string $version, string $channel, string $descript
"description" => <<<DESCRIPTION
$description
[Details]($detailsUrl) | [Source Code]($sourceUrl) | [Build Log]($buildLogUrl) | [Download]($pharDownloadUrl)
[Details]($detailsUrl) | [Source Code]($sourceUrl) | [Build Log]($buildLogUrl) | [Download]($pharDownloadUrl)$phpEmbedLink
DESCRIPTION,
"url" => $detailsUrl,
"color" => $channel === "stable" ? 0x57ab5a : 0xc69026
@ -84,10 +89,21 @@ $detailsUrl = $buildInfoJson["details_url"];
$sourceUrl = $buildInfoJson["source_url"];
$pharDownloadUrl = $buildInfoJson["download_url"];
$buildLogUrl = $buildInfoJson["build_log_url"];
$phpBinaryUrl = $buildInfoJson["php_download_url"] ?? null;
$description = $releaseInfoJson["body"];
$discordPayload = generateDiscordEmbed($buildInfoJson["base_version"], $buildInfoJson["channel"], $description, $detailsUrl, $sourceUrl, $pharDownloadUrl, $buildLogUrl, (int) $newsPingRoleId);
$discordPayload = generateDiscordEmbed(
$buildInfoJson["base_version"],
$buildInfoJson["channel"],
$description,
$detailsUrl,
$sourceUrl,
$pharDownloadUrl,
$buildLogUrl,
(int) $newsPingRoleId,
$phpBinaryUrl
);
$response = Internet::postURL(
$hookURL,

View File

@ -10,12 +10,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.24.0
uses: shivammathur/setup-php@2.26.0
with:
php-version: 8.0
php-version: 8.1
- name: Restore Composer package cache
uses: actions/cache@v3

View File

@ -11,16 +11,18 @@ jobs:
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
php-version: [8.1]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: true
- name: Setup PHP
uses: shivammathur/setup-php@2.24.0
uses: shivammathur/setup-php@2.26.0
with:
php-version: 8.0
php-version: ${{ matrix.php-version }}
- name: Restore Composer package cache
uses: actions/cache@v3
@ -58,8 +60,21 @@ jobs:
echo CHANGELOG_SUFFIX=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "" : "-" . \pocketmine\VersionInfo::BUILD_CHANNEL;') >> $GITHUB_OUTPUT
echo PRERELEASE=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "false" : "true";') >> $GITHUB_OUTPUT
- name: Generate PHP binary download URL
id: php-binary-url
run: |
echo PHP_BINARY_URL="${{ github.server_url }}/${{ github.repository_owner }}/PHP-Binaries/releases/tag/php-${{ matrix.php-version }}-latest" >> $GITHUB_OUTPUT
- name: Generate build info
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} ${{ steps.build-number.outputs.BUILD_NUMBER }} ${{ github.run_id }} > build_info.json
run: |
php build/generate-build-info-json.php \
${{ github.sha }} \
${{ steps.get-pm-version.outputs.PM_VERSION }} \
${{ github.repository }} \
${{ steps.build-number.outputs.BUILD_NUMBER }} \
${{ github.run_id }} \
${{ steps.php-binary-url.outputs.PHP_BINARY_URL }} \
> build_info.json
- name: Upload release artifacts
uses: actions/upload-artifact@v3
@ -71,7 +86,7 @@ jobs:
${{ github.workspace }}/build_info.json
- name: Create draft release
uses: ncipollo/release-action@v1.12.0
uses: ncipollo/release-action@v1.13.0
with:
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
commit: ${{ github.sha }}
@ -84,3 +99,5 @@ jobs:
**For Minecraft: Bedrock Edition ${{ steps.get-pm-version.outputs.MCPE_VERSION }}**
Please see the [changelogs](${{ github.server_url }}/${{ github.repository }}/blob/${{ steps.get-pm-version.outputs.PM_VERSION }}/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}${{ steps.get-pm-version.outputs.CHANGELOG_SUFFIX }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
:information_source: Download the recommended PHP binary [here](${{ steps.php-binary-url.outputs.PHP_BINARY_URL }}).

View File

@ -6,47 +6,26 @@ on:
workflow_dispatch:
jobs:
build-php:
name: Prepare PHP
runs-on: ${{ matrix.image }}
strategy:
matrix:
image: [ubuntu-20.04]
php: [8.0.28, 8.1.16, 8.2.3]
steps:
- name: Build and prepare PHP cache
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
phpstan:
name: PHPStan analysis
needs: build-php
runs-on: ${{ matrix.image }}
strategy:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: [8.0.28, 8.1.16, 8.2.3]
php: ["8.1", "8.2"]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup PHP
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
uses: pmmp/setup-php-action@2.0.0
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
- name: Restore Composer package cache
uses: actions/cache@v3
with:
@ -58,34 +37,30 @@ jobs:
composer-v2-cache-
- name: Install Composer dependencies
run: php composer.phar install --prefer-dist --no-interaction
run: composer install --prefer-dist --no-interaction
- name: Run PHPStan
run: ./vendor/bin/phpstan analyze --no-progress --memory-limit=2G
phpunit:
name: PHPUnit tests
needs: build-php
runs-on: ${{ matrix.image }}
strategy:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: [8.0.28, 8.1.16, 8.2.3]
php: ["8.1", "8.2"]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup PHP
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
uses: pmmp/setup-php-action@2.0.0
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
- name: Restore Composer package cache
uses: actions/cache@v3
with:
@ -97,36 +72,32 @@ jobs:
composer-v2-cache-
- name: Install Composer dependencies
run: php composer.phar install --prefer-dist --no-interaction
run: composer install --prefer-dist --no-interaction
- name: Run PHPUnit tests
run: ./vendor/bin/phpunit --bootstrap vendor/autoload.php --fail-on-warning tests/phpunit
integration:
name: Integration tests
needs: build-php
runs-on: ${{ matrix.image }}
strategy:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: [8.0.28, 8.1.16, 8.2.3]
php: ["8.1", "8.2"]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: true
- name: Setup PHP
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
uses: pmmp/setup-php-action@2.0.0
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
- name: Restore Composer package cache
uses: actions/cache@v3
with:
@ -138,34 +109,30 @@ jobs:
composer-v2-cache-
- name: Install Composer dependencies
run: php composer.phar install --no-dev --prefer-dist --no-interaction
run: composer install --no-dev --prefer-dist --no-interaction
- name: Run integration tests
run: ./tests/travis.sh -t4
codegen:
name: Generated Code consistency checks
needs: build-php
runs-on: ${{ matrix.image }}
strategy:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: [8.0.28, 8.1.16, 8.2.3]
php: ["8.1", "8.2"]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup PHP
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
uses: pmmp/setup-php-action@2.0.0
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
- name: Restore Composer package cache
uses: actions/cache@v3
with:
@ -177,7 +144,7 @@ jobs:
composer-v2-cache-
- name: Install Composer dependencies
run: php composer.phar install --no-dev --prefer-dist --no-interaction
run: composer install --no-dev --prefer-dist --no-interaction
- name: Regenerate registry annotations
run: php build/generate-registry-annotations.php src
@ -191,6 +158,9 @@ jobs:
- name: Regenerate BedrockData available files constants
run: php build/generate-bedrockdata-path-consts.php
- name: Regenerate YmlServerProperties constants
run: php build/generate-pocketmine-yml-property-consts.php
- name: Verify code is unchanged
run: |
git diff
@ -203,13 +173,13 @@ jobs:
fail-fast: false
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.24.0
uses: shivammathur/setup-php@2.26.0
with:
php-version: 8.0
tools: php-cs-fixer:3.11
php-version: 8.1
tools: php-cs-fixer:3.17
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,51 +0,0 @@
<?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);
const VERSIONS = [
"8.0",
"8.1",
"8.2"
];
$workflowFile = file_get_contents(__DIR__ . '/main.yml');
$newWorkflowFile = $workflowFile;
foreach(VERSIONS as $v){
$releaseInfo = file_get_contents("https://secure.php.net/releases?json&version=$v");
if($releaseInfo === false){
throw new \RuntimeException("Failed to contact php.net API");
}
$data = json_decode($releaseInfo, true);
if(!is_array($data) || !isset($data["version"]) || !is_string($data["version"]) || preg_match('/^\d+\.\d+\.\d+(-[A-Za-z\d]+)?$/', $data["version"]) === 0){
throw new \RuntimeException("Invalid data returned by API");
}
$updated = preg_replace("/$v\.\d+/", $data["version"], $newWorkflowFile);
if($updated !== $newWorkflowFile){
echo "Updated $v revision to " . $data["version"] . "\n";
}
$newWorkflowFile = $updated;
}
if($workflowFile !== $newWorkflowFile){
echo "Writing modified workflow file\n";
file_put_contents(__DIR__ . '/main.yml', $newWorkflowFile);
}

View File

@ -8,12 +8,13 @@ on:
jobs:
build:
runs-on: ubuntu-latest
concurrency: update-updater-api # only one job can run at a time, to avoid git conflicts when updating the repository
steps:
- name: Install jq
run: sudo apt update && sudo apt install jq -y
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
repository: ${{ github.repository_owner }}/update.pmmp.io
ssh-key: ${{ secrets.UPDATE_PMMP_IO_DEPLOY_KEY }}

View File

@ -30,6 +30,13 @@
<option name="USE_TAB_CHARACTER" value="true" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="Markdown">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="PHP">
<option name="CLASS_BRACE_STYLE" value="1" />
<option name="METHOD_BRACE_STYLE" value="1" />

View File

@ -2,13 +2,13 @@
## Pre-requisites
- A bash shell (git bash is sufficient for Windows)
- [`git`](https://git-scm.com) available in your shell
- PHP 8.0 or newer available in your shell
- PHP 8.1 or newer available in your shell
- [`composer`](https://getcomposer.org) available in your shell
## Custom PHP binaries
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
- [Prebuilt binaries](https://jenkins.pmmp.io/job/PHP-8.0-Aggregate)
- [Prebuilt binaries](https://github.com/pmmp/PHP-Binaries/releases)
- [Compile scripts](https://github.com/pmmp/php-build-scripts) are provided as a submodule in the path `build/php`
If you use a custom binary, you'll need to replace `composer` usages in this guide with `path/to/your/php path/to/your/composer.phar`.
@ -29,11 +29,5 @@ Run `composer make-server` using your preferred PHP binary. It'll drop a `Pocket
You can also use the `--out` option to change the output filename.
There is a bug in PHP that might cause an error which looks like this:
```
Fatal error: Uncaught BadMethodCallException: unable to create temporary file in PocketMine-MP/build/server-phar.php:119
```
You can work around it by setting `ulimit -n` to some bigger number, e.g. `8192`, or by updating your PHP version to at least 8.0.3.
## Running PocketMine-MP from source code
Run `src/PocketMine.php` using your preferred PHP binary.

View File

@ -18,6 +18,28 @@ Larger contributions like feature additions should be preceded by a [Change Prop
## Other things you'll need
- [git](https://git-scm.com/)
## List of `pocketmine` namespaces which are in other repos
PocketMine-MP has several dependencies which are independent from the main server code. Most of them use the `pocketmine` namespace.
Some of these add extra classes to packages which already exist in PocketMine-MP.
Take a look at the table below if you can't find the class or function you're looking for.
| Source URL | Namespace, class or function |
|:----------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------|
| [pmmp/BedrockProtocol](https://github.com/pmmp/BedrockProtocol) | `pocketmine\network\mcpe\protocol` |
| [pmmp/BinaryUtils](https://github.com/pmmp/BinaryUtils) | `pocketmine\utils\BinaryDataException`</br>`pocketmine\utils\BinaryStream`</br>`pocketmine\utils\Binary` |
| [pmmp/Color](https://github.com/pmmp/Color) | `pocketmine\color` |
| [pmmp/ErrorHandler](https://github.com/pmmp/ErrorHandler) | `pocketmine\errorhandler` |
| [pmmp/Log](https://github.com/pmmp/Log) | `AttachableLogger`</br>`BufferedLogger`</br>`GlobalLogger`</br>`LogLevel`</br>`Logger`</br>`PrefixedLogger`</br>`SimpleLogger` |
| [pmmp/Math](https://github.com/pmmp/Math) | `pocketmine\math` |
| [pmmp/NBT](https://github.com/pmmp/NBT) | `pocketmine\nbt` |
| [pmmp/RakLibIpc](https://github.com/pmmp/RakLibIpc) | `raklib\server\ipc` |
| [pmmp/RakLib](https://github.com/pmmp/RakLib) | `raklib` |
| [pmmp/Snooze](https://github.com/pmmp/Snooze) | `pocketmine\snooze` |
| [pmmp/ext-chunkutils2](https://github.com/pmmp/ext-chunkutils2) | `pocketmine\world\format\LightArray`</br>`pocketmine\world\format\PalettedBlockArray`</br>`pocketmine\world\format\io\SubChunkConverter` |
| [pmmp/ext-morton](https://github.com/pmmp/ext-morton) | `morton2d_decode`</br>`morton2d_encode`</br>`morton3d_decode`</br>`morton3d_encode` |
| [pmmp/ext-libdeflate](https://github.com/pmmp/ext-libdeflate) | `libdeflate_deflate_compress`</br>`libdeflate_gzip_compress`</br>`libdeflate_zlib_compress` |
## Choosing a target branch
PocketMine-MP has three primary branches of development.

View File

@ -4,8 +4,8 @@
<img src="https://github.com/pmmp/PocketMine-MP/blob/stable/.github/readme/pocketmine.png" alt="The PocketMine-MP logo" title="PocketMine" loading="eager" />
<![endif]-->
<picture>
<source srcset="https://github.com/pmmp/PocketMine-MP/raw/stable/.github/readme/pocketmine-dark.png" media="(prefers-color-scheme: dark)">
<img src="https://github.com/pmmp/PocketMine-MP/raw/stable/.github/readme/pocketmine.png" loading="eager" />
<source srcset="https://raw.githubusercontent.com/pmmp/PocketMine-MP/stable/.github/readme/pocketmine-dark-rgb.gif" media="(prefers-color-scheme: dark)">
<img src="https://raw.githubusercontent.com/pmmp/PocketMine-MP/stable/.github/readme/pocketmine-rgb.gif" loading="eager" />
</picture>
</a><br>
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
@ -26,7 +26,7 @@
- [Docker image](https://github.com/pmmp/PocketMine-MP/pkgs/container/pocketmine-mp)
- [Plugin repository](https://poggit.pmmp.io/plugins)
## Discussion/Help
## Community & Support
- [Forums](https://forums.pmmp.io/)
- [Discord](https://discord.gg/bmSAZBG)
- [StackOverflow](https://stackoverflow.com/tags/pocketmine)
@ -35,7 +35,7 @@
* [Building and running from source](BUILDING.md)
* [Developer documentation](https://devdoc.pmmp.io) - General documentation for PocketMine-MP plugin developers
* [Latest release API documentation](https://apidoc.pmmp.io) - Doxygen API documentation generated for each release
* [Latest bleeding-edge API documentation](https://apidoc-dev.pmmp.io) - Doxygen API documentation generated weekly from `next-major` branch
* [Latest bleeding-edge API documentation](https://apidoc-dev.pmmp.io) - Doxygen API documentation generated weekly from `major-next` branch
* [DevTools](https://github.com/pmmp/DevTools/) - Development tools plugin for creating plugins
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
* [Contributing Guidelines](CONTRIBUTING.md)

View File

@ -44,6 +44,7 @@ use function fwrite;
use function is_string;
use function ksort;
use function mb_strtoupper;
use function preg_replace;
use function sort;
use function strrpos;
use function strtoupper;
@ -138,7 +139,7 @@ function generateBlockStateNames(BlockPaletteReport $data) : void{
fwrite($output, generateClassHeader(BlockStateNames::class));
foreach(Utils::stringifyKeys($data->seenStateValues) as $state => $values){
$constName = mb_strtoupper($state, 'US-ASCII');
$constName = mb_strtoupper(preg_replace("/^minecraft:/", "mc_", $state) ?? throw new AssumptionFailedError("This regex is not invalid"), 'US-ASCII');
fwrite($output, "\tpublic const $constName = \"$state\";\n");
}
@ -158,7 +159,7 @@ function generateBlockStringValues(BlockPaletteReport $data) : void{
continue;
}
$anyWritten = true;
$constName = mb_strtoupper($stateName . "_" . $value, 'US-ASCII');
$constName = mb_strtoupper(preg_replace("/^minecraft:/", "mc_", $stateName) . "_" . $value, 'US-ASCII');
fwrite($output, "\tpublic const $constName = \"$value\";\n");
}
if($anyWritten){

View File

@ -23,13 +23,13 @@ declare(strict_types=1);
require dirname(__DIR__) . '/vendor/autoload.php';
if(count($argv) !== 6){
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)> <build number> <github actions run ID>\n");
if(count($argv) !== 7){
fwrite(STDERR, "required args: <git hash> <tag name> <github repo (owner/name)> <build number> <github actions run ID> <PHP binary download URL>\n");
exit(1);
}
echo json_encode([
"php_version" => sprintf("%d.%d", PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
"php_version" => sprintf("%d.%d", PHP_MAJOR_VERSION, PHP_MINOR_VERSION), //deprecated
"base_version" => \pocketmine\VersionInfo::BASE_VERSION,
"build" => (int) $argv[4],
"is_dev" => \pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD,
@ -41,4 +41,5 @@ echo json_encode([
"download_url" => "https://github.com/$argv[3]/releases/download/$argv[2]/PocketMine-MP.phar",
"source_url" => "https://github.com/$argv[3]/tree/$argv[2]",
"build_log_url" => "https://github.com/$argv[3]/actions/runs/$argv[5]",
"php_download_url" => $argv[6],
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR) . "\n";

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\build\generate_item_serializer_ids;
use pocketmine\data\bedrock\item\BlockItemIdMap;
use pocketmine\errorhandler\ErrorToExceptionHandler;
use pocketmine\network\mcpe\convert\ItemTypeDictionaryFromDataHelper;
use pocketmine\network\mcpe\protocol\serializer\ItemTypeDictionary;
@ -45,10 +46,10 @@ function constifyMcId(string $id) : string{
return strtoupper(explode(":", $id, 2)[1]);
}
function generateItemIds(ItemTypeDictionary $dictionary) : void{
function generateItemIds(ItemTypeDictionary $dictionary, BlockItemIdMap $blockItemIdMap) : void{
$ids = [];
foreach($dictionary->getEntries() as $entry){
if($entry->getNumericId() < 256){ //blockitems are serialized via BlockStateSerializer
if($entry->getStringId() === "minecraft:air" || $blockItemIdMap->lookupBlockId($entry->getStringId()) !== null){ //blockitems are serialized via BlockStateSerializer
continue;
}
$ids[$entry->getStringId()] = $entry->getStringId();
@ -92,6 +93,7 @@ if($raw === false){
}
$dictionary = ItemTypeDictionaryFromDataHelper::loadFromString($raw);
generateItemIds($dictionary);
$blockItemIdMap = BlockItemIdMap::getInstance();
generateItemIds($dictionary, $blockItemIdMap);
echo "Done. Don't forget to run CS fixup after generating code.\n";

View File

@ -0,0 +1,120 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
use pocketmine\utils\Filesystem;
use pocketmine\utils\Utils;
require dirname(__DIR__) . '/vendor/autoload.php';
$defaultConfig = yaml_parse(Filesystem::fileGetContents(dirname(__DIR__) . '/resources/pocketmine.yml'));
if(!is_array($defaultConfig)){
fwrite(STDERR, "Invalid default pocketmine.yml\n");
exit(1);
}
$constants = [];
/**
* @param mixed[] $properties
* @param string[] $constants
* @phpstan-param array<string, string> $constants
* @phpstan-param-out array<string, string> $constants
*/
function collectProperties(string $prefix, array $properties, array &$constants) : void{
foreach($properties as $propertyName => $property){
$fullPropertyName = ($prefix !== "" ? $prefix . "." : "") . $propertyName;
$constName = str_replace([".", "-"], "_", strtoupper($fullPropertyName));
$constants[$constName] = $fullPropertyName;
if(is_array($property)){
collectProperties($fullPropertyName, $property, $constants);
}
}
}
collectProperties("", $defaultConfig, $constants);
ksort($constants, SORT_STRING);
$file = fopen(dirname(__DIR__) . '/src/YmlServerProperties.php', 'wb');
if($file === false){
fwrite(STDERR, "Failed to open output file\n");
exit(1);
}
fwrite($file, "<?php\n");
fwrite($file, <<<'HEADER'
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
HEADER
);
fwrite($file, "declare(strict_types=1);\n\n");
fwrite($file, "namespace pocketmine;\n\n");
fwrite($file, <<<'DOC'
/**
* @internal
* Constants for all properties available in pocketmine.yml.
* This is generated by build/generate-pocketmine-yml-property-consts.php.
* Do not edit this file manually.
*/
DOC
);
fwrite($file, "final class YmlServerProperties{\n");
fwrite($file, <<<'CONSTRUCTOR'
private function __construct(){
//NOOP
}
CONSTRUCTOR
);
foreach(Utils::stringifyKeys($constants) as $constName => $propertyName){
fwrite($file, "\tpublic const $constName = '$propertyName';\n");
}
fwrite($file, "}\n");
fclose($file);
echo "Done. Don't forget to run CS fixup after generating code.\n";

View File

@ -27,11 +27,12 @@ use pocketmine\block\utils\BellAttachmentType;
use pocketmine\block\utils\CopperOxidation;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\DirtType;
use pocketmine\block\utils\DripleafState;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\FroglightType;
use pocketmine\block\utils\LeverFacing;
use pocketmine\block\utils\MobHeadType;
use pocketmine\block\utils\MushroomBlockType;
use pocketmine\block\utils\SkullType;
use pocketmine\block\utils\SlabType;
use pocketmine\item\MedicineType;
use pocketmine\item\PotionType;
@ -145,12 +146,13 @@ $enumsUsed = [
CopperOxidation::getAll(),
CoralType::getAll(),
DirtType::getAll(),
DripleafState::getAll(),
DyeColor::getAll(),
FroglightType::getAll(),
LeverFacing::getAll(),
MedicineType::getAll(),
MushroomBlockType::getAll(),
SkullType::getAll(),
MobHeadType::getAll(),
SlabType::getAll(),
SuspiciousStewType::getAll(),
PotionType::getAll()

View File

@ -54,13 +54,13 @@ Released 11th April 2023.
### `pocketmine\timings`
- The following API constants have been deprecated:
- `Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX` - this is superseded by timings group support (see `Timings::GROUP_BREAKDOWN`)
- `Timings::INCLUDED_BY_OTHER_TIMINGS_PREFIX` - this is superseded by timings group support (see `Timings::GROUP_BREAKDOWN`)
- The following API constants have been added:
- `Timings::GROUP_BREAKDOWN` - this group makes a timer appear in the `Minecraft - Breakdown` section of a timings report
- `Timings::GROUP_BREAKDOWN` - this group makes a timer appear in the `Minecraft - Breakdown` section of a timings report
- The following API methods have been added:
- `public TimingsHandler->getGroup() : string` - returns the name of the table in which this timer will appear in a timings report
- `public TimingsHandler->getGroup() : string` - returns the name of the table in which this timer will appear in a timings report
- The following API methods have changed signatures:
- `TimingsHandler->__construct()` now accepts an additional, optional `string $group` parameter, which defaults to `Minecraft`.
- `TimingsHandler->__construct()` now accepts an additional, optional `string $group` parameter, which defaults to `Minecraft`.
### `pocketmine\world`
#### Highlights
@ -75,3 +75,37 @@ It works similarly to the `ChunkLoader` system, in that chunks will be ticked as
- The following API methods have been added:
- `public World->registerTickingChunk(ChunkTicker $ticker, int $chunkX, int $chunkZ) : void` - registers a chunk to be ticked by the given `ChunkTicker`
- `public World->unregisterTickingChunk(ChunkTicker $ticker, int $chunkX, int $chunkZ) : void` - unregisters a chunk from being ticked by the given `ChunkTicker`
# 4.19.1
Released 14th April 2023.
## Fixes
- Fixed inventory rollbacks when spreading items in ender chests.
- Fixed inventory rollbacks when shift-clicking to craft and the outputs would have been split across multiple inventory slots.
- Fixed incorrect spawn terrain generation for newly created worlds.
- Fixed `chunk-ticking.tick-radius` not disabling chunk ticking when set to `0`.
- Fixed chunks not being ticked if they previously left a player's simulation distance without leaving their view distance.
- Fixed height of collision boxes for Grass Path and Farmland blocks.
# 4.19.2
Released 14th April 2023.
## Fixes
- Fixed player timings duplication leading to extremely large timings reports when timings runs for a long time with many players.
- Packet timings are now indexed by class FQN instead of packet ID. This prevents erroneous timer reuse on packet ID reuse (e.g. multi version servers).
- Fixed entity timings being shared by different classes with the same short name. This led to incorrect timings being reported for some entities when custom entities were used.
# 4.19.3
Released 21st April 2023.
## General
- Error IDs for `Packet processing error` disconnects are now split into 4-character chunks to make them easier to type (since they can't be copied from the disconnection screen of a client).
## Fixes
- Fixed entity-block intersections being checked twice per tick. Besides wasting CPU time, this may have caused unexpected behaviour during entity-block interactions with blocks like water or cacti.
- Fixed performance issue in network inventory synchronization due item NBT being prepared twice.
- Fixed `tools/simulate-chunk-selector.php` argument parsing being completely broken (weird behaviour of PHP `getopt()`).
## Internals
- `TimingsHandler->stopTiming()` now logs an error message if a subtimer wasn't stopped, rather than throwing an exception.
- Due to interactions between `try...finally` and unexpected errors, throwing exceptions made it difficult for plugin developers to debug errors in their plugins, since it obscured the original error.

79
changelogs/4.20.md Normal file
View File

@ -0,0 +1,79 @@
**For Minecraft: Bedrock Edition 1.19.80**
### Note about API versions
Plugins which don't touch the `pocketmine\network\mcpe` namespace are compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the `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.
### Interim releases
If you're upgrading from 4.17.x directly to 4.20.x, please also read the following changelogs, as the interim releases contain important changes:
- [4.18.0](https://github.com/pmmp/PocketMine-MP/blob/4.20.0/changelogs/4.18.md#4180) - major performance improvements, internal network changes, minor API additions
- [4.19.0](https://github.com/pmmp/PocketMine-MP/blob/4.20.0/changelogs/4.19.md#4190) - minor performance improvements, improved timings system, minor API additions
# 4.20.0
Released 26th April 2023.
## General
- Added support for Minecraft: Bedrock Edition 1.19.80.
- Removed support for older versions.
## Fixes
- Fixed packet processing error when attempting to use a stonecutter.
- Fixed armor slots containing ghost items when cancelling right-click to equip armor.
- Fixed crash in `HandlerList->getListenersByPriority()` when no listeners are registered at the given priority.
## API
### `pocketmine\block`
- The following API methods have been added:
- `public BaseSign->getEditorEntityRuntimeId() : int` - returns the entity runtime ID of the player currently editing this sign, or `null` if none
- `public BaseSign->setEditorEntityRuntimeId(?int $editorEntityRuntimeId) : $this` - sets the entity runtime ID of the player currently editing this sign
### `pocketmine\player`
- The following API methods have been added:
- `public Player->openSignEditor(Vector3 $position) : void` - opens the client-side sign editor GUI for the given position
# 4.20.1
Released 27th April 2023.
## Fixes
- Fixed server crash when firing a bow while holding arrows in the offhand slot.
## Internals
- `ItemStackContainerIdTranslator::translate()` now requires an additional `int $slotId` parameter and returns `array{int, int}` (translated window ID, translated slot ID) to be used with `InventoryManager->locateWindowAndSlot()`.
- `InventoryManager->locateWindowAndSlot()` now checks if the translated slot actually exists in the requested inventory, and returns `null` if not. Previously, it would return potentially invalid slot IDs without checking them, potentially leading to crashes.
# 4.20.2
Released 4th May 2023.
## Fixes
- Fixed all types of wooden logs appearing as oak in the inventory.
- Fixed a performance issue in `BaseInventory->canAddItem()` (missing `continue` causing useless logic to run).
# 4.20.3
Released 6th May 2023.
## Improvements
- Reduced memory usage of `RuntimeBlockMapping` from 25 MB to 9 MB. Since every thread has its own copy of the block map, this saves a substantial amount of memory.
## Fixes
- Fixed players falling through blocks in spectator mode.
- Fixed timings reports getting bloated by prolific usage of `PluginManager->registerEvent()`.
- This was caused by creating a new timings handler for each call, regardless of whether a timer already existed for the given event and callback.
- Fixed `Full Server Tick` and other records being missing from timings reports.
- This was caused by timings handler depth not getting reset when timings was disabled and later re-enabled.
# 4.20.4
Released 6th May 2023.
## Fixes
- Fixed players being forced into flight mode in every game mode.
- Moral of the story: do not assume anything in Mojang internals does what its name suggests...
# 4.20.5
Released 30th May 2023.
## Fixes
- Fixed server crash due to a bug in upstream dependency [`netresearch/jsonmapper`](https://github.com/cweiske/JsonMapper).

77
changelogs/4.21.md Normal file
View File

@ -0,0 +1,77 @@
**For Minecraft: Bedrock Edition 1.19.80**
### Note about API versions
Plugins which don't touch the `pocketmine\network\mcpe` namespace, and don't use reflection or any internal methods,
will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the `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.
# 4.21.0
Released 17th May 2023.
## General
- PHP 8.1 is now required. Most plugins should run without changes, but some might need to be updated due to language-level deprecations.
- Ticking chunk count is now shown separately from loaded chunk count in the `/status` command, providing useful performance information.
- Further improved performance of ticking chunk selection.
- Improved performance of some inventory functions.
- Reduced server memory footprint in most cases by ~9 MB per thread.
- Due to large overhead, async network compression is now only used for packets larger than 10 KB by default.
## Configuration
- Added the following new `pocketmine.yml` configuration options:
- `network.async-compression-threshold` - minimum size of packet which will be compressed using `AsyncTask`
- Default is 10 KB, which means that very few packets will use async compression in practice. This is because the overhead of compressing async is currently so high that it's not worth it for smaller packets.
## Timings
- Timings reports no longer include the unused metadata fields `Entities` and `LivingEntities`.
- Timings reports now correctly calculate the peak time of a timer.
- Previously it was incorrectly recorded as the longest time spent in a single tick, rather than the longest time spent in a single activation.
- Timings report version has been bumped to `2` to reflect this change.
- All world-specific timers now have generic aggregate timings, making it much easier to locate performance patterns across all worlds.
## Gameplay
- Players in spectator mode are no longer able to pick blocks, and now have finite resources similar to survival mode.
## API
### `pocketmine\world`
- The following API methods have been added:
- `public World->getTickingChunks() : list<int>` - returns a list of chunk position hashes (a la `World::chunkHash()`) which are currently valid for random ticking
### `pocketmine\inventory`
- The following API methods have been added:
- `protected BaseInventory->getMatchingItemCount(int $slot, Item $test, bool $checkDamage, bool $checkTags) : int` - returns the number of items in the given stack if the content of the slot matches the test item, or zero otherwise
- This should be overridden if directly extending `BaseInventory` to provide a performance-optimised version. A slow default implementation is provided, but it will be removed in the future.
## Internals
### Entity
- Unused `NameTag` tag is no longer saved for `Human` entities.
### Inventory
- `BaseInventory` now uses a new internal method `getMatchingItemCount()` to locate items in the inventory without useless cloning. This improves performance of various API methods, such as `addItem()`, `contains()`, and more.
- Specialization of `Inventory->isSlotEmpty()` in `BaseInventory` subclasses has been added to improve performance of some API methods.
### Network
- `RuntimeBlockMapping` no longer keeps all block palette NBT data in memory.
- This significantly reduces server idle memory footprint.
- For multi-version implementations, this will have a significant impact on memory usage, since a different block palette is often required to support each version.
- NBT will be lazy-loaded into memory and cached if `getBedrockKnownStates()` is called. However, this is not used by PocketMine-MP under normal circumstances.
- Removed unnecessary usage of `Utils::validateCallableSignature()` from some internal network pathways, improving performance.
### Scheduler
- `AsyncPool` no longer double-checks progress updates on completed tasks.
### World
- Ticking chunks are now tracked in `World->validTickingChunks` and `World->recheckTickingChunks`.
- This allows avoiding rechecking every ticking chunk for validity during ticking chunk selection, improving performance.
- In some cases, this allows bypassing chunk selection entirely, reducing selection cost to zero.
- Registered but ineligible ticking chunks are no longer rechecked every tick.
- This was causing wasted cycles during async worker backlog.
- The internal system must call `markTickingChunkForRecheck()` whenever a ticking chunk's eligibility for ticking has potentially changed, rather than just when it has changed from a yes to a no.
# 4.21.1
Released 30th May 2023.
## Fixes
- Fixed server crash due to a bug in upstream dependency [`netresearch/jsonmapper`](https://github.com/cweiske/JsonMapper).

58
changelogs/4.22.md Normal file
View File

@ -0,0 +1,58 @@
# 4.22.0
Released 7th June 2023.
**For Minecraft: Bedrock Edition 1.20.0**
This is a support release for Minecraft: Bedrock Edition 1.20.0.
**Plugin compatibility:** Plugins for previous 4.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## Interim releases
If you're upgrading from 4.20.x directly to 4.22.x, please also read the following changelogs, as the interim releases contain important changes:
- [4.21.0](https://github.com/pmmp/PocketMine-MP/blob/4.22.0/changelogs/4.21.md#4210) - PHP 8.1 minimum version, minor performance improvements
## General
- Added support for Minecraft: Bedrock Edition 1.20.0.
- Removed support for older versions.
## Fixes
- Removed deprecated `ReflectionProperty::setAccessible()` calls.
- Fixed jukebox music not stopping when destroyed by an explosion.
# 4.22.1
Released 9th June 2023.
## Fixes
- Replaced workaround for an old teleporting client bug:
- This workaround broke due to an additional client bug introduced by 1.20, causing players to become frozen to observers when teleported.
- The original client bug has still not been fixed, meaning a new workaround was needed, but no perfect solution could be found.
- The new workaround involves broadcasting teleport movements as regular movements, which causes unwanted interpolation between the old and new positions, but otherwise works correctly. This solution is not ideal, but it is the best we can do for now.
- See issues [#4394](https://github.com/pmmp/PocketMine-MP/issues/4394) and [#5810](https://github.com/pmmp/PocketMine-MP/issues/5810) for more details.
# 4.22.2
Released 1st July 2023.
## Changes
- Added obsoletion warnings to the server log at the end of the startup sequence.
## Fixes
- Fixed players being disconnected en masse with "Not authenticated" messages.
- This occurred due to a check intended to disable the old authentication key after July 1st.
- We expected that the new key would have been deployed by Mojang by now, but it seems like that has not yet happened.
- Due to the lack of a hard date for the key changeover, we guessed that July 1st would be a safe bet, but this appears to have backfired.
- This version will accept both old and new keys indefinitely.
- A security release will be published to remove the old key after the transition occurs.
# 4.22.3
Released 11th July 2023.
## Fixes
- Fixed mishandling of NBT leading to a server crash when editing signs.
- Fixed an edge case crash that could occur in `AsyncTask->__destruct()` when thread-local storage referenced other `AsyncTask` objects.
## Internals
- Added a concurrency lock to prevent the `update-updater-api` GitHub Action from running for multiple releases at the same time (which would have caused one of them to fail due to git conflicts).

68
changelogs/4.23.md Normal file
View File

@ -0,0 +1,68 @@
# 4.23.0
Released 12th July 2023.
**For Minecraft: Bedrock Edition 1.20.10**
This is a support release for Minecraft: Bedrock Edition 1.20.10.
**Plugin compatibility:** Plugins for previous 4.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## General
- Added support for Minecraft: Bedrock Edition 1.20.10.
- Removed support for older versions.
## Fixes
- Fixed Docker image build failure due to outdated `build/php` submodule.
# 4.23.1
Released 14th July 2023.
## Fixes
- Hardened validation of JWT signing keys in `LoginPacket`.
- Fixed server crash due to a bug in upstream dependency [`netresearch/jsonmapper`](https://github.com/cweiske/JsonMapper).
# 4.23.2
Released 18th July 2023.
## Fixes
- Fixed login errors due to a new `sandboxId` field appearing in the Xbox Live authentication data in `LoginPacket`. All clients, regardless of version, are affected by this change.
# 4.23.3
Released 24th July 2023.
## Documentation
- Fixed typo in `ChunkSelector::selectChunks()` documentation.
## Fixes
- Fixed the server not stopping properly during crash conditions on *nix platforms.
- Fixed `HORSE_EQUIP` and `SMITHING_TABLE_TEMPLATE` container UI types not being handled by `ItemStackContainerIdTranslator`. This bug prevented plugins from implementing missing inventory types.
- Player emotes no longer broadcast messages to other players. This was unintended behaviour caused by a client-side behavioural change.
- Shulker boxes no longer support the placement of torches or other similar blocks.
- Fire can now be placed on upper slabs and the top of upside-down stairs.
# 4.23.4
Released 1st August 2023.
## Fixes
- Fixed exponentially increasing lag when many hundreds of non-mergeable dropped items occupied the same space. This disproportionately affected SkyBlock servers due to large cactus farms using water to collect items together.
# 4.23.5
Released 9th August 2023.
## General
- Updated translation data to [pmmp/Language 2.19.6](https://github.com/pmmp/Language/releases/tag/2.19.6).
## Fixes
- Fixed `PluginBase->saveResource()` leaking file resources when the data file already exists in the plugin's data folder. This bug existed since 2014 and was only discovered recently.
- Fixed coral blocks becoming dead after calling `getDropsForCompatibleTool()` on them.
- Fixed `BlockDeathEvent->getOldState()` returning a block which is already dead.
# 4.23.6
Released 21st August 2023.
## Fixes
- Added a workaround for armor and other inventories not working correctly after inventory sync. This is caused by a client bug.

17
changelogs/4.24.md Normal file
View File

@ -0,0 +1,17 @@
# 4.24.0
Released 20th September 2023.
**For Minecraft: Bedrock Edition 1.20.30**
This is a support release for Minecraft: Bedrock Edition 1.20.30.
**Plugin compatibility:** Plugins for previous 4.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## General
- Added support for Minecraft: Bedrock Edition 1.20.30.
- Removed support for older versions.
- Updated 4.x obsoletion message.

View File

@ -93,3 +93,123 @@ Released 11th April 2023.
## Internals
- Make use of `Item->canStackWith()` instead of `Item->equals()` wherever possible, to make the code more readable.
# 5.0.0-BETA3
Released 17th May 2023.
**This release includes changes from the following releases:**
- [4.19.1](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.19.md#4191)
- [4.19.2](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.19.md#4192)
- [4.19.3](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.19.md#4193)
- [4.20.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4200)
- [4.20.1](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4201)
- [4.20.2](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4202)
- [4.20.3](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4203)
- [4.20.4](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.20.md#4204)
- [4.21.0](https://github.com/pmmp/PocketMine-MP/blob/5.0.0-BETA3/changelogs/4.21.md#4210)
## General
- Improved light propagation performance by 10-15%.
## Fixes
- Fixed late initialization of coral type in `BaseCoral`.
## Tools
- `tools/generate-blockstate-upgrade-schema.php` has the following improvements:
- Now generates better errors when inconsistent blockstate versions are encountered.
- Now generates more stable outputs when re-run on the same input.
- Output now uses `copiedState` in `remappedStates` where possible. This significantly reduces the size of the output for blocks with partially flattened states.
## Gameplay
- The following blocks have been added:
- Cave Vines
- The following items have been added:
- Glow Berries
- Mangrove Boat (incomplete)
- Fixed flower pots being able to be placed inside flower pots.
## API
### `pocketmine\block`
- The following API methods have been renamed:
- `Block->isSameType()` -> `Block->hasSameTypeId()`
- `Block->describeType()` -> `Block->describeBlockItemState()`
- `Block->describeState()` -> `Block->describeBlockOnlyState()`
- The following API methods have been removed:
- `Block->getRequiredTypeDataBits()`
- `Block->getRequiredStateDataBits()`
- The following API methods have been added:
- `public Block->generateStatePermutations() : \Generator<int, Block, void, void>` - yields all possible states this block type can be in (used for `RuntimeBlockStateRegistry`)
- The following API methods have signature changes:
- `Sapling::__construct()` now accepts `SaplingType $saplingType` instead of `TreeType $treeType`
- `RuntimeBlockStateRegistry->register()` no longer accepts an `$override` parameter.
- The following classes have been added:
- `utils\SaplingType` - enum of all sapling types
- `utils\TreeType` has been moved to `pocketmine\world\generator\object` namespace.
### `pocketmine\data\bedrock\item\upgrade`
- The following API methods have been added:
- `public ItemIdMetaUpgrader->getSchemas() : array<int, BlockStateUpgradeSchema>` - returns a list of loaded schemas indexed by schema ID
- `public ItemIdMetaUpgradeSchema->getRenamedIds() : array<string, string>` - returns a map of old ID -> new ID
- `public ItemIdMetaUpgradeSchema->getRemappedMetas() : array<string, array<int, string>>` - returns a map of old ID -> list of old meta -> new ID
### `pocketmine\event\block`
- The following API methods have been added:
- `public BlockGrowEvent->getPlayer() : ?Player` - returns the player that triggered the block growth, or `null` if it was not triggered by a player
- The following API methods have signature changes:
- `BlockGrowEvent::__construct()` now accepts an optional `?Player $player` parameter.
### `pocketmine\event\world`
- The following classes have been added:
- `WorldDisplayNameChangeEvent` - called when a world's display name is changed
### `pocketmine\item`
- `Boat` now uses a new `BoatType` enum instead of `TreeType`. This is because not all tree types have an associated boat type, and some boat types are not made from tree materials (e.g. bamboo raft).
- The following API methods have been removed:
- `Boat->getWoodType()`
- The following API methods have been added:
- `public Boat->getType() : BoatType`
- `public Item->getStateId() : int` - returns an encoded ID containing the item type ID and encoded item state
- The following API methods have been renamed:
- `Item->describeType()` -> `Item->describeState()`
- The following classes have been added:
- `BoatType` - enum of all boat types
- The following API methods have signature changes:
- `BoatType::__construct()` now accepts `BoatType $boatType` instead of `TreeType $woodType`.
### `pocketmine\world`
- The following API methods have been added:
- `public World->setDisplayName(string $name) : void`
### `pocketmine\world\format`
- Fixed outdated documentation for various methods of `Chunk`.
### `pocketmine\world\format\io\data`
- The following API interface requirements have been added:
- `public WorldData->setDisplayName(string $value) : void`
## Internals
- Reduced global usage in world providers. In the future, we want to have blockstate deserializers etc. injected rather than being global singletons.
- `BlockStateUpgrader` now always updates the blockstate version, even if no changes were made. PM itself doesn't require this, but it's useful for tools to know whether to upgrade the data again (e.g. in testing scenarios).
- `BlockStateDictionary` memory usage is now reduced from 9 MB to 3.5 MB using various techniques, including string reuse and binary-encoded states.
- `RuntimeBlockMapping` has been renamed to `BlockTranslator`.
- Singletons in the `pocketmine\network\mcpe\convert` package have been centralized under `TypeConverter`. In the future, this will be injected where needed, allowing different converters to be used for different sessions (useful for multiversion).
- Overriding of serializers and deserializers of items and blocks is now consistently disallowed. Due to the lack of a good reason to allow overriding built-in blocks and items, this is no longer allowed.
# 5.0.0-BETA4
Released 23rd May 2023.
## General
- [`ext-pmmpthread` version 6.0.0](https://github.com/pmmp/ext-pmmpthread/releases/6.0.0) (renamed from `ext-pthreads`) is now required. This version has API changes compared to pthreads v5. Please read the linked changelog for details.
- [`pocketmine/snooze` version 0.5.0](https://github.com/pmmp/Snooze/releases/0.5.0) is now required.
- `pocketmine/classloader` and `pocketmine/log-pthreads` packages have been removed. The relevant classes from these packages are now included in-house in the `pocketmine/thread` namespace.
- `BaseClassLoader` is replaced with `pocketmine\thread\ThreadSafeClassLoader`
- `ThreadedLogger` is replaced by `pocketmine\thread\ThreadSafeLogger`
- `AttachableThreadedLogger` is replaced by `pocketmine\thread\AttachableThreadSafeLogger`
- `ThreadedLoggerAttachment` is replaced by `pocketmine\thread\ThreadSafeLoggerAttachment`
## Fixes
- Fixed crash on unknown blocks due to late initialization of properties in `UnknownBlock`.
## API changes
### `pocketmine\scheduler`
- `AsyncTask->setResult()` now works with thread-safe objects. This was previously not possible due to limitations in the `pthreads` extension.

791
changelogs/5.0.md Normal file
View File

@ -0,0 +1,791 @@
# 5.0.0
Released 1st June 2023.
**For Minecraft: Bedrock Edition 1.19.80**
5.0.0 is a major feature update to PocketMine-MP, including support for Bedrock worlds from 1.13 onwards, a large array of new blocks and items, and various changes to the plugin API.
It is **not** compatible with plugins written for 4.x.y, and plugins may require code changes to work with it.
**As this changelog is quite large, its accuracy and completeness cannot be guaranteed.**
Make sure you're looking at the [latest revision](https://github.com/pmmp/PocketMine-MP/blob/stable/changelogs/5.0.md), as it may be amended after release.
## Core
- Worlds are now saved according to the Bedrock 1.19.80 format.
- Worlds generated by Bedrock from 1.13.0 and up are now supported (previously, only worlds up to 1.12 were supported).
- `/particle` now accepts strings for particle data instead of integers.
- `/particle` no longer accepts integers for block or item IDs.
- The usage of `blockcrack`, `iconcrack` and `blockdust` particle types in `/particle` now follows the same pattern as
other particle types, with the data for each being passed in the `data` parameter instead of being baked into the
particle name.
- Commands are now enabled by default in worlds exported from PocketMine-MP to Bedrock.
## Build system
- `build/generate-block-serializer-consts.php` has been added to generate `BlockTypeNames`, `BlockStateNames` and `BlockStateStringValues` in the `pocketmine\data\bedrock\block` package.
- `build/generate-item-type-names.php` has been added to generate `ItemTypeNames` in the `pocketmine\data\bedrock\item` package.
- `build/generate-runtime-enum-serializers.php` has been added to generate `RuntimeEnumSerializer`, `RuntimeEnumSerializerTrait`, and `RuntimeEnumSizeCalculatorTrait` in `pocketmine\data\runtime` package.
## Localization
- Localized disconnect messages are now used in the following cases:
- Server full
- Player not on the server whitelist
- Player on the server ban list
- Invalid skin
- Invalid username
- Kicked using `/kick`
- Banned using `/ban`
- Failure to find a safe spawn position
- Session open, session close and session player name discovery messages are now localized.
- All permissions now have localized descriptions. These are not currently used by PocketMine-MP, but may be useful for plugins.
## Performance
- Improved performance of dropping block inventory contents when the block is destroyed.
- Improved light propagation performance by 10-15%.
- [`ext-pmmpthread` version 6.0.0](https://github.com/pmmp/ext-pmmpthread/releases/tag/6.0.0) is now used, featuring significant performance improvements for thread-safe objects and various threading use-cases.
## Tools
- The following tool scripts have been added:
- `generate-block-palette-spec.php` - generates a JSON file with a readable overview of blocks, their state
properties, and their possible values
- `generate-blockstate-upgrade-schema.php` - generates JSON blockstate upgrade schemas like those found
in [BedrockBlockUpgradeSchema](https://github.com/pmmp/BedrockBlockUpgradeSchema)
- `generate-item-upgrade-schema.php` - generates JSON item ID/meta upgrade schemas like those found
in [BedrockItemUpgradeSchema](https://github.com/pmmp/BedrockItemUpgradeSchema)
- `generate-bedrock-data-from-packets.php` - generates various files for [BedrockData](https://github.com/pmmp/BedrockData)
- This script accepts a txt file containing base64-encoded packet dumps.
- This script has been in use for several years, but has only now been open-sourced.
- It's used to generate data such as crafting recipes, creative inventory data, and various other blobs of data needed to support the current version of Minecraft: Bedrock Edition.
## Gameplay
### Blocks
- Added the following new blocks:
- Amethyst Block
- Ancient Debris
- Azalea Leaves
- Basalt
- Blackstone blocks, slabs, stairs, and walls
- Cakes with Candle & Dyed Candle
- Calcite
- Candle & Dyed Candle
- Cartography Table (not currently usable due to maps not being implemented)
- Cauldron
- Cave Vines
- Chain
- Chiseled Deepslate
- Chiseled Nether Bricks
- Chiseled Polished Blackstone
- Chorus Flower
- Chorus Plant
- Cobbled Deepslate blocks, slabs, stairs, and walls
- Copper Ore
- Copper block (random oxidation not yet implemented)
- Crached Deepslate Tiles
- Cracked Deepslate Bricks
- Cracked Nether Bricks
- Cracked Polished Blackstone Bricks
- Crimson buttons, doors, fences, fence gates, hyphae, planks, pressure plates, signs, slabs, stairs, stems, and trapdoors
- Crying Obsidian
- Cut Copper block, stairs and slabs (random oxidation not yet implemented)
- Deepslate
- Deepslate Bricks blocks, slabs, stairs, and walls
- Deepslate Ores (coal, copper, diamond, emerald, gold, iron, lapis lazuli, redstone)
- Deepslate Tiles blocks, slabs, stairs, and walls
- Flowering Azalea Leaves
- Froglight (pearlescent, verdant, ochre)
- Gilded Blackstone
- Glow Item Frame
- Hanging Roots
- Honeycomb Block
- Light Block
- Lightning Rod
- Mangrove Leaves
- Mangrove Roots
- Mangrove buttons, doors, fences, fence gates, logs, planks, pressure plates, signs, slabs, stairs, trapdoors, and wood
- Mud Bricks blocks, slabs, stairs, and walls
- Muddy Mangrove Roots
- Nether Gold Ore
- Netherite Block
- Polished Basalt
- Polished Blackstone Bricks blocks, slabs, stairs, and walls
- Polished Blackstone blocks, buttons, pressure plates, slabs, stairs, and walls
- Polished Deepslate blocks, slabs, stairs, and walls
- Quartz Bricks
- Reinforced Deepslate
- Rooted Dirt
- Sculk
- Shroomlight
- Smithing Table
- Smooth Basalt
- Soul Fire
- Soul Lantern
- Soul Soil
- Soul Torch
- Spore Blossom
- Tinted Glass
- Tuff
- Twisting Vines
- Warped Wart Block
- Warped buttons, doors, fences, fence gates, hyphae, planks, pressure plates, signs, slabs, stairs, stems, and trapdoors
- Weeping Vines
- Wither Rose
- Added support for basalt generators
- Added support for dyeing sign text and making it glow.
- All-sided logs ("wood", for want of a better name) can now be placed in X, Y, and Z orientations.
- Coral and coral fans now behave correctly when placed out of water (they no longer immediately die).
- Fixed dead bush being able to be placed on some invalid blocks (e.g. stone).
- Fixed lava setting entities on fire for an incorrect duration (Java vs Bedrock inconsistency).
- Fixed sugarcane not being able to be placed on some blocks.
- Iron Ore and Gold Ore now drop Raw Iron and Raw Gold respectively, instead of the ore blocks.
- Item frames can now be placed on the top and bottom of blocks.
- Stripping logs by right-clicking them with an axe is now supported.
- TNT can now be ignited by fire charges.
- Vines can now only be placed on the side of full-cube blocks.
- Walls now connect when placed, following the pre-1.16 logic. (1.16 logic is planned to be implemented, but currently low priority.)
- Anvils are now damaged when they hit the ground after falling.
- Added missing sounds for anvils hitting the ground after falling.
- Anvils now damage entities when they fall on top of them.
### Items
- Added the following new items:
- Amethyst Shard
- Antidote (from Education Edition)
- Copper Ingot
- Disc Fragment (5)
- Echo Shard
- Elixir (from Education Edition)
- Eye Drops (from Education Edition)
- Fire Charge
- Glow Berries
- Glow Ink Sac
- Honey Bottle
- Honeycomb
- Mangrove Boat (incomplete)
- Music Disc (5)
- Music Disc (Otherside)
- Music Disc (Pigstep)
- Netherite Axe
- Netherite Boots
- Netherite Chestplate
- Netherite Helmet
- Netherite Ingot
- Netherite Leggings
- Netherite Pickaxe
- Netherite Scrap
- Netherite Shovel
- Netherite Sword
- Phantom Membrane
- Raw Copper
- Raw Gold
- Raw Iron
- Spyglass
- Suspicious Stew
- Tonic (from Education Edition)
- Glass bottles can now be filled with water by clicking on a water source block.
- Implemented Swift Sneak enchantment.
- Armour durability is now only reduced when the wearer receives a type of damage that the armour can protect against.
- Bells now ring when hit by a projectile.
### Worlds
- World height of -64 to 319 is now supported.
- Added support for 3D biomes. This isn't used by PocketMine-MP yet, but is necessary to be able to fully load 1.18 worlds.
## API
### General
- Union and mixed native parameter, return and property types are now used where appropriate.
- Protected and public properties now use native property types wherever possible.
- Parameter and return typehints have been applied in many places where it wasn't previously possible.
### Dependencies
- [`ext-pmmpthread` version 6.0.0](https://github.com/pmmp/ext-pmmpthread/releases/6.0.0) (renamed from `ext-pthreads`) is now required. This version features major API changes and improvements. Please read the [upgrading guide](https://github.com/pmmp/ext-pmmpthread/blob/fork/docs/UPGRADING_4.x_to_6.0.md) for details.
- [`pocketmine/snooze` version 0.5.0](https://github.com/pmmp/Snooze/releases/0.5.0) is now required.
- [`pocketmine/raklib` version 0.15.0](https://github.com/pmmp/RakLib/releases/0.15.0) is now required.
- [`pocketmine/raklib-ipc` version 0.2.0](https://github.com/pmmp/RakLibIpc/releases/0.2.0) is now required.
- `pocketmine/classloader` and `pocketmine/log-pthreads` packages have been removed. The relevant classes from these packages are now included in-house in the `pocketmine/thread` namespace.
- `BaseClassLoader` is replaced with `pocketmine\thread\ThreadSafeClassLoader`
- `ThreadedLogger` is replaced by `pocketmine\thread\ThreadSafeLogger`
- `AttachableThreadedLogger` is replaced by `pocketmine\thread\AttachableThreadSafeLogger`
- `ThreadedLoggerAttachment` is replaced by `pocketmine\thread\ThreadSafeLoggerAttachment`
- `webmozart/path-util` has been removed (replaced by [`symfony/filesystem`](https://github.com/symfony/filesystem)).
### `pocketmine\block`
#### Highlights
- Blocks no longer use internal Minecraft IDs and metadata to identify themselves. All APIs associated with legacy IDs
and meta have been removed.
- A new set of runtime IDs generated from `VanillaBlocks` is used to identify block types. These IDs are defined
in `BlockTypeIds`.
- These new IDs are used for runtime representation of blocks on chunks, and for type comparison purposes.
- Block type IDs are used at **runtime only**. **Do not store them in configs or databases**, as they are subject to
change without warning.
- Block type IDs are **specific to PocketMine-MP** and have no relation to the IDs used by Minecraft.
- Block type IDs cannot be negative
- Block type IDs must not be reused, even if overriding an already defined block
- Block state properties (e.g. facing, colour, etc.) are now represented by PM-specific state data instead of legacy
metadata. The state data consists of:
- Block-item state properties - retained by items when the block is broken (colour, wet/dry, coral type, etc.) - handled by `Block->describeBlockItemState()`
- Block-only state data - discarded when the block is broken (facing direction, lit/unlit, powered/unpowered, etc.) - handled by `Block->describeBlockOnlyState()`
- Chunks now store dynamic state ID derived from the runtime type ID and runtime (PocketMine-MP defined) state data.
- Introduced "type tags" concept, which allows marking certain blocks as having certain behaviours.
- The idea for this system was borrowed from the Minecraft Java tags system.
- It's still in very early concept stage, but is currently used for deciding which types of blocks plants can be placed on without needing to enumerate every single ID in every class, eliminating a bunch of boilerplate code and improving consistency.
- All `Block` descendents now accept `BlockTypeInfo` in the constructor, instead of `BlockBreakInfo`. This allows for future additions without needing to change dozens of overridden constructors.
- `&$returnedItems` reference parameter is now used in some places such as `Block->onInteract()` to enable actions to return items to players without caring about whether they are in creative or anything else.
- This eliminates boilerplate code of deciding whether to set the player's held item or not, as well as automatically dropping any overflow items that don't fit into the inventory.
- This is currently used when filling/emptying cauldrons using buckets or glass bottles.
- Dependency between `RuntimeBlockStateRegistry` (previously `BlockFactory`) and `VanillaBlocks` has been inverted.
- Now, blocks types are defined in `VanillaBlocks`
- `RuntimeBlockStateRegistry` automatically registers states for blocks defined in `VanillaBlocks`.
- Manual registration in `RuntimeBlockStateRegistry` is still required for custom blocks (see section below about registering new blocks).
- `RuntimeBlockStateRegistry` now has only one purpose - to map internal blockstate IDs to `Block` objects when reading blocks from chunks. It should not be used by plugins unless registering new blocks.
- To get a block at runtime, e.g. stone, use `VanillaBlocks::STONE()`
- To load a block from **old** config or database data:
1. Use `GlobalBlockStateHandlers::getUpgrader()->upgradeIntIdMeta()` to convert it to modern data
2. Pass the data to `GlobalBlockStateHandlers::getDeserializer()` to get a blockstate ID
3. Pass the blockstate ID to `RuntimeBlockStateRegistry::fromStateId()` to get a `Block` instance
- Prefer using `StringToItemParser` wherever possible for configs and databases (see `lookupAliases()` and `lookupBlockAliases()`).
#### Registering new blocks
##### In a plugin
To add a vanilla block in a plugin which isn't yet supported by PocketMine-MP, do the following:
1. Get a new type ID using `BlockTypeIds::newId()` - _you'll want to keep this in a property somewhere if you want to
compare using `getTypeId()` later_
2. Set up the block type somewhere - _this can be anywhere you like, e.g. a plugin main class property, but using
a `RegistryTrait` class is recommended - you'll need this later to create new instances of the block_
3. Register the block in `RuntimeBlockStateRegistry` - _this informs the server of all the block's possible states so
that it can be read from chunks at runtime_
4. Register a deserializer for the block's Minecraft ID in `BlockStateToObjectDeserializer` - _needed for the block to
be recognized when loaded from disk_
5. Register a serializer for the block in `BlockObjectToStateSerializer` - _needed for the block to be saved to disk,
and to be sent over the network_
6. Optionally, register a string alias for the block in `StringToItemParser` - _so that it can be given via `/give`_
To see a demo of how to do this in a plugin, see [this example plugin](https://github.com/pmmp/RegisterBlocksDemoPM5).
Registering custom blocks follows a similar process, but requires additional steps to modify `BlockStateDictionary`
which won't be covered here.
Since this is not currently officially supported by PocketMine-MP, this won't be covered here.
This is admittedly rather more of a hassle than in PM4, but this system offers significantly more flexibility than the
old system.
##### As a PocketMine-MP core contribution
To register a new vanilla block into the core, the process is slightly different:
1. Instead of using `BlockTypeIds::newId()`, add a new constant for the block to `BlockTypeIds`
2. Register the new block in `VanillaBlocks` - `RuntimeBlockStateRegistry` will automagically take notice of all blocks
defined in `VanillaBlocks`
3. Follow steps 4 onwards above
#### Change list
- The following classes have been removed:
- `BlockIdentifierFlattened`
- `BlockLegacyIdHelper`
- `BlockLegacyIds`
- `BlockLegacyMetadata`
- `utils\BlockDataSerializer`
- `utils\ColorInMetadataTrait` - `utils\ColoredTrait` now implements colour type data serialization uniformly
- `utils\InvalidBlockStateException` - this has been superseded by `pocketmine\data\runtime\InvalidSerializedRuntimeDataException`
- `utils\NormalHorizontalFacingInMetadataTrait` - `utils\HorizontalFacingTrait` now implements facing type data serialization uniformly
- `utils\PillarRotationInMetadataTrait` - `utils\PillarRotationTrait` now implements rotation type data serialization uniformly
- The following classes have been renamed:
- `BlockFactory` -> `RuntimeBlockStateRegistry` - this class is now exclusively used for mapping state IDs to block instances for runtime chunk block reading
- `Skull` -> `MobHead`
- `utils\SkullType` -> `utils\MobHeadType`
- `utils\TreeType` -> `pocketmine\world\generator\object\TreeType`
- The following classes have been added:
- `BaseCake`
- `BaseFire`
- `BlockTypeIds` - list of type IDs, one for each entry in `VanillaBlocks`
- `BlockTypeInfo`
- `BlockTypeTags`
- `CakeWithCandle`
- `CakeWithDyedCandle`
- `Candle`
- `CartographyTable`
- `Chain`
- `CopperOre`
- `CopperSlab`
- `CopperStairs`
- `Copper`
- `DyedCandle`
- `GildedBlackstone`
- `GoldOre`
- `HangingRoots`
- `IronOre`
- `Light`
- `LightningRod`
- `NetherGoldOre`
- `Sculk`
- `SmithingTable`
- `SoulFire`
- `WitherRose`
- `utils\CandleTrait`
- `utils\CopperOxidation`
- `utils\CopperTrait`
- `utils\SaplingType` - enum of all sapling types
- `utils\WallConnectionType` - enum of all possible wall connection types
- `utils\WoodTypeTrait`
- `utils\WoodType` - enum of all possible wood types, used for wood material blocks like planks and logs
- The following API methods have been removed:
- `Block->getId()` - for type comparisons, use `Block->getTypeId()` instead
- `Block->getMeta()` - for state comparisons, use `Block->getStateId()` instead
- `Block->getStateBitmask()`
- `Block->readStateFromData()`
- `Block->writeStateToItemMeta()`
- `Block->writeStateToMeta()`
- `BlockFactory->get()` - see notes above about `RuntimeBlockStateRegistry`
- `BlockIdentifier->getAllBlockIds()`
- `BlockIdentifier->getBlockId()`
- `BlockIdentifier->getItemId()`
- `BlockIdentifier->getVariant()`
- `Door->isPowered()`
- `Door->setPowered()`
- `MobHead->isNoDrops()` (previously `Skull->isNoDrops()`)
- `MobHead->setNoDrops()` (previously `Skull->setNoDrops()`)
- `VanillaBlocks::*_GLAZED_TERRACOTTA()` - use `VanillaBlocks::GLAZED_TERRACOTTA()->setColor(DyeColor::WHATEVER())` instead
- `utils\FallableTrait->getId()` is no longer required
- `utils\FallableTrait->getMeta()` is no longer required
- `utils\MobHeadType->getMagicNumber()` (previously `utils\SkullType->getMagicNumber()`)
- `utils\MobHeadType::fromMagicNumber()` (previously `utils\SkullType::fromMagicNumber()`)
- The following constants have been removed:
- `Block::INTERNAL_METADATA_BITS`
- `Block::INTERNAL_METADATA_MASK`
- The following API methods have been renamed:
- `Block->getFullId()` -> `Block->getStateId()`
- `Block->isSameType()` -> `Block->hasSameTypeId()`
- `MobHead->getSkullType()` -> `MobHead->getMobHeadType()` (previously `Skull->getSkullType()`)
- `MobHead->setSkullType()` -> `MobHead->setMobHeadType()` (previously `Skull->setSkullType()`)
- The following API methods have signature changes:
- `Block->onBreak()` now accepts `array<Item> &$returnedItems` reference parameter.
- `Block->onInteract()` now accepts `array<Item> &$returnedItems` reference parameter.
- `Block->readStateFromWorld()` now returns `Block` - this allows blocks to replace themselves with a different block entirely based on world conditions.
- `BlockIdentifier->__construct()` now accepts `int $blockTypeId`, and no longer accepts `int $blockId, int $variant, ?int $itemId`
- `ItemFrame->getFacing()` may now return `Facing::UP` and `Facing::DOWN`
- `ItemFrame->setFacing()` now accepts `Facing::UP` and `Facing::DOWN`
- `Leaves->__construct()` now accepts `LeavesType $leavesType` instead of `TreeType $treeType`
- `RuntimeBlockStateRegistry->register()` no longer accepts an `$override` parameter.
- `Sapling::__construct()` now accepts `SaplingType $saplingType` instead of `TreeType $treeType`
- `utils\SignText::__construct()` now accepts two new optional parameters: `?Color $baseColor` and `bool $glowing`
- `utils\SignText::fromBlob()` now accepts two new optional parameters: `?Color $baseColor` and `bool $glowing`
- The following API methods have been added:
- `protected Block->describeBlockOnlyState(RuntimeDataDescriber $w) : void` - describes state properties which are discarded when the block is broken or block-picked, such as facing, powered, etc.
- `public Block->describeBlockItemState(RuntimeDataDescriber $w) : void` - describes state properties which are kept by the item when the block is broken or block-picked, such as dye color
- `public Block->generateStatePermutations() : \Generator<int, Block, void, void>` - yields all possible states this block type can be in (used for `RuntimeBlockStateRegistry`)
- `public Block->getTypeTags() : array<string>`
- `public Block->hasTypeTag(string $tag) : bool`
- `public Block->isFireProofAsItem() : bool`
- `public Block->onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void`
- `public BlockIdentifier->getBlockTypeId() : int` - returns the block's type ID according to `BlockTypeIds`
- `public Furnace->getFurnaceType() : utils\FurnaceType`
- `public GlazedTerracotta->getColor() : utils\DyeColor` (from `ColoredTrait`) - this was previously unsupported due to legacy limitations
- `public GlazedTerracotta->setColor(utils\DyeColor $color) : $this` (from `ColoredTrait`) - this was previously unsupported due to legacy limitations
- `public Leaves->getLeavesType() : utils\LeavesType` - returns the type of leaves
- `public Wall->getConnection(int $face) : utils\WallConnectionType`
- `public Wall->getConnections() : array<int, utils\WallConnectionType>` - returns the wall's connections and their types (see `utils\WallConnectionType`)
- `public Wall->isPost() : bool`
- `public Wall->setConnection(int $face, ?utils\WallConnectionType $type) : $this`
- `public Wall->setConnections()` - sets the wall's connections and their types (see `utils\WallConnectionType`)
- `public Wall->setPost(bool $post) : $this`
- `public Wood->isStripped() : bool`
- `public Wood->setStripped(bool $stripped) : $this`
- `public static BlockBreakInfo::axe(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : BlockBreakInfo`
- `public static BlockBreakInfo::pickaxe(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : BlockBreakInfo`
- `public static BlockBreakInfo::shovel(float $hardness, ?ToolTier $toolTier = null, ?float $blastResistance = null) : BlockBreakInfo`
- `public static BlockBreakInfo::tier(float $hardness, int $toolType, ToolTier $toolTier, ?float $blastResistance = null) : BlockBreakInfo`
- `public tile\Spawnable->getRenderUpdateBugWorkaroundStateProperties(Block $block) : array<string, Tag>` - allows spawnable tiles to spoof block state properties to work around client-side rendering bugs without actually changing the block server-side
- `public utils\SignText->getBaseColor() : \pocketmine\color\Color`
- `public utils\SignText->isGlowing() : bool`
- The following classes now use new traits, adding API methods and/or properties:
- `FenceGate` uses `utils\WoodTypeTrait`
- `GlazedTerracotta` uses `utils\ColoredTrait`
- `Planks` uses `utils\WoodTypeTrait`
- `Wood` uses `utils\WoodTypeTrait`
- `WoodenButton` uses `utils\WoodTypeTrait`
- `WoodenDoor` uses `utils\WoodTypeTrait`
- `WoodenFence` uses `utils\WoodTypeTrait`
- `WoodenPressurePlate` uses `utils\WoodTypeTrait`
- `WoodenSlab` uses `utils\WoodTypeTrait`
- `WoodenStairs` uses `utils\WoodTypeTrait`
- `WoodenTrapdoor` uses `utils\WoodTypeTrait`
- The following API interface requirements have been added (BC breaking):
- `public utils\Fallable->getFallDamagePerBlock() : float` (default implementation provided by `utils\FallableTrait`)
- `public utils\Fallable->getLandSound() : ?Sound` (default implementation provided by `utils\FallableTrait`)
- `public utils\Fallable->getMaxFallDamage() : float` (default implementation provided by `utils\FallableTrait`)
- `public utils\Fallable->onHitGround(FallingBlock $blockEntity) : bool` (default implementation provided by `utils\FallableTrait`)
### `pocketmine\command`
- Command permissions are now always checked by the server when running a command.
- This only affects commands implemented by extending `Command`. Plugins using `PluginBase->onCommand()` are not affected by this change, since they already had permissions checked by the server anyway.
- Previously, direct inheritors of `Command` were responsible for checking permissions, which required developers to duplicate the same code in every command, and opened lots of potential for security vulnerabilities.
- If you want to do something on permission denied (e.g. sending a special message, or audit logging), you can do so by overriding `Command->testPermission()`, instead of baking the code directly into `Command->execute()`.
- If you don't want to use permissions at all, just create a permission with a default of `true` (or belonging to `pocketmine.group.user`) and assign that.
- `SimpleCommandMap` now requires all commands to have a permission set when registered.
- If you actually want to allow everyone to use your command (not advised), you can add a new permission to the `pocketmine.group.user` group, or use `default: true` for `plugin.yml` permissions.
- The following API methods have changed behaviour:
- `Command->testPermissionSilent()` now returns `false` if there are no permissions associated with the command. This is to prevent commands with no permissions being usable by everyone, which has previously been a source of security issues.
- The following API methods have been added:
- `public Command->getPermissions() : list<string>` - returns a list of permissions which grant usage access to this command. A user with one or more of these permissions will be able to invoke the command's `execute()` method
- `public Command->setPermissions(list<string> $permissions) : void` - sets the permissions which grant usage access to this command. This should be used instead of `setPermission()` with `;` separators (which is now deprecated)
### `pocketmine\crafting`
- JSON models have been updated to reflect updated crafting data format.
- The following enum classes have new members:
- `ShapelessRecipeType` has new members `CARTOGRAPHY` and `SMITHING`
- The following classes have been added:
- `ExactRecipeIngredient` - matches an exact item
- `MetaWildcardRecipeIngredient` - matches an item with the given legacy Minecraft ID, but any metadata value
- `RecipeIngredient` interface
- `TagWildcardRecipeIngredient` - matches an item based on its Minecraft tags, e.g. `minecraft:wooden_tier`
- The following API methods have signature changes:
- `FurnaceRecipe->__construct()` now accepts `RecipeIngredient` instead of `Item`
- `FurnaceRecipe->getInput()` now returns `RecipeIngredient` instead of `Item`
- `PotionContainerChangeRecipe->__construct()` now accepts `string, RecipeIngredient, string` (using Minecraft string IDs instead of legacy integers).
- `PotionContainerChangeRecipe->getIngredient()` now returns `RecipeIngredient` instead of `Item`.
- `PotionContainerChangeRecipe->getInputItemId()` now returns `string` (using Minecraft string IDs instead of legacy integers).
- `PotionContainerChangeRecipe->getOutputItemId()` now returns `string` (using Minecraft string IDs instead of legacy integers).
- `PotionTypeRecipe->__construct()` now accepts `RecipeIngredient` instead of `Item`
- `PotionTypeRecipe->getIngredient()` now returns `RecipeIngredient` instead of `Item`
- `PotionTypeRecipe->getInput()` now returns `RecipeIngredient` instead of `Item`
- `ShapedRecipe->__construct()` now accepts `RecipeIngredient` instead of `Item`
- `ShapedRecipe->getIngredient()` now returns `?RecipeIngredient` instead of `?Item`
- `ShapedRecipe->getIngredientList()` now returns `RecipeIngredient[]` instead of `Item[]`
- `ShapedRecipe->getIngredientMap()` now returns `RecipeIngredient[][]` instead of `Item[][]`
- `ShapelessRecipe->__construct()` `$type` parameter is now mandatory.
- `ShapelessRecipe->__construct()` now accepts `RecipeIngredient` instead of `Item`
- `ShapelessRecipe->getIngredientList()` now returns `RecipeIngredient[]` instead of `Item[]`
### `pocketmine\data`
- New packages `bedrock\block` and `bedrock\item` have been added. These packages contain all the necessary code for loading and saving Bedrock blocks and items from disk.
- New package `runtime` has been added. This package contains code for serializing runtime data for blocks and items.
- `LegacyToStringBidirectionalIdMap` has been reduced to `LegacyToStringIdMap`.
- Since we never map from string ID to legacy ID, bidirectional mapping is no longer necessary.
- This affects the following subclasses:
- `LegacyBiomeIdToStringIdMap`
- `LegacyBlockIdToStringIdMap`
- `LegacyEntityIdToStringIdMap`
- `LegacyItemIdToStringIdMap`
- The following internal API methods have been added:
- `public LegacyToStringIdMap->add(string $string, int $legacy) : void` - adds a mapping from a custom legacy ID to custom string ID, needed for upgrading old saved data
### `pocketmine\entity`
- `Entity` now declares new abstract methods which must be implemented by subclasses:
- `public Entity->getInitialDragMultiplier() : float`
- `public Entity->getInitialGravity() : float`
- The following new API methods have been added:
- `public Living->getDisplayName() : string`
- The following API methods have changed signatures:
- `EntityFactory->register()` no longer accepts a `$legacyMcpeSaveId` parameter (now handled by internal conversions instead).
- The following API methods have been renamed:
- `Entity->isImmobile()` -> `Entity->hasNoClientPredictions()`
- `Entity->setImmobile()` -> `Entity->setNoClientPredictions()`
- The following internal fields have been renamed:
- `Entity->immobile` -> `Entity->noClientPredictions`
- The following classes have been removed:
- `EntityLegacyIds`
### `pocketmine\event`
- The following classes have inheritance changes:
- `block\BlockPlaceEvent` no longer extends `BlockEvent`, and therefore no longer has `getBlock()`. Use `getTransaction()` instead (may contain multiple blocks).
- `BlockFormEvent` now includes information about the block which caused the event.
- The following new classes have been added:
- `world\WorldDisplayNameChangeEvent` - called when a world's display name is changed
- The following classes have been renamed:
- `entity\ExplosionPrimeEvent` -> `entity\EntityPreExplodeEvent`
- The following API methods have been added:
- `public block\BlockFormEvent->getCausingBlock() : Block`
- `public block\BlockGrowEvent->getPlayer() : ?Player` - returns the player that triggered the block growth, or `null` if it was not triggered by a player
- `public block\BlockPlaceEvent->getTransaction() : BlockTransaction` - returns the transaction containing a list of changed block positions and the blockstates they will be changed to
- `public server\DataPacketSendEvent->setPackets(list<ClientboundPacket> $packets) : void`
- The following API methods have changed signatures:
- `block\BlockPlaceEvent->__construct()` now accepts `BlockTransaction $transaction` instead of `Block $blockPlace, Block $blockReplace`
- `entity\EntityPreExplodeEvent->__construct()` has the `$force` parameter renamed to `$radius`
- `entity\EntityPreExplodeEvent->getForce() : float` -> `entity\EntityPreExplodeEvent->getRadius() : float`
- `entity\EntityPreExplodeEvent->setForce(float $force) : void` -> `entity\EntityPreExplodeEvent->setRadius(float $radius) : void`
- The following API methods have been removed:
- `block\BlockPlaceEvent->getBlockReplaced()` - this information is now provided in the `BlockTransaction` object returned by `BlockPlaceEvent->getTransaction()`
- The following new API constants have been added:
- `entity\EntityDamageEvent::CAUSE_FALLING_BLOCK`
- `entity\EntityDamageEvent::MODIFIER_ARMOR_HELMET`
### `pocketmine\event\player`
- `PlayerPreLoginEvent`, `PlayerDuplicateLoginEvent` and `PlayerKickEvent` now supports setting separate log reasons (disconnect reason) and disconnect screen messages.
- The following classes have been removed:
- `PlayerCommandPreprocessEvent`
- The following API methods have changed signatures:
- `PlayerDuplicateLoginEvent->getDisconnectMessage()` now returns `Translatable|string` instead of `string`
- `PlayerDuplicateLoginEvent->setDisconnectMessage()` now accepts `Translatable|string` instead of `string`
- `PlayerKickEvent->getReason()` now returns `Translatable|string` instead of `string`
- `PlayerKickEvent->setReason()` now accepts `Translatable|string` instead of `string`
- `PlayerLoginEvent->getKickMessage()` now returns `Translatable|string` instead of `string`
- `PlayerLoginEvent->setKickMessage()` now accepts `Translatable|string` instead of `string`
- `PlayerPreLoginEvent->getFinalKickMessage()` now returns `Translatable|string` instead of `string`
- `PlayerPreLoginEvent->getKickMessage()` now returns `Translatable|string|null` instead of `string|null`
- `PlayerPreLoginEvent->setKickFlag()` (previously `setKickReason()`) now accepts `Translatable|string $disconnectReason, Translatable|string|null $disconnectScreenMessage = null` instead of `Translatable|string $message`
- `PlayerPreLoginEvent->setKickReason()` now accepts `Translatable|string` for the `$message` parameter instead of `string`
- `PlayerQuitEvent->getQuitReason()` now returns `Translatable|string` instead of `string`
- The following API methods have been removed:
- `PlayerChatEvent->getFormat()` (use `PlayerChatEvent->getChatFormatter()` instead)
- `PlayerChatEvent->setFormat()` (use `PlayerChatEvent->setChatFormatter()` instead)
- `PlayerDuplicateLoginEvent->getDisconnectMessage()` - replaced by `getDisconnectReason()` and `getDisconnectScreenMessage()`
- `PlayerDuplicateLoginEvent->setDisconnectMessage()` - replaced by `setDisconnectReason()` and `setDisconnectScreenMessage()`
- `PlayerKickEvent->getReason()` - replaced by `getDisconnectReason()` and `getDisconnectScreenMessage()`
- `PlayerKickEvent->setReason()` - replaced by `setDisconnectReason()` and `setDisconnectScreenMessage()`
- The following new API methods have been added:
- `public PlayerChatEvent->getChatFormatter() : \pocketmine\player\chat\ChatFormatter` - returns the chat formatter to be used for this event
- `public PlayerChatEvent->setChatFormatter(\pocketmine\player\chat\ChatFormatter $formatter) : void` - sets the chat formatter to be used for this event
- `public PlayerDeathEvent->getDeathScreenMessage() : Translatable|string` - returns the message to be displayed on the death screen
- `public PlayerDeathEvent->setDeathScreenMessage(Translatable|string $deathScreenMessage) : void` - sets the message to be displayed on the death screen
- `public PlayerDuplicateLoginEvent->getDisconnectReason() : Translatable|string` - returns the reason for the disconnection displayed in the console and server log
- `public PlayerDuplicateLoginEvent->getDisconnectScreenMessage() : Translatable|string|null` - returns the message to be displayed on the disconnect screen (the message in `getDisconnectReason()` is used if null is returned)
- `public PlayerDuplicateLoginEvent->setDisconnectReason(Translatable|string $disconnectReason) : void` - sets the reason for the disconnection displayed in the console and server log
- `public PlayerDuplicateLoginEvent->setDisconnectScreenMessage(Translatable|string|null $disconnectScreenMessage) : void` - sets the message to be displayed on the disconnect screen (the message in `setDisconnectReason()` is used if null is passed)
- `public PlayerKickEvent->getDisconnectReason() : Translatable|string` - returns the reason for the disconnection displayed in the console and server log
- `public PlayerKickEvent->getDisconnectScreenMessage() : Translatable|string|null` - returns the message to be displayed on the disconnect screen (the message in `getDisconnectReason()` is used if null is returned)
- `public PlayerKickEvent->setDisconnectReason(Translatable|string $disconnectReason) : void` - sets the reason for the disconnection displayed in the console and server log
- `public PlayerKickEvent->setDisconnectScreenMessage(Translatable|string|null $disconnectScreenMessage) : void` - sets the message to be displayed on the disconnect screen (the message in `setDisconnectReason()` is used if null is passed)
- `public PlayerPreLoginEvent->getDisconnectScreenMessage(int $flag) : Translatable|string|null` - returns the message to be displayed on the disconnect screen for the specified kick flag, if set
- `public PlayerPreLoginEvent->getFinalDisconnectScreenMessage() : Translatable|string|null` - returns the message to be displayed on the disconnect screen, taking into account the kick flags set
- The following classes have inheritance changes:
- `PlayerPreLoginEvent` no longer implements `Cancellable`. This caused unexpected behaviour for most plugin devs due to default-ignoring cancelled events, forcing people to usually have to use `@handleCancelled` to handle the event when they wanted to use it.
- The following API constants have been renamed:
- `PlayerPreLoginEvent::KICK_REASON_BANNED` -> `PlayerPreLoginEvent::KICK_FLAG_BANNED`
- `PlayerPreLoginEvent::KICK_REASON_PLUGIN` -> `PlayerPreLoginEvent::KICK_FLAG_PLUGIN`
- `PlayerPreLoginEvent::KICK_REASON_PRIORITY` -> `PlayerPreLoginEvent::KICK_FLAG_PRIORITY`
- `PlayerPreLoginEvent::KICK_REASON_SERVER_FULL` -> `PlayerPreLoginEvent::KICK_FLAG_SERVER_FULL`
- `PlayerPreLoginEvent::KICK_REASON_SERVER_WHITELISTED` -> `PlayerPreLoginEvent::KICK_FLAG_SERVER_WHITELISTED`
- The following API methods have been renamed:
- `PlayerPreLoginEvent->clearAllKickReasons()` -> `PlayerPreLoginEvent->clearAllKickFlags()`
- `PlayerPreLoginEvent->clearKickReason()` -> `PlayerPreLoginEvent->clearKickFlag()`
- `PlayerPreLoginEvent->getFinalKickMessage()` -> `PlayerPreLoginEvent->getFinalDisconnectReason()` (now used for logs only, if a disconnect screen message is set for the highest priority flag)
- `PlayerPreLoginEvent->getKickMessage()` -> `PlayerPreLoginEvent->getDisconnectReason()` (now used for logs only, if a disconnect screen message is set for the flag)
- `PlayerPreLoginEvent->getKickReasons()` -> `PlayerPreLoginEvent->getKickFlags()`
- `PlayerPreLoginEvent->isKickReasonSet()` -> `PlayerPreLoginEvent->isKickFlagSet()`
- `PlayerPreLoginEvent->setKickReason()` -> `PlayerPreLoginEvent->setKickFlag()`
### `pocketmine\item`
#### Highlights
- `ItemFactory` has been removed. Vanilla item registration is now done via `VanillaItems`.
- To get an item at runtime, e.g. iron ingot, use `VanillaItems::IRON_INGOT()`
- To get a block as an item, e.g. stone, use `VanillaBlocks::STONE()->asItem()`
- To load an item from legacy ID and meta:
1. Use `GlobalItemDataHandlers::getUpgrader()->upgradeItemTypeDataInt()` to convert the legacy ID and meta to `SavedItemStackData`
2. Pass the itemstack data to `GlobalItemDataHandlers::getDeserializer()` to get an `Item` instance
- Items no longer use internal Minecraft string IDs and metadata to identify themselves. All APIs associated with legacy
IDs and/or meta have been removed.
- A new set of runtime item IDs generated from `VanillaItems` is now used to identify item types. These IDs are defined
in `ItemTypeIds`.
- These new IDs are primarily intended for type comparison purposes.
- Item type IDs are used at **runtime only**. They should **NOT** be stored in configs or databases, as they are not
guaranteed to remain the same between versions.
- In some cases, items may have additional "type data" which provides extra type information about an item. This
replaces item metadata in some cases.
- Type data may be used to store dynamic type information such as dye colour, potion type, etc.
- Items must have the same type ID **and** type data in order to be stackable.
- Blocks, when represented as items:
- retain their block type data, but not state data (for example, different colours of concrete don't stack, but things
like facing don't affect stackability)
- use the negative of their block type ID (e.g. a block with type ID `1` will have an item type ID of `-1`).
- Durable items (e.g. tools, armour) now use NBT `Damage` tag to store durability (like Minecraft 1.13+), instead of
legacy meta values.
- `&$returnedItems` reference parameter is now used in some places (e.g. `onInteractBlock()`) to enable actions to return items to players without caring about whether they are in creative or anything else.
- This eliminates boilerplate code of deciding whether to set the player's held item or not, as well as automatically dropping any overflow items that don't fit into the inventory.
- This is used for things like filling/emptying buckets and bottles, and equipping armor.
- Blocks which previously had separate items, such as mob heads and beds, no longer do. Their item form can be acquired using `Block->asItem()` in the same way as every other block. This is facilitated by the new serializer system.
#### Implementing new items
##### In a plugin
This follows a similar process to registering blocks.
1. Get a new type ID using `ItemTypeIds::newId()` - _you'll want to keep this in a property somewhere if you want to
compare using `getTypeId()` later_
2. Set up the item type somewhere - _this can be anywhere you like, e.g. a plugin main class property, but using
a `RegistryTrait` class is recommended - you'll need this later to create new instances of the item_
3. Register a deserializer in `ItemDeserializer` - _needed for the item to be recognized when loaded from disk_
4. Register a serializer in `ItemSerializer` - _needed for the item to be saved to disk, and to be sent over the
network_
5. Optionally, register a string alias for the item in `StringToItemParser` - _so that it can be given via `/give`_
To see a demo of how to do this in a plugin, see [this example plugin](https://github.com/pmmp/RegisterBlocksDemoPM5).
Again, it's acknowledged this is rather more cumbersome than it should be, but this is an ongoing process.
##### As a PocketMine-MP core contribution
To register a new vanilla item into the core, the process is slightly different:
1. Instead of using `ItemTypeIds::newId()`, add a new constant for the block to `ItemTypeIds`
2. Register the new item in `VanillaItems`
3. Follow steps 3 onwards from the plugin instructions above
#### Change list
- `Item` is no longer `json_encode()`-able.
- The original purpose of this was to allow items to be serialized to JSON for crafting data generated from `CraftingDataPacket`. Due to changes in the generation methodology, bypassing `Item`s entirely, this is no longer necessary.
- In addition, `jsonSerialize()` required the item to know about the method by which it will be serialized (since there is no way to inject context), creating a cyclic dependency between the `Item` implementation and its serialization method.
- It's relatively easy to write a replacement method to encode items to JSON as you desire.
- `Item::legacyJsonDeserialize()` (previously `Item::jsonDeserialize()`) is retained to allow loading legacy data, although it may be removed in the future.
- The following classes have been removed:
- `Bed`
- `ItemFactory`
- `ItemIds`
- `Skull`
- The following classes have been added:
- `BoatType` - enum of all boat types
- `CoralFan`
- `HoneyBottle`
- `MedicineType`
- `Medicine`
- `Spyglass`
- `SuspiciousStewType`
- `SuspiciousStew`
- The following API methods have been added:
- `protected Item->describeState(RuntimeDataDescriber $w) : void`
- `public Armor->clearCustomColor() : $this` - clears the custom color of an armor item
- `public ArmorTypeInfo->getToughness() : int`
- `public ArmorTypeInfo->isFireProof() : bool`
- `public Boat->getType() : BoatType`
- `public Dye->setColor(\pocketmine\block\utils\DyeColor $color) : $this`
- `public Item->getStateId() : int` - returns a runtime numeric state ID for comparisons including information such as coral type, dye color, etc. - DO NOT save this to disk or databases
- `public Item->getTypeId() : int` - returns a runtime numeric type ID for comparisons - DO NOT save this to disk or databases
- `public Item->isFireProof() : bool`
- `public ItemIdentifer->getTypeId() : int`
- `public Potion->setType(PotionType $type) : $this`
- `public SplashPotion->setType(PotionType $type) : $this`
- `public StringToItemParser->lookupAliases(Item $item) : list<string>` - returns a list of all registered aliases for the given item
- `public StringToItemParser->lookupBlockAliases(Block $block) : list<string>` - returns a list of all registered aliases for the given block
- `public static ItemIdentifier::fromBlock(Block $block) : self`
- The following API methods have been removed:
- `Boat->getWoodType()`
- `Item->getId()` - for type comparisons, use `Item->getTypeId()` instead
- `Item->getMeta()` - use the item's specific API methods to compare information such as colour, potion type etc.
- `Item->hasAnyDamageValue()` - for meta wildcard recipe ingredients, use `pocketmine\crafting\MetaWildcardRecipeIngredient` instead
- `ItemIdentifier->getId()`
- `ItemIdentifier->getMeta()`
- The following API methods have been renamed:
- `Item::jsonDeserialize()` -> `Item::legacyJsonDeserialize()`
- The following API methods have signature changes:
- `ArmorTypeInfo->__construct()` now accepts optional parameters `int $toughness` and `bool $fireProof`
- `BoatType::__construct()` now accepts `BoatType $boatType` instead of `TreeType $woodType`.
- `Item->onAttackEntity()` now accepts `array<Item> &$returnedItems` reference parameter.
- `Item->onClickAir()` now accepts `array<Item> &$returnedItems` reference parameter.
- `Item->onDestroyBlock()` now accepts `array<Item> &$returnedItems` reference parameter.
- `Item->onInteractBlock()` now accepts `array<Item> &$returnedItems` reference parameter.
- `Item->onReleaseUsing()` now accepts `array<Item> &$returnedItems` reference parameter.
- `ItemIdentifier->__construct()` no longer accepts a `$variant` parameter, and now expects an item type ID for the ID parameter
- `LegacyStringToItemParser->addMapping()` now accepts a string for ID, instead of an integer
- The following API methods have behaviour changes:
- `Item->equals()`'s `$checkDamage` parameter is now ignored, as tool damage is now stored as an NBT tag. This parameter wasn't removed due to being followed by a second `bool` parameter, which would potentially end up in the wrong place and silently cause bugs in updated plugins.
- `Item->equals()`'s `$checkTags` parameter will now cause tool and armor damage to be checked if true.
- The following enums have new members:
- `ToolTier` has new member `NETHERITE`
### `pocketmine\network`
- The following API methods have changed signatures:
- `NetworkSessionManager->close()` now accepts an additional `Translatable|string|null $disconnectScreenMessage` parameter.
- The following API methods have changed signatures:
- `query\QueryInfo->getPlayerList()` now returns `list<string>` instead of `list<Player>`
- `query\QueryInfo->setPlayerList()` now accepts `list<string>` instead of `list<Player>`
### `pocketmine\player`
- The following API methods have changed signatures:
- `Player->disconnect()` now accepts `Translatable|string` for `$reason` instead of `string` (to allow localized disconnect messages)
- `Player->disconnect()` now accepts an additional `Translatable|string|null $disconnectScreenMessage` parameter, which is the message to be displayed on the disconnect screen (the message in `$reason` is used if null is passed)
- `Player->kick()` now accepts `Translatable|string` for `$reason` instead of `string` (to allow localized kick messages)
- `Player->kick()` now accepts an additional `Translatable|string|null $disconnectScreenMessage` parameter, which is the message to be displayed on the disconnect screen (the message in `$reason` is used if null is passed)
- `Player->sendJukeboxPopup()` now accepts `Translatable|string` instead of `string, string[]`
- The following classes have been removed:
- `PlayerChunkLoader` - deprecated in 4.19.0 (this was technically internal, but never marked as such)
### `pocketmine\player\chat`
- The following new classes have been added:
- `ChatFormatter` - interface implemented by chat formatters - this is far more powerful than the old API
- `LegacyRawChatFormatter` - implements the same behaviour previously used by `PlayerChatEvent->setFormat()`
- `StandardChatFormatter` - formats chat messages in the vanilla Minecraft style
### `pocketmine\scheduler`
- `AsyncTask->setResult()` now works with thread-safe objects. This was previously not possible due to limitations in the `pthreads` extension.
### `pocketmine\world`
- The following API methods have been added:
- `public World->setDisplayName(string $name) : void`
- The following API methods have changed signatures:
- `Explosion->__construct()` has the `$size` parameter renamed to `$radius`
- The following public properties have been renamed:
- `Explosion->size` -> `Explosion->radius`
### `pocketmine\world\format`
- Chunks are now considered dirty (modified) by default, unless loaded from a `WorldProvider` by `World`. Previously, chunks were considered unmodified by default, which allowed several pathways to bugs.
- The following classes have been added:
- `io\GlobalBlockStateHandlers` - gives access to block data serializer, deserializer, and upgraders
- `io\GlobalItemDataHandlers` - gives access to item data serializer, deserializer, and upgraders
- `io\LoadedChunkData` - represents a chunk loaded from disk, along with information such as whether the chunk was upgraded and what fixes it requires
- The following new API methods have been added:
- `public SubChunk->getBiomeArray() : PalettedBlockArray`
- The following classes have been removed:
- `BiomeArray` - `PalettedBlockArray` is now used for 3D biome data
- The following API methods have changed signatures:
- `Chunk->getBiomeId()` now accepts `int $x, int $y, int $z` instead of `int $x, int $z`
- `Chunk->setBiomeId()` now accepts `int $x, int $y, int $z` instead of `int $x, int $z`
- `Chunk->__construct()` no longer accepts `BiomeArray` as a parameter (contained in each subchunk instead)
- `SubChunk->__construct()` now accepts `int $emptyBlockId, list<PalettedBlockArray> $blockLayers, PalettedBlockArray $biomes, ?LightArray $blockLight, ?LightArray $skyLight` instead of `int, list<PalettedBlockArray>, ?LightArray, ?LightArray`
- `io\WorldProvider->loadChunk()` now returns `LoadedChunkData` instead of `ChunkData`
- `io\WorldProvider->getAllChunks()` now yields `LoadedChunkData` instead of `ChunkData`
- `io\ChunkData->__construct()` now accepts `array<int, SubChunk>, bool $populated` instead of `Chunk $chunk`
- The following API methods have been renamed:
- `Chunk->getFullBlock()` -> `Chunk->getBlockStateId()`
- `Chunk->setFullBlock()` -> `Chunk->setBlockStateId()`
- `SubChunk->getFullBlock()` -> `SubChunk->getBlockStateId()`
- `SubChunk->setFullBlock()` -> `SubChunk->setBlockStateId()`
- The following API interface requirements have been added:
- `public io\data\WorldData->setDisplayName(string $value) : void`
### `pocketmine\world\generator\object`
- The following API methods have been removed:
- `TreeType::fromMagicNumber()`
- `TreeType->getMagicNumber()`
### `pocketmine\world\sound`
- The following classes have been added:
- `CopperWaxApplySound`
- `CopperWaxRemoveSound`
- `DyeUseSound`
- `InkSacUseSound`
- The following enums have new members:
- `NoteInstrument` has new members `BELL`, `FLUTE`, `CHIME`, `XYLOPHONE`, `IRON_XYLOPHONE`, `COW_BELL`, `DIDGERIDOO`, `BIT`, `BANJO`, `PLING`
- The following API methods have been removed:
- `NoteInstrument::fromMagicNumber()`
- `NoteInstrument->getMagicNumber()`
## Internals
- All external usages of `KnownTranslationKeys` are now removed. All localized messages are now sent using `Translatable` objects (usually from `KnownTranslationFactory`).
- All usages of NBT keys now use class constants instead of hardcoded strings (except for an occasional overlooked one).
- Built-in commands now declare their names inside the class constructor, rather than accepting them as parameters. This improves code consistency.
- Commands now use an array for permissions internally, instead of a string separated by `;`.
- Make use of `Item->canStackWith()` instead of `Item->equals()` wherever possible, to make the code more readable.
- Moved command timings to `Timings`.
- Overriding of serializers and deserializers of items and blocks is now consistently disallowed. Since overriding stuff is non-cooperative, it doesn't make any sense in plugins, which must coexist with other plugins. If you want to modify the functionality of built-in stuff, you have several alternative options:
- Use existing API (e.g. events, API methods) - most uses of overrides in PM4 and earlier were abuses that could have been done with events
- Submit feature proposals or pull requests for new API to be added (e.g. new events)
- Register completely custom items, and reuse behaviour from the item you want to mimic
- Fork PocketMine-MP and alter the code directly - this way your plugins aren't pretending to be cooperative with other plugins
- `level.dat`, block, item, entity, tile and chunk data are now tagged with a version ID as per `VersionInfo::WORLD_DATA_VERSION`. This allows the server to apply fixes to older worlds if necessary.
- Protocol creative inventory entries are now cached in `CreativeInventoryCache` to improve performance of initial join and game mode changes.
- Singletons in the `pocketmine\network\mcpe\convert` package have been centralized under `TypeConverter`. In the future, this will be injected where needed, allowing different converters to be used for different sessions (useful for multiversion).
- `BlockStateDictionary` memory usage is now reduced from 9 MB to 3.5 MB using various techniques, including string reuse and binary-encoded states.
- `NetworkSession` disconnect APIs now accept `Translatable|string` instead of `string` to allow localized disconnect messages.
- `NetworkSession` disconnect methods have been altered to allow specifying a different disconnect reason and disconnection screen message.
- `RuntimeBlockMapping` has been renamed to `BlockTranslator`.
# 5.0.1
Released 3rd June 2023.
## Changes
- [`ext-pmmpthread` version 6.0.1](https://github.com/pmmp/ext-pmmpthread/releases/tag/6.0.1) is now required (for bug fixes).
## Fixes
- Fixed server crash when breaking blocks placed in the same session (mishandled default block states).
- Fixed spore blossoms not dropping when broken.
- Fixed jukebox music not stopping when destroyed by an explosion.
## Documentation
- Added documentation for `BlockSpreadEvent->__construct()` parameters.

52
changelogs/5.1.md Normal file
View File

@ -0,0 +1,52 @@
# 5.1.0
Released 7th June 2023.
**For Minecraft: Bedrock Edition 1.20.0**
This is a support release for Minecraft: Bedrock Edition 1.20.0.
**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` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## General
- Added support for Minecraft: Bedrock Edition 1.20.0.
- Removed support for older versions.
# 5.1.1
Released 7th June 2023.
## Fixes
- Fixed blockstates being saved with the wrong version ID for 1.20.0.
# 5.1.2
Released 9th June 2023.
**This release includes changes from the following releases:**
- [4.22.1](https://github.com/pmmp/PocketMine-MP/blob/4.22.1/changelogs/4.22.md#4221) - Teleportation client bug workarounds
This release contains no other changes.
# 5.1.3
Released 1st July 2023.
**This release includes changes from the following releases:**
- [4.22.2](https://github.com/pmmp/PocketMine-MP/blob/4.22.2/changelogs/4.22.md#4222) - Authentication time bomb fix
## General
- Updated logos to new RGB-style logo. Thanks to @MrCakeSlayer and @HBIDamian for their efforts.
- Improved error messages generated by the world system when some version tags are missing from `level.dat` in Bedrock worlds.
- Outsourced Composer dependencies now only receive patch updates automatically (pinned using the `~` constraint).
- Minor and major updates now require manually updating `composer.json`, to ensure that the plugin API is not broken by libraries getting randomly updated from one patch release to the next.
## Documentation
- Updated doc comment for `Player->setGamemode()` to remove outdated information.
- Added documentation for the `$clickVector` parameter of `Block->onInteract()` to specify that it is relative to the block's position.
- Added missing `@required` tag for `BlockStateUpgradeSchemaModelBlockRemap->newState`.
## Fixes
- Fixed blue candles not appearing in the creative inventory.
- Fixed server crash when block-picking candle cakes.
- `World->useItemOn()` now ensures that the `$clickVector` components are always in the range of 0-1. Previously, any invalid values were accepted, potentially leading to a crash.

79
changelogs/5.2.md Normal file
View File

@ -0,0 +1,79 @@
# 5.2.0
Released 4th July 2023.
**For Minecraft: Bedrock Edition 1.20.0**
This is a minor technical update, including changes to AsyncTask error handling and support for BedrockBlockUpgradeSchema version 3.0.0.
**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.
## Core
- [BedrockBlockUpgradeSchema version 3.0.0](https://github.com/pmmp/BedrockBlockUpgradeSchema/releases/tag/3.0.0) is now supported.
- [`ext-pmmpthread` version 6.0.4](https://github.com/pmmp/ext-pmmpthread/releases/tag/6.0.4) is now required (bug fixes required to support technical changes in this release).
## Performance
- Improved performance of `AsyncPool->submitTask()` and `AsyncPool->submitTaskToWorker()`.
- Added new timings for `AsyncTask->onProgressUpdate()` and `AsyncTask->onCompletion()`.
## Gameplay
### Blocks
- Added the following new blocks:
- Cherry Button
- Cherry Door
- Cherry Fence
- Cherry Fence Gate
- Cherry Leaves
- Cherry Log
- Cherry Planks
- Cherry Pressure Plate
- Cherry Sign
- Cherry Slab
- Cherry Stairs
- Cherry Trapdoor
- Cherry Wood
- Glow Lichen
- Piglin Head
## Tools
- `generate-block-upgrade-schema.php` now supports generating schemas a la BedrockBlockUpgradeSchema version 3.0.0, using `newFlattenedName` to reduce schema size.
- Improved property remapping detection in `generate-block-upgrade-schema.php`. It now detects related properties with more confidence (even when multiple properties were change), and no longer considers unrelated properties as mapped (e.g. `mapped_type` and `deprecated` in 1.9->1.10).
## API
### `pocketmine\data\bedrock\block`
- The following new API methods have been added:
- `public BlockStateData->toVanillaNbt() : CompoundTag` - returns the NBT for the blockstate without any PMMP extra metadata (`toNbt()` will normally include a `PMMPDataVersion` tag).
### `pocketmine\data\runtime`
- The following new API methods have been added:
- `public RuntimeDataDescriber->facingFlags(list<int> $faces) : void`
### `pocketmine\scheduler`
- `AsyncTask->onRun()` no longer tolerates uncaught exceptions.
- This means that any uncaught exceptions thrown from `AsyncTask->onRun()` will now crash the worker thread, and by extension, the server.
- This change makes it easier to debug errors by detecting them earlier.
- The following API methods have been deprecated:
- `AsyncTask->onError()`
## Internals
- `AsyncTask->progressUpdates` is now lazily initialized when a task publishes a progress update.
- This was previously not possible due to technical limitations of the `ext-pmmpthread` extension.
- This change improves performance of `AsyncPool->submitTask()` and `AsyncPool->submitTaskToWorker()`, as well as reducing the amount of work needed to check for progress updates on tick.
- Errors in `AsyncWorker` now cascade and crash the whole server.
- This makes it easier to debug errors by detecting them earlier.
- This includes all types of unexpected errors, such as OOM, uncaught exceptions, etc.
- This change is not expected to affect normal server operation, as worker threads are not expected to crash under normal circumstances.
- `AsyncTask::$threadLocalStorage` now uses a plain `array` instead of `ArrayObject`. The `ArrayObject` was a workaround for `ext-pthreads` to prevent thread-locals getting copied to the worker thread, and is no longer necessary.
- Regenerated `pocketmine\data\bedrock\item\ItemTypeNames` for Bedrock 1.20 (BC breaking, some item names have changed).
- Fixed `build/generate-item-type-names.php` not including some newer blockitems, such as doors and hanging signs.
# 5.2.1
Released 11th July 2023.
**This release includes changes from the following releases:**
- [4.22.3](https://github.com/pmmp/PocketMine-MP/blob/4.22.3/changelogs/4.22.md#4223) - Fixes for some crash issues
This release contains no other changes.

81
changelogs/5.3.md Normal file
View File

@ -0,0 +1,81 @@
# 5.3.0
Released 12th July 2023.
**For Minecraft: Bedrock Edition 1.20.10**
This is a support release for Minecraft: Bedrock Edition 1.20.10.
**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.
## Interim releases
If you're upgrading directly from 5.1.x to 5.3.x, please also read the following changelogs, as the interim releases contain important changes:
- [5.2.0](https://github.com/pmmp/PocketMine-MP/blob/5.2.0/changelogs/5.2.md#520)
## Included releases
**This release includes changes from the following releases:**
- [4.23.0](https://github.com/pmmp/PocketMine-MP/blob/4.23.0/changelogs/4.23.md#4230) - Support for Minecraft: Bedrock Edition 1.20.10
## Internals
- `BlockTypeNames`, `BlockStateNames`, `BlockStateStringValues` and `ItemTypeNames` in the `pocketmine\data\bedrock` package have BC-breaking changes to accommodate Bedrock 1.20.10.
# 5.3.1
Released 14th July 2023.
## Included releases
**This release includes changes from the following releases:**
- [4.23.1](https://github.com/pmmp/PocketMine-MP/blob/4.23.1/changelogs/4.23.md#4231) - Security fixes
## General
- Updated `build/php` submodule to pmmp/PHP-Binaries@e0c918d1379465964acefd562d9e48f87cfc2c9e.
# 5.3.2
Released 18th July 2023.
## Included releases
**This release includes changes from the following releases:**
- [4.23.2](https://github.com/pmmp/PocketMine-MP/blob/4.23.2/changelogs/4.23.md#4232) - Fix for `sandboxId`-related login errors
## Documentation
- Fixed documentation error in `StringToTParser`.
## Fixes
- Fixed turtle helmet not being able to be unequipped.
## Internals
- Armor pieces are no longer set back into the armor inventory if no change was made. This reduces the number of slot updates sent to clients, as well as avoiding unnecessary updates for armor pieces which have Unbreaking enchantments.
# 5.3.3
Released 24th July 2023.
## Included releases
**This release includes changes from the following releases:**
- [4.23.3](https://github.com/pmmp/PocketMine-MP/blob/4.23.3/changelogs/4.23.md#4233) - Various bug fixes
## Fixes
- Added a workaround for PM4 worlds with chunks corrupted by [Refaltor77/CustomItemAPI](https://github.com/Refaltor77/CustomItemAPI).
- While this was not the fault of PocketMine-MP itself, a significant number of users were affected by this problem.
- This error was not detected by PM4 due to missing validation of certain data which should not have existed in 1.12.
- An error will now be logged when this corruption is detected, but the affected chunks should otherwise load normally.
- Relaxed validation of expected 3D biome array counts per chunk in LevelDB worlds.
- Vanilla Bedrock currently saves 24 palettes (and only 24 are required), but it saved 25, 32, or 64 biome palettes per chunk in older versions.
- Core validation for these padding biomes was very strict, enforcing exact compliance with vanilla.
- Since only 24 palettes are actually required, the remaining palettes may now be omitted irrespective of the chunk version.
- An error will still be logged when this mistake is detected, but the affected chunks will otherwise load normally.
- Fixed `/kill` not working on players who had (re)spawned in the 3 seconds immediately after (re)spawning (due to `noDamageTicks`).
- Fixed `/kill` not working correctly for players with high levels of Health Boost or other health-altering effects.
- Fixed netherite items being destroyed by lava.
- Fireproof entities no longer display the burning animation when in fire or lava. This does not apply to creative players, who are immortal rather than being fireproof.
- Fixed frosted ice melting in certain conditions which didn't match vanilla Bedrock.
# 5.3.4
Released 1st August 2023.
## Included releases
This release includes changes from the following releases:
- [4.23.4](https://github.com/pmmp/PocketMine-MP/blob/4.23.4/changelogs/4.23.md#4234) - Item entity lag fix
This release contains no other significant changes.

133
changelogs/5.4.md Normal file
View File

@ -0,0 +1,133 @@
# 5.4.0
Released 1st August 2023.
**For Minecraft: Bedrock Edition 1.20.10**
This is a minor feature update, including a handful of new gameplay features, new plugin APIs and improvements to error reporting.
**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
- Improved error reporting for async task and thread crashes.
- Players may now have different creative inventories.
## Gameplay
### General
- Added support for 1.5-block height sneaking.
- Fixed missing player arm swing and sounds when punching the air.
### Blocks
- Implemented the following new blocks:
- Big Dripleaf Head
- Big Dripleaf Stem
- Small Dripleaf
- Acacia saplings now grow into acacia trees.
- Fixed melon and pumpkin stems not attaching to the correct block when growing.
- Various blocks now drop more items when mined with a compatible tool enchanted with Fortune.
### Items
- Implemented Strong Slowness potion.
- Implemented Fortune enchantment.
## API
### `pocketmine\block`
- The following new classes have been added:
- `utils\FortuneDropHelper` - utility methods for calculating the drop counts for Fortune-affected blocks
- The following new API methods have been added:
- `protected Block->getAdjacentSupportType(int $facing) : utils\SupportType` - returns the type of support provided by the block in the given direction on the adjacent face
### `pocketmine\entity`
- The following new API constants have been added:
- `Living::DEFAULT_KNOCKBACK_FORCE`
- `Living::DEFAULT_KNOCKBACK_VERTICAL_LIMIT`
### `pocketmine\entity\animation`
- `ConsumingItemAnimation` now accepts `Living` instances instead of just `Human`.
### `pocketmine\event`
- The following new classes have been added:
- `PlayerMissSwingEvent` - called when the player attempts the attack action (left click on desktop) without any target
- This is possible thanks to the introduction of new flags in `PlayerAuthInputPacket` in Bedrock 1.20.10
- The following new API methods have been added:
- `public EntityDamageByEntityEvent->getVerticalKnockBackLimit() : float`
- `public EntityDamageByEntityEvent->setVerticalKnockBackLimit(float $verticalKnockBackLimit) : void` - sets the max vertical velocity that can result from the victim being knocked back
### `pocketmine\player`
- The following new API methods have been added:
- `public Player->getCreativeInventory() : pocketmine\inventory\CreativeInventory`
- `public Player->setCreativeInventory(pocketmine\inventory\CreativeInventory $inventory) : void`
- `public Player->missSwing() : void` - performs actions associated with the attack action when there is no target (see `PlayerMissSwingEvent`)
### `pocketmine\scheduler`
- Cancellation functionality has been removed from `AsyncTask`, as it didn't make any sense and wasn't used by anything for what it was intended for.
- It broke sequential task execution - later tasks might depend on state from earlier tasks
- It didn't actually cancel the task anyway - at best, it prevented it from running, but couldn't interrupt it (though interrupting a task does not make sense either)
- The following API methods have been deprecated, and their functionality has been removed:
- `AsyncTask->hasCancelledRun()`
- `AsyncTask->cancelRun()`
## Internals
- Uncaught exceptions and fatal errors in `AsyncTask`, threads extending `pocketmine\thread\Thread`, and `pocketmine\thread\Worker` are now recorded in crashdumps, making it significantly easier to debug errors in these areas.
- JWT signature DER <-> raw conversions are now handled in-house using code in `JwtUtils`
- Due to the simplicity of the conversion and only requiring a tiny subset of the ASN.1 spec, it didn't make much sense to introduce another dependency.
- `fgrosse/phpasn1` is no longer required. This package was abandoned by its author and only used by PocketMine-MP for this one purpose.
- Various usages of `Closure::fromCallable()` have been replaced by PHP 8.1 first-class callable syntax.
- Blocks requiring support shifted to a "can be supported at" model, rather than "can be supported by".
- This model reduces repeated logic when placing and performing nearby block updates (no need to hardcode facing everywhere).
- In addition, this change facilitates the use of the newly introduced `Block->getAdjacentSupportType()` API method, reducing boilerplate support-type checking code.
- Bell block code has been simplified and cleaned up.
- `TallGrass` and `DoubleTallGrass` now use a shared `TallGrassTrait` to reduce code duplication.
# 5.4.1
Released 8th August 2023.
## General
- Updated translation data to [pmmp/Language 2.19.6](https://github.com/pmmp/Language/releases/tag/2.19.6).
- [`ext-pmmpthread` 6.0.7](https://github.com/pmmp/ext-pmmpthread/releases/tag/6.0.7) is now required (needed for bug fixes).
## Fixes
- Fixed Podzol not dropping itself when mined with Silk Touch.
- Fixed `World->getSafeSpawn()` not accepting positions below `y=0` (world height limit change).
- Fixed `pocketmine\thread\Thread` and `pocketmine\thread\Worker` instances not logging any information when they crash.
- Fixed `CraftItemEvent` not cloning returned items.
## Internals
- Foreach by-reference is now disallowed via a custom PHPStan rule.
# 5.4.2
Released 9th August 2023.
## Included releases
- [4.23.5](https://github.com/pmmp/PocketMine-MP/blob/4.23.5/changelogs/4.23.md#4235) - Minor bug fixes
## Fixes
- Fixed cake accepting candle placement when slices have already been eaten.
- Fixed fire charges not lighting candles.
# 5.4.3
Released 21st August 2023.
## Included releases
- [4.23.6](https://github.com/pmmp/PocketMine-MP/blob/4.23.6/changelogs/4.23.md#4236) - Armor inventory client bug workaround
## Fixes
- Fixed crashdumps not generating correctly on fatal errors.
- Fixed `PotionCauldron::setPotionItem()` not validating the item type.
- Fixed chorus fruit not considering teleport destinations below y=0.
- Fixed cake dropping itself when mined.
# 5.4.4
Released 6th September 2023.
## General
- Crashdumps caused by non-phar plugins are now submitted to the Crash Archive, the same as other plugins. Previously, non-phar plugin crashes would not be submitted, causing maintainers to potentially miss important issues.
## Fixes
- Fixed player Y coordinates sometimes being slightly below the top of the block they were standing on (floating point error due to subtracting eye height).
- Fixed template slot of smithing tables not accepting any items.
- `tools/generate-bedrock-data-from-packets.php` is now significantly less spammy when warning about duplicated recipes.
- Fixed empty stack traces in `lastError` data of crashdumps.

156
changelogs/5.5-beta.md Normal file
View File

@ -0,0 +1,156 @@
# 5.5.0-BETA1
Released 23rd August 2023.
**For Minecraft: Bedrock Edition 1.20.10**
This is a minor feature release, including performance improvements, new API methods, and new gameplay features.
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## Dependencies
- Updated `pocketmine/math` dependency to [`1.0.0`](https://github.com/pmmp/Math/releases/tag/1.0.0).
- Updated `pocketmine/nbt` dependency to [`1.0.0`](https://github.com/pmmp/NBT/releases/tag/1.0.0).
## Performance
- Some events are now no longer fired if no handlers are registered.
- This improves performance by avoiding unnecessary object allocations and function calls.
- Events such as `DataPacketReceiveEvent`, `DataPacketSendEvent` and `PlayerMoveEvent` are optimized away almost completely by this change, offering some much-needed performance gains.
- Significantly improved performance of small moving entities, such as dropped items.
- This was achieved by a combination of changes, which together improved observed performance with 2000 item entities moving in water by 30-40%.
- The benefit of this will be most noticeable in SkyBlock servers, where large cactus farms can generate thousands of dropped items.
- `World->getCollisionBoxes()` now uses an improved search method, which reduces the work done by the function by almost 90% for small entities.
- This improves performance of collision detection for small entities, such as dropped items.
## Gameplay
### General
- Implemented enchanting using an enchanting table (yes, finally!)
- Thanks to [@S3v3Nice](https://github.com/S3v3Nice) for investing lots of time and effort into developing this.
- Since this feature is quite complex, it's possible there may be bugs. Please be vigilant and report any issues you find.
### Blocks
- The following new blocks have been implemented:
- Pink Petals
- Pressure plates are now functional, in the sense that they react when entities stand on them and perform the correct logic.
- Note that since redstone is not yet implemented, pressure plates do not activate any redstone devices, similar to buttons and levers.
- Signs can now be edited by right-clicking them.
- Signs can now be waxed using a honeycomb, which prevents them from being edited.
### Items
- The following new items have been implemented:
- Enchanted Book
## API
### `pocketmine\block`
- The following new API methods have been added:
- `public Block->getEnchantmentTags() : list<string>` returns a list of strings indicating which types of enchantment can be applied to the block when in item form
- `public BlockTypeInfo->getEnchantmentTags() : list<string>`
- `protected PressurePlate->getActivationBox() : AxisAlignedBB` - returns the AABB entities must intersect with in order to activate the pressure plate (not the same as the visual shape)
- `protected PressurePlate->hasOutputSignal() : bool` - returns whether the pressure plate has an output signal - this should be implemented by subclasses
- `protected PressurePlate->calculatePlateState() : array{Block, ?bool}` - returns the state the pressure plate will change to if the given list of entities are standing on it, and a bool indicating whether the plate activated or deactivated this tick
- `protected PressurePlate->filterIrrelevantEntities(list<Entity> $entities) : list<Entity>` - returns the given list filtered of entities that don't affect the plate's state (e.g. dropped items don't affect stone pressure plates)
- `public BaseSign->isWaxed() : bool`
- `public BaseSign->setWaxed(bool $waxed) : $this`
- `public inventory\EnchantInventory->getInput() : Item`
- `public inventory\EnchantInventory->getLapis() : Item`
- `public inventory\EnchantInventory->getOutput(int $optionId) : ?Item` - returns the item that would be produced if the input item was enchanted with the selected option, or `null` if the option is invalid
- `public inventory\EnchantInventory->getOption(int $optionId) : EnchantOption` - returns the enchanting option at the given index
- The following API methods have signature changes:
- `BlockTypeInfo->__construct()` now accepts an optional `list<string> $enchantmentTags` parameter
- `PressurePlate->__construct()` now accepts an optional `int $deactivationDelayTicks` parameter
- `WeightedPressurePlate->__construct()` now accepts optional `int $deactivationDelayTicks` and `float $signalStrengthFactor` parameters
- `SimplePressurePlate->__construct()` now accepts an optional `int $deactivationDelayTicks` parameter
- The following new classes have been added:
- `PinkPetals`
- `utils\BlockEventHelper` - provides helper methods for calling block-related events
- The following classes have been deprecated:
- `WeightedPressurePlateLight`
- `WeightedPressurePlateHeavy`
### `pocketmine\entity`
- The following new API methods have been added:
- `public Human->getEnchantmentSeed() : int` - returns the current seed used to randomize options shown on the enchanting table for this human
- `public Human->setEnchantmentSeed(int $seed) : void`
- `public Human->regenerateEnchantmentSeed() : void` - returns a new randomly generated seed which can be set with `setEnchantmentSeed()`
### `pocketmine\event`
- The following new classes have been added:
- `block\FarmlandHydrationChangeEvent` - called when farmland is hydrated or dehydrated
- `block\PressurePlateUpdateEvent` - called when a pressure plate is activated or changes its power output
- `player\PlayerEnchantingOptionsRequestEvent` - called when a player puts an item to be enchanted into an enchanting table, to allow plugins to modify the enchanting options shown
- `player\PlayerItemEnchantEvent` - called when a player enchants an item in an enchanting table
- `world\WorldDifficultyChangeEvent` - called when a world's difficulty is changed
- The following new API methods have been added:
- `public static Event::hasHandlers() : bool` - returns whether the event class has any registered handlers - used like `SomeEvent::hasHandlers()`
- `public HandlerListManager->getHandlersFor(class-string<? extends Event> $event) : list<RegisteredListener>` - returns a list of all registered listeners for the given event class, using cache if available
### `pocketmine\inventory\transaction`
- The following new classes have been added:
- `EnchantingTransaction` - used when a player enchants an item in an enchanting table
### `pocketmine\item`
- The following new API methods have been added:
- `public Armor->getMaterial() : ArmorMaterial` - returns an object containing properties shared by all items of the same armor material
- `public ArmorTypeInfo->getMaterial() : ArmorMaterial`
- `public Item->getEnchantability() : int` - returns the enchantability value of the item - higher values increase the chance of more powerful enchantments being offered by an enchanting table
- `public Item->getEnchantmentTags() : list<string>` - returns a list of strings indicating which types of enchantment can be applied to the item
- `public ToolTier->getEnchantability() : int`
- The following API methods have signature changes:
- `Item->__construct()` now accepts an optional `list<string> $enchantmentTags` parameter
- `ArmorTypeInfo->__construct()` now accepts an optional `?ArmorMaterial $material` parameter
- The following new classes have been added:
- `ArmorMaterial` - container for shared armor properties
- `VanillaArmorMaterials` - all vanilla armor materials
- `EnchantedBook` - represents an enchanted book item
### `pocketmine\item\enchantment`
- The following new classes have been added:
- `AvailableEnchantmentRegistry` - enchantments to be displayed on the enchanting table are selected from here - custom enchantments may be added
- `EnchantingHelper` - static class containing various helper methods for enchanting tables
- `EnchantingOption` - represents an option on the enchanting table menu
- `IncompatibleEnchantmentGroups` - list of constants naming groups of enchantments that are incompatible with each other - custom enchantments may be added using these group names to make them incompatible with existing enchantments in the same group
- `IncompatibleEnchantmentRegistry` - manages which enchantments are considered incompatible with each other - custom enchantments may be added using existing group names to make them incompatible with existing enchantments in the same group, or to entirely new groups
- `ItemEnchantmentTagRegistry` - manages item enchantment compatibility tags and which tags include which other tags
- `ItemEnchantmentTags` - list of constants naming item types for enchantment compatibility checks
- The following classes have been deprecated
- `ItemFlags`
- The following API methods have been added:
- `public Enchantment->isCompatibleWith(Enchantment $other) : bool`
- `public Enchantment->getMinEnchantingPower()` - returns the minimum enchanting power (derived from enchantability and number of bookshelves) needed to allow this enchantment to show on the enchanting table with a given level
- `public Enchantment->getMaxEnchantingPower()` - upper limit of enchanting power for this enchantment to be offered on the enchanting table with a given level
- The following API methods have signature changes:
- `Enchantment->__construct()` now accepts optional `(\Closure(int $level) : int)|null $minEnchantingPower` and `int $enchantingPowerRange` parameters
- `Enchantment->__construct()` parameters `$primaryItemFlags` and `$secondaryItemFlags` are now deprecated and no longer used
- `ProtectionEnchantment->__construct()` has extra parameters to reflect `Enchantment->__construct()` changes
- The following API methods have been deprecated:
- `Enchantment->getPrimaryItemFlags()` - use API methods provided by `AvailableEnchantmentRegistry` instead
- `Enchantment->getSecondaryItemFlags()` - use API methods provided by `AvailableEnchantmentRegistry` instead
- `Enchantment->hasPrimaryItemType()`
- `Enchantment->hasSecondaryItemType()`
### `pocketmine\plugin`
- The following new API methods have been added:
- `public PluginBase->getResourcePath(string $filename) : string` - returns a URI to an embedded resource file that can be used with `file_get_contents()` and similar functions
- `public PluginBase->getResourceFolder() : string` - returns a URI to the plugin's folder of embedded resources
- The following API methods have been deprecated:
- `PluginBase->getResource()` - prefer using `getResourcePath()` with `file_get_contents()` or other PHP built-in functions instead
### `pocketmine\resourcepacks`
- The following new API methods have been added:
- `public ResourcePackManager->setResourcePacksRequired(bool $value) : void` - sets whether players must accept resource packs in order to join
### `pocketmine\world\generator`
- The following new API methods have been added:
- `public GeneratorManager->addAlias(string $name, string $alias) : void` - allows registering a generator alias without copying the generator registration parameters
### `pocketmine\world\sound`
- The following new classes have been added:
- `PressurePlateActivateSound`
- `PressurePlateDeactivateSound`
### `pocketmine\utils`
- The following new API methods have been added:
- `public StringToTParser->registerAlias(string $existing, string $alias) : void` - allows registering a string alias without copying registration parameters

162
changelogs/5.5.md Normal file
View File

@ -0,0 +1,162 @@
# 5.5.0
Released 6th September 2023.
**For Minecraft: Bedrock Edition 1.20.10**
This is a minor feature release, including performance improvements, new API methods, and new gameplay features.
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## Dependencies
- Updated `pocketmine/math` dependency to [`1.0.0`](https://github.com/pmmp/Math/releases/tag/1.0.0).
- Updated `pocketmine/nbt` dependency to [`1.0.0`](https://github.com/pmmp/NBT/releases/tag/1.0.0).
## Performance
- Some events are now no longer fired if no handlers are registered.
- This improves performance by avoiding unnecessary object allocations and function calls.
- Events such as `DataPacketReceiveEvent`, `DataPacketSendEvent` and `PlayerMoveEvent` are optimized away almost completely by this change, offering some much-needed performance gains.
- Significantly improved performance of small moving entities, such as dropped items.
- This was achieved by a combination of changes, which together improved observed performance with 2000 item entities moving in water by 30-40%.
- The benefit of this will be most noticeable in SkyBlock servers, where large cactus farms can generate thousands of dropped items.
- `World->getCollisionBoxes()` now uses an improved search method, which reduces the work done by the function by almost 90% for small entities.
- This improves performance of collision detection for small entities, such as dropped items.
## Gameplay
### General
- Implemented enchanting using an enchanting table (yes, finally!)
- Thanks to [@S3v3Nice](https://github.com/S3v3Nice) for investing lots of time and effort into developing this.
- Since this feature is quite complex, it's possible there may be bugs. Please be vigilant and report any issues you find.
### Blocks
- The following new blocks have been implemented:
- Pink Petals
- Pressure plates are now functional, in the sense that they react when entities stand on them and perform the correct logic.
- Note that since redstone is not yet implemented, pressure plates do not activate any redstone devices, similar to buttons and levers.
- Signs can now be edited by right-clicking them.
- Signs can now be waxed using a honeycomb, which prevents them from being edited.
### Items
- The following new items have been implemented:
- Enchanted Book
## API
### `pocketmine\block`
- The following new API methods have been added:
- `public Block->getEnchantmentTags() : list<string>` returns a list of strings indicating which types of enchantment can be applied to the block when in item form
- `public BlockTypeInfo->getEnchantmentTags() : list<string>`
- `protected PressurePlate->getActivationBox() : AxisAlignedBB` - returns the AABB entities must intersect with in order to activate the pressure plate (not the same as the visual shape)
- `protected PressurePlate->hasOutputSignal() : bool` - returns whether the pressure plate has an output signal - this should be implemented by subclasses
- `protected PressurePlate->calculatePlateState() : array{Block, ?bool}` - returns the state the pressure plate will change to if the given list of entities are standing on it, and a bool indicating whether the plate activated or deactivated this tick
- `protected PressurePlate->filterIrrelevantEntities(list<Entity> $entities) : list<Entity>` - returns the given list filtered of entities that don't affect the plate's state (e.g. dropped items don't affect stone pressure plates)
- `public BaseSign->isWaxed() : bool`
- `public BaseSign->setWaxed(bool $waxed) : $this`
- `public inventory\EnchantInventory->getInput() : Item`
- `public inventory\EnchantInventory->getLapis() : Item`
- `public inventory\EnchantInventory->getOutput(int $optionId) : ?Item` - returns the item that would be produced if the input item was enchanted with the selected option, or `null` if the option is invalid
- `public inventory\EnchantInventory->getOption(int $optionId) : EnchantOption` - returns the enchanting option at the given index
- The following API methods have signature changes:
- `BlockTypeInfo->__construct()` now accepts an optional `list<string> $enchantmentTags` parameter
- `PressurePlate->__construct()` now accepts an optional `int $deactivationDelayTicks` parameter
- `WeightedPressurePlate->__construct()` now accepts optional `int $deactivationDelayTicks` and `float $signalStrengthFactor` parameters
- `SimplePressurePlate->__construct()` now accepts an optional `int $deactivationDelayTicks` parameter
- The following new classes have been added:
- `PinkPetals`
- `utils\BlockEventHelper` - provides helper methods for calling block-related events
- The following classes have been deprecated:
- `WeightedPressurePlateLight`
- `WeightedPressurePlateHeavy`
### `pocketmine\entity`
- The following new API methods have been added:
- `public Human->getEnchantmentSeed() : int` - returns the current seed used to randomize options shown on the enchanting table for this human
- `public Human->setEnchantmentSeed(int $seed) : void`
- `public Human->regenerateEnchantmentSeed() : void` - returns a new randomly generated seed which can be set with `setEnchantmentSeed()`
### `pocketmine\event`
- The following new classes have been added:
- `block\FarmlandHydrationChangeEvent` - called when farmland is hydrated or dehydrated
- `block\PressurePlateUpdateEvent` - called when a pressure plate is activated or changes its power output
- `player\PlayerEnchantingOptionsRequestEvent` - called when a player puts an item to be enchanted into an enchanting table, to allow plugins to modify the enchanting options shown
- `player\PlayerItemEnchantEvent` - called when a player enchants an item in an enchanting table
- `world\WorldDifficultyChangeEvent` - called when a world's difficulty is changed
- The following new API methods have been added:
- `public static Event::hasHandlers() : bool` - returns whether the event class has any registered handlers - used like `SomeEvent::hasHandlers()`
- `public HandlerListManager->getHandlersFor(class-string<? extends Event> $event) : list<RegisteredListener>` - returns a list of all registered listeners for the given event class, using cache if available
### `pocketmine\inventory\transaction`
- The following new classes have been added:
- `EnchantingTransaction` - used when a player enchants an item in an enchanting table
### `pocketmine\item`
- The following new API methods have been added:
- `public Armor->getMaterial() : ArmorMaterial` - returns an object containing properties shared by all items of the same armor material
- `public ArmorTypeInfo->getMaterial() : ArmorMaterial`
- `public Item->getEnchantability() : int` - returns the enchantability value of the item - higher values increase the chance of more powerful enchantments being offered by an enchanting table
- `public Item->getEnchantmentTags() : list<string>` - returns a list of strings indicating which types of enchantment can be applied to the item
- `public ToolTier->getEnchantability() : int`
- The following API methods have signature changes:
- `Item->__construct()` now accepts an optional `list<string> $enchantmentTags` parameter
- `ArmorTypeInfo->__construct()` now accepts an optional `?ArmorMaterial $material` parameter
- The following new classes have been added:
- `ArmorMaterial` - container for shared armor properties
- `VanillaArmorMaterials` - all vanilla armor materials
- `EnchantedBook` - represents an enchanted book item
### `pocketmine\item\enchantment`
- The following new classes have been added:
- `AvailableEnchantmentRegistry` - enchantments to be displayed on the enchanting table are selected from here - custom enchantments may be added
- `EnchantingHelper` - static class containing various helper methods for enchanting tables
- `EnchantingOption` - represents an option on the enchanting table menu
- `IncompatibleEnchantmentGroups` - list of constants naming groups of enchantments that are incompatible with each other - custom enchantments may be added using these group names to make them incompatible with existing enchantments in the same group
- `IncompatibleEnchantmentRegistry` - manages which enchantments are considered incompatible with each other - custom enchantments may be added using existing group names to make them incompatible with existing enchantments in the same group, or to entirely new groups
- `ItemEnchantmentTagRegistry` - manages item enchantment compatibility tags and which tags include which other tags
- `ItemEnchantmentTags` - list of constants naming item types for enchantment compatibility checks
- The following classes have been deprecated
- `ItemFlags`
- The following API methods have been added:
- `public Enchantment->isCompatibleWith(Enchantment $other) : bool`
- `public Enchantment->getMinEnchantingPower()` - returns the minimum enchanting power (derived from enchantability and number of bookshelves) needed to allow this enchantment to show on the enchanting table with a given level
- `public Enchantment->getMaxEnchantingPower()` - upper limit of enchanting power for this enchantment to be offered on the enchanting table with a given level
- The following API methods have signature changes:
- `Enchantment->__construct()` now accepts optional `(\Closure(int $level) : int)|null $minEnchantingPower` and `int $enchantingPowerRange` parameters
- `Enchantment->__construct()` parameters `$primaryItemFlags` and `$secondaryItemFlags` are now deprecated and no longer used
- `ProtectionEnchantment->__construct()` has extra parameters to reflect `Enchantment->__construct()` changes
- The following API methods have been deprecated:
- `Enchantment->getPrimaryItemFlags()` - use API methods provided by `AvailableEnchantmentRegistry` instead
- `Enchantment->getSecondaryItemFlags()` - use API methods provided by `AvailableEnchantmentRegistry` instead
- `Enchantment->hasPrimaryItemType()`
- `Enchantment->hasSecondaryItemType()`
### `pocketmine\plugin`
- The following new API methods have been added:
- `public PluginBase->getResourcePath(string $filename) : string` - returns a URI to an embedded resource file that can be used with `file_get_contents()` and similar functions
- `public PluginBase->getResourceFolder() : string` - returns a URI to the plugin's folder of embedded resources
- The following API methods have been deprecated:
- `PluginBase->getResource()` - prefer using `getResourcePath()` with `file_get_contents()` or other PHP built-in functions instead
### `pocketmine\resourcepacks`
- The following new API methods have been added:
- `public ResourcePackManager->setResourcePacksRequired(bool $value) : void` - sets whether players must accept resource packs in order to join
### `pocketmine\world\generator`
- The following new API methods have been added:
- `public GeneratorManager->addAlias(string $name, string $alias) : void` - allows registering a generator alias without copying the generator registration parameters
### `pocketmine\world\sound`
- The following new classes have been added:
- `PressurePlateActivateSound`
- `PressurePlateDeactivateSound`
### `pocketmine\utils`
- The following new API methods have been added:
- `public StringToTParser->registerAlias(string $existing, string $alias) : void` - allows registering a string alias without copying registration parameters
## Internals
- Various `TypeIdMap` classes in the `pocketmine\data\bedrock` package now use the new `IntSaveIdMapTrait` to reduce code duplication.
- Added a new `ServerProperties` class containing constants for all known `server.properties` keys.
- Added a new `YmlServerProperties` class containing generated constants for all known `pocketmine.yml` keys. These keys can be used with `Config->getNested()`.

34
changelogs/5.6.md Normal file
View File

@ -0,0 +1,34 @@
# 5.6.0
Released 20th September 2023.
**For Minecraft: Bedrock Edition 1.20.30**
This is a support release for Minecraft: Bedrock Edition 1.20.30.
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## General
- Added support for Minecraft: Bedrock Edition 1.20.30.
- Removed support for older versions.
## Fixes
- Fixed support conditions for hanging roots, cave vines and dead bushes.
- Fixed connection conditions for fences, glass panes, iron bars, and walls.
# 5.6.1
Released 20th October 2023.
## Performance
- Improved performance of cactus growth by disabling neighbour updates when only the age property was updated. While this isn't a perfect solution, it provides significant performance gains for servers with large cactus farms.
## Fixes
- Fixed `tools/generate-bedrock-data-from-packets.php` incorrectly interpreting network meta as blockstates in some cases (broken crafting recipes).
- Fixed crafting recipes involving beds, skulls and some other items not working correctly (incorrectly interpreted data).
- Fixed crashes when flower pot or cauldron blockentities exist in places where they shouldn't (leftovers from upgraded PM3 worlds).
- Fixed `Entity->broadcastSound()` not firing `WorldSoundEvent` (bypassing internal sound system).
- Fixed wooden signs, buttons and doors not being able to be used as furnace fuel.
- Fixed bone meal and tools only working when used on the top side of dirt and grass. Bone meal now works from any side, and tools work on any side except the bottom.

View File

@ -5,7 +5,7 @@
"homepage": "https://pmmp.io",
"license": "LGPL-3.0",
"require": {
"php": "^8.0",
"php": "^8.1",
"php-64bit": "*",
"ext-chunkutils2": "^0.3.1",
"ext-crypto": "^0.3.1",
@ -22,7 +22,7 @@
"ext-openssl": "*",
"ext-pcre": "*",
"ext-phar": "*",
"ext-pthreads": "^5.1",
"ext-pmmpthread": "^6.0.7",
"ext-reflection": "*",
"ext-simplexml": "*",
"ext-sockets": "*",
@ -31,34 +31,31 @@
"ext-zip": "*",
"ext-zlib": ">=1.2.11",
"composer-runtime-api": "^2.0",
"adhocore/json-comment": "^1.1",
"fgrosse/phpasn1": "^2.3",
"netresearch/jsonmapper": "^4.0",
"pocketmine/bedrock-block-upgrade-schema": "~1.1.1+bedrock-1.19.70",
"pocketmine/bedrock-data": "~2.1.1+bedrock-1.19.70",
"pocketmine/bedrock-item-upgrade-schema": "~1.1.0+bedrock-1.19.70",
"pocketmine/bedrock-protocol": "~20.1.1+bedrock-1.19.70",
"adhocore/json-comment": "~1.2.0",
"pocketmine/netresearch-jsonmapper": "~v4.2.1000",
"pocketmine/bedrock-block-upgrade-schema": "~3.2.0+bedrock-1.20.30",
"pocketmine/bedrock-data": "~2.5.0+bedrock-1.20.30",
"pocketmine/bedrock-item-upgrade-schema": "~1.5.0+bedrock-1.20.30",
"pocketmine/bedrock-protocol": "~24.0.0+bedrock-1.20.30",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/classloader": "^0.3.0",
"pocketmine/color": "^0.3.0",
"pocketmine/errorhandler": "^0.6.0",
"pocketmine/locale-data": "~2.19.0",
"pocketmine/log": "^0.4.0",
"pocketmine/log-pthreads": "^0.5.0",
"pocketmine/math": "^0.4.0",
"pocketmine/nbt": "^0.3.2",
"pocketmine/math": "~1.0.0",
"pocketmine/nbt": "~1.0.0",
"pocketmine/raklib": "^0.15.0",
"pocketmine/raklib-ipc": "^0.2.0",
"pocketmine/snooze": "^0.4.0",
"ramsey/uuid": "^4.1",
"symfony/filesystem": "^5.4"
"pocketmine/snooze": "^0.5.0",
"ramsey/uuid": "~4.7.0",
"symfony/filesystem": "~6.3.0"
},
"require-dev": {
"phpstan/phpstan": "1.10.11",
"phpstan/phpstan": "1.10.39",
"phpstan/phpstan-phpunit": "^1.1.0",
"phpstan/phpstan-strict-rules": "^1.2.0",
"phpunit/phpunit": "^9.2"
"phpunit/phpunit": "~10.3.0 || ~10.2.0 || ~10.1.0"
},
"autoload": {
"psr-4": {
@ -76,7 +73,7 @@
},
"config": {
"platform": {
"php": "8.0.0"
"php": "8.1.0"
},
"sort-packages": true
},

1267
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,7 @@ includes:
rules:
- pocketmine\phpstan\rules\DisallowEnumComparisonRule
- pocketmine\phpstan\rules\DisallowForeachByReferenceRule
- pocketmine\phpstan\rules\UnsafeForeachArrayOfStringRule
# - pocketmine\phpstan\rules\ThreadedSupportedTypesRule
@ -43,8 +44,7 @@ parameters:
stubFiles:
- tests/phpstan/stubs/JsonMapper.stub
- tests/phpstan/stubs/leveldb.stub
- tests/phpstan/stubs/phpasn1.stub
- tests/phpstan/stubs/pthreads.stub
- tests/phpstan/stubs/pmmpthread.stub
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
staticReflectionClassNamePatterns:
- "#^COM$#"

View File

@ -85,8 +85,11 @@ network:
batch-threshold: 256
#Compression level used when sending batched packets. Higher = more CPU, less bandwidth usage
compression-level: 6
#Use AsyncTasks for compression. Adds half/one tick delay, less CPU load on main thread
#Use AsyncTasks for compression during the main game session. Increases latency, but may reduce main thread load
async-compression: false
#Threshold for async compression, in bytes. Only packets larger than this will be compressed asynchronously
#Due to large overhead of AsyncTask, async compression isn't worth it except for large packets
async-compression-threshold: 10000
#Experimental. Use UPnP to automatically port forward
upnp-forwarding: false
#Maximum size in bytes of packets sent over the network (default 1492 bytes). Packets larger than this will be

View File

@ -30,6 +30,7 @@ use pocketmine\scheduler\GarbageCollectionTask;
use pocketmine\timings\Timings;
use pocketmine\utils\Process;
use pocketmine\utils\Utils;
use pocketmine\YmlServerProperties as Yml;
use Symfony\Component\Filesystem\Path;
use function arsort;
use function count;
@ -109,7 +110,7 @@ class MemoryManager{
}
private function init(ServerConfigGroup $config) : void{
$this->memoryLimit = $config->getPropertyInt("memory.main-limit", 0) * 1024 * 1024;
$this->memoryLimit = $config->getPropertyInt(Yml::MEMORY_MAIN_LIMIT, 0) * 1024 * 1024;
$defaultMemory = 1024;
@ -127,7 +128,7 @@ class MemoryManager{
}
}
$hardLimit = $config->getPropertyInt("memory.main-hard-limit", $defaultMemory);
$hardLimit = $config->getPropertyInt(Yml::MEMORY_MAIN_HARD_LIMIT, $defaultMemory);
if($hardLimit <= 0){
ini_set("memory_limit", '-1');
@ -135,22 +136,22 @@ class MemoryManager{
ini_set("memory_limit", $hardLimit . "M");
}
$this->globalMemoryLimit = $config->getPropertyInt("memory.global-limit", 0) * 1024 * 1024;
$this->checkRate = $config->getPropertyInt("memory.check-rate", self::DEFAULT_CHECK_RATE);
$this->continuousTrigger = $config->getPropertyBool("memory.continuous-trigger", true);
$this->continuousTriggerRate = $config->getPropertyInt("memory.continuous-trigger-rate", self::DEFAULT_CONTINUOUS_TRIGGER_RATE);
$this->globalMemoryLimit = $config->getPropertyInt(Yml::MEMORY_GLOBAL_LIMIT, 0) * 1024 * 1024;
$this->checkRate = $config->getPropertyInt(Yml::MEMORY_CHECK_RATE, self::DEFAULT_CHECK_RATE);
$this->continuousTrigger = $config->getPropertyBool(Yml::MEMORY_CONTINUOUS_TRIGGER, true);
$this->continuousTriggerRate = $config->getPropertyInt(Yml::MEMORY_CONTINUOUS_TRIGGER_RATE, self::DEFAULT_CONTINUOUS_TRIGGER_RATE);
$this->garbageCollectionPeriod = $config->getPropertyInt("memory.garbage-collection.period", self::DEFAULT_TICKS_PER_GC);
$this->garbageCollectionTrigger = $config->getPropertyBool("memory.garbage-collection.low-memory-trigger", true);
$this->garbageCollectionAsync = $config->getPropertyBool("memory.garbage-collection.collect-async-worker", true);
$this->garbageCollectionPeriod = $config->getPropertyInt(Yml::MEMORY_GARBAGE_COLLECTION_PERIOD, self::DEFAULT_TICKS_PER_GC);
$this->garbageCollectionTrigger = $config->getPropertyBool(Yml::MEMORY_GARBAGE_COLLECTION_LOW_MEMORY_TRIGGER, true);
$this->garbageCollectionAsync = $config->getPropertyBool(Yml::MEMORY_GARBAGE_COLLECTION_COLLECT_ASYNC_WORKER, true);
$this->lowMemChunkRadiusOverride = $config->getPropertyInt("memory.max-chunks.chunk-radius", 4);
$this->lowMemChunkGC = $config->getPropertyBool("memory.max-chunks.trigger-chunk-collect", true);
$this->lowMemChunkRadiusOverride = $config->getPropertyInt(Yml::MEMORY_MAX_CHUNKS_CHUNK_RADIUS, 4);
$this->lowMemChunkGC = $config->getPropertyBool(Yml::MEMORY_MAX_CHUNKS_TRIGGER_CHUNK_COLLECT, true);
$this->lowMemDisableChunkCache = $config->getPropertyBool("memory.world-caches.disable-chunk-cache", true);
$this->lowMemClearWorldCache = $config->getPropertyBool("memory.world-caches.low-memory-trigger", true);
$this->lowMemDisableChunkCache = $config->getPropertyBool(Yml::MEMORY_WORLD_CACHES_DISABLE_CHUNK_CACHE, true);
$this->lowMemClearWorldCache = $config->getPropertyBool(Yml::MEMORY_WORLD_CACHES_LOW_MEMORY_TRIGGER, true);
$this->dumpWorkers = $config->getPropertyBool("memory.memory-dump.dump-async-worker", true);
$this->dumpWorkers = $config->getPropertyBool(Yml::MEMORY_MEMORY_DUMP_DUMP_ASYNC_WORKER, true);
gc_enable();
}
@ -314,9 +315,6 @@ class MemoryManager{
continue;
}
if(!$property->isPublic()){
$property->setAccessible(true);
}
if(!$property->isInitialized()){
continue;
}
@ -362,7 +360,7 @@ class MemoryManager{
'_SESSION' => true
];
foreach(Utils::stringifyKeys($GLOBALS) as $varName => $value){
foreach($GLOBALS as $varName => $value){
if(isset($ignoredGlobals[$varName])){
continue;
}
@ -440,9 +438,6 @@ class MemoryManager{
continue;
}
}
if(!$property->isPublic()){
$property->setAccessible(true);
}
if(!$property->isInitialized($object)){
continue;
}

View File

@ -26,6 +26,7 @@ namespace pocketmine {
use Composer\InstalledVersions;
use pocketmine\errorhandler\ErrorToExceptionHandler;
use pocketmine\thread\ThreadManager;
use pocketmine\thread\ThreadSafeClassLoader;
use pocketmine\utils\Filesystem;
use pocketmine\utils\MainLogger;
use pocketmine\utils\Process;
@ -50,7 +51,7 @@ namespace pocketmine {
require_once __DIR__ . '/VersionInfo.php';
const MIN_PHP_VERSION = "8.0.0";
const MIN_PHP_VERSION = "8.1.0";
/**
* @param string $message
@ -103,7 +104,7 @@ namespace pocketmine {
"openssl" => "OpenSSL",
"pcre" => "PCRE",
"phar" => "Phar",
"pthreads" => "pthreads",
"pmmpthread" => "pmmpthread",
"reflection" => "Reflection",
"sockets" => "Sockets",
"spl" => "SPL",
@ -118,12 +119,9 @@ namespace pocketmine {
}
}
if(($pthreads_version = phpversion("pthreads")) !== false){
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
if(version_compare($pthreads_version, "5.1.0") < 0 || version_compare($pthreads_version, "6.0.0") >= 0){
$messages[] = "pthreads ^5.0.0 is required, while you have $pthreads_version.";
if(($pmmpthread_version = phpversion("pmmpthread")) !== false){
if(version_compare($pmmpthread_version, "6.0.7") < 0 || version_compare($pmmpthread_version, "7.0.0") >= 0){
$messages[] = "pmmpthread ^6.0.7 is required, while you have $pmmpthread_version.";
}
}
@ -265,9 +263,6 @@ JIT_WARNING
exit(1);
}
}
if(extension_loaded('parallel')){
\parallel\bootstrap(\pocketmine\COMPOSER_AUTOLOADER_PATH);
}
ErrorToExceptionHandler::set();
@ -333,7 +328,7 @@ JIT_WARNING
/*
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
*/
$autoloader = new \BaseClassLoader();
$autoloader = new ThreadSafeClassLoader();
$autoloader->register(false);
new Server($autoloader, $logger, $dataPath, $pluginPath);
@ -341,12 +336,12 @@ JIT_WARNING
$logger->info("Stopping other threads");
$killer = new ServerKiller(8);
$killer->start(PTHREADS_INHERIT_NONE);
$killer->start();
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
if(ThreadManager::getInstance()->stopAll() > 0){
$logger->debug("Some threads could not be stopped, performing a force-kill");
Process::kill(Process::pid(), true);
Process::kill(Process::pid());
}
}while(false);

View File

@ -53,7 +53,7 @@ use pocketmine\network\mcpe\compression\CompressBatchPromise;
use pocketmine\network\mcpe\compression\CompressBatchTask;
use pocketmine\network\mcpe\compression\Compressor;
use pocketmine\network\mcpe\compression\ZlibCompressor;
use pocketmine\network\mcpe\convert\GlobalItemTypeDictionary;
use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\network\mcpe\encryption\EncryptionContext;
use pocketmine\network\mcpe\EntityEventBroadcaster;
use pocketmine\network\mcpe\NetworkSession;
@ -80,7 +80,6 @@ use pocketmine\player\PlayerDataProvider;
use pocketmine\player\PlayerDataSaveException;
use pocketmine\player\PlayerInfo;
use pocketmine\plugin\PharPluginLoader;
use pocketmine\plugin\Plugin;
use pocketmine\plugin\PluginEnableOrder;
use pocketmine\plugin\PluginGraylist;
use pocketmine\plugin\PluginManager;
@ -92,6 +91,9 @@ use pocketmine\resourcepacks\ResourcePackManager;
use pocketmine\scheduler\AsyncPool;
use pocketmine\snooze\SleeperHandler;
use pocketmine\stats\SendUsageTask;
use pocketmine\thread\log\AttachableThreadSafeLogger;
use pocketmine\thread\ThreadCrashException;
use pocketmine\thread\ThreadSafeClassLoader;
use pocketmine\timings\Timings;
use pocketmine\timings\TimingsHandler;
use pocketmine\updater\UpdateChecker;
@ -117,6 +119,7 @@ use pocketmine\world\Position;
use pocketmine\world\World;
use pocketmine\world\WorldCreationOptions;
use pocketmine\world\WorldManager;
use pocketmine\YmlServerProperties as Yml;
use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Filesystem\Path;
use function array_fill;
@ -205,6 +208,8 @@ class Server{
private const TICKS_PER_TPS_OVERLOAD_WARNING = 5 * self::TARGET_TICKS_PER_SECOND;
private const TICKS_PER_STATS_REPORT = 300 * self::TARGET_TICKS_PER_SECOND;
private const DEFAULT_ASYNC_COMPRESSION_THRESHOLD = 10_000;
private static ?Server $instance = null;
private TimeTrackingSleeperHandler $tickSleeper;
@ -263,6 +268,7 @@ class Server{
private Network $network;
private bool $networkCompressionAsync = true;
private int $networkCompressionAsyncThreshold = self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD;
private Language $language;
private bool $forceLanguage = false;
@ -351,15 +357,15 @@ class Server{
}
public function getPort() : int{
return $this->configGroup->getConfigInt("server-port", self::DEFAULT_PORT_IPV4);
return $this->configGroup->getConfigInt(ServerProperties::SERVER_PORT_IPV4, self::DEFAULT_PORT_IPV4);
}
public function getPortV6() : int{
return $this->configGroup->getConfigInt("server-portv6", self::DEFAULT_PORT_IPV6);
return $this->configGroup->getConfigInt(ServerProperties::SERVER_PORT_IPV6, self::DEFAULT_PORT_IPV6);
}
public function getViewDistance() : int{
return max(2, $this->configGroup->getConfigInt("view-distance", self::DEFAULT_MAX_VIEW_DISTANCE));
return max(2, $this->configGroup->getConfigInt(ServerProperties::VIEW_DISTANCE, self::DEFAULT_MAX_VIEW_DISTANCE));
}
/**
@ -370,12 +376,12 @@ class Server{
}
public function getIp() : string{
$str = $this->configGroup->getConfigString("server-ip");
$str = $this->configGroup->getConfigString(ServerProperties::SERVER_IPV4);
return $str !== "" ? $str : "0.0.0.0";
}
public function getIpV6() : string{
$str = $this->configGroup->getConfigString("server-ipv6");
$str = $this->configGroup->getConfigString(ServerProperties::SERVER_IPV6);
return $str !== "" ? $str : "::";
}
@ -384,37 +390,37 @@ class Server{
}
public function getGamemode() : GameMode{
return GameMode::fromString($this->configGroup->getConfigString("gamemode", GameMode::SURVIVAL()->name())) ?? GameMode::SURVIVAL();
return GameMode::fromString($this->configGroup->getConfigString(ServerProperties::GAME_MODE, GameMode::SURVIVAL()->name())) ?? GameMode::SURVIVAL();
}
public function getForceGamemode() : bool{
return $this->configGroup->getConfigBool("force-gamemode", false);
return $this->configGroup->getConfigBool(ServerProperties::FORCE_GAME_MODE, false);
}
/**
* Returns Server global difficulty. Note that this may be overridden in individual worlds.
*/
public function getDifficulty() : int{
return $this->configGroup->getConfigInt("difficulty", World::DIFFICULTY_NORMAL);
return $this->configGroup->getConfigInt(ServerProperties::DIFFICULTY, World::DIFFICULTY_NORMAL);
}
public function hasWhitelist() : bool{
return $this->configGroup->getConfigBool("white-list", false);
return $this->configGroup->getConfigBool(ServerProperties::WHITELIST, false);
}
public function isHardcore() : bool{
return $this->configGroup->getConfigBool("hardcore", false);
return $this->configGroup->getConfigBool(ServerProperties::HARDCORE, false);
}
public function getMotd() : string{
return $this->configGroup->getConfigString("motd", self::DEFAULT_SERVER_NAME);
return $this->configGroup->getConfigString(ServerProperties::MOTD, self::DEFAULT_SERVER_NAME);
}
public function getLoader() : \DynamicClassLoader{
public function getLoader() : ThreadSafeClassLoader{
return $this->autoloader;
}
public function getLogger() : \AttachableThreadedLogger{
public function getLogger() : AttachableThreadSafeLogger{
return $this->logger;
}
@ -490,7 +496,7 @@ class Server{
}
public function shouldSavePlayerData() : bool{
return $this->configGroup->getPropertyBool("player.save-player-data", true);
return $this->configGroup->getPropertyBool(Yml::PLAYER_SAVE_PLAYER_DATA, true);
}
public function getOfflinePlayer(string $name) : Player|OfflinePlayer|null{
@ -564,6 +570,7 @@ class Server{
$playerPromiseResolver = new PromiseResolver();
$createPlayer = function(Location $location) use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $offlinePlayerData) : void{
/** @see Player::__construct() */
$player = new $class($this, $session, $playerInfo, $authenticated, $location, $offlinePlayerData);
if(!$player->hasPlayedBefore()){
$player->onGround = true; //TODO: this hack is needed for new players in-air ticks - they don't get detected as on-ground until they move
@ -730,7 +737,7 @@ class Server{
* @return string[][]
*/
public function getCommandAliases() : array{
$section = $this->configGroup->getProperty("aliases");
$section = $this->configGroup->getProperty(YmlServerProperties::ALIASES);
$result = [];
if(is_array($section)){
foreach($section as $key => $value){
@ -756,8 +763,8 @@ class Server{
}
public function __construct(
private \DynamicClassLoader $autoloader,
private \AttachableThreadedLogger $logger,
private ThreadSafeClassLoader $autoloader,
private AttachableThreadSafeLogger $logger,
string $dataPath,
string $pluginPath
){
@ -805,36 +812,36 @@ class Server{
$this->configGroup = new ServerConfigGroup(
new Config($pocketmineYmlPath, Config::YAML, []),
new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES, [
"motd" => self::DEFAULT_SERVER_NAME,
"server-port" => self::DEFAULT_PORT_IPV4,
"server-portv6" => self::DEFAULT_PORT_IPV6,
"enable-ipv6" => true,
"white-list" => false,
"max-players" => self::DEFAULT_MAX_PLAYERS,
"gamemode" => GameMode::SURVIVAL()->name(),
"force-gamemode" => false,
"hardcore" => false,
"pvp" => true,
"difficulty" => World::DIFFICULTY_NORMAL,
"generator-settings" => "",
"level-name" => "world",
"level-seed" => "",
"level-type" => "DEFAULT",
"enable-query" => true,
"auto-save" => true,
"view-distance" => self::DEFAULT_MAX_VIEW_DISTANCE,
"xbox-auth" => true,
"language" => "eng"
ServerProperties::MOTD => self::DEFAULT_SERVER_NAME,
ServerProperties::SERVER_PORT_IPV4 => self::DEFAULT_PORT_IPV4,
ServerProperties::SERVER_PORT_IPV6 => self::DEFAULT_PORT_IPV6,
ServerProperties::ENABLE_IPV6 => true,
ServerProperties::WHITELIST => false,
ServerProperties::MAX_PLAYERS => self::DEFAULT_MAX_PLAYERS,
ServerProperties::GAME_MODE => GameMode::SURVIVAL()->name(),
ServerProperties::FORCE_GAME_MODE => false,
ServerProperties::HARDCORE => false,
ServerProperties::PVP => true,
ServerProperties::DIFFICULTY => World::DIFFICULTY_NORMAL,
ServerProperties::DEFAULT_WORLD_GENERATOR_SETTINGS => "",
ServerProperties::DEFAULT_WORLD_NAME => "world",
ServerProperties::DEFAULT_WORLD_SEED => "",
ServerProperties::DEFAULT_WORLD_GENERATOR => "DEFAULT",
ServerProperties::ENABLE_QUERY => true,
ServerProperties::AUTO_SAVE => true,
ServerProperties::VIEW_DISTANCE => self::DEFAULT_MAX_VIEW_DISTANCE,
ServerProperties::XBOX_AUTH => true,
ServerProperties::LANGUAGE => "eng"
])
);
$debugLogLevel = $this->configGroup->getPropertyInt("debug.level", 1);
$debugLogLevel = $this->configGroup->getPropertyInt(Yml::DEBUG_LEVEL, 1);
if($this->logger instanceof MainLogger){
$this->logger->setLogDebug($debugLogLevel > 1);
}
$this->forceLanguage = $this->configGroup->getPropertyBool("settings.force-language", false);
$selectedLang = $this->configGroup->getConfigString("language", $this->configGroup->getPropertyString("settings.language", Language::FALLBACK_LANGUAGE));
$this->forceLanguage = $this->configGroup->getPropertyBool(Yml::SETTINGS_FORCE_LANGUAGE, false);
$selectedLang = $this->configGroup->getConfigString(ServerProperties::LANGUAGE, $this->configGroup->getPropertyString("settings.language", Language::FALLBACK_LANGUAGE));
try{
$this->language = new Language($selectedLang);
}catch(LanguageNotFoundException $e){
@ -850,11 +857,11 @@ class Server{
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::language_selected($this->getLanguage()->getName(), $this->getLanguage()->getLang())));
if(VersionInfo::IS_DEVELOPMENT_BUILD){
if(!$this->configGroup->getPropertyBool("settings.enable-dev-builds", false)){
if(!$this->configGroup->getPropertyBool(Yml::SETTINGS_ENABLE_DEV_BUILDS, false)){
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error1(VersionInfo::NAME)));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error2()));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error3()));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error4("settings.enable-dev-builds")));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error4(YmlServerProperties::SETTINGS_ENABLE_DEV_BUILDS)));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error5("https://github.com/pmmp/PocketMine-MP/releases")));
$this->forceShutdownExit();
@ -872,7 +879,7 @@ class Server{
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_start(TextFormat::AQUA . $this->getVersion() . TextFormat::RESET)));
if(($poolSize = $this->configGroup->getPropertyString("settings.async-workers", "auto")) === "auto"){
if(($poolSize = $this->configGroup->getPropertyString(Yml::SETTINGS_ASYNC_WORKERS, "auto")) === "auto"){
$poolSize = 2;
$processors = Utils::getCoreCount() - 2;
@ -883,28 +890,32 @@ class Server{
$poolSize = max(1, (int) $poolSize);
}
$this->asyncPool = new AsyncPool($poolSize, max(-1, $this->configGroup->getPropertyInt("memory.async-worker-hard-limit", 256)), $this->autoloader, $this->logger, $this->tickSleeper);
$this->asyncPool = new AsyncPool($poolSize, max(-1, $this->configGroup->getPropertyInt(Yml::MEMORY_ASYNC_WORKER_HARD_LIMIT, 256)), $this->autoloader, $this->logger, $this->tickSleeper);
$netCompressionThreshold = -1;
if($this->configGroup->getPropertyInt("network.batch-threshold", 256) >= 0){
$netCompressionThreshold = $this->configGroup->getPropertyInt("network.batch-threshold", 256);
if($this->configGroup->getPropertyInt(Yml::NETWORK_BATCH_THRESHOLD, 256) >= 0){
$netCompressionThreshold = $this->configGroup->getPropertyInt(Yml::NETWORK_BATCH_THRESHOLD, 256);
}
if($netCompressionThreshold < 0){
$netCompressionThreshold = null;
}
$netCompressionLevel = $this->configGroup->getPropertyInt("network.compression-level", 6);
$netCompressionLevel = $this->configGroup->getPropertyInt(Yml::NETWORK_COMPRESSION_LEVEL, 6);
if($netCompressionLevel < 1 || $netCompressionLevel > 9){
$this->logger->warning("Invalid network compression level $netCompressionLevel set, setting to default 6");
$netCompressionLevel = 6;
}
ZlibCompressor::setInstance(new ZlibCompressor($netCompressionLevel, $netCompressionThreshold, ZlibCompressor::DEFAULT_MAX_DECOMPRESSION_SIZE));
$this->networkCompressionAsync = $this->configGroup->getPropertyBool("network.async-compression", true);
$this->networkCompressionAsync = $this->configGroup->getPropertyBool(Yml::NETWORK_ASYNC_COMPRESSION, true);
$this->networkCompressionAsyncThreshold = max(
$this->configGroup->getPropertyInt(Yml::NETWORK_ASYNC_COMPRESSION_THRESHOLD, self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD),
$netCompressionThreshold ?? self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD
);
EncryptionContext::$ENABLED = $this->configGroup->getPropertyBool("network.enable-encryption", true);
EncryptionContext::$ENABLED = $this->configGroup->getPropertyBool(Yml::NETWORK_ENABLE_ENCRYPTION, true);
$this->doTitleTick = $this->configGroup->getPropertyBool("console.title-tick", true) && Terminal::hasFormattingCodes();
$this->doTitleTick = $this->configGroup->getPropertyBool(Yml::CONSOLE_TITLE_TICK, true) && Terminal::hasFormattingCodes();
$this->operators = new Config(Path::join($this->dataPath, "ops.txt"), Config::ENUM);
$this->whitelist = new Config(Path::join($this->dataPath, "white-list.txt"), Config::ENUM);
@ -922,9 +933,9 @@ class Server{
$this->banByIP = new BanList($bannedIpsTxt);
$this->banByIP->load();
$this->maxPlayers = $this->configGroup->getConfigInt("max-players", self::DEFAULT_MAX_PLAYERS);
$this->maxPlayers = $this->configGroup->getConfigInt(ServerProperties::MAX_PLAYERS, self::DEFAULT_MAX_PLAYERS);
$this->onlineMode = $this->configGroup->getConfigBool("xbox-auth", true);
$this->onlineMode = $this->configGroup->getConfigBool(ServerProperties::XBOX_AUTH, true);
if($this->onlineMode){
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_auth_enabled()));
}else{
@ -933,8 +944,8 @@ class Server{
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_authProperty_disabled()));
}
if($this->configGroup->getConfigBool("hardcore", false) && $this->getDifficulty() < World::DIFFICULTY_HARD){
$this->configGroup->setConfigInt("difficulty", World::DIFFICULTY_HARD);
if($this->configGroup->getConfigBool(ServerProperties::HARDCORE, false) && $this->getDifficulty() < World::DIFFICULTY_HARD){
$this->configGroup->setConfigInt(ServerProperties::DIFFICULTY, World::DIFFICULTY_HARD);
}
@cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion());
@ -953,8 +964,8 @@ class Server{
)));
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_license($this->getName())));
TimingsHandler::setEnabled($this->configGroup->getPropertyBool("settings.enable-profiling", false));
$this->profilingTickRate = $this->configGroup->getPropertyInt("settings.profile-report-trigger", self::TARGET_TICKS_PER_SECOND);
TimingsHandler::setEnabled($this->configGroup->getPropertyBool(Yml::SETTINGS_ENABLE_PROFILING, false));
$this->profilingTickRate = $this->configGroup->getPropertyInt(Yml::SETTINGS_PROFILE_REPORT_TRIGGER, self::TARGET_TICKS_PER_SECOND);
DefaultPermissions::registerCorePermissions();
@ -976,13 +987,13 @@ class Server{
$this->forceShutdownExit();
return;
}
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool("plugins.legacy-data-dir", true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist);
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool(Yml::PLUGINS_LEGACY_DATA_DIR, true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist);
$this->pluginManager->registerInterface(new PharPluginLoader($this->autoloader));
$this->pluginManager->registerInterface(new ScriptPluginLoader());
$providerManager = new WorldProviderManager();
if(
($format = $providerManager->getProviderByName($formatName = $this->configGroup->getPropertyString("level-settings.default-format", ""))) !== null &&
($format = $providerManager->getProviderByName($formatName = $this->configGroup->getPropertyString(Yml::LEVEL_SETTINGS_DEFAULT_FORMAT, ""))) !== null &&
$format instanceof WritableWorldProviderManagerEntry
){
$providerManager->setDefault($format);
@ -991,16 +1002,16 @@ class Server{
}
$this->worldManager = new WorldManager($this, Path::join($this->dataPath, "worlds"), $providerManager);
$this->worldManager->setAutoSave($this->configGroup->getConfigBool("auto-save", $this->worldManager->getAutoSave()));
$this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt("ticks-per.autosave", $this->worldManager->getAutoSaveInterval()));
$this->worldManager->setAutoSave($this->configGroup->getConfigBool(ServerProperties::AUTO_SAVE, $this->worldManager->getAutoSave()));
$this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt(Yml::TICKS_PER_AUTOSAVE, $this->worldManager->getAutoSaveInterval()));
$this->updater = new UpdateChecker($this, $this->configGroup->getPropertyString("auto-updater.host", "update.pmmp.io"));
$this->updater = new UpdateChecker($this, $this->configGroup->getPropertyString(Yml::AUTO_UPDATER_HOST, "update.pmmp.io"));
$this->queryInfo = new QueryInfo($this);
$this->playerDataProvider = new DatFilePlayerDataProvider(Path::join($this->dataPath, "players"));
register_shutdown_function([$this, "crashDump"]);
register_shutdown_function($this->crashDump(...));
$loadErrorCount = 0;
$this->pluginManager->loadPlugins($this->pluginPath, $loadErrorCount);
@ -1031,7 +1042,7 @@ class Server{
return;
}
if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){
if($this->configGroup->getPropertyBool(Yml::ANONYMOUS_STATISTICS_ENABLED, true)){
$this->sendUsageTicker = self::TICKS_PER_STATS_REPORT;
$this->sendUsage(SendUsageTask::TYPE_OPEN);
}
@ -1047,7 +1058,7 @@ class Server{
$this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_USERS, $forwarder);
//TODO: move console parts to a separate component
if($this->configGroup->getPropertyBool("console.enable-input", true)){
if($this->configGroup->getPropertyBool(Yml::CONSOLE_ENABLE_INPUT, true)){
$this->console = new ConsoleReaderChildProcessDaemon($this->logger);
}
@ -1082,7 +1093,7 @@ class Server{
$anyWorldFailedToLoad = false;
foreach((array) $this->configGroup->getProperty("worlds", []) as $name => $options){
foreach((array) $this->configGroup->getProperty(Yml::WORLDS, []) as $name => $options){
if($options === null){
$options = [];
}elseif(!is_array($options)){
@ -1126,11 +1137,11 @@ class Server{
}
if($this->worldManager->getDefaultWorld() === null){
$default = $this->configGroup->getConfigString("level-name", "world");
$default = $this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_NAME, "world");
if(trim($default) == ""){
$this->getLogger()->warning("level-name cannot be null, using default");
$default = "world";
$this->configGroup->setConfigString("level-name", "world");
$this->configGroup->setConfigString(ServerProperties::DEFAULT_WORLD_NAME, "world");
}
if(!$this->worldManager->loadWorld($default, true)){
if($this->worldManager->isWorldGenerated($default)){
@ -1138,8 +1149,8 @@ class Server{
return false;
}
$generatorName = $this->configGroup->getConfigString("level-type");
$generatorOptions = $this->configGroup->getConfigString("generator-settings");
$generatorName = $this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_GENERATOR);
$generatorOptions = $this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_GENERATOR_SETTINGS);
$generatorClass = $getGenerator($generatorName, $generatorOptions, $default);
if($generatorClass === null){
@ -1149,7 +1160,7 @@ class Server{
$creationOptions = WorldCreationOptions::create()
->setGeneratorClass($generatorClass)
->setGeneratorOptions($generatorOptions);
$convertedSeed = Generator::convertSeed($this->configGroup->getConfigString("level-seed"));
$convertedSeed = Generator::convertSeed($this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_SEED));
if($convertedSeed !== null){
$creationOptions->setSeed($convertedSeed);
}
@ -1174,11 +1185,12 @@ class Server{
bool $useQuery,
PacketBroadcaster $packetBroadcaster,
EntityEventBroadcaster $entityEventBroadcaster,
PacketSerializerContext $packetSerializerContext
PacketSerializerContext $packetSerializerContext,
TypeConverter $typeConverter
) : bool{
$prettyIp = $ipV6 ? "[$ip]" : $ip;
try{
$rakLibRegistered = $this->network->registerInterface(new RakLibInterface($this, $ip, $port, $ipV6, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext));
$rakLibRegistered = $this->network->registerInterface(new RakLibInterface($this, $ip, $port, $ipV6, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter));
}catch(NetworkInterfaceStartException $e){
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_networkStartFailed(
$ip,
@ -1202,17 +1214,18 @@ class Server{
}
private function startupPrepareNetworkInterfaces() : bool{
$useQuery = $this->configGroup->getConfigBool("enable-query", true);
$useQuery = $this->configGroup->getConfigBool(ServerProperties::ENABLE_QUERY, true);
$packetSerializerContext = new PacketSerializerContext(GlobalItemTypeDictionary::getInstance()->getDictionary());
$typeConverter = TypeConverter::getInstance();
$packetSerializerContext = new PacketSerializerContext($typeConverter->getItemTypeDictionary());
$packetBroadcaster = new StandardPacketBroadcaster($this, $packetSerializerContext);
$entityEventBroadcaster = new StandardEntityEventBroadcaster($packetBroadcaster);
$entityEventBroadcaster = new StandardEntityEventBroadcaster($packetBroadcaster, $typeConverter);
if(
!$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext) ||
!$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter) ||
(
$this->configGroup->getConfigBool("enable-ipv6", true) &&
!$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext)
$this->configGroup->getConfigBool(ServerProperties::ENABLE_IPV6, true) &&
!$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter)
)
){
return false;
@ -1226,7 +1239,7 @@ class Server{
$this->network->blockAddress($entry->getName(), -1);
}
if($this->configGroup->getPropertyBool("network.upnp-forwarding", false)){
if($this->configGroup->getPropertyBool(Yml::NETWORK_UPNP_FORWARDING, false)){
$this->network->registerInterface(new UPnPNetworkInterface($this->logger, Internet::getInternalIP(), $this->getPort()));
}
@ -1357,7 +1370,7 @@ class Server{
}
$promise = new CompressBatchPromise();
if(!$sync){
if(!$sync && strlen($buffer) >= $this->networkCompressionAsyncThreshold){
$task = new CompressBatchTask($buffer, $promise, $compressor);
$this->asyncPool->submitTask($task);
}else{
@ -1416,7 +1429,7 @@ class Server{
private function forceShutdownExit() : void{
$this->forceShutdown();
Process::kill(Process::pid(), true);
Process::kill(Process::pid());
}
public function forceShutdown() : void{
@ -1446,7 +1459,7 @@ class Server{
}
if(isset($this->network)){
$this->network->getSessionManager()->close($this->configGroup->getPropertyString("settings.shutdown-message", "Server closed"));
$this->network->getSessionManager()->close($this->configGroup->getPropertyString(YmlServerProperties::SETTINGS_SHUTDOWN_MESSAGE, "Server closed"));
}
if(isset($this->worldManager)){
@ -1484,7 +1497,7 @@ class Server{
}catch(\Throwable $e){
$this->logger->logException($e);
$this->logger->emergency("Crashed while crashing, killing process");
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
}
}
@ -1505,23 +1518,38 @@ class Server{
$trace = $e->getTrace();
}
$errstr = $e->getMessage();
$errfile = $e->getFile();
$errline = $e->getLine();
//If this is a thread crash, this logs where the exception came from on the main thread, as opposed to the
//crashed thread. This is intentional, and might be useful for debugging
//Assume that the thread already logged the original exception with the correct stack trace
$this->logger->logException($e, $trace);
if($e instanceof ThreadCrashException){
$info = $e->getCrashInfo();
$type = $info->getType();
$errstr = $info->getMessage();
$errfile = $info->getFile();
$errline = $info->getLine();
$printableTrace = $info->getTrace();
$thread = $info->getThreadName();
}else{
$type = get_class($e);
$errstr = $e->getMessage();
$errfile = $e->getFile();
$errline = $e->getLine();
$printableTrace = Utils::printableTraceWithMetadata($trace);
$thread = "Main";
}
$errstr = preg_replace('/\s+/', ' ', trim($errstr));
$errfile = Filesystem::cleanPath($errfile);
$this->logger->logException($e, $trace);
$lastError = [
"type" => get_class($e),
"type" => $type,
"message" => $errstr,
"fullFile" => $e->getFile(),
"file" => $errfile,
"fullFile" => $errfile,
"file" => Filesystem::cleanPath($errfile),
"line" => $errline,
"trace" => $trace
"trace" => $printableTrace,
"thread" => $thread
];
global $lastExceptionError, $lastError;
@ -1568,7 +1596,7 @@ class Server{
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_submit($crashDumpPath)));
if($this->configGroup->getPropertyBool("auto-report.enabled", true)){
if($this->configGroup->getPropertyBool(Yml::AUTO_REPORT_ENABLED, true)){
$report = true;
$stamp = Path::join($this->getDataPath(), "crashdumps", ".last_crash");
@ -1579,15 +1607,6 @@ class Server{
}
@touch($stamp); //update file timestamp
$plugin = $dump->getData()->plugin;
if($plugin !== ""){
$p = $this->pluginManager->getPlugin($plugin);
if($p instanceof Plugin && !($p->getPluginLoader() instanceof PharPluginLoader)){
$this->logger->debug("Not sending crashdump due to caused by non-phar plugin");
$report = false;
}
}
if($dump->getData()->error["type"] === \ParseError::class){
$report = false;
}
@ -1598,7 +1617,7 @@ class Server{
}
if($report){
$url = ($this->configGroup->getPropertyBool("auto-report.use-https", true) ? "https" : "http") . "://" . $this->configGroup->getPropertyString("auto-report.host", "crash.pmmp.io") . "/submit/api";
$url = ($this->configGroup->getPropertyBool(Yml::AUTO_REPORT_USE_HTTPS, true) ? "https" : "http") . "://" . $this->configGroup->getPropertyString(Yml::AUTO_REPORT_HOST, "crash.pmmp.io") . "/submit/api";
$postUrlError = "Unknown error";
$reply = Internet::postURL($url, [
"report" => "yes",
@ -1638,7 +1657,7 @@ class Server{
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
sleep($spacing);
}
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
exit(1);
}
@ -1709,7 +1728,7 @@ class Server{
}
public function sendUsage(int $type = SendUsageTask::TYPE_STATUS) : void{
if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){
if($this->configGroup->getPropertyBool(Yml::ANONYMOUS_STATISTICS_ENABLED, true)){
$this->asyncPool->submitTask(new SendUsageTask($this, $type, $this->uniquePlayers));
}
$this->uniquePlayers = [];

58
src/ServerProperties.php Normal file
View File

@ -0,0 +1,58 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine;
/**
* @internal
* Constants for all properties available in server.properties.
*/
final class ServerProperties{
private function __construct(){
//NOOP
}
public const AUTO_SAVE = "auto-save";
public const DEFAULT_WORLD_GENERATOR = "level-type";
public const DEFAULT_WORLD_GENERATOR_SETTINGS = "generator-settings";
public const DEFAULT_WORLD_NAME = "level-name";
public const DEFAULT_WORLD_SEED = "level-seed";
public const DIFFICULTY = "difficulty";
public const ENABLE_IPV6 = "enable-ipv6";
public const ENABLE_QUERY = "enable-query";
public const FORCE_GAME_MODE = "force-gamemode";
public const GAME_MODE = "gamemode";
public const HARDCORE = "hardcore";
public const LANGUAGE = "language";
public const MAX_PLAYERS = "max-players";
public const MOTD = "motd";
public const PVP = "pvp";
public const SERVER_IPV4 = "server-ip";
public const SERVER_IPV6 = "server-ipv6";
public const SERVER_PORT_IPV4 = "server-port";
public const SERVER_PORT_IPV6 = "server-portv6";
public const VIEW_DISTANCE = "view-distance";
public const WHITELIST = "white-list";
public const XBOX_AUTH = "xbox-auth";
}

View File

@ -31,10 +31,24 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
public const BASE_VERSION = "5.0.0-BETA2";
public const BASE_VERSION = "5.6.1";
public const IS_DEVELOPMENT_BUILD = false;
public const BUILD_CHANNEL = "beta";
public const BUILD_CHANNEL = "stable";
/**
* PocketMine-MP-specific version ID for world data. Used to determine what fixes need to be applied to old world
* data (e.g. stuff saved wrongly by past versions).
* This version supplements the Minecraft vanilla world version.
*
* This should be bumped if any **non-Mojang** BC-breaking change or bug fix is made to world save data of any kind
* (entities, tiles, blocks, biomes etc.). For example, if PM accidentally saved a block with its facing value
* swapped, we would bump this, but not if Mojang did the same change.
*/
public const WORLD_DATA_VERSION = 1;
/**
* Name of the NBT tag used to store the world data version.
*/
public const TAG_WORLD_DATA_VERSION = "PMMPDataVersion"; //TAG_Long
private function __construct(){
//NOOP

118
src/YmlServerProperties.php Normal file
View File

@ -0,0 +1,118 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine;
/**
* @internal
* Constants for all properties available in pocketmine.yml.
* This is generated by build/generate-pocketmine-yml-property-consts.php.
* Do not edit this file manually.
*/
final class YmlServerProperties{
private function __construct(){
//NOOP
}
public const ALIASES = 'aliases';
public const ANONYMOUS_STATISTICS = 'anonymous-statistics';
public const ANONYMOUS_STATISTICS_ENABLED = 'anonymous-statistics.enabled';
public const ANONYMOUS_STATISTICS_HOST = 'anonymous-statistics.host';
public const AUTO_REPORT = 'auto-report';
public const AUTO_REPORT_ENABLED = 'auto-report.enabled';
public const AUTO_REPORT_HOST = 'auto-report.host';
public const AUTO_REPORT_SEND_CODE = 'auto-report.send-code';
public const AUTO_REPORT_SEND_PHPINFO = 'auto-report.send-phpinfo';
public const AUTO_REPORT_SEND_SETTINGS = 'auto-report.send-settings';
public const AUTO_REPORT_USE_HTTPS = 'auto-report.use-https';
public const AUTO_UPDATER = 'auto-updater';
public const AUTO_UPDATER_ENABLED = 'auto-updater.enabled';
public const AUTO_UPDATER_HOST = 'auto-updater.host';
public const AUTO_UPDATER_ON_UPDATE = 'auto-updater.on-update';
public const AUTO_UPDATER_ON_UPDATE_WARN_CONSOLE = 'auto-updater.on-update.warn-console';
public const AUTO_UPDATER_PREFERRED_CHANNEL = 'auto-updater.preferred-channel';
public const AUTO_UPDATER_SUGGEST_CHANNELS = 'auto-updater.suggest-channels';
public const CHUNK_GENERATION = 'chunk-generation';
public const CHUNK_GENERATION_POPULATION_QUEUE_SIZE = 'chunk-generation.population-queue-size';
public const CHUNK_SENDING = 'chunk-sending';
public const CHUNK_SENDING_PER_TICK = 'chunk-sending.per-tick';
public const CHUNK_SENDING_SPAWN_RADIUS = 'chunk-sending.spawn-radius';
public const CHUNK_TICKING = 'chunk-ticking';
public const CHUNK_TICKING_BLOCKS_PER_SUBCHUNK_PER_TICK = 'chunk-ticking.blocks-per-subchunk-per-tick';
public const CHUNK_TICKING_DISABLE_BLOCK_TICKING = 'chunk-ticking.disable-block-ticking';
public const CHUNK_TICKING_TICK_RADIUS = 'chunk-ticking.tick-radius';
public const CONSOLE = 'console';
public const CONSOLE_ENABLE_INPUT = 'console.enable-input';
public const CONSOLE_TITLE_TICK = 'console.title-tick';
public const DEBUG = 'debug';
public const DEBUG_LEVEL = 'debug.level';
public const LEVEL_SETTINGS = 'level-settings';
public const LEVEL_SETTINGS_DEFAULT_FORMAT = 'level-settings.default-format';
public const MEMORY = 'memory';
public const MEMORY_ASYNC_WORKER_HARD_LIMIT = 'memory.async-worker-hard-limit';
public const MEMORY_CHECK_RATE = 'memory.check-rate';
public const MEMORY_CONTINUOUS_TRIGGER = 'memory.continuous-trigger';
public const MEMORY_CONTINUOUS_TRIGGER_RATE = 'memory.continuous-trigger-rate';
public const MEMORY_GARBAGE_COLLECTION = 'memory.garbage-collection';
public const MEMORY_GARBAGE_COLLECTION_COLLECT_ASYNC_WORKER = 'memory.garbage-collection.collect-async-worker';
public const MEMORY_GARBAGE_COLLECTION_LOW_MEMORY_TRIGGER = 'memory.garbage-collection.low-memory-trigger';
public const MEMORY_GARBAGE_COLLECTION_PERIOD = 'memory.garbage-collection.period';
public const MEMORY_GLOBAL_LIMIT = 'memory.global-limit';
public const MEMORY_MAIN_HARD_LIMIT = 'memory.main-hard-limit';
public const MEMORY_MAIN_LIMIT = 'memory.main-limit';
public const MEMORY_MAX_CHUNKS = 'memory.max-chunks';
public const MEMORY_MAX_CHUNKS_CHUNK_RADIUS = 'memory.max-chunks.chunk-radius';
public const MEMORY_MAX_CHUNKS_TRIGGER_CHUNK_COLLECT = 'memory.max-chunks.trigger-chunk-collect';
public const MEMORY_MEMORY_DUMP = 'memory.memory-dump';
public const MEMORY_MEMORY_DUMP_DUMP_ASYNC_WORKER = 'memory.memory-dump.dump-async-worker';
public const MEMORY_WORLD_CACHES = 'memory.world-caches';
public const MEMORY_WORLD_CACHES_DISABLE_CHUNK_CACHE = 'memory.world-caches.disable-chunk-cache';
public const MEMORY_WORLD_CACHES_LOW_MEMORY_TRIGGER = 'memory.world-caches.low-memory-trigger';
public const NETWORK = 'network';
public const NETWORK_ASYNC_COMPRESSION = 'network.async-compression';
public const NETWORK_ASYNC_COMPRESSION_THRESHOLD = 'network.async-compression-threshold';
public const NETWORK_BATCH_THRESHOLD = 'network.batch-threshold';
public const NETWORK_COMPRESSION_LEVEL = 'network.compression-level';
public const NETWORK_ENABLE_ENCRYPTION = 'network.enable-encryption';
public const NETWORK_MAX_MTU_SIZE = 'network.max-mtu-size';
public const NETWORK_UPNP_FORWARDING = 'network.upnp-forwarding';
public const PLAYER = 'player';
public const PLAYER_SAVE_PLAYER_DATA = 'player.save-player-data';
public const PLAYER_VERIFY_XUID = 'player.verify-xuid';
public const PLUGINS = 'plugins';
public const PLUGINS_LEGACY_DATA_DIR = 'plugins.legacy-data-dir';
public const SETTINGS = 'settings';
public const SETTINGS_ASYNC_WORKERS = 'settings.async-workers';
public const SETTINGS_ENABLE_DEV_BUILDS = 'settings.enable-dev-builds';
public const SETTINGS_ENABLE_PROFILING = 'settings.enable-profiling';
public const SETTINGS_FORCE_LANGUAGE = 'settings.force-language';
public const SETTINGS_PROFILE_REPORT_TRIGGER = 'settings.profile-report-trigger';
public const SETTINGS_QUERY_PLUGINS = 'settings.query-plugins';
public const SETTINGS_SHUTDOWN_MESSAGE = 'settings.shutdown-message';
public const TICKS_PER = 'ticks-per';
public const TICKS_PER_AUTOSAVE = 'ticks-per.autosave';
public const TIMINGS = 'timings';
public const TIMINGS_HOST = 'timings.host';
public const WORLDS = 'worlds';
}

View File

@ -51,11 +51,11 @@ class Anvil extends Transparent implements Fallable{
private int $damage = self::UNDAMAGED;
protected function describeType(RuntimeDataDescriber $w) : void{
public function describeBlockItemState(RuntimeDataDescriber $w) : void{
$w->boundedInt(2, self::UNDAMAGED, self::VERY_DAMAGED, $this->damage);
}
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
}

View File

@ -55,7 +55,7 @@ class Bamboo extends Transparent{
protected bool $ready = false;
protected int $leafSize = self::NO_LEAVES;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->boundedInt(2, self::NO_LEAVES, self::LARGE_LEAVES, $this->leafSize);
$w->bool($this->thick);
$w->bool($this->ready);
@ -131,7 +131,7 @@ class Bamboo extends Transparent{
private function seekToTop() : Bamboo{
$world = $this->position->getWorld();
$top = $this;
while(($next = $world->getBlock($top->position->up())) instanceof Bamboo && $next->isSameType($this)){
while(($next = $world->getBlock($top->position->up())) instanceof Bamboo && $next->hasSameTypeId($this)){
$top = $next;
}
return $top;
@ -156,7 +156,7 @@ class Bamboo extends Transparent{
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
$below = $world->getBlock($this->position->down());
if(!$this->canBeSupportedBy($below) && !$below->isSameType($this)){
if(!$this->canBeSupportedBy($below) && !$below->hasSameTypeId($this)){
$world->useBreakOn($this->position);
}
}
@ -168,7 +168,7 @@ class Bamboo extends Transparent{
}
$height = 1;
while($world->getBlock($this->position->subtract(0, $height, 0))->isSameType($this)){
while($world->getBlock($this->position->subtract(0, $height, 0))->hasSameTypeId($this)){
if(++$height >= $maxHeight){
return false;
}

View File

@ -36,7 +36,7 @@ use pocketmine\world\BlockTransaction;
final class BambooSapling extends Flowable{
private bool $ready = false;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->bool($this->ready);
}

View File

@ -38,7 +38,7 @@ class Barrel extends Opaque{
protected bool $open = false;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->facing($this->facing);
$w->bool($this->open);
}

View File

@ -0,0 +1,136 @@
<?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;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\event\block\StructureGrowEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
abstract class BaseBigDripleaf extends Transparent{
use HorizontalFacingTrait;
abstract protected function isHead() : bool;
private function canBeSupportedBy(Block $block, bool $head) : bool{
//TODO: Moss block
return
($block instanceof BaseBigDripleaf && $block->isHead() === $head) ||
$block->getTypeId() === BlockTypeIds::CLAY ||
$block->hasTypeTag(BlockTypeTags::DIRT) ||
$block->hasTypeTag(BlockTypeTags::MUD);
}
public function onNearbyBlockChange() : void{
if(
(!$this->isHead() && !$this->getSide(Facing::UP) instanceof BaseBigDripleaf) ||
!$this->canBeSupportedBy($this->getSide(Facing::DOWN), false)
){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$block = $blockReplace->getSide(Facing::DOWN);
if(!$this->canBeSupportedBy($block, true)){
return false;
}
if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
if($block instanceof BaseBigDripleaf){
$this->facing = $block->getFacing();
$tx->addBlock($block->getPosition(), VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($this->facing));
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && $this->grow($player)){
$item->pop();
return true;
}
return false;
}
private function seekToHead() : ?BaseBigDripleaf{
if($this->isHead()){
return $this;
}
$step = 1;
while(($next = $this->getSide(Facing::UP, $step)) instanceof BaseBigDripleaf){
if($next->isHead()){
return $next;
}
$step++;
}
return null;
}
private function grow(?Player $player) : bool{
$head = $this->seekToHead();
if($head === null){
return false;
}
$pos = $head->getPosition();
$up = $pos->up();
$world = $pos->getWorld();
if(
!$world->isInWorld($up->getFloorX(), $up->getFloorY(), $up->getFloorZ()) ||
$world->getBlock($up)->getTypeId() !== BlockTypeIds::AIR
){
return false;
}
$tx = new BlockTransaction($world);
$tx->addBlock($pos, VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($head->getFacing()));
$tx->addBlock($up, VanillaBlocks::BIG_DRIPLEAF_HEAD()->setFacing($head->getFacing()));
$ev = new StructureGrowEvent($head, $tx, $player);
$ev->call();
if(!$ev->isCancelled()){
return $tx->apply();
}
return false;
}
public function getFlameEncouragement() : int{
return 15;
}
public function getFlammability() : int{
return 100;
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
}

View File

@ -23,10 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\CoralTypeTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\event\block\BlockDeathEvent;
use pocketmine\item\Item;
use function mt_rand;
@ -34,8 +34,8 @@ abstract class BaseCoral extends Transparent{
use CoralTypeTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
parent::__construct($idInfo, $name, $typeInfo);
$this->coralType = CoralType::TUBE();
parent::__construct($idInfo, $name, $typeInfo);
}
public function onNearbyBlockChange() : void{
@ -46,11 +46,7 @@ abstract class BaseCoral extends Transparent{
public function onScheduledUpdate() : void{
if(!$this->dead && !$this->isCoveredWithWater()){
$ev = new BlockDeathEvent($this, $this->setDead(true));
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
}
BlockEventHelper::die($this, (clone $this)->setDead(true));
}
}

View File

@ -38,7 +38,7 @@ use function in_array;
abstract class BaseRail extends Flowable{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockReplace->getSide(Facing::DOWN)->getSupportType(Facing::UP)->hasEdgeSupport()){
if($blockReplace->getAdjacentSupportType(Facing::DOWN)->hasEdgeSupport()){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -222,7 +222,7 @@ abstract class BaseRail extends Flowable{
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->getSide(Facing::DOWN)->getSupportType(Facing::UP)->hasEdgeSupport()){
if(!$this->getAdjacentSupportType(Facing::DOWN)->hasEdgeSupport()){
$world->useBreakOn($this->position);
}else{
foreach($this->getCurrentShapeConnections() as $connection){

View File

@ -49,6 +49,8 @@ abstract class BaseSign extends Transparent{
use WoodTypeTrait;
protected SignText $text;
private bool $waxed = false;
protected ?int $editorEntityRuntimeId = null;
/** @var \Closure() : Item */
@ -69,6 +71,7 @@ abstract class BaseSign extends Transparent{
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileSign){
$this->text = $tile->getText();
$this->waxed = $tile->isWaxed();
$this->editorEntityRuntimeId = $tile->getEditorEntityRuntimeId();
}
@ -80,6 +83,7 @@ abstract class BaseSign extends Transparent{
$tile = $this->position->getWorld()->getTile($this->position);
assert($tile instanceof TileSign);
$tile->setText($this->text);
$tile->setWaxed($this->waxed);
$tile->setEditorEntityRuntimeId($this->editorEntityRuntimeId);
}
@ -117,6 +121,15 @@ abstract class BaseSign extends Transparent{
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onPostPlace() : void{
$player = $this->editorEntityRuntimeId !== null ?
$this->position->getWorld()->getEntity($this->editorEntityRuntimeId) :
null;
if($player instanceof Player){
$player->openSignEditor($this->position);
}
}
private function doSignChange(SignText $newText, Player $player, Item $item) : bool{
$ev = new SignChangeEvent($this, $player, $newText);
$ev->call();
@ -138,10 +151,26 @@ abstract class BaseSign extends Transparent{
return false;
}
private function wax(Player $player, Item $item) : bool{
if($this->waxed){
return false;
}
$this->waxed = true;
$this->position->getWorld()->setBlock($this->position, $this);
$item->pop();
return true;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player === null){
return false;
}
if($this->waxed){
return true;
}
$dyeColor = $item instanceof Dye ? $item->getColor() : match($item->getTypeId()){
ItemTypeIds::BONE_MEAL => DyeColor::WHITE(),
ItemTypeIds::LAPIS_LAZULI => DyeColor::BLUE(),
@ -150,20 +179,25 @@ abstract class BaseSign extends Transparent{
};
if($dyeColor !== null){
$color = $dyeColor->equals(DyeColor::BLACK()) ? new Color(0, 0, 0) : $dyeColor->getRgbValue();
if($color->toARGB() === $this->text->getBaseColor()->toARGB()){
return false;
}
if($this->doSignChange(new SignText($this->text->getLines(), $color, $this->text->isGlowing()), $player, $item)){
if(
$color->toARGB() !== $this->text->getBaseColor()->toARGB() &&
$this->doSignChange(new SignText($this->text->getLines(), $color, $this->text->isGlowing()), $player, $item)
){
$this->position->getWorld()->addSound($this->position, new DyeUseSound());
return true;
}
}elseif($item->getTypeId() === ItemTypeIds::INK_SAC){
return $this->changeSignGlowingState(false, $player, $item);
}elseif($item->getTypeId() === ItemTypeIds::GLOW_INK_SAC){
return $this->changeSignGlowingState(true, $player, $item);
}elseif(match($item->getTypeId()){
ItemTypeIds::INK_SAC => $this->changeSignGlowingState(false, $player, $item),
ItemTypeIds::GLOW_INK_SAC => $this->changeSignGlowingState(true, $player, $item),
ItemTypeIds::HONEYCOMB => $this->wax($player, $item),
default => false
}){
return true;
}
return false;
$player->openSignEditor($this->position);
return true;
}
/**
@ -179,6 +213,30 @@ abstract class BaseSign extends Transparent{
return $this;
}
/**
* Returns whether the sign has been waxed using a honeycomb. If true, the sign cannot be edited by a player.
*/
public function isWaxed() : bool{ return $this->waxed; }
/** @return $this */
public function setWaxed(bool $waxed) : self{
$this->waxed = $waxed;
return $this;
}
/**
* Sets the runtime entity ID of the player editing this sign. Only this player will be able to edit the sign.
* This is used to prevent multiple players from editing the same sign at the same time, and to prevent players
* from editing signs they didn't place.
*/
public function getEditorEntityRuntimeId() : ?int{ return $this->editorEntityRuntimeId; }
/** @return $this */
public function setEditorEntityRuntimeId(?int $editorEntityRuntimeId) : self{
$this->editorEntityRuntimeId = $editorEntityRuntimeId;
return $this;
}
/**
* Called by the player controller (network session) to update the sign text, firing events as appropriate.
*
@ -195,13 +253,14 @@ abstract class BaseSign extends Transparent{
}
$ev = new SignChangeEvent($this, $author, new SignText(array_map(function(string $line) : string{
return TextFormat::clean($line, false);
}, $text->getLines())));
if($this->editorEntityRuntimeId === null || $this->editorEntityRuntimeId !== $author->getId()){
}, $text->getLines()), $this->text->getBaseColor(), $this->text->isGlowing()));
if($this->waxed || $this->editorEntityRuntimeId !== $author->getId()){
$ev->cancel();
}
$ev->call();
if(!$ev->isCancelled()){
$this->setText($ev->getNewText());
$this->setEditorEntityRuntimeId(null);
$this->position->getWorld()->setBlock($this->position, $this);
return true;
}
@ -212,4 +271,8 @@ abstract class BaseSign extends Transparent{
public function asItem() : Item{
return ($this->asItemCallback)();
}
public function getFuelTime() : int{
return $this->woodType->isFlammable() ? 200 : 0;
}
}

View File

@ -53,7 +53,7 @@ class Bed extends Transparent{
parent::__construct($idInfo, $name, $typeInfo);
}
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->bool($this->occupied);
$w->bool($this->head);
@ -177,11 +177,11 @@ class Bed extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if($this->canBeSupportedAt($blockReplace)){
$this->facing = $player !== null ? $player->getHorizontalFacing() : Facing::NORTH;
$next = $this->getSide($this->getOtherHalfSide());
if($next->canBeReplaced() && $this->canBeSupportedBy($next->getSide(Facing::DOWN))){
if($next->canBeReplaced() && $this->canBeSupportedAt($next)){
$nextState = clone $this;
$nextState->head = true;
$tx->addBlock($blockReplace->position, $this)->addBlock($next->position, $nextState);
@ -208,8 +208,8 @@ class Bed extends Transparent{
return parent::getAffectedBlocks();
}
private function canBeSupportedBy(Block $block) : bool{
return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE());
private function canBeSupportedAt(Block $block) : bool{
return !$block->getAdjacentSupportType(Facing::DOWN)->equals(SupportType::NONE());
}
public function getMaxStackSize() : int{ return 1; }

View File

@ -28,7 +28,7 @@ use pocketmine\data\runtime\RuntimeDataDescriber;
class Bedrock extends Opaque{
private bool $burnsForever = false;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->bool($this->burnsForever);
}

View File

@ -23,9 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
class Beetroot extends Crops{
@ -33,7 +33,7 @@ class Beetroot extends Crops{
if($this->age >= self::MAX_AGE){
return [
VanillaItems::BEETROOT(),
VanillaItems::BEETROOT_SEEDS()->setCount(mt_rand(0, 3))
VanillaItems::BEETROOT_SEEDS()->setCount(FortuneDropHelper::binomial($item, 0))
];
}

View File

@ -35,6 +35,7 @@ use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\BellRingSound;
@ -48,7 +49,7 @@ final class Bell extends Transparent{
parent::__construct($idInfo, $name, $typeInfo);
}
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->bellAttachmentType($this->attachmentType);
$w->horizontalFacing($this->facing);
}
@ -87,46 +88,44 @@ final class Bell extends Transparent{
return $this;
}
private function canBeSupportedBy(Block $block, int $face) : bool{
return !$block->getSupportType($face)->equals(SupportType::NONE());
private function canBeSupportedAt(Block $block, int $face) : bool{
return !$block->getAdjacentSupportType($face)->equals(SupportType::NONE());
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}
if($face === Facing::UP){
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->down()), Facing::UP)){
return false;
}
if($player !== null){
$this->setFacing(Facing::opposite($player->getHorizontalFacing()));
}
$this->setAttachmentType(BellAttachmentType::FLOOR());
}elseif($face === Facing::DOWN){
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->up()), Facing::DOWN)){
return false;
}
$this->setAttachmentType(BellAttachmentType::CEILING());
}else{
$this->setFacing($face);
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide(Facing::opposite($face))), $face)){
$this->setAttachmentType(BellAttachmentType::ONE_WALL());
}else{
return false;
}
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide($face)), Facing::opposite($face))){
$this->setAttachmentType(BellAttachmentType::TWO_WALLS());
}
$this->setAttachmentType(
$this->canBeSupportedAt($blockReplace, $face) ?
BellAttachmentType::TWO_WALLS() :
BellAttachmentType::ONE_WALL()
);
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onNearbyBlockChange() : void{
if(
($this->attachmentType->equals(BellAttachmentType::CEILING()) && !$this->canBeSupportedBy($this->getSide(Facing::UP), Facing::DOWN)) ||
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && !$this->canBeSupportedBy($this->getSide(Facing::DOWN), Facing::UP)) ||
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) && !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)) ||
($this->attachmentType->equals(BellAttachmentType::TWO_WALLS()) && (!$this->canBeSupportedBy($this->getSide($this->facing), Facing::opposite($this->facing)) || !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)))
){
$this->position->getWorld()->useBreakOn($this->position);
foreach(match($this->attachmentType){
BellAttachmentType::CEILING() => [Facing::UP],
BellAttachmentType::FLOOR() => [Facing::DOWN],
BellAttachmentType::ONE_WALL() => [Facing::opposite($this->facing)],
BellAttachmentType::TWO_WALLS() => [$this->facing, Facing::opposite($this->facing)],
default => throw new AssumptionFailedError("All cases of BellAttachmentType must be handled")
} as $supportBlockDirection){
if(!$this->canBeSupportedAt($this, $supportBlockDirection)){
$this->position->getWorld()->useBreakOn($this->position);
break;
}
}
}
@ -159,13 +158,11 @@ final class Bell extends Transparent{
}
private function isValidFaceToRing(int $faceHit) : bool{
return (
$this->attachmentType->equals(BellAttachmentType::CEILING()) ||
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && Facing::axis($faceHit) === Facing::axis($this->facing)) ||
(
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) || $this->attachmentType->equals(BellAttachmentType::TWO_WALLS())) &&
($faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true))
)
);
return match($this->attachmentType){
BellAttachmentType::CEILING() => true,
BellAttachmentType::FLOOR() => Facing::axis($faceHit) === Facing::axis($this->facing),
BellAttachmentType::ONE_WALL(), BellAttachmentType::TWO_WALLS() => $faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true),
default => throw new AssumptionFailedError("All cases of BellAttachmentType must be handled")
};
}
}

View File

@ -0,0 +1,132 @@
<?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;
use pocketmine\block\utils\DripleafState;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Projectile;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\world\sound\DripleafTiltDownSound;
use pocketmine\world\sound\DripleafTiltUpSound;
class BigDripleafHead extends BaseBigDripleaf{
protected DripleafState $leafState;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
$this->leafState = DripleafState::STABLE();
parent::__construct($idInfo, $name, $typeInfo);
}
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
parent::describeBlockOnlyState($w);
$w->dripleafState($this->leafState);
}
protected function isHead() : bool{
return true;
}
public function getLeafState() : DripleafState{
return $this->leafState;
}
/** @return $this */
public function setLeafState(DripleafState $leafState) : self{
$this->leafState = $leafState;
return $this;
}
public function hasEntityCollision() : bool{
return true;
}
private function setTiltAndScheduleTick(DripleafState $tilt) : void{
$this->position->getWorld()->setBlock($this->position, $this->setLeafState($tilt));
$delay = $tilt->getScheduledUpdateDelayTicks();
if($delay !== null){
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, $delay);
}
}
private function getLeafTopOffset() : float{
return match($this->leafState){
DripleafState::STABLE(), DripleafState::UNSTABLE() => 1 / 16,
DripleafState::PARTIAL_TILT() => 3 / 16,
default => 0
};
}
public function onEntityInside(Entity $entity) : bool{
if(!$entity instanceof Projectile && $this->leafState->equals(DripleafState::STABLE())){
//the entity must be standing on top of the leaf - do not collapse if the entity is standing underneath
$intersection = AxisAlignedBB::one()
->offset($this->position->x, $this->position->y, $this->position->z)
->trim(Facing::DOWN, 1 - $this->getLeafTopOffset());
if($entity->getBoundingBox()->intersectsWith($intersection)){
$this->setTiltAndScheduleTick(DripleafState::UNSTABLE());
return false;
}
}
return true;
}
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
if(!$this->leafState->equals(DripleafState::FULL_TILT())){
$this->setTiltAndScheduleTick(DripleafState::FULL_TILT());
$this->position->getWorld()->addSound($this->position, new DripleafTiltDownSound());
}
}
public function onScheduledUpdate() : void{
if(!$this->leafState->equals(DripleafState::STABLE())){
if($this->leafState->equals(DripleafState::FULL_TILT())){
$this->position->getWorld()->setBlock($this->position, $this->setLeafState(DripleafState::STABLE()));
$this->position->getWorld()->addSound($this->position, new DripleafTiltUpSound());
}else{
$this->setTiltAndScheduleTick(match($this->leafState->id()){
DripleafState::UNSTABLE()->id() => DripleafState::PARTIAL_TILT(),
DripleafState::PARTIAL_TILT()->id() => DripleafState::FULL_TILT(),
default => throw new AssumptionFailedError("All types should be covered")
});
$this->position->getWorld()->addSound($this->position, new DripleafTiltDownSound());
}
}
}
protected function recalculateCollisionBoxes() : array{
if(!$this->leafState->equals(DripleafState::FULL_TILT())){
return [
AxisAlignedBB::one()
->trim(Facing::DOWN, 11 / 16)
->trim(Facing::UP, $this->getLeafTopOffset())
];
}
return [];
}
}

View File

@ -0,0 +1,41 @@
<?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;
use pocketmine\item\Item;
class BigDripleafStem extends BaseBigDripleaf{
protected function isHead() : bool{
return false;
}
protected function recalculateCollisionBoxes() : array{
return [];
}
public function asItem() : Item{
return VanillaBlocks::BIG_DRIPLEAF_HEAD()->asItem();
}
}

View File

@ -29,17 +29,22 @@ namespace pocketmine\block;
use pocketmine\block\tile\Spawnable;
use pocketmine\block\tile\Tile;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\InvalidSerializedRuntimeDataException;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\data\runtime\RuntimeDataReader;
use pocketmine\data\runtime\RuntimeDataSizeCalculator;
use pocketmine\data\runtime\RuntimeDataWriter;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Projectile;
use pocketmine\item\enchantment\AvailableEnchantmentRegistry;
use pocketmine\item\enchantment\ItemEnchantmentTagRegistry;
use pocketmine\item\enchantment\ItemEnchantmentTags;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\Item;
use pocketmine\item\ItemBlock;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
@ -57,6 +62,11 @@ class Block{
public const INTERNAL_STATE_DATA_BITS = 8;
public const INTERNAL_STATE_DATA_MASK = ~(~0 << self::INTERNAL_STATE_DATA_BITS);
/**
* @internal
*/
public const EMPTY_STATE_ID = (BlockTypeIds::AIR << self::INTERNAL_STATE_DATA_BITS) | (BlockTypeIds::AIR & self::INTERNAL_STATE_DATA_MASK);
protected BlockIdentifier $idInfo;
protected string $fallbackName;
protected BlockTypeInfo $typeInfo;
@ -65,16 +75,10 @@ class Block{
/** @var AxisAlignedBB[]|null */
protected ?array $collisionBoxes = null;
/**
* @var int[]
* @phpstan-var array<string, int>
*/
private static array $typeDataBits = [];
/**
* @var int[]
* @phpstan-var array<string, int>
*/
private static array $stateDataBits = [];
private int $requiredBlockItemStateDataBits;
private int $requiredBlockOnlyStateDataBits;
private Block $defaultState;
/**
* @param string $name English name of the block type (TODO: implement translations)
@ -84,6 +88,18 @@ class Block{
$this->fallbackName = $name;
$this->typeInfo = $typeInfo;
$this->position = new Position(0, 0, 0, null);
$calculator = new RuntimeDataSizeCalculator();
$this->describeBlockItemState($calculator);
$this->requiredBlockItemStateDataBits = $calculator->getBitsUsed();
$calculator = new RuntimeDataSizeCalculator();
$this->describeBlockOnlyState($calculator);
$this->requiredBlockOnlyStateDataBits = $calculator->getBitsUsed();
$defaultState = clone $this;
$this->defaultState = $defaultState;
$defaultState->defaultState = $defaultState;
}
public function __clone(){
@ -107,10 +123,10 @@ class Block{
/**
* Returns a type ID that identifies this type of block. This allows comparing basic block types, e.g. wool, stone,
* glass, etc.
* glass, etc. Type ID will not change for a given block type.
*
* This does **NOT** include information like facing, open/closed, powered/unpowered, colour, etc. This means that,
* for example, red wool and green wool have the same type ID.
* Information such as colour, powered, open/closed, etc. is **not** included in this ID.
* If you want to get a state ID that includes this information, use {@link Block::getStateId()} instead.
*
* @see BlockTypeIds
*/
@ -125,25 +141,37 @@ class Block{
* blocks in chunks at runtime.
*
* This usually encodes all properties of the block, such as facing, open/closed, powered/unpowered, colour, etc.
* However, some blocks (such as signs and chests) may store additional properties in an associated "tile" if they
* State ID may change depending on the properties of the block (e.g. a torch facing east will have a different
* state ID to one facing west).
*
* Some blocks (such as signs and chests) may store additional properties in an associated "tile" if they
* have too many possible values to be encoded into the state ID. These extra properties are **NOT** included in
* this function's result.
*
* This ID can be used to later obtain a copy of this block using {@link RuntimeBlockStateRegistry::fromStateId()}.
* This ID can be used to later obtain a copy of the block with the same state properties by using
* {@link RuntimeBlockStateRegistry::fromStateId()}.
*/
public function getStateId() : int{
return ($this->getTypeId() << self::INTERNAL_STATE_DATA_BITS) | $this->computeTypeAndStateData();
$typeId = $this->getTypeId();
//TODO: this XOR mask improves hashtable distribution, but it's only effective if the number of unique block
//type IDs is larger than the number of available state data bits. We should probably hash (e.g. using xxhash)
//the type ID to create a better mask.
//Alternatively, we could hash the whole state ID, but this is currently problematic, since we currently need
//to be able to recover the state data from the state ID because of UnknownBlock.
return ($typeId << self::INTERNAL_STATE_DATA_BITS) | ($this->encodeFullState() ^ ($typeId & self::INTERNAL_STATE_DATA_MASK));
}
/**
* Returns whether the given block has an equivalent type to this one. This compares the type IDs.
* Returns whether the given block has the same type ID as this one.
*/
public function isSameType(Block $other) : bool{
public function hasSameTypeId(Block $other) : bool{
return $this->getTypeId() === $other->getTypeId();
}
/**
* Returns whether the given block has the same type and properties as this block.
*
* Note: Tile data (e.g. sign text, chest contents) are not compared here.
*/
public function isSameState(Block $other) : bool{
return $this->getStateId() === $other->getStateId();
@ -170,97 +198,74 @@ class Block{
/**
* Returns the block as an item.
* State information such as facing, powered/unpowered, open/closed, etc., is discarded.
* Type information such as colour, wood type, etc. is preserved.
* Block-only state such as facing, powered/unpowered, open/closed, etc., is discarded.
* Block-item state such as colour, wood type, etc. is preserved.
* Complex state properties stored in the tile data (e.g. inventory) are discarded.
*/
public function asItem() : Item{
return new ItemBlock($this);
$normalized = clone $this->defaultState;
$normalized->decodeBlockItemState($this->encodeBlockItemState());
return new ItemBlock($normalized);
}
final public function getRequiredTypeDataBits() : int{
$class = get_class($this);
if(isset(self::$typeDataBits[$class])){
return self::$typeDataBits[$class];
}
$calculator = new RuntimeDataSizeCalculator();
$this->describeType($calculator);
return self::$typeDataBits[$class] = $calculator->getBitsUsed();
}
private function decodeBlockItemState(int $data) : void{
$reader = new RuntimeDataReader($this->requiredBlockItemStateDataBits, $data);
final public function getRequiredStateDataBits() : int{
$class = get_class($this);
if(isset(self::$stateDataBits[$class])){
return self::$stateDataBits[$class];
}
$calculator = new RuntimeDataSizeCalculator();
$this->describeState($calculator);
return self::$stateDataBits[$class] = $calculator->getBitsUsed();
}
/**
* @internal
*/
final public function decodeTypeData(int $data) : void{
$typeBits = $this->getRequiredTypeDataBits();
$reader = new RuntimeDataReader($typeBits, $data);
$this->describeType($reader);
$this->describeBlockItemState($reader);
$readBits = $reader->getOffset();
if($typeBits !== $readBits){
throw new \LogicException(get_class($this) . ": Exactly $typeBits bits of type data were provided, but $readBits were read");
if($this->requiredBlockItemStateDataBits !== $readBits){
throw new \LogicException(get_class($this) . ": Exactly $this->requiredBlockItemStateDataBits bits of block-item state data were provided, but $readBits were read");
}
}
/**
* @internal
*/
final public function decodeTypeAndStateData(int $data) : void{
$typeBits = $this->getRequiredTypeDataBits();
$stateBits = $this->getRequiredStateDataBits();
$reader = new RuntimeDataReader($typeBits + $stateBits, $data);
$this->decodeTypeData($reader->readInt($typeBits));
private function decodeBlockOnlyState(int $data) : void{
$reader = new RuntimeDataReader($this->requiredBlockOnlyStateDataBits, $data);
$this->describeState($reader);
$readBits = $reader->getOffset() - $typeBits;
if($stateBits !== $readBits){
throw new \LogicException(get_class($this) . ": Exactly $stateBits bits of state data were provided, but $readBits were read");
$this->describeBlockOnlyState($reader);
$readBits = $reader->getOffset();
if($this->requiredBlockOnlyStateDataBits !== $readBits){
throw new \LogicException(get_class($this) . ": Exactly $this->requiredBlockOnlyStateDataBits bits of block-only state data were provided, but $readBits were read");
}
}
/**
* @internal
*/
final public function computeTypeData() : int{
$typeBits = $this->getRequiredTypeDataBits();
$writer = new RuntimeDataWriter($typeBits);
private function decodeFullState(int $data) : void{
$reader = new RuntimeDataReader($this->requiredBlockItemStateDataBits + $this->requiredBlockOnlyStateDataBits, $data);
$this->decodeBlockItemState($reader->readInt($this->requiredBlockItemStateDataBits));
$this->decodeBlockOnlyState($reader->readInt($this->requiredBlockOnlyStateDataBits));
}
$this->describeType($writer);
private function encodeBlockItemState() : int{
$writer = new RuntimeDataWriter($this->requiredBlockItemStateDataBits);
$this->describeBlockItemState($writer);
$writtenBits = $writer->getOffset();
if($typeBits !== $writtenBits){
throw new \LogicException(get_class($this) . ": Exactly $typeBits bits of type data were expected, but $writtenBits were written");
if($this->requiredBlockItemStateDataBits !== $writtenBits){
throw new \LogicException(get_class($this) . ": Exactly $this->requiredBlockItemStateDataBits bits of block-item state data were expected, but $writtenBits were written");
}
return $writer->getValue();
}
/**
* @internal
*/
final public function computeTypeAndStateData() : int{
$typeBits = $this->getRequiredTypeDataBits();
$stateBits = $this->getRequiredStateDataBits();
$writer = new RuntimeDataWriter($typeBits + $stateBits);
$writer->writeInt($typeBits, $this->computeTypeData());
private function encodeBlockOnlyState() : int{
$writer = new RuntimeDataWriter($this->requiredBlockOnlyStateDataBits);
$this->describeState($writer);
$writtenBits = $writer->getOffset() - $typeBits;
if($stateBits !== $writtenBits){
throw new \LogicException(get_class($this) . ": Exactly $stateBits bits of state data were expected, but $writtenBits were written");
$this->describeBlockOnlyState($writer);
$writtenBits = $writer->getOffset();
if($this->requiredBlockOnlyStateDataBits !== $writtenBits){
throw new \LogicException(get_class($this) . ": Exactly $this->requiredBlockOnlyStateDataBits bits of block-only state data were expected, but $writtenBits were written");
}
return $writer->getValue();
}
private function encodeFullState() : int{
$writer = new RuntimeDataWriter($this->requiredBlockItemStateDataBits + $this->requiredBlockOnlyStateDataBits);
$writer->writeInt($this->requiredBlockItemStateDataBits, $this->encodeBlockItemState());
$writer->writeInt($this->requiredBlockOnlyStateDataBits, $this->encodeBlockOnlyState());
return $writer->getValue();
}
/**
* Describes properties of this block which apply to both the block and item form of the block.
* Examples of suitable properties include colour, skull type, and any other information which **IS** kept when the
@ -269,7 +274,7 @@ class Block{
* The method implementation must NOT use conditional logic to determine which properties are written. It must
* always write the same properties in the same order, regardless of the current state of the block.
*/
protected function describeType(RuntimeDataDescriber $w) : void{
public function describeBlockItemState(RuntimeDataDescriber $w) : void{
//NOOP
}
@ -281,10 +286,39 @@ class Block{
* The method implementation must NOT use conditional logic to determine which properties are written. It must
* always write the same properties in the same order, regardless of the current state of the block.
*/
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
//NOOP
}
/**
* Generates copies of this Block in all possible state permutations.
* Every possible combination of known properties (e.g. facing, open/closed, powered/unpowered, on/off) will be
* generated.
*
* @phpstan-return \Generator<int, Block, void, void>
*/
public function generateStatePermutations() : \Generator{
//TODO: this bruteforce approach to discovering all valid states is very inefficient for larger state data sizes
//at some point we'll need to find a better way to do this
$bits = $this->requiredBlockItemStateDataBits + $this->requiredBlockOnlyStateDataBits;
if($bits > Block::INTERNAL_STATE_DATA_BITS){
throw new \LogicException("Block state data cannot use more than " . Block::INTERNAL_STATE_DATA_BITS . " bits");
}
for($stateData = 0; $stateData < (1 << $bits); ++$stateData){
$v = clone $this;
try{
$v->decodeFullState($stateData);
if($v->encodeFullState() !== $stateData){
throw new \LogicException(static::class . "::decodeStateData() accepts invalid state data (returned " . $v->encodeFullState() . " for input $stateData)");
}
}catch(InvalidSerializedRuntimeDataException){ //invalid property combination, leave it
continue;
}
yield $v;
}
}
/**
* Called when this block is created, set, or has a neighbouring block update, to re-detect dynamic properties which
* are not saved on the world.
@ -391,6 +425,19 @@ class Block{
return $this->typeInfo->getBreakInfo();
}
/**
* Returns tags that represent the type of item being enchanted and are used to determine
* what enchantments can be applied to the item of this block during in-game enchanting (enchanting table, anvil, fishing, etc.).
* @see ItemEnchantmentTags
* @see ItemEnchantmentTagRegistry
* @see AvailableEnchantmentRegistry
*
* @return string[]
*/
public function getEnchantmentTags() : array{
return $this->typeInfo->getEnchantmentTags();
}
/**
* Do the actions needed so the block is broken with the Item
*
@ -437,7 +484,8 @@ class Block{
/**
* Do actions when interacted by Item. Returns if it has done anything
*
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
* @param Vector3 $clickVector Exact position where the click occurred, relative to the block's integer position
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
*/
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
return false;
@ -720,7 +768,7 @@ class Block{
* @return string
*/
public function __toString(){
return "Block[" . $this->getName() . "] (" . $this->getTypeId() . ":" . $this->computeTypeAndStateData() . ")";
return "Block[" . $this->getName() . "] (" . $this->getTypeId() . ":" . $this->encodeFullState() . ")";
}
/**
@ -832,6 +880,10 @@ class Block{
return SupportType::FULL();
}
protected function getAdjacentSupportType(int $facing) : SupportType{
return $this->getSide($facing)->getSupportType(Facing::opposite($facing));
}
public function isFullCube() : bool{
$bb = $this->getCollisionBoxes();

View File

@ -24,11 +24,14 @@ declare(strict_types=1);
namespace pocketmine\block;
/**
* Enum of all the block runtime IDs used by PocketMine-MP. These IDs are specific to PocketMine-MP and have no
* relevance to any Minecraft vanilla things.
* Every block in {@link VanillaBlocks} has a corresponding constant in this class. These constants can be used to
* identify and compare block types efficiently using {@link Block::getTypeId()}.
*
* WARNING: DO NOT STORE THESE IDS. They can and will change without warning.
* They should ONLY be used to IDENTIFY blocks at runtime.
* Type ID is also used internally as part of block state ID, which is used to store blocks and their simple properties
* in a memory-efficient way in chunks at runtime.
*
* WARNING: These are NOT a replacement for Minecraft legacy IDs. Do **NOT** hardcode their values, or store them in
* configs or databases. They will change without warning.
*/
final class BlockTypeIds{
@ -713,8 +716,29 @@ final class BlockTypeIds{
public const AZALEA_LEAVES = 10686;
public const FLOWERING_AZALEA_LEAVES = 10687;
public const REINFORCED_DEEPSLATE = 10688;
public const CAVE_VINES = 10689;
public const GLOW_LICHEN = 10690;
public const CHERRY_BUTTON = 10691;
public const CHERRY_DOOR = 10692;
public const CHERRY_FENCE = 10693;
public const CHERRY_FENCE_GATE = 10694;
public const CHERRY_LEAVES = 10695;
public const CHERRY_LOG = 10696;
public const CHERRY_PLANKS = 10697;
public const CHERRY_PRESSURE_PLATE = 10698;
public const CHERRY_SAPLING = 10699;
public const CHERRY_SIGN = 10700;
public const CHERRY_SLAB = 10701;
public const CHERRY_STAIRS = 10702;
public const CHERRY_TRAPDOOR = 10703;
public const CHERRY_WALL_SIGN = 10704;
public const CHERRY_WOOD = 10705;
public const SMALL_DRIPLEAF = 10706;
public const BIG_DRIPLEAF_HEAD = 10707;
public const BIG_DRIPLEAF_STEM = 10708;
public const PINK_PETALS = 10709;
public const FIRST_UNUSED_BLOCK_ID = 10689;
public const FIRST_UNUSED_BLOCK_ID = 10710;
private static int $nextDynamicId = self::FIRST_UNUSED_BLOCK_ID;

View File

@ -35,10 +35,12 @@ final class BlockTypeInfo{
/**
* @param string[] $typeTags
* @param string[] $enchantmentTags
*/
public function __construct(
private BlockBreakInfo $breakInfo,
array $typeTags = []
array $typeTags = [],
private array $enchantmentTags = []
){
$this->typeTags = array_fill_keys($typeTags, true);
}
@ -49,4 +51,17 @@ final class BlockTypeInfo{
public function getTypeTags() : array{ return array_keys($this->typeTags); }
public function hasTypeTag(string $tag) : bool{ return isset($this->typeTags[$tag]); }
/**
* Returns tags that represent the type of item being enchanted and are used to determine
* what enchantments can be applied to the item of this block during in-game enchanting (enchanting table, anvil, fishing, etc.).
* @see ItemEnchantmentTags
* @see ItemEnchantmentTagRegistry
* @see AvailableEnchantmentRegistry
*
* @return string[]
*/
public function getEnchantmentTags() : array{
return $this->enchantmentTags;
}
}

View File

@ -43,7 +43,7 @@ class BrewingStand extends Transparent{
*/
protected array $slots = [];
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->brewingStandSlots($this->slots);
}

View File

@ -38,7 +38,7 @@ abstract class Button extends Flowable{
protected bool $pressed = false;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->facing($this->facing);
$w->bool($this->pressed);
}
@ -52,7 +52,7 @@ abstract class Button extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
if($this->canBeSupportedAt($blockReplace, $face)){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -83,12 +83,12 @@ abstract class Button extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)){
if(!$this->canBeSupportedAt($this, $this->facing)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $support, int $face) : bool{
return $support->getSupportType($face)->hasCenterSupport();
private function canBeSupportedAt(Block $block, int $face) : bool{
return $block->getAdjacentSupportType(Facing::opposite($face))->hasCenterSupport();
}
}

View File

@ -23,10 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
@ -41,7 +41,7 @@ class Cactus extends Transparent{
protected int $age = 0;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->boundedInt(4, 0, self::MAX_AGE, $this->age);
}
@ -79,7 +79,7 @@ class Cactus extends Transparent{
}
private function canBeSupportedBy(Block $block) : bool{
return $block->isSameType($this) || $block->hasTypeTag(BlockTypeTags::SAND);
return $block->hasSameTypeId($this) || $block->hasTypeTag(BlockTypeTags::SAND);
}
public function onNearbyBlockChange() : void{
@ -102,7 +102,7 @@ class Cactus extends Transparent{
}
public function onRandomTick() : void{
if(!$this->getSide(Facing::DOWN)->isSameType($this)){
if(!$this->getSide(Facing::DOWN)->hasSameTypeId($this)){
$world = $this->position->getWorld();
if($this->age === self::MAX_AGE){
for($y = 1; $y < 3; ++$y){
@ -111,21 +111,16 @@ class Cactus extends Transparent{
}
$b = $world->getBlockAt($this->position->x, $this->position->y + $y, $this->position->z);
if($b->getTypeId() === BlockTypeIds::AIR){
$ev = new BlockGrowEvent($b, VanillaBlocks::CACTUS());
$ev->call();
if($ev->isCancelled()){
break;
}
$world->setBlock($b->position, $ev->getNewState());
BlockEventHelper::grow($b, VanillaBlocks::CACTUS(), null);
}else{
break;
}
}
$this->age = 0;
$world->setBlock($this->position, $this);
$world->setBlock($this->position, $this, update: false);
}else{
++$this->age;
$world->setBlock($this->position, $this);
$world->setBlock($this->position, $this, update: false);
}
}
}

View File

@ -36,7 +36,7 @@ class Cake extends BaseCake{
protected int $bites = 0;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->boundedInt(3, 0, self::MAX_BITES, $this->bites);
}
@ -64,7 +64,7 @@ class Cake extends BaseCake{
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof ItemBlock){
if($this->bites === 0 && $item instanceof ItemBlock){
$block = $item->getBlock();
$resultBlock = null;
if($block->getTypeId() === BlockTypeIds::CANDLE){
@ -83,6 +83,10 @@ class Cake extends BaseCake{
return parent::onInteract($item, $face, $clickVector, $player, $returnedItems);
}
public function getDropsForCompatibleTool(Item $item) : array{
return [];
}
public function getResidue() : Block{
$clone = clone $this;
$clone->bites++;

View File

@ -64,7 +64,7 @@ class CakeWithCandle extends BaseCake{
}
public function getPickedItem(bool $addUserData = false) : Item{
return VanillaBlocks::CAKE()->getPickedItem($addUserData);
return VanillaBlocks::CAKE()->asItem();
}
public function getResidue() : Block{

View File

@ -37,7 +37,7 @@ use pocketmine\world\BlockTransaction;
class Candle extends Transparent{
use CandleTrait {
describeState as encodeLitState;
describeBlockOnlyState as encodeLitState;
getLightLevel as getBaseLightLevel;
}
@ -46,7 +46,7 @@ class Candle extends Transparent{
private int $count = self::MIN_COUNT;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$this->encodeLitState($w);
$w->boundedInt(2, self::MIN_COUNT, self::MAX_COUNT, $this->count);
}
@ -95,7 +95,7 @@ class Candle extends Transparent{
}
protected function getCandleIfCompatibleType(Block $block) : ?Candle{
return $block instanceof Candle && $block->isSameType($this) ? $block : null;
return $block instanceof Candle && $block->hasSameTypeId($this) ? $block : null;
}
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
@ -104,8 +104,7 @@ class Candle extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $blockReplace->getSide(Facing::DOWN);
if(!$down->getSupportType(Facing::UP)->hasCenterSupport()){
if(!$blockReplace->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport()){
return false;
}
$existing = $this->getCandleIfCompatibleType($blockReplace);

View File

@ -23,15 +23,15 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
class Carrot extends Crops{
public function getDropsForCompatibleTool(Item $item) : array{
return [
VanillaItems::CARROT()->setCount($this->age >= self::MAX_AGE ? mt_rand(1, 4) : 1)
VanillaItems::CARROT()->setCount($this->age >= self::MAX_AGE ? FortuneDropHelper::binomial($item, 1) : 1)
];
}

View File

@ -24,9 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
class CarvedPumpkin extends Opaque{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
}

182
src/block/CaveVines.php Normal file
View File

@ -0,0 +1,182 @@
<?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;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\GlowBerriesPickSound;
use function mt_rand;
class CaveVines extends Flowable{
public const MAX_AGE = 25;
protected int $age = 0;
protected bool $berries = false;
protected bool $head = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->boundedInt(5, 0, self::MAX_AGE, $this->age);
$w->bool($this->berries);
$w->bool($this->head);
}
public function hasBerries() : bool{ return $this->berries; }
/** @return $this */
public function setBerries(bool $berries) : self{
$this->berries = $berries;
return $this;
}
public function isHead() : bool{ return $this->head; }
/** @return $this */
public function setHead(bool $head) : self{
$this->head = $head;
return $this;
}
public function getAge() : int{
return $this->age;
}
/** @return $this */
public function setAge(int $age) : self{
if($age < 0 || $age > self::MAX_AGE){
throw new \InvalidArgumentException("Age must be in range 0-" . self::MAX_AGE);
}
$this->age = $age;
return $this;
}
public function canClimb() : bool{
return true;
}
public function getLightLevel() : int{
return $this->berries ? 14 : 0;
}
private function canBeSupportedAt(Block $block) : bool{
$supportBlock = $block->getSide(Facing::UP);
return $supportBlock->getSupportType(Facing::DOWN)->equals(SupportType::FULL()) || $supportBlock->hasSameTypeId($this);
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
$this->age = mt_rand(0, self::MAX_AGE);
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($this->berries){
$this->position->getWorld()->dropItem($this->position, $this->asItem());
$this->position->getWorld()->addSound($this->position, new GlowBerriesPickSound());
$this->position->getWorld()->setBlock($this->position, $this->setBerries(false));
return true;
}
if($item instanceof Fertilizer){
$newState = (clone $this)
->setBerries(true)
->setHead(!$this->getSide(Facing::DOWN)->hasSameTypeId($this));
if(BlockEventHelper::grow($this, $newState, $player)){
$item->pop();
}
return true;
}
return false;
}
public function onRandomTick() : void{
$head = !$this->getSide(Facing::DOWN)->hasSameTypeId($this);
if($head !== $this->head){
$this->position->getWorld()->setBlock($this->position, $this->setHead($head));
}
if($this->age < self::MAX_AGE && mt_rand(1, 10) === 1){
$growthPos = $this->position->getSide(Facing::DOWN);
$world = $growthPos->getWorld();
if($world->isInWorld($growthPos->getFloorX(), $growthPos->getFloorY(), $growthPos->getFloorZ())){
$block = $world->getBlock($growthPos);
if($block->getTypeId() === BlockTypeIds::AIR){
$newState = VanillaBlocks::CAVE_VINES()
->setAge($this->age + 1)
->setBerries(mt_rand(1, 9) === 1);
BlockEventHelper::grow($block, $newState, null);
}
}
}
}
public function ticksRandomly() : bool{
return true;
}
protected function recalculateCollisionBoxes() : array{
return [];
}
public function hasEntityCollision() : bool{
return true;
}
public function onEntityInside(Entity $entity) : bool{
$entity->resetFallDistance();
return false;
}
public function getDropsForCompatibleTool(Item $item) : array{
return $this->berries ? [$this->asItem()] : [];
}
public function isAffectedBySilkTouch() : bool{
return true;
}
public function asItem() : Item{
return VanillaItems::GLOW_BERRIES();
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
}

View File

@ -24,14 +24,12 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
final class ChemistryTable extends Opaque{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
//TODO

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\block\tile\Chest as TileChest;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\event\block\ChestPairEvent;
use pocketmine\item\Item;
@ -36,7 +35,6 @@ use pocketmine\player\Player;
class Chest extends Transparent{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
/**
* @return AxisAlignedBB[]
@ -57,13 +55,13 @@ class Chest extends Transparent{
foreach([false, true] as $clockwise){
$side = Facing::rotateY($this->facing, $clockwise);
$c = $this->getSide($side);
if($c instanceof Chest && $c->isSameType($this) && $c->facing === $this->facing){
if($c instanceof Chest && $c->hasSameTypeId($this) && $c->facing === $this->facing){
$pair = $world->getTile($c->position);
if($pair instanceof TileChest && !$pair->isPaired()){
[$left, $right] = $clockwise ? [$c, $this] : [$this, $c];
$ev = new ChestPairEvent($left, $right);
$ev->call();
if(!$ev->isCancelled() && $world->getBlock($this->position)->isSameType($this) && $world->getBlock($c->position)->isSameType($c)){
if(!$ev->isCancelled() && $world->getBlock($this->position)->hasSameTypeId($this) && $world->getBlock($c->position)->hasSameTypeId($c)){
$pair->pairWith($tile);
$tile->pairWith($pair);
break;

View File

@ -49,7 +49,7 @@ final class ChorusFlower extends Flowable{
private int $age = self::MIN_AGE;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->boundedInt(3, self::MIN_AGE, self::MAX_AGE, $this->age);
}

View File

@ -40,7 +40,7 @@ final class ChorusPlant extends Flowable{
$bb = AxisAlignedBB::one();
foreach($this->getAllSides() as $facing => $block){
$id = $block->getTypeId();
if($id !== BlockTypeIds::END_STONE && $id !== BlockTypeIds::CHORUS_FLOWER && !$block->isSameType($this)){
if($id !== BlockTypeIds::END_STONE && $id !== BlockTypeIds::CHORUS_FLOWER && !$block->hasSameTypeId($this)){
$bb->trim($facing, 2 / 16);
}
}
@ -49,7 +49,7 @@ final class ChorusPlant extends Flowable{
}
private function canBeSupportedBy(Block $block) : bool{
return $block->isSameType($this) || $block->getTypeId() === BlockTypeIds::END_STONE;
return $block->hasSameTypeId($this) || $block->getTypeId() === BlockTypeIds::END_STONE;
}
private function canStay(Position $position) : bool{

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
@ -31,7 +32,7 @@ class CoalOre extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
return [
VanillaItems::COAL()
VanillaItems::COAL()->setCount(FortuneDropHelper::weighted($item, min: 1, maxBase: 1))
];
}

View File

@ -23,11 +23,11 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\block\utils\WoodType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
@ -46,7 +46,7 @@ class CocoaBlock extends Transparent{
protected int $age = 0;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->boundedInt(2, 0, self::MAX_AGE, $this->age);
}
@ -94,7 +94,7 @@ class CocoaBlock extends Transparent{
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && $this->grow()){
if($item instanceof Fertilizer && $this->grow($player)){
$item->pop();
return true;
@ -119,16 +119,11 @@ class CocoaBlock extends Transparent{
}
}
private function grow() : bool{
private function grow(?Player $player = null) : bool{
if($this->age < self::MAX_AGE){
$block = clone $this;
$block->age++;
$ev = new BlockGrowEvent($this, $block);
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
return true;
}
return BlockEventHelper::grow($this, $block, $player);
}
return false;
}

View File

@ -23,11 +23,11 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\Fallable;
use pocketmine\block\utils\FallableTrait;
use pocketmine\event\block\BlockFormEvent;
use pocketmine\math\Facing;
class ConcretePowder extends Opaque implements Fallable{
@ -43,11 +43,7 @@ class ConcretePowder extends Opaque implements Fallable{
public function onNearbyBlockChange() : void{
if(($water = $this->getAdjacentWater()) !== null){
$ev = new BlockFormEvent($this, VanillaBlocks::CONCRETE()->setColor($this->color), $water);
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
}
BlockEventHelper::form($this, VanillaBlocks::CONCRETE()->setColor($this->color), $water);
}else{
$this->startFalling();
}

View File

@ -23,13 +23,16 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
final class CopperOre extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
return [VanillaItems::RAW_COPPER()];
return [
VanillaItems::RAW_COPPER()->setCount(FortuneDropHelper::weighted($item, min: 2, maxBase: 5)),
];
}
public function isAffectedBySilkTouch() : bool{ return true; }

View File

@ -32,7 +32,7 @@ use pocketmine\world\BlockTransaction;
final class Coral extends BaseCoral{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($tx->fetchBlock($blockReplace->getPosition()->down()))){
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
@ -40,14 +40,14 @@ final class Coral extends BaseCoral{
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->canBeSupportedBy($world->getBlock($this->position->down()))){
if(!$this->canBeSupportedAt($this)){
$world->useBreakOn($this->position);
}else{
parent::onNearbyBlockChange();
}
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->hasCenterSupport();
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport();
}
}

View File

@ -23,9 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\CoralTypeTrait;
use pocketmine\event\block\BlockDeathEvent;
use pocketmine\item\Item;
use function mt_rand;
@ -55,17 +55,13 @@ final class CoralBlock extends Opaque{
}
}
if(!$hasWater){
$ev = new BlockDeathEvent($this, $this->setDead(true));
$ev->call();
if(!$ev->isCancelled()){
$world->setBlock($this->position, $ev->getNewState());
}
BlockEventHelper::die($this, (clone $this)->setDead(true));
}
}
}
public function getDropsForCompatibleTool(Item $item) : array{
return [$this->setDead(true)->asItem()];
return [(clone $this)->setDead(true)->asItem()];
}
public function isAffectedBySilkTouch() : bool{

View File

@ -23,8 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\math\Facing;
@ -38,7 +38,7 @@ abstract class Crops extends Flowable{
protected int $age = 0;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->boundedInt(3, 0, self::MAX_AGE, $this->age);
}
@ -68,11 +68,7 @@ abstract class Crops extends Flowable{
if($block->age > self::MAX_AGE){
$block->age = self::MAX_AGE;
}
$ev = new BlockGrowEvent($this, $block);
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
if(BlockEventHelper::grow($this, $block, $player)){
$item->pop();
}
@ -96,11 +92,7 @@ abstract class Crops extends Flowable{
if($this->age < self::MAX_AGE && mt_rand(0, 2) === 1){
$block = clone $this;
++$block->age;
$ev = new BlockGrowEvent($this, $block);
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
}
BlockEventHelper::grow($this, $block, null);
}
}
}

View File

@ -41,7 +41,7 @@ class DaylightSensor extends Transparent{
protected bool $inverted = false;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->boundedInt(4, 0, 15, $this->signalStrength);
$w->bool($this->inverted);
}

View File

@ -66,13 +66,19 @@ class DeadBush extends Flowable{
}
private function canBeSupportedBy(Block $block) : bool{
$blockId = $block->getTypeId();
return $blockId === BlockTypeIds::SAND
|| $blockId === BlockTypeIds::RED_SAND
|| $blockId === BlockTypeIds::PODZOL
|| $blockId === BlockTypeIds::MYCELIUM
|| $blockId === BlockTypeIds::DIRT
|| $blockId === BlockTypeIds::HARDENED_CLAY
|| $blockId === BlockTypeIds::STAINED_CLAY;
return
$block->hasTypeTag(BlockTypeTags::SAND) ||
$block->hasTypeTag(BlockTypeTags::MUD) ||
match($block->getTypeId()){
//can't use DIRT tag here because it includes farmland
BlockTypeIds::PODZOL,
BlockTypeIds::MYCELIUM,
BlockTypeIds::DIRT,
BlockTypeIds::GRASS,
BlockTypeIds::HARDENED_CLAY,
BlockTypeIds::STAINED_CLAY => true,
//TODO: moss block
default => false,
};
}
}

View File

@ -28,8 +28,8 @@ use pocketmine\data\runtime\RuntimeDataDescriber;
class DetectorRail extends StraightOnlyRail{
protected bool $activated = false;
protected function describeState(RuntimeDataDescriber $w) : void{
parent::describeState($w);
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
parent::describeBlockOnlyState($w);
$w->bool($this->activated);
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
@ -31,7 +32,7 @@ class DiamondOre extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
return [
VanillaItems::DIAMOND()
VanillaItems::DIAMOND()->setCount(FortuneDropHelper::weighted($item, min: 1, maxBase: 1))
];
}

View File

@ -45,7 +45,7 @@ class Dirt extends Opaque{
parent::__construct($idInfo, $name, $typeInfo);
}
protected function describeType(RuntimeDataDescriber $w) : void{
public function describeBlockItemState(RuntimeDataDescriber $w) : void{
$w->dirtType($this->dirtType);
}
@ -59,7 +59,12 @@ class Dirt extends Opaque{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
$world = $this->position->getWorld();
if($face === Facing::UP && $item instanceof Hoe){
if($face !== Facing::DOWN && $item instanceof Hoe){
$up = $this->getSide(Facing::UP);
if($up->getTypeId() !== BlockTypeIds::AIR){
return true;
}
$item->applyDamage(1);
$newBlock = $this->dirtType->equals(DirtType::NORMAL()) ? VanillaBlocks::FARMLAND() : VanillaBlocks::DIRT();

View File

@ -41,7 +41,7 @@ class Door extends Transparent{
protected bool $hingeRight = false;
protected bool $open = false;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->bool($this->top);
$w->bool($this->hingeRight);
@ -53,7 +53,7 @@ class Door extends Transparent{
//copy door properties from other half
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
if($other instanceof Door && $other->isSameType($this)){
if($other instanceof Door && $other->hasSameTypeId($this)){
if($this->top){
$this->facing = $other->facing;
$this->open = $other->open;
@ -106,7 +106,7 @@ class Door extends Transparent{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN)) && !$this->getSide(Facing::DOWN) instanceof Door){ //Replace with common break method
if(!$this->canBeSupportedAt($this) && !$this->getSide(Facing::DOWN) instanceof Door){ //Replace with common break method
$this->position->getWorld()->useBreakOn($this->position); //this will delete both halves if they exist
}
}
@ -114,8 +114,7 @@ class Door extends Transparent{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face === Facing::UP){
$blockUp = $this->getSide(Facing::UP);
$blockDown = $this->getSide(Facing::DOWN);
if(!$blockUp->canBeReplaced() || !$this->canBeSupportedBy($blockDown)){
if(!$blockUp->canBeReplaced() || !$this->canBeSupportedAt($blockReplace)){
return false;
}
@ -126,7 +125,7 @@ class Door extends Transparent{
$next = $this->getSide(Facing::rotateY($this->facing, false));
$next2 = $this->getSide(Facing::rotateY($this->facing, true));
if($next->isSameType($this) || (!$next2->isTransparent() && $next->isTransparent())){ //Door hinge
if($next->hasSameTypeId($this) || (!$next2->isTransparent() && $next->isTransparent())){ //Door hinge
$this->hingeRight = true;
}
@ -145,7 +144,7 @@ class Door extends Transparent{
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
$world = $this->position->getWorld();
if($other instanceof Door && $other->isSameType($this)){
if($other instanceof Door && $other->hasSameTypeId($this)){
$other->open = $this->open;
$world->setBlock($other->position, $other);
}
@ -166,13 +165,13 @@ class Door extends Transparent{
public function getAffectedBlocks() : array{
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
if($other->isSameType($this)){
if($other->hasSameTypeId($this)){
return [$this, $other];
}
return parent::getAffectedBlocks();
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->hasEdgeSupport();
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->hasEdgeSupport();
}
}

View File

@ -33,7 +33,7 @@ use pocketmine\world\BlockTransaction;
class DoublePlant extends Flowable{
protected bool $top = false;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->bool($this->top);
}
@ -65,7 +65,7 @@ class DoublePlant extends Flowable{
return (
$other instanceof DoublePlant &&
$other->isSameType($this) &&
$other->hasSameTypeId($this) &&
$other->top !== $this->top
);
}

View File

@ -23,19 +23,21 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\TallGrassTrait;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
class DoubleTallGrass extends DoublePlant{
use TallGrassTrait {
getDropsForIncompatibleTool as traitGetDropsForIncompatibleTool;
}
public function canBeReplaced() : bool{
return true;
}
public function getDropsForIncompatibleTool(Item $item) : array{
if($this->top && mt_rand(0, 7) === 0){
return [VanillaItems::WHEAT_SEEDS()];
if($this->top){
return $this->traitGetDropsForIncompatibleTool($item);
}
return [];
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
@ -31,7 +32,7 @@ class EmeraldOre extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
return [
VanillaItems::EMERALD()
VanillaItems::EMERALD()->setCount(FortuneDropHelper::weighted($item, min: 1, maxBase: 1))
];
}

View File

@ -24,18 +24,16 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
class EndPortalFrame extends Opaque{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
protected bool $eye = false;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->bool($this->eye);
}

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\block\inventory\EnderChestInventory;
use pocketmine\block\tile\EnderChest as TileEnderChest;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
@ -36,7 +35,6 @@ use pocketmine\player\Player;
class EnderChest extends Transparent{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
public function getLightLevel() : int{
return 7;

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity;
use pocketmine\entity\Living;
use pocketmine\event\block\FarmlandHydrationChangeEvent;
use pocketmine\event\entity\EntityTrampleFarmlandEvent;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
@ -37,7 +38,7 @@ class Farmland extends Transparent{
protected int $wetness = 0; //"moisture" blockstate property in PC
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->boundedInt(3, 0, self::MAX_WETNESS, $this->wetness);
}
@ -56,7 +57,7 @@ class Farmland extends Transparent{
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()]; //TODO: this should be trimmed at the top by 1/16, but MCPE currently treats them as a full block (https://bugs.mojang.com/browse/MCPE-12109)
return [AxisAlignedBB::one()->trim(Facing::UP, 1 / 16)];
}
public function onNearbyBlockChange() : void{
@ -73,14 +74,22 @@ class Farmland extends Transparent{
$world = $this->position->getWorld();
if(!$this->canHydrate()){
if($this->wetness > 0){
$this->wetness--;
$world->setBlock($this->position, $this, false);
$event = new FarmlandHydrationChangeEvent($this, $this->wetness, $this->wetness - 1);
$event->call();
if(!$event->isCancelled()){
$this->wetness = $event->getNewHydration();
$world->setBlock($this->position, $this, false);
}
}else{
$world->setBlock($this->position, VanillaBlocks::DIRT());
}
}elseif($this->wetness < self::MAX_WETNESS){
$this->wetness = self::MAX_WETNESS;
$world->setBlock($this->position, $this, false);
$event = new FarmlandHydrationChangeEvent($this, $this->wetness, self::MAX_WETNESS);
$event->call();
if(!$event->isCancelled()){
$this->wetness = $event->getNewHydration();
$world->setBlock($this->position, $this, false);
}
}
}

View File

@ -42,7 +42,7 @@ class Fence extends Transparent{
foreach(Facing::HORIZONTAL as $facing){
$block = $this->getSide($facing);
if($block instanceof static || $block instanceof FenceGate || ($block->isSolid() && !$block->isTransparent())){
if($block instanceof static || $block instanceof FenceGate || $block->getSupportType(Facing::opposite($facing))->equals(SupportType::FULL())){
$this->connections[$facing] = true;
}else{
unset($this->connections[$facing]);

View File

@ -42,7 +42,7 @@ class FenceGate extends Transparent{
protected bool $open = false;
protected bool $inWall = false;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->bool($this->open);
$w->bool($this->inWall);

View File

@ -37,7 +37,7 @@ abstract class FillableCauldron extends Transparent{
private int $fillLevel = self::MIN_FILL_LEVEL;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->boundedInt(3, self::MIN_FILL_LEVEL, self::MAX_FILL_LEVEL, $this->fillLevel);
}

View File

@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\BlockBurnEvent;
use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\math\Facing;
use pocketmine\world\format\Chunk;
use pocketmine\world\World;
@ -39,7 +40,7 @@ class Fire extends BaseFire{
protected int $age = 0;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->boundedInt(4, 0, self::MAX_AGE, $this->age);
}
@ -58,12 +59,16 @@ class Fire extends BaseFire{
return 1;
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->equals(SupportType::FULL());
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
$down = $this->getSide(Facing::DOWN);
if(SoulFire::canBeSupportedBy($down)){
$world->setBlock($this->position, VanillaBlocks::SOUL_FIRE());
}elseif($down->isTransparent() && !$this->hasAdjacentFlammableBlocks()){
}elseif(!$this->canBeSupportedBy($this->getSide(Facing::DOWN)) && !$this->hasAdjacentFlammableBlocks()){
$world->setBlock($this->position, VanillaBlocks::AIR());
}else{
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(30, 40));
@ -140,9 +145,13 @@ class Fire extends BaseFire{
private function burnBlock(Block $block, int $chanceBound) : void{
if(mt_rand(0, $chanceBound) < $block->getFlammability()){
$ev = new BlockBurnEvent($block, $this);
$ev->call();
if(!$ev->isCancelled()){
$cancelled = false;
if(BlockBurnEvent::hasHandlers()){
$ev = new BlockBurnEvent($block, $this);
$ev->call();
$cancelled = $ev->isCancelled();
}
if(!$cancelled){
$block->onIncinerate();
$world = $this->position->getWorld();
@ -220,13 +229,6 @@ class Fire extends BaseFire{
}
private function spreadBlock(Block $block, Block $newState) : bool{
$ev = new BlockSpreadEvent($block, $this, $newState);
$ev->call();
if(!$ev->isCancelled()){
$block->position->getWorld()->setBlock($block->position, $ev->getNewState());
return true;
}
return false;
return BlockEventHelper::spread($block, $newState, $this);
}
}

View File

@ -37,7 +37,7 @@ use function rad2deg;
final class FloorCoralFan extends BaseCoral{
private int $axis = Axis::X;
protected function describeState(RuntimeDataDescriber $w) : void{
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalAxis($this->axis);
}
@ -53,7 +53,7 @@ final class FloorCoralFan extends BaseCoral{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($tx->fetchBlock($blockReplace->getPosition()->down()))){
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
if($player !== null){
@ -75,15 +75,15 @@ final class FloorCoralFan extends BaseCoral{
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->canBeSupportedBy($world->getBlock($this->position->down()))){
if(!$this->canBeSupportedAt($this)){
$world->useBreakOn($this->position);
}else{
parent::onNearbyBlockChange();
}
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->hasCenterSupport();
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport();
}
public function asItem() : Item{

Some files were not shown because too many files have changed in this diff Show More