Compare commits

..

212 Commits
5.0.1 ... 5.4.0

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Cancelling task runs doesn't make any sense.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

closes #5818

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

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

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

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

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

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

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

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

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

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

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

probably fixes #4986

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-05 15:01:41 +01:00
57cbc25080 Merge remote-tracking branch 'origin/stable' into minor-next 2023-06-04 16:10:07 +01:00
b9bdfe580b Bump version to 5.2.0+dev
next feature release go brrrr
2023-06-04 16:07:10 +01:00
6d7f44d8fe Implement glow lichen (#5401) 2023-06-04 16:04:08 +01:00
f9818efff4 Fixed PHPUnit deprecation warnings 2023-06-04 14:00:26 +01:00
7fef8f0ab6 5.0.2 is next 2023-06-03 21:56:30 +01:00
215 changed files with 4546 additions and 1411 deletions

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

View File

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

View File

@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.25.2
uses: shivammathur/setup-php@2.25.5
with:
php-version: 8.1

View File

@ -18,7 +18,7 @@ jobs:
submodules: true
- name: Setup PHP
uses: shivammathur/setup-php@2.25.2
uses: shivammathur/setup-php@2.25.5
with:
php-version: 8.1

View File

@ -173,10 +173,10 @@ jobs:
- uses: actions/checkout@v3
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.25.2
uses: shivammathur/setup-php@2.25.5
with:
php-version: 8.1
tools: php-cs-fixer:3.16
tools: php-cs-fixer:3.17
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -8,6 +8,7 @@ on:
jobs:
build:
runs-on: ubuntu-latest
concurrency: update-updater-api # only one job can run at a time, to avoid git conflicts when updating the repository
steps:
- name: Install jq

View File

@ -4,8 +4,8 @@
<img src="https://github.com/pmmp/PocketMine-MP/blob/stable/.github/readme/pocketmine.png" alt="The PocketMine-MP logo" title="PocketMine" loading="eager" />
<![endif]-->
<picture>
<source srcset="https://github.com/pmmp/PocketMine-MP/raw/stable/.github/readme/pocketmine-dark.png" media="(prefers-color-scheme: dark)">
<img src="https://github.com/pmmp/PocketMine-MP/raw/stable/.github/readme/pocketmine.png" loading="eager" />
<source srcset="https://raw.githubusercontent.com/pmmp/PocketMine-MP/stable/.github/readme/pocketmine-dark-rgb.gif" media="(prefers-color-scheme: dark)">
<img src="https://raw.githubusercontent.com/pmmp/PocketMine-MP/stable/.github/readme/pocketmine-rgb.gif" loading="eager" />
</picture>
</a><br>
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
@ -26,7 +26,7 @@
- [Docker image](https://github.com/pmmp/PocketMine-MP/pkgs/container/pocketmine-mp)
- [Plugin repository](https://poggit.pmmp.io/plugins)
## Discussion/Help
## Community & Support
- [Forums](https://forums.pmmp.io/)
- [Discord](https://discord.gg/bmSAZBG)
- [StackOverflow](https://stackoverflow.com/tags/pocketmine)

View File

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

View File

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

View File

@ -27,6 +27,7 @@ use pocketmine\block\utils\BellAttachmentType;
use pocketmine\block\utils\CopperOxidation;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\DirtType;
use pocketmine\block\utils\DripleafState;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\FroglightType;
use pocketmine\block\utils\LeverFacing;
@ -145,6 +146,7 @@ $enumsUsed = [
CopperOxidation::getAll(),
CoralType::getAll(),
DirtType::getAll(),
DripleafState::getAll(),
DyeColor::getAll(),
FroglightType::getAll(),
LeverFacing::getAll(),

58
changelogs/4.22.md Normal file
View File

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

51
changelogs/4.23.md Normal file
View File

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

52
changelogs/5.1.md Normal file
View File

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

79
changelogs/5.2.md Normal file
View File

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

81
changelogs/5.3.md Normal file
View File

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

83
changelogs/5.4.md Normal file
View File

@ -0,0 +1,83 @@
# 5.4.0
Released 1st August 2023.
**For Minecraft: Bedrock Edition 1.20.10**
This is a minor feature update, including a handful of new gameplay features, new plugin APIs and improvements to error reporting.
**Plugin compatibility:** Plugins for previous 5.x versions will run unchanged on this release, unless they use internal APIs, reflection, or packages like the `pocketmine\network\mcpe` or `pocketmine\data` namespace.
Do not update plugin minimum API versions unless you need new features added in this release.
**WARNING: If your plugin uses the `pocketmine\network\mcpe` namespace, you're not shielded by API change constraints.**
Consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you're using packets directly.
## General
- Improved error reporting for async task and thread crashes.
- Players may now have different creative inventories.
## Gameplay
### General
- Added support for 1.5-block height sneaking.
- Fixed missing player arm swing and sounds when punching the air.
### Blocks
- Implemented the following new blocks:
- Big Dripleaf Head
- Big Dripleaf Stem
- Small Dripleaf
- Acacia saplings now grow into acacia trees.
- Fixed melon and pumpkin stems not attaching to the correct block when growing.
- Various blocks now drop more items when mined with a compatible tool enchanted with Fortune.
### Items
- Implemented Strong Slowness potion.
- Implemented Fortune enchantment.
## API
### `pocketmine\block`
- The following new classes have been added:
- `utils\FortuneDropHelper` - utility methods for calculating the drop counts for Fortune-affected blocks
- The following new API methods have been added:
- `protected Block->getAdjacentSupportType(int $facing) : utils\SupportType` - returns the type of support provided by the block in the given direction on the adjacent face
### `pocketmine\entity`
- The following new API constants have been added:
- `Living::DEFAULT_KNOCKBACK_FORCE`
- `Living::DEFAULT_KNOCKBACK_VERTICAL_LIMIT`
### `pocketmine\entity\animation`
- `ConsumingItemAnimation` now accepts `Living` instances instead of just `Human`.
### `pocketmine\event`
- The following new classes have been added:
- `PlayerMissSwingEvent` - called when the player attempts the attack action (left click on desktop) without any target
- This is possible thanks to the introduction of new flags in `PlayerAuthInputPacket` in Bedrock 1.20.10
- The following new API methods have been added:
- `public EntityDamageByEntityEvent->getVerticalKnockBackLimit() : float`
- `public EntityDamageByEntityEvent->setVerticalKnockBackLimit(float $verticalKnockBackLimit) : void` - sets the max vertical velocity that can result from the victim being knocked back
### `pocketmine\player`
- The following new API methods have been added:
- `public Player->getCreativeInventory() : pocketmine\inventory\CreativeInventory`
- `public Player->setCreativeInventory(pocketmine\inventory\CreativeInventory $inventory) : void`
- `public Player->missSwing() : void` - performs actions associated with the attack action when there is no target (see `PlayerMissSwingEvent`)
### `pocketmine\scheduler`
- Cancellation functionality has been removed from `AsyncTask`, as it didn't make any sense and wasn't used by anything for what it was intended for.
- It broke sequential task execution - later tasks might depend on state from earlier tasks
- It didn't actually cancel the task anyway - at best, it prevented it from running, but couldn't interrupt it (though interrupting a task does not make sense either)
- The following API methods have been deprecated, and their functionality has been removed:
- `AsyncTask->hasCancelledRun()`
- `AsyncTask->cancelRun()`
## Internals
- Uncaught exceptions and fatal errors in `AsyncTask`, threads extending `pocketmine\thread\Thread`, and `pocketmine\thread\Worker` are now recorded in crashdumps, making it significantly easier to debug errors in these areas.
- JWT signature DER <-> raw conversions are now handled in-house using code in `JwtUtils`
- Due to the simplicity of the conversion and only requiring a tiny subset of the ASN.1 spec, it didn't make much sense to introduce another dependency.
- `fgrosse/phpasn1` is no longer required. This package was abandoned by its author and only used by PocketMine-MP for this one purpose.
- Various usages of `Closure::fromCallable()` have been replaced by PHP 8.1 first-class callable syntax.
- Blocks requiring support shifted to a "can be supported at" model, rather than "can be supported by".
- This model reduces repeated logic when placing and performing nearby block updates (no need to hardcode facing everywhere).
- In addition, this change facilitates the use of the newly introduced `Block->getAdjacentSupportType()` API method, reducing boilerplate support-type checking code.
- Bell block code has been simplified and cleaned up.
- `TallGrass` and `DoubleTallGrass` now use a shared `TallGrassTrait` to reduce code duplication.

View File

@ -22,7 +22,7 @@
"ext-openssl": "*",
"ext-pcre": "*",
"ext-phar": "*",
"ext-pmmpthread": "^6.0.1",
"ext-pmmpthread": "^6.0.4",
"ext-reflection": "*",
"ext-simplexml": "*",
"ext-sockets": "*",
@ -31,13 +31,12 @@
"ext-zip": "*",
"ext-zlib": ">=1.2.11",
"composer-runtime-api": "^2.0",
"adhocore/json-comment": "^1.1",
"fgrosse/phpasn1": "^2.3",
"pocketmine/netresearch-jsonmapper": "~v4.2.999",
"pocketmine/bedrock-block-upgrade-schema": "~2.1.0+bedrock-1.19.80",
"pocketmine/bedrock-data": "~2.2.0+bedrock-1.19.80",
"pocketmine/bedrock-item-upgrade-schema": "~1.2.0+bedrock-1.19.80",
"pocketmine/bedrock-protocol": "~21.0.0+bedrock-1.19.80",
"adhocore/json-comment": "~1.2.0",
"pocketmine/netresearch-jsonmapper": "~v4.2.1000",
"pocketmine/bedrock-block-upgrade-schema": "~3.1.0+bedrock-1.20.10",
"pocketmine/bedrock-data": "~2.4.0+bedrock-1.20.10",
"pocketmine/bedrock-item-upgrade-schema": "~1.4.0+bedrock-1.20.10",
"pocketmine/bedrock-protocol": "~23.0.2+bedrock-1.20.10",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/color": "^0.3.0",
@ -49,11 +48,11 @@
"pocketmine/raklib": "^0.15.0",
"pocketmine/raklib-ipc": "^0.2.0",
"pocketmine/snooze": "^0.5.0",
"ramsey/uuid": "^4.1",
"symfony/filesystem": "^6.2"
"ramsey/uuid": "~4.7.0",
"symfony/filesystem": "~6.3.0"
},
"require-dev": {
"phpstan/phpstan": "1.10.15",
"phpstan/phpstan": "1.10.16",
"phpstan/phpstan-phpunit": "^1.1.0",
"phpstan/phpstan-strict-rules": "^1.2.0",
"phpunit/phpunit": "^10.1"

199
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f48120203fe576d1ef1b7eddd8460d8f",
"content-hash": "ccd20e7656bc05ec2acd8e28aad9fcf2",
"packages": [
{
"name": "adhocore/json-comment",
@ -120,94 +120,18 @@
],
"time": "2023-01-15T23:15:59+00:00"
},
{
"name": "fgrosse/phpasn1",
"version": "v2.5.0",
"source": {
"type": "git",
"url": "https://github.com/fgrosse/PHPASN1.git",
"reference": "42060ed45344789fb9f21f9f1864fc47b9e3507b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fgrosse/PHPASN1/zipball/42060ed45344789fb9f21f9f1864fc47b9e3507b",
"reference": "42060ed45344789fb9f21f9f1864fc47b9e3507b",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"php-coveralls/php-coveralls": "~2.0",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
},
"suggest": {
"ext-bcmath": "BCmath is the fallback extension for big integer calculations",
"ext-curl": "For loading OID information from the web if they have not bee defined statically",
"ext-gmp": "GMP is the preferred extension for big integer calculations",
"phpseclib/bcmath_compat": "BCmath polyfill for servers where neither GMP nor BCmath is available"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"FG\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Friedrich Große",
"email": "friedrich.grosse@gmail.com",
"homepage": "https://github.com/FGrosse",
"role": "Author"
},
{
"name": "All contributors",
"homepage": "https://github.com/FGrosse/PHPASN1/contributors"
}
],
"description": "A PHP Framework that allows you to encode and decode arbitrary ASN.1 structures using the ITU-T X.690 Encoding Rules.",
"homepage": "https://github.com/FGrosse/PHPASN1",
"keywords": [
"DER",
"asn.1",
"asn1",
"ber",
"binary",
"decoding",
"encoding",
"x.509",
"x.690",
"x509",
"x690"
],
"support": {
"issues": "https://github.com/fgrosse/PHPASN1/issues",
"source": "https://github.com/fgrosse/PHPASN1/tree/v2.5.0"
},
"abandoned": true,
"time": "2022-12-19T11:08:26+00:00"
},
{
"name": "pocketmine/bedrock-block-upgrade-schema",
"version": "2.1.0",
"version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockBlockUpgradeSchema.git",
"reference": "1c07ced86be7d185551082441b5a2b9b7fbd6b21"
"reference": "6d4ae416043337946a22fc31e8065ca2c21f472d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/1c07ced86be7d185551082441b5a2b9b7fbd6b21",
"reference": "1c07ced86be7d185551082441b5a2b9b7fbd6b21",
"url": "https://api.github.com/repos/pmmp/BedrockBlockUpgradeSchema/zipball/6d4ae416043337946a22fc31e8065ca2c21f472d",
"reference": "6d4ae416043337946a22fc31e8065ca2c21f472d",
"shasum": ""
},
"type": "library",
@ -218,22 +142,22 @@
"description": "Schemas describing how to upgrade saved block data in older Minecraft: Bedrock Edition world saves",
"support": {
"issues": "https://github.com/pmmp/BedrockBlockUpgradeSchema/issues",
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/2.1.0"
"source": "https://github.com/pmmp/BedrockBlockUpgradeSchema/tree/3.1.0"
},
"time": "2023-04-19T17:58:49+00:00"
"time": "2023-07-12T12:05:36+00:00"
},
{
"name": "pocketmine/bedrock-data",
"version": "2.2.0+bedrock-1.19.80",
"version": "2.4.0+bedrock-1.20.10",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockData.git",
"reference": "33dd83601442b377af42ac91473278243cafd576"
"reference": "f98bd1cae46d2920058acf3b23c0bedeac79f4ab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/33dd83601442b377af42ac91473278243cafd576",
"reference": "33dd83601442b377af42ac91473278243cafd576",
"url": "https://api.github.com/repos/pmmp/BedrockData/zipball/f98bd1cae46d2920058acf3b23c0bedeac79f4ab",
"reference": "f98bd1cae46d2920058acf3b23c0bedeac79f4ab",
"shasum": ""
},
"type": "library",
@ -244,22 +168,22 @@
"description": "Blobs of data generated from Minecraft: Bedrock Edition, used by PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/BedrockData/issues",
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.19.80"
"source": "https://github.com/pmmp/BedrockData/tree/bedrock-1.20.10"
},
"time": "2023-04-26T20:00:35+00:00"
"time": "2023-07-12T11:51:54+00:00"
},
{
"name": "pocketmine/bedrock-item-upgrade-schema",
"version": "1.2.0",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockItemUpgradeSchema.git",
"reference": "dd804c3f2b1e8990434812627e62eb5bde9670a5"
"reference": "60d199afe5e371fd189b21d685ec1fed6ba54230"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/dd804c3f2b1e8990434812627e62eb5bde9670a5",
"reference": "dd804c3f2b1e8990434812627e62eb5bde9670a5",
"url": "https://api.github.com/repos/pmmp/BedrockItemUpgradeSchema/zipball/60d199afe5e371fd189b21d685ec1fed6ba54230",
"reference": "60d199afe5e371fd189b21d685ec1fed6ba54230",
"shasum": ""
},
"type": "library",
@ -270,22 +194,22 @@
"description": "JSON schemas for upgrading items found in older Minecraft: Bedrock world saves",
"support": {
"issues": "https://github.com/pmmp/BedrockItemUpgradeSchema/issues",
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.2.0"
"source": "https://github.com/pmmp/BedrockItemUpgradeSchema/tree/1.4.0"
},
"time": "2023-04-19T18:16:14+00:00"
"time": "2023-07-12T12:08:37+00:00"
},
{
"name": "pocketmine/bedrock-protocol",
"version": "21.0.1+bedrock-1.19.80",
"version": "23.0.2+bedrock-1.20.10",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "981ea2e76e207a25c1361df858c639feba5cf348"
"reference": "69a309a2dd7dcf3ec8c316385b866397e8c2cbfd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/981ea2e76e207a25c1361df858c639feba5cf348",
"reference": "981ea2e76e207a25c1361df858c639feba5cf348",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/69a309a2dd7dcf3ec8c316385b866397e8c2cbfd",
"reference": "69a309a2dd7dcf3ec8c316385b866397e8c2cbfd",
"shasum": ""
},
"require": {
@ -317,9 +241,9 @@
"description": "An implementation of the Minecraft: Bedrock Edition protocol in PHP",
"support": {
"issues": "https://github.com/pmmp/BedrockProtocol/issues",
"source": "https://github.com/pmmp/BedrockProtocol/tree/21.0.1+bedrock-1.19.80"
"source": "https://github.com/pmmp/BedrockProtocol/tree/23.0.2+bedrock-1.20.10"
},
"time": "2023-04-26T21:00:01+00:00"
"time": "2023-07-24T15:35:36+00:00"
},
{
"name": "pocketmine/binaryutils",
@ -639,16 +563,16 @@
},
{
"name": "pocketmine/netresearch-jsonmapper",
"version": "v4.2.999",
"version": "v4.2.1000",
"source": {
"type": "git",
"url": "https://github.com/pmmp/netresearch-jsonmapper.git",
"reference": "f700806dec756ed825a8200dc2950ead98265956"
"reference": "078764e869e9b732f97206ec9363480a77c35532"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/netresearch-jsonmapper/zipball/f700806dec756ed825a8200dc2950ead98265956",
"reference": "f700806dec756ed825a8200dc2950ead98265956",
"url": "https://api.github.com/repos/pmmp/netresearch-jsonmapper/zipball/078764e869e9b732f97206ec9363480a77c35532",
"reference": "078764e869e9b732f97206ec9363480a77c35532",
"shasum": ""
},
"require": {
@ -687,9 +611,9 @@
"support": {
"email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues",
"source": "https://github.com/pmmp/netresearch-jsonmapper/tree/v4.2.999"
"source": "https://github.com/pmmp/netresearch-jsonmapper/tree/v4.2.1000"
},
"time": "2023-06-01T13:43:01+00:00"
"time": "2023-07-14T10:44:14+00:00"
},
{
"name": "pocketmine/raklib",
@ -998,16 +922,16 @@
},
{
"name": "symfony/filesystem",
"version": "v6.2.10",
"version": "v6.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894"
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/fd588debf7d1bc16a2c84b4b3b71145d9946b894",
"reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
"reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae",
"shasum": ""
},
"require": {
@ -1041,7 +965,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v6.2.10"
"source": "https://github.com/symfony/filesystem/tree/v6.3.1"
},
"funding": [
{
@ -1057,7 +981,7 @@
"type": "tidelift"
}
],
"time": "2023-04-18T13:46:08+00:00"
"time": "2023-06-01T08:30:39+00:00"
},
{
"name": "symfony/polyfill-ctype",
@ -1287,16 +1211,16 @@
},
{
"name": "nikic/php-parser",
"version": "v4.15.5",
"version": "v4.16.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e"
"reference": "19526a33fb561ef417e822e85f08a00db4059c17"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e",
"reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17",
"reference": "19526a33fb561ef417e822e85f08a00db4059c17",
"shasum": ""
},
"require": {
@ -1337,9 +1261,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5"
"source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0"
},
"time": "2023-05-19T20:20:00+00:00"
"time": "2023-06-25T14:52:30+00:00"
},
{
"name": "phar-io/manifest",
@ -1454,16 +1378,16 @@
},
{
"name": "phpstan/phpstan",
"version": "1.10.15",
"version": "1.10.16",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd"
"reference": "352bdbb960bb523e3d71b834862589f910921c23"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/762c4dac4da6f8756eebb80e528c3a47855da9bd",
"reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/352bdbb960bb523e3d71b834862589f910921c23",
"reference": "352bdbb960bb523e3d71b834862589f910921c23",
"shasum": ""
},
"require": {
@ -1512,7 +1436,7 @@
"type": "tidelift"
}
],
"time": "2023-05-09T15:28:01+00:00"
"time": "2023-06-05T08:21:46+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
@ -1937,16 +1861,16 @@
},
{
"name": "phpunit/phpunit",
"version": "10.2.0",
"version": "10.2.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "3aad97fde1f3e490e2b316ba56bc4680310e3c3f"
"reference": "1c17815c129f133f3019cc18e8d0c8622e6d9bcd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3aad97fde1f3e490e2b316ba56bc4680310e3c3f",
"reference": "3aad97fde1f3e490e2b316ba56bc4680310e3c3f",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1c17815c129f133f3019cc18e8d0c8622e6d9bcd",
"reference": "1c17815c129f133f3019cc18e8d0c8622e6d9bcd",
"shasum": ""
},
"require": {
@ -2018,7 +1942,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.2.0"
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.2.6"
},
"funding": [
{
@ -2034,7 +1958,7 @@
"type": "tidelift"
}
],
"time": "2023-06-02T05:42:13+00:00"
"time": "2023-07-17T12:08:28+00:00"
},
{
"name": "sebastian/cli-parser",
@ -2546,16 +2470,16 @@
},
{
"name": "sebastian/global-state",
"version": "6.0.0",
"version": "6.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "aab257c712de87b90194febd52e4d184551c2d44"
"reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/aab257c712de87b90194febd52e4d184551c2d44",
"reference": "aab257c712de87b90194febd52e4d184551c2d44",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4",
"reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4",
"shasum": ""
},
"require": {
@ -2595,7 +2519,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/6.0.0"
"security": "https://github.com/sebastianbergmann/global-state/security/policy",
"source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1"
},
"funding": [
{
@ -2603,7 +2528,7 @@
"type": "github"
}
],
"time": "2023-02-03T07:07:38+00:00"
"time": "2023-07-19T07:19:23+00:00"
},
{
"name": "sebastian/lines-of-code",
@ -3020,7 +2945,7 @@
"ext-openssl": "*",
"ext-pcre": "*",
"ext-phar": "*",
"ext-pmmpthread": "^6.0.1",
"ext-pmmpthread": "^6.0.4",
"ext-reflection": "*",
"ext-simplexml": "*",
"ext-sockets": "*",

View File

@ -120,8 +120,8 @@ namespace pocketmine {
}
if(($pmmpthread_version = phpversion("pmmpthread")) !== false){
if(version_compare($pmmpthread_version, "6.0.1") < 0 || version_compare($pmmpthread_version, "7.0.0") >= 0){
$messages[] = "pmmpthread ^6.0.1 is required, while you have $pmmpthread_version.";
if(version_compare($pmmpthread_version, "6.0.4") < 0 || version_compare($pmmpthread_version, "7.0.0") >= 0){
$messages[] = "pmmpthread ^6.0.4 is required, while you have $pmmpthread_version.";
}
}
@ -341,7 +341,7 @@ JIT_WARNING
if(ThreadManager::getInstance()->stopAll() > 0){
$logger->debug("Some threads could not be stopped, performing a force-kill");
Process::kill(Process::pid(), true);
Process::kill(Process::pid());
}
}while(false);

View File

@ -93,6 +93,7 @@ use pocketmine\scheduler\AsyncPool;
use pocketmine\snooze\SleeperHandler;
use pocketmine\stats\SendUsageTask;
use pocketmine\thread\log\AttachableThreadSafeLogger;
use pocketmine\thread\ThreadCrashException;
use pocketmine\thread\ThreadSafeClassLoader;
use pocketmine\timings\Timings;
use pocketmine\timings\TimingsHandler;
@ -1009,7 +1010,7 @@ class Server{
$this->playerDataProvider = new DatFilePlayerDataProvider(Path::join($this->dataPath, "players"));
register_shutdown_function([$this, "crashDump"]);
register_shutdown_function($this->crashDump(...));
$loadErrorCount = 0;
$this->pluginManager->loadPlugins($this->pluginPath, $loadErrorCount);
@ -1427,7 +1428,7 @@ class Server{
private function forceShutdownExit() : void{
$this->forceShutdown();
Process::kill(Process::pid(), true);
Process::kill(Process::pid());
}
public function forceShutdown() : void{
@ -1495,7 +1496,7 @@ class Server{
}catch(\Throwable $e){
$this->logger->logException($e);
$this->logger->emergency("Crashed while crashing, killing process");
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
}
}
@ -1516,23 +1517,38 @@ class Server{
$trace = $e->getTrace();
}
$errstr = $e->getMessage();
$errfile = $e->getFile();
$errline = $e->getLine();
//If this is a thread crash, this logs where the exception came from on the main thread, as opposed to the
//crashed thread. This is intentional, and might be useful for debugging
//Assume that the thread already logged the original exception with the correct stack trace
$this->logger->logException($e, $trace);
if($e instanceof ThreadCrashException){
$info = $e->getCrashInfo();
$type = $info->getType();
$errstr = $info->getMessage();
$errfile = $info->getFile();
$errline = $info->getLine();
$printableTrace = $info->getTrace();
$thread = $info->getThreadName();
}else{
$type = get_class($e);
$errstr = $e->getMessage();
$errfile = $e->getFile();
$errline = $e->getLine();
$printableTrace = Utils::printableTraceWithMetadata($trace);
$thread = "Main";
}
$errstr = preg_replace('/\s+/', ' ', trim($errstr));
$errfile = Filesystem::cleanPath($errfile);
$this->logger->logException($e, $trace);
$lastError = [
"type" => get_class($e),
"type" => $type,
"message" => $errstr,
"fullFile" => $e->getFile(),
"file" => $errfile,
"fullFile" => $errfile,
"file" => Filesystem::cleanPath($errfile),
"line" => $errline,
"trace" => $trace
"trace" => $printableTrace,
"thread" => $thread
];
global $lastExceptionError, $lastError;
@ -1649,7 +1665,7 @@ class Server{
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
sleep($spacing);
}
@Process::kill(Process::pid(), true);
@Process::kill(Process::pid());
exit(1);
}

View File

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

View File

@ -0,0 +1,136 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\event\block\StructureGrowEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
abstract class BaseBigDripleaf extends Transparent{
use HorizontalFacingTrait;
abstract protected function isHead() : bool;
private function canBeSupportedBy(Block $block, bool $head) : bool{
//TODO: Moss block
return
($block instanceof BaseBigDripleaf && $block->isHead() === $head) ||
$block->getTypeId() === BlockTypeIds::CLAY ||
$block->hasTypeTag(BlockTypeTags::DIRT) ||
$block->hasTypeTag(BlockTypeTags::MUD);
}
public function onNearbyBlockChange() : void{
if(
(!$this->isHead() && !$this->getSide(Facing::UP) instanceof BaseBigDripleaf) ||
!$this->canBeSupportedBy($this->getSide(Facing::DOWN), false)
){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$block = $blockReplace->getSide(Facing::DOWN);
if(!$this->canBeSupportedBy($block, true)){
return false;
}
if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
if($block instanceof BaseBigDripleaf){
$this->facing = $block->getFacing();
$tx->addBlock($block->getPosition(), VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($this->facing));
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && $this->grow($player)){
$item->pop();
return true;
}
return false;
}
private function seekToHead() : ?BaseBigDripleaf{
if($this->isHead()){
return $this;
}
$step = 1;
while(($next = $this->getSide(Facing::UP, $step)) instanceof BaseBigDripleaf){
if($next->isHead()){
return $next;
}
$step++;
}
return null;
}
private function grow(?Player $player) : bool{
$head = $this->seekToHead();
if($head === null){
return false;
}
$pos = $head->getPosition();
$up = $pos->up();
$world = $pos->getWorld();
if(
!$world->isInWorld($up->getFloorX(), $up->getFloorY(), $up->getFloorZ()) ||
$world->getBlock($up)->getTypeId() !== BlockTypeIds::AIR
){
return false;
}
$tx = new BlockTransaction($world);
$tx->addBlock($pos, VanillaBlocks::BIG_DRIPLEAF_STEM()->setFacing($head->getFacing()));
$tx->addBlock($up, VanillaBlocks::BIG_DRIPLEAF_HEAD()->setFacing($head->getFacing()));
$ev = new StructureGrowEvent($head, $tx, $player);
$ev->call();
if(!$ev->isCancelled()){
return $tx->apply();
}
return false;
}
public function getFlameEncouragement() : int{
return 15;
}
public function getFlammability() : int{
return 100;
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,132 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\DripleafState;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Projectile;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\world\sound\DripleafTiltDownSound;
use pocketmine\world\sound\DripleafTiltUpSound;
class BigDripleafHead extends BaseBigDripleaf{
protected DripleafState $leafState;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
$this->leafState = DripleafState::STABLE();
parent::__construct($idInfo, $name, $typeInfo);
}
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
parent::describeBlockOnlyState($w);
$w->dripleafState($this->leafState);
}
protected function isHead() : bool{
return true;
}
public function getLeafState() : DripleafState{
return $this->leafState;
}
/** @return $this */
public function setLeafState(DripleafState $leafState) : self{
$this->leafState = $leafState;
return $this;
}
public function hasEntityCollision() : bool{
return true;
}
private function setTiltAndScheduleTick(DripleafState $tilt) : void{
$this->position->getWorld()->setBlock($this->position, $this->setLeafState($tilt));
$delay = $tilt->getScheduledUpdateDelayTicks();
if($delay !== null){
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, $delay);
}
}
private function getLeafTopOffset() : float{
return match($this->leafState){
DripleafState::STABLE(), DripleafState::UNSTABLE() => 1 / 16,
DripleafState::PARTIAL_TILT() => 3 / 16,
default => 0
};
}
public function onEntityInside(Entity $entity) : bool{
if(!$entity instanceof Projectile && $this->leafState->equals(DripleafState::STABLE())){
//the entity must be standing on top of the leaf - do not collapse if the entity is standing underneath
$intersection = AxisAlignedBB::one()
->offset($this->position->x, $this->position->y, $this->position->z)
->trim(Facing::DOWN, 1 - $this->getLeafTopOffset());
if($entity->getBoundingBox()->intersectsWith($intersection)){
$this->setTiltAndScheduleTick(DripleafState::UNSTABLE());
return false;
}
}
return true;
}
public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResult) : void{
if(!$this->leafState->equals(DripleafState::FULL_TILT())){
$this->setTiltAndScheduleTick(DripleafState::FULL_TILT());
$this->position->getWorld()->addSound($this->position, new DripleafTiltDownSound());
}
}
public function onScheduledUpdate() : void{
if(!$this->leafState->equals(DripleafState::STABLE())){
if($this->leafState->equals(DripleafState::FULL_TILT())){
$this->position->getWorld()->setBlock($this->position, $this->setLeafState(DripleafState::STABLE()));
$this->position->getWorld()->addSound($this->position, new DripleafTiltUpSound());
}else{
$this->setTiltAndScheduleTick(match($this->leafState->id()){
DripleafState::UNSTABLE()->id() => DripleafState::PARTIAL_TILT(),
DripleafState::PARTIAL_TILT()->id() => DripleafState::FULL_TILT(),
default => throw new AssumptionFailedError("All types should be covered")
});
$this->position->getWorld()->addSound($this->position, new DripleafTiltDownSound());
}
}
}
protected function recalculateCollisionBoxes() : array{
if(!$this->leafState->equals(DripleafState::FULL_TILT())){
return [
AxisAlignedBB::one()
->trim(Facing::DOWN, 11 / 16)
->trim(Facing::UP, $this->getLeafTopOffset())
];
}
return [];
}
}

View File

@ -0,0 +1,41 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
class BigDripleafStem extends BaseBigDripleaf{
protected function isHead() : bool{
return false;
}
protected function recalculateCollisionBoxes() : array{
return [];
}
public function asItem() : Item{
return VanillaBlocks::BIG_DRIPLEAF_HEAD()->asItem();
}
}

View File

@ -41,6 +41,7 @@ use pocketmine\item\Item;
use pocketmine\item\ItemBlock;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
@ -467,7 +468,8 @@ class Block{
/**
* Do actions when interacted by Item. Returns if it has done anything
*
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
* @param Vector3 $clickVector Exact position where the click occurred, relative to the block's integer position
* @param Item[] &$returnedItems Items to be added to the target's inventory (or dropped, if the inventory is full)
*/
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
return false;
@ -862,6 +864,10 @@ class Block{
return SupportType::FULL();
}
protected function getAdjacentSupportType(int $facing) : SupportType{
return $this->getSide($facing)->getSupportType(Facing::opposite($facing));
}
public function isFullCube() : bool{
$bb = $this->getCollisionBoxes();

View File

@ -717,8 +717,27 @@ final class BlockTypeIds{
public const FLOWERING_AZALEA_LEAVES = 10687;
public const REINFORCED_DEEPSLATE = 10688;
public const CAVE_VINES = 10689;
public const GLOW_LICHEN = 10690;
public const CHERRY_BUTTON = 10691;
public const CHERRY_DOOR = 10692;
public const CHERRY_FENCE = 10693;
public const CHERRY_FENCE_GATE = 10694;
public const CHERRY_LEAVES = 10695;
public const CHERRY_LOG = 10696;
public const CHERRY_PLANKS = 10697;
public const CHERRY_PRESSURE_PLATE = 10698;
public const CHERRY_SAPLING = 10699;
public const CHERRY_SIGN = 10700;
public const CHERRY_SLAB = 10701;
public const CHERRY_STAIRS = 10702;
public const CHERRY_TRAPDOOR = 10703;
public const CHERRY_WALL_SIGN = 10704;
public const CHERRY_WOOD = 10705;
public const SMALL_DRIPLEAF = 10706;
public const BIG_DRIPLEAF_HEAD = 10707;
public const BIG_DRIPLEAF_STEM = 10708;
public const FIRST_UNUSED_BLOCK_ID = 10690;
public const FIRST_UNUSED_BLOCK_ID = 10709;
private static int $nextDynamicId = self::FIRST_UNUSED_BLOCK_ID;

View File

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

View File

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

View File

@ -104,8 +104,7 @@ class Candle extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $blockReplace->getSide(Facing::DOWN);
if(!$down->getSupportType(Facing::UP)->hasCenterSupport()){
if(!$blockReplace->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport()){
return false;
}
$existing = $this->getCandleIfCompatibleType($blockReplace);

View File

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

View File

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

View File

@ -87,18 +87,18 @@ class CaveVines extends Flowable{
return $this->berries ? 14 : 0;
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::DOWN)->equals(SupportType::FULL()) || $block->hasSameTypeId($this);
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::UP)->equals(SupportType::FULL()) || $block->hasSameTypeId($this);
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::UP))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::UP))){
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
$this->age = mt_rand(0, self::MAX_AGE);

View File

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

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\block\tile\Chest as TileChest;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\event\block\ChestPairEvent;
use pocketmine\item\Item;
@ -36,7 +35,6 @@ use pocketmine\player\Player;
class Chest extends Transparent{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
/**
* @return AxisAlignedBB[]

View File

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

View File

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

View File

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

View File

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

View File

@ -106,7 +106,7 @@ class Door extends Transparent{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN)) && !$this->getSide(Facing::DOWN) instanceof Door){ //Replace with common break method
if(!$this->canBeSupportedAt($this) && !$this->getSide(Facing::DOWN) instanceof Door){ //Replace with common break method
$this->position->getWorld()->useBreakOn($this->position); //this will delete both halves if they exist
}
}
@ -114,8 +114,7 @@ class Door extends Transparent{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face === Facing::UP){
$blockUp = $this->getSide(Facing::UP);
$blockDown = $this->getSide(Facing::DOWN);
if(!$blockUp->canBeReplaced() || !$this->canBeSupportedBy($blockDown)){
if(!$blockUp->canBeReplaced() || !$this->canBeSupportedAt($blockReplace)){
return false;
}
@ -172,7 +171,7 @@ class Door extends Transparent{
return parent::getAffectedBlocks();
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->hasEdgeSupport();
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->hasEdgeSupport();
}
}

View File

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

View File

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

View File

@ -24,14 +24,12 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
class EndPortalFrame extends Opaque{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
protected bool $eye = false;

View File

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

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\BlockBurnEvent;
use pocketmine\event\block\BlockSpreadEvent;
@ -58,12 +59,16 @@ class Fire extends BaseFire{
return 1;
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->equals(SupportType::FULL());
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
$down = $this->getSide(Facing::DOWN);
if(SoulFire::canBeSupportedBy($down)){
$world->setBlock($this->position, VanillaBlocks::SOUL_FIRE());
}elseif($down->isTransparent() && !$this->hasAdjacentFlammableBlocks()){
}elseif(!$this->canBeSupportedBy($this->getSide(Facing::DOWN)) && !$this->hasAdjacentFlammableBlocks()){
$world->setBlock($this->position, VanillaBlocks::AIR());
}else{
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(30, 40));

View File

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

View File

@ -90,7 +90,7 @@ class FlowerPot extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
@ -98,13 +98,13 @@ class FlowerPot extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->hasCenterSupport();
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport();
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{

View File

@ -48,12 +48,7 @@ class FrostedIce extends Ice{
}
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->checkAdjacentBlocks(2)){
$world->useBreakOn($this->position);
}else{
$world->scheduleDelayedBlockUpdate($this->position, mt_rand(20, 40));
}
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(20, 40));
}
public function onRandomTick() : void{

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\block\tile\Furnace as TileFurnace;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\crafting\FurnaceType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
@ -35,7 +34,6 @@ use function mt_rand;
class Furnace extends Opaque{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
protected FurnaceType $furnaceType;

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
@ -30,7 +31,7 @@ use function mt_rand;
final class GildedBlackstone extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
if(mt_rand(1, 10) === 1){
if(FortuneDropHelper::bonusChanceDivisor($item, 10, 3)){
return [VanillaItems::GOLD_NUGGET()->setCount(mt_rand(2, 5))];
}

View File

@ -26,12 +26,10 @@ namespace pocketmine\block;
use pocketmine\block\utils\ColoredTrait;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
class GlazedTerracotta extends Opaque{
use ColoredTrait;
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockTypeInfo $typeInfo){
$this->color = DyeColor::BLACK();

284
src/block/GlowLichen.php Normal file
View File

@ -0,0 +1,284 @@
<?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\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\World;
use function array_key_first;
use function count;
use function shuffle;
class GlowLichen extends Transparent{
/** @var int[] */
protected array $faces = [];
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->facingFlags($this->faces);
}
/** @return int[] */
public function getFaces() : array{ return $this->faces; }
public function hasFace(int $face) : bool{
return isset($this->faces[$face]);
}
/**
* @param int[] $faces
* @return $this
*/
public function setFaces(array $faces) : self{
$uniqueFaces = [];
foreach($faces as $face){
Facing::validate($face);
$uniqueFaces[$face] = $face;
}
$this->faces = $uniqueFaces;
return $this;
}
/** @return $this */
public function setFace(int $face, bool $value) : self{
Facing::validate($face);
if($value){
$this->faces[$face] = $face;
}else{
unset($this->faces[$face]);
}
return $this;
}
public function getLightLevel() : int{
return 7;
}
public function isSolid() : bool{
return false;
}
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{
return [];
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
public function canBeReplaced() : bool{
return true;
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->faces = $blockReplace instanceof GlowLichen ? $blockReplace->faces : [];
$availableFaces = $this->getAvailableFaces();
if(count($availableFaces) === 0){
return false;
}
$opposite = Facing::opposite($face);
$placedFace = isset($availableFaces[$opposite]) ? $opposite : array_key_first($availableFaces);
$this->faces[$placedFace] = $placedFace;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onNearbyBlockChange() : void{
$changed = false;
foreach($this->faces as $face){
if(!$this->getAdjacentSupportType($face)->equals(SupportType::FULL())){
unset($this->faces[$face]);
$changed = true;
}
}
if($changed){
$world = $this->position->getWorld();
if(count($this->faces) === 0){
$world->useBreakOn($this->position);
}else{
$world->setBlock($this->position, $this);
}
}
}
private function getSpreadBlock(Block $replace, int $spreadFace) : ?Block{
if($replace instanceof self && $replace->hasSameTypeId($this)){
if($replace->hasFace($spreadFace)){
return null;
}
$result = $replace;
}elseif($replace->getTypeId() === BlockTypeIds::AIR){
$result = VanillaBlocks::GLOW_LICHEN();
}else{
//TODO: if this is a water block, generate a waterlogged block
return null;
}
return $result->setFace($spreadFace, true);
}
private function spread(World $world, Vector3 $replacePos, int $spreadFace) : bool{
$supportBlock = $world->getBlock($replacePos->getSide($spreadFace));
$supportFace = Facing::opposite($spreadFace);
if(!$supportBlock->getSupportType($supportFace)->equals(SupportType::FULL())){
return false;
}
$replacedBlock = $supportBlock->getSide($supportFace);
$replacementBlock = $this->getSpreadBlock($replacedBlock, Facing::opposite($supportFace));
if($replacementBlock === null){
return false;
}
$ev = new BlockSpreadEvent($replacedBlock, $this, $replacementBlock);
$ev->call();
if(!$ev->isCancelled()){
$world->setBlock($replacedBlock->getPosition(), $ev->getNewState());
return true;
}
return false;
}
/**
* @phpstan-return \Generator<int, int, void, void>
*/
private static function getShuffledSpreadFaces(int $sourceFace) : \Generator{
$skipAxis = Facing::axis($sourceFace);
$faces = Facing::ALL;
shuffle($faces);
foreach($faces as $spreadFace){
if(Facing::axis($spreadFace) !== $skipAxis){
yield $spreadFace;
}
}
}
private function spreadAroundSupport(int $sourceFace) : bool{
$world = $this->position->getWorld();
$supportPos = $this->position->getSide($sourceFace);
foreach(self::getShuffledSpreadFaces($sourceFace) as $spreadFace){
$replacePos = $supportPos->getSide($spreadFace);
if($this->spread($world, $replacePos, Facing::opposite($spreadFace))){
return true;
}
}
return false;
}
private function spreadAdjacentToSupport(int $sourceFace) : bool{
$world = $this->position->getWorld();
foreach(self::getShuffledSpreadFaces($sourceFace) as $spreadFace){
$replacePos = $this->position->getSide($spreadFace);
if($this->spread($world, $replacePos, $sourceFace)){
return true;
}
}
return false;
}
private function spreadWithinSelf(int $sourceFace) : bool{
foreach(self::getShuffledSpreadFaces($sourceFace) as $spreadFace){
if(!$this->hasFace($spreadFace) && $this->spread($this->position->getWorld(), $this->position, $spreadFace)){
return true;
}
}
return false;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($item instanceof Fertilizer && count($this->faces) > 0){
$shuffledFaces = $this->faces;
shuffle($shuffledFaces);
$spreadMethods = [
$this->spreadAroundSupport(...),
$this->spreadAdjacentToSupport(...),
$this->spreadWithinSelf(...),
];
shuffle($spreadMethods);
foreach($shuffledFaces as $sourceFace){
foreach($spreadMethods as $spreadMethod){
if($spreadMethod($sourceFace)){
$item->pop();
break 2;
}
}
}
return true;
}
return false;
}
public function getDrops(Item $item) : array{
if(($item->getBlockToolType() & BlockToolType::SHEARS) !== 0){
return $this->getDropsForCompatibleTool($item);
}
return [];
}
public function getFlameEncouragement() : int{
return 15;
}
public function getFlammability() : int{
return 100;
}
/**
* @return array<int, int> $faces
*/
private function getAvailableFaces() : array{
$faces = [];
foreach(Facing::ALL as $face){
if(!$this->hasFace($face) && $this->getAdjacentSupportType($face)->equals(SupportType::FULL())){
$faces[$face] = $face;
}
}
return $faces;
}
}

View File

@ -23,9 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
use function min;
class Glowstone extends Transparent{
@ -35,7 +36,7 @@ class Glowstone extends Transparent{
public function getDropsForCompatibleTool(Item $item) : array{
return [
VanillaItems::GLOWSTONE_DUST()->setCount(mt_rand(2, 4))
VanillaItems::GLOWSTONE_DUST()->setCount(min(4, FortuneDropHelper::discrete($item, 2, 4)))
];
}

View File

@ -25,15 +25,15 @@ namespace pocketmine\block;
use pocketmine\block\utils\Fallable;
use pocketmine\block\utils\FallableTrait;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
class Gravel extends Opaque implements Fallable{
use FallableTrait;
public function getDropsForCompatibleTool(Item $item) : array{
if(mt_rand(1, 10) === 1){
if(FortuneDropHelper::bonusChanceDivisor($item, 10, 3)){
return [
VanillaItems::FLINT()
];

View File

@ -163,18 +163,18 @@ class ItemFrame extends Flowable{
return true;
}
private function canBeSupportedBy(Block $block, int $face) : bool{
return !$block->getSupportType($face)->equals(SupportType::NONE());
private function canBeSupportedAt(Block $block, int $face) : bool{
return !$block->getAdjacentSupportType($face)->equals(SupportType::NONE());
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)){
if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing))){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
if(!$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}

View File

@ -70,7 +70,7 @@ class Ladder extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face) && Facing::axis($face) !== Axis::Y){
if($this->canBeSupportedAt($blockReplace, Facing::opposite($face)) && Facing::axis($face) !== Axis::Y){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -79,12 +79,12 @@ class Ladder extends Transparent{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::opposite($this->facing)), $this->facing)){ //Replace with common break method
if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing))){ //Replace with common break method
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $block, int $face) : bool{
return $block->getSupportType($face)->equals(SupportType::FULL());
private function canBeSupportedAt(Block $block, int $face) : bool{
return $block->getAdjacentSupportType($face)->equals(SupportType::FULL());
}
}

View File

@ -77,22 +77,23 @@ class Lantern extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::UP), Facing::DOWN) && !$this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN), Facing::UP)){
$downSupport = $this->canBeSupportedAt($blockReplace, Facing::DOWN);
if(!$downSupport && !$this->canBeSupportedAt($blockReplace, Facing::UP)){
return false;
}
$this->hanging = ($face === Facing::DOWN || !$this->canBeSupportedBy($this->position->getWorld()->getBlock($blockReplace->getPosition()->down()), Facing::UP));
$this->hanging = $face === Facing::DOWN || !$downSupport;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
public function onNearbyBlockChange() : void{
$face = $this->hanging ? Facing::UP : Facing::DOWN;
if(!$this->canBeSupportedBy($this->getSide($face), Facing::opposite($face))){
if(!$this->canBeSupportedAt($this, $face)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $block, int $face) : bool{
return $block->getSupportType($face)->hasCenterSupport();
private function canBeSupportedAt(Block $block, int $face) : bool{
return $block->getAdjacentSupportType($face)->hasCenterSupport();
}
}

View File

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

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\block\utils\LeavesType;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
@ -138,7 +139,8 @@ class Leaves extends Transparent{
}
$drops = [];
if(mt_rand(1, 20) === 1){ //Saplings
if(FortuneDropHelper::bonusChanceDivisor($item, 20, 4)){ //Saplings
// TODO: according to the wiki, the jungle saplings have a different drop rate
$sapling = (match($this->leavesType){
LeavesType::ACACIA() => VanillaBlocks::ACACIA_SAPLING(),
LeavesType::BIRCH() => VanillaBlocks::BIRCH_SAPLING(),
@ -148,16 +150,20 @@ class Leaves extends Transparent{
LeavesType::SPRUCE() => VanillaBlocks::SPRUCE_SAPLING(),
LeavesType::MANGROVE(), //TODO: mangrove propagule
LeavesType::AZALEA(), LeavesType::FLOWERING_AZALEA() => null, //TODO: azalea
LeavesType::CHERRY() => null, //TODO: cherry
default => throw new AssumptionFailedError("Unreachable")
})?->asItem();
if($sapling !== null){
$drops[] = $sapling;
}
}
if(($this->leavesType->equals(LeavesType::OAK()) || $this->leavesType->equals(LeavesType::DARK_OAK())) && mt_rand(1, 200) === 1){ //Apples
if(
($this->leavesType->equals(LeavesType::OAK()) || $this->leavesType->equals(LeavesType::DARK_OAK())) &&
FortuneDropHelper::bonusChanceDivisor($item, 200, 20)
){ //Apples
$drops[] = VanillaItems::APPLE();
}
if(mt_rand(1, 50) === 1){
if(FortuneDropHelper::bonusChanceDivisor($item, 50, 5)){
$drops[] = VanillaItems::STICK()->setCount(mt_rand(1, 2));
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\block\tile\Lectern as TileLectern;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
@ -39,7 +38,6 @@ use function count;
class Lectern extends Transparent{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
protected int $viewedPage = 0;
protected ?WritableBookBase $book = null;

View File

@ -66,7 +66,7 @@ class Lever extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
if(!$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}
@ -90,8 +90,7 @@ class Lever extends Flowable{
}
public function onNearbyBlockChange() : void{
$facing = $this->facing->getFacing();
if(!$this->canBeSupportedBy($this->getSide(Facing::opposite($facing)), $facing)){
if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing->getFacing()))){
$this->position->getWorld()->useBreakOn($this->position);
}
}
@ -107,8 +106,8 @@ class Lever extends Flowable{
return true;
}
private function canBeSupportedBy(Block $block, int $face) : bool{
return $block->getSupportType($face)->hasCenterSupport();
private function canBeSupportedAt(Block $block, int $face) : bool{
return $block->getAdjacentSupportType($face)->hasCenterSupport();
}
//TODO

View File

@ -312,7 +312,7 @@ abstract class Liquid extends Transparent{
}
if($adjacentDecay <= self::MAX_DECAY){
$calculator = new MinimumCostFlowCalculator($world, $this->getFlowDecayPerBlock(), \Closure::fromCallable([$this, 'canFlowInto']));
$calculator = new MinimumCostFlowCalculator($world, $this->getFlowDecayPerBlock(), $this->canFlowInto(...));
foreach($calculator->getOptimalFlowDirections($this->position->getFloorX(), $this->position->getFloorY(), $this->position->getFloorZ()) as $facing){
$this->flowIntoBlock($world->getBlock($this->position->getSide($facing)), $adjacentDecay, false);
}

View File

@ -25,14 +25,12 @@ namespace pocketmine\block;
use pocketmine\block\inventory\LoomInventory;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
final class Loom extends Opaque{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player !== null){

View File

@ -23,15 +23,16 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
use function min;
class Melon extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
return [
VanillaItems::MELON()->setCount(mt_rand(3, 7))
VanillaItems::MELON()->setCount(min(9, FortuneDropHelper::discrete($item, 3, 7)))
];
}

View File

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

View File

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

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity;
@ -82,16 +83,13 @@ class NetherVines extends Flowable{
return true;
}
private function getSupportFace() : int{
return Facing::opposite($this->growthFace);
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType($this->getSupportFace())->hasCenterSupport() || $block->hasSameTypeId($this);
private function canBeSupportedAt(Block $block) : bool{
$supportBlock = $block->getSide(Facing::opposite($this->growthFace));
return $supportBlock->getSupportType($this->growthFace)->hasCenterSupport() || $supportBlock->hasSameTypeId($this);
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide($this->getSupportFace()))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
@ -108,7 +106,7 @@ class NetherVines extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide($this->getSupportFace()))){
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
$this->age = mt_rand(0, self::MAX_AGE - 1);
@ -179,7 +177,7 @@ class NetherVines extends Flowable{
}
public function getDropsForCompatibleTool(Item $item) : array{
if(($item->getBlockToolType() & BlockToolType::SHEARS) !== 0 || mt_rand(1, 3) === 1){
if(($item->getBlockToolType() & BlockToolType::SHEARS) !== 0 || FortuneDropHelper::bonusChanceFixed($item, 1 / 3, 2 / 9)){
return [$this->asItem()];
}
return [];

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
@ -85,7 +86,7 @@ class NetherWartPlant extends Flowable{
public function getDropsForCompatibleTool(Item $item) : array{
return [
$this->asItem()->setCount($this->age === self::MAX_AGE ? mt_rand(2, 4) : 1)
$this->asItem()->setCount($this->age === self::MAX_AGE ? FortuneDropHelper::discrete($item, 2, 4) : 1)
];
}
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function mt_rand;
@ -31,7 +32,8 @@ class Potato extends Crops{
public function getDropsForCompatibleTool(Item $item) : array{
$result = [
VanillaItems::POTATO()->setCount($this->age >= self::MAX_AGE ? mt_rand(1, 5) : 1)
//min/max would be 2-5 in Java
VanillaItems::POTATO()->setCount($this->age >= self::MAX_AGE ? FortuneDropHelper::binomial($item, 1) : 1)
];
if($this->age >= self::MAX_AGE && mt_rand(0, 49) === 0){
$result[] = VanillaItems::POISONOUS_POTATO();

View File

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

View File

@ -85,7 +85,7 @@ class RedstoneComparator extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
if($this->canBeSupportedAt($blockReplace)){
if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
@ -102,13 +102,13 @@ class RedstoneComparator extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $block) : bool{
return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE());
private function canBeSupportedAt(Block $block) : bool{
return !$block->getAdjacentSupportType(Facing::DOWN)->equals(SupportType::NONE());
}
//TODO: redstone functionality

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
@ -81,7 +82,7 @@ class RedstoneOre extends Opaque{
public function getDropsForCompatibleTool(Item $item) : array{
return [
VanillaItems::REDSTONE_DUST()->setCount(mt_rand(4, 5))
VanillaItems::REDSTONE_DUST()->setCount(FortuneDropHelper::discrete($item, 4, 5))
];
}

View File

@ -68,7 +68,7 @@ class RedstoneRepeater extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
if($this->canBeSupportedAt($blockReplace)){
if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
@ -88,13 +88,13 @@ class RedstoneRepeater extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $block) : bool{
return !$block->getSupportType(Facing::UP)->equals(SupportType::NONE());
private function canBeSupportedAt(Block $block) : bool{
return !$block->getAdjacentSupportType(Facing::DOWN)->equals(SupportType::NONE());
}
//TODO: redstone functionality

View File

@ -35,7 +35,7 @@ class RedstoneWire extends Flowable{
use AnalogRedstoneSignalEmitterTrait;
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if($this->canBeSupportedAt($blockReplace)){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
return false;
@ -49,13 +49,13 @@ class RedstoneWire extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::UP)->hasCenterSupport();
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->hasCenterSupport();
}
public function asItem() : Item{

View File

@ -23,8 +23,10 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use function min;
class SeaLantern extends Transparent{
@ -34,7 +36,7 @@ class SeaLantern extends Transparent{
public function getDropsForCompatibleTool(Item $item) : array{
return [
VanillaItems::PRISMARINE_CRYSTALS()->setCount(3)
VanillaItems::PRISMARINE_CRYSTALS()->setCount(min(5, FortuneDropHelper::discrete($item, 2, 3)))
];
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\tile\ShulkerBox as TileShulkerBox;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
@ -110,4 +111,8 @@ class ShulkerBox extends Opaque{
return true;
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
}

170
src/block/SmallDripleaf.php Normal file
View File

@ -0,0 +1,170 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\StructureGrowEvent;
use pocketmine\item\Fertilizer;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\Position;
use function mt_rand;
class SmallDripleaf extends Transparent{
use HorizontalFacingTrait;
protected bool $top = false;
public function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
$w->horizontalFacing($this->facing);
$w->bool($this->top);
}
public function isTop() : bool{
return $this->top;
}
/** @return $this */
public function setTop(bool $top) : self{
$this->top = $top;
return $this;
}
private function canBeSupportedBy(Block $block) : bool{
//TODO: Moss
//TODO: Small Dripleaf also can be placed on dirt, coarse dirt, farmland, grass blocks,
// podzol, rooted dirt, mycelium, and mud if these blocks are underwater (needs waterlogging)
return $block->getTypeId() === BlockTypeIds::CLAY;
}
public function onNearbyBlockChange() : void{
if(!$this->top && !$this->canBeSupportedBy($this->getSide(Facing::DOWN))){
$this->position->getWorld()->useBreakOn($this->position);
return;
}
$face = $this->top ? Facing::DOWN : Facing::UP;
if(!$this->getSide($face)->hasSameTypeId($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$block = $blockReplace->getSide(Facing::UP);
if($block->getTypeId() !== BlockTypeIds::AIR || !$this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
return false;
}
if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
$tx->addBlock($block->getPosition(), VanillaBlocks::SMALL_DRIPLEAF()
->setFacing($this->facing)
->setTop(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($item instanceof Fertilizer && $this->grow($player)){
$item->pop();
return true;
}
return false;
}
private function canGrowTo(Position $pos) : bool{
$world = $pos->getWorld();
if(!$world->isInWorld($pos->getFloorX(), $pos->getFloorY(), $pos->getFloorZ())){
return false;
}
$block = $world->getBlock($pos);
return $block->hasSameTypeId($this) || $block->getTypeId() === BlockTypeIds::AIR;
}
private function grow(?Player $player) : bool{
$bottomBlock = $this->top ? $this->getSide(Facing::DOWN) : $this;
if(!$this->hasSameTypeId($bottomBlock)){
return false;
}
$world = $this->position->getWorld();
$tx = new BlockTransaction($world);
$height = mt_rand(2, 5);
$grown = 0;
for($i = 0; $i < $height; $i++){
$pos = $bottomBlock->getSide(Facing::UP, $i)->getPosition();
if(!$this->canGrowTo($pos)){
break;
}
$block = ++$grown < $height && $this->canGrowTo($pos->getSide(Facing::UP)) ?
VanillaBlocks::BIG_DRIPLEAF_STEM() :
VanillaBlocks::BIG_DRIPLEAF_HEAD();
$tx->addBlock($pos, $block->setFacing($this->facing));
}
if($grown > 1){
$ev = new StructureGrowEvent($bottomBlock, $tx, $player);
$ev->call();
if(!$ev->isCancelled()){
return $tx->apply();
}
}
return false;
}
public function getAffectedBlocks() : array{
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
if($other->hasSameTypeId($this)){
return [$this, $other];
}
return parent::getAffectedBlocks();
}
public function getDropsForCompatibleTool(Item $item) : array{
if(!$this->top){
return [$this->asItem()];
}
return [];
}
public function getFlameEncouragement() : int{
return 15;
}
public function getFlammability() : int{
return 100;
}
public function getSupportType(int $facing) : SupportType{
return SupportType::NONE();
}
protected function recalculateCollisionBoxes() : array{
return [];
}
}

View File

@ -80,8 +80,8 @@ class SnowLayer extends Flowable implements Fallable{
return SupportType::NONE();
}
private function canBeSupportedBy(Block $b) : bool{
return $b->getSupportType(Facing::UP)->equals(SupportType::FULL());
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::DOWN)->equals(SupportType::FULL());
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
@ -91,7 +91,7 @@ class SnowLayer extends Flowable implements Fallable{
}
$this->layers = $blockReplace->layers + 1;
}
if($this->canBeSupportedBy($blockReplace->getSide(Facing::DOWN))){
if($this->canBeSupportedAt($blockReplace)){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}

View File

@ -32,12 +32,12 @@ use pocketmine\world\BlockTransaction;
final class SporeBlossom extends Flowable{
private function canBeSupportedBy(Block $block) : bool{
return $block->getSupportType(Facing::DOWN)->equals(SupportType::FULL());
private function canBeSupportedAt(Block $block) : bool{
return $block->getAdjacentSupportType(Facing::UP)->equals(SupportType::FULL());
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canBeSupportedBy($blockReplace->getSide(Facing::UP))){
if(!$this->canBeSupportedAt($blockReplace)){
return false;
}
@ -45,7 +45,7 @@ final class SporeBlossom extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->canBeSupportedBy($this->getSide(Facing::UP))){
if(!$this->canBeSupportedAt($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
use pocketmine\math\Facing;
@ -30,11 +31,35 @@ use function array_rand;
use function mt_rand;
abstract class Stem extends Crops{
protected int $facing = Facing::UP;
protected function describeBlockOnlyState(RuntimeDataDescriber $w) : void{
parent::describeBlockOnlyState($w);
$w->facingExcept($this->facing, Facing::DOWN);
}
public function getFacing() : int{ return $this->facing; }
/** @return $this */
public function setFacing(int $facing) : self{
if($facing === Facing::DOWN){
throw new \InvalidArgumentException("DOWN is not a valid facing for this block");
}
$this->facing = $facing;
return $this;
}
abstract protected function getPlant() : Block;
public function onNearbyBlockChange() : void{
if($this->facing !== Facing::UP && !$this->getSide($this->facing)->hasSameTypeId($this->getPlant())){
$this->position->getWorld()->setBlock($this->position, $this->setFacing(Facing::UP));
}
parent::onNearbyBlockChange();
}
public function onRandomTick() : void{
if(mt_rand(0, 2) === 1){
if($this->facing === Facing::UP && mt_rand(0, 2) === 1){
$world = $this->position->getWorld();
if($this->age < self::MAX_AGE){
$block = clone $this;
@ -52,11 +77,13 @@ abstract class Stem extends Crops{
}
}
$side = $this->getSide(Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)]);
$facing = Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)];
$side = $this->getSide($facing);
if($side->getTypeId() === BlockTypeIds::AIR && $side->getSide(Facing::DOWN)->hasTypeTag(BlockTypeTags::DIRT)){
$ev = new BlockGrowEvent($side, $grow);
$ev->call();
if(!$ev->isCancelled()){
$world->setBlock($this->position, $this->setFacing($facing));
$world->setBlock($side->position, $ev->getNewState());
}
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\block\inventory\StonecutterInventory;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\SupportType;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
@ -35,7 +34,6 @@ use pocketmine\player\Player;
class Stonecutter extends Transparent{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player !== null){

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\FortuneDropHelper;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\entity\Entity;
use pocketmine\entity\Living;
@ -108,13 +109,14 @@ class SweetBerryBush extends Flowable{
}
public function getDropsForCompatibleTool(Item $item) : array{
if(($dropAmount = $this->getBerryDropAmount()) > 0){
return [
$this->asItem()->setCount($dropAmount)
];
}
return [];
$count = match($this->age){
self::STAGE_MATURE => FortuneDropHelper::discrete($item, 2, 3),
self::STAGE_BUSH_SOME_BERRIES => FortuneDropHelper::discrete($item, 1, 2),
default => 0
};
return [
$this->asItem()->setCount($count)
];
}
public function onNearbyBlockChange() : void{

View File

@ -23,19 +23,15 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\TallGrassTrait;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use function mt_rand;
class TallGrass extends Flowable{
public function canBeReplaced() : bool{
return true;
}
use TallGrassTrait;
private function canBeSupportedBy(Block $block) : bool{
return $block->hasTypeTag(BlockTypeTags::DIRT) || $block->hasTypeTag(BlockTypeTags::MUD);
@ -54,22 +50,4 @@ class TallGrass extends Flowable{
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function getDropsForIncompatibleTool(Item $item) : array{
if(mt_rand(0, 15) === 0){
return [
VanillaItems::WHEAT_SEEDS()
];
}
return [];
}
public function getFlameEncouragement() : int{
return 60;
}
public function getFlammability() : int{
return 100;
}
}

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\Axis;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
@ -56,15 +55,13 @@ class Torch extends Flowable{
}
public function onNearbyBlockChange() : void{
$face = Facing::opposite($this->facing);
if(!$this->canBeSupportedBy($this->getSide($face), $this->facing)){
if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing))){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face !== Facing::DOWN && $this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
if($face !== Facing::DOWN && $this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}else{
@ -75,8 +72,7 @@ class Torch extends Flowable{
Facing::EAST,
Facing::DOWN
] as $side){
$block = $this->getSide($side);
if($this->canBeSupportedBy($block, Facing::opposite($side))){
if($this->canBeSupportedAt($blockReplace, $side)){
$this->facing = Facing::opposite($side);
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -85,8 +81,9 @@ class Torch extends Flowable{
return false;
}
private function canBeSupportedBy(Block $support, int $face) : bool{
return ($face === Facing::UP && $support->getSupportType($face)->hasCenterSupport()) ||
(Facing::axis($face) !== Axis::Y && $support->getSupportType($face)->equals(SupportType::FULL()));
private function canBeSupportedAt(Block $block, int $face) : bool{
return $face === Facing::DOWN ?
$block->getAdjacentSupportType($face)->hasCenterSupport() :
$block->getAdjacentSupportType($face)->equals(SupportType::FULL());
}
}

View File

@ -113,6 +113,8 @@ use function mb_strtolower;
* @method static Bedrock BEDROCK()
* @method static Beetroot BEETROOTS()
* @method static Bell BELL()
* @method static BigDripleafHead BIG_DRIPLEAF_HEAD()
* @method static BigDripleafStem BIG_DRIPLEAF_STEM()
* @method static WoodenButton BIRCH_BUTTON()
* @method static WoodenDoor BIRCH_DOOR()
* @method static WoodenFence BIRCH_FENCE()
@ -159,6 +161,20 @@ use function mb_strtolower;
* @method static CaveVines CAVE_VINES()
* @method static Chain CHAIN()
* @method static ChemicalHeat CHEMICAL_HEAT()
* @method static WoodenButton CHERRY_BUTTON()
* @method static WoodenDoor CHERRY_DOOR()
* @method static WoodenFence CHERRY_FENCE()
* @method static FenceGate CHERRY_FENCE_GATE()
* @method static Leaves CHERRY_LEAVES()
* @method static Wood CHERRY_LOG()
* @method static Planks CHERRY_PLANKS()
* @method static WoodenPressurePlate CHERRY_PRESSURE_PLATE()
* @method static FloorSign CHERRY_SIGN()
* @method static WoodenSlab CHERRY_SLAB()
* @method static WoodenStairs CHERRY_STAIRS()
* @method static WoodenTrapdoor CHERRY_TRAPDOOR()
* @method static WallSign CHERRY_WALL_SIGN()
* @method static Wood CHERRY_WOOD()
* @method static Chest CHEST()
* @method static Opaque CHISELED_DEEPSLATE()
* @method static Opaque CHISELED_NETHER_BRICKS()
@ -417,6 +433,7 @@ use function mb_strtolower;
* @method static ItemFrame GLOWING_ITEM_FRAME()
* @method static GlowingObsidian GLOWING_OBSIDIAN()
* @method static Glowstone GLOWSTONE()
* @method static GlowLichen GLOW_LICHEN()
* @method static Opaque GOLD()
* @method static GoldOre GOLD_ORE()
* @method static Opaque GRANITE()
@ -643,6 +660,7 @@ use function mb_strtolower;
* @method static Opaque SHROOMLIGHT()
* @method static ShulkerBox SHULKER_BOX()
* @method static Slime SLIME()
* @method static SmallDripleaf SMALL_DRIPLEAF()
* @method static SmithingTable SMITHING_TABLE()
* @method static Furnace SMOKER()
* @method static Opaque SMOOTH_BASALT()
@ -864,6 +882,7 @@ final class VanillaBlocks{
self::register("glass_pane", new GlassPane(new BID(Ids::GLASS_PANE), "Glass Pane", $glassBreakInfo));
self::register("glowing_obsidian", new GlowingObsidian(new BID(Ids::GLOWING_OBSIDIAN), "Glowing Obsidian", new Info(BreakInfo::pickaxe(10.0, ToolTier::DIAMOND(), 50.0))));
self::register("glowstone", new Glowstone(new BID(Ids::GLOWSTONE), "Glowstone", new Info(BreakInfo::pickaxe(0.3))));
self::register("glow_lichen", new GlowLichen(new BID(Ids::GLOW_LICHEN), "Glow Lichen", new Info(BreakInfo::axe(0.2, null, 0.2))));
self::register("gold", new Opaque(new BID(Ids::GOLD), "Gold Block", new Info(BreakInfo::pickaxe(3.0, ToolTier::IRON(), 30.0))));
$grassBreakInfo = BreakInfo::shovel(0.6);
@ -1582,6 +1601,10 @@ final class VanillaBlocks{
self::register("hanging_roots", new HangingRoots(new BID(Ids::HANGING_ROOTS), "Hanging Roots", new Info(BreakInfo::instant(ToolType::SHEARS, 1))));
self::register("cave_vines", new CaveVines(new BID(Ids::CAVE_VINES), "Cave Vines", new Info(BreakInfo::instant())));
self::register("small_dripleaf", new SmallDripleaf(new BID(Ids::SMALL_DRIPLEAF), "Small Dripleaf", new Info(BreakInfo::instant(BlockToolType::SHEARS, toolHarvestLevel: 1))));
self::register("big_dripleaf_head", new BigDripleafHead(new BID(Ids::BIG_DRIPLEAF_HEAD), "Big Dripleaf", new Info(BreakInfo::instant())));
self::register("big_dripleaf_stem", new BigDripleafStem(new BID(Ids::BIG_DRIPLEAF_STEM), "Big Dripleaf Stem", new Info(BreakInfo::instant())));
}
private static function registerBlocksR18() : void{

View File

@ -42,7 +42,7 @@ final class WallCoralFan extends BaseCoral{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$axis = Facing::axis($face);
if(($axis !== Axis::X && $axis !== Axis::Z) || !$this->canBeSupportedBy($blockReplace->getSide(Facing::opposite($face)), $face)){
if(($axis !== Axis::X && $axis !== Axis::Z) || !$this->canBeSupportedAt($blockReplace, Facing::opposite($face))){
return false;
}
$this->facing = $face;
@ -54,15 +54,15 @@ final class WallCoralFan extends BaseCoral{
public function onNearbyBlockChange() : void{
$world = $this->position->getWorld();
if(!$this->canBeSupportedBy($world->getBlock($this->position->getSide(Facing::opposite($this->facing))), $this->facing)){
if(!$this->canBeSupportedAt($this, Facing::opposite($this->facing))){
$world->useBreakOn($this->position);
}else{
parent::onNearbyBlockChange();
}
}
private function canBeSupportedBy(Block $block, int $face) : bool{
return $block->getSupportType($face)->hasCenterSupport();
private function canBeSupportedAt(Block $block, int $face) : bool{
return $block->getAdjacentSupportType($face)->hasCenterSupport();
}
public function asItem() : Item{

View File

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

View File

@ -58,6 +58,7 @@ final class WoodLikeBlockIdHelper{
WoodType::MANGROVE()->id() => Ids::MANGROVE_PLANKS,
WoodType::CRIMSON()->id() => Ids::CRIMSON_PLANKS,
WoodType::WARPED()->id() => Ids::WARPED_PLANKS,
WoodType::CHERRY()->id() => Ids::CHERRY_PLANKS,
default => throw new AssumptionFailedError("All tree types should be covered")
});
}
@ -73,6 +74,7 @@ final class WoodLikeBlockIdHelper{
WoodType::MANGROVE()->id() => Ids::MANGROVE_FENCE,
WoodType::CRIMSON()->id() => Ids::CRIMSON_FENCE,
WoodType::WARPED()->id() => Ids::WARPED_FENCE,
WoodType::CHERRY()->id() => Ids::CHERRY_FENCE,
default => throw new AssumptionFailedError("All tree types should be covered")
});
}
@ -88,6 +90,7 @@ final class WoodLikeBlockIdHelper{
WoodType::MANGROVE()->id() => Ids::MANGROVE_SLAB,
WoodType::CRIMSON()->id() => Ids::CRIMSON_SLAB,
WoodType::WARPED()->id() => Ids::WARPED_SLAB,
WoodType::CHERRY()->id() => Ids::CHERRY_SLAB,
default => throw new AssumptionFailedError("All tree types should be covered")
});
}
@ -103,6 +106,7 @@ final class WoodLikeBlockIdHelper{
WoodType::MANGROVE()->id() => Ids::MANGROVE_LOG,
WoodType::CRIMSON()->id() => Ids::CRIMSON_STEM,
WoodType::WARPED()->id() => Ids::WARPED_STEM,
WoodType::CHERRY()->id() => Ids::CHERRY_LOG,
default => throw new AssumptionFailedError("All tree types should be covered")
});
}
@ -118,6 +122,7 @@ final class WoodLikeBlockIdHelper{
WoodType::MANGROVE()->id() => Ids::MANGROVE_WOOD,
WoodType::CRIMSON()->id() => Ids::CRIMSON_HYPHAE,
WoodType::WARPED()->id() => Ids::WARPED_HYPHAE,
WoodType::CHERRY()->id() => Ids::CHERRY_WOOD,
default => throw new AssumptionFailedError("All tree types should be covered")
});
}
@ -133,6 +138,7 @@ final class WoodLikeBlockIdHelper{
LeavesType::MANGROVE()->id() => Ids::MANGROVE_LEAVES,
LeavesType::AZALEA()->id() => Ids::AZALEA_LEAVES,
LeavesType::FLOWERING_AZALEA()->id() => Ids::FLOWERING_AZALEA_LEAVES,
LeavesType::CHERRY()->id() => Ids::CHERRY_LEAVES,
default => throw new AssumptionFailedError("All leaves types should be covered")
});
}
@ -209,7 +215,12 @@ final class WoodLikeBlockIdHelper{
new BID(Ids::WARPED_WALL_SIGN, TileSign::class),
fn() => VanillaItems::WARPED_SIGN()
];
case WoodType::CHERRY()->id():
return [
new BID(Ids::CHERRY_SIGN, TileSign::class),
new BID(Ids::CHERRY_WALL_SIGN, TileSign::class),
fn() => VanillaItems::CHERRY_SIGN()
];
}
throw new AssumptionFailedError("Switch should cover all wood types");
}
@ -225,6 +236,7 @@ final class WoodLikeBlockIdHelper{
WoodType::MANGROVE()->id() => Ids::MANGROVE_TRAPDOOR,
WoodType::CRIMSON()->id() => Ids::CRIMSON_TRAPDOOR,
WoodType::WARPED()->id() => Ids::WARPED_TRAPDOOR,
WoodType::CHERRY()->id() => Ids::CHERRY_TRAPDOOR,
default => throw new AssumptionFailedError("All wood types should be covered")
});
}
@ -240,6 +252,7 @@ final class WoodLikeBlockIdHelper{
WoodType::MANGROVE()->id() => Ids::MANGROVE_BUTTON,
WoodType::CRIMSON()->id() => Ids::CRIMSON_BUTTON,
WoodType::WARPED()->id() => Ids::WARPED_BUTTON,
WoodType::CHERRY()->id() => Ids::CHERRY_BUTTON,
default => throw new AssumptionFailedError("All wood types should be covered")
});
}
@ -255,6 +268,7 @@ final class WoodLikeBlockIdHelper{
WoodType::MANGROVE()->id() => Ids::MANGROVE_PRESSURE_PLATE,
WoodType::CRIMSON()->id() => Ids::CRIMSON_PRESSURE_PLATE,
WoodType::WARPED()->id() => Ids::WARPED_PRESSURE_PLATE,
WoodType::CHERRY()->id() => Ids::CHERRY_PRESSURE_PLATE,
default => throw new AssumptionFailedError("All wood types should be covered")
});
}
@ -270,6 +284,7 @@ final class WoodLikeBlockIdHelper{
WoodType::MANGROVE()->id() => Ids::MANGROVE_DOOR,
WoodType::CRIMSON()->id() => Ids::CRIMSON_DOOR,
WoodType::WARPED()->id() => Ids::WARPED_DOOR,
WoodType::CHERRY()->id() => Ids::CHERRY_DOOR,
default => throw new AssumptionFailedError("All wood types should be covered")
});
}
@ -285,6 +300,7 @@ final class WoodLikeBlockIdHelper{
WoodType::MANGROVE()->id() => Ids::MANGROVE_FENCE_GATE,
WoodType::CRIMSON()->id() => Ids::CRIMSON_FENCE_GATE,
WoodType::WARPED()->id() => Ids::WARPED_FENCE_GATE,
WoodType::CHERRY()->id() => Ids::CHERRY_FENCE_GATE,
default => throw new AssumptionFailedError("All wood types should be covered")
});
}
@ -300,6 +316,7 @@ final class WoodLikeBlockIdHelper{
WoodType::MANGROVE()->id() => Ids::MANGROVE_STAIRS,
WoodType::CRIMSON()->id() => Ids::CRIMSON_STAIRS,
WoodType::WARPED()->id() => Ids::WARPED_STAIRS,
WoodType::CHERRY()->id() => Ids::CHERRY_STAIRS,
default => throw new AssumptionFailedError("All wood types should be covered")
});
}

View File

@ -0,0 +1,65 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\utils\EnumTrait;
/**
* This doc-block is generated automatically, do not modify it manually.
* This must be regenerated whenever registry members are added, removed or changed.
* @see build/generate-registry-annotations.php
* @generate-registry-docblock
*
* @method static DripleafState FULL_TILT()
* @method static DripleafState PARTIAL_TILT()
* @method static DripleafState STABLE()
* @method static DripleafState UNSTABLE()
*/
final class DripleafState{
use EnumTrait {
register as Enum_register;
__construct as Enum___construct;
}
protected static function setup() : void{
self::registerAll(
new self("stable", null),
new self("unstable", 10),
new self("partial_tilt", 10),
new self("full_tilt", 100)
);
}
private function __construct(
string $enumName,
private ?int $scheduledUpdateDelayTicks
){
$this->Enum___construct($enumName);
}
public function getScheduledUpdateDelayTicks() : ?int{
return $this->scheduledUpdateDelayTicks;
}
}

View File

@ -0,0 +1,129 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\Item;
use function max;
use function min;
use function mt_getrandmax;
use function mt_rand;
final class FortuneDropHelper{
/**
* If a random number between 0-1 is greater than 2/(level+2), this multiplies the max drop amount by level+1, and
* picks a random amount between the minimum and multiplied maximum. Each level of fortune increases the chance of
* fortune activation, and also increases the maximum drop limit when activated.
*
* Otherwise, returns a random amount of the item between the minimum and original maximum.
*
* @param Item $usedItem The item used to break the block
* @param int $min Minimum amount
* @param int $maxBase Maximum amount, as if fortune level was 0
*
* @return int the number of items to drop
*/
public static function weighted(Item $usedItem, int $min, int $maxBase) : int{
if($maxBase < $min){
throw new \InvalidArgumentException("Maximum drop amount must be greater than or equal to minimum drop amount");
}
$fortuneLevel = $usedItem->getEnchantmentLevel(VanillaEnchantments::FORTUNE());
return mt_rand($min,
$fortuneLevel > 0 && mt_rand() / mt_getrandmax() > 2 / ($fortuneLevel + 2) ?
$maxBase * ($fortuneLevel + 1) :
$maxBase
);
}
/**
* Increases the drop amount according to a binomial distribution. The function will roll maxBase+level times, and add 1
* if a random number between 0-1 is less than the given probability. Each level of fortune adds one extra roll.
*
* As many as maxBase+level items can be dropped. This applies even if the fortune level is 0.
*
* @param float $chance The chance of adding 1 to the amount for each roll, must be in the range 0-1
* @param int $min Minimum amount
* @param int $minRolls Number of rolls if fortune level is 0, added to fortune level to calculate total rolls
*
* @return int the number of items to drop
*/
public static function binomial(Item $usedItem, int $min, int $minRolls = 3, float $chance = 4 / 7) : int{
$fortuneLevel = $usedItem->getEnchantmentLevel(VanillaEnchantments::FORTUNE());
$count = $min;
$rolls = $minRolls + $fortuneLevel;
for($i = 0; $i < $rolls; ++$i){
if(mt_rand() / mt_getrandmax() < $chance){
++$count;
}
}
return $count;
}
/**
* Adds the fortune level to the base max and picks a random number between the minimim and adjusted maximum.
* Each amount in the range has an equal chance of being picked.
*
* @param int $maxBase Maximum base amount, as if the fortune level was 0
*
* @return int the number of items to drop
*/
public static function discrete(Item $usedItem, int $min, int $maxBase) : int{
if($maxBase < $min){
throw new \InvalidArgumentException("Minimum base drop amount must be less than or equal to maximum base drop amount");
}
$max = $maxBase + $usedItem->getEnchantmentLevel(VanillaEnchantments::FORTUNE());
return mt_rand($min, $max);
}
/**
* Calculates a chance of getting an extra bonus drop by reducing the chance divisor by a given amount per fortune
* level.
*
* @param int $divisorBase The number to divide 1 by to get the chance, as if the fortune level was 0
* @param int $divisorSubtractPerLevel The amount to subtract from the divisor for each level of fortune
*
* @return bool whether the bonus drop should be added
*/
public static function bonusChanceDivisor(Item $usedItem, int $divisorBase, int $divisorSubtractPerLevel) : bool{
$fortuneLevel = $usedItem->getEnchantmentLevel(VanillaEnchantments::FORTUNE());
return mt_rand(1, max(1, $divisorBase - ($fortuneLevel * $divisorSubtractPerLevel))) === 1;
}
/**
* Calculates a chance of getting an extra bonus drop by increasing the chance by a fixed amount per fortune level.
*
* @param float $chanceBase The base chance of getting a bonus drop, as if the fortune level was 0
* @param float $addedChancePerLevel The amount to add to the chance for each level of fortune
*/
public static function bonusChanceFixed(Item $usedItem, float $chanceBase, float $addedChancePerLevel) : bool{
$fortuneLevel = $usedItem->getEnchantmentLevel(VanillaEnchantments::FORTUNE());
$chance = min(1, $chanceBase + ($fortuneLevel * $addedChancePerLevel));
return mt_rand() / mt_getrandmax() < $chance;
}
}

View File

@ -34,6 +34,7 @@ use pocketmine\utils\EnumTrait;
* @method static LeavesType ACACIA()
* @method static LeavesType AZALEA()
* @method static LeavesType BIRCH()
* @method static LeavesType CHERRY()
* @method static LeavesType DARK_OAK()
* @method static LeavesType FLOWERING_AZALEA()
* @method static LeavesType JUNGLE()
@ -57,7 +58,8 @@ final class LeavesType{
new self("dark_oak", "Dark Oak"),
new self("mangrove", "Mangrove"),
new self("azalea", "Azalea"),
new self("flowering_azalea", "Flowering Azalea")
new self("flowering_azalea", "Flowering Azalea"),
new self("cherry", "Cherry")
);
}

View File

@ -33,6 +33,7 @@ use pocketmine\utils\EnumTrait;
*
* @method static MobHeadType CREEPER()
* @method static MobHeadType DRAGON()
* @method static MobHeadType PIGLIN()
* @method static MobHeadType PLAYER()
* @method static MobHeadType SKELETON()
* @method static MobHeadType WITHER_SKELETON()
@ -50,7 +51,8 @@ final class MobHeadType{
new MobHeadType("zombie", "Zombie Head"),
new MobHeadType("player", "Player Head"),
new MobHeadType("creeper", "Creeper Head"),
new MobHeadType("dragon", "Dragon Head")
new MobHeadType("dragon", "Dragon Head"),
new MobHeadType("piglin", "Piglin Head")
);
}

View File

@ -0,0 +1,54 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
/**
* @internal
*/
trait TallGrassTrait{
public function canBeReplaced() : bool{
return true;
}
public function getDropsForIncompatibleTool(Item $item) : array{
if(FortuneDropHelper::bonusChanceDivisor($item, 8, 2)){
return [
VanillaItems::WHEAT_SEEDS()
];
}
return [];
}
public function getFlameEncouragement() : int{
return 60;
}
public function getFlammability() : int{
return 100;
}
}

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