Compare commits

...

476 Commits

Author SHA1 Message Date
9564c81582 Release 4.17.0 2023-03-14 18:14:40 +00:00
3de7a8c27f Updated for 1.19.70 2023-03-14 18:08:10 +00:00
d376399b7f Update composer dependencies
bedrock-item-upgrade-schema and bedrock-block-upgrade-schema are now minor-version-locked, to prevent introducing new upgrade schemas not intended for the currently in-use version
previously I'd intended to do this using max schema IDs, but this has proven to be error-prone, so it makes more sense to lock them in using package version constraints instead.
2023-03-14 17:29:25 +00:00
e2071e59c8 actions: update PHP versions 2023-03-13 17:44:10 +00:00
b13e97de3d Timings: fixed receivePacket timer showing 2x the actual number of received packets 2023-03-11 19:13:10 +00:00
328b87fc18 Bump phpstan/phpstan from 1.10.4 to 1.10.6 (#5617)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.4 to 1.10.6.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.10.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.4...1.10.6)

---
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-03-10 11:49:34 +00:00
acaa1a9ce1 contributing: update table to reflect branch name changes
these branches were renamed to make them more auto-complete-friendly.
2023-03-07 17:28:31 +00:00
3aec0fa3df 4.16.1 is next 2023-03-07 16:19:51 +00:00
fa131dab12 Release 4.16.0 2023-03-07 16:19:50 +00:00
bb4a82b1e7 Merge branch 'next-minor' into stable 2023-03-07 16:15:57 +00:00
93d844a281 build/make-release: improve support for non-stable release channels 2023-03-07 16:12:27 +00:00
616844696e 4.15.4 is next 2023-03-07 15:33:03 +00:00
71e3e36522 Release 4.15.3 2023-03-07 15:33:03 +00:00
a1b42d419f Merge branch 'stable' into next-minor 2023-03-07 15:24:24 +00:00
ef942a627f actions: drop concurrency group
this is causing builds to get randomly cancelled when multiple branches are pushed at once.
2023-03-07 15:23:12 +00:00
fd8c276bd2 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-03-07 15:15:21 +00:00
9783380d1a Merge branch 'stable' into next-minor 2023-03-07 15:13:39 +00:00
a784d93bfd Update composer dependencies 2023-03-07 15:13:16 +00:00
a05e8b366f Bump phpstan/phpstan from 1.10.3 to 1.10.4 (#5610)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.3 to 1.10.4.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.10.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.3...1.10.4)

---
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-03-07 14:40:08 +00:00
87a2e0460c Ping Discord news subscribers on new releases 2023-03-04 17:09:32 +00:00
4073c3fb39 Update composer dependencies 2023-03-04 16:56:08 +00:00
e227e6d8bf Merge branch 'stable' into next-minor 2023-03-04 16:55:56 +00:00
3aa40829ae Update composer dependencies 2023-03-04 16:55:31 +00:00
035d4b7263 MemoryManager: stringify floats, fixes #5598 2023-03-04 16:47:58 +00:00
3db1492c18 Fix CS again 2023-03-04 16:43:29 +00:00
a523189149 Added separate timings for broadcast and session buffer compression 2023-03-04 16:41:41 +00:00
f8893efb94 Don't bother with global batch compression if there is only 1 recipient
this allows the session to achieve better ratios, and also reduces worker pool spam.
2023-03-04 16:34:00 +00:00
70f1ee3e97 draft-release: set prerelease flag properly 2023-03-04 16:29:26 +00:00
eb2f0ed3d0 4.16.0-BETA3 is next 2023-03-04 16:19:34 +00:00
14e7d3e143 Release 4.16.0-BETA2 2023-03-04 16:19:34 +00:00
6d636fc2c7 4.16.0-BETA2 is next 2023-03-04 16:18:04 +00:00
a39f61a33d Release 4.16.0-BETA1 2023-03-04 16:18:01 +00:00
aaec21f544 Compressor: Use minCompressionThreshold exclusively
closes #5589
2023-03-04 15:07:50 +00:00
0edc5f8113 Bump phpunit/phpunit from 9.6.3 to 9.6.4 (#5597)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.3 to 9.6.4.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/main/ChangeLog-9.6.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.3...9.6.4)

---
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-03-03 14:06:18 +00:00
a382f0fd92 Bump phpstan/phpstan-phpunit from 1.3.8 to 1.3.10 (#5602)
Bumps [phpstan/phpstan-phpunit](https://github.com/phpstan/phpstan-phpunit) from 1.3.8 to 1.3.10.
- [Release notes](https://github.com/phpstan/phpstan-phpunit/releases)
- [Commits](https://github.com/phpstan/phpstan-phpunit/compare/1.3.8...1.3.10)

---
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-03-03 14:05:59 +00:00
0fcd2e7894 Merge branch 'stable' into next-minor 2023-02-28 19:23:25 +00:00
369e0855a7 Update composer dependencies 2023-02-28 19:17:46 +00:00
a6cf39b94e Update composer dependencies 2023-02-25 20:39:01 +00:00
17afd38274 Bump phpstan/phpstan from 1.10.1 to 1.10.3 (#5593)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.1 to 1.10.3.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.10.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.1...1.10.3)

---
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-02-25 20:36:33 +00:00
8f024cb382 Bump docker/build-push-action from 3.3.0 to 4.0.0 (#5545)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.3.0 to 4.0.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.3.0...v4.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-02-25 20:04:34 +00:00
e7209679fb ... 2023-02-24 22:23:00 +00:00
da054736b1 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-02-24 22:19:38 +00:00
d92173cded 4.15.3 is next 2023-02-24 22:18:34 +00:00
308cdb6863 Release 4.15.2 2023-02-24 22:18:34 +00:00
ae50b952f1 Accept 1.19.63 (same protocol, different protocol version) 2023-02-24 22:15:58 +00:00
f44946cb49 ... 2023-02-23 22:00:24 +00:00
f704bfb63a Use BedrockData 2.0.0 2023-02-23 21:52:17 +00:00
9acb4d64db Added generated constants for available BedrockData files
this makes it easier to detect unused files, detect removed files, and also avoid typos in usages.
2023-02-23 21:45:12 +00:00
8234360c8d Avoid creating batch buffers just to determine whether a batch should be globally compressed
Instead, sum together the lengths of encoded packet buffers and use that to decide whether to build the buffer or not.
2023-02-22 22:43:10 +00:00
6a64486f55 StandardPacketBroadcaster: Improve performance when broadcasting small packets
In refactors during PM4, I stripped out packet buffer caching, as it was problematic when events alter packets in undetectable ways.
However, I never cleaned this part of the code up properly after enabling DataPacketSendEvent to include multiple packets and multiple targets, so we were still individually encoding the packet(s) for every single session if the sum total of the sizes was below 256 bytes.

This change encodes packets once in the StandardPacketBroadcaster and retains their buffers to post to the session's send buffer directly if the resulting batch is below compression threshold.
This code is still not optimal (see ##5589), but fixing this brings broadcasting performance back to PM3 levels, without any of PM3's problems.
2023-02-22 21:52:12 +00:00
6ec778d0af Bump phpstan/phpstan from 1.9.18 to 1.10.1 (#5588)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.9.18 to 1.10.1.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.10.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.9.18...1.10.1)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  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-02-22 13:47:54 +00:00
75bb4f8da6 Merge branch 'stable' into next-minor 2023-02-21 18:32:58 +00:00
efdd7a186d World: fixed population timer sometimes not being stopped 2023-02-21 18:31:33 +00:00
c4ecb3d128 Merge branch 'stable' into next-minor 2023-02-21 15:37:06 +00:00
b574d49d36 4.15.2 is next 2023-02-21 15:23:25 +00:00
47e9ecd257 Release 4.15.1 2023-02-21 15:23:25 +00:00
799739fe86 Updated build/php submodule to pmmp/PHP-Binaries@b2207cf70d 2023-02-21 15:22:38 +00:00
59a04c971f Getter and setter for gravity (#5584)
closes #5525
2023-02-21 15:01:22 +00:00
168af31fd7 Bump phpstan/phpstan from 1.9.17 to 1.9.18 (#5585)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.9.17 to 1.9.18.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.10.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.9.17...1.9.18)

---
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-02-20 18:39:29 +00:00
871bd169a8 Timings: remove unnecessary code 2023-02-19 17:58:12 +00:00
4dbcd714bd NetworkSession: fixed some segments of recv/send logic not being covered by their respective network timings 2023-02-19 17:21:10 +00:00
d5e92b4ae6 ... 2023-02-19 16:53:04 +00:00
2a3288c4f9 Avoid useless throwaway PacketBatch objects 2023-02-19 16:50:03 +00:00
9cdb641936 Added encode packet timings
these changes required some new APIs in BedrockProtocol.
2023-02-19 16:47:20 +00:00
b56b35b10d ItemEntity: fixed a bunch of suspicious logic in entityBaseTick()
closes #5580
2023-02-17 20:14:38 +00:00
324bc27b5a Merge branch 'stable' into next-minor 2023-02-17 19:59:28 +00:00
71aad310c6 stfu 2023-02-17 16:39:46 +00:00
38828e2b42 4.15.1 is next 2023-02-17 16:37:34 +00:00
9a6d7b505c Release 4.15.0 2023-02-17 16:37:34 +00:00
1e3b025916 1.19.62 2023-02-17 16:36:32 +00:00
396d64c60b 4.14.2 is next 2023-02-15 15:19:39 +00:00
d7a0f5362e Release 4.14.1 2023-02-15 15:19:38 +00:00
c5dcd268ad CS 2023-02-15 15:04:41 +00:00
910c4c4b24 Updated BedrockProtocol 2023-02-15 15:02:00 +00:00
2fd6e769e6 NetworkSession: Improved packet budgeting
this fixes players getting kicked during server lag spikes.

closes #5532
2023-02-15 14:59:05 +00:00
69155015c9 Double quote array expansions to avoid re-splitting elements. (#5570)
See: https://github.com/koalaman/shellcheck/wiki/SC2068
2023-02-13 12:24:47 +00:00
6854830b6e start.sh: Use -n instead of ! -z (#5567)
See https://github.com/koalaman/shellcheck/wiki/SC2236
2023-02-13 12:21:35 +00:00
2c413768a5 Merge branch 'stable' into next-minor 2023-02-11 17:15:12 +00:00
fbaf8e3fc8 Update composer dependencies 2023-02-11 17:13:12 +00:00
c62845e92a 4.14.1 is next 2023-02-08 20:21:43 +00:00
c7930ce9ec Release 4.14.0 2023-02-08 20:21:42 +00:00
475888b031 InGamePacketHandler: do not process repeated skin change requests for the same full skin ID
this fixes a feedback loop with persona skins in 1.19.60.
2023-02-08 20:16:41 +00:00
40b90bb722 InGamePacketHandler: log a debug when processing skin change requests 2023-02-08 19:47:12 +00:00
5a4550a4fc CS 2023-02-08 18:55:49 +00:00
7bbc04e6de Silence PlayerSkinPacket debug messages during spawn response stage
the client sends its skin here in 1.19.60 for some reason, which makes no sense - I can only assume it's a bug
2023-02-08 18:55:38 +00:00
3ba662f64f 1.19.60 2023-02-08 18:46:37 +00:00
5d7b99daf4 Bump phpstan/phpstan from 1.9.15 to 1.9.16 (#5560)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.9.15 to 1.9.16.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.10.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.9.15...1.9.16)

---
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-02-08 10:55:09 +00:00
e47627f565 Bump build/php from f51e954 to fb297eb (#5558)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `f51e954` to `fb297eb`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](f51e954743...fb297eb511)

---
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-02-08 10:09:15 +00:00
39207c7992 Bump phpstan/phpstan from 1.9.14 to 1.9.15 (#5557)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.9.14 to 1.9.15.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.10.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.9.14...1.9.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-02-07 12:39:49 +00:00
41ab698f93 wrong filename 2023-02-06 12:29:54 +00:00
e45a6d8311 Merge branch 'stable' into next-minor 2023-02-06 12:27:09 +00:00
8912a97be7 Update Composer dependencies 2023-02-06 12:11:42 +00:00
8d2a9ce67c Clean PHPStan baselines 2023-02-06 12:09:19 +00:00
811352e2ef Bump build/php from c658506 to f51e954 (#5555)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `c658506` to `f51e954`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](c6585061ca...f51e954743)

---
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-02-06 11:50:10 +00:00
981385cf4a GeneratorManager: Removed redundant Closure wrapping (#5551) 2023-02-04 14:04:31 +00:00
cfa1e7486a Move legacy recipes and creative items in-house
having them here allows BedrockData to represent latest versions freely, without being limited by technical limitations of PM4.
2023-02-02 15:25:03 +00:00
3c46bf01c6 Begin removing dependence on obsolete files from BedrockData
these files were only kept for backwards compatibility, and aren't actively maintained. They are only needed for legacy conversions in the modern day era.
2023-02-02 14:47:38 +00:00
4562cfb85b 4.13.1 is next 2023-01-30 21:55:26 +00:00
cb1aac3cd4 Release 4.13.0 2023-01-30 21:55:26 +00:00
3dd1a14fb7 Merge branch 'next-minor' into stable 2023-01-30 21:52:41 +00:00
63c3127248 Scrub PHPStan baselines 2023-01-30 21:52:31 +00:00
96c32d24ba Update composer dependencies 2023-01-30 13:23:40 +00:00
d64a9d8b52 Merge branch 'stable' into next-minor 2023-01-30 12:58:50 +00:00
92c29b8172 Update transitive composer dependencies 2023-01-30 12:53:06 +00:00
0ac9584bbb Bump shivammathur/setup-php from 2.23.0 to 2.24.0 (#5543)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.23.0 to 2.24.0.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.23.0...2.24.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-01-30 12:49:42 +00:00
fe12e8d944 Bump build/php from 1c44c61 to c658506 (#5542)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `1c44c61` to `c658506`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](1c44c615c3...c6585061ca)

---
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-01-30 12:39:14 +00:00
7529953f0a Bump phpstan/phpstan from 1.9.13 to 1.9.14 (#5523)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.9.13 to 1.9.14.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.10.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.9.13...1.9.14)

---
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-01-27 23:08:36 +00:00
00dbb6855a Bump build/php from 83bec42 to 1c44c61 (#5539)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `83bec42` to `1c44c61`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](83bec42c3c...1c44c615c3)

---
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-01-27 23:08:08 +00:00
7eca3e8081 Fix typo
closes #5533
2023-01-26 14:52:50 +00:00
b58d7fc82a Bump build/php from af250d7 to 83bec42 (#5534)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `af250d7` to `83bec42`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](af250d7e06...83bec42c3c)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-26 13:00:07 +00:00
ceea8220a9 Bump symfony/filesystem from 5.4.13 to 5.4.19 (#5530)
Bumps [symfony/filesystem](https://github.com/symfony/filesystem) from 5.4.13 to 5.4.19.
- [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.13...v5.4.19)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-25 13:23:48 +00:00
18013e9551 Bump build/php from b479ec4 to af250d7 (#5527)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `b479ec4` to `af250d7`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](b479ec438f...af250d7e06)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-24 13:51:50 +00:00
bd3e9e1cad Do not allow more than 1 run to compile PHP at a time
this causes cache collisions and build failures
2023-01-23 20:13:29 +00:00
6173471cca Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-01-23 19:40:14 +00:00
644881372d Merge branch 'stable' into next-minor 2023-01-23 19:37:02 +00:00
a12aac71fd Updated setup-php-action 2023-01-23 19:36:52 +00:00
608fcd6cd7 4.12.12 is next 2023-01-22 20:44:31 +00:00
ce9b25e97a Release 4.12.11 2023-01-22 20:44:26 +00:00
f948cb0086 PocketMine.php: refuse pthreads 5.0 2023-01-21 15:30:36 +00:00
6c52723d97 Merge branch 'stable' into next-minor 2023-01-20 15:40:32 +00:00
d5b7bf77b0 Bump build/php from 6b605ed to b479ec4 (#5521)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `6b605ed` to `b479ec4`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](6b605ed7c4...b479ec438f)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-20 09:44:19 +00:00
b1a5b02d3a Updated DevTools to 1.16.1 2023-01-20 01:55:52 +00:00
74e052de51 Terminal: fix deprecation error on PHP 8.2 2023-01-20 01:30:39 +00:00
a5397d55fe Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-01-20 01:13:27 +00:00
65ef929d22 Update Actions PHP versions 2023-01-20 01:13:15 +00:00
441919c5e3 Begin testing on PHP 8.2 2023-01-20 01:12:35 +00:00
448aeec780 Bump phpstan/phpstan from 1.9.12 to 1.9.13 (#5520)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.9.12 to 1.9.13.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.10.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.9.12...1.9.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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-19 13:04:28 +00:00
78aea5c34c Merge branch 'stable' into next-minor 2023-01-18 20:46:10 +00:00
d7f40f75d2 PlayerPreLoginEvent: fixed documentation errors 2023-01-18 20:45:49 +00:00
b47035fbab Merge branch 'stable' into next-minor 2023-01-18 19:48:29 +00:00
f0925ff9dc draft-release: link to the correct channel-specific changelog
not having this made releasing alphas and betas error-prone, because I'd have to manually amend the changelog URL in the release.
2023-01-18 16:32:22 +00:00
d9324b9951 4.13.0-BETA2 is next 2023-01-18 16:15:47 +00:00
1d9336ed67 Release 4.13.0-BETA1 2023-01-18 16:15:43 +00:00
d37142af4b Merge branch 'stable' into next-minor 2023-01-18 15:30:42 +00:00
7c068101b7 CSÂ 2023-01-18 15:17:37 +00:00
217f9aea02 4.12.11 is next 2023-01-18 15:16:33 +00:00
2f5e08067d Release 4.12.10 2023-01-18 15:16:30 +00:00
a8556dff02 RakLibInterface: include Snooze events in Connection Handler timings 2023-01-18 15:02:33 +00:00
664089861a Bump phpstan/phpstan from 1.9.11 to 1.9.12 (#5517)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.9.11 to 1.9.12.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.10.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.9.11...1.9.12)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-18 14:27:51 +00:00
edb8f19a0c Merge branch 'stable' into next-minor 2023-01-16 19:56:38 +00:00
6c0254c1eb Block: document parameters of place() 2023-01-16 19:49:24 +00:00
0bb9fb09cc CS again 2023-01-16 19:39:24 +00:00
ab21fcdd67 Server: fixed load statistics not including Snooze processing time
this has been a bug ever since Snooze was first introduced. The load statistic, similarly to timings, did not account for time spent processing notifications between ticks. The problem is that this is often where a significant amoutn of the load actually comes from, because Snooze is most often activated due to incoming packets.

This change fixes the problem by including the time spent processing notifications since the previous tick in the current tick's usage metric.
2023-01-16 19:26:32 +00:00
ad6a423d12 Merge branch 'stable' into next-minor 2023-01-16 18:30:13 +00:00
b03df4f1e6 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2023-01-16 18:25:34 +00:00
0a2a6e2b3a 4.12.10 is next 2023-01-16 18:25:20 +00:00
0eb751c1c9 Release 4.12.9 2023-01-16 18:25:17 +00:00
b59b1e491e Bump phpunit/phpunit from 9.5.27 to 9.5.28 (#5514)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.5.27 to 9.5.28.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.5.28/ChangeLog-9.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.5.27...9.5.28)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-16 18:06:42 +00:00
95e8c68fde Bump docker/build-push-action from 3.2.0 to 3.3.0 (#5513)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.2.0...v3.3.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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-16 18:06:31 +00:00
7e16f9be8f InGamePacketHandler: handle block actions before use item transactions
the START_BREAK and transaction to break the block may arrive in the same packet, causing events to be fired in the wrong order.

fixes #5490
2023-01-16 17:50:11 +00:00
768650cee0 CS 2023-01-16 17:46:50 +00:00
c2c529e2da Include Snooze interrupts in timings results
fixes #5511

This requires any Timings instances to be updated to
pmmp/timings@5410f62436, otherwise the TPS
reported will be incorrect.
2023-01-16 17:40:39 +00:00
289e86e899 Make use of World::requestSafeSpawn() 2023-01-14 17:55:00 +00:00
7d59bafd83 World: added requestSafeSpawn() (async)
this simplifies usages of safe spawns, since the caller doesn't need to know which chunks will be needed for the spawn to be selected.

We'll need this in the future, because safe spawns may also get diverted horizontally as well as vertically, which might require loading adjacent chunks as well as the chunk the position is actually in.
2023-01-14 17:42:17 +00:00
1bbe053848 Language: fixed another couple of hardcoded translation keys 2023-01-13 17:52:20 +00:00
2ed48c8469 ... 2023-01-13 17:46:16 +00:00
d786ed5ebf WorldManager: fixed debug spam 2023-01-13 17:43:02 +00:00
a9f06fc5f4 Replaced hardcoded record.nowPlaying with KnownTranslationKeys 2023-01-13 17:27:57 +00:00
dff3f45d22 Constify more tick-related things 2023-01-13 16:29:09 +00:00
1e17d86421 Constify server TPS and server tick time
this makes it significantly easier to perform experiments involving the server TPS.
2023-01-13 16:03:15 +00:00
ba18a81e88 NetworkSession: fixed rate limit getting exhausted after 2.5 seconds during PvP 2023-01-13 15:28:03 +00:00
329c2a6c0f Merge branch 'stable' into next-minor 2023-01-12 22:17:00 +00:00
39218017ca Fixed walls and thin blocks not connecting to each other
closes #5498
2023-01-12 22:16:41 +00:00
fc487b17be DumpMemoryCommand: use localized description 2023-01-12 22:10:13 +00:00
91ac47ecba Merge branch 'stable' into next-minor 2023-01-12 21:47:37 +00:00
f4a1d69075 Bell: fixed support requirements
this somehow got overlooked in the support types refactor.
2023-01-12 21:45:25 +00:00
cbeae906e1 Torch: remove unused variable 2023-01-12 21:34:44 +00:00
b25e8e26f0 BaseBanner: fixed incorrect support requirements 2023-01-12 21:31:50 +00:00
a79be994de World: fixed block placement when clicking on replaceable blocks
in vanilla, it appears to behave as if the player always clicked on the up face if a block was replaced.

In PM, we were still using the original face, which caused bugs when, for example, placing a button next to a wall by clicking on the side of tallgrass. The button would replace the tallgrass, but stick to the wall, instead of placing itself on the ground like vanilla expects.

This may appear unusual to anyone who also happens to implement canBePlacedAt(), since the facing behaviour will be different. However, this behaviour appears to match vanilla, and even slabs (which I feared might break because of this change) work perfectly.

In the future, it may be desirable to pass some other value here, such as null, to indicate that the clicked block is being replaced. However, that's a BC break and therefore outside of the scope of a stable bug fix.
2023-01-12 21:11:48 +00:00
e26c8b9e9f block: eliminate suspicious usages of $blockClicked in place() 2023-01-12 20:35:26 +00:00
4e9c3e101d Bell: fixed blocks not being able to be placed when not ringing the bell 2023-01-12 19:42:33 +00:00
d295e1be54 PressurePlate: destroy self when no support is present 2023-01-12 19:36:47 +00:00
2f3fcef97c Fixed blocks incorrectly using blockClicked for support checks
this caused some interesting bugs, such as being able to place floating pressure plates by clicking on the side of a solid block halfway up a wall.
2023-01-12 19:36:23 +00:00
4df1f7f502 Updated composer dependencies (next-minor) 2023-01-12 19:03:55 +00:00
d74719704e Merge branch 'stable' into next-minor 2023-01-12 19:02:07 +00:00
c5056e0a43 phpstan 1.9.11 2023-01-12 19:01:57 +00:00
a47aa50477 Update composer dependencies 2023-01-12 18:59:18 +00:00
5021096bdd Fixed walls and thin blocks not connecting to each other
closes #5498
2023-01-09 20:46:57 +00:00
f7930a3a0b 4.12.9 is next 2023-01-09 00:04:40 +00:00
bb7df60a4d Release 4.12.8 2023-01-09 00:04:40 +00:00
992cb06da6 NetworkSession: fixed rate limit not being increased correctly on Windows
due to the 15ms scheduler interval, the server will often sleep 45ms instead of 50ms, which causes the budget not to get updated.
2023-01-09 00:01:56 +00:00
bb3f87f862 NetworkSession: allow 2 batches per tick
apparently InventoryTransactionPacket may arrive outside of the normal update cycle, since it's prioritized to reduce latency.
2023-01-09 00:00:39 +00:00
d2eddf9d33 relocate comments 2023-01-08 20:56:51 +00:00
81ca0c8fbf Language: do not parse translations if the text was a plain key
this unintentionally allowed translations to reference other translations 1 level deep, which is not desired behaviour.
This also improves performance for the cases where formatting isn't used.
2023-01-08 20:56:12 +00:00
fc77b14760 4.12.8 is next 2023-01-08 20:23:18 +00:00
52b6f1a492 Release 4.12.7 2023-01-08 20:23:15 +00:00
0233e74f4f NetworkSession: micro optimisation - do not check if a debugger is active unless the packet limit is exceeded 2023-01-08 19:45:14 +00:00
dd355c58d8 NetworkSession: fix CS 2023-01-08 19:35:43 +00:00
267032cff9 NetworkSession: do not rate limit packets if a debugging session is active 2023-01-08 19:31:39 +00:00
d4b8c47a65 Language: document poorly-named function parseTranslation() 2023-01-08 16:46:25 +00:00
4a3d9f8f83 Make client-aware translation handling more coherent
I have no clear idea why this was still using translateString(), since it's entirely unnecessary when we aren't selectively translating.
2023-01-08 16:45:57 +00:00
1c96e7936c Remove dead translation code
we don't translate raw string parameters anywhere else these days, so there's no reason to do so here either. The parameters array is already reduced to string[] by this point anyway.
2023-01-08 16:20:05 +00:00
6cecd690b2 CS 2023-01-07 21:33:53 +00:00
91e38d1f97 NetworkSession: compensate for server lag in batch budgeting 2023-01-07 21:33:34 +00:00
653178c1fd 4.12.7 is next 2023-01-07 16:22:01 +00:00
eb06535ed1 Release 4.12.6 2023-01-07 16:22:01 +00:00
f9bcc8e862 NetworkSession: added a rate-limit for incoming batches 2023-01-07 16:19:02 +00:00
ece49f011c Merge branch 'stable' into next-minor 2023-01-06 01:50:17 +00:00
f43ca405d4 4.12.6 is next 2023-01-06 00:44:58 +00:00
d146175d27 Release 4.12.5 2023-01-06 00:44:58 +00:00
3baa5ab712 InGamePacketHandler: removed obsolete workaround 2023-01-06 00:41:57 +00:00
e647e8c933 World: Use existing function to notify nearby blocks of an update (#5494) 2023-01-05 16:55:35 +00:00
c02bead12b Bump phpstan/phpstan from 1.9.6 to 1.9.7 (#5495)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.9.6 to 1.9.7.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.9.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.9.6...1.9.7)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-05 16:46:45 +00:00
e9ca25c1cb typo 2023-01-05 16:45:56 +00:00
a513cca582 Stop Dependabot from creating PRs for locale-data minor and major versions 2023-01-05 16:45:22 +00:00
9a47c1d401 Bump shivammathur/setup-php from 2.22.0 to 2.23.0 (#5474)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.22.0 to 2.23.0.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.22.0...2.23.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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-04 20:15:11 +00:00
433f5451d7 Improve World::notifyNeighbourBlockUpdate() doc (#5491) 2023-01-04 20:11:55 +00:00
64e505defb Bump phpstan/phpstan from 1.9.4 to 1.9.6 (#5492)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.9.4 to 1.9.6.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.9.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.9.4...1.9.6)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-04 20:05:34 +00:00
33d1755eae Player: fixed not receiving slot updates for small crafting grid
I'm not really sure why this tracking logic is here and not in InventoryManager, but for now it is what it is.
2023-01-04 01:28:25 +00:00
fc63c54116 CraftingManager: more detailed type information for shapelessRecipes and shapedRecipes 2023-01-04 00:32:26 +00:00
db07976aab TypeConverter: do not send useless meta to the client 2023-01-03 23:50:31 +00:00
0e4b79ea77 InGamePacketHandler: fixed client-side predictions not getting rolled back for block placement 2023-01-03 19:43:21 +00:00
588c9b114b 4.12.5 is next 2023-01-03 19:30:02 +00:00
b095f606c1 Release 4.12.4 2023-01-03 19:29:47 +00:00
b312e93176 Limit list max size in transactions
this duct tape is to limit the impact of a security vulnerability being actively exploited.
2023-01-02 22:59:48 +00:00
172ce659b8 Use str_starts_with, str_ends_with and str_contains instead of strpos (#5485) 2022-12-31 13:02:23 +00:00
61933624d2 NetworkSession: Lift batch limit to 1300 to allow shift-click crafting to work correctly
the theoretical limit for transactions in this case is 64x9 (inputs) + 64x9 (output on crafting grid) + 64 (outputs to main slot) + 64 CraftingEventPackets = 1280.
This is an extreme case which assumes that a recipe could generate up to 64x10 (640) output items per iteration, filling every slot of the output grid, which should never occur in any reasonable circumstances.
2022-12-30 22:11:35 +00:00
0d31b25fba Use str_starts_with and str_contains instead of strpos (#5482) 2022-12-30 21:41:30 +00:00
90beaeaeb4 4.12.4 is next 2022-12-28 21:01:50 +00:00
466f7e98ed Release 4.12.3 2022-12-28 21:01:47 +00:00
59be901efe Fixed unauthenticated sessions taking up player slots 2022-12-28 20:42:33 +00:00
0d169b4e80 Filesystem: added fileGetContents to reduce ErrorToExceptionHandler boilerplate code 2022-12-25 17:13:51 +00:00
b1c0eae1f6 NetworkSession: tidy up common disconnection logic 2022-12-24 20:36:18 +00:00
80832ff763 NetworkSession: do not send packets to disconnected sessions
this is mostly harmless, since the packets land in a buffer that gets discarded, but we also need to avoid calling DataPacketSendEvent.
2022-12-24 20:12:50 +00:00
f7d0d16eb3 NetworkSession: defer destructive cleanup until the next session tick() call
this fixes crashes when kicking players during PlayerJoinEvent and various other events.
2022-12-24 20:06:00 +00:00
6375139d0b DefaultPermissions: improve readability slightly 2022-12-24 17:47:17 +00:00
567bd8abb5 Add .self and .other permissions for gameplay-altering commands (#5470)
I'm not quite sure this is the best way to enable such functionality, but it's already used for some other stuff, so I'm not too worried for now.

This allows the following commands to have their usage limited to self or others:
- /effect
- /enchant
- /gamemode
- /give
- /spawnpoint
- /teleport
- /title

I envision this being useful for creative mode servers, and test servers such as test.pmmp.io.
2022-12-24 17:22:18 +00:00
3d038b28ff SplashPotion: const-ify missed NBT key 2022-12-24 15:19:56 +00:00
0c9b6a6797 DatFilePlayerDataProvider: added documentation 2022-12-23 19:00:45 +00:00
639f089c55 .. 2022-12-23 18:59:36 +00:00
9010b2743c Move player data storage handling behind an interface 2022-12-23 18:58:49 +00:00
4c91c4aaf1 ÂMemoryManager: replace switch with match 2022-12-23 17:36:08 +00:00
17125ce0e3 Merge branch 'stable' into next-minor 2022-12-23 16:56:54 +00:00
3987ee6cb2 PluginDescription: const-ify plugin.yml parsing keys 2022-12-23 16:11:03 +00:00
51a684c0ea PermissionParser: remove hardcoded default strings in defaultFromString() 2022-12-23 16:03:01 +00:00
43e69041fc PermissionParser: use constants for keys 2022-12-23 16:00:38 +00:00
5d2b0acfc8 GamemodeCommand: report failure if the target's game mode is already the desired game mode
this has irritated me for years.
2022-12-22 18:38:10 +00:00
7d1d62042c attempted fix for GitHub rate limiting php-cs-fixer installation
from https://github.com/shivammathur/setup-php/issues/678#issuecomment-1363128626
2022-12-22 18:13:03 +00:00
2a33c9ed3b Fix PHPStan 2022-12-22 16:53:14 +00:00
b03733442b Move translation flattening logic from Player to NetworkSession
this is network-specific stuff, so it doesn't belong in Player.
2022-12-22 16:51:09 +00:00
9c9929ff39 Player: break cycle between sendMessage() and sendTranslation() 2022-12-22 16:37:36 +00:00
566a8a261f Player: deprecate sendTranslation() in favour of sendMessage() 2022-12-22 16:32:54 +00:00
a9e5f92958 Show death message on death screen (#5386) 2022-12-22 15:36:31 +00:00
17dde140a5 Bump phpstan/phpstan-phpunit from 1.3.2 to 1.3.3 (#5465)
Bumps [phpstan/phpstan-phpunit](https://github.com/phpstan/phpstan-phpunit) from 1.3.2 to 1.3.3.
- [Release notes](https://github.com/phpstan/phpstan-phpunit/releases)
- [Commits](https://github.com/phpstan/phpstan-phpunit/compare/1.3.2...1.3.3)

---
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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-22 15:23:10 +00:00
ee7d4728d8 World: added cache for isChunkTickable()
this considerably reduces the amount of work done by the function, since it's usually checking the same chunks over and over again.
2022-12-19 21:20:21 +00:00
923dcec4e7 Revert "World: do not refresh ticked chunks list every tick"
This reverts commit aebcfc516f.

this has edge cases in the handling of adjacent chunk locks which I
didn't consider at the time. Once accounting for those edge cases, it
became significantly more complex to the point that I realized this
needed more planning.
2022-12-19 20:57:51 +00:00
1e5597f0d5 World: account for null chunk edge case in tickChunk()
the target chunk may no longer be loaded if it was unloaded during a previous chunk's tick (e.g. during BlockGrowEvent).
Since the parent function iterates over a pre-selected array of chunks, the chunk will still be present in the list even if it's no longer loaded by the time it's reached.
2022-12-19 20:20:52 +00:00
aebcfc516f World: do not refresh ticked chunks list every tick
this is just wasting CPU time, since the effects aren't noticeable on such a small timescale anyway.
This reduces the CPU impact of chunk selection by 95%. However, this is the lesser part of chunk ticking, and the lion's share of the performance impact still comes from actually ticking the chunks.
2022-12-19 20:17:29 +00:00
97ef209c5f HandlerList: added missing class-string type for constructor 2022-12-19 16:26:36 +00:00
99faeb8d05 Merge remote-tracking branch 'origin/stable' into next-minor 2022-12-19 15:55:59 +00:00
1305fd5fb2 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2022-12-19 15:52:56 +00:00
7a137f932f Updated build/php submodule to pmmp/php-build-scripts@6b605ed7c4 2022-12-19 15:52:44 +00:00
63e8b1cf3a Bump phpstan/phpstan from 1.9.3 to 1.9.4 (#5458)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.9.3 to 1.9.4.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.9.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.9.3...1.9.4)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-19 15:39:59 +00:00
65bce762ff Updated transient Composer dependencies 2022-12-19 15:34:17 +00:00
529700bb8b PotionTypeIdMap: fixed uninitialized fields
I have no idea why this didn't ever cause a problem before... probably an edge-case in the typed properties implementation
2022-12-19 15:33:15 +00:00
b2017c8462 and more 2022-12-18 22:14:31 +00:00
bf44edd179 Constify a bunch of NBT keys, pass 1 2022-12-18 22:12:15 +00:00
aa374083d8 Accept new BedrockProtocol version 2022-12-18 21:00:52 +00:00
8c0d3943d8 Added length validation for resource pack encryption keys 2022-12-15 22:36:06 +00:00
d02c6668b2 ResourcePackManager: added setPackEncryptionKey()
this allows plugins to install their own encrypted resource packs
2022-12-15 22:29:34 +00:00
880d01daea ResourcePackManager: added setResourceStack()
this enables plugins to modify the resource pack stack however they see fit.

Modifying the existing stack can be done by doing array modifications on the result of getResourceStack() and then setting it back again using this method.
2022-12-15 22:10:53 +00:00
50b70708fb ResourcePackManager: extracted loadPackFromPath() private method from constructor body 2022-12-15 21:59:54 +00:00
437fa615b8 4.12.3 is next 2022-12-15 21:08:28 +00:00
0ee6cdb058 Release 4.12.2 2022-12-15 21:08:23 +00:00
97d6a79b25 Updated BedrockProtocol 2022-12-15 20:37:36 +00:00
8b5e4c1c16 Updated PHPStan 2022-12-15 20:16:56 +00:00
c5d716dc9d Added keep on death methods for items (#5395) 2022-12-15 20:10:20 +00:00
95d0a3bf41 Merge branch 'stable' into next-minor 2022-12-15 19:38:22 +00:00
cf707e15c2 fix 2022-12-15 19:36:16 +00:00
1308cda5c2 Implemented hook method Item::onInteractEntity() (#5432)
this is called when the player right-clicks on an entity to do some action, such as shearing, naming etc.
2022-12-15 19:30:52 +00:00
214a5ddc15 Bump netresearch/jsonmapper from 4.0.0 to 4.1.0 (#5446)
Bumps [netresearch/jsonmapper](https://github.com/cweiske/jsonmapper) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/cweiske/jsonmapper/releases)
- [Changelog](https://github.com/cweiske/jsonmapper/blob/master/ChangeLog)
- [Commits](https://github.com/cweiske/jsonmapper/compare/v4.0.0...v4.1.0)

---
updated-dependencies:
- dependency-name: netresearch/jsonmapper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-15 19:28:11 +00:00
9f7dfe3355 Bump phpunit/phpunit from 9.5.26 to 9.5.27 (#5447)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.5.26 to 9.5.27.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/main/ChangeLog-9.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.5.26...9.5.27)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-15 19:21:39 +00:00
9b55d18393 Bump ncipollo/release-action from 1.11.2 to 1.12.0 (#5451)
Bumps [ncipollo/release-action](https://github.com/ncipollo/release-action) from 1.11.2 to 1.12.0.
- [Release notes](https://github.com/ncipollo/release-action/releases)
- [Commits](https://github.com/ncipollo/release-action/compare/v1.11.2...v1.12.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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-15 19:20:28 +00:00
31465525e3 Fixed PHP-CS-Fixer not import global constants. (#5449) 2022-12-12 17:12:33 +00:00
74613b9b09 Bump phpstan/phpstan-phpunit from 1.2.2 to 1.3.0 (#5445)
Bumps [phpstan/phpstan-phpunit](https://github.com/phpstan/phpstan-phpunit) from 1.2.2 to 1.3.0.
- [Release notes](https://github.com/phpstan/phpstan-phpunit/releases)
- [Commits](https://github.com/phpstan/phpstan-phpunit/compare/1.2.2...1.3.0)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-10 21:17:03 +00:00
1cefe24414 InGamePacketHandler: fixed transaction predictions not getting rolled back for failed use/release/interact transactions
this was caused by b5cfab497d.
2022-12-10 21:16:08 +00:00
4357c110c8 Add the event: WorldParticleEvent (#5428) 2022-12-06 14:19:14 +00:00
8bf85d4a18 bootstrap: avoid using is_writable() to check for data directory access permissions
closes #5440
2022-12-06 14:13:37 +00:00
b5e6dec0c6 Filesystem: capture error information from attempted lock file creation 2022-12-06 14:06:08 +00:00
a3306914cc bootstrap: do not require the plugins dir to be writable
on a modern installation, the plugins folder does not need to be writable by the server. Perhaps DevTools should be checking this for /genplugin, but it's not required otherwise.
2022-12-06 13:58:50 +00:00
3b32ea1b0b Update PhpStorm code style settings 2022-12-06 13:22:54 +00:00
7ec32f981e Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2022-12-06 13:22:15 +00:00
b0c87e9d06 Added phpdoc_align rule for php-cs-fixer 2022-12-06 13:21:57 +00:00
99996b62d6 Align PhpDoc @param tags according to PHP-CS-Fixer 2022-12-06 13:21:20 +00:00
fed2a6d917 Add the event: WorldSoundEvent (#5322) 2022-12-06 13:06:40 +00:00
1d4b6dc66e Only reduce durability when armor reduced damage. (#5444)
https://minecraft.fandom.com/wiki/Durability#Armor_durability
2022-12-05 21:10:36 +00:00
1cb6d9f5af Bump dessant/support-requests from 2 to 3 (#5442)
Bumps [dessant/support-requests](https://github.com/dessant/support-requests) from 2 to 3.
- [Release notes](https://github.com/dessant/support-requests/releases)
- [Changelog](https://github.com/dessant/support-requests/blob/master/CHANGELOG.md)
- [Commits](https://github.com/dessant/support-requests/compare/v2...v3)

---
updated-dependencies:
- dependency-name: dessant/support-requests
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-05 21:10:09 +00:00
174c9a48f5 Merge branch 'next-minor' of github.com:pmmp/PocketMine-MP into next-minor 2022-12-05 14:12:45 +00:00
0a9b52618d 4.12.2 is next 2022-12-04 23:11:48 +00:00
7ae6425d05 Release 4.12.1 2022-12-04 23:11:48 +00:00
b5cfab497d Clean up inventory content syncing, fixes #5441
these remnants should have been cleaned up in 4.11, but I somehow managed to skip over them.
2022-12-04 23:05:30 +00:00
774e23137e changelog: added detail about InventoryManager internals changes
this isn't considered part of the API, but certain specialized popular plugins (e.g. InvMenu) require it.
2022-12-01 20:48:38 +00:00
3984d220bb Implemented the swift sneak enchantment (#5404)
Co-authored-by: Dylan T <dktapps@pmmp.io>

closes #5301
2022-12-01 20:38:41 +00:00
43bc3c7b25 Added tool to dump JSON contents of encoded crashdump data 2022-12-01 19:36:31 +00:00
eb62dc3294 Added documentation for RegistryTrait, EnumTrait and CloningRegistryTrait 2022-11-30 21:04:17 +00:00
0b497654f2 Merge remote-tracking branch 'origin/stable' into next-minor 2022-11-30 19:51:24 +00:00
279056fe2f 4.12.1 is next 2022-11-30 16:35:58 +00:00
cd233b123b Release 4.12.0 2022-11-30 16:35:58 +00:00
64dd5e3bf6 Update dependencies for 1.19.50 2022-11-30 16:32:04 +00:00
4e5cc57560 Bump build/php from 9353116 to 27cc1fc (#5438)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `9353116` to `27cc1fc`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](9353116fa8...27cc1fcdfa)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-28 11:15:09 +00:00
d476a4c1aa Implement a Living::getDisplayName() (#5384) 2022-11-27 19:48:55 +00:00
95263795a8 Durable: fix misbehaviour of isBroken() since fe982c697b (#5436)
this broke tool and armour break sounds.
2022-11-27 00:13:41 +00:00
2db86d151f Bump ncipollo/release-action from 1.11.1 to 1.11.2 (#5414)
Bumps [ncipollo/release-action](https://github.com/ncipollo/release-action) from 1.11.1 to 1.11.2.
- [Release notes](https://github.com/ncipollo/release-action/releases)
- [Commits](https://github.com/ncipollo/release-action/compare/v1.11.1...v1.11.2)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-26 20:26:02 +00:00
f0358b09b7 changelog: added commit links to internals changes 2022-11-25 21:47:27 +00:00
80a432d9ff Merge branch 'next-minor' into stable 2022-11-25 20:30:57 +00:00
ec9f9a469f 4.11.1 is next 2022-11-25 20:29:49 +00:00
d450264e1c Release 4.11.0 2022-11-25 20:29:46 +00:00
5e92f55d35 4.10.3 is next 2022-11-25 15:20:18 +00:00
58c1bfe5d2 Release 4.10.2 2022-11-25 15:20:15 +00:00
641d35a30f Updated pocketmine/locale-data to get new translations 2022-11-25 14:59:58 +00:00
642630a4d2 ... 2022-11-25 14:57:47 +00:00
d79e6354a0 Merge branch 'stable' into next-minor 2022-11-25 14:41:05 +00:00
ff63983de4 Update transient composer dependencies 2022-11-25 14:39:34 +00:00
588215044e Update BedrockProtocol 2022-11-25 14:37:37 +00:00
5c1e9a35a9 Fix missing sounds when interacting with item frames (#5383)
closes #5168
2022-11-25 14:28:41 +00:00
aad9f5fb45 Terminal: use fallback escape codes if TERM env var is not set
tput requires a value for TERM, so it will generate errors if the var is
not set, as it appears not to be in PhpStorm on macOS.
2022-11-24 22:52:33 +00:00
a8dca190c6 Updated build/php submodule to pmmp/php-build-scripts@9353116fa8 2022-11-24 21:07:59 +00:00
e5f5fe80f9 BlockGrowEvent: Remove unnecessary Cancellable implementation (#5359)
this is already implemented by BaseBlockChangeEvent
2022-11-23 13:29:23 +00:00
36ab34df29 Implement BlockDeathEvent (#5420)
closes #4711
2022-11-23 12:57:26 +00:00
dda8ff18b1 Missing space (#5419) 2022-11-21 10:25:17 +00:00
6562335120 CrashDump: fixed failure to generate crash report when error messages contain invalid characters
closes #2986
2022-11-15 22:00:20 +00:00
0c463a8721 PlayerCreationEvent: update woefully inadequate documentation
closes #4581
2022-11-15 21:45:08 +00:00
a66f966b08 Update API documentation for Inventory methods 2022-11-15 21:00:13 +00:00
cca22046ab Updated pocketmine/locale-data 2022-11-15 20:21:39 +00:00
d19f0bf7be Language: added getAll() 2022-11-15 15:27:14 +00:00
ff2391e74a FormattedCommandAlias: use new string for description 2022-11-15 15:26:55 +00:00
39e10da88d PlayerChatEvent: replace hardcoded translation key with KnownTranslationKeys constant 2022-11-15 15:15:34 +00:00
beed6efd4e 4.11.0-BETA3 is next 2022-11-13 14:30:11 +00:00
e5bc4deb12 Release 4.11.0-BETA2 2022-11-13 14:29:59 +00:00
2fcff13578 World: added getter and setter for simulation radius 2022-11-12 23:32:12 +00:00
b4b8ef1c6b World: Improve performance of ticked chunk selection when lots of loaders use the same chunk
since we use the same simulation distance for every loader, multiple loaders on the same chunk will produce the same set of ticked chunks.
2022-11-12 22:21:30 +00:00
9650b7f03a Update PHPStan to 1.9.2 2022-11-12 17:31:39 +00:00
a3502a711d Merge branch 'stable' into next-minor 2022-11-12 17:01:58 +00:00
83ddcce987 World: Considerably simplify ticked chunk selection
WARNING: This WILL have a performance impact on larger servers, but that's the price to pay for having crops actually grow.

The old overengineered method for doing this was causing glacially slow crop growth, vanilla parity issues and really just didn't make much sense. This method is probably incorrect too, but it will at least produce visible results.
2022-11-12 16:57:35 +00:00
732dac6fc1 Player: revert accidental change from ef100b248b 2022-11-12 14:43:22 +00:00
d5e3636908 Timezone: Apparently timezone_id returned by timezone_abbreviations_list() may be null... 2022-11-12 14:40:37 +00:00
ef100b248b Improved doc comment for Internet::getIP() (#5406) 2022-11-12 13:52:49 +00:00
d03bbb0426 Implemented darkness effect (#5402) 2022-11-10 12:57:14 +00:00
93e661aa4e Removed useless @inheritDoc (#5399) 2022-11-09 13:40:35 +00:00
50efcf7424 Bump ramsey/uuid from 4.5.1 to 4.6.0 (#5400)
Bumps [ramsey/uuid](https://github.com/ramsey/uuid) from 4.5.1 to 4.6.0.
- [Release notes](https://github.com/ramsey/uuid/releases)
- [Changelog](https://github.com/ramsey/uuid/blob/4.x/CHANGELOG.md)
- [Commits](https://github.com/ramsey/uuid/compare/4.5.1...4.6.0)

---
updated-dependencies:
- dependency-name: ramsey/uuid
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-09 13:40:09 +00:00
a7ac6070dc Correct damage calculation for non-arrow projectiles (#5394) 2022-11-07 20:05:53 +00:00
069062f122 4.11.0-BETA2 is next 2022-11-07 15:18:09 +00:00
bf7014e0ec Release 4.11.0-BETA1 2022-11-07 15:18:05 +00:00
824ed0a56a Merge branch 'stable' into next-minor 2022-11-07 15:04:48 +00:00
b3ccf41307 4.10.2 is next 2022-11-07 14:50:44 +00:00
a39938e6b6 Release 4.10.1 2022-11-07 14:50:43 +00:00
d5bf88acc0 Added missing changelog items for 4.10.0 release
these really ought to have been released in 4.9.2, but it's too late for that now.
2022-11-07 14:43:11 +00:00
2d0602d19f World: fixed spawning in the void when the spawn terrain is higher than y=70 on default worlds
fixes #5390
2022-11-07 14:24:17 +00:00
3a2a23b236 Fixed totem activating when having 1HP instead of 0HP (#5380) 2022-11-07 13:54:14 +00:00
1a8c8af523 Bump shivammathur/setup-php from 2.21.2 to 2.22.0 (#5375)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.21.2 to 2.22.0.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.21.2...2.22.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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-07 13:40:53 +00:00
1e9d83f014 BaseInventory: validate given array in setContents() (#5391) 2022-11-07 13:09:05 +00:00
6153a2ac70 Merge remote-tracking branch 'origin/stable' into next-minor 2022-11-04 20:51:40 +00:00
ed452b9ccd Scrub PHPStan baselines 2022-11-04 20:51:22 +00:00
c19880e045 bootstrap: fix PHPStan error 2022-11-04 20:50:27 +00:00
cdbdcb5d67 Merge branch 'stable' into next-minor 2022-11-04 20:44:28 +00:00
29301614e8 Remove dead comments (#5389) 2022-11-04 20:23:56 +00:00
2fdc46c165 PHPStan 1.9 features 2022-11-04 20:23:34 +00:00
bfd1b2c635 PHPStan 1.9.1 2022-11-04 18:28:07 +00:00
1671405cd0 Merge branch 'stable' into next-minor 2022-11-02 16:03:30 +00:00
fe982c697b Durable: reset durability when overstacked items are broken
this is not really defined behaviour, but it makes more sense than the current behaviour, which makes the tool unbreakable unintentionally.

fixes #5378
2022-11-02 15:42:44 +00:00
1572b31b8d FormattedCommandAlias: do not fill empty strings for missing placeholder arguments
this is pretty much always going to cause unexpected behaviour, as most execute() implementations don't expect empty strings, and it can also pad the args with dummy entries, breaking argument count requirements (e.g. aliasing say  and using the alias with no arguments will confuse the target command).

Instead:
- Drop arguments that cannot be resolved (leave them unspecified)
- If they are at the end of the argument sequence, this is OK - it will behave the same as if some optional arguments weren't specified.
- If they are in the middle of the argument sequence, this will generate an error - this is preferable to having the target invoked with an empty string, which might cause unexpected behaviour.

fixes #5379
2022-11-02 15:02:29 +00:00
b6f6671a81 Merge branch 'stable' into next-minor 2022-10-31 15:34:24 +00:00
6da467b142 Updated composer dependencies 2022-10-31 15:27:56 +00:00
44af519cd6 SpawnResponsePacketHandler: silence PlayerAuthInputPacket debug spam (#5368) 2022-10-30 19:24:26 +00:00
fb31e6085e StatusCommand: fix condition order for TPS colour (#5366) 2022-10-26 23:26:55 +01:00
e4548da173 4.10.1 is next 2022-10-26 01:19:08 +01:00
0d5287bf0b Release 4.10.0 2022-10-26 01:19:02 +01:00
a9361b3f8b Changes for 1.19.40 2022-10-25 23:11:41 +01:00
6e4c62744e Bump phpstan/phpstan from 1.8.10 to 1.8.11 (#5364)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.8.10 to 1.8.11.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.9.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.8.10...1.8.11)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-25 19:55:01 +01:00
9a0ead6deb Validate paths in --data and --plugins
closes #2861
2022-10-21 14:28:22 +01:00
d74824c8d5 Correctly use Command->getLabel() instead of Command->getName()
getName() essentially serves as an ID for the command for CommandExecutors. It has no other sane use case.

Since it's not unique (multiple commands with the same name may be registered, and the fallback alias will be used on conflict), it cannot be used for array indexing. It's also not correct to use it for any display purpose, since the command may not be able to be invoked by its 'name' if there was a conflict.

There is an open debate about what to do with getName() and the wider CommandExecutor ecosystem, but that's a topic for another discussion.

closes #5344
2022-10-18 19:34:12 +01:00
d4eb73abe9 Bump phpstan/phpstan from 1.8.9 to 1.8.10 (#5351)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.8.9 to 1.8.10.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.9.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.8.9...1.8.10)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-18 16:56:55 +01:00
7864294336 Merge branch 'stable' into next-minor 2022-10-16 16:53:14 +01:00
2a910c1cc2 World: more minor documentation improvements 2022-10-16 16:50:42 +01:00
cd04a3db2e World: ensure that addParticle/addSound don't send stuff to players who are not in range, even when an array of targets is given
closes #5347
2022-10-16 16:45:52 +01:00
572def9245 World: Improve quality of type information 2022-10-16 16:21:59 +01:00
20f5bed926 Bump phpstan/phpstan from 1.8.8 to 1.8.9 (#5341)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.8.8 to 1.8.9.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.9.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.8.8...1.8.9)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-16 15:36:01 +01:00
14d17a9546 Remove Erroneous documentation (#5346) 2022-10-16 15:21:35 +01:00
b74c092d9b Server: removed reference to nonexistent API method 2022-10-15 15:06:43 +01:00
7bcc663b60 Migrate core code to using symfony/filesystem
webmozart/path-util is retained for plugin compatibility, but is dropped in 5.0
2022-10-14 21:51:29 +01:00
b3bda788d9 Server: Deprecated getPlayerByPrefix()
this is only used for commands anyway, but we can't get rid of it yet.
2022-10-14 21:45:09 +01:00
2cc8a56e68 Server: fixed borked serverCommand timings 2022-10-14 20:02:44 +01:00
57deb60355 Merge branch 'stable' into next-minor 2022-10-13 21:03:50 +01:00
92e47b98f8 Updated DevTools submodule to pmmp/DevTools@bd0fa048da 2022-10-13 21:02:39 +01:00
b84c110819 Fix CS according to newest php-cs-fixer 2022-10-13 21:00:57 +01:00
4fadb63f67 Bump build/php from 50062b5 to 14ed8ea (#5337)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `50062b5` to `14ed8ea`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](50062b5861...14ed8eaadd)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-13 16:29:01 +01:00
c83f0896ac Bump ncipollo/release-action from 1.10.0 to 1.11.1 (#5319)
Bumps [ncipollo/release-action](https://github.com/ncipollo/release-action) from 1.10.0 to 1.11.1.
- [Release notes](https://github.com/ncipollo/release-action/releases)
- [Commits](https://github.com/ncipollo/release-action/compare/v1.10.0...v1.11.1)

---
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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-13 13:07:03 +01:00
0d29a138fb Bump docker/build-push-action from 3.1.1 to 3.2.0 (#5336)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.1.1...v3.2.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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-13 13:06:25 +01:00
421379fc77 SplashPotion: Use World::getCollidingEntities() instead of World::getNearbyEntities() (#5326)
fixes spectator players receiving effects from splash potions
2022-10-11 22:57:35 +01:00
293cea7714 4.9.2 is next 2022-10-11 22:47:58 +01:00
15645759e9 Release 4.9.1 2022-10-11 22:47:54 +01:00
6ae7cb288e Merge remote-tracking branch 'origin/stable' into next-minor 2022-10-11 21:59:40 +01:00
7df2719fce Update Composer dependencies 2022-10-11 21:57:22 +01:00
10b8dcfdd1 Bump phpstan/phpstan from 1.8.6 to 1.8.8 (#5324)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.8.6 to 1.8.8.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.9.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.8.6...1.8.8)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-07 11:43:39 +01:00
c1fbac412e event: ensure that modifications to items expected to be readonly have no effect
this isn't a very glorious fix, but it's the best I have for now.
2022-10-07 11:33:14 +01:00
3feaa18f6c DelegateInventory: use WeakReference and __destruct to clean up inventory listener
this is more sane, since it allows the delegate to be reused without unexpected behaviour.
2022-09-30 15:12:37 +01:00
41970feb57 Entity: Fire EntitySpawnEvent/ItemSpawnEvent on the first entity tick, instead of in the constructor (#5314)
This allows plugins to modify the entity via setters in EntitySpawnEvent without their changes getting overwritten by setter calls directly after the 'new YourEntity' statement.

As well as benefiting plugins, this also clears a path for a BC-breaking change in PM5 (to have the programmer use addEntity() to spawn entities, instead of the constructor doing it, which will improve on a number of data handling aspects).

fixes #4973

This targets next-minor because it has some side effects on plugins that depended on the old behaviour, such as VanillaHopper, so it's not suitable for a patch release.
2022-09-29 22:30:12 +01:00
cd4bb91676 Living: alter eye height so the player doesn't drown on the surface of water when swimming
fixes #4989
2022-09-29 00:15:07 +01:00
2be527060f Sign: Fixed desync of colour and glowing state when using dye on signs
fixes #4932
2022-09-28 23:34:08 +01:00
6f68c6d8a0 Melon: extend Solid instead of Transparent, fixes #5050 2022-09-28 23:07:53 +01:00
ac16378410 Silence pre-spawn PlayerAuthInputPacket debug spam 2022-09-28 21:58:23 +01:00
1f9dfa77bf PreSpawnPacketHandler: emit a separate debug message for sending creative data 2022-09-28 21:58:23 +01:00
0c7f8470b9 Avoid repeated strtolower usages in a couple of places 2022-09-28 21:30:06 +01:00
fc56c041f3 Correct knockback from explosions (#5161) 2022-09-28 21:09:07 +01:00
d6bbf8217d ResourcePackManager: avoid repeated operation 2022-09-28 20:57:17 +01:00
22486dd75e Mushroom: check the light for placement, unless placed on mycelium or podzol (#5054)
The previous behaviour was inconsistent with vanilla.
2022-09-28 18:41:23 +01:00
37ec1193ea Update PHPStan baselines 2022-09-28 18:34:01 +01:00
bda0ca23b4 Living: deprecated hasLineOfSight() 2022-09-28 17:34:51 +01:00
b21cd82e94 Allow specifying a key for encrypted resource packs (#5297) 2022-09-28 17:27:33 +01:00
1c7b1e9e5d Fix sugarcane behaviour on fertilizers (#4930) 2022-09-28 16:38:24 +01:00
b87e4d8bd3 Introduce and use TextFormat::addBase() (#5268)
This function adds "base" format to a string. The given formats are inserted directly after any RESET code in the sequence.

An example of where this is needed is in the logger.

Without this change, the following code:
$logger->notice("I'm a " . TextFormat::RED . "special" . TextFormat::RESET . " cookie");

causes the "cookie" part of the message to show as grey, instead of the expected aqua for NOTICE level messages.

There are also many workarounds for this problem throughout the server, mostly in command outputs, being forced to use WHITE instead of RESET to avoid breaking the logger output.
2022-09-28 16:13:11 +01:00
86a2f8e360 Merge branch 'stable' into next-minor 2022-09-28 01:01:51 +01:00
def2f8c145 InventoryManager: ensure the windowID is valid before attempting to remove any window
this is currently a harmless bug, since remove() isn't currently doing any heavy lifting.
2022-09-28 01:01:42 +01:00
ed7c95549d PreSpawnPacketHandler: add a bunch of debug messages
this is useful for observing timings during first spawn, so that performance issues can be more easily spotted.
2022-09-27 21:08:31 +01:00
cfb0cad7e0 Console commands now write to stdout directly, instead of being fed through the logger
this has a number of implications:
- Console command outputs are now (obviously) not logged. This is consistent with every other type of command sender, be it RCON, players, or anything else.
- The assumption that the console command sender must be able to see the logger output is now broken, since the command sender can receive output separately from the logs.

In the future, it might be desirable to send the console command output to stderr instead of stdout, so that stdout can be silenced while still allowing commands to be used.

closes #2543
2022-09-27 21:03:03 +01:00
83e5b0adb6 ConsoleCommandSender is no longer responsible for forwarding broadcast messages to the logger (#5311)
This is a step towards implementing #2543.
2022-09-27 20:58:33 +01:00
4650a3bb22 CONTRIBUTING: added a table of what types of changes are accepted by what branches 2022-09-27 18:13:59 +01:00
5e5661de75 Play burp sound when consuming a FoodSource (#5158) 2022-09-27 17:21:55 +01:00
e2f1b10165 Bump phpunit/phpunit from 9.5.24 to 9.5.25 (#5308)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.5.24 to 9.5.25.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/main/ChangeLog-9.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.5.24...9.5.25)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-27 17:18:58 +01:00
455f9fa92e Bump tests/plugins/DevTools from bd0fa04 to 95921c6 (#5307)
Bumps [tests/plugins/DevTools](https://github.com/pmmp/DevTools) from `bd0fa04` to `95921c6`.
- [Release notes](https://github.com/pmmp/DevTools/releases)
- [Commits](bd0fa048da...95921c6d87)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-27 17:18:47 +01:00
dec188d4ad TaskHandler: mark some public methods as @internal (#5310)
closes #5309
2022-09-27 17:17:29 +01:00
2db3498891 Updated DevTools submodule to pmmp/DevTools@bd0fa048da 2022-09-24 21:26:42 +01:00
a7dfa0907c Merge branch 'stable' into next-minor 2022-09-24 18:07:56 +01:00
f448b2e685 Block: Improve documentation for a whole bunch of methods 2022-09-24 18:06:46 +01:00
6a0c54f850 Block: Relocate and document addVelocityToEntity()
maybe we should consider merging this with onEntityInside(), since they are both called for the same reasons? ...
2022-09-24 17:32:02 +01:00
77a18d0aea Block: add documentation for getFrictionFactor()
has no one ever questioned the fact that a higher _friction_ factor _reduces_ the block's friction???
2022-09-24 17:05:38 +01:00
140a809c40 Block: improve documentation of hasEntityCollision() and onEntityInside() 2022-09-24 17:04:42 +01:00
cb7c136035 Added documentation for some base Block classes 2022-09-24 16:54:21 +01:00
83a136a176 EntityFactory: Avoid code duplication on validation of creation functions (#5294) 2022-09-24 13:55:24 +01:00
3f7d8a3777 Bump phpstan/phpstan-strict-rules from 1.4.3 to 1.4.4 (#5300)
Bumps [phpstan/phpstan-strict-rules](https://github.com/phpstan/phpstan-strict-rules) from 1.4.3 to 1.4.4.
- [Release notes](https://github.com/phpstan/phpstan-strict-rules/releases)
- [Commits](https://github.com/phpstan/phpstan-strict-rules/compare/1.4.3...1.4.4)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-24 13:45:39 +01:00
Ali
3c55db531d HealthBoostEffect: Ensure that current health is within limits after reducing max health on removal(#5303) 2022-09-24 13:45:12 +01:00
93d4475111 Bump phpstan/phpstan from 1.8.5 to 1.8.6 (#5299)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.8.5 to 1.8.6.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.8.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.8.5...1.8.6)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-23 11:42:50 +01:00
e4fc523251 Introduce Player::sendToastNotification() (#5102) 2022-09-23 11:37:08 +01:00
7804172846 Player: added API documentation for some functions 2022-09-21 14:46:04 +01:00
7d29ac8293 Merge branch 'stable' into next-minor 2022-09-21 14:21:27 +01:00
481bda8cd5 Bump build/php from cf79c01 to 50062b5 (#5293)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `cf79c01` to `50062b5`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](cf79c01722...50062b5861)

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-21 12:43:06 +01:00
d1c75da14b Player: lock flight state in spectator mode
players should not be able to stop flying in spectator mode
2022-09-20 21:53:51 +01:00
89e29448ee Merge branch 'stable' into next-minor 2022-09-20 20:18:06 +01:00
66e70e5b0e 4.9.1 is next 2022-09-20 20:09:38 +01:00
9f97654f6f Update InstantDamage and Regeneration values (#5279) 2022-09-15 20:26:37 +01:00
441b06f6c7 Merge branch 'stable' into next-minor 2022-09-15 12:44:53 +01:00
ffb3af3e0d fix CS 2022-09-02 00:59:58 +01:00
b3f03d7ae6 Poll console on the main thread, instead of using a separate thread
There's no need to use an extra thread for this, since there's no concern of a socket getting stuck in a blocking read.

This is one less thing that can go wrong because of pthreads.
2022-09-02 00:58:49 +01:00
2585160ca2 ConsoleReaderChildProcess: Commit suicide if the parent process dies and doesn't clean up
This happens if the main server process was forcibly killed, e.g. by the kill command on Linux, or taskkill/TaskManager on Windows.

Previously, the process would stick around as a zombie, which messed up terminals in some cases (e.g. git bash), though even having zombies with no side effects is bad enough.
2022-09-02 00:25:31 +01:00
14d3e6c7d5 Allow disabling the console reader via pocketmine.yml
Useful to save resources on headless servers where the console is never used (e.g. hosted server, Docker, etc.)
2022-09-01 23:43:54 +01:00
65ec318c30 PluginManager: Ensure dependents are disabled before dependencies in disablePlugins() (#5227)
this could later be expanded to disablePlugin() to make this disable order mandatory, to provide certainty for plugin devs.

Alternative solutions to this include disabling plugins in the opposite order that they were enabled in, but this doesn't allow for random plugin disables. This way seemed to make sense.
2022-08-31 18:43:30 +01:00
a25cb3741a Limit valid supporting blocks of dead bush (#5055) 2022-08-31 02:18:18 +01:00
5b89833d5c Merge branch 'stable' into next-minor 2022-08-27 17:27:15 +01:00
c16893cbac Merge branch 'stable' into next-minor 2022-08-25 19:25:19 +01:00
5d5366a7c8 Merge branch 'stable' into next-minor 2022-08-21 19:11:59 +01:00
d6af2b12f4 Merge branch 'complex-inventory-rewrite' into next-minor 2022-08-18 17:30:00 +01:00
ad2d59923c Merge branch 'stable' into next-minor 2022-08-18 17:06:15 +01:00
792c1b62b7 Introduce and use TransactionBuilder for inventory evacuations 2022-08-18 17:04:12 +01:00
e90abecf38 Rewrite InventoryManager handling of complex mapped inventories
this turned out to be necessary when dealing with the ItemStackRequest system.
2022-08-17 14:42:30 +01:00
4d34885b15 Merge branch 'stable' into next-minor 2022-08-14 20:11:10 +01:00
f7ab0a3b92 Merge branch 'stable' into next-minor 2022-08-14 18:37:56 +01:00
16ed16722a Merge branch 'stable' into next-minor 2022-07-24 21:21:37 +01:00
42f9336f7a Split packet receive timings into decode and handle subcomponents 2022-07-24 21:16:52 +01:00
2940547026 Eliminate repeated calls to Position->getWorld()
as well as improving readability, it also improves performance in some areas.
2022-07-20 20:44:05 +01:00
24e72ec109 ContainerTrait: improve performance of block destroy hook
this was creating useless vector3s for every iteration, as well as repeatedly invoking Position->getWorld() for no reason.
2022-07-20 20:39:37 +01:00
dbc0b9634b Merge branch 'stable' into next-minor 2022-07-19 20:35:47 +01:00
040516054f Merge branch 'stable' into next-minor 2022-07-19 20:20:10 +01:00
4e3964ffce Armor: added clearCustomColor() 2022-07-16 15:10:07 +01:00
93254523e6 Merge branch 'stable' into next-minor 2022-07-14 22:04:38 +01:00
e00f8e3a32 Merge branch 'stable' into next-minor 2022-07-14 20:59:06 +01:00
e2855aadff Simplify handling of broken transactions for crafting and friends
this allows stuff like smithing tables to work without needing any extra hacks.

Implementing enchanting or anvils would require some extra work, but I don't plan to implement those under the legacy transaction system anyway.
2022-07-14 20:50:06 +01:00
4d6ec66270 Merge branch 'stable' into next-minor 2022-07-14 19:54:38 +01:00
f1a63098bd Merge branch 'stable' into next-minor 2022-07-14 16:06:15 +01:00
4b1052022c Merge branch 'stable' into next-minor 2022-07-13 17:00:58 +01:00
5a8983dd81 Merge branch 'stable' into next-minor 2022-07-06 16:17:04 +01:00
38651fde74 Merge branch 'stable' into next-minor 2022-06-29 16:53:31 +01:00
63ee03a7be Merge branch 'stable' into next-minor 2022-06-24 01:40:39 +01:00
088a2e478c Merge branch 'stable' into next-minor 2022-06-24 01:32:53 +01:00
35fd71eddf Fix CS in VersionInfo
this got overlooked because I just nuked the changes coming in from stable and didn't notice the formatting changes.
2022-06-07 20:26:02 +01:00
be168beba0 Merge branch 'stable' into next-minor 2022-06-07 19:55:58 +01:00
4b73bedd57 Bump version to 4.6.0+dev 2022-06-01 19:45:20 +01:00
298 changed files with 61080 additions and 2101 deletions

View File

@ -6,6 +6,12 @@ updates:
interval: daily
time: "10:00"
open-pull-requests-limit: 10
ignore:
#only allow patch updates for locale-data - this has to be updated manually due to codegen
- dependency-name: pocketmine/locale-data
update-types:
- "version-update:semver-major"
- "version-update:semver-minor"
- package-ecosystem: gitsubmodule
directory: "/"

View File

@ -46,7 +46,7 @@ jobs:
run: echo ::set-output name=NAME::$(echo "${GITHUB_REPOSITORY,,}")
- name: Build image for tag
uses: docker/build-push-action@v3.1.1
uses: docker/build-push-action@v4.0.0
with:
push: true
context: ./pocketmine-mp
@ -59,7 +59,7 @@ jobs:
- name: Build image for major tag
if: steps.channel.outputs.CHANNEL == 'stable'
uses: docker/build-push-action@v3.1.1
uses: docker/build-push-action@v4.0.0
with:
push: true
context: ./pocketmine-mp
@ -72,7 +72,7 @@ jobs:
- name: Build image for minor tag
if: steps.channel.outputs.CHANNEL == 'stable'
uses: docker/build-push-action@v3.1.1
uses: docker/build-push-action@v4.0.0
with:
push: true
context: ./pocketmine-mp
@ -85,7 +85,7 @@ jobs:
- name: Build image for latest tag
if: steps.channel.outputs.CHANNEL == 'stable'
uses: docker/build-push-action@v3.1.1
uses: docker/build-push-action@v4.0.0
with:
push: true
context: ./pocketmine-mp

View File

@ -18,8 +18,9 @@ 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) : array{
function generateDiscordEmbed(string $version, string $channel, string $description, string $detailsUrl, string $sourceUrl, string $pharDownloadUrl, string $buildLogUrl, int $newsPingRoleId) : array{
return [
"content" => "<@&$newsPingRoleId> New PocketMine-MP release: $version ($channel)",
"embeds" => [
[
"title" => "New PocketMine-MP release: $version ($channel)",
@ -35,11 +36,11 @@ DESCRIPTION,
];
}
if(count($argv) !== 5){
fwrite(STDERR, "Required arguments: github repo, version, API token\n");
if(count($argv) !== 6){
fwrite(STDERR, "Required arguments: github repo, version, API token, webhook URL, ping role ID\n");
exit(1);
}
[, $repo, $tagName, $token, $hookURL] = $argv;
[, $repo, $tagName, $token, $hookURL, $newsPingRoleId] = $argv;
$result = Internet::getURL('https://api.github.com/repos/' . $repo . '/releases/tags/' . $tagName, extraHeaders: [
'Authorization: token ' . $token
@ -86,7 +87,7 @@ $buildLogUrl = $buildInfoJson["build_log_url"];
$description = $releaseInfoJson["body"];
$discordPayload = generateDiscordEmbed($buildInfoJson["base_version"], $buildInfoJson["channel"], $description, $detailsUrl, $sourceUrl, $pharDownloadUrl, $buildLogUrl);
$discordPayload = generateDiscordEmbed($buildInfoJson["base_version"], $buildInfoJson["channel"], $description, $detailsUrl, $sourceUrl, $pharDownloadUrl, $buildLogUrl, (int) $newsPingRoleId);
$response = Internet::postURL(
$hookURL,

View File

@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.21.2
uses: shivammathur/setup-php@2.24.0
with:
php-version: 8.0
@ -35,4 +35,4 @@ jobs:
run: echo ::set-output name=TAG_NAME::$(echo "${{ github.ref }}" | sed 's{^refs/tags/{{')
- name: Run webhook post script
run: php .github/workflows/discord-release-embed.php ${{ github.repository }} ${{ steps.tag-name.outputs.TAG_NAME }} ${{ github.token }} ${{ secrets.DISCORD_RELEASE_WEBHOOK }}
run: php .github/workflows/discord-release-embed.php ${{ github.repository }} ${{ steps.tag-name.outputs.TAG_NAME }} ${{ github.token }} ${{ secrets.DISCORD_RELEASE_WEBHOOK }} ${{ secrets.DISCORD_NEWS_PING_ROLE_ID }}

View File

@ -18,7 +18,7 @@ jobs:
submodules: true
- name: Setup PHP
uses: shivammathur/setup-php@2.21.2
uses: shivammathur/setup-php@2.24.0
with:
php-version: 8.0
@ -55,6 +55,8 @@ jobs:
echo ::set-output name=MCPE_VERSION::$(php -r 'require "vendor/autoload.php"; echo \pocketmine\network\mcpe\protocol\ProtocolInfo::MINECRAFT_VERSION_NETWORK;')
echo ::set-output name=PM_VERSION_SHORT::$(php -r 'require "vendor/autoload.php"; $v = explode(".", \pocketmine\VersionInfo::BASE_VERSION); array_pop($v); echo implode(".", $v);')
echo ::set-output name=PM_VERSION_MD::$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\VersionInfo::BASE_VERSION);')
echo ::set-output name=CHANGELOG_SUFFIX::$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "" : "-" . \pocketmine\VersionInfo::BUILD_CHANNEL;')
echo ::set-output name=PRERELEASE::$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "false" : "true";')
- 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
@ -69,15 +71,16 @@ jobs:
${{ github.workspace }}/build_info.json
- name: Create draft release
uses: ncipollo/release-action@v1.10.0
uses: ncipollo/release-action@v1.12.0
with:
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
commit: ${{ github.sha }}
draft: true
prerelease: ${{ steps.get-pm-version.outputs.PRERELEASE }}
name: PocketMine-MP ${{ steps.get-pm-version.outputs.PM_VERSION }}
tag: ${{ steps.get-pm-version.outputs.PM_VERSION }}
token: ${{ secrets.GITHUB_TOKEN }}
body: |
**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 }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
Please see the [changelogs](${{ github.server_url }}/${{ github.repository }}/blob/${{ steps.get-pm-version.outputs.PM_VERSION }}/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}${{ steps.get-pm-version.outputs.CHANGELOG_SUFFIX }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.

View File

@ -13,14 +13,15 @@ jobs:
strategy:
matrix:
image: [ubuntu-20.04]
php: [8.0.23, 8.1.10]
php: [8.0.28, 8.1.16, 8.2.3]
steps:
- name: Build and prepare PHP cache
uses: pmmp/setup-php-action@82a44d659bf5046612c69f036af3e14dc32e3fa8
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "4"
phpstan:
name: PHPStan analysis
@ -31,16 +32,17 @@ jobs:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: [8.0.23, 8.1.10]
php: [8.0.28, 8.1.16, 8.2.3]
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: pmmp/setup-php-action@82a44d659bf5046612c69f036af3e14dc32e3fa8
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "4"
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
@ -69,16 +71,17 @@ jobs:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: [8.0.23, 8.1.10]
php: [8.0.28, 8.1.16, 8.2.3]
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: pmmp/setup-php-action@82a44d659bf5046612c69f036af3e14dc32e3fa8
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "4"
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
@ -107,7 +110,7 @@ jobs:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: [8.0.23, 8.1.10]
php: [8.0.28, 8.1.16, 8.2.3]
steps:
- uses: actions/checkout@v3
@ -115,10 +118,11 @@ jobs:
submodules: true
- name: Setup PHP
uses: pmmp/setup-php-action@82a44d659bf5046612c69f036af3e14dc32e3fa8
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "4"
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
@ -147,16 +151,17 @@ jobs:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: [8.0.23, 8.1.10]
php: [8.0.28, 8.1.16, 8.2.3]
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: pmmp/setup-php-action@82a44d659bf5046612c69f036af3e14dc32e3fa8
uses: pmmp/setup-php-action@6dd74c145250109942b08fc63cd5118edd2fd256
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "4"
- name: Install Composer
run: curl -sS https://getcomposer.org/installer | php
@ -180,6 +185,9 @@ jobs:
- name: Regenerate KnownTranslation APIs
run: php build/generate-known-translation-apis.php
- name: Regenerate BedrockData available files constants
run: php build/generate-bedrockdata-path-consts.php
- name: Verify code is unchanged
run: |
git diff
@ -195,10 +203,12 @@ jobs:
- uses: actions/checkout@v3
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.21.2
uses: shivammathur/setup-php@2.24.0
with:
php-version: 8.0
tools: php-cs-fixer:3.11
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run PHP-CS-Fixer
run: php-cs-fixer fix --dry-run --diff --ansi

View File

@ -8,7 +8,7 @@ jobs:
support:
runs-on: ubuntu-latest
steps:
- uses: dessant/support-requests@v2
- uses: dessant/support-requests@v3
with:
github-token: ${{ github.token }}
support-label: "Support request"

View File

@ -23,7 +23,8 @@ declare(strict_types=1);
const VERSIONS = [
"8.0",
"8.1"
"8.1",
"8.2"
];
$workflowFile = file_get_contents(__DIR__ . '/main.yml');

View File

@ -62,6 +62,11 @@
<option name="USE_TAB_CHARACTER" value="true" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="Shell Script">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="neon">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />

View File

@ -66,6 +66,9 @@ BODY,
],
'indentation_type' => true,
'logical_operators' => true,
'native_constant_invocation' => [
'scope' => 'namespaced'
],
'native_function_invocation' => [
'scope' => 'namespaced',
'include' => ['@all'],
@ -92,6 +95,12 @@ BODY,
],
'sort_algorithm' => 'alpha'
],
'phpdoc_align' => [
'align' => 'vertical',
'tags' => [
'param',
]
],
'phpdoc_line_span' => [
'property' => 'single',
'method' => null,

View File

@ -18,6 +18,32 @@ Larger contributions like feature additions should be preceded by a [Change Prop
## Other things you'll need
- [git](https://git-scm.com/)
## Choosing a target branch
PocketMine-MP has three primary branches of development.
| Type of change | `stable` | `minor-next` | `major-next` |
|:---------------|:--------:|:------------:|:------------:|
| Bug fixes | ✔️ | ✔️ | ✔️ |
| Improvements to API docs | ✔️ | ✔️ | ✔️ |
| Cleaning up code | ❌ | ✔️ | ✔️ |
| Changing code formatting or style | ❌ | ✔️ | ✔️ |
| Addition of new core features | ❌ | 🟡 Only if non-disruptive | ✔️ |
| Changing core behaviour (e.g. making something use threads) | ❌ | ✔️ | ✔️ |
| Addition of new configuration options | ❌ | 🟡 Only if optional | ✔️ |
| Addition of new API classes, methods or constants | ❌ | ✔️ | ✔️ |
| Deprecating API classes, methods or constants | ❌ | ✔️ | ✔️ |
| Adding optional parameters to an API method | ❌ | ✔️ | ✔️ |
| Changing API behaviour | ❌ | 🟡 Only if backwards-compatible | ✔️ |
| Removal of API | ❌ | ❌ | ✔️ |
| Backwards-incompatible API change (e.g. renaming a method) | ❌ | ❌ | ✔️ |
### Notes
- **Non-disruptive** means that usage should not be significantly altered by the change.
- Examples of **non-disruptive** changes include adding new commands, or gameplay features like blocks and items.
- Examples of **disruptive** changes include changing the way the server is run, world format changes (since those require downtime for the user to convert their world).
- **API** includes all public and protected classes, functions and constants (unless marked as `@internal`).
- Private members are not part of the API, **unless in a trait**.
## Making a pull request
The basic procedure to create a pull request is:
1. [Fork the repository on GitHub](https://github.com/pmmp/PocketMine-MP/fork). This gives you your own copy of the repository to make changes to.

View File

@ -0,0 +1,128 @@
<?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\build\generate_bedrockdata_path_consts;
use Symfony\Component\Filesystem\Path;
use function dirname;
use function fclose;
use function fopen;
use function fwrite;
use function is_file;
use function scandir;
use function str_replace;
use function strtoupper;
use const PHP_EOL;
use const pocketmine\BEDROCK_DATA_PATH;
use const SCANDIR_SORT_ASCENDING;
use const STDERR;
require dirname(__DIR__) . '/vendor/autoload.php';
function constantify(string $permissionName) : string{
return strtoupper(str_replace([".", "-"], "_", $permissionName));
}
$files = scandir(BEDROCK_DATA_PATH, SCANDIR_SORT_ASCENDING);
if($files === false){
fwrite(STDERR, "Couldn't find any files in " . BEDROCK_DATA_PATH . PHP_EOL);
exit(1);
}
$consts = [];
foreach($files as $file){
if($file === '.' || $file === '..'){
continue;
}
if($file[0] === '.'){
continue;
}
$path = Path::join(BEDROCK_DATA_PATH, $file);
if(!is_file($path)){
continue;
}
foreach([
'README.md',
'LICENSE',
'composer.json',
] as $ignored){
if($file === $ignored){
continue 2;
}
}
$consts[] = $file;
}
$output = fopen(dirname(__DIR__) . '/src/data/bedrock/BedrockDataFiles.php', 'wb');
if($output === false){
fwrite(STDERR, "Couldn't open output file" . PHP_EOL);
exit(1);
}
fwrite($output, <<<'HEADER'
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\data\bedrock;
use const pocketmine\BEDROCK_DATA_PATH;
final class BedrockDataFiles{
private function __construct(){
//NOOP
}
HEADER
);
foreach($consts as $constName => $fileName){
fwrite($output, "\tpublic const " . constantify($fileName) . " = BEDROCK_DATA_PATH . '/$fileName';\n");
}
fwrite($output, "}\n");
fclose($output);
echo "Done. Don't forget to run CS fixup after generating code.\n";

View File

@ -25,7 +25,7 @@ namespace pocketmine\build\generate_known_translation_apis;
use pocketmine\lang\Translatable;
use pocketmine\utils\Utils;
use Webmozart\PathUtil\Path;
use Symfony\Component\Filesystem\Path;
use function array_map;
use function count;
use function dirname;

View File

@ -36,9 +36,10 @@ use function ksort;
use function mb_strtoupper;
use function preg_match;
use function sprintf;
use function str_ends_with;
use function str_replace;
use function substr;
use const SORT_STRING;
use const STDERR;
if(count($argv) !== 2){
fwrite(STDERR, "Provide a path to process\n");
@ -120,7 +121,7 @@ require dirname(__DIR__) . '/vendor/autoload.php';
if(is_dir($argv[1])){
/** @var string $file */
foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($argv[1], \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::CURRENT_AS_PATHNAME)) as $file){
if(substr($file, -4) !== ".php"){
if(!str_ends_with($file, ".php")){
continue;
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\build\make_release;
use pocketmine\utils\Filesystem;
use pocketmine\utils\Utils;
use pocketmine\utils\VersionString;
use pocketmine\VersionInfo;
@ -30,17 +31,18 @@ use function array_keys;
use function array_map;
use function dirname;
use function fgets;
use function file_get_contents;
use function file_put_contents;
use function fwrite;
use function getopt;
use function is_string;
use function max;
use function preg_match;
use function preg_replace;
use function sleep;
use function sprintf;
use function str_pad;
use function strlen;
use function strtolower;
use function system;
use const STDERR;
use const STDIN;
@ -50,7 +52,7 @@ use const STR_PAD_LEFT;
require_once dirname(__DIR__) . '/vendor/autoload.php';
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev, string $channel) : void{
$versionInfo = Utils::assumeNotFalse(file_get_contents($versionInfoPath), $versionInfoPath . " should always exist");
$versionInfo = Filesystem::fileGetContents($versionInfoPath);
$versionInfo = preg_replace(
$pattern = '/^([\t ]*public )?const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
'$1const BASE_VERSION = "' . $newVersion . '";',
@ -102,22 +104,43 @@ function main() : void{
$filteredOpts[$optName] = $optValue;
}
$channel = $filteredOpts["channel"] ?? null;
if(isset($filteredOpts["current"])){
$currentVer = new VersionString($filteredOpts["current"]);
}else{
$currentVer = new VersionString(VersionInfo::BASE_VERSION);
}
if(isset($filteredOpts["next"])){
$nextVer = new VersionString($filteredOpts["next"]);
$nextVer = isset($filteredOpts["next"]) ? new VersionString($filteredOpts["next"]) : null;
$suffix = $currentVer->getSuffix();
if($suffix !== ""){
if($channel === "stable"){
fwrite(STDERR, "error: cannot release a suffixed build into the stable channel\n");
exit(1);
}
if(preg_match('/^([A-Za-z]+)(\d+)$/', $suffix, $matches) !== 1){
echo "error: invalid current version suffix \"$suffix\"; aborting\n";
exit(1);
}
$nextVer ??= new VersionString(sprintf(
"%u.%u.%u-%s%u",
$currentVer->getMajor(),
$currentVer->getMinor(),
$currentVer->getPatch(),
$matches[1],
((int) $matches[2]) + 1
));
$channel ??= strtolower($matches[1]);
}else{
$nextVer = new VersionString(sprintf(
$nextVer ??= new VersionString(sprintf(
"%u.%u.%u",
$currentVer->getMajor(),
$currentVer->getMinor(),
$currentVer->getPatch() + 1
));
$channel ??= "stable";
}
$channel = $filteredOpts["channel"] ?? VersionInfo::BUILD_CHANNEL;
echo "About to tag version $currentVer. Next version will be $nextVer.\n";
echo "$currentVer will be published on release channel \"$channel\".\n";

View File

@ -40,12 +40,13 @@ use function rtrim;
use function sprintf;
use function str_replace;
use function unlink;
use const DIRECTORY_SEPARATOR;
use const PHP_EOL;
require dirname(__DIR__) . '/vendor/autoload.php';
/**
* @param string[] $strings
* @param string[] $strings
*
* @return string[]
*/

53
changelogs/4.10.md Normal file
View File

@ -0,0 +1,53 @@
**For Minecraft: Bedrock Edition 1.19.40**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.10.0
Released 26th October 2022.
## General
- Added support for Minecraft: Bedrock Edition 1.19.40.
- Removed support for older versions.
## Fixes
- Fixed incorrect command descriptions showing in `/help` when multiple commands use the same name. Previously, the most recently registered command would show, even though it wouldn't actually be invoked.
- Fixed splash potions affecting players in spectator mode.
- Fixed `World->addParticle()` sending particles to players who couldn't possibly see them when a list of targets was used.
- Fixed `World->addSound()` sending sounds to players who couldn't possibly hear them when a list of targets was used.
## Documentation
- Improved type information available for various API methods in `World`.
# 4.10.1
Released 7th November 2022.
## Fixes
- Fixed spawning in the void if spawn terrain in a world is solid at the default spawn position.
- Fixed totems of undying activating when the player has 1 HP remaining.
- Fixed durable items such as tools becoming unbreakable when in stacks larger than 1. Now, the durability correctly resets when the tool breaks.
- TPS below 12 now correctly shows as red in `/status`. Previously, it showed as orange due to a condition ordering bug.
- Improved handling of missing arguments in user-defined `pocketmine.yml` command aliases. Previously, missing arguments would be filled with an empty string, which caused a variety of unexpected behaviour.
## Internals
- Added validation for the array given to `BaseInventory->setContents()` to ensure that it contains only `Item` instances.
- Silenced `PlayerAuthInputPacket` spam when the session is in the "spawn response" state.
- Updated to PHPStan 1.9.
# 4.10.2
Released 25th November 2022.
## Fixes
- Fixed crashes on macOS and Linux when using console colours without the `TERM` environment variable set.
- Fixed crashdumps not being generated when error messages contained invalid UTF-8 characters.
## Documentation
- Clarified documentation of caching behaviour for `Internet::getIP()`.
- Added and improved documentation for many `Inventory` methods.
- Rewritten documentation for `PlayerCreationEvent` with warnings and more detail.
## Internals
- Non-arrow projectile damage is now unscaled. Scaling according to velocity is only applied to arrows. This currently doesn't cause any observable change in behaviour, but is required for future additions.

92
changelogs/4.11-beta.md Normal file
View File

@ -0,0 +1,92 @@
**For Minecraft: Bedrock Edition 1.19.40**
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.11.0-BETA1
Released 7th November 2022.
## General
- Packet receive timings have now been split into two subcategories - Decode and Handle.
- Console command entry can now be disabled via the `console.enable-input` setting in `pocketmine.yml`.
- Best suited for headless servers (e.g. in a Docker container) where the console will never be used anyway.
- Disabling the console reader slightly reduces memory usage, because console reading currently requires an additional subprocess.
- Console command output now appears on the terminal only, and is not written to the log file.
- The output from console commands now appears with a `Command output |` prefix, instead of as a log message.
- Introduced validation for the `--data` and `--plugins` command line options.
- Encrypted resource packs are now supported, by means of adding a `.key` file alongside the pack in the `resource_packs` folder.
- e.g. `MyEncryptedPack.zip` -> `MyEncryptedPack.zip.key`
## Gameplay
- Fixed supporting blocks of dead bush to be in line with vanilla.
- Sugarcane can now be grown using bonemeal on any part of the sugarcane. Previously, it only worked when used on the bottom block.
- Fixed modifier values for Instant Damage and Regeneration effects.
## API
### General
- Plugins are now always disabled before their dependencies, to ensure that they are able to shutdown properly (e.g. a core plugin depending on a database plugin may want to save data to a DB during `onDisable()`).
- [`webmozart/path-util`](https://packagist.org/packages/webmozart/path-util) has been deprecated, and will be dropped in favour of [`symfony/filesystem`](https://packagist.org/packages/symfony/filesystem) in PM5.
- To prepare for this change, simply replace any usage of `Webmozart\PathUtil\Path` with `Symfony\Component\Filesystem\Path`, which is available as a dependency in this release.
### `pocketmine`
- The following API methods are now deprecated:
- `Server->getPlayerByPrefix()`
### `pocketmine\entity`
- `EntitySpawnEvent` and `ItemSpawnEvent` are now fired on the first tick after the entity is added to the world. Previously, these events were called directly from the entity constructor, making it impossible to get properties like velocity which are often set after the entity is created.
- The following API methods are now deprecated:
- `Living->hasLineOfSight()`
### `pocketmine\item`
- The following new API methods have been added:
- `public Armor->clearCustomColor() : $this`
### `pocketmine\inventory\transaction`
- Introduced a `TransactionBuilder` class. This makes it less of a hassle to build an `InventoryTransaction` server-side, since the regular `Inventory` API methods can be used, rather than having to manually create `SlotChangeAction`s.
### `pocketmine\player`
- The following new API methods have been added:
- `public Player->sendToastNotification(string $title, string $body) : void` - makes a grey box appear at the top of the player's screen containing the specified message
### `pocketmine\utils`
- The following new API methods have been added:
- `public static TextFormat::addBase(string $baseFormat, string $string) : string` - used for coloured log messages, changes the base formatting of a string by inserting the given formatting codes after every RESET code
## Internals
- Improved performance of `ContainerTrait` dropping items on block destroy. (24e72ec109c1442b09558df89b6833cf2f2e0ec7)
- Avoid repeated calls to `Position->getWorld()` (use local variables). (2940547026db40ce76deb46e992870de3ead79ad)
- Revamped the way `InventoryManager` handles fake inventory slot mappings for stuff like crafting tables. (e90abecf38d9c57635fa0497514bba7e546a2469)
- Console polling is now done on the main thread (no longer a performance concern).
- Console reader subprocess should now automatically die if the server main process is killed, instead of persisting as a zombie.
- `ConsoleCommandSender` is no longer responsible for relaying broadcast messages to `MainLogger`. A new `BroadcastLoggerForwarder` has been added, which is subscribed to the appropriate server broadcast channels in order to relay messages. This ensures that chat messages and command audit messages are logged.
- `DelegateInventory` now uses `WeakReference` to track its inventory listener. This allows the delegate to be reused.
# 4.11.0-BETA2
Released 13th November 2022.
## Configuration
- The `chunk-ticking.per-tick` setting is now deprecated, and will be removed in a future release.
- The functionality of this setting has been removed, since it caused more problems than it solved.
- Setting it to zero will still disable chunk ticking (for now), but this should now be done by setting `chunk-ticking.tick-radius` to `0` instead.
## Gameplay
- Improved chunk random ticking:
- Removed the limit on chunks ticked per tick, and its associated config option is no longer respected.
- This change significantly improves crop and plant growth with large numbers of players, but may cause higher CPU usage.
- This limit was causing a linear decrease in chunk ticking speed with larger numbers of players, leading to worsened gameplay experience.
- Every chunk within the configured tick radius of a player will be ticked. Previously, chunks were randomly selected from the radius.
- Implemented Darkness effect.
## API
### `pocketmine\world`
- The following new API methods have been added:
- `public World->getChunkTickRadius() : int` - returns the world's simulation radius
- `public World->setChunkTickRadius(int $radius) : void` - sets the world's simulation radius
## Internals
- Non-arrow projectile damage is now unscaled. Scaling according to velocity is only applied to arrows. This currently doesn't cause any observable change in behaviour, but is required for future additions.

106
changelogs/4.11.md Normal file
View File

@ -0,0 +1,106 @@
**For Minecraft: Bedrock Edition 1.19.40**
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.11.0
Released 25th November 2022.
## General
- Packet receive timings have now been split into two subcategories - Decode and Handle.
- Console command entry can now be disabled via the `console.enable-input` setting in `pocketmine.yml`.
- Best suited for headless servers (e.g. in a Docker container) where the console will never be used anyway.
- Disabling the console reader slightly reduces memory usage, because console reading currently requires an additional subprocess.
- Console command output now appears on the terminal only, and is not written to the log file.
- The output from console commands now appears with a `Command output |` prefix, instead of as a log message.
- User-defined `pocketmine.yml` custom commands now use a generic description which makes clear the command is config-defined.
- Introduced validation for the `--data` and `--plugins` command line options.
- Encrypted resource packs are now supported, by means of adding a `.key` file alongside the pack in the `resource_packs` folder.
- e.g. `MyEncryptedPack.zip` -> `MyEncryptedPack.zip.key`
- The file must contain the raw key bytes, and must not end with a newline.
## Configuration
- The `chunk-ticking.per-tick` setting is now deprecated, and will be removed in a future release.
- The functionality of this setting has been removed, since it caused more problems than it solved.
- Setting it to zero will still disable chunk ticking (for now), but this should now be done by setting `chunk-ticking.tick-radius` to `0` instead.
## Gameplay
- Fixed supporting blocks of dead bush to be in line with vanilla.
- Sugarcane can now be grown using bonemeal on any part of the sugarcane. Previously, it only worked when used on the bottom block.
- Fixed missing sounds when adding, rotating, or removing items in item frames.
- Fixed modifier values for Instant Damage and Regeneration effects.
- Implemented Darkness effect.
- Improved chunk random ticking:
- Removed the limit on chunks ticked per tick, and its associated config option is no longer respected.
- This change significantly improves crop and plant growth with large numbers of players.
- This limit was causing a linear decrease in chunk ticking speed with larger numbers of players, leading to worsened gameplay experience.
- **Warning: This change will result in increased CPU usage if players are spread over a very large area.**
- Every chunk within the configured tick radius of a player will be ticked. Previously, chunks were randomly selected from the radius.
## API
### General
- Plugins are now always disabled before their dependencies, to ensure that they are able to shutdown properly (e.g. a core plugin depending on a database plugin may want to save data to a DB during `onDisable()`).
- [`webmozart/path-util`](https://packagist.org/packages/webmozart/path-util) has been deprecated, and will be dropped in favour of [`symfony/filesystem`](https://packagist.org/packages/symfony/filesystem) in PM5.
- To prepare for this change, simply replace any usage of `Webmozart\PathUtil\Path` with `Symfony\Component\Filesystem\Path`, which is available as a dependency in this release.
### `pocketmine`
- The following API methods are now deprecated:
- `Server->getPlayerByPrefix()`
### `pocketmine\entity`
- `EntitySpawnEvent` and `ItemSpawnEvent` are now fired on the first tick after the entity is added to the world. Previously, these events were called directly from the entity constructor, making it impossible to get properties like velocity which are often set after the entity is created.
- The following API methods are now deprecated:
- `Living->hasLineOfSight()`
### `pocketmine\event\block`
- The following new classes have been added:
- `BlockDeathEvent` - event called when coral or coral blocks die due to lack of water
### `pocketmine\item`
- The following new API methods have been added:
- `public Armor->clearCustomColor() : $this`
### `pocketmine\inventory\transaction`
- Introduced a `TransactionBuilder` class. This makes it less of a hassle to build an `InventoryTransaction` server-side, since the regular `Inventory` API methods can be used, rather than having to manually create `SlotChangeAction`s.
### `pocketmine\lang`
- The following new API methods have been added:
- `public Language->getAll() : array<string, string>`
### `pocketmine\player`
- The following new API methods have been added:
- `public Player->sendToastNotification(string $title, string $body) : void` - makes a grey box appear at the top of the player's screen containing the specified message
### `pocketmine\utils`
- The following new API methods have been added:
- `public static TextFormat::addBase(string $baseFormat, string $string) : string` - used for coloured log messages, changes the base formatting of a string by inserting the given formatting codes after every RESET code
### `pocketmine\world`
- The following new API methods have been added:
- `public World->getChunkTickRadius() : int` - returns the world's simulation radius
- `public World->setChunkTickRadius(int $radius) : void` - sets the world's simulation radius
### `pocketmine\world\sound`
- The following new classes have been added:
- `ItemFrameAddItemSound`
- `ItemFrameRemoveItemSound`
- `ItemFrameRotateItemSound`
## Internals
- Improved performance of `ContainerTrait` dropping items on block destroy. ([link](https://github.com/pmmp/PocketMine-MP/commits/24e72ec109c1442b09558df89b6833cf2f2e0ec7))
- Avoid repeated calls to `Position->getWorld()` (use local variables). ([link](https://github.com/pmmp/PocketMine-MP/commit/2940547026db40ce76deb46e992870de3ead79ad))
- Revamped the way `InventoryManager` handles fake inventory slot mappings for stuff like crafting tables. ([link](https://github.com/pmmp/PocketMine-MP/commit/e90abecf38d9c57635fa0497514bba7e546a2469))
- Inventories are now mapped on a per-slot basis. This means that more than one inventory can be mapped to the same window ID, which is necessary for correctly handling "UI" inventories like crafting tables.
- `InventoryManager->getWindow(int $windowId) : ?Inventory` is replaced by `locateWindowAndSlot` (see below).
- Added `InventoryManager->locateWindowAndSlot(int $windowId, int $netSlotId) : array{Inventory, int}` - accepts a window ID and absolute slot ID, and returns the associated inventory and the slot relative to the inventory's own start (for use with `getItem()` etc.).
- Slot offset mapping for "UI" inventories is now handled in `InventoryManager->createComplexSlotMapping()` instead of in `TypeConverter`.
- Console polling is now done on the main thread (no longer a performance concern). ([link](https://github.com/pmmp/PocketMine-MP/commit/b3f03d7ae645de67a54b7300c09b94eeca16298e))
- Console reader subprocess should now automatically die if the server main process is killed, instead of persisting as a zombie. ([link](https://github.com/pmmp/PocketMine-MP/commit/2585160ca2c4df5758b8b980331307402ff9f0fb))
- `ConsoleCommandSender` is no longer responsible for relaying broadcast messages to `MainLogger`. A new `BroadcastLoggerForwarder` has been added, which is subscribed to the appropriate server broadcast channels in order to relay messages. This ensures that chat messages and command audit messages are logged. ([link](https://github.com/pmmp/PocketMine-MP/commit/83e5b0adb6fa0dddec377182bb1c7945ac8f7820))
- `DelegateInventory` now uses `WeakReference` to track its inventory listener. This allows the delegate to be reused. ([link](https://github.com/pmmp/PocketMine-MP/commit/3feaa18f6c10c3a99c0deca75f57ec2d74b92ab4))
- Non-arrow projectile damage is now unscaled. Scaling according to velocity is only applied to arrows. This currently doesn't cause any observable change in behaviour, but is required for future additions.

119
changelogs/4.12.md Normal file
View File

@ -0,0 +1,119 @@
**For Minecraft: Bedrock Edition 1.19.50**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.12.0
Released 30th November 2022.
## General
- Added support for Minecraft: Bedrock Edition 1.19.50.
- Removed support for older versions.
# 4.12.1
Released 4th December 2022.
## Fixes
- Fixed items glitching when dragging a stack of items across the crafting grid (desync issues).
# 4.12.2
Released 15th December 2022.
## Fixes
- Folder used for plugins (optionally specified by `--plugins`) is no longer required to be writable.
- Fixed broken writable check for server data folder (`is_writable()` broken on NFS and similar filesystems).
- `Filesystem::createLockFile()` exceptions now include more information about why the lock file could not be created.
- Fixed client-side item predictions not being rolled back when cancelling events such as `PlayerItemUseEvent`.
## Dependencies
- Updated BedrockProtocol to [17.1.0](https://github.com/pmmp/BedrockProtocol/releases/tag/17.1.0+bedrock-1.19.50). This adds some missing `LevelSoundEvent` constants and fixes the values for `ContainerUIIds`.
# 4.12.3
Released 28th December 2022.
## Fixes
- Fixed unauthenticated connections taking up player count slots, preventing players from joining.
- Fixed a possible crash in `World->tickChunk()` when plugins unload chunks during some events.
- `/gamemode` will now report a failure to change game mode if the player is already in the requested game mode.
# 4.12.4
Released 3rd January 2023.
## Fixes
- Added workarounds for an active exploit being used to deny service to servers.
# 4.12.5
Released 6th January 2023.
## Fixes
- Removed a workaround for an old client bug in custom form responses. The code contained a denial-of-service vulnerability.
# 4.12.6
Released 7th January 2023.
## Changes
- Added a new security measure to `NetworkSession` to detect and ban players who flood the server with packets.
# 4.12.7
Released 8th January 2023.
## Fixes
- Fixed players getting kicked when the server lags for too long.
- Fixed players getting kicked when a debugging session is active and a breakpoint is hit.
# 4.12.8
Released 9th January 2023.
## Fixes
- Fixed players getting kicked during PvP.
- Fixed players randomly getting kicked on Windows (improper rate limit handling wrt. 15ms timer resolution).
# 4.12.9
Released 16th January 2023.
## Improvements
### Timings
- Added new timers:
- `Server Mid-Tick Processing` - time spent processing Snooze interrupts between ticks (e.g. incoming network packets)
- `Server Tick Update Cycle` - time spent processing regular per-tick updates (e.g. entity movement, world updates, etc.) (`Server->tick()`)
- `Full Server Tick` timer now counts the total of `Server Mid-Tick Processing` and `Server Tick Update Cycle`, which generates more accurate performance metrics.
- Previously, this timer only counted the time spent during regular per-tick updates, and the time recorded by `Server Mid-Tick Processing` was not included in the report at all.
## Fixes
- Fixed blocks such as pressure plates being able to be placed without the correct supporting blocks if the clicked block was solid.
- Pressure plates now self-destruct when the block below them is removed.
- Fixed being unable to place blocks by clicking on the side of a bell (when the click doesn't result in ringing the bell).
- Fixed various rotation-aware blocks (e.g. stairs) behaving incorrectly when placed by clicking on the side of a replaceable block (e.g. tall grass).
- Fixed banners being able to be placed on top of blocks such as skulls.
- Fixed server-side collision boxes of walls and glass (which should connect, but didn't). Note that wall connections still don't show client side - this just fixes the collision boxes.
- Fixed `PlayerInteractEvent` with `LEFT_CLICK` sometimes firing before `BlockBreakEvent` when breaking blocks.
## Other changes
- Increased packet batch budget for player sessions.
# 4.12.10
Released 18th January 2023.
## Fixes
- Fixed reported server load not including the time spent processing Snooze interrupts between ticks (e.g. incoming network packets).
- Fixed `Connection Handler` entry in timings report not including time spent receiving packets.
## Note about server load & performance
This version will report higher apparent server load than previous versions. The actual performance of the server is unchanged; the previous reported load was inaccurate.
These bugs have been present for nearly 5 years (ever since the first introduction of Snooze in 3.0.0).
# 4.12.11
Released 22nd January 2023.
## General
- Code is now tested and analysed using PHP 8.2 in addition to 8.1 and 8.0.
## Fixes
- Fixed pthreads 5.0.0 incorrectly being treated as compatible.
- Fixed deprecation errors on PHP 8.2.
## Documentation
- Updated documentation in `PlayerPreLoginEvent`.

94
changelogs/4.13-beta.md Normal file
View File

@ -0,0 +1,94 @@
**For Minecraft: Bedrock Edition 1.19.50**
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.13.0-BETA1
Released 18th January 2023.
## Gameplay
- Death message is now shown on the death screen when a player dies.
- Armour damage is now only increased if the armour reduced the damage taken.
- Implemented Swift Sneak enchantment.
- Fixed incorrect collision box calculation of walls and glass/bars when connected. Note: Client-side, wall connections are still broken; this only fixes projectile flight server-side.
## Performance
- Improved performance of chunk selection for chunk random ticking using a cache. This improves performance of chunk random ticking by 10-20%.
## Localization
- Added localized description for the `/dumpmemory` command.
## Permissions
- Added the following new core permissions:
- `pocketmine.command.effect.other` - allows the player to use the `/effect` command on other players (default operator only)
- `pocketmine.command.effect.self` - allows the player to use the `/effect` command on themselves (default operator only)
- `pocketmine.command.enchant.other` - allows the player to use the `/enchant` command on other players (default operator only)
- `pocketmine.command.enchant.self` - allows the player to use the `/enchant` command on themselves (default operator only)
- `pocketmine.command.gamemode.other` - allows the player to use the `/gamemode` command on other players (default operator only)
- `pocketmine.command.gamemode.self` - allows the player to use the `/gamemode` command on themselves (default operator only)
- `pocketmine.command.give.other` - allows the player to use the `/give` command on other players (default operator only)
- `pocketmine.command.give.self` - allows the player to use the `/give` command on themselves (default operator only)
- `pocketmine.command.spawnpoint.other` - allows the player to use the `/spawnpoint` command on other players (default operator only)
- `pocketmine.command.spawnpoint.self` - allows the player to use the `/spawnpoint` command on themselves (default operator only)
- `pocketmine.command.teleport.other` - allows the player to use the `/teleport` command on other players (default operator only)
- `pocketmine.command.teleport.self` - allows the player to use the `/teleport` command on themselves (default operator only)
- `pocketmine.command.title.other` - allows the player to use the `/title` command on other players (default operator only)
- `pocketmine.command.title.self` - allows the player to use the `/title` command on themselves (default operator only)
## Internals
- Decoupled `Player->sendMessage()` and `Player->sendTranslation()`.
- Refactored resource pack loading in `ResourcePackManager` to make it easier to understand.
- Client-aware translation processing has been moved to `NetworkSession` due to being client-specific.
- Replaced hardcoded strings with constants in various places.
- `NetworkSession` destructive cleanup is now deferred to the next session tick. This fixes various `InventoryManager` crashes when kicking players during events.
- Updated code using `strpos()` to use `str_starts_with()`, `str_ends_with()` and `str_contains()` where appropriate.
- Added documentation for some internal methods.
## API
### `pocketmine\command`
- The following new API methods have been added:
- `protected VanillaCommand->fetchPermittedPlayerTarget(...) : ?Player` - fetches a player target according to the given sender permissions, or null if not found or not permitted
### `pocketmine\entity`
- The following new API methods have been added:
- `public Living->getDisplayName() : string` - the name of the entity to be shown in death messages, commands etc.
### `pocketmine\event\world`
- The following new classes have been added:
- `WorldSoundEvent` - called when a sound is played in a world
- `WorldParticleEvent` - called when a particle is spawned in a world
### `pocketmine\item`
- The following new API methods have been added:
- `public Item->onInteractEntity(Player $player, Entity $entity, Vector3 $clickVector) : bool` - called when a player interacts with an entity with this item in hand
### `pocketmine\lang`
- `Language->translate()` and `Language->translateString()` no longer parse nested translation in the "base text". This was never intended behaviour, and didn't work beyond the first level anyway.
### `pocketmine\player`
- The following new interfaces have been added:
- `PlayerDataProvider` - implemented by classes which want to offer storage for player data
- The following new classes have been added:
- `DatFilePlayerDataProvider` - the default player data provider, which stores `.dat` files in the `players` folder
- `PlayerDataLoadException` - thrown when an error occurs while loading player data
- `PlayerDataSaveException` - thrown when an error occurs while saving player data
- The following API methods have been deprecated:
- `Player->sendTranslation()` - use `Player->sendMessage()` instead with a `Translatable` message
### `pocketmine\resourcepacks`
- The following new API methods have been added:
- `public ResourcePackManager->setResourceStack(list<ResourcePack> $resourceStack) : void` - sets the list of resource packs to be applied by players
- `public ResourcePackManager->setPackEncryptionKey(string $id, ?string $key) : void` - sets the encryption key to be used for a resource pack
### `pocketmine\utils`
- The following new API methods have been added:
- `public static Filesystem::fileGetContents(...) : string` - a wrapper around `file_get_contents()` which throws an exception on failure
### `pocketmine\world`
- The following new API methods have been added:
- `public World->requestSafeSpawn(?Vector3 $spawn = null) : Promise<Position>` - an async version of `getSafeSpawn()` which generates all the needed chunks before returning

94
changelogs/4.13.md Normal file
View File

@ -0,0 +1,94 @@
**For Minecraft: Bedrock Edition 1.19.50**
This is a minor feature release for PocketMine-MP, introducing some new features and improvements.
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.13.0
Released 30th January 2023.
## Gameplay
- Death message is now shown on the death screen when a player dies.
- Armour damage is now only increased if the armour reduced the damage taken.
- Implemented Swift Sneak enchantment.
- Fixed incorrect collision box calculation of walls and glass/bars when connected. Note: Client-side, wall connections are still broken; this only fixes projectile flight server-side.
## Performance
- Improved performance of chunk selection for chunk random ticking using a cache. This improves performance of chunk random ticking by 10-20%.
## Localization
- Added localized description for the `/dumpmemory` command.
## Permissions
- Added the following new core permissions:
- `pocketmine.command.effect.other` - allows the player to use the `/effect` command on other players (default operator only)
- `pocketmine.command.effect.self` - allows the player to use the `/effect` command on themselves (default operator only)
- `pocketmine.command.enchant.other` - allows the player to use the `/enchant` command on other players (default operator only)
- `pocketmine.command.enchant.self` - allows the player to use the `/enchant` command on themselves (default operator only)
- `pocketmine.command.gamemode.other` - allows the player to use the `/gamemode` command on other players (default operator only)
- `pocketmine.command.gamemode.self` - allows the player to use the `/gamemode` command on themselves (default operator only)
- `pocketmine.command.give.other` - allows the player to use the `/give` command on other players (default operator only)
- `pocketmine.command.give.self` - allows the player to use the `/give` command on themselves (default operator only)
- `pocketmine.command.spawnpoint.other` - allows the player to use the `/spawnpoint` command on other players (default operator only)
- `pocketmine.command.spawnpoint.self` - allows the player to use the `/spawnpoint` command on themselves (default operator only)
- `pocketmine.command.teleport.other` - allows the player to use the `/teleport` command on other players (default operator only)
- `pocketmine.command.teleport.self` - allows the player to use the `/teleport` command on themselves (default operator only)
- `pocketmine.command.title.other` - allows the player to use the `/title` command on other players (default operator only)
- `pocketmine.command.title.self` - allows the player to use the `/title` command on themselves (default operator only)
## Internals
- Decoupled `Player->sendMessage()` and `Player->sendTranslation()`.
- Refactored resource pack loading in `ResourcePackManager` to make it easier to understand.
- Client-aware translation processing has been moved to `NetworkSession` due to being client-specific.
- Replaced hardcoded strings with constants in various places.
- `NetworkSession` destructive cleanup is now deferred to the next session tick. This fixes various `InventoryManager` crashes when kicking players during events.
- Updated code using `strpos()` to use `str_starts_with()`, `str_ends_with()` and `str_contains()` where appropriate.
- Added documentation for some internal methods.
## API
### `pocketmine\command`
- The following new API methods have been added:
- `protected VanillaCommand->fetchPermittedPlayerTarget(...) : ?Player` - fetches a player target according to the given sender permissions, or null if not found or not permitted
### `pocketmine\entity`
- The following new API methods have been added:
- `public Living->getDisplayName() : string` - the name of the entity to be shown in death messages, commands etc.
### `pocketmine\event\world`
- The following new classes have been added:
- `WorldSoundEvent` - called when a sound is played in a world
- `WorldParticleEvent` - called when a particle is spawned in a world
### `pocketmine\item`
- The following new API methods have been added:
- `public Item->onInteractEntity(Player $player, Entity $entity, Vector3 $clickVector) : bool` - called when a player interacts with an entity with this item in hand
### `pocketmine\lang`
- `Language->translate()` and `Language->translateString()` no longer parse nested translation in the "base text". This was never intended behaviour, and didn't work beyond the first level anyway.
### `pocketmine\player`
- The following new interfaces have been added:
- `PlayerDataProvider` - implemented by classes which want to offer storage for player data
- The following new classes have been added:
- `DatFilePlayerDataProvider` - the default player data provider, which stores `.dat` files in the `players` folder
- `PlayerDataLoadException` - thrown when an error occurs while loading player data
- `PlayerDataSaveException` - thrown when an error occurs while saving player data
- The following API methods have been deprecated:
- `Player->sendTranslation()` - use `Player->sendMessage()` instead with a `Translatable` message
### `pocketmine\resourcepacks`
- The following new API methods have been added:
- `public ResourcePackManager->setResourceStack(list<ResourcePack> $resourceStack) : void` - sets the list of resource packs to be applied by players
- `public ResourcePackManager->setPackEncryptionKey(string $id, ?string $key) : void` - sets the encryption key to be used for a resource pack
### `pocketmine\utils`
- The following new API methods have been added:
- `public static Filesystem::fileGetContents(...) : string` - a wrapper around `file_get_contents()` which throws an exception on failure
### `pocketmine\world`
- The following new API methods have been added:
- `public World->requestSafeSpawn(?Vector3 $spawn = null) : Promise<Position>` - an async version of `getSafeSpawn()` which generates all the needed chunks before returning

21
changelogs/4.14.md Normal file
View File

@ -0,0 +1,21 @@
**For Minecraft: Bedrock Edition 1.19.60**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.14.0
Released 8th February 2023.
## General
- Added support for Minecraft: Bedrock Edition 1.19.60.
- Removed support for older versions.
# 4.14.1
Released 15th February 2023.
## Fixes
- Fixed all players getting kicked with `Receiving packets too fast` if a server tick takes longer than 5 seconds (e.g. because of autosave or GC).
- Fixed players getting kicked when linking with entities.

38
changelogs/4.15.md Normal file
View File

@ -0,0 +1,38 @@
**For Minecraft: Bedrock Edition 1.19.62**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.15.0
Released 17th February 2023.
## General
- Added support for Minecraft: Bedrock Edition 1.19.62.
- Removed support for older versions.
# 4.15.1
Released 21st February 2023.
## Fixes
- Fixed dropped items not despawning when in non-ticking chunks.
- Fixed dropped items not despawning if an infinite pickup delay is set.
- Fixed infinite despawn delay (never despawn) being ignored for dropped items.
# 4.15.2
Released 24th February 2023.
## General
- Accept Minecraft: Bedrock Edition 1.19.63 (identical protocol to 1.19.62, but different version due to Mojang mixup).
## Fixes
- Fixed `World Population` timer sometimes not being stopped, causing strange results in timings reports.
# 4.15.3
Released 7th March 2023.
## Fixes
- Fixed `/dumpmemory` crash when any object contained an `INF` or `NaN` float value.
- Updated RakLib for security fixes.

45
changelogs/4.16-beta.md Normal file
View File

@ -0,0 +1,45 @@
**For Minecraft: Bedrock Edition 1.19.62**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.16.0-BETA1
Released 4th March 2023.
## General
- Added granular timings for packet encode, similar to the existing timings for packet decode.
- Timings now covers several areas of the network system which were previously not counted by network timings, but were counted by total timings. This provides a better insight into the performance of the network system.
## Performance
- Improved performance of packet batch handling by avoiding unnecessary object allocations.
- Improved performance of packet broadcasting when the broadcast size is below the batch threshold. Previously, the packets would be encoded once by every recipient, but now they are encoded once and then added to the send buffer of each session in their raw form.
- This change mostly affects servers with larger maps, where players are more widely distributed.
## Build system
- Added a new script `build/generate-bedrockdata-path-consts.php`, which must be run whenever BedrockData is updated. This script generates a class of constants with the file paths of all BedrockData files.
## API
### `pocketmine\entity`
- The following new API methods have been added:
- `public Entity->getGravity() : float` - returns the entity's gravity acceleration in blocks/tick^2
- `public Entity->setGravity(float $gravity) : void` - sets the entity's gravity acceleration in blocks/tick^2
## Internals
- Now uses [`pocketmine/bedrock-data` 2.0.0](https://github.com/pmmp/BedrockData/releases/tag/2.0.0+bedrock-1.19.60).
- This version is now used by both PM4 and PM5, reducing maintenance burden.
- Now uses [`pocketmine/bedrock-protocol` 19.3.0](https://github.com/pmmp/BedrockProtocol/releases/tag/19.3.0+bedrock-1.19.62).
- This version provides new APIs for handling packet batches which enabled improving performance and adding new features, such as detailed packet encode timings.
- Crafting recipes and creative inventory data are now loaded from `recipes/legacy_recipes.json` and `recipes/legacy_creativeitems.json` respectively. Previously, these were loaded from BedrockData directly, but BedrockData 2.0 now uses a format which can't be supported in 4.x without BC breaks.
- Added dependencies on [`pocketmine/bedrock-block-upgrade-schema`](https://github.com/pmmp/BedrockBlockUpgradeSchema) and [`pocketmine/bedrock-item-upgrade-schema`](https://github.com/pmmp/BedrockItemUpgradeSchema). These provide mapping files no longer present in BedrockData 2.0.
- Reduced and/or eliminated most usages of `PacketBatch`, since it only appeared as a throwaway object and was therefore wasting performance.
- `Compressor` now exposes `getCompressionThreshold()` instead of `willCompress()`, which allows determining whether a batch will be compressed without allocating it.
- Added `pocketmine\data\bedrock\BedrockDataFiles`, an auto-generated class of constants with the file paths of all BedrockData files. This makes it easier to locate usages, detect unused files and avoid typos.
# 4.16.0-BETA2
Released 4th March 2023.
## General
- Fixed incorrect release channel for 4.16.0-BETA1.

41
changelogs/4.16.md Normal file
View File

@ -0,0 +1,41 @@
**For Minecraft: Bedrock Edition 1.19.62**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.16.0
Released 7th March 2023.
## General
- Added granular timings for packet encode, similar to the existing timings for packet decode.
- Split `Player Network Send - Compression` timings into two timers, one for `Session Buffer` compression and one for `Broadcast` compression.
- Timings now covers several areas of the network system which were previously not counted by network timings, but were counted by total timings. This provides a better insight into the performance of the network system.
## Performance
- Improved performance of packet batch handling by avoiding unnecessary object allocations.
- Improved performance of packet broadcasting when the broadcast size is below the batch threshold. Previously, the packets would be encoded once by every recipient, but now they are encoded once and then added to the send buffer of each session in their raw form.
- This change mostly affects servers with larger maps, where players are more widely distributed.
- Improved performance of packet broadcasting when the broadcast has only one recipient (allow the session to compress the packet with the rest of its buffer).
## Build system
- Added a new script `build/generate-bedrockdata-path-consts.php`, which must be run whenever BedrockData is updated. This script generates a class of constants with the file paths of all BedrockData files.
## API
### `pocketmine\entity`
- The following new API methods have been added:
- `public Entity->getGravity() : float` - returns the entity's gravity acceleration in blocks/tick^2
- `public Entity->setGravity(float $gravity) : void` - sets the entity's gravity acceleration in blocks/tick^2
## Internals
- Now uses [`pocketmine/bedrock-data` 2.0.0](https://github.com/pmmp/BedrockData/releases/tag/2.0.0+bedrock-1.19.60).
- This version is now used by both PM4 and PM5, reducing maintenance burden.
- Now uses [`pocketmine/bedrock-protocol` 19.3.0](https://github.com/pmmp/BedrockProtocol/releases/tag/19.3.0+bedrock-1.19.62).
- This version provides new APIs for handling packet batches which enabled improving performance and adding new features, such as detailed packet encode timings.
- Crafting recipes and creative inventory data are now loaded from `recipes/legacy_recipes.json` and `recipes/legacy_creativeitems.json` respectively. Previously, these were loaded from BedrockData directly, but BedrockData 2.0 now uses a format which can't be supported in 4.x without BC breaks.
- Added dependencies on [`pocketmine/bedrock-block-upgrade-schema`](https://github.com/pmmp/BedrockBlockUpgradeSchema) and [`pocketmine/bedrock-item-upgrade-schema`](https://github.com/pmmp/BedrockItemUpgradeSchema). These provide mapping files no longer present in BedrockData 2.0.
- Reduced and/or eliminated most usages of `PacketBatch`, since it only appeared as a throwaway object and was therefore wasting performance.
- `Compressor` now exposes `getCompressionThreshold()` instead of `willCompress()`, which allows determining whether a batch will be compressed without allocating it.
- Added `pocketmine\data\bedrock\BedrockDataFiles`, an auto-generated class of constants with the file paths of all BedrockData files. This makes it easier to locate usages, detect unused files and avoid typos.

14
changelogs/4.17.md Normal file
View File

@ -0,0 +1,14 @@
**For Minecraft: Bedrock Edition 1.19.70**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.17.0
Released 14th March 2023.
## General
- Added support for Minecraft: Bedrock Edition 1.19.70.
- Removed support for older versions.

View File

@ -12,3 +12,25 @@ Released 20th September 2022.
## General
- Added support for Minecraft: Bedrock Edition 1.19.30.
- Removed support for older versions.
# 4.9.1
Released 11th October 2022.
## Documentation
- Added and improved documentation for many API methods in `Player` and `Block`.
- Added missing `@internal` tag for `TaskHandler->setNextRun()`, `TaskHandler->remove()` and `TaskHandler->run()`.
## Fixes
- Flight state is now locked by the server in spectator mode. This prevents any attempt by the client to toggle flight mode.
- Fixed entity health exceeding its max health after the expiry of Health Boost effect.
- Fixed burp sound not being played when a player eats food.
- Fixed placement conditions for mushrooms - they can now only be placed when the light level at the target is <= 12, or on podzol or mycelium.
- Fixed sign text appearing to change colour and/or glow when using dye on a sign - since this feature is not yet implemented, no change should occur.
- Fixed players drowning when sprint-swimming on the surface of water.
## Internals
- Added more detailed debug logging during the player login sequence.
- Silenced debug spam during `PreSpawnPacketHandler`, considerably reducing debug noise when players join.
- Fixed an edge case in `InventoryManager->removeWindow()`. This bug didn't have any effect on stable versions, but caused a `next-minor` development version to crash.
- `Item`s returned by event getters are now cloned if modifying the result will have no useful side effects.
- Updated `pocketmine/bedrock-data` to [`1.11.1`](https://github.com/pmmp/BedrockData/tree/1.11.1%2Bbedrock-1.19.30), which reduces bandwidth consumption during logins by not sending useless biome generation data.

View File

@ -34,14 +34,16 @@
"adhocore/json-comment": "^1.1",
"fgrosse/phpasn1": "^2.3",
"netresearch/jsonmapper": "^4.0",
"pocketmine/bedrock-data": "~1.11.0+bedrock-1.19.30",
"pocketmine/bedrock-protocol": "~13.0.0+bedrock-1.19.30",
"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.0.0+bedrock-1.19.70",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/classloader": "^0.2.0",
"pocketmine/color": "^0.2.0",
"pocketmine/color": "^0.3.0",
"pocketmine/errorhandler": "^0.6.0",
"pocketmine/locale-data": "~2.8.0 <2.8.9",
"pocketmine/locale-data": "~2.18.0",
"pocketmine/log": "^0.4.0",
"pocketmine/log-pthreads": "^0.4.0",
"pocketmine/math": "^0.4.0",
@ -50,10 +52,11 @@
"pocketmine/raklib-ipc": "^0.1.0",
"pocketmine/snooze": "^0.3.0",
"ramsey/uuid": "^4.1",
"symfony/filesystem": "^5.4",
"webmozart/path-util": "^2.3"
},
"require-dev": {
"phpstan/phpstan": "1.8.5",
"phpstan/phpstan": "1.10.6",
"phpstan/phpstan-phpunit": "^1.1.0",
"phpstan/phpstan-strict-rules": "^1.2.0",
"phpunit/phpunit": "^9.2"

749
composer.lock generated

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

49988
resources/legacy_recipes.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -119,8 +119,6 @@ chunk-sending:
spawn-radius: 4
chunk-ticking:
#Max amount of chunks processed each tick
per-tick: 40
#Radius of chunks around a player to tick
tick-radius: 3
#Number of blocks inside ticking areas' subchunks that get ticked every tick. Higher values will accelerate events
@ -168,6 +166,9 @@ timings:
host: timings.pmmp.io
console:
#Whether to accept commands via the console. If disabled, anything typed on the console will be ignored.
#Useful to save resources on headless servers where the console is never used (e.g. hosted server, Docker, etc.)
enable-input: true
#Choose whether to enable server stats reporting on the console title.
#NOTE: The title ticker will be disabled regardless if console colours are not enabled.
title-tick: true

View File

@ -10,3 +10,4 @@ resource_stack:
# - natural.zip
# - vanilla.zip
#If you want to force clients to use vanilla resources, you must place a vanilla resource pack in your resources folder and add it to the stack here.
#To specify a resource encryption key, put the key in the <resource>.key file alongside the resource pack. Example: vanilla.zip.key

View File

@ -37,4 +37,6 @@ define('pocketmine\PATH', dirname(__DIR__) . '/');
define('pocketmine\RESOURCE_PATH', dirname(__DIR__) . '/resources/');
define('pocketmine\BEDROCK_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-data/');
define('pocketmine\LOCALE_DATA_PATH', dirname(__DIR__) . '/vendor/pocketmine/locale-data/');
define('pocketmine\BEDROCK_BLOCK_UPGRADE_SCHEMA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-block-upgrade-schema/');
define('pocketmine\BEDROCK_ITEM_UPGRADE_SCHEMA_PATH', dirname(__DIR__) . '/vendor/pocketmine/bedrock-item-upgrade-schema/');
define('pocketmine\COMPOSER_AUTOLOADER_PATH', dirname(__DIR__) . '/vendor/autoload.php');

View File

@ -30,7 +30,7 @@ use pocketmine\scheduler\GarbageCollectionTask;
use pocketmine\timings\Timings;
use pocketmine\utils\Process;
use pocketmine\utils\Utils;
use Webmozart\PathUtil\Path;
use Symfony\Component\Filesystem\Path;
use function arsort;
use function count;
use function fclose;
@ -49,6 +49,7 @@ use function ini_get;
use function ini_set;
use function intdiv;
use function is_array;
use function is_float;
use function is_object;
use function is_resource;
use function is_string;
@ -69,6 +70,10 @@ use const JSON_UNESCAPED_SLASHES;
use const SORT_NUMERIC;
class MemoryManager{
private const DEFAULT_CHECK_RATE = Server::TARGET_TICKS_PER_SECOND;
private const DEFAULT_CONTINUOUS_TRIGGER_RATE = Server::TARGET_TICKS_PER_SECOND * 2;
private const DEFAULT_TICKS_PER_GC = 30 * 60 * Server::TARGET_TICKS_PER_SECOND;
private int $memoryLimit;
private int $globalMemoryLimit;
private int $checkRate;
@ -113,20 +118,12 @@ class MemoryManager{
if($m <= 0){
$defaultMemory = 0;
}else{
switch(mb_strtoupper($matches[2])){
case "K":
$defaultMemory = intdiv($m, 1024);
break;
case "M":
$defaultMemory = $m;
break;
case "G":
$defaultMemory = $m * 1024;
break;
default:
$defaultMemory = $m;
break;
}
$defaultMemory = match(mb_strtoupper($matches[2])){
"K" => intdiv($m, 1024),
"M" => $m,
"G" => $m * 1024,
default => $m,
};
}
}
@ -139,11 +136,11 @@ class MemoryManager{
}
$this->globalMemoryLimit = $config->getPropertyInt("memory.global-limit", 0) * 1024 * 1024;
$this->checkRate = $config->getPropertyInt("memory.check-rate", 20);
$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", 30);
$this->continuousTriggerRate = $config->getPropertyInt("memory.continuous-trigger-rate", self::DEFAULT_CONTINUOUS_TRIGGER_RATE);
$this->garbageCollectionPeriod = $config->getPropertyInt("memory.garbage-collection.period", 36000);
$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);
@ -286,7 +283,7 @@ class MemoryManager{
/**
* Static memory dumper accessible from any thread.
*
* @param mixed $startingObject
* @param mixed $startingObject
*/
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger) : void{
$hardLimit = Utils::assumeNotFalse(ini_get('memory_limit'), "memory_limit INI directive should always exist");
@ -398,7 +395,7 @@ class MemoryManager{
do{
$continue = false;
foreach($objects as $hash => $object){
foreach(Utils::stringifyKeys($objects) as $hash => $object){
if(!is_object($object)){
continue;
}
@ -480,9 +477,14 @@ class MemoryManager{
/**
* @param mixed $from
* @param object[] $objects reference parameter
* @param object[] $objects reference parameter
* @param int[] $refCounts reference parameter
*
* @phpstan-param array<string, object> $objects
* @phpstan-param array<string, int> $refCounts
* @phpstan-param-out array<string, object> $objects
* @phpstan-param-out array<string, int> $refCounts
*
* @return mixed
*/
private static function continueDump($from, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
@ -518,6 +520,8 @@ class MemoryManager{
$data = "(string) len(" . strlen($from) . ") " . substr(Utils::printable($from), 0, $maxStringSize);
}elseif(is_resource($from)){
$data = "(resource) " . print_r($from, true);
}elseif(is_float($from)){
$data = "(float) $from";
}else{
$data = $from;
}

View File

@ -34,16 +34,19 @@ namespace pocketmine {
use pocketmine\utils\Timezone;
use pocketmine\utils\Utils;
use pocketmine\wizard\SetupWizard;
use Webmozart\PathUtil\Path;
use Symfony\Component\Filesystem\Path;
use function defined;
use function extension_loaded;
use function function_exists;
use function getcwd;
use function is_dir;
use function mkdir;
use function phpversion;
use function preg_match;
use function preg_quote;
use function realpath;
use function version_compare;
use const DIRECTORY_SEPARATOR;
require_once __DIR__ . '/VersionInfo.php';
@ -119,7 +122,7 @@ namespace pocketmine {
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
if(version_compare($pthreads_version, "4.0.0") < 0 || version_compare($pthreads_version, "5.0.0") > 0){
if(version_compare($pthreads_version, "4.0.0") < 0 || version_compare($pthreads_version, "5.0.0") >= 0){
$messages[] = "pthreads ^4.0.0 is required, while you have $pthreads_version.";
}
}
@ -201,6 +204,22 @@ JIT_WARNING
ini_set('assert.exception', '1');
}
function getopt_string(string $opt) : ?string{
$opts = getopt("", ["$opt:"]);
if(isset($opts[$opt])){
if(is_string($opts[$opt])){
return $opts[$opt];
}
if(is_array($opts[$opt])){
critical_error("Cannot specify --$opt multiple times");
}else{
critical_error("Missing value for --$opt");
}
exit(1);
}
return null;
}
/**
* @return void
*/
@ -252,27 +271,42 @@ JIT_WARNING
ErrorToExceptionHandler::set();
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
$cwd = Utils::assumeNotFalse(realpath(Utils::assumeNotFalse(getcwd())));
$dataPath = isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : $cwd . DIRECTORY_SEPARATOR;
$pluginPath = isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : $cwd . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR;
$dataPath = getopt_string("data") ?? $cwd;
$pluginPath = getopt_string("plugins") ?? $cwd . DIRECTORY_SEPARATOR . "plugins";
Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX);
if(!file_exists($dataPath)){
mkdir($dataPath, 0777, true);
if(!@mkdir($dataPath, 0777, true) && !is_dir($dataPath)){
critical_error("Unable to create/access data directory at $dataPath. Check that the target location is accessible by the current user.");
exit(1);
}
//this has to be done after we're sure the data path exists
$dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR;
$lockFilePath = Path::join($dataPath, 'server.lock');
if(($pid = Filesystem::createLockFile($lockFilePath)) !== null){
try{
$pid = Filesystem::createLockFile($lockFilePath);
}catch(\InvalidArgumentException $e){
critical_error($e->getMessage());
critical_error("Please ensure that there is enough space on the disk and that the current user has read/write permissions to the selected data directory $dataPath.");
exit(1);
}
if($pid !== null){
critical_error("Another " . VersionInfo::NAME . " instance (PID $pid) is already using this folder (" . realpath($dataPath) . ").");
critical_error("Please stop the other server first before running a new one.");
exit(1);
}
if(!@mkdir($pluginPath, 0777, true) && !is_dir($pluginPath)){
critical_error("Unable to create plugin directory at $pluginPath. Check that the target location is accessible by the current user.");
exit(1);
}
$pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
//Logger has a dependency on timezone
Timezone::init();
$opts = getopt("", ["no-wizard", "enable-ansi", "disable-ansi"]);
if(isset($opts["enable-ansi"])){
Terminal::init(true);
}elseif(isset($opts["disable-ansi"])){

View File

@ -31,7 +31,7 @@ use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\command\SimpleCommandMap;
use pocketmine\console\ConsoleCommandSender;
use pocketmine\console\ConsoleReaderThread;
use pocketmine\console\ConsoleReaderChildProcessDaemon;
use pocketmine\crafting\CraftingManager;
use pocketmine\crafting\CraftingManagerFromDataHelper;
use pocketmine\crash\CrashDump;
@ -49,10 +49,7 @@ use pocketmine\lang\KnownTranslationFactory;
use pocketmine\lang\Language;
use pocketmine\lang\LanguageNotFoundException;
use pocketmine\lang\Translatable;
use pocketmine\nbt\BigEndianNbtSerializer;
use pocketmine\nbt\NbtDataException;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\network\mcpe\compression\CompressBatchPromise;
use pocketmine\network\mcpe\compression\CompressBatchTask;
use pocketmine\network\mcpe\compression\Compressor;
@ -72,9 +69,13 @@ use pocketmine\network\query\QueryInfo;
use pocketmine\network\upnp\UPnPNetworkInterface;
use pocketmine\permission\BanList;
use pocketmine\permission\DefaultPermissions;
use pocketmine\player\DatFilePlayerDataProvider;
use pocketmine\player\GameMode;
use pocketmine\player\OfflinePlayer;
use pocketmine\player\Player;
use pocketmine\player\PlayerDataLoadException;
use pocketmine\player\PlayerDataProvider;
use pocketmine\player\PlayerDataSaveException;
use pocketmine\player\PlayerInfo;
use pocketmine\plugin\PharPluginLoader;
use pocketmine\plugin\Plugin;
@ -88,12 +89,12 @@ use pocketmine\promise\PromiseResolver;
use pocketmine\resourcepacks\ResourcePackManager;
use pocketmine\scheduler\AsyncPool;
use pocketmine\snooze\SleeperHandler;
use pocketmine\snooze\SleeperNotifier;
use pocketmine\stats\SendUsageTask;
use pocketmine\timings\Timings;
use pocketmine\timings\TimingsHandler;
use pocketmine\updater\UpdateChecker;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\BroadcastLoggerForwarder;
use pocketmine\utils\Config;
use pocketmine\utils\Filesystem;
use pocketmine\utils\Internet;
@ -105,17 +106,18 @@ use pocketmine\utils\SignalHandler;
use pocketmine\utils\Terminal;
use pocketmine\utils\TextFormat;
use pocketmine\utils\Utils;
use pocketmine\world\format\Chunk;
use pocketmine\world\format\io\WorldProviderManager;
use pocketmine\world\format\io\WritableWorldProviderManagerEntry;
use pocketmine\world\generator\Generator;
use pocketmine\world\generator\GeneratorManager;
use pocketmine\world\generator\InvalidGeneratorOptionsException;
use pocketmine\world\Position;
use pocketmine\world\World;
use pocketmine\world\WorldCreationOptions;
use pocketmine\world\WorldManager;
use Ramsey\Uuid\UuidInterface;
use Webmozart\PathUtil\Path;
use Symfony\Component\Filesystem\Path;
use function array_fill;
use function array_sum;
use function base64_encode;
use function cli_set_process_title;
@ -124,7 +126,6 @@ use function count;
use function date;
use function fclose;
use function file_exists;
use function file_get_contents;
use function file_put_contents;
use function filemtime;
use function fopen;
@ -161,13 +162,9 @@ use function time;
use function touch;
use function trim;
use function yaml_parse;
use function zlib_decode;
use function zlib_encode;
use const DIRECTORY_SEPARATOR;
use const PHP_EOL;
use const PHP_INT_MAX;
use const PTHREADS_INHERIT_NONE;
use const ZLIB_ENCODING_GZIP;
/**
* The class that manages everything
@ -185,9 +182,30 @@ class Server{
public const DEFAULT_PORT_IPV6 = 19133;
public const DEFAULT_MAX_VIEW_DISTANCE = 16;
/**
* Worlds, network, commands and most other things are polled this many times per second on average.
* Between ticks, the server will sleep to ensure that the average tick rate is maintained.
* It may wake up between ticks if a Snooze notification source is triggered (e.g. to process network packets).
*/
public const TARGET_TICKS_PER_SECOND = 20;
/**
* The average time between ticks, in seconds.
*/
public const TARGET_SECONDS_PER_TICK = 1 / self::TARGET_TICKS_PER_SECOND;
public const TARGET_NANOSECONDS_PER_TICK = 1_000_000_000 / self::TARGET_TICKS_PER_SECOND;
/**
* The TPS threshold below which the server will generate log warnings.
*/
private const TPS_OVERLOAD_WARNING_THRESHOLD = self::TARGET_TICKS_PER_SECOND * 0.6;
private const TICKS_PER_WORLD_CACHE_CLEAR = 5 * self::TARGET_TICKS_PER_SECOND;
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 static ?Server $instance = null;
private SleeperHandler $tickSleeper;
private TimeTrackingSleeperHandler $tickSleeper;
private BanList $banByName;
@ -203,7 +221,7 @@ class Server{
private PluginManager $pluginManager;
private float $profilingTickRate = 20;
private float $profilingTickRate = self::TARGET_TICKS_PER_SECOND;
private UpdateChecker $updater;
@ -213,10 +231,10 @@ class Server{
private int $tickCounter = 0;
private float $nextTick = 0;
/** @var float[] */
private array $tickAverage = [20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20];
private array $tickAverage;
/** @var float[] */
private array $useAverage = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
private float $currentTPS = 20;
private array $useAverage;
private float $currentTPS = self::TARGET_TICKS_PER_SECOND;
private float $currentUse = 0;
private float $startTime;
@ -226,7 +244,8 @@ class Server{
private MemoryManager $memoryManager;
private ConsoleReaderThread $console;
private ?ConsoleReaderChildProcessDaemon $console = null;
private ?ConsoleCommandSender $consoleSender = null;
private SimpleCommandMap $commandMap;
@ -251,6 +270,8 @@ class Server{
private string $dataPath;
private string $pluginPath;
private PlayerDataProvider $playerDataProvider;
/**
* @var string[]
* @phpstan-var array<string, string>
@ -484,49 +505,22 @@ class Server{
return $result;
}
private function getPlayerDataPath(string $username) : string{
return Path::join($this->getDataPath(), 'players', strtolower($username) . '.dat');
}
/**
* Returns whether the server has stored any saved data for this player.
*/
public function hasOfflinePlayerData(string $name) : bool{
return file_exists($this->getPlayerDataPath($name));
}
private function handleCorruptedPlayerData(string $name) : void{
$path = $this->getPlayerDataPath($name);
rename($path, $path . '.bak');
$this->logger->error($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_playerCorrupted($name)));
return $this->playerDataProvider->hasData($name);
}
public function getOfflinePlayerData(string $name) : ?CompoundTag{
return Timings::$syncPlayerDataLoad->time(function() use ($name) : ?CompoundTag{
$name = strtolower($name);
$path = $this->getPlayerDataPath($name);
if(file_exists($path)){
$contents = @file_get_contents($path);
if($contents === false){
throw new \RuntimeException("Failed to read player data file \"$path\" (permission denied?)");
}
$decompressed = @zlib_decode($contents);
if($decompressed === false){
$this->logger->debug("Failed to decompress raw player data for \"$name\"");
$this->handleCorruptedPlayerData($name);
return null;
}
try{
return (new BigEndianNbtSerializer())->read($decompressed)->mustGetCompoundTag();
}catch(NbtDataException $e){ //corrupt data
$this->logger->debug("Failed to decode NBT data for \"$name\": " . $e->getMessage());
$this->handleCorruptedPlayerData($name);
return null;
}
try{
return $this->playerDataProvider->loadData($name);
}catch(PlayerDataLoadException $e){
$this->logger->debug("Failed to load player data for $name: " . $e->getMessage());
$this->logger->error($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_playerCorrupted($name)));
return null;
}
return null;
});
}
@ -540,11 +534,9 @@ class Server{
if(!$ev->isCancelled()){
Timings::$syncPlayerDataSave->time(function() use ($name, $ev) : void{
$nbt = new BigEndianNbtSerializer();
$contents = Utils::assumeNotFalse(zlib_encode($nbt->write(new TreeRoot($ev->getSaveData())), ZLIB_ENCODING_GZIP), "zlib_encode() failed unexpectedly");
try{
Filesystem::safeFilePutContents($this->getPlayerDataPath($name), $contents);
}catch(\RuntimeException $e){
$this->playerDataProvider->saveData($name, $ev->getSaveData());
}catch(PlayerDataSaveException $e){
$this->logger->critical($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_saveError($name, $e->getMessage())));
$this->logger->logException($e);
}
@ -560,55 +552,55 @@ class Server{
$ev->call();
$class = $ev->getPlayerClass();
if($offlinePlayerData !== null && ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString("Level", ""))) !== null){
if($offlinePlayerData !== null && ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString(Player::TAG_LEVEL, ""))) !== null){
$playerPos = EntityDataHelper::parseLocation($offlinePlayerData, $world);
$spawn = $playerPos->asVector3();
}else{
$world = $this->worldManager->getDefaultWorld();
if($world === null){
throw new AssumptionFailedError("Default world should always be loaded");
}
$playerPos = null;
$spawn = $world->getSpawnLocation();
}
/** @phpstan-var PromiseResolver<Player> $playerPromiseResolver */
$playerPromiseResolver = new PromiseResolver();
$world->requestChunkPopulation($spawn->getFloorX() >> Chunk::COORD_BIT_SIZE, $spawn->getFloorZ() >> Chunk::COORD_BIT_SIZE, null)->onCompletion(
function() use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $world, $playerPos, $spawn, $offlinePlayerData) : void{
if(!$session->isConnected()){
$playerPromiseResolver->reject();
return;
}
/* Stick with the original spawn at the time of generation request, even if it changed since then.
* This is because we know for sure that that chunk will be generated, but the one at the new location
* might not be, and it would be much more complex to go back and redo the whole thing.
*
* TODO: this relies on the assumption that getSafeSpawn() will only alter the Y coordinate of the
* provided position. If this assumption is broken, we'll start seeing crashes in here.
*/
/**
* @see Player::__construct()
* @var Player $player
*/
$player = new $class($this, $session, $playerInfo, $authenticated, $playerPos ?? Location::fromObject($world->getSafeSpawn($spawn), $world), $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
}
$playerPromiseResolver->resolve($player);
},
static function() use ($playerPromiseResolver, $session) : void{
if($session->isConnected()){
$session->disconnect("Spawn terrain generation failed");
}
$playerPromiseResolver->reject();
$createPlayer = function(Location $location) use ($playerPromiseResolver, $class, $session, $playerInfo, $authenticated, $offlinePlayerData) : void{
$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
}
);
$playerPromiseResolver->resolve($player);
};
if($playerPos === null){ //new player or no valid position due to world not being loaded
$world->requestSafeSpawn()->onCompletion(
function(Position $spawn) use ($createPlayer, $playerPromiseResolver, $session, $world) : void{
if(!$session->isConnected()){
$playerPromiseResolver->reject();
return;
}
$createPlayer(Location::fromObject($spawn, $world));
},
function() use ($playerPromiseResolver, $session) : void{
if($session->isConnected()){
//TODO: this needs to be localized - this might be reached if the spawn world was unloaded while the player was logging in
$session->disconnect("Failed to find a safe spawn location");
}
$playerPromiseResolver->reject();
}
);
}else{ //returning player with a valid position - safe spawn not required
$createPlayer($playerPos);
}
return $playerPromiseResolver->getPromise();
}
/**
* @deprecated This method's results are unpredictable. The string "Steve" will return the player named "SteveJobs",
* until another player named "SteveJ" joins the server, at which point it will return that player instead. Prefer
* filtering the results of {@link Server::getOnlinePlayers()} yourself.
*
* Returns an online player whose name begins with or equals the given string (case insensitive).
* The closest match will be returned, or null if there are no online matches.
*
@ -776,8 +768,11 @@ class Server{
}
self::$instance = $this;
$this->startTime = microtime(true);
$this->tickAverage = array_fill(0, self::TARGET_TICKS_PER_SECOND, self::TARGET_TICKS_PER_SECOND);
$this->useAverage = array_fill(0, self::TARGET_TICKS_PER_SECOND, 0);
$this->tickSleeper = new SleeperHandler();
Timings::init();
$this->tickSleeper = new TimeTrackingSleeperHandler(Timings::$serverInterrupts);
$this->signalHandler = new SignalHandler(function() : void{
$this->logger->info("Received signal interrupt, stopping the server");
@ -802,7 +797,7 @@ class Server{
$this->logger->info("Loading server configuration");
$pocketmineYmlPath = Path::join($this->dataPath, "pocketmine.yml");
if(!file_exists($pocketmineYmlPath)){
$content = Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml")), "Missing required resource file");
$content = Filesystem::fileGetContents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml"));
if(VersionInfo::IS_DEVELOPMENT_BUILD){
$content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content);
}
@ -896,6 +891,9 @@ class Server{
if($this->configGroup->getPropertyInt("network.batch-threshold", 256) >= 0){
$netCompressionThreshold = $this->configGroup->getPropertyInt("network.batch-threshold", 256);
}
if($netCompressionThreshold < 0){
$netCompressionThreshold = null;
}
$netCompressionLevel = $this->configGroup->getPropertyInt("network.compression-level", 6);
if($netCompressionLevel < 1 || $netCompressionLevel > 9){
@ -957,15 +955,14 @@ class Server{
)));
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_license($this->getName())));
Timings::init();
TimingsHandler::setEnabled($this->configGroup->getPropertyBool("settings.enable-profiling", false));
$this->profilingTickRate = $this->configGroup->getPropertyInt("settings.profile-report-trigger", 20);
$this->profilingTickRate = $this->configGroup->getPropertyInt("settings.profile-report-trigger", self::TARGET_TICKS_PER_SECOND);
DefaultPermissions::registerCorePermissions();
$this->commandMap = new SimpleCommandMap($this);
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\BEDROCK_DATA_PATH, "recipes.json"));
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\RESOURCE_PATH, "legacy_recipes.json"));
$this->resourceManager = new ResourcePackManager(Path::join($this->getDataPath(), "resource_packs"), $this->logger);
@ -975,7 +972,7 @@ class Server{
copy(Path::join(\pocketmine\RESOURCE_PATH, 'plugin_list.yml'), $graylistFile);
}
try{
$pluginGraylist = PluginGraylist::fromArray(yaml_parse(file_get_contents($graylistFile)));
$pluginGraylist = PluginGraylist::fromArray(yaml_parse(Filesystem::fileGetContents($graylistFile)));
}catch(\InvalidArgumentException $e){
$this->logger->emergency("Failed to load $graylistFile: " . $e->getMessage());
$this->forceShutdownExit();
@ -997,12 +994,14 @@ 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", 6000));
$this->worldManager->setAutoSaveInterval($this->configGroup->getPropertyInt("ticks-per.autosave", $this->worldManager->getAutoSaveInterval()));
$this->updater = new UpdateChecker($this, $this->configGroup->getPropertyString("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"]);
$loadErrorCount = 0;
@ -1035,7 +1034,7 @@ class Server{
}
if($this->configGroup->getPropertyBool("anonymous-statistics.enabled", true)){
$this->sendUsageTicker = 6000;
$this->sendUsageTicker = self::TICKS_PER_STATS_REPORT;
$this->sendUsage(SendUsageTask::TYPE_OPEN);
}
@ -1045,22 +1044,14 @@ class Server{
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_donate(TextFormat::AQUA . "https://patreon.com/pocketminemp" . TextFormat::RESET)));
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_startFinished(strval(round(microtime(true) - $this->startTime, 3)))));
//TODO: move console parts to a separate component
$consoleSender = new ConsoleCommandSender($this, $this->language);
$this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_ADMINISTRATIVE, $consoleSender);
$this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_USERS, $consoleSender);
$forwarder = new BroadcastLoggerForwarder($this, $this->logger, $this->language);
$this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_ADMINISTRATIVE, $forwarder);
$this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_USERS, $forwarder);
$consoleNotifier = new SleeperNotifier();
$commandBuffer = new \Threaded();
$this->console = new ConsoleReaderThread($commandBuffer, $consoleNotifier);
$this->tickSleeper->addNotifier($consoleNotifier, function() use ($commandBuffer, $consoleSender) : void{
Timings::$serverCommand->startTiming();
while(($line = $commandBuffer->shift()) !== null){
$this->dispatchCommand($consoleSender, (string) $line);
}
Timings::$serverCommand->stopTiming();
});
$this->console->start(PTHREADS_INHERIT_NONE);
//TODO: move console parts to a separate component
if($this->configGroup->getPropertyBool("console.enable-input", true)){
$this->console = new ConsoleReaderChildProcessDaemon($this->logger);
}
$this->tickProcessor();
$this->forceShutdown();
@ -1272,7 +1263,7 @@ class Server{
}
/**
* @param CommandSender[]|null $recipients
* @param CommandSender[]|null $recipients
*/
public function broadcastMessage(Translatable|string $message, ?array $recipients = null) : int{
$recipients = $recipients ?? $this->getBroadcastChannelSubscribers(self::BROADCAST_CHANNEL_USERS);
@ -1325,9 +1316,9 @@ class Server{
}
/**
* @param int $fadeIn Duration in ticks for fade-in. If -1 is given, client-sided defaults will be used.
* @param int $stay Duration in ticks to stay on screen for
* @param int $fadeOut Duration in ticks for fade-out.
* @param int $fadeIn Duration in ticks for fade-in. If -1 is given, client-sided defaults will be used.
* @param int $stay Duration in ticks to stay on screen for
* @param int $fadeOut Duration in ticks for fade-out.
* @param Player[]|null $recipients
*/
public function broadcastTitle(string $title, string $subtitle = "", int $fadeIn = -1, int $stay = -1, int $fadeOut = -1, ?array $recipients = null) : int{
@ -1390,14 +1381,16 @@ class Server{
*
* @param bool|null $sync Compression on the main thread (true) or workers (false). Default is automatic (null).
*/
public function prepareBatch(PacketBatch $stream, Compressor $compressor, ?bool $sync = null) : CompressBatchPromise{
public function prepareBatch(PacketBatch $stream, Compressor $compressor, ?bool $sync = null, ?TimingsHandler $timings = null) : CompressBatchPromise{
$timings ??= Timings::$playerNetworkSendCompress;
try{
Timings::$playerNetworkSendCompress->startTiming();
$timings->startTiming();
$buffer = $stream->getBuffer();
if($sync === null){
$sync = !($this->networkCompressionAsync && $compressor->willCompress($buffer));
$threshold = $compressor->getCompressionThreshold();
$sync = !$this->networkCompressionAsync || $threshold === null || strlen($stream->getBuffer()) < $threshold;
}
$promise = new CompressBatchPromise();
@ -1410,7 +1403,7 @@ class Server{
return $promise;
}finally{
Timings::$playerNetworkSendCompress->stopTiming();
$timings->stopTiming();
}
}
@ -1513,7 +1506,7 @@ class Server{
$this->configGroup->save();
}
if(isset($this->console)){
if($this->console !== null){
$this->getLogger()->debug("Closing console");
$this->console->quit();
}
@ -1720,7 +1713,7 @@ class Server{
$session = $player->getNetworkSession();
$position = $player->getPosition();
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_player_logIn(
TextFormat::AQUA . $player->getName() . TextFormat::WHITE,
TextFormat::AQUA . $player->getName() . TextFormat::RESET,
$session->getIp(),
(string) $session->getPort(),
(string) $player->getId(),
@ -1825,11 +1818,11 @@ class Server{
$this->network->tick();
Timings::$connection->stopTiming();
if(($this->tickCounter % 20) === 0){
if(($this->tickCounter % self::TARGET_TICKS_PER_SECOND) === 0){
if($this->doTitleTick){
$this->titleTick();
}
$this->currentTPS = 20;
$this->currentTPS = self::TARGET_TICKS_PER_SECOND;
$this->currentUse = 0;
$queryRegenerateEvent = new QueryRegenerateEvent(new QueryInfo($this));
@ -1841,38 +1834,49 @@ class Server{
}
if($this->sendUsageTicker > 0 && --$this->sendUsageTicker === 0){
$this->sendUsageTicker = 6000;
$this->sendUsageTicker = self::TICKS_PER_STATS_REPORT;
$this->sendUsage(SendUsageTask::TYPE_STATUS);
}
if(($this->tickCounter % 100) === 0){
if(($this->tickCounter % self::TICKS_PER_WORLD_CACHE_CLEAR) === 0){
foreach($this->worldManager->getWorlds() as $world){
$world->clearCache();
}
}
if($this->getTicksPerSecondAverage() < 12){
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_tickOverload()));
}
if(($this->tickCounter % self::TICKS_PER_TPS_OVERLOAD_WARNING) === 0 && $this->getTicksPerSecondAverage() < self::TPS_OVERLOAD_WARNING_THRESHOLD){
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_tickOverload()));
}
$this->getMemoryManager()->check();
if($this->console !== null){
Timings::$serverCommand->startTiming();
while(($line = $this->console->readLine()) !== null){
$this->consoleSender ??= new ConsoleCommandSender($this, $this->language);
$this->dispatchCommand($this->consoleSender, $line);
}
Timings::$serverCommand->stopTiming();
}
Timings::$serverTick->stopTiming();
$now = microtime(true);
$this->currentTPS = min(20, 1 / max(0.001, $now - $tickTime));
$this->currentUse = min(1, ($now - $tickTime) / 0.05);
$totalTickTimeSeconds = $now - $tickTime + ($this->tickSleeper->getNotificationProcessingTime() / 1_000_000_000);
$this->currentTPS = min(self::TARGET_TICKS_PER_SECOND, 1 / max(0.001, $totalTickTimeSeconds));
$this->currentUse = min(1, $totalTickTimeSeconds / self::TARGET_SECONDS_PER_TICK);
TimingsHandler::tick($this->currentTPS <= $this->profilingTickRate);
$idx = $this->tickCounter % 20;
$idx = $this->tickCounter % self::TARGET_TICKS_PER_SECOND;
$this->tickAverage[$idx] = $this->currentTPS;
$this->useAverage[$idx] = $this->currentUse;
$this->tickSleeper->resetNotificationProcessingTime();
if(($this->nextTick - $tickTime) < -1){
$this->nextTick = $tickTime;
}else{
$this->nextTick += 0.05;
$this->nextTick += self::TARGET_SECONDS_PER_TICK;
}
}
}

View File

@ -44,7 +44,7 @@ final class ServerConfigGroup{
){}
/**
* @param mixed $defaultValue
* @param mixed $defaultValue
*
* @return mixed
*/

View File

@ -0,0 +1,64 @@
<?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;
use pocketmine\snooze\SleeperHandler;
use pocketmine\timings\TimingsHandler;
use function hrtime;
/**
* Custom Snooze sleeper handler which captures notification processing time.
* @internal
*/
final class TimeTrackingSleeperHandler extends SleeperHandler{
private int $notificationProcessingTimeNs = 0;
public function __construct(
private TimingsHandler $timings
){
parent::__construct();
}
/**
* Returns the time in nanoseconds spent processing notifications since the last reset.
*/
public function getNotificationProcessingTime() : int{ return $this->notificationProcessingTimeNs; }
/**
* Resets the notification processing time tracker to zero.
*/
public function resetNotificationProcessingTime() : void{ $this->notificationProcessingTimeNs = 0; }
public function processNotifications() : void{
$startTime = hrtime(true);
$this->timings->startTiming();
try{
parent::processNotifications();
}finally{
$this->notificationProcessingTimeNs += hrtime(true) - $startTime;
$this->timings->stopTiming();
}
}
}

View File

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

View File

@ -164,9 +164,10 @@ class Bamboo extends Transparent{
}
public function onNearbyBlockChange() : void{
$below = $this->position->getWorld()->getBlock($this->position->down());
$world = $this->position->getWorld();
$below = $world->getBlock($this->position->down());
if(!$this->canBeSupportedBy($below) && !$below->isSameType($this)){
$this->position->getWorld()->useBreakOn($this->position);
$world->useBreakOn($this->position);
}
}
@ -212,7 +213,7 @@ class Bamboo extends Transparent{
}
}
$tx = new BlockTransaction($this->position->getWorld());
$tx = new BlockTransaction($world);
foreach($newBlocks as $idx => $newBlock){
$tx->addBlock($this->position->subtract(0, $idx - $growAmount, 0), $newBlock);
}

View File

@ -82,8 +82,9 @@ final class BambooSapling extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->position->getWorld()->getBlock($this->position->down()))){
$this->position->getWorld()->useBreakOn($this->position);
$world = $this->position->getWorld();
if(!$this->canBeSupportedBy($world->getBlock($this->position->down()))){
$world->useBreakOn($this->position);
}
}

View File

@ -87,7 +87,7 @@ abstract class BaseBanner extends Transparent{
}
/**
* @param BannerPatternLayer[] $patterns
* @param BannerPatternLayer[] $patterns
*
* @phpstan-param list<BannerPatternLayer> $patterns
* @return $this
@ -112,7 +112,14 @@ abstract class BaseBanner extends Transparent{
return SupportType::NONE();
}
private function canBeSupportedBy(Block $block) : bool{
return $block->isSolid();
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide($this->getSupportingFace()))){
return false;
}
if($item instanceof ItemBanner){
$this->color = $item->getColor();
$this->setPatterns($item->getPatterns());
@ -124,7 +131,7 @@ abstract class BaseBanner extends Transparent{
abstract protected function getSupportingFace() : int;
public function onNearbyBlockChange() : void{
if($this->getSide($this->getSupportingFace())->getId() === BlockLegacyIds::AIR){
if(!$this->canBeSupportedBy($this->getSide($this->getSupportingFace()))){
$this->position->getWorld()->useBreakOn($this->position);
}
}

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\CoralTypeTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\event\block\BlockDeathEvent;
use pocketmine\item\Item;
abstract class BaseCoral extends Transparent{
@ -50,7 +51,11 @@ abstract class BaseCoral extends Transparent{
//TODO: check water inside the block itself (not supported on the API yet)
if(!$hasWater){
$world->setBlock($this->position, $this->setDead(true));
$ev = new BlockDeathEvent($this, $this->setDead(true));
$ev->call();
if(!$ev->isCancelled()){
$world->setBlock($this->position, $ev->getNewState());
}
}
}
}

View File

@ -162,6 +162,7 @@ abstract class BaseRail extends Flowable{
$thisConnections = $this->getConnectedDirections();
$changed = false;
$world = $this->position->getWorld();
do{
$possible = $this->getPossibleConnectionDirections($thisConnections);
$continue = false;
@ -189,7 +190,7 @@ abstract class BaseRail extends Flowable{
if(isset($otherPossible[$otherSide])){
$otherConnections[] = $otherSide;
$other->setConnections($otherConnections);
$this->position->getWorld()->setBlock($other->position, $other);
$world->setBlock($other->position, $other);
$changed = true;
$thisConnections[] = $thisSide;
@ -202,7 +203,7 @@ abstract class BaseRail extends Flowable{
if($changed){
$this->setConnections($thisConnections);
$this->position->getWorld()->setBlock($this->position, $this);
$world->setBlock($this->position, $this);
}
}
@ -220,12 +221,13 @@ abstract class BaseRail extends Flowable{
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->getSide(Facing::DOWN)->getSupportType(Facing::UP)->hasEdgeSupport()){
$this->position->getWorld()->useBreakOn($this->position);
$world->useBreakOn($this->position);
}else{
foreach($this->getCurrentShapeConnections() as $connection){
if(($connection & RailConnectionInfo::FLAG_ASCEND) !== 0 && !$this->getSide($connection & ~RailConnectionInfo::FLAG_ASCEND)->getSupportType(Facing::UP)->hasEdgeSupport()){
$this->position->getWorld()->useBreakOn($this->position);
$world->useBreakOn($this->position);
break;
}
}

View File

@ -114,14 +114,13 @@ final class Bell extends Transparent{
return $this;
}
private function canBeSupportedBy(Block $block) : bool{
//TODO: this isn't the actual logic, but it's the closest approximation we can support for now
return $block->isSolid();
private function canBeSupportedBy(Block $block, int $face) : bool{
return !$block->getSupportType($face)->equals(SupportType::NONE());
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face === Facing::UP){
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->down()))){
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->down()), Facing::UP)){
return false;
}
if($player !== null){
@ -129,18 +128,18 @@ final class Bell extends Transparent{
}
$this->setAttachmentType(BellAttachmentType::FLOOR());
}elseif($face === Facing::DOWN){
if(!$this->canBeSupportedBy($tx->fetchBlock($this->position->up()))){
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))))){
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)))){
if($this->canBeSupportedBy($tx->fetchBlock($this->position->getSide($face)), Facing::opposite($face))){
$this->setAttachmentType(BellAttachmentType::TWO_WALLS());
}
}
@ -149,10 +148,10 @@ final class Bell extends Transparent{
public function onNearbyBlockChange() : void{
if(
($this->attachmentType->equals(BellAttachmentType::CEILING()) && !$this->canBeSupportedBy($this->getSide(Facing::UP))) ||
($this->attachmentType->equals(BellAttachmentType::FLOOR()) && !$this->canBeSupportedBy($this->getSide(Facing::DOWN))) ||
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) && !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)))) ||
($this->attachmentType->equals(BellAttachmentType::TWO_WALLS()) && (!$this->canBeSupportedBy($this->getSide($this->facing)) || !$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)))))
($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);
}
@ -161,28 +160,28 @@ final class Bell extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
$faceHit = Facing::opposite($player->getHorizontalFacing());
if($this->attachmentType->equals(BellAttachmentType::CEILING())){
$this->ring($faceHit);
}
if($this->attachmentType->equals(BellAttachmentType::FLOOR()) && Facing::axis($faceHit) === Facing::axis($this->facing)){
$this->ring($faceHit);
}
if(
($this->attachmentType->equals(BellAttachmentType::ONE_WALL()) || $this->attachmentType->equals(BellAttachmentType::TWO_WALLS())) &&
($faceHit === Facing::rotateY($this->facing, false) || $faceHit === Facing::rotateY($this->facing, true))
$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))
)
){
$this->ring($faceHit);
return true;
}
}
return true;
return false;
}
public function ring(int $faceHit) : void{
$this->position->getWorld()->addSound($this->position, new BellRingSound());
$tile = $this->position->getWorld()->getTile($this->position);
$world = $this->position->getWorld();
$world->addSound($this->position, new BellRingSound());
$tile = $world->getTile($this->position);
if($tile instanceof TileBell){
$this->position->getWorld()->broadcastPacketToViewers($this->position, $tile->createFakeUpdatePacket($faceHit));
$world->broadcastPacketToViewers($this->position, $tile->createFakeUpdatePacket($faceHit));
}
}
}

View File

@ -62,7 +62,7 @@ class Block{
protected ?array $collisionBoxes = null;
/**
* @param string $name English name of the block type (TODO: implement translations)
* @param string $name English name of the block type (TODO: implement translations)
*/
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
if(($idInfo->getVariant() & $this->getStateBitmask()) !== 0){
@ -78,25 +78,47 @@ class Block{
$this->position = clone $this->position;
}
/**
* Returns an object containing information about how to identify and store this block type, such as its legacy
* numeric ID(s), tile type (if any), and legacy variant metadata.
*/
public function getIdInfo() : BlockIdentifier{
return $this->idInfo;
}
/**
* Returns the printable English name of the block.
*/
public function getName() : string{
return $this->fallbackName;
}
/**
* @deprecated
*
* Returns the legacy numeric Minecraft block ID.
*/
public function getId() : int{
return $this->idInfo->getBlockId();
}
/**
* @internal
*
* Returns the full blockstate ID of this block. This is a compact way of representing a blockstate used to store
* blocks in chunks at runtime.
*
* This ID can be used to later obtain a copy of this block using {@link BlockFactory::get()}.
*/
public function getFullId() : int{
return ($this->getId() << self::INTERNAL_METADATA_BITS) | $this->getMeta();
}
/**
* 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.
*/
public function asItem() : Item{
return ItemFactory::getInstance()->get(
$this->idInfo->getItemId(),
@ -104,6 +126,12 @@ class Block{
);
}
/**
* @deprecated
*
* Returns the legacy Minecraft block meta value. This is a mixed-purpose value, which is used to store different
* things for different blocks.
*/
public function getMeta() : int{
$stateMeta = $this->writeStateToMeta();
assert(($stateMeta & ~$this->getStateBitmask()) === 0);
@ -116,6 +144,7 @@ class Block{
/**
* Returns a bitmask used to extract state bits from block metadata.
* This is used to remove unwanted information from the legacy meta value when getting the block as an item.
*/
public function getStateBitmask() : int{
return 0;
@ -143,11 +172,18 @@ class Block{
$this->collisionBoxes = null;
}
/**
* Writes information about the block into the world. This writes the blockstate ID into the chunk, and creates
* and/or removes tiles as necessary.
*
* Note: Do not call this directly. Pass the block to {@link World::setBlock()} instead.
*/
public function writeStateToWorld() : void{
$this->position->getWorld()->getOrLoadChunkAtPosition($this->position)->setFullBlock($this->position->x & Chunk::COORD_MASK, $this->position->y, $this->position->z & Chunk::COORD_MASK, $this->getFullId());
$world = $this->position->getWorld();
$world->getOrLoadChunkAtPosition($this->position)->setFullBlock($this->position->x & Chunk::COORD_MASK, $this->position->y, $this->position->z & Chunk::COORD_MASK, $this->getFullId());
$tileType = $this->idInfo->getTileClass();
$oldTile = $this->position->getWorld()->getTile($this->position);
$oldTile = $world->getTile($this->position);
if($oldTile !== null){
if($tileType === null || !($oldTile instanceof $tileType)){
$oldTile->close();
@ -161,13 +197,13 @@ class Block{
* @var Tile $tile
* @see Tile::__construct()
*/
$tile = new $tileType($this->position->getWorld(), $this->position->asVector3());
$this->position->getWorld()->addTile($tile);
$tile = new $tileType($world, $this->position->asVector3());
$world->addTile($tile);
}
}
/**
* Returns a type ID that identifies this type of block. This does not include information like facing, colour,
* Returns a type ID that identifies this type of block. This does not include information like facing, open/closed,
* powered/unpowered, etc.
*/
public function getTypeId() : int{
@ -198,22 +234,44 @@ class Block{
return true;
}
/**
* Returns whether this block can be replaced by another block placed in the same position.
*/
public function canBeReplaced() : bool{
return false;
}
/**
* Returns whether this block can replace the given block in the given placement conditions.
* This is used to allow slabs of the same type to combine into double slabs.
*/
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
return $blockReplace->canBeReplaced();
}
/**
* Places the Block, using block space and block target, and side. Returns if the block has been placed.
* Generates a block transaction to set all blocks affected by placing this block. Usually this is just the block
* itself, but may be multiple blocks in some cases (such as doors).
*
* @param BlockTransaction $tx Blocks to be set should be added to this transaction (do not modify thr world directly)
* @param Item $item Item used to place the block
* @param Block $blockReplace Block expected to be replaced
* @param Block $blockClicked Block that was clicked using the item
* @param int $face Face of the clicked block which was clicked
* @param Vector3 $clickVector Exact position inside the clicked block where the click occurred, relative to the block's position
* @param Player|null $player Player who placed the block, or null if it was not a player
*
* @return bool whether the placement should go ahead
*/
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$tx->addBlock($blockReplace->position, $this);
return true;
}
/**
* Called immediately after the block has been placed in the world. Since placement uses a block transaction, some
* things may not be possible until after the transaction has been executed.
*/
public function onPostPlace() : void{
}
@ -229,10 +287,11 @@ class Block{
* Do the actions needed so the block is broken with the Item
*/
public function onBreak(Item $item, ?Player $player = null) : bool{
if(($t = $this->position->getWorld()->getTile($this->position)) !== null){
$world = $this->position->getWorld();
if(($t = $world->getTile($this->position)) !== null){
$t->onBlockDestroyed();
}
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::AIR());
$world->setBlock($this->position, VanillaBlocks::AIR());
return true;
}
@ -252,7 +311,7 @@ class Block{
/**
* Called when this block is randomly updated due to chunk ticking.
* WARNING: This will not be called if ticksRandomly() does not return true!
* WARNING: This will not be called if {@link Block::ticksRandomly()} does not return true!
*/
public function onRandomTick() : void{
@ -273,8 +332,7 @@ class Block{
}
/**
* Called when this block is attacked (left-clicked). This is called when a player left-clicks the block to try and
* start to break it in survival mode.
* Called when this block is attacked (left-clicked) by a player attempting to start breaking it in survival.
*
* @return bool if an action took place, prevents starting to break the block if true.
*/
@ -282,11 +340,19 @@ class Block{
return false;
}
/**
* Returns a multiplier applied to the velocity of entities moving on top of this block. A higher value will make
* the block more slippery (like ice).
*
* @return float 0.0-1.0
*/
public function getFrictionFactor() : float{
return 0.6;
}
/**
* Returns the amount of light emitted by this block.
*
* @return int 0-15
*/
public function getLightLevel() : int{
@ -329,10 +395,6 @@ class Block{
return false;
}
public function hasEntityCollision() : bool{
return false;
}
/**
* Returns whether entities can climb up this block.
*/
@ -340,10 +402,6 @@ class Block{
return false;
}
public function addVelocityToEntity(Entity $entity) : ?Vector3{
return null;
}
final public function getPosition() : Position{
return $this->position;
}
@ -426,6 +484,7 @@ class Block{
/**
* Returns the item that players will equip when middle-clicking on this block.
* If addUserData is true, additional data may be added, such as banner patterns, chest contents, etc.
*/
public function getPickedItem(bool $addUserData = false) : Item{
$item = $this->asItem();
@ -549,7 +608,7 @@ class Block{
}
/**
* Checks for collision against an AxisAlignedBB
* Returns whether any of the block's collision boxes intersect with the given AxisAlignedBB.
*/
public function collidesWithBB(AxisAlignedBB $bb) : bool{
foreach($this->getCollisionBoxes() as $bb2){
@ -561,10 +620,21 @@ class Block{
return false;
}
/**
* Returns whether the block has actions to be executed when an entity enters its cell (full cube space).
*
* @see Block::onEntityInside()
*/
public function hasEntityCollision() : bool{
return false;
}
/**
* Called when an entity's bounding box clips inside this block's cell. Note that the entity may not be intersecting
* with the collision box or bounding box.
*
* WARNING: This will not be called if {@link Block::hasEntityCollision()} returns false.
*
* @return bool Whether the block is still the same after the intersection. If it changed (e.g. due to an explosive
* being ignited), this should return false.
*/
@ -572,6 +642,19 @@ class Block{
return true;
}
/**
* Returns a direction vector describing which way an entity intersecting this block should be pushed.
* This is used by liquids to push entities in liquid currents.
*
* The returned vector is summed with vectors from every other block the entity is intersecting, and normalized to
* produce a final direction vector.
*
* WARNING: This will not be called if {@link Block::hasEntityCollision()} does not return true!
*/
public function addVelocityToEntity(Entity $entity) : ?Vector3{
return null;
}
/**
* Called when an entity lands on this block (usually due to falling).
* @return float|null The new vertical velocity of the entity, or null if unchanged.
@ -581,6 +664,13 @@ class Block{
}
/**
* Returns an array of collision bounding boxes for this block.
* These are used for:
* - entity movement collision checks (to ensure entities can't clip through blocks)
* - projectile flight paths
* - block placement (to ensure the player can't place blocks inside itself or another entity)
* - anti-cheat checks in plugins
*
* @return AxisAlignedBB[]
*/
final public function getCollisionBoxes() : array{
@ -611,6 +701,10 @@ class Block{
return [AxisAlignedBB::one()];
}
/**
* Returns the type of support that the block can provide on the given face. This is used to determine whether
* blocks placed on the given face can be supported by this block.
*/
public function getSupportType(int $facing) : SupportType{
return SupportType::FULL();
}
@ -621,6 +715,10 @@ class Block{
return count($bb) === 1 && $bb[0]->getAverageEdgeLength() >= 1 && $bb[0]->isCube();
}
/**
* Performs a ray trace along the line between the two positions using the block's collision boxes.
* Returns the intersection point closest to pos1, or null if no intersection occurred.
*/
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
$bbs = $this->getCollisionBoxes();
if(count($bbs) === 0){

View File

@ -968,7 +968,7 @@ class BlockFactory{
* NOTE: If you are registering a new block type, you will need to add it to the creative inventory yourself - it
* will not automatically appear there.
*
* @param bool $override Whether to override existing registrations
* @param bool $override Whether to override existing registrations
*
* @throws \RuntimeException if something attempted to override an already-registered block without specifying the
* $override parameter.

View File

@ -130,10 +130,11 @@ class BrewingStand extends Transparent{
}
public function onScheduledUpdate() : void{
$brewing = $this->position->getWorld()->getTile($this->position);
$world = $this->position->getWorld();
$brewing = $world->getTile($this->position);
if($brewing instanceof TileBrewingStand){
if($brewing->onUpdate()){
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1);
$world->scheduleDelayedBlockUpdate($this->position, 1);
}
$changed = false;
@ -146,7 +147,7 @@ class BrewingStand extends Transparent{
}
if($changed){
$this->position->getWorld()->setBlock($this->position, $this);
$world->setBlock($this->position, $this);
}
}
}

View File

@ -61,7 +61,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($blockClicked, $face)){
if($this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -73,9 +73,10 @@ abstract class Button extends Flowable{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->pressed){
$this->pressed = true;
$this->position->getWorld()->setBlock($this->position, $this);
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, $this->getActivationTime());
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new RedstonePowerOnSound());
$world = $this->position->getWorld();
$world->setBlock($this->position, $this);
$world->scheduleDelayedBlockUpdate($this->position, $this->getActivationTime());
$world->addSound($this->position->add(0.5, 0.5, 0.5), new RedstonePowerOnSound());
}
return true;
@ -84,8 +85,9 @@ abstract class Button extends Flowable{
public function onScheduledUpdate() : void{
if($this->pressed){
$this->pressed = false;
$this->position->getWorld()->setBlock($this->position, $this);
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new RedstonePowerOffSound());
$world = $this->position->getWorld();
$world->setBlock($this->position, $this);
$world->addSound($this->position->add(0.5, 0.5, 0.5), new RedstonePowerOffSound());
}
}

View File

@ -88,13 +88,14 @@ class Cactus extends Transparent{
public function onNearbyBlockChange() : void{
$down = $this->getSide(Facing::DOWN);
$world = $this->position->getWorld();
if($down->getId() !== BlockLegacyIds::SAND && !$down->isSameType($this)){
$this->position->getWorld()->useBreakOn($this->position);
$world->useBreakOn($this->position);
}else{
foreach(Facing::HORIZONTAL as $side){
$b = $this->getSide($side);
if($b->isSolid()){
$this->position->getWorld()->useBreakOn($this->position);
$world->useBreakOn($this->position);
break;
}
}
@ -107,28 +108,29 @@ class Cactus extends Transparent{
public function onRandomTick() : void{
if(!$this->getSide(Facing::DOWN)->isSameType($this)){
$world = $this->position->getWorld();
if($this->age === self::MAX_AGE){
for($y = 1; $y < 3; ++$y){
if(!$this->position->getWorld()->isInWorld($this->position->x, $this->position->y + $y, $this->position->z)){
if(!$world->isInWorld($this->position->x, $this->position->y + $y, $this->position->z)){
break;
}
$b = $this->position->getWorld()->getBlockAt($this->position->x, $this->position->y + $y, $this->position->z);
$b = $world->getBlockAt($this->position->x, $this->position->y + $y, $this->position->z);
if($b->getId() === BlockLegacyIds::AIR){
$ev = new BlockGrowEvent($b, VanillaBlocks::CACTUS());
$ev->call();
if($ev->isCancelled()){
break;
}
$this->position->getWorld()->setBlock($b->position, $ev->getNewState());
$world->setBlock($b->position, $ev->getNewState());
}else{
break;
}
}
$this->age = 0;
$this->position->getWorld()->setBlock($this->position, $this);
$world->setBlock($this->position, $this);
}else{
++$this->age;
$this->position->getWorld()->setBlock($this->position, $this);
$world->setBlock($this->position, $this);
}
}
}

View File

@ -51,13 +51,13 @@ class Chest extends Transparent{
}
public function onPostPlace() : void{
$tile = $this->position->getWorld()->getTile($this->position);
$world = $this->position->getWorld();
$tile = $world->getTile($this->position);
if($tile instanceof TileChest){
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){
$world = $this->position->getWorld();
$pair = $world->getTile($c->position);
if($pair instanceof TileChest && !$pair->isPaired()){
[$left, $right] = $clockwise ? [$c, $this] : [$this, $c];

View File

@ -27,6 +27,7 @@ use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\CoralTypeTrait;
use pocketmine\block\utils\InvalidBlockStateException;
use pocketmine\data\bedrock\CoralTypeIdMap;
use pocketmine\event\block\BlockDeathEvent;
use pocketmine\item\Item;
use function mt_rand;
@ -77,7 +78,11 @@ final class CoralBlock extends Opaque{
}
}
if(!$hasWater){
$world->setBlock($this->position, $this->setDead(true));
$ev = new BlockDeathEvent($this, $this->setDead(true));
$ev->call();
if(!$ev->isCancelled()){
$world->setBlock($this->position, $ev->getNewState());
}
}
}
}

View File

@ -100,21 +100,23 @@ class DaylightSensor extends Transparent{
}
public function onScheduledUpdate() : void{
$world = $this->position->getWorld();
$signalStrength = $this->recalculateSignalStrength();
if($this->signalStrength !== $signalStrength){
$this->signalStrength = $signalStrength;
$this->position->getWorld()->setBlock($this->position, $this);
$world->setBlock($this->position, $this);
}
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 20);
$world->scheduleDelayedBlockUpdate($this->position, 20);
}
private function recalculateSignalStrength() : int{
$lightLevel = $this->position->getWorld()->getRealBlockSkyLightAt($this->position->x, $this->position->y, $this->position->z);
$world = $this->position->getWorld();
$lightLevel = $world->getRealBlockSkyLightAt($this->position->x, $this->position->y, $this->position->z);
if($this->inverted){
return 15 - $lightLevel;
}
$sunAngle = $this->position->getWorld()->getSunAnglePercentage();
$sunAngle = $world->getSunAnglePercentage();
return max(0, (int) round($lightLevel * cos(($sunAngle + ((($sunAngle < 0.5 ? 0 : 1) - $sunAngle) / 5)) * 2 * M_PI)));
}

View File

@ -34,7 +34,7 @@ use function mt_rand;
class DeadBush extends Flowable{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->getSide(Facing::DOWN)->isTransparent()){
if($this->canBeSupportedBy($this->getSide(Facing::DOWN))){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -42,7 +42,7 @@ class DeadBush extends Flowable{
}
public function onNearbyBlockChange() : void{
if($this->getSide(Facing::DOWN)->isTransparent()){
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
$this->position->getWorld()->useBreakOn($this->position);
}
}
@ -64,4 +64,14 @@ class DeadBush extends Flowable{
public function getFlammability() : int{
return 100;
}
private function canBeSupportedBy(Block $block) : bool{
$blockId = $block->getId();
return $blockId === BlockLegacyIds::SAND
|| $blockId === BlockLegacyIds::PODZOL
|| $blockId === BlockLegacyIds::MYCELIUM
|| $blockId === BlockLegacyIds::DIRT
|| $blockId === BlockLegacyIds::HARDENED_CLAY
|| $blockId === BlockLegacyIds::STAINED_HARDENED_CLAY;
}
}

View File

@ -63,8 +63,9 @@ class Dirt extends Opaque{
$item->applyDamage(1);
$newBlock = $this->coarse ? VanillaBlocks::DIRT() : VanillaBlocks::FARMLAND();
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
$this->position->getWorld()->setBlock($this->position, $newBlock);
$world = $this->position->getWorld();
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
$world->setBlock($this->position, $newBlock);
return true;
}

View File

@ -163,13 +163,14 @@ class Door extends Transparent{
$this->open = !$this->open;
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
$world = $this->position->getWorld();
if($other instanceof Door && $other->isSameType($this)){
$other->open = $this->open;
$this->position->getWorld()->setBlock($other->position, $other);
$world->setBlock($other->position, $other);
}
$this->position->getWorld()->setBlock($this->position, $this);
$this->position->getWorld()->addSound($this->position, new DoorSound());
$world->setBlock($this->position, $this);
$world->addSound($this->position, new DoorSound());
return true;
}

View File

@ -62,8 +62,9 @@ class DragonEgg extends Transparent implements Fallable{
}
public function teleport() : void{
$world = $this->position->getWorld();
for($tries = 0; $tries < 16; ++$tries){
$block = $this->position->getWorld()->getBlockAt(
$block = $world->getBlockAt(
$this->position->x + mt_rand(-16, 16),
max(World::Y_MIN, min(World::Y_MAX - 1, $this->position->y + mt_rand(-8, 8))),
$this->position->z + mt_rand(-16, 16)
@ -76,9 +77,9 @@ class DragonEgg extends Transparent implements Fallable{
}
$blockPos = $ev->getTo();
$this->position->getWorld()->addParticle($this->position, new DragonEggTeleportParticle($this->position->x - $blockPos->x, $this->position->y - $blockPos->y, $this->position->z - $blockPos->z));
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::AIR());
$this->position->getWorld()->setBlock($blockPos, $this);
$world->addParticle($this->position, new DragonEggTeleportParticle($this->position->x - $blockPos->x, $this->position->y - $blockPos->y, $this->position->z - $blockPos->z));
$world->setBlock($this->position, VanillaBlocks::AIR());
$world->setBlock($blockPos, $this);
break;
}
}

View File

@ -78,16 +78,17 @@ class Farmland extends Transparent{
}
public function onRandomTick() : void{
$world = $this->position->getWorld();
if(!$this->canHydrate()){
if($this->wetness > 0){
$this->wetness--;
$this->position->getWorld()->setBlock($this->position, $this, false);
$world->setBlock($this->position, $this, false);
}else{
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::DIRT());
$world->setBlock($this->position, VanillaBlocks::DIRT());
}
}elseif($this->wetness < self::MAX_WETNESS){
$this->wetness = self::MAX_WETNESS;
$this->position->getWorld()->setBlock($this->position, $this, false);
$world->setBlock($this->position, $this, false);
}
}

View File

@ -117,8 +117,9 @@ class FenceGate extends Transparent{
}
}
$this->position->getWorld()->setBlock($this->position, $this);
$this->position->getWorld()->addSound($this->position, new DoorSound());
$world = $this->position->getWorld();
$world->setBlock($this->position, $this);
$world->addSound($this->position, new DoorSound());
return true;
}

View File

@ -100,10 +100,11 @@ class Fire extends Flowable{
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if($this->getSide(Facing::DOWN)->isTransparent() && !$this->hasAdjacentFlammableBlocks()){
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::AIR());
$world->setBlock($this->position, VanillaBlocks::AIR());
}else{
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(30, 40));
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(30, 40));
}
}
@ -136,11 +137,12 @@ class Fire extends Flowable{
}
}
$world = $this->position->getWorld();
if($result !== null){
$this->position->getWorld()->setBlock($this->position, $result);
$world->setBlock($this->position, $result);
}
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(30, 40));
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(30, 40));
if($canSpread){
$this->burnBlocksAround();
@ -181,7 +183,8 @@ class Fire extends Flowable{
if(!$ev->isCancelled()){
$block->onIncinerate();
if($this->position->getWorld()->getBlock($block->getPosition())->isSameState($block)){
$world = $this->position->getWorld();
if($world->getBlock($block->getPosition())->isSameState($block)){
$spreadedFire = false;
if(mt_rand(0, $this->age + 9) < 5){ //TODO: check rain
$fire = clone $this;
@ -189,7 +192,7 @@ class Fire extends Flowable{
$spreadedFire = $this->spreadBlock($block, $fire);
}
if(!$spreadedFire){
$this->position->getWorld()->setBlock($block->position, VanillaBlocks::AIR());
$world->setBlock($block->position, VanillaBlocks::AIR());
}
}
}

View File

@ -26,6 +26,10 @@ namespace pocketmine\block;
use pocketmine\block\utils\SupportType;
use pocketmine\math\AxisAlignedBB;
/**
* "Flowable" blocks are destroyed if water flows into the same space as the block. These blocks usually don't have any
* collision boxes, and can't provide support for other blocks.
*/
abstract class Flowable extends Transparent{
public function canBeFlowedInto() : bool{

View File

@ -122,6 +122,7 @@ class FlowerPot extends Flowable{
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$world = $this->position->getWorld();
$plant = $item->getBlock();
if($this->plant !== null){
if($this->isValidPlant($plant)){
@ -137,16 +138,16 @@ class FlowerPot extends Flowable{
$removedItems = $player->getInventory()->addItem(...$removedItems);
}
foreach($removedItems as $drops){
$this->position->getWorld()->dropItem($this->position->add(0.5, 0.5, 0.5), $drops);
$world->dropItem($this->position->add(0.5, 0.5, 0.5), $drops);
}
$this->setPlant(null);
$this->position->getWorld()->setBlock($this->position, $this);
$world->setBlock($this->position, $this);
return true;
}elseif($this->isValidPlant($plant)){
$this->setPlant($plant);
$item->pop();
$this->position->getWorld()->setBlock($this->position, $this);
$world->setBlock($this->position, $this);
return true;
}

View File

@ -56,16 +56,18 @@ class FrostedIce extends Ice{
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->checkAdjacentBlocks(2)){
$this->position->getWorld()->useBreakOn($this->position);
$world->useBreakOn($this->position);
}else{
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(20, 40));
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(20, 40));
}
}
public function onRandomTick() : void{
$world = $this->position->getWorld();
if((!$this->checkAdjacentBlocks(4) || mt_rand(0, 2) === 0) &&
$this->position->getWorld()->getHighestAdjacentFullLightAt($this->position->x, $this->position->y, $this->position->z) >= 12 - $this->age){
$world->getHighestAdjacentFullLightAt($this->position->x, $this->position->y, $this->position->z) >= 12 - $this->age){
if($this->tryMelt()){
foreach($this->getAllSides() as $block){
if($block instanceof FrostedIce){
@ -74,7 +76,7 @@ class FrostedIce extends Ice{
}
}
}else{
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(20, 40));
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(20, 40));
}
}
@ -106,18 +108,19 @@ class FrostedIce extends Ice{
* @return bool Whether the ice was destroyed.
*/
private function tryMelt() : bool{
$world = $this->position->getWorld();
if($this->age >= self::MAX_AGE){
$ev = new BlockMeltEvent($this, VanillaBlocks::WATER());
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
$world->setBlock($this->position, $ev->getNewState());
}
return true;
}
$this->age++;
$this->position->getWorld()->setBlock($this->position, $this);
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(20, 40));
$world->setBlock($this->position, $this);
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(20, 40));
return false;
}
}

View File

@ -83,12 +83,13 @@ class Furnace extends Opaque{
}
public function onScheduledUpdate() : void{
$furnace = $this->position->getWorld()->getTile($this->position);
$world = $this->position->getWorld();
$furnace = $world->getTile($this->position);
if($furnace instanceof TileFurnace && $furnace->onUpdate()){
if(mt_rand(1, 60) === 1){ //in vanilla this is between 1 and 5 seconds; try to average about 3
$this->position->getWorld()->addSound($this->position, $furnace->getFurnaceType()->getCookSound());
$world->addSound($this->position, $furnace->getFurnaceType()->getCookSound());
}
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1); //TODO: check this
$world->scheduleDelayedBlockUpdate($this->position, 1); //TODO: check this
}
}
}

View File

@ -53,13 +53,14 @@ class Grass extends Opaque{
}
public function onRandomTick() : void{
$lightAbove = $this->position->getWorld()->getFullLightAt($this->position->x, $this->position->y + 1, $this->position->z);
if($lightAbove < 4 && $this->position->getWorld()->getBlockAt($this->position->x, $this->position->y + 1, $this->position->z)->getLightFilter() >= 2){
$world = $this->position->getWorld();
$lightAbove = $world->getFullLightAt($this->position->x, $this->position->y + 1, $this->position->z);
if($lightAbove < 4 && $world->getBlockAt($this->position->x, $this->position->y + 1, $this->position->z)->getLightFilter() >= 2){
//grass dies
$ev = new BlockSpreadEvent($this, $this, VanillaBlocks::DIRT());
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState(), false);
$world->setBlock($this->position, $ev->getNewState(), false);
}
}elseif($lightAbove >= 9){
//try grass spread
@ -68,12 +69,12 @@ class Grass extends Opaque{
$y = mt_rand($this->position->y - 3, $this->position->y + 1);
$z = mt_rand($this->position->z - 1, $this->position->z + 1);
$b = $this->position->getWorld()->getBlockAt($x, $y, $z);
$b = $world->getBlockAt($x, $y, $z);
if(
!($b instanceof Dirt) ||
$b->isCoarse() ||
$this->position->getWorld()->getFullLightAt($x, $y + 1, $z) < 4 ||
$this->position->getWorld()->getBlockAt($x, $y + 1, $z)->getLightFilter() >= 2
$world->getFullLightAt($x, $y + 1, $z) < 4 ||
$world->getBlockAt($x, $y + 1, $z)->getLightFilter() >= 2
){
continue;
}
@ -81,7 +82,7 @@ class Grass extends Opaque{
$ev = new BlockSpreadEvent($b, $this, VanillaBlocks::GRASS());
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($b->position, $ev->getNewState(), false);
$world->setBlock($b->position, $ev->getNewState(), false);
}
}
}
@ -91,23 +92,24 @@ class Grass extends Opaque{
if($face !== Facing::UP){
return false;
}
$world = $this->position->getWorld();
if($item instanceof Fertilizer){
$item->pop();
TallGrassObject::growGrass($this->position->getWorld(), $this->position, new Random(mt_rand()), 8, 2);
TallGrassObject::growGrass($world, $this->position, new Random(mt_rand()), 8, 2);
return true;
}elseif($item instanceof Hoe){
$item->applyDamage(1);
$newBlock = VanillaBlocks::FARMLAND();
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
$this->position->getWorld()->setBlock($this->position, $newBlock);
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
$world->setBlock($this->position, $newBlock);
return true;
}elseif($item instanceof Shovel && $this->getSide(Facing::UP)->getId() === BlockLegacyIds::AIR){
$item->applyDamage(1);
$newBlock = VanillaBlocks::GRASS_PATH();
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
$this->position->getWorld()->setBlock($this->position, $newBlock);
$world->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
$world->setBlock($this->position, $newBlock);
return true;
}

View File

@ -51,11 +51,12 @@ class Ice extends Transparent{
}
public function onRandomTick() : void{
if($this->position->getWorld()->getHighestAdjacentBlockLight($this->position->x, $this->position->y, $this->position->z) >= 12){
$world = $this->position->getWorld();
if($world->getHighestAdjacentBlockLight($this->position->x, $this->position->y, $this->position->z) >= 12){
$ev = new BlockMeltEvent($this, VanillaBlocks::WATER());
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
$world->setBlock($this->position, $ev->getNewState());
}
}
}

View File

@ -31,6 +31,9 @@ use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\ItemFrameAddItemSound;
use pocketmine\world\sound\ItemFrameRemoveItemSound;
use pocketmine\world\sound\ItemFrameRotateItemSound;
use function is_infinite;
use function is_nan;
use function lcg_value;
@ -136,8 +139,12 @@ class ItemFrame extends Flowable{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->framedItem !== null){
$this->itemRotation = ($this->itemRotation + 1) % self::ROTATIONS;
$this->position->getWorld()->addSound($this->position, new ItemFrameRotateItemSound());
}elseif(!$item->isNull()){
$this->framedItem = $item->pop();
$this->position->getWorld()->addSound($this->position, new ItemFrameAddItemSound());
}else{
return true;
}
@ -151,11 +158,13 @@ class ItemFrame extends Flowable{
if($this->framedItem === null){
return false;
}
$world = $this->position->getWorld();
if(lcg_value() <= $this->itemDropChance){
$this->position->getWorld()->dropItem($this->position->add(0.5, 0.5, 0.5), clone $this->framedItem);
$world->dropItem($this->position->add(0.5, 0.5, 0.5), clone $this->framedItem);
$world->addSound($this->position, new ItemFrameRemoveItemSound());
}
$this->setFramedItem(null);
$this->position->getWorld()->setBlock($this->position, $this);
$world->setBlock($this->position, $this);
return true;
}
@ -166,7 +175,7 @@ class ItemFrame extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face === Facing::DOWN || $face === Facing::UP || !$blockClicked->isSolid()){
if($face === Facing::DOWN || $face === Facing::UP || !$blockReplace->getSide(Facing::opposite($face))->isSolid()){
return false;
}

View File

@ -26,6 +26,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\Jukebox as JukeboxTile;
use pocketmine\item\Item;
use pocketmine\item\Record;
use pocketmine\lang\KnownTranslationKeys;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\RecordSound;
@ -44,7 +45,7 @@ class Jukebox extends Opaque{
if($this->record !== null){
$this->ejectRecord();
}elseif($item instanceof Record){
$player->sendJukeboxPopup("record.nowPlaying", [$player->getLanguage()->translate($item->getRecordType()->getTranslatableName())]);
$player->sendJukeboxPopup(KnownTranslationKeys::RECORD_NOWPLAYING, [$player->getLanguage()->translate($item->getRecordType()->getTranslatableName())]);
$this->insertRecord($item->pop());
}
}

View File

@ -70,7 +70,7 @@ class Ladder extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($blockClicked, $face) && Facing::axis($face) !== Axis::Y){
if($this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face) && Facing::axis($face) !== Axis::Y){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}

View File

@ -84,6 +84,7 @@ class Leaves extends Transparent{
/**
* @param true[] $visited reference parameter
* @phpstan-param array<int, true> $visited
* @phpstan-param-out array<int, true> $visited
*/
protected function findLog(Vector3 $pos, array &$visited = [], int $distance = 0) : bool{
$index = World::blockHash($pos->x, $pos->y, $pos->z);
@ -123,11 +124,12 @@ class Leaves extends Transparent{
if(!$this->noDecay && $this->checkDecay){
$ev = new LeavesDecayEvent($this);
$ev->call();
$world = $this->position->getWorld();
if($ev->isCancelled() || $this->findLog($this->position)){
$this->checkDecay = false;
$this->position->getWorld()->setBlock($this->position, $this, false);
$world->setBlock($this->position, $this, false);
}else{
$this->position->getWorld()->useBreakOn($this->position);
$world->useBreakOn($this->position);
}
}
}

View File

@ -128,8 +128,9 @@ class Lectern extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->book === null && $item instanceof WritableBookBase){
$this->position->getWorld()->setBlock($this->position, $this->setBook($item));
$this->position->getWorld()->addSound($this->position, new LecternPlaceBookSound());
$world = $this->position->getWorld();
$world->setBlock($this->position, $this->setBook($item));
$world->addSound($this->position, new LecternPlaceBookSound());
$item->pop();
}
return true;
@ -137,8 +138,9 @@ class Lectern extends Transparent{
public function onAttack(Item $item, int $face, ?Player $player = null) : bool{
if($this->book !== null){
$this->position->getWorld()->dropItem($this->position->up(), $this->book);
$this->position->getWorld()->setBlock($this->position, $this->setBook(null));
$world = $this->position->getWorld();
$world->dropItem($this->position->up(), $this->book);
$world->setBlock($this->position, $this->setBook(null));
}
return false;
}
@ -152,12 +154,13 @@ class Lectern extends Transparent{
}
$this->viewedPage = $newPage;
$world = $this->position->getWorld();
if(!$this->producingSignal){
$this->producingSignal = true;
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1);
$world->scheduleDelayedBlockUpdate($this->position, 1);
}
$this->position->getWorld()->setBlock($this->position, $this);
$world->setBlock($this->position, $this);
return true;
}

View File

@ -95,7 +95,7 @@ class Lever extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockClicked, $face)){
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
return false;
}
@ -127,8 +127,9 @@ class Lever extends Flowable{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->activated = !$this->activated;
$this->position->getWorld()->setBlock($this->position, $this);
$this->position->getWorld()->addSound(
$world = $this->position->getWorld();
$world->setBlock($this->position, $this);
$world->addSound(
$this->position->add(0.5, 0.5, 0.5),
$this->activated ? new RedstonePowerOnSound() : new RedstonePowerOffSound()
);

View File

@ -329,7 +329,7 @@ abstract class Liquid extends Transparent{
}
if($adjacentDecay <= self::MAX_DECAY){
$calculator = new MinimumCostFlowCalculator($this->position->getWorld(), $this->getFlowDecayPerBlock(), \Closure::fromCallable([$this, 'canFlowInto']));
$calculator = new MinimumCostFlowCalculator($world, $this->getFlowDecayPerBlock(), \Closure::fromCallable([$this, 'canFlowInto']));
foreach($calculator->getOptimalFlowDirections($this->position->getFloorX(), $this->position->getFloorY(), $this->position->getFloorZ()) as $facing){
$this->flowIntoBlock($world->getBlock($this->position->getSide($facing)), $adjacentDecay, false);
}
@ -348,11 +348,12 @@ abstract class Liquid extends Transparent{
$ev = new BlockSpreadEvent($block, $this, $new);
$ev->call();
if(!$ev->isCancelled()){
$world = $this->position->getWorld();
if($block->getId() !== BlockLegacyIds::AIR){
$this->position->getWorld()->useBreakOn($block->position);
$world->useBreakOn($block->position);
}
$this->position->getWorld()->setBlock($block->position, $ev->getNewState());
$world->setBlock($block->position, $ev->getNewState());
}
}
}
@ -382,8 +383,9 @@ abstract class Liquid extends Transparent{
$ev = new BlockFormEvent($this, $result);
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new FizzSound(2.6 + (lcg_value() - lcg_value()) * 0.8));
$world = $this->position->getWorld();
$world->setBlock($this->position, $ev->getNewState());
$world->addSound($this->position->add(0.5, 0.5, 0.5), new FizzSound(2.6 + (lcg_value() - lcg_value()) * 0.8));
}
return true;
}

View File

@ -27,7 +27,7 @@ use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
class Melon extends Transparent{
class Melon extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
return [

View File

@ -49,13 +49,14 @@ class Mycelium extends Opaque{
$x = mt_rand($this->position->x - 1, $this->position->x + 1);
$y = mt_rand($this->position->y - 2, $this->position->y + 2);
$z = mt_rand($this->position->z - 1, $this->position->z + 1);
$block = $this->position->getWorld()->getBlockAt($x, $y, $z);
$world = $this->position->getWorld();
$block = $world->getBlockAt($x, $y, $z);
if($block instanceof Dirt && !$block->isCoarse()){
if($block->getSide(Facing::UP) instanceof Transparent){
$ev = new BlockSpreadEvent($block, $this, VanillaBlocks::MYCELIUM());
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($block->position, $ev->getNewState());
$world->setBlock($block->position, $ev->getNewState());
}
}
}

View File

@ -23,6 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
/**
* Opaque blocks do not allow light to pass through. They are usually collidable full-cube blocks.
* Most blocks in Minecraft fall into this category.
*/
class Opaque extends Block{
public function isSolid() : bool{

View File

@ -45,7 +45,7 @@ abstract class PressurePlate extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($blockClicked)){
if($this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
return false;
@ -55,5 +55,11 @@ abstract class PressurePlate extends Transparent{
return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE());
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
$this->position->getWorld()->useBreakOn($this->position);
}
}
//TODO
}

View File

@ -36,8 +36,9 @@ class Pumpkin extends Opaque{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($item instanceof Shears && in_array($face, Facing::HORIZONTAL, true)){
$item->applyDamage(1);
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::CARVED_PUMPKIN()->setFacing($face));
$this->position->getWorld()->dropItem($this->position->add(0.5, 0.5, 0.5), VanillaItems::PUMPKIN_SEEDS()->setCount(1));
$world = $this->position->getWorld();
$world->setBlock($this->position, VanillaBlocks::CARVED_PUMPKIN()->setFacing($face));
$world->dropItem($this->position->add(0.5, 0.5, 0.5), VanillaItems::PUMPKIN_SEEDS()->setCount(1));
return true;
}
return false;

View File

@ -43,7 +43,11 @@ class RedMushroom extends Flowable{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $this->getSide(Facing::DOWN);
if(!$down->isTransparent()){
$position = $this->getPosition();
$lightLevel = $position->getWorld()->getFullLightAt($position->x, $position->y, $position->z);
$downId = $down->getId();
//TODO: nylium support
if(($lightLevel <= 12 && !$down->isTransparent()) || $downId === BlockLegacyIds::MYCELIUM || $downId === BlockLegacyIds::PODZOL){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}

View File

@ -96,12 +96,13 @@ class Sapling extends Flowable{
}
public function onRandomTick() : void{
if($this->position->getWorld()->getFullLightAt($this->position->getFloorX(), $this->position->getFloorY(), $this->position->getFloorZ()) >= 8 && mt_rand(1, 7) === 1){
$world = $this->position->getWorld();
if($world->getFullLightAt($this->position->getFloorX(), $this->position->getFloorY(), $this->position->getFloorZ()) >= 8 && mt_rand(1, 7) === 1){
if($this->ready){
$this->grow(null);
}else{
$this->ready = true;
$this->position->getWorld()->setBlock($this->position, $this);
$world->setBlock($this->position, $this);
}
}
}

View File

@ -111,11 +111,12 @@ class SnowLayer extends Flowable implements Fallable{
}
public function onRandomTick() : void{
if($this->position->getWorld()->getBlockLightAt($this->position->x, $this->position->y, $this->position->z) >= 12){
$world = $this->position->getWorld();
if($world->getBlockLightAt($this->position->x, $this->position->y, $this->position->z) >= 12){
$ev = new BlockMeltEvent($this, VanillaBlocks::AIR());
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
$world->setBlock($this->position, $ev->getNewState());
}
}
}

View File

@ -35,13 +35,14 @@ abstract class Stem extends Crops{
public function onRandomTick() : void{
if(mt_rand(0, 2) === 1){
$world = $this->position->getWorld();
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());
$world->setBlock($this->position, $ev->getNewState());
}
}else{
$grow = $this->getPlant();
@ -57,7 +58,7 @@ abstract class Stem extends Crops{
$ev = new BlockGrowEvent($side, $grow);
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($side->position, $ev->getNewState());
$world->setBlock($side->position, $ev->getNewState());
}
}
}

View File

@ -31,6 +31,7 @@ use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\Position;
class Sugarcane extends Flowable{
public const MAX_AGE = 15;
@ -49,27 +50,37 @@ class Sugarcane extends Flowable{
return 0b1111;
}
private function grow() : bool{
private function seekToBottom() : Position{
$world = $this->position->getWorld();
$bottom = $this->position;
while(($next = $world->getBlock($bottom->down()))->isSameType($this)){
$bottom = $next->position;
}
return $bottom;
}
private function grow(Position $pos) : bool{
$grew = false;
$world = $pos->getWorld();
for($y = 1; $y < 3; ++$y){
if(!$this->position->getWorld()->isInWorld($this->position->x, $this->position->y + $y, $this->position->z)){
if(!$world->isInWorld($pos->x, $pos->y + $y, $pos->z)){
break;
}
$b = $this->position->getWorld()->getBlockAt($this->position->x, $this->position->y + $y, $this->position->z);
$b = $world->getBlockAt($pos->x, $pos->y + $y, $pos->z);
if($b->getId() === BlockLegacyIds::AIR){
$ev = new BlockGrowEvent($b, VanillaBlocks::SUGARCANE());
$ev->call();
if($ev->isCancelled()){
break;
}
$this->position->getWorld()->setBlock($b->position, $ev->getNewState());
$world->setBlock($b->position, $ev->getNewState());
$grew = true;
}else{
}elseif(!$b->isSameType($this)){
break;
}
}
$this->age = 0;
$this->position->getWorld()->setBlock($this->position, $this);
$world->setBlock($pos, $this);
return $grew;
}
@ -86,7 +97,7 @@ class Sugarcane extends Flowable{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($item instanceof Fertilizer){
if(!$this->getSide(Facing::DOWN)->isSameType($this) && $this->grow()){
if($this->grow($this->seekToBottom())){
$item->pop();
}
@ -110,7 +121,7 @@ class Sugarcane extends Flowable{
public function onRandomTick() : void{
if(!$this->getSide(Facing::DOWN)->isSameType($this)){
if($this->age === self::MAX_AGE){
$this->grow();
$this->grow($this->position);
}else{
++$this->age;
$this->position->getWorld()->setBlock($this->position, $this);

View File

@ -90,6 +90,7 @@ class SweetBerryBush extends Flowable{
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$world = $this->position->getWorld();
if($this->age < self::STAGE_MATURE && $item instanceof Fertilizer){
$block = clone $this;
$block->age++;
@ -98,13 +99,13 @@ class SweetBerryBush extends Flowable{
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
$world->setBlock($this->position, $ev->getNewState());
$item->pop();
}
}elseif(($dropAmount = $this->getBerryDropAmount()) > 0){
$this->position->getWorld()->setBlock($this->position, $this->setAge(self::STAGE_BUSH_NO_BERRIES));
$this->position->getWorld()->dropItem($this->position, $this->asItem()->setCount($dropAmount));
$world->setBlock($this->position, $this->setAge(self::STAGE_BUSH_NO_BERRIES));
$world->dropItem($this->position, $this->asItem()->setCount($dropAmount));
}
return true;

View File

@ -110,11 +110,12 @@ class TNT extends Opaque{
}
public function ignite(int $fuse = 80) : void{
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::AIR());
$world = $this->position->getWorld();
$world->setBlock($this->position, VanillaBlocks::AIR());
$mot = (new Random())->nextSignedFloat() * M_PI * 2;
$tnt = new PrimedTNT(Location::fromObject($this->position->add(0.5, 0, 0.5), $this->position->getWorld()));
$tnt = new PrimedTNT(Location::fromObject($this->position->add(0.5, 0, 0.5), $world));
$tnt->setFuse($fuse);
$tnt->setWorksUnderwater($this->worksUnderwater);
$tnt->setMotion(new Vector3(-sin($mot) * 0.02, 0.2, -cos($mot) * 0.02));

View File

@ -29,6 +29,9 @@ use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use function count;
/**
* Thin blocks behave like glass panes. They connect to full-cube blocks horizontally adjacent to them if possible.
*/
class Thin extends Transparent{
/** @var bool[] facing => dummy */
protected array $connections = [];
@ -38,7 +41,7 @@ class Thin extends Transparent{
foreach(Facing::HORIZONTAL as $facing){
$side = $this->getSide($facing);
if($side instanceof Thin || $side->isFullCube()){
if($side instanceof Thin || $side instanceof Wall || $side->isFullCube()){
$this->connections[$facing] = true;
}else{
unset($this->connections[$facing]);

View File

@ -65,7 +65,6 @@ class Torch extends Flowable{
}
public function onNearbyBlockChange() : void{
$below = $this->getSide(Facing::DOWN);
$face = Facing::opposite($this->facing);
if(!$this->canBeSupportedBy($this->getSide($face), $this->facing)){
@ -74,10 +73,7 @@ class Torch extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockClicked->canBeReplaced() && $this->canBeSupportedBy($blockClicked->getSide(Facing::DOWN), Facing::UP)){
$this->facing = Facing::UP;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}elseif($face !== Facing::DOWN && $this->canBeSupportedBy($blockClicked, $face)){
if($face !== Facing::DOWN && $this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}else{

View File

@ -23,6 +23,12 @@ declare(strict_types=1);
namespace pocketmine\block;
/**
* Transparent blocks do not block any light from propagating through them.
*
* Note: This does **not** imply that the block is **visually** transparent. For example, chests allow light to pass
* through, but the player cannot see through them except at the edges.
*/
class Transparent extends Block{
public function isTransparent() : bool{

View File

@ -96,8 +96,9 @@ class Trapdoor extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->open = !$this->open;
$this->position->getWorld()->setBlock($this->position, $this);
$this->position->getWorld()->addSound($this->position, new DoorSound());
$world = $this->position->getWorld();
$world->setBlock($this->position, $this);
$world->addSound($this->position, new DoorSound());
return true;
}
}

View File

@ -25,6 +25,9 @@ namespace pocketmine\block;
use pocketmine\item\Item;
/**
* Represents a block which is unrecognized or not implemented.
*/
class UnknownBlock extends Transparent{
public function __construct(BlockIdentifier $idInfo, BlockBreakInfo $breakInfo){

View File

@ -116,7 +116,7 @@ class Vine extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$blockClicked->isFullCube() || Facing::axis($face) === Axis::Y){
if(!$blockReplace->getSide(Facing::opposite($face))->isFullCube() || Facing::axis($face) === Axis::Y){
return false;
}
@ -141,10 +141,11 @@ class Vine extends Flowable{
}
if($changed){
$world = $this->position->getWorld();
if(count($this->faces) === 0){
$this->position->getWorld()->useBreakOn($this->position);
$world->useBreakOn($this->position);
}else{
$this->position->getWorld()->setBlock($this->position, $this);
$world->setBlock($this->position, $this);
}
}
}

View File

@ -39,7 +39,7 @@ class Wall 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 instanceof Thin || ($block->isSolid() && !$block->isTransparent())){
$this->connections[$facing] = $facing;
}else{
unset($this->connections[$facing]);

View File

@ -113,7 +113,7 @@ final class WallCoralFan extends BaseCoral{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$axis = Facing::axis($face);
if(($axis !== Axis::X && $axis !== Axis::Z) || !$this->canBeSupportedBy($blockClicked, $face)){
if(($axis !== Axis::X && $axis !== Axis::Z) || !$this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
return false;
}
$this->facing = $face;

View File

@ -39,19 +39,23 @@ class WaterLily extends Flowable{
return [AxisAlignedBB::one()->contract(1 / 16, 0, 1 / 16)->trim(Facing::UP, 63 / 64)];
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockClicked instanceof Water){
$up = $blockClicked->getSide(Facing::UP);
if($up->canBeReplaced()){
return parent::place($tx, $item, $up, $blockClicked, $face, $clickVector, $player);
}
}
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
return !$blockReplace instanceof Water && parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
}
return false;
private function canBeSupportedBy(Block $block) : bool{
return $block instanceof Water;
}
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::DOWN))){
return false;
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onNearbyBlockChange() : void{
if(!($this->getSide(Facing::DOWN) instanceof Water)){
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
$this->position->getWorld()->useBreakOn($this->position);
}
}

View File

@ -48,9 +48,10 @@ class BarrelInventory extends SimpleInventory implements BlockInventory{
protected function animateBlock(bool $isOpen) : void{
$holder = $this->getHolder();
$block = $holder->getWorld()->getBlock($holder);
$world = $holder->getWorld();
$block = $world->getBlock($holder);
if($block instanceof Barrel){
$holder->getWorld()->setBlock($holder, $block->setOpen($isOpen));
$world->setBlock($holder, $block->setOpen($isOpen));
}
}
}

View File

@ -135,7 +135,7 @@ class Banner extends Spawnable{
}
/**
* @param BannerPatternLayer[] $patterns
* @param BannerPatternLayer[] $patterns
*
* @phpstan-param list<BannerPatternLayer> $patterns
*/

View File

@ -52,7 +52,7 @@ trait ContainerTrait{
$newContents = [];
/** @var CompoundTag $itemNBT */
foreach($inventoryTag as $itemNBT){
$newContents[$itemNBT->getByte("Slot")] = Item::nbtDeserialize($itemNBT);
$newContents[$itemNBT->getByte(Item::TAG_SLOT)] = Item::nbtDeserialize($itemNBT);
}
$inventory->setContents($newContents);
@ -96,8 +96,10 @@ trait ContainerTrait{
$inv = $this->getRealInventory();
$pos = $this->getPosition();
$world = $pos->getWorld();
$dropPos = $pos->add(0.5, 0.5, 0.5);
foreach($inv->getContents() as $k => $item){
$pos->getWorld()->dropItem($pos->add(0.5, 0.5, 0.5), $item);
$world->dropItem($dropPos, $item);
}
$inv->clearAll();
}

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