Compare commits

..

40 Commits
4.3.3 ... 4.3.4

Author SHA1 Message Date
7bbb2617c8 Release 4.3.4 2022-05-22 16:12:12 +01:00
2ec65ba799 ExplosionPrimeEvent: require a positive explosion radius 2022-05-21 23:22:04 +01:00
3dd7c09351 Improve documentation of ExplosionPrimeEvent and EntityExplodeEvent 2022-05-21 23:00:34 +01:00
afc6e8878d EntityExplodeEvent: clamp yield in range 0-100 2022-05-21 22:44:45 +01:00
7eaf1246a0 Explosion: cap yield at 100%
this could overflow if the explosion size is less than 1.
While this currently doesn't have any negative effects, if we decided to support >100% yield, this would cause some issues.
2022-05-21 22:43:26 +01:00
645c44ae9c Explosion: remove unused variables 2022-05-21 22:41:28 +01:00
331b05c681 Improve documentation of EntitySpawnEvent and EntityDespawnEvent 2022-05-21 22:11:37 +01:00
3abe80184a Update ItemSpawnEvent doc (#5059) 2022-05-21 22:09:21 +01:00
7618b13c6e ItemDespawnEvent: improve documentation 2022-05-21 21:57:14 +01:00
351cd4bfd7 Improve documentation of world-related events 2022-05-21 21:46:53 +01:00
1154c7c1ab PlayerQuitEvent: improve documentation 2022-05-21 21:23:13 +01:00
4a3e42f82e PlayerTransferEvent: add documentation 2022-05-21 21:21:51 +01:00
8ecf9717d6 PlayerItemHeldEvent: add documentation
since some nuances of the intended behaviour were previously unclear...
2022-05-21 21:21:13 +01:00
3ca80b353b InventoryTransactionEvent: rewrite documentation 2022-05-21 21:20:11 +01:00
7d172e2211 PlayerCommandPreprocessEvent: updated documentation 2022-05-21 21:07:29 +01:00
e934e2bd26 PlayerDropItemEvent: updated documentation
this can be triggered by dropping an item outside of the inventory menu while the inventory window is open.
2022-05-21 21:05:27 +01:00
3177d19730 PlayerKickEvent: improved woefully inadequate documentation 2022-05-21 21:03:56 +01:00
82104a8251 UpdateNotifyEvent: updated documentation 2022-05-21 20:32:30 +01:00
e9a17374d1 Rewrite documentation of CommandEvent
no wonder people get the idea to use this shit for banning commands ...
2022-05-21 20:29:25 +01:00
c82dfef9b0 Player: fix weird behaviour when teleporting sleeping players
closes #4672
2022-05-21 20:08:12 +01:00
688be0a404 Server: apply server.properties difficulty to newly generated worlds
see #5057

jury is out on whether or not this should override difficulty on preexisting worlds, but it's non-controversial that it should apply at least to newly generated worlds.
2022-05-21 18:46:38 +01:00
33e6b63fe5 Explosion: remove unused local variable in explodeB() 2022-05-21 17:39:11 +01:00
5d92eddc82 InventoryTransaction: provide object ID of failed action for debugging identification
closes #3235
2022-05-21 17:35:21 +01:00
0324392cd8 Clean PHPStan baseline 2022-05-21 17:12:47 +01:00
01b0742bd4 LightUpdate: account for virtual nodes in prepareNodes()
fixes #3959
2022-05-21 17:07:49 +01:00
fcb2ccab99 NetworkSession: Sync all attributes on respawn 2022-05-21 16:22:35 +01:00
a45a96b3ee ShulkerBoxInventory: fixed inappropriate usage of BlockLegacyIds when comparing item IDS 2022-05-21 15:40:25 +01:00
26df37e6ef Minecart: fixed max stack size to match vanilla (#5051) 2022-05-20 16:57:48 +01:00
554f96bc24 InventoryManager: Defer opening new windows to the client until the window close handshake has been completed
fixes #5021 and probably a bunch of other inventory related glitches

When the server initiates a window close, it does so by sending a ContainerClose to the client, which causes the
client to behave as if it initiated the close itself. It responds by sending a ContainerClose back to the server,
which the server is then expected to respond to.

Sending the client a new window before sending this final response creates buggy behaviour on the client, which
is problematic when switching windows. Therefore, we defer sending any new windows until after the client
responds to our window close instruction, so that we can complete the window handshake correctly.

This is a pile of complicated garbage that only exists because Mojang overengineered the process of opening and
closing inventory windows.
2022-05-20 16:54:15 +01:00
0ea3861d43 Fixed paintings not working in newly generated worlds
Paintings would not work unless at least one entity was loaded from disk
(or saved).
2022-05-20 11:13:14 +01:00
a323a5e56d Bump docker/login-action from 1 to 2 (#5048)
Bumps [docker/login-action](https://github.com/docker/login-action) from 1 to 2.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-18 13:30:39 +01:00
79caba22a7 Bump docker/build-push-action from 2.10.0 to 3.0.0 (#5046)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 2.10.0 to 3.0.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v2.10.0...v3.0.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-18 13:29:44 +01:00
30815bc8a2 Bump actions/upload-artifact from 2 to 3 (#5047)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-18 13:29:19 +01:00
161ab5af16 Bump docker/setup-buildx-action from 1 to 2 (#5042)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 1 to 2.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-17 15:24:47 +01:00
ab41594da2 Bump actions/checkout from 2 to 3 (#5041)
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-17 15:24:23 +01:00
80d4c11061 Bump ncipollo/release-action from 1.8.6 to 1.10.0 (#5040)
Bumps [ncipollo/release-action](https://github.com/ncipollo/release-action) from 1.8.6 to 1.10.0.
- [Release notes](https://github.com/ncipollo/release-action/releases)
- [Commits](https://github.com/ncipollo/release-action/compare/v1.8.6...v1.10.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-17 15:17:33 +01:00
e767796986 Bump shivammathur/setup-php from 2.12.0 to 2.18.1 (#5043)
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.12.0 to 2.18.1.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.12.0...2.18.1)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-17 15:16:08 +01:00
dea7031b86 Bump actions/cache from 2 to 3 (#5044)
Bumps [actions/cache](https://github.com/actions/cache) from 2 to 3.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-17 15:15:52 +01:00
7e3d099d5b Update dependabot.yml 2022-05-17 15:08:52 +01:00
5abc7f866a 4.3.4 is next 2022-05-16 17:50:41 +01:00
41 changed files with 307 additions and 106 deletions

View File

@ -11,3 +11,8 @@ updates:
directory: "/"
schedule:
interval: daily
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily

View File

@ -12,16 +12,16 @@ jobs:
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Clone pmmp/PocketMine-Docker repository
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
repository: pmmp/PocketMine-Docker
fetch-depth: 1
@ -46,7 +46,7 @@ jobs:
run: echo ::set-output name=NAME::$(echo "${GITHUB_REPOSITORY,,}")
- name: Build image for tag
uses: docker/build-push-action@v2.10.0
uses: docker/build-push-action@v3.0.0
with:
push: true
context: ./pocketmine-mp
@ -59,7 +59,7 @@ jobs:
- name: Build image for major tag
if: steps.channel.outputs.CHANNEL == 'stable'
uses: docker/build-push-action@v2.10.0
uses: docker/build-push-action@v3.0.0
with:
push: true
context: ./pocketmine-mp
@ -72,7 +72,7 @@ jobs:
- name: Build image for minor tag
if: steps.channel.outputs.CHANNEL == 'stable'
uses: docker/build-push-action@v2.10.0
uses: docker/build-push-action@v3.0.0
with:
push: true
context: ./pocketmine-mp
@ -85,7 +85,7 @@ jobs:
- name: Build image for latest tag
if: steps.channel.outputs.CHANNEL == 'stable'
uses: docker/build-push-action@v2.10.0
uses: docker/build-push-action@v3.0.0
with:
push: true
context: ./pocketmine-mp

View File

@ -13,17 +13,17 @@ jobs:
fail-fast: false
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
- name: Setup PHP
uses: shivammathur/setup-php@2.12.0
uses: shivammathur/setup-php@2.18.1
with:
php-version: 8.0
- name: Restore Composer package cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.cache/composer/files
@ -60,7 +60,7 @@ jobs:
run: php build/generate-build-info-json.php ${{ github.sha }} ${{ steps.get-pm-version.outputs.PM_VERSION }} ${{ github.repository }} ${{ steps.build-number.outputs.BUILD_NUMBER }} > build_info.json
- name: Upload release artifacts
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: release_artifacts
path: |
@ -69,7 +69,7 @@ jobs:
${{ github.workspace }}/build_info.json
- name: Create draft release
uses: ncipollo/release-action@v1.8.6
uses: ncipollo/release-action@v1.10.0
with:
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
commit: ${{ github.sha }}

View File

@ -34,7 +34,7 @@ jobs:
php: [8.0.18]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Setup PHP
uses: pmmp/setup-php-action@aa636a4fe0c1c035fd9a3f05e360eadd86e06440
@ -46,7 +46,7 @@ jobs:
run: curl -sS https://getcomposer.org/installer | php
- name: Restore Composer package cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.cache/composer/files
@ -72,7 +72,7 @@ jobs:
php: [8.0.18]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Setup PHP
uses: pmmp/setup-php-action@aa636a4fe0c1c035fd9a3f05e360eadd86e06440
@ -84,7 +84,7 @@ jobs:
run: curl -sS https://getcomposer.org/installer | php
- name: Restore Composer package cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.cache/composer/files
@ -110,7 +110,7 @@ jobs:
php: [8.0.18]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: true
@ -124,7 +124,7 @@ jobs:
run: curl -sS https://getcomposer.org/installer | php
- name: Restore Composer package cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.cache/composer/files
@ -150,7 +150,7 @@ jobs:
php: [8.0.18]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Setup PHP
uses: pmmp/setup-php-action@aa636a4fe0c1c035fd9a3f05e360eadd86e06440
@ -162,7 +162,7 @@ jobs:
run: curl -sS https://getcomposer.org/installer | php
- name: Restore Composer package cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.cache/composer/files
@ -192,10 +192,10 @@ jobs:
fail-fast: false
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Setup PHP and tools
uses: shivammathur/setup-php@2.15.0
uses: shivammathur/setup-php@2.18.1
with:
php-version: 8.0
tools: php-cs-fixer:3.2

View File

@ -13,7 +13,7 @@ jobs:
- name: Install jq
run: sudo apt update && sudo apt install jq -y
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
repository: pmmp/update.pmmp.io
ssh-key: ${{ secrets.UPDATE_PMMP_IO_DEPLOY_KEY }}

View File

@ -43,3 +43,35 @@ Released 16th May 2022.
- Fixed server crash when chunks are unloaded during chunk generation callbacks
- Fixed dead coral fan items placing coral fans in the wrong orientation.
- Fixed max stack size of boat items.
# 4.3.4
Released 22nd May 2022.
## Fixes
- Fixed `difficulty` in `server.properties` having no effect - it's now applied to newly generated worlds.
- Note: this setting still doesn't behave the same way as vanilla due to potential disruption to existing servers.
- Fixed paintings not working in newly generated worlds and some other cases.
- Fixed inventory window switching breaking the inventory UI in some cases (e.g. pressing E while clicking a chest).
- Fixed minecart items incorrectly stacking.
- Fixed incorrect light levels in translucent blocks at the top of the world.
- Fixed teleporting sleeping players causing broken behaviour on the sleeping player's client.
- Fixed `EntityExplodeEvent->setYield()` accepting values outside the range 0-100.
- Fixed `ExplosionPrimeEvent->setForce()` accepting negative values (later resulting in crashes).
## Documentation
- Updated documentation for the following events:
- `CommandEvent`
- `EntityDespawnEvent`
- `EntityExplodeEvent`
- `EntitySpawnEvent`
- `ExplosionPrimeEvent`
- `InventoryTransactionEvent`
- `ItemDespawnEvent`
- `ItemSpawnEvent`
- `PlayerCommandPreprocessEvent`
- `PlayerDropItemEvent`
- `PlayerItemHeldEvent`
- `PlayerKickEvent`
- `PlayerQuitEvent`
- `PlayerTransferEvent`
- `UpdateNotifyEvent`

View File

@ -1093,6 +1093,7 @@ class Server{
$creationOptions->setGeneratorClass($generatorClass);
$creationOptions->setGeneratorOptions($generatorOptions);
$creationOptions->setDifficulty($this->getDifficulty());
if(isset($options["difficulty"]) && is_string($options["difficulty"])){
$creationOptions->setDifficulty(World::getDifficultyFromString($options["difficulty"]));
}
@ -1127,6 +1128,7 @@ class Server{
if($convertedSeed !== null){
$creationOptions->setSeed($convertedSeed);
}
$creationOptions->setDifficulty($this->getDifficulty());
$this->worldManager->generateWorld($default, $creationOptions);
}
}

View File

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

View File

@ -23,9 +23,9 @@ declare(strict_types=1);
namespace pocketmine\block\inventory;
use pocketmine\block\BlockLegacyIds;
use pocketmine\inventory\SimpleInventory;
use pocketmine\item\Item;
use pocketmine\item\ItemIds;
use pocketmine\network\mcpe\protocol\BlockEventPacket;
use pocketmine\network\mcpe\protocol\types\BlockPosition;
use pocketmine\world\Position;
@ -50,7 +50,7 @@ class ShulkerBoxInventory extends SimpleInventory implements BlockInventory{
}
public function canAddItem(Item $item) : bool{
if($item->getId() === BlockLegacyIds::UNDYED_SHULKER_BOX || $item->getId() === BlockLegacyIds::SHULKER_BOX){
if($item->getId() === ItemIds::UNDYED_SHULKER_BOX || $item->getId() === ItemIds::SHULKER_BOX){
return false;
}
return parent::canAddItem($item);

View File

@ -173,8 +173,6 @@ final class EntityFactory{
$this->register(Human::class, function(World $world, CompoundTag $nbt) : Human{
return new Human(Helper::parseLocation($nbt, $world), Human::parseSkinNBT($nbt), $nbt);
}, ['Human']);
PaintingMotive::init();
}
/**

View File

@ -24,6 +24,8 @@ declare(strict_types=1);
namespace pocketmine\entity\object;
class PaintingMotive{
private static bool $initialized = false;
/** @var PaintingMotive[] */
protected static $motives = [];
@ -76,6 +78,9 @@ class PaintingMotive{
* @return PaintingMotive[]
*/
public static function getAll() : array{
if(!self::$initialized){
self::init();
}
return self::$motives;
}

View File

@ -26,7 +26,9 @@ namespace pocketmine\event\entity;
use pocketmine\entity\Entity;
/**
* Called when a entity is despawned
* Called when an entity is removed from the world. This could be for a variety of reasons, including chunks being
* unloaded, entity death, etc.
*
* @phpstan-extends EntityEvent<Entity>
*/
class EntityDespawnEvent extends EntityEvent{

View File

@ -31,7 +31,11 @@ use pocketmine\utils\Utils;
use pocketmine\world\Position;
/**
* Called when a entity explodes
* Called when an entity explodes, after the explosion's impact has been calculated.
* No changes have been made to the world at this stage.
*
* @see ExplosionPrimeEvent
*
* @phpstan-extends EntityEvent<Entity>
*/
class EntityExplodeEvent extends EntityEvent implements Cancellable{
@ -47,12 +51,16 @@ class EntityExplodeEvent extends EntityEvent implements Cancellable{
protected $yield;
/**
* @param Block[] $blocks
* @param Block[] $blocks
* @param float $yield 0-100
*/
public function __construct(Entity $entity, Position $position, array $blocks, float $yield){
$this->entity = $entity;
$this->position = $position;
$this->blocks = $blocks;
if($yield < 0.0 || $yield > 100.0){
throw new \InvalidArgumentException("Yield must be in range 0.0 - 100.0");
}
$this->yield = $yield;
}
@ -61,6 +69,8 @@ class EntityExplodeEvent extends EntityEvent implements Cancellable{
}
/**
* Returns a list of blocks destroyed by the explosion.
*
* @return Block[]
*/
public function getBlockList() : array{
@ -68,6 +78,8 @@ class EntityExplodeEvent extends EntityEvent implements Cancellable{
}
/**
* Sets the blocks destroyed by the explosion.
*
* @param Block[] $blocks
*/
public function setBlockList(array $blocks) : void{
@ -75,11 +87,22 @@ class EntityExplodeEvent extends EntityEvent implements Cancellable{
$this->blocks = $blocks;
}
/**
* Returns the percentage chance of drops from each block destroyed by the explosion.
* @return float 0-100
*/
public function getYield() : float{
return $this->yield;
}
/**
* Sets the percentage chance of drops from each block destroyed by the explosion.
* @param float $yield 0-100
*/
public function setYield(float $yield) : void{
if($yield < 0.0 || $yield > 100.0){
throw new \InvalidArgumentException("Yield must be in range 0.0 - 100.0");
}
$this->yield = $yield;
}
}

View File

@ -26,7 +26,8 @@ namespace pocketmine\event\entity;
use pocketmine\entity\Entity;
/**
* Called when a entity is spawned
* Called when an entity is added to the world. This might be a new entity or an entity loaded from storage.
*
* @phpstan-extends EntityEvent<Entity>
*/
class EntitySpawnEvent extends EntityEvent{

View File

@ -28,7 +28,11 @@ use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
/**
* Called when a entity decides to explode
* Called when an entity decides to explode, before the explosion's impact is calculated.
* This allows changing the force of the explosion and whether it will destroy blocks.
*
* @see EntityExplodeEvent
*
* @phpstan-extends EntityEvent<Entity>
*/
class ExplosionPrimeEvent extends EntityEvent implements Cancellable{
@ -40,6 +44,9 @@ class ExplosionPrimeEvent extends EntityEvent implements Cancellable{
private $blockBreaking;
public function __construct(Entity $entity, float $force){
if($force <= 0){
throw new \InvalidArgumentException("Explosion radius must be positive");
}
$this->entity = $entity;
$this->force = $force;
$this->blockBreaking = true;
@ -50,6 +57,9 @@ class ExplosionPrimeEvent extends EntityEvent implements Cancellable{
}
public function setForce(float $force) : void{
if($force <= 0){
throw new \InvalidArgumentException("Explosion radius must be positive");
}
$this->force = $force;
}

View File

@ -28,6 +28,9 @@ use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
/**
* Called when a dropped item tries to despawn due to its despawn delay running out.
* Cancelling the event will reset the despawn delay to default (5 minutes).
*
* @phpstan-extends EntityEvent<ItemEntity>
*/
class ItemDespawnEvent extends EntityEvent implements Cancellable{

View File

@ -26,6 +26,15 @@ namespace pocketmine\event\entity;
use pocketmine\entity\object\ItemEntity;
/**
* Called when an item is spawned or loaded.
*
* Some possible reasons include:
* - item is loaded from disk
* - player dropping an item
* - block drops
* - loot of a player or entity
*
* @see PlayerDropItemEvent
* @phpstan-extends EntityEvent<ItemEntity>
*/
class ItemSpawnEvent extends EntityEvent{

View File

@ -29,8 +29,17 @@ use pocketmine\event\Event;
use pocketmine\inventory\transaction\InventoryTransaction;
/**
* Called when there is a transaction between two Inventory objects.
* The source of this can be a Player, entities, mobs, or even hoppers in the future!
* Called when a player performs actions involving items in inventories.
*
* This may involve multiple inventories, and may include actions such as:
* - moving items from one slot to another
* - splitting itemstacks
* - dragging itemstacks across inventory slots (slot painting)
* - dropping an item on the ground
* - taking an item from the creative inventory menu
* - destroying (trashing) an item
*
* @see https://doc.pmmp.io/en/rtfd/developer-reference/inventory-transactions.html for more information on inventory transactions
*/
class InventoryTransactionEvent extends Event implements Cancellable{
use CancellableTrait;

View File

@ -28,12 +28,10 @@ use pocketmine\event\CancellableTrait;
use pocketmine\player\Player;
/**
* Called when a player runs a command or chats, early in the process
* Called when a player runs a command or chats, before it is processed.
*
* You don't want to use this except for a few cases like logging commands,
* blocking commands on certain places, or applying modifiers.
*
* The message contains a slash at the start
* If the message is prefixed with a / (forward slash), it will be interpreted as a command.
* Otherwise, it will be broadcasted as a chat message.
*/
class PlayerCommandPreprocessEvent extends PlayerEvent implements Cancellable{
use CancellableTrait;

View File

@ -29,7 +29,7 @@ use pocketmine\item\Item;
use pocketmine\player\Player;
/**
* Called when a player tries to drop an item from its hotbar
* Called when a player tries to drop an item
*/
class PlayerDropItemEvent extends PlayerEvent implements Cancellable{
use CancellableTrait;

View File

@ -28,6 +28,11 @@ use pocketmine\event\CancellableTrait;
use pocketmine\item\Item;
use pocketmine\player\Player;
/**
* Called when a player's held item changes.
* This could be because they selected a different hotbar slot, or because the item in the selected hotbar slot was
* changed.
*/
class PlayerItemHeldEvent extends PlayerEvent implements Cancellable{
use CancellableTrait;

View File

@ -29,7 +29,7 @@ use pocketmine\lang\Translatable;
use pocketmine\player\Player;
/**
* Called when a player leaves the server
* Called when a player is kicked (forcibly disconnected) from the server, e.g. if an operator used /kick.
*/
class PlayerKickEvent extends PlayerEvent implements Cancellable{
use CancellableTrait;
@ -46,18 +46,33 @@ class PlayerKickEvent extends PlayerEvent implements Cancellable{
$this->reason = $reason;
}
/**
* Sets the message shown on the kicked player's disconnection screen.
* This message is also displayed in the console and server log.
*/
public function setReason(string $reason) : void{
$this->reason = $reason;
}
/**
* Returns the message shown on the kicked player's disconnection screen.
* This message is also displayed in the console and server log.
* When kicked by the /kick command, the default is something like "Kicked by admin.".
*/
public function getReason() : string{
return $this->reason;
}
/**
* Sets the quit message broadcasted to other players.
*/
public function setQuitMessage(Translatable|string $quitMessage) : void{
$this->quitMessage = $quitMessage;
}
/**
* Returns the quit message broadcasted to other players, e.g. "Steve left the game".
*/
public function getQuitMessage() : Translatable|string{
return $this->quitMessage;
}

View File

@ -27,7 +27,14 @@ use pocketmine\lang\Translatable;
use pocketmine\player\Player;
/**
* Called when a player leaves the server
* Called when a player disconnects from the server for any reason.
*
* Some possible reasons include:
* - being kicked by an operator
* - disconnecting from the game
* - timeout due to network connectivity issues
*
* @see PlayerKickEvent
*/
class PlayerQuitEvent extends PlayerEvent{
@ -42,14 +49,23 @@ class PlayerQuitEvent extends PlayerEvent{
$this->quitReason = $quitReason;
}
/**
* Sets the quit message broadcasted to other players.
*/
public function setQuitMessage(Translatable|string $quitMessage) : void{
$this->quitMessage = $quitMessage;
}
/**
* Returns the quit message broadcasted to other players, e.g. "Steve left the game".
*/
public function getQuitMessage() : Translatable|string{
return $this->quitMessage;
}
/**
* Returns the disconnect reason shown in the server log and on the console.
*/
public function getQuitReason() : string{
return $this->quitReason;
}

View File

@ -27,6 +27,9 @@ use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
use pocketmine\player\Player;
/**
* Called when a player attempts to be transferred to another server, e.g. by using /transferserver.
*/
class PlayerTransferEvent extends PlayerEvent implements Cancellable{
use CancellableTrait;
@ -44,26 +47,44 @@ class PlayerTransferEvent extends PlayerEvent implements Cancellable{
$this->message = $message;
}
/**
* Returns the destination server address. This could be an IP or a domain name.
*/
public function getAddress() : string{
return $this->address;
}
/**
* Sets the destination server address.
*/
public function setAddress(string $address) : void{
$this->address = $address;
}
/**
* Returns the destination server port.
*/
public function getPort() : int{
return $this->port;
}
/**
* Sets the destination server port.
*/
public function setPort(int $port) : void{
$this->port = $port;
}
/**
* Returns the disconnect reason shown in the server log and on the console.
*/
public function getMessage() : string{
return $this->message;
}
/**
* Sets the disconnect reason shown in the server log and on the console.
*/
public function setMessage(string $message) : void{
$this->message = $message;
}

View File

@ -28,12 +28,18 @@ use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
/**
* Called when any CommandSender runs a command, early in the process
* Called when any CommandSender runs a command, before it is parsed.
*
* You don't want to use this except for a few cases like logging commands,
* blocking commands on certain places, or applying modifiers.
* This can be used for logging commands, or preprocessing the command string to add custom features (e.g. selectors).
*
* The message DOES NOT contain a slash at the start
* WARNING: DO NOT use this to block commands. Many commands have aliases.
* For example, /version can also be invoked using /ver or /about.
* To prevent command senders from using certain commands, deny them permission to use the commands you don't want them
* to have access to.
*
* @see Permissible::addAttachment()
*
* The message DOES NOT begin with a slash.
*/
class CommandEvent extends ServerEvent implements Cancellable{
use CancellableTrait;

View File

@ -26,7 +26,7 @@ namespace pocketmine\event\server;
use pocketmine\updater\UpdateChecker;
/**
* Called when the AutoUpdater receives notification of an available PocketMine-MP update.
* Called when the update checker receives notification of an available PocketMine-MP update.
* Plugins may use this event to perform actions when an update notification is received.
*/
class UpdateNotifyEvent extends ServerEvent{

View File

@ -27,7 +27,7 @@ use pocketmine\world\format\Chunk;
use pocketmine\world\World;
/**
* Called when a Chunk is loaded
* Called when a Chunk is loaded or newly created by the world generator.
*/
class ChunkLoadEvent extends ChunkEvent{
/** @var bool */
@ -38,6 +38,10 @@ class ChunkLoadEvent extends ChunkEvent{
$this->newChunk = $newChunk;
}
/**
* Returns whether the chunk is newly generated.
* If false, the chunk was loaded from storage.
*/
public function isNewChunk() : bool{
return $this->newChunk;
}

View File

@ -24,7 +24,8 @@ declare(strict_types=1);
namespace pocketmine\event\world;
/**
* Called when a Chunk is populated (after receiving it on the main thread)
* Called when a Chunk is fully populated by the world generator.
* This means that the terrain has been generated, and all artifacts (e.g. trees, grass, ponds, etc.) have been placed.
*/
class ChunkPopulateEvent extends ChunkEvent{

View File

@ -27,7 +27,7 @@ use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
/**
* Called when a Chunk is unloaded
* Called when a Chunk is unloaded from memory.
*/
class ChunkUnloadEvent extends ChunkEvent implements Cancellable{
use CancellableTrait;

View File

@ -24,7 +24,7 @@ declare(strict_types=1);
namespace pocketmine\event\world;
/**
* Called when a World is initializing
* Called when a new world is created/generated.
*/
class WorldInitEvent extends WorldEvent{

View File

@ -24,7 +24,7 @@ declare(strict_types=1);
namespace pocketmine\event\world;
/**
* Called when a World is loaded
* Called when a world is loaded or newly created/generated.
*/
class WorldLoadEvent extends WorldEvent{

View File

@ -24,7 +24,7 @@ declare(strict_types=1);
namespace pocketmine\event\world;
/**
* Called when a World is saved
* Called when a world is saved. Saving may be triggered manually (e.g. via commands) or automatically (autosave).
*/
class WorldSaveEvent extends WorldEvent{

View File

@ -27,7 +27,7 @@ use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
/**
* Called when a World is unloaded
* Called when a world is unloaded from memory.
*/
class WorldUnloadEvent extends WorldEvent implements Cancellable{
use CancellableTrait;

View File

@ -148,7 +148,7 @@ class InventoryTransaction{
try{
$action->validate($this->source);
}catch(TransactionValidationException $e){
throw new TransactionValidationException(get_class($action) . ": " . $e->getMessage(), 0, $e);
throw new TransactionValidationException(get_class($action) . "#" . spl_object_id($action) . ": " . $e->getMessage(), 0, $e);
}
if(!$action->getSourceItem()->isNull()){

View File

@ -25,5 +25,9 @@ namespace pocketmine\item;
class Minecart extends Item{
public function getMaxStackSize() : int{
return 1;
}
//TODO
}

View File

@ -67,13 +67,6 @@ use function spl_object_id;
* @phpstan-type ContainerOpenClosure \Closure(int $id, Inventory $inventory) : (list<ClientboundPacket>|null)
*/
class InventoryManager{
//TODO: HACK!
//these IDs are used for 1.16 to restore 1.14ish crafting & inventory behaviour; since they don't seem to have any
//effect on the behaviour of inventory transactions I don't currently plan to integrate these into the main system.
private const RESERVED_WINDOW_ID_RANGE_START = ContainerIds::LAST - 10;
private const HARDCODED_INVENTORY_WINDOW_ID = self::RESERVED_WINDOW_ID_RANGE_START + 2;
/** @var Player */
private $player;
/** @var NetworkSession */
@ -84,15 +77,6 @@ class InventoryManager{
/** @var int */
private $lastInventoryNetworkId = ContainerIds::FIRST;
/**
* TODO: HACK! This tracks GUIs for inventories that the server considers "always open" so that the client can't
* open them twice. (1.16 hack)
* @var true[]
* @phpstan-var array<int, true>
* @internal
*/
protected $openHardcodedWindows = [];
/**
* @var Item[][]
* @phpstan-var array<int, array<int, Item>>
@ -104,6 +88,10 @@ class InventoryManager{
/** @phpstan-var ObjectSet<ContainerOpenClosure> */
private ObjectSet $containerOpenCallbacks;
private ?int $pendingCloseWindowId = null;
/** @phpstan-var \Closure() : void */
private ?\Closure $pendingOpenWindowCallback = null;
public function __construct(Player $player, NetworkSession $session){
$this->player = $player;
$this->session = $session;
@ -125,6 +113,12 @@ class InventoryManager{
$this->windowMap[$id] = $inventory;
}
private function addDynamic(Inventory $inventory) : int{
$this->lastInventoryNetworkId = max(ContainerIds::FIRST, ($this->lastInventoryNetworkId + 1) % ContainerIds::LAST);
$this->add($this->lastInventoryNetworkId, $inventory);
return $this->lastInventoryNetworkId;
}
private function remove(int $id) : void{
unset($this->windowMap[$id], $this->initiatedSlotChanges[$id]);
}
@ -168,21 +162,47 @@ class InventoryManager{
}
}
/**
* When the server initiates a window close, it does so by sending a ContainerClose to the client, which causes the
* client to behave as if it initiated the close itself. It responds by sending a ContainerClose back to the server,
* which the server is then expected to respond to.
*
* Sending the client a new window before sending this final response creates buggy behaviour on the client, which
* is problematic when switching windows. Therefore, we defer sending any new windows until after the client
* responds to our window close instruction, so that we can complete the window handshake correctly.
*
* This is a pile of complicated garbage that only exists because Mojang overengineered the process of opening and
* closing inventory windows.
*
* @phpstan-param \Closure() : void $func
*/
private function openWindowDeferred(\Closure $func) : void{
if($this->pendingCloseWindowId !== null){
$this->session->getLogger()->debug("Deferring opening of new window, waiting for close ack of window $this->pendingCloseWindowId");
$this->pendingOpenWindowCallback = $func;
}else{
$func();
}
}
public function onCurrentWindowChange(Inventory $inventory) : void{
$this->onCurrentWindowRemove();
$this->add($this->lastInventoryNetworkId = max(ContainerIds::FIRST, ($this->lastInventoryNetworkId + 1) % self::RESERVED_WINDOW_ID_RANGE_START), $inventory);
foreach($this->containerOpenCallbacks as $callback){
$pks = $callback($this->lastInventoryNetworkId, $inventory);
if($pks !== null){
foreach($pks as $pk){
$this->session->sendDataPacket($pk);
$this->openWindowDeferred(function() use ($inventory) : void{
$windowId = $this->addDynamic($inventory);
foreach($this->containerOpenCallbacks as $callback){
$pks = $callback($windowId, $inventory);
if($pks !== null){
foreach($pks as $pk){
$this->session->sendDataPacket($pk);
}
$this->syncContents($inventory);
return;
}
$this->syncContents($inventory);
return;
}
}
throw new \LogicException("Unsupported inventory type");
throw new \LogicException("Unsupported inventory type");
});
}
/** @phpstan-return ObjectSet<ContainerOpenClosure> */
@ -218,31 +238,32 @@ class InventoryManager{
}
public function onClientOpenMainInventory() : void{
$id = self::HARDCODED_INVENTORY_WINDOW_ID;
if(!isset($this->openHardcodedWindows[$id])){
//TODO: HACK! this restores 1.14ish behaviour, but this should be able to be listened to and
//controlled by plugins. However, the player is always a subscriber to their own inventory so it
//doesn't integrate well with the regular container system right now.
$this->openHardcodedWindows[$id] = true;
$this->onCurrentWindowRemove();
$this->openWindowDeferred(function() : void{
$windowId = $this->addDynamic($this->player->getInventory());
$this->session->sendDataPacket(ContainerOpenPacket::entityInv(
InventoryManager::HARDCODED_INVENTORY_WINDOW_ID,
$windowId,
WindowTypes::INVENTORY,
$this->player->getId()
));
}
});
}
public function onCurrentWindowRemove() : void{
if(isset($this->windowMap[$this->lastInventoryNetworkId])){
$this->remove($this->lastInventoryNetworkId);
$this->session->sendDataPacket(ContainerClosePacket::create($this->lastInventoryNetworkId, true));
if($this->pendingCloseWindowId !== null){
throw new AssumptionFailedError("We should not have opened a new window while a window was waiting to be closed");
}
$this->pendingCloseWindowId = $this->lastInventoryNetworkId;
}
}
public function onClientRemoveWindow(int $id) : void{
if(isset($this->openHardcodedWindows[$id])){
unset($this->openHardcodedWindows[$id]);
}elseif($id === $this->lastInventoryNetworkId){
if($id === $this->lastInventoryNetworkId){
$this->remove($id);
$this->player->removeCurrentWindow();
}else{
@ -252,6 +273,13 @@ class InventoryManager{
//Always send this, even if no window matches. If we told the client to close a window, it will behave as if it
//initiated the close and expect an ack.
$this->session->sendDataPacket(ContainerClosePacket::create($id, false));
if($this->pendingOpenWindowCallback !== null && $id === $this->pendingCloseWindowId){
$this->session->getLogger()->debug("Opening deferred window after close ack of window $id");
$this->pendingCloseWindowId = null;
($this->pendingOpenWindowCallback)();
$this->pendingOpenWindowCallback = null;
}
}
public function syncSlot(Inventory $inventory, int $slot) : void{

View File

@ -723,6 +723,7 @@ class NetworkSession{
}
public function onServerRespawn() : void{
$this->syncAttributes($this->player, $this->player->getAttributeMap()->getAll());
$this->player->sendData(null);
$this->syncAdventureSettings($this->player);

View File

@ -2373,6 +2373,7 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
if(parent::teleport($pos, $yaw, $pitch)){
$this->removeCurrentWindow();
$this->stopSleep();
$this->sendPosition($this->location, $this->location->yaw, $this->location->pitch, MovePlayerPacket::MODE_TELEPORT);
$this->broadcastMovement(true);
@ -2384,7 +2385,6 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
if($this->spawnChunkLoadCount !== -1){
$this->spawnChunkLoadCount = 0;
}
$this->stopSleep();
$this->blockBreakHandler = null;
//TODO: workaround for player last pos not getting updated
@ -2481,7 +2481,6 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
return false;
}
//TODO: client side race condition here makes the opening work incorrectly
$this->removeCurrentWindow();
if(($inventoryManager = $this->getNetworkSession()->getInvManager()) === null){

View File

@ -42,6 +42,7 @@ use pocketmine\world\utils\SubChunkExplorer;
use pocketmine\world\utils\SubChunkExplorerStatus;
use function ceil;
use function floor;
use function min;
use function mt_rand;
use function sqrt;
@ -95,9 +96,6 @@ class Explosion{
$blockFactory = BlockFactory::getInstance();
$currentChunk = null;
$currentSubChunk = null;
$mRays = $this->rays - 1;
for($i = 0; $i < $this->rays; ++$i){
for($j = 0; $j < $this->rays; ++$j){
@ -156,10 +154,8 @@ class Explosion{
* and creating sounds and particles.
*/
public function explodeB() : bool{
$updateBlocks = [];
$source = (new Vector3($this->source->x, $this->source->y, $this->source->z))->floor();
$yield = (1 / $this->size) * 100;
$yield = min(100, (1 / $this->size) * 100);
if($this->what instanceof Entity){
$ev = new EntityExplodeEvent($this->what, $this->source, $this->affectedBlocks, $yield);

View File

@ -114,6 +114,9 @@ abstract class LightUpdate{
$context->removalQueue->enqueue([$x, $y, $z, $oldLevel]);
}
}
}elseif($this->getEffectiveLight($x, $y, $z) > 0){ //outside the chunk (e.g. virtual sky light from y=256)
$context->spreadVisited[$blockHash] = true;
$context->spreadQueue->enqueue([$x, $y, $z]);
}
}
return $context;

View File

@ -610,6 +610,11 @@ parameters:
count: 1
path: ../../../src/network/mcpe/NetworkSession.php
-
message: "#^Cannot call method getAttributeMap\\(\\) on pocketmine\\\\player\\\\Player\\|null\\.$#"
count: 1
path: ../../../src/network/mcpe/NetworkSession.php
-
message: "#^Cannot call method getLanguage\\(\\) on pocketmine\\\\player\\\\Player\\|null\\.$#"
count: 1
@ -665,6 +670,11 @@ parameters:
count: 1
path: ../../../src/network/mcpe/NetworkSession.php
-
message: "#^Parameter \\#1 \\$entity of method pocketmine\\\\network\\\\mcpe\\\\NetworkSession\\:\\:syncAttributes\\(\\) expects pocketmine\\\\entity\\\\Living, pocketmine\\\\player\\\\Player\\|null given\\.$#"
count: 1
path: ../../../src/network/mcpe/NetworkSession.php
-
message: "#^Parameter \\#1 \\$for of method pocketmine\\\\network\\\\mcpe\\\\NetworkSession\\:\\:syncAdventureSettings\\(\\) expects pocketmine\\\\player\\\\Player, pocketmine\\\\player\\\\Player\\|null given\\.$#"
count: 2
@ -945,11 +955,6 @@ parameters:
count: 1
path: ../../../src/utils/Utils.php
-
message: "#^Parameter \\#2 \\$array of function array_map expects array, mixed given\\.$#"
count: 1
path: ../../../src/utils/Utils.php
-
message: "#^Cannot call method getFullBlock\\(\\) on pocketmine\\\\world\\\\format\\\\SubChunk\\|null\\.$#"
count: 1