Compare commits

..

46 Commits

Author SHA1 Message Date
1c60aa9769 Release 4.1.0 2022-02-07 19:22:53 +00:00
e9dd9df0a0 Merge remote-tracking branch 'origin/stable' into staging/4.1 2022-02-07 17:22:18 +00:00
032b15efe0 fix BlockFactory consistency check 2022-02-07 15:49:32 +00:00
256826d9c7 Fixed uninitialized color fields of stained glass, stained clay and stained hardened glass 2022-02-07 15:39:54 +00:00
c273b29dec BambooSapling: fixed wrong bit being used for readiness
closes #4809
2022-02-07 15:38:05 +00:00
7ddd547190 Merge remote-tracking branch 'origin/stable' into staging/4.1 2022-02-06 23:55:52 +00:00
38e34093cf ResourcePackManifest: Stop throwing exceptions on extra properties (#4804)
This code currently throws errors when properties other than the base required ones are added. This can be from resource packs created by "bridge.", where the IDE adds a "generated_with" property to the manifest. This leads to resource packs created by bridge., which are otherwise completely valid, not being loaded.
2022-02-06 23:22:22 +00:00
dd1ebb5915 4.0.10 is next 2022-02-05 16:08:23 +00:00
df1cdbe921 Release 4.0.9 2022-02-05 16:08:10 +00:00
7846ea8acc LevelDB: do not barf on chunk version 8
this covers a wide range from 1.2.13 to 1.8.
2022-02-05 04:18:37 +00:00
1dc0d5f96a WorldManager: do not calculate safe spawn if there are no players in the unloaded world 2022-02-04 19:24:51 +00:00
712ffb3e31 WorldManager: fixed loading the default world's spawn chunk when unloading the default world
yo dawg
I heard you like loading and unloading
so I put some loading inside your unloading
so you can load while you unload
2022-02-04 19:22:37 +00:00
2a4111868c Fixed incorrect doc for EncryptionContext (#4791)
* Fixed incorrect doc for EncryptionContext

* Update src/network/mcpe/encryption/EncryptionContext.php

Co-authored-by: Dylan T <odigiman@gmail.com>
2022-02-02 13:12:33 +00:00
123701ed76 Bump tests/plugins/DevTools from 39510af to e884a4c (#4788)
Bumps [tests/plugins/DevTools](https://github.com/pmmp/DevTools) from `39510af` to `e884a4c`.
- [Release notes](https://github.com/pmmp/DevTools/releases)
- [Commits](39510af5bc...e884a4c234)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-02 00:05:33 +00:00
28dce8783f Bump build/php from bd329db to 30eed13 (#4787)
Bumps [build/php](https://github.com/pmmp/php-build-scripts) from `bd329db` to `30eed13`.
- [Release notes](https://github.com/pmmp/php-build-scripts/releases)
- [Commits](bd329dba08...30eed13faa)

---
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>
2022-02-02 00:05:17 +00:00
3781b62d35 Update dependabot.yml 2022-02-01 23:58:49 +00:00
859f062267 StringToItemParser: fixed *_concrete_powder giving concrete instead of concrete powder 2022-02-01 23:29:47 +00:00
cfdbfa3d58 Liquid: fixed implicit assumption of 0 == air 2022-01-28 21:07:41 +00:00
e9a6c0ba58 Liquid: added missing bounds check for setDecay() 2022-01-28 21:03:44 +00:00
d16b6fe61e Merge branch 'stable' into staging/4.1 2022-01-28 20:40:07 +00:00
7a75fcda44 Merge branch 'bell-4745' into stable 2022-01-28 20:21:28 +00:00
8d289ab01d Bell: fixed collision boxes
closes #4745
2022-01-28 20:20:41 +00:00
40c7497efe Updated BedrockProtocol to 7.3.1 2022-01-28 15:06:56 +00:00
6ccb1ff114 4.1.0-BETA3 is next 2022-01-27 00:55:09 +00:00
1d2593208a Release 4.1.0-BETA2 2022-01-27 00:55:02 +00:00
a7bdef69e2 Merge remote-tracking branch 'origin/stable' into next-minor 2022-01-27 00:40:34 +00:00
d9ea647925 InGamePacketHandler: add a hack for swimming AABB client bug 2022-01-27 00:28:54 +00:00
6673289c33 Fixed spectator players being able to drop items (#4775)
closes #4765
2022-01-27 00:03:19 +00:00
822af4f7f5 Bump pocketmine/locale-data from 2.4.2 to 2.4.3 (#4773)
Bumps [pocketmine/locale-data](https://github.com/pmmp/Language) from 2.4.2 to 2.4.3.
- [Release notes](https://github.com/pmmp/Language/releases)
- [Commits](https://github.com/pmmp/Language/compare/2.4.2...2.4.3)

---
updated-dependencies:
- dependency-name: pocketmine/locale-data
  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>
2022-01-26 00:45:05 +00:00
3155c90396 Fixed incorrect drops for Cobweb (#4759) 2022-01-26 00:25:00 +00:00
1dbfedce4c Bump pocketmine/locale-data from 2.3.33 to 2.4.2 (#4769)
Bumps [pocketmine/locale-data](https://github.com/pmmp/Language) from 2.3.33 to 2.4.2.
- [Release notes](https://github.com/pmmp/Language/releases)
- [Commits](https://github.com/pmmp/Language/compare/2.3.33...2.4.2)

---
updated-dependencies:
- dependency-name: pocketmine/locale-data
  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>
2022-01-26 00:19:02 +00:00
3ab5b5a79d 4.0.9 is next 2022-01-25 23:33:24 +00:00
8a4bc72b34 Release 4.0.8 2022-01-25 23:33:20 +00:00
6cbc14f2b2 World: fixed block update bug introduced by 3faeb5a556 2022-01-25 21:53:15 +00:00
75d0fc4749 BlockFactory: Make stone slab registration a little less unpleasant to read 2022-01-25 19:23:04 +00:00
ea161af4e5 Added FurnaceType->getCookSound() 2022-01-25 19:01:49 +00:00
0bf5f97fe9 Implement furnace sound (#4755)
closes #4363 

The following classes have been added:
- BlastFurnaceSound
- SmokerSound
- FurnaceSound
2022-01-25 18:52:31 +00:00
b9f1bcf0e4 Implement PlayerViewDistanceChangeEvent (#4749)
closes #4550
2022-01-25 18:00:26 +00:00
32b07e0940 World: avoid repeated getInstance() calls in hot paths 2022-01-24 21:08:12 +00:00
99f087e5e1 Bump phpunit/phpunit from 9.5.12 to 9.5.13 (#4767)
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.5.12 to 9.5.13.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/master/ChangeLog-9.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.5.12...9.5.13)

---
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>
2022-01-24 14:21:49 +00:00
22a4117109 Merge remote-tracking branch 'origin/stable' into next-minor 2022-01-23 15:47:13 +00:00
aaf7a88de7 HayBale: fixed fall damage 2022-01-22 21:26:44 +00:00
e0da99a973 feat: Implement Brewing (#4413)
The following API constants have been added:
- tile\BrewingStand::BREW_TIME_TICKS
The following public API methods have been added:
- utils\BrewingStandSlot->getSlotNumber() : int
- CraftingManager->getPotionTypeRecipes() : array<string, array<string, PotionTypeRecipe>>
- CraftingManager->getPotionContainerChangeRecipes() : array<int, array<string, PotionContainerChangeRecipe>>
- CraftingManager->registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void
- CraftingManager->registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void
The following classes have been added:
- BrewingRecipe
- PotionTypeRecipe
- PotionContainerChangeRecipe
- BrewItemEvent
- BrewingFuelUseEvent
- PotionFinishBrewingSound
2022-01-22 16:54:58 +00:00
b2630a0920 Merge remote-tracking branch 'origin/stable' into next-minor 2022-01-22 14:46:55 +00:00
67a0ae0246 Fixed incorrect drops for ender chest (#4751) 2022-01-22 14:01:56 +00:00
5ae20459dd 4.1.0-BETA2 is next 2022-01-22 02:23:09 +00:00
50 changed files with 1183 additions and 102 deletions

View File

@ -6,3 +6,8 @@ updates:
interval: daily
time: "10:00"
open-pull-requests-limit: 10
- package-ecosystem: gitsubmodule
directory: "/"
schedule:
interval: daily

View File

@ -1620,3 +1620,28 @@ Released 21st January 2022.
- Fixed ender pearls teleporting players when thrown by a player directly against a wall when cancelling `ProjectileLaunchEvent`.
- Fixed collision box of brewing stand.
- Fixed break times and tool types of bamboo, nether wart blocks, infested stone and leaves.
# 4.0.8
Released 25th January 2022.
## Fixes
- Fixed ender chest not dropping itself when mined with a Silk Touch pickaxe.
- The correct amount of fall damage is now taken when falling from a height onto hay bales.
# 4.0.9
Released 5th February 2022.
## Fixes
### Core
- The spawn chunk of the default world is no longer loaded during shutdown. Previously, it would attempt to find a safe spawn to teleport players to, only to unload the target world of that safe spawn and not use it.
- The spawn chunk of the default world is no longer loaded when unloading a non-default world containing zero players.
- Fixed chunk version `8` in Bedrock worlds being treated as corrupted. These appeared in worlds between 1.2.13 and 1.8.0.
### API
- Added missing bounds check to `Liquid->setDecay()`.
- Fixed `StringToItemParser` returning concrete instead of concrete powder when given `<color>_concrete_powder`.
### Gameplay
- Cobwebs now drop themselves when broken using shears.
- Fixed spectator players being able to drop items.
- Fixed collision shapes of Bell in different orientations.

166
changelogs/4.1-beta.md Normal file
View File

@ -0,0 +1,166 @@
**For Minecraft: Bedrock Edition 1.18.0**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 4.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.1.0-BETA1
Released 22nd January 2022.
## General
- Game mode names (e.g. `survival`, `creative`) may now be used for the `gamemode` property in `server.properties`.
- Increased default maximum render distance to 16 chunks. Players with a render distance smaller than this will notice no difference.
- The setup wizard now prompts for a maximum render distance value.
- The setup wizard now prompts for an IPv6 port selection. Previously it would always use 19133.
- `chunk-ticking.disable-block-ticking` now accepts block names like those used in the `/give` command.
- The `/clear` command now behaves more like vanilla:
- The order of inventories is now the same as Bedrock.
- The cursor and offhand inventories are now cleared if necessary.
## Technical
- `PlayerAuthInputPacket` is now used instead of `MovePlayerPacket` for processing movements. This improves position and rotation accuracy.
- `&&` and `||` are now always used instead of `and` and `or`.
- New version of `pocketmine/errorhandler` is used by this version, adding support for `ErrorToExceptionHandler::trap()`. This enables reliably capturing `E_WARNING` and `E_NOTICE` from functions such as `yaml_parse()` and friends.
- New dependency versions are required by this version:
- `pocketmine/bedrock-protocol` has been updated from 7.1.0 to [7.3.0](https://github.com/pmmp/BedrockProtocol/releases/tag/7.3.0%2Bbedrock-1.18.0).
- `pocketmine/errorhandler` has been updated from 0.3.0 to [0.6.0](https://github.com/pmmp/ErrorHandler/releases/tag/0.6.0).
## API
### Block
- The following classes have been added:
- `Lectern`
- `Pumpkin`
- The following public API methods have been added:
- `Block->getTypeId() : int` - returns an integer which uniquely identifies the block type, ignoring things like facing, colour etc.
- `VanillaBlocks::LECTERN()`
### Entity
- The following classes have been added:
- `animation\ItemEntityStackSizeChangeAnimation`
- The following public API methods have been added:
- `object\ItemEntity->isMergeable(object\ItemEntity $other) : bool`
- `object\ItemEntity->setStackSize(int $size) : void`
- `object\ItemEntity->tryMergeInto(object\ItemEntity $other) : bool`
- `ExperienceManager->canAttractXpOrbs() : bool`
- `ExperienceManager->setCanAttractXpOrbs(bool $v = true) : void`
- `Entity->getSize() : EntitySizeInfo`
- `Living->isGliding() : bool`
- `Living->isSwimming() : bool`
- `Living->setGliding(bool $value = true) : void`
- `Living->setSwimming(bool $value = true) : void`
- The following protected API methods have been added:
- `Entity->getBlocksIntersected(float $inset) : \Generator<int, Block, void, void>`
### Event
- `BlockSpreadEvent` is now called when fire spreads to the positions of blocks it burns away.
- `BlockFormEvent` is now called when concrete powder turns into concrete due to contact with water.
- The following classes have been added:
- `BlockMeltEvent` - called when ice or snow melts
- `ChestPairEvent` - called when two chests try to form a pair
- `PlayerToggleGlideEvent` - called when a player starts or stops gliding
- `PlayerToggleSwimEvent` - called when a player starts or stops swimming
### Item
- The following public API methods have been added:
- `SplashPotion->getType() : PotionType`
- `VanillaItems::AIR()`
- The following API methods have been deprecated:
- `ItemFactory::air()` - use `VanillaItems::AIR()` instead
### Player
- The following public API methods have been added:
- `Player->hasBlockCollision() : bool`
- `Player->setHasBlockCollision(bool $value)` - allows controlling spectator-like no-clip behaviour without changing game mode
- `Player->toggleSwim(bool $swim) : bool` - called by the network system when the client tries to start/stop swimming
- `Player->toggleGlide(bool $glide) : bool` - called by the network system when the client tries to start/stop gliding
### Server
- The following public API constants have been added:
- `Server::DEFAULT_SERVER_NAME`
- `Server::DEFAULT_MAX_PLAYERS`
- `Server::DEFAULT_PORT_IPV4`
- `Server::DEFAULT_PORT_IPV6`
- `Server::DEFAULT_MAX_VIEW_DISTANCE`
### Utils
- Config parsing errors are now always represented by `ConfigLoadException` and include the path to the file in the message.
- Added `TextFormat::MINECOIN_GOLD`, and support for it to the various `TextFormat` methods.
- The following public API methods have been added:
- `Utils::assumeNotFalse()` - static analysis crutch to silence PHPStan errors without using `ignoreErrors` or `@phpstan-ignore-line`, which are both too coarse.
- The following public API properties have been added:
- `Terminal::$COLOR_MINECOIN_GOLD`
- The following classes have been added:
- `ConfigLoadException`
- Fixed `Random->nextSignedInt()` to actually return a signed int. Previously it would return any integer value between 0 and 4,294,957,295.
- Fixed `Random->nextSignedFloat()` to return a float between `-1.0` and `1.0`. Previously it would return any value between `0.0` and `2.0`.
- `VersionString->getNumber()` output is now structured differently to fix overflow issues caused by the old format.
### World
- The following classes have been added:
- `sound\ItemUseOnBlockSound`
- `sound\LecternPlaceBookSound`
## Gameplay
### Blocks
- Fire now spreads.
- Implemented lectern blocks.
- Added missing sounds for hoeing grass and dirt.
- Added missing sounds for using a shovel on grass to create grass path.
- Pumpkins can now be carved using shears.
### Items
- Dropped items of the same type now merge with each other.
### Misc
- Implemented player swimming.
# 4.1.0-BETA2
Released 27th January 2022.
## API
### Block
- The following API methods have been added:
- `utils\BrewingStandSlot->getSlotNumber() : int`
- `utils\FurnaceType->getCookSound() : Sound`
- The following API constants have been added:
- `tile\BrewingStand::BREW_TIME_TICKS`
### Crafting
- The following API methods have been added:
- `CraftingManager->getPotionContainerChangeRecipes() : array<int, array<string, PotionContainerChangeRecipe>>`
- `CraftingManager->getPotionTypeRecipes() : array<string, array<string, PotionTypeRecipe>>`
- `CraftingManager->registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void`
- `CraftingManager->registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void`
- The following classes have been added:
- `BrewingRecipe`
- `PotionContainerChangeRecipe`
- `PotionTypeRecipe`
### Event
- The following classes have been added:
- `BrewItemEvent` - called when a brewing stand finishes brewing potions; this is called up to 3 times (once for each brewing slot, as needed)
- `BrewingFuelUseEvent` - called when a brewing stand consumes blaze powder
- `PlayerViewDistanceChangeEvent` - called whenever a player alters their render distance or requests one for the first time when connecting
### World
#### Sound
- The following classes have been added:
- `BlastFurnaceSound` - the sound made by a blast furnace during smelting
- `FurnaceSound` - the sound made by a regular furnace during cooking or smelting
- `PotionFinishBrewingSound` - the sound made by a brewing stand when a potion finishes being brewed
- `SmokerSound` - the sound made by a smoker during cooking
## Gameplay
### Blocks
- Brewing stands can now be used for brewing potions.
- The visual appearance of a brewing stand now updates correctly when the contents of its inventory changes (adding/removing potions).
- Added missing sounds for furnace, blast furnace and smoker.
- Fixed ender chest not dropping itself when mined with a Silk Touch pickaxe.
- Cobwebs now drop themselves when mined using shears.
- The correct amount of fall damage is now taken when falling from a height onto hay bales.
- Fixed block updating bug introduced by beta1 which caused crops and other plants to never grow.
### Misc
- Added a workaround for client hitbox size bug after swimming which caused the player to be able to fit into one-block-tall gaps.

View File

@ -6,8 +6,8 @@ Plugin developers should **only** update their required API to this version if y
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 4.1.0-BETA1
Released 22nd January 2022.
# 4.1.0
Released 7th February 2022.
## General
- Game mode names (e.g. `survival`, `creative`) may now be used for the `gamemode` property in `server.properties`.
@ -35,6 +35,21 @@ Released 22nd January 2022.
- The following public API methods have been added:
- `Block->getTypeId() : int` - returns an integer which uniquely identifies the block type, ignoring things like facing, colour etc.
- `VanillaBlocks::LECTERN()`
- `utils\BrewingStandSlot->getSlotNumber() : int`
- `utils\FurnaceType->getCookSound() : Sound`
- The following API constants have been added:
- `tile\BrewingStand::BREW_TIME_TICKS`
### Crafting
- The following API methods have been added:
- `CraftingManager->getPotionContainerChangeRecipes() : array<int, array<string, PotionContainerChangeRecipe>>`
- `CraftingManager->getPotionTypeRecipes() : array<string, array<string, PotionTypeRecipe>>`
- `CraftingManager->registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void`
- `CraftingManager->registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void`
- The following classes have been added:
- `BrewingRecipe`
- `PotionContainerChangeRecipe`
- `PotionTypeRecipe`
### Entity
- The following classes have been added:
@ -58,9 +73,12 @@ Released 22nd January 2022.
- `BlockFormEvent` is now called when concrete powder turns into concrete due to contact with water.
- The following classes have been added:
- `BlockMeltEvent` - called when ice or snow melts
- `BrewItemEvent` - called when a brewing stand finishes brewing potions; this is called up to 3 times (once for each brewing slot, as needed)
- `BrewingFuelUseEvent` - called when a brewing stand consumes blaze powder
- `ChestPairEvent` - called when two chests try to form a pair
- `PlayerToggleGlideEvent` - called when a player starts or stops gliding
- `PlayerToggleSwimEvent` - called when a player starts or stops swimming
- `PlayerViewDistanceChangeEvent` - called whenever a player alters their render distance or requests one for the first time when connecting
### Item
- The following public API methods have been added:
@ -99,8 +117,12 @@ Released 22nd January 2022.
### World
- The following classes have been added:
- `sound\BlastFurnaceSound` - the sound made by a blast furnace during smelting
- `sound\FurnaceSound` - the sound made by a regular furnace during cooking or smelting
- `sound\ItemUseOnBlockSound`
- `sound\LecternPlaceBookSound`
- `sound\PotionFinishBrewingSound` - the sound made by a brewing stand when a potion finishes being brewed
- `sound\SmokerSound` - the sound made by a smoker during cooking
## Gameplay
### Blocks
@ -109,9 +131,12 @@ Released 22nd January 2022.
- Added missing sounds for hoeing grass and dirt.
- Added missing sounds for using a shovel on grass to create grass path.
- Pumpkins can now be carved using shears.
- Brewing stands can now be used for brewing potions.
- The visual appearance of a brewing stand now updates correctly when the contents of its inventory changes (adding/removing potions).
- Added missing sounds for furnace, blast furnace and smoker.
- Fixed ender chest not dropping itself when mined with a Silk Touch pickaxe.
- Cobwebs now drop themselves when mined using shears.
- The correct amount of fall damage is now taken when falling from a height onto hay bales.
### Items
- Dropped items of the same type now merge with each other.
### Misc
- Implemented player swimming.

View File

@ -41,7 +41,7 @@
"pocketmine/classloader": "^0.2.0",
"pocketmine/color": "^0.2.0",
"pocketmine/errorhandler": "^0.6.0",
"pocketmine/locale-data": "~2.3.0",
"pocketmine/locale-data": "~2.4.2",
"pocketmine/log": "^0.4.0",
"pocketmine/log-pthreads": "^0.4.0",
"pocketmine/math": "^0.4.0",

40
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": "292d4bf59374d46e1ae84272f0abd522",
"content-hash": "9aa2f11ba68d00423732973554fafb20",
"packages": [
{
"name": "adhocore/json-comment",
@ -275,16 +275,16 @@
},
{
"name": "pocketmine/bedrock-protocol",
"version": "7.3.0+bedrock-1.18.0",
"version": "7.3.1+bedrock-1.18.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "418b4dbaa6720b6c6c4385a4d321d9c0b3dbf14b"
"reference": "c2667453b03ca08a8c54cd89a1fd45cb29196aeb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/418b4dbaa6720b6c6c4385a4d321d9c0b3dbf14b",
"reference": "418b4dbaa6720b6c6c4385a4d321d9c0b3dbf14b",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/c2667453b03ca08a8c54cd89a1fd45cb29196aeb",
"reference": "c2667453b03ca08a8c54cd89a1fd45cb29196aeb",
"shasum": ""
},
"require": {
@ -298,7 +298,7 @@
"ramsey/uuid": "^4.1"
},
"require-dev": {
"phpstan/phpstan": "1.3.1",
"phpstan/phpstan": "1.4.2",
"phpstan/phpstan-phpunit": "^1.0.0",
"phpstan/phpstan-strict-rules": "^1.0.0",
"phpunit/phpunit": "^9.5"
@ -316,9 +316,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/7.3.0+bedrock-1.18.0"
"source": "https://github.com/pmmp/BedrockProtocol/tree/7.3.1+bedrock-1.18.0"
},
"time": "2022-01-06T20:44:27+00:00"
"time": "2022-01-26T21:14:23+00:00"
},
{
"name": "pocketmine/binaryutils",
@ -536,16 +536,16 @@
},
{
"name": "pocketmine/locale-data",
"version": "2.3.33",
"version": "2.4.3",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Language.git",
"reference": "44998ca9c055f872a33e59cd4d2736d081ba84b5"
"reference": "4d0b081f1a79407e087968ea76aaf330db6ea2b5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/Language/zipball/44998ca9c055f872a33e59cd4d2736d081ba84b5",
"reference": "44998ca9c055f872a33e59cd4d2736d081ba84b5",
"url": "https://api.github.com/repos/pmmp/Language/zipball/4d0b081f1a79407e087968ea76aaf330db6ea2b5",
"reference": "4d0b081f1a79407e087968ea76aaf330db6ea2b5",
"shasum": ""
},
"type": "library",
@ -553,9 +553,9 @@
"description": "Language resources used by PocketMine-MP",
"support": {
"issues": "https://github.com/pmmp/Language/issues",
"source": "https://github.com/pmmp/Language/tree/2.3.33"
"source": "https://github.com/pmmp/Language/tree/2.4.3"
},
"time": "2022-01-16T22:08:04+00:00"
"time": "2022-01-25T23:18:24+00:00"
},
{
"name": "pocketmine/log",
@ -2389,16 +2389,16 @@
},
{
"name": "phpunit/phpunit",
"version": "9.5.12",
"version": "9.5.13",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "93d4bf4c37aec6384bb9e5d390d9049a463a7256"
"reference": "597cb647654ede35e43b137926dfdfef0fb11743"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/93d4bf4c37aec6384bb9e5d390d9049a463a7256",
"reference": "93d4bf4c37aec6384bb9e5d390d9049a463a7256",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/597cb647654ede35e43b137926dfdfef0fb11743",
"reference": "597cb647654ede35e43b137926dfdfef0fb11743",
"shasum": ""
},
"require": {
@ -2476,7 +2476,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.12"
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.13"
},
"funding": [
{
@ -2488,7 +2488,7 @@
"type": "github"
}
],
"time": "2022-01-21T05:54:47+00:00"
"time": "2022-01-24T07:33:35+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@ -31,9 +31,9 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
public const BASE_VERSION = "4.1.0-BETA1";
public const BASE_VERSION = "4.1.0";
public const IS_DEVELOPMENT_BUILD = false;
public const BUILD_CHANNEL = "beta";
public const BUILD_CHANNEL = "stable";
private function __construct(){
//NOOP

View File

@ -36,14 +36,14 @@ final class BambooSapling extends Flowable{
private bool $ready = false;
public function readStateFromData(int $id, int $stateMeta) : void{
$this->ready = ($stateMeta & BlockLegacyMetadata::SAPLING_FLAG_READY) !== 0;
$this->ready = ($stateMeta & BlockLegacyMetadata::BAMBOO_SAPLING_FLAG_READY) !== 0;
}
protected function writeStateToMeta() : int{
return $this->ready ? BlockLegacyMetadata::SAPLING_FLAG_READY : 0;
return $this->ready ? BlockLegacyMetadata::BAMBOO_SAPLING_FLAG_READY : 0;
}
public function getStateBitmask() : int{ return 0b1000; }
public function getStateBitmask() : int{ return 0b1; }
public function isReady() : bool{ return $this->ready; }

View File

@ -29,6 +29,7 @@ use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\InvalidBlockStateException;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
@ -78,6 +79,28 @@ final class Bell extends Transparent{
return 0b1111;
}
protected function recalculateCollisionBoxes() : array{
if($this->attachmentType->equals(BellAttachmentType::FLOOR())){
return [
AxisAlignedBB::one()->squash(Facing::axis($this->facing), 1 / 4)->trim(Facing::UP, 3 / 16)
];
}
if($this->attachmentType->equals(BellAttachmentType::CEILING())){
return [
AxisAlignedBB::one()->contract(1 / 4, 0, 1 / 4)->trim(Facing::DOWN, 1 / 4)
];
}
$box = AxisAlignedBB::one()
->squash(Facing::axis(Facing::rotateY($this->facing, true)), 1 / 4)
->trim(Facing::UP, 1 / 16)
->trim(Facing::DOWN, 1 / 4);
return [
$this->attachmentType->equals(BellAttachmentType::ONE_WALL()) ? $box->trim($this->facing, 3 / 16) : $box
];
}
public function getAttachmentType() : BellAttachmentType{ return $this->attachmentType; }
/** @return $this */

View File

@ -398,35 +398,42 @@ class BlockFactory{
//TODO: in the future this won't be the same for all the types
$stoneSlabBreakInfo = new BlockBreakInfo(2.0, BlockToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel(), 30.0);
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(1, Meta::STONE_SLAB_BRICK), "Brick", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(1, Meta::STONE_SLAB_COBBLESTONE), "Cobblestone", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(1, Meta::STONE_SLAB_FAKE_WOODEN), "Fake Wooden", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(1, Meta::STONE_SLAB_NETHER_BRICK), "Nether Brick", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(1, Meta::STONE_SLAB_QUARTZ), "Quartz", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(1, Meta::STONE_SLAB_SANDSTONE), "Sandstone", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(1, Meta::STONE_SLAB_SMOOTH_STONE), "Smooth Stone", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(1, Meta::STONE_SLAB_STONE_BRICK), "Stone Brick", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(2, Meta::STONE_SLAB2_DARK_PRISMARINE), "Dark Prismarine", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(2, Meta::STONE_SLAB2_MOSSY_COBBLESTONE), "Mossy Cobblestone", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(2, Meta::STONE_SLAB2_PRISMARINE), "Prismarine", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(2, Meta::STONE_SLAB2_PRISMARINE_BRICKS), "Prismarine Bricks", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(2, Meta::STONE_SLAB2_PURPUR), "Purpur", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(2, Meta::STONE_SLAB2_RED_NETHER_BRICK), "Red Nether Brick", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(2, Meta::STONE_SLAB2_RED_SANDSTONE), "Red Sandstone", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(2, Meta::STONE_SLAB2_SMOOTH_SANDSTONE), "Smooth Sandstone", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(3, Meta::STONE_SLAB3_ANDESITE), "Andesite", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(3, Meta::STONE_SLAB3_DIORITE), "Diorite", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(3, Meta::STONE_SLAB3_END_STONE_BRICK), "End Stone Brick", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(3, Meta::STONE_SLAB3_GRANITE), "Granite", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(3, Meta::STONE_SLAB3_POLISHED_ANDESITE), "Polished Andesite", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(3, Meta::STONE_SLAB3_POLISHED_DIORITE), "Polished Diorite", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(3, Meta::STONE_SLAB3_POLISHED_GRANITE), "Polished Granite", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(3, Meta::STONE_SLAB3_SMOOTH_RED_SANDSTONE), "Smooth Red Sandstone", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(4, Meta::STONE_SLAB4_CUT_RED_SANDSTONE), "Cut Red Sandstone", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(4, Meta::STONE_SLAB4_CUT_SANDSTONE), "Cut Sandstone", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(4, Meta::STONE_SLAB4_MOSSY_STONE_BRICK), "Mossy Stone Brick", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(4, Meta::STONE_SLAB4_SMOOTH_QUARTZ), "Smooth Quartz", $stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(new Slab(BlockLegacyIdHelper::getStoneSlabIdentifier(4, Meta::STONE_SLAB4_STONE), "Stone", $stoneSlabBreakInfo));
$getStoneSlabId = static fn(int $stoneSlabId, int $meta) => BlockLegacyIdHelper::getStoneSlabIdentifier($stoneSlabId, $meta);
foreach([
new Slab($getStoneSlabId(1, Meta::STONE_SLAB_BRICK), "Brick", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(1, Meta::STONE_SLAB_COBBLESTONE), "Cobblestone", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(1, Meta::STONE_SLAB_FAKE_WOODEN), "Fake Wooden", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(1, Meta::STONE_SLAB_NETHER_BRICK), "Nether Brick", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(1, Meta::STONE_SLAB_QUARTZ), "Quartz", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(1, Meta::STONE_SLAB_SANDSTONE), "Sandstone", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(1, Meta::STONE_SLAB_SMOOTH_STONE), "Smooth Stone", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(1, Meta::STONE_SLAB_STONE_BRICK), "Stone Brick", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(2, Meta::STONE_SLAB2_DARK_PRISMARINE), "Dark Prismarine", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(2, Meta::STONE_SLAB2_MOSSY_COBBLESTONE), "Mossy Cobblestone", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(2, Meta::STONE_SLAB2_PRISMARINE), "Prismarine", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(2, Meta::STONE_SLAB2_PRISMARINE_BRICKS), "Prismarine Bricks", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(2, Meta::STONE_SLAB2_PURPUR), "Purpur", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(2, Meta::STONE_SLAB2_RED_NETHER_BRICK), "Red Nether Brick", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(2, Meta::STONE_SLAB2_RED_SANDSTONE), "Red Sandstone", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(2, Meta::STONE_SLAB2_SMOOTH_SANDSTONE), "Smooth Sandstone", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(3, Meta::STONE_SLAB3_ANDESITE), "Andesite", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(3, Meta::STONE_SLAB3_DIORITE), "Diorite", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(3, Meta::STONE_SLAB3_END_STONE_BRICK), "End Stone Brick", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(3, Meta::STONE_SLAB3_GRANITE), "Granite", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(3, Meta::STONE_SLAB3_POLISHED_ANDESITE), "Polished Andesite", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(3, Meta::STONE_SLAB3_POLISHED_DIORITE), "Polished Diorite", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(3, Meta::STONE_SLAB3_POLISHED_GRANITE), "Polished Granite", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(3, Meta::STONE_SLAB3_SMOOTH_RED_SANDSTONE), "Smooth Red Sandstone", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(4, Meta::STONE_SLAB4_CUT_RED_SANDSTONE), "Cut Red Sandstone", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(4, Meta::STONE_SLAB4_CUT_SANDSTONE), "Cut Sandstone", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(4, Meta::STONE_SLAB4_MOSSY_STONE_BRICK), "Mossy Stone Brick", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(4, Meta::STONE_SLAB4_SMOOTH_QUARTZ), "Smooth Quartz", $stoneSlabBreakInfo),
new Slab($getStoneSlabId(4, Meta::STONE_SLAB4_STONE), "Stone", $stoneSlabBreakInfo),
] as $slabType){
$this->registerSlabWithDoubleHighBitsRemapping($slabType);
}
$this->registerAllMeta(new Opaque(new BID(Ids::STONECUTTER, 0), "Stonecutter", new BlockBreakInfo(3.5, BlockToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
$this->registerAllMeta(new Sugarcane(new BID(Ids::REEDS_BLOCK, 0, ItemIds::REEDS), "Sugarcane", BlockBreakInfo::instant()));
$this->registerAllMeta(new SweetBerryBush(new BID(Ids::SWEET_BERRY_BUSH, 0, ItemIds::SWEET_BERRIES), "Sweet Berry Bush", BlockBreakInfo::instant()));

View File

@ -42,6 +42,8 @@ final class BlockLegacyMetadata{
public const BAMBOO_LEAF_SIZE_SHIFT = 1;
public const BAMBOO_LEAF_SIZE_MASK = 0x03;
public const BAMBOO_SAPLING_FLAG_READY = 0x01;
public const BARREL_FLAG_OPEN = 0x08;
public const BED_FLAG_HEAD = 0x08;

View File

@ -125,6 +125,24 @@ class BrewingStand extends Transparent{
}
public function onScheduledUpdate() : void{
//TODO
$brewing = $this->position->getWorld()->getTile($this->position);
if($brewing instanceof TileBrewingStand){
if($brewing->onUpdate()){
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1);
}
$changed = false;
foreach(BrewingStandSlot::getAll() as $slot){
$occupied = !$brewing->getInventory()->isSlotEmpty($slot->getSlotNumber());
if($occupied !== $this->hasSlot($slot)){
$this->setSlot($slot, $occupied);
$changed = true;
}
}
if($changed){
$this->position->getWorld()->setBlock($this->position, $this);
}
}
}
}

View File

@ -39,6 +39,9 @@ class Cobweb extends Flowable{
}
public function getDropsForCompatibleTool(Item $item) : array{
if(($item->getBlockToolType() & BlockToolType::SHEARS) !== 0){
return [$this->asItem()];
}
return [
VanillaItems::STRING()
];

View File

@ -66,4 +66,8 @@ class EnderChest extends Transparent{
VanillaBlocks::OBSIDIAN()->asItem()->setCount(8)
];
}
public function isAffectedBySilkTouch() : bool{
return true;
}
}

View File

@ -29,6 +29,7 @@ use pocketmine\block\utils\NormalHorizontalFacingInMetadataTrait;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use function mt_rand;
class Furnace extends Opaque{
use FacesOppositePlacingPlayerTrait;
@ -84,6 +85,9 @@ class Furnace extends Opaque{
public function onScheduledUpdate() : void{
$furnace = $this->position->getWorld()->getTile($this->position);
if($furnace instanceof TileFurnace && $furnace->onUpdate()){
if(mt_rand(1, 60) === 1){ //in vanilla this is between 1 and 5 seconds; try to average about 3
$this->position->getWorld()->addSound($this->position, $furnace->getFurnaceType()->getCookSound());
}
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1); //TODO: check this
}
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\PillarRotationInMetadataTrait;
use pocketmine\entity\Entity;
class HayBale extends Opaque{
use PillarRotationInMetadataTrait;
@ -35,4 +36,9 @@ class HayBale extends Opaque{
public function getFlammability() : int{
return 20;
}
public function onEntityLand(Entity $entity) : ?float{
$entity->fallDistance *= 0.2;
return null;
}
}

View File

@ -83,6 +83,9 @@ abstract class Liquid extends Transparent{
/** @return $this */
public function setDecay(int $decay) : self{
if($decay < 0 || $decay > 7){
throw new \InvalidArgumentException("Decay must be in range 0-7");
}
$this->decay = $decay;
return $this;
}
@ -339,7 +342,7 @@ abstract class Liquid extends Transparent{
$ev = new BlockSpreadEvent($block, $this, $new);
$ev->call();
if(!$ev->isCancelled()){
if($block->getId() > 0){
if($block->getId() !== BlockLegacyIds::AIR){
$this->position->getWorld()->useBreakOn($block->position);
}

View File

@ -24,7 +24,13 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColorInMetadataTrait;
use pocketmine\block\utils\DyeColor;
final class StainedGlass extends Glass{
use ColorInMetadataTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->color = DyeColor::WHITE();
parent::__construct($idInfo, $name, $breakInfo);
}
}

View File

@ -24,7 +24,13 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColorInMetadataTrait;
use pocketmine\block\utils\DyeColor;
final class StainedGlassPane extends GlassPane{
use ColorInMetadataTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->color = DyeColor::WHITE();
parent::__construct($idInfo, $name, $breakInfo);
}
}

View File

@ -24,7 +24,13 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColorInMetadataTrait;
use pocketmine\block\utils\DyeColor;
final class StainedHardenedClay extends HardenedClay{
use ColorInMetadataTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->color = DyeColor::WHITE();
parent::__construct($idInfo, $name, $breakInfo);
}
}

View File

@ -24,7 +24,13 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColorInMetadataTrait;
use pocketmine\block\utils\DyeColor;
final class StainedHardenedGlass extends HardenedGlass{
use ColorInMetadataTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->color = DyeColor::WHITE();
parent::__construct($idInfo, $name, $breakInfo);
}
}

View File

@ -24,7 +24,13 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColorInMetadataTrait;
use pocketmine\block\utils\DyeColor;
final class StainedHardenedGlassPane extends HardenedGlassPane{
use ColorInMetadataTrait;
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->color = DyeColor::WHITE();
parent::__construct($idInfo, $name, $breakInfo);
}
}

View File

@ -24,16 +24,29 @@ declare(strict_types=1);
namespace pocketmine\block\tile;
use pocketmine\block\inventory\BrewingStandInventory;
use pocketmine\crafting\BrewingRecipe;
use pocketmine\event\block\BrewingFuelUseEvent;
use pocketmine\event\block\BrewItemEvent;
use pocketmine\inventory\CallbackInventoryListener;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\protocol\ContainerSetDataPacket;
use pocketmine\player\Player;
use pocketmine\world\sound\PotionFinishBrewingSound;
use pocketmine\world\World;
use function array_map;
use function count;
class BrewingStand extends Spawnable implements Container, Nameable{
use NameableTrait {
addAdditionalSpawnData as addNameSpawnData;
}
use ContainerTrait;
use NameableTrait;
public const BREW_TIME_TICKS = 400; // Brew time in ticks
private const TAG_BREW_TIME = "BrewTime"; //TAG_Short
private const TAG_BREW_TIME_PE = "CookTime"; //TAG_Short
@ -41,15 +54,11 @@ class BrewingStand extends Spawnable implements Container, Nameable{
private const TAG_REMAINING_FUEL_TIME = "Fuel"; //TAG_Byte
private const TAG_REMAINING_FUEL_TIME_PE = "FuelAmount"; //TAG_Short
/** @var BrewingStandInventory */
private $inventory;
private BrewingStandInventory $inventory;
/** @var int */
private $brewTime = 0;
/** @var int */
private $maxFuelTime = 0;
/** @var int */
private $remainingFuelTime = 0;
private int $brewTime = 0;
private int $maxFuelTime = 0;
private int $remainingFuelTime = 0;
public function __construct(World $world, Vector3 $pos){
parent::__construct($world, $pos);
@ -83,6 +92,14 @@ class BrewingStand extends Spawnable implements Container, Nameable{
$nbt->setShort(self::TAG_REMAINING_FUEL_TIME_PE, $this->remainingFuelTime);
}
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
$this->addNameSpawnData($nbt);
$nbt->setShort(self::TAG_BREW_TIME_PE, $this->brewTime);
$nbt->setShort(self::TAG_MAX_FUEL_TIME, $this->maxFuelTime);
$nbt->setShort(self::TAG_REMAINING_FUEL_TIME_PE, $this->remainingFuelTime);
}
public function getDefaultName() : string{
return "Brewing Stand";
}
@ -108,4 +125,135 @@ class BrewingStand extends Spawnable implements Container, Nameable{
public function getRealInventory(){
return $this->inventory;
}
private function checkFuel(Item $item) : void{
$ev = new BrewingFuelUseEvent($this);
if(!$item->equals(VanillaItems::BLAZE_POWDER(), true, false)){
$ev->cancel();
}
$ev->call();
if($ev->isCancelled()){
return;
}
$item->pop();
$this->inventory->setItem(BrewingStandInventory::SLOT_FUEL, $item);
$this->maxFuelTime = $this->remainingFuelTime = $ev->getFuelTime();
}
/**
* @return BrewingRecipe[]
* @phpstan-return array<int, BrewingRecipe>
*/
private function getBrewableRecipes() : array{
if($this->inventory->getItem(BrewingStandInventory::SLOT_INGREDIENT)->isNull()){
return [];
}
$recipes = [];
foreach([BrewingStandInventory::SLOT_BOTTLE_LEFT, BrewingStandInventory::SLOT_BOTTLE_MIDDLE, BrewingStandInventory::SLOT_BOTTLE_RIGHT] as $slot){
$input = $this->inventory->getItem($slot);
if($input->isNull()){
continue;
}
if(($recipe = $this->position->getWorld()->getServer()->getCraftingManager()->matchBrewingRecipe($input, $this->inventory->getItem(BrewingStandInventory::SLOT_INGREDIENT))) !== null){
$recipes[$slot] = $recipe;
}
}
return $recipes;
}
public function onUpdate() : bool{
if($this->closed){
return false;
}
$this->timings->startTiming();
$prevBrewTime = $this->brewTime;
$prevRemainingFuelTime = $this->remainingFuelTime;
$prevMaxFuelTime = $this->maxFuelTime;
$ret = false;
$fuel = $this->inventory->getItem(BrewingStandInventory::SLOT_FUEL);
$ingredient = $this->inventory->getItem(BrewingStandInventory::SLOT_INGREDIENT);
$recipes = $this->getBrewableRecipes();
$canBrew = count($recipes) !== 0;
if($this->remainingFuelTime <= 0 && $canBrew){
$this->checkFuel($fuel);
}
if($this->remainingFuelTime > 0){
if($canBrew){
if($this->brewTime === 0){
$this->brewTime = self::BREW_TIME_TICKS;
--$this->remainingFuelTime;
}
--$this->brewTime;
if($this->brewTime <= 0){
$anythingBrewed = false;
foreach($recipes as $slot => $recipe){
$input = $this->inventory->getItem($slot);
$output = $recipe->getResultFor($input);
if($output === null){
continue;
}
$ev = new BrewItemEvent($this, $slot, $input, $output, $recipe);
$ev->call();
if($ev->isCancelled()){
continue;
}
$this->inventory->setItem($slot, $ev->getResult());
$anythingBrewed = true;
}
if($anythingBrewed){
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new PotionFinishBrewingSound());
}
$ingredient->pop();
$this->inventory->setItem(BrewingStandInventory::SLOT_INGREDIENT, $ingredient);
$this->brewTime = 0;
}else{
$ret = true;
}
}else{
$this->brewTime = 0;
}
}else{
$this->brewTime = $this->remainingFuelTime = $this->maxFuelTime = 0;
}
$viewers = array_map(fn(Player $p) => $p->getNetworkSession()->getInvManager(), $this->inventory->getViewers());
foreach($viewers as $v){
if($v === null){
continue;
}
if($prevBrewTime !== $this->brewTime){
$v->syncData($this->inventory, ContainerSetDataPacket::PROPERTY_BREWING_STAND_BREW_TIME, $this->brewTime);
}
if($prevRemainingFuelTime !== $this->remainingFuelTime){
$v->syncData($this->inventory, ContainerSetDataPacket::PROPERTY_BREWING_STAND_FUEL_AMOUNT, $this->remainingFuelTime);
}
if($prevMaxFuelTime !== $this->maxFuelTime){
$v->syncData($this->inventory, ContainerSetDataPacket::PROPERTY_BREWING_STAND_FUEL_TOTAL, $this->maxFuelTime);
}
}
$this->timings->stopTiming();
return $ret;
}
}

View File

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block\utils;
use pocketmine\block\inventory\BrewingStandInventory;
use pocketmine\utils\EnumTrait;
/**
@ -36,13 +37,24 @@ use pocketmine\utils\EnumTrait;
* @method static BrewingStandSlot SOUTHWEST()
*/
final class BrewingStandSlot{
use EnumTrait;
use EnumTrait {
__construct as Enum___construct;
}
protected static function setup() : void{
self::registerAll(
new self("east"),
new self("northwest"),
new self("southwest")
new self("east", BrewingStandInventory::SLOT_BOTTLE_LEFT),
new self("northwest", BrewingStandInventory::SLOT_BOTTLE_MIDDLE),
new self("southwest", BrewingStandInventory::SLOT_BOTTLE_RIGHT)
);
}
private function __construct(string $enumName, private int $slotNumber){
$this->Enum___construct($enumName);
}
/**
* Returns the brewing stand inventory slot number associated with this visual slot.
*/
public function getSlotNumber() : int{ return $this->slotNumber; }
}

View File

@ -0,0 +1,30 @@
<?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\crafting;
use pocketmine\item\Item;
interface BrewingRecipe{
public function getResultFor(Item $input) : ?Item;
}

View File

@ -45,6 +45,18 @@ class CraftingManager{
*/
protected $furnaceRecipeManagers;
/**
* @var PotionTypeRecipe[][]
* @phpstan-var array<string, array<string, PotionTypeRecipe>>
*/
protected $potionTypeRecipes = [];
/**
* @var PotionContainerChangeRecipe[][]
* @phpstan-var array<int, array<string, PotionContainerChangeRecipe>>
*/
protected $potionContainerChangeRecipes = [];
/**
* @var ObjectSet
* @phpstan-var ObjectSet<\Closure() : void>
@ -140,6 +152,22 @@ class CraftingManager{
return $this->furnaceRecipeManagers[$furnaceType->id()];
}
/**
* @return PotionTypeRecipe[][]
* @phpstan-return array<string, array<string, PotionTypeRecipe>>
*/
public function getPotionTypeRecipes() : array{
return $this->potionTypeRecipes;
}
/**
* @return PotionContainerChangeRecipe[][]
* @phpstan-return array<int, array<string, PotionContainerChangeRecipe>>
*/
public function getPotionContainerChangeRecipes() : array{
return $this->potionContainerChangeRecipes;
}
public function registerShapedRecipe(ShapedRecipe $recipe) : void{
$this->shapedRecipes[self::hashOutputs($recipe->getResults())][] = $recipe;
@ -156,6 +184,25 @@ class CraftingManager{
}
}
public function registerPotionTypeRecipe(PotionTypeRecipe $recipe) : void{
$input = $recipe->getInput();
$ingredient = $recipe->getIngredient();
$this->potionTypeRecipes[$input->getId() . ":" . $input->getMeta()][$ingredient->getId() . ":" . ($ingredient->hasAnyDamageValue() ? "?" : $ingredient->getMeta())] = $recipe;
foreach($this->recipeRegisteredCallbacks as $callback){
$callback();
}
}
public function registerPotionContainerChangeRecipe(PotionContainerChangeRecipe $recipe) : void{
$ingredient = $recipe->getIngredient();
$this->potionContainerChangeRecipes[$recipe->getInputItemId()][$ingredient->getId() . ":" . ($ingredient->hasAnyDamageValue() ? "?" : $ingredient->getMeta())] = $recipe;
foreach($this->recipeRegisteredCallbacks as $callback){
$callback();
}
}
/**
* @param Item[] $outputs
*/
@ -206,4 +253,11 @@ class CraftingManager{
}
}
}
public function matchBrewingRecipe(Item $input, Item $ingredient) : ?BrewingRecipe{
return $this->potionTypeRecipes[$input->getId() . ":" . $input->getMeta()][$ingredient->getId() . ":" . $ingredient->getMeta()] ??
$this->potionTypeRecipes[$input->getId() . ":" . $input->getMeta()][$ingredient->getId() . ":?"] ??
$this->potionContainerChangeRecipes[$input->getId()][$ingredient->getId() . ":" . $ingredient->getMeta()] ??
$this->potionContainerChangeRecipes[$input->getId()][$ingredient->getId() . ":?"] ?? null;
}
}

View File

@ -77,6 +77,20 @@ final class CraftingManagerFromDataHelper{
Item::jsonDeserialize($recipe["input"]))
);
}
foreach($recipes["potion_type"] as $recipe){
$result->registerPotionTypeRecipe(new PotionTypeRecipe(
Item::jsonDeserialize($recipe["input"]),
Item::jsonDeserialize($recipe["ingredient"]),
Item::jsonDeserialize($recipe["output"])
));
}
foreach($recipes["potion_container_change"] as $recipe){
$result->registerPotionContainerChangeRecipe(new PotionContainerChangeRecipe(
$recipe["input_item_id"],
Item::jsonDeserialize($recipe["ingredient"]),
$recipe["output_item_id"]
));
}
return $result;
}

View File

@ -24,6 +24,10 @@ declare(strict_types=1);
namespace pocketmine\crafting;
use pocketmine\utils\EnumTrait;
use pocketmine\world\sound\BlastFurnaceSound;
use pocketmine\world\sound\FurnaceSound;
use pocketmine\world\sound\SmokerSound;
use pocketmine\world\sound\Sound;
/**
* This doc-block is generated automatically, do not modify it manually.
@ -42,15 +46,17 @@ final class FurnaceType{
protected static function setup() : void{
self::registerAll(
new self("furnace", 200),
new self("blast_furnace", 100),
new self("smoker", 100),
new self("furnace", 200, new FurnaceSound()),
new self("blast_furnace", 100, new BlastFurnaceSound()),
new self("smoker", 100, new SmokerSound()),
);
}
private function __construct(string $enumName, private int $cookDurationTicks){
private function __construct(string $enumName, private int $cookDurationTicks, private Sound $cookSound){
$this->Enum___construct($enumName);
}
public function getCookDurationTicks() : int{ return $this->cookDurationTicks; }
public function getCookSound() : Sound{ return $this->cookSound; }
}

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\crafting;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
class PotionContainerChangeRecipe implements BrewingRecipe{
public function __construct(
private int $inputItemId,
private Item $ingredient,
private int $outputItemId
){
$this->ingredient = clone $ingredient;
}
public function getInputItemId() : int{
return $this->inputItemId;
}
public function getIngredient() : Item{
return clone $this->ingredient;
}
public function getOutputItemId() : int{
return $this->outputItemId;
}
public function getResultFor(Item $input) : ?Item{
return $input->getId() === $this->getInputItemId() ? ItemFactory::getInstance()->get($this->getOutputItemId(), $input->getMeta()) : null;
}
}

View File

@ -0,0 +1,55 @@
<?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\crafting;
use pocketmine\item\Item;
class PotionTypeRecipe implements BrewingRecipe{
public function __construct(
private Item $input,
private Item $ingredient,
private Item $output
){
$this->input = clone $input;
$this->ingredient = clone $ingredient;
$this->output = clone $output;
}
public function getInput() : Item{
return clone $this->input;
}
public function getIngredient() : Item{
return clone $this->ingredient;
}
public function getOutput() : Item{
return clone $this->output;
}
public function getResultFor(Item $input) : ?Item{
return $input->equals($this->input, true, false) ? $this->getOutput() : null;
}
}

View File

@ -0,0 +1,71 @@
<?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\event\block;
use pocketmine\block\tile\BrewingStand;
use pocketmine\crafting\BrewingRecipe;
use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
use pocketmine\item\Item;
class BrewItemEvent extends BlockEvent implements Cancellable{
use CancellableTrait;
public function __construct(
private BrewingStand $brewingStand,
private int $slot,
private Item $input,
private Item $result,
private BrewingRecipe $recipe
){
parent::__construct($brewingStand->getBlock());
}
public function getBrewingStand() : BrewingStand{
return $this->brewingStand;
}
/**
* Returns which slot of the brewing stand's inventory the potion is in.
*/
public function getSlot() : int{
return $this->slot;
}
public function getInput() : Item{
return clone $this->input;
}
public function getResult() : Item{
return clone $this->result;
}
public function setResult(Item $result) : void{
$this->result = clone $result;
}
public function getRecipe() : BrewingRecipe{
return $this->recipe;
}
}

View File

@ -0,0 +1,64 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\event\block;
use pocketmine\block\tile\BrewingStand;
use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
/**
* Called when a brewing stand consumes a new fuel item.
*/
class BrewingFuelUseEvent extends BlockEvent implements Cancellable{
use CancellableTrait;
private int $fuelTime = 20;
public function __construct(
private BrewingStand $brewingStand
){
parent::__construct($brewingStand->getBlock());
}
public function getBrewingStand() : BrewingStand{
return $this->brewingStand;
}
/**
* Returns how many times the fuel can be used for potion brewing before it runs out.
*/
public function getFuelTime() : int{
return $this->fuelTime;
}
/**
* Sets how many times the fuel can be used for potion brewing before it runs out.
*/
public function setFuelTime(int $fuelTime) : void{
if($fuelTime <= 0){
throw new \InvalidArgumentException("Fuel time must be positive");
}
$this->fuelTime = $fuelTime;
}
}

View File

@ -0,0 +1,55 @@
<?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\event\player;
use pocketmine\player\Player;
/**
* Called when a player requests a different viewing distance than the current one.
*/
class PlayerViewDistanceChangeEvent extends PlayerEvent{
protected int $newDistance;
protected int $oldDistance;
public function __construct(Player $player, int $oldDistance, int $newDistance){
$this->player = $player;
$this->oldDistance = $oldDistance;
$this->newDistance = $newDistance;
}
/**
* Returns the new view radius, measured in chunks.
*/
public function getNewDistance() : int{
return $this->newDistance;
}
/**
* Returns the old view radius, measured in chunks.
* A value of -1 means that the player has just connected and did not have a view distance before this event.
*/
public function getOldDistance() : int{
return $this->oldDistance;
}
}

View File

@ -46,6 +46,9 @@ class DropItemAction extends InventoryAction{
public function onPreExecute(Player $source) : bool{
$ev = new PlayerDropItemEvent($source, $this->targetItem);
if($source->isSpectator()){
$ev->cancel();
}
$ev->call();
if($ev->isCancelled()){
return false;

View File

@ -49,7 +49,7 @@ final class StringToItemParser extends StringToTParser{
$result->registerBlock($prefix("bed"), fn() => VanillaBlocks::BED()->setColor($color));
$result->registerBlock($prefix("carpet"), fn() => VanillaBlocks::CARPET()->setColor($color));
$result->registerBlock($prefix("concrete"), fn() => VanillaBlocks::CONCRETE()->setColor($color));
$result->registerBlock($prefix("concrete_powder"), fn() => VanillaBlocks::CONCRETE()->setColor($color));
$result->registerBlock($prefix("concrete_powder"), fn() => VanillaBlocks::CONCRETE_POWDER()->setColor($color));
$result->registerBlock($prefix("stained_clay"), fn() => VanillaBlocks::STAINED_CLAY()->setColor($color));
$result->registerBlock($prefix("stained_glass"), fn() => VanillaBlocks::STAINED_GLASS()->setColor($color));
$result->registerBlock($prefix("stained_glass_pane"), fn() => VanillaBlocks::STAINED_GLASS_PANE()->setColor($color));

View File

@ -26,12 +26,15 @@ namespace pocketmine\network\mcpe\cache;
use pocketmine\crafting\CraftingManager;
use pocketmine\crafting\FurnaceType;
use pocketmine\item\Item;
use pocketmine\network\mcpe\convert\ItemTranslator;
use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\network\mcpe\protocol\CraftingDataPacket;
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
use pocketmine\network\mcpe\protocol\types\recipe\CraftingRecipeBlockName;
use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipe as ProtocolFurnaceRecipe;
use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipeBlockName;
use pocketmine\network\mcpe\protocol\types\recipe\PotionContainerChangeRecipe as ProtocolPotionContainerChangeRecipe;
use pocketmine\network\mcpe\protocol\types\recipe\PotionTypeRecipe as ProtocolPotionTypeRecipe;
use pocketmine\network\mcpe\protocol\types\recipe\RecipeIngredient;
use pocketmine\network\mcpe\protocol\types\recipe\ShapedRecipe as ProtocolShapedRecipe;
use pocketmine\network\mcpe\protocol\types\recipe\ShapelessRecipe as ProtocolShapelessRecipe;
@ -137,7 +140,39 @@ final class CraftingDataCache{
}
}
$potionTypeRecipes = [];
foreach($manager->getPotionTypeRecipes() as $recipes){
foreach($recipes as $recipe){
$input = $converter->coreItemStackToNet($recipe->getInput());
$ingredient = $converter->coreItemStackToNet($recipe->getIngredient());
$output = $converter->coreItemStackToNet($recipe->getOutput());
$potionTypeRecipes[] = new ProtocolPotionTypeRecipe(
$input->getId(),
$input->getMeta(),
$ingredient->getId(),
$ingredient->getMeta(),
$output->getId(),
$output->getMeta()
);
}
}
$potionContainerChangeRecipes = [];
$itemTranslator = ItemTranslator::getInstance();
foreach($manager->getPotionContainerChangeRecipes() as $recipes){
foreach($recipes as $recipe){
$input = $itemTranslator->toNetworkId($recipe->getInputItemId(), 0);
$ingredient = $itemTranslator->toNetworkId($recipe->getIngredient()->getId(), 0);
$output = $itemTranslator->toNetworkId($recipe->getOutputItemId(), 0);
$potionContainerChangeRecipes[] = new ProtocolPotionContainerChangeRecipe(
$input[0],
$ingredient[0],
$output[0]
);
}
}
Timings::$craftingDataCacheRebuild->stopTiming();
return CraftingDataPacket::create($recipesWithTypeIds, [], [], [], true);
return CraftingDataPacket::create($recipesWithTypeIds, $potionTypeRecipes, $potionContainerChangeRecipes, [], true);
}
}

View File

@ -61,7 +61,7 @@ class EncryptionContext{
}
/**
* Returns an EncryptionContext suitable for decrypting Minecraft packets from 1.16.200 and up.
* Returns an EncryptionContext suitable for decrypting Minecraft packets from 1.16.220.50 (protocol version 429) and up.
*
* MCPE uses GCM, but without the auth tag, which defeats the whole purpose of using GCM.
* GCM is just a wrapper around CTR which adds the auth tag, so CTR can replace GCM for this case.

View File

@ -90,6 +90,8 @@ use pocketmine\network\mcpe\protocol\SubClientLoginPacket;
use pocketmine\network\mcpe\protocol\TextPacket;
use pocketmine\network\mcpe\protocol\types\ActorEvent;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
use pocketmine\network\mcpe\protocol\types\entity\FloatMetadataProperty;
use pocketmine\network\mcpe\protocol\types\inventory\ContainerIds;
use pocketmine\network\mcpe\protocol\types\inventory\MismatchTransactionData;
use pocketmine\network\mcpe\protocol\types\inventory\NetworkInventoryAction;
@ -222,6 +224,11 @@ class InGamePacketHandler extends PacketHandler{
($gliding !== null && !$this->player->toggleGlide($gliding));
if((bool) $mismatch){
$this->player->sendData([$this->player]);
}elseif($packet->hasFlag(PlayerAuthInputFlags::STOP_SWIMMING) || $packet->hasFlag(PlayerAuthInputFlags::STOP_GLIDING)){
//TODO: HACK! workaround for a client bug where the AABB doesn't change back properly when stopping swimming or gliding
$this->player->sendData([$this->player], [
EntityMetadataProperties::BOUNDING_BOX_HEIGHT => new FloatMetadataProperty($this->player->getSize()->getHeight())
]);
}
if($packet->hasFlag(PlayerAuthInputFlags::START_JUMPING)){

View File

@ -73,6 +73,7 @@ use pocketmine\event\player\PlayerToggleSneakEvent;
use pocketmine\event\player\PlayerToggleSprintEvent;
use pocketmine\event\player\PlayerToggleSwimEvent;
use pocketmine\event\player\PlayerTransferEvent;
use pocketmine\event\player\PlayerViewDistanceChangeEvent;
use pocketmine\form\Form;
use pocketmine\form\FormValidationException;
use pocketmine\inventory\CallbackInventoryListener;
@ -507,7 +508,14 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
}
public function setViewDistance(int $distance) : void{
$this->viewDistance = $this->server->getAllowedViewDistance($distance);
$newViewDistance = $this->server->getAllowedViewDistance($distance);
if($newViewDistance !== $this->viewDistance){
$ev = new PlayerViewDistanceChangeEvent($this, $this->viewDistance, $newViewDistance);
$ev->call();
}
$this->viewDistance = $newViewDistance;
$this->spawnThreshold = (int) (min($this->viewDistance, $this->server->getConfigGroup()->getPropertyInt("chunk-sending.spawn-radius", 4)) ** 2 * M_PI);

View File

@ -106,7 +106,6 @@ class ZippedResourcePack implements ResourcePack{
}
$mapper = new \JsonMapper();
$mapper->bExceptionOnUndefinedProperty = true;
$mapper->bExceptionOnMissingData = true;
try{

View File

@ -493,7 +493,7 @@ class World implements ChunkManager{
foreach(BlockFactory::getInstance()->getAllKnownStates() as $state){
$dontTickName = $dontTickBlocks[$state->getTypeId()] ?? null;
if($dontTickName === null && !$state->ticksRandomly()){
if($dontTickName === null && $state->ticksRandomly()){
$this->randomTickBlocks[$state->getFullId()] = true;
}
}
@ -971,6 +971,8 @@ class World implements ChunkManager{
public function createBlockUpdatePackets(array $blocks) : array{
$packets = [];
$blockMapping = RuntimeBlockMapping::getInstance();
foreach($blocks as $b){
if(!($b instanceof Vector3)){
throw new \TypeError("Expected Vector3 in blocks array, got " . (is_object($b) ? get_class($b) : gettype($b)));
@ -980,7 +982,7 @@ class World implements ChunkManager{
$blockPosition = BlockPosition::fromVector3($b);
$packets[] = UpdateBlockPacket::create(
$blockPosition,
RuntimeBlockMapping::getInstance()->toRuntimeId($fullBlock->getFullId()),
$blockMapping->toRuntimeId($fullBlock->getFullId()),
UpdateBlockPacket::FLAG_NETWORK,
UpdateBlockPacket::DATA_LAYER_NORMAL
);
@ -1129,6 +1131,7 @@ class World implements ChunkManager{
$entity->onRandomUpdate();
}
$blockFactory = BlockFactory::getInstance();
foreach($chunk->getSubChunks() as $Y => $subChunk){
if(!$subChunk->isEmptyFast()){
$k = 0;
@ -1145,8 +1148,7 @@ class World implements ChunkManager{
$state = $subChunk->getFullBlock($x, $y, $z);
if(isset($this->randomTickBlocks[$state])){
/** @var Block $block */
$block = BlockFactory::getInstance()->fromFullBlock($state);
$block = $blockFactory->fromFullBlock($state);
$block->position($this, $chunkX * Chunk::EDGE_LENGTH + $x, ($Y << SubChunk::COORD_BIT_SIZE) + $y, $chunkZ * Chunk::EDGE_LENGTH + $z);
$block->onRandomTick();
}

View File

@ -153,16 +153,18 @@ class WorldManager{
}
$this->server->getLogger()->info($this->server->getLanguage()->translate(KnownTranslationFactory::pocketmine_level_unloading($world->getDisplayName())));
try{
$safeSpawn = $this->defaultWorld !== null ? $this->defaultWorld->getSafeSpawn() : null;
}catch(WorldException $e){
$safeSpawn = null;
}
foreach($world->getPlayers() as $player){
if($world === $this->defaultWorld || $safeSpawn === null){
$player->disconnect("Forced default world unload");
}else{
$player->teleport($safeSpawn);
if(count($world->getPlayers()) !== 0){
try{
$safeSpawn = $this->defaultWorld !== null && $this->defaultWorld !== $world ? $this->defaultWorld->getSafeSpawn() : null;
}catch(WorldException $e){
$safeSpawn = null;
}
foreach($world->getPlayers() as $player){
if($safeSpawn === null){
$player->disconnect("Forced default world unload");
}else{
$player->teleport($safeSpawn);
}
}
}

View File

@ -263,6 +263,7 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
case 11: //MCPE 1.11.0.1 beta (???)
case 10: //MCPE 1.9 (???)
case 9: //MCPE 1.8 (???)
case 8: //MCPE 1.2.13 (paletted subchunks)
case 7: //MCPE 1.2 (???)
case 6: //MCPE 1.2.0.2 beta (???)
case 4: //MCPE 1.1

View File

@ -0,0 +1,35 @@
<?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\world\sound;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\types\LevelSoundEvent;
final class BlastFurnaceSound implements Sound{
public function encode(Vector3 $pos) : array{
return [LevelSoundEventPacket::nonActorSound(LevelSoundEvent::BLOCK_BLASTFURNACE_FIRE_CRACKLE, $pos, false)];
}
}

View File

@ -0,0 +1,35 @@
<?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\world\sound;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\types\LevelSoundEvent;
final class FurnaceSound implements Sound{
public function encode(Vector3 $pos) : array{
return [LevelSoundEventPacket::nonActorSound(LevelSoundEvent::BLOCK_FURNACE_LIT, $pos, false)];
}
}

View File

@ -0,0 +1,35 @@
<?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\world\sound;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\types\LevelSoundEvent;
final class PotionFinishBrewingSound implements Sound{
public function encode(Vector3 $pos) : array{
return [LevelSoundEventPacket::nonActorSound(LevelSoundEvent::POTION_BREWED, $pos, false)];
}
}

View File

@ -0,0 +1,35 @@
<?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\world\sound;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\types\LevelSoundEvent;
final class SmokerSound implements Sound{
public function encode(Vector3 $pos) : array{
return [LevelSoundEventPacket::nonActorSound(LevelSoundEvent::BLOCK_SMOKER_SMOKE, $pos, false)];
}
}

File diff suppressed because one or more lines are too long