Compare commits

..

153 Commits

Author SHA1 Message Date
a35c3406a8 Release 5.12.0 2024-02-28 18:14:37 +00:00
54ea404d80 Merge branch 'minor-next' into stable 2024-02-28 17:39:25 +00:00
98042f844f Merge remote-tracking branch 'origin/stable' into minor-next 2024-02-28 17:36:21 +00:00
a0cca53f52 Fixed mismatched predictions due to NBT key order differences
this is a pain :(
It appears the client always sorts the keys in alphabetical order due to use of std::map. However I'm not sure of the exact ordering behaviour, so it needs to be investigated.
2024-02-27 16:07:43 +00:00
6872118355 Update BedrockProtocol to release version 2024-02-27 14:15:31 +00:00
efd113bdc8 Integrate pmmp/BedrockProtocol@65b3d0b341 2024-02-26 17:09:09 +00:00
34a5f91aa9 5.11.3 is next 2024-02-26 14:45:48 +00:00
aee3656415 Release 5.11.2 2024-02-26 14:45:47 +00:00
c58e599eb2 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into stable 2024-02-26 14:35:40 +00:00
47f0119660 InGamePacketHandler: added an extra check 2024-02-26 14:35:21 +00:00
561ffd3da3 Bump pmmp/setup-php-action from 3.0.0 to 3.1.0 (#6267)
Bumps [pmmp/setup-php-action](https://github.com/pmmp/setup-php-action) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/pmmp/setup-php-action/releases)
- [Commits](https://github.com/pmmp/setup-php-action/compare/3.0.0...3.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-26 14:27:56 +00:00
b744e09352 5.11.2 is next 2024-02-23 14:19:02 +00:00
7b89dda420 Release 5.11.1 2024-02-23 14:19:01 +00:00
db665fefdb Harden JsonMapper defaults in general 2024-02-23 14:10:24 +00:00
6872661fd0 Harden JsonMapper on login JSON handling 2024-02-23 14:10:02 +00:00
920341668f Implemented working Name tag (#5209) 2024-02-19 18:46:48 +00:00
4fab518384 PluginManager: do not accept generator functions as event handlers
closes #4912

I didn't merge the original PR because this needs to be checked for explicitly registered handlers as well as auto-detected ones from listeners.
2024-02-19 16:53:53 +00:00
e06b042cd0 Bump pmmp/setup-php-action from 2.0.0 to 3.0.0 (#6259)
Bumps [pmmp/setup-php-action](https://github.com/pmmp/setup-php-action) from 2.0.0 to 3.0.0.
- [Release notes](https://github.com/pmmp/setup-php-action/releases)
- [Commits](https://github.com/pmmp/setup-php-action/compare/2.0.0...3.0.0)

---
updated-dependencies:
- dependency-name: pmmp/setup-php-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>
2024-02-19 16:16:28 +00:00
44ce9ca610 Bump phpstan/phpstan from 1.10.57 to 1.10.58 (#6260)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.57 to 1.10.58.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.57...1.10.58)

---
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>
2024-02-19 16:16:16 +00:00
2616d8c5ad New biome IDs, courtesy of build/generate-biome-ids 2024-02-19 16:10:46 +00:00
61d0181bfd Added script to generate biome IDs
this has been sitting in my local workspace for a very long time
2024-02-19 16:10:22 +00:00
db894e3a4a Fixed Utils::cloneObjectArray() template signature (#6255) 2024-02-16 16:52:10 +00:00
53cbc44d70 Update PULL_REQUEST_TEMPLATE.md
[ci skip]
2024-02-15 14:51:34 +00:00
be102dc95f Bump ncipollo/release-action from 1.13.0 to 1.14.0 (#6250)
Bumps [ncipollo/release-action](https://github.com/ncipollo/release-action) from 1.13.0 to 1.14.0.
- [Release notes](https://github.com/ncipollo/release-action/releases)
- [Commits](https://github.com/ncipollo/release-action/compare/v1.13.0...v1.14.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 11:51:31 +00:00
d211392b67 Merge remote-tracking branch 'origin/stable' into minor-next 2024-02-12 11:46:48 +00:00
eaab1a8784 ChunkSerializer: fixed count calculation for non-overworld chunks
plugins that implement dimensions can't change the number of subchunks used by Chunk, they can only choose to use a subset of them.
2024-02-07 18:58:41 +00:00
169d3e0de8 5.11.1 is next 2024-02-07 13:01:30 +00:00
ce8fecc6ec Release 5.11.0 2024-02-07 13:01:30 +00:00
4fcb644c51 Added missing imports 2024-02-07 12:51:39 +00:00
826cbea0bc Use newer php-cs-fixer on Actions 2024-02-07 12:51:27 +00:00
fe06bfcda0 Import alias cleanup courtesy of newest php-cs-fixer 2024-02-07 12:50:37 +00:00
f54ed8362d tools/convert-world: add a namespace
not sure why this was left in the global namespace to its own devices
2024-02-07 12:49:05 +00:00
8c7a4d720a Fixed inconsistent global namespace reference 2024-02-07 12:46:11 +00:00
6492e7f4a2 1.20.60 support 2024-02-07 12:33:44 +00:00
6bb84bc46c Add Promise::all (#6152) 2024-02-06 12:42:24 +00:00
20837c9894 Merge remote-tracking branch 'origin/stable' into minor-next 2024-02-05 12:43:39 +00:00
f207d1bbf2 Make CocoaBlock Flowable (#6218) 2024-02-05 12:36:09 +00:00
5709d727a2 Bump phpstan/phpstan from 1.10.55 to 1.10.57 (#6235)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.55 to 1.10.57.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.55...1.10.57)

---
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>
2024-02-05 12:30:19 +00:00
234199d241 Bump actions/cache from 3 to 4 (#6229)
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  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>
2024-02-05 12:29:49 +00:00
e28d20a68e Bump shivammathur/setup-php from 2.28.0 to 2.29.0 (#6228)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.28.0 to 2.29.0.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.28.0...2.29.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>
2024-02-05 12:29:34 +00:00
81d5b9ba06 tools/generate-bedrock-data-from-packets: add more exception detail for unexpected block runtimeIDs 2024-01-22 18:49:06 +00:00
d97c8e2fd2 tools/generate-item-upgrade-schema: filter old IDs that were already renamed by previous schemas
this caused weird outputs if an item was renamed multiple times.
2024-01-22 18:48:32 +00:00
c7c20d4d79 tools/generate-block-palette-spec: fixed sorting 2024-01-09 16:43:11 +00:00
c6a09e5ed8 Merge branch 'stable' into minor-next 2024-01-09 16:17:55 +00:00
e77cd39316 ItemBlock: add a workaround for air items with a stack size bigger than 0
In the future we should look into making empty slots be represented by null or a different, special item type, instead of breaking the air block for this purpose.

closes #6185
closes #6016
2024-01-09 15:55:41 +00:00
a459e3c1a9 Block: improve some documentation 2024-01-09 13:35:36 +00:00
288bd4018b Block: deprecate isSolid()
As discussed many years ago in #2551, no one actually knows what this property actually means. It definitely isn't the conventionally expected definition of 'solid' found in the real world, as signs are solid but flower pots are not.
2024-01-09 13:35:10 +00:00
9b03b082ab Added --version option 2024-01-09 13:04:14 +00:00
db3bb55a2b Change PHP_DEBUG constant usage to ZEND_DEBUG_BUILD
In PHP 8.4, the type of `PHP_DEBUG` changes from `int` to `bool`.
See [PHP.Watch: PHP 8.4: `PHP_ZTS` and `PHP_DEBUG` constant value type changed from `int` to `bool`](https://php.watch/versions/8.4/PHP_ZTS-PHP_DEBUG-const-type-change).

This changes the constants to `ZEND_DEBUG_BUILD`, which contains the same value but as a `bool` across all PHP versions.

closes #6222
2024-01-09 12:30:24 +00:00
8372c9efc2 Merge branch 'stable' into minor-next 2024-01-09 12:27:25 +00:00
4db38ee452 Updated PHPStan 2024-01-08 16:20:42 +00:00
ee977c8001 Updated composer dependencies 2024-01-08 16:18:13 +00:00
5b5c73f660 Matrixify jobs that run on all PHP versions
this allows us to specify PHP versions in just one place instead of 4,
and also makes the display of jobs in the UI nicer.
2024-01-08 16:13:09 +00:00
f83280ece6 Bump tests/plugins/DevTools from 411fd5b to c6dca35 (#6216)
Bumps [tests/plugins/DevTools](https://github.com/pmmp/DevTools) from `411fd5b` to `c6dca35`.
- [Release notes](https://github.com/pmmp/DevTools/releases)
- [Commits](411fd5bdc0...c6dca357c7)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-08 16:11:18 +00:00
19556634e3 Bump build/php from 73e5950 to 6f619bf (#6220)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `73e5950` to `6f619bf`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](73e5950eb9...6f619bf7a0)

---
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>
2024-01-08 16:08:54 +00:00
5718a1a20e Reduce frequency of annoying Dependabot updates
phpstan is releasing sometimes 4-5 times a week at this point, generating lots of noise.
2024-01-08 11:38:29 +00:00
5386e86079 ProcessLoginTask: remove old root key (#6211) 2024-01-03 12:50:05 +00:00
1b0ef468f3 CommonThreadPartsTrait: remove outdated documentation
This is now automatically called by the final run(), and the user now only needs to implement onRun(), so they have no business calling this function.
2023-12-21 13:09:05 +00:00
b69843a8bd CommonThreadPartsTrait: add common implementation of quit()
there's no need for the worker specialization here (isShutdown and shutdown are aliased to isJoined and join respectively), and the unstacking is not really desirable either as we previously learned with AsyncPool.
2023-12-21 12:56:51 +00:00
03619ebca9 Thread/Worker: Remove duplicated code
Despite the comments, there doesn't seem to be an obvious reason for these to be copy-pasted. Perhaps there was some legacy reason for this with legacy pthreads.
In fact, it looks likely that quit() will probably be able to be traitified too.
2023-12-21 12:44:03 +00:00
fd1bc1b845 AsyncWorker: deprecate ThreadStore methods
these are inconvenient and don't make any sense. It's far easier and more static-analysis-friendly to just use static properties.
2023-12-21 12:39:55 +00:00
c05116849a AsyncWorker: clean up nonsensical sleeper notifier handling code 2023-12-21 12:39:12 +00:00
7a55a6e6b6 ServerKiller: harden against spurious wakeups
If awakened by spurious wakeup, the thread would immediately exit without doing anything, rendering it useless.
Not sure how it took so long for this to be found...
2023-12-20 17:22:11 +00:00
bf99917f2a ThreadSafeClassLoader: add native property types 2023-12-20 17:01:20 +00:00
57f3a04bc5 data: Use statically analyzable ways of ensuring all cases are registered
PHPStan will verify that these matches cover all cases, which guarantees that all cases will be covered.
In addition, if PHPStan is not used, the constructors will immediately bail out when they hit a case that isn't covered.
The only downside is the extra indentation :(
2023-12-20 16:07:05 +00:00
c51b1b2812 Create LightableTrait and remove repetitive code (#6111) 2023-12-20 15:21:11 +00:00
80125f9b19 Modernize single-use phpstan-template tags 2023-12-20 15:20:28 +00:00
8dc28b7ea8 RuntimeDataDescriber: remove useless template parameter 2023-12-20 15:15:43 +00:00
58ce746ae1 Remove dead PHPStan ignored error 2023-12-20 14:44:24 +00:00
74cb0be868 Noise: give PHPStan some help understanding SplFixedArray 2023-12-20 14:43:36 +00:00
4d9b97d2bb Merge branch 'stable' into minor-next 2023-12-20 14:30:38 +00:00
90af8cfd69 Update composer dependencies 2023-12-20 14:29:02 +00:00
c8da9dea95 WorldManager: Remove unused if in unloadWorld() (#6203) 2023-12-20 10:38:00 +00:00
e1f4fd3048 ProcessLoginTask: remove dead comments
This is no longer an issue since b2df405cc0.
2023-12-15 16:01:43 +00:00
d3d7f24015 Noise: make calls with many parameters less nauseating to read 2023-12-15 15:32:54 +00:00
944dd7d3e4 BaseBanner: remove unnecessary array_filter() usage 2023-12-15 15:19:44 +00:00
a03013d582 Bump phpstan/phpstan from 1.10.47 to 1.10.50 (#6198)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.47 to 1.10.50.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.47...1.10.50)

---
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-12-15 14:49:32 +00:00
053abfbb6f Bump actions/upload-artifact from 3 to 4 (#6199)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  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-12-15 12:23:49 +00:00
00a8ea267c 5.10.1 is next 2023-12-14 16:54:42 +00:00
daeba95101 Release 5.10.0 2023-12-14 16:54:38 +00:00
a750af72db Updated build/php submodule to pmmp/PHP-Binaries@73e5950eb9 2023-12-14 16:05:38 +00:00
61decaa2f8 Merge branch 'minor-next' into stable 2023-12-14 16:04:51 +00:00
06b2e61d3c Merge remote-tracking branch 'origin/stable' into minor-next 2023-12-14 14:02:15 +00:00
b4838f5b4e 5.9.1 is next 2023-12-06 15:02:57 +00:00
46307973e3 Release 5.9.0 2023-12-06 15:02:57 +00:00
2f1d6115a0 Merge branch 'legacy/pm4' into stable 2023-12-06 14:55:18 +00:00
ba89ae5bf2 4.26.1 is next 2023-12-06 14:53:00 +00:00
30433bba10 Release 4.26.0 2023-12-06 14:52:59 +00:00
ed3fe2b727 Update dependencies for 1.20.50 2023-12-06 14:47:44 +00:00
927f129c6e Fixed borked world loading 2023-12-06 14:41:19 +00:00
2a136c7804 Update composer dependencies 2023-12-06 14:37:27 +00:00
25cca1b63f Changes for 1.20.50 2023-12-06 14:29:23 +00:00
15574ec99a Update composer dependencies 2023-12-06 14:28:30 +00:00
2420dee8be AsyncTask: Fix retrieval of null data from the thread-local storage (#6176) 2023-12-06 13:40:09 +00:00
bd65948453 Bump phpstan/phpstan from 1.10.46 to 1.10.47 (#6189)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.46 to 1.10.47.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.46...1.10.47)

---
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-12-06 13:29:40 +00:00
0984aa670d Bump phpstan/phpstan from 1.10.44 to 1.10.46 (#6182)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.44 to 1.10.46.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.44...1.10.46)

---
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-11-29 16:33:04 +00:00
239f9ed83a Bump shivammathur/setup-php from 2.27.1 to 2.28.0 (#6179)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.27.1 to 2.28.0.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.27.1...2.28.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-11-29 16:32:42 +00:00
b2df405cc0 NetworkSession: Send less information to clients on error disconnects
in particular, the information from VerifyLoginTask shouldn't be sent to clients, as it could contain sensitive information.
This change only affects disconnection screens. The server log shows the same amount of information as before (though formatted differently in some cases).
2023-11-29 16:31:59 +00:00
ace
d596dc571d Fix pitcher pod wrongly registered as a block (#6162) 2023-11-27 14:46:20 +00:00
bc11894f0a Bump build/php from 6b4c9c7 to b0ffbdb (#6178)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `6b4c9c7` to `b0ffbdb`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](6b4c9c76bd...b0ffbdbe33)

---
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-11-27 11:01:36 +00:00
d51475dc72 Bump docker/build-push-action from 5.0.0 to 5.1.0 (#6169)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.0.0 to 5.1.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5.0.0...v5.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-24 16:31:34 +00:00
233c8b746d Bump phpstan/phpstan from 1.10.41 to 1.10.44 (#6172)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.41 to 1.10.44.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.41...1.10.44)

---
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-11-24 16:31:18 +00:00
c1f0f13d5a Add PHP 8.3 to test matrix 2023-11-24 16:29:27 +00:00
06e2d36294 Bump build/php from 19f2ee6 to 6b4c9c7 (#6171)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `19f2ee6` to `6b4c9c7`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](19f2ee6d33...6b4c9c76bd)

---
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-11-22 11:06:32 +00:00
a1748a92ca Avoid unnecessary TypeConverter::getInstance() calls
we already have it available within these contexts
2023-11-17 14:00:25 +00:00
fbcf4649eb Avoid unnecessary Entity::getWorld() calls in loops 2023-11-17 13:58:41 +00:00
0f620fad94 ChunkCache: inline unnecessary function 2023-11-17 13:30:44 +00:00
67ad2bad17 World: fixed edge case that could lead to crash during block update sending 2023-11-17 13:24:06 +00:00
bc07778434 Avoid unnecessary CompressBatchPromise allocations for sync-prepared batches
Sync-prepared batches account for the vast majority of outbound packets. Avoiding these useless objects further reduces the overhead of zero-compressed packets, as the creation of these objects is a significant part of the overhead for these cases.

closes #6157
2023-11-17 12:35:42 +00:00
519784460f Merge branch 'stable' into minor-next 2023-11-17 12:04:10 +00:00
a25597ca30 Server: updated documentation for prepareBatch() 2023-11-17 12:01:19 +00:00
ace
89fbb3fd0d Fix loading of Item Frame item rotation (#6123) 2023-11-16 10:16:29 +00:00
e9c5846a06 World: simplify condition 2023-11-16 10:06:43 +00:00
886ed60e6a Bump build/php from 3c3c483 to 19f2ee6 (#6163)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `3c3c483` to `19f2ee6`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](3c3c483baa...19f2ee6d33)

---
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-11-16 09:39:26 +00:00
8f107e785b Bump dessant/support-requests from 3 to 4 (#6160)
Bumps [dessant/support-requests](https://github.com/dessant/support-requests) from 3 to 4.
- [Release notes](https://github.com/dessant/support-requests/releases)
- [Changelog](https://github.com/dessant/support-requests/blob/main/CHANGELOG.md)
- [Commits](https://github.com/dessant/support-requests/compare/v3...v4)

---
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>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-15 17:06:23 +00:00
69f197dbec PluginBase: fixed erroneous replacement 2023-11-14 13:04:14 +00:00
13f34a500c PluginBase: clean up inconsistent getter vs property access usages 2023-11-14 12:59:38 +00:00
e5c96faa4b Server: clean up inconsistent getter vs property access usages 2023-11-14 12:59:05 +00:00
dd98e4aaed block: clean up unnecessary getter usages
with the assistance of a custom phpstan rule
this inconsistent mess has been bothering me for a long time
2023-11-14 12:47:33 +00:00
e525699dd4 TimeTrackingSleeperHandler: record time spent in each Snooze handler 2023-11-13 11:35:39 +00:00
0ad6429fee Fix RegistryTrait documentation (#6153) 2023-11-13 11:15:07 +00:00
923c922960 Merge branch 'stable' into minor-next 2023-11-13 11:13:12 +00:00
77590fb63a Server: fixed prepareBatch() not being marked as internal 2023-11-13 11:12:12 +00:00
bd43ff6579 Update README.md
[ci skip]
2023-11-10 16:27:57 +00:00
c2189bc2df Update README.md
[ci skip]
2023-11-10 16:16:49 +00:00
58ea94bab8 ... 2023-11-10 15:41:17 +00:00
22b10e4cb0 Timings: Stop using BREAKDOWN group
with tree timings, the breakdown is actually pretty annoying, since it makes it hard to find a timer in the aggregate lists.
2023-11-10 15:36:35 +00:00
c44758f36c StringToItemParser: added pitcher_plant and pitcher_pod
it seems a bit weird to map pitcher_pod to PITCHER_CROP(). Perhaps this wasn't implemented correctly.
2023-11-10 15:26:02 +00:00
7a4cf8ef68 Prepare for PHP 8.2 as primary version 2023-11-09 19:04:53 +00:00
269b3d89a2 Update build/php submodule to pmmp/PHP-Binaries@39885cf248 2023-11-09 19:03:12 +00:00
b3766834c6 Merge branch 'stable' into minor-next 2023-11-09 19:02:08 +00:00
93699024da 5.8.3 is next 2023-11-09 18:51:20 +00:00
c3c81b09e8 Release 5.8.2 2023-11-09 18:51:17 +00:00
08f9873c32 Update build/php submodule to pmmp/PHP-Binaries@3c3c483baa 2023-11-09 18:30:03 +00:00
50592dc269 Merge branch 'stable' into minor-next 2023-11-09 18:05:38 +00:00
e3700cab50 ZlibCompressor: use libdeflate for level 0 compression
this is supported since libdeflate 1.15 and ext-libdeflate 0.2.0.
Everyone should be using these versions by now anyway, and if they aren't, they should update.

libdeflate's level 0 compression is over 20 times faster than zlib, so this is a nice performance improvement.
2023-11-09 18:05:07 +00:00
4103631bc1 Added Smithing Template items (#6132) 2023-11-09 14:25:49 +00:00
ace
c1ed182112 Fix loading of sign text from vanilla world (#6122) 2023-11-09 14:22:37 +00:00
5f3a2a5096 BlockStateUpgrader: fixed undefined array key when flattening a block whose new ID is the same as the old
this came up during 1.20.50 testing, where minecraft:stone[stone_type=stone] continues to have an ID minecraft:stone without the stone_type property.
This could have appeared in other ways, such as with an invalid legacy blockstate.
2023-11-08 18:52:22 +00:00
8ccaf907d1 tools/generate-blockstate-upgrade-schema: do not optimize state remaps with unchanged IDs
processRemappedStates() needs to know about the full set of states to generate reliable mappings.
Without it, it may generate flattening rules or state matching criteria that unintentionally match states that it's not aware of.
Sadly, this does make some schemas bigger, but it's for the best.
2023-11-08 15:19:02 +00:00
6b5c405939 Bump shivammathur/setup-php from 2.26.0 to 2.27.1 (#6142)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.26.0 to 2.27.1.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.26.0...2.27.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-08 12:06:43 +00:00
d09af2e30d World: don't assume that random Vector3 are int vectors
we can safely assume this for blocks (though the type info doesn't reflect it) but this is not safe to assume for random APIs that might be used by plugins.
2023-11-06 17:15:17 +00:00
bbe66e8e09 Block: Improve performance of encodeFullState()
if there's no state data to encode, we can avoid useless calls and object allocations.
For the best cases (blocks which don't use state data at all) this improves the performance of getStateId() by more than 10x.
Blocks which use one or the other benefit by a smaller but still significant margin.
2023-11-06 17:04:39 +00:00
457660235e Crops must have access to a light level of at least 9 2023-11-06 16:02:57 +00:00
9fc9609694 Fix ancient debris not being fireproof (#6138) 2023-11-06 15:01:43 +00:00
1055b7580a Bump phpstan/phpstan from 1.10.40 to 1.10.41 (#6139)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.40 to 1.10.41.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.40...1.10.41)

---
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-11-06 15:00:06 +00:00
3385087c56 Fix Iron & Gold ores not affected by fortune (#6134) 2023-11-04 10:57:53 +00:00
d3b7861d1a Constify bootstrap options 2023-11-02 16:15:57 +00:00
a6b36d6c3c CropGrowthHelper: avoid unnecessary checks 2023-11-02 15:32:22 +00:00
109673382d Implemented modifiers for crop growth speed
closes #6070

there are some unresolved questions about the growth speed of beetroots, pitcher plants and torchflower crops, but that's a topic for another commit.
this change also doesn't account for the light levels.
2023-11-02 15:16:11 +00:00
1e4a1565bb Stem: fixed not attaching to grown pumpkin/melon
no idea how this got missed ...
2023-11-02 14:48:45 +00:00
8aaa6dd176 Stem: do not disable ticking when the stem is not attached to a pumpkin
fixes #6131
2023-11-02 14:47:55 +00:00
07dff9c9e8 5.8.2 is next 2023-11-01 17:55:23 +00:00
155 changed files with 2645 additions and 1314 deletions

View File

@ -34,7 +34,10 @@ Requires translations:
## Tests
<!--
Details should be provided of tests done. Simply saying "tested" or equivalent is not acceptable.
Attach scripts or actions to test this pull request, as well as the result
PRs which have not been tested MUST be marked as draft.
-->
I tested this PR by doing the following (tick all that apply):
- [ ] Writing PHPUnit tests (commit these in the `tests/phpunit` folder)
- [ ] Playtesting using a Minecraft client (provide screenshots or a video)
- [ ] Writing a test plugin (provide the code and sample output)
- [ ] Other (provide details)

View File

@ -3,7 +3,7 @@ updates:
- package-ecosystem: composer
directory: "/"
schedule:
interval: daily
interval: weekly
time: "10:00"
open-pull-requests-limit: 10
ignore:
@ -21,4 +21,4 @@ updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
interval: weekly

View File

@ -53,7 +53,7 @@ jobs:
run: echo NAME=$(echo "${GITHUB_REPOSITORY,,}") >> $GITHUB_OUTPUT
- name: Build image for tag
uses: docker/build-push-action@v5.0.0
uses: docker/build-push-action@v5.1.0
with:
push: true
context: ./pocketmine-mp
@ -66,7 +66,7 @@ jobs:
- name: Build image for major tag
if: steps.channel.outputs.CHANNEL == 'stable'
uses: docker/build-push-action@v5.0.0
uses: docker/build-push-action@v5.1.0
with:
push: true
context: ./pocketmine-mp
@ -79,7 +79,7 @@ jobs:
- name: Build image for minor tag
if: steps.channel.outputs.CHANNEL == 'stable'
uses: docker/build-push-action@v5.0.0
uses: docker/build-push-action@v5.1.0
with:
push: true
context: ./pocketmine-mp
@ -92,7 +92,7 @@ jobs:
- name: Build image for latest tag
if: steps.channel.outputs.CHANNEL == 'stable'
uses: docker/build-push-action@v5.0.0
uses: docker/build-push-action@v5.1.0
with:
push: true
context: ./pocketmine-mp

View File

@ -13,12 +13,12 @@ jobs:
- uses: actions/checkout@v4
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.26.0
uses: shivammathur/setup-php@2.29.0
with:
php-version: 8.1
php-version: 8.2
- name: Restore Composer package cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
~/.cache/composer/files

View File

@ -12,7 +12,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php-version: [8.1]
php-version: [8.2]
steps:
- uses: actions/checkout@v4
@ -20,12 +20,12 @@ jobs:
submodules: true
- name: Setup PHP
uses: shivammathur/setup-php@2.26.0
uses: shivammathur/setup-php@2.29.0
with:
php-version: ${{ matrix.php-version }}
- name: Restore Composer package cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: |
~/.cache/composer/files
@ -77,7 +77,7 @@ jobs:
> build_info.json
- name: Upload release artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: release_artifacts
path: |
@ -86,7 +86,7 @@ jobs:
${{ github.workspace }}/build_info.json
- name: Create draft release
uses: ncipollo/release-action@v1.13.0
uses: ncipollo/release-action@v1.14.0
with:
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
commit: ${{ github.sha }}

165
.github/workflows/main-php-matrix.yml vendored Normal file
View File

@ -0,0 +1,165 @@
name: CI (all supported PHP versions)
on:
workflow_call:
inputs:
php:
description: 'PHP version in X.Y format'
required: true
type: string
#these are parameterized to ease updating
pm-version-major:
description: 'PocketMine-MP major version'
default: 5
type: number
image:
description: 'Runner image to use'
default: 'ubuntu-20.04'
type: string
jobs:
phpstan:
name: PHPStan analysis
runs-on: ${{ inputs.image }}
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: pmmp/setup-php-action@3.1.0
with:
php-version: ${{ inputs.php }}
install-path: "./bin"
pm-version-major: ${{ inputs.pm-version-major }}
- name: Restore Composer package cache
uses: actions/cache@v4
with:
path: |
~/.cache/composer/files
~/.cache/composer/vcs
key: "composer-v2-cache-${{ inputs.php }}-${{ hashFiles('./composer.lock') }}"
restore-keys: |
composer-v2-cache-
- name: Install Composer dependencies
run: composer install --prefer-dist --no-interaction
- name: Run PHPStan
run: ./vendor/bin/phpstan analyze --no-progress --memory-limit=2G
phpunit:
name: PHPUnit tests
runs-on: ${{ inputs.image }}
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: pmmp/setup-php-action@3.1.0
with:
php-version: ${{ inputs.php }}
install-path: "./bin"
pm-version-major: ${{ inputs.pm-version-major }}
- name: Restore Composer package cache
uses: actions/cache@v4
with:
path: |
~/.cache/composer/files
~/.cache/composer/vcs
key: "composer-v2-cache-${{ inputs.php }}-${{ hashFiles('./composer.lock') }}"
restore-keys: |
composer-v2-cache-
- name: Install Composer dependencies
run: composer install --prefer-dist --no-interaction
- name: Run PHPUnit tests
run: ./vendor/bin/phpunit --bootstrap vendor/autoload.php --fail-on-warning tests/phpunit
integration:
name: Integration tests
runs-on: ${{ inputs.image }}
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Setup PHP
uses: pmmp/setup-php-action@3.1.0
with:
php-version: ${{ inputs.php }}
install-path: "./bin"
pm-version-major: ${{ inputs.pm-version-major }}
- name: Restore Composer package cache
uses: actions/cache@v4
with:
path: |
~/.cache/composer/files
~/.cache/composer/vcs
key: "composer-v2-cache-${{ inputs.php }}-${{ hashFiles('./composer.lock') }}"
restore-keys: |
composer-v2-cache-
- name: Install Composer dependencies
run: composer install --no-dev --prefer-dist --no-interaction
- name: Run integration tests
run: ./tests/travis.sh -t4
codegen:
name: Generated Code consistency checks
runs-on: ${{ inputs.image }}
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: pmmp/setup-php-action@3.1.0
with:
php-version: ${{ inputs.php }}
install-path: "./bin"
pm-version-major: ${{ inputs.pm-version-major }}
- name: Restore Composer package cache
uses: actions/cache@v4
with:
path: |
~/.cache/composer/files
~/.cache/composer/vcs
key: "composer-v2-cache-${{ inputs.php }}-${{ hashFiles('./composer.lock') }}"
restore-keys: |
composer-v2-cache-
- name: Install Composer dependencies
run: composer install --no-dev --prefer-dist --no-interaction
- name: Regenerate registry annotations
run: php build/generate-registry-annotations.php src
- 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: Regenerate YmlServerProperties constants
run: php build/generate-pocketmine-yml-property-consts.php
- name: Verify code is unchanged
run: |
git diff
git diff --quiet

View File

@ -6,162 +6,17 @@ on:
workflow_dispatch:
jobs:
phpstan:
name: PHPStan analysis
runs-on: ${{ matrix.image }}
all-php-versions:
name: PHP ${{ matrix.php }}
strategy:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: ["8.1", "8.2"]
php: ["8.1", "8.2", "8.3"]
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: pmmp/setup-php-action@2.0.0
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
- name: Restore Composer package cache
uses: actions/cache@v3
with:
path: |
~/.cache/composer/files
~/.cache/composer/vcs
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
restore-keys: |
composer-v2-cache-
- name: Install Composer dependencies
run: composer install --prefer-dist --no-interaction
- name: Run PHPStan
run: ./vendor/bin/phpstan analyze --no-progress --memory-limit=2G
phpunit:
name: PHPUnit tests
runs-on: ${{ matrix.image }}
strategy:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: ["8.1", "8.2"]
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: pmmp/setup-php-action@2.0.0
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
- name: Restore Composer package cache
uses: actions/cache@v3
with:
path: |
~/.cache/composer/files
~/.cache/composer/vcs
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
restore-keys: |
composer-v2-cache-
- name: Install Composer dependencies
run: composer install --prefer-dist --no-interaction
- name: Run PHPUnit tests
run: ./vendor/bin/phpunit --bootstrap vendor/autoload.php --fail-on-warning tests/phpunit
integration:
name: Integration tests
runs-on: ${{ matrix.image }}
strategy:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: ["8.1", "8.2"]
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Setup PHP
uses: pmmp/setup-php-action@2.0.0
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
- name: Restore Composer package cache
uses: actions/cache@v3
with:
path: |
~/.cache/composer/files
~/.cache/composer/vcs
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
restore-keys: |
composer-v2-cache-
- name: Install Composer dependencies
run: composer install --no-dev --prefer-dist --no-interaction
- name: Run integration tests
run: ./tests/travis.sh -t4
codegen:
name: Generated Code consistency checks
runs-on: ${{ matrix.image }}
strategy:
fail-fast: false
matrix:
image: [ubuntu-20.04]
php: ["8.1", "8.2"]
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: pmmp/setup-php-action@2.0.0
with:
php-version: ${{ matrix.php }}
install-path: "./bin"
pm-version-major: "5"
- name: Restore Composer package cache
uses: actions/cache@v3
with:
path: |
~/.cache/composer/files
~/.cache/composer/vcs
key: "composer-v2-cache-${{ matrix.php }}-${{ hashFiles('./composer.lock') }}"
restore-keys: |
composer-v2-cache-
- name: Install Composer dependencies
run: composer install --no-dev --prefer-dist --no-interaction
- name: Regenerate registry annotations
run: php build/generate-registry-annotations.php src
- 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: Regenerate YmlServerProperties constants
run: php build/generate-pocketmine-yml-property-consts.php
- name: Verify code is unchanged
run: |
git diff
git diff --quiet
uses: ./.github/workflows/main-php-matrix.yml
with:
php: ${{ matrix.php }}
secrets: inherit
codestyle:
name: Code Style checks
@ -173,10 +28,10 @@ jobs:
- uses: actions/checkout@v4
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.26.0
uses: shivammathur/setup-php@2.29.0
with:
php-version: 8.1
tools: php-cs-fixer:3.17
php-version: 8.2
tools: php-cs-fixer:3.49
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

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

View File

@ -2,7 +2,7 @@
## Pre-requisites
- A bash shell (git bash is sufficient for Windows)
- [`git`](https://git-scm.com) available in your shell
- PHP 8.1 or newer available in your shell
- PHP 8.2 or newer available in your shell
- [`composer`](https://getcomposer.org) available in your shell
## Custom PHP binaries

View File

@ -20,31 +20,61 @@
<a href="https://github.com/pmmp/PocketMine-MP/releases/latest"><img alt="GitHub release (latest by SemVer)" src="https://img.shields.io/github/downloads/pmmp/PocketMine-MP/latest/total?sort=semver"></a>
</p>
## Getting started
## What is this?
PocketMine-MP is a highly customisable server software for Minecraft: Bedrock Edition, built from scratch in PHP, with over 10 years of history.
If you're looking to create a Minecraft: Bedrock server with **custom functionality**, look no further.
- 🧩 **Powerful plugin API** - extend and customise gameplay as you see fit
- 🗺️ **Rich ecosystem** and **large developer community** - find plugins easily and learn to develop your own
- 🌐 **Multi-world support** - offer a more varied game experience to players without transferring them to other server nodes
- 🏎️ **Performance** - get 100+ players onto one server (depending on hardware and plugins)
- ⤴️ **Continuously updated** - new Minecraft versions are usually supported within days
## :x: PocketMine-MP is NOT a vanilla Minecraft server software.
**It is poorly suited to hosting vanilla survival servers.**
It doesn't have many features from the vanilla game, such as vanilla world generation, redstone, mob AI, and various other things.
If you just want to play **vanilla survival multiplayer**, consider using the [official Minecraft: Bedrock server software](https://minecraft.net/download/server/bedrock) instead of PocketMine-MP.
If that's not an option for you, you may be able to add some of PocketMine-MP's missing features using plugins from [Poggit](https://poggit.pmmp.io/plugins), or write plugins to implement them yourself.
## Getting Started
- [Documentation](http://pmmp.readthedocs.org/)
- [Installation instructions](https://pmmp.readthedocs.io/en/rtfd/installation.html)
- [Docker image](https://github.com/pmmp/PocketMine-MP/pkgs/container/pocketmine-mp)
- [Plugin repository](https://poggit.pmmp.io/plugins)
## Community & Support
- [Forums](https://forums.pmmp.io/)
- [Discord](https://discord.gg/bmSAZBG)
- [StackOverflow](https://stackoverflow.com/tags/pocketmine)
Join our [Discord](https://discord.gg/bmSAZBG) server to chat with other users and developers.
You can also post questions on [StackOverflow](https://stackoverflow.com/tags/pocketmine) under the tag `pocketmine`.
## Developing Plugins
If you want to write your own plugins, the following resources may be useful.
Don't forget you can always ask our community if you need help.
## For developers
* [Building and running from source](BUILDING.md)
* [Developer documentation](https://devdoc.pmmp.io) - General documentation for PocketMine-MP plugin developers
* [Latest release API documentation](https://apidoc.pmmp.io) - Doxygen API documentation generated for each release
* [Latest bleeding-edge API documentation](https://apidoc-dev.pmmp.io) - Doxygen API documentation generated weekly from `major-next` branch
* [DevTools](https://github.com/pmmp/DevTools/) - Development tools plugin for creating plugins
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
## Contributing to PocketMine-MP
PocketMine-MP accepts community contributions! The following resources will be useful if you want to contribute to PocketMine-MP.
* [Building and running PocketMine-MP from source](BUILDING.md)
* [Contributing Guidelines](CONTRIBUTING.md)
## Donate
- Bitcoin Cash (BCH): `qq3r46hn6ljnhnqnfwxt5pg3g447eq9jhvw5ddfear`
PocketMine-MP is free, but it requires a lot of time and effort from unpaid volunteers to develop. Donations enable us to keep delivering support for new versions and adding features your players love.
You can support development using the following methods:
- [Patreon](https://www.patreon.com/pocketminemp)
- Bitcoin (BTC): `171u8K9e4FtU6j3e5sqNoxKUgEw9qWQdRV`
- Stellar Lumens (XLM): `GAAC5WZ33HCTE3BFJFZJXONMEIBNHFLBXM2HJVAZHXXPYA3HP5XPPS7T`
- [Patreon](https://www.patreon.com/pocketminemp)
Thanks for your support!
## Licensing information
This project is licensed under LGPL-3.0. Please see the [LICENSE](/LICENSE) file for details.

View File

@ -0,0 +1,133 @@
<?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_biome_ids;
use pocketmine\data\bedrock\BedrockDataFiles;
use pocketmine\utils\Filesystem;
use pocketmine\utils\Utils;
use function asort;
use function dirname;
use function fclose;
use function fopen;
use function fwrite;
use function is_array;
use function is_int;
use function is_string;
use function json_decode;
use function str_replace;
use function strtoupper;
use const SORT_NUMERIC;
require dirname(__DIR__) . '/vendor/autoload.php';
const HEADER = <<<'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);
HEADER;
/** @return resource */
function safe_fopen(string $file, string $flags){
$result = fopen($file, $flags);
if($result === false){
throw new \RuntimeException("Failed to open file");
}
return $result;
}
function make_const_name(string $name) : string{
return strtoupper(str_replace(['.', 'minecraft:'], ['_', ''], $name));
}
/**
* @param int[] $map
* @phpstan-param array<string, int> $map
*/
function generate(array $map, string $outputFile) : void{
$file = safe_fopen($outputFile, 'wb');
fwrite($file, HEADER);
fwrite($file, <<<'CLASSHEADER'
namespace pocketmine\data\bedrock;
final class BiomeIds{
private function __construct(){
//NOOP
}
CLASSHEADER
);
$list = $map;
asort($list, SORT_NUMERIC);
$lastId = -1;
foreach(Utils::stringifyKeys($list) as $name => $id){
if($name === ""){
continue;
}
if($id !== $lastId + 1){
fwrite($file, "\n");
}
$lastId = $id;
fwrite($file, "\tpublic const " . make_const_name($name) . ' = ' . $id . ';' . "\n");
}
fwrite($file, "}\n");
fclose($file);
}
$ids = json_decode(Filesystem::fileGetContents(BedrockDataFiles::BIOME_ID_MAP_JSON), true);
if(!is_array($ids)){
throw new \RuntimeException("Invalid biome ID map, expected array for root JSON object");
}
$cleanedIds = [];
foreach($ids as $name => $id){
if(!is_string($name) || !is_int($id)){
throw new \RuntimeException("Invalid biome ID map, expected string => int map");
}
$cleanedIds[$name] = $id;
}
generate($cleanedIds, dirname(__DIR__) . '/src/data/bedrock/BiomeIds.php');
echo "Done. Don't forget to run CS fixup after generating code.\n";

View File

@ -21,6 +21,9 @@
declare(strict_types=1);
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\VersionInfo;
require dirname(__DIR__) . '/vendor/autoload.php';
if(count($argv) !== 7){
@ -30,12 +33,12 @@ if(count($argv) !== 7){
echo json_encode([
"php_version" => sprintf("%d.%d", PHP_MAJOR_VERSION, PHP_MINOR_VERSION), //deprecated
"base_version" => \pocketmine\VersionInfo::BASE_VERSION,
"base_version" => VersionInfo::BASE_VERSION,
"build" => (int) $argv[4],
"is_dev" => \pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD,
"channel" => \pocketmine\VersionInfo::BUILD_CHANNEL,
"is_dev" => VersionInfo::IS_DEVELOPMENT_BUILD,
"channel" => VersionInfo::BUILD_CHANNEL,
"git_commit" => $argv[1],
"mcpe_version" => \pocketmine\network\mcpe\protocol\ProtocolInfo::MINECRAFT_VERSION_NETWORK,
"mcpe_version" => ProtocolInfo::MINECRAFT_VERSION_NETWORK,
"date" => time(), //TODO: maybe we should embed this in VersionInfo?
"details_url" => "https://github.com/$argv[3]/releases/tag/$argv[2]",
"download_url" => "https://github.com/$argv[3]/releases/download/$argv[2]/PocketMine-MP.phar",

View File

@ -32,6 +32,7 @@ use function getcwd;
use function getopt;
use function implode;
use function ini_get;
use function is_string;
use function microtime;
use function preg_quote;
use function realpath;
@ -147,8 +148,17 @@ function main() : void{
}else{
$build = 0;
}
if(isset($opts["out"])){
if(!is_string($opts["out"])){
echo "--out cannot be specified multiple times" . PHP_EOL;
exit(1);
}
$pharPath = $opts["out"];
}else{
$pharPath = getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar";
}
foreach(buildPhar(
$opts["out"] ?? getcwd() . DIRECTORY_SEPARATOR . "PocketMine-MP.phar",
$pharPath,
dirname(__DIR__) . DIRECTORY_SEPARATOR,
[
'resources',

16
changelogs/4.26.md Normal file
View File

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

46
changelogs/5.10.md Normal file
View File

@ -0,0 +1,46 @@
# 5.10.0
Released 14th December 2023.
**For Minecraft: Bedrock Edition 1.20.50**
This is a minor feature release, including new gameplay features and minor performance improvements.
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## General
- PHP 8.2 is now used by default. PHP 8.1 is still supported, but will be removed in a future 5.x release.
- Improved timings reports by removing `Breakdown` timings group. This group serves no purpose with tree timings and made for confusing reading.
## Performance
- Improved performance of `Block::encodeFullState()` in most conditions. This in turn improves performance of `World::setBlock()` and `World::setBlockAt()`.
- Improved network compression performance by avoiding unnecessary object allocations.
- Timings now report time spent in individual `Snooze` handlers, making it easier to debug performance issues.
## Gameplay
### Blocks
- Implemented crop growth speed modifiers.
- The following things now positively affect crop growth speed:
- Being planted on or being adjacent to farmland (hydrated farmland offers a larger benefit than dry farmland)
- Potential light level of at least 9
- Being planted in rows with space between them (or a different type of crop)
- The following things now negatively affect crop growth speed:
- Improper arrangement (e.g. the same crop on all sides)
- Insufficient light level (below 9)
- Poorly arranged crops will grow slower in this version. Past versions behaved as if crops were always planted in ideal conditions.
- Crops planted in ideal conditions will grow at the same speed as before.
### Items
- Added the following new items:
- All types of Smithing Template
- Pitcher Pod is now correctly registered. In previous versions, it was mapped to the Pitcher Crop block, causing incorrect name display in commands.
## Internals
- Cleaned up various getter usages where direct property access is possible.
- Avoided unnecessary repeated getter calls in some loops.
- `NetworkSession` may now track `string` instead of `CompressBatchPromise` when a batch was synchronously compressed. This significantly reduces object allocations and improves performance.
- `NetworkSession` now sends less information to clients on login validation failure. This avoids leaking potentially sensitive error information to clients.
- Clients can correlate their disconnects with server-side logs using the `Error ID` shown on the disconnect screen.

45
changelogs/5.11.md Normal file
View File

@ -0,0 +1,45 @@
# 5.11.0
Released 7th February 2024.
**For Minecraft: Bedrock Edition 1.20.60**
This is a support release for Minecraft: Bedrock Edition 1.20.60.
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## General
- Added support for Minecraft: Bedrock Edition 1.20.60.
- Removed support for earlier versions.
## Fixes
- Fixed `tools/generate-item-upgrade-schema.php` not correctly handling items whose IDs were changed multiple times.
- Fixed `ServerKiller` not working correctly in some cases (incorrectly handled wake-up conditions).
- `ItemBlock`s of `Air` blocks are now always considered as "null" items regardless of count, and don't occupy inventory slots.
## Internals
- Restructured GitHub Actions CI workflows to make them easier to maintain (no need to update PHP versions in multiple places anymore).
- GitHub Actions CodeStyle workflow now uses php-cs-fixer 3.49.x.
- Dependabot updates are now processed weekly instead of daily.
# 5.11.1
Released 23rd February 2024.
## Fixes
- Fixed subchunk count calculation in `ChunkSerializer` for non-overworld dimension (useful for dimension plugins).
- Harden options used for processing JSON data, particularly on the network, to close security issues.
## Documentation
- Fixed PHPStan signature for `Utils::cloneObjectArray()`.
## Internals
- Updated GitHub Actions versions to get rid of deprecation warnings.
# 5.11.2
Released 26th February 2024.
## Fixes
- Added extra checks for `BookEditPacket` handling.

54
changelogs/5.12.md Normal file
View File

@ -0,0 +1,54 @@
# 5.12.0
Released 28th February 2024
**For Minecraft: Bedrock Edition 1.20.60**
This is a minor feature release, with a few new features and improvements.
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## General
- Added a `--version` command-line option to display the server version and exit.
## Tools
- Added `tools/generate-biome-ids.php` to generate `pocketmine\data\bedrock\BiomeIds`.
- Fixed ordering of property values generated by `tools/generate-block-palette-spec.php`.
## API
### `pocketmine\block`
- The following new classes have been added:
- `utils\LightableTrait` - used by blocks with `getLit()` and `setLit()` methods
- The following methods have been deprecated:
- `Block->isSolid()` - this method returns confusing results which don't match expectations and no one really knows what it actually means
- `CocoaBlock` now extends `Flowable` to match vanilla Minecraft behaviour.
### `pocketmine\plugin`
- `PluginManager->registerEvent()` now throws an exception when given a generator function for the event handler.
- `PluginManager->registerEvents()` now throws an exception if any of the detected event handlers are generator functions. Use `@notHandler` to have the function ignored if intended.
### `pocketmine\promise`
- The following methods have been added:
- `public static Promise::all(list<Promise> $promises) : Promise` - returns a promise that is resolved once all given promises are resolved, or is rejected if any of the promises are rejected.
### `pocketmine\scheduler`
- The following methods have been deprecated:
- `AsyncWorker->getFromThreadStore()` - use class static properties for thread-local storage
- `AsyncWorker->removeFromThreadStore()`
- `AsyncWorker->saveToThreadStore()`
## Documentation
- Improved documentation of various methods in `Block`.
## Gameplay
- The following new items have been added:
- Name Tag
## Internals
- Removed specialization of shutdown logic for `Thread` vs `Worker` (no specialization is required).
- Authentication system no longer accepts logins signed with the old Mojang root public key.
- ID to enum mappings in `pocketmine\data` now use a new `match` convention to allow static analysis to ensure that all enum cases are handled.
- Updated version of `pocketmine/bedrock-protocol` allows avoiding decoding of some itemstack data from the client in most cases, improving performance.

View File

@ -117,3 +117,22 @@ Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if
- Removed code generation step for `RuntimeDataDescriber` enum serialization. All described enums now use PHP 8.1 native enums, which can be described without codegen using `RuntimeDataDescriber->enum()`.
- Added `DeprecatedLegacyEnumAccessRule` custom PHPStan rule to flag legacy `EnumTrait` case accessors.
- Cleaned up remaining hardcoded `Config` keys in `SetupWizard`. These usages now use auto-generated constants like the rest of the codebase.
# 5.8.2
Released 9th November 2023.
## Performance
- Improved performance of small packet zero-compression (unintended use of slow zlib compressor instead of fast libdeflate one).
- This affected the majority of outbound packets, as most packets are below the 256-byte threshold for compression.
- This faster method is over 20x faster than the old method, producing noticeable performance gains for large servers.
## Fixes
- Fixed melons and pumpkins not growing.
- Fixed melon and pumpkin stems not attaching to the grown melon/pumpkin.
- Fixed iron and gold ores not being affected by the Fortune enchantment.
- Fixed ancient debris burning in lava.
- Fixed sign (front) text loading from vanilla world saves (back text is not yet supported).
## Internals
- Removed bogus optimization from `tools/generate-blockstate-upgrade-schema.php` that could cause incorrect `remappedStates` generation when some of the states stayed under the old ID.
- Fixed possible crash in `BlockStateUpgrader` name flattening rule handling with invalid blockstate NBT data.

30
changelogs/5.9.md Normal file
View File

@ -0,0 +1,30 @@
# 5.9.0
Released 6th December 2023.
**For Minecraft: Bedrock Edition 1.20.50**
This is a support release for Minecraft: Bedrock Edition 1.20.50.
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## General
- Added support for Minecraft: Bedrock Edition 1.20.50.
- Removed support for older versions.
## Fixes
- Fixed `pitcher_plant` and `pitcher_pod` not being accepted by `StringToItemParser` (and therefore not being usable in commands).
- Rotation of items in item frames in worlds from newer versions of Bedrock is now correctly loaded.
- Fixed possible crash in block update sending if a chunk was unloaded during a previous chunk's block update syncing.
- Fixed `AsyncTask::fetchLocal()` throwing an exception if `null` was stored in the local storage.
## Documentation
- `Server::prepareBatch()` is now correctly marked as `@internal`.
- Updated documentation for `Server::prepareBatch()` to accurately reflect its behaviour.
- Fixed incorrect path in doc comments of `EnumTrait` and `RegistryTrait`.
## Internals
- Added PHP 8.3 to the test matrix. This has not been thoroughly tested yet, so it should only be used for testing purposes.

View File

@ -32,11 +32,11 @@
"ext-zlib": ">=1.2.11",
"composer-runtime-api": "^2.0",
"adhocore/json-comment": "~1.2.0",
"pocketmine/netresearch-jsonmapper": "~v4.2.1000",
"pocketmine/bedrock-block-upgrade-schema": "~3.3.0+bedrock-1.20.40",
"pocketmine/bedrock-data": "~2.6.0+bedrock-1.20.40",
"pocketmine/bedrock-item-upgrade-schema": "~1.5.0+bedrock-1.20.30",
"pocketmine/bedrock-protocol": "~25.0.0+bedrock-1.20.40",
"pocketmine/netresearch-jsonmapper": "~v4.4.999",
"pocketmine/bedrock-block-upgrade-schema": "~3.5.0+bedrock-1.20.60",
"pocketmine/bedrock-data": "~2.8.0+bedrock-1.20.60",
"pocketmine/bedrock-item-upgrade-schema": "~1.7.0+bedrock-1.20.60",
"pocketmine/bedrock-protocol": "~28.0.0+bedrock-1.20.60",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/color": "^0.3.0",
@ -49,10 +49,10 @@
"pocketmine/raklib-ipc": "^0.2.0",
"pocketmine/snooze": "^0.5.0",
"ramsey/uuid": "~4.7.0",
"symfony/filesystem": "~6.3.0"
"symfony/filesystem": "~6.4.0"
},
"require-dev": {
"phpstan/phpstan": "1.10.40",
"phpstan/phpstan": "1.10.58",
"phpstan/phpstan-phpunit": "^1.1.0",
"phpstan/phpstan-strict-rules": "^1.2.0",
"phpunit/phpunit": "~10.3.0 || ~10.2.0 || ~10.1.0"

195
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ca499c3c5acafac837f7384ecdae136e",
"content-hash": "f43d60f8c44393f5c42b7ba27cd8ccc0",
"packages": [
{
"name": "adhocore/json-comment",
@ -122,16 +122,16 @@
},
{
"name": "pocketmine/bedrock-block-upgrade-schema",
"version": "3.3.0",
"version": "3.5.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockBlockUpgradeSchema.git",
"reference": "ee46b9367af262bbddd9f122d4d5b5b495b892e7"
"reference": "1ed4ba738333c4b4afe4fef8e9326a45c89f12e3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/ee46b9367af262bbddd9f122d4d5b5b495b892e7",
"reference": "ee46b9367af262bbddd9f122d4d5b5b495b892e7",
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/1ed4ba738333c4b4afe4fef8e9326a45c89f12e3",
"reference": "1ed4ba738333c4b4afe4fef8e9326a45c89f12e3",
"shasum": ""
},
"type": "library",
@ -142,22 +142,22 @@
"description": "Schemas describing how to upgrade saved block data in older Minecraft: Bedrock Edition world saves",
"support": {
"issues": "https://github.com/pmmp/BedrockBlockUpgradeSchema/issues",
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/3.3.0"
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/3.5.0"
},
"time": "2023-10-16T16:11:02+00:00"
"time": "2024-02-07T11:46:50+00:00"
},
{
"name": "pocketmine/bedrock-data",
"version": "2.6.0+bedrock-1.20.40",
"version": "2.8.0+bedrock-1.20.60",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockData.git",
"reference": "37e780d28b470230bda3579b04cb50d406e3fbe6"
"reference": "d8ea0355b7c835564af9fe6e273e650ac62c84a2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/37e780d28b470230bda3579b04cb50d406e3fbe6",
"reference": "37e780d28b470230bda3579b04cb50d406e3fbe6",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/d8ea0355b7c835564af9fe6e273e650ac62c84a2",
"reference": "d8ea0355b7c835564af9fe6e273e650ac62c84a2",
"shasum": ""
},
"type": "library",
@ -168,22 +168,22 @@
"description": "Blobs of data generated from Minecraft: Bedrock Edition, used by PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/BedrockData/issues",
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.20.40"
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.20.60"
},
"time": "2023-10-26T10:39:13+00:00"
"time": "2024-02-07T11:23:46+00:00"
},
{
"name": "pocketmine/bedrock-item-upgrade-schema",
"version": "1.5.0",
"version": "1.7.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockItemUpgradeSchema.git",
"reference": "3edc9ebbad9a4f2d9c8f53b3a5ba44d4a792ad93"
"reference": "69772dd58e2b2c7b7513fa2bcdc46e782228641c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/3edc9ebbad9a4f2d9c8f53b3a5ba44d4a792ad93",
"reference": "3edc9ebbad9a4f2d9c8f53b3a5ba44d4a792ad93",
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/69772dd58e2b2c7b7513fa2bcdc46e782228641c",
"reference": "69772dd58e2b2c7b7513fa2bcdc46e782228641c",
"shasum": ""
},
"type": "library",
@ -194,27 +194,26 @@
"description": "JSON schemas for upgrading items found in older Minecraft: Bedrock world saves",
"support": {
"issues": "https://github.com/pmmp/BedrockItemUpgradeSchema/issues",
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.5.0"
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.7.0"
},
"time": "2023-09-01T19:58:57+00:00"
"time": "2024-02-07T11:58:05+00:00"
},
{
"name": "pocketmine/bedrock-protocol",
"version": "25.0.0+bedrock-1.20.40",
"version": "28.0.0+bedrock-1.20.60",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "69c36c96f6835e93fc278071aa2bb9829abe5cf8"
"reference": "6e73f21cdc7433f0674dfcdf4817f478aa5528e6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/69c36c96f6835e93fc278071aa2bb9829abe5cf8",
"reference": "69c36c96f6835e93fc278071aa2bb9829abe5cf8",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/6e73f21cdc7433f0674dfcdf4817f478aa5528e6",
"reference": "6e73f21cdc7433f0674dfcdf4817f478aa5528e6",
"shasum": ""
},
"require": {
"ext-json": "*",
"netresearch/jsonmapper": "^4.0",
"php": "^8.1",
"pocketmine/binaryutils": "^0.2.0",
"pocketmine/color": "^0.2.0 || ^0.3.0",
@ -223,10 +222,10 @@
"ramsey/uuid": "^4.1"
},
"require-dev": {
"phpstan/phpstan": "1.10.33",
"phpstan/phpstan": "1.10.59",
"phpstan/phpstan-phpunit": "^1.0.0",
"phpstan/phpstan-strict-rules": "^1.0.0",
"phpunit/phpunit": "^9.5"
"phpunit/phpunit": "^9.5 || ^10.0"
},
"type": "library",
"autoload": {
@ -241,9 +240,9 @@
"description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP",
"support": {
"issues": "https://github.com/pmmp/BedrockProtocol/issues",
"source": "https://github.com/pmmp/BedrockProtocol/tree/25.0.0+bedrock-1.20.40"
"source": "https://github.com/pmmp/BedrockProtocol/tree/28.0.0+bedrock-1.20.60"
},
"time": "2023-10-26T11:03:10+00:00"
"time": "2024-02-26T16:18:34+00:00"
},
{
"name": "pocketmine/binaryutils",
@ -563,16 +562,16 @@
},
{
"name": "pocketmine/netresearch-jsonmapper",
"version": "v4.2.1000",
"version": "v4.4.999",
"source": {
"type": "git",
"url": "https://github.com/pmmp/netresearch-jsonmapper.git",
"reference": "078764e869e9b732f97206ec9363480a77c35532"
"reference": "9a6610033d56e358e86a3e4fd5f87063c7318833"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/netresearch-jsonmapper/zipball/078764e869e9b732f97206ec9363480a77c35532",
"reference": "078764e869e9b732f97206ec9363480a77c35532",
"url": "https://api.github.com/repos/pmmp/netresearch-jsonmapper/zipball/9a6610033d56e358e86a3e4fd5f87063c7318833",
"reference": "9a6610033d56e358e86a3e4fd5f87063c7318833",
"shasum": ""
},
"require": {
@ -586,7 +585,7 @@
"netresearch/jsonmapper": "~4.2.0"
},
"require-dev": {
"phpunit/phpunit": "~7.5 || ~8.0 || ~9.0",
"phpunit/phpunit": "~7.5 || ~8.0 || ~9.0 || ~10.0",
"squizlabs/php_codesniffer": "~3.5"
},
"type": "library",
@ -611,9 +610,9 @@
"support": {
"email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues",
"source": "https://github.com/pmmp/netresearch-jsonmapper/tree/v4.2.1000"
"source": "https://github.com/pmmp/netresearch-jsonmapper/tree/v4.4.999"
},
"time": "2023-07-14T10:44:14+00:00"
"time": "2024-02-23T13:17:01+00:00"
},
{
"name": "pocketmine/raklib",
@ -830,16 +829,16 @@
},
{
"name": "ramsey/uuid",
"version": "4.7.4",
"version": "4.7.5",
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
"reference": "60a4c63ab724854332900504274f6150ff26d286"
"reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/60a4c63ab724854332900504274f6150ff26d286",
"reference": "60a4c63ab724854332900504274f6150ff26d286",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
"reference": "5f0df49ae5ad6efb7afa69e6bfab4e5b1e080d8e",
"shasum": ""
},
"require": {
@ -906,7 +905,7 @@
],
"support": {
"issues": "https://github.com/ramsey/uuid/issues",
"source": "https://github.com/ramsey/uuid/tree/4.7.4"
"source": "https://github.com/ramsey/uuid/tree/4.7.5"
},
"funding": [
{
@ -918,20 +917,20 @@
"type": "tidelift"
}
],
"time": "2023-04-15T23:01:58+00:00"
"time": "2023-11-08T05:53:05+00:00"
},
{
"name": "symfony/filesystem",
"version": "v6.3.1",
"version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae"
"reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/952a8cb588c3bc6ce76f6023000fb932f16a6e59",
"reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59",
"shasum": ""
},
"require": {
@ -965,7 +964,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v6.3.1"
"source": "https://github.com/symfony/filesystem/tree/v6.4.0"
},
"funding": [
{
@ -981,7 +980,7 @@
"type": "tidelift"
}
],
"time": "2023-06-01T08:30:39+00:00"
"time": "2023-07-26T17:27:13+00:00"
},
{
"name": "symfony/polyfill-ctype",
@ -1211,25 +1210,27 @@
},
{
"name": "nikic/php-parser",
"version": "v4.17.1",
"version": "v5.0.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d"
"reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
"reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4a21235f7e56e713259a6f76bf4b5ea08502b9dc",
"reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-json": "*",
"ext-tokenizer": "*",
"php": ">=7.0"
"php": ">=7.4"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
@ -1237,7 +1238,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
"dev-master": "5.0-dev"
}
},
"autoload": {
@ -1261,9 +1262,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1"
"source": "https://github.com/nikic/PHP-Parser/tree/v5.0.0"
},
"time": "2023-08-13T19:53:39+00:00"
"time": "2024-01-07T17:17:35+00:00"
},
{
"name": "phar-io/manifest",
@ -1378,16 +1379,16 @@
},
{
"name": "phpstan/phpstan",
"version": "1.10.40",
"version": "1.10.58",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d"
"reference": "a23518379ec4defd9e47cbf81019526861623ec2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/93c84b5bf7669920d823631e39904d69b9c7dc5d",
"reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/a23518379ec4defd9e47cbf81019526861623ec2",
"reference": "a23518379ec4defd9e47cbf81019526861623ec2",
"shasum": ""
},
"require": {
@ -1436,7 +1437,7 @@
"type": "tidelift"
}
],
"time": "2023-10-30T14:48:31+00:00"
"time": "2024-02-12T20:02:57+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
@ -1541,23 +1542,23 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "10.1.7",
"version": "10.1.11",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "355324ca4980b8916c18b9db29f3ef484078f26e"
"reference": "78c3b7625965c2513ee96569a4dbb62601784145"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/355324ca4980b8916c18b9db29f3ef484078f26e",
"reference": "355324ca4980b8916c18b9db29f3ef484078f26e",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/78c3b7625965c2513ee96569a4dbb62601784145",
"reference": "78c3b7625965c2513ee96569a4dbb62601784145",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^4.15",
"nikic/php-parser": "^4.18 || ^5.0",
"php": ">=8.1",
"phpunit/php-file-iterator": "^4.0",
"phpunit/php-text-template": "^3.0",
@ -1607,7 +1608,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.7"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.11"
},
"funding": [
{
@ -1615,7 +1616,7 @@
"type": "github"
}
],
"time": "2023-10-04T15:34:17+00:00"
"time": "2023-12-21T15:38:30+00:00"
},
{
"name": "phpunit/php-file-iterator",
@ -2207,20 +2208,20 @@
},
{
"name": "sebastian/complexity",
"version": "3.1.0",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
"reference": "68cfb347a44871f01e33ab0ef8215966432f6957"
"reference": "68ff824baeae169ec9f2137158ee529584553799"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68cfb347a44871f01e33ab0ef8215966432f6957",
"reference": "68cfb347a44871f01e33ab0ef8215966432f6957",
"url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799",
"reference": "68ff824baeae169ec9f2137158ee529584553799",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.10",
"nikic/php-parser": "^4.18 || ^5.0",
"php": ">=8.1"
},
"require-dev": {
@ -2229,7 +2230,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.1-dev"
"dev-main": "3.2-dev"
}
},
"autoload": {
@ -2253,7 +2254,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
"security": "https://github.com/sebastianbergmann/complexity/security/policy",
"source": "https://github.com/sebastianbergmann/complexity/tree/3.1.0"
"source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0"
},
"funding": [
{
@ -2261,20 +2262,20 @@
"type": "github"
}
],
"time": "2023-09-28T11:50:59+00:00"
"time": "2023-12-21T08:37:17+00:00"
},
{
"name": "sebastian/diff",
"version": "5.0.3",
"version": "5.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b"
"reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b",
"reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/fbf413a49e54f6b9b17e12d900ac7f6101591b7f",
"reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f",
"shasum": ""
},
"require": {
@ -2287,7 +2288,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "5.0-dev"
"dev-main": "5.1-dev"
}
},
"autoload": {
@ -2320,7 +2321,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
"security": "https://github.com/sebastianbergmann/diff/security/policy",
"source": "https://github.com/sebastianbergmann/diff/tree/5.0.3"
"source": "https://github.com/sebastianbergmann/diff/tree/5.1.0"
},
"funding": [
{
@ -2328,7 +2329,7 @@
"type": "github"
}
],
"time": "2023-05-01T07:48:21+00:00"
"time": "2023-12-22T10:55:06+00:00"
},
{
"name": "sebastian/environment",
@ -2536,20 +2537,20 @@
},
{
"name": "sebastian/lines-of-code",
"version": "2.0.1",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
"reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d"
"reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d",
"reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d",
"url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0",
"reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.10",
"nikic/php-parser": "^4.18 || ^5.0",
"php": ">=8.1"
},
"require-dev": {
@ -2582,7 +2583,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
"security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1"
"source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2"
},
"funding": [
{
@ -2590,7 +2591,7 @@
"type": "github"
}
],
"time": "2023-08-31T09:25:50+00:00"
"time": "2023-12-21T08:38:20+00:00"
},
{
"name": "sebastian/object-enumerator",
@ -2878,16 +2879,16 @@
},
{
"name": "theseer/tokenizer",
"version": "1.2.1",
"version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
"reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
"reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
"reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
"shasum": ""
},
"require": {
@ -2916,7 +2917,7 @@
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.1"
"source": "https://github.com/theseer/tokenizer/tree/1.2.2"
},
"funding": [
{
@ -2924,7 +2925,7 @@
"type": "github"
}
],
"time": "2021-07-28T10:34:58+00:00"
"time": "2023-11-20T00:12:19+00:00"
}
],
"aliases": [],
@ -2964,5 +2965,5 @@
"platform-overrides": {
"php": "8.1.0"
},
"plugin-api-version": "2.3.0"
"plugin-api-version": "2.6.0"
}

50
src/BootstrapOptions.php Normal file
View File

@ -0,0 +1,50 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine;
/**
* Constants for all the command-line options that PocketMine-MP supports.
* Other options not listed here can be used to override server.properties and pocketmine.yml values temporarily.
*
* @internal
*/
final class BootstrapOptions{
private function __construct(){
//NOOP
}
/** Disables the setup wizard on first startup */
public const NO_WIZARD = "no-wizard";
/** Force-disables console text colour and formatting */
public const DISABLE_ANSI = "disable-ansi";
/** Force-enables console text colour and formatting */
public const ENABLE_ANSI = "enable-ansi";
/** Path to look in for plugins */
public const PLUGINS = "plugins";
/** Path to store and load server data */
public const DATA = "data";
/** Shows basic server version information and exits */
public const VERSION = "version";
}

View File

@ -25,6 +25,7 @@ namespace pocketmine {
use Composer\InstalledVersions;
use pocketmine\errorhandler\ErrorToExceptionHandler;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\thread\ThreadManager;
use pocketmine\thread\ThreadSafeClassLoader;
use pocketmine\utils\Filesystem;
@ -40,14 +41,17 @@ namespace pocketmine {
use function extension_loaded;
use function function_exists;
use function getcwd;
use function getopt;
use function is_dir;
use function mkdir;
use function phpversion;
use function preg_match;
use function preg_quote;
use function printf;
use function realpath;
use function version_compare;
use const DIRECTORY_SEPARATOR;
use const PHP_EOL;
require_once __DIR__ . '/VersionInfo.php';
@ -144,6 +148,13 @@ namespace pocketmine {
$messages[] = "chunkutils2 ^$wantedVersionMin is required, while you have $chunkutils2_version.";
}
if(($libdeflate_version = phpversion("libdeflate")) !== false){
//make sure level 0 compression is available
if(version_compare($libdeflate_version, "0.2.0") < 0 || version_compare($libdeflate_version, "0.3.0") >= 0){
$messages[] = "php-libdeflate ^0.2.0 is required, while you have $libdeflate_version.";
}
}
if(extension_loaded("pocketmine")){
$messages[] = "The native PocketMine extension is no longer supported.";
}
@ -159,7 +170,7 @@ namespace pocketmine {
* @return void
*/
function emit_performance_warnings(\Logger $logger){
if(PHP_DEBUG !== 0){
if(ZEND_DEBUG_BUILD){
$logger->warning("This PHP binary was compiled in debug mode. This has a major impact on performance.");
}
if(extension_loaded("xdebug") && (!function_exists('xdebug_info') || count(xdebug_info('mode')) !== 0)){
@ -266,9 +277,14 @@ JIT_WARNING
ErrorToExceptionHandler::set();
if(count(getopt("", [BootstrapOptions::VERSION])) > 0){
printf("%s %s (git hash %s) for Minecraft: Bedrock Edition %s\n", VersionInfo::NAME, VersionInfo::VERSION()->getFullVersion(true), VersionInfo::GIT_HASH(), ProtocolInfo::MINECRAFT_VERSION);
exit(0);
}
$cwd = Utils::assumeNotFalse(realpath(Utils::assumeNotFalse(getcwd())));
$dataPath = getopt_string("data") ?? $cwd;
$pluginPath = getopt_string("plugins") ?? $cwd . DIRECTORY_SEPARATOR . "plugins";
$dataPath = getopt_string(BootstrapOptions::DATA) ?? $cwd;
$pluginPath = getopt_string(BootstrapOptions::PLUGINS) ?? $cwd . DIRECTORY_SEPARATOR . "plugins";
Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX);
if(!@mkdir($dataPath, 0777, true) && !is_dir($dataPath)){
@ -301,10 +317,10 @@ JIT_WARNING
//Logger has a dependency on timezone
Timezone::init();
$opts = getopt("", ["no-wizard", "enable-ansi", "disable-ansi"]);
if(isset($opts["enable-ansi"])){
$opts = getopt("", [BootstrapOptions::NO_WIZARD, BootstrapOptions::ENABLE_ANSI, BootstrapOptions::DISABLE_ANSI]);
if(isset($opts[BootstrapOptions::ENABLE_ANSI])){
Terminal::init(true);
}elseif(isset($opts["disable-ansi"])){
}elseif(isset($opts[BootstrapOptions::DISABLE_ANSI])){
Terminal::init(false);
}else{
Terminal::init();
@ -317,7 +333,7 @@ JIT_WARNING
$exitCode = 0;
do{
if(!file_exists(Path::join($dataPath, "server.properties")) && !isset($opts["no-wizard"])){
if(!file_exists(Path::join($dataPath, "server.properties")) && !isset($opts[BootstrapOptions::NO_WIZARD])){
$installer = new SetupWizard($dataPath);
if(!$installer->run()){
$exitCode = -1;

View File

@ -59,7 +59,7 @@ use pocketmine\network\mcpe\EntityEventBroadcaster;
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\PacketBroadcaster;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\serializer\PacketSerializerContext;
use pocketmine\network\mcpe\protocol\types\CompressionAlgorithm;
use pocketmine\network\mcpe\raklib\RakLibInterface;
use pocketmine\network\mcpe\StandardEntityEventBroadcaster;
use pocketmine\network\mcpe\StandardPacketBroadcaster;
@ -125,6 +125,7 @@ use Symfony\Component\Filesystem\Path;
use function array_fill;
use function array_sum;
use function base64_encode;
use function chr;
use function cli_set_process_title;
use function copy;
use function count;
@ -523,7 +524,7 @@ class Server{
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)));
$this->logger->error($this->language->translate(KnownTranslationFactory::pocketmine_data_playerCorrupted($name)));
return null;
}
});
@ -542,7 +543,7 @@ class Server{
try{
$this->playerDataProvider->saveData($name, $ev->getSaveData());
}catch(PlayerDataSaveException $e){
$this->logger->critical($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_saveError($name, $e->getMessage())));
$this->logger->critical($this->language->translate(KnownTranslationFactory::pocketmine_data_saveError($name, $e->getMessage())));
$this->logger->logException($e);
}
});
@ -737,7 +738,7 @@ class Server{
* @return string[][]
*/
public function getCommandAliases() : array{
$section = $this->configGroup->getProperty(YmlServerProperties::ALIASES);
$section = $this->configGroup->getProperty(Yml::ALIASES);
$result = [];
if(is_array($section)){
foreach($section as $key => $value){
@ -854,14 +855,14 @@ class Server{
}
}
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::language_selected($this->getLanguage()->getName(), $this->getLanguage()->getLang())));
$this->logger->info($this->language->translate(KnownTranslationFactory::language_selected($this->language->getName(), $this->language->getLang())));
if(VersionInfo::IS_DEVELOPMENT_BUILD){
if(!$this->configGroup->getPropertyBool(Yml::SETTINGS_ENABLE_DEV_BUILDS, false)){
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error1(VersionInfo::NAME)));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error2()));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error3()));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error4(YmlServerProperties::SETTINGS_ENABLE_DEV_BUILDS)));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error4(Yml::SETTINGS_ENABLE_DEV_BUILDS)));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_devBuild_error5("https://github.com/pmmp/PocketMine-MP/releases")));
$this->forceShutdownExit();
@ -877,7 +878,7 @@ class Server{
$this->memoryManager = new MemoryManager($this);
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_start(TextFormat::AQUA . $this->getVersion() . TextFormat::RESET)));
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_start(TextFormat::AQUA . $this->getVersion() . TextFormat::RESET)));
if(($poolSize = $this->configGroup->getPropertyString(Yml::SETTINGS_ASYNC_WORKERS, "auto")) === "auto"){
$poolSize = 2;
@ -937,11 +938,11 @@ class Server{
$this->onlineMode = $this->configGroup->getConfigBool(ServerProperties::XBOX_AUTH, true);
if($this->onlineMode){
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_auth_enabled()));
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_auth_enabled()));
}else{
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_auth_disabled()));
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_authWarning()));
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_authProperty_disabled()));
$this->logger->warning($this->language->translate(KnownTranslationFactory::pocketmine_server_auth_disabled()));
$this->logger->warning($this->language->translate(KnownTranslationFactory::pocketmine_server_authWarning()));
$this->logger->warning($this->language->translate(KnownTranslationFactory::pocketmine_server_authProperty_disabled()));
}
if($this->configGroup->getConfigBool(ServerProperties::HARDCORE, false) && $this->getDifficulty() < World::DIFFICULTY_HARD){
@ -952,17 +953,17 @@ class Server{
$this->serverID = Utils::getMachineUniqueId($this->getIp() . $this->getPort());
$this->getLogger()->debug("Server unique id: " . $this->getServerUniqueId());
$this->getLogger()->debug("Machine unique id: " . Utils::getMachineUniqueId());
$this->logger->debug("Server unique id: " . $this->getServerUniqueId());
$this->logger->debug("Machine unique id: " . Utils::getMachineUniqueId());
$this->network = new Network($this->logger);
$this->network->setName($this->getMotd());
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_info(
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_info(
$this->getName(),
(VersionInfo::IS_DEVELOPMENT_BUILD ? TextFormat::YELLOW : "") . $this->getPocketMineVersion() . TextFormat::RESET
)));
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_license($this->getName())));
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_license($this->getName())));
TimingsHandler::setEnabled($this->configGroup->getPropertyBool(Yml::SETTINGS_ENABLE_PROFILING, false));
$this->profilingTickRate = $this->configGroup->getPropertyInt(Yml::SETTINGS_PROFILE_REPORT_TRIGGER, self::TARGET_TICKS_PER_SECOND);
@ -973,7 +974,7 @@ class Server{
$this->craftingManager = CraftingManagerFromDataHelper::make(Path::join(\pocketmine\BEDROCK_DATA_PATH, "recipes"));
$this->resourceManager = new ResourcePackManager(Path::join($this->getDataPath(), "resource_packs"), $this->logger);
$this->resourceManager = new ResourcePackManager(Path::join($this->dataPath, "resource_packs"), $this->logger);
$pluginGraylist = null;
$graylistFile = Path::join($this->dataPath, "plugin_list.yml");
@ -987,7 +988,7 @@ class Server{
$this->forceShutdownExit();
return;
}
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool(Yml::PLUGINS_LEGACY_DATA_DIR, true) ? null : Path::join($this->getDataPath(), "plugin_data"), $pluginGraylist);
$this->pluginManager = new PluginManager($this, $this->configGroup->getPropertyBool(Yml::PLUGINS_LEGACY_DATA_DIR, true) ? null : Path::join($this->dataPath, "plugin_data"), $pluginGraylist);
$this->pluginManager->registerInterface(new PharPluginLoader($this->autoloader));
$this->pluginManager->registerInterface(new ScriptPluginLoader());
@ -1049,9 +1050,9 @@ class Server{
$this->configGroup->save();
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_defaultGameMode($this->getGamemode()->getTranslatableName())));
$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)))));
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_defaultGameMode($this->getGamemode()->getTranslatableName())));
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_donate(TextFormat::AQUA . "https://patreon.com/pocketminemp" . TextFormat::RESET)));
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_startFinished(strval(round(microtime(true) - $this->startTime, 3)))));
$forwarder = new BroadcastLoggerForwarder($this, $this->logger, $this->language);
$this->subscribeToBroadcastChannel(self::BROADCAST_CHANNEL_ADMINISTRATIVE, $forwarder);
@ -1139,13 +1140,13 @@ class Server{
if($this->worldManager->getDefaultWorld() === null){
$default = $this->configGroup->getConfigString(ServerProperties::DEFAULT_WORLD_NAME, "world");
if(trim($default) == ""){
$this->getLogger()->warning("level-name cannot be null, using default");
$this->logger->warning("level-name cannot be null, using default");
$default = "world";
$this->configGroup->setConfigString(ServerProperties::DEFAULT_WORLD_NAME, "world");
}
if(!$this->worldManager->loadWorld($default, true)){
if($this->worldManager->isWorldGenerated($default)){
$this->getLogger()->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
return false;
}
@ -1154,7 +1155,7 @@ class Server{
$generatorClass = $getGenerator($generatorName, $generatorOptions, $default);
if($generatorClass === null){
$this->getLogger()->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_level_defaultError()));
return false;
}
$creationOptions = WorldCreationOptions::create()
@ -1185,12 +1186,11 @@ class Server{
bool $useQuery,
PacketBroadcaster $packetBroadcaster,
EntityEventBroadcaster $entityEventBroadcaster,
PacketSerializerContext $packetSerializerContext,
TypeConverter $typeConverter
) : bool{
$prettyIp = $ipV6 ? "[$ip]" : $ip;
try{
$rakLibRegistered = $this->network->registerInterface(new RakLibInterface($this, $ip, $port, $ipV6, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter));
$rakLibRegistered = $this->network->registerInterface(new RakLibInterface($this, $ip, $port, $ipV6, $packetBroadcaster, $entityEventBroadcaster, $typeConverter));
}catch(NetworkInterfaceStartException $e){
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_networkStartFailed(
$ip,
@ -1200,7 +1200,7 @@ class Server{
return false;
}
if($rakLibRegistered){
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_networkStart($prettyIp, (string) $port)));
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_networkStart($prettyIp, (string) $port)));
}
if($useQuery){
if(!$rakLibRegistered){
@ -1208,7 +1208,7 @@ class Server{
//if it's not registered we need to make sure Query still works
$this->network->registerInterface(new DedicatedQueryNetworkInterface($ip, $port, $ipV6, new \PrefixedLogger($this->logger, "Dedicated Query Interface")));
}
$this->logger->info($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_query_running($prettyIp, (string) $port)));
$this->logger->info($this->language->translate(KnownTranslationFactory::pocketmine_server_query_running($prettyIp, (string) $port)));
}
return true;
}
@ -1217,15 +1217,14 @@ class Server{
$useQuery = $this->configGroup->getConfigBool(ServerProperties::ENABLE_QUERY, true);
$typeConverter = TypeConverter::getInstance();
$packetSerializerContext = new PacketSerializerContext($typeConverter->getItemTypeDictionary());
$packetBroadcaster = new StandardPacketBroadcaster($this, $packetSerializerContext);
$packetBroadcaster = new StandardPacketBroadcaster($this);
$entityEventBroadcaster = new StandardEntityEventBroadcaster($packetBroadcaster, $typeConverter);
if(
!$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter) ||
!$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $typeConverter) ||
(
$this->configGroup->getConfigBool(ServerProperties::ENABLE_IPV6, true) &&
!$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter)
!$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $typeConverter)
)
){
return false;
@ -1356,29 +1355,43 @@ class Server{
}
/**
* Broadcasts a list of packets in a batch to a list of players
* @internal
* Promises to compress the given batch buffer using the selected compressor, optionally on a separate thread.
*
* If the buffer is smaller than the batch-threshold (usually 256), the buffer will be compressed at level 0 if supported
* by the compressor. This means that the payload will be wrapped with the appropriate header and footer, but not
* actually compressed.
*
* If the buffer is larger than the async-compression-threshold (usually 10,000), the buffer may be compressed in
* a separate thread (if available).
*
* @param bool|null $sync Compression on the main thread (true) or workers (false). Default is automatic (null).
*/
public function prepareBatch(string $buffer, Compressor $compressor, ?bool $sync = null, ?TimingsHandler $timings = null) : CompressBatchPromise{
public function prepareBatch(string $buffer, Compressor $compressor, ?bool $sync = null, ?TimingsHandler $timings = null) : CompressBatchPromise|string{
$timings ??= Timings::$playerNetworkSendCompress;
try{
$timings->startTiming();
if($sync === null){
$threshold = $compressor->getCompressionThreshold();
$sync = !$this->networkCompressionAsync || $threshold === null || strlen($buffer) < $threshold;
}
$threshold = $compressor->getCompressionThreshold();
if($threshold === null || strlen($buffer) < $compressor->getCompressionThreshold()){
$compressionType = CompressionAlgorithm::NONE;
$compressed = $buffer;
$promise = new CompressBatchPromise();
if(!$sync && strlen($buffer) >= $this->networkCompressionAsyncThreshold){
$task = new CompressBatchTask($buffer, $promise, $compressor);
$this->asyncPool->submitTask($task);
}else{
$promise->resolve($compressor->compress($buffer));
$sync ??= !$this->networkCompressionAsync;
if(!$sync && strlen($buffer) >= $this->networkCompressionAsyncThreshold){
$promise = new CompressBatchPromise();
$task = new CompressBatchTask($buffer, $promise, $compressor);
$this->asyncPool->submitTask($task);
return $promise;
}
$compressionType = $compressor->getNetworkId();
$compressed = $compressor->compress($buffer);
}
return $promise;
return chr($compressionType) . $compressed;
}finally{
$timings->stopTiming();
}
@ -1455,43 +1468,43 @@ class Server{
$this->shutdown();
if(isset($this->pluginManager)){
$this->getLogger()->debug("Disabling all plugins");
$this->logger->debug("Disabling all plugins");
$this->pluginManager->disablePlugins();
}
if(isset($this->network)){
$this->network->getSessionManager()->close($this->configGroup->getPropertyString(YmlServerProperties::SETTINGS_SHUTDOWN_MESSAGE, "Server closed"));
$this->network->getSessionManager()->close($this->configGroup->getPropertyString(Yml::SETTINGS_SHUTDOWN_MESSAGE, "Server closed"));
}
if(isset($this->worldManager)){
$this->getLogger()->debug("Unloading all worlds");
$this->logger->debug("Unloading all worlds");
foreach($this->worldManager->getWorlds() as $world){
$this->worldManager->unloadWorld($world, true);
}
}
$this->getLogger()->debug("Removing event handlers");
$this->logger->debug("Removing event handlers");
HandlerListManager::global()->unregisterAll();
if(isset($this->asyncPool)){
$this->getLogger()->debug("Shutting down async task worker pool");
$this->logger->debug("Shutting down async task worker pool");
$this->asyncPool->shutdown();
}
if(isset($this->configGroup)){
$this->getLogger()->debug("Saving properties");
$this->logger->debug("Saving properties");
$this->configGroup->save();
}
if($this->console !== null){
$this->getLogger()->debug("Closing console");
$this->logger->debug("Closing console");
$this->console->quit();
}
if(isset($this->network)){
$this->getLogger()->debug("Stopping network interfaces");
$this->logger->debug("Stopping network interfaces");
foreach($this->network->getInterfaces() as $interface){
$this->getLogger()->debug("Stopping network interface " . get_class($interface));
$this->logger->debug("Stopping network interface " . get_class($interface));
$this->network->unregisterInterface($interface);
}
}
@ -1559,7 +1572,7 @@ class Server{
}
private function writeCrashDumpFile(CrashDump $dump) : string{
$crashFolder = Path::join($this->getDataPath(), "crashdumps");
$crashFolder = Path::join($this->dataPath, "crashdumps");
if(!is_dir($crashFolder)){
mkdir($crashFolder);
}
@ -1590,17 +1603,17 @@ class Server{
ini_set("error_reporting", '0');
ini_set("memory_limit", '-1'); //Fix error dump not dumped on memory problems
try{
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_create()));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_crash_create()));
$dump = new CrashDump($this, $this->pluginManager ?? null);
$crashDumpPath = $this->writeCrashDumpFile($dump);
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_submit($crashDumpPath)));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_crash_submit($crashDumpPath)));
if($this->configGroup->getPropertyBool(Yml::AUTO_REPORT_ENABLED, true)){
$report = true;
$stamp = Path::join($this->getDataPath(), "crashdumps", ".last_crash");
$stamp = Path::join($this->dataPath, "crashdumps", ".last_crash");
$crashInterval = 120; //2 minutes
if(($lastReportTime = @filemtime($stamp)) !== false && $lastReportTime + $crashInterval >= time()){
$report = false;
@ -1631,7 +1644,7 @@ class Server{
if(isset($data->crashId) && is_int($data->crashId) && isset($data->crashUrl) && is_string($data->crashUrl)){
$reportId = $data->crashId;
$reportUrl = $data->crashUrl;
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_archive($reportUrl, (string) $reportId)));
$this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_crash_archive($reportUrl, (string) $reportId)));
}elseif(isset($data->error) && is_string($data->error)){
$this->logger->emergency("Automatic crash report submission failed: $data->error");
}else{
@ -1645,7 +1658,7 @@ class Server{
}catch(\Throwable $e){
$this->logger->logException($e);
try{
$this->logger->critical($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_error($e->getMessage())));
$this->logger->critical($this->language->translate(KnownTranslationFactory::pocketmine_crash_error($e->getMessage())));
}catch(\Throwable $e){}
}
@ -1763,7 +1776,7 @@ class Server{
echo "\x1b]0;" . $this->getName() . " " .
$this->getPocketMineVersion() .
" | Online $online/" . $this->getMaxPlayers() .
" | Online $online/" . $this->maxPlayers .
($connecting > 0 ? " (+$connecting connecting)" : "") .
" | Memory " . $usage .
" | U " . round($bandwidthStats->getSend()->getAverageBytes() / 1024, 2) .
@ -1828,10 +1841,10 @@ class Server{
}
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->logger->warning($this->language->translate(KnownTranslationFactory::pocketmine_server_tickOverload()));
}
$this->getMemoryManager()->check();
$this->memoryManager->check();
if($this->console !== null){
Timings::$serverCommand->startTiming();

View File

@ -24,7 +24,9 @@ declare(strict_types=1);
namespace pocketmine;
use pocketmine\snooze\SleeperHandler;
use pocketmine\snooze\SleeperHandlerEntry;
use pocketmine\timings\TimingsHandler;
use pocketmine\utils\Utils;
use function hrtime;
/**
@ -35,12 +37,29 @@ final class TimeTrackingSleeperHandler extends SleeperHandler{
private int $notificationProcessingTimeNs = 0;
/**
* @var TimingsHandler[]
* @phpstan-var array<string, TimingsHandler>
*/
private static array $handlerTimings = [];
public function __construct(
private TimingsHandler $timings
){
parent::__construct();
}
public function addNotifier(\Closure $handler) : SleeperHandlerEntry{
$name = Utils::getNiceClosureName($handler);
$timings = self::$handlerTimings[$name] ??= new TimingsHandler("Snooze Handler: " . $name, $this->timings);
return parent::addNotifier(function() use ($timings, $handler) : void{
$timings->startTiming();
$handler();
$timings->stopTiming();
});
}
/**
* Returns the time in nanoseconds spent processing notifications since the last reset.
*/

View File

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

View File

@ -173,7 +173,7 @@ class Bamboo extends Transparent{
$newHeight = $height + $growAmount;
$stemBlock = (clone $this)->setReady(false)->setLeafSize(self::NO_LEAVES);
if($newHeight >= 4 && !$stemBlock->isThick()){ //don't change it to false if height is less, because it might have been chopped
if($newHeight >= 4 && !$stemBlock->thick){ //don't change it to false if height is less, because it might have been chopped
$stemBlock = $stemBlock->setThick(true);
}
$smallLeavesBlock = (clone $stemBlock)->setLeafSize(self::SMALL_LEAVES);

View File

@ -55,12 +55,12 @@ class Barrel extends Opaque{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
if(abs($player->getPosition()->getX() - $this->position->getX()) < 2 && abs($player->getPosition()->getZ() - $this->position->getZ()) < 2){
$y = $player->getEyePos()->getY();
if(abs($player->getPosition()->x - $this->position->x) < 2 && abs($player->getPosition()->z - $this->position->z) < 2){
$y = $player->getEyePos()->y;
if($y - $this->position->getY() > 2){
if($y - $this->position->y > 2){
$this->facing = Facing::UP;
}elseif($this->position->getY() - $y > 0){
}elseif($this->position->y - $y > 0){
$this->facing = Facing::DOWN;
}else{
$this->facing = Facing::opposite($player->getHorizontalFacing());

View File

@ -34,7 +34,6 @@ use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use function array_filter;
use function assert;
use function count;
@ -89,11 +88,12 @@ abstract class BaseBanner extends Transparent{
* @return $this
*/
public function setPatterns(array $patterns) : self{
$checked = array_filter($patterns, fn($v) => $v instanceof BannerPatternLayer);
if(count($checked) !== count($patterns)){
throw new \TypeError("Deque must only contain " . BannerPatternLayer::class . " objects");
foreach($patterns as $pattern){
if(!$pattern instanceof BannerPatternLayer){
throw new \TypeError("Array must only contain " . BannerPatternLayer::class . " objects");
}
}
$this->patterns = $checked;
$this->patterns = $patterns;
return $this;
}

View File

@ -65,8 +65,8 @@ abstract class BaseBigDripleaf extends Transparent{
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
if($block instanceof BaseBigDripleaf){
$this->facing = $block->getFacing();
$tx->addBlock($block->getPosition(), VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($this->facing));
$this->facing = $block->facing;
$tx->addBlock($block->position, VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($this->facing));
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -98,7 +98,7 @@ abstract class BaseBigDripleaf extends Transparent{
if($head === null){
return false;
}
$pos = $head->getPosition();
$pos = $head->position;
$up = $pos->up();
$world = $pos->getWorld();
if(
@ -110,8 +110,8 @@ abstract class BaseBigDripleaf extends Transparent{
$tx = new BlockTransaction($world);
$tx->addBlock($pos, VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($head->getFacing()));
$tx->addBlock($up, VanillaBlocks::BIG_DRIPLEAF_HEAD()->setFacing($head->getFacing()));
$tx->addBlock($pos, VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($head->facing));
$tx->addBlock($up, VanillaBlocks::BIG_DRIPLEAF_HEAD()->setFacing($head->facing));
$ev = new StructureGrowEvent($head, $tx, $player);
$ev->call();

View File

@ -145,7 +145,7 @@ class Bed extends Transparent{
$b = ($this->isHeadPart() ? $this : $other);
if($b->isOccupied()){
if($b->occupied){
$player->sendMessage(KnownTranslationFactory::tile_bed_occupied()->prefix(TextFormat::GRAY));
return true;

View File

@ -270,11 +270,22 @@ class Block{
}
private function encodeFullState() : int{
$writer = new RuntimeDataWriter($this->requiredBlockItemStateDataBits + $this->requiredBlockOnlyStateDataBits);
$writer->writeInt($this->requiredBlockItemStateDataBits, $this->encodeBlockItemState());
$writer->writeInt($this->requiredBlockOnlyStateDataBits, $this->encodeBlockOnlyState());
$blockItemBits = $this->requiredBlockItemStateDataBits;
$blockOnlyBits = $this->requiredBlockOnlyStateDataBits;
return $writer->getValue();
if($blockOnlyBits === 0 && $blockItemBits === 0){
return 0;
}
$result = 0;
if($blockItemBits > 0){
$result |= $this->encodeBlockItemState();
}
if($blockOnlyBits > 0){
$result |= $this->encodeBlockOnlyState() << $blockItemBits;
}
return $result;
}
/**
@ -391,7 +402,7 @@ class Block{
}
/**
* AKA: Block->isPlaceable
* Returns whether this block can be placed when obtained as an item.
*/
public function canBePlaced() : bool{
return true;
@ -561,16 +572,28 @@ class Block{
return $this->getLightFilter() > 0;
}
/**
* Returns whether this block allows any light to pass through it.
*/
public function isTransparent() : bool{
return false;
}
/**
* @deprecated TL;DR: Don't use this function. Its results are confusing and inconsistent.
*
* No one is sure what the meaning of this property actually is. It's borrowed from Minecraft Java Edition, and is
* used by various blocks for support checks.
*
* Things like signs and banners are considered "solid" despite having no collision box, and things like skulls and
* flower pots are considered non-solid despite obviously being "solid" in the conventional, real-world sense.
*/
public function isSolid() : bool{
return true;
}
/**
* AKA: Block->isFlowable
* Returns whether this block can be destroyed by liquid flowing into its cell.
*/
public function canBeFlowedInto() : bool{
return false;

View File

@ -97,7 +97,7 @@ class ChiseledBookshelf extends Opaque{
return false;
}
$x = Facing::axis($face) === Axis::X ? $clickVector->getZ() : $clickVector->getX();
$x = Facing::axis($face) === Axis::X ? $clickVector->z : $clickVector->x;
$slot = ChiseledBookshelfSlot::fromBlockFaceCoordinates(
Facing::isPositive(Facing::rotateY($face, true)) ? 1 - $x : $x,
$clickVector->y

View File

@ -54,7 +54,7 @@ final class ChorusFlower extends Flowable{
}
private function canBeSupportedAt(Block $block) : bool{
$position = $block->getPosition();
$position = $block->position;
$world = $position->getWorld();
$down = $world->getBlock($position->down());
@ -152,7 +152,7 @@ final class ChorusFlower extends Flowable{
if($tx === null){
$tx = new BlockTransaction($this->position->getWorld());
}
$tx->addBlock($this->position->getSide($facing), (clone $this)->setAge(min(self::MAX_AGE, $this->getAge() + $ageChange)));
$tx->addBlock($this->position->getSide($facing), (clone $this)->setAge(min(self::MAX_AGE, $this->age + $ageChange)));
return $tx;
}

View File

@ -51,7 +51,7 @@ final class ChorusPlant extends Flowable{
}
private function canBeSupportedAt(Block $block) : bool{
$position = $block->getPosition();
$position = $block->position;
$world = $position->getWorld();
$down = $world->getBlock($position->down());

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\block\utils\WoodType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Fertilizer;
@ -40,7 +39,7 @@ use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use function mt_rand;
class CocoaBlock extends Transparent{
class CocoaBlock extends Flowable{
use HorizontalFacingTrait;
use AgeableTrait;
@ -65,10 +64,6 @@ class CocoaBlock extends Transparent{
];
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE;
}
private function canAttachTo(Block $block) : bool{
return $block instanceof Wood && $block->getWoodType() === WoodType::JUNGLE;
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\CropGrowthHelper;
use pocketmine\block\utils\StaticSupportTrait;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
@ -66,7 +67,7 @@ abstract class Crops extends Flowable{
}
public function onRandomTick() : void{
if($this->age < self::MAX_AGE && mt_rand(0, 2) === 1){
if($this->age < self::MAX_AGE && CropGrowthHelper::canGrow($this)){
$block = clone $this;
++$block->age;
BlockEventHelper::grow($this, $block, null);

View File

@ -24,17 +24,18 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\CropGrowthHelper;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\StructureGrowEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use function mt_rand;
final class DoublePitcherCrop extends DoublePlant{
use AgeableTrait {
@ -101,10 +102,19 @@ final class DoublePitcherCrop extends DoublePlant{
}
public function onRandomTick() : void{
//TODO: the growth speed is influenced by farmland and nearby crops
//only the bottom half of the plant can grow randomly
if(mt_rand(0, 2) === 0 && !$this->top){
if(CropGrowthHelper::canGrow($this) && !$this->top){
$this->grow(null);
}
}
public function getDropsForCompatibleTool(Item $item) : array{
return [
$this->age >= self::MAX_AGE ? VanillaBlocks::PITCHER_PLANT()->asItem() : VanillaItems::PITCHER_POD()
];
}
public function asItem() : Item{
return VanillaItems::PITCHER_POD();
}
}

View File

@ -152,7 +152,7 @@ class Farmland extends Transparent{
$ev = new EntityTrampleFarmlandEvent($entity, $this);
$ev->call();
if(!$ev->isCancelled()){
$this->getPosition()->getWorld()->setBlock($this->getPosition(), VanillaBlocks::DIRT());
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::DIRT());
}
}
return null;

View File

@ -140,7 +140,7 @@ class Fire extends BaseFire{
$block->onIncinerate();
$world = $this->position->getWorld();
if($world->getBlock($block->getPosition())->isSameState($block)){
if($world->getBlock($block->position)->isSameState($block)){
$spreadedFire = false;
if(mt_rand(0, $this->age + 9) < 5){ //TODO: check rain
$fire = clone $this;

View File

@ -58,7 +58,7 @@ final class FloorCoralFan extends BaseCoral{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
$playerBlockPos = $player->getPosition()->floor();
$directionVector = $blockReplace->getPosition()->subtractVector($playerBlockPos)->normalize();
$directionVector = $blockReplace->position->subtractVector($playerBlockPos)->normalize();
$angle = rad2deg(atan2($directionVector->getZ(), $directionVector->getX()));
if($angle <= 45 || 315 <= $angle || (135 <= $angle && $angle <= 225)){

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\Furnace as TileFurnace;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\LightableTrait;
use pocketmine\crafting\FurnaceType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
@ -34,11 +35,10 @@ use function mt_rand;
class Furnace extends Opaque{
use FacesOppositePlacingPlayerTrait;
use LightableTrait;
protected FurnaceType $furnaceType;
protected bool $lit = false;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo, FurnaceType $furnaceType){
$this->furnaceType = $furnaceType;
parent::__construct($idInfo, $name, $typeInfo);
@ -57,18 +57,6 @@ class Furnace extends Opaque{
return $this->lit ? 13 : 0;
}
public function isLit() : bool{
return $this->lit;
}
/**
* @return $this
*/
public function setLit(bool $lit = true) : self{
$this->lit = $lit;
return $this;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player instanceof Player){
$furnace = $this->position->getWorld()->getTile($this->position);

View File

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

View File

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

View File

@ -61,7 +61,7 @@ class Jukebox extends Opaque{
public function ejectRecord() : void{
if($this->record !== null){
$this->getPosition()->getWorld()->dropItem($this->getPosition()->add(0.5, 1, 0.5), $this->record);
$this->position->getWorld()->dropItem($this->position->add(0.5, 1, 0.5), $this->record);
$this->record = null;
$this->stopSound();
}
@ -76,12 +76,12 @@ class Jukebox extends Opaque{
public function startSound() : void{
if($this->record !== null){
$this->getPosition()->getWorld()->addSound($this->getPosition(), new RecordSound($this->record->getRecordType()));
$this->position->getWorld()->addSound($this->position, new RecordSound($this->record->getRecordType()));
}
}
public function stopSound() : void{
$this->getPosition()->getWorld()->addSound($this->getPosition(), new RecordStopSound());
$this->position->getWorld()->addSound($this->position, new RecordStopSound());
}
public function onBreak(Item $item, ?Player $player = null, array &$returnedItems = []) : bool{

View File

@ -108,8 +108,8 @@ class NetherVines extends Flowable{
private function grow(?Player $player, int $growthAmount = 1) : bool{
$top = $this->seekToTip();
$age = $top->getAge();
$pos = $top->getPosition();
$age = $top->age;
$pos = $top->position;
$world = $pos->getWorld();
$changedBlocks = 0;

View File

@ -70,13 +70,13 @@ class PinkPetals extends Flowable{
}
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
return ($blockReplace instanceof PinkPetals && $blockReplace->getCount() < self::MAX_COUNT) || $this->supportedWhenPlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
return ($blockReplace instanceof PinkPetals && $blockReplace->count < self::MAX_COUNT) || $this->supportedWhenPlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockReplace instanceof PinkPetals && $blockReplace->getCount() < self::MAX_COUNT){
$this->count = $blockReplace->getCount() + 1;
$this->facing = $blockReplace->getFacing();
if($blockReplace instanceof PinkPetals && $blockReplace->count < self::MAX_COUNT){
$this->count = $blockReplace->count + 1;
$this->facing = $blockReplace->facing;
}elseif($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}

View File

@ -25,17 +25,18 @@ namespace pocketmine\block;
use pocketmine\block\utils\AgeableTrait;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\CropGrowthHelper;
use pocketmine\block\utils\StaticSupportTrait;
use pocketmine\event\block\StructureGrowEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use function mt_rand;
final class PitcherCrop extends Flowable{
use AgeableTrait;
@ -97,9 +98,12 @@ final class PitcherCrop extends Flowable{
}
public function onRandomTick() : void{
//TODO: the growth speed is influenced by farmland and nearby crops
if(mt_rand(0, 2) === 0){
if(CropGrowthHelper::canGrow($this)){
$this->grow(null);
}
}
public function asItem() : Item{
return VanillaItems::PITCHER_POD();
}
}

View File

@ -43,7 +43,7 @@ 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);
$position = $this->getPosition();
$position = $this->position;
$lightLevel = $position->getWorld()->getFullLightAt($position->x, $position->y, $position->z);
$downId = $down->getTypeId();
//TODO: nylium support

View File

@ -24,7 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\block\utils\LightableTrait;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\Vector3;
@ -32,23 +32,7 @@ use pocketmine\player\Player;
use function mt_rand;
class RedstoneOre extends Opaque{
protected bool $lit = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->bool($this->lit);
}
public function isLit() : bool{
return $this->lit;
}
/**
* @return $this
*/
public function setLit(bool $lit = true) : self{
$this->lit = $lit;
return $this;
}
use LightableTrait;
public function getLightLevel() : int{
return $this->lit ? 9 : 0;

View File

@ -23,28 +23,22 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\LightableTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
class RedstoneTorch extends Torch{
protected bool $lit = true;
use LightableTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
$this->lit = true;
parent::__construct($idInfo, $name, $typeInfo);
}
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
parent::describeBlockOnlyState($w);
$w->bool($this->lit);
}
public function isLit() : bool{
return $this->lit;
}
/**
* @return $this
*/
public function setLit(bool $lit = true) : self{
$this->lit = $lit;
return $this;
}
public function getLightLevel() : int{
return $this->lit ? 7 : 0;
}

View File

@ -83,7 +83,7 @@ class SmallDripleaf extends Transparent{
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
$tx->addBlock($block->getPosition(), VanillaBlocks::SMALL_DRIPLEAF()
$tx->addBlock($block->position, VanillaBlocks::SMALL_DRIPLEAF()
->setFacing($this->facing)
->setTop(true)
);
@ -117,7 +117,7 @@ class SmallDripleaf extends Transparent{
$height = mt_rand(2, 5);
$grown = 0;
for($i = 0; $i < $height; $i++){
$pos = $bottomBlock->getSide(Facing::UP, $i)->getPosition();
$pos = $bottomBlock->getSide(Facing::UP, $i)->position;
if(!$this->canGrowTo($pos)){
break;
}

View File

@ -106,8 +106,8 @@ class Stair extends Transparent{
public function getSupportType(int $facing) : SupportType{
if(
$facing === Facing::UP && $this->isUpsideDown() ||
$facing === Facing::DOWN && !$this->isUpsideDown() ||
$facing === Facing::UP && $this->upsideDown ||
$facing === Facing::DOWN && !$this->upsideDown ||
($facing === $this->facing && $this->shape !== StairShape::OUTER_LEFT && $this->shape !== StairShape::OUTER_RIGHT) ||
($facing === Facing::rotate($this->facing, Axis::Y, false) && $this->shape === StairShape::INNER_LEFT) ||
($facing === Facing::rotate($this->facing, Axis::Y, true) && $this->shape === StairShape::INNER_RIGHT)

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\CropGrowthHelper;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\Facing;
@ -58,8 +59,12 @@ abstract class Stem extends Crops{
parent::onNearbyBlockChange();
}
public function ticksRandomly() : bool{
return $this->age < self::MAX_AGE || $this->facing === Facing::UP;
}
public function onRandomTick() : void{
if($this->facing === Facing::UP && mt_rand(0, 2) === 1){
if($this->facing === Facing::UP && CropGrowthHelper::canGrow($this)){
$world = $this->position->getWorld();
if($this->age < self::MAX_AGE){
$block = clone $this;
@ -76,7 +81,9 @@ abstract class Stem extends Crops{
$facing = Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)];
$side = $this->getSide($facing);
if($side->getTypeId() === BlockTypeIds::AIR && $side->getSide(Facing::DOWN)->hasTypeTag(BlockTypeTags::DIRT)){
BlockEventHelper::grow($side, $grow, null);
if(BlockEventHelper::grow($side, $grow, null)){
$this->position->getWorld()->setBlock($this->position, $this->setFacing($facing));
}
}
}
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockEventHelper;
use pocketmine\block\utils\CropGrowthHelper;
use pocketmine\block\utils\StaticSupportTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Fertilizer;
@ -32,7 +33,6 @@ use pocketmine\item\VanillaItems;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use function mt_rand;
final class TorchflowerCrop extends Flowable{
use StaticSupportTrait;
@ -79,7 +79,7 @@ final class TorchflowerCrop extends Flowable{
}
public function onRandomTick() : void{
if(mt_rand(0, 2) === 1){
if(CropGrowthHelper::canGrow($this)){
BlockEventHelper::grow($this, $this->getNextState(), null);
}
}

View File

@ -788,7 +788,7 @@ final class VanillaBlocks{
}
protected static function setup() : void{
$railBreakInfo = new Info(new BlockBreakInfo(0.7));
$railBreakInfo = new Info(new BreakInfo(0.7));
self::register("activator_rail", new ActivatorRail(new BID(Ids::ACTIVATOR_RAIL), "Activator Rail", $railBreakInfo));
self::register("air", new Air(new BID(Ids::AIR), "Air", new Info(BreakInfo::indestructible(-1.0))));
self::register("anvil", new Anvil(new BID(Ids::ANVIL), "Anvil", new Info(BreakInfo::pickaxe(5.0, ToolTier::WOOD, 6000.0))));
@ -1495,7 +1495,9 @@ final class VanillaBlocks{
//for some reason, slabs have weird hardness like the legacy ones
$slabBreakInfo = new Info(BreakInfo::pickaxe(2.0, ToolTier::WOOD, 30.0));
self::register("ancient_debris", new Opaque(new BID(Ids::ANCIENT_DEBRIS), "Ancient Debris", new Info(BreakInfo::pickaxe(30, ToolTier::DIAMOND, 3600.0))));
self::register("ancient_debris", new class(new BID(Ids::ANCIENT_DEBRIS), "Ancient Debris", new Info(BreakInfo::pickaxe(30, ToolTier::DIAMOND, 3600.0))) extends Opaque{
public function isFireProofAsItem() : bool{ return true; }
});
$netheriteBreakInfo = new Info(BreakInfo::pickaxe(50, ToolTier::DIAMOND, 3600.0));
self::register("netherite", new class(new BID(Ids::NETHERITE), "Netherite Block", $netheriteBreakInfo) extends Opaque{
public function isFireProofAsItem() : bool{ return true; }
@ -1636,7 +1638,7 @@ final class VanillaBlocks{
self::register("cave_vines", new CaveVines(new BID(Ids::CAVE_VINES), "Cave Vines", new Info(BreakInfo::instant())));
self::register("small_dripleaf", new SmallDripleaf(new BID(Ids::SMALL_DRIPLEAF), "Small Dripleaf", new Info(BreakInfo::instant(BlockToolType::SHEARS, toolHarvestLevel: 1))));
self::register("small_dripleaf", new SmallDripleaf(new BID(Ids::SMALL_DRIPLEAF), "Small Dripleaf", new Info(BreakInfo::instant(ToolType::SHEARS, toolHarvestLevel: 1))));
self::register("big_dripleaf_head", new BigDripleafHead(new BID(Ids::BIG_DRIPLEAF_HEAD), "Big Dripleaf", new Info(BreakInfo::instant())));
self::register("big_dripleaf_stem", new BigDripleafStem(new BID(Ids::BIG_DRIPLEAF_STEM), "Big Dripleaf Stem", new Info(BreakInfo::instant())));
}

View File

@ -171,7 +171,7 @@ final class WoodLikeBlockIdHelper{
};
}
public static function getTrapdoorIdentifier(WoodType $treeType) : BlockIdentifier{
public static function getTrapdoorIdentifier(WoodType $treeType) : BID{
return new BID(match($treeType){
WoodType::OAK => Ids::OAK_TRAPDOOR,
WoodType::SPRUCE => Ids::SPRUCE_TRAPDOOR,
@ -186,7 +186,7 @@ final class WoodLikeBlockIdHelper{
});
}
public static function getButtonIdentifier(WoodType $treeType) : BlockIdentifier{
public static function getButtonIdentifier(WoodType $treeType) : BID{
return new BID(match($treeType){
WoodType::OAK => Ids::OAK_BUTTON,
WoodType::SPRUCE => Ids::SPRUCE_BUTTON,
@ -201,7 +201,7 @@ final class WoodLikeBlockIdHelper{
});
}
public static function getPressurePlateIdentifier(WoodType $treeType) : BlockIdentifier{
public static function getPressurePlateIdentifier(WoodType $treeType) : BID{
return new BID(match($treeType){
WoodType::OAK => Ids::OAK_PRESSURE_PLATE,
WoodType::SPRUCE => Ids::SPRUCE_PRESSURE_PLATE,
@ -216,7 +216,7 @@ final class WoodLikeBlockIdHelper{
});
}
public static function getDoorIdentifier(WoodType $treeType) : BlockIdentifier{
public static function getDoorIdentifier(WoodType $treeType) : BID{
return new BID(match($treeType){
WoodType::OAK => Ids::OAK_DOOR,
WoodType::SPRUCE => Ids::SPRUCE_DOOR,
@ -231,7 +231,7 @@ final class WoodLikeBlockIdHelper{
});
}
public static function getFenceGateIdentifier(WoodType $treeType) : BlockIdentifier{
public static function getFenceGateIdentifier(WoodType $treeType) : BID{
return new BID(match($treeType){
WoodType::OAK => Ids::OAK_FENCE_GATE,
WoodType::SPRUCE => Ids::SPRUCE_FENCE_GATE,
@ -246,7 +246,7 @@ final class WoodLikeBlockIdHelper{
});
}
public static function getStairsIdentifier(WoodType $treeType) : BlockIdentifier{
public static function getStairsIdentifier(WoodType $treeType) : BID{
return new BID(match($treeType){
WoodType::OAK => Ids::OAK_STAIRS,
WoodType::SPRUCE => Ids::SPRUCE_STAIRS,

View File

@ -47,20 +47,20 @@ trait AnimatedBlockInventoryTrait{
public function onOpen(Player $who) : void{
parent::onOpen($who);
if($this->getHolder()->isValid() && $this->getViewerCount() === 1){
if($this->holder->isValid() && $this->getViewerCount() === 1){
//TODO: this crap really shouldn't be managed by the inventory
$this->animateBlock(true);
$this->getHolder()->getWorld()->addSound($this->getHolder()->add(0.5, 0.5, 0.5), $this->getOpenSound());
$this->holder->getWorld()->addSound($this->holder->add(0.5, 0.5, 0.5), $this->getOpenSound());
}
}
abstract protected function animateBlock(bool $isOpen) : void;
public function onClose(Player $who) : void{
if($this->getHolder()->isValid() && $this->getViewerCount() === 1){
if($this->holder->isValid() && $this->getViewerCount() === 1){
//TODO: this crap really shouldn't be managed by the inventory
$this->animateBlock(false);
$this->getHolder()->getWorld()->addSound($this->getHolder()->add(0.5, 0.5, 0.5), $this->getCloseSound());
$this->holder->getWorld()->addSound($this->holder->add(0.5, 0.5, 0.5), $this->getCloseSound());
}
parent::onClose($who);
}

View File

@ -139,7 +139,7 @@ class Chest extends Spawnable implements Container, Nameable{
if($pair->doubleInventory !== null){
$this->doubleInventory = $pair->doubleInventory;
}else{
if(($pair->getPosition()->x + ($pair->getPosition()->z << 15)) > ($this->position->x + ($this->position->z << 15))){ //Order them correctly
if(($pair->position->x + ($pair->position->z << 15)) > ($this->position->x + ($this->position->z << 15))){ //Order them correctly
$this->doubleInventory = $pair->doubleInventory = new DoubleChestInventory($pair->inventory, $this->inventory);
}else{
$this->doubleInventory = $pair->doubleInventory = new DoubleChestInventory($this->inventory, $pair->inventory);

View File

@ -27,6 +27,7 @@ use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\world\World;
@ -52,13 +53,17 @@ class ItemFrame extends Spawnable{
if(($itemTag = $nbt->getCompoundTag(self::TAG_ITEM)) !== null){
$this->item = Item::nbtDeserialize($itemTag);
}
$this->itemRotation = $nbt->getByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
if($nbt->getTag(self::TAG_ITEM_ROTATION) instanceof FloatTag){
$this->itemRotation = (int) ($nbt->getFloat(self::TAG_ITEM_ROTATION, $this->itemRotation * 45) / 45);
} else {
$this->itemRotation = $nbt->getByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
}
$this->itemDropChance = $nbt->getFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
}
protected function writeSaveData(CompoundTag $nbt) : void{
$nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
$nbt->setByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
$nbt->setFloat(self::TAG_ITEM_ROTATION, $this->itemRotation * 45);
if(!$this->item->isNull()){
$nbt->setTag(self::TAG_ITEM, $this->item->nbtSerialize());
}
@ -98,7 +103,7 @@ class ItemFrame extends Spawnable{
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
$nbt->setFloat(self::TAG_ITEM_DROP_CHANCE, $this->itemDropChance);
$nbt->setByte(self::TAG_ITEM_ROTATION, $this->itemRotation);
$nbt->setFloat(self::TAG_ITEM_ROTATION, $this->itemRotation * 45);
if(!$this->item->isNull()){
$nbt->setTag(self::TAG_ITEM, TypeConverter::getInstance()->getItemTranslator()->toNetworkNbt($this->item));
}

View File

@ -77,22 +77,30 @@ class Sign extends Spawnable{
parent::__construct($world, $pos);
}
private function readTextTag(CompoundTag $nbt, bool $lightingBugResolved) : void{
$baseColor = new Color(0, 0, 0);
$glowingText = false;
if(($baseColorTag = $nbt->getTag(self::TAG_TEXT_COLOR)) instanceof IntTag){
$baseColor = Color::fromARGB(Binary::unsignInt($baseColorTag->getValue()));
}
if($lightingBugResolved && ($glowingTextTag = $nbt->getTag(self::TAG_GLOWING_TEXT)) instanceof ByteTag){
//both of these must be 1 - if only one is set, it's a leftover from 1.16.210 experimental features
//see https://bugs.mojang.com/browse/MCPE-117835
$glowingText = $glowingTextTag->getValue() !== 0;
}
$this->text = SignText::fromBlob(mb_scrub($nbt->getString(self::TAG_TEXT_BLOB), 'UTF-8'), $baseColor, $glowingText);
}
public function readSaveData(CompoundTag $nbt) : void{
if(($textBlobTag = $nbt->getTag(self::TAG_TEXT_BLOB)) instanceof StringTag){ //MCPE 1.2 save format
$baseColor = new Color(0, 0, 0);
$glowingText = false;
if(($baseColorTag = $nbt->getTag(self::TAG_TEXT_COLOR)) instanceof IntTag){
$baseColor = Color::fromARGB(Binary::unsignInt($baseColorTag->getValue()));
$frontTextTag = $nbt->getTag(self::TAG_FRONT_TEXT);
if($frontTextTag instanceof CompoundTag){
$this->readTextTag($frontTextTag, true);
}elseif($nbt->getTag(self::TAG_TEXT_BLOB) instanceof StringTag){ //MCPE 1.2 save format
$lightingBugResolved = false;
if(($lightingBugResolvedTag = $nbt->getTag(self::TAG_LEGACY_BUG_RESOLVE)) instanceof ByteTag){
$lightingBugResolved = $lightingBugResolvedTag->getValue() !== 0;
}
if(
($glowingTextTag = $nbt->getTag(self::TAG_GLOWING_TEXT)) instanceof ByteTag &&
($lightingBugResolvedTag = $nbt->getTag(self::TAG_LEGACY_BUG_RESOLVE)) instanceof ByteTag
){
//both of these must be 1 - if only one is set, it's a leftover from 1.16.210 experimental features
//see https://bugs.mojang.com/browse/MCPE-117835
$glowingText = $glowingTextTag->getValue() !== 0 && $lightingBugResolvedTag->getValue() !== 0;
}
$this->text = SignText::fromBlob(mb_scrub($textBlobTag->getValue(), 'UTF-8'), $baseColor, $glowingText);
$this->readTextTag($nbt, $lightingBugResolved);
}else{
$text = [];
for($i = 0; $i < SignText::LINE_COUNT; ++$i){
@ -107,15 +115,19 @@ class Sign extends Spawnable{
}
protected function writeSaveData(CompoundTag $nbt) : void{
$nbt->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()));
$nbt->setTag(self::TAG_FRONT_TEXT, CompoundTag::create()
->setString(self::TAG_TEXT_BLOB, implode("\n", $this->text->getLines()))
->setInt(self::TAG_TEXT_COLOR, Binary::signInt($this->text->getBaseColor()->toARGB()))
->setByte(self::TAG_GLOWING_TEXT, $this->text->isGlowing() ? 1 : 0)
->setByte(self::TAG_PERSIST_FORMATTING, 1)
);
$nbt->setTag(self::TAG_BACK_TEXT, CompoundTag::create()
->setString(self::TAG_TEXT_BLOB, "")
->setInt(self::TAG_TEXT_COLOR, Binary::signInt(0xff_00_00_00))
->setByte(self::TAG_GLOWING_TEXT, 0)
->setByte(self::TAG_PERSIST_FORMATTING, 1)
);
for($i = 0; $i < SignText::LINE_COUNT; ++$i){ //Backwards-compatibility
$textKey = sprintf(self::TAG_TEXT_LINE, $i + 1);
$nbt->setString($textKey, $this->text->getLine($i));
}
$nbt->setInt(self::TAG_TEXT_COLOR, Binary::signInt($this->text->getBaseColor()->toARGB()));
$nbt->setByte(self::TAG_GLOWING_TEXT, $this->text->isGlowing() ? 1 : 0);
$nbt->setByte(self::TAG_LEGACY_BUG_RESOLVE, 1);
$nbt->setByte(self::TAG_WAXED, $this->waxed ? 1 : 0);
}

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\block\Block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\projectile\Projectile;
use pocketmine\item\Durable;
use pocketmine\item\enchantment\VanillaEnchantments;
@ -38,24 +37,12 @@ use pocketmine\world\sound\FireExtinguishSound;
use pocketmine\world\sound\FlintSteelSound;
trait CandleTrait{
private bool $lit = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->bool($this->lit);
}
use LightableTrait;
public function getLightLevel() : int{
return $this->lit ? 3 : 0;
}
public function isLit() : bool{ return $this->lit; }
/** @return $this */
public function setLit(bool $lit) : self{
$this->lit = $lit;
return $this;
}
/** @see Block::onInteract() */
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item->getTypeId() === ItemTypeIds::FIRE_CHARGE || $item->getTypeId() === ItemTypeIds::FLINT_AND_STEEL || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){

View File

@ -0,0 +1,120 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\block\Block;
use pocketmine\block\Farmland;
use function mt_rand;
final class CropGrowthHelper{
private const ON_HYDRATED_FARMLAND_BONUS = 3;
private const ON_DRY_FARMLAND_BONUS = 1;
private const ADJACENT_HYDRATED_FARMLAND_BONUS = 3 / 4;
private const ADJACENT_DRY_FARMLAND_BONUS = 1 / 4;
private const IMPROPER_ARRANGEMENT_DIVISOR = 2;
private const MIN_LIGHT_LEVEL = 9;
private function __construct(){
//NOOP
}
/**
* Returns the speed at which this crop will grow, depending on its surroundings.
* The default is once every 26 random ticks.
*
* Things which influence this include nearby farmland (bonus for hydrated farmland) and the position of other
* nearby crops of the same type (nearby crops of the same type will negatively influence growth speed unless
* planted in rows and properly spaced apart).
*/
public static function calculateMultiplier(Block $block) : float{
$result = 1;
$position = $block->getPosition();
$world = $position->getWorld();
$baseX = $position->getFloorX();
$baseY = $position->getFloorY();
$baseZ = $position->getFloorZ();
$farmland = $world->getBlockAt($baseX, $baseY - 1, $baseZ);
if($farmland instanceof Farmland){
$result += $farmland->getWetness() > 0 ? self::ON_HYDRATED_FARMLAND_BONUS : self::ON_DRY_FARMLAND_BONUS;
}
$xRow = false;
$zRow = false;
$improperArrangement = false;
for($x = -1; $x <= 1; $x++){
for($z = -1; $z <= 1; $z++){
if($x === 0 && $z === 0){
continue;
}
$nextFarmland = $world->getBlockAt($baseX + $x, $baseY - 1, $baseZ + $z);
if(!$nextFarmland instanceof Farmland){
continue;
}
$result += $nextFarmland->getWetness() > 0 ? self::ADJACENT_HYDRATED_FARMLAND_BONUS : self::ADJACENT_DRY_FARMLAND_BONUS;
if(!$improperArrangement){
$nextCrop = $world->getBlockAt($baseX + $x, $baseY, $baseZ + $z);
if($nextCrop->hasSameTypeId($block)){
match(0){
$x => $zRow ? $improperArrangement = true : $xRow = true,
$z => $xRow ? $improperArrangement = true : $zRow = true,
default => $improperArrangement = true,
};
}
}
}
}
//crops can be arranged in rows, but the rows must not cross and must be spaced apart by at least one block
if($improperArrangement){
$result /= self::IMPROPER_ARRANGEMENT_DIVISOR;
}
return $result;
}
public static function hasEnoughLight(Block $block, int $minLevel = self::MIN_LIGHT_LEVEL) : bool{
$position = $block->getPosition();
$world = $position->getWorld();
//crop growth is not affected by time of day since 1.11 or so
return $world->getPotentialLightAt($position->x, $position->y, $position->z) >= $minLevel;
}
public static function canGrow(Block $block) : bool{
//while it may be tempting to use mt_rand(0, 25) < multiplier, this would make crops grow a bit faster than
//vanilla in most cases due to the remainder of 25 / multiplier not being discarded
return mt_rand(0, (int) (25 / self::calculateMultiplier($block))) === 0 && self::hasEnoughLight($block);
}
}

View File

@ -0,0 +1,46 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\data\runtime\RuntimeDataDescriber;
trait LightableTrait{
protected bool $lit = false;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->bool($this->lit);
}
public function isLit() : bool{
return $this->lit;
}
/**
* @return $this
*/
public function setLit(bool $lit = true) : self{
$this->lit = $lit;
return $this;
}
}

View File

@ -43,44 +43,48 @@ final class BannerPatternTypeIdMap{
private array $enumToId = [];
public function __construct(){
$this->register("bo", BannerPatternType::BORDER);
$this->register("bri", BannerPatternType::BRICKS);
$this->register("mc", BannerPatternType::CIRCLE);
$this->register("cre", BannerPatternType::CREEPER);
$this->register("cr", BannerPatternType::CROSS);
$this->register("cbo", BannerPatternType::CURLY_BORDER);
$this->register("lud", BannerPatternType::DIAGONAL_LEFT);
$this->register("rd", BannerPatternType::DIAGONAL_RIGHT);
$this->register("ld", BannerPatternType::DIAGONAL_UP_LEFT);
$this->register("rud", BannerPatternType::DIAGONAL_UP_RIGHT);
$this->register("flo", BannerPatternType::FLOWER);
$this->register("gra", BannerPatternType::GRADIENT);
$this->register("gru", BannerPatternType::GRADIENT_UP);
$this->register("hh", BannerPatternType::HALF_HORIZONTAL);
$this->register("hhb", BannerPatternType::HALF_HORIZONTAL_BOTTOM);
$this->register("vh", BannerPatternType::HALF_VERTICAL);
$this->register("vhr", BannerPatternType::HALF_VERTICAL_RIGHT);
$this->register("moj", BannerPatternType::MOJANG);
$this->register("mr", BannerPatternType::RHOMBUS);
$this->register("sku", BannerPatternType::SKULL);
$this->register("ss", BannerPatternType::SMALL_STRIPES);
$this->register("bl", BannerPatternType::SQUARE_BOTTOM_LEFT);
$this->register("br", BannerPatternType::SQUARE_BOTTOM_RIGHT);
$this->register("tl", BannerPatternType::SQUARE_TOP_LEFT);
$this->register("tr", BannerPatternType::SQUARE_TOP_RIGHT);
$this->register("sc", BannerPatternType::STRAIGHT_CROSS);
$this->register("bs", BannerPatternType::STRIPE_BOTTOM);
$this->register("cs", BannerPatternType::STRIPE_CENTER);
$this->register("dls", BannerPatternType::STRIPE_DOWNLEFT);
$this->register("drs", BannerPatternType::STRIPE_DOWNRIGHT);
$this->register("ls", BannerPatternType::STRIPE_LEFT);
$this->register("ms", BannerPatternType::STRIPE_MIDDLE);
$this->register("rs", BannerPatternType::STRIPE_RIGHT);
$this->register("ts", BannerPatternType::STRIPE_TOP);
$this->register("bt", BannerPatternType::TRIANGLE_BOTTOM);
$this->register("tt", BannerPatternType::TRIANGLE_TOP);
$this->register("bts", BannerPatternType::TRIANGLES_BOTTOM);
$this->register("tts", BannerPatternType::TRIANGLES_TOP);
foreach(BannerPatternType::cases() as $case){
$this->register(match($case){
BannerPatternType::BORDER => "bo",
BannerPatternType::BRICKS => "bri",
BannerPatternType::CIRCLE => "mc",
BannerPatternType::CREEPER => "cre",
BannerPatternType::CROSS => "cr",
BannerPatternType::CURLY_BORDER => "cbo",
BannerPatternType::DIAGONAL_LEFT => "lud",
BannerPatternType::DIAGONAL_RIGHT => "rd",
BannerPatternType::DIAGONAL_UP_LEFT => "ld",
BannerPatternType::DIAGONAL_UP_RIGHT => "rud",
BannerPatternType::FLOWER => "flo",
BannerPatternType::GRADIENT => "gra",
BannerPatternType::GRADIENT_UP => "gru",
BannerPatternType::HALF_HORIZONTAL => "hh",
BannerPatternType::HALF_HORIZONTAL_BOTTOM => "hhb",
BannerPatternType::HALF_VERTICAL => "vh",
BannerPatternType::HALF_VERTICAL_RIGHT => "vhr",
BannerPatternType::MOJANG => "moj",
BannerPatternType::RHOMBUS => "mr",
BannerPatternType::SKULL => "sku",
BannerPatternType::SMALL_STRIPES => "ss",
BannerPatternType::SQUARE_BOTTOM_LEFT => "bl",
BannerPatternType::SQUARE_BOTTOM_RIGHT => "br",
BannerPatternType::SQUARE_TOP_LEFT => "tl",
BannerPatternType::SQUARE_TOP_RIGHT => "tr",
BannerPatternType::STRAIGHT_CROSS => "sc",
BannerPatternType::STRIPE_BOTTOM => "bs",
BannerPatternType::STRIPE_CENTER => "cs",
BannerPatternType::STRIPE_DOWNLEFT => "dls",
BannerPatternType::STRIPE_DOWNRIGHT => "drs",
BannerPatternType::STRIPE_LEFT => "ls",
BannerPatternType::STRIPE_MIDDLE => "ms",
BannerPatternType::STRIPE_RIGHT => "rs",
BannerPatternType::STRIPE_TOP => "ts",
BannerPatternType::TRIANGLE_BOTTOM => "bt",
BannerPatternType::TRIANGLE_TOP => "tt",
BannerPatternType::TRIANGLES_BOTTOM => "bts",
BannerPatternType::TRIANGLES_TOP => "tts",
}, $case);
}
}
public function register(string $stringId, BannerPatternType $type) : void{

View File

@ -111,4 +111,15 @@ final class BiomeIds{
public const CRIMSON_FOREST = 179;
public const WARPED_FOREST = 180;
public const BASALT_DELTAS = 181;
public const JAGGED_PEAKS = 182;
public const FROZEN_PEAKS = 183;
public const SNOWY_SLOPES = 184;
public const GROVE = 185;
public const MEADOW = 186;
public const LUSH_CAVES = 187;
public const DRIPSTONE_CAVES = 188;
public const STONY_PEAKS = 189;
public const DEEP_DARK = 190;
public const MANGROVE_SWAMP = 191;
public const CHERRY_GROVE = 192;
}

View File

@ -48,22 +48,28 @@ final class DyeColorIdMap{
private array $enumToItemId = [];
private function __construct(){
$this->register(0, ItemTypeNames::WHITE_DYE, DyeColor::WHITE);
$this->register(1, ItemTypeNames::ORANGE_DYE, DyeColor::ORANGE);
$this->register(2, ItemTypeNames::MAGENTA_DYE, DyeColor::MAGENTA);
$this->register(3, ItemTypeNames::LIGHT_BLUE_DYE, DyeColor::LIGHT_BLUE);
$this->register(4, ItemTypeNames::YELLOW_DYE, DyeColor::YELLOW);
$this->register(5, ItemTypeNames::LIME_DYE, DyeColor::LIME);
$this->register(6, ItemTypeNames::PINK_DYE, DyeColor::PINK);
$this->register(7, ItemTypeNames::GRAY_DYE, DyeColor::GRAY);
$this->register(8, ItemTypeNames::LIGHT_GRAY_DYE, DyeColor::LIGHT_GRAY);
$this->register(9, ItemTypeNames::CYAN_DYE, DyeColor::CYAN);
$this->register(10, ItemTypeNames::PURPLE_DYE, DyeColor::PURPLE);
$this->register(11, ItemTypeNames::BLUE_DYE, DyeColor::BLUE);
$this->register(12, ItemTypeNames::BROWN_DYE, DyeColor::BROWN);
$this->register(13, ItemTypeNames::GREEN_DYE, DyeColor::GREEN);
$this->register(14, ItemTypeNames::RED_DYE, DyeColor::RED);
$this->register(15, ItemTypeNames::BLACK_DYE, DyeColor::BLACK);
foreach(DyeColor::cases() as $case){
[$colorId, $dyeItemId] = match($case){
DyeColor::WHITE => [0, ItemTypeNames::WHITE_DYE],
DyeColor::ORANGE => [1, ItemTypeNames::ORANGE_DYE],
DyeColor::MAGENTA => [2, ItemTypeNames::MAGENTA_DYE],
DyeColor::LIGHT_BLUE => [3, ItemTypeNames::LIGHT_BLUE_DYE],
DyeColor::YELLOW => [4, ItemTypeNames::YELLOW_DYE],
DyeColor::LIME => [5, ItemTypeNames::LIME_DYE],
DyeColor::PINK => [6, ItemTypeNames::PINK_DYE],
DyeColor::GRAY => [7, ItemTypeNames::GRAY_DYE],
DyeColor::LIGHT_GRAY => [8, ItemTypeNames::LIGHT_GRAY_DYE],
DyeColor::CYAN => [9, ItemTypeNames::CYAN_DYE],
DyeColor::PURPLE => [10, ItemTypeNames::PURPLE_DYE],
DyeColor::BLUE => [11, ItemTypeNames::BLUE_DYE],
DyeColor::BROWN => [12, ItemTypeNames::BROWN_DYE],
DyeColor::GREEN => [13, ItemTypeNames::GREEN_DYE],
DyeColor::RED => [14, ItemTypeNames::RED_DYE],
DyeColor::BLACK => [15, ItemTypeNames::BLACK_DYE],
};
$this->register($colorId, $dyeItemId, $case);
}
}
private function register(int $id, string $itemId, DyeColor $color) : void{

View File

@ -32,9 +32,13 @@ final class MedicineTypeIdMap{
use IntSaveIdMapTrait;
private function __construct(){
$this->register(MedicineTypeIds::ANTIDOTE, MedicineType::ANTIDOTE);
$this->register(MedicineTypeIds::ELIXIR, MedicineType::ELIXIR);
$this->register(MedicineTypeIds::EYE_DROPS, MedicineType::EYE_DROPS);
$this->register(MedicineTypeIds::TONIC, MedicineType::TONIC);
foreach(MedicineType::cases() as $case){
$this->register(match($case){
MedicineType::ANTIDOTE => MedicineTypeIds::ANTIDOTE,
MedicineType::ELIXIR => MedicineTypeIds::ELIXIR,
MedicineType::EYE_DROPS => MedicineTypeIds::EYE_DROPS,
MedicineType::TONIC => MedicineTypeIds::TONIC,
}, $case);
}
}
}

View File

@ -32,12 +32,16 @@ final class MobHeadTypeIdMap{
use IntSaveIdMapTrait;
private function __construct(){
$this->register(0, MobHeadType::SKELETON);
$this->register(1, MobHeadType::WITHER_SKELETON);
$this->register(2, MobHeadType::ZOMBIE);
$this->register(3, MobHeadType::PLAYER);
$this->register(4, MobHeadType::CREEPER);
$this->register(5, MobHeadType::DRAGON);
$this->register(6, MobHeadType::PIGLIN);
foreach(MobHeadType::cases() as $case){
$this->register(match($case){
MobHeadType::SKELETON => 0,
MobHeadType::WITHER_SKELETON => 1,
MobHeadType::ZOMBIE => 2,
MobHeadType::PLAYER => 3,
MobHeadType::CREEPER => 4,
MobHeadType::DRAGON => 5,
MobHeadType::PIGLIN => 6,
}, $case);
}
}
}

View File

@ -33,16 +33,20 @@ final class MushroomBlockTypeIdMap{
use IntSaveIdMapTrait;
public function __construct(){
$this->register(LegacyMeta::MUSHROOM_BLOCK_ALL_PORES, MushroomBlockType::PORES);
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_NORTHWEST_CORNER, MushroomBlockType::CAP_NORTHWEST);
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_NORTH_SIDE, MushroomBlockType::CAP_NORTH);
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_NORTHEAST_CORNER, MushroomBlockType::CAP_NORTHEAST);
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_WEST_SIDE, MushroomBlockType::CAP_WEST);
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_TOP_ONLY, MushroomBlockType::CAP_MIDDLE);
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_EAST_SIDE, MushroomBlockType::CAP_EAST);
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTHWEST_CORNER, MushroomBlockType::CAP_SOUTHWEST);
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTH_SIDE, MushroomBlockType::CAP_SOUTH);
$this->register(LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTHEAST_CORNER, MushroomBlockType::CAP_SOUTHEAST);
$this->register(LegacyMeta::MUSHROOM_BLOCK_ALL_CAP, MushroomBlockType::ALL_CAP);
foreach(MushroomBlockType::cases() as $case){
$this->register(match($case){
MushroomBlockType::PORES => LegacyMeta::MUSHROOM_BLOCK_ALL_PORES,
MushroomBlockType::CAP_NORTHWEST => LegacyMeta::MUSHROOM_BLOCK_CAP_NORTHWEST_CORNER,
MushroomBlockType::CAP_NORTH => LegacyMeta::MUSHROOM_BLOCK_CAP_NORTH_SIDE,
MushroomBlockType::CAP_NORTHEAST => LegacyMeta::MUSHROOM_BLOCK_CAP_NORTHEAST_CORNER,
MushroomBlockType::CAP_WEST => LegacyMeta::MUSHROOM_BLOCK_CAP_WEST_SIDE,
MushroomBlockType::CAP_MIDDLE => LegacyMeta::MUSHROOM_BLOCK_CAP_TOP_ONLY,
MushroomBlockType::CAP_EAST => LegacyMeta::MUSHROOM_BLOCK_CAP_EAST_SIDE,
MushroomBlockType::CAP_SOUTHWEST => LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTHWEST_CORNER,
MushroomBlockType::CAP_SOUTH => LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTH_SIDE,
MushroomBlockType::CAP_SOUTHEAST => LegacyMeta::MUSHROOM_BLOCK_CAP_SOUTHEAST_CORNER,
MushroomBlockType::ALL_CAP => LegacyMeta::MUSHROOM_BLOCK_ALL_CAP,
}, $case);
}
}
}

View File

@ -32,21 +32,25 @@ final class NoteInstrumentIdMap{
use IntSaveIdMapTrait;
private function __construct(){
$this->register(0, NoteInstrument::PIANO);
$this->register(1, NoteInstrument::BASS_DRUM);
$this->register(2, NoteInstrument::SNARE);
$this->register(3, NoteInstrument::CLICKS_AND_STICKS);
$this->register(4, NoteInstrument::DOUBLE_BASS);
$this->register(5, NoteInstrument::BELL);
$this->register(6, NoteInstrument::FLUTE);
$this->register(7, NoteInstrument::CHIME);
$this->register(8, NoteInstrument::GUITAR);
$this->register(9, NoteInstrument::XYLOPHONE);
$this->register(10, NoteInstrument::IRON_XYLOPHONE);
$this->register(11, NoteInstrument::COW_BELL);
$this->register(12, NoteInstrument::DIDGERIDOO);
$this->register(13, NoteInstrument::BIT);
$this->register(14, NoteInstrument::BANJO);
$this->register(15, NoteInstrument::PLING);
foreach(NoteInstrument::cases() as $case){
$this->register(match($case){
NoteInstrument::PIANO => 0,
NoteInstrument::BASS_DRUM => 1,
NoteInstrument::SNARE => 2,
NoteInstrument::CLICKS_AND_STICKS => 3,
NoteInstrument::DOUBLE_BASS => 4,
NoteInstrument::BELL => 5,
NoteInstrument::FLUTE => 6,
NoteInstrument::CHIME => 7,
NoteInstrument::GUITAR => 8,
NoteInstrument::XYLOPHONE => 9,
NoteInstrument::IRON_XYLOPHONE => 10,
NoteInstrument::COW_BELL => 11,
NoteInstrument::DIDGERIDOO => 12,
NoteInstrument::BIT => 13,
NoteInstrument::BANJO => 14,
NoteInstrument::PLING => 15,
}, $case);
}
}
}

View File

@ -32,48 +32,52 @@ final class PotionTypeIdMap{
use IntSaveIdMapTrait;
private function __construct(){
$this->register(PotionTypeIds::WATER, PotionType::WATER);
$this->register(PotionTypeIds::MUNDANE, PotionType::MUNDANE);
$this->register(PotionTypeIds::LONG_MUNDANE, PotionType::LONG_MUNDANE);
$this->register(PotionTypeIds::THICK, PotionType::THICK);
$this->register(PotionTypeIds::AWKWARD, PotionType::AWKWARD);
$this->register(PotionTypeIds::NIGHT_VISION, PotionType::NIGHT_VISION);
$this->register(PotionTypeIds::LONG_NIGHT_VISION, PotionType::LONG_NIGHT_VISION);
$this->register(PotionTypeIds::INVISIBILITY, PotionType::INVISIBILITY);
$this->register(PotionTypeIds::LONG_INVISIBILITY, PotionType::LONG_INVISIBILITY);
$this->register(PotionTypeIds::LEAPING, PotionType::LEAPING);
$this->register(PotionTypeIds::LONG_LEAPING, PotionType::LONG_LEAPING);
$this->register(PotionTypeIds::STRONG_LEAPING, PotionType::STRONG_LEAPING);
$this->register(PotionTypeIds::FIRE_RESISTANCE, PotionType::FIRE_RESISTANCE);
$this->register(PotionTypeIds::LONG_FIRE_RESISTANCE, PotionType::LONG_FIRE_RESISTANCE);
$this->register(PotionTypeIds::SWIFTNESS, PotionType::SWIFTNESS);
$this->register(PotionTypeIds::LONG_SWIFTNESS, PotionType::LONG_SWIFTNESS);
$this->register(PotionTypeIds::STRONG_SWIFTNESS, PotionType::STRONG_SWIFTNESS);
$this->register(PotionTypeIds::SLOWNESS, PotionType::SLOWNESS);
$this->register(PotionTypeIds::LONG_SLOWNESS, PotionType::LONG_SLOWNESS);
$this->register(PotionTypeIds::WATER_BREATHING, PotionType::WATER_BREATHING);
$this->register(PotionTypeIds::LONG_WATER_BREATHING, PotionType::LONG_WATER_BREATHING);
$this->register(PotionTypeIds::HEALING, PotionType::HEALING);
$this->register(PotionTypeIds::STRONG_HEALING, PotionType::STRONG_HEALING);
$this->register(PotionTypeIds::HARMING, PotionType::HARMING);
$this->register(PotionTypeIds::STRONG_HARMING, PotionType::STRONG_HARMING);
$this->register(PotionTypeIds::POISON, PotionType::POISON);
$this->register(PotionTypeIds::LONG_POISON, PotionType::LONG_POISON);
$this->register(PotionTypeIds::STRONG_POISON, PotionType::STRONG_POISON);
$this->register(PotionTypeIds::REGENERATION, PotionType::REGENERATION);
$this->register(PotionTypeIds::LONG_REGENERATION, PotionType::LONG_REGENERATION);
$this->register(PotionTypeIds::STRONG_REGENERATION, PotionType::STRONG_REGENERATION);
$this->register(PotionTypeIds::STRENGTH, PotionType::STRENGTH);
$this->register(PotionTypeIds::LONG_STRENGTH, PotionType::LONG_STRENGTH);
$this->register(PotionTypeIds::STRONG_STRENGTH, PotionType::STRONG_STRENGTH);
$this->register(PotionTypeIds::WEAKNESS, PotionType::WEAKNESS);
$this->register(PotionTypeIds::LONG_WEAKNESS, PotionType::LONG_WEAKNESS);
$this->register(PotionTypeIds::WITHER, PotionType::WITHER);
$this->register(PotionTypeIds::TURTLE_MASTER, PotionType::TURTLE_MASTER);
$this->register(PotionTypeIds::LONG_TURTLE_MASTER, PotionType::LONG_TURTLE_MASTER);
$this->register(PotionTypeIds::STRONG_TURTLE_MASTER, PotionType::STRONG_TURTLE_MASTER);
$this->register(PotionTypeIds::SLOW_FALLING, PotionType::SLOW_FALLING);
$this->register(PotionTypeIds::LONG_SLOW_FALLING, PotionType::LONG_SLOW_FALLING);
$this->register(PotionTypeIds::STRONG_SLOWNESS, PotionType::STRONG_SLOWNESS);
foreach(PotionType::cases() as $case){
$this->register(match($case){
PotionType::WATER => PotionTypeIds::WATER,
PotionType::MUNDANE => PotionTypeIds::MUNDANE,
PotionType::LONG_MUNDANE => PotionTypeIds::LONG_MUNDANE,
PotionType::THICK => PotionTypeIds::THICK,
PotionType::AWKWARD => PotionTypeIds::AWKWARD,
PotionType::NIGHT_VISION => PotionTypeIds::NIGHT_VISION,
PotionType::LONG_NIGHT_VISION => PotionTypeIds::LONG_NIGHT_VISION,
PotionType::INVISIBILITY => PotionTypeIds::INVISIBILITY,
PotionType::LONG_INVISIBILITY => PotionTypeIds::LONG_INVISIBILITY,
PotionType::LEAPING => PotionTypeIds::LEAPING,
PotionType::LONG_LEAPING => PotionTypeIds::LONG_LEAPING,
PotionType::STRONG_LEAPING => PotionTypeIds::STRONG_LEAPING,
PotionType::FIRE_RESISTANCE => PotionTypeIds::FIRE_RESISTANCE,
PotionType::LONG_FIRE_RESISTANCE => PotionTypeIds::LONG_FIRE_RESISTANCE,
PotionType::SWIFTNESS => PotionTypeIds::SWIFTNESS,
PotionType::LONG_SWIFTNESS => PotionTypeIds::LONG_SWIFTNESS,
PotionType::STRONG_SWIFTNESS => PotionTypeIds::STRONG_SWIFTNESS,
PotionType::SLOWNESS => PotionTypeIds::SLOWNESS,
PotionType::LONG_SLOWNESS => PotionTypeIds::LONG_SLOWNESS,
PotionType::WATER_BREATHING => PotionTypeIds::WATER_BREATHING,
PotionType::LONG_WATER_BREATHING => PotionTypeIds::LONG_WATER_BREATHING,
PotionType::HEALING => PotionTypeIds::HEALING,
PotionType::STRONG_HEALING => PotionTypeIds::STRONG_HEALING,
PotionType::HARMING => PotionTypeIds::HARMING,
PotionType::STRONG_HARMING => PotionTypeIds::STRONG_HARMING,
PotionType::POISON => PotionTypeIds::POISON,
PotionType::LONG_POISON => PotionTypeIds::LONG_POISON,
PotionType::STRONG_POISON => PotionTypeIds::STRONG_POISON,
PotionType::REGENERATION => PotionTypeIds::REGENERATION,
PotionType::LONG_REGENERATION => PotionTypeIds::LONG_REGENERATION,
PotionType::STRONG_REGENERATION => PotionTypeIds::STRONG_REGENERATION,
PotionType::STRENGTH => PotionTypeIds::STRENGTH,
PotionType::LONG_STRENGTH => PotionTypeIds::LONG_STRENGTH,
PotionType::STRONG_STRENGTH => PotionTypeIds::STRONG_STRENGTH,
PotionType::WEAKNESS => PotionTypeIds::WEAKNESS,
PotionType::LONG_WEAKNESS => PotionTypeIds::LONG_WEAKNESS,
PotionType::WITHER => PotionTypeIds::WITHER,
PotionType::TURTLE_MASTER => PotionTypeIds::TURTLE_MASTER,
PotionType::LONG_TURTLE_MASTER => PotionTypeIds::LONG_TURTLE_MASTER,
PotionType::STRONG_TURTLE_MASTER => PotionTypeIds::STRONG_TURTLE_MASTER,
PotionType::SLOW_FALLING => PotionTypeIds::SLOW_FALLING,
PotionType::LONG_SLOW_FALLING => PotionTypeIds::LONG_SLOW_FALLING,
PotionType::STRONG_SLOWNESS => PotionTypeIds::STRONG_SLOWNESS,
}, $case);
}
}
}

View File

@ -32,15 +32,20 @@ final class SuspiciousStewTypeIdMap{
use IntSaveIdMapTrait;
private function __construct(){
$this->register(SuspiciousStewTypeIds::POPPY, SuspiciousStewType::POPPY);
$this->register(SuspiciousStewTypeIds::CORNFLOWER, SuspiciousStewType::CORNFLOWER);
$this->register(SuspiciousStewTypeIds::TULIP, SuspiciousStewType::TULIP);
$this->register(SuspiciousStewTypeIds::AZURE_BLUET, SuspiciousStewType::AZURE_BLUET);
$this->register(SuspiciousStewTypeIds::LILY_OF_THE_VALLEY, SuspiciousStewType::LILY_OF_THE_VALLEY);
$this->register(SuspiciousStewTypeIds::DANDELION, SuspiciousStewType::DANDELION);
$this->register(SuspiciousStewTypeIds::BLUE_ORCHID, SuspiciousStewType::BLUE_ORCHID);
$this->register(SuspiciousStewTypeIds::ALLIUM, SuspiciousStewType::ALLIUM);
$this->register(SuspiciousStewTypeIds::OXEYE_DAISY, SuspiciousStewType::OXEYE_DAISY);
$this->register(SuspiciousStewTypeIds::WITHER_ROSE, SuspiciousStewType::WITHER_ROSE);
foreach(SuspiciousStewType::cases() as $case){
$this->register(match($case){
SuspiciousStewType::POPPY => SuspiciousStewTypeIds::POPPY,
SuspiciousStewType::CORNFLOWER => SuspiciousStewTypeIds::CORNFLOWER,
SuspiciousStewType::TULIP => SuspiciousStewTypeIds::TULIP,
SuspiciousStewType::AZURE_BLUET => SuspiciousStewTypeIds::AZURE_BLUET,
SuspiciousStewType::LILY_OF_THE_VALLEY => SuspiciousStewTypeIds::LILY_OF_THE_VALLEY,
SuspiciousStewType::DANDELION => SuspiciousStewTypeIds::DANDELION,
SuspiciousStewType::BLUE_ORCHID => SuspiciousStewTypeIds::BLUE_ORCHID,
SuspiciousStewType::ALLIUM => SuspiciousStewTypeIds::ALLIUM,
SuspiciousStewType::OXEYE_DAISY => SuspiciousStewTypeIds::OXEYE_DAISY,
SuspiciousStewType::WITHER_ROSE => SuspiciousStewTypeIds::WITHER_ROSE,
}, $case);
}
}
}

View File

@ -42,8 +42,8 @@ final class BlockStateData{
public const CURRENT_VERSION =
(1 << 24) | //major
(20 << 16) | //minor
(40 << 8) | //patch
(3); //revision
(60 << 8) | //patch
(1); //revision
public const TAG_NAME = "name";
public const TAG_STATES = "states";

View File

@ -56,7 +56,6 @@ final class BlockStateNames{
public const CHEMISTRY_TABLE_TYPE = "chemistry_table_type";
public const CHISEL_TYPE = "chisel_type";
public const CLUSTER_COUNT = "cluster_count";
public const COLOR = "color";
public const COLOR_BIT = "color_bit";
public const COMPOSTER_FILL_LEVEL = "composter_fill_level";
public const CONDITIONAL_BIT = "conditional_bit";
@ -66,6 +65,7 @@ final class BlockStateNames{
public const CORAL_HANG_TYPE_BIT = "coral_hang_type_bit";
public const COVERED_BIT = "covered_bit";
public const CRACKED_STATE = "cracked_state";
public const CRAFTING = "crafting";
public const DAMAGE = "damage";
public const DEAD_BIT = "dead_bit";
public const DEPRECATED = "deprecated";
@ -109,6 +109,7 @@ final class BlockStateNames{
public const OCCUPIED_BIT = "occupied_bit";
public const OLD_LEAF_TYPE = "old_leaf_type";
public const OPEN_BIT = "open_bit";
public const ORIENTATION = "orientation";
public const OUTPUT_LIT_BIT = "output_lit_bit";
public const OUTPUT_SUBTRACT_BIT = "output_subtract_bit";
public const PERSISTENT_BIT = "persistent_bit";
@ -136,7 +137,6 @@ final class BlockStateNames{
public const STONE_SLAB_TYPE_2 = "stone_slab_type_2";
public const STONE_SLAB_TYPE_3 = "stone_slab_type_3";
public const STONE_SLAB_TYPE_4 = "stone_slab_type_4";
public const STONE_TYPE = "stone_type";
public const STRIPPED_BIT = "stripped_bit";
public const STRUCTURE_BLOCK_TYPE = "structure_block_type";
public const STRUCTURE_VOID_TYPE = "structure_void_type";
@ -144,6 +144,7 @@ final class BlockStateNames{
public const TALL_GRASS_TYPE = "tall_grass_type";
public const TOGGLE_BIT = "toggle_bit";
public const TORCH_FACING_DIRECTION = "torch_facing_direction";
public const TRIAL_SPAWNER_STATE = "trial_spawner_state";
public const TRIGGERED_BIT = "triggered_bit";
public const TURTLE_EGG_COUNT = "turtle_egg_count";
public const TWISTING_VINES_AGE = "twisting_vines_age";

View File

@ -62,23 +62,6 @@ final class BlockStateStringValues{
public const CHISEL_TYPE_LINES = "lines";
public const CHISEL_TYPE_SMOOTH = "smooth";
public const COLOR_BLACK = "black";
public const COLOR_BLUE = "blue";
public const COLOR_BROWN = "brown";
public const COLOR_CYAN = "cyan";
public const COLOR_GRAY = "gray";
public const COLOR_GREEN = "green";
public const COLOR_LIGHT_BLUE = "light_blue";
public const COLOR_LIME = "lime";
public const COLOR_MAGENTA = "magenta";
public const COLOR_ORANGE = "orange";
public const COLOR_PINK = "pink";
public const COLOR_PURPLE = "purple";
public const COLOR_RED = "red";
public const COLOR_SILVER = "silver";
public const COLOR_WHITE = "white";
public const COLOR_YELLOW = "yellow";
public const CORAL_COLOR_BLUE = "blue";
public const CORAL_COLOR_PINK = "pink";
public const CORAL_COLOR_PURPLE = "purple";
@ -168,6 +151,19 @@ final class BlockStateStringValues{
public const OLD_LEAF_TYPE_OAK = "oak";
public const OLD_LEAF_TYPE_SPRUCE = "spruce";
public const ORIENTATION_DOWN_EAST = "down_east";
public const ORIENTATION_DOWN_NORTH = "down_north";
public const ORIENTATION_DOWN_SOUTH = "down_south";
public const ORIENTATION_DOWN_WEST = "down_west";
public const ORIENTATION_EAST_UP = "east_up";
public const ORIENTATION_NORTH_UP = "north_up";
public const ORIENTATION_SOUTH_UP = "south_up";
public const ORIENTATION_UP_EAST = "up_east";
public const ORIENTATION_UP_NORTH = "up_north";
public const ORIENTATION_UP_SOUTH = "up_south";
public const ORIENTATION_UP_WEST = "up_west";
public const ORIENTATION_WEST_UP = "west_up";
public const PILLAR_AXIS_X = "x";
public const PILLAR_AXIS_Y = "y";
public const PILLAR_AXIS_Z = "z";
@ -241,14 +237,6 @@ final class BlockStateStringValues{
public const STONE_SLAB_TYPE_4_SMOOTH_QUARTZ = "smooth_quartz";
public const STONE_SLAB_TYPE_4_STONE = "stone";
public const STONE_TYPE_ANDESITE = "andesite";
public const STONE_TYPE_ANDESITE_SMOOTH = "andesite_smooth";
public const STONE_TYPE_DIORITE = "diorite";
public const STONE_TYPE_DIORITE_SMOOTH = "diorite_smooth";
public const STONE_TYPE_GRANITE = "granite";
public const STONE_TYPE_GRANITE_SMOOTH = "granite_smooth";
public const STONE_TYPE_STONE = "stone";
public const STRUCTURE_BLOCK_TYPE_CORNER = "corner";
public const STRUCTURE_BLOCK_TYPE_DATA = "data";
public const STRUCTURE_BLOCK_TYPE_EXPORT = "export";

View File

@ -37,6 +37,7 @@ final class BlockTypeNames{
public const ACACIA_FENCE_GATE = "minecraft:acacia_fence_gate";
public const ACACIA_HANGING_SIGN = "minecraft:acacia_hanging_sign";
public const ACACIA_LOG = "minecraft:acacia_log";
public const ACACIA_PLANKS = "minecraft:acacia_planks";
public const ACACIA_PRESSURE_PLATE = "minecraft:acacia_pressure_plate";
public const ACACIA_STAIRS = "minecraft:acacia_stairs";
public const ACACIA_STANDING_SIGN = "minecraft:acacia_standing_sign";
@ -48,6 +49,7 @@ final class BlockTypeNames{
public const AMETHYST_BLOCK = "minecraft:amethyst_block";
public const AMETHYST_CLUSTER = "minecraft:amethyst_cluster";
public const ANCIENT_DEBRIS = "minecraft:ancient_debris";
public const ANDESITE = "minecraft:andesite";
public const ANDESITE_STAIRS = "minecraft:andesite_stairs";
public const ANVIL = "minecraft:anvil";
public const AZALEA = "minecraft:azalea";
@ -90,6 +92,7 @@ final class BlockTypeNames{
public const BIRCH_FENCE_GATE = "minecraft:birch_fence_gate";
public const BIRCH_HANGING_SIGN = "minecraft:birch_hanging_sign";
public const BIRCH_LOG = "minecraft:birch_log";
public const BIRCH_PLANKS = "minecraft:birch_planks";
public const BIRCH_PRESSURE_PLATE = "minecraft:birch_pressure_plate";
public const BIRCH_STAIRS = "minecraft:birch_stairs";
public const BIRCH_STANDING_SIGN = "minecraft:birch_standing_sign";
@ -185,9 +188,12 @@ final class BlockTypeNames{
public const CHERRY_WOOD = "minecraft:cherry_wood";
public const CHEST = "minecraft:chest";
public const CHISELED_BOOKSHELF = "minecraft:chiseled_bookshelf";
public const CHISELED_COPPER = "minecraft:chiseled_copper";
public const CHISELED_DEEPSLATE = "minecraft:chiseled_deepslate";
public const CHISELED_NETHER_BRICKS = "minecraft:chiseled_nether_bricks";
public const CHISELED_POLISHED_BLACKSTONE = "minecraft:chiseled_polished_blackstone";
public const CHISELED_TUFF = "minecraft:chiseled_tuff";
public const CHISELED_TUFF_BRICKS = "minecraft:chiseled_tuff_bricks";
public const CHORUS_FLOWER = "minecraft:chorus_flower";
public const CHORUS_PLANT = "minecraft:chorus_plant";
public const CLAY = "minecraft:clay";
@ -208,7 +214,11 @@ final class BlockTypeNames{
public const COMPOSTER = "minecraft:composter";
public const CONDUIT = "minecraft:conduit";
public const COPPER_BLOCK = "minecraft:copper_block";
public const COPPER_BULB = "minecraft:copper_bulb";
public const COPPER_DOOR = "minecraft:copper_door";
public const COPPER_GRATE = "minecraft:copper_grate";
public const COPPER_ORE = "minecraft:copper_ore";
public const COPPER_TRAPDOOR = "minecraft:copper_trapdoor";
public const CORAL_BLOCK = "minecraft:coral_block";
public const CORAL_FAN = "minecraft:coral_fan";
public const CORAL_FAN_DEAD = "minecraft:coral_fan_dead";
@ -219,6 +229,7 @@ final class BlockTypeNames{
public const CRACKED_DEEPSLATE_TILES = "minecraft:cracked_deepslate_tiles";
public const CRACKED_NETHER_BRICKS = "minecraft:cracked_nether_bricks";
public const CRACKED_POLISHED_BLACKSTONE_BRICKS = "minecraft:cracked_polished_blackstone_bricks";
public const CRAFTER = "minecraft:crafter";
public const CRAFTING_TABLE = "minecraft:crafting_table";
public const CRIMSON_BUTTON = "minecraft:crimson_button";
public const CRIMSON_DOOR = "minecraft:crimson_door";
@ -259,6 +270,7 @@ final class BlockTypeNames{
public const DARK_OAK_FENCE_GATE = "minecraft:dark_oak_fence_gate";
public const DARK_OAK_HANGING_SIGN = "minecraft:dark_oak_hanging_sign";
public const DARK_OAK_LOG = "minecraft:dark_oak_log";
public const DARK_OAK_PLANKS = "minecraft:dark_oak_planks";
public const DARK_OAK_PRESSURE_PLATE = "minecraft:dark_oak_pressure_plate";
public const DARK_OAK_STAIRS = "minecraft:dark_oak_stairs";
public const DARK_OAK_TRAPDOOR = "minecraft:dark_oak_trapdoor";
@ -297,6 +309,7 @@ final class BlockTypeNames{
public const DETECTOR_RAIL = "minecraft:detector_rail";
public const DIAMOND_BLOCK = "minecraft:diamond_block";
public const DIAMOND_ORE = "minecraft:diamond_ore";
public const DIORITE = "minecraft:diorite";
public const DIORITE_STAIRS = "minecraft:diorite_stairs";
public const DIRT = "minecraft:dirt";
public const DIRT_WITH_ROOTS = "minecraft:dirt_with_roots";
@ -442,7 +455,12 @@ final class BlockTypeNames{
public const END_ROD = "minecraft:end_rod";
public const END_STONE = "minecraft:end_stone";
public const ENDER_CHEST = "minecraft:ender_chest";
public const EXPOSED_CHISELED_COPPER = "minecraft:exposed_chiseled_copper";
public const EXPOSED_COPPER = "minecraft:exposed_copper";
public const EXPOSED_COPPER_BULB = "minecraft:exposed_copper_bulb";
public const EXPOSED_COPPER_DOOR = "minecraft:exposed_copper_door";
public const EXPOSED_COPPER_GRATE = "minecraft:exposed_copper_grate";
public const EXPOSED_COPPER_TRAPDOOR = "minecraft:exposed_copper_trapdoor";
public const EXPOSED_CUT_COPPER = "minecraft:exposed_cut_copper";
public const EXPOSED_CUT_COPPER_SLAB = "minecraft:exposed_cut_copper_slab";
public const EXPOSED_CUT_COPPER_STAIRS = "minecraft:exposed_cut_copper_stairs";
@ -470,6 +488,7 @@ final class BlockTypeNames{
public const GOLD_BLOCK = "minecraft:gold_block";
public const GOLD_ORE = "minecraft:gold_ore";
public const GOLDEN_RAIL = "minecraft:golden_rail";
public const GRANITE = "minecraft:granite";
public const GRANITE_STAIRS = "minecraft:granite_stairs";
public const GRASS = "minecraft:grass";
public const GRASS_PATH = "minecraft:grass_path";
@ -498,10 +517,40 @@ final class BlockTypeNames{
public const GREEN_WOOL = "minecraft:green_wool";
public const GRINDSTONE = "minecraft:grindstone";
public const HANGING_ROOTS = "minecraft:hanging_roots";
public const HARD_BLACK_STAINED_GLASS = "minecraft:hard_black_stained_glass";
public const HARD_BLACK_STAINED_GLASS_PANE = "minecraft:hard_black_stained_glass_pane";
public const HARD_BLUE_STAINED_GLASS = "minecraft:hard_blue_stained_glass";
public const HARD_BLUE_STAINED_GLASS_PANE = "minecraft:hard_blue_stained_glass_pane";
public const HARD_BROWN_STAINED_GLASS = "minecraft:hard_brown_stained_glass";
public const HARD_BROWN_STAINED_GLASS_PANE = "minecraft:hard_brown_stained_glass_pane";
public const HARD_CYAN_STAINED_GLASS = "minecraft:hard_cyan_stained_glass";
public const HARD_CYAN_STAINED_GLASS_PANE = "minecraft:hard_cyan_stained_glass_pane";
public const HARD_GLASS = "minecraft:hard_glass";
public const HARD_GLASS_PANE = "minecraft:hard_glass_pane";
public const HARD_STAINED_GLASS = "minecraft:hard_stained_glass";
public const HARD_STAINED_GLASS_PANE = "minecraft:hard_stained_glass_pane";
public const HARD_GRAY_STAINED_GLASS = "minecraft:hard_gray_stained_glass";
public const HARD_GRAY_STAINED_GLASS_PANE = "minecraft:hard_gray_stained_glass_pane";
public const HARD_GREEN_STAINED_GLASS = "minecraft:hard_green_stained_glass";
public const HARD_GREEN_STAINED_GLASS_PANE = "minecraft:hard_green_stained_glass_pane";
public const HARD_LIGHT_BLUE_STAINED_GLASS = "minecraft:hard_light_blue_stained_glass";
public const HARD_LIGHT_BLUE_STAINED_GLASS_PANE = "minecraft:hard_light_blue_stained_glass_pane";
public const HARD_LIGHT_GRAY_STAINED_GLASS = "minecraft:hard_light_gray_stained_glass";
public const HARD_LIGHT_GRAY_STAINED_GLASS_PANE = "minecraft:hard_light_gray_stained_glass_pane";
public const HARD_LIME_STAINED_GLASS = "minecraft:hard_lime_stained_glass";
public const HARD_LIME_STAINED_GLASS_PANE = "minecraft:hard_lime_stained_glass_pane";
public const HARD_MAGENTA_STAINED_GLASS = "minecraft:hard_magenta_stained_glass";
public const HARD_MAGENTA_STAINED_GLASS_PANE = "minecraft:hard_magenta_stained_glass_pane";
public const HARD_ORANGE_STAINED_GLASS = "minecraft:hard_orange_stained_glass";
public const HARD_ORANGE_STAINED_GLASS_PANE = "minecraft:hard_orange_stained_glass_pane";
public const HARD_PINK_STAINED_GLASS = "minecraft:hard_pink_stained_glass";
public const HARD_PINK_STAINED_GLASS_PANE = "minecraft:hard_pink_stained_glass_pane";
public const HARD_PURPLE_STAINED_GLASS = "minecraft:hard_purple_stained_glass";
public const HARD_PURPLE_STAINED_GLASS_PANE = "minecraft:hard_purple_stained_glass_pane";
public const HARD_RED_STAINED_GLASS = "minecraft:hard_red_stained_glass";
public const HARD_RED_STAINED_GLASS_PANE = "minecraft:hard_red_stained_glass_pane";
public const HARD_WHITE_STAINED_GLASS = "minecraft:hard_white_stained_glass";
public const HARD_WHITE_STAINED_GLASS_PANE = "minecraft:hard_white_stained_glass_pane";
public const HARD_YELLOW_STAINED_GLASS = "minecraft:hard_yellow_stained_glass";
public const HARD_YELLOW_STAINED_GLASS_PANE = "minecraft:hard_yellow_stained_glass_pane";
public const HARDENED_CLAY = "minecraft:hardened_clay";
public const HAY_BLOCK = "minecraft:hay_block";
public const HEAVY_WEIGHTED_PRESSURE_PLATE = "minecraft:heavy_weighted_pressure_plate";
@ -527,6 +576,7 @@ final class BlockTypeNames{
public const JUNGLE_FENCE_GATE = "minecraft:jungle_fence_gate";
public const JUNGLE_HANGING_SIGN = "minecraft:jungle_hanging_sign";
public const JUNGLE_LOG = "minecraft:jungle_log";
public const JUNGLE_PLANKS = "minecraft:jungle_planks";
public const JUNGLE_PRESSURE_PLATE = "minecraft:jungle_pressure_plate";
public const JUNGLE_STAIRS = "minecraft:jungle_stairs";
public const JUNGLE_STANDING_SIGN = "minecraft:jungle_standing_sign";
@ -651,6 +701,7 @@ final class BlockTypeNames{
public const OAK_FENCE = "minecraft:oak_fence";
public const OAK_HANGING_SIGN = "minecraft:oak_hanging_sign";
public const OAK_LOG = "minecraft:oak_log";
public const OAK_PLANKS = "minecraft:oak_planks";
public const OAK_STAIRS = "minecraft:oak_stairs";
public const OBSERVER = "minecraft:observer";
public const OBSIDIAN = "minecraft:obsidian";
@ -666,7 +717,12 @@ final class BlockTypeNames{
public const ORANGE_STAINED_GLASS_PANE = "minecraft:orange_stained_glass_pane";
public const ORANGE_TERRACOTTA = "minecraft:orange_terracotta";
public const ORANGE_WOOL = "minecraft:orange_wool";
public const OXIDIZED_CHISELED_COPPER = "minecraft:oxidized_chiseled_copper";
public const OXIDIZED_COPPER = "minecraft:oxidized_copper";
public const OXIDIZED_COPPER_BULB = "minecraft:oxidized_copper_bulb";
public const OXIDIZED_COPPER_DOOR = "minecraft:oxidized_copper_door";
public const OXIDIZED_COPPER_GRATE = "minecraft:oxidized_copper_grate";
public const OXIDIZED_COPPER_TRAPDOOR = "minecraft:oxidized_copper_trapdoor";
public const OXIDIZED_CUT_COPPER = "minecraft:oxidized_cut_copper";
public const OXIDIZED_CUT_COPPER_SLAB = "minecraft:oxidized_cut_copper_slab";
public const OXIDIZED_CUT_COPPER_STAIRS = "minecraft:oxidized_cut_copper_stairs";
@ -690,9 +746,9 @@ final class BlockTypeNames{
public const PISTON_ARM_COLLISION = "minecraft:piston_arm_collision";
public const PITCHER_CROP = "minecraft:pitcher_crop";
public const PITCHER_PLANT = "minecraft:pitcher_plant";
public const PLANKS = "minecraft:planks";
public const PODZOL = "minecraft:podzol";
public const POINTED_DRIPSTONE = "minecraft:pointed_dripstone";
public const POLISHED_ANDESITE = "minecraft:polished_andesite";
public const POLISHED_ANDESITE_STAIRS = "minecraft:polished_andesite_stairs";
public const POLISHED_BASALT = "minecraft:polished_basalt";
public const POLISHED_BLACKSTONE = "minecraft:polished_blackstone";
@ -712,8 +768,15 @@ final class BlockTypeNames{
public const POLISHED_DEEPSLATE_SLAB = "minecraft:polished_deepslate_slab";
public const POLISHED_DEEPSLATE_STAIRS = "minecraft:polished_deepslate_stairs";
public const POLISHED_DEEPSLATE_WALL = "minecraft:polished_deepslate_wall";
public const POLISHED_DIORITE = "minecraft:polished_diorite";
public const POLISHED_DIORITE_STAIRS = "minecraft:polished_diorite_stairs";
public const POLISHED_GRANITE = "minecraft:polished_granite";
public const POLISHED_GRANITE_STAIRS = "minecraft:polished_granite_stairs";
public const POLISHED_TUFF = "minecraft:polished_tuff";
public const POLISHED_TUFF_DOUBLE_SLAB = "minecraft:polished_tuff_double_slab";
public const POLISHED_TUFF_SLAB = "minecraft:polished_tuff_slab";
public const POLISHED_TUFF_STAIRS = "minecraft:polished_tuff_stairs";
public const POLISHED_TUFF_WALL = "minecraft:polished_tuff_wall";
public const PORTAL = "minecraft:portal";
public const POTATOES = "minecraft:potatoes";
public const POWDER_SNOW = "minecraft:powder_snow";
@ -816,6 +879,7 @@ final class BlockTypeNames{
public const SPRUCE_FENCE_GATE = "minecraft:spruce_fence_gate";
public const SPRUCE_HANGING_SIGN = "minecraft:spruce_hanging_sign";
public const SPRUCE_LOG = "minecraft:spruce_log";
public const SPRUCE_PLANKS = "minecraft:spruce_planks";
public const SPRUCE_PRESSURE_PLATE = "minecraft:spruce_pressure_plate";
public const SPRUCE_STAIRS = "minecraft:spruce_stairs";
public const SPRUCE_STANDING_SIGN = "minecraft:spruce_standing_sign";
@ -866,10 +930,20 @@ final class BlockTypeNames{
public const TORCHFLOWER_CROP = "minecraft:torchflower_crop";
public const TRAPDOOR = "minecraft:trapdoor";
public const TRAPPED_CHEST = "minecraft:trapped_chest";
public const TRIAL_SPAWNER = "minecraft:trial_spawner";
public const TRIP_WIRE = "minecraft:trip_wire";
public const TRIPWIRE_HOOK = "minecraft:tripwire_hook";
public const TUBE_CORAL = "minecraft:tube_coral";
public const TUFF = "minecraft:tuff";
public const TUFF_BRICK_DOUBLE_SLAB = "minecraft:tuff_brick_double_slab";
public const TUFF_BRICK_SLAB = "minecraft:tuff_brick_slab";
public const TUFF_BRICK_STAIRS = "minecraft:tuff_brick_stairs";
public const TUFF_BRICK_WALL = "minecraft:tuff_brick_wall";
public const TUFF_BRICKS = "minecraft:tuff_bricks";
public const TUFF_DOUBLE_SLAB = "minecraft:tuff_double_slab";
public const TUFF_SLAB = "minecraft:tuff_slab";
public const TUFF_STAIRS = "minecraft:tuff_stairs";
public const TUFF_WALL = "minecraft:tuff_wall";
public const TURTLE_EGG = "minecraft:turtle_egg";
public const TWISTING_VINES = "minecraft:twisting_vines";
public const UNDERWATER_TORCH = "minecraft:underwater_torch";
@ -903,27 +977,52 @@ final class BlockTypeNames{
public const WARPED_WART_BLOCK = "minecraft:warped_wart_block";
public const WATER = "minecraft:water";
public const WATERLILY = "minecraft:waterlily";
public const WAXED_CHISELED_COPPER = "minecraft:waxed_chiseled_copper";
public const WAXED_COPPER = "minecraft:waxed_copper";
public const WAXED_COPPER_BULB = "minecraft:waxed_copper_bulb";
public const WAXED_COPPER_DOOR = "minecraft:waxed_copper_door";
public const WAXED_COPPER_GRATE = "minecraft:waxed_copper_grate";
public const WAXED_COPPER_TRAPDOOR = "minecraft:waxed_copper_trapdoor";
public const WAXED_CUT_COPPER = "minecraft:waxed_cut_copper";
public const WAXED_CUT_COPPER_SLAB = "minecraft:waxed_cut_copper_slab";
public const WAXED_CUT_COPPER_STAIRS = "minecraft:waxed_cut_copper_stairs";
public const WAXED_DOUBLE_CUT_COPPER_SLAB = "minecraft:waxed_double_cut_copper_slab";
public const WAXED_EXPOSED_CHISELED_COPPER = "minecraft:waxed_exposed_chiseled_copper";
public const WAXED_EXPOSED_COPPER = "minecraft:waxed_exposed_copper";
public const WAXED_EXPOSED_COPPER_BULB = "minecraft:waxed_exposed_copper_bulb";
public const WAXED_EXPOSED_COPPER_DOOR = "minecraft:waxed_exposed_copper_door";
public const WAXED_EXPOSED_COPPER_GRATE = "minecraft:waxed_exposed_copper_grate";
public const WAXED_EXPOSED_COPPER_TRAPDOOR = "minecraft:waxed_exposed_copper_trapdoor";
public const WAXED_EXPOSED_CUT_COPPER = "minecraft:waxed_exposed_cut_copper";
public const WAXED_EXPOSED_CUT_COPPER_SLAB = "minecraft:waxed_exposed_cut_copper_slab";
public const WAXED_EXPOSED_CUT_COPPER_STAIRS = "minecraft:waxed_exposed_cut_copper_stairs";
public const WAXED_EXPOSED_DOUBLE_CUT_COPPER_SLAB = "minecraft:waxed_exposed_double_cut_copper_slab";
public const WAXED_OXIDIZED_CHISELED_COPPER = "minecraft:waxed_oxidized_chiseled_copper";
public const WAXED_OXIDIZED_COPPER = "minecraft:waxed_oxidized_copper";
public const WAXED_OXIDIZED_COPPER_BULB = "minecraft:waxed_oxidized_copper_bulb";
public const WAXED_OXIDIZED_COPPER_DOOR = "minecraft:waxed_oxidized_copper_door";
public const WAXED_OXIDIZED_COPPER_GRATE = "minecraft:waxed_oxidized_copper_grate";
public const WAXED_OXIDIZED_COPPER_TRAPDOOR = "minecraft:waxed_oxidized_copper_trapdoor";
public const WAXED_OXIDIZED_CUT_COPPER = "minecraft:waxed_oxidized_cut_copper";
public const WAXED_OXIDIZED_CUT_COPPER_SLAB = "minecraft:waxed_oxidized_cut_copper_slab";
public const WAXED_OXIDIZED_CUT_COPPER_STAIRS = "minecraft:waxed_oxidized_cut_copper_stairs";
public const WAXED_OXIDIZED_DOUBLE_CUT_COPPER_SLAB = "minecraft:waxed_oxidized_double_cut_copper_slab";
public const WAXED_WEATHERED_CHISELED_COPPER = "minecraft:waxed_weathered_chiseled_copper";
public const WAXED_WEATHERED_COPPER = "minecraft:waxed_weathered_copper";
public const WAXED_WEATHERED_COPPER_BULB = "minecraft:waxed_weathered_copper_bulb";
public const WAXED_WEATHERED_COPPER_DOOR = "minecraft:waxed_weathered_copper_door";
public const WAXED_WEATHERED_COPPER_GRATE = "minecraft:waxed_weathered_copper_grate";
public const WAXED_WEATHERED_COPPER_TRAPDOOR = "minecraft:waxed_weathered_copper_trapdoor";
public const WAXED_WEATHERED_CUT_COPPER = "minecraft:waxed_weathered_cut_copper";
public const WAXED_WEATHERED_CUT_COPPER_SLAB = "minecraft:waxed_weathered_cut_copper_slab";
public const WAXED_WEATHERED_CUT_COPPER_STAIRS = "minecraft:waxed_weathered_cut_copper_stairs";
public const WAXED_WEATHERED_DOUBLE_CUT_COPPER_SLAB = "minecraft:waxed_weathered_double_cut_copper_slab";
public const WEATHERED_CHISELED_COPPER = "minecraft:weathered_chiseled_copper";
public const WEATHERED_COPPER = "minecraft:weathered_copper";
public const WEATHERED_COPPER_BULB = "minecraft:weathered_copper_bulb";
public const WEATHERED_COPPER_DOOR = "minecraft:weathered_copper_door";
public const WEATHERED_COPPER_GRATE = "minecraft:weathered_copper_grate";
public const WEATHERED_COPPER_TRAPDOOR = "minecraft:weathered_copper_trapdoor";
public const WEATHERED_CUT_COPPER = "minecraft:weathered_cut_copper";
public const WEATHERED_CUT_COPPER_SLAB = "minecraft:weathered_cut_copper_slab";
public const WEATHERED_CUT_COPPER_STAIRS = "minecraft:weathered_cut_copper_stairs";

View File

@ -315,6 +315,44 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
}
public function registerFlatColorBlockSerializers() : void{
$this->map(Blocks::STAINED_HARDENED_GLASS(), fn(StainedHardenedGlass $block) => Writer::create(match($block->getColor()){
DyeColor::BLACK => Ids::HARD_BLACK_STAINED_GLASS,
DyeColor::BLUE => Ids::HARD_BLUE_STAINED_GLASS,
DyeColor::BROWN => Ids::HARD_BROWN_STAINED_GLASS,
DyeColor::CYAN => Ids::HARD_CYAN_STAINED_GLASS,
DyeColor::GRAY => Ids::HARD_GRAY_STAINED_GLASS,
DyeColor::GREEN => Ids::HARD_GREEN_STAINED_GLASS,
DyeColor::LIGHT_BLUE => Ids::HARD_LIGHT_BLUE_STAINED_GLASS,
DyeColor::LIGHT_GRAY => Ids::HARD_LIGHT_GRAY_STAINED_GLASS,
DyeColor::LIME => Ids::HARD_LIME_STAINED_GLASS,
DyeColor::MAGENTA => Ids::HARD_MAGENTA_STAINED_GLASS,
DyeColor::ORANGE => Ids::HARD_ORANGE_STAINED_GLASS,
DyeColor::PINK => Ids::HARD_PINK_STAINED_GLASS,
DyeColor::PURPLE => Ids::HARD_PURPLE_STAINED_GLASS,
DyeColor::RED => Ids::HARD_RED_STAINED_GLASS,
DyeColor::WHITE => Ids::HARD_WHITE_STAINED_GLASS,
DyeColor::YELLOW => Ids::HARD_YELLOW_STAINED_GLASS,
}));
$this->map(Blocks::STAINED_HARDENED_GLASS_PANE(), fn(StainedHardenedGlassPane $block) => Writer::create(match($block->getColor()){
DyeColor::BLACK => Ids::HARD_BLACK_STAINED_GLASS_PANE,
DyeColor::BLUE => Ids::HARD_BLUE_STAINED_GLASS_PANE,
DyeColor::BROWN => Ids::HARD_BROWN_STAINED_GLASS_PANE,
DyeColor::CYAN => Ids::HARD_CYAN_STAINED_GLASS_PANE,
DyeColor::GRAY => Ids::HARD_GRAY_STAINED_GLASS_PANE,
DyeColor::GREEN => Ids::HARD_GREEN_STAINED_GLASS_PANE,
DyeColor::LIGHT_BLUE => Ids::HARD_LIGHT_BLUE_STAINED_GLASS_PANE,
DyeColor::LIGHT_GRAY => Ids::HARD_LIGHT_GRAY_STAINED_GLASS_PANE,
DyeColor::LIME => Ids::HARD_LIME_STAINED_GLASS_PANE,
DyeColor::MAGENTA => Ids::HARD_MAGENTA_STAINED_GLASS_PANE,
DyeColor::ORANGE => Ids::HARD_ORANGE_STAINED_GLASS_PANE,
DyeColor::PINK => Ids::HARD_PINK_STAINED_GLASS_PANE,
DyeColor::PURPLE => Ids::HARD_PURPLE_STAINED_GLASS_PANE,
DyeColor::RED => Ids::HARD_RED_STAINED_GLASS_PANE,
DyeColor::WHITE => Ids::HARD_WHITE_STAINED_GLASS_PANE,
DyeColor::YELLOW => Ids::HARD_YELLOW_STAINED_GLASS_PANE,
}));
$this->map(Blocks::GLAZED_TERRACOTTA(), function(GlazedTerracotta $block) : Writer{
return Writer::create(match($block->getColor()){
DyeColor::BLACK => Ids::BLACK_GLAZED_TERRACOTTA,
@ -521,7 +559,8 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$this->map(Blocks::ACACIA_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::ACACIA_WALL_SIGN)));
$this->mapLog(Blocks::ACACIA_LOG(), Ids::ACACIA_LOG, Ids::STRIPPED_ACACIA_LOG);
$this->mapSimple(Blocks::ACACIA_FENCE(), Ids::ACACIA_FENCE);
//wood, planks and slabs still use the old way of storing wood type
$this->mapSimple(Blocks::ACACIA_PLANKS(), Ids::ACACIA_PLANKS);
//wood and slabs still use the old way of storing wood type
$this->map(Blocks::BIRCH_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::BIRCH_BUTTON)));
$this->map(Blocks::BIRCH_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::BIRCH_DOOR)));
@ -532,8 +571,9 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$this->map(Blocks::BIRCH_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::BIRCH_WALL_SIGN)));
$this->mapLog(Blocks::BIRCH_LOG(), Ids::BIRCH_LOG, Ids::STRIPPED_BIRCH_LOG);
$this->mapSimple(Blocks::BIRCH_FENCE(), Ids::BIRCH_FENCE);
$this->mapSimple(Blocks::BIRCH_PLANKS(), Ids::BIRCH_PLANKS);
$this->mapStairs(Blocks::BIRCH_STAIRS(), Ids::BIRCH_STAIRS);
//wood, planks and slabs still use the old way of storing wood type
//wood and slabs still use the old way of storing wood type
$this->map(Blocks::CHERRY_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::CHERRY_BUTTON)));
$this->map(Blocks::CHERRY_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::CHERRY_DOOR)));
@ -582,8 +622,9 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$this->map(Blocks::DARK_OAK_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::DARKOAK_WALL_SIGN)));
$this->mapLog(Blocks::DARK_OAK_LOG(), Ids::DARK_OAK_LOG, Ids::STRIPPED_DARK_OAK_LOG);
$this->mapSimple(Blocks::DARK_OAK_FENCE(), Ids::DARK_OAK_FENCE);
$this->mapSimple(Blocks::DARK_OAK_PLANKS(), Ids::DARK_OAK_PLANKS);
$this->mapStairs(Blocks::DARK_OAK_STAIRS(), Ids::DARK_OAK_STAIRS);
//wood, planks and slabs still use the old way of storing wood type
//wood and slabs still use the old way of storing wood type
$this->map(Blocks::JUNGLE_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::JUNGLE_BUTTON)));
$this->map(Blocks::JUNGLE_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::JUNGLE_DOOR)));
@ -594,8 +635,9 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$this->map(Blocks::JUNGLE_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::JUNGLE_WALL_SIGN)));
$this->mapLog(Blocks::JUNGLE_LOG(), Ids::JUNGLE_LOG, Ids::STRIPPED_JUNGLE_LOG);
$this->mapSimple(Blocks::JUNGLE_FENCE(), Ids::JUNGLE_FENCE);
$this->mapSimple(Blocks::JUNGLE_PLANKS(), Ids::JUNGLE_PLANKS);
$this->mapStairs(Blocks::JUNGLE_STAIRS(), Ids::JUNGLE_STAIRS);
//wood, planks and slabs still use the old way of storing wood type
//wood and slabs still use the old way of storing wood type
$this->map(Blocks::MANGROVE_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::MANGROVE_BUTTON)));
$this->map(Blocks::MANGROVE_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::MANGROVE_DOOR)));
@ -630,20 +672,22 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$this->map(Blocks::OAK_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::WALL_SIGN)));
$this->mapLog(Blocks::OAK_LOG(), Ids::OAK_LOG, Ids::STRIPPED_OAK_LOG);
$this->mapSimple(Blocks::OAK_FENCE(), Ids::OAK_FENCE);
$this->mapSimple(Blocks::OAK_PLANKS(), Ids::OAK_PLANKS);
$this->mapStairs(Blocks::OAK_STAIRS(), Ids::OAK_STAIRS);
//wood, planks and slabs still use the old way of storing wood type
//wood and slabs still use the old way of storing wood type
$this->mapSimple(Blocks::SPRUCE_FENCE(), Ids::SPRUCE_FENCE);
$this->mapLog(Blocks::SPRUCE_LOG(), Ids::SPRUCE_LOG, Ids::STRIPPED_SPRUCE_LOG);
$this->map(Blocks::SPRUCE_BUTTON(), fn(WoodenButton $block) => Helper::encodeButton($block, new Writer(Ids::SPRUCE_BUTTON)));
$this->map(Blocks::SPRUCE_DOOR(), fn(WoodenDoor $block) => Helper::encodeDoor($block, new Writer(Ids::SPRUCE_DOOR)));
$this->map(Blocks::SPRUCE_FENCE_GATE(), fn(FenceGate $block) => Helper::encodeFenceGate($block, new Writer(Ids::SPRUCE_FENCE_GATE)));
$this->map(Blocks::SPRUCE_PRESSURE_PLATE(), fn(WoodenPressurePlate $block) => Helper::encodeSimplePressurePlate($block, new Writer(Ids::SPRUCE_PRESSURE_PLATE)));
$this->map(Blocks::SPRUCE_SIGN(), fn(FloorSign $block) => Helper::encodeFloorSign($block, new Writer(Ids::SPRUCE_STANDING_SIGN)));
$this->mapStairs(Blocks::SPRUCE_STAIRS(), Ids::SPRUCE_STAIRS);
$this->map(Blocks::SPRUCE_TRAPDOOR(), fn(WoodenTrapdoor $block) => Helper::encodeTrapdoor($block, new Writer(Ids::SPRUCE_TRAPDOOR)));
$this->map(Blocks::SPRUCE_WALL_SIGN(), fn(WallSign $block) => Helper::encodeWallSign($block, new Writer(Ids::SPRUCE_WALL_SIGN)));
//wood, planks and slabs still use the old way of storing wood type
$this->mapLog(Blocks::SPRUCE_LOG(), Ids::SPRUCE_LOG, Ids::STRIPPED_SPRUCE_LOG);
$this->mapSimple(Blocks::SPRUCE_FENCE(), Ids::SPRUCE_FENCE);
$this->mapSimple(Blocks::SPRUCE_PLANKS(), Ids::SPRUCE_PLANKS);
$this->mapStairs(Blocks::SPRUCE_STAIRS(), Ids::SPRUCE_STAIRS);
//wood and slabs still use the old way of storing wood type
$this->map(Blocks::WARPED_BUTTON(), fn(Button $block) => Helper::encodeButton($block, new Writer(Ids::WARPED_BUTTON)));
$this->map(Blocks::WARPED_DOOR(), fn(Door $block) => Helper::encodeDoor($block, new Writer(Ids::WARPED_DOOR)));
@ -661,18 +705,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
}
private function registerLegacyWoodBlockSerializers() : void{
foreach([
StringValues::WOOD_TYPE_ACACIA => Blocks::ACACIA_PLANKS(),
StringValues::WOOD_TYPE_BIRCH => Blocks::BIRCH_PLANKS(),
StringValues::WOOD_TYPE_DARK_OAK => Blocks::DARK_OAK_PLANKS(),
StringValues::WOOD_TYPE_JUNGLE => Blocks::JUNGLE_PLANKS(),
StringValues::WOOD_TYPE_OAK => Blocks::OAK_PLANKS(),
StringValues::WOOD_TYPE_SPRUCE => Blocks::SPRUCE_PLANKS(),
] as $woodType => $block){
$this->map($block, fn() => Writer::create(Ids::PLANKS)
->writeString(StateNames::WOOD_TYPE, $woodType));
}
foreach([
StringValues::WOOD_TYPE_ACACIA => Blocks::ACACIA_SLAB(),
StringValues::WOOD_TYPE_BIRCH => Blocks::BIRCH_SLAB(),
@ -716,6 +748,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$this->mapSimple(Blocks::AIR(), Ids::AIR);
$this->mapSimple(Blocks::AMETHYST(), Ids::AMETHYST_BLOCK);
$this->mapSimple(Blocks::ANCIENT_DEBRIS(), Ids::ANCIENT_DEBRIS);
$this->mapSimple(Blocks::ANDESITE(), Ids::ANDESITE);
$this->mapSimple(Blocks::BARRIER(), Ids::BARRIER);
$this->mapSimple(Blocks::BEACON(), Ids::BEACON);
$this->mapSimple(Blocks::BLACKSTONE(), Ids::BLACKSTONE);
@ -758,6 +791,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$this->mapSimple(Blocks::DEEPSLATE_TILES(), Ids::DEEPSLATE_TILES);
$this->mapSimple(Blocks::DIAMOND(), Ids::DIAMOND_BLOCK);
$this->mapSimple(Blocks::DIAMOND_ORE(), Ids::DIAMOND_ORE);
$this->mapSimple(Blocks::DIORITE(), Ids::DIORITE);
$this->mapSimple(Blocks::DRAGON_EGG(), Ids::DRAGON_EGG);
$this->mapSimple(Blocks::DRIED_KELP(), Ids::DRIED_KELP_BLOCK);
$this->mapSimple(Blocks::ELEMENT_ACTINIUM(), Ids::ELEMENT_89);
@ -892,6 +926,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$this->mapSimple(Blocks::GLOWSTONE(), Ids::GLOWSTONE);
$this->mapSimple(Blocks::GOLD(), Ids::GOLD_BLOCK);
$this->mapSimple(Blocks::GOLD_ORE(), Ids::GOLD_ORE);
$this->mapSimple(Blocks::GRANITE(), Ids::GRANITE);
$this->mapSimple(Blocks::GRASS(), Ids::GRASS);
$this->mapSimple(Blocks::GRASS_PATH(), Ids::GRASS_PATH);
$this->mapSimple(Blocks::GRAVEL(), Ids::GRAVEL);
@ -933,9 +968,12 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$this->mapSimple(Blocks::PACKED_ICE(), Ids::PACKED_ICE);
$this->mapSimple(Blocks::PACKED_MUD(), Ids::PACKED_MUD);
$this->mapSimple(Blocks::PODZOL(), Ids::PODZOL);
$this->mapSimple(Blocks::POLISHED_ANDESITE(), Ids::POLISHED_ANDESITE);
$this->mapSimple(Blocks::POLISHED_BLACKSTONE(), Ids::POLISHED_BLACKSTONE);
$this->mapSimple(Blocks::POLISHED_BLACKSTONE_BRICKS(), Ids::POLISHED_BLACKSTONE_BRICKS);
$this->mapSimple(Blocks::POLISHED_DEEPSLATE(), Ids::POLISHED_DEEPSLATE);
$this->mapSimple(Blocks::POLISHED_DIORITE(), Ids::POLISHED_DIORITE);
$this->mapSimple(Blocks::POLISHED_GRANITE(), Ids::POLISHED_GRANITE);
$this->mapSimple(Blocks::QUARTZ_BRICKS(), Ids::QUARTZ_BRICKS);
$this->mapSimple(Blocks::RAW_COPPER(), Ids::RAW_COPPER_BLOCK);
$this->mapSimple(Blocks::RAW_GOLD(), Ids::RAW_GOLD_BLOCK);
@ -957,6 +995,7 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$this->mapSimple(Blocks::SOUL_SAND(), Ids::SOUL_SAND);
$this->mapSimple(Blocks::SOUL_SOIL(), Ids::SOUL_SOIL);
$this->mapSimple(Blocks::SPORE_BLOSSOM(), Ids::SPORE_BLOSSOM);
$this->mapSimple(Blocks::STONE(), Ids::STONE);
$this->mapSimple(Blocks::TINTED_GLASS(), Ids::TINTED_GLASS);
$this->mapSimple(Blocks::TORCHFLOWER(), Ids::TORCHFLOWER);
$this->mapSimple(Blocks::TUFF(), Ids::TUFF);
@ -985,7 +1024,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
})
->writeBlockFace($block->getFacing())
);
$this->map(Blocks::ANDESITE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_ANDESITE));
$this->map(Blocks::ANDESITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_ANDESITE));
$this->map(Blocks::ANDESITE_STAIRS(), fn(Stair $block) => Helper::encodeStairs($block, new Writer(Ids::ANDESITE_STAIRS)));
$this->map(Blocks::ANDESITE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_ANDESITE));
@ -1268,7 +1306,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
->writeBool(StateNames::RAIL_DATA_BIT, $block->isActivated())
->writeInt(StateNames::RAIL_DIRECTION, $block->getShape());
});
$this->map(Blocks::DIORITE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_DIORITE));
$this->map(Blocks::DIORITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_DIORITE));
$this->mapStairs(Blocks::DIORITE_STAIRS(), Ids::DIORITE_STAIRS);
$this->map(Blocks::DIORITE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_DIORITE));
@ -1335,7 +1372,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
->writeFacingFlags($block->getFaces());
});
$this->map(Blocks::GLOWING_ITEM_FRAME(), fn(ItemFrame $block) => Helper::encodeItemFrame($block, Ids::GLOW_FRAME));
$this->map(Blocks::GRANITE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_GRANITE));
$this->map(Blocks::GRANITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_GRANITE));
$this->mapStairs(Blocks::GRANITE_STAIRS(), Ids::GRANITE_STAIRS);
$this->map(Blocks::GRANITE_WALL(), fn(Wall $block) => Helper::encodeLegacyWall($block, StringValues::WALL_BLOCK_TYPE_GRANITE));
@ -1473,7 +1509,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
->writeInt(StateNames::GROWTH, $block->getAge() + 1 + PitcherCrop::MAX_AGE)
->writeBool(StateNames::UPPER_BLOCK_BIT, $block->isTop());
});
$this->map(Blocks::POLISHED_ANDESITE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_ANDESITE_SMOOTH));
$this->map(Blocks::POLISHED_ANDESITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_POLISHED_ANDESITE));
$this->mapStairs(Blocks::POLISHED_ANDESITE_STAIRS(), Ids::POLISHED_ANDESITE_STAIRS);
$this->map(Blocks::POLISHED_BASALT(), function(SimplePillar $block) : Writer{
@ -1491,10 +1526,8 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
$this->mapSlab(Blocks::POLISHED_DEEPSLATE_SLAB(), Ids::POLISHED_DEEPSLATE_SLAB, Ids::POLISHED_DEEPSLATE_DOUBLE_SLAB);
$this->mapStairs(Blocks::POLISHED_DEEPSLATE_STAIRS(), Ids::POLISHED_DEEPSLATE_STAIRS);
$this->map(Blocks::POLISHED_DEEPSLATE_WALL(), fn(Wall $block) => Helper::encodeWall($block, new Writer(Ids::POLISHED_DEEPSLATE_WALL)));
$this->map(Blocks::POLISHED_DIORITE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_DIORITE_SMOOTH));
$this->map(Blocks::POLISHED_DIORITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_POLISHED_DIORITE));
$this->mapStairs(Blocks::POLISHED_DIORITE_STAIRS(), Ids::POLISHED_DIORITE_STAIRS);
$this->map(Blocks::POLISHED_GRANITE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_GRANITE_SMOOTH));
$this->map(Blocks::POLISHED_GRANITE_SLAB(), fn(Slab $block) => Helper::encodeStoneSlab3($block, StringValues::STONE_SLAB_TYPE_3_POLISHED_GRANITE));
$this->mapStairs(Blocks::POLISHED_GRANITE_STAIRS(), Ids::POLISHED_GRANITE_STAIRS);
$this->map(Blocks::POPPY(), fn() => Helper::encodeRedFlower(StringValues::FLOWER_TYPE_POPPY));
@ -1622,15 +1655,6 @@ final class BlockObjectToStateSerializer implements BlockStateSerializer{
->writeString(StateNames::SPONGE_TYPE, $block->isWet() ? StringValues::SPONGE_TYPE_WET : StringValues::SPONGE_TYPE_DRY);
});
$this->map(Blocks::SPRUCE_SAPLING(), fn(Sapling $block) => Helper::encodeSapling($block, StringValues::SAPLING_TYPE_SPRUCE));
$this->map(Blocks::STAINED_HARDENED_GLASS(), function(StainedHardenedGlass $block) : Writer{
return Writer::create(Ids::HARD_STAINED_GLASS)
->writeColor($block->getColor());
});
$this->map(Blocks::STAINED_HARDENED_GLASS_PANE(), function(StainedHardenedGlassPane $block) : Writer{
return Writer::create(Ids::HARD_STAINED_GLASS_PANE)
->writeColor($block->getColor());
});
$this->map(Blocks::STONE(), fn() => Helper::encodeStone(StringValues::STONE_TYPE_STONE));
$this->map(Blocks::STONECUTTER(), fn(Stonecutter $block) => Writer::create(Ids::STONECUTTER_BLOCK)
->writeCardinalHorizontalFacing($block->getFacing()));
$this->map(Blocks::STONE_BRICKS(), fn() => Helper::encodeStoneBricks(StringValues::STONE_BRICK_TYPE_DEFAULT));

View File

@ -25,7 +25,6 @@ namespace pocketmine\data\bedrock\block\convert;
use pocketmine\block\utils\BellAttachmentType;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\SlabType;
use pocketmine\block\utils\WallConnectionType;
use pocketmine\data\bedrock\block\BlockLegacyMetadata;
@ -236,30 +235,6 @@ final class BlockStateReader{
};
}
/** @throws BlockStateDeserializeException */
public function readColor() : DyeColor{
// * color (StringTag) = black, blue, brown, cyan, gray, green, light_blue, lime, magenta, orange, pink, purple, red, silver, white, yellow
return match($color = $this->readString(BlockStateNames::COLOR)){
StringValues::COLOR_BLACK => DyeColor::BLACK,
StringValues::COLOR_BLUE => DyeColor::BLUE,
StringValues::COLOR_BROWN => DyeColor::BROWN,
StringValues::COLOR_CYAN => DyeColor::CYAN,
StringValues::COLOR_GRAY => DyeColor::GRAY,
StringValues::COLOR_GREEN => DyeColor::GREEN,
StringValues::COLOR_LIGHT_BLUE => DyeColor::LIGHT_BLUE,
StringValues::COLOR_LIME => DyeColor::LIME,
StringValues::COLOR_MAGENTA => DyeColor::MAGENTA,
StringValues::COLOR_ORANGE => DyeColor::ORANGE,
StringValues::COLOR_PINK => DyeColor::PINK,
StringValues::COLOR_PURPLE => DyeColor::PURPLE,
StringValues::COLOR_RED => DyeColor::RED,
StringValues::COLOR_SILVER => DyeColor::LIGHT_GRAY,
StringValues::COLOR_WHITE => DyeColor::WHITE,
StringValues::COLOR_YELLOW => DyeColor::YELLOW,
default => throw $this->badValueException(BlockStateNames::COLOR, $color),
};
}
/** @throws BlockStateDeserializeException */
public function readCoralFacing() : int{
return $this->parseFacingValue($this->readInt(BlockStateNames::CORAL_DIRECTION), [

View File

@ -57,42 +57,42 @@ use pocketmine\math\Facing;
final class BlockStateSerializerHelper{
public static function encodeAllSidedLog(Wood $block) : BlockStateWriter{
return BlockStateWriter::create(Ids::WOOD)
public static function encodeAllSidedLog(Wood $block) : Writer{
return Writer::create(Ids::WOOD)
->writeBool(BlockStateNames::STRIPPED_BIT, $block->isStripped())
->writePillarAxis($block->getAxis())
->writeLegacyWoodType($block->getWoodType());
}
public static function encodeButton(Button $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeButton(Button $block, Writer $out) : Writer{
return $out
->writeFacingDirection($block->getFacing())
->writeBool(BlockStateNames::BUTTON_PRESSED_BIT, $block->isPressed());
}
public static function encodeCandle(Candle $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeCandle(Candle $block, Writer $out) : Writer{
return $out
->writeBool(StateNames::LIT, $block->isLit())
->writeInt(StateNames::CANDLES, $block->getCount() - 1);
}
public static function encodeChemistryTable(ChemistryTable $block, string $chemistryTableType, BlockStateWriter $out) : BlockStateWriter{
public static function encodeChemistryTable(ChemistryTable $block, string $chemistryTableType, Writer $out) : Writer{
return $out
->writeString(BlockStateNames::CHEMISTRY_TABLE_TYPE, $chemistryTableType)
->writeLegacyHorizontalFacing(Facing::opposite($block->getFacing()));
}
public static function encodeCrops(Crops $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeCrops(Crops $block, Writer $out) : Writer{
return $out->writeInt(BlockStateNames::GROWTH, $block->getAge());
}
public static function encodeColoredTorch(Torch $block, bool $highBit, BlockStateWriter $out) : BlockStateWriter{
public static function encodeColoredTorch(Torch $block, bool $highBit, Writer $out) : Writer{
return $out
->writeBool(BlockStateNames::COLOR_BIT, $highBit)
->writeTorchFacing($block->getFacing());
}
public static function encodeCauldron(string $liquid, int $fillLevel) : BlockStateWriter{
public static function encodeCauldron(string $liquid, int $fillLevel) : Writer{
return Writer::create(Ids::CAULDRON)
->writeString(BlockStateNames::CAULDRON_LIQUID, $liquid)
->writeInt(BlockStateNames::FILL_LEVEL, $fillLevel);
@ -107,7 +107,7 @@ final class BlockStateSerializerHelper{
};
}
public static function encodeDoor(Door $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeDoor(Door $block, Writer $out) : Writer{
return $out
->writeBool(BlockStateNames::UPPER_BLOCK_BIT, $block->isTop())
->writeLegacyHorizontalFacing(Facing::rotateY($block->getFacing(), true))
@ -115,111 +115,111 @@ final class BlockStateSerializerHelper{
->writeBool(BlockStateNames::OPEN_BIT, $block->isOpen());
}
public static function encodeDoublePlant(DoublePlant $block, string $doublePlantType, BlockStateWriter $out) : BlockStateWriter{
public static function encodeDoublePlant(DoublePlant $block, string $doublePlantType, Writer $out) : Writer{
return $out
->writeBool(BlockStateNames::UPPER_BLOCK_BIT, $block->isTop())
->writeString(BlockStateNames::DOUBLE_PLANT_TYPE, $doublePlantType);
}
public static function encodeFenceGate(FenceGate $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeFenceGate(FenceGate $block, Writer $out) : Writer{
return $out
->writeLegacyHorizontalFacing($block->getFacing())
->writeBool(BlockStateNames::IN_WALL_BIT, $block->isInWall())
->writeBool(BlockStateNames::OPEN_BIT, $block->isOpen());
}
public static function encodeFloorSign(FloorSign $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeFloorSign(FloorSign $block, Writer $out) : Writer{
return $out
->writeInt(BlockStateNames::GROUND_SIGN_DIRECTION, $block->getRotation());
}
public static function encodeFurnace(Furnace $block, string $unlitId, string $litId) : BlockStateWriter{
return BlockStateWriter::create($block->isLit() ? $litId : $unlitId)
public static function encodeFurnace(Furnace $block, string $unlitId, string $litId) : Writer{
return Writer::create($block->isLit() ? $litId : $unlitId)
->writeCardinalHorizontalFacing($block->getFacing());
}
public static function encodeItemFrame(ItemFrame $block, string $id) : BlockStateWriter{
public static function encodeItemFrame(ItemFrame $block, string $id) : Writer{
return Writer::create($id)
->writeBool(StateNames::ITEM_FRAME_MAP_BIT, $block->hasMap())
->writeBool(StateNames::ITEM_FRAME_PHOTO_BIT, false)
->writeFacingDirection($block->getFacing());
}
public static function encodeLeaves(Leaves $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeLeaves(Leaves $block, Writer $out) : Writer{
return $out
->writeBool(BlockStateNames::PERSISTENT_BIT, $block->isNoDecay())
->writeBool(BlockStateNames::UPDATE_BIT, $block->isCheckDecay());
}
public static function encodeLeaves1(Leaves $block, string $type) : BlockStateWriter{
return self::encodeLeaves($block, BlockStateWriter::create(Ids::LEAVES)
public static function encodeLeaves1(Leaves $block, string $type) : Writer{
return self::encodeLeaves($block, Writer::create(Ids::LEAVES)
->writeString(BlockStateNames::OLD_LEAF_TYPE, $type));
}
public static function encodeLeaves2(Leaves $block, string $type) : BlockStateWriter{
return self::encodeLeaves($block, BlockStateWriter::create(Ids::LEAVES2)
public static function encodeLeaves2(Leaves $block, string $type) : Writer{
return self::encodeLeaves($block, Writer::create(Ids::LEAVES2)
->writeString(BlockStateNames::NEW_LEAF_TYPE, $type));
}
public static function encodeLiquid(Liquid $block, string $stillId, string $flowingId) : BlockStateWriter{
return BlockStateWriter::create($block->isStill() ? $stillId : $flowingId)
public static function encodeLiquid(Liquid $block, string $stillId, string $flowingId) : Writer{
return Writer::create($block->isStill() ? $stillId : $flowingId)
->writeInt(BlockStateNames::LIQUID_DEPTH, $block->getDecay() | ($block->isFalling() ? 0x8 : 0));
}
public static function encodeLog(Wood $block, string $unstrippedId, string $strippedId) : BlockStateWriter{
public static function encodeLog(Wood $block, string $unstrippedId, string $strippedId) : Writer{
$out = $block->isStripped() ?
BlockStateWriter::create($strippedId) :
BlockStateWriter::create($unstrippedId);
Writer::create($strippedId) :
Writer::create($unstrippedId);
return $out
->writePillarAxis($block->getAxis());
}
public static function encodeMushroomBlock(RedMushroomBlock $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeMushroomBlock(RedMushroomBlock $block, Writer $out) : Writer{
return $out
->writeInt(BlockStateNames::HUGE_MUSHROOM_BITS, MushroomBlockTypeIdMap::getInstance()->toId($block->getMushroomBlockType()));
}
public static function encodeQuartz(string $type, int $axis) : BlockStateWriter{
return BlockStateWriter::create(Ids::QUARTZ_BLOCK)
public static function encodeQuartz(string $type, int $axis) : Writer{
return Writer::create(Ids::QUARTZ_BLOCK)
->writeString(BlockStateNames::CHISEL_TYPE, $type)
->writePillarAxis($axis); //this isn't needed for all types, but we have to write it anyway
}
public static function encodeRedFlower(string $type) : BlockStateWriter{
return BlockStateWriter::create(Ids::RED_FLOWER)->writeString(BlockStateNames::FLOWER_TYPE, $type);
public static function encodeRedFlower(string $type) : Writer{
return Writer::create(Ids::RED_FLOWER)->writeString(BlockStateNames::FLOWER_TYPE, $type);
}
public static function encodeSandstone(string $id, string $type) : BlockStateWriter{
return BlockStateWriter::create($id)->writeString(BlockStateNames::SAND_STONE_TYPE, $type);
public static function encodeSandstone(string $id, string $type) : Writer{
return Writer::create($id)->writeString(BlockStateNames::SAND_STONE_TYPE, $type);
}
public static function encodeSapling(Sapling $block, string $type) : BlockStateWriter{
return BlockStateWriter::create(Ids::SAPLING)
public static function encodeSapling(Sapling $block, string $type) : Writer{
return Writer::create(Ids::SAPLING)
->writeBool(BlockStateNames::AGE_BIT, $block->isReady())
->writeString(BlockStateNames::SAPLING_TYPE, $type);
}
public static function encodeSimplePressurePlate(SimplePressurePlate $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeSimplePressurePlate(SimplePressurePlate $block, Writer $out) : Writer{
//TODO: not sure what the deal is here ... seems like a mojang bug / artifact of bad implementation?
//best to keep this separate from weighted plates anyway...
return $out
->writeInt(BlockStateNames::REDSTONE_SIGNAL, $block->isPressed() ? 15 : 0);
}
public static function encodeSlab(Slab $block, string $singleId, string $doubleId) : BlockStateWriter{
public static function encodeSlab(Slab $block, string $singleId, string $doubleId) : Writer{
$slabType = $block->getSlabType();
return BlockStateWriter::create($slabType === SlabType::DOUBLE ? $doubleId : $singleId)
return Writer::create($slabType === SlabType::DOUBLE ? $doubleId : $singleId)
//this is (intentionally) also written for double slabs (as zero) to maintain bug parity with MCPE
->writeSlabPosition($slabType === SlabType::DOUBLE ? SlabType::BOTTOM : $slabType);
}
public static function encodeStairs(Stair $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeStairs(Stair $block, Writer $out) : Writer{
return $out
->writeBool(BlockStateNames::UPSIDE_DOWN_BIT, $block->isUpsideDown())
->writeWeirdoHorizontalFacing($block->getFacing());
}
public static function encodeStem(Stem $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeStem(Stem $block, Writer $out) : Writer{
//In PM, we use Facing::UP to indicate that the stem is not attached to a pumpkin/melon, since this makes the
//most intuitive sense (the stem is pointing at the sky). However, Bedrock uses the DOWN state for this, which
//is absurd, and I refuse to make our API similarly absurd.
@ -228,45 +228,40 @@ final class BlockStateSerializerHelper{
->writeFacingWithoutUp($facing === Facing::UP ? Facing::DOWN : $facing);
}
public static function encodeStone(string $type) : BlockStateWriter{
return BlockStateWriter::create(Ids::STONE)
->writeString(BlockStateNames::STONE_TYPE, $type);
}
public static function encodeStoneBricks(string $type) : BlockStateWriter{
return BlockStateWriter::create(Ids::STONEBRICK)
public static function encodeStoneBricks(string $type) : Writer{
return Writer::create(Ids::STONEBRICK)
->writeString(BlockStateNames::STONE_BRICK_TYPE, $type);
}
private static function encodeStoneSlab(Slab $block, string $singleId, string $doubleId, string $typeKey, string $typeValue) : BlockStateWriter{
private static function encodeStoneSlab(Slab $block, string $singleId, string $doubleId, string $typeKey, string $typeValue) : Writer{
return self::encodeSlab($block, $singleId, $doubleId)
->writeString($typeKey, $typeValue);
}
public static function encodeStoneSlab1(Slab $block, string $typeValue) : BlockStateWriter{
public static function encodeStoneSlab1(Slab $block, string $typeValue) : Writer{
return self::encodeStoneSlab($block, Ids::STONE_BLOCK_SLAB, Ids::DOUBLE_STONE_BLOCK_SLAB, BlockStateNames::STONE_SLAB_TYPE, $typeValue);
}
public static function encodeStoneSlab2(Slab $block, string $typeValue) : BlockStateWriter{
public static function encodeStoneSlab2(Slab $block, string $typeValue) : Writer{
return self::encodeStoneSlab($block, Ids::STONE_BLOCK_SLAB2, Ids::DOUBLE_STONE_BLOCK_SLAB2, BlockStateNames::STONE_SLAB_TYPE_2, $typeValue);
}
public static function encodeStoneSlab3(Slab $block, string $typeValue) : BlockStateWriter{
public static function encodeStoneSlab3(Slab $block, string $typeValue) : Writer{
return self::encodeStoneSlab($block, Ids::STONE_BLOCK_SLAB3, Ids::DOUBLE_STONE_BLOCK_SLAB3, BlockStateNames::STONE_SLAB_TYPE_3, $typeValue);
}
public static function encodeStoneSlab4(Slab $block, string $typeValue) : BlockStateWriter{
public static function encodeStoneSlab4(Slab $block, string $typeValue) : Writer{
return self::encodeStoneSlab($block, Ids::STONE_BLOCK_SLAB4, Ids::DOUBLE_STONE_BLOCK_SLAB4, BlockStateNames::STONE_SLAB_TYPE_4, $typeValue);
}
public static function encodeTrapdoor(Trapdoor $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeTrapdoor(Trapdoor $block, Writer $out) : Writer{
return $out
->write5MinusHorizontalFacing($block->getFacing())
->writeBool(BlockStateNames::UPSIDE_DOWN_BIT, $block->isTop())
->writeBool(BlockStateNames::OPEN_BIT, $block->isOpen());
}
public static function encodeWall(Wall $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeWall(Wall $block, Writer $out) : Writer{
return $out
->writeBool(BlockStateNames::WALL_POST_BIT, $block->isPost())
->writeWallConnectionType(BlockStateNames::WALL_CONNECTION_TYPE_EAST, $block->getConnection(Facing::EAST))
@ -275,17 +270,17 @@ final class BlockStateSerializerHelper{
->writeWallConnectionType(BlockStateNames::WALL_CONNECTION_TYPE_WEST, $block->getConnection(Facing::WEST));
}
public static function encodeLegacyWall(Wall $block, string $type) : BlockStateWriter{
return self::encodeWall($block, BlockStateWriter::create(Ids::COBBLESTONE_WALL))
public static function encodeLegacyWall(Wall $block, string $type) : Writer{
return self::encodeWall($block, Writer::create(Ids::COBBLESTONE_WALL))
->writeString(BlockStateNames::WALL_BLOCK_TYPE, $type);
}
public static function encodeWallSign(WallSign $block, BlockStateWriter $out) : BlockStateWriter{
public static function encodeWallSign(WallSign $block, Writer $out) : Writer{
return $out
->writeHorizontalFacing($block->getFacing());
}
public static function encodeWoodenSlab(Slab $block, string $typeValue) : BlockStateWriter{
public static function encodeWoodenSlab(Slab $block, string $typeValue) : Writer{
return self::encodeSlab($block, Ids::WOODEN_SLAB, Ids::DOUBLE_WOODEN_SLAB)
->writeString(BlockStateNames::WOOD_TYPE, $typeValue);
}

View File

@ -185,6 +185,48 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
}
private function registerFlatColorBlockDeserializers() : void{
foreach([
Ids::HARD_BLACK_STAINED_GLASS => DyeColor::BLACK,
Ids::HARD_BLUE_STAINED_GLASS => DyeColor::BLUE,
Ids::HARD_BROWN_STAINED_GLASS => DyeColor::BROWN,
Ids::HARD_CYAN_STAINED_GLASS => DyeColor::CYAN,
Ids::HARD_GRAY_STAINED_GLASS => DyeColor::GRAY,
Ids::HARD_GREEN_STAINED_GLASS => DyeColor::GREEN,
Ids::HARD_LIGHT_BLUE_STAINED_GLASS => DyeColor::LIGHT_BLUE,
Ids::HARD_LIGHT_GRAY_STAINED_GLASS => DyeColor::LIGHT_GRAY,
Ids::HARD_LIME_STAINED_GLASS => DyeColor::LIME,
Ids::HARD_MAGENTA_STAINED_GLASS => DyeColor::MAGENTA,
Ids::HARD_ORANGE_STAINED_GLASS => DyeColor::ORANGE,
Ids::HARD_PINK_STAINED_GLASS => DyeColor::PINK,
Ids::HARD_PURPLE_STAINED_GLASS => DyeColor::PURPLE,
Ids::HARD_RED_STAINED_GLASS => DyeColor::RED,
Ids::HARD_WHITE_STAINED_GLASS => DyeColor::WHITE,
Ids::HARD_YELLOW_STAINED_GLASS => DyeColor::YELLOW,
] as $id => $color){
$this->map($id, fn(Reader $in) => Blocks::STAINED_HARDENED_GLASS()->setColor($color));
}
foreach([
Ids::HARD_BLACK_STAINED_GLASS_PANE => DyeColor::BLACK,
Ids::HARD_BLUE_STAINED_GLASS_PANE => DyeColor::BLUE,
Ids::HARD_BROWN_STAINED_GLASS_PANE => DyeColor::BROWN,
Ids::HARD_CYAN_STAINED_GLASS_PANE => DyeColor::CYAN,
Ids::HARD_GRAY_STAINED_GLASS_PANE => DyeColor::GRAY,
Ids::HARD_GREEN_STAINED_GLASS_PANE => DyeColor::GREEN,
Ids::HARD_LIGHT_BLUE_STAINED_GLASS_PANE => DyeColor::LIGHT_BLUE,
Ids::HARD_LIGHT_GRAY_STAINED_GLASS_PANE => DyeColor::LIGHT_GRAY,
Ids::HARD_LIME_STAINED_GLASS_PANE => DyeColor::LIME,
Ids::HARD_MAGENTA_STAINED_GLASS_PANE => DyeColor::MAGENTA,
Ids::HARD_ORANGE_STAINED_GLASS_PANE => DyeColor::ORANGE,
Ids::HARD_PINK_STAINED_GLASS_PANE => DyeColor::PINK,
Ids::HARD_PURPLE_STAINED_GLASS_PANE => DyeColor::PURPLE,
Ids::HARD_RED_STAINED_GLASS_PANE => DyeColor::RED,
Ids::HARD_WHITE_STAINED_GLASS_PANE => DyeColor::WHITE,
Ids::HARD_YELLOW_STAINED_GLASS_PANE => DyeColor::YELLOW,
] as $id => $color){
$this->map($id, fn(Reader $in) => Blocks::STAINED_HARDENED_GLASS_PANE()->setColor($color));
}
foreach([
Ids::BLACK_GLAZED_TERRACOTTA => DyeColor::BLACK,
Ids::BLUE_GLAZED_TERRACOTTA => DyeColor::BLUE,
@ -427,6 +469,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$this->map(Ids::ACACIA_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::ACACIA_WALL_SIGN(), $in));
$this->mapLog(Ids::ACACIA_LOG, Ids::STRIPPED_ACACIA_LOG, fn() => Blocks::ACACIA_LOG());
$this->mapSimple(Ids::ACACIA_FENCE, fn() => Blocks::ACACIA_FENCE());
$this->mapSimple(Ids::ACACIA_PLANKS, fn() => Blocks::ACACIA_PLANKS());
$this->mapStairs(Ids::ACACIA_STAIRS, fn() => Blocks::ACACIA_STAIRS());
//wood, planks and slabs still use the old way of storing wood type
@ -439,6 +482,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$this->map(Ids::BIRCH_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::BIRCH_WALL_SIGN(), $in));
$this->mapLog(Ids::BIRCH_LOG, Ids::STRIPPED_BIRCH_LOG, fn() => Blocks::BIRCH_LOG());
$this->mapSimple(Ids::BIRCH_FENCE, fn() => Blocks::BIRCH_FENCE());
$this->mapSimple(Ids::BIRCH_PLANKS, fn() => Blocks::BIRCH_PLANKS());
$this->mapStairs(Ids::BIRCH_STAIRS, fn() => Blocks::BIRCH_STAIRS());
//wood, planks and slabs still use the old way of storing wood type
@ -483,6 +527,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$this->map(Ids::DARK_OAK_TRAPDOOR, fn(Reader $in) => Helper::decodeTrapdoor(Blocks::DARK_OAK_TRAPDOOR(), $in));
$this->mapLog(Ids::DARK_OAK_LOG, Ids::STRIPPED_DARK_OAK_LOG, fn() => Blocks::DARK_OAK_LOG());
$this->mapSimple(Ids::DARK_OAK_FENCE, fn() => Blocks::DARK_OAK_FENCE());
$this->mapSimple(Ids::DARK_OAK_PLANKS, fn() => Blocks::DARK_OAK_PLANKS());
$this->mapStairs(Ids::DARK_OAK_STAIRS, fn() => Blocks::DARK_OAK_STAIRS());
//wood, planks and slabs still use the old way of storing wood type
@ -495,6 +540,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$this->map(Ids::JUNGLE_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::JUNGLE_WALL_SIGN(), $in));
$this->mapLog(Ids::JUNGLE_LOG, Ids::STRIPPED_JUNGLE_LOG, fn() => Blocks::JUNGLE_LOG());
$this->mapSimple(Ids::JUNGLE_FENCE, fn() => Blocks::JUNGLE_FENCE());
$this->mapSimple(Ids::JUNGLE_PLANKS, fn() => Blocks::JUNGLE_PLANKS());
$this->mapStairs(Ids::JUNGLE_STAIRS, fn() => Blocks::JUNGLE_STAIRS());
//wood, planks and slabs still use the old way of storing wood type
@ -526,6 +572,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$this->map(Ids::WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::OAK_WALL_SIGN(), $in));
$this->mapLog(Ids::OAK_LOG, Ids::STRIPPED_OAK_LOG, fn() => Blocks::OAK_LOG());
$this->mapSimple(Ids::OAK_FENCE, fn() => Blocks::OAK_FENCE());
$this->mapSimple(Ids::OAK_PLANKS, fn() => Blocks::OAK_PLANKS());
$this->mapStairs(Ids::OAK_STAIRS, fn() => Blocks::OAK_STAIRS());
//wood, planks and slabs still use the old way of storing wood type
@ -538,6 +585,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$this->map(Ids::SPRUCE_WALL_SIGN, fn(Reader $in) => Helper::decodeWallSign(Blocks::SPRUCE_WALL_SIGN(), $in));
$this->mapLog(Ids::SPRUCE_LOG, Ids::STRIPPED_SPRUCE_LOG, fn() => Blocks::SPRUCE_LOG());
$this->mapSimple(Ids::SPRUCE_FENCE, fn() => Blocks::SPRUCE_FENCE());
$this->mapSimple(Ids::SPRUCE_PLANKS, fn() => Blocks::SPRUCE_PLANKS());
$this->mapStairs(Ids::SPRUCE_STAIRS, fn() => Blocks::SPRUCE_STAIRS());
//wood, planks and slabs still use the old way of storing wood type
@ -557,18 +605,6 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
}
private function registerLegacyWoodBlockDeserializers() : void{
$this->map(Ids::PLANKS, function(Reader $in) : Block{
return match($woodName = $in->readString(StateNames::WOOD_TYPE)){
StringValues::WOOD_TYPE_OAK => Blocks::OAK_PLANKS(),
StringValues::WOOD_TYPE_SPRUCE => Blocks::SPRUCE_PLANKS(),
StringValues::WOOD_TYPE_BIRCH => Blocks::BIRCH_PLANKS(),
StringValues::WOOD_TYPE_JUNGLE => Blocks::JUNGLE_PLANKS(),
StringValues::WOOD_TYPE_ACACIA => Blocks::ACACIA_PLANKS(),
StringValues::WOOD_TYPE_DARK_OAK => Blocks::DARK_OAK_PLANKS(),
default => throw $in->badValueException(StateNames::WOOD_TYPE, $woodName),
};
});
$this->mapSlab(Ids::WOODEN_SLAB, Ids::DOUBLE_WOODEN_SLAB, fn(Reader $in) => Helper::mapWoodenSlabType($in));
$this->map(Ids::WOOD, fn(Reader $in) : Block => Helper::decodeLog(match($woodType = $in->readString(StateNames::WOOD_TYPE)){
@ -608,6 +644,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$this->mapSimple(Ids::AIR, fn() => Blocks::AIR());
$this->mapSimple(Ids::AMETHYST_BLOCK, fn() => Blocks::AMETHYST());
$this->mapSimple(Ids::ANCIENT_DEBRIS, fn() => Blocks::ANCIENT_DEBRIS());
$this->mapSimple(Ids::ANDESITE, fn() => Blocks::ANDESITE());
$this->mapSimple(Ids::BARRIER, fn() => Blocks::BARRIER());
$this->mapSimple(Ids::BEACON, fn() => Blocks::BEACON());
$this->mapSimple(Ids::BLACKSTONE, fn() => Blocks::BLACKSTONE());
@ -648,6 +685,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$this->mapSimple(Ids::DEEPSLATE_TILES, fn() => Blocks::DEEPSLATE_TILES());
$this->mapSimple(Ids::DIAMOND_BLOCK, fn() => Blocks::DIAMOND());
$this->mapSimple(Ids::DIAMOND_ORE, fn() => Blocks::DIAMOND_ORE());
$this->mapSimple(Ids::DIORITE, fn() => Blocks::DIORITE());
$this->mapSimple(Ids::DRAGON_EGG, fn() => Blocks::DRAGON_EGG());
$this->mapSimple(Ids::DRIED_KELP_BLOCK, fn() => Blocks::DRIED_KELP());
$this->mapSimple(Ids::ELEMENT_0, fn() => Blocks::ELEMENT_ZERO());
@ -782,6 +820,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$this->mapSimple(Ids::GLOWSTONE, fn() => Blocks::GLOWSTONE());
$this->mapSimple(Ids::GOLD_BLOCK, fn() => Blocks::GOLD());
$this->mapSimple(Ids::GOLD_ORE, fn() => Blocks::GOLD_ORE());
$this->mapSimple(Ids::GRANITE, fn() => Blocks::GRANITE());
$this->mapSimple(Ids::GRASS, fn() => Blocks::GRASS());
$this->mapSimple(Ids::GRASS_PATH, fn() => Blocks::GRASS_PATH());
$this->mapSimple(Ids::GRAVEL, fn() => Blocks::GRAVEL());
@ -820,9 +859,12 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$this->mapSimple(Ids::PACKED_ICE, fn() => Blocks::PACKED_ICE());
$this->mapSimple(Ids::PACKED_MUD, fn() => Blocks::PACKED_MUD());
$this->mapSimple(Ids::PODZOL, fn() => Blocks::PODZOL());
$this->mapSimple(Ids::POLISHED_ANDESITE, fn() => Blocks::POLISHED_ANDESITE());
$this->mapSimple(Ids::POLISHED_BLACKSTONE, fn() => Blocks::POLISHED_BLACKSTONE());
$this->mapSimple(Ids::POLISHED_BLACKSTONE_BRICKS, fn() => Blocks::POLISHED_BLACKSTONE_BRICKS());
$this->mapSimple(Ids::POLISHED_DEEPSLATE, fn() => Blocks::POLISHED_DEEPSLATE());
$this->mapSimple(Ids::POLISHED_DIORITE, fn() => Blocks::POLISHED_DIORITE());
$this->mapSimple(Ids::POLISHED_GRANITE, fn() => Blocks::POLISHED_GRANITE());
$this->mapSimple(Ids::QUARTZ_BRICKS, fn() => Blocks::QUARTZ_BRICKS());
$this->mapSimple(Ids::QUARTZ_ORE, fn() => Blocks::NETHER_QUARTZ_ORE());
$this->mapSimple(Ids::RAW_COPPER_BLOCK, fn() => Blocks::RAW_COPPER());
@ -844,6 +886,7 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
$this->mapSimple(Ids::SOUL_SAND, fn() => Blocks::SOUL_SAND());
$this->mapSimple(Ids::SOUL_SOIL, fn() => Blocks::SOUL_SOIL());
$this->mapSimple(Ids::SPORE_BLOSSOM, fn() => Blocks::SPORE_BLOSSOM());
$this->mapSimple(Ids::STONE, fn() => Blocks::STONE());
$this->mapSimple(Ids::STONECUTTER, fn() => Blocks::LEGACY_STONECUTTER());
$this->mapSimple(Ids::TINTED_GLASS, fn() => Blocks::TINTED_GLASS());
$this->mapSimple(Ids::TORCHFLOWER, fn() => Blocks::TORCHFLOWER());
@ -1158,14 +1201,6 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
->setShape($in->readBoundedInt(StateNames::RAIL_DIRECTION, 0, 5));
});
$this->mapStairs(Ids::GRANITE_STAIRS, fn() => Blocks::GRANITE_STAIRS());
$this->map(Ids::HARD_STAINED_GLASS, function(Reader $in) : Block{
return Blocks::STAINED_HARDENED_GLASS()
->setColor($in->readColor());
});
$this->map(Ids::HARD_STAINED_GLASS_PANE, function(Reader $in) : Block{
return Blocks::STAINED_HARDENED_GLASS_PANE()
->setColor($in->readColor());
});
$this->map(Ids::HAY_BLOCK, function(Reader $in) : Block{
$in->ignored(StateNames::DEPRECATED);
return Blocks::HAY_BALE()->setAxis($in->readPillarAxis());
@ -1528,18 +1563,6 @@ final class BlockStateToObjectDeserializer implements BlockStateDeserializer{
return Blocks::BANNER()
->setRotation($in->readBoundedInt(StateNames::GROUND_SIGN_DIRECTION, 0, 15));
});
$this->map(Ids::STONE, function(Reader $in) : Block{
return match($type = $in->readString(StateNames::STONE_TYPE)){
StringValues::STONE_TYPE_ANDESITE => Blocks::ANDESITE(),
StringValues::STONE_TYPE_ANDESITE_SMOOTH => Blocks::POLISHED_ANDESITE(),
StringValues::STONE_TYPE_DIORITE => Blocks::DIORITE(),
StringValues::STONE_TYPE_DIORITE_SMOOTH => Blocks::POLISHED_DIORITE(),
StringValues::STONE_TYPE_GRANITE => Blocks::GRANITE(),
StringValues::STONE_TYPE_GRANITE_SMOOTH => Blocks::POLISHED_GRANITE(),
StringValues::STONE_TYPE_STONE => Blocks::STONE(),
default => throw $in->badValueException(StateNames::STONE_TYPE, $type),
};
});
$this->mapStairs(Ids::STONE_BRICK_STAIRS, fn() => Blocks::STONE_BRICK_STAIRS());
$this->map(Ids::STONE_BUTTON, fn(Reader $in) => Helper::decodeButton(Blocks::STONE_BUTTON(), $in));
$this->map(Ids::STONE_PRESSURE_PLATE, fn(Reader $in) => Helper::decodeSimplePressurePlate(Blocks::STONE_PRESSURE_PLATE(), $in));

View File

@ -25,7 +25,6 @@ namespace pocketmine\data\bedrock\block\convert;
use pocketmine\block\utils\BellAttachmentType;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\SlabType;
use pocketmine\block\utils\WallConnectionType;
use pocketmine\block\utils\WoodType;
@ -193,29 +192,6 @@ final class BlockStateWriter{
});
}
/** @return $this */
public function writeColor(DyeColor $color) : self{
$this->writeString(BlockStateNames::COLOR, match($color){
DyeColor::BLACK => StringValues::COLOR_BLACK,
DyeColor::BLUE => StringValues::COLOR_BLUE,
DyeColor::BROWN => StringValues::COLOR_BROWN,
DyeColor::CYAN => StringValues::COLOR_CYAN,
DyeColor::GRAY => StringValues::COLOR_GRAY,
DyeColor::GREEN => StringValues::COLOR_GREEN,
DyeColor::LIGHT_BLUE => StringValues::COLOR_LIGHT_BLUE,
DyeColor::LIGHT_GRAY => StringValues::COLOR_SILVER,
DyeColor::LIME => StringValues::COLOR_LIME,
DyeColor::MAGENTA => StringValues::COLOR_MAGENTA,
DyeColor::ORANGE => StringValues::COLOR_ORANGE,
DyeColor::PINK => StringValues::COLOR_PINK,
DyeColor::PURPLE => StringValues::COLOR_PURPLE,
DyeColor::RED => StringValues::COLOR_RED,
DyeColor::WHITE => StringValues::COLOR_WHITE,
DyeColor::YELLOW => StringValues::COLOR_YELLOW,
});
return $this;
}
/** @return $this */
public function writeCoralFacing(int $value) : self{
$this->writeInt(BlockStateNames::CORAL_DIRECTION, match($value){

View File

@ -389,6 +389,9 @@ final class BlockStateUpgradeSchemaUtils{
}
$jsonMapper = new \JsonMapper();
$jsonMapper->bExceptionOnMissingData = true;
$jsonMapper->bExceptionOnUndefinedProperty = true;
$jsonMapper->bStrictObjectTypeChecking = true;
try{
$model = $jsonMapper->map($json, new BlockStateUpgradeSchemaModel());
}catch(\JsonMapper_Exception $e){

View File

@ -86,7 +86,7 @@ final class BlockStateUpgrader{
if(is_string($remap->newName)){
$newName = $remap->newName;
}else{
$flattenedValue = $oldState[$remap->newName->flattenedProperty];
$flattenedValue = $oldState[$remap->newName->flattenedProperty] ?? null;
if($flattenedValue instanceof StringTag){
$newName = sprintf("%s%s%s", $remap->newName->prefix, $flattenedValue->getValue(), $remap->newName->suffix);
unset($oldState[$remap->newName->flattenedProperty]);

View File

@ -147,7 +147,6 @@ final class ItemSerializerDeserializerRegistrar{
$this->map1to1Block(Ids::JUNGLE_DOOR, Blocks::JUNGLE_DOOR());
$this->map1to1Block(Ids::MANGROVE_DOOR, Blocks::MANGROVE_DOOR());
$this->map1to1Block(Ids::NETHER_WART, Blocks::NETHER_WART());
$this->map1to1Block(Ids::PITCHER_POD, Blocks::PITCHER_CROP());
$this->map1to1Block(Ids::REPEATER, Blocks::REDSTONE_REPEATER());
$this->map1to1Block(Ids::SPRUCE_DOOR, Blocks::SPRUCE_DOOR());
$this->map1to1Block(Ids::SUGAR_CANE, Blocks::SUGARCANE());
@ -193,6 +192,7 @@ final class ItemSerializerDeserializerRegistrar{
$this->map1to1Item(Ids::CLAY_BALL, Items::CLAY());
$this->map1to1Item(Ids::CLOCK, Items::CLOCK());
$this->map1to1Item(Ids::COAL, Items::COAL());
$this->map1to1Item(Ids::COAST_ARMOR_TRIM_SMITHING_TEMPLATE, Items::COAST_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::COCOA_BEANS, Items::COCOA_BEANS());
$this->map1to1Item(Ids::COD, Items::RAW_FISH());
$this->map1to1Item(Ids::COMPASS, Items::COMPASS());
@ -221,6 +221,7 @@ final class ItemSerializerDeserializerRegistrar{
$this->map1to1Item(Ids::DISC_FRAGMENT_5, Items::DISC_FRAGMENT_5());
$this->map1to1Item(Ids::DRAGON_BREATH, Items::DRAGON_BREATH());
$this->map1to1Item(Ids::DRIED_KELP, Items::DRIED_KELP());
$this->map1to1Item(Ids::DUNE_ARMOR_TRIM_SMITHING_TEMPLATE, Items::DUNE_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::ECHO_SHARD, Items::ECHO_SHARD());
$this->map1to1Item(Ids::EGG, Items::EGG());
$this->map1to1Item(Ids::EMERALD, Items::EMERALD());
@ -228,6 +229,7 @@ final class ItemSerializerDeserializerRegistrar{
$this->map1to1Item(Ids::ENCHANTED_GOLDEN_APPLE, Items::ENCHANTED_GOLDEN_APPLE());
$this->map1to1Item(Ids::ENDER_PEARL, Items::ENDER_PEARL());
$this->map1to1Item(Ids::EXPERIENCE_BOTTLE, Items::EXPERIENCE_BOTTLE());
$this->map1to1Item(Ids::EYE_ARMOR_TRIM_SMITHING_TEMPLATE, Items::EYE_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::FEATHER, Items::FEATHER());
$this->map1to1Item(Ids::FERMENTED_SPIDER_EYE, Items::FERMENTED_SPIDER_EYE());
$this->map1to1Item(Ids::FIRE_CHARGE, Items::FIRE_CHARGE());
@ -257,6 +259,7 @@ final class ItemSerializerDeserializerRegistrar{
$this->map1to1Item(Ids::HEART_OF_THE_SEA, Items::HEART_OF_THE_SEA());
$this->map1to1Item(Ids::HONEY_BOTTLE, Items::HONEY_BOTTLE());
$this->map1to1Item(Ids::HONEYCOMB, Items::HONEYCOMB());
$this->map1to1Item(Ids::HOST_ARMOR_TRIM_SMITHING_TEMPLATE, Items::HOST_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::INK_SAC, Items::INK_SAC());
$this->map1to1Item(Ids::IRON_AXE, Items::IRON_AXE());
$this->map1to1Item(Ids::IRON_BOOTS, Items::IRON_BOOTS());
@ -302,6 +305,7 @@ final class ItemSerializerDeserializerRegistrar{
$this->map1to1Item(Ids::MUSIC_DISC_WAIT, Items::RECORD_WAIT());
$this->map1to1Item(Ids::MUSIC_DISC_WARD, Items::RECORD_WARD());
$this->map1to1Item(Ids::MUTTON, Items::RAW_MUTTON());
$this->map1to1Item(Ids::NAME_TAG, Items::NAME_TAG());
$this->map1to1Item(Ids::NAUTILUS_SHELL, Items::NAUTILUS_SHELL());
$this->map1to1Item(Ids::NETHER_STAR, Items::NETHER_STAR());
$this->map1to1Item(Ids::NETHERBRICK, Items::NETHER_BRICK());
@ -316,11 +320,13 @@ final class ItemSerializerDeserializerRegistrar{
$this->map1to1Item(Ids::NETHERITE_SCRAP, Items::NETHERITE_SCRAP());
$this->map1to1Item(Ids::NETHERITE_SHOVEL, Items::NETHERITE_SHOVEL());
$this->map1to1Item(Ids::NETHERITE_SWORD, Items::NETHERITE_SWORD());
$this->map1to1Item(Ids::NETHERITE_UPGRADE_SMITHING_TEMPLATE, Items::NETHERITE_UPGRADE_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::OAK_BOAT, Items::OAK_BOAT());
$this->map1to1Item(Ids::OAK_SIGN, Items::OAK_SIGN());
$this->map1to1Item(Ids::PAINTING, Items::PAINTING());
$this->map1to1Item(Ids::PAPER, Items::PAPER());
$this->map1to1Item(Ids::PHANTOM_MEMBRANE, Items::PHANTOM_MEMBRANE());
$this->map1to1Item(Ids::PITCHER_POD, Items::PITCHER_POD());
$this->map1to1Item(Ids::POISONOUS_POTATO, Items::POISONOUS_POTATO());
$this->map1to1Item(Ids::POPPED_CHORUS_FRUIT, Items::POPPED_CHORUS_FRUIT());
$this->map1to1Item(Ids::PORKCHOP, Items::RAW_PORKCHOP());
@ -335,18 +341,25 @@ final class ItemSerializerDeserializerRegistrar{
$this->map1to1Item(Ids::RABBIT_FOOT, Items::RABBIT_FOOT());
$this->map1to1Item(Ids::RABBIT_HIDE, Items::RABBIT_HIDE());
$this->map1to1Item(Ids::RABBIT_STEW, Items::RABBIT_STEW());
$this->map1to1Item(Ids::RAISER_ARMOR_TRIM_SMITHING_TEMPLATE, Items::RAISER_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::RAW_COPPER, Items::RAW_COPPER());
$this->map1to1Item(Ids::RAW_GOLD, Items::RAW_GOLD());
$this->map1to1Item(Ids::RAW_IRON, Items::RAW_IRON());
$this->map1to1Item(Ids::REDSTONE, Items::REDSTONE_DUST());
$this->map1to1Item(Ids::RIB_ARMOR_TRIM_SMITHING_TEMPLATE, Items::RIB_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::ROTTEN_FLESH, Items::ROTTEN_FLESH());
$this->map1to1Item(Ids::SALMON, Items::RAW_SALMON());
$this->map1to1Item(Ids::SCUTE, Items::SCUTE());
$this->map1to1Item(Ids::TURTLE_SCUTE, Items::SCUTE());
$this->map1to1Item(Ids::SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE, Items::SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE, Items::SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::SHEARS, Items::SHEARS());
$this->map1to1Item(Ids::SHULKER_SHELL, Items::SHULKER_SHELL());
$this->map1to1Item(Ids::SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE, Items::SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::SLIME_BALL, Items::SLIMEBALL());
$this->map1to1Item(Ids::SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE, Items::SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::SNOWBALL, Items::SNOWBALL());
$this->map1to1Item(Ids::SPIDER_EYE, Items::SPIDER_EYE());
$this->map1to1Item(Ids::SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE, Items::SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::SPRUCE_BOAT, Items::SPRUCE_BOAT());
$this->map1to1Item(Ids::SPRUCE_SIGN, Items::SPRUCE_SIGN());
$this->map1to1Item(Ids::SPYGLASS, Items::SPYGLASS());
@ -361,14 +374,19 @@ final class ItemSerializerDeserializerRegistrar{
$this->map1to1Item(Ids::SUGAR, Items::SUGAR());
$this->map1to1Item(Ids::SWEET_BERRIES, Items::SWEET_BERRIES());
$this->map1to1Item(Ids::TORCHFLOWER_SEEDS, Items::TORCHFLOWER_SEEDS());
$this->map1to1Item(Ids::TIDE_ARMOR_TRIM_SMITHING_TEMPLATE, Items::TIDE_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::TOTEM_OF_UNDYING, Items::TOTEM());
$this->map1to1Item(Ids::TROPICAL_FISH, Items::CLOWNFISH());
$this->map1to1Item(Ids::TURTLE_HELMET, Items::TURTLE_HELMET());
$this->map1to1Item(Ids::VEX_ARMOR_TRIM_SMITHING_TEMPLATE, Items::VEX_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::VILLAGER_SPAWN_EGG, Items::VILLAGER_SPAWN_EGG());
$this->map1to1Item(Ids::WARD_ARMOR_TRIM_SMITHING_TEMPLATE, Items::WARD_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::WARPED_SIGN, Items::WARPED_SIGN());
$this->map1to1Item(Ids::WATER_BUCKET, Items::WATER_BUCKET());
$this->map1to1Item(Ids::WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE, Items::WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::WHEAT, Items::WHEAT());
$this->map1to1Item(Ids::WHEAT_SEEDS, Items::WHEAT_SEEDS());
$this->map1to1Item(Ids::WILD_ARMOR_TRIM_SMITHING_TEMPLATE, Items::WILD_ARMOR_TRIM_SMITHING_TEMPLATE());
$this->map1to1Item(Ids::WOODEN_AXE, Items::WOODEN_AXE());
$this->map1to1Item(Ids::WOODEN_HOE, Items::WOODEN_HOE());
$this->map1to1Item(Ids::WOODEN_PICKAXE, Items::WOODEN_PICKAXE());

View File

@ -38,6 +38,8 @@ final class ItemTypeNames{
public const ANGLER_POTTERY_SHERD = "minecraft:angler_pottery_sherd";
public const APPLE = "minecraft:apple";
public const ARCHER_POTTERY_SHERD = "minecraft:archer_pottery_sherd";
public const ARMADILLO_SCUTE = "minecraft:armadillo_scute";
public const ARMADILLO_SPAWN_EGG = "minecraft:armadillo_spawn_egg";
public const ARMOR_STAND = "minecraft:armor_stand";
public const ARMS_UP_POTTERY_SHERD = "minecraft:arms_up_pottery_sherd";
public const ARROW = "minecraft:arrow";
@ -79,6 +81,7 @@ final class ItemTypeNames{
public const BOW = "minecraft:bow";
public const BOWL = "minecraft:bowl";
public const BREAD = "minecraft:bread";
public const BREEZE_SPAWN_EGG = "minecraft:breeze_spawn_egg";
public const BREWER_POTTERY_SHERD = "minecraft:brewer_pottery_sherd";
public const BREWING_STAND = "minecraft:brewing_stand";
public const BRICK = "minecraft:brick";
@ -134,6 +137,7 @@ final class ItemTypeNames{
public const COOKED_RABBIT = "minecraft:cooked_rabbit";
public const COOKED_SALMON = "minecraft:cooked_salmon";
public const COOKIE = "minecraft:cookie";
public const COPPER_DOOR = "minecraft:copper_door";
public const COPPER_INGOT = "minecraft:copper_ingot";
public const CORAL = "minecraft:coral";
public const COW_SPAWN_EGG = "minecraft:cow_spawn_egg";
@ -150,6 +154,7 @@ final class ItemTypeNames{
public const DARK_OAK_DOOR = "minecraft:dark_oak_door";
public const DARK_OAK_HANGING_SIGN = "minecraft:dark_oak_hanging_sign";
public const DARK_OAK_SIGN = "minecraft:dark_oak_sign";
public const DEBUG_STICK = "minecraft:debug_stick";
public const DIAMOND = "minecraft:diamond";
public const DIAMOND_AXE = "minecraft:diamond_axe";
public const DIAMOND_BOOTS = "minecraft:diamond_boots";
@ -186,6 +191,7 @@ final class ItemTypeNames{
public const EVOKER_SPAWN_EGG = "minecraft:evoker_spawn_egg";
public const EXPERIENCE_BOTTLE = "minecraft:experience_bottle";
public const EXPLORER_POTTERY_SHERD = "minecraft:explorer_pottery_sherd";
public const EXPOSED_COPPER_DOOR = "minecraft:exposed_copper_door";
public const EYE_ARMOR_TRIM_SMITHING_TEMPLATE = "minecraft:eye_armor_trim_smithing_template";
public const FEATHER = "minecraft:feather";
public const FENCE = "minecraft:fence";
@ -235,6 +241,8 @@ final class ItemTypeNames{
public const GREEN_DYE = "minecraft:green_dye";
public const GUARDIAN_SPAWN_EGG = "minecraft:guardian_spawn_egg";
public const GUNPOWDER = "minecraft:gunpowder";
public const HARD_STAINED_GLASS = "minecraft:hard_stained_glass";
public const HARD_STAINED_GLASS_PANE = "minecraft:hard_stained_glass_pane";
public const HEART_OF_THE_SEA = "minecraft:heart_of_the_sea";
public const HEART_POTTERY_SHERD = "minecraft:heart_pottery_sherd";
public const HEARTBREAK_POTTERY_SHERD = "minecraft:heartbreak_pottery_sherd";
@ -347,6 +355,7 @@ final class ItemTypeNames{
public const OAK_SIGN = "minecraft:oak_sign";
public const OCELOT_SPAWN_EGG = "minecraft:ocelot_spawn_egg";
public const ORANGE_DYE = "minecraft:orange_dye";
public const OXIDIZED_COPPER_DOOR = "minecraft:oxidized_copper_door";
public const PAINTING = "minecraft:painting";
public const PANDA_SPAWN_EGG = "minecraft:panda_spawn_egg";
public const PAPER = "minecraft:paper";
@ -360,6 +369,7 @@ final class ItemTypeNames{
public const PILLAGER_SPAWN_EGG = "minecraft:pillager_spawn_egg";
public const PINK_DYE = "minecraft:pink_dye";
public const PITCHER_POD = "minecraft:pitcher_pod";
public const PLANKS = "minecraft:planks";
public const PLENTY_POTTERY_SHERD = "minecraft:plenty_pottery_sherd";
public const POISONOUS_POTATO = "minecraft:poisonous_potato";
public const POLAR_BEAR_SPAWN_EGG = "minecraft:polar_bear_spawn_egg";
@ -399,7 +409,6 @@ final class ItemTypeNames{
public const SALMON = "minecraft:salmon";
public const SALMON_BUCKET = "minecraft:salmon_bucket";
public const SALMON_SPAWN_EGG = "minecraft:salmon_spawn_egg";
public const SCUTE = "minecraft:scute";
public const SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE = "minecraft:sentry_armor_trim_smithing_template";
public const SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE = "minecraft:shaper_armor_trim_smithing_template";
public const SHEAF_POTTERY_SHERD = "minecraft:sheaf_pottery_sherd";
@ -461,11 +470,13 @@ final class ItemTypeNames{
public const TORCHFLOWER_SEEDS = "minecraft:torchflower_seeds";
public const TOTEM_OF_UNDYING = "minecraft:totem_of_undying";
public const TRADER_LLAMA_SPAWN_EGG = "minecraft:trader_llama_spawn_egg";
public const TRIAL_KEY = "minecraft:trial_key";
public const TRIDENT = "minecraft:trident";
public const TROPICAL_FISH = "minecraft:tropical_fish";
public const TROPICAL_FISH_BUCKET = "minecraft:tropical_fish_bucket";
public const TROPICAL_FISH_SPAWN_EGG = "minecraft:tropical_fish_spawn_egg";
public const TURTLE_HELMET = "minecraft:turtle_helmet";
public const TURTLE_SCUTE = "minecraft:turtle_scute";
public const TURTLE_SPAWN_EGG = "minecraft:turtle_spawn_egg";
public const VEX_ARMOR_TRIM_SMITHING_TEMPLATE = "minecraft:vex_armor_trim_smithing_template";
public const VEX_SPAWN_EGG = "minecraft:vex_spawn_egg";
@ -479,7 +490,12 @@ final class ItemTypeNames{
public const WARPED_HANGING_SIGN = "minecraft:warped_hanging_sign";
public const WARPED_SIGN = "minecraft:warped_sign";
public const WATER_BUCKET = "minecraft:water_bucket";
public const WAXED_COPPER_DOOR = "minecraft:waxed_copper_door";
public const WAXED_EXPOSED_COPPER_DOOR = "minecraft:waxed_exposed_copper_door";
public const WAXED_OXIDIZED_COPPER_DOOR = "minecraft:waxed_oxidized_copper_door";
public const WAXED_WEATHERED_COPPER_DOOR = "minecraft:waxed_weathered_copper_door";
public const WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE = "minecraft:wayfinder_armor_trim_smithing_template";
public const WEATHERED_COPPER_DOOR = "minecraft:weathered_copper_door";
public const WHEAT = "minecraft:wheat";
public const WHEAT_SEEDS = "minecraft:wheat_seeds";
public const WHITE_DYE = "minecraft:white_dye";
@ -487,6 +503,7 @@ final class ItemTypeNames{
public const WITCH_SPAWN_EGG = "minecraft:witch_spawn_egg";
public const WITHER_SKELETON_SPAWN_EGG = "minecraft:wither_skeleton_spawn_egg";
public const WITHER_SPAWN_EGG = "minecraft:wither_spawn_egg";
public const WOLF_ARMOR = "minecraft:wolf_armor";
public const WOLF_SPAWN_EGG = "minecraft:wolf_spawn_egg";
public const WOODEN_AXE = "minecraft:wooden_axe";
public const WOODEN_DOOR = "minecraft:wooden_door";

View File

@ -88,6 +88,9 @@ final class ItemIdMetaUpgradeSchemaUtils{
}
$jsonMapper = new \JsonMapper();
$jsonMapper->bExceptionOnMissingData = true;
$jsonMapper->bExceptionOnUndefinedProperty = true;
$jsonMapper->bStrictObjectTypeChecking = true;
try{
$model = $jsonMapper->map($json, new ItemIdMetaUpgradeSchemaModel());
}catch(\JsonMapper_Exception $e){

View File

@ -44,10 +44,14 @@ final class GameModeIdMap{
private array $enumToId = [];
public function __construct(){
$this->register(0, GameMode::SURVIVAL);
$this->register(1, GameMode::CREATIVE);
$this->register(2, GameMode::ADVENTURE);
$this->register(3, GameMode::SPECTATOR);
foreach(GameMode::cases() as $case){
$this->register(match($case){
GameMode::SURVIVAL => 0,
GameMode::CREATIVE => 1,
GameMode::ADVENTURE => 2,
GameMode::SPECTATOR => 3,
}, $case);
}
}
private function register(int $id, GameMode $type) : void{

View File

@ -29,11 +29,6 @@ namespace pocketmine\data\runtime;
* @deprecated
*/
trait LegacyRuntimeEnumDescriberTrait{
/**
* @phpstan-template T of \UnitEnum
* @phpstan-param T $case
*/
abstract protected function enum(\UnitEnum &$case) : void;
public function bellAttachmentType(\pocketmine\block\utils\BellAttachmentType &$value) : void{

View File

@ -89,10 +89,6 @@ interface RuntimeDataDescriber extends RuntimeEnumDescriber{
public function straightOnlyRailShape(int &$railShape) : void;
/**
* @phpstan-template T of \UnitEnum
* @phpstan-param T $case
*/
public function enum(\UnitEnum &$case) : void;
/**

View File

@ -252,6 +252,14 @@ abstract class Entity{
return $this->alwaysShowNameTag;
}
/**
* Returns whether players can rename this entity using a name tag.
* Note that plugins can still name entities using setNameTag().
*/
public function canBeRenamed() : bool{
return false;
}
public function setNameTag(string $name) : void{
$this->nameTag = $name;
$this->networkPropertiesDirty = true;

View File

@ -132,6 +132,10 @@ abstract class Living extends Entity{
abstract public function getName() : string;
public function canBeRenamed() : bool{
return true;
}
protected function initEntity(CompoundTag $nbt) : void{
parent::initEntity($nbt);

View File

@ -173,8 +173,9 @@ abstract class Projectile extends Entity{
$entityHit = null;
$hitResult = null;
$world = $this->getWorld();
foreach(VoxelRayTrace::betweenPoints($start, $end) as $vector3){
$block = $this->getWorld()->getBlockAt($vector3->x, $vector3->y, $vector3->z);
$block = $world->getBlockAt($vector3->x, $vector3->y, $vector3->z);
$blockHitResult = $this->calculateInterceptWithBlock($block, $start, $end);
if($blockHitResult !== null){
@ -188,7 +189,7 @@ abstract class Projectile extends Entity{
$entityDistance = PHP_INT_MAX;
$newDiff = $end->subtractVector($start);
foreach($this->getWorld()->getCollidingEntities($this->boundingBox->addCoord($newDiff->x, $newDiff->y, $newDiff->z)->expand(1, 1, 1), $this) as $entity){
foreach($world->getCollidingEntities($this->boundingBox->addCoord($newDiff->x, $newDiff->y, $newDiff->z)->expand(1, 1, 1), $this) as $entity){
if($entity->getId() === $this->getOwningEntityId() && $this->ticksLived < 5){
continue;
}
@ -256,7 +257,7 @@ abstract class Projectile extends Entity{
);
}
$this->getWorld()->onEntityMoved($this);
$world->onEntityMoved($this);
$this->checkBlockIntersections();
Timings::$projectileMove->stopTiming();

View File

@ -31,8 +31,9 @@ class Snowball extends Throwable{
public static function getNetworkTypeId() : string{ return EntityIds::SNOWBALL; }
protected function onHit(ProjectileHitEvent $event) : void{
$world = $this->getWorld();
for($i = 0; $i < 6; ++$i){
$this->getWorld()->addParticle($this->location, new SnowballPoofParticle());
$world->addParticle($this->location, new SnowballPoofParticle());
}
}
}

View File

@ -37,8 +37,7 @@ class HandlerList{
private array $affectedHandlerCaches = [];
/**
* @phpstan-template TEvent of Event
* @phpstan-param class-string<TEvent> $class
* @phpstan-param class-string<covariant Event> $class
*/
public function __construct(
private string $class,

View File

@ -86,8 +86,7 @@ class HandlerListManager{
*
* Calling this method also lazily initializes the $classMap inheritance tree of handler lists.
*
* @phpstan-template TEvent of Event
* @phpstan-param class-string<TEvent> $event
* @phpstan-param class-string<covariant Event> $event
*
* @throws \ReflectionException
* @throws \InvalidArgumentException
@ -113,8 +112,7 @@ class HandlerListManager{
}
/**
* @phpstan-template TEvent of Event
* @phpstan-param class-string<TEvent> $event
* @phpstan-param class-string<covariant Event> $event
*
* @return RegisteredListener[]
*/

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\item;
use pocketmine\block\Block;
use pocketmine\block\BlockTypeIds;
use pocketmine\data\runtime\RuntimeDataDescriber;
/**
@ -58,4 +59,12 @@ final class ItemBlock extends Item{
public function getMaxStackSize() : int{
return $this->block->getMaxStackSize();
}
public function isNull() : bool{
//TODO: we really shouldn't need to treat air as a special case here
//this is needed because the "null" empty slot item is represented by an air block, but there's no real reason
//why air should be needed at all. A separate special item type (or actual null) should be used instead, but
//this would cause a lot of BC breaks, so we can't do it yet.
return parent::isNull() || $this->block->getTypeId() === BlockTypeIds::AIR;
}
}

View File

@ -305,8 +305,27 @@ final class ItemTypeIds{
public const CHERRY_SIGN = 20266;
public const ENCHANTED_BOOK = 20267;
public const TORCHFLOWER_SEEDS = 20268;
public const NETHERITE_UPGRADE_SMITHING_TEMPLATE = 20269;
public const SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE = 20270;
public const VEX_ARMOR_TRIM_SMITHING_TEMPLATE = 20271;
public const WILD_ARMOR_TRIM_SMITHING_TEMPLATE = 20272;
public const COAST_ARMOR_TRIM_SMITHING_TEMPLATE = 20273;
public const DUNE_ARMOR_TRIM_SMITHING_TEMPLATE = 20274;
public const WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE = 20275;
public const RAISER_ARMOR_TRIM_SMITHING_TEMPLATE = 20276;
public const SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE = 20277;
public const HOST_ARMOR_TRIM_SMITHING_TEMPLATE = 20278;
public const WARD_ARMOR_TRIM_SMITHING_TEMPLATE = 20279;
public const SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE = 20280;
public const TIDE_ARMOR_TRIM_SMITHING_TEMPLATE = 20281;
public const SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE = 20282;
public const RIB_ARMOR_TRIM_SMITHING_TEMPLATE = 20283;
public const EYE_ARMOR_TRIM_SMITHING_TEMPLATE = 20284;
public const SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE = 20285;
public const PITCHER_POD = 20286;
public const NAME_TAG = 20287;
public const FIRST_UNUSED_ITEM_ID = 20269;
public const FIRST_UNUSED_ITEM_ID = 20288;
private static int $nextDynamicId = self::FIRST_UNUSED_ITEM_ID;

40
src/item/NameTag.php Normal file
View File

@ -0,0 +1,40 @@
<?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\item;
use pocketmine\entity\Entity;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
class NameTag extends Item{
public function onInteractEntity(Player $player, Entity $entity, Vector3 $clickVector) : bool{
if($entity->canBeRenamed() && $this->hasCustomName()){
$entity->setNameTag($this->getCustomName());
$this->pop();
return true;
}
return false;
}
}

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