Compare commits

...

245 Commits

Author SHA1 Message Date
ba6828c6bd Release 5.22.0 (Bedrock 1.21.50 support) (#6559)
Co-authored-by: Dylan K. Taylor <dktapps@pmmp.io>
2024-12-04 13:36:52 +00:00
c56d4d3e3c dependabot: update github actions deps together, monthly 2024-12-03 14:56:22 +00:00
06028aac97 issues: don't recommend forums to get help 2024-12-03 02:07:58 +00:00
49da50659f Bump docker/build-push-action from 6.9.0 to 6.10.0 (#6553) 2024-12-02 16:36:12 +00:00
fcef015f32 L link 2024-12-02 00:40:55 +00:00
44771c892d Use PlayerAuthInputPacket::SNEAKING flag to test for sneaking (#6544)
This binds internal sneaking to whether or not the player is currently pressing the shift key, which fixes #5792 and fixes #5903.

However, it does introduce visual issues with sneaking, as explained in #6548. This needs to be worked on separately. For now, it's better we trade 2 functional bugs for 1 visual bug.
2024-12-01 13:14:30 +00:00
9cab72ed59 5.21.3 is next
Commit created by: https://github.com/pmmp/RestrictedActions/actions/runs/12090411351
2024-11-29 20:43:17 +00:00
2bd9f4108b 5.21.2 (#6545) 2024-11-29 20:42:14 +00:00
cd2a1fdc1d Bump build/php from 8a396c6 to 5016e0a (#6541) 2024-11-29 11:03:27 +00:00
d666f17ec6 Bump build/php from a51259d to 8a396c6 (#6540) 2024-11-28 15:46:30 +00:00
0543bf301e draft-release: updated php_download_url 2024-11-27 19:19:51 +00:00
daacc8eddb Updated setup-php-action to 3.2.0 2024-11-27 17:56:00 +00:00
8cdc7d7ee1 auto-approve: drop pull_request_review trigger
this doesn't work for PRs from forks, since fork PRs don't have access to repo secrets.

we'll need some more advanced mechanism to avoid redundant reviews, but that's a job for another time.
2024-11-25 20:43:59 +00:00
a9787f0d99 Fix PHPStan error 2024-11-25 14:32:17 +00:00
5325ecee37 Deal with a whole lot of PHPStan suppressed key casting errors
closes #6534
2024-11-25 14:30:58 +00:00
aef4fa7174 Remove unused variable 2024-11-24 23:50:30 +00:00
53aa380ca3 Candle: fix extinguish logic
closes #5983
2024-11-24 23:49:32 +00:00
7460e12b6a pr-remove-waiting-label: suppress failure on 404 errors
this usually means the label wasn't on the PR in the first place
2024-11-23 21:48:30 +00:00
5b72f202bf actions: automatically remove waiting label from PRs on synchronize
there are probably other conditions where we'd want to remove this, but this will do for now.
2024-11-23 20:13:46 +00:00
0070426e97 auto-approve: only re-review if previous review was dismissed
this avoids unnecessary spam when someone clicks "Update branch" on the PR.
2024-11-23 19:07:24 +00:00
7c2ed7d884 Fix insta break check (#6528) 2024-11-21 02:22:10 +00:00
bf7a53b00f Update api-change-request.md
[ci skip]
2024-11-19 17:47:46 +00:00
e710b3750f Adjust pretty name of closures on PHP 8.4 (#6351)
related to https://github.com/php/php-src/pull/13550

see analog symfony change: https://github.com/symfony/symfony/pull/54614
2024-11-19 17:05:21 +00:00
faf1e26bac Fix: implicitly nullable parameter declarations deprecated (#6522) 2024-11-18 23:54:22 +00:00
b2aa6396c3 auto-approve: don't request approvals for draft PRs 2024-11-16 23:15:07 +00:00
48a908ee8c maybe making this specific to gameplay wasn't a good idea 2024-11-16 01:36:51 +00:00
4331f69b9c Update team-pr-auto-approve.yml 2024-11-15 20:44:51 +00:00
8a693f2a4c team-pr-auto-approve: Use RestrictedActions auto approver 2024-11-15 20:08:54 +00:00
b5469dede2 Flowable blocks now can't be placed inside liquid (#5392) 2024-11-15 00:10:43 +00:00
09bf203267 Update RuntimeDataDescriber.php 2024-11-12 22:57:14 +00:00
f3cc4a28e1 Easy wins for PHPStan 2.0 support 2024-11-12 22:12:54 +00:00
fe70150db2 Update composer dependencies 2024-11-12 21:47:52 +00:00
054538e6b7 Update PULL_REQUEST_TEMPLATE.md 2024-11-12 17:54:31 +00:00
1f86949836 Create CODEOWNERS 2024-11-12 14:37:02 +00:00
053a71c59d Bump build/php from 084822a to a51259d (#6495) 2024-11-12 14:28:32 +00:00
07d5046b83 5.21.2 is next
Commit created by: https://github.com/pmmp/RestrictedActions/actions/runs/11796630402
2024-11-12 11:48:59 +00:00
4a702b97fd Prepare 5.21.1 release (#6493) 2024-11-12 11:48:01 +00:00
d2c3b8dacb Fix GC cycle count increases on player disconnect (#6487) 2024-11-11 16:10:19 +01:00
2ff6470792 Fixed server crash when applying item cooldown (#6491)
This commit fixes server crash when applying a cooldown to any item which count is equals to 1.

closes #6490 
closes #6488
2024-11-10 19:15:30 +00:00
231eec911f Enchanted Golden Apple: Regeneration 5 => 2 matching Java (#6445) 2024-11-09 19:43:30 +00:00
8c04d47b1b Make weakness effect only applicable for melee damage (#6489) 2024-11-09 19:18:30 +00:00
b3b8aaddff Bump docker/build-push-action from 6.8.0 to 6.9.0 (#6465) 2024-11-04 16:29:01 +00:00
2173aab967 Bump thollander/actions-comment-pull-request from 2 to 3 (#6482) 2024-11-04 16:05:38 +00:00
e598364f06 5.21.1 is next
Commit created by: https://github.com/pmmp/RestrictedActions/actions/runs/11652565588
2024-11-03 15:30:16 +00:00
734ca1cc6b Merge pull request #6480 from pmmp/minor-next
5.21.0
2024-11-03 15:29:06 +00:00
96b12bddc1 Prepare 5.21.0 release 2024-11-03 15:24:43 +00:00
84464cde4f Update BedrockBlockUpgradeSchema 2024-11-03 14:44:50 +00:00
72fc138631 Regenerate PHPStan baselines 2024-11-03 14:43:34 +00:00
c63d0ef1b6 Fix dodgy ignored PHPStan error 2024-11-03 14:43:34 +00:00
82c416624d Merge pull request #6416 from pmmp/blockstate-schema-generator-improvements
Blockstate schema generator improvements
2024-11-03 14:10:38 +00:00
9e19391f20 Merge branch 'minor-next' into blockstate-schema-generator-improvements 2024-11-03 14:06:57 +00:00
c0b74b0341 Update BlockStateUpgrader.php 2024-11-03 14:05:46 +00:00
3c96e72f7d Merge remote-tracking branch 'origin/stable' into minor-next 2024-11-03 14:01:47 +00:00
0376e37966 5.20.2 is next
Commit created by: https://github.com/pmmp/RestrictedActions/actions/runs/11614028030
2024-10-31 14:38:30 +00:00
94dff74494 Prepare 5.20.1 release (#6479) 2024-10-31 14:35:42 +00:00
0065fe649f New release workflow triggered by the merge of a PR changing
IS_DEVELOPMENT_BUILD to false

This is more streamlined than the previous approach, and works better
for a world where 1 person isn't doing all the work.

Now, the flow is simpler:
- Do changes (e.g. protocol update), changelog & set IS_DEVELOPMENT_BUILD to false all in a single PR, which can be squash-merged if desired
- Once the PR is merged, a draft release will be prepared
- RestrictedActions will automatically set IS_DEVELOPMENT_BUILD back to
  true and bump the version
- Tag will be created when the release is published

Previously, multiple PRs might be needed, and the PR containing the
release changelog couldn't be squash-merged. Manual intervention was
also required to create a tag and prepare a release.

This PR also includes new CI checks to check for basic errors like
forgotten changelog files to ensure changelog links work correctly.

Note: Only PRs from PMMP Team members with **write** access to the
repository can trigger release generation. Random people cannot trigger
release generation by sending PRs.
2024-10-31 13:57:38 +00:00
8ef5e737de Temporary resolve loading old skulls from storage (#6476) 2024-10-27 01:29:34 +01:00
e7d8d99ca6 5.20.1 is next 2024-10-26 15:42:43 +01:00
414e8acf8c Release 5.20.0 2024-10-26 15:42:43 +01:00
d372af351a Fix changelog typo 2024-10-26 15:40:22 +01:00
4814db4fe7 Assemble 1.21.40 (#6471) 2024-10-25 14:21:51 +01:00
d01203d7c4 Reduce code duplication 2024-10-24 18:50:39 +01:00
847f931660 Merge branch 'minor-next' into blockstate-schema-generator-improvements 2024-10-24 17:46:57 +01:00
22718c4971 Add support for specialized flattenedProperties in schema format 2024-10-24 16:12:28 +01:00
acbfb0a3e9 Support for updating a batch of schemas using BlockPaletteArchive 2024-10-24 13:30:55 +01:00
7f9e79c83e Automatically test new schemas to ensure they produce the results predicted by the input file 2024-10-24 13:30:24 +01:00
7e343617b9 Rename ICopper to CopperMaterial (#6470) 2024-10-23 11:34:42 +01:00
d945cbf517 Merge remote-tracking branch 'origin/minor-next' into blockstate-schema-generator-improvements 2024-10-17 21:00:11 +01:00
c4e72c880e Merge 'stable' into 'minor-next'
Automatic merge performed by: https://github.com/pmmp/RestrictedActions/actions/runs/11392123557
2024-10-17 19:59:13 +00:00
3ef7001d8e Merge branch 'stable' into blockstate-schema-generator-improvements 2024-10-17 20:55:34 +01:00
f1b1a7022d and a sanity check just in case 2024-10-17 20:55:12 +01:00
59d14de1d8 generate-blockstate-upgrade-schema: fallback to exact state match when encountering ambiguous filters
this popped up due to new changes in 1.20.40. Really we need to improve the way the filters are calculated, but this workaround solves the issue for now.
2024-10-17 20:51:17 +01:00
c8f567b093 Fix missing arg count check 2024-10-17 20:24:57 +01:00
5cc1068cd4 Bump docker/build-push-action from 6.7.0 to 6.8.0 (#6462) 2024-10-03 21:29:22 +00:00
f6e6f15c63 Implemented a proper way to handle items cooldown (#6405) 2024-09-25 13:28:17 -05:00
4e6b34f573 Implement new 1.21 copper blocks (#6366)
Added the following new blocks:
- All types of Copper Bulb
- All types of Copper Door
- All types of Copper Trapdoor
- All types of Chiseled Copper
- All types of Copper Grate
2024-09-24 21:25:10 -05:00
a4a07a8e5a Merge 'stable' into 'minor-next'
Automatic merge performed by: https://github.com/pmmp/RestrictedActions/actions/runs/10986731877
2024-09-23 02:36:00 +00:00
0a7cbdd56d Release 5.19.0 (1.21.30 support) 2024-09-21 11:50:04 -05:00
a5babb2c9f 5.19.1 is next 2024-09-20 19:00:23 -05:00
49c2f13cf0 Release 5.19.0 2024-09-20 18:59:45 -05:00
60cac18104 Assemble 1.21.30 (#6453) 2024-09-20 18:47:25 -05:00
f6e2a1ecce Validate transaction slots (#6304) 2024-09-09 09:48:38 +02:00
00e39821f0 Release 5.18.1 (patch) 2024-09-03 06:46:21 -05:00
72d941fc1b Update 5.18.md 2024-09-03 11:33:05 +01:00
8cb2e577a1 Implement missing last interacted slot property in chiseled bookshelf (#6440) 2024-09-02 18:02:06 -05:00
2a7b183ab8 5.18.2 is next 2024-09-02 11:25:50 -05:00
e9b597af6c Release 5.18.1 2024-09-02 11:24:42 -05:00
9381fc4172 Blue Ice: No longer emits light & it's now dropped when mined with a tool with silk touch enchantment (#6438) 2024-08-31 22:33:11 -06:00
281afb6838 Bump phpstan/phpstan in the development-patch-updates group (#6435) 2024-08-26 23:05:11 +00:00
ede363eb0f Fix shift crafting (#6433)
This field was added to the action in 1.21.20. Previously, the client would behave as if clicking the crafting result slot many times. Now it behaves more like recipe book shift-clicking.
2024-08-22 21:53:21 +01:00
bdbcfd10cc Add ShellCheck (#6407)
Co-authored-by: IvanCraft623 <57236932+IvanCraft623@users.noreply.github.com>
2024-08-19 22:52:51 +01:00
e6f9cdd990 Bump docker/build-push-action from 6.6.1 to 6.7.0 (#6432) 2024-08-19 18:12:06 +00:00
5241118f0b Merge branch 'minor-next' into blockstate-schema-generator-improvements 2024-08-19 19:05:08 +01:00
93a270d251 Merge 'stable' into 'minor-next'
Automatic merge performed by: https://github.com/pmmp/RestrictedActions/actions/runs/10458521667
2024-08-19 18:03:24 +00:00
a7638cf914 Give an approving review to team member PRs automatically
Branch protection rules currently require 2 approving reviews to merge a PR. What we really want is for 2 team members to be aware of every change. If a team member makes a PR, only one other approval should be needed.

Since GitHub doesn't currently allow us to set different review thresholds for different users/teams, sending an automatic approval via GitHub Actions is the next best thing. This should reduce friction of team development work.
2024-08-19 19:02:17 +01:00
c44e6c59fc Merge pull request #6430 from pmmp/sync-minor-next
Merge branch 'stable' into minor-next
2024-08-18 17:49:25 +01:00
92f380bb9c Merge branch 'stable' into sync-minor-next 2024-08-17 11:17:48 -05:00
c32744ebc7 Release 5.18.0 (1.21.20 support) 2024-08-16 08:44:40 -05:00
e3baf3cddb 5.18.1 is next 2024-08-16 07:56:01 -05:00
9176b2494a Release 5.18.0 2024-08-16 07:54:59 -05:00
0f365886e0 Assemble 1.21.20 (#6423)
Co-authored-by: Dylan T. <dktapps@pmmp.io>
Co-authored-by: IvanCraft623 <ivancraft623@gmail.com>
2024-08-16 11:26:49 +01:00
8c3cf7a687 Use VISIBLE_MOB_EFFECTS actor metadata property to send effect bubbles (#6414)
Close #6402
2024-08-14 22:48:10 -05:00
994fa5f792 Merge 'stable' into 'minor-next'
Automatic merge performed by: https://github.com/pmmp/RestrictedActions/actions/runs/10373700926
2024-08-13 16:37:45 +00:00
3ed9615180 Merge pull request #6422 from pmmp/5.17.1
Release patch update 5.17.1
2024-08-13 17:28:27 +01:00
f5ab2979a0 5.17.2 is next 2024-08-13 10:56:03 -05:00
929cd63135 Release 5.17.1 2024-08-13 10:55:29 -05:00
585dc835e7 Fixed anvil placing rotation. (#6375)
Co-authored-by: IvanCraft623 <57236932+IvanCraft623@users.noreply.github.com>
2024-08-13 16:19:07 +01:00
13f5cc9f87 ChiseledBookshelf: fixed function visibility (#6421) 2024-08-13 16:11:22 +01:00
1ce774ae73 Merge 'stable' into 'minor-next'
Automatic merge performed by: https://github.com/pmmp/RestrictedActions/actions/runs/10371827817
2024-08-13 14:36:00 +00:00
d077bda30c Bump docker/build-push-action from 6.5.0 to 6.6.1 (#6419) 2024-08-13 14:35:01 +00:00
e017780cc3 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into minor-next 2024-08-13 13:37:56 +00:00
25c66e4c8b Bump phpstan/phpstan in the development-patch-updates group (#6420) 2024-08-13 13:36:14 +00:00
ee17ac5246 Merge branch 'stable' of github.com:pmmp/PocketMine-MP into minor-next 2024-08-09 13:32:07 +01:00
33dc995cc7 blockstate-upgrade-schema-utils: added a command to update old schemas to a newer format
this is useful when the generator was updated with new features & optimisations, to reduce the size and/or improve readability of existing schemas.
2024-08-09 13:12:46 +01:00
26761c2b87 Blockstate schema tool now supports testing schemas as well as generating them
this is useful when making changes to the generator, since regenerated schemas can now be tested for validity. This helps to find bugs in the generator.
2024-08-09 12:38:03 +01:00
5a926a79cb Bump phpstan/phpstan in the development-patch-updates group (#6412) 2024-08-06 14:21:20 +00:00
c4a2b6494d Implement Aqua Affinity enchantment (#6408) 2024-08-06 09:12:47 -05:00
2aa64dc15e Simplify phpstan-doc type hint for better readability 2024-08-05 17:13:23 -05:00
d0d7a995fb Add a TODO in BlockStateUpgrader
this issue can be worked around by adding a dummy schema, but it's a bit clunky.
2024-08-05 22:38:32 +01:00
be2437ac6e Support for flattening TAG_Byte and TAG_Int properties
this allows optimisation in upcoming versions.
2024-08-05 22:38:02 +01:00
bdb5845cec Allow name flattening rules where multiple old values map to the same new ID
this allows more compaction in certain cases, such as tallgrass recently.
instead of blacklisting any mapping which reuses the same flattened infix, we select the flatten property which produces the smallest number of distinct rules, which produces the most compact schema possible.
this change also permits potentially flattening other types of properties such as for corals (live/dead and type), although only one may be selected at a time.
2024-08-05 22:34:40 +01:00
54e7749c0b Bump docker/build-push-action from 6.3.0 to 6.5.0 (#6409) 2024-07-30 06:52:28 +00:00
237677c028 Bump phpstan/phpstan from 1.11.2 to 1.11.8 in the development-patch-updates group (#6410) 2024-07-30 06:47:56 +00:00
787afb6b00 Implement all new 1.21 tuff blocks (#6391) 2024-07-23 11:34:46 -05:00
df4ada81e5 BedrockWorldData: Update version constants to 1.21.2 (#6399)
Co-authored-by: Dylan T <14214667+dktapps@users.noreply.github.com>
2024-07-16 00:51:06 -05:00
a96f1a5083 Bump docker/build-push-action from 5.3.0 to 6.3.0 (#6387) 2024-07-14 18:17:41 +00:00
1f510caf88 Bump the phpstan group with 2 updates (#6401) 2024-07-12 13:16:44 +00:00
32be474840 dependabot: group PHPStan dependency updates always
these typically need to be updated together anyway
2024-07-12 14:12:47 +01:00
f750b01d8b dependabot: group patch updates into a single PR 2024-07-12 14:10:14 +01:00
31484ee5c1 Merge pull request #6400 from pmmp/dependabot/github_actions/shivammathur/setup-php-2.31.1 2024-07-12 12:46:19 +00:00
786d84a9e1 Bump shivammathur/setup-php from 2.30.4 to 2.31.1
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.30.4 to 2.31.1.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.30.4...2.31.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>
2024-07-12 12:43:18 +00:00
d6c48fd3a2 Implement new 1.21 paintings (#6393) 2024-07-12 13:24:43 +01:00
85606925a1 BlockStateData: add a note about CURRENT_VERSION
this is not the same as current game version, as the revision is determined by some Mojang internal factors.
2024-07-12 11:26:51 +01:00
ef9791eaed Merge pull request #6397 from pmmp/stable
Merge branch 'stable' into minor-next
2024-07-10 18:56:52 +01:00
accaa0acce Implement ICopper interface for blocks with common properties (#6390) 2024-07-10 11:15:06 -05:00
616f96a703 Release 5.17.0 (1.21.2 support) 2024-07-10 09:31:25 -05:00
824e270041 5.17.1 is next 2024-07-09 21:16:13 -05:00
37bf4bc0b0 Release 5.17.0 2024-07-09 21:15:18 -05:00
5d60ba36b7 Support for 1.21.2 2024-07-09 21:07:47 -05:00
68d2e2915e Bells always drops themselves (#4802) 2024-07-07 15:20:45 -05:00
2ffc38c835 Implement campfire & soul campfire (#4696) 2024-07-07 15:01:34 -05:00
20f5741ed7 Bowl: Add fuel return value (#6384) 2024-07-05 17:41:22 -05:00
f6c0b228ec Add flow and guster banner patterns 2024-07-04 16:47:18 -05:00
23b2b75acf Merge pull request #6380 from pmmp/dependabot/composer/phpunit/phpunit-10.5.24 2024-07-04 21:16:19 +00:00
25ea9b2218 Bump phpunit/phpunit from 10.3.5 to 10.5.24
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 10.3.5 to 10.5.24.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/10.5.24/ChangeLog-10.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/10.3.5...10.5.24)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 10:53:54 +00:00
77db7a8941 Merge pull request #6381 from pmmp/dependabot/composer/symfony/filesystem-6.4.9 2024-07-01 10:53:02 +00:00
af4294295b Bump symfony/filesystem from 6.4.7 to 6.4.9
Bumps [symfony/filesystem](https://github.com/symfony/filesystem) from 6.4.7 to 6.4.9.
- [Release notes](https://github.com/symfony/filesystem/releases)
- [Changelog](https://github.com/symfony/filesystem/blob/7.1/CHANGELOG.md)
- [Commits](https://github.com/symfony/filesystem/compare/v6.4.7...v6.4.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 10:19:24 +00:00
b342c497d1 Added 1.21 banner patterns. 2024-06-23 13:27:52 +03:00
428e38f913 Merge branch 'stable' into minor-next 2024-06-21 10:42:32 -05:00
5ae13209c0 Merge branch 'stable' into merge-stable 2024-06-20 19:21:33 -05:00
585aee9386 Fixed an oopsie from 5ef247620a
I added it to the wrong set of artifacts :(
2024-06-13 18:58:32 +01:00
433bd6a8aa 5.16.1 is next 2024-06-13 18:55:21 +01:00
22a1549998 Release 5.16.0 2024-06-13 18:55:18 +01:00
0ec8465fcf shut! 2024-06-13 18:43:10 +01:00
f121654452 Assemble 1.21.0 2024-06-13 18:41:41 +01:00
08c6e63aac Bump phpstan/phpstan from 1.10.67 to 1.11.2 (#6352)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.67 to 1.11.2.
- [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.67...1.11.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-31 17:01:51 +01:00
4c418b4318 Remove unnecessary return statement (#6350) 2024-05-31 16:54:50 +01:00
fb9a74e879 gitignore files generated by install-local-protocol.sh 2024-05-13 11:52:31 +01:00
554775841e Added script for linking local versions of Bedrock* deps for testing 2024-05-13 11:48:23 +01:00
373dd9938c Update composer dependencies 2024-05-13 11:37:32 +01:00
f772bb7384 WoodenStairs can be a fuel (#6345) 2024-05-13 09:34:18 +01:00
5ef247620a Attach permission doc to every release 2024-05-07 12:46:31 +01:00
1b082f99e9 DefaultPermissions: fixed typo 2024-05-07 12:34:42 +01:00
Max
371eccd007 Make access modifier consistent with parent abstract class (#6341) 2024-05-07 12:02:50 +01:00
9b6a0c9945 Bump phpstan/phpstan-strict-rules from 1.5.3 to 1.5.5 (#6335)
Bumps [phpstan/phpstan-strict-rules](https://github.com/phpstan/phpstan-strict-rules) from 1.5.3 to 1.5.5.
- [Release notes](https://github.com/phpstan/phpstan-strict-rules/releases)
- [Commits](https://github.com/phpstan/phpstan-strict-rules/compare/1.5.3...1.5.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 15:41:59 +01:00
ab3be50b49 Bump phpstan/phpstan from 1.10.66 to 1.10.67 (#6337)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.66 to 1.10.67.
- [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.66...1.10.67)

---
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-05-06 15:41:50 +01:00
27dc43f131 Bump shivammathur/setup-php from 2.30.2 to 2.30.4 (#6339)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.30.2 to 2.30.4.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.30.2...2.30.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 15:41:40 +01:00
d67f5a5c6f Bump symfony/filesystem from 6.4.6 to 6.4.7 (#6342)
Bumps [symfony/filesystem](https://github.com/symfony/filesystem) from 6.4.6 to 6.4.7.
- [Release notes](https://github.com/symfony/filesystem/releases)
- [Changelog](https://github.com/symfony/filesystem/blob/7.0/CHANGELOG.md)
- [Commits](https://github.com/symfony/filesystem/compare/v6.4.6...v6.4.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 15:41:28 +01:00
ed158f8a1b Server: include uptime in crash restart throttle message
this makes it clearer why the wait duration is chosen instead of it looking random.
2024-04-29 16:36:14 +01:00
d70a7d34a7 Living: don't knockback or do hurt FX when attacked during cooldown
players were switching from a weaker tool to a stronger one to get double knockback in PvP.
while it's intended that we don't cancel the second attack during hit cooldown if the damage is
higher (the first damage is subtracted to prevent doubling up), we don't want them to get double
knockback.
this behaviour now matches vanilla to the best of my observations.

Come at me PvP community... I know some people are going to hate this change
2024-04-29 15:51:43 +01:00
be6754494f 5.15.1 is next 2024-04-25 11:52:31 +01:00
d273ccf87c Release 5.15.0 2024-04-25 11:52:30 +01:00
737f5066a0 Fully cover codegen in CI 2024-04-25 11:48:22 +01:00
10238d7934 Removed beta change 2024-04-25 11:39:09 +01:00
6077748caa Changes for 1.20.80 2024-04-25 11:31:41 +01:00
50e2c469a5 Bump phpstan/phpstan-strict-rules from 1.5.2 to 1.5.3 (#6326)
Bumps [phpstan/phpstan-strict-rules](https://github.com/phpstan/phpstan-strict-rules) from 1.5.2 to 1.5.3.
- [Release notes](https://github.com/phpstan/phpstan-strict-rules/releases)
- [Commits](https://github.com/phpstan/phpstan-strict-rules/compare/1.5.2...1.5.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 14:24:59 +01:00
fa87602661 Bump build/php from f9601e5 to 084822a (#6323)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `f9601e5` to `084822a`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](f9601e5313...084822aa9e)

---
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-04-08 14:24:48 +01:00
d3c9c137ad Bump symfony/filesystem from 6.4.3 to 6.4.6 (#6327)
Bumps [symfony/filesystem](https://github.com/symfony/filesystem) from 6.4.3 to 6.4.6.
- [Release notes](https://github.com/symfony/filesystem/releases)
- [Changelog](https://github.com/symfony/filesystem/blob/7.0/CHANGELOG.md)
- [Commits](https://github.com/symfony/filesystem/compare/v6.4.3...v6.4.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-08 14:24:11 +01:00
37322e0d50 Armor: only make sound when the item was equipped by player action
this ensures the greatest amount of consistency with vanilla.

in order to prevent the sounds being broadcasted on armor damage with the old method, we'd also have to sacrifice the sound when replacing one leather helmet with another, for example.
this approach minimizes the gameplay impact at the possible expense of plugins.

closes #6325
2024-04-08 14:05:47 +01:00
55cf24aa02 5.14.2 is next 2024-04-05 18:41:27 +01:00
3590d84d03 Release 5.14.1 2024-04-05 18:41:27 +01:00
68f8fa8caf Update pmmpthread required version 2024-04-05 18:40:43 +01:00
1ad190024a 5.14.1 is next 2024-04-05 18:16:22 +01:00
769a149057 Release 5.14.0 2024-04-05 18:16:19 +01:00
ea339355bb Merge branch 'minor-next' into stable 2024-04-05 17:30:59 +01:00
b9288c238b Update BedrockBlockUpgradeSchema 2024-04-05 17:29:16 +01:00
16f29c775e tools/generate-blockstate-upgrade-schema: added support for generating newFlattenedName with value transforms
as seen in pmmp/BedrockBlockUpgradeSchema@ebd768e5b2, this enables use of newFlattenedName in more places (by allowing the flattened values to be transformed before building the new ID), as well as reducing the number of remappedStates in general by compacting stuff which was partially transformed like color silver -> light_gray.
2024-04-05 17:13:38 +01:00
e30e27dd57 Fix CS 2024-04-03 15:43:43 +01:00
cd6634d34b Bump shivammathur/setup-php from 2.30.0 to 2.30.2 (#6315)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.30.0 to 2.30.2.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.30.0...2.30.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-03 15:37:13 +01:00
f013079ff6 Fixed MainLogger BC break 2024-04-03 15:31:37 +01:00
c4abac4606 Bump build/php from 6f619bf to f9601e5 (#6321)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `6f619bf` to `f9601e5`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](6f619bf7a0...f9601e5313)

---
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-04-03 14:03:46 +01:00
11fbc8db6f Make use of pmmpthread 6.1.0 for Thread::getRunningCount()
ThreadManager doesn't count these correctly anymore since pmmpthread since thread-safe statics aren't copied anymore.
2024-04-02 19:40:44 +01:00
022362a01a Update pocketmine/errorhandler to 0.7.0 2024-04-02 19:37:07 +01:00
98380e46bf Ignore non-fatal error types in crash handlers
ErrorToExceptionHandler currently prevents these from appearing by turning them into exceptions, but this won't always be the case.
For example, in the future we may not want to turn ALL types of E_* errors into exceptions (e.g. E_DEPRECATED).
2024-04-02 19:22:40 +01:00
dad9a7e6cd Merge branch 'stable' into minor-next 2024-04-02 16:35:31 +01:00
de6a91dabc Rework consistency check to tolerate dynamic type IDs
we don't actually care about the specific values, only whether all the blocks and their states have been correctly registered.
I'd prefer to track all of the state data permutations, but the APIs for that are private, so tracking the number of permutations will have to suffice (this should be good enough to detect bugs anyway, and also takes way less space).
2024-04-01 18:44:01 +01:00
0615afa766 Bump phpstan/phpstan from 1.10.65 to 1.10.66 (#6317)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.65 to 1.10.66.
- [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.65...1.10.66)

---
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-04-01 16:12:31 +01:00
d5919dc094 ... 2024-03-25 17:24:52 +00:00
09904dc519 workaround for callback-validator not understanding arrow functions 2024-03-25 14:58:21 +00:00
f799cfaba6 Implemented sound when equipping armor (#6303) 2024-03-25 14:15:54 +00:00
11f119551d Bump phpstan/phpstan from 1.10.62 to 1.10.65 (#6308)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.62 to 1.10.65.
- [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.62...1.10.65)

---
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-03-25 10:55:22 +00:00
2584314202 NetherRoots: fix placement on soul soil (#6299) 2024-03-25 10:53:16 +00:00
337e462c8f Added new banner patterns (#6298) 2024-03-25 10:52:21 +00:00
b680a1693c Added sound when picking sweet berries (#6287) 2024-03-19 10:18:30 +00:00
0e5395c59b PocketMine-MP.phar self-extraction to decompressed cache (#6217)
Because ext-phar sucks, tmp gets spammed by cache files for every thread when loading files from the phar on the fly.

Instead, we convert the `.phar` into a decompressed `.tar` in the tmp directory and require files from inside it. Surprisingly, this works because `ext-phar` supports `tar` and `zip` natively. No stream wrapper is required, as the `PocketMine.php` bootstrap loads files relative to its location, so the cache is automatically used for everything.

To be honest I would rather get rid of phars entirely, but they are still the easiest way to have PhpStorm load PocketMine-MP API information for now, and the alternatives are more complicated and inconvenient.

### Caveats
Everywhere that previously used `new Phar(Phar::running(false))` in the core code needs to be updated to use `PharData` for this to work correctly. Plugins don't need to do anything.

### Why not just use `Phar::decompressFiles()`?
This requires setting `phar.readonly` to `0`, which is a security issue. Technically, we could have used a subprocess to do this, but it just didn't seem right.

### WTF? `phar://` can be used on `tar` files???
Yup. I was just as surprised to find out that `require` works in such contexts.

### Relevant issues
- Closes #6214 

## Changes
### API changes
None.

### Behavioural changes
Server startup will be slightly slower, as the phar has to decompress and convert itself into a `.tar`. However, testing showed that this generally takes less than 200 ms, so it should be barely noticeable.

## Backwards compatibility
No BC issues.

## Tests
Locally tested and the CI will also verify
2024-03-18 16:48:17 +00:00
94e0bf954b Bump docker/build-push-action from 5.2.0 to 5.3.0 (#6288)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5.2.0...v5.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-18 15:08:13 +00:00
556b00d11f Bump phpstan/phpstan from 1.10.60 to 1.10.62 (#6289)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.60 to 1.10.62.
- [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.60...1.10.62)

---
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-03-18 15:06:50 +00:00
981f49ff56 CS 2024-03-15 18:03:44 +00:00
f527a4c8fe Added --no-log-file command line option
while this would be more user-friendly as a config option, configs are a pain because they aren't initialized until after the server log has already been set up.
In any case, I foresee that people will likely want to bake this into Dockerfiles directly anyway.
2024-03-15 17:53:50 +00:00
7148c7a222 Log rotate (#4032)
`server.log` is not rotated by default and grows unmanageably large, to the point where it's so huge that it's not possible to read it with any standard text editor anymore.

This PR implements automatic log rotation. 
- When the `server.log` reaches 32MB in size, it's moved to the `log_archive/` folder of the server's data folder.
- The archive's file name will look something like this: `server.2024-03-15T15.26.24.0.log`
- The file's name contains the date and time when the file was archived. This may be useful if you're trying to find logs from a particular time frame.

This has several benefits:
- Much more easily find logs from a particular time frame without scrolling through GBs of logs
- Free up space without stopping the server - Archived log files in `log_archive/` can be safely deleted and/or modified while the server is running

If you want to automatically compress or clean up the log files, I suggest an external cron job or disk watcher.

Closes #4029.
2024-03-15 16:44:37 +00:00
e31fd122d9 BlockStateReader: micro optimize unread properties check
this has a pretty much insignificant performance impact, but reduces the cost of this check to basically 0.
2024-03-14 17:54:26 +00:00
a835069564 Merge remote-tracking branch 'origin/stable' into minor-next 2024-03-14 12:47:04 +00:00
b77193b987 ZlibCompressor: Increase max decompression size to accommodate larger skins
again, very annoying that we have to account for this (it makes it easier for attackers to waste CPU time and memory), but we don't really have much of a choice.
2024-03-14 12:34:30 +00:00
11ca208d93 RakLib: Allow larger number of split packet parts
some persona skins are insanely bloated and get split into hundreds of parts.
it's quite annoying that we have to accommodate this, but we can't keep allowing players to experience login timeouts without an obvious indication what's wrong.
2024-03-14 12:32:26 +00:00
8d7f1a8557 BlockStateUpgraderTest: fixed tests for 7ff0ae19d6 2024-03-13 18:35:07 +00:00
7ff0ae19d6 BlockStateUpgrader: a simple yet hard-to-explain optimization
Prior to this commit, upgrade schemas would be applied to blockstates with the same version, as there wasn't any way to know if they should be applied or not given Mojang's tendency to forget to bump the version.
However, it occurred to me that we only need to do this if there are multiple schemas present for the same version ID, which is rarely the case.
This allows skipping costly logic for blockstates on the newest version (the common case), reducing the time taken to process the blockstate for upgrading by over 30%.
Overall, this translates into less than 10% real performance improvement for chunk loading, but it's still a worthwhile improvement.
2024-03-13 18:19:51 +00:00
1de66cb0de RegistryTrait: added fast path optimization
this reduces VanillaBlocks access time from 360 ns to 230 ns on my machine - an improvement of about 35%.
2024-03-13 17:11:06 +00:00
9f3533d870 Improved logging for block decode errors
this is still noisy, but less so than before.
this also adds logging to places where it was previously missing.
2024-03-13 16:42:23 +00:00
2d24fac067 5.13.1 is next 2024-03-13 14:59:21 +00:00
f193a990b0 Release 5.13.0 2024-03-13 14:59:21 +00:00
c11c0679e3 Fix CS 2024-03-13 14:55:54 +00:00
ba48f258f3 Support for 1.20.70 2024-03-13 14:53:27 +00:00
e105c9bd76 5.12.2 is next 2024-03-13 13:48:59 +00:00
23f4632409 Release 5.12.1 2024-03-13 13:48:56 +00:00
264ce06cbf Updated composer dependencies 2024-03-12 16:51:12 +00:00
a6202d0442 BlockStateUpgrader: calculate output version ID in a less stupid way
this improves the performance by a conservative 10%.
2024-03-12 11:48:48 +00:00
8ec304e66e BlockStateUpgradeSchema: avoid unnecessary property access and calculation
this was costing a surprisingly large 5-10% of the processing time for blockstate data.
2024-03-12 11:45:08 +00:00
cbffbd23f9 Bump docker/build-push-action from 5.1.0 to 5.2.0 (#6281)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.1.0 to 5.2.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5.1.0...v5.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 09:30:29 +00:00
9d7aec5891 Bump phpstan/phpstan from 1.10.59 to 1.10.60 (#6282)
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.59 to 1.10.60.
- [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.59...1.10.60)

---
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-03-12 09:30:03 +00:00
ac8dbf8640 BlockStateUpgrader: extract state remap to its own function 2024-03-06 12:56:49 +00:00
dbc7105e5b Merge branch 'resource-pack-ack-receipts' into minor-next 2024-03-04 15:46:31 +00:00
3b97d067a3 Merge remote-tracking branch 'origin/stable' into minor-next 2024-03-04 15:40:10 +00:00
b0390a39fd Update composer dependencies 2024-03-04 15:17:48 +00:00
5cb69e00d0 NetworkSession: remove hardcoded limit
this is already covered by the dynamic Game Packets rate limit, which is much more effective at dealing with this anyway.
2024-03-04 14:36:40 +00:00
781e3643dd Clean up 2024-03-04 14:25:47 +00:00
2ca50ecd36 Bump shivammathur/setup-php from 2.29.0 to 2.30.0 (#6273)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.29.0 to 2.30.0.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.29.0...2.30.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-03-04 11:54:53 +00:00
5ad63f27bb Update RakLib (again) 2024-03-02 01:02:57 +00:00
f13eaaab05 Update RakLib 2024-03-02 00:08:49 +00:00
72f3c0b4b9 NetworkSession: fixed timings not being stopped when handling uncompressed packets 2024-03-01 17:36:40 +00:00
b9a1ef1357 Throttle resource pack sending using ack receipts
this isn't the best solution, as it limits the download speed somewhat, but it's relatively simple and works quite well.
closes #3127
2024-03-01 17:07:19 +00:00
4abc36275c Remove newline 2024-03-01 17:02:44 +00:00
4b5ac53276 Fixes 2024-03-01 17:01:32 +00:00
90409b50d1 Allow offering different resource packs to different players (#6249)
closes #6248
2024-03-01 14:53:59 +00:00
bc2abf4b15 First shot at packet ack receipt support
this will be useful for preventing resource pack sending from overloading the network.
it's not the best solution for that (since it means the RTT will limit the pack download speed), but it's easier than implementing congestion control and will work fine in most cases.
2024-03-01 14:41:53 +00:00
b2c97cf2f1 5.12.1 is next 2024-02-28 18:14:41 +00:00
237 changed files with 7324 additions and 2441 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1 @@
* @pmmp/server-developers

View File

@ -7,13 +7,13 @@ assignees: ''
---
<!--- tell us what you want -->
## Description
<!--- Describe the problem you want to solve -->
## Problem description
<!--- explain why you want this and why it's a good idea -->
## Justification
<!--- Describe what changes you want to make to solve this problem -->
## Proposed solution
<!--- (optional) describe alternative methods you've explored to achieve your goal -->
## Alternative methods
## Alternative solutions that don't require API changes

View File

@ -3,9 +3,6 @@ contact_links:
- name: Help & support on Discord
url: https://discord.gg/bmSAZBG
about: We don't accept support requests on the issue tracker. Please try asking on Discord instead.
- name: Help & support on forums
url: https://forums.pmmp.io
about: We don't accept support requests on the issue tracker. Please try asking on forums instead.
- name: Documentation
url: https://pmmp.rtfd.io
about: PocketMine-MP documentation

View File

@ -1,43 +1,32 @@
## Introduction
<!-- Summarize your PR here. Keep it short and simple. -->
<!-- Explain existing problems or why this pull request is necessary -->
### Relevant issues
<!-- List relevant issues here -->
### Related issues & PRs
<!--
* Fixes #1
* Fixes #2
* Related to #2
-->
## Changes
### API changes
<!-- Any additions to the API that should be documented in release notes? -->
<!-- If not, you can delete this section -->
### Behavioural changes
<!-- Any change in how the server behaves, or its performance? -->
<!-- If not, you can delete this section -->
## Backwards compatibility
<!-- Any possible backwards incompatible changes? How are they solved, or how can they be solved? -->
<!-- If not, you can delete this section -->
## Follow-up
<!-- Suggest any actions to be done before/after merging this pull request -->
<!--
Requires translations:
| Name | Value in eng.ini |
| :--: | :---: |
| `foo.bar` | `Foo bar` |
-->
<!-- For example, future changes that this PR lays the groundwork for -->
## Tests
<!--
PRs which have not been tested MUST be marked as draft.
If this PR affects gameplay or user experience in some way, it must be manually tested.
Include any screenshots or videos of manual testing here.
Any test plugin code should also be pasted here if it can't be adapted to a PHPUnit test.
-->
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

@ -12,6 +12,22 @@ updates:
update-types:
- "version-update:semver-major"
- "version-update:semver-minor"
groups:
production-patch-updates:
dependency-type: production
patterns:
- "*"
update-types:
- "patch"
development-patch-updates:
dependency-type: development
patterns:
- "*"
update-types:
- "patch"
phpstan:
patterns:
- "phpstan/*"
- package-ecosystem: gitsubmodule
directory: "/"
@ -21,4 +37,7 @@ updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
interval: monthly
groups:
github-actions:
patterns: ["*"]

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.1.0
uses: docker/build-push-action@v6.10.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.1.0
uses: docker/build-push-action@v6.10.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.1.0
uses: docker/build-push-action@v6.10.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.1.0
uses: docker/build-push-action@v6.10.0
with:
push: true
context: ./pocketmine-mp

View File

@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v4
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.29.0
uses: shivammathur/setup-php@2.31.1
with:
php-version: 8.2

View File

@ -0,0 +1,65 @@
name: Draft release from PR
on:
#presume that pull_request_target is safe at this point, since the PR was approved and merged
#we need write access to prepare the release & create comments
pull_request_target:
types:
- closed
branches:
- stable
- minor-next
- major-next
- "legacy/*"
paths:
- "src/VersionInfo.php"
jobs:
check:
name: Check release
uses: ./.github/workflows/draft-release-pr-check.yml
draft:
name: Create GitHub draft release
needs: [check]
if: needs.check.outputs.valid == 'true'
uses: ./.github/workflows/draft-release.yml
post-draft-url-comment:
name: Post draft release URL as comment
needs: [draft]
runs-on: ubuntu-20.04
steps:
- name: Post draft release URL on PR
uses: thollander/actions-comment-pull-request@v3
with:
message: "[Draft release ${{ needs.draft.outputs.version }}](${{ needs.draft.outputs.draft-url }}) has been created for commit ${{ github.sha }}. Please review and publish it."
trigger-post-release-workflow:
name: Trigger post-release RestrictedActions workflow
# Not sure if needs is actually needed here
needs: [check]
if: needs.check.outputs.valid == 'true'
runs-on: ubuntu-20.04
steps:
- name: Generate access token
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.RESTRICTED_ACTIONS_DISPATCH_ID }}
private-key: ${{ secrets.RESTRICTED_ACTIONS_DISPATCH_KEY }}
owner: ${{ github.repository_owner }}
repositories: RestrictedActions
- name: Dispatch post-release restricted action
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ steps.generate-token.outputs.token }}
repository: ${{ github.repository_owner }}/RestrictedActions
event-type: pocketmine_mp_post_release
client-payload: '{"branch": "${{ github.ref }}"}'

View File

@ -0,0 +1,13 @@
#Allows creating a release by pushing a tag
#This might be useful for retroactive releases
name: Draft release from git tag
on:
push:
tags: "*"
jobs:
draft:
name: Create GitHub draft release
if: "startsWith(github.event.head_commit.message, 'Release ')"
uses: ./.github/workflows/draft-release.yml

View File

@ -0,0 +1,111 @@
name: Release PR checks
on:
#do checks on every PR update
pull_request:
branches:
- stable
- minor-next
- major-next
- "legacy/*"
paths:
- "src/VersionInfo.php"
#allow this workflow to be invoked on PR merge, prior to creating the release
workflow_call:
outputs:
valid:
description: Whether this commit is valid for release
value: ${{ jobs.check-intent.outputs.valid && jobs.check-validity.result == 'success' }}
permissions:
contents: read #for user access check
jobs:
check-intent:
name: Check release trigger
runs-on: ubuntu-20.04
outputs:
valid: ${{ steps.validate.outputs.DEV_BUILD == 'false' }}
steps:
- uses: actions/checkout@v4
- name: Check IS_DEVELOPMENT_BUILD flag
id: validate
run: |
echo DEV_BUILD=$(sed -n "s/^\s*public const IS_DEVELOPMENT_BUILD = \(true\|false\);$/\1/p" src/VersionInfo.php) >> $GITHUB_OUTPUT
check-validity:
name: Validate release info
needs: [check-intent]
#don't do these checks if this isn't a release - we don't want to generate unnecessary failed statuses
if: needs.check-intent.outputs.valid == 'true'
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@2.31.1
with:
php-version: 8.2
- name: Restore Composer package cache
uses: actions/cache@v4
with:
path: |
~/.cache/composer/files
~/.cache/composer/vcs
key: "composer-v2-cache-${{ hashFiles('./composer.lock') }}"
restore-keys: |
composer-v2-cache-
- name: Install Composer dependencies
run: composer install --no-dev --prefer-dist --no-interaction --ignore-platform-reqs
- name: Check author permissions
id: check-permission
uses: actions-cool/check-user-permission@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
require: write
username: ${{ github.event.pull_request.user.login }}
#technically this would be fine for dependabot but generally bots don't count as team members
check-bot: true
- name: Abort if user permissions are insufficient
#user doesn't have permission or is a bot
if: steps.check-permission.outputs.require-result != 'true' || steps.check-permission.outputs.check-result != 'false'
run: |
echo "::error::This user is not authorized to trigger releases"
exit 1
- name: Check changelog file is present
id: file-presence
run: |
CHANGELOG_FILE="changelogs/$(php build/dump-version-info.php changelog_file_name)"
if [ ! -f "${{ github.workspace }}/$CHANGELOG_FILE" ]; then
echo "::error::$CHANGELOG_FILE does not exist"
exit 1
fi
echo FILE="$CHANGELOG_FILE" >> $GITHUB_OUTPUT
- name: Check header is present in changelog file
run: |
FILE="${{ steps.file-presence.outputs.FILE }}"
VERSION="$(php build/dump-version-info.php base_version)"
if ! grep -Fqx "# $VERSION" "${{ github.workspace }}/$FILE"; then
echo "::error::Header for $VERSION not found in $FILE"
exit 1
fi
- name: Check version is valid for the selected channel
run: |
CHANNEL="$(php build/dump-version-info.php channel)"
if [ "$(php build/dump-version-info.php suffix_valid)" != "true" ]; then
echo "::error::Version $(php build/dump-version-info.php base_version) is not allowed on the $CHANNEL channel"
exit 1
fi

View File

@ -1,26 +1,36 @@
name: Draft release
on:
push:
tags: "*"
workflow_call:
outputs:
draft-url:
description: 'The URL of the draft release'
value: ${{ jobs.draft.outputs.draft-url }}
version:
description: 'PocketMine-MP version'
value: ${{ jobs.draft.outputs.version }}
jobs:
draft:
name: Create GitHub draft release
if: "startsWith(github.event.head_commit.message, 'Release ')"
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
php-version: [8.2]
outputs:
draft-url: ${{ steps.create-draft.outputs.html_url }}
version: ${{ steps.get-pm-version.outputs.PM_VERSION }}
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Setup PHP
uses: shivammathur/setup-php@2.29.0
uses: shivammathur/setup-php@2.31.1
with:
php-version: ${{ matrix.php-version }}
@ -53,17 +63,17 @@ jobs:
- name: Get PocketMine-MP release version
id: get-pm-version
run: |
echo PM_VERSION=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BASE_VERSION;') >> $GITHUB_OUTPUT
echo MCPE_VERSION=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\network\mcpe\protocol\ProtocolInfo::MINECRAFT_VERSION_NETWORK;') >> $GITHUB_OUTPUT
echo PM_VERSION_SHORT=$(php -r 'require "vendor/autoload.php"; $v = explode(".", \pocketmine\VersionInfo::BASE_VERSION); array_pop($v); echo implode(".", $v);') >> $GITHUB_OUTPUT
echo PM_VERSION_MD=$(php -r 'require "vendor/autoload.php"; echo str_replace(".", "", \pocketmine\VersionInfo::BASE_VERSION);') >> $GITHUB_OUTPUT
echo CHANGELOG_SUFFIX=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "" : "-" . \pocketmine\VersionInfo::BUILD_CHANNEL;') >> $GITHUB_OUTPUT
echo PRERELEASE=$(php -r 'require "vendor/autoload.php"; echo \pocketmine\VersionInfo::BUILD_CHANNEL === "stable" ? "false" : "true";') >> $GITHUB_OUTPUT
echo PM_VERSION=$(php build/dump-version-info.php base_version) >> $GITHUB_OUTPUT
echo PM_MAJOR=$(php build/dump-version-info.php major_version) >> $GITHUB_OUTPUT
echo MCPE_VERSION=$(php build/dump-version-info.php mcpe_version) >> $GITHUB_OUTPUT
echo CHANGELOG_FILE_NAME=$(php build/dump-version-info.php changelog_file_name) >> $GITHUB_OUTPUT
echo CHANGELOG_MD_HEADER=$(php build/dump-version-info.php changelog_md_header) >> $GITHUB_OUTPUT
echo PRERELEASE=$(php build/dump-version-info.php prerelease) >> $GITHUB_OUTPUT
- name: Generate PHP binary download URL
id: php-binary-url
run: |
echo PHP_BINARY_URL="${{ github.server_url }}/${{ github.repository_owner }}/PHP-Binaries/releases/tag/php-${{ matrix.php-version }}-latest" >> $GITHUB_OUTPUT
echo PHP_BINARY_URL="${{ github.server_url }}/${{ github.repository_owner }}/PHP-Binaries/releases/tag/pm${{ steps.get-pm-version.outputs.PM_MAJOR }}-php-${{ matrix.php-version }}-latest" >> $GITHUB_OUTPUT
- name: Generate build info
run: |
@ -76,6 +86,9 @@ jobs:
${{ steps.php-binary-url.outputs.PHP_BINARY_URL }} \
> build_info.json
- name: Generate core permission doc for doc.pmmp.io
run: php tools/generate-permission-doc.php rst
- name: Upload release artifacts
uses: actions/upload-artifact@v4
with:
@ -84,20 +97,23 @@ jobs:
${{ github.workspace }}/PocketMine-MP.phar
${{ github.workspace }}/start.*
${{ github.workspace }}/build_info.json
${{ github.workspace }}/core-permissions.rst
- name: Create draft release
uses: ncipollo/release-action@v1.14.0
id: create-draft
with:
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json,${{ github.workspace }}/core-permissions.rst
commit: ${{ github.sha }}
draft: true
prerelease: ${{ steps.get-pm-version.outputs.PRERELEASE }}
name: PocketMine-MP ${{ steps.get-pm-version.outputs.PM_VERSION }}
tag: ${{ steps.get-pm-version.outputs.PM_VERSION }}
token: ${{ secrets.GITHUB_TOKEN }}
skipIfReleaseExists: true #for release PRs, tags will be created on release publish and trigger the tag release workflow - don't create a second draft
body: |
**For Minecraft: Bedrock Edition ${{ steps.get-pm-version.outputs.MCPE_VERSION }}**
Please see the [changelogs](${{ github.server_url }}/${{ github.repository }}/blob/${{ steps.get-pm-version.outputs.PM_VERSION }}/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}${{ steps.get-pm-version.outputs.CHANGELOG_SUFFIX }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
Please see the [changelogs](${{ github.server_url }}/${{ github.repository }}/blob/${{ steps.get-pm-version.outputs.PM_VERSION }}/changelogs/${{ steps.get-pm-version.outputs.CHANGELOG_FILE_NAME }}#${{ steps.get-pm-version.outputs.CHANGELOG_MD_HEADER }}) for details.
:information_source: Download the recommended PHP binary [here](${{ steps.php-binary-url.outputs.PHP_BINARY_URL }}).

View File

@ -30,7 +30,7 @@ jobs:
- uses: actions/checkout@v4
- name: Setup PHP
uses: pmmp/setup-php-action@3.1.0
uses: pmmp/setup-php-action@3.2.0
with:
php-version: ${{ inputs.php }}
install-path: "./bin"
@ -62,7 +62,7 @@ jobs:
- uses: actions/checkout@v4
- name: Setup PHP
uses: pmmp/setup-php-action@3.1.0
uses: pmmp/setup-php-action@3.2.0
with:
php-version: ${{ inputs.php }}
install-path: "./bin"
@ -96,7 +96,7 @@ jobs:
submodules: true
- name: Setup PHP
uses: pmmp/setup-php-action@3.1.0
uses: pmmp/setup-php-action@3.2.0
with:
php-version: ${{ inputs.php }}
install-path: "./bin"
@ -128,7 +128,7 @@ jobs:
- uses: actions/checkout@v4
- name: Setup PHP
uses: pmmp/setup-php-action@3.1.0
uses: pmmp/setup-php-action@3.2.0
with:
php-version: ${{ inputs.php }}
install-path: "./bin"
@ -147,17 +147,8 @@ jobs:
- 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: Update generated code
run: composer update-codegen
- name: Verify code is unchanged
run: |

View File

@ -28,7 +28,7 @@ jobs:
- uses: actions/checkout@v4
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.29.0
uses: shivammathur/setup-php@2.31.1
with:
php-version: 8.2
tools: php-cs-fixer:3.49
@ -37,3 +37,15 @@ jobs:
- name: Run PHP-CS-Fixer
run: php-cs-fixer fix --dry-run --diff --ansi
shellcheck:
name: ShellCheck
runs-on: ubuntu-20.04
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Run ShellCheck
uses: ludeeus/action-shellcheck@2.0.0

View File

@ -0,0 +1,33 @@
name: Remove waiting label from PRs
on:
pull_request_target:
types: synchronize
jobs:
delabel:
name: Remove label
runs-on: ubuntu-latest
steps:
- name: Remove label
uses: actions/github-script@v7
with:
github-token: ${{ github.token }}
script: |
const [owner, repo] = context.payload.repository.full_name.split('/');
try {
await github.rest.issues.removeLabel({
owner: owner,
repo: repo,
issue_number: context.payload.number,
name: "Status: Waiting on Author",
});
} catch (error) {
if (error.status === 404) {
//probably label wasn't set on the issue
console.log('Failed to remove label (probably label isn\'t on the PR): ' + error.message);
} else {
throw error;
}
}

View File

@ -0,0 +1,38 @@
#Due to GitHub awkwardness, it's not easy to reduce the review requirement for collaborators.
#Our policy is that 2 collaborators should be aware of every change.
#For outside PRs, this means 2 collaborator reviews.
#For PRs made by collaborators, this means 1 reviewer + the author.
#We trust that collaborators don't need as much oversight.
name: Auto approve collaborator PRs
on:
pull_request_target:
types:
- opened
- reopened
- ready_for_review
- synchronize
jobs:
dispatch:
name: Request approval
runs-on: ubuntu-latest
if: '! github.event.pull_request.draft'
steps:
- name: Generate access token
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ vars.RESTRICTED_ACTIONS_DISPATCH_ID }}
private-key: ${{ secrets.RESTRICTED_ACTIONS_DISPATCH_KEY }}
owner: ${{ github.repository_owner }}
repositories: RestrictedActions
- name: Dispatch restricted action
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ steps.generate-token.outputs.token }}
repository: ${{ github.repository_owner }}/RestrictedActions
event-type: auto_approve_collaborator_pr
client-payload: '{"repo": "${{ github.repository }}", "pull_request_id": "${{ github.event.pull_request.number }}", "reviewer_id": "0" }'

3
.gitignore vendored
View File

@ -53,3 +53,6 @@ Documentation/*
# php-cs-fixer
/.php_cs.cache
/.php-cs-fixer.cache
# install-local-protocol.sh
/composer-local-protocol.*

View File

@ -123,7 +123,7 @@ The following are required as a minimum for pull requests. PRs that don't meet t
- Remember, PRs with small diffs are much easier to review. Small PRs are generally reviewed and merged much faster than large ones.
- **Start small.** Try fixing minor bugs or doing something isolated (e.g. adding a new block or item) before attempting larger changes.
- This helps you get familiar with the codebase, the contribution process, and the expectations of maintainers.
- Check out the [issues page]() for something that you could tackle without too much effort.
- Check out ["Easy task" issues](https://github.com/pmmp/PocketMine-MP/issues?q=is%3Aissue+is%3Aopen+label%3A%22Easy+task%22) on the issues page for something that you could tackle without too much effort.
- **Do not copy-paste other people's code**. Many PRs involve discussion about the changes, and changes are often requested by reviewers. If you don't understand the code you're copy-pasting, your PR is likely to fail.
- **Do not edit code directly on github.com.** We recommend learning how to use [`git`](https://git-scm.com). `git` allows you to "clone" a repository onto your computer, so that you can make changes using an IDE.
- **Use an IDE, not a text editor.** We recommend PhpStorm or VSCode.

View File

@ -0,0 +1,87 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\VersionInfo;
require dirname(__DIR__) . '/vendor/autoload.php';
/*
* Dumps version info in a machine-readable format for use in GitHub Actions workflows
*/
/**
* @var string[]|\Closure[] $options
* @phpstan-var array<string, string|\Closure() : string> $options
*/
$options = [
"base_version" => VersionInfo::BASE_VERSION,
"major_version" => fn() => explode(".", VersionInfo::BASE_VERSION)[0],
"mcpe_version" => ProtocolInfo::MINECRAFT_VERSION_NETWORK,
"is_dev" => VersionInfo::IS_DEVELOPMENT_BUILD,
"changelog_file_name" => function() : string{
$version = VersionInfo::VERSION();
$result = $version->getMajor() . "." . $version->getMinor();
$suffix = $version->getSuffix();
if($suffix !== ""){
if(preg_match('/^([A-Za-z]+)(\d+)$/', $suffix, $matches) !== 1){
fwrite(STDERR, "error: invalid current version suffix \"$suffix\"; aborting" . PHP_EOL);
exit(1);
}
$baseSuffix = $matches[1];
$result .= "-" . strtolower($baseSuffix);
}
return $result . ".md";
},
"changelog_md_header" => fn() : string => str_replace(".", "", VersionInfo::BASE_VERSION),
"prerelease" => fn() : bool => VersionInfo::VERSION()->getSuffix() !== "",
"channel" => VersionInfo::BUILD_CHANNEL,
"suffix_valid" => function() : bool{
//TODO: maybe this should be put into its own script?
$suffix = VersionInfo::VERSION()->getSuffix();
if(VersionInfo::BUILD_CHANNEL === "stable"){
//stable builds may not have suffixes
return $suffix === "";
}
if(VersionInfo::BUILD_CHANNEL === "alpha" || VersionInfo::BUILD_CHANNEL === "beta"){
$upperChannel = strtoupper(VersionInfo::BUILD_CHANNEL);
$upperSuffix = strtoupper($suffix);
return str_starts_with($upperSuffix, $upperChannel) && is_numeric(substr($upperSuffix, strlen($upperChannel)));
}
return true;
}
];
if(count($argv) !== 2 || !isset($options[$argv[1]])){
fwrite(STDERR, "Please provide an option (one of: " . implode(", ", array_keys($options)) . PHP_EOL);
exit(1);
}
$result = $options[$argv[1]];
if($result instanceof Closure){
$result = $result();
}
if(is_bool($result)){
echo $result ? "true" : "false";
}else{
echo $result;
}

View File

@ -122,7 +122,7 @@ if(!is_array($ids)){
throw new \RuntimeException("Invalid biome ID map, expected array for root JSON object");
}
$cleanedIds = [];
foreach($ids as $name => $id){
foreach(Utils::promoteKeys($ids) as $name => $id){
if(!is_string($name) || !is_int($id)){
throw new \RuntimeException("Invalid biome ID map, expected string => int map");
}

View File

@ -102,6 +102,25 @@ function generateClassHeader(string $className) : string{
return <<<HEADER
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace $namespace;

View File

@ -61,6 +61,25 @@ function generateItemIds(ItemTypeDictionary $dictionary, BlockItemIdMap $blockIt
fwrite($file, <<<'HEADER'
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\data\bedrock\item;

View File

@ -42,7 +42,7 @@ $constants = [];
* @phpstan-param-out array<string, string> $constants
*/
function collectProperties(string $prefix, array $properties, array &$constants) : void{
foreach($properties as $propertyName => $property){
foreach(Utils::promoteKeys($properties) as $propertyName => $property){
$fullPropertyName = ($prefix !== "" ? $prefix . "." : "") . $propertyName;
$constName = str_replace([".", "-"], "_", strtoupper($fullPropertyName));

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\build\update_registry_annotations;
use pocketmine\utils\Utils;
use function basename;
use function class_exists;
use function count;
@ -48,6 +49,7 @@ if(count($argv) !== 2){
/**
* @param object[] $members
* @phpstan-param array<string, object> $members
*/
function generateMethodAnnotations(string $namespaceName, array $members) : string{
$selfName = basename(__FILE__);
@ -60,7 +62,7 @@ function generateMethodAnnotations(string $namespaceName, array $members) : stri
static $lineTmpl = " * @method static %2\$s %s()";
$memberLines = [];
foreach($members as $name => $member){
foreach(Utils::stringifyKeys($members) as $name => $member){
$reflect = new \ReflectionClass($member);
while($reflect !== false && $reflect->isAnonymous()){
$reflect = $reflect->getParentClass();

View File

@ -86,7 +86,8 @@ function systemWrapper(string $command, string $errorMessage) : void{
function main() : void{
$filteredOpts = [];
foreach(Utils::stringifyKeys(getopt("", ["current:", "next:", "channel:", "help"])) as $optName => $optValue){
$postCommitOnly = false;
foreach(Utils::stringifyKeys(getopt("", ["current:", "next:", "channel:", "help", "post"])) as $optName => $optValue){
if($optName === "help"){
fwrite(STDOUT, "Options:\n");
@ -96,6 +97,10 @@ function main() : void{
}
exit(0);
}
if($optName === "post"){
$postCommitOnly = true;
continue;
}
if(!is_string($optValue)){
fwrite(STDERR, "--$optName expects exactly 1 value\n");
exit(1);
@ -141,20 +146,25 @@ function main() : void{
$channel ??= "stable";
}
echo "About to tag version $currentVer. Next version will be $nextVer.\n";
echo "$currentVer will be published on release channel \"$channel\".\n";
echo "please add appropriate notes to the changelog and press enter...";
fgets(STDIN);
systemWrapper('git add "' . dirname(__DIR__) . '/changelogs"', "failed to stage changelog changes");
system('git diff --cached --quiet "' . dirname(__DIR__) . '/changelogs"', $result);
if($result === 0){
echo "error: no changelog changes detected; aborting\n";
exit(1);
}
$versionInfoPath = dirname(__DIR__) . '/src/VersionInfo.php';
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false, $channel);
systemWrapper('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"', "failed to create release commit");
systemWrapper('git tag ' . $currentVer->getBaseVersion(), "failed to create release tag");
if($postCommitOnly){
echo "Skipping release commit & tag. Bumping to next version $nextVer directly.\n";
}else{
echo "About to tag version $currentVer. Next version will be $nextVer.\n";
echo "$currentVer will be published on release channel \"$channel\".\n";
echo "please add appropriate notes to the changelog and press enter...";
fgets(STDIN);
systemWrapper('git add "' . dirname(__DIR__) . '/changelogs"', "failed to stage changelog changes");
system('git diff --cached --quiet "' . dirname(__DIR__) . '/changelogs"', $result);
if($result === 0){
echo "error: no changelog changes detected; aborting\n";
exit(1);
}
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false, $channel);
systemWrapper('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"', "failed to create release commit");
systemWrapper('git tag ' . $currentVer->getBaseVersion(), "failed to create release tag");
}
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true, $channel);
systemWrapper('git add "' . $versionInfoPath . '"', "failed to stage changes for post-release commit");

168
build/server-phar-stub.php Normal file
View File

@ -0,0 +1,168 @@
<?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\server_phar_stub;
use function clearstatcache;
use function copy;
use function fclose;
use function fflush;
use function flock;
use function fopen;
use function fwrite;
use function getmypid;
use function hrtime;
use function is_dir;
use function is_file;
use function mkdir;
use function number_format;
use function str_replace;
use function stream_get_contents;
use function sys_get_temp_dir;
use function tempnam;
use function unlink;
use const DIRECTORY_SEPARATOR;
use const LOCK_EX;
use const LOCK_NB;
use const LOCK_UN;
/**
* Finds the appropriate tmp directory to store the decompressed phar cache, accounting for potential file name
* collisions.
*/
function preparePharCacheDirectory() : string{
clearstatcache();
$i = 0;
do{
$tmpPath = sys_get_temp_dir() . '/PocketMine-MP-phar-cache.' . $i;
$i++;
}while(is_file($tmpPath));
if(!@mkdir($tmpPath) && !is_dir($tmpPath)){
throw new \RuntimeException("Failed to create temporary directory $tmpPath. Please ensure the disk has enough space and that the current user has permission to write to this location.");
}
return $tmpPath;
}
/**
* Deletes caches left behind by previous server instances.
* This ensures that the tmp directory doesn't get flooded by servers crashing in restart loops.
*/
function cleanupPharCache(string $tmpPath) : void{
clearstatcache();
/** @var string[] $matches */
foreach(new \RegexIterator(
new \FilesystemIterator(
$tmpPath,
\FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS
),
'/(.+)\.lock$/',
\RegexIterator::GET_MATCH
) as $matches){
$lockFilePath = $matches[0];
$baseTmpPath = $matches[1];
$file = @fopen($lockFilePath, "rb");
if($file === false){
//another process probably deleted the lock file already
continue;
}
if(flock($file, LOCK_EX | LOCK_NB)){
//this tmpfile is no longer in use
flock($file, LOCK_UN);
fclose($file);
unlink($lockFilePath);
unlink($baseTmpPath . ".tar");
unlink($baseTmpPath);
echo "Deleted stale phar cache at $baseTmpPath\n";
}else{
$pid = stream_get_contents($file);
fclose($file);
echo "Phar cache at $baseTmpPath is still in use by PID $pid\n";
}
}
}
function convertPharToTar(string $tmpName, string $pharPath) : string{
$tmpPharPath = $tmpName . ".phar";
copy($pharPath, $tmpPharPath);
$phar = new \Phar($tmpPharPath);
//phar requires phar.readonly=0, and zip doesn't support disabling compression - tar is the only viable option
//we don't need phar anyway since we don't need to directly execute the file, only require files from inside it
$phar->convertToData(\Phar::TAR, \Phar::NONE);
unset($phar);
\Phar::unlinkArchive($tmpPharPath);
return $tmpName . ".tar";
}
/**
* Locks a phar tmp cache to prevent it from being deleted by other server instances.
* This code looks similar to Filesystem::createLockFile(), but we can't use that because it's inside the compressed
* phar.
*/
function lockPharCache(string $lockFilePath) : void{
//this static variable will keep the file(s) locked until the process ends
static $lockFiles = [];
$lockFile = fopen($lockFilePath, "wb");
if($lockFile === false){
throw new \RuntimeException("Failed to open temporary file");
}
flock($lockFile, LOCK_EX); //this tells other server instances not to delete this cache file
fwrite($lockFile, (string) getmypid()); //maybe useful for debugging
fflush($lockFile);
$lockFiles[$lockFilePath] = $lockFile;
}
/**
* Prepares a decompressed .tar of PocketMine-MP.phar in the system temp directory for loading code from.
*
* @return string path to the temporary decompressed phar (actually a .tar)
*/
function preparePharCache(string $tmpPath, string $pharPath) : string{
clearstatcache();
$tmpName = tempnam($tmpPath, "PMMP");
if($tmpName === false){
throw new \RuntimeException("Failed to create temporary file");
}
lockPharCache($tmpName . ".lock");
return convertPharToTar($tmpName, $pharPath);
}
$tmpDir = preparePharCacheDirectory();
cleanupPharCache($tmpDir);
echo "Preparing PocketMine-MP.phar decompressed cache...\n";
$start = hrtime(true);
$cacheName = preparePharCache($tmpDir, __FILE__);
echo "Cache ready at $cacheName in " . number_format((hrtime(true) - $start) / 1e9, 2) . "s\n";
require 'phar://' . str_replace(DIRECTORY_SEPARATOR, '/', $cacheName) . '/src/PocketMine.php';

View File

@ -23,7 +23,9 @@ declare(strict_types=1);
namespace pocketmine\build\server_phar;
use pocketmine\utils\Filesystem;
use pocketmine\utils\Git;
use Symfony\Component\Filesystem\Path;
use function array_map;
use function count;
use function dirname;
@ -169,21 +171,7 @@ function main() : void{
'git' => $gitHash,
'build' => $build
],
<<<'STUB'
<?php
$tmpDir = sys_get_temp_dir();
if(!is_readable($tmpDir) or !is_writable($tmpDir)){
echo "ERROR: tmpdir $tmpDir is not accessible." . PHP_EOL;
echo "Check that the directory exists, and that the current user has read/write permissions for it." . PHP_EOL;
echo "Alternatively, set 'sys_temp_dir' to a different directory in your php.ini file." . PHP_EOL;
exit(1);
}
require("phar://" . __FILE__ . "/src/PocketMine.php");
__HALT_COMPILER();
STUB
,
Filesystem::fileGetContents(Path::join(__DIR__, 'server-phar-stub.php')) . "\n__HALT_COMPILER();",
\Phar::SHA1,
\Phar::GZ
) as $line){

View File

@ -52,3 +52,12 @@ Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if
- 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.
# 5.12.1
Released 13th March 2024.
## Fixes
- Fixed `Player Network Receive - Decompression` timings not being stopped correctly when receiving an uncompressed packet.
## Internals
- Removed hardcoded batch packet size limit. This was already covered by other limits anyway.

16
changelogs/5.13.md Normal file
View File

@ -0,0 +1,16 @@
# 5.13.0
Released 13th March 2024.
**For Minecraft: Bedrock Edition 1.20.70**
This is a support release for Minecraft: Bedrock Edition 1.20.70.
**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.70.
- Removed support for earlier versions.

94
changelogs/5.14.md Normal file
View File

@ -0,0 +1,94 @@
# 5.14.0
Released 5th April 2024.
**For Minecraft: Bedrock Edition 1.20.70**
This is a minor feature release, including performance improvements, minor gameplay features, new API features, and various internal 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 support for a `--no-log-file` command-line option, which disables the creation of a `server.log` file.
- **Use this with caution.** If you don't have another mechanism for collecting logs (e.g. Docker), this may make debugging harder.
- Added support for automatic `server.log` rotation. When the `server.log` exceeds 32 MB, it will be renamed and moved to the `log_archive` folder in the server's data directory.
- Files in the `log_archive` folder can be safely modified or deleted without stopping the server.
- We suggest a cron job or similar to manage old log files (e.g. deleting or compressing them).
- Added a new cache mechanism for `PocketMine-MP.phar`. This has several advantages:
- Caches are now reused by all threads - this significantly reduces `/tmp` usage (previously every thread generated its own cache, wasting lots of space)
- Dead cache files are automatically cleaned up by new servers - this means that a server crash loop won't flood `/tmp` anymore
- `/status` now reports a more accurate number of threads on Windows.
- Large resource packs are now able to be properly downloaded from the server.
- Larger player skin sizes are now accepted by the server.
- Improved logging from world providers to reduce spam when chunks contain invalid data.
- Added more error logging for Anvil, PMAnvil and MCRegion worlds.
- PHP deprecation warnings no longer cause the server to crash. This should make it easier for server owners to update to newer PHP versions.
## Performance
- Improved world loading performance. This was achieved through a combination of changes:
- Improvements to `BlockStateUpgrader` to avoid unnecessary work
- Improvements to `BlockStateUpgradeSchema` to clean up stupid code
- Improvements to `BlockStateReader` unused state handling
- Optimizations to `RegistryTrait` (see below)
- Improved performance of `RegistryTrait::__callStatic()` accessor by introducing a fast-path optimization. Ensure that you access registries with the correct function name case to benefit from this.
- This improves the performance of `VanillaBlocks::WHATEVER()`, `VanillaItems`, etc.
## Tools
- `tools/generate-blockstate-upgrade-schema.php` now supports generating schemas using `flattenedValueRemaps` (described in [BlockStateUpgradeSchema](https://github.com/pmmp/BedrockBlockUpgradeSchema/releases/tag/4.0.0)).
## Gameplay
- Added sounds for armour equipping and unequipping.
- Added sound for picking berries from a sweet berry bush.
## API
### `pocketmine\block\utils`
- The following enum cases have been added:
- `BannerPatternType::GLOBE`
- `BannerPatternType::PIGLIN`
### `pocketmine\event\player`
- The following classes have been added:
- `PlayerResourcePackOfferEvent` - called before the server tells a connecting client which resource packs are available to download - allows customizing the pack list and other options
### `pocketmine\item`
- The following API methods have been added:
- `public ArmorMaterial->getEquipSound() : ?\pocketmine\world\Sound` - returns the sound to play when this armour is equipped or unequipped
- The following API methods have signature changes:
- `ArmorMaterial->__construct()` now accepts an optional `?Sound $equipSound` parameter
### `pocketmine\utils`
- The following API methods have signature changes:
- `MainLogger->__construct()` now accepts `null` for the `$logFile` parameter - this disables the creation of a logger thread and log file
- `MainLogger->__construct()` now accepts an optional `?string $logArchiveDir` parameter. If set, this enables log archiving in the specified directory when the current log file exceeds 32 MB.
## Dependencies
- Now uses [`pocketmine/bedrock-block-upgrade-schema` version 4.0.0](https://github.com/pmmp/BedrockBlockUpgradeSchema/releases/tag/4.0.0).
- Now uses [`pmmp/ext-pmmpthread` version 6.1.0](https://github.com/pmmp/ext-pmmpthread/releases/tag/6.1.0).
- Now uses [`pocketmine/errorhandler` version 0.7.0](https://github.com/pmmp/ErrorHandler/releases/tag/0.7.0).
- Now uses [`pocketmine/raklib` version 1.1.0](https://github.com/pmmp/RakLib/releases/tag/1.1.0).
- Now uses [`pocketmine/raklib-ipc` version 1.0.0](https://github.com/pmmp/RakLibIpc/releases/tag/1.0.0).
## Internals
- (Re)Added support for RakLib packet ACK receipts. This was used to throttle resource pack sending and prevent network overloading.
- Added `NetworkSession->sendDataPacketWithReceipt()` to make use of this feature.
- `PacketSender` now requires an additional `?int $receiptId` parameter.
- `ResourcePackPacketHandler` now uses `sendDataPacketWithReceipt()` to send resource packs, and delays sending the next chunk until the current one is acknowledged.
- `ResourcePackPacketHandler` now accepts resource pack info directly in the constructor, instead of `ResourcePackManager`. This eases the implementation of `PlayerResourcePackOfferEvent`.
- Increased `ZlibCompressor::DEFAULT_MAX_DECOMPRESSION_SIZE` to 8 MB (previously 2 MB). While this weakens server security, it appears to be necessary to deal with extremely bloated Persona skins.
- Increased max split packet parts accepted by `RakLib` to 512 (previously 128). Again, this is necessary to deal with extremely bloated Persona skins.
- Added a new cache mechanism for `PocketMine-MP.phar`.
- `ext-phar`'s default mechanism is extremely wasteful (generating a separate cache file per thread), and doesn't clean up after itself.
- The new cache mechanism is shared between all threads, and automatically cleans up stale caches.
- The phar stub (`build/server-phar-stub.php`) now converts the phar contents into a `.tar`, and decompresses all the files into `$TMPDIR/PocketMine-MP-phar-cache.<random>/`.
- `phar://` URIs still work with this system, but `new Phar(__FILE__)` must be replaced by `new PharData(__FILE__)` within PocketMine-MP core code.
- Backtraces from a `phar`'d server will now point to a location in the extracted phar cache, rather than the phar itself.
- `block_factory_consistency_check` test (actually for `RuntimeBlockStateRegistry`) now stores less data, and is no longer affected by changes to internal state ID construction.
# 5.14.1
Released 5th April 2024.
## Fixes
- Fixed incorrect `pmmpthread` version check in server bootstrap.

16
changelogs/5.15.md Normal file
View File

@ -0,0 +1,16 @@
# 5.15.0
Released 25th April 2024.
**For Minecraft: Bedrock Edition 1.20.80**
This is a support release for Minecraft: Bedrock Edition 1.20.80.
**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.80.
- Removed support for earlier versions.

26
changelogs/5.16.md Normal file
View File

@ -0,0 +1,26 @@
# 5.16.0
Released 13th June 2024.
**For Minecraft: Bedrock Edition 1.21.0**
This is a support release for Minecraft: Bedrock Edition 1.21.0.
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## General
- Added support for Minecraft: Bedrock Edition 1.21.0.
- Removed support for earlier versions.
- Generated permission docs are now included with every release.
- Crash throttle message (which appears when the server crashed after being up for less than 120 seconds) now shows the server uptime as well as the wait time. This should make it clearer how the wait time is decided.
## Tools
- Added `install-local-protocol.sh` script. This allows installing local copies of protocol dependencies without needing to create releases. Useful for integration testing when doing protocol updates.
## Fixes
- Attacking an entity with a higher damage weapon while it's on attack cooldown from a lower damage weapon (switching) no longer causes additional knockback to the victim.
- Wooden stairs can now be used as fuel in furnaces.
- Fixed incorrect description of the permission `pocketmine.command.save.perform`.

38
changelogs/5.17.md Normal file
View File

@ -0,0 +1,38 @@
# 5.17.0
Released 10th July 2024.
**For Minecraft: Bedrock Edition 1.21.2**
This is a support release for Minecraft: Bedrock Edition 1.21.2.
**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.21.2.
- Removed support for earlier versions.
## API
### `pocketmine\player`
- The following methods have been added:
- `public function closeAllForms() : void` - closes the current viewing form and forms in queue.
## Fixes
- Bowl can now be used as fuel.
- Bells always drops themselves even when using an incompatible tool.
# 5.17.1
Released 13th August 2024.
## Documentation
- Added a note about `BlockStateData::CURRENT_VERSION`.
## Fixes
- Fixed anvil placement rotation to match vanilla.
- Fixed outdated `BedrockWorldData` version, this was preventing use newer worlds.
## Internals
- Dependabot: PHPStan and patch updates are now grouped into a single PR.

30
changelogs/5.18.md Normal file
View File

@ -0,0 +1,30 @@
# 5.18.0
Released 16th August 2024.
**For Minecraft: Bedrock Edition 1.21.20**
This is a support release for Minecraft: Bedrock Edition 1.21.20.
**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.21.20.
- Removed support for earlier versions.
## Fixes
- Use `VISIBLE_MOB_EFFECTS` actor metadata property to send effect bubbles, this fixes effect bubbles not showing
# 5.18.1
Released 3rd September 2024.
## Fixes
- Fixed shift-crafting.
- Blue Ice block no longer emits light & it's now dropped when mined with a tool with silk touch enchantment.
## Internals
- Pull Requests from team members now get an approval automatically. This means that if a team member makes a PR, only one other approval should be needed.
- Added [ShellCheck](https://github.com/koalaman/shellcheck) to the CI tests.

16
changelogs/5.19.md Normal file
View File

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

25
changelogs/5.20.md Normal file
View File

@ -0,0 +1,25 @@
# 5.20.0
Released 26th October 2024.
**For Minecraft: Bedrock Edition 1.21.40**
This is a support release for Minecraft: Bedrock Edition 1.21.40.
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## General
- Added support for Minecraft: Bedrock Edition 1.21.40.
- Removed support for earlier versions.
## Fixes
- Fixed a bug in `tools/generate-blockstate-upgrade-schema.php` that caused it to fail on 1.21.40 with the new mushroom block changes.
# 5.20.1
Released 31st October 2024.
## Fixes
- Workaround old mob heads in world saves not being upgraded correctly and causing crashes.

128
changelogs/5.21.md Normal file
View File

@ -0,0 +1,128 @@
# 5.21.0
Released 3rd November 2024.
This is a minor feature release, including gameplay features and minor internals 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.
## Gameplay
- Added the following new blocks:
- Campfire
- Chiseled Copper
- Chiseled Tuff
- Chiseled Tuff Bricks
- Copper Bulb
- Copper Door
- Copper Grate
- Copper Trapdoor
- Polished Tuff, Slabs, Stairs and Walls
- Soul Campfire
- Tuff Bricks, Slabs, Stairs and Walls
- Tuff Slab, Stairs and Walls
- Added the following new types of painting:
- backyard
- baroque
- bouquet
- cavebird
- changing
- cotan
- endboss
- fern
- finding
- humble
- lowmist
- meditative
- orb
- owlemons
- passage
- pond
- prairie_ride
- sunflowers
- tides
- unpacked
- Armor slots are now properly restricted (on the server side) to only contain the appropriate type of armor or headwear.
- Implemented Aqua Affinity enchantment. Since the server doesn't currently enforce any movement restrictions in water, this enchantment works based on client-side behaviour only.
## API
### `pocketmine\block`
- The following new API methods have been added:
- `public ChiseledBookshelf->getLastInteractedSlot() : ?ChiseledBookshelfSlot`
- `public ChiseledBookshelf->setLastInteractedSlot(?ChiseledBookshelfSlot $lastInteractedSlot) : $this`
- The following new classes have been added:
- `utils\CopperMaterial` - interface implemented by all copper-like blocks with oxidation and waxed properties
- `CopperBulb`
- `CopperDoor`
- `CopperGrate`
- `CopperTrapdoor`
- `SoulCampfire`
- `Campfire`
- The following enums have new cases:
- `utils\BannerPatternType` has new cases `FLOW` and `GUSTER`
### `pocketmine\crafting`
- The following enums have new cases:
- `FurnaceType` has new cases `CAMPFIRE` and `SOUL_CAMPFIRE`
### `pocketmine\event`
- The following new classes have been added:
- `block\CampfireCookEvent` - called when a campfire finishes cooking an item
### `pocketmine\inventory`
- Added support for slot validators, which permit restricting the types of items a player can put into an inventory slot.
- The following new classes have been added:
- `transaction\action\SlotValidator` - interface
- `transaction\action\CallbackSlotValidator` - class allowing a closure to be used for slot content validation
- `SlotValidatedInventory` - implemented by inventories which support the use of slot validators
### `pocketmine\item`
- The following new API methods have been added:
- `public Item->getCooldownTag() : ?string` - returns the cooldown group this item belongs to, used for ensuring that, for example, different types of goat horns all respect a general horn cooldown
- The following new classes have been added:
- `ItemCooldownTags` - list of cooldown group tags used by PocketMine-MP
### `pocketmine\world\sound`
- The following new classes have been added
- `CampfireSound` - sound made by campfires while lit
## Tools
- `tools/blockstate-upgrade-schema-utils.php` (formerly `generate-blockstate-upgrade-schema.php`) has several improvements:
- Support for generating `flattenedProperties` rules as per [BedrockBlockUpgradeSchema 5.0.0](https://github.com/pmmp/BedrockBlockUpgradeSchema/releases/tag/5.0.0)
- Improved criteria for flattened property selection to minimize the amount of rules required
- Several subcommands are now available:
- `generate` - generates a schema from provided data
- `update` - regenerates an existing schema in a newer format
- `update-all` - regenerates a folder of existing schemas in a newer format (useful for updating `BedrockBlockUpgradeSchema` en masse)
- `test` - verifies that a schema produces the results expected by provided data
## Internals
- Fixed incorrect visibility of `createEntity` in spawn eggs.
- Added support for newer `BedrockBlockUpgradeSchema` in `BlockStateUpgrader`.
# 5.21.1
Released 12th November 2024.
## Fixes
- Fixed server crash when applying a cooldown to an item with 1 count.
- Fixed garbage collector cycle count increase on player disconnect.
- Fixed weakness effect being applied to all attack types, causing damage splash potions to become weaker.
- Fixed Enchanted Golden Apple regeneration effect amplifier to match vanilla.
# 5.21.2
Released 29th November 2024.
## Fixes
- Fixed blocks destroyable by water being able to be placed inside water.
- Fixed deprecation warnings about nullable typehints on PHP 8.4.
- Fixed `Utils::getNiceClosureName()` not working correctly on PHP 8.4.
- Fixed incorrect break animations when breaking the block behind an instantly-breakable block like a torch.
- Fixed candle extinguish logic.
- Fixed various documentation issues around array key types.
- Introduced a new PHPStan rule along with `Utils::promoteKeys()` to improve PHPStan error reporting around unspecified array key types. Previously, some errors were missed due to PHPStan's BenevolentUnionType.
## DevOps
- `pmmp/server-developers` team is now automatically requested for review on any new PR.
- `Status: Waiting on Author` label is now automatically removed from PRs when they are updated.

16
changelogs/5.22.md Normal file
View File

@ -0,0 +1,16 @@
# 5.22.0
Released 4th December 2024.
**For Minecraft: Bedrock Edition 1.21.50**
This is a support release for Minecraft: Bedrock Edition 1.21.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.21.50.
- Removed support for earlier versions.

View File

@ -22,7 +22,7 @@
"ext-openssl": "*",
"ext-pcre": "*",
"ext-phar": "*",
"ext-pmmpthread": "^6.0.7",
"ext-pmmpthread": "^6.1.0",
"ext-reflection": "*",
"ext-simplexml": "*",
"ext-sockets": "*",
@ -33,29 +33,29 @@
"composer-runtime-api": "^2.0",
"adhocore/json-comment": "~1.2.0",
"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/bedrock-block-upgrade-schema": "~5.0.0+bedrock-1.21.40",
"pocketmine/bedrock-data": "~2.15.0+bedrock-1.21.50",
"pocketmine/bedrock-item-upgrade-schema": "~1.14.0+bedrock-1.21.50",
"pocketmine/bedrock-protocol": "~35.0.0+bedrock-1.21.50",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/color": "^0.3.0",
"pocketmine/errorhandler": "^0.6.0",
"pocketmine/errorhandler": "^0.7.0",
"pocketmine/locale-data": "~2.19.0",
"pocketmine/log": "^0.4.0",
"pocketmine/math": "~1.0.0",
"pocketmine/nbt": "~1.0.0",
"pocketmine/raklib": "^0.15.0",
"pocketmine/raklib-ipc": "^0.2.0",
"pocketmine/raklib": "~1.1.0",
"pocketmine/raklib-ipc": "~1.0.0",
"pocketmine/snooze": "^0.5.0",
"ramsey/uuid": "~4.7.0",
"symfony/filesystem": "~6.4.0"
},
"require-dev": {
"phpstan/phpstan": "1.10.58",
"phpstan/phpstan": "1.11.11",
"phpstan/phpstan-phpunit": "^1.1.0",
"phpstan/phpstan-strict-rules": "^1.2.0",
"phpunit/phpunit": "~10.3.0 || ~10.2.0 || ~10.1.0"
"phpunit/phpunit": "^10.5.24"
},
"autoload": {
"psr-4": {
@ -83,11 +83,14 @@
"@composer install --no-dev --classmap-authoritative --ignore-platform-reqs",
"@php -dphar.readonly=0 build/server-phar.php"
],
"update-registry-annotations": [
"update-codegen": [
"@php build/generate-bedrockdata-path-consts.php",
"@php build/generate-biome-ids.php",
"@php build/generate-block-serializer-consts.php vendor/pocketmine/bedrock-data/canonical_block_states.nbt",
"@php build/generate-item-type-names.php vendor/pocketmine/bedrock-data/required_item_list.json",
"@php build/generate-known-translation-apis.php",
"@php build/generate-pocketmine-yml-property-consts.php",
"@php build/generate-registry-annotations.php src"
],
"update-translation-apis": [
"@php build/generate-known-translation-apis.php"
]
}
}

475
composer.lock generated

File diff suppressed because it is too large Load Diff

21
install-local-protocol.sh Normal file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env bash
echo "--- Installing BedrockProtocol, BedrockData, BedrockBlockUpgradeSchema, BedrockItemUpgradeSchema dependencies from local repositories."
echo "--- This allows you to perform integration tests using PocketMine-MP, without immediately publishing new versions of these libraries."
cp composer.json composer-local-protocol.json
cp composer.lock composer-local-protocol.lock
export COMPOSER=composer-local-protocol.json
composer config repositories.bedrock-protocol path ../deps/BedrockProtocol
composer config repositories.bedrock-data path ../deps/BedrockData
composer config repositories.bedrock-block-upgrade-schema path ../deps/BedrockBlockUpgradeSchema
composer config repositories.bedrock-item-upgrade-schema path ../deps/BedrockItemUpgradeSchema
composer require pocketmine/bedrock-protocol:*@dev pocketmine/bedrock-data:*@dev pocketmine/bedrock-block-upgrade-schema:*@dev pocketmine/bedrock-item-upgrade-schema:*@dev
composer install
echo "--- Local dependencies have been successfully installed."
echo "--- This script does not modify composer.json. To go back to the original dependency versions, simply run 'composer install'."

View File

@ -40,6 +40,7 @@ parameters:
- build/php
dynamicConstantNames:
- pocketmine\VersionInfo::IS_DEVELOPMENT_BUILD
- pocketmine\VersionInfo::BUILD_CHANNEL
- pocketmine\DEBUG
- pocketmine\IS_DEVELOPMENT_BUILD
stubFiles:
@ -47,8 +48,6 @@ parameters:
- tests/phpstan/stubs/leveldb.stub
- tests/phpstan/stubs/pmmpthread.stub
reportUnmatchedIgnoredErrors: false #no other way to silence platform-specific non-warnings
staticReflectionClassNamePatterns:
- "#^COM$#"
typeAliases:
#variadics don't work for this - mixed probably shouldn't work either, but for now it does
#what we actually need is something that accepts an infinite number of parameters, but in the absence of that,

View File

@ -47,4 +47,6 @@ final class BootstrapOptions{
public const DATA = "data";
/** Shows basic server version information and exits */
public const VERSION = "version";
/** Disables writing logs to server.log */
public const NO_LOG_FILE = "no-log-file";
}

View File

@ -332,7 +332,7 @@ class MemoryManager{
continue;
}
$methodStatics = [];
foreach($method->getStaticVariables() as $name => $variable){
foreach(Utils::promoteKeys($method->getStaticVariables()) as $name => $variable){
$methodStatics[$name] = self::continueDump($variable, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
if(count($methodStatics) > 0){
@ -360,7 +360,7 @@ class MemoryManager{
'_SESSION' => true
];
foreach($GLOBALS as $varName => $value){
foreach(Utils::promoteKeys($GLOBALS) as $varName => $value){
if(isset($ignoredGlobals[$varName])){
continue;
}
@ -376,7 +376,7 @@ class MemoryManager{
$reflect = new \ReflectionFunction($function);
$vars = [];
foreach($reflect->getStaticVariables() as $varName => $variable){
foreach(Utils::promoteKeys($reflect->getStaticVariables()) as $varName => $variable){
$vars[$varName] = self::continueDump($variable, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
if(count($vars) > 0){
@ -416,7 +416,7 @@ class MemoryManager{
$info["this"] = self::continueDump($closureThis, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
foreach($reflect->getStaticVariables() as $name => $variable){
foreach(Utils::promoteKeys($reflect->getStaticVariables()) as $name => $variable){
$info["referencedVars"][$name] = self::continueDump($variable, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
}else{
@ -499,7 +499,7 @@ class MemoryManager{
}
$data = [];
$numeric = 0;
foreach($from as $key => $value){
foreach(Utils::promoteKeys($from) as $key => $value){
$data[$numeric] = [
"k" => self::continueDump($key, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize),
"v" => self::continueDump($value, $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize),

View File

@ -124,8 +124,8 @@ namespace pocketmine {
}
if(($pmmpthread_version = phpversion("pmmpthread")) !== false){
if(version_compare($pmmpthread_version, "6.0.7") < 0 || version_compare($pmmpthread_version, "7.0.0") >= 0){
$messages[] = "pmmpthread ^6.0.7 is required, while you have $pmmpthread_version.";
if(version_compare($pmmpthread_version, "6.1.0") < 0 || version_compare($pmmpthread_version, "7.0.0") >= 0){
$messages[] = "pmmpthread ^6.1.0 is required, while you have $pmmpthread_version.";
}
}
@ -317,7 +317,7 @@ JIT_WARNING
//Logger has a dependency on timezone
Timezone::init();
$opts = getopt("", [BootstrapOptions::NO_WIZARD, BootstrapOptions::ENABLE_ANSI, BootstrapOptions::DISABLE_ANSI]);
$opts = getopt("", [BootstrapOptions::NO_WIZARD, BootstrapOptions::ENABLE_ANSI, BootstrapOptions::DISABLE_ANSI, BootstrapOptions::NO_LOG_FILE]);
if(isset($opts[BootstrapOptions::ENABLE_ANSI])){
Terminal::init(true);
}elseif(isset($opts[BootstrapOptions::DISABLE_ANSI])){
@ -325,8 +325,13 @@ JIT_WARNING
}else{
Terminal::init();
}
$logFile = isset($opts[BootstrapOptions::NO_LOG_FILE]) ? null : Path::join($dataPath, "server.log");
$logger = new MainLogger($logFile, Terminal::hasFormattingCodes(), "Server", new \DateTimeZone(Timezone::get()), false, Path::join($dataPath, "log_archive"));
if($logFile === null){
$logger->notice("Logging to file disabled. Ensure logs are collected by other means (e.g. Docker logs).");
}
$logger = new MainLogger(Path::join($dataPath, "server.log"), Terminal::hasFormattingCodes(), "Server", new \DateTimeZone(Timezone::get()));
\GlobalLogger::set($logger);
emit_performance_warnings($logger);

View File

@ -736,12 +736,15 @@ class Server{
/**
* @return string[][]
* @phpstan-return array<string, list<string>>
*/
public function getCommandAliases() : array{
$section = $this->configGroup->getProperty(Yml::ALIASES);
$result = [];
if(is_array($section)){
foreach($section as $key => $value){
foreach(Utils::promoteKeys($section) as $key => $value){
//TODO: more validation needed here
//key might not be a string, value might not be list<string>
$commands = [];
if(is_array($value)){
$commands = $value;
@ -749,7 +752,7 @@ class Server{
$commands[] = (string) $value;
}
$result[$key] = $commands;
$result[(string) $key] = $commands;
}
}
@ -1094,7 +1097,11 @@ class Server{
$anyWorldFailedToLoad = false;
foreach((array) $this->configGroup->getProperty(Yml::WORLDS, []) as $name => $options){
foreach(Utils::promoteKeys((array) $this->configGroup->getProperty(Yml::WORLDS, [])) as $name => $options){
if(!is_string($name)){
//TODO: this probably should be an error
continue;
}
if($options === null){
$options = [];
}elseif(!is_array($options)){
@ -1666,9 +1673,11 @@ class Server{
$this->isRunning = false;
//Force minimum uptime to be >= 120 seconds, to reduce the impact of spammy crash loops
$spacing = ((int) $this->startTime) - time() + 120;
$uptime = time() - ((int) $this->startTime);
$minUptime = 120;
$spacing = $minUptime - $uptime;
if($spacing > 0){
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
echo "--- Uptime {$uptime}s - waiting {$spacing}s to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
sleep($spacing);
}
@Process::kill(Process::pid());

View File

@ -31,7 +31,7 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
public const BASE_VERSION = "5.12.0";
public const BASE_VERSION = "5.22.0";
public const IS_DEVELOPMENT_BUILD = false;
public const BUILD_CHANNEL = "stable";
@ -63,7 +63,8 @@ final class VersionInfo{
if(\Phar::running(true) === ""){
$gitHash = Git::getRepositoryStatePretty(\pocketmine\PATH);
}else{
$phar = new \Phar(\Phar::running(false));
$pharPath = \Phar::running(false);
$phar = \Phar::isValidPharFilename($pharPath) ? new \Phar($pharPath) : new \PharData($pharPath);
$meta = $phar->getMetadata();
if(isset($meta["git"])){
$gitHash = $meta["git"];
@ -82,7 +83,8 @@ final class VersionInfo{
if(self::$buildNumber === null){
self::$buildNumber = 0;
if(\Phar::running(true) !== ""){
$phar = new \Phar(\Phar::running(false));
$pharPath = \Phar::running(false);
$phar = \Phar::isValidPharFilename($pharPath) ? new \Phar($pharPath) : new \PharData($pharPath);
$meta = $phar->getMetadata();
if(is_array($meta) && isset($meta["build"]) && is_int($meta["build"])){
self::$buildNumber = $meta["build"];

View File

@ -91,7 +91,7 @@ class Anvil extends Transparent implements Fallable{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player !== null){
$this->facing = Facing::rotateY($player->getHorizontalFacing(), true);
$this->facing = Facing::rotateY($player->getHorizontalFacing(), false);
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}

View File

@ -150,6 +150,10 @@ final class Bell extends Transparent{
}
}
public function getDropsForIncompatibleTool(Item $item) : array{
return [$this->asItem()];
}
private function isValidFaceToRing(int $faceHit) : bool{
return match($this->attachmentType){
BellAttachmentType::CEILING => true,

View File

@ -362,6 +362,8 @@ class Block{
*
* A replacement block may be returned. This is useful if the block type changed due to reading of world data (e.g.
* data from a block entity).
*
* @phpstan-impure
*/
public function readStateFromWorld() : Block{
return $this;

View File

@ -745,8 +745,28 @@ final class BlockTypeIds{
public const PITCHER_PLANT = 10715;
public const PITCHER_CROP = 10716;
public const DOUBLE_PITCHER_CROP = 10717;
public const CAMPFIRE = 10718;
public const SOUL_CAMPFIRE = 10719;
public const TUFF_SLAB = 10720;
public const TUFF_STAIRS = 10721;
public const TUFF_WALL = 10722;
public const CHISELED_TUFF = 10723;
public const TUFF_BRICKS = 10724;
public const TUFF_BRICK_SLAB = 10725;
public const TUFF_BRICK_STAIRS = 10726;
public const TUFF_BRICK_WALL = 10727;
public const CHISELED_TUFF_BRICKS = 10728;
public const POLISHED_TUFF = 10729;
public const POLISHED_TUFF_SLAB = 10730;
public const POLISHED_TUFF_STAIRS = 10731;
public const POLISHED_TUFF_WALL = 10732;
public const COPPER_BULB = 10733;
public const COPPER_DOOR = 10734;
public const COPPER_TRAPDOOR = 10735;
public const CHISELED_COPPER = 10736;
public const COPPER_GRATE = 10737;
public const FIRST_UNUSED_BLOCK_ID = 10718;
public const FIRST_UNUSED_BLOCK_ID = 10738;
private static int $nextDynamicId = self::FIRST_UNUSED_BLOCK_ID;

View File

@ -27,10 +27,6 @@ use pocketmine\item\Item;
class BlueIce extends Opaque{
public function getLightLevel() : int{
return 1;
}
public function getFrictionFactor() : float{
return 0.99;
}
@ -38,4 +34,8 @@ class BlueIce extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
return [];
}
public function isAffectedBySilkTouch() : bool{
return true;
}
}

View File

@ -52,6 +52,9 @@ class CakeWithCandle extends BaseCake{
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($this->lit && $face !== Facing::UP){
return true;
}
if($this->onInteractCandle($item, $face, $clickVector, $player, $returnedItems)){
return true;
}

277
src/block/Campfire.php Normal file
View File

@ -0,0 +1,277 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\inventory\CampfireInventory;
use pocketmine\block\tile\Campfire as TileCampfire;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\LightableTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\crafting\FurnaceRecipe;
use pocketmine\crafting\FurnaceType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity;
use pocketmine\entity\Living;
use pocketmine\entity\projectile\Projectile;
use pocketmine\entity\projectile\SplashPotion;
use pocketmine\event\block\CampfireCookEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Durable;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\Item;
use pocketmine\item\ItemTypeIds;
use pocketmine\item\PotionType;
use pocketmine\item\Shovel;
use pocketmine\item\VanillaItems;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\sound\BlazeShootSound;
use pocketmine\world\sound\FireExtinguishSound;
use pocketmine\world\sound\FlintSteelSound;
use pocketmine\world\sound\ItemFrameAddItemSound;
use function count;
use function min;
use function mt_rand;
class Campfire extends Transparent{
use HorizontalFacingTrait{
HorizontalFacingTrait::describeBlockOnlyState as encodeFacingState;
}
use LightableTrait{
LightableTrait::describeBlockOnlyState as encodeLitState;
}
private const UPDATE_INTERVAL_TICKS = 10;
protected CampfireInventory $inventory;
/**
* @var int[] slot => ticks
* @phpstan-var array<int, int>
*/
protected array $cookingTimes = [];
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$this->encodeFacingState($w);
$this->encodeLitState($w);
}
public function readStateFromWorld() : Block{
parent::readStateFromWorld();
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileCampfire){
$this->inventory = $tile->getInventory();
$this->cookingTimes = $tile->getCookingTimes();
}else{
$this->inventory = new CampfireInventory($this->position);
}
return $this;
}
public function writeStateToWorld() : void{
parent::writeStateToWorld();
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileCampfire){
$tile->setCookingTimes($this->cookingTimes);
}
}
public function hasEntityCollision() : bool{
return true;
}
public function getLightLevel() : int{
return $this->lit ? 15 : 0;
}
public function isAffectedBySilkTouch() : bool{
return true;
}
public function getDropsForCompatibleTool(Item $item) : array{
return [
VanillaItems::CHARCOAL()->setCount(2)
];
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE;
}
protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 9 / 16)];
}
public function getInventory() : CampfireInventory{
return $this->inventory;
}
protected function getFurnaceType() : FurnaceType{
return FurnaceType::CAMPFIRE;
}
protected function getEntityCollisionDamage() : int{
return 1;
}
/**
* Sets the number of ticks during the item in the given slot has been cooked.
*/
public function setCookingTime(int $slot, int $time) : void{
if($slot < 0 || $slot > 3){
throw new \InvalidArgumentException("Slot must be in range 0-3");
}
if($time < 0 || $time > $this->getFurnaceType()->getCookDurationTicks()){
throw new \InvalidArgumentException("CookingTime must be in range 0-" . $this->getFurnaceType()->getCookDurationTicks());
}
$this->cookingTimes[$slot] = $time;
}
/**
* Returns the number of ticks during the item in the given slot has been cooked.
*/
public function getCookingTime(int $slot) : int{
return $this->cookingTimes[$slot] ?? 0;
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->getSide(Facing::DOWN) instanceof Campfire){
return false;
}
if($player !== null){
$this->facing = $player->getHorizontalFacing();
}
$this->lit = true;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if(!$this->lit){
if($item->getTypeId() === ItemTypeIds::FIRE_CHARGE){
$item->pop();
$this->ignite();
$this->position->getWorld()->addSound($this->position, new BlazeShootSound());
return true;
}elseif($item->getTypeId() === ItemTypeIds::FLINT_AND_STEEL || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
if($item instanceof Durable){
$item->applyDamage(1);
}
$this->ignite();
return true;
}
}elseif($item instanceof Shovel){
$item->applyDamage(1);
$this->extinguish();
return true;
}
if($this->position->getWorld()->getServer()->getCraftingManager()->getFurnaceRecipeManager($this->getFurnaceType())->match($item) !== null){
$ingredient = clone $item;
$ingredient->setCount(1);
if(count($this->inventory->addItem($ingredient)) === 0){
$item->pop();
$this->position->getWorld()->addSound($this->position, new ItemFrameAddItemSound());
return true;
}
}
return false;
}
public function onNearbyBlockChange() : void{
if($this->lit && $this->getSide(Facing::UP)->getTypeId() === BlockTypeIds::WATER){
$this->extinguish();
//TODO: Waterlogging
}
}
public function onEntityInside(Entity $entity) : bool{
if(!$this->lit){
if($entity->isOnFire()){
$this->ignite();
return false;
}
}elseif($entity instanceof Living){
$entity->attack(new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, $this->getEntityCollisionDamage()));
}
return true;
}
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
if($this->lit && $projectile instanceof SplashPotion && $projectile->getPotionType() === PotionType::WATER){
$this->extinguish();
}
}
public function onScheduledUpdate() : void{
if($this->lit){
$items = $this->inventory->getContents();
$furnaceType = $this->getFurnaceType();
$maxCookDuration = $furnaceType->getCookDurationTicks();
foreach($items as $slot => $item){
$this->setCookingTime($slot, min($maxCookDuration, $this->getCookingTime($slot) + self::UPDATE_INTERVAL_TICKS));
if($this->getCookingTime($slot) >= $maxCookDuration){
$result =
($recipe = $this->position->getWorld()->getServer()->getCraftingManager()->getFurnaceRecipeManager($furnaceType)->match($item)) instanceof FurnaceRecipe ?
$recipe->getResult() :
VanillaItems::AIR();
$ev = new CampfireCookEvent($this, $slot, $item, $result);
$ev->call();
if ($ev->isCancelled()){
continue;
}
$this->inventory->setItem($slot, VanillaItems::AIR());
$this->setCookingTime($slot, 0);
$this->position->getWorld()->dropItem($this->position->add(0.5, 1, 0.5), $ev->getResult());
}
}
if(count($items) > 0){
$this->position->getWorld()->setBlock($this->position, $this);
}
if(mt_rand(1, 6) === 1){
$this->position->getWorld()->addSound($this->position, $furnaceType->getCookSound());
}
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, self::UPDATE_INTERVAL_TICKS);
}
}
private function extinguish() : void{
$this->position->getWorld()->addSound($this->position, new FireExtinguishSound());
$this->position->getWorld()->setBlock($this->position, $this->setLit(false));
}
private function ignite() : void{
$this->position->getWorld()->addSound($this->position, new FlintSteelSound());
$this->position->getWorld()->setBlock($this->position, $this->setLit(true));
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, self::UPDATE_INTERVAL_TICKS);
}
}

View File

@ -48,11 +48,32 @@ class ChiseledBookshelf extends Opaque{
*/
private array $slots = [];
private ?ChiseledBookshelfSlot $lastInteractedSlot = null;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->enumSet($this->slots, ChiseledBookshelfSlot::cases());
}
public function readStateFromWorld() : Block{
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileChiseledBookshelf){
$this->lastInteractedSlot = $tile->getLastInteractedSlot();
}else{
$this->lastInteractedSlot = null;
}
return $this;
}
public function writeStateToWorld() : void{
parent::writeStateToWorld();
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileChiseledBookshelf){
$tile->setLastInteractedSlot($this->lastInteractedSlot);
}
}
/**
* Returns whether the given slot is displayed as occupied.
* This doesn't guarantee that there is or isn't a book in the bookshelf's inventory.
@ -92,6 +113,23 @@ class ChiseledBookshelf extends Opaque{
return $this->slots;
}
/**
* Returns the last slot interacted by a player or null if no slot has been interacted with yet.
*/
public function getLastInteractedSlot() : ?ChiseledBookshelfSlot{
return $this->lastInteractedSlot;
}
/**
* Sets the last slot interacted by a player.
*
* @return $this
*/
public function setLastInteractedSlot(?ChiseledBookshelfSlot $lastInteractedSlot) : self{
$this->lastInteractedSlot = $lastInteractedSlot;
return $this;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($face !== $this->facing){
return false;
@ -112,10 +150,12 @@ class ChiseledBookshelf extends Opaque{
$returnedItems[] = $inventory->getItem($slot->value);
$inventory->clear($slot->value);
$this->setSlot($slot, false);
$this->lastInteractedSlot = $slot;
}elseif($item instanceof WritableBookBase || $item instanceof Book || $item instanceof EnchantedBook){
//TODO: type tags like blocks would be better for this
$inventory->setItem($slot->value, $item->pop());
$this->setSlot($slot, true);
$this->lastInteractedSlot = $slot;
}else{
return true;
}

View File

@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CopperMaterial;
use pocketmine\block\utils\CopperTrait;
class Copper extends Opaque{
class Copper extends Opaque implements CopperMaterial{
use CopperTrait;
}

69
src/block/CopperBulb.php Normal file
View File

@ -0,0 +1,69 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CopperMaterial;
use pocketmine\block\utils\CopperOxidation;
use pocketmine\block\utils\CopperTrait;
use pocketmine\block\utils\LightableTrait;
use pocketmine\block\utils\PoweredByRedstoneTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
class CopperBulb extends Opaque implements CopperMaterial{
use CopperTrait;
use PoweredByRedstoneTrait;
use LightableTrait{
describeBlockOnlyState as encodeLitState;
}
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$this->encodeLitState($w);
$w->bool($this->powered);
}
/** @return $this */
public function togglePowered(bool $powered) : self{
if($powered === $this->powered){
return $this;
}
if ($powered) {
$this->setLit(!$this->lit);
}
$this->setPowered($powered);
return $this;
}
public function getLightLevel() : int{
if ($this->lit) {
return match($this->oxidation){
CopperOxidation::NONE => 15,
CopperOxidation::EXPOSED => 12,
CopperOxidation::WEATHERED => 8,
CopperOxidation::OXIDIZED => 4,
};
}
return 0;
}
}

53
src/block/CopperDoor.php Normal file
View File

@ -0,0 +1,53 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CopperMaterial;
use pocketmine\block\utils\CopperTrait;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
class CopperDoor extends Door implements CopperMaterial{
use CopperTrait{
onInteract as onInteractCopper;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if ($player !== null && $player->isSneaking() && $this->onInteractCopper($item, $face, $clickVector, $player, $returnedItems)) {
//copy copper properties to other half
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
$world = $this->position->getWorld();
if ($other instanceof CopperDoor) {
$other->setOxidation($this->oxidation);
$other->setWaxed($this->waxed);
$world->setBlock($other->position, $other);
}
return true;
}
return parent::onInteract($item, $face, $clickVector, $player, $returnedItems);
}
}

33
src/block/CopperGrate.php Normal file
View File

@ -0,0 +1,33 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CopperMaterial;
use pocketmine\block\utils\CopperTrait;
class CopperGrate extends Transparent implements CopperMaterial{
use CopperTrait;
//TODO: waterlogging!
}

View File

@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CopperMaterial;
use pocketmine\block\utils\CopperTrait;
class CopperSlab extends Slab{
class CopperSlab extends Slab implements CopperMaterial{
use CopperTrait;
}

View File

@ -23,8 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CopperMaterial;
use pocketmine\block\utils\CopperTrait;
class CopperStairs extends Stair{
class CopperStairs extends Stair implements CopperMaterial{
use CopperTrait;
}

View File

@ -0,0 +1,44 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CopperMaterial;
use pocketmine\block\utils\CopperTrait;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
class CopperTrapdoor extends Trapdoor implements CopperMaterial{
use CopperTrait{
onInteract as onInteractCopper;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if ($player !== null && $player->isSneaking() && $this->onInteractCopper($item, $face, $clickVector, $player, $returnedItems)) {
return true;
}
return parent::onInteract($item, $face, $clickVector, $player, $returnedItems);
}
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\utils\SupportType;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
/**
* "Flowable" blocks are destroyed if water flows into the same space as the block. These blocks usually don't have any
@ -40,6 +41,11 @@ abstract class Flowable extends Transparent{
return false;
}
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
return (!$this->canBeFlowedInto() || !$blockReplace instanceof Liquid) &&
parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
}
/**
* @return AxisAlignedBB[]
*/

View File

@ -34,6 +34,7 @@ final class NetherRoots extends Flowable{
$supportBlock = $block->getSide(Facing::DOWN);
return
$supportBlock->hasTypeTag(BlockTypeTags::DIRT) ||
$supportBlock->hasTypeTag(BlockTypeTags::MUD);
$supportBlock->hasTypeTag(BlockTypeTags::MUD) ||
$supportBlock->getTypeId() === BlockTypeIds::SOUL_SOIL;
}
}

View File

@ -132,6 +132,7 @@ class RuntimeBlockStateRegistry{
/**
* @return Block[]
* @phpstan-return array<int, Block>
*/
public function getAllKnownStates() : array{
return $this->fullList;

View File

@ -0,0 +1,48 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\crafting\FurnaceType;
use pocketmine\item\Item;
class SoulCampfire extends Campfire{
public function getLightLevel() : int{
return $this->lit ? 10 : 0;
}
public function getDropsForCompatibleTool(Item $item) : array{
return [
VanillaBlocks::SOUL_SOIL()->asItem()
];
}
protected function getEntityCollisionDamage() : int{
return 2;
}
protected function getFurnaceType() : FurnaceType{
return FurnaceType::SOUL_CAMPFIRE;
}
}

View File

@ -36,6 +36,7 @@ use pocketmine\item\VanillaItems;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\SweetBerriesPickSound;
use function mt_rand;
class SweetBerryBush extends Flowable{
@ -81,6 +82,7 @@ class SweetBerryBush extends Flowable{
}elseif(($dropAmount = $this->getBerryDropAmount()) > 0){
$world->setBlock($this->position, $this->setAge(self::STAGE_BUSH_NO_BERRIES));
$world->dropItem($this->position, $this->asItem()->setCount($dropAmount));
$world->addSound($this->position, new SweetBerriesPickSound());
}
return true;

View File

@ -36,6 +36,7 @@ use pocketmine\block\tile\Bed as TileBed;
use pocketmine\block\tile\Bell as TileBell;
use pocketmine\block\tile\BlastFurnace as TileBlastFurnace;
use pocketmine\block\tile\BrewingStand as TileBrewingStand;
use pocketmine\block\tile\Campfire as TileCampfire;
use pocketmine\block\tile\Cauldron as TileCauldron;
use pocketmine\block\tile\Chest as TileChest;
use pocketmine\block\tile\ChiseledBookshelf as TileChiseledBookshelf;
@ -154,6 +155,7 @@ use function strtolower;
* @method static CakeWithCandle CAKE_WITH_CANDLE()
* @method static CakeWithDyedCandle CAKE_WITH_DYED_CANDLE()
* @method static Opaque CALCITE()
* @method static Campfire CAMPFIRE()
* @method static Candle CANDLE()
* @method static Carpet CARPET()
* @method static Carrot CARROTS()
@ -179,6 +181,7 @@ use function strtolower;
* @method static Wood CHERRY_WOOD()
* @method static Chest CHEST()
* @method static ChiseledBookshelf CHISELED_BOOKSHELF()
* @method static Copper CHISELED_COPPER()
* @method static Opaque CHISELED_DEEPSLATE()
* @method static Opaque CHISELED_NETHER_BRICKS()
* @method static Opaque CHISELED_POLISHED_BLACKSTONE()
@ -186,6 +189,8 @@ use function strtolower;
* @method static Opaque CHISELED_RED_SANDSTONE()
* @method static Opaque CHISELED_SANDSTONE()
* @method static Opaque CHISELED_STONE_BRICKS()
* @method static Opaque CHISELED_TUFF()
* @method static Opaque CHISELED_TUFF_BRICKS()
* @method static ChorusFlower CHORUS_FLOWER()
* @method static ChorusPlant CHORUS_PLANT()
* @method static Clay CLAY()
@ -205,7 +210,11 @@ use function strtolower;
* @method static Concrete CONCRETE()
* @method static ConcretePowder CONCRETE_POWDER()
* @method static Copper COPPER()
* @method static CopperBulb COPPER_BULB()
* @method static CopperDoor COPPER_DOOR()
* @method static CopperGrate COPPER_GRATE()
* @method static CopperOre COPPER_ORE()
* @method static CopperTrapdoor COPPER_TRAPDOOR()
* @method static Coral CORAL()
* @method static CoralBlock CORAL_BLOCK()
* @method static FloorCoralFan CORAL_FAN()
@ -607,6 +616,10 @@ use function strtolower;
* @method static Opaque POLISHED_GRANITE()
* @method static Slab POLISHED_GRANITE_SLAB()
* @method static Stair POLISHED_GRANITE_STAIRS()
* @method static Opaque POLISHED_TUFF()
* @method static Slab POLISHED_TUFF_SLAB()
* @method static Stair POLISHED_TUFF_STAIRS()
* @method static Wall POLISHED_TUFF_WALL()
* @method static Flower POPPY()
* @method static Potato POTATOES()
* @method static PotionCauldron POTION_CAULDRON()
@ -685,6 +698,7 @@ use function strtolower;
* @method static Slab SMOOTH_STONE_SLAB()
* @method static Snow SNOW()
* @method static SnowLayer SNOW_LAYER()
* @method static SoulCampfire SOUL_CAMPFIRE()
* @method static SoulFire SOUL_FIRE()
* @method static Lantern SOUL_LANTERN()
* @method static SoulSand SOUL_SAND()
@ -735,6 +749,13 @@ use function strtolower;
* @method static Tripwire TRIPWIRE()
* @method static TripwireHook TRIPWIRE_HOOK()
* @method static Opaque TUFF()
* @method static Opaque TUFF_BRICKS()
* @method static Slab TUFF_BRICK_SLAB()
* @method static Stair TUFF_BRICK_STAIRS()
* @method static Wall TUFF_BRICK_WALL()
* @method static Slab TUFF_SLAB()
* @method static Stair TUFF_STAIRS()
* @method static Wall TUFF_WALL()
* @method static NetherVines TWISTING_VINES()
* @method static UnderwaterTorch UNDERWATER_TORCH()
* @method static Vine VINES()
@ -826,6 +847,11 @@ final class VanillaBlocks{
self::register("brown_mushroom", new BrownMushroom(new BID(Ids::BROWN_MUSHROOM), "Brown Mushroom", new Info(BreakInfo::instant(), [Tags::POTTABLE_PLANTS])));
self::register("cactus", new Cactus(new BID(Ids::CACTUS), "Cactus", new Info(new BreakInfo(0.4), [Tags::POTTABLE_PLANTS])));
self::register("cake", new Cake(new BID(Ids::CAKE), "Cake", new Info(new BreakInfo(0.5))));
$campfireBreakInfo = new Info(BreakInfo::axe(2.0));
self::register("campfire", new Campfire(new BID(Ids::CAMPFIRE, TileCampfire::class), "Campfire", $campfireBreakInfo));
self::register("soul_campfire", new SoulCampfire(new BID(Ids::SOUL_CAMPFIRE, TileCampfire::class), "Soul Campfire", $campfireBreakInfo));
self::register("carrots", new Carrot(new BID(Ids::CARROTS), "Carrot Block", new Info(BreakInfo::instant())));
$chestBreakInfo = new Info(BreakInfo::axe(2.5));
@ -1261,6 +1287,7 @@ final class VanillaBlocks{
self::registerBlocksR17();
self::registerBlocksR18();
self::registerMudBlocks();
self::registerTuffBlocks();
self::registerCraftingTables();
self::registerChorusBlocks();
@ -1568,7 +1595,6 @@ final class VanillaBlocks{
self::register("amethyst_cluster", new AmethystCluster(new BID(Ids::AMETHYST_CLUSTER), "Amethyst Cluster", $amethystInfo));
self::register("calcite", new Opaque(new BID(Ids::CALCITE), "Calcite", new Info(BreakInfo::pickaxe(0.75, ToolTier::WOOD))));
self::register("tuff", new Opaque(new BID(Ids::TUFF), "Tuff", new Info(BreakInfo::pickaxe(1.5, ToolTier::WOOD, 30.0))));
self::register("raw_copper", new Opaque(new BID(Ids::RAW_COPPER), "Raw Copper Block", new Info(BreakInfo::pickaxe(5, ToolTier::STONE, 30.0))));
self::register("raw_gold", new Opaque(new BID(Ids::RAW_GOLD), "Raw Gold Block", new Info(BreakInfo::pickaxe(5, ToolTier::IRON, 30.0))));
@ -1621,9 +1647,16 @@ final class VanillaBlocks{
self::register("lightning_rod", new LightningRod(new BID(Ids::LIGHTNING_ROD), "Lightning Rod", $copperBreakInfo));
self::register("copper", new Copper(new BID(Ids::COPPER), "Copper Block", $copperBreakInfo));
self::register("chiseled_copper", new Copper(new BID(Ids::CHISELED_COPPER), "Chiseled Copper", $copperBreakInfo));
self::register("copper_grate", new CopperGrate(new BID(Ids::COPPER_GRATE), "Copper Grate", $copperBreakInfo));
self::register("cut_copper", new Copper(new BID(Ids::CUT_COPPER), "Cut Copper Block", $copperBreakInfo));
self::register("cut_copper_slab", new CopperSlab(new BID(Ids::CUT_COPPER_SLAB), "Cut Copper Slab", $copperBreakInfo));
self::register("cut_copper_stairs", new CopperStairs(new BID(Ids::CUT_COPPER_STAIRS), "Cut Copper Stairs", $copperBreakInfo));
self::register("copper_bulb", new CopperBulb(new BID(Ids::COPPER_BULB), "Copper Bulb", $copperBreakInfo));
$copperDoorBreakInfo = new Info(BreakInfo::pickaxe(3.0, ToolTier::STONE, 30.0));
self::register("copper_door", new CopperDoor(new BID(Ids::COPPER_DOOR), "Copper Door", $copperDoorBreakInfo));
self::register("copper_trapdoor", new CopperTrapdoor(new BID(Ids::COPPER_TRAPDOOR), "Copper Trapdoor", $copperDoorBreakInfo));
$candleBreakInfo = new Info(new BreakInfo(0.1));
self::register("candle", new Candle(new BID(Ids::CANDLE), "Candle", $candleBreakInfo));
@ -1659,6 +1692,27 @@ final class VanillaBlocks{
self::register("mud_brick_wall", new Wall(new BID(Ids::MUD_BRICK_WALL), "Mud Brick Wall", $mudBricksBreakInfo));
}
private static function registerTuffBlocks() : void{
$tuffBreakInfo = new Info(BreakInfo::pickaxe(1.5, ToolTier::WOOD, 30.0));
self::register("tuff", new Opaque(new BID(Ids::TUFF), "Tuff", $tuffBreakInfo));
self::register("tuff_slab", new Slab(new BID(Ids::TUFF_SLAB), "Tuff", $tuffBreakInfo));
self::register("tuff_stairs", new Stair(new BID(Ids::TUFF_STAIRS), "Tuff Stairs", $tuffBreakInfo));
self::register("tuff_wall", new Wall(new BID(Ids::TUFF_WALL), "Tuff Wall", $tuffBreakInfo));
self::register("chiseled_tuff", new Opaque(new BID(Ids::CHISELED_TUFF), "Chiseled Tuff", $tuffBreakInfo));
self::register("tuff_bricks", new Opaque(new BID(Ids::TUFF_BRICKS), "Tuff Bricks", $tuffBreakInfo));
self::register("tuff_brick_slab", new Slab(new BID(Ids::TUFF_BRICK_SLAB), "Tuff Brick", $tuffBreakInfo));
self::register("tuff_brick_stairs", new Stair(new BID(Ids::TUFF_BRICK_STAIRS), "Tuff Brick Stairs", $tuffBreakInfo));
self::register("tuff_brick_wall", new Wall(new BID(Ids::TUFF_BRICK_WALL), "Tuff Brick Wall", $tuffBreakInfo));
self::register("chiseled_tuff_bricks", new Opaque(new BID(Ids::CHISELED_TUFF_BRICKS), "Chiseled Tuff Bricks", $tuffBreakInfo));
self::register("polished_tuff", new Opaque(new BID(Ids::POLISHED_TUFF), "Polished Tuff", $tuffBreakInfo));
self::register("polished_tuff_slab", new Slab(new BID(Ids::POLISHED_TUFF_SLAB), "Polished Tuff", $tuffBreakInfo));
self::register("polished_tuff_stairs", new Stair(new BID(Ids::POLISHED_TUFF_STAIRS), "Polished Tuff Stairs", $tuffBreakInfo));
self::register("polished_tuff_wall", new Wall(new BID(Ids::POLISHED_TUFF_WALL), "Polished Tuff Wall", $tuffBreakInfo));
}
private static function registerCauldronBlocks() : void{
$cauldronBreakInfo = new Info(BreakInfo::pickaxe(2, ToolTier::WOOD));

View File

@ -28,6 +28,10 @@ use pocketmine\block\utils\WoodTypeTrait;
class WoodenStairs extends Stair{
use WoodTypeTrait;
public function getFuelTime() : int{
return $this->woodType->isFlammable() ? 300 : 0;
}
public function getFlameEncouragement() : int{
return 5;
}

View File

@ -21,19 +21,20 @@
declare(strict_types=1);
namespace pocketmine\data\bedrock\block\upgrade;
namespace pocketmine\block\inventory;
final class BlockStateUpgradeSchemaFlattenedName{
use pocketmine\inventory\SimpleInventory;
use pocketmine\world\Position;
public function __construct(
public string $prefix,
public string $flattenedProperty,
public string $suffix
){}
class CampfireInventory extends SimpleInventory implements BlockInventory{
use BlockInventoryTrait;
public function equals(self $that) : bool{
return $this->prefix === $that->prefix &&
$this->flattenedProperty === $that->flattenedProperty &&
$this->suffix === $that->suffix;
public function __construct(Position $holder){
$this->holder = $holder;
parent::__construct(4);
}
public function getMaxStackSize() : int{
return 1;
}
}

View File

@ -39,7 +39,10 @@ class EnchantInventory extends SimpleInventory implements BlockInventory, Tempor
public const SLOT_INPUT = 0;
public const SLOT_LAPIS = 1;
/** @var EnchantingOption[] $options */
/**
* @var EnchantingOption[] $options
* @phpstan-var list<EnchantingOption>
*/
private array $options = [];
public function __construct(Position $holder){

143
src/block/tile/Campfire.php Normal file
View File

@ -0,0 +1,143 @@
<?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\tile;
use pocketmine\block\Campfire as BlockCampfire;
use pocketmine\block\inventory\CampfireInventory;
use pocketmine\inventory\CallbackInventoryListener;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\world\World;
class Campfire extends Spawnable implements Container{
use ContainerTrait;
private const TAG_FIRST_INPUT_ITEM = "Item1"; //TAG_Compound
private const TAG_SECOND_INPUT_ITEM = "Item2"; //TAG_Compound
private const TAG_THIRD_INPUT_ITEM = "Item3"; //TAG_Compound
private const TAG_FOURTH_INPUT_ITEM = "Item4"; //TAG_Compound
private const TAG_FIRST_COOKING_TIME = "ItemTime1"; //TAG_Int
private const TAG_SECOND_COOKING_TIME = "ItemTime2"; //TAG_Int
private const TAG_THIRD_COOKING_TIME = "ItemTime3"; //TAG_Int
private const TAG_FOURTH_COOKING_TIME = "ItemTime4"; //TAG_Int
protected CampfireInventory $inventory;
/** @var array<int, int> */
private array $cookingTimes = [];
public function __construct(World $world, Vector3 $pos){
parent::__construct($world, $pos);
$this->inventory = new CampfireInventory($this->position);
$this->inventory->getListeners()->add(CallbackInventoryListener::onAnyChange(
static function(Inventory $unused) use ($world, $pos) : void{
$block = $world->getBlock($pos);
if($block instanceof BlockCampfire){
$world->setBlock($pos, $block);
}
})
);
}
public function getInventory() : CampfireInventory{
return $this->inventory;
}
public function getRealInventory() : CampfireInventory{
return $this->inventory;
}
/**
* @return int[]
* @phpstan-return array<int, int>
*/
public function getCookingTimes() : array{
return $this->cookingTimes;
}
/**
* @param int[] $cookingTimes
* @phpstan-param array<int, int> $cookingTimes
*/
public function setCookingTimes(array $cookingTimes) : void{
$this->cookingTimes = $cookingTimes;
}
public function readSaveData(CompoundTag $nbt) : void{
$items = [];
$listeners = $this->inventory->getListeners()->toArray();
$this->inventory->getListeners()->remove(...$listeners); //prevent any events being fired by initialization
foreach([
[0, self::TAG_FIRST_INPUT_ITEM, self::TAG_FIRST_COOKING_TIME],
[1, self::TAG_SECOND_INPUT_ITEM, self::TAG_SECOND_COOKING_TIME],
[2, self::TAG_THIRD_INPUT_ITEM, self::TAG_THIRD_COOKING_TIME],
[3, self::TAG_FOURTH_INPUT_ITEM, self::TAG_FOURTH_COOKING_TIME],
] as [$slot, $itemTag, $cookingTimeTag]){
if(($tag = $nbt->getTag($itemTag)) instanceof CompoundTag){
$items[$slot] = Item::nbtDeserialize($tag);
}
if(($tag = $nbt->getTag($cookingTimeTag)) instanceof IntTag){
$this->cookingTimes[$slot] = $tag->getValue();
}
}
$this->inventory->setContents($items);
$this->inventory->getListeners()->add(...$listeners);
}
protected function writeSaveData(CompoundTag $nbt) : void{
foreach([
[0, self::TAG_FIRST_INPUT_ITEM, self::TAG_FIRST_COOKING_TIME],
[1, self::TAG_SECOND_INPUT_ITEM, self::TAG_SECOND_COOKING_TIME],
[2, self::TAG_THIRD_INPUT_ITEM, self::TAG_THIRD_COOKING_TIME],
[3, self::TAG_FOURTH_INPUT_ITEM, self::TAG_FOURTH_COOKING_TIME],
] as [$slot, $itemTag, $cookingTimeTag]){
$item = $this->inventory->getItem($slot);
if(!$item->isNull()){
$nbt->setTag($itemTag, $item->nbtSerialize());
if(isset($this->cookingTimes[$slot])){
$nbt->setInt($cookingTimeTag, $this->cookingTimes[$slot]);
}
}
}
}
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
foreach([
0 => self::TAG_FIRST_INPUT_ITEM,
1 => self::TAG_SECOND_INPUT_ITEM,
2 => self::TAG_THIRD_INPUT_ITEM,
3 => self::TAG_FOURTH_INPUT_ITEM
] as $slot => $tag){
$item = $this->inventory->getItem($slot);
if(!$item->isNull()){
$nbt->setTag($tag, TypeConverter::getInstance()->getItemTranslator()->toNetworkNbt($item));
}
}
}
}

View File

@ -40,8 +40,12 @@ use function count;
class ChiseledBookshelf extends Tile implements Container{
use ContainerTrait;
private const TAG_LAST_INTERACTED_SLOT = "LastInteractedSlot"; //TAG_Int
private SimpleInventory $inventory;
private ?ChiseledBookshelfSlot $lastInteractedSlot = null;
public function __construct(World $world, Vector3 $pos){
parent::__construct($world, $pos);
$this->inventory = new SimpleInventory(count(ChiseledBookshelfSlot::cases()));
@ -55,12 +59,30 @@ class ChiseledBookshelf extends Tile implements Container{
return $this->inventory;
}
public function readSaveData(CompoundTag $nbt) : void{
$this->loadItems($nbt);
public function getLastInteractedSlot() : ?ChiseledBookshelfSlot{
return $this->lastInteractedSlot;
}
public function writeSaveData(CompoundTag $nbt) : void{
public function setLastInteractedSlot(?ChiseledBookshelfSlot $lastInteractedSlot) : void{
$this->lastInteractedSlot = $lastInteractedSlot;
}
public function readSaveData(CompoundTag $nbt) : void{
$this->loadItems($nbt);
$lastInteractedSlot = $nbt->getInt(self::TAG_LAST_INTERACTED_SLOT, 0);
if($lastInteractedSlot !== 0){
$this->lastInteractedSlot = ChiseledBookshelfSlot::tryFrom($lastInteractedSlot - 1);
}
}
protected function writeSaveData(CompoundTag $nbt) : void{
$this->saveItems($nbt);
$nbt->setInt(self::TAG_LAST_INTERACTED_SLOT, $this->lastInteractedSlot !== null ?
$this->lastInteractedSlot->value + 1 :
0
);
}
protected function loadItems(CompoundTag $tag) : void{

View File

@ -57,6 +57,7 @@ final class TileFactory{
$this->register(Bell::class, ["Bell", "minecraft:bell"]);
$this->register(BlastFurnace::class, ["BlastFurnace", "minecraft:blast_furnace"]);
$this->register(BrewingStand::class, ["BrewingStand", "minecraft:brewing_stand"]);
$this->register(Campfire::class, ["Campfire", "minecraft:campfire"]);
$this->register(Cauldron::class, ["Cauldron", "minecraft:cauldron"]);
$this->register(Chest::class, ["Chest", "minecraft:chest"]);
$this->register(ChiseledBookshelf::class, ["ChiseledBookshelf", "minecraft:chiseled_bookshelf"]);
@ -79,7 +80,6 @@ final class TileFactory{
$this->register(MobHead::class, ["Skull", "minecraft:skull"]);
$this->register(GlowingItemFrame::class, ["GlowItemFrame"]);
//TODO: Campfire
//TODO: ChalkboardBlock
//TODO: ChemistryTable
//TODO: CommandBlock

View File

@ -81,14 +81,18 @@ enum BannerPatternType{
case DIAGONAL_RIGHT;
case DIAGONAL_UP_LEFT;
case DIAGONAL_UP_RIGHT;
case FLOW;
case FLOWER;
case GLOBE;
case GRADIENT;
case GRADIENT_UP;
case GUSTER;
case HALF_HORIZONTAL;
case HALF_HORIZONTAL_BOTTOM;
case HALF_VERTICAL;
case HALF_VERTICAL_RIGHT;
case MOJANG;
case PIGLIN;
case RHOMBUS;
case SKULL;
case SMALL_STRIPES;

View File

@ -0,0 +1,38 @@
<?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;
/**
* Represents copper blocks that have oxidized and waxed variations.
*/
interface CopperMaterial{
public function getOxidation() : CopperOxidation;
public function setOxidation(CopperOxidation $oxidation) : CopperMaterial;
public function isWaxed() : bool;
public function setWaxed(bool $waxed) : CopperMaterial;
}

View File

@ -36,13 +36,17 @@ use function str_contains;
class SignText{
public const LINE_COUNT = 4;
/** @var string[] */
/**
* @var string[]
* @phpstan-var array{0: string, 1: string, 2: string, 3: string}
*/
private array $lines;
private Color $baseColor;
private bool $glowing;
/**
* @param string[]|null $lines index-sensitive; keys 0-3 will be used, regardless of array order
* @phpstan-param array{0?: string, 1?: string, 2?: string, 3?: string}|null $lines
*
* @throws \InvalidArgumentException if the array size is greater than 4
* @throws \InvalidArgumentException if invalid keys (out of bounds or string) are found in the array
@ -82,6 +86,7 @@ class SignText{
* Returns an array of lines currently on the sign.
*
* @return string[]
* @phpstan-return array{0: string, 1: string, 2: string, 3: string}
*/
public function getLines() : array{
return $this->lines;

View File

@ -44,10 +44,16 @@ abstract class Command{
private string $nextLabel;
private string $label;
/** @var string[] */
/**
* @var string[]
* @phpstan-var list<string>
*/
private array $aliases = [];
/** @var string[] */
/**
* @var string[]
* @phpstan-var list<string>
*/
private array $activeAliases = [];
private ?CommandMap $commandMap = null;
@ -62,6 +68,7 @@ abstract class Command{
/**
* @param string[] $aliases
* @phpstan-param list<string> $aliases
*/
public function __construct(string $name, Translatable|string $description = "", Translatable|string|null $usageMessage = null, array $aliases = []){
$this->name = $name;
@ -182,6 +189,7 @@ abstract class Command{
/**
* @return string[]
* @phpstan-return list<string>
*/
public function getAliases() : array{
return $this->activeAliases;
@ -201,6 +209,7 @@ abstract class Command{
/**
* @param string[] $aliases
* @phpstan-param list<string> $aliases
*/
public function setAliases(array $aliases) : void{
$this->aliases = $aliases;

View File

@ -70,6 +70,7 @@ use pocketmine\lang\KnownTranslationFactory;
use pocketmine\Server;
use pocketmine\timings\Timings;
use pocketmine\utils\TextFormat;
use pocketmine\utils\Utils;
use function array_shift;
use function count;
use function implode;
@ -80,7 +81,10 @@ use function trim;
class SimpleCommandMap implements CommandMap{
/** @var Command[] */
/**
* @var Command[]
* @phpstan-var array<string, Command>
*/
protected array $knownCommands = [];
public function __construct(private Server $server){
@ -169,7 +173,7 @@ class SimpleCommandMap implements CommandMap{
}
public function unregister(Command $command) : bool{
foreach($this->knownCommands as $lbl => $cmd){
foreach(Utils::promoteKeys($this->knownCommands) as $lbl => $cmd){
if($cmd === $command){
unset($this->knownCommands[$lbl]);
}
@ -237,6 +241,7 @@ class SimpleCommandMap implements CommandMap{
/**
* @return Command[]
* @phpstan-return array<string, Command>
*/
public function getCommands() : array{
return $this->knownCommands;
@ -245,7 +250,7 @@ class SimpleCommandMap implements CommandMap{
public function registerServerAliases() : void{
$values = $this->server->getCommandAliases();
foreach($values as $alias => $commandStrings){
foreach(Utils::stringifyKeys($values) as $alias => $commandStrings){
if(str_contains($alias, ":")){
$this->server->getLogger()->warning($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_command_alias_illegal($alias)));
continue;

View File

@ -110,14 +110,15 @@ class CraftingManager{
/**
* @param Item[] $items
* @phpstan-param list<Item> $items
*
* @return Item[]
* @phpstan-return list<Item>
*/
private static function pack(array $items) : array{
/** @var Item[] $result */
$result = [];
foreach($items as $i => $item){
foreach($items as $item){
foreach($result as $otherItem){
if($item->canStackWith($otherItem)){
$otherItem->setCount($otherItem->getCount() + $item->getCount());
@ -134,6 +135,7 @@ class CraftingManager{
/**
* @param Item[] $outputs
* @phpstan-param list<Item> $outputs
*/
private static function hashOutputs(array $outputs) : string{
$outputs = self::pack($outputs);

View File

@ -193,7 +193,7 @@ final class CraftingManagerFromDataHelper{
*/
private static function loadJsonObjectListIntoModel(\JsonMapper $mapper, string $modelClass, array $data) : array{
$result = [];
foreach($data as $i => $item){
foreach(Utils::promoteKeys($data) as $i => $item){
if(!is_object($item)){
throw new SavedDataLoadingException("Invalid entry at index $i: expected object, got " . get_debug_type($item));
}
@ -236,6 +236,7 @@ final class CraftingManagerFromDataHelper{
}
$outputs[] = $output;
}
//TODO: check unlocking requirements - our current system doesn't support this
$result->registerShapelessRecipe(new ShapelessRecipe(
$inputs,
$outputs,
@ -262,6 +263,7 @@ final class CraftingManagerFromDataHelper{
}
$outputs[] = $output;
}
//TODO: check unlocking requirements - our current system doesn't support this
$result->registerShapedRecipe(new ShapedRecipe(
$recipe->shape,
$inputs,
@ -273,7 +275,8 @@ final class CraftingManagerFromDataHelper{
"furnace" => FurnaceType::FURNACE,
"blast_furnace" => FurnaceType::BLAST_FURNACE,
"smoker" => FurnaceType::SMOKER,
//TODO: campfire
"campfire" => FurnaceType::CAMPFIRE,
"soul_campfire" => FurnaceType::SOUL_CAMPFIRE,
default => null
};
if($furnaceType === null){

View File

@ -30,6 +30,7 @@ interface CraftingRecipe{
* Returns a list of items needed to craft this recipe. This MUST NOT include Air items or items with a zero count.
*
* @return RecipeIngredient[]
* @phpstan-return list<RecipeIngredient>
*/
public function getIngredientList() : array;
@ -37,6 +38,7 @@ interface CraftingRecipe{
* Returns a list of results this recipe will produce when the inputs in the given crafting grid are consumed.
*
* @return Item[]
* @phpstan-return list<Item>
*/
public function getResultsFor(CraftingGrid $grid) : array;

View File

@ -25,6 +25,7 @@ namespace pocketmine\crafting;
use pocketmine\utils\LegacyEnumShimTrait;
use pocketmine\world\sound\BlastFurnaceSound;
use pocketmine\world\sound\CampfireSound;
use pocketmine\world\sound\FurnaceSound;
use pocketmine\world\sound\SmokerSound;
use pocketmine\world\sound\Sound;
@ -35,8 +36,10 @@ use function spl_object_id;
* These are retained for backwards compatibility only.
*
* @method static FurnaceType BLAST_FURNACE()
* @method static FurnaceType CAMPFIRE()
* @method static FurnaceType FURNACE()
* @method static FurnaceType SMOKER()
* @method static FurnaceType SOUL_CAMPFIRE()
*
* @phpstan-type TMetadata array{0: int, 1: Sound}
*/
@ -46,6 +49,8 @@ enum FurnaceType{
case FURNACE;
case BLAST_FURNACE;
case SMOKER;
case CAMPFIRE;
case SOUL_CAMPFIRE;
/**
* @phpstan-return TMetadata
@ -58,6 +63,7 @@ enum FurnaceType{
self::FURNACE => [200, new FurnaceSound()],
self::BLAST_FURNACE => [100, new BlastFurnaceSound()],
self::SMOKER => [100, new SmokerSound()],
self::CAMPFIRE, self::SOUL_CAMPFIRE => [600, new CampfireSound()]
};
}

View File

@ -32,11 +32,20 @@ use function str_contains;
use function strlen;
class ShapedRecipe implements CraftingRecipe{
/** @var string[] */
/**
* @var string[]
* @phpstan-var list<string>
*/
private array $shape = [];
/** @var RecipeIngredient[] char => RecipeIngredient map */
/**
* @var RecipeIngredient[] char => RecipeIngredient map
* @phpstan-var array<string, RecipeIngredient>
*/
private array $ingredientList = [];
/** @var Item[] */
/**
* @var Item[]
* @phpstan-var list<Item>
*/
private array $results = [];
private int $height;
@ -56,6 +65,10 @@ class ShapedRecipe implements CraftingRecipe{
* @param Item[] $results List of items that this recipe produces when crafted.
*
* Note: Recipes **do not** need to be square. Do NOT add padding for empty rows/columns.
*
* @phpstan-param list<string> $shape
* @phpstan-param array<string, RecipeIngredient> $ingredients
* @phpstan-param list<Item> $results
*/
public function __construct(array $shape, array $ingredients, array $results){
$this->height = count($shape);
@ -84,7 +97,7 @@ class ShapedRecipe implements CraftingRecipe{
$this->shape = $shape;
foreach($ingredients as $char => $i){
foreach(Utils::stringifyKeys($ingredients) as $char => $i){
if(!str_contains(implode($this->shape), $char)){
throw new \InvalidArgumentException("Symbol '$char' does not appear in the recipe shape");
}
@ -105,6 +118,7 @@ class ShapedRecipe implements CraftingRecipe{
/**
* @return Item[]
* @phpstan-return list<Item>
*/
public function getResults() : array{
return Utils::cloneObjectArray($this->results);
@ -112,6 +126,7 @@ class ShapedRecipe implements CraftingRecipe{
/**
* @return Item[]
* @phpstan-return list<Item>
*/
public function getResultsFor(CraftingGrid $grid) : array{
return $this->getResults();
@ -119,6 +134,7 @@ class ShapedRecipe implements CraftingRecipe{
/**
* @return (RecipeIngredient|null)[][]
* @phpstan-return list<list<RecipeIngredient|null>>
*/
public function getIngredientMap() : array{
$ingredients = [];
@ -132,9 +148,6 @@ class ShapedRecipe implements CraftingRecipe{
return $ingredients;
}
/**
* @return RecipeIngredient[]
*/
public function getIngredientList() : array{
$ingredients = [];
@ -157,6 +170,7 @@ class ShapedRecipe implements CraftingRecipe{
/**
* Returns an array of strings containing characters representing the recipe's shape.
* @return string[]
* @phpstan-return list<string>
*/
public function getShape() : array{
return $this->shape;

View File

@ -28,15 +28,24 @@ use pocketmine\utils\Utils;
use function count;
class ShapelessRecipe implements CraftingRecipe{
/** @var RecipeIngredient[] */
/**
* @var RecipeIngredient[]
* @phpstan-var list<RecipeIngredient>
*/
private array $ingredients = [];
/** @var Item[] */
/**
* @var Item[]
* @phpstan-var list<Item>
*/
private array $results;
private ShapelessRecipeType $type;
/**
* @param RecipeIngredient[] $ingredients No more than 9 total. This applies to sum of item stack counts, not count of array.
* @param Item[] $results List of result items created by this recipe.
*
* @phpstan-param list<RecipeIngredient> $ingredients
* @phpstan-param list<Item> $results
*/
public function __construct(array $ingredients, array $results, ShapelessRecipeType $type){
$this->type = $type;
@ -50,6 +59,7 @@ class ShapelessRecipe implements CraftingRecipe{
/**
* @return Item[]
* @phpstan-return list<Item>
*/
public function getResults() : array{
return Utils::cloneObjectArray($this->results);
@ -63,9 +73,6 @@ class ShapelessRecipe implements CraftingRecipe{
return $this->type;
}
/**
* @return RecipeIngredient[]
*/
public function getIngredientList() : array{
return $this->ingredients;
}

View File

@ -23,7 +23,9 @@ declare(strict_types=1);
namespace pocketmine\crafting\json;
final class ShapedRecipeData{
use function count;
final class ShapedRecipeData implements \JsonSerializable{
/**
* @required
* @var string[]
@ -51,22 +53,39 @@ final class ShapedRecipeData{
/** @required */
public int $priority;
/** @var RecipeIngredientData[] */
public array $unlockingIngredients = [];
/**
* TODO: convert this to use promoted properties - avoiding them for now since it would break JsonMapper
*
* @param string[] $shape
* @param RecipeIngredientData[] $input
* @param ItemStackData[] $output
* @param RecipeIngredientData[] $unlockingIngredients
*
* @phpstan-param list<string> $shape
* @phpstan-param array<string, RecipeIngredientData> $input
* @phpstan-param list<ItemStackData> $output
* @phpstan-param list<RecipeIngredientData> $unlockingIngredients
*/
public function __construct(array $shape, array $input, array $output, string $block, int $priority){
public function __construct(array $shape, array $input, array $output, string $block, int $priority, array $unlockingIngredients = []){
$this->block = $block;
$this->priority = $priority;
$this->shape = $shape;
$this->input = $input;
$this->output = $output;
$this->unlockingIngredients = $unlockingIngredients;
}
/**
* @return mixed[]
*/
public function jsonSerialize() : array{
$result = (array) $this;
if(count($this->unlockingIngredients) === 0){
unset($result["unlockingIngredients"]);
}
return $result;
}
}

View File

@ -23,7 +23,9 @@ declare(strict_types=1);
namespace pocketmine\crafting\json;
final class ShapelessRecipeData{
use function count;
final class ShapelessRecipeData implements \JsonSerializable{
/**
* @required
@ -45,17 +47,34 @@ final class ShapelessRecipeData{
/** @required */
public int $priority;
/** @var RecipeIngredientData[] */
public array $unlockingIngredients = [];
/**
* @param RecipeIngredientData[] $input
* @param ItemStackData[] $output
* @param RecipeIngredientData[] $unlockingIngredients
*
* @phpstan-param list<RecipeIngredientData> $input
* @phpstan-param list<ItemStackData> $output
* @phpstan-param list<RecipeIngredientData> $unlockingIngredients
*/
public function __construct(array $input, array $output, string $block, int $priority){
public function __construct(array $input, array $output, string $block, int $priority, array $unlockingIngredients = []){
$this->block = $block;
$this->priority = $priority;
$this->input = $input;
$this->output = $output;
$this->unlockingIngredients = $unlockingIngredients;
}
/**
* @return mixed[]
*/
public function jsonSerialize() : array{
$result = (array) $this;
if(count($this->unlockingIngredients) === 0){
unset($result["unlockingIngredients"]);
}
return $result;
}
}

View File

@ -63,6 +63,12 @@ use function strpos;
use function substr;
use function zend_version;
use function zlib_encode;
use const E_COMPILE_ERROR;
use const E_CORE_ERROR;
use const E_ERROR;
use const E_PARSE;
use const E_RECOVERABLE_ERROR;
use const E_USER_ERROR;
use const FILE_IGNORE_NEW_LINES;
use const JSON_THROW_ON_ERROR;
use const JSON_UNESCAPED_SLASHES;
@ -85,6 +91,9 @@ class CrashDump{
public const PLUGIN_INVOLVEMENT_DIRECT = "direct";
public const PLUGIN_INVOLVEMENT_INDIRECT = "indirect";
public const FATAL_ERROR_MASK =
E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR;
private CrashDumpData $data;
private string $encodedData;
@ -186,7 +195,7 @@ class CrashDump{
$error = $lastExceptionError;
}else{
$error = error_get_last();
if($error === null){
if($error === null || ($error["type"] & self::FATAL_ERROR_MASK) === 0){
throw new \RuntimeException("Crash error information missing - did something use exit()?");
}
$error["trace"] = Utils::printableTrace(Utils::currentTrace(3)); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump

View File

@ -43,7 +43,10 @@ final class CrashDumpData implements \JsonSerializable{
public string $plugin = "";
/** @var string[] */
/**
* @var string[]
* @phpstan-var array<int, string>
*/
public array $code = [];
/** @var string[] */
@ -55,7 +58,10 @@ final class CrashDumpData implements \JsonSerializable{
*/
public array $plugins = [];
/** @var string[] */
/**
* @var string[]
* @phpstan-var list<string>
*/
public array $parameters = [];
public string $serverDotProperties = "";

View File

@ -56,13 +56,17 @@ final class BannerPatternTypeIdMap{
BannerPatternType::DIAGONAL_UP_LEFT => "ld",
BannerPatternType::DIAGONAL_UP_RIGHT => "rud",
BannerPatternType::FLOWER => "flo",
BannerPatternType::FLOW => "flw",
BannerPatternType::GLOBE => "glb",
BannerPatternType::GRADIENT => "gra",
BannerPatternType::GRADIENT_UP => "gru",
BannerPatternType::GUSTER => "gus",
BannerPatternType::HALF_HORIZONTAL => "hh",
BannerPatternType::HALF_HORIZONTAL_BOTTOM => "hhb",
BannerPatternType::HALF_VERTICAL => "vh",
BannerPatternType::HALF_VERTICAL_RIGHT => "vhr",
BannerPatternType::MOJANG => "moj",
BannerPatternType::PIGLIN => "pig",
BannerPatternType::RHOMBUS => "mr",
BannerPatternType::SKULL => "sku",
BannerPatternType::SMALL_STRIPES => "ss",

View File

@ -35,6 +35,7 @@ final class BedrockDataFiles{
public const BIOME_DEFINITIONS_FULL_NBT = BEDROCK_DATA_PATH . '/biome_definitions_full.nbt';
public const BIOME_ID_MAP_JSON = BEDROCK_DATA_PATH . '/biome_id_map.json';
public const BLOCK_ID_TO_ITEM_ID_MAP_JSON = BEDROCK_DATA_PATH . '/block_id_to_item_id_map.json';
public const BLOCK_PROPERTIES_TABLE_JSON = BEDROCK_DATA_PATH . '/block_properties_table.json';
public const BLOCK_STATE_META_MAP_JSON = BEDROCK_DATA_PATH . '/block_state_meta_map.json';
public const CANONICAL_BLOCK_STATES_NBT = BEDROCK_DATA_PATH . '/canonical_block_states.nbt';
public const COMMAND_ARG_TYPES_JSON = BEDROCK_DATA_PATH . '/command_arg_types.json';
@ -44,6 +45,7 @@ final class BedrockDataFiles{
public const ITEM_TAGS_JSON = BEDROCK_DATA_PATH . '/item_tags.json';
public const LEVEL_SOUND_ID_MAP_JSON = BEDROCK_DATA_PATH . '/level_sound_id_map.json';
public const PARTICLE_ID_MAP_JSON = BEDROCK_DATA_PATH . '/particle_id_map.json';
public const PROTOCOL_INFO_JSON = BEDROCK_DATA_PATH . '/protocol_info.json';
public const R12_TO_CURRENT_BLOCK_MAP_BIN = BEDROCK_DATA_PATH . '/r12_to_current_block_map.bin';
public const R16_TO_CURRENT_ITEM_MAP_JSON = BEDROCK_DATA_PATH . '/r16_to_current_item_map.json';
public const REQUIRED_ITEM_LIST_JSON = BEDROCK_DATA_PATH . '/required_item_list.json';

View File

@ -122,4 +122,5 @@ final class BiomeIds{
public const DEEP_DARK = 190;
public const MANGROVE_SWAMP = 191;
public const CHERRY_GROVE = 192;
public const PALE_GARDEN = 193;
}

View File

@ -43,6 +43,7 @@ final class EnchantmentIdMap{
$this->register(EnchantmentIds::PROJECTILE_PROTECTION, VanillaEnchantments::PROJECTILE_PROTECTION());
$this->register(EnchantmentIds::THORNS, VanillaEnchantments::THORNS());
$this->register(EnchantmentIds::RESPIRATION, VanillaEnchantments::RESPIRATION());
$this->register(EnchantmentIds::AQUA_AFFINITY, VanillaEnchantments::AQUA_AFFINITY());
$this->register(EnchantmentIds::SHARPNESS, VanillaEnchantments::SHARPNESS());
//TODO: smite, bane of arthropods (these don't make sense now because their applicable mobs don't exist yet)

View File

@ -48,7 +48,7 @@ final class ItemTagToIdMap{
throw new AssumptionFailedError("Invalid item tag map, expected array");
}
$cleanMap = [];
foreach($map as $tagName => $ids){
foreach(Utils::promoteKeys($map) as $tagName => $ids){
if(!is_string($tagName)){
throw new AssumptionFailedError("Invalid item tag name $tagName, expected string as key");
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\data\bedrock;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Filesystem;
use pocketmine\utils\Utils;
use function is_array;
use function is_int;
use function is_string;
@ -43,7 +44,7 @@ abstract class LegacyToStringIdMap{
if(!is_array($stringToLegacyId)){
throw new AssumptionFailedError("Invalid format of ID map");
}
foreach($stringToLegacyId as $stringId => $legacyId){
foreach(Utils::promoteKeys($stringToLegacyId) as $stringId => $legacyId){
if(!is_string($stringId) || !is_int($legacyId)){
throw new AssumptionFailedError("ID map should have string keys and int values");
}

View File

@ -38,11 +38,14 @@ use function implode;
final class BlockStateData{
/**
* Bedrock version of the most recent backwards-incompatible change to blockstates.
*
* This is *not* the same as current game version. It should match the numbers in the
* newest blockstate upgrade schema used in BedrockBlockUpgradeSchema.
*/
public const CURRENT_VERSION =
(1 << 24) | //major
(20 << 16) | //minor
(60 << 8) | //patch
(21 << 16) | //minor
(40 << 8) | //patch
(1); //revision
public const TAG_NAME = "name";

View File

@ -34,7 +34,6 @@ final class BlockStateNames{
public const ACTIVE = "active";
public const AGE = "age";
public const AGE_BIT = "age_bit";
public const ALLOW_UNDERWATER_BIT = "allow_underwater_bit";
public const ATTACHED_BIT = "attached_bit";
public const ATTACHMENT = "attachment";
public const BAMBOO_LEAF_SIZE = "bamboo_leaf_size";
@ -42,7 +41,6 @@ final class BlockStateNames{
public const BIG_DRIPLEAF_HEAD = "big_dripleaf_head";
public const BIG_DRIPLEAF_TILT = "big_dripleaf_tilt";
public const BITE_COUNTER = "bite_counter";
public const BLOCK_LIGHT_LEVEL = "block_light_level";
public const BLOOM = "bloom";
public const BOOKS_STORED = "books_stored";
public const BREWING_STAND_SLOT_A_BIT = "brewing_stand_slot_a_bit";
@ -53,27 +51,19 @@ final class BlockStateNames{
public const CAN_SUMMON = "can_summon";
public const CANDLES = "candles";
public const CAULDRON_LIQUID = "cauldron_liquid";
public const CHEMISTRY_TABLE_TYPE = "chemistry_table_type";
public const CHISEL_TYPE = "chisel_type";
public const CLUSTER_COUNT = "cluster_count";
public const COLOR_BIT = "color_bit";
public const COMPOSTER_FILL_LEVEL = "composter_fill_level";
public const CONDITIONAL_BIT = "conditional_bit";
public const CORAL_COLOR = "coral_color";
public const CORAL_DIRECTION = "coral_direction";
public const CORAL_FAN_DIRECTION = "coral_fan_direction";
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";
public const DIRECTION = "direction";
public const DIRT_TYPE = "dirt_type";
public const DISARMED_BIT = "disarmed_bit";
public const DOOR_HINGE_BIT = "door_hinge_bit";
public const DOUBLE_PLANT_TYPE = "double_plant_type";
public const DRAG_DOWN = "drag_down";
public const DRIPSTONE_THICKNESS = "dripstone_thickness";
public const END_PORTAL_EYE_BIT = "end_portal_eye_bit";
@ -81,7 +71,6 @@ final class BlockStateNames{
public const EXTINGUISHED = "extinguished";
public const FACING_DIRECTION = "facing_direction";
public const FILL_LEVEL = "fill_level";
public const FLOWER_TYPE = "flower_type";
public const GROUND_SIGN_DIRECTION = "ground_sign_direction";
public const GROWING_PLANT_AGE = "growing_plant_age";
public const GROWTH = "growth";
@ -103,20 +92,22 @@ final class BlockStateNames{
public const MC_FACING_DIRECTION = "minecraft:facing_direction";
public const MC_VERTICAL_HALF = "minecraft:vertical_half";
public const MOISTURIZED_AMOUNT = "moisturized_amount";
public const MONSTER_EGG_STONE_TYPE = "monster_egg_stone_type";
public const MULTI_FACE_DIRECTION_BITS = "multi_face_direction_bits";
public const NEW_LEAF_TYPE = "new_leaf_type";
public const NATURAL = "natural";
public const OCCUPIED_BIT = "occupied_bit";
public const OLD_LEAF_TYPE = "old_leaf_type";
public const OMINOUS = "ominous";
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 PALE_MOSS_CARPET_SIDE_EAST = "pale_moss_carpet_side_east";
public const PALE_MOSS_CARPET_SIDE_NORTH = "pale_moss_carpet_side_north";
public const PALE_MOSS_CARPET_SIDE_SOUTH = "pale_moss_carpet_side_south";
public const PALE_MOSS_CARPET_SIDE_WEST = "pale_moss_carpet_side_west";
public const PERSISTENT_BIT = "persistent_bit";
public const PILLAR_AXIS = "pillar_axis";
public const PORTAL_AXIS = "portal_axis";
public const POWERED_BIT = "powered_bit";
public const PRISMARINE_BLOCK_TYPE = "prismarine_block_type";
public const PROPAGULE_STAGE = "propagule_stage";
public const RAIL_DATA_BIT = "rail_data_bit";
public const RAIL_DIRECTION = "rail_direction";
@ -124,24 +115,13 @@ final class BlockStateNames{
public const REPEATER_DELAY = "repeater_delay";
public const RESPAWN_ANCHOR_CHARGE = "respawn_anchor_charge";
public const ROTATION = "rotation";
public const SAND_STONE_TYPE = "sand_stone_type";
public const SAND_TYPE = "sand_type";
public const SAPLING_TYPE = "sapling_type";
public const SCULK_SENSOR_PHASE = "sculk_sensor_phase";
public const SEA_GRASS_TYPE = "sea_grass_type";
public const SPONGE_TYPE = "sponge_type";
public const STABILITY = "stability";
public const STABILITY_CHECK = "stability_check";
public const STONE_BRICK_TYPE = "stone_brick_type";
public const STONE_SLAB_TYPE = "stone_slab_type";
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 STRIPPED_BIT = "stripped_bit";
public const STRUCTURE_BLOCK_TYPE = "structure_block_type";
public const STRUCTURE_VOID_TYPE = "structure_void_type";
public const SUSPENDED_BIT = "suspended_bit";
public const TALL_GRASS_TYPE = "tall_grass_type";
public const TIP = "tip";
public const TOGGLE_BIT = "toggle_bit";
public const TORCH_FACING_DIRECTION = "torch_facing_direction";
public const TRIAL_SPAWNER_STATE = "trial_spawner_state";
@ -151,8 +131,8 @@ final class BlockStateNames{
public const UPDATE_BIT = "update_bit";
public const UPPER_BLOCK_BIT = "upper_block_bit";
public const UPSIDE_DOWN_BIT = "upside_down_bit";
public const VAULT_STATE = "vault_state";
public const VINE_DIRECTION_BITS = "vine_direction_bits";
public const WALL_BLOCK_TYPE = "wall_block_type";
public const WALL_CONNECTION_TYPE_EAST = "wall_connection_type_east";
public const WALL_CONNECTION_TYPE_NORTH = "wall_connection_type_north";
public const WALL_CONNECTION_TYPE_SOUTH = "wall_connection_type_south";
@ -160,5 +140,4 @@ final class BlockStateNames{
public const WALL_POST_BIT = "wall_post_bit";
public const WEEPING_VINES_AGE = "weeping_vines_age";
public const WEIRDO_DIRECTION = "weirdo_direction";
public const WOOD_TYPE = "wood_type";
}

View File

@ -52,59 +52,16 @@ final class BlockStateStringValues{
public const CAULDRON_LIQUID_POWDER_SNOW = "powder_snow";
public const CAULDRON_LIQUID_WATER = "water";
public const CHEMISTRY_TABLE_TYPE_COMPOUND_CREATOR = "compound_creator";
public const CHEMISTRY_TABLE_TYPE_ELEMENT_CONSTRUCTOR = "element_constructor";
public const CHEMISTRY_TABLE_TYPE_LAB_TABLE = "lab_table";
public const CHEMISTRY_TABLE_TYPE_MATERIAL_REDUCER = "material_reducer";
public const CHISEL_TYPE_CHISELED = "chiseled";
public const CHISEL_TYPE_DEFAULT = "default";
public const CHISEL_TYPE_LINES = "lines";
public const CHISEL_TYPE_SMOOTH = "smooth";
public const CORAL_COLOR_BLUE = "blue";
public const CORAL_COLOR_PINK = "pink";
public const CORAL_COLOR_PURPLE = "purple";
public const CORAL_COLOR_RED = "red";
public const CORAL_COLOR_YELLOW = "yellow";
public const CRACKED_STATE_CRACKED = "cracked";
public const CRACKED_STATE_MAX_CRACKED = "max_cracked";
public const CRACKED_STATE_NO_CRACKS = "no_cracks";
public const DAMAGE_BROKEN = "broken";
public const DAMAGE_SLIGHTLY_DAMAGED = "slightly_damaged";
public const DAMAGE_UNDAMAGED = "undamaged";
public const DAMAGE_VERY_DAMAGED = "very_damaged";
public const DIRT_TYPE_COARSE = "coarse";
public const DIRT_TYPE_NORMAL = "normal";
public const DOUBLE_PLANT_TYPE_FERN = "fern";
public const DOUBLE_PLANT_TYPE_GRASS = "grass";
public const DOUBLE_PLANT_TYPE_PAEONIA = "paeonia";
public const DOUBLE_PLANT_TYPE_ROSE = "rose";
public const DOUBLE_PLANT_TYPE_SUNFLOWER = "sunflower";
public const DOUBLE_PLANT_TYPE_SYRINGA = "syringa";
public const DRIPSTONE_THICKNESS_BASE = "base";
public const DRIPSTONE_THICKNESS_FRUSTUM = "frustum";
public const DRIPSTONE_THICKNESS_MERGE = "merge";
public const DRIPSTONE_THICKNESS_MIDDLE = "middle";
public const DRIPSTONE_THICKNESS_TIP = "tip";
public const FLOWER_TYPE_ALLIUM = "allium";
public const FLOWER_TYPE_CORNFLOWER = "cornflower";
public const FLOWER_TYPE_HOUSTONIA = "houstonia";
public const FLOWER_TYPE_LILY_OF_THE_VALLEY = "lily_of_the_valley";
public const FLOWER_TYPE_ORCHID = "orchid";
public const FLOWER_TYPE_OXEYE = "oxeye";
public const FLOWER_TYPE_POPPY = "poppy";
public const FLOWER_TYPE_TULIP_ORANGE = "tulip_orange";
public const FLOWER_TYPE_TULIP_PINK = "tulip_pink";
public const FLOWER_TYPE_TULIP_RED = "tulip_red";
public const FLOWER_TYPE_TULIP_WHITE = "tulip_white";
public const LEVER_DIRECTION_DOWN_EAST_WEST = "down_east_west";
public const LEVER_DIRECTION_DOWN_NORTH_SOUTH = "down_north_south";
public const LEVER_DIRECTION_EAST = "east";
@ -136,21 +93,6 @@ final class BlockStateStringValues{
public const MC_VERTICAL_HALF_BOTTOM = "bottom";
public const MC_VERTICAL_HALF_TOP = "top";
public const MONSTER_EGG_STONE_TYPE_CHISELED_STONE_BRICK = "chiseled_stone_brick";
public const MONSTER_EGG_STONE_TYPE_COBBLESTONE = "cobblestone";
public const MONSTER_EGG_STONE_TYPE_CRACKED_STONE_BRICK = "cracked_stone_brick";
public const MONSTER_EGG_STONE_TYPE_MOSSY_STONE_BRICK = "mossy_stone_brick";
public const MONSTER_EGG_STONE_TYPE_STONE = "stone";
public const MONSTER_EGG_STONE_TYPE_STONE_BRICK = "stone_brick";
public const NEW_LEAF_TYPE_ACACIA = "acacia";
public const NEW_LEAF_TYPE_DARK_OAK = "dark_oak";
public const OLD_LEAF_TYPE_BIRCH = "birch";
public const OLD_LEAF_TYPE_JUNGLE = "jungle";
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";
@ -164,6 +106,22 @@ final class BlockStateStringValues{
public const ORIENTATION_UP_WEST = "up_west";
public const ORIENTATION_WEST_UP = "west_up";
public const PALE_MOSS_CARPET_SIDE_EAST_NONE = "none";
public const PALE_MOSS_CARPET_SIDE_EAST_SHORT = "short";
public const PALE_MOSS_CARPET_SIDE_EAST_TALL = "tall";
public const PALE_MOSS_CARPET_SIDE_NORTH_NONE = "none";
public const PALE_MOSS_CARPET_SIDE_NORTH_SHORT = "short";
public const PALE_MOSS_CARPET_SIDE_NORTH_TALL = "tall";
public const PALE_MOSS_CARPET_SIDE_SOUTH_NONE = "none";
public const PALE_MOSS_CARPET_SIDE_SOUTH_SHORT = "short";
public const PALE_MOSS_CARPET_SIDE_SOUTH_TALL = "tall";
public const PALE_MOSS_CARPET_SIDE_WEST_NONE = "none";
public const PALE_MOSS_CARPET_SIDE_WEST_SHORT = "short";
public const PALE_MOSS_CARPET_SIDE_WEST_TALL = "tall";
public const PILLAR_AXIS_X = "x";
public const PILLAR_AXIS_Y = "y";
public const PILLAR_AXIS_Z = "z";
@ -172,71 +130,10 @@ final class BlockStateStringValues{
public const PORTAL_AXIS_X = "x";
public const PORTAL_AXIS_Z = "z";
public const PRISMARINE_BLOCK_TYPE_BRICKS = "bricks";
public const PRISMARINE_BLOCK_TYPE_DARK = "dark";
public const PRISMARINE_BLOCK_TYPE_DEFAULT = "default";
public const SAND_STONE_TYPE_CUT = "cut";
public const SAND_STONE_TYPE_DEFAULT = "default";
public const SAND_STONE_TYPE_HEIROGLYPHS = "heiroglyphs";
public const SAND_STONE_TYPE_SMOOTH = "smooth";
public const SAND_TYPE_NORMAL = "normal";
public const SAND_TYPE_RED = "red";
public const SAPLING_TYPE_ACACIA = "acacia";
public const SAPLING_TYPE_BIRCH = "birch";
public const SAPLING_TYPE_DARK_OAK = "dark_oak";
public const SAPLING_TYPE_JUNGLE = "jungle";
public const SAPLING_TYPE_OAK = "oak";
public const SAPLING_TYPE_SPRUCE = "spruce";
public const SEA_GRASS_TYPE_DEFAULT = "default";
public const SEA_GRASS_TYPE_DOUBLE_BOT = "double_bot";
public const SEA_GRASS_TYPE_DOUBLE_TOP = "double_top";
public const SPONGE_TYPE_DRY = "dry";
public const SPONGE_TYPE_WET = "wet";
public const STONE_BRICK_TYPE_CHISELED = "chiseled";
public const STONE_BRICK_TYPE_CRACKED = "cracked";
public const STONE_BRICK_TYPE_DEFAULT = "default";
public const STONE_BRICK_TYPE_MOSSY = "mossy";
public const STONE_BRICK_TYPE_SMOOTH = "smooth";
public const STONE_SLAB_TYPE_BRICK = "brick";
public const STONE_SLAB_TYPE_COBBLESTONE = "cobblestone";
public const STONE_SLAB_TYPE_NETHER_BRICK = "nether_brick";
public const STONE_SLAB_TYPE_QUARTZ = "quartz";
public const STONE_SLAB_TYPE_SANDSTONE = "sandstone";
public const STONE_SLAB_TYPE_SMOOTH_STONE = "smooth_stone";
public const STONE_SLAB_TYPE_STONE_BRICK = "stone_brick";
public const STONE_SLAB_TYPE_WOOD = "wood";
public const STONE_SLAB_TYPE_2_MOSSY_COBBLESTONE = "mossy_cobblestone";
public const STONE_SLAB_TYPE_2_PRISMARINE_BRICK = "prismarine_brick";
public const STONE_SLAB_TYPE_2_PRISMARINE_DARK = "prismarine_dark";
public const STONE_SLAB_TYPE_2_PRISMARINE_ROUGH = "prismarine_rough";
public const STONE_SLAB_TYPE_2_PURPUR = "purpur";
public const STONE_SLAB_TYPE_2_RED_NETHER_BRICK = "red_nether_brick";
public const STONE_SLAB_TYPE_2_RED_SANDSTONE = "red_sandstone";
public const STONE_SLAB_TYPE_2_SMOOTH_SANDSTONE = "smooth_sandstone";
public const STONE_SLAB_TYPE_3_ANDESITE = "andesite";
public const STONE_SLAB_TYPE_3_DIORITE = "diorite";
public const STONE_SLAB_TYPE_3_END_STONE_BRICK = "end_stone_brick";
public const STONE_SLAB_TYPE_3_GRANITE = "granite";
public const STONE_SLAB_TYPE_3_POLISHED_ANDESITE = "polished_andesite";
public const STONE_SLAB_TYPE_3_POLISHED_DIORITE = "polished_diorite";
public const STONE_SLAB_TYPE_3_POLISHED_GRANITE = "polished_granite";
public const STONE_SLAB_TYPE_3_SMOOTH_RED_SANDSTONE = "smooth_red_sandstone";
public const STONE_SLAB_TYPE_4_CUT_RED_SANDSTONE = "cut_red_sandstone";
public const STONE_SLAB_TYPE_4_CUT_SANDSTONE = "cut_sandstone";
public const STONE_SLAB_TYPE_4_MOSSY_STONE_BRICK = "mossy_stone_brick";
public const STONE_SLAB_TYPE_4_SMOOTH_QUARTZ = "smooth_quartz";
public const STONE_SLAB_TYPE_4_STONE = "stone";
public const STRUCTURE_BLOCK_TYPE_CORNER = "corner";
public const STRUCTURE_BLOCK_TYPE_DATA = "data";
public const STRUCTURE_BLOCK_TYPE_EXPORT = "export";
@ -244,14 +141,6 @@ final class BlockStateStringValues{
public const STRUCTURE_BLOCK_TYPE_LOAD = "load";
public const STRUCTURE_BLOCK_TYPE_SAVE = "save";
public const STRUCTURE_VOID_TYPE_AIR = "air";
public const STRUCTURE_VOID_TYPE_VOID = "void";
public const TALL_GRASS_TYPE_DEFAULT = "default";
public const TALL_GRASS_TYPE_FERN = "fern";
public const TALL_GRASS_TYPE_SNOW = "snow";
public const TALL_GRASS_TYPE_TALL = "tall";
public const TORCH_FACING_DIRECTION_EAST = "east";
public const TORCH_FACING_DIRECTION_NORTH = "north";
public const TORCH_FACING_DIRECTION_SOUTH = "south";
@ -264,20 +153,10 @@ final class BlockStateStringValues{
public const TURTLE_EGG_COUNT_THREE_EGG = "three_egg";
public const TURTLE_EGG_COUNT_TWO_EGG = "two_egg";
public const WALL_BLOCK_TYPE_ANDESITE = "andesite";
public const WALL_BLOCK_TYPE_BRICK = "brick";
public const WALL_BLOCK_TYPE_COBBLESTONE = "cobblestone";
public const WALL_BLOCK_TYPE_DIORITE = "diorite";
public const WALL_BLOCK_TYPE_END_BRICK = "end_brick";
public const WALL_BLOCK_TYPE_GRANITE = "granite";
public const WALL_BLOCK_TYPE_MOSSY_COBBLESTONE = "mossy_cobblestone";
public const WALL_BLOCK_TYPE_MOSSY_STONE_BRICK = "mossy_stone_brick";
public const WALL_BLOCK_TYPE_NETHER_BRICK = "nether_brick";
public const WALL_BLOCK_TYPE_PRISMARINE = "prismarine";
public const WALL_BLOCK_TYPE_RED_NETHER_BRICK = "red_nether_brick";
public const WALL_BLOCK_TYPE_RED_SANDSTONE = "red_sandstone";
public const WALL_BLOCK_TYPE_SANDSTONE = "sandstone";
public const WALL_BLOCK_TYPE_STONE_BRICK = "stone_brick";
public const VAULT_STATE_ACTIVE = "active";
public const VAULT_STATE_EJECTING = "ejecting";
public const VAULT_STATE_INACTIVE = "inactive";
public const VAULT_STATE_UNLOCKING = "unlocking";
public const WALL_CONNECTION_TYPE_EAST_NONE = "none";
public const WALL_CONNECTION_TYPE_EAST_SHORT = "short";
@ -295,11 +174,4 @@ final class BlockStateStringValues{
public const WALL_CONNECTION_TYPE_WEST_SHORT = "short";
public const WALL_CONNECTION_TYPE_WEST_TALL = "tall";
public const WOOD_TYPE_ACACIA = "acacia";
public const WOOD_TYPE_BIRCH = "birch";
public const WOOD_TYPE_DARK_OAK = "dark_oak";
public const WOOD_TYPE_JUNGLE = "jungle";
public const WOOD_TYPE_OAK = "oak";
public const WOOD_TYPE_SPRUCE = "spruce";
}

View File

@ -33,28 +33,38 @@ final class BlockTypeNames{
public const ACACIA_BUTTON = "minecraft:acacia_button";
public const ACACIA_DOOR = "minecraft:acacia_door";
public const ACACIA_DOUBLE_SLAB = "minecraft:acacia_double_slab";
public const ACACIA_FENCE = "minecraft:acacia_fence";
public const ACACIA_FENCE_GATE = "minecraft:acacia_fence_gate";
public const ACACIA_HANGING_SIGN = "minecraft:acacia_hanging_sign";
public const ACACIA_LEAVES = "minecraft:acacia_leaves";
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_SAPLING = "minecraft:acacia_sapling";
public const ACACIA_SLAB = "minecraft:acacia_slab";
public const ACACIA_STAIRS = "minecraft:acacia_stairs";
public const ACACIA_STANDING_SIGN = "minecraft:acacia_standing_sign";
public const ACACIA_TRAPDOOR = "minecraft:acacia_trapdoor";
public const ACACIA_WALL_SIGN = "minecraft:acacia_wall_sign";
public const ACACIA_WOOD = "minecraft:acacia_wood";
public const ACTIVATOR_RAIL = "minecraft:activator_rail";
public const AIR = "minecraft:air";
public const ALLIUM = "minecraft:allium";
public const ALLOW = "minecraft:allow";
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_DOUBLE_SLAB = "minecraft:andesite_double_slab";
public const ANDESITE_SLAB = "minecraft:andesite_slab";
public const ANDESITE_STAIRS = "minecraft:andesite_stairs";
public const ANDESITE_WALL = "minecraft:andesite_wall";
public const ANVIL = "minecraft:anvil";
public const AZALEA = "minecraft:azalea";
public const AZALEA_LEAVES = "minecraft:azalea_leaves";
public const AZALEA_LEAVES_FLOWERED = "minecraft:azalea_leaves_flowered";
public const AZURE_BLUET = "minecraft:azure_bluet";
public const BAMBOO = "minecraft:bamboo";
public const BAMBOO_BLOCK = "minecraft:bamboo_block";
public const BAMBOO_BUTTON = "minecraft:bamboo_button";
@ -88,16 +98,21 @@ final class BlockTypeNames{
public const BIG_DRIPLEAF = "minecraft:big_dripleaf";
public const BIRCH_BUTTON = "minecraft:birch_button";
public const BIRCH_DOOR = "minecraft:birch_door";
public const BIRCH_DOUBLE_SLAB = "minecraft:birch_double_slab";
public const BIRCH_FENCE = "minecraft:birch_fence";
public const BIRCH_FENCE_GATE = "minecraft:birch_fence_gate";
public const BIRCH_HANGING_SIGN = "minecraft:birch_hanging_sign";
public const BIRCH_LEAVES = "minecraft:birch_leaves";
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_SAPLING = "minecraft:birch_sapling";
public const BIRCH_SLAB = "minecraft:birch_slab";
public const BIRCH_STAIRS = "minecraft:birch_stairs";
public const BIRCH_STANDING_SIGN = "minecraft:birch_standing_sign";
public const BIRCH_TRAPDOOR = "minecraft:birch_trapdoor";
public const BIRCH_WALL_SIGN = "minecraft:birch_wall_sign";
public const BIRCH_WOOD = "minecraft:birch_wood";
public const BLACK_CANDLE = "minecraft:black_candle";
public const BLACK_CANDLE_CAKE = "minecraft:black_candle_cake";
public const BLACK_CARPET = "minecraft:black_carpet";
@ -122,6 +137,7 @@ final class BlockTypeNames{
public const BLUE_CONCRETE_POWDER = "minecraft:blue_concrete_powder";
public const BLUE_GLAZED_TERRACOTTA = "minecraft:blue_glazed_terracotta";
public const BLUE_ICE = "minecraft:blue_ice";
public const BLUE_ORCHID = "minecraft:blue_orchid";
public const BLUE_SHULKER_BOX = "minecraft:blue_shulker_box";
public const BLUE_STAINED_GLASS = "minecraft:blue_stained_glass";
public const BLUE_STAINED_GLASS_PANE = "minecraft:blue_stained_glass_pane";
@ -131,9 +147,15 @@ final class BlockTypeNames{
public const BOOKSHELF = "minecraft:bookshelf";
public const BORDER_BLOCK = "minecraft:border_block";
public const BRAIN_CORAL = "minecraft:brain_coral";
public const BRAIN_CORAL_BLOCK = "minecraft:brain_coral_block";
public const BRAIN_CORAL_FAN = "minecraft:brain_coral_fan";
public const BRAIN_CORAL_WALL_FAN = "minecraft:brain_coral_wall_fan";
public const BREWING_STAND = "minecraft:brewing_stand";
public const BRICK_BLOCK = "minecraft:brick_block";
public const BRICK_DOUBLE_SLAB = "minecraft:brick_double_slab";
public const BRICK_SLAB = "minecraft:brick_slab";
public const BRICK_STAIRS = "minecraft:brick_stairs";
public const BRICK_WALL = "minecraft:brick_wall";
public const BROWN_CANDLE = "minecraft:brown_candle";
public const BROWN_CANDLE_CAKE = "minecraft:brown_candle_cake";
public const BROWN_CARPET = "minecraft:brown_carpet";
@ -149,6 +171,9 @@ final class BlockTypeNames{
public const BROWN_WOOL = "minecraft:brown_wool";
public const BUBBLE_COLUMN = "minecraft:bubble_column";
public const BUBBLE_CORAL = "minecraft:bubble_coral";
public const BUBBLE_CORAL_BLOCK = "minecraft:bubble_coral_block";
public const BUBBLE_CORAL_FAN = "minecraft:bubble_coral_fan";
public const BUBBLE_CORAL_WALL_FAN = "minecraft:bubble_coral_wall_fan";
public const BUDDING_AMETHYST = "minecraft:budding_amethyst";
public const CACTUS = "minecraft:cactus";
public const CAKE = "minecraft:cake";
@ -167,8 +192,8 @@ final class BlockTypeNames{
public const CAVE_VINES_HEAD_WITH_BERRIES = "minecraft:cave_vines_head_with_berries";
public const CHAIN = "minecraft:chain";
public const CHAIN_COMMAND_BLOCK = "minecraft:chain_command_block";
public const CHALKBOARD = "minecraft:chalkboard";
public const CHEMICAL_HEAT = "minecraft:chemical_heat";
public const CHEMISTRY_TABLE = "minecraft:chemistry_table";
public const CHERRY_BUTTON = "minecraft:cherry_button";
public const CHERRY_DOOR = "minecraft:cherry_door";
public const CHERRY_DOUBLE_SLAB = "minecraft:cherry_double_slab";
@ -187,31 +212,44 @@ final class BlockTypeNames{
public const CHERRY_WALL_SIGN = "minecraft:cherry_wall_sign";
public const CHERRY_WOOD = "minecraft:cherry_wood";
public const CHEST = "minecraft:chest";
public const CHIPPED_ANVIL = "minecraft:chipped_anvil";
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_QUARTZ_BLOCK = "minecraft:chiseled_quartz_block";
public const CHISELED_RED_SANDSTONE = "minecraft:chiseled_red_sandstone";
public const CHISELED_RESIN_BRICKS = "minecraft:chiseled_resin_bricks";
public const CHISELED_SANDSTONE = "minecraft:chiseled_sandstone";
public const CHISELED_STONE_BRICKS = "minecraft:chiseled_stone_bricks";
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";
public const CLIENT_REQUEST_PLACEHOLDER_BLOCK = "minecraft:client_request_placeholder_block";
public const CLOSED_EYEBLOSSOM = "minecraft:closed_eyeblossom";
public const COAL_BLOCK = "minecraft:coal_block";
public const COAL_ORE = "minecraft:coal_ore";
public const COARSE_DIRT = "minecraft:coarse_dirt";
public const COBBLED_DEEPSLATE = "minecraft:cobbled_deepslate";
public const COBBLED_DEEPSLATE_DOUBLE_SLAB = "minecraft:cobbled_deepslate_double_slab";
public const COBBLED_DEEPSLATE_SLAB = "minecraft:cobbled_deepslate_slab";
public const COBBLED_DEEPSLATE_STAIRS = "minecraft:cobbled_deepslate_stairs";
public const COBBLED_DEEPSLATE_WALL = "minecraft:cobbled_deepslate_wall";
public const COBBLESTONE = "minecraft:cobblestone";
public const COBBLESTONE_DOUBLE_SLAB = "minecraft:cobblestone_double_slab";
public const COBBLESTONE_SLAB = "minecraft:cobblestone_slab";
public const COBBLESTONE_WALL = "minecraft:cobblestone_wall";
public const COCOA = "minecraft:cocoa";
public const COLORED_TORCH_BP = "minecraft:colored_torch_bp";
public const COLORED_TORCH_RG = "minecraft:colored_torch_rg";
public const COLORED_TORCH_BLUE = "minecraft:colored_torch_blue";
public const COLORED_TORCH_GREEN = "minecraft:colored_torch_green";
public const COLORED_TORCH_PURPLE = "minecraft:colored_torch_purple";
public const COLORED_TORCH_RED = "minecraft:colored_torch_red";
public const COMMAND_BLOCK = "minecraft:command_block";
public const COMPOSTER = "minecraft:composter";
public const COMPOUND_CREATOR = "minecraft:compound_creator";
public const CONDUIT = "minecraft:conduit";
public const COPPER_BLOCK = "minecraft:copper_block";
public const COPPER_BULB = "minecraft:copper_bulb";
@ -219,18 +257,16 @@ final class BlockTypeNames{
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";
public const CORAL_FAN_HANG = "minecraft:coral_fan_hang";
public const CORAL_FAN_HANG2 = "minecraft:coral_fan_hang2";
public const CORAL_FAN_HANG3 = "minecraft:coral_fan_hang3";
public const CORNFLOWER = "minecraft:cornflower";
public const CRACKED_DEEPSLATE_BRICKS = "minecraft:cracked_deepslate_bricks";
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 CRACKED_STONE_BRICKS = "minecraft:cracked_stone_bricks";
public const CRAFTER = "minecraft:crafter";
public const CRAFTING_TABLE = "minecraft:crafting_table";
public const CREAKING_HEART = "minecraft:creaking_heart";
public const CREEPER_HEAD = "minecraft:creeper_head";
public const CRIMSON_BUTTON = "minecraft:crimson_button";
public const CRIMSON_DOOR = "minecraft:crimson_door";
public const CRIMSON_DOUBLE_SLAB = "minecraft:crimson_double_slab";
@ -253,6 +289,12 @@ final class BlockTypeNames{
public const CUT_COPPER = "minecraft:cut_copper";
public const CUT_COPPER_SLAB = "minecraft:cut_copper_slab";
public const CUT_COPPER_STAIRS = "minecraft:cut_copper_stairs";
public const CUT_RED_SANDSTONE = "minecraft:cut_red_sandstone";
public const CUT_RED_SANDSTONE_DOUBLE_SLAB = "minecraft:cut_red_sandstone_double_slab";
public const CUT_RED_SANDSTONE_SLAB = "minecraft:cut_red_sandstone_slab";
public const CUT_SANDSTONE = "minecraft:cut_sandstone";
public const CUT_SANDSTONE_DOUBLE_SLAB = "minecraft:cut_sandstone_double_slab";
public const CUT_SANDSTONE_SLAB = "minecraft:cut_sandstone_slab";
public const CYAN_CANDLE = "minecraft:cyan_candle";
public const CYAN_CANDLE_CAKE = "minecraft:cyan_candle_cake";
public const CYAN_CARPET = "minecraft:cyan_carpet";
@ -264,26 +306,51 @@ final class BlockTypeNames{
public const CYAN_STAINED_GLASS_PANE = "minecraft:cyan_stained_glass_pane";
public const CYAN_TERRACOTTA = "minecraft:cyan_terracotta";
public const CYAN_WOOL = "minecraft:cyan_wool";
public const DAMAGED_ANVIL = "minecraft:damaged_anvil";
public const DANDELION = "minecraft:dandelion";
public const DARK_OAK_BUTTON = "minecraft:dark_oak_button";
public const DARK_OAK_DOOR = "minecraft:dark_oak_door";
public const DARK_OAK_DOUBLE_SLAB = "minecraft:dark_oak_double_slab";
public const DARK_OAK_FENCE = "minecraft:dark_oak_fence";
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_LEAVES = "minecraft:dark_oak_leaves";
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_SAPLING = "minecraft:dark_oak_sapling";
public const DARK_OAK_SLAB = "minecraft:dark_oak_slab";
public const DARK_OAK_STAIRS = "minecraft:dark_oak_stairs";
public const DARK_OAK_TRAPDOOR = "minecraft:dark_oak_trapdoor";
public const DARK_OAK_WOOD = "minecraft:dark_oak_wood";
public const DARK_PRISMARINE = "minecraft:dark_prismarine";
public const DARK_PRISMARINE_DOUBLE_SLAB = "minecraft:dark_prismarine_double_slab";
public const DARK_PRISMARINE_SLAB = "minecraft:dark_prismarine_slab";
public const DARK_PRISMARINE_STAIRS = "minecraft:dark_prismarine_stairs";
public const DARKOAK_STANDING_SIGN = "minecraft:darkoak_standing_sign";
public const DARKOAK_WALL_SIGN = "minecraft:darkoak_wall_sign";
public const DAYLIGHT_DETECTOR = "minecraft:daylight_detector";
public const DAYLIGHT_DETECTOR_INVERTED = "minecraft:daylight_detector_inverted";
public const DEAD_BRAIN_CORAL = "minecraft:dead_brain_coral";
public const DEAD_BRAIN_CORAL_BLOCK = "minecraft:dead_brain_coral_block";
public const DEAD_BRAIN_CORAL_FAN = "minecraft:dead_brain_coral_fan";
public const DEAD_BRAIN_CORAL_WALL_FAN = "minecraft:dead_brain_coral_wall_fan";
public const DEAD_BUBBLE_CORAL = "minecraft:dead_bubble_coral";
public const DEAD_BUBBLE_CORAL_BLOCK = "minecraft:dead_bubble_coral_block";
public const DEAD_BUBBLE_CORAL_FAN = "minecraft:dead_bubble_coral_fan";
public const DEAD_BUBBLE_CORAL_WALL_FAN = "minecraft:dead_bubble_coral_wall_fan";
public const DEAD_FIRE_CORAL = "minecraft:dead_fire_coral";
public const DEAD_FIRE_CORAL_BLOCK = "minecraft:dead_fire_coral_block";
public const DEAD_FIRE_CORAL_FAN = "minecraft:dead_fire_coral_fan";
public const DEAD_FIRE_CORAL_WALL_FAN = "minecraft:dead_fire_coral_wall_fan";
public const DEAD_HORN_CORAL = "minecraft:dead_horn_coral";
public const DEAD_HORN_CORAL_BLOCK = "minecraft:dead_horn_coral_block";
public const DEAD_HORN_CORAL_FAN = "minecraft:dead_horn_coral_fan";
public const DEAD_HORN_CORAL_WALL_FAN = "minecraft:dead_horn_coral_wall_fan";
public const DEAD_TUBE_CORAL = "minecraft:dead_tube_coral";
public const DEAD_TUBE_CORAL_BLOCK = "minecraft:dead_tube_coral_block";
public const DEAD_TUBE_CORAL_FAN = "minecraft:dead_tube_coral_fan";
public const DEAD_TUBE_CORAL_WALL_FAN = "minecraft:dead_tube_coral_wall_fan";
public const DEADBUSH = "minecraft:deadbush";
public const DECORATED_POT = "minecraft:decorated_pot";
public const DEEPSLATE = "minecraft:deepslate";
@ -306,22 +373,23 @@ final class BlockTypeNames{
public const DEEPSLATE_TILE_WALL = "minecraft:deepslate_tile_wall";
public const DEEPSLATE_TILES = "minecraft:deepslate_tiles";
public const DENY = "minecraft:deny";
public const DEPRECATED_ANVIL = "minecraft:deprecated_anvil";
public const DEPRECATED_PURPUR_BLOCK_1 = "minecraft:deprecated_purpur_block_1";
public const DEPRECATED_PURPUR_BLOCK_2 = "minecraft:deprecated_purpur_block_2";
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_DOUBLE_SLAB = "minecraft:diorite_double_slab";
public const DIORITE_SLAB = "minecraft:diorite_slab";
public const DIORITE_STAIRS = "minecraft:diorite_stairs";
public const DIORITE_WALL = "minecraft:diorite_wall";
public const DIRT = "minecraft:dirt";
public const DIRT_WITH_ROOTS = "minecraft:dirt_with_roots";
public const DISPENSER = "minecraft:dispenser";
public const DOUBLE_CUT_COPPER_SLAB = "minecraft:double_cut_copper_slab";
public const DOUBLE_PLANT = "minecraft:double_plant";
public const DOUBLE_STONE_BLOCK_SLAB = "minecraft:double_stone_block_slab";
public const DOUBLE_STONE_BLOCK_SLAB2 = "minecraft:double_stone_block_slab2";
public const DOUBLE_STONE_BLOCK_SLAB3 = "minecraft:double_stone_block_slab3";
public const DOUBLE_STONE_BLOCK_SLAB4 = "minecraft:double_stone_block_slab4";
public const DOUBLE_WOODEN_SLAB = "minecraft:double_wooden_slab";
public const DRAGON_EGG = "minecraft:dragon_egg";
public const DRAGON_HEAD = "minecraft:dragon_head";
public const DRIED_KELP_BLOCK = "minecraft:dried_kelp_block";
public const DRIPSTONE_BLOCK = "minecraft:dripstone_block";
public const DROPPER = "minecraft:dropper";
@ -444,6 +512,7 @@ final class BlockTypeNames{
public const ELEMENT_97 = "minecraft:element_97";
public const ELEMENT_98 = "minecraft:element_98";
public const ELEMENT_99 = "minecraft:element_99";
public const ELEMENT_CONSTRUCTOR = "minecraft:element_constructor";
public const EMERALD_BLOCK = "minecraft:emerald_block";
public const EMERALD_ORE = "minecraft:emerald_ore";
public const ENCHANTING_TABLE = "minecraft:enchanting_table";
@ -454,6 +523,9 @@ final class BlockTypeNames{
public const END_PORTAL_FRAME = "minecraft:end_portal_frame";
public const END_ROD = "minecraft:end_rod";
public const END_STONE = "minecraft:end_stone";
public const END_STONE_BRICK_DOUBLE_SLAB = "minecraft:end_stone_brick_double_slab";
public const END_STONE_BRICK_SLAB = "minecraft:end_stone_brick_slab";
public const END_STONE_BRICK_WALL = "minecraft:end_stone_brick_wall";
public const ENDER_CHEST = "minecraft:ender_chest";
public const EXPOSED_CHISELED_COPPER = "minecraft:exposed_chiseled_copper";
public const EXPOSED_COPPER = "minecraft:exposed_copper";
@ -467,8 +539,12 @@ final class BlockTypeNames{
public const EXPOSED_DOUBLE_CUT_COPPER_SLAB = "minecraft:exposed_double_cut_copper_slab";
public const FARMLAND = "minecraft:farmland";
public const FENCE_GATE = "minecraft:fence_gate";
public const FERN = "minecraft:fern";
public const FIRE = "minecraft:fire";
public const FIRE_CORAL = "minecraft:fire_coral";
public const FIRE_CORAL_BLOCK = "minecraft:fire_coral_block";
public const FIRE_CORAL_FAN = "minecraft:fire_coral_fan";
public const FIRE_CORAL_WALL_FAN = "minecraft:fire_coral_wall_fan";
public const FLETCHING_TABLE = "minecraft:fletching_table";
public const FLOWER_POT = "minecraft:flower_pot";
public const FLOWERING_AZALEA = "minecraft:flowering_azalea";
@ -489,8 +565,11 @@ final class BlockTypeNames{
public const GOLD_ORE = "minecraft:gold_ore";
public const GOLDEN_RAIL = "minecraft:golden_rail";
public const GRANITE = "minecraft:granite";
public const GRANITE_DOUBLE_SLAB = "minecraft:granite_double_slab";
public const GRANITE_SLAB = "minecraft:granite_slab";
public const GRANITE_STAIRS = "minecraft:granite_stairs";
public const GRASS = "minecraft:grass";
public const GRANITE_WALL = "minecraft:granite_wall";
public const GRASS_BLOCK = "minecraft:grass_block";
public const GRASS_PATH = "minecraft:grass_path";
public const GRAVEL = "minecraft:gravel";
public const GRAY_CANDLE = "minecraft:gray_candle";
@ -553,13 +632,23 @@ final class BlockTypeNames{
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_CORE = "minecraft:heavy_core";
public const HEAVY_WEIGHTED_PRESSURE_PLATE = "minecraft:heavy_weighted_pressure_plate";
public const HONEY_BLOCK = "minecraft:honey_block";
public const HONEYCOMB_BLOCK = "minecraft:honeycomb_block";
public const HOPPER = "minecraft:hopper";
public const HORN_CORAL = "minecraft:horn_coral";
public const HORN_CORAL_BLOCK = "minecraft:horn_coral_block";
public const HORN_CORAL_FAN = "minecraft:horn_coral_fan";
public const HORN_CORAL_WALL_FAN = "minecraft:horn_coral_wall_fan";
public const ICE = "minecraft:ice";
public const INFESTED_CHISELED_STONE_BRICKS = "minecraft:infested_chiseled_stone_bricks";
public const INFESTED_COBBLESTONE = "minecraft:infested_cobblestone";
public const INFESTED_CRACKED_STONE_BRICKS = "minecraft:infested_cracked_stone_bricks";
public const INFESTED_DEEPSLATE = "minecraft:infested_deepslate";
public const INFESTED_MOSSY_STONE_BRICKS = "minecraft:infested_mossy_stone_bricks";
public const INFESTED_STONE = "minecraft:infested_stone";
public const INFESTED_STONE_BRICKS = "minecraft:infested_stone_bricks";
public const INFO_UPDATE = "minecraft:info_update";
public const INFO_UPDATE2 = "minecraft:info_update2";
public const INVISIBLE_BEDROCK = "minecraft:invisible_bedrock";
@ -572,28 +661,48 @@ final class BlockTypeNames{
public const JUKEBOX = "minecraft:jukebox";
public const JUNGLE_BUTTON = "minecraft:jungle_button";
public const JUNGLE_DOOR = "minecraft:jungle_door";
public const JUNGLE_DOUBLE_SLAB = "minecraft:jungle_double_slab";
public const JUNGLE_FENCE = "minecraft:jungle_fence";
public const JUNGLE_FENCE_GATE = "minecraft:jungle_fence_gate";
public const JUNGLE_HANGING_SIGN = "minecraft:jungle_hanging_sign";
public const JUNGLE_LEAVES = "minecraft:jungle_leaves";
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_SAPLING = "minecraft:jungle_sapling";
public const JUNGLE_SLAB = "minecraft:jungle_slab";
public const JUNGLE_STAIRS = "minecraft:jungle_stairs";
public const JUNGLE_STANDING_SIGN = "minecraft:jungle_standing_sign";
public const JUNGLE_TRAPDOOR = "minecraft:jungle_trapdoor";
public const JUNGLE_WALL_SIGN = "minecraft:jungle_wall_sign";
public const JUNGLE_WOOD = "minecraft:jungle_wood";
public const KELP = "minecraft:kelp";
public const LAB_TABLE = "minecraft:lab_table";
public const LADDER = "minecraft:ladder";
public const LANTERN = "minecraft:lantern";
public const LAPIS_BLOCK = "minecraft:lapis_block";
public const LAPIS_ORE = "minecraft:lapis_ore";
public const LARGE_AMETHYST_BUD = "minecraft:large_amethyst_bud";
public const LARGE_FERN = "minecraft:large_fern";
public const LAVA = "minecraft:lava";
public const LEAVES = "minecraft:leaves";
public const LEAVES2 = "minecraft:leaves2";
public const LECTERN = "minecraft:lectern";
public const LEVER = "minecraft:lever";
public const LIGHT_BLOCK = "minecraft:light_block";
public const LIGHT_BLOCK_0 = "minecraft:light_block_0";
public const LIGHT_BLOCK_1 = "minecraft:light_block_1";
public const LIGHT_BLOCK_10 = "minecraft:light_block_10";
public const LIGHT_BLOCK_11 = "minecraft:light_block_11";
public const LIGHT_BLOCK_12 = "minecraft:light_block_12";
public const LIGHT_BLOCK_13 = "minecraft:light_block_13";
public const LIGHT_BLOCK_14 = "minecraft:light_block_14";
public const LIGHT_BLOCK_15 = "minecraft:light_block_15";
public const LIGHT_BLOCK_2 = "minecraft:light_block_2";
public const LIGHT_BLOCK_3 = "minecraft:light_block_3";
public const LIGHT_BLOCK_4 = "minecraft:light_block_4";
public const LIGHT_BLOCK_5 = "minecraft:light_block_5";
public const LIGHT_BLOCK_6 = "minecraft:light_block_6";
public const LIGHT_BLOCK_7 = "minecraft:light_block_7";
public const LIGHT_BLOCK_8 = "minecraft:light_block_8";
public const LIGHT_BLOCK_9 = "minecraft:light_block_9";
public const LIGHT_BLUE_CANDLE = "minecraft:light_blue_candle";
public const LIGHT_BLUE_CANDLE_CAKE = "minecraft:light_blue_candle_cake";
public const LIGHT_BLUE_CARPET = "minecraft:light_blue_carpet";
@ -617,6 +726,8 @@ final class BlockTypeNames{
public const LIGHT_GRAY_WOOL = "minecraft:light_gray_wool";
public const LIGHT_WEIGHTED_PRESSURE_PLATE = "minecraft:light_weighted_pressure_plate";
public const LIGHTNING_ROD = "minecraft:lightning_rod";
public const LILAC = "minecraft:lilac";
public const LILY_OF_THE_VALLEY = "minecraft:lily_of_the_valley";
public const LIME_CANDLE = "minecraft:lime_candle";
public const LIME_CANDLE_CAKE = "minecraft:lime_candle_cake";
public const LIME_CARPET = "minecraft:lime_carpet";
@ -667,16 +778,23 @@ final class BlockTypeNames{
public const MANGROVE_TRAPDOOR = "minecraft:mangrove_trapdoor";
public const MANGROVE_WALL_SIGN = "minecraft:mangrove_wall_sign";
public const MANGROVE_WOOD = "minecraft:mangrove_wood";
public const MATERIAL_REDUCER = "minecraft:material_reducer";
public const MEDIUM_AMETHYST_BUD = "minecraft:medium_amethyst_bud";
public const MELON_BLOCK = "minecraft:melon_block";
public const MELON_STEM = "minecraft:melon_stem";
public const MOB_SPAWNER = "minecraft:mob_spawner";
public const MONSTER_EGG = "minecraft:monster_egg";
public const MOSS_BLOCK = "minecraft:moss_block";
public const MOSS_CARPET = "minecraft:moss_carpet";
public const MOSSY_COBBLESTONE = "minecraft:mossy_cobblestone";
public const MOSSY_COBBLESTONE_DOUBLE_SLAB = "minecraft:mossy_cobblestone_double_slab";
public const MOSSY_COBBLESTONE_SLAB = "minecraft:mossy_cobblestone_slab";
public const MOSSY_COBBLESTONE_STAIRS = "minecraft:mossy_cobblestone_stairs";
public const MOSSY_COBBLESTONE_WALL = "minecraft:mossy_cobblestone_wall";
public const MOSSY_STONE_BRICK_DOUBLE_SLAB = "minecraft:mossy_stone_brick_double_slab";
public const MOSSY_STONE_BRICK_SLAB = "minecraft:mossy_stone_brick_slab";
public const MOSSY_STONE_BRICK_STAIRS = "minecraft:mossy_stone_brick_stairs";
public const MOSSY_STONE_BRICK_WALL = "minecraft:mossy_stone_brick_wall";
public const MOSSY_STONE_BRICKS = "minecraft:mossy_stone_bricks";
public const MOVING_BLOCK = "minecraft:moving_block";
public const MUD = "minecraft:mud";
public const MUD_BRICK_DOUBLE_SLAB = "minecraft:mud_brick_double_slab";
@ -685,10 +803,14 @@ final class BlockTypeNames{
public const MUD_BRICK_WALL = "minecraft:mud_brick_wall";
public const MUD_BRICKS = "minecraft:mud_bricks";
public const MUDDY_MANGROVE_ROOTS = "minecraft:muddy_mangrove_roots";
public const MUSHROOM_STEM = "minecraft:mushroom_stem";
public const MYCELIUM = "minecraft:mycelium";
public const NETHER_BRICK = "minecraft:nether_brick";
public const NETHER_BRICK_DOUBLE_SLAB = "minecraft:nether_brick_double_slab";
public const NETHER_BRICK_FENCE = "minecraft:nether_brick_fence";
public const NETHER_BRICK_SLAB = "minecraft:nether_brick_slab";
public const NETHER_BRICK_STAIRS = "minecraft:nether_brick_stairs";
public const NETHER_BRICK_WALL = "minecraft:nether_brick_wall";
public const NETHER_GOLD_ORE = "minecraft:nether_gold_ore";
public const NETHER_SPROUTS = "minecraft:nether_sprouts";
public const NETHER_WART = "minecraft:nether_wart";
@ -696,16 +818,24 @@ final class BlockTypeNames{
public const NETHERITE_BLOCK = "minecraft:netherite_block";
public const NETHERRACK = "minecraft:netherrack";
public const NETHERREACTOR = "minecraft:netherreactor";
public const NORMAL_STONE_DOUBLE_SLAB = "minecraft:normal_stone_double_slab";
public const NORMAL_STONE_SLAB = "minecraft:normal_stone_slab";
public const NORMAL_STONE_STAIRS = "minecraft:normal_stone_stairs";
public const NOTEBLOCK = "minecraft:noteblock";
public const OAK_DOUBLE_SLAB = "minecraft:oak_double_slab";
public const OAK_FENCE = "minecraft:oak_fence";
public const OAK_HANGING_SIGN = "minecraft:oak_hanging_sign";
public const OAK_LEAVES = "minecraft:oak_leaves";
public const OAK_LOG = "minecraft:oak_log";
public const OAK_PLANKS = "minecraft:oak_planks";
public const OAK_SAPLING = "minecraft:oak_sapling";
public const OAK_SLAB = "minecraft:oak_slab";
public const OAK_STAIRS = "minecraft:oak_stairs";
public const OAK_WOOD = "minecraft:oak_wood";
public const OBSERVER = "minecraft:observer";
public const OBSIDIAN = "minecraft:obsidian";
public const OCHRE_FROGLIGHT = "minecraft:ochre_froglight";
public const OPEN_EYEBLOSSOM = "minecraft:open_eyeblossom";
public const ORANGE_CANDLE = "minecraft:orange_candle";
public const ORANGE_CANDLE_CAKE = "minecraft:orange_candle_cake";
public const ORANGE_CARPET = "minecraft:orange_carpet";
@ -716,7 +846,9 @@ final class BlockTypeNames{
public const ORANGE_STAINED_GLASS = "minecraft:orange_stained_glass";
public const ORANGE_STAINED_GLASS_PANE = "minecraft:orange_stained_glass_pane";
public const ORANGE_TERRACOTTA = "minecraft:orange_terracotta";
public const ORANGE_TULIP = "minecraft:orange_tulip";
public const ORANGE_WOOL = "minecraft:orange_wool";
public const OXEYE_DAISY = "minecraft:oxeye_daisy";
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";
@ -729,7 +861,31 @@ final class BlockTypeNames{
public const OXIDIZED_DOUBLE_CUT_COPPER_SLAB = "minecraft:oxidized_double_cut_copper_slab";
public const PACKED_ICE = "minecraft:packed_ice";
public const PACKED_MUD = "minecraft:packed_mud";
public const PALE_HANGING_MOSS = "minecraft:pale_hanging_moss";
public const PALE_MOSS_BLOCK = "minecraft:pale_moss_block";
public const PALE_MOSS_CARPET = "minecraft:pale_moss_carpet";
public const PALE_OAK_BUTTON = "minecraft:pale_oak_button";
public const PALE_OAK_DOOR = "minecraft:pale_oak_door";
public const PALE_OAK_DOUBLE_SLAB = "minecraft:pale_oak_double_slab";
public const PALE_OAK_FENCE = "minecraft:pale_oak_fence";
public const PALE_OAK_FENCE_GATE = "minecraft:pale_oak_fence_gate";
public const PALE_OAK_HANGING_SIGN = "minecraft:pale_oak_hanging_sign";
public const PALE_OAK_LEAVES = "minecraft:pale_oak_leaves";
public const PALE_OAK_LOG = "minecraft:pale_oak_log";
public const PALE_OAK_PLANKS = "minecraft:pale_oak_planks";
public const PALE_OAK_PRESSURE_PLATE = "minecraft:pale_oak_pressure_plate";
public const PALE_OAK_SAPLING = "minecraft:pale_oak_sapling";
public const PALE_OAK_SLAB = "minecraft:pale_oak_slab";
public const PALE_OAK_STAIRS = "minecraft:pale_oak_stairs";
public const PALE_OAK_STANDING_SIGN = "minecraft:pale_oak_standing_sign";
public const PALE_OAK_TRAPDOOR = "minecraft:pale_oak_trapdoor";
public const PALE_OAK_WALL_SIGN = "minecraft:pale_oak_wall_sign";
public const PALE_OAK_WOOD = "minecraft:pale_oak_wood";
public const PEARLESCENT_FROGLIGHT = "minecraft:pearlescent_froglight";
public const PEONY = "minecraft:peony";
public const PETRIFIED_OAK_DOUBLE_SLAB = "minecraft:petrified_oak_double_slab";
public const PETRIFIED_OAK_SLAB = "minecraft:petrified_oak_slab";
public const PIGLIN_HEAD = "minecraft:piglin_head";
public const PINK_CANDLE = "minecraft:pink_candle";
public const PINK_CANDLE_CAKE = "minecraft:pink_candle_cake";
public const PINK_CARPET = "minecraft:pink_carpet";
@ -741,14 +897,18 @@ final class BlockTypeNames{
public const PINK_STAINED_GLASS = "minecraft:pink_stained_glass";
public const PINK_STAINED_GLASS_PANE = "minecraft:pink_stained_glass_pane";
public const PINK_TERRACOTTA = "minecraft:pink_terracotta";
public const PINK_TULIP = "minecraft:pink_tulip";
public const PINK_WOOL = "minecraft:pink_wool";
public const PISTON = "minecraft:piston";
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 PLAYER_HEAD = "minecraft:player_head";
public const PODZOL = "minecraft:podzol";
public const POINTED_DRIPSTONE = "minecraft:pointed_dripstone";
public const POLISHED_ANDESITE = "minecraft:polished_andesite";
public const POLISHED_ANDESITE_DOUBLE_SLAB = "minecraft:polished_andesite_double_slab";
public const POLISHED_ANDESITE_SLAB = "minecraft:polished_andesite_slab";
public const POLISHED_ANDESITE_STAIRS = "minecraft:polished_andesite_stairs";
public const POLISHED_BASALT = "minecraft:polished_basalt";
public const POLISHED_BLACKSTONE = "minecraft:polished_blackstone";
@ -769,22 +929,33 @@ final class BlockTypeNames{
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_DOUBLE_SLAB = "minecraft:polished_diorite_double_slab";
public const POLISHED_DIORITE_SLAB = "minecraft:polished_diorite_slab";
public const POLISHED_DIORITE_STAIRS = "minecraft:polished_diorite_stairs";
public const POLISHED_GRANITE = "minecraft:polished_granite";
public const POLISHED_GRANITE_DOUBLE_SLAB = "minecraft:polished_granite_double_slab";
public const POLISHED_GRANITE_SLAB = "minecraft:polished_granite_slab";
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 POPPY = "minecraft:poppy";
public const PORTAL = "minecraft:portal";
public const POTATOES = "minecraft:potatoes";
public const POWDER_SNOW = "minecraft:powder_snow";
public const POWERED_COMPARATOR = "minecraft:powered_comparator";
public const POWERED_REPEATER = "minecraft:powered_repeater";
public const PRISMARINE = "minecraft:prismarine";
public const PRISMARINE_BRICK_DOUBLE_SLAB = "minecraft:prismarine_brick_double_slab";
public const PRISMARINE_BRICK_SLAB = "minecraft:prismarine_brick_slab";
public const PRISMARINE_BRICKS = "minecraft:prismarine_bricks";
public const PRISMARINE_BRICKS_STAIRS = "minecraft:prismarine_bricks_stairs";
public const PRISMARINE_DOUBLE_SLAB = "minecraft:prismarine_double_slab";
public const PRISMARINE_SLAB = "minecraft:prismarine_slab";
public const PRISMARINE_STAIRS = "minecraft:prismarine_stairs";
public const PRISMARINE_WALL = "minecraft:prismarine_wall";
public const PUMPKIN = "minecraft:pumpkin";
public const PUMPKIN_STEM = "minecraft:pumpkin_stem";
public const PURPLE_CANDLE = "minecraft:purple_candle";
@ -799,10 +970,16 @@ final class BlockTypeNames{
public const PURPLE_TERRACOTTA = "minecraft:purple_terracotta";
public const PURPLE_WOOL = "minecraft:purple_wool";
public const PURPUR_BLOCK = "minecraft:purpur_block";
public const PURPUR_DOUBLE_SLAB = "minecraft:purpur_double_slab";
public const PURPUR_PILLAR = "minecraft:purpur_pillar";
public const PURPUR_SLAB = "minecraft:purpur_slab";
public const PURPUR_STAIRS = "minecraft:purpur_stairs";
public const QUARTZ_BLOCK = "minecraft:quartz_block";
public const QUARTZ_BRICKS = "minecraft:quartz_bricks";
public const QUARTZ_DOUBLE_SLAB = "minecraft:quartz_double_slab";
public const QUARTZ_ORE = "minecraft:quartz_ore";
public const QUARTZ_PILLAR = "minecraft:quartz_pillar";
public const QUARTZ_SLAB = "minecraft:quartz_slab";
public const QUARTZ_STAIRS = "minecraft:quartz_stairs";
public const RAIL = "minecraft:rail";
public const RAW_COPPER_BLOCK = "minecraft:raw_copper_block";
@ -813,18 +990,25 @@ final class BlockTypeNames{
public const RED_CARPET = "minecraft:red_carpet";
public const RED_CONCRETE = "minecraft:red_concrete";
public const RED_CONCRETE_POWDER = "minecraft:red_concrete_powder";
public const RED_FLOWER = "minecraft:red_flower";
public const RED_GLAZED_TERRACOTTA = "minecraft:red_glazed_terracotta";
public const RED_MUSHROOM = "minecraft:red_mushroom";
public const RED_MUSHROOM_BLOCK = "minecraft:red_mushroom_block";
public const RED_NETHER_BRICK = "minecraft:red_nether_brick";
public const RED_NETHER_BRICK_DOUBLE_SLAB = "minecraft:red_nether_brick_double_slab";
public const RED_NETHER_BRICK_SLAB = "minecraft:red_nether_brick_slab";
public const RED_NETHER_BRICK_STAIRS = "minecraft:red_nether_brick_stairs";
public const RED_NETHER_BRICK_WALL = "minecraft:red_nether_brick_wall";
public const RED_SAND = "minecraft:red_sand";
public const RED_SANDSTONE = "minecraft:red_sandstone";
public const RED_SANDSTONE_DOUBLE_SLAB = "minecraft:red_sandstone_double_slab";
public const RED_SANDSTONE_SLAB = "minecraft:red_sandstone_slab";
public const RED_SANDSTONE_STAIRS = "minecraft:red_sandstone_stairs";
public const RED_SANDSTONE_WALL = "minecraft:red_sandstone_wall";
public const RED_SHULKER_BOX = "minecraft:red_shulker_box";
public const RED_STAINED_GLASS = "minecraft:red_stained_glass";
public const RED_STAINED_GLASS_PANE = "minecraft:red_stained_glass_pane";
public const RED_TERRACOTTA = "minecraft:red_terracotta";
public const RED_TULIP = "minecraft:red_tulip";
public const RED_WOOL = "minecraft:red_wool";
public const REDSTONE_BLOCK = "minecraft:redstone_block";
public const REDSTONE_LAMP = "minecraft:redstone_lamp";
@ -835,11 +1019,21 @@ final class BlockTypeNames{
public const REINFORCED_DEEPSLATE = "minecraft:reinforced_deepslate";
public const REPEATING_COMMAND_BLOCK = "minecraft:repeating_command_block";
public const RESERVED6 = "minecraft:reserved6";
public const RESIN_BLOCK = "minecraft:resin_block";
public const RESIN_BRICK_DOUBLE_SLAB = "minecraft:resin_brick_double_slab";
public const RESIN_BRICK_SLAB = "minecraft:resin_brick_slab";
public const RESIN_BRICK_STAIRS = "minecraft:resin_brick_stairs";
public const RESIN_BRICK_WALL = "minecraft:resin_brick_wall";
public const RESIN_BRICKS = "minecraft:resin_bricks";
public const RESIN_CLUMP = "minecraft:resin_clump";
public const RESPAWN_ANCHOR = "minecraft:respawn_anchor";
public const ROSE_BUSH = "minecraft:rose_bush";
public const SAND = "minecraft:sand";
public const SANDSTONE = "minecraft:sandstone";
public const SANDSTONE_DOUBLE_SLAB = "minecraft:sandstone_double_slab";
public const SANDSTONE_SLAB = "minecraft:sandstone_slab";
public const SANDSTONE_STAIRS = "minecraft:sandstone_stairs";
public const SAPLING = "minecraft:sapling";
public const SANDSTONE_WALL = "minecraft:sandstone_wall";
public const SCAFFOLDING = "minecraft:scaffolding";
public const SCULK = "minecraft:sculk";
public const SCULK_CATALYST = "minecraft:sculk_catalyst";
@ -849,19 +1043,31 @@ final class BlockTypeNames{
public const SEA_LANTERN = "minecraft:sea_lantern";
public const SEA_PICKLE = "minecraft:sea_pickle";
public const SEAGRASS = "minecraft:seagrass";
public const SHORT_GRASS = "minecraft:short_grass";
public const SHROOMLIGHT = "minecraft:shroomlight";
public const SILVER_GLAZED_TERRACOTTA = "minecraft:silver_glazed_terracotta";
public const SKULL = "minecraft:skull";
public const SKELETON_SKULL = "minecraft:skeleton_skull";
public const SLIME = "minecraft:slime";
public const SMALL_AMETHYST_BUD = "minecraft:small_amethyst_bud";
public const SMALL_DRIPLEAF_BLOCK = "minecraft:small_dripleaf_block";
public const SMITHING_TABLE = "minecraft:smithing_table";
public const SMOKER = "minecraft:smoker";
public const SMOOTH_BASALT = "minecraft:smooth_basalt";
public const SMOOTH_QUARTZ = "minecraft:smooth_quartz";
public const SMOOTH_QUARTZ_DOUBLE_SLAB = "minecraft:smooth_quartz_double_slab";
public const SMOOTH_QUARTZ_SLAB = "minecraft:smooth_quartz_slab";
public const SMOOTH_QUARTZ_STAIRS = "minecraft:smooth_quartz_stairs";
public const SMOOTH_RED_SANDSTONE = "minecraft:smooth_red_sandstone";
public const SMOOTH_RED_SANDSTONE_DOUBLE_SLAB = "minecraft:smooth_red_sandstone_double_slab";
public const SMOOTH_RED_SANDSTONE_SLAB = "minecraft:smooth_red_sandstone_slab";
public const SMOOTH_RED_SANDSTONE_STAIRS = "minecraft:smooth_red_sandstone_stairs";
public const SMOOTH_SANDSTONE = "minecraft:smooth_sandstone";
public const SMOOTH_SANDSTONE_DOUBLE_SLAB = "minecraft:smooth_sandstone_double_slab";
public const SMOOTH_SANDSTONE_SLAB = "minecraft:smooth_sandstone_slab";
public const SMOOTH_SANDSTONE_STAIRS = "minecraft:smooth_sandstone_stairs";
public const SMOOTH_STONE = "minecraft:smooth_stone";
public const SMOOTH_STONE_DOUBLE_SLAB = "minecraft:smooth_stone_double_slab";
public const SMOOTH_STONE_SLAB = "minecraft:smooth_stone_slab";
public const SNIFFER_EGG = "minecraft:sniffer_egg";
public const SNOW = "minecraft:snow";
public const SNOW_LAYER = "minecraft:snow_layer";
@ -875,53 +1081,66 @@ final class BlockTypeNames{
public const SPORE_BLOSSOM = "minecraft:spore_blossom";
public const SPRUCE_BUTTON = "minecraft:spruce_button";
public const SPRUCE_DOOR = "minecraft:spruce_door";
public const SPRUCE_DOUBLE_SLAB = "minecraft:spruce_double_slab";
public const SPRUCE_FENCE = "minecraft:spruce_fence";
public const SPRUCE_FENCE_GATE = "minecraft:spruce_fence_gate";
public const SPRUCE_HANGING_SIGN = "minecraft:spruce_hanging_sign";
public const SPRUCE_LEAVES = "minecraft:spruce_leaves";
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_SAPLING = "minecraft:spruce_sapling";
public const SPRUCE_SLAB = "minecraft:spruce_slab";
public const SPRUCE_STAIRS = "minecraft:spruce_stairs";
public const SPRUCE_STANDING_SIGN = "minecraft:spruce_standing_sign";
public const SPRUCE_TRAPDOOR = "minecraft:spruce_trapdoor";
public const SPRUCE_WALL_SIGN = "minecraft:spruce_wall_sign";
public const SPRUCE_WOOD = "minecraft:spruce_wood";
public const STANDING_BANNER = "minecraft:standing_banner";
public const STANDING_SIGN = "minecraft:standing_sign";
public const STICKY_PISTON = "minecraft:sticky_piston";
public const STICKY_PISTON_ARM_COLLISION = "minecraft:sticky_piston_arm_collision";
public const STONE = "minecraft:stone";
public const STONE_BLOCK_SLAB = "minecraft:stone_block_slab";
public const STONE_BLOCK_SLAB2 = "minecraft:stone_block_slab2";
public const STONE_BLOCK_SLAB3 = "minecraft:stone_block_slab3";
public const STONE_BLOCK_SLAB4 = "minecraft:stone_block_slab4";
public const STONE_BRICK_DOUBLE_SLAB = "minecraft:stone_brick_double_slab";
public const STONE_BRICK_SLAB = "minecraft:stone_brick_slab";
public const STONE_BRICK_STAIRS = "minecraft:stone_brick_stairs";
public const STONE_BRICK_WALL = "minecraft:stone_brick_wall";
public const STONE_BRICKS = "minecraft:stone_bricks";
public const STONE_BUTTON = "minecraft:stone_button";
public const STONE_PRESSURE_PLATE = "minecraft:stone_pressure_plate";
public const STONE_STAIRS = "minecraft:stone_stairs";
public const STONEBRICK = "minecraft:stonebrick";
public const STONECUTTER = "minecraft:stonecutter";
public const STONECUTTER_BLOCK = "minecraft:stonecutter_block";
public const STRIPPED_ACACIA_LOG = "minecraft:stripped_acacia_log";
public const STRIPPED_ACACIA_WOOD = "minecraft:stripped_acacia_wood";
public const STRIPPED_BAMBOO_BLOCK = "minecraft:stripped_bamboo_block";
public const STRIPPED_BIRCH_LOG = "minecraft:stripped_birch_log";
public const STRIPPED_BIRCH_WOOD = "minecraft:stripped_birch_wood";
public const STRIPPED_CHERRY_LOG = "minecraft:stripped_cherry_log";
public const STRIPPED_CHERRY_WOOD = "minecraft:stripped_cherry_wood";
public const STRIPPED_CRIMSON_HYPHAE = "minecraft:stripped_crimson_hyphae";
public const STRIPPED_CRIMSON_STEM = "minecraft:stripped_crimson_stem";
public const STRIPPED_DARK_OAK_LOG = "minecraft:stripped_dark_oak_log";
public const STRIPPED_DARK_OAK_WOOD = "minecraft:stripped_dark_oak_wood";
public const STRIPPED_JUNGLE_LOG = "minecraft:stripped_jungle_log";
public const STRIPPED_JUNGLE_WOOD = "minecraft:stripped_jungle_wood";
public const STRIPPED_MANGROVE_LOG = "minecraft:stripped_mangrove_log";
public const STRIPPED_MANGROVE_WOOD = "minecraft:stripped_mangrove_wood";
public const STRIPPED_OAK_LOG = "minecraft:stripped_oak_log";
public const STRIPPED_OAK_WOOD = "minecraft:stripped_oak_wood";
public const STRIPPED_PALE_OAK_LOG = "minecraft:stripped_pale_oak_log";
public const STRIPPED_PALE_OAK_WOOD = "minecraft:stripped_pale_oak_wood";
public const STRIPPED_SPRUCE_LOG = "minecraft:stripped_spruce_log";
public const STRIPPED_SPRUCE_WOOD = "minecraft:stripped_spruce_wood";
public const STRIPPED_WARPED_HYPHAE = "minecraft:stripped_warped_hyphae";
public const STRIPPED_WARPED_STEM = "minecraft:stripped_warped_stem";
public const STRUCTURE_BLOCK = "minecraft:structure_block";
public const STRUCTURE_VOID = "minecraft:structure_void";
public const SUNFLOWER = "minecraft:sunflower";
public const SUSPICIOUS_GRAVEL = "minecraft:suspicious_gravel";
public const SUSPICIOUS_SAND = "minecraft:suspicious_sand";
public const SWEET_BERRY_BUSH = "minecraft:sweet_berry_bush";
public const TALLGRASS = "minecraft:tallgrass";
public const TALL_GRASS = "minecraft:tall_grass";
public const TARGET = "minecraft:target";
public const TINTED_GLASS = "minecraft:tinted_glass";
public const TNT = "minecraft:tnt";
@ -934,6 +1153,9 @@ final class BlockTypeNames{
public const TRIP_WIRE = "minecraft:trip_wire";
public const TRIPWIRE_HOOK = "minecraft:tripwire_hook";
public const TUBE_CORAL = "minecraft:tube_coral";
public const TUBE_CORAL_BLOCK = "minecraft:tube_coral_block";
public const TUBE_CORAL_FAN = "minecraft:tube_coral_fan";
public const TUBE_CORAL_WALL_FAN = "minecraft:tube_coral_wall_fan";
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";
@ -946,12 +1168,14 @@ final class BlockTypeNames{
public const TUFF_WALL = "minecraft:tuff_wall";
public const TURTLE_EGG = "minecraft:turtle_egg";
public const TWISTING_VINES = "minecraft:twisting_vines";
public const UNDERWATER_TNT = "minecraft:underwater_tnt";
public const UNDERWATER_TORCH = "minecraft:underwater_torch";
public const UNDYED_SHULKER_BOX = "minecraft:undyed_shulker_box";
public const UNKNOWN = "minecraft:unknown";
public const UNLIT_REDSTONE_TORCH = "minecraft:unlit_redstone_torch";
public const UNPOWERED_COMPARATOR = "minecraft:unpowered_comparator";
public const UNPOWERED_REPEATER = "minecraft:unpowered_repeater";
public const VAULT = "minecraft:vault";
public const VERDANT_FROGLIGHT = "minecraft:verdant_froglight";
public const VINE = "minecraft:vine";
public const WALL_BANNER = "minecraft:wall_banner";
@ -1029,6 +1253,7 @@ final class BlockTypeNames{
public const WEATHERED_DOUBLE_CUT_COPPER_SLAB = "minecraft:weathered_double_cut_copper_slab";
public const WEB = "minecraft:web";
public const WEEPING_VINES = "minecraft:weeping_vines";
public const WET_SPONGE = "minecraft:wet_sponge";
public const WHEAT = "minecraft:wheat";
public const WHITE_CANDLE = "minecraft:white_candle";
public const WHITE_CANDLE_CAKE = "minecraft:white_candle_cake";
@ -1040,23 +1265,23 @@ final class BlockTypeNames{
public const WHITE_STAINED_GLASS = "minecraft:white_stained_glass";
public const WHITE_STAINED_GLASS_PANE = "minecraft:white_stained_glass_pane";
public const WHITE_TERRACOTTA = "minecraft:white_terracotta";
public const WHITE_TULIP = "minecraft:white_tulip";
public const WHITE_WOOL = "minecraft:white_wool";
public const WITHER_ROSE = "minecraft:wither_rose";
public const WOOD = "minecraft:wood";
public const WITHER_SKELETON_SKULL = "minecraft:wither_skeleton_skull";
public const WOODEN_BUTTON = "minecraft:wooden_button";
public const WOODEN_DOOR = "minecraft:wooden_door";
public const WOODEN_PRESSURE_PLATE = "minecraft:wooden_pressure_plate";
public const WOODEN_SLAB = "minecraft:wooden_slab";
public const YELLOW_CANDLE = "minecraft:yellow_candle";
public const YELLOW_CANDLE_CAKE = "minecraft:yellow_candle_cake";
public const YELLOW_CARPET = "minecraft:yellow_carpet";
public const YELLOW_CONCRETE = "minecraft:yellow_concrete";
public const YELLOW_CONCRETE_POWDER = "minecraft:yellow_concrete_powder";
public const YELLOW_FLOWER = "minecraft:yellow_flower";
public const YELLOW_GLAZED_TERRACOTTA = "minecraft:yellow_glazed_terracotta";
public const YELLOW_SHULKER_BOX = "minecraft:yellow_shulker_box";
public const YELLOW_STAINED_GLASS = "minecraft:yellow_stained_glass";
public const YELLOW_STAINED_GLASS_PANE = "minecraft:yellow_stained_glass_pane";
public const YELLOW_TERRACOTTA = "minecraft:yellow_terracotta";
public const YELLOW_WOOL = "minecraft:yellow_wool";
public const ZOMBIE_HEAD = "minecraft:zombie_head";
}

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