Merge branch 'next-minor' into next-major

This commit is contained in:
Dylan K. Taylor 2022-12-15 19:50:27 +00:00
commit 4d79aced07
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
77 changed files with 395 additions and 126 deletions

View File

@ -69,7 +69,7 @@ jobs:
${{ github.workspace }}/build_info.json ${{ github.workspace }}/build_info.json
- name: Create draft release - name: Create draft release
uses: ncipollo/release-action@v1.11.2 uses: ncipollo/release-action@v1.12.0
with: with:
artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json artifacts: ${{ github.workspace }}/PocketMine-MP.phar,${{ github.workspace }}/start.*,${{ github.workspace }}/build_info.json
commit: ${{ github.sha }} commit: ${{ github.sha }}

View File

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

View File

@ -62,6 +62,11 @@
<option name="USE_TAB_CHARACTER" value="true" /> <option name="USE_TAB_CHARACTER" value="true" />
</indentOptions> </indentOptions>
</codeStyleSettings> </codeStyleSettings>
<codeStyleSettings language="Shell Script">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="neon"> <codeStyleSettings language="neon">
<indentOptions> <indentOptions>
<option name="USE_TAB_CHARACTER" value="true" /> <option name="USE_TAB_CHARACTER" value="true" />

View File

@ -66,6 +66,9 @@ BODY,
], ],
'indentation_type' => true, 'indentation_type' => true,
'logical_operators' => true, 'logical_operators' => true,
'native_constant_invocation' => [
'scope' => 'namespaced'
],
'native_function_invocation' => [ 'native_function_invocation' => [
'scope' => 'namespaced', 'scope' => 'namespaced',
'include' => ['@all'], 'include' => ['@all'],
@ -92,6 +95,12 @@ BODY,
], ],
'sort_algorithm' => 'alpha' 'sort_algorithm' => 'alpha'
], ],
'phpdoc_align' => [
'align' => 'vertical',
'tags' => [
'param',
]
],
'phpdoc_line_span' => [ 'phpdoc_line_span' => [
'property' => 'single', 'property' => 'single',
'method' => null, 'method' => null,

View File

@ -48,6 +48,8 @@ use function sort;
use function strrpos; use function strrpos;
use function strtoupper; use function strtoupper;
use function substr; use function substr;
use const SORT_STRING;
use const STDERR;
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';

View File

@ -36,6 +36,8 @@ use function file_get_contents;
use function fopen; use function fopen;
use function fwrite; use function fwrite;
use function strtoupper; use function strtoupper;
use const SORT_STRING;
use const STDERR;
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';

View File

@ -39,6 +39,7 @@ use function sprintf;
use function str_replace; use function str_replace;
use function substr; use function substr;
use const SORT_STRING; use const SORT_STRING;
use const STDERR;
if(count($argv) !== 2){ if(count($argv) !== 2){
fwrite(STDERR, "Provide a path to process\n"); fwrite(STDERR, "Provide a path to process\n");

View File

@ -48,6 +48,7 @@ use function lcfirst;
use function log; use function log;
use function ob_get_clean; use function ob_get_clean;
use function ob_start; use function ob_start;
use const SORT_STRING;
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';

View File

@ -40,6 +40,7 @@ use function rtrim;
use function sprintf; use function sprintf;
use function str_replace; use function str_replace;
use function unlink; use function unlink;
use const DIRECTORY_SEPARATOR;
use const PHP_EOL; use const PHP_EOL;
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';

38
composer.lock generated
View File

@ -198,16 +198,16 @@
}, },
{ {
"name": "netresearch/jsonmapper", "name": "netresearch/jsonmapper",
"version": "v4.0.0", "version": "v4.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/cweiske/jsonmapper.git", "url": "https://github.com/cweiske/jsonmapper.git",
"reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d" "reference": "cfa81ea1d35294d64adb9c68aa4cb9e92400e53f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/cfa81ea1d35294d64adb9c68aa4cb9e92400e53f",
"reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d", "reference": "cfa81ea1d35294d64adb9c68aa4cb9e92400e53f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -243,9 +243,9 @@
"support": { "support": {
"email": "cweiske@cweiske.de", "email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues", "issues": "https://github.com/cweiske/jsonmapper/issues",
"source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0" "source": "https://github.com/cweiske/jsonmapper/tree/v4.1.0"
}, },
"time": "2020-12-01T19:48:11+00:00" "time": "2022-12-08T20:46:14+00:00"
}, },
{ {
"name": "pocketmine/bedrock-block-upgrade-schema", "name": "pocketmine/bedrock-block-upgrade-schema",
@ -1824,21 +1824,21 @@
}, },
{ {
"name": "phpstan/phpstan-phpunit", "name": "phpstan/phpstan-phpunit",
"version": "1.2.2", "version": "1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git", "url": "https://github.com/phpstan/phpstan-phpunit.git",
"reference": "dea1f87344c6964c607d9076dee42d891f3923f0" "reference": "4c06b7e3f2c40081334d86975350dda814bd064a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/dea1f87344c6964c607d9076dee42d891f3923f0", "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/4c06b7e3f2c40081334d86975350dda814bd064a",
"reference": "dea1f87344c6964c607d9076dee42d891f3923f0", "reference": "4c06b7e3f2c40081334d86975350dda814bd064a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.2 || ^8.0", "php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.8.11" "phpstan/phpstan": "^1.9.0"
}, },
"conflict": { "conflict": {
"phpunit/phpunit": "<7.0" "phpunit/phpunit": "<7.0"
@ -1870,9 +1870,9 @@
"description": "PHPUnit extensions and rules for PHPStan", "description": "PHPUnit extensions and rules for PHPStan",
"support": { "support": {
"issues": "https://github.com/phpstan/phpstan-phpunit/issues", "issues": "https://github.com/phpstan/phpstan-phpunit/issues",
"source": "https://github.com/phpstan/phpstan-phpunit/tree/1.2.2" "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.0"
}, },
"time": "2022-10-28T10:23:07+00:00" "time": "2022-12-07T15:46:24+00:00"
}, },
{ {
"name": "phpstan/phpstan-strict-rules", "name": "phpstan/phpstan-strict-rules",
@ -2242,16 +2242,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "9.5.26", "version": "9.5.27",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2" "reference": "a2bc7ffdca99f92d959b3f2270529334030bba38"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/851867efcbb6a1b992ec515c71cdcf20d895e9d2", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a2bc7ffdca99f92d959b3f2270529334030bba38",
"reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2", "reference": "a2bc7ffdca99f92d959b3f2270529334030bba38",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2324,7 +2324,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.26" "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.27"
}, },
"funding": [ "funding": [
{ {
@ -2340,7 +2340,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-10-28T06:00:21+00:00" "time": "2022-12-09T07:31:23+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",

View File

@ -39,11 +39,14 @@ namespace pocketmine {
use function extension_loaded; use function extension_loaded;
use function function_exists; use function function_exists;
use function getcwd; use function getcwd;
use function is_dir;
use function mkdir;
use function phpversion; use function phpversion;
use function preg_match; use function preg_match;
use function preg_quote; use function preg_quote;
use function realpath; use function realpath;
use function version_compare; use function version_compare;
use const DIRECTORY_SEPARATOR;
require_once __DIR__ . '/VersionInfo.php'; require_once __DIR__ . '/VersionInfo.php';
@ -273,25 +276,33 @@ JIT_WARNING
$pluginPath = getopt_string("plugins") ?? $cwd . DIRECTORY_SEPARATOR . "plugins"; $pluginPath = getopt_string("plugins") ?? $cwd . DIRECTORY_SEPARATOR . "plugins";
Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX); Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX);
if(!@mkdir($dataPath, 0777, true) && (!is_dir($dataPath) || !is_writable($dataPath))){ if(!@mkdir($dataPath, 0777, true) && !is_dir($dataPath)){
critical_error("Unable to create/access data directory at $dataPath. Check that the target location is accessible by the current user."); critical_error("Unable to create/access data directory at $dataPath. Check that the target location is accessible by the current user.");
exit(1); exit(1);
} }
//this has to be done after we're sure the data path exists //this has to be done after we're sure the data path exists
$dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR; $dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR;
if(!@mkdir($pluginPath, 0777, true) && (!is_dir($pluginPath) || !is_writable($pluginPath))){
critical_error("Unable to create plugin directory at $pluginPath. Check that the target location is accessible by the current user.");
exit(1);
}
$pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
$lockFilePath = Path::join($dataPath, 'server.lock'); $lockFilePath = Path::join($dataPath, 'server.lock');
if(($pid = Filesystem::createLockFile($lockFilePath)) !== null){ try{
$pid = Filesystem::createLockFile($lockFilePath);
}catch(\InvalidArgumentException $e){
critical_error($e->getMessage());
critical_error("Please ensure that there is enough space on the disk and that the current user has read/write permissions to the selected data directory $dataPath.");
exit(1);
}
if($pid !== null){
critical_error("Another " . VersionInfo::NAME . " instance (PID $pid) is already using this folder (" . realpath($dataPath) . ")."); critical_error("Another " . VersionInfo::NAME . " instance (PID $pid) is already using this folder (" . realpath($dataPath) . ").");
critical_error("Please stop the other server first before running a new one."); critical_error("Please stop the other server first before running a new one.");
exit(1); exit(1);
} }
if(!@mkdir($pluginPath, 0777, true) && !is_dir($pluginPath)){
critical_error("Unable to create plugin directory at $pluginPath. Check that the target location is accessible by the current user.");
exit(1);
}
$pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
//Logger has a dependency on timezone //Logger has a dependency on timezone
Timezone::init(); Timezone::init();

View File

@ -37,6 +37,7 @@ class ShapelessRecipe implements CraftingRecipe{
/** /**
* @param RecipeIngredient[] $ingredients No more than 9 total. This applies to sum of item stack counts, not count of array. * @param RecipeIngredient[] $ingredients No more than 9 total. This applies to sum of item stack counts, not count of array.
* @param Item[] $results List of result items created by this recipe. * @param Item[] $results List of result items created by this recipe.
*
* TODO: we'll want to make the type parameter mandatory in PM5 * TODO: we'll want to make the type parameter mandatory in PM5
*/ */
public function __construct(array $ingredients, array $results, ?ShapelessRecipeType $type = null){ public function __construct(array $ingredients, array $results, ?ShapelessRecipeType $type = null){

View File

@ -34,6 +34,7 @@ use function gettype;
use function is_array; use function is_array;
use function is_string; use function is_string;
use function json_decode; use function json_decode;
use const JSON_THROW_ON_ERROR;
use const pocketmine\BEDROCK_DATA_PATH; use const pocketmine\BEDROCK_DATA_PATH;
/** /**

View File

@ -31,6 +31,7 @@ use function array_flip;
use function file_get_contents; use function file_get_contents;
use function is_array; use function is_array;
use function json_decode; use function json_decode;
use const JSON_THROW_ON_ERROR;
use const pocketmine\BEDROCK_DATA_PATH; use const pocketmine\BEDROCK_DATA_PATH;
/** /**

View File

@ -37,6 +37,7 @@ use pocketmine\nbt\tag\StringTag;
use pocketmine\utils\Binary; use pocketmine\utils\Binary;
use function assert; use function assert;
use function ksort; use function ksort;
use const SORT_NUMERIC;
final class ItemDataUpgrader{ final class ItemDataUpgrader{
private const TAG_LEGACY_ID = "id"; //TAG_Short (or TAG_String for Java itemstacks) private const TAG_LEGACY_ID = "id"; //TAG_Short (or TAG_String for Java itemstacks)

View File

@ -31,6 +31,8 @@ use function gettype;
use function is_object; use function is_object;
use function json_decode; use function json_decode;
use function ksort; use function ksort;
use const JSON_THROW_ON_ERROR;
use const SORT_NUMERIC;
final class ItemIdMetaUpgradeSchemaUtils{ final class ItemIdMetaUpgradeSchemaUtils{

View File

@ -32,6 +32,7 @@ use function is_array;
use function is_string; use function is_string;
use function json_decode; use function json_decode;
use function mb_strtolower; use function mb_strtolower;
use const JSON_THROW_ON_ERROR;
use const pocketmine\BEDROCK_ITEM_UPGRADE_SCHEMA_PATH; use const pocketmine\BEDROCK_ITEM_UPGRADE_SCHEMA_PATH;
/** /**

View File

@ -439,7 +439,9 @@ abstract class Living extends Entity{
*/ */
protected function applyPostDamageEffects(EntityDamageEvent $source) : void{ protected function applyPostDamageEffects(EntityDamageEvent $source) : void{
$this->setAbsorption(max(0, $this->getAbsorption() + $source->getModifier(EntityDamageEvent::MODIFIER_ABSORPTION))); $this->setAbsorption(max(0, $this->getAbsorption() + $source->getModifier(EntityDamageEvent::MODIFIER_ABSORPTION)));
if($source->canBeReducedByArmor()){
$this->damageArmor($source->getBaseDamage()); $this->damageArmor($source->getBaseDamage());
}
if($source instanceof EntityDamageByEntityEvent && ($attacker = $source->getDamager()) !== null){ if($source instanceof EntityDamageByEntityEvent && ($attacker = $source->getDamager()) !== null){
$damage = 0; $damage = 0;

View File

@ -0,0 +1,73 @@
<?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\world;
use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\particle\Particle;
use pocketmine\world\World;
class WorldParticleEvent extends WorldEvent implements Cancellable{
use CancellableTrait;
/**
* @param Player[] $recipients
*/
public function __construct(
World $world,
private Particle $particle,
private Vector3 $position,
private array $recipients
){
parent::__construct($world);
}
public function getParticle() : Particle{
return $this->particle;
}
public function setParticle(Particle $particle) : void{
$this->particle = $particle;
}
public function getPosition() : Vector3{
return $this->position;
}
/**
* @return Player[]
*/
public function getRecipients() : array{
return $this->recipients;
}
/**
* @param Player[] $recipients
*/
public function setRecipients(array $recipients) : void{
$this->recipients = $recipients;
}
}

View File

@ -0,0 +1,77 @@
<?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\world;
use pocketmine\event\Cancellable;
use pocketmine\event\CancellableTrait;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\Sound;
use pocketmine\world\World;
/**
* Called when a sound is played in a world
* @see World::addSound()
*/
class WorldSoundEvent extends WorldEvent implements Cancellable{
use CancellableTrait;
/**
* @param Player[] $recipients
*/
public function __construct(
World $world,
private Sound $sound,
private Vector3 $position,
private array $recipients
){
parent::__construct($world);
}
public function getSound() : Sound{
return $this->sound;
}
public function setSound(Sound $sound) : void{
$this->sound = $sound;
}
public function getPosition() : Vector3{
return $this->position;
}
/**
* @return Player[]
*/
public function getRecipients() : array{
return $this->recipients;
}
/**
* @param Player[] $recipients
*/
public function setRecipients(array $recipients) : void{
$this->recipients = $recipients;
}
}

View File

@ -568,6 +568,16 @@ class Item implements \JsonSerializable{
return false; return false;
} }
/**
* Called when a player uses the item to interact with entity, for example by using a name tag.
*
* @param Vector3 $clickVector The exact position of the click (absolute coordinates)
* @return bool whether some action took place
*/
public function onInteractEntity(Player $player, Entity $entity, Vector3 $clickVector) : bool{
return false;
}
/** /**
* Returns the number of ticks a player must wait before activating this item again. * Returns the number of ticks a player must wait before activating this item again.
*/ */

View File

@ -36,6 +36,7 @@ use function get_debug_type;
use function is_array; use function is_array;
use function is_int; use function is_int;
use function json_decode; use function json_decode;
use const JSON_THROW_ON_ERROR;
/** /**
* Handles translation of network block runtime IDs into blockstate data, and vice versa * Handles translation of network block runtime IDs into blockstate data, and vice versa

View File

@ -34,6 +34,7 @@ use function openssl_digest;
use function openssl_error_string; use function openssl_error_string;
use function openssl_pkey_derive; use function openssl_pkey_derive;
use function str_pad; use function str_pad;
use const STR_PAD_LEFT;
final class EncryptionUtils{ final class EncryptionUtils{

View File

@ -306,6 +306,8 @@ class InGamePacketHandler extends PacketHandler{
public function handleInventoryTransaction(InventoryTransactionPacket $packet) : bool{ public function handleInventoryTransaction(InventoryTransactionPacket $packet) : bool{
$result = true; $result = true;
$this->inventoryManager->addPredictedSlotChanges($packet->trData->getActions());
if($packet->trData instanceof NormalTransactionData){ if($packet->trData instanceof NormalTransactionData){
$result = $this->handleNormalTransaction($packet->trData); $result = $this->handleNormalTransaction($packet->trData);
}elseif($packet->trData instanceof MismatchTransactionData){ }elseif($packet->trData instanceof MismatchTransactionData){
@ -355,7 +357,6 @@ class InGamePacketHandler extends PacketHandler{
return false; return false;
} }
} }
$this->inventoryManager->addPredictedSlotChanges($data->getActions());
if($isCraftingPart){ if($isCraftingPart){
if($this->craftingTransaction === null){ if($this->craftingTransaction === null){

View File

@ -52,6 +52,7 @@ use function mt_rand;
use function random_bytes; use function random_bytes;
use function rtrim; use function rtrim;
use function substr; use function substr;
use const PHP_INT_MAX;
class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{
/** /**

View File

@ -40,6 +40,7 @@ use function strlen;
use function time; use function time;
use function trim; use function trim;
use const AF_INET; use const AF_INET;
use const AF_INET6;
use const IPPROTO_IPV6; use const IPPROTO_IPV6;
use const IPV6_V6ONLY; use const IPV6_V6ONLY;
use const PHP_INT_MAX; use const PHP_INT_MAX;

View File

@ -73,6 +73,12 @@ use function sprintf;
use function strlen; use function strlen;
use function trim; use function trim;
use const AF_INET; use const AF_INET;
use const PREG_BACKTRACK_LIMIT_ERROR;
use const PREG_BAD_UTF8_ERROR;
use const PREG_BAD_UTF8_OFFSET_ERROR;
use const PREG_INTERNAL_ERROR;
use const PREG_JIT_STACKLIMIT_ERROR;
use const PREG_RECURSION_LIMIT_ERROR;
use const SO_RCVTIMEO; use const SO_RCVTIMEO;
use const SOCK_DGRAM; use const SOCK_DGRAM;
use const SOCKET_ETIMEDOUT; use const SOCKET_ETIMEDOUT;

View File

@ -1836,7 +1836,17 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$ev->call(); $ev->call();
$item = $this->inventory->getItemInHand();
$oldItem = clone $item;
if(!$ev->isCancelled()){ if(!$ev->isCancelled()){
if($item->onInteractEntity($this, $entity, $clickPos)){
if($this->hasFiniteResources() && !$item->equalsExact($oldItem) && $oldItem->equalsExact($this->inventory->getItemInHand())){
if($item instanceof Durable && $item->isBroken()){
$this->broadcastSound(new ItemBreakSound());
}
$this->inventory->setItemInHand($item);
}
}
return $entity->onInteract($this, $clickPos); return $entity->onInteract($this, $clickPos);
} }
return false; return false;

View File

@ -45,6 +45,7 @@ use function stream_copy_to_stream;
use function strpos; use function strpos;
use function strtolower; use function strtolower;
use function trim; use function trim;
use const DIRECTORY_SEPARATOR;
abstract class PluginBase implements Plugin, CommandExecutor{ abstract class PluginBase implements Plugin, CommandExecutor{
private bool $isEnabled = false; private bool $isEnabled = false;

View File

@ -29,6 +29,7 @@ use pocketmine\lang\Translatable;
use pocketmine\permission\PermissibleBase; use pocketmine\permission\PermissibleBase;
use pocketmine\permission\PermissibleDelegateTrait; use pocketmine\permission\PermissibleDelegateTrait;
use pocketmine\Server; use pocketmine\Server;
use const PHP_INT_MAX;
/** /**
* Forwards any messages it receives via sendMessage() to the given logger. Used for forwarding chat messages and * Forwards any messages it receives via sendMessage() to the given logger. Used for forwarding chat messages and

View File

@ -55,6 +55,7 @@ use const CASE_LOWER;
use const JSON_BIGINT_AS_STRING; use const JSON_BIGINT_AS_STRING;
use const JSON_PRETTY_PRINT; use const JSON_PRETTY_PRINT;
use const JSON_THROW_ON_ERROR; use const JSON_THROW_ON_ERROR;
use const YAML_UTF8_ENCODING;
/** /**
* Config Class for simple config manipulation of multiple formats. * Config Class for simple config manipulation of multiple formats.

View File

@ -182,9 +182,10 @@ final class Filesystem{
* @throws \InvalidArgumentException if the lock file path is invalid (e.g. parent directory doesn't exist, permission denied) * @throws \InvalidArgumentException if the lock file path is invalid (e.g. parent directory doesn't exist, permission denied)
*/ */
public static function createLockFile(string $lockFilePath) : ?int{ public static function createLockFile(string $lockFilePath) : ?int{
$resource = fopen($lockFilePath, "a+b"); try{
if($resource === false){ $resource = ErrorToExceptionHandler::trapAndRemoveFalse(fn() => fopen($lockFilePath, "a+b"));
throw new \InvalidArgumentException("Invalid lock file path or read/write permissions denied"); }catch(\ErrorException $e){
throw new \InvalidArgumentException("Failed to open lock file: " . $e->getMessage(), 0, $e);
} }
if(!flock($resource, LOCK_EX | LOCK_NB)){ if(!flock($resource, LOCK_EX | LOCK_NB)){
//wait for a shared lock to avoid race conditions if two servers started at the same time - this makes sure the //wait for a shared lock to avoid race conditions if two servers started at the same time - this makes sure the

View File

@ -51,7 +51,9 @@ use pocketmine\event\world\ChunkLoadEvent;
use pocketmine\event\world\ChunkPopulateEvent; use pocketmine\event\world\ChunkPopulateEvent;
use pocketmine\event\world\ChunkUnloadEvent; use pocketmine\event\world\ChunkUnloadEvent;
use pocketmine\event\world\SpawnChangeEvent; use pocketmine\event\world\SpawnChangeEvent;
use pocketmine\event\world\WorldParticleEvent;
use pocketmine\event\world\WorldSaveEvent; use pocketmine\event\world\WorldSaveEvent;
use pocketmine\event\world\WorldSoundEvent;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\item\ItemUseResult; use pocketmine\item\ItemUseResult;
use pocketmine\item\LegacyStringToItemParser; use pocketmine\item\LegacyStringToItemParser;
@ -669,9 +671,19 @@ class World implements ChunkManager{
* @param Player[]|null $players * @param Player[]|null $players
*/ */
public function addSound(Vector3 $pos, Sound $sound, ?array $players = null) : void{ public function addSound(Vector3 $pos, Sound $sound, ?array $players = null) : void{
$pk = $sound->encode($pos); $players ??= $this->getViewersForPosition($pos);
$ev = new WorldSoundEvent($this, $sound, $pos, $players);
$ev->call();
if($ev->isCancelled()){
return;
}
$pk = $ev->getSound()->encode($pos);
$players = $ev->getRecipients();
if(count($pk) > 0){ if(count($pk) > 0){
if($players === null){ if($players === $this->getViewersForPosition($pos)){
foreach($pk as $e){ foreach($pk as $e){
$this->broadcastPacketToViewers($pos, $e); $this->broadcastPacketToViewers($pos, $e);
} }
@ -685,14 +697,24 @@ class World implements ChunkManager{
* @param Player[]|null $players * @param Player[]|null $players
*/ */
public function addParticle(Vector3 $pos, Particle $particle, ?array $players = null) : void{ public function addParticle(Vector3 $pos, Particle $particle, ?array $players = null) : void{
$pk = $particle->encode($pos); $players ??= $this->getViewersForPosition($pos);
$ev = new WorldParticleEvent($this, $particle, $pos, $players);
$ev->call();
if($ev->isCancelled()){
return;
}
$pk = $ev->getParticle()->encode($pos);
$players = $ev->getRecipients();
if(count($pk) > 0){ if(count($pk) > 0){
if($players === null){ if($players === $this->getViewersForPosition($pos)){
foreach($pk as $e){ foreach($pk as $e){
$this->broadcastPacketToViewers($pos, $e); $this->broadcastPacketToViewers($pos, $e);
} }
}else{ }else{
$this->server->broadcastPackets($this->filterViewersForPosition($pos, $players), $pk); $this->server->broadcastPackets($this->filterViewersForPosition($pos, $ev->getRecipients()), $pk);
} }
} }
} }

View File

@ -29,6 +29,7 @@ use function file_get_contents;
use function is_array; use function is_array;
use function json_decode; use function json_decode;
use function print_r; use function print_r;
use const SORT_STRING;
class BlockTest extends TestCase{ class BlockTest extends TestCase{

View File

@ -43,6 +43,10 @@ use function rename;
use function round; use function round;
use function scandir; use function scandir;
use function unlink; use function unlink;
use const PATHINFO_EXTENSION;
use const PHP_BINARY;
use const SCANDIR_SORT_NONE;
use const SORT_NUMERIC;
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';

View File

@ -37,6 +37,8 @@ use function realpath;
use function trim; use function trim;
use function zlib_decode; use function zlib_decode;
use const FILE_IGNORE_NEW_LINES; use const FILE_IGNORE_NEW_LINES;
use const JSON_PRETTY_PRINT;
use const JSON_UNESCAPED_SLASHES;
use const PHP_EOL; use const PHP_EOL;
use const STDERR; use const STDERR;

View File

@ -40,6 +40,9 @@ use function fwrite;
use function get_class; use function get_class;
use function json_encode; use function json_encode;
use function ksort; use function ksort;
use const JSON_PRETTY_PRINT;
use const SORT_STRING;
use const STDERR;
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';

View File

@ -41,6 +41,8 @@ use function file_put_contents;
use function fwrite; use function fwrite;
use function json_encode; use function json_encode;
use function ksort; use function ksort;
use const JSON_PRETTY_PRINT;
use const SORT_STRING;
use const STDERR; use const STDERR;
require_once dirname(__DIR__) . '/vendor/autoload.php'; require_once dirname(__DIR__) . '/vendor/autoload.php';

View File

@ -40,6 +40,11 @@ use function json_decode;
use function json_encode; use function json_encode;
use function ksort; use function ksort;
use function scandir; use function scandir;
use const JSON_FORCE_OBJECT;
use const JSON_PRETTY_PRINT;
use const JSON_THROW_ON_ERROR;
use const SCANDIR_SORT_ASCENDING;
use const SORT_STRING;
require dirname(__DIR__) . '/vendor/autoload.php'; require dirname(__DIR__) . '/vendor/autoload.php';

View File

@ -49,9 +49,13 @@ use function socket_strerror;
use function strlen; use function strlen;
use function time; use function time;
use function trim; use function trim;
use const AF_INET;
use const MSG_DONTROUTE; use const MSG_DONTROUTE;
use const PHP_BINARY; use const PHP_BINARY;
use const PHP_INT_MAX; use const PHP_INT_MAX;
use const SOCK_DGRAM;
use const SOL_UDP;
use const STDIN;
require_once 'vendor/autoload.php'; require_once 'vendor/autoload.php';